<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
  <meta charset="utf-8">
  
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Best Practices &mdash; Sponge 6.0.0 documentation</title>

    <link rel="shortcut icon" href="../../_static/favicon.ico"/>




    <link rel="stylesheet" href="../../_static/css/theme.css" type="text/css" />

    <link rel="stylesheet" href="../../_static/spongedocs.css" type="text/css" />

        <link rel="index" title="Index"
              href="../../genindex.html"/>        <link rel="search" title="Search" href="../../search.html"/>    <link rel="top" title="Sponge 6.0.0 documentation" href="../../index.html"/>        <link rel="up" title="Practices" href="index.html"/>        <link rel="next" title="Bad Practices" href="bad.html"/>        <link rel="prev" title="Practices" href="index.html"/>
    <!-- Google Analytics -->
    <script>
        (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
        (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
        m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
        })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

        ga('create', 'UA-59476017-2', 'auto');
        ga('send', 'pageview');
    </script>

  <script src="../../_static/js/modernizr.min.js"></script>

</head>

<body class="wy-body-for-nav" role="document">

  <div class="wy-grid-for-nav">

    <nav data-toggle="wy-nav-shift" class="wy-nav-side">
      <div class="wy-side-scroll">
        <div class="wy-side-nav-search">
    <div id="sp-logo-container" class="page-scroll">
        <a class="logo" href="../../index.html">
            <img src="../../_static/spongie-mark-dark.svg">
            <span>Sponge</span>
            <i class="fa fa-fw fa-chevron-down"></i>
        </a>
        <div id="sp-logo-menu">
            <ul id="sp-logo-dropdown">
                <li><a href="https://www.spongepowered.org"><i class="fa-fw fa fa-home"></i>Homepage</a></li>
                <li><a href="https://forums.spongepowered.org"><i class="fa-fw fa fa-comments"></i>Forums</a></li>
                <li><a href="https://github.com/SpongePowered"><i class="fa-fw fa fa-code"></i>Code</a></li>
                <li class="active"><a href="https://docs.spongepowered.org"><i class="fa-fw fa fa-book"></i>Docs</a></li>
                <li><a href="https://jd.spongepowered.org"><i class="fa-fw fa fa-graduation-cap"></i>Javadocs</a></li>
                <li><a href="https://forums.spongepowered.org/c/plugins/plugin-releases"><i class="fa-fw fa fa-plug"></i>Plugins</a></li>
                <li><a href="https://www.spongepowered.org/downloads"><i class="fa-fw fa fa-download"></i>Downloads</a></li>
                <li><a href="https://www.spongepowered.org/chat"><i class="fa-fw fa fa-comment"></i>Chat</a></li>
            </ul>
        </div>
    </div>

<div role="search">
  <form id="rtd-search-form" class="wy-form" action="../../search.html" method="get">
    <input type="text" name="q" placeholder="Search docs" />
    <input type="hidden" name="check_keywords" value="yes" />
    <input type="hidden" name="area" value="default" />
  </form>
</div>        </div>

        <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
                <ul>
<li class="toctree-l1"><a class="reference internal" href="../../server/index.html">Creating a Server</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../preparing/index.html">Preparing for Development</a></li>
</ul>
<ul class="current">
<li class="toctree-l1 current"><a class="reference internal" href="../index.html">Creating a Plugin</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="../buildsystem.html">Build Systems</a></li>
<li class="toctree-l2"><a class="reference internal" href="../workspace/index.html">Setting Up Your Workspace</a></li>
<li class="toctree-l2"><a class="reference internal" href="../project/index.html">Setting Up Your Project</a></li>
<li class="toctree-l2"><a class="reference internal" href="../plugin-identifier.html">Plugin Identifiers</a></li>
<li class="toctree-l2"><a class="reference internal" href="../plugin-class.html">Main Plugin Class</a></li>
<li class="toctree-l2"><a class="reference internal" href="../lifecycle.html">Plugin Lifecycle</a></li>
<li class="toctree-l2"><a class="reference internal" href="../injection.html">Dependency Injection</a></li>
<li class="toctree-l2 current"><a class="reference internal" href="index.html">Practices</a><ul class="current">
<li class="toctree-l3 current"><a class="current reference internal" href="#">Best Practices</a></li>
<li class="toctree-l3"><a class="reference internal" href="bad.html">Bad Practices</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../optional/index.html">Optionals</a></li>
<li class="toctree-l2"><a class="reference internal" href="../logging.html">Logging and Debugging</a></li>
<li class="toctree-l2"><a class="reference internal" href="../commands/index.html">Commands</a></li>
<li class="toctree-l2"><a class="reference internal" href="../event/index.html">Events</a></li>
<li class="toctree-l2"><a class="reference internal" href="../assets.html">The Asset API</a></li>
<li class="toctree-l2"><a class="reference internal" href="../configuration/index.html">Configuring Plugins</a></li>
<li class="toctree-l2"><a class="reference internal" href="../text/index.html">Text</a></li>
<li class="toctree-l2"><a class="reference internal" href="../data/index.html">The Data API</a></li>
<li class="toctree-l2"><a class="reference internal" href="../blocks/index.html">Blocks</a></li>
<li class="toctree-l2"><a class="reference internal" href="../entities/index.html">Entities</a></li>
<li class="toctree-l2"><a class="reference internal" href="../items/index.html">Items</a></li>
<li class="toctree-l2"><a class="reference internal" href="../trade-offers.html">Trade-Offers</a></li>
<li class="toctree-l2"><a class="reference internal" href="../effects.html">Effects</a></li>
<li class="toctree-l2"><a class="reference internal" href="../scheduler.html">Scheduler</a></li>
<li class="toctree-l2"><a class="reference internal" href="../services.html">Services</a></li>
<li class="toctree-l2"><a class="reference internal" href="../database.html">Databases</a></li>
<li class="toctree-l2"><a class="reference internal" href="../permissions.html">Permissions</a></li>
<li class="toctree-l2"><a class="reference internal" href="../bans.html">Bans</a></li>
<li class="toctree-l2"><a class="reference internal" href="../bookview.html">Book Views</a></li>
<li class="toctree-l2"><a class="reference internal" href="../economy/index.html">Economy</a></li>
<li class="toctree-l2"><a class="reference internal" href="../wgen/index.html">World Generation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../manager.html">Plugin Manager</a></li>
<li class="toctree-l2"><a class="reference internal" href="../game-profile-manager.html">Game Profile Manager</a></li>
<li class="toctree-l2"><a class="reference internal" href="../offline-userplayer-data.html">Offline Player Data</a></li>
<li class="toctree-l2"><a class="reference internal" href="../debugging.html">Plugin Debugging</a></li>
<li class="toctree-l2"><a class="reference internal" href="../tab-lists.html">Tab Lists</a></li>
<li class="toctree-l2"><a class="reference internal" href="../plugin-meta.html">Plugin Metadata</a></li>
<li class="toctree-l2"><a class="reference internal" href="../ray-tracing.html">Ray Tracing</a></li>
<li class="toctree-l2"><a class="reference internal" href="../tutorials.html">Tutorials</a></li>
<li class="toctree-l2"><a class="reference internal" href="../internals/index.html">Implementation-dependent Plugins</a></li>
</ul>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../ore/index.html">Ore Documentation</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../contributing/index.html">Contributing to Sponge</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../about/index.html">About the Sponge Project</a></li>
</ul>

        </div>
      </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">

      <nav class="wy-nav-top" role="navigation" aria-label="top navigation">
        <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
        <a href="../../index.html">Sponge</a>
      </nav>


      <div class="wy-nav-content">
        <div class="rst-content">

 

<div role="navigation" aria-label="breadcrumbs navigation">
  <ul class="wy-breadcrumbs">
    <li><a href="../../index.html">Docs</a> &raquo;</li>
          <li><a href="../index.html">Creating a Plugin</a> &raquo;</li>
          <li><a href="index.html">Practices</a> &raquo;</li>
    <li>Best Practices</li>
      <li class="wy-breadcrumbs-aside">
            <a href="https://github.com/SpongePowered/SpongeDocs/blob/BestPractises/source/plugin/practices/best.rst" class="fa fa-github"> Edit on GitHub</a>
      </li>
  </ul>
  <hr/>
</div>          <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
           <div itemprop="articleBody">
  <div class="section" id="best-practices">
<h1>Best Practices<a class="headerlink" href="#best-practices" title="Permalink to this headline">¶</a></h1>
<p>There are many ways to create a plugin, and many pitfalls for an unwary developer. Here we describe the plugin
development practices that will make the most of the Sponge API, setting sensible boundaries for the benefit of
compatibility. This information may change and expand as the Sponge project matures.</p>
<div class="section" id="plugin-development-guidelines">
<h2>Plugin Development Guidelines<a class="headerlink" href="#plugin-development-guidelines" title="Permalink to this headline">¶</a></h2>
<p>The following guidelines have been prepared to aid Sponge plugin developers. It is not a definitive or comprehensive
list, merely an attempt to detail some issues that are likely to arise during plugin development, and propose our best
solutions.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">We reserve the use of <em>Sponge</em> for official SpongePowered works. Please don&#8217;t use <em>Sponge</em> as part of your plugin
name, unless (1) your plugin primarily concerns the Minecraft block &#8220;Sponge&#8221;, or (2) your plugin also has versions
for other APIs (in which case you may append &#8220;for Sponge&#8221; to the title).</p>
</div>
<div class="section" id="economy-api">
<h3>Economy API<a class="headerlink" href="#economy-api" title="Permalink to this headline">¶</a></h3>
<p>The Economy API is used to link economy plugins with other plugins that use the economy (i.e. shops). You can read
about the Economy API <a class="reference internal" href="../economy/index.html"><span class="doc">here</span></a>, which details everything you need to know about the API.</p>
</div>
<div class="section" id="packets">
<h3>Packets<a class="headerlink" href="#packets" title="Permalink to this headline">¶</a></h3>
<p>Anything to do with intercepting packets, or introducing custom items/blocks/entities/etc, is <em>not</em> planned to be part
of the Sponge API. Note that using packets may be looking at the problem the wrong way, as there may be a solution
achievable with the existing Sponge API. In some cases it may be possible to add whatever is needed to the Sponge API;
otherwise, the alternative is to use the Forge API and create a Mod instead.</p>
</div>
<div class="section" id="using-forge-or-nms-classes">
<h3>Using Forge or NMS Classes<a class="headerlink" href="#using-forge-or-nms-classes" title="Permalink to this headline">¶</a></h3>
<p>We do not recommend working with Forge or Minecraft base classes at all, unless it is to provide compatibility with a
mod for Sponge API. Most uses of NMS (net.minecraft.server) code in plugins do not fail gracefully, making
troubleshooting very difficult. Maintaining NMS modifications is also more difficult than using the Sponge API. Mods that
add to the Sponge API using code internals will have to specifically write an API, which does not rely on underlying
Minecraft code, to be usable by Sponge plugins. However, plugins can be created that load separate “compatibility”
modules to interact with the underlying implementation (SpongeForge or SpongeVanilla).</p>
<p>Plugins using implementation-specific code are very likely to break between versions, and should be clearly labelled
as such wherever they are hosted. These may more appropriately labelled as &#8220;Mods&#8221;.</p>
</div>
<div class="section" id="mixins">
<h3>Mixins<a class="headerlink" href="#mixins" title="Permalink to this headline">¶</a></h3>
<p>Mixins are specifically for transforming classes before other mods/plugins start. ForgeModLoader calls these mods
“Coremods”. SpongeForge is a Coremod, and deploys mixins on startup. Mixins can be used by plugins, but be aware of the
additional complexities involved.</p>
<p><strong>Hybrid Mods</strong></p>
<p>Sponge plugins which leverage mixins may also be a considered core mods, based on content.</p>
<ul class="simple">
<li>To use mixins in FML, it must be a coremod. The jar may also contain a Sponge plugin,
so most properly the container is a &#8220;hybrid mod&#8221;.</li>
<li>To use mixins in SpongeVanilla, intentions must be declared in the manifest.
SpongeVanilla then injects the mixins.</li>
<li>Having both types in a single jar is entirely possible. (Indeed, a single jar could
easily contain a tweaker, FML mod, coremod, bukkit plugin, sponge plugin, and/or litemod.)</li>
</ul>
<p>Some definitions may be helpful here.</p>
<dl class="docutils">
<dt>Tweak Mod (aka Tweaker)</dt>
<dd>a subsystem-level mod which hooks directly into the game using LaunchWrapper, usually used for
ModSystems (eg. LiteLoader, FML) and stand-alone mods (eg. Optifine). Can interact with any aspect
of the game environment directly. Generally breaks every version.</dd>
<dt>Core Mod</dt>
<dd>has almost equivalent power of a Tweak Mod but must be bootstrapped by a ModSystem.
Can interact with any aspect of the game environment directly. Generally breaks on every new Game version.</dd>
<dt>Mod</dt>
<dd>interacts with the game only via a ModSystem, the mod is exposed to game objects directly but will
generally only hook into the game via hooks provided by the ModSystem. Generally breaks every major
version of the Game (depending on features used). The term mod is also used as an umbrella term for
anything which modifies the game, though for the sake of clarity we&#8217;ll use this definition.</dd>
<dt>Plugin</dt>
<dd>interacts with the game only via an API, does not interact with game objects directly in any way,
only leverages objects exposed by the API. Generally breaks only when the API is revised
(and sometimes not even then).</dd>
</dl>
<p>It&#8217;s also important to distinguish the container from the contents. Issues with terminology tends to
arise because a jar containing a mod tends to get referred to as a &#8220;mod&#8221;.
Any plugin which is not fully decoupled via the API puts itself into the category of Mod.
This type of &#8220;plugin&#8221; may be prevalent where there are shortcomings in an API.</p>
<p><strong>Advantages of Hybrid Mods</strong></p>
<p>A hybrid mod leverages both a plugin component which interacts via the API, and a mod (or even coremod)
in the same package. This has the disadvantages of a mod (breaks every version) but also the power of a
mod (can interact with the game directly) coupled with some of the benefits of a Plugin (high-level
abstract access to the game, and can also interact with other plugins as a peer).</p>
<p>The primary benefit of this system is that the maintenance burden is reduced when updating the mod,
because any features accessed via the API are likely to be much more stable.</p>
<p>This type of mod can be used to implement plugins whose needs overflow the capability of the API (in
the case of a plugin which needs to leverage mixins for a particular feature); but can also be used
for mods which want to leverage services afforded by the API (eg. a mod which wants to provide direct
support for permissions or chat channels).</p>
<p>Unlike NMS-exploiting &#8220;plugins&#8221;, a hybrid mod makes its nature clear.</p>
</div>
</div>
<div class="section" id="plugin-interoperability">
<h2>Plugin Interoperability<a class="headerlink" href="#plugin-interoperability" title="Permalink to this headline">¶</a></h2>
<p>An explanation of how to communicate with other plugins, <em>TBA</em>.</p>
</div>
</div>

           </div>
          </div>
<footer>
    <div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
        <a href="bad.html" class="btn btn-neutral float-right" title="Bad Practices" accesskey="n">Next <span class="fa fa-arrow-circle-right"></span></a>
        <a href="index.html" class="btn btn-neutral" title="Practices" accesskey="p"><span class="fa fa-arrow-circle-left"></span> Previous</a>
    </div>

  <hr/>

  <div role="contentinfo">
    <p>&copy; Copyright 2014-2017, Sponge Contributors.
    </p>
  </div>Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>. 
</footer>
        </div>
      </div>

    </section>

  </div>


<div class="rst-versions" data-toggle="rst-versions" role="note" aria-label="versions">
    <span class="rst-current-version" data-toggle="rst-current-version">
        <i class="fa fa-book"> <span>SpongeDocs</span></i>
        v: 6.0.0
        <span class="fa fa-caret-down"></span>
    </span>
    <div id="versions" class="rst-other-versions">




            <dl>
                <dt>Contribute</dt>
                    <dd><a href="https://github.com/SpongePowered/SpongeDocs/blob/BestPractises/source/plugin/practices/best.rst">Source</a></dd>
                    <dd><a href="https://github.com/SpongePowered/SpongeDocs/edit/BestPractises/source/plugin/practices/best.rst">Edit</a></dd>
            </dl>
    </div>
</div>

    <script type="text/javascript">
        var DOCUMENTATION_OPTIONS = {
            URL_ROOT:'../../',
            VERSION:'6.0.0',
            COLLAPSE_INDEX:false,
            FILE_SUFFIX:'.html',
            HAS_SOURCE:  true
        };
    </script>      <script type="text/javascript" src="../../_static/jquery.js"></script>      <script type="text/javascript" src="../../_static/underscore.js"></script>      <script type="text/javascript" src="../../_static/doctools.js"></script>      <script type="text/javascript" src="../../_static/spongedocs.js"></script>

    <script type="text/javascript" src="../../_static/js/theme.js"></script>

  <script type="text/javascript">
      jQuery(function () {
          SphinxRtdTheme.StickyNav.enable();
      });
  </script>
 
</body>
</html>