<pclass="last">You are reading an old version of the Evennia documentation. <ahref="https://www.evennia.com/docs/latest/index.html">The latest version is here</a></p>.
<h1>Making a Persistent object Handler<aclass="headerlink"href="#making-a-persistent-object-handler"title="Permalink to this headline">¶</a></h1>
<p>A <em>handler</em> is a convenient way to group functionality on an object. This allows you to logically
group all actions related to that thing in one place. This tutorial expemplifies how to make your
own handlers and make sure data you store in them survives a reload.</p>
<p>For example, when you do <codeclass="docutils literal notranslate"><spanclass="pre">obj.attributes.get("key")</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">obj.tags.add('tagname')</span></code> you are evoking
handlers stored as <codeclass="docutils literal notranslate"><spanclass="pre">.attributes</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">tags</span></code> on the <codeclass="docutils literal notranslate"><spanclass="pre">obj</span></code>. On these handlers are methods (<codeclass="docutils literal notranslate"><spanclass="pre">get()</span></code>
and <codeclass="docutils literal notranslate"><spanclass="pre">add()</span></code> in this example).</p>
<sectionid="base-handler-example">
<h2>Base Handler example<aclass="headerlink"href="#base-handler-example"title="Permalink to this headline">¶</a></h2>
<p>Here is a base way to set up an on-object handler:</p>
<p>What happens here is that we make a new class <codeclass="docutils literal notranslate"><spanclass="pre">NameChanger</span></code>. We use the
<codeclass="docutils literal notranslate"><spanclass="pre">@lazy_property</span></code> decorator to set it up - this means the handler will not be
actually created until someone really wants to use it, by accessing
<codeclass="docutils literal notranslate"><spanclass="pre">obj.namechange</span></code> later. The decorated <codeclass="docutils literal notranslate"><spanclass="pre">namechange</span></code> method returns the handler
and makes sure to initialize it with <codeclass="docutils literal notranslate"><spanclass="pre">self</span></code> - this becomes the <codeclass="docutils literal notranslate"><spanclass="pre">obj</span></code> inside the
handler!</p>
<p>We then make a silly method <codeclass="docutils literal notranslate"><spanclass="pre">add_to_key</span></code> that uses the handler to manipulate the
key of the object. In this example, the handler is pretty pointless, but
grouping functionality this way can both make for an easy-to-remember API and
can also allow you cache data for easy access - this is how the
<h2>Persistent storage of data in handler<aclass="headerlink"href="#persistent-storage-of-data-in-handler"title="Permalink to this headline">¶</a></h2>
<p>Let’s say we want to track ‘quests’ in our handler. A ‘quest’ is a regular class
that represents the quest. Let’s make it simple as an example:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># for example in mygame/world/quests.py</span>
<p>We expect the dev to make subclasses of this to implement different quests. Exactly how this works
doesn’t matter, the key is that we want to track <codeclass="docutils literal notranslate"><spanclass="pre">self.current_step</span></code> - a property that <em>should
survive a server reload</em>. But so far there is no way for <codeclass="docutils literal notranslate"><spanclass="pre">Quest</span></code> to accomplish this, it’s just a
normal Python class with no connection to the database.</p>
<sectionid="handler-with-save-load-capability">
<h3>Handler with save/load capability<aclass="headerlink"href="#handler-with-save-load-capability"title="Permalink to this headline">¶</a></h3>
<p>Let’s make a <codeclass="docutils literal notranslate"><spanclass="pre">QuestHandler</span></code> that manages a character’s quests.</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># for example in the same mygame/world/quests.py</span>
<p>The handler is just a normal Python class and has no database-storage on its own. But it has a link
to <codeclass="docutils literal notranslate"><spanclass="pre">.obj</span></code>, which is assumed to be a full typeclased entity, on which we can create
persistent <aclass="reference internal"href="../Components/Attributes.html"><spanclass="doc std std-doc">Attributes</span></a> to store things however we like!</p>
<p>We make two helper methods <codeclass="docutils literal notranslate"><spanclass="pre">_load</span></code> and
<codeclass="docutils literal notranslate"><spanclass="pre">_save</span></code> that handles local fetches and saves <codeclass="docutils literal notranslate"><spanclass="pre">storage</span></code> to an Attribute on the object. To avoid
saving more than necessary, we have a property <codeclass="docutils literal notranslate"><spanclass="pre">do_save</span></code>. This we will set in <codeclass="docutils literal notranslate"><spanclass="pre">Quest</span></code> below.</p>
<blockquote>
<div><p>Note that once we <codeclass="docutils literal notranslate"><spanclass="pre">_save</span></code> the data, we need to call <codeclass="docutils literal notranslate"><spanclass="pre">_load</span></code> again. This is to make sure the version we store on the handler is properly de-serialized. If you get an error about data being <codeclass="docutils literal notranslate"><spanclass="pre">bytes</span></code>, you probably missed this step.</p>
</div></blockquote>
</section>
<sectionid="make-quests-storable">
<h3>Make quests storable<aclass="headerlink"href="#make-quests-storable"title="Permalink to this headline">¶</a></h3>
<p>The handler will save all <codeclass="docutils literal notranslate"><spanclass="pre">Quest</span></code> objects as a <codeclass="docutils literal notranslate"><spanclass="pre">dict</span></code> in an Attribute on <codeclass="docutils literal notranslate"><spanclass="pre">obj</span></code>. We are not done yet
though, the <codeclass="docutils literal notranslate"><spanclass="pre">Quest</span></code> object needs access to the <codeclass="docutils literal notranslate"><spanclass="pre">obj</span></code> too - not only will this is important to figure
out if the quest is complete (the <codeclass="docutils literal notranslate"><spanclass="pre">Quest</span></code> must be able to check the quester’s inventory to see if
they have the red key, for example), it also allows the <codeclass="docutils literal notranslate"><spanclass="pre">Quest</span></code> to tell the handler when its state
changed and it should be saved.</p>
<p>We change the <codeclass="docutils literal notranslate"><spanclass="pre">Quest</span></code> such:</p>
<spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">questhandler</span><spanclass="o">.</span><spanclass="n">do_save</span><spanclass="o">=</span><spanclass="kc">True</span><spanclass="c1"># this triggers save in handler!</span>
<spanclass="c1"># [same as before]</span>
</pre></div>
</div>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">Quest.__init__</span></code> now takes <codeclass="docutils literal notranslate"><spanclass="pre">obj</span></code> as argument, to match what we pass to it in
<codeclass="docutils literal notranslate"><spanclass="pre">QuestHandler.add</span></code>. We want to monitor the changing of <codeclass="docutils literal notranslate"><spanclass="pre">current_step</span></code>, so we
make it into a <codeclass="docutils literal notranslate"><spanclass="pre">property</span></code>. When we edit that value, we set the <codeclass="docutils literal notranslate"><spanclass="pre">do_save</span></code> flag on
the handler, which means it will save the status to database once it has checked
progress on all its quests. The <codeclass="docutils literal notranslate"><spanclass="pre">Quest.questhandler</span></code> property allows to easily
get back to the handler (and the object on which it sits).</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">__serialize__dbobjs__</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">__deserialize_dbobjs__</span></code> methods are needed
because <codeclass="docutils literal notranslate"><spanclass="pre">Attributes</span></code> can’t store ‘hidden’ database objects (the <codeclass="docutils literal notranslate"><spanclass="pre">Quest.obj</span></code>
property. The methods help Evennia serialize/deserialize <codeclass="docutils literal notranslate"><spanclass="pre">Quest</span></code> propertly when
the handler saves it. For more information, see <aclass="reference internal"href="../Components/Attributes.html#storing-single-objects"><spanclass="std std-doc">Storing Single
objects</span></a> in the Attributes</p>
</section>
<sectionid="tying-it-all-together">
<h3>Tying it all together<aclass="headerlink"href="#tying-it-all-together"title="Permalink to this headline">¶</a></h3>
<p>The final thing we need to do is to add the quest-handler to the character:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># in mygame/typeclasses/characters.py</span>
<spanclass="kn">from</span><spanclass="nn">.world.quests</span><spanclass="kn">import</span><spanclass="n">QuestHandler</span><spanclass="c1"># as an example</span>
<p>and be sure that quest data is not lost between reloads.</p>
<p>You can find a full-fledged quest-handler example as <aclass="reference internal"href="../api/evennia.contrib.tutorials.evadventure.quests.html#evennia-contrib-tutorials-evadventure-quests"><spanclass="std std-ref">EvAdventure
<pclass="last">You are reading an old version of the Evennia documentation. <ahref="https://www.evennia.com/docs/latest/index.html">The latest version is here</a></p>.