evennia/docs/1.0-dev/Contribs/Crafting.html
2021-10-26 22:36:27 +02:00

336 lines
No EOL
28 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Crafting system contrib &#8212; Evennia 1.0-dev documentation</title>
<link rel="stylesheet" href="../_static/nature.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="evennia.contrib.crafting.crafting" href="../api/evennia.contrib.crafting.crafting.html" />
<link rel="prev" title="Contrib modules" href="Contrib-Overview.html" />
</head><body>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="../api/evennia.contrib.crafting.crafting.html" title="evennia.contrib.crafting.crafting"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="Contrib-Overview.html" title="Contrib modules"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="Contrib-Overview.html" accesskey="U">Contrib modules</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Crafting system contrib</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section class="tex2jax_ignore mathjax_ignore" id="crafting-system-contrib">
<h1>Crafting system contrib<a class="headerlink" href="#crafting-system-contrib" title="Permalink to this headline"></a></h1>
<p><em>Contrib by Griatch 2020</em></p>
<div class="versionadded">
<p><span class="versionmodified added">New in version 1.0.</span></p>
</div>
<p>This contrib implements a full Crafting system that can be expanded and modified to fit your game.</p>
<ul class="simple">
<li><p>See the <a class="reference internal" href="../api/evennia.contrib.crafting.crafting.html#evennia-contrib-crafting-crafting"><span class="std std-ref">evennia/contrib/crafting/crafting.py API</span></a> for installation
instructrions.</p></li>
<li><p>See the <a class="reference internal" href="../api/evennia.contrib.crafting.example_recipes.html#evennia-contrib-crafting-example-recipes"><span class="std std-ref">sword example</span></a> for an example of how to design
a crafting tree for crafting a sword from base elements.</p></li>
</ul>
<p>From in-game it uses the new <code class="docutils literal notranslate"><span class="pre">craft</span></code> command:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>&gt; craft bread from flour, eggs, salt, water, yeast using oven, roller
&gt; craft bandage from cloth using scissors
</pre></div>
</div>
<p>The syntax is <code class="docutils literal notranslate"><span class="pre">craft</span> <span class="pre">&lt;recipe&gt;</span> <span class="pre">[from</span> <span class="pre">&lt;ingredient&gt;,...][</span> <span class="pre">using</span> <span class="pre">&lt;tool&gt;,...]</span></code>.</p>
<p>The above example uses the <code class="docutils literal notranslate"><span class="pre">bread</span></code> <em>recipe</em> and requires <code class="docutils literal notranslate"><span class="pre">flour</span></code>, <code class="docutils literal notranslate"><span class="pre">eggs</span></code>, <code class="docutils literal notranslate"><span class="pre">salt</span></code>, <code class="docutils literal notranslate"><span class="pre">water</span></code> and <code class="docutils literal notranslate"><span class="pre">yeast</span></code> objects
to be in your inventory. These will be consumed as part of crafting (baking) the bread.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">oven</span></code> and <code class="docutils literal notranslate"><span class="pre">roller</span></code> are “tools” that can be either in your inventory or in your current location (you are not carrying an oven
around with you after all). Tools are <em>not</em> consumed in the crafting. If the added ingredients/tools matches
the requirements of the recipe, a new <code class="docutils literal notranslate"><span class="pre">bread</span></code> object will appear in the crafters inventory.</p>
<p>If you wanted, you could also picture recipes without any consumables:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">craft</span> <span class="n">fireball</span> <span class="n">using</span> <span class="n">wand</span><span class="p">,</span> <span class="n">spellbook</span>
</pre></div>
</div>
<p>With a little creativity, the recipe concept could be adopted to all sorts of things, like puzzles or
magic systems.</p>
<p>In code, you can craft using the <code class="docutils literal notranslate"><span class="pre">evennia.contrib.crafting.crafting.craft</span></code> function:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.contrib.crafting.crafting</span> <span class="kn">import</span> <span class="n">craft</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">craft</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s2">&quot;recipename&quot;</span><span class="p">,</span> <span class="o">*</span><span class="n">inputs</span><span class="p">)</span>
</pre></div>
</div>
<p>Here, <code class="docutils literal notranslate"><span class="pre">caller</span></code> is the one doing the crafting and <code class="docutils literal notranslate"><span class="pre">*inputs</span></code> is any combination of consumables and/or tool
Objects. The system will identify which is which by the <a class="reference internal" href="../Components/Tags.html"><span class="doc std std-doc">Tags</span></a> on them (see below)
The <code class="docutils literal notranslate"><span class="pre">result</span></code> is always a list.</p>
<section id="adding-new-recipes">
<h2>Adding new recipes<a class="headerlink" href="#adding-new-recipes" title="Permalink to this headline"></a></h2>
<p>A <em>recipe</em> is a class inheriting from <code class="docutils literal notranslate"><span class="pre">evennia.contrib.crafting.crafting.CraftingRecipe</span></code>. This class
implements the most common form of crafting - that using in-game objects. Each recipe is a separate class
which gets initialized with the consumables/tools you provide.</p>
<p>For the <code class="docutils literal notranslate"><span class="pre">craft</span></code> command to find your custom recipes, you need to tell Evennia where they are. Add a new
line to your <code class="docutils literal notranslate"><span class="pre">mygame/server/conf/settings.py</span></code> file, with a list to any new modules with recipe classes.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">CRAFT_RECIPE_MODULES</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;world.myrecipes&quot;</span><span class="p">]</span>
</pre></div>
</div>
<p>(You need to reload after adding this). All global-level classes in these modules (whose names dont start
with underscore) are considered by the system as viable recipes.</p>
<p>Here we assume you created <code class="docutils literal notranslate"><span class="pre">mygame/world/myrecipes.py</span></code> to match the above example setting:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/world/myrecipes.py</span>
<span class="kn">from</span> <span class="nn">evennia.contrib.crafting.crafting</span> <span class="kn">import</span> <span class="n">CraftingRecipe</span>
<span class="k">class</span> <span class="nc">WoodenPuppetRecipe</span><span class="p">(</span><span class="n">CraftingRecipe</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;A puppet&quot;&quot;&quot;</span><span class="s2">&quot;</span>
<span class="n">name</span> <span class="o">=</span> <span class="s2">&quot;wooden puppet&quot;</span> <span class="c1"># name to refer to this recipe as</span>
<span class="n">tool_tags</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;knife&quot;</span><span class="p">]</span>
<span class="n">consumable_tags</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;wood&quot;</span><span class="p">]</span>
<span class="n">output_prototypes</span> <span class="o">=</span> <span class="p">[</span>
<span class="p">{</span><span class="s2">&quot;key&quot;</span><span class="p">:</span> <span class="s2">&quot;A carved wooden doll&quot;</span><span class="p">,</span>
<span class="s2">&quot;typeclass&quot;</span><span class="p">:</span> <span class="s2">&quot;typeclasses.objects.decorations.Toys&quot;</span><span class="p">,</span>
<span class="s2">&quot;desc&quot;</span><span class="p">:</span> <span class="s2">&quot;A small carved doll&quot;</span><span class="p">}</span>
<span class="p">]</span>
</pre></div>
</div>
<p>This specifies which tags to look for in the inputs. It defines a <a class="reference internal" href="../Components/Prototypes.html"><span class="doc std std-doc">Prototype</span></a>
for the recipe to use to spawn the result on the fly (a recipe could spawn more than one result if needed).
Instead of specifying the full prototype-dict, you could also just provide a list of <code class="docutils literal notranslate"><span class="pre">prototype_key</span></code>s to
existing prototypes you have.</p>
<p>After reloading the server, this recipe would now be available to use. To try it we should
create materials and tools to insert into the recipe.</p>
<p>The recipe analyzes inputs, looking for <a class="reference internal" href="../Components/Tags.html"><span class="doc std std-doc">Tags</span></a> with specific tag-categories.
The tag-category used can be set per-recipe using the (<code class="docutils literal notranslate"><span class="pre">.consumable_tag_category</span></code> and
<code class="docutils literal notranslate"><span class="pre">.tool_tag_category</span></code> respectively). The defaults are <code class="docutils literal notranslate"><span class="pre">crafting_material</span></code> and <code class="docutils literal notranslate"><span class="pre">crafting_tool</span></code>. For
the puppet we need one object with the <code class="docutils literal notranslate"><span class="pre">wood</span></code> tag and another with the <code class="docutils literal notranslate"><span class="pre">knife</span></code> tag:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">create_object</span>
<span class="n">knife</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="s2">&quot;Hobby knife&quot;</span><span class="p">,</span> <span class="n">tags</span><span class="o">=</span><span class="p">[(</span><span class="s2">&quot;knife&quot;</span><span class="p">,</span> <span class="s2">&quot;crafting_tool&quot;</span><span class="p">)])</span>
<span class="n">wood</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="s2">&quot;Piece of wood&quot;</span><span class="p">,</span> <span class="n">tags</span><span class="p">[(</span><span class="s2">&quot;wood&quot;</span><span class="p">,</span> <span class="s2">&quot;crafting_material&quot;</span><span class="p">)])</span>
</pre></div>
</div>
<p>Note that the objects can have any name, all that matters is the tag/tag-category. This means if a
“bayonet” also had the “knife” crafting tag, it could also be used to carve a puppet. This is also
potentially interesting for use in puzzles and to allow users to experiment and find alternatives to
know ingredients.</p>
<p>By the way, there is also a simple shortcut for doing this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">tools</span><span class="p">,</span> <span class="n">consumables</span> <span class="o">=</span> <span class="n">WoodenPuppetRecipe</span><span class="o">.</span><span class="n">seed</span><span class="p">()</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">seed</span></code> class-method will create simple dummy objects that fulfills the recipes requirements. This
is great for testing.</p>
<p>Assuming these objects were put in our inventory, we could now craft using the in-game command:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>&gt; craft wooden puppet from wood using hobby knife
</pre></div>
</div>
<p>In code we would do</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.contrub.crafting.crafting</span> <span class="kn">import</span> <span class="n">craft</span>
<span class="n">puppet</span> <span class="o">=</span> <span class="n">craft</span><span class="p">(</span><span class="n">crafter</span><span class="p">,</span> <span class="s2">&quot;wooden puppet&quot;</span><span class="p">,</span> <span class="n">knife</span><span class="p">,</span> <span class="n">wood</span><span class="p">)</span>
</pre></div>
</div>
<p>In the call to <code class="docutils literal notranslate"><span class="pre">craft</span></code>, the order of <code class="docutils literal notranslate"><span class="pre">knife</span></code> and <code class="docutils literal notranslate"><span class="pre">wood</span></code> doesnt matter - the recipe will sort out which
is which based on their tags.</p>
</section>
<section id="deeper-customization-of-recipes">
<h2>Deeper customization of recipes<a class="headerlink" href="#deeper-customization-of-recipes" title="Permalink to this headline"></a></h2>
<p>For customizing recipes further, it helps to understand how to use the recipe-class directly:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">MyRecipe</span><span class="p">(</span><span class="n">CraftingRecipe</span><span class="p">):</span>
<span class="c1"># ...</span>
<span class="n">tools</span><span class="p">,</span> <span class="n">consumables</span> <span class="o">=</span> <span class="n">MyRecipe</span><span class="o">.</span><span class="n">seed</span><span class="p">()</span>
<span class="n">recipe</span> <span class="o">=</span> <span class="n">MyRecipe</span><span class="p">(</span><span class="n">crafter</span><span class="p">,</span> <span class="o">*</span><span class="p">(</span><span class="n">tools</span> <span class="o">+</span> <span class="n">consumables</span><span class="p">))</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">recipe</span><span class="o">.</span><span class="n">craft</span><span class="p">()</span>
</pre></div>
</div>
<p>This is useful for testing and allows you to use the class directly without adding it to a module
in <code class="docutils literal notranslate"><span class="pre">settings.CRAFTING_RECIPE_MODULES</span></code>.</p>
<p>Even without modifying more than the class properties, there are a lot of options to set on
the <code class="docutils literal notranslate"><span class="pre">CraftingRecipe</span></code> class. Easiest is to refer to the
<a class="reference internal" href="../api/evennia.contrib.crafting.crafting.html#evennia.contrib.crafting.crafting.CraftingRecipe" title="evennia.contrib.crafting.crafting.CraftingRecipe"><span class="xref myst py py-class">CraftingRecipe api documentation</span></a>.
For example, you can customize the validation-error messages, decide if the ingredients have
to be exactly right, if a failure still consumes the ingredients or not, and much more.</p>
<p>For even more control you can override hooks in your own class:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">pre_craft</span></code> - this should handle input validation and store its data in <code class="docutils literal notranslate"><span class="pre">.validated_consumables</span></code> and
<code class="docutils literal notranslate"><span class="pre">validated_tools</span></code> respectively. On error, this reports the error to the crafter and raises the
<code class="docutils literal notranslate"><span class="pre">CraftingValidationError</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">craft</span></code> - this will only be called if <code class="docutils literal notranslate"><span class="pre">pre_craft</span></code> finished without an exception. This should
return the result of the crafting, by spawnging the prototypes. Or the empty list if crafting
fails for some reason. This is the place to add skill-checks or random chance if you need it
for your game.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">post_craft</span></code> - this receives the result from <code class="docutils literal notranslate"><span class="pre">craft</span></code> and handles error messages and also deletes
any consumables as needed. It may also modify the result before returning it.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">msg</span></code> - this is a wrapper for <code class="docutils literal notranslate"><span class="pre">self.crafter.msg</span></code> and should be used to send messages to the
crafter. Centralizing this means you can also easily modify the sending style in one place later.</p></li>
</ul>
<p>The class constructor (and the <code class="docutils literal notranslate"><span class="pre">craft</span></code> access function) takes optional <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code>. These are passed
into each crafting hook. These are unused by default but could be used to customize things per-call.</p>
<section id="skilled-crafters">
<h3>Skilled crafters<a class="headerlink" href="#skilled-crafters" title="Permalink to this headline"></a></h3>
<p>What the crafting system does not have out of the box is a skill system - the notion of being able
to fail the craft if you are not skilled enough. Just how skills work is game-dependent, so to add
this you need to make your own recipe parent class and have your recipes inherit from this.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">random</span> <span class="kn">import</span> <span class="n">randint</span>
<span class="kn">from</span> <span class="nn">evennia.contrib.crafting.crafting</span> <span class="kn">import</span> <span class="n">CraftingRecipe</span>
<span class="k">class</span> <span class="nc">SkillRecipe</span><span class="p">(</span><span class="n">CraftingRecipe</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;A recipe that considers skill&quot;&quot;&quot;</span>
<span class="n">difficulty</span> <span class="o">=</span> <span class="mi">20</span>
<span class="k">def</span> <span class="nf">craft</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;The input is ok. Determine if crafting succeeds&quot;&quot;&quot;</span>
<span class="c1"># this is set at initialization</span>
<span class="n">crafter</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">crafte</span>
<span class="c1"># let&#39;s assume the skill is stored directly on the crafter</span>
<span class="c1"># - the skill is 0..100.</span>
<span class="n">crafting_skill</span> <span class="o">=</span> <span class="n">crafter</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">skill_crafting</span>
<span class="c1"># roll for success:</span>
<span class="k">if</span> <span class="n">randint</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">100</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="p">(</span><span class="n">crafting_skill</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">difficulty</span><span class="p">):</span>
<span class="c1"># all is good, craft away</span>
<span class="k">return</span> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">craft</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;You are not good enough to craft this. Better luck next time!&quot;</span><span class="p">)</span>
<span class="k">return</span> <span class="p">[]</span>
</pre></div>
</div>
<p>In this example we introduce a <code class="docutils literal notranslate"><span class="pre">.difficulty</span></code> for the recipe and makes a dice roll to see
if we succed. We would of course make this a lot more immersive and detailed in a full game. In
principle you could customize each recipe just the way you want it, but you could also inherit from
a central parent like this to cut down on work.</p>
<p>The <a class="reference internal" href="../api/evennia.contrib.crafting.example_recipes.html#evennia-contrib-crafting-example-recipes"><span class="std std-ref">sword recipe example module</span></a> also shows an example
of a random skill-check being implemented in a parent and then inherited for multiple use.</p>
</section>
</section>
<section id="even-more-customization">
<h2>Even more customization<a class="headerlink" href="#even-more-customization" title="Permalink to this headline"></a></h2>
<p>If you want to build something even more custom (maybe using different input types of validation logic)
you could also look at the <code class="docutils literal notranslate"><span class="pre">CraftingRecipe</span></code> parent class <code class="docutils literal notranslate"><span class="pre">CraftingRecipeBase</span></code>.
It implements just the minimum needed to be a recipe and for big changes you may be better off starting
from this rather than the more opinionated <code class="docutils literal notranslate"><span class="pre">CraftingRecipe</span></code>.</p>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/evennia_logo.png" alt="Logo"/>
</a></p>
<div id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" />
<input type="submit" value="Go" />
</form>
</div>
</div>
<script>$('#searchbox').show(0);</script>
<p><h3><a href="../index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Crafting system contrib</a><ul>
<li><a class="reference internal" href="#adding-new-recipes">Adding new recipes</a></li>
<li><a class="reference internal" href="#deeper-customization-of-recipes">Deeper customization of recipes</a><ul>
<li><a class="reference internal" href="#skilled-crafters">Skilled crafters</a></li>
</ul>
</li>
<li><a class="reference internal" href="#even-more-customization">Even more customization</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="Contrib-Overview.html"
title="previous chapter">Contrib modules</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="../api/evennia.contrib.crafting.crafting.html"
title="next chapter">evennia.contrib.crafting.crafting</a></p>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="../_sources/Contribs/Crafting.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div><h3>Links</h3>
<ul>
<li><a href="https://www.evennia.com">Home page</a> </li>
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
<li><a href="http://games.evennia.com">Game Index</a> </li>
<li>
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
<a href="https://evennia.blogspot.com/">Blog</a>
</li>
</ul>
<h3>Versions</h3>
<ul>
<li><a href="Crafting.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
</ul>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="../api/evennia.contrib.crafting.crafting.html" title="evennia.contrib.crafting.crafting"
>next</a> |</li>
<li class="right" >
<a href="Contrib-Overview.html" title="Contrib modules"
>previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="Contrib-Overview.html" >Contrib modules</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Crafting system contrib</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2020, The Evennia developer community.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
</div>
</body>
</html>