mirror of
https://github.com/evennia/evennia.git
synced 2026-04-04 15:07:16 +02:00
Updated HTML docs.
This commit is contained in:
parent
680d522982
commit
bf918801fd
87 changed files with 2284 additions and 4014 deletions
|
|
@ -18,7 +18,7 @@
|
|||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Objects" href="Objects.html" />
|
||||
<link rel="prev" title="Sessions" href="Sessions.html" />
|
||||
<link rel="prev" title="Typeclasses" href="Typeclasses.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
|
|
@ -33,7 +33,7 @@
|
|||
<a href="Objects.html" title="Objects"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Sessions.html" title="Sessions"
|
||||
<a href="Typeclasses.html" title="Typeclasses"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" accesskey="U">Core Components</a> »</li>
|
||||
|
|
@ -63,15 +63,17 @@
|
|||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Accounts</a><ul>
|
||||
<li><a class="reference internal" href="#how-to-customize-your-own-account-types">How to customize your own Account types</a></li>
|
||||
<li><a class="reference internal" href="#working-with-accounts">Working with Accounts</a><ul>
|
||||
<li><a class="reference internal" href="#properties-on-accounts">Properties on Accounts</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Sessions.html"
|
||||
title="previous chapter">Sessions</a></p>
|
||||
<p class="topless"><a href="Typeclasses.html"
|
||||
title="previous chapter">Typeclasses</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Objects.html"
|
||||
title="next chapter">Objects</a></p>
|
||||
|
|
@ -116,7 +118,7 @@
|
|||
<p>An <em>Account</em> represents a unique game account - one player playing the game. Whereas a player can potentially connect to the game from several Clients/Sessions, they will normally have only one Account.</p>
|
||||
<p>The Account object has no in-game representation. In order to actually get on the game the Account must <em>puppet</em> an <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Object</span></a> (normally a <a class="reference internal" href="Objects.html#characters"><span class="std std-doc">Character</span></a>).</p>
|
||||
<p>Exactly how many Sessions can interact with an Account and its Puppets at once is determined by
|
||||
Evennia’s <a class="reference internal" href="Sessions.html#multisession-mode"><span class="std std-doc">MULTISESSION_MODE</span></a> setting.</p>
|
||||
Evennia’s <span class="xref myst">MULTISESSION_MODE</span></p>
|
||||
<p>Apart from storing login information and other account-specific data, the Account object is what is chatting on Evennia’s default <a class="reference internal" href="Channels.html"><span class="doc std std-doc">Channels</span></a>. It is also a good place to store <a class="reference internal" href="Locks.html"><span class="doc std std-doc">Permissions</span></a> to be consistent between different in-game characters. It can also hold player-level configuration options.</p>
|
||||
<p>The Account object has its own default <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">CmdSet</span></a>, the <code class="docutils literal notranslate"><span class="pre">AccountCmdSet</span></code>. The commands in this set are available to the player no matter which character they are puppeting. Most notably the default game’s <code class="docutils literal notranslate"><span class="pre">exit</span></code>, <code class="docutils literal notranslate"><span class="pre">who</span></code> and chat-channel commands are in the Account cmdset.</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> ooc
|
||||
|
|
@ -128,8 +130,8 @@ Evennia’s <a class="reference internal" href="Sessions.html#multisession-mode"
|
|||
</div>
|
||||
<p>This re-puppets the latest character.</p>
|
||||
<p>Note that the Account object can have, and often does have, a different set of <a class="reference internal" href="Permissions.html"><span class="doc std std-doc">Permissions</span></a> from the Character they control. Normally you should put your permissions on the Account level - this will overrule permissions set on the Character level. For the permissions of the Character to come into play the default <code class="docutils literal notranslate"><span class="pre">quell</span></code> command can be used. This allows for exploring the game using a different permission set (but you can’t escalate your permissions this way - for hierarchical permissions like <code class="docutils literal notranslate"><span class="pre">Builder</span></code>, <code class="docutils literal notranslate"><span class="pre">Admin</span></code> etc, the <em>lower</em> of the permissions on the Character/Account will always be used).</p>
|
||||
<section id="how-to-customize-your-own-account-types">
|
||||
<h2>How to customize your own Account types<a class="headerlink" href="#how-to-customize-your-own-account-types" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="working-with-accounts">
|
||||
<h2>Working with Accounts<a class="headerlink" href="#working-with-accounts" title="Permalink to this headline">¶</a></h2>
|
||||
<p>You will usually not want more than one Account typeclass for all new accounts.</p>
|
||||
<p>An Evennia Account is, per definition, a Python class that includes <code class="docutils literal notranslate"><span class="pre">evennia.DefaultAccount</span></code> among its parents. In <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/accounts.py</span></code> there is an empty class ready for you to modify. Evennia defaults to using this (it inherits directly from <code class="docutils literal notranslate"><span class="pre">DefaultAccount</span></code>).</p>
|
||||
<p>Here’s an example of modifying the default Account class in code:</p>
|
||||
|
|
@ -157,9 +159,8 @@ Evennia’s <a class="reference internal" href="Sessions.html#multisession-mode"
|
|||
<blockquote>
|
||||
<div><p>If you wanted Evennia to default to a completely <em>different</em> Account class located elsewhere, you > must point Evennia to it. Add <code class="docutils literal notranslate"><span class="pre">BASE_ACCOUNT_TYPECLASS</span></code> to your settings file, and give the python path to your custom class as its value. By default this points to <code class="docutils literal notranslate"><span class="pre">typeclasses.accounts.Account</span></code>, the empty template we used above.</p>
|
||||
</div></blockquote>
|
||||
</section>
|
||||
<section id="properties-on-accounts">
|
||||
<h2>Properties on Accounts<a class="headerlink" href="#properties-on-accounts" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Properties on Accounts<a class="headerlink" href="#properties-on-accounts" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Beyond those properties assigned to all typeclassed objects (see <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclasses</span></a>), the Account also has the following custom properties:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">user</span></code> - a unique link to a <code class="docutils literal notranslate"><span class="pre">User</span></code> Django object, representing the logged-in user.</p></li>
|
||||
|
|
@ -184,6 +185,7 @@ the commands found in the cmdset defined by <code class="docutils literal notran
|
|||
<li><p><code class="docutils literal notranslate"><span class="pre">search</span></code> - search for Accounts.</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
|
|
@ -205,7 +207,7 @@ the commands found in the cmdset defined by <code class="docutils literal notran
|
|||
<a href="Objects.html" title="Objects"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Sessions.html" title="Sessions"
|
||||
<a href="Typeclasses.html" title="Typeclasses"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" >Core Components</a> »</li>
|
||||
|
|
|
|||
|
|
@ -63,21 +63,21 @@
|
|||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Attributes</a><ul>
|
||||
<li><a class="reference internal" href="#managing-attributes-in-code">Managing Attributes in Code</a><ul>
|
||||
<li><a class="reference internal" href="#working-with-attributes">Working with Attributes</a><ul>
|
||||
<li><a class="reference internal" href="#using-db">Using .db</a></li>
|
||||
<li><a class="reference internal" href="#using-attributes">Using .attributes</a></li>
|
||||
<li><a class="reference internal" href="#using-attributeproperty">Using AttributeProperty</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#properties-of-attributes">Properties of Attributes</a></li>
|
||||
<li><a class="reference internal" href="#managing-attributes-in-game">Managing Attributes in-game</a></li>
|
||||
<li><a class="reference internal" href="#locking-and-checking-attributes">Locking and checking Attributes</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#what-types-of-data-can-i-save-in-an-attribute">What types of data can I save in an Attribute?</a><ul>
|
||||
<li><a class="reference internal" href="#storing-single-objects">Storing single objects</a></li>
|
||||
<li><a class="reference internal" href="#storing-multiple-objects">Storing multiple objects</a></li>
|
||||
<li><a class="reference internal" href="#retrieving-mutable-objects">Retrieving Mutable objects</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#properties-of-attributes">Properties of Attributes</a></li>
|
||||
<li><a class="reference internal" href="#in-memory-attributes-nattributes">In-memory Attributes (NAttributes)</a><ul>
|
||||
<li><a class="reference internal" href="#persistent-vs-non-persistent">Persistent vs non-persistent</a></li>
|
||||
</ul>
|
||||
|
|
@ -155,27 +155,11 @@
|
|||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<p><em>Attributes</em> allow you to to store arbitrary data on objects and make sure the data survives a server reboot. An Attribute can store pretty much any
|
||||
Python data structure and data type, like numbers, strings, lists, dicts etc. You can also
|
||||
store (references to) database objects like characters and rooms.</p>
|
||||
<ul class="simple">
|
||||
<li><p><a class="reference internal" href="#what-types-of-data-can-i-save-in-an-attribute"><span class="std std-doc">What can be stored in an Attribute</span></a> is a must-read to avoid being surprised, also for experienced developers. Attributes can store <em>almost</em> everything
|
||||
but you need to know the quirks.</p></li>
|
||||
<li><p><a class="reference internal" href="#in-memory-attributes-nattributes"><span class="std std-doc">NAttributes</span></a> are the in-memory, non-persistent
|
||||
siblings of Attributes.</p></li>
|
||||
<li><p><a class="reference internal" href="#managing-attributes-in-game"><span class="std std-doc">Managing Attributes In-game</span></a> for in-game builder commands.</p></li>
|
||||
</ul>
|
||||
<section id="managing-attributes-in-code">
|
||||
<h2>Managing Attributes in Code<a class="headerlink" href="#managing-attributes-in-code" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Attributes are usually handled in code. All <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclassed</span></a> entities
|
||||
(<a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a>, <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a>, <a class="reference internal" href="Scripts.html"><span class="doc std std-doc">Scripts</span></a> and
|
||||
<a class="reference internal" href="Channels.html"><span class="doc std std-doc">Channels</span></a>) can (and usually do) have Attributes associated with them. There
|
||||
<p><em>Attributes</em> allow you to to store arbitrary data on objects and make sure the data survives a server reboot. An Attribute can store pretty much any Python data structure and data type, like numbers, strings, lists, dicts etc. You can also store (references to) database objects like characters and rooms.</p>
|
||||
<section id="working-with-attributes">
|
||||
<h2>Working with Attributes<a class="headerlink" href="#working-with-attributes" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Attributes are usually handled in code. All <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclassed</span></a> entities (<a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a>, <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a>, <a class="reference internal" href="Scripts.html"><span class="doc std std-doc">Scripts</span></a> and <a class="reference internal" href="Channels.html"><span class="doc std std-doc">Channels</span></a>) can (and usually do) have Attributes associated with them. There
|
||||
are three ways to manage Attributes, all of which can be mixed.</p>
|
||||
<ul class="simple">
|
||||
<li><p><a class="reference internal" href="#using-db"><span class="std std-doc">Using the <code class="docutils literal notranslate"><span class="pre">.db</span></code> property shortcut</span></a></p></li>
|
||||
<li><p><a class="reference internal" href="#using-attributes"><span class="std std-doc">Using the <code class="docutils literal notranslate"><span class="pre">.attributes</span></code> manager (<code class="docutils literal notranslate"><span class="pre">AttributeManager</span></code>)</span></a></p></li>
|
||||
<li><p><a class="reference internal" href="#using-attributeproperty"><span class="std std-doc">Using <code class="docutils literal notranslate"><span class="pre">AttributeProperty</span></code> for assigning Attributes in a way similar to Django fields</span></a></p></li>
|
||||
</ul>
|
||||
<section id="using-db">
|
||||
<h3>Using .db<a class="headerlink" href="#using-db" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The simplest way to get/set Attributes is to use the <code class="docutils literal notranslate"><span class="pre">.db</span></code> shortcut. This allows for setting and getting Attributes that lack a <em>category</em> (having category <code class="docutils literal notranslate"><span class="pre">None</span></code>)</p>
|
||||
|
|
@ -239,8 +223,7 @@ the <a class="reference internal" href="../api/evennia.typeclasses.attributes.ht
|
|||
</pre></div>
|
||||
</div>
|
||||
<p>If you don’t specify a category, the Attribute’s <code class="docutils literal notranslate"><span class="pre">category</span></code> will be <code class="docutils literal notranslate"><span class="pre">None</span></code> and can thus also be found via <code class="docutils literal notranslate"><span class="pre">.db</span></code>. <code class="docutils literal notranslate"><span class="pre">None</span></code> is considered a category of its own, so you won’t find <code class="docutils literal notranslate"><span class="pre">None</span></code>-category Attributes mixed with Attributes having categories.</p>
|
||||
<p>Here are the methods of the <code class="docutils literal notranslate"><span class="pre">AttributeHandler</span></code>. See
|
||||
the <a class="reference internal" href="../api/evennia.typeclasses.attributes.html#evennia.typeclasses.attributes.AttributeHandler" title="evennia.typeclasses.attributes.AttributeHandler"><span class="xref myst py py-class">AttributeHandler API</span></a> for more details.</p>
|
||||
<p>Here are the methods of the <code class="docutils literal notranslate"><span class="pre">AttributeHandler</span></code>. See the <a class="reference internal" href="../api/evennia.typeclasses.attributes.html#evennia.typeclasses.attributes.AttributeHandler" title="evennia.typeclasses.attributes.AttributeHandler"><span class="xref myst py py-class">AttributeHandler API</span></a> for more details.</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">has(...)</span></code> - this checks if the object has an Attribute with this key. This is equivalent
|
||||
to doing <code class="docutils literal notranslate"><span class="pre">obj.db.attrname</span></code> except you can also check for a specific `category.</p></li>
|
||||
|
|
@ -330,16 +313,45 @@ The drawback is that without a database precense you can’t find the Attribute
|
|||
<span class="n">char</span><span class="o">.</span><span class="n">attributes</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"sleepy"</span><span class="p">)</span> <span class="c1"># now returns True</span>
|
||||
|
||||
<span class="n">char</span><span class="o">.</span><span class="n">sleepy</span> <span class="c1"># now returns True, involves db access</span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>You can e.g. <code class="docutils literal notranslate"><span class="pre">del</span> <span class="pre">char.strength</span></code> to set the value back to the default (the value defined
|
||||
in the <code class="docutils literal notranslate"><span class="pre">AttributeProperty</span></code>).</p>
|
||||
<p>You can e.g. <code class="docutils literal notranslate"><span class="pre">del</span> <span class="pre">char.strength</span></code> to set the value back to the default (the value defined in the <code class="docutils literal notranslate"><span class="pre">AttributeProperty</span></code>).</p>
|
||||
<p>See the <a class="reference internal" href="../api/evennia.typeclasses.attributes.html#evennia.typeclasses.attributes.AttributeProperty" title="evennia.typeclasses.attributes.AttributeProperty"><span class="xref myst py py-class">AttributeProperty API</span></a> for more details on how to create it with special options, like giving access-restrictions.</p>
|
||||
</section>
|
||||
<section id="properties-of-attributes">
|
||||
<h3>Properties of Attributes<a class="headerlink" href="#properties-of-attributes" title="Permalink to this headline">¶</a></h3>
|
||||
<p>An <code class="docutils literal notranslate"><span class="pre">Attribute</span></code> object is stored in the database. It has the following properties:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">key</span></code> - the name of the Attribute. When doing e.g. <code class="docutils literal notranslate"><span class="pre">obj.db.attrname</span> <span class="pre">=</span> <span class="pre">value</span></code>, this property is set
|
||||
to <code class="docutils literal notranslate"><span class="pre">attrname</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">value</span></code> - this is the value of the Attribute. This value can be anything which can be pickled -
|
||||
objects, lists, numbers or what have you (see
|
||||
<a class="reference internal" href="#what-types-of-data-can-i-save-in-an-attribute"><span class="std std-doc">this section</span></a> for more info). In the
|
||||
example
|
||||
<code class="docutils literal notranslate"><span class="pre">obj.db.attrname</span> <span class="pre">=</span> <span class="pre">value</span></code>, the <code class="docutils literal notranslate"><span class="pre">value</span></code> is stored here.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">category</span></code> - this is an optional property that is set to None for most Attributes. Setting this
|
||||
allows to use Attributes for different functionality. This is usually not needed unless you want
|
||||
to use Attributes for very different functionality (<a class="reference internal" href="Nicks.html"><span class="doc std std-doc">Nicks</span></a> is an example of using
|
||||
Attributes in this way). To modify this property you need to use the <a class="reference internal" href="#attributes"><span class="std std-doc">Attribute Handler</span></a></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">strvalue</span></code> - this is a separate value field that only accepts strings. This severely limits the
|
||||
data possible to store, but allows for easier database lookups. This property is usually not used
|
||||
except when re-using Attributes for some other purpose (<a class="reference internal" href="Nicks.html"><span class="doc std std-doc">Nicks</span></a> use it). It is only
|
||||
accessible via the <a class="reference internal" href="#attributes"><span class="std std-doc">Attribute Handler</span></a>.</p></li>
|
||||
</ul>
|
||||
<p>There are also two special properties:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">attrtype</span></code> - this is used internally by Evennia to separate <a class="reference internal" href="Nicks.html"><span class="doc std std-doc">Nicks</span></a>, from Attributes (Nicks
|
||||
use Attributes behind the scenes).</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">model</span></code> - this is a <em>natural-key</em> describing the model this Attribute is attached to. This is on
|
||||
the form <em>appname.modelclass</em>, like <code class="docutils literal notranslate"><span class="pre">objects.objectdb</span></code>. It is used by the Attribute and
|
||||
NickHandler to quickly sort matches in the database. Neither this nor <code class="docutils literal notranslate"><span class="pre">attrtype</span></code> should normally
|
||||
need to be modified.</p></li>
|
||||
</ul>
|
||||
<p>Non-database attributes are not stored in the database and have no equivalence
|
||||
to <code class="docutils literal notranslate"><span class="pre">category</span></code> nor <code class="docutils literal notranslate"><span class="pre">strvalue</span></code>, <code class="docutils literal notranslate"><span class="pre">attrtype</span></code> or <code class="docutils literal notranslate"><span class="pre">model</span></code>.</p>
|
||||
</section>
|
||||
<section id="managing-attributes-in-game">
|
||||
<h2>Managing Attributes in-game<a class="headerlink" href="#managing-attributes-in-game" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Managing Attributes in-game<a class="headerlink" href="#managing-attributes-in-game" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Attributes are mainly used by code. But one can also allow the builder to use Attributes to
|
||||
‘turn knobs’ in-game. For example a builder could want to manually tweak the “level” Attribute of an
|
||||
enemy NPC to lower its difficuly.</p>
|
||||
|
|
@ -375,7 +387,7 @@ set mypobj/mystring = [1, 2, foo] # foo is invalid Python (no quotes)
|
|||
<p>For the last line you’ll get a warning and the value instead will be saved as a string <code class="docutils literal notranslate"><span class="pre">"[1,</span> <span class="pre">2,</span> <span class="pre">foo]"</span></code>.</p>
|
||||
</section>
|
||||
<section id="locking-and-checking-attributes">
|
||||
<h2>Locking and checking Attributes<a class="headerlink" href="#locking-and-checking-attributes" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Locking and checking Attributes<a class="headerlink" href="#locking-and-checking-attributes" title="Permalink to this headline">¶</a></h3>
|
||||
<p>While the <code class="docutils literal notranslate"><span class="pre">set</span></code> command is limited to builders, individual Attributes are usually not
|
||||
locked down. You may want to lock certain sensitive Attributes, in particular for games
|
||||
where you allow player building. You can add such limitations by adding a <a class="reference internal" href="Locks.html"><span class="doc std std-doc">lock string</span></a>
|
||||
|
|
@ -418,6 +430,7 @@ To check the <code class="docutils literal notranslate"><span class="pre">lockst
|
|||
<p>The same keywords are available to use with <code class="docutils literal notranslate"><span class="pre">obj.attributes.set()</span></code> and <code class="docutils literal notranslate"><span class="pre">obj.attributes.remove()</span></code>,
|
||||
those will check for the <code class="docutils literal notranslate"><span class="pre">attredit</span></code> lock type.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="what-types-of-data-can-i-save-in-an-attribute">
|
||||
<h2>What types of data can I save in an Attribute?<a class="headerlink" href="#what-types-of-data-can-i-save-in-an-attribute" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The database doesn’t know anything about Python objects, so Evennia must <em>serialize</em> Attribute
|
||||
|
|
@ -613,38 +626,6 @@ instead of <code class="docutils literal notranslate"><span class="pre">_SaverLi
|
|||
explicitly save it back to the Attribute for it to save.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="properties-of-attributes">
|
||||
<h2>Properties of Attributes<a class="headerlink" href="#properties-of-attributes" title="Permalink to this headline">¶</a></h2>
|
||||
<p>An <code class="docutils literal notranslate"><span class="pre">Attribute</span></code> object is stored in the database. It has the following properties:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">key</span></code> - the name of the Attribute. When doing e.g. <code class="docutils literal notranslate"><span class="pre">obj.db.attrname</span> <span class="pre">=</span> <span class="pre">value</span></code>, this property is set
|
||||
to <code class="docutils literal notranslate"><span class="pre">attrname</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">value</span></code> - this is the value of the Attribute. This value can be anything which can be pickled -
|
||||
objects, lists, numbers or what have you (see
|
||||
<a class="reference internal" href="#what-types-of-data-can-i-save-in-an-attribute"><span class="std std-doc">this section</span></a> for more info). In the
|
||||
example
|
||||
<code class="docutils literal notranslate"><span class="pre">obj.db.attrname</span> <span class="pre">=</span> <span class="pre">value</span></code>, the <code class="docutils literal notranslate"><span class="pre">value</span></code> is stored here.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">category</span></code> - this is an optional property that is set to None for most Attributes. Setting this
|
||||
allows to use Attributes for different functionality. This is usually not needed unless you want
|
||||
to use Attributes for very different functionality (<a class="reference internal" href="Nicks.html"><span class="doc std std-doc">Nicks</span></a> is an example of using
|
||||
Attributes in this way). To modify this property you need to use the <a class="reference internal" href="#attributes"><span class="std std-doc">Attribute Handler</span></a></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">strvalue</span></code> - this is a separate value field that only accepts strings. This severely limits the
|
||||
data possible to store, but allows for easier database lookups. This property is usually not used
|
||||
except when re-using Attributes for some other purpose (<a class="reference internal" href="Nicks.html"><span class="doc std std-doc">Nicks</span></a> use it). It is only
|
||||
accessible via the <a class="reference internal" href="#attributes"><span class="std std-doc">Attribute Handler</span></a>.</p></li>
|
||||
</ul>
|
||||
<p>There are also two special properties:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">attrtype</span></code> - this is used internally by Evennia to separate <a class="reference internal" href="Nicks.html"><span class="doc std std-doc">Nicks</span></a>, from Attributes (Nicks
|
||||
use Attributes behind the scenes).</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">model</span></code> - this is a <em>natural-key</em> describing the model this Attribute is attached to. This is on
|
||||
the form <em>appname.modelclass</em>, like <code class="docutils literal notranslate"><span class="pre">objects.objectdb</span></code>. It is used by the Attribute and
|
||||
NickHandler to quickly sort matches in the database. Neither this nor <code class="docutils literal notranslate"><span class="pre">attrtype</span></code> should normally
|
||||
need to be modified.</p></li>
|
||||
</ul>
|
||||
<p>Non-database attributes are not stored in the database and have no equivalence
|
||||
to <code class="docutils literal notranslate"><span class="pre">category</span></code> nor <code class="docutils literal notranslate"><span class="pre">strvalue</span></code>, <code class="docutils literal notranslate"><span class="pre">attrtype</span></code> or <code class="docutils literal notranslate"><span class="pre">model</span></code>.</p>
|
||||
</section>
|
||||
<section id="in-memory-attributes-nattributes">
|
||||
<h2>In-memory Attributes (NAttributes)<a class="headerlink" href="#in-memory-attributes-nattributes" title="Permalink to this headline">¶</a></h2>
|
||||
<p><em>NAttributes</em> (short of Non-database Attributes) mimic Attributes in most things except they
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
<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="Batch Command Processor" href="Batch-Command-Processor.html" />
|
||||
<link rel="prev" title="Batch Processors" href="Batch-Processors.html" />
|
||||
<link rel="next" title="Inputfuncs" href="Inputfuncs.html" />
|
||||
<link rel="prev" title="Batch Command Processor" href="Batch-Command-Processor.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
|
|
@ -30,13 +30,14 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Batch-Command-Processor.html" title="Batch Command Processor"
|
||||
<a href="Inputfuncs.html" title="Inputfuncs"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Batch-Processors.html" title="Batch Processors"
|
||||
<a href="Batch-Command-Processor.html" title="Batch Command Processor"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" accesskey="U">Core Components</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" >Core Components</a> »</li>
|
||||
<li class="nav-item nav-item-2"><a href="Batch-Processors.html" accesskey="U">Batch Processors</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Batch Code Processor</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
|
|
@ -63,7 +64,6 @@
|
|||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Batch Code Processor</a><ul>
|
||||
<li><a class="reference internal" href="#basic-usage">Basic Usage</a></li>
|
||||
<li><a class="reference internal" href="#the-batch-file">The batch file</a></li>
|
||||
<li><a class="reference internal" href="#debug-mode">Debug mode</a></li>
|
||||
<li><a class="reference internal" href="#interactive-mode">Interactive mode</a></li>
|
||||
|
|
@ -79,11 +79,11 @@
|
|||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Batch-Processors.html"
|
||||
title="previous chapter">Batch Processors</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Batch-Command-Processor.html"
|
||||
title="next chapter">Batch Command Processor</a></p>
|
||||
title="previous chapter">Batch Command Processor</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Inputfuncs.html"
|
||||
title="next chapter">Inputfuncs</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
|
|
@ -116,59 +116,29 @@
|
|||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="batch-code-processor">
|
||||
<h1>Batch Code Processor<a class="headerlink" href="#batch-code-processor" title="Permalink to this headline">¶</a></h1>
|
||||
<p>For an introduction and motivation to using batch processors, see <a class="reference internal" href="Batch-Processors.html"><span class="doc std std-doc">here</span></a>. This
|
||||
page describes the Batch-<em>code</em> processor. The Batch-<em>command</em> one is covered [here](Batch-Command-
|
||||
Processor).</p>
|
||||
<section id="basic-usage">
|
||||
<h2>Basic Usage<a class="headerlink" href="#basic-usage" title="Permalink to this headline">¶</a></h2>
|
||||
<p>For an introduction and motivation to using batch processors, see <a class="reference internal" href="Batch-Processors.html"><span class="doc std std-doc">here</span></a>. This page describes the Batch-<em>code</em> processor. The Batch-<em>command</em> one is covered [here](Batch-Command- Processor).</p>
|
||||
<p>The batch-code processor is a superuser-only function, invoked by</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > @batchcode path.to.batchcodefile
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > batchcode path.to.batchcodefile
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Where <code class="docutils literal notranslate"><span class="pre">path.to.batchcodefile</span></code> is the path to a <em>batch-code file</em>. Such a file should have a name
|
||||
ending in “<code class="docutils literal notranslate"><span class="pre">.py</span></code>” (but you shouldn’t include that in the path). The path is given like a python path
|
||||
relative to a folder you define to hold your batch files, set by <code class="docutils literal notranslate"><span class="pre">BATCH_IMPORT_PATH</span></code> in your
|
||||
settings. Default folder is (assuming your game is called “mygame”) <code class="docutils literal notranslate"><span class="pre">mygame/world/</span></code>. So if you want
|
||||
to run the example batch file in <code class="docutils literal notranslate"><span class="pre">mygame/world/batch_code.py</span></code>, you could simply use</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > @batchcode batch_code
|
||||
<p>Where <code class="docutils literal notranslate"><span class="pre">path.to.batchcodefile</span></code> is the path to a <em>batch-code file</em>. Such a file should have a name ending in “<code class="docutils literal notranslate"><span class="pre">.py</span></code>” (but you shouldn’t include that in the path). The path is given like a python path relative to a folder you define to hold your batch files, set by <code class="docutils literal notranslate"><span class="pre">BATCH_IMPORT_PATH</span></code> in your settings. Default folder is (assuming your game is called “mygame”) <code class="docutils literal notranslate"><span class="pre">mygame/world/</span></code>. So if you want to run the example batch file in <code class="docutils literal notranslate"><span class="pre">mygame/world/batch_code.py</span></code>, you could simply use</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > batchcode batch_code
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This will try to run through the entire batch file in one go. For more gradual, <em>interactive</em>
|
||||
control you can use the <code class="docutils literal notranslate"><span class="pre">/interactive</span></code> switch. The switch <code class="docutils literal notranslate"><span class="pre">/debug</span></code> will put the processor in
|
||||
<em>debug</em> mode. Read below for more info.</p>
|
||||
</section>
|
||||
<p>This will try to run through the entire batch file in one go. For more gradual, <em>interactive</em> control you can use the <code class="docutils literal notranslate"><span class="pre">/interactive</span></code> switch. The switch <code class="docutils literal notranslate"><span class="pre">/debug</span></code> will put the processor in <em>debug</em> mode. Read below for more info.</p>
|
||||
<section id="the-batch-file">
|
||||
<h2>The batch file<a class="headerlink" href="#the-batch-file" title="Permalink to this headline">¶</a></h2>
|
||||
<p>A batch-code file is a normal Python file. The difference is that since the batch processor loads
|
||||
and executes the file rather than importing it, you can reliably update the file, then call it
|
||||
again, over and over and see your changes without needing to <code class="docutils literal notranslate"><span class="pre">@reload</span></code> the server. This makes for
|
||||
easy testing. In the batch-code file you have also access to the following global variables:</p>
|
||||
<p>A batch-code file is a normal Python file. The difference is that since the batch processor loads and executes the file rather than importing it, you can reliably update the file, then call it again, over and over and see your changes without needing to <code class="docutils literal notranslate"><span class="pre">reload</span></code> the server. This makes for easy testing. In the batch-code file you have also access to the following global variables:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">caller</span></code> - This is a reference to the object running the batchprocessor.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">DEBUG</span></code> - This is a boolean that lets you determine if this file is currently being run in debug-
|
||||
mode or not. See below how this can be useful.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">DEBUG</span></code> - This is a boolean that lets you determine if this file is currently being run in debug-mode or not. See below how this can be useful.</p></li>
|
||||
</ul>
|
||||
<p>Running a plain Python file through the processor will just execute the file from beginning to end.
|
||||
If you want to get more control over the execution you can use the processor’s <em>interactive</em> mode.
|
||||
This runs certain code blocks on their own, rerunning only that part until you are happy with it. In
|
||||
order to do this you need to add special markers to your file to divide it up into smaller chunks.
|
||||
These take the form of comments, so the file remains valid Python.</p>
|
||||
<p>Here are the rules of syntax of the batch-code <code class="docutils literal notranslate"><span class="pre">*.py</span></code> file.</p>
|
||||
<p>Running a plain Python file through the processor will just execute the file from beginning to end. If you want to get more control over the execution you can use the processor’s <em>interactive</em> mode. This runs certain code blocks on their own, rerunning only that part until you are happy with it. In order to do this you need to add special markers to your file to divide it up into smaller chunks. These take the form of comments, so the file remains valid Python.</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">#CODE</span></code> as the first on a line marks the start of a <em>code</em> block. It will last until the beginning
|
||||
of another marker or the end of the file. Code blocks contain functional python code. Each <code class="docutils literal notranslate"><span class="pre">#CODE</span></code>
|
||||
block will be run in complete isolation from other parts of the file, so make sure it’s self-
|
||||
contained.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">#HEADER</span></code> as the first on a line marks the start of a <em>header</em> block. It lasts until the next
|
||||
marker or the end of the file. This is intended to hold imports and variables you will need for all
|
||||
other blocks .All python code defined in a header block will always be inserted at the top of every
|
||||
<code class="docutils literal notranslate"><span class="pre">#CODE</span></code> blocks in the file. You may have more than one <code class="docutils literal notranslate"><span class="pre">#HEADER</span></code> block, but that is equivalent to
|
||||
having one big one. Note that you can’t exchange data between code blocks, so editing a header-
|
||||
variable in one code block won’t affect that variable in any other code block!</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">#INSERT</span> <span class="pre">path.to.file</span></code> will insert another batchcode (Python) file at that position.</p></li>
|
||||
<li><p>A <code class="docutils literal notranslate"><span class="pre">#</span></code> that is not starting a <code class="docutils literal notranslate"><span class="pre">#HEADER</span></code>, <code class="docutils literal notranslate"><span class="pre">#CODE</span></code> or <code class="docutils literal notranslate"><span class="pre">#INSERT</span></code> instruction is considered a comment.</p></li>
|
||||
<li><p>Inside a block, normal Python syntax rules apply. For the sake of indentation, each block acts as
|
||||
a separate python module.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">#CODE</span></code> as the first on a line marks the start of a <em>code</em> block. It will last until the beginning of another marker or the end of the file. Code blocks contain functional python code. Each <code class="docutils literal notranslate"><span class="pre">#CODE</span></code> block will be run in complete isolation from other parts of the file, so make sure it’s self- contained.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">#HEADER</span></code> as the first on a line marks the start of a <em>header</em> block. It lasts until the next marker or the end of the file. This is intended to hold imports and variables you will need for all other blocks .All python code defined in a header block will always be inserted at the top of every <code class="docutils literal notranslate"><span class="pre">#CODE</span></code> blocks in the file. You may have more than one <code class="docutils literal notranslate"><span class="pre">#HEADER</span></code> block, but that is equivalent to having one big one. Note that you can’t exchange data between code blocks, so editing a header- variable in one code block won’t affect that variable in any other code block!</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">#INSERT</span> <span class="pre">path.to.file</span></code> will insert another batchcode (Python) file at that position. - A <code class="docutils literal notranslate"><span class="pre">#</span></code> that is not starting a <code class="docutils literal notranslate"><span class="pre">#HEADER</span></code>, <code class="docutils literal notranslate"><span class="pre">#CODE</span></code> or <code class="docutils literal notranslate"><span class="pre">#INSERT</span></code> instruction is considered a comment.</p></li>
|
||||
<li><p>Inside a block, normal Python syntax rules apply. For the sake of indentation, each block acts as a separate python module.</p></li>
|
||||
</ul>
|
||||
<p>Below is a version of the example file found in <code class="docutils literal notranslate"><span class="pre">evennia/contrib/tutorial_examples/</span></code>.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1">#</span>
|
||||
|
|
@ -215,36 +185,24 @@ a separate python module.</p></li>
|
|||
<section id="debug-mode">
|
||||
<h2>Debug mode<a class="headerlink" href="#debug-mode" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Try to run the example script with</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > @batchcode/debug tutorial_examples.example_batch_code
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > batchcode/debug tutorial_examples.example_batch_code
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The batch script will run to the end and tell you it completed. You will also get messages that the
|
||||
button and the two pieces of furniture were created. Look around and you should see the button
|
||||
there. But you won’t see any chair nor a table! This is because we ran this with the <code class="docutils literal notranslate"><span class="pre">/debug</span></code>
|
||||
switch, which is directly visible as <code class="docutils literal notranslate"><span class="pre">DEBUG==True</span></code> inside the script. In the above example we
|
||||
handled this state by deleting the chair and table again.</p>
|
||||
<p>The debug mode is intended to be used when you test out a batchscript. Maybe you are looking for
|
||||
bugs in your code or try to see if things behave as they should. Running the script over and over
|
||||
would then create an ever-growing stack of chairs and tables, all with the same name. You would have
|
||||
to go back and painstakingly delete them later.</p>
|
||||
<p>The batch script will run to the end and tell you it completed. You will also get messages that the button and the two pieces of furniture were created. Look around and you should see the button there. But you won’t see any chair nor a table! This is because we ran this with the <code class="docutils literal notranslate"><span class="pre">/debug</span></code> switch, which is directly visible as <code class="docutils literal notranslate"><span class="pre">DEBUG==True</span></code> inside the script. In the above example we handled this state by deleting the chair and table again.</p>
|
||||
<p>The debug mode is intended to be used when you test out a batchscript. Maybe you are looking for bugs in your code or try to see if things behave as they should. Running the script over and over would then create an ever-growing stack of chairs and tables, all with the same name. You would have to go back and painstakingly delete them later.</p>
|
||||
</section>
|
||||
<section id="interactive-mode">
|
||||
<h2>Interactive mode<a class="headerlink" href="#interactive-mode" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Interactive mode works very similar to the [batch-command processor counterpart](Batch-Command-
|
||||
Processor). It allows you more step-wise control over how the batch file is executed. This is useful
|
||||
for debugging or for picking and choosing only particular blocks to run. Use <code class="docutils literal notranslate"><span class="pre">@batchcode</span></code> with the
|
||||
<code class="docutils literal notranslate"><span class="pre">/interactive</span></code> flag to enter interactive mode.</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > @batchcode/interactive tutorial_examples.batch_code
|
||||
<p>Interactive mode works very similar to the [batch-command processor counterpart](Batch-Command- Processor). It allows you more step-wise control over how the batch file is executed. This is useful for debugging or for picking and choosing only particular blocks to run. Use <code class="docutils literal notranslate"><span class="pre">batchcode</span></code> with the <code class="docutils literal notranslate"><span class="pre">/interactive</span></code> flag to enter interactive mode.</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > batchcode/interactive tutorial_examples.batch_code
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>You should see the following:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>01/02: red_button = create_object(red_button.RedButton, [...] (hh for help)
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This shows that you are on the first <code class="docutils literal notranslate"><span class="pre">#CODE</span></code> block, the first of only two commands in this batch
|
||||
file. Observe that the block has <em>not</em> actually been executed at this point!</p>
|
||||
<p>To take a look at the full code snippet you are about to run, use <code class="docutils literal notranslate"><span class="pre">ll</span></code> (a batch-processor version of
|
||||
<code class="docutils literal notranslate"><span class="pre">look</span></code>).</p>
|
||||
<p>This shows that you are on the first <code class="docutils literal notranslate"><span class="pre">#CODE</span></code> block, the first of only two commands in this batch file. Observe that the block has <em>not</em> actually been executed at this point!</p>
|
||||
<p>To take a look at the full code snippet you are about to run, use <code class="docutils literal notranslate"><span class="pre">ll</span></code> (a batch-processor version of <code class="docutils literal notranslate"><span class="pre">look</span></code>).</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="kn">from</span> <span class="nn">evennia.utils</span> <span class="kn">import</span> <span class="n">create</span><span class="p">,</span> <span class="n">search</span>
|
||||
<span class="kn">from</span> <span class="nn">evennia.contrib.tutorial_examples</span> <span class="kn">import</span> <span class="n">red_button</span>
|
||||
<span class="kn">from</span> <span class="nn">typeclasses.objects</span> <span class="kn">import</span> <span class="n">Object</span>
|
||||
|
|
@ -258,21 +216,14 @@ file. Observe that the block has <em>not</em> actually been executed at this poi
|
|||
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"A red button was created."</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Compare with the example code given earlier. Notice how the content of <code class="docutils literal notranslate"><span class="pre">#HEADER</span></code> has been pasted at
|
||||
the top of the <code class="docutils literal notranslate"><span class="pre">#CODE</span></code> block. Use <code class="docutils literal notranslate"><span class="pre">pp</span></code> to actually execute this block (this will create the button
|
||||
<p>Compare with the example code given earlier. Notice how the content of <code class="docutils literal notranslate"><span class="pre">#HEADER</span></code> has been pasted at the top of the <code class="docutils literal notranslate"><span class="pre">#CODE</span></code> block. Use <code class="docutils literal notranslate"><span class="pre">pp</span></code> to actually execute this block (this will create the button
|
||||
and give you a message). Use <code class="docutils literal notranslate"><span class="pre">nn</span></code> (next) to go to the next command. Use <code class="docutils literal notranslate"><span class="pre">hh</span></code> for a list of commands.</p>
|
||||
<p>If there are tracebacks, fix them in the batch file, then use <code class="docutils literal notranslate"><span class="pre">rr</span></code> to reload the file. You will
|
||||
still be at the same code block and can rerun it easily with <code class="docutils literal notranslate"><span class="pre">pp</span></code> as needed. This makes for a simple
|
||||
debug cycle. It also allows you to rerun individual troublesome blocks - as mentioned, in a large
|
||||
batch file this can be very useful (don’t forget the <code class="docutils literal notranslate"><span class="pre">/debug</span></code> mode either).</p>
|
||||
<p>Use <code class="docutils literal notranslate"><span class="pre">nn</span></code> and <code class="docutils literal notranslate"><span class="pre">bb</span></code> (next and back) to step through the file; e.g. <code class="docutils literal notranslate"><span class="pre">nn</span> <span class="pre">12</span></code> will jump 12 steps forward
|
||||
(without processing any blocks in between). All normal commands of Evennia should work too while
|
||||
working in interactive mode.</p>
|
||||
<p>If there are tracebacks, fix them in the batch file, then use <code class="docutils literal notranslate"><span class="pre">rr</span></code> to reload the file. You will still be at the same code block and can rerun it easily with <code class="docutils literal notranslate"><span class="pre">pp</span></code> as needed. This makes for a simple debug cycle. It also allows you to rerun individual troublesome blocks - as mentioned, in a large batch file this can be very useful (don’t forget the <code class="docutils literal notranslate"><span class="pre">/debug</span></code> mode either).</p>
|
||||
<p>Use <code class="docutils literal notranslate"><span class="pre">nn</span></code> and <code class="docutils literal notranslate"><span class="pre">bb</span></code> (next and back) to step through the file; e.g. <code class="docutils literal notranslate"><span class="pre">nn</span> <span class="pre">12</span></code> will jump 12 steps forward (without processing any blocks in between). All normal commands of Evennia should work too while working in interactive mode.</p>
|
||||
</section>
|
||||
<section id="limitations-and-caveats">
|
||||
<h2>Limitations and Caveats<a class="headerlink" href="#limitations-and-caveats" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The batch-code processor is by far the most flexible way to build a world in Evennia. There are
|
||||
however some caveats you need to keep in mind.</p>
|
||||
<p>The batch-code processor is by far the most flexible way to build a world in Evennia. There are however some caveats you need to keep in mind.</p>
|
||||
<section id="safety">
|
||||
<h3>Safety<a class="headerlink" href="#safety" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Or rather the lack of it. There is a reason only <em>superusers</em> are allowed to run the batch-code
|
||||
|
|
@ -286,24 +237,11 @@ really do anything outside what the game commands allow them to.</p>
|
|||
</section>
|
||||
<section id="no-communication-between-code-blocks">
|
||||
<h3>No communication between code blocks<a class="headerlink" href="#no-communication-between-code-blocks" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Global variables won’t work in code batch files, each block is executed as stand-alone environments.
|
||||
<code class="docutils literal notranslate"><span class="pre">#HEADER</span></code> blocks are literally pasted on top of each <code class="docutils literal notranslate"><span class="pre">#CODE</span></code> block so updating some header-variable
|
||||
in your block will not make that change available in another block. Whereas a python execution
|
||||
limitation, allowing this would also lead to very hard-to-debug code when using the interactive mode</p>
|
||||
<ul class="simple">
|
||||
<li><p>this would be a classical example of “spaghetti code”.</p></li>
|
||||
</ul>
|
||||
<p>The main practical issue with this is when building e.g. a room in one code block and later want to
|
||||
connect that room with a room you built in the current block. There are two ways to do this:</p>
|
||||
<p>Global variables won’t work in code batch files, each block is executed as stand-alone environments. <code class="docutils literal notranslate"><span class="pre">#HEADER</span></code> blocks are literally pasted on top of each <code class="docutils literal notranslate"><span class="pre">#CODE</span></code> block so updating some header-variable in your block will not make that change available in another block. Whereas a python execution limitation, allowing this would also lead to very hard-to-debug code when using the interactive mode - this would be a classical example of “spaghetti code”.</p>
|
||||
<p>The main practical issue with this is when building e.g. a room in one code block and later want to connect that room with a room you built in the current block. There are two ways to do this:</p>
|
||||
<ul>
|
||||
<li><p>Perform a database search for the name of the room you created (since you cannot know in advance
|
||||
which dbref it got assigned). The problem is that a name may not be unique (you may have a lot of “A
|
||||
dark forest” rooms). There is an easy way to handle this though - use <a class="reference internal" href="Tags.html"><span class="doc std std-doc">Tags</span></a> or <em>Aliases</em>. You
|
||||
can assign any number of tags and/or aliases to any object. Make sure that one of those tags or
|
||||
aliases is unique to the room (like “room56”) and you will henceforth be able to always uniquely
|
||||
search and find it later.</p></li>
|
||||
<li><p>Use the <code class="docutils literal notranslate"><span class="pre">caller</span></code> global property as an inter-block storage. For example, you could have a
|
||||
dictionary of room references in an <code class="docutils literal notranslate"><span class="pre">ndb</span></code>:</p>
|
||||
<li><p>Perform a database search for the name of the room you created (since you cannot know in advance which dbref it got assigned). The problem is that a name may not be unique (you may have a lot of “A dark forest” rooms). There is an easy way to handle this though - use <a class="reference internal" href="Tags.html"><span class="doc std std-doc">Tags</span></a> or <em>Aliases</em>. You can assign any number of tags and/or aliases to any object. Make sure that one of those tags or aliases is unique to the room (like “room56”) and you will henceforth be able to always uniquely search and find it later.</p></li>
|
||||
<li><p>Use the <code class="docutils literal notranslate"><span class="pre">caller</span></code> global property as an inter-block storage. For example, you could have a dictionary of room references in an <code class="docutils literal notranslate"><span class="pre">ndb</span></code>:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1">#HEADER </span>
|
||||
<span class="k">if</span> <span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">all_rooms</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">all_rooms</span> <span class="o">=</span> <span class="p">{}</span>
|
||||
|
|
@ -320,23 +258,16 @@ dictionary of room references in an <code class="docutils literal notranslate"><
|
|||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Note how we check in <code class="docutils literal notranslate"><span class="pre">#HEADER</span></code> if <code class="docutils literal notranslate"><span class="pre">caller.ndb.all_rooms</span></code> doesn’t already exist before creating the
|
||||
dict. Remember that <code class="docutils literal notranslate"><span class="pre">#HEADER</span></code> is copied in front of every <code class="docutils literal notranslate"><span class="pre">#CODE</span></code> block. Without that <code class="docutils literal notranslate"><span class="pre">if</span></code> statement
|
||||
<p>Note how we check in <code class="docutils literal notranslate"><span class="pre">#HEADER</span></code> if <code class="docutils literal notranslate"><span class="pre">caller.ndb.all_rooms</span></code> doesn’t already exist before creating the dict. Remember that <code class="docutils literal notranslate"><span class="pre">#HEADER</span></code> is copied in front of every <code class="docutils literal notranslate"><span class="pre">#CODE</span></code> block. Without that <code class="docutils literal notranslate"><span class="pre">if</span></code> statement
|
||||
we’d be wiping the dict every block!</p>
|
||||
</section>
|
||||
<section id="dont-treat-a-batchcode-file-like-any-python-file">
|
||||
<h3>Don’t treat a batchcode file like any Python file<a class="headerlink" href="#dont-treat-a-batchcode-file-like-any-python-file" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Despite being a valid Python file, a batchcode file should <em>only</em> be run by the batchcode processor.
|
||||
You should not do things like define Typeclasses or Commands in them, or import them into other
|
||||
code. Importing a module in Python will execute base level of the module, which in the case of your
|
||||
average batchcode file could mean creating a lot of new objects every time.</p>
|
||||
<p>Despite being a valid Python file, a batchcode file should <em>only</em> be run by the batchcode processor. You should not do things like define Typeclasses or Commands in them, or import them into other code. Importing a module in Python will execute base level of the module, which in the case of your average batchcode file could mean creating a lot of new objects every time.</p>
|
||||
</section>
|
||||
<section id="dont-let-code-rely-on-the-batch-files-real-file-path">
|
||||
<h3>Don’t let code rely on the batch-file’s real file path<a class="headerlink" href="#dont-let-code-rely-on-the-batch-files-real-file-path" title="Permalink to this headline">¶</a></h3>
|
||||
<p>When you import things into your batchcode file, don’t use relative imports but always import with
|
||||
paths starting from the root of your game directory or evennia library. Code that relies on the
|
||||
batch file’s “actual” location <em>will fail</em>. Batch code files are read as text and the strings
|
||||
executed. When the code runs it has no knowledge of what file those strings where once a part of.</p>
|
||||
<p>When you import things into your batchcode file, don’t use relative imports but always import with paths starting from the root of your game directory or evennia library. Code that relies on the batch file’s “actual” location <em>will fail</em>. Batch code files are read as text and the strings executed. When the code runs it has no knowledge of what file those strings where once a part of.</p>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
|
@ -357,13 +288,14 @@ executed. When the code runs it has no knowledge of what file those strings wher
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Batch-Command-Processor.html" title="Batch Command Processor"
|
||||
<a href="Inputfuncs.html" title="Inputfuncs"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Batch-Processors.html" title="Batch Processors"
|
||||
<a href="Batch-Command-Processor.html" title="Batch Command Processor"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" >Core Components</a> »</li>
|
||||
<li class="nav-item nav-item-2"><a href="Batch-Processors.html" >Batch Processors</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Batch Code Processor</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
<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="Inputfuncs" href="Inputfuncs.html" />
|
||||
<link rel="prev" title="Batch Code Processor" href="Batch-Code-Processor.html" />
|
||||
<link rel="next" title="Batch Code Processor" href="Batch-Code-Processor.html" />
|
||||
<link rel="prev" title="Batch Processors" href="Batch-Processors.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
|
|
@ -30,13 +30,14 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Inputfuncs.html" title="Inputfuncs"
|
||||
<a href="Batch-Code-Processor.html" title="Batch Code Processor"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Batch-Code-Processor.html" title="Batch Code Processor"
|
||||
<a href="Batch-Processors.html" title="Batch Processors"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" accesskey="U">Core Components</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" >Core Components</a> »</li>
|
||||
<li class="nav-item nav-item-2"><a href="Batch-Processors.html" accesskey="U">Batch Processors</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Batch Command Processor</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
|
|
@ -63,21 +64,20 @@
|
|||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Batch Command Processor</a><ul>
|
||||
<li><a class="reference internal" href="#basic-usage">Basic Usage</a></li>
|
||||
<li><a class="reference internal" href="#the-batch-file">The batch file</a></li>
|
||||
<li><a class="reference internal" href="#interactive-mode">Interactive mode</a></li>
|
||||
<li><a class="reference internal" href="#limitations-and-caveats">Limitations and Caveats</a></li>
|
||||
<li><a class="reference internal" href="#assorted-notes">Assorted notes</a></li>
|
||||
<li><a class="reference internal" href="#editor-highlighting-for-ev-files">Editor highlighting for .ev files</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Batch-Code-Processor.html"
|
||||
title="previous chapter">Batch Code Processor</a></p>
|
||||
<p class="topless"><a href="Batch-Processors.html"
|
||||
title="previous chapter">Batch Processors</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Inputfuncs.html"
|
||||
title="next chapter">Inputfuncs</a></p>
|
||||
<p class="topless"><a href="Batch-Code-Processor.html"
|
||||
title="next chapter">Batch Code Processor</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
|
|
@ -113,10 +113,8 @@
|
|||
<p>For an introduction and motivation to using batch processors, see <a class="reference internal" href="Batch-Processors.html"><span class="doc std std-doc">here</span></a>. This
|
||||
page describes the Batch-<em>command</em> processor. The Batch-<em>code</em> one is covered [here](Batch-Code-
|
||||
Processor).</p>
|
||||
<section id="basic-usage">
|
||||
<h2>Basic Usage<a class="headerlink" href="#basic-usage" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The batch-command processor is a superuser-only function, invoked by</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > @batchcommand path.to.batchcmdfile
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > batchcommand path.to.batchcmdfile
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Where <code class="docutils literal notranslate"><span class="pre">path.to.batchcmdfile</span></code> is the path to a <em>batch-command file</em> with the “<code class="docutils literal notranslate"><span class="pre">.ev</span></code>” file ending.
|
||||
|
|
@ -124,7 +122,7 @@ This path is given like a python path relative to a folder you define to hold yo
|
|||
with <code class="docutils literal notranslate"><span class="pre">BATCH_IMPORT_PATH</span></code> in your settings. Default folder is (assuming your game is in the <code class="docutils literal notranslate"><span class="pre">mygame</span></code>
|
||||
folder) <code class="docutils literal notranslate"><span class="pre">mygame/world</span></code>. So if you want to run the example batch file in
|
||||
<code class="docutils literal notranslate"><span class="pre">mygame/world/batch_cmds.ev</span></code>, you could use</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > @batchcommand batch_cmds
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > batchcommand batch_cmds
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>A batch-command file contains a list of Evennia in-game commands separated by comments. The
|
||||
|
|
@ -132,30 +130,18 @@ processor will run the batch file from beginning to end. Note that <em>it will n
|
|||
it fail</em> (there is no universal way for the processor to know what a failure looks like for all
|
||||
different commands). So keep a close watch on the output, or use <em>Interactive mode</em> (see below) to
|
||||
run the file in a more controlled, gradual manner.</p>
|
||||
</section>
|
||||
<section id="the-batch-file">
|
||||
<h2>The batch file<a class="headerlink" href="#the-batch-file" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The batch file is a simple plain-text file containing Evennia commands. Just like you would write
|
||||
them in-game, except you have more freedom with line breaks.</p>
|
||||
<p>Here are the rules of syntax of an <code class="docutils literal notranslate"><span class="pre">*.ev</span></code> file. You’ll find it’s really, really simple:</p>
|
||||
<ul class="simple">
|
||||
<li><p>All lines having the <code class="docutils literal notranslate"><span class="pre">#</span></code> (hash)-symbol <em>as the first one on the line</em> are considered <em>comments</em>.
|
||||
All non-comment lines are treated as a command and/or their arguments.</p></li>
|
||||
<li><p>Comment lines have an actual function – they mark the <em>end of the previous command definition</em>.
|
||||
So never put two commands directly after one another in the file - separate them with a comment, or
|
||||
the second of the two will be considered an argument to the first one. Besides, using plenty of
|
||||
comments is good practice anyway.</p></li>
|
||||
<li><p>A line that starts with the word <code class="docutils literal notranslate"><span class="pre">#INSERT</span></code> is a comment line but also signifies a special
|
||||
instruction. The syntax is <code class="docutils literal notranslate"><span class="pre">#INSERT</span> <span class="pre"><path.batchfile></span></code> and tries to import a given batch-cmd file
|
||||
into this one. The inserted batch file (file ending <code class="docutils literal notranslate"><span class="pre">.ev</span></code>) will run normally from the point of the
|
||||
<code class="docutils literal notranslate"><span class="pre">#INSERT</span></code> instruction.</p></li>
|
||||
<li><p>Extra whitespace in a command definition is <em>ignored</em>. - A completely empty line translates in to
|
||||
a line break in texts. Two empty lines thus means a new paragraph (this is obviously only relevant
|
||||
for commands accepting such formatting, such as the <code class="docutils literal notranslate"><span class="pre">@desc</span></code> command).</p></li>
|
||||
<li><p>All lines having the <code class="docutils literal notranslate"><span class="pre">#</span></code> (hash)-symbol <em>as the first one on the line</em> are considered <em>comments</em>. All non-comment lines are treated as a command and/or their arguments.</p></li>
|
||||
<li><p>Comment lines have an actual function – they mark the <em>end of the previous command definition</em>. So never put two commands directly after one another in the file - separate them with a comment, or the second of the two will be considered an argument to the first one. Besides, using plenty of comments is good practice anyway.</p></li>
|
||||
<li><p>A line that starts with the word <code class="docutils literal notranslate"><span class="pre">#INSERT</span></code> is a comment line but also signifies a special instruction. The syntax is <code class="docutils literal notranslate"><span class="pre">#INSERT</span> <span class="pre"><path.batchfile></span></code> and tries to import a given batch-cmd file into this one. The inserted batch file (file ending <code class="docutils literal notranslate"><span class="pre">.ev</span></code>) will run normally from the point of the <code class="docutils literal notranslate"><span class="pre">#INSERT</span></code> instruction.</p></li>
|
||||
<li><p>Extra whitespace in a command definition is <em>ignored</em>. - A completely empty line translates in to a line break in texts. Two empty lines thus means a new paragraph (this is obviously only relevant for commands accepting such formatting, such as the <code class="docutils literal notranslate"><span class="pre">@desc</span></code> command).</p></li>
|
||||
<li><p>The very last command in the file is not required to end with a comment.</p></li>
|
||||
<li><p>You <em>cannot</em> nest another <code class="docutils literal notranslate"><span class="pre">@batchcommand</span></code> statement into your batch file. If you want to link many
|
||||
batch-files together, use the <code class="docutils literal notranslate"><span class="pre">#INSERT</span></code> batch instruction instead. You also cannot launch the
|
||||
<code class="docutils literal notranslate"><span class="pre">@batchcode</span></code> command from your batch file, the two batch processors are not compatible.</p></li>
|
||||
<li><p>You <em>cannot</em> nest another <code class="docutils literal notranslate"><span class="pre">batchcommand</span></code> statement into your batch file. If you want to link many batch-files together, use the <code class="docutils literal notranslate"><span class="pre">#INSERT</span></code> batch instruction instead. You also cannot launch the <code class="docutils literal notranslate"><span class="pre">batchcode</span></code> command from your batch file, the two batch processors are not compatible.</p></li>
|
||||
</ul>
|
||||
<p>Below is a version of the example file found in <code class="docutils literal notranslate"><span class="pre">evennia/contrib/tutorial_examples/batch_cmds.ev</span></code>.</p>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span> <span class="c1">#</span>
|
||||
|
|
@ -201,23 +187,17 @@ batch-files together, use the <code class="docutils literal notranslate"><span c
|
|||
</pre></div>
|
||||
</div>
|
||||
<p>To test this, run <code class="docutils literal notranslate"><span class="pre">@batchcommand</span></code> on the file:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> @batchcommand contrib.tutorial_examples.batch_cmds
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> batchcommand contrib.tutorial_examples.batch_cmds
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>A button will be created, described and dropped in Limbo. All commands will be executed by the user
|
||||
calling the command.</p>
|
||||
<p>A button will be created, described and dropped in Limbo. All commands will be executed by the user calling the command.</p>
|
||||
<blockquote>
|
||||
<div><p>Note that if you interact with the button, you might find that its description changes, loosing
|
||||
your custom-set description above. This is just the way this particular object works.</p>
|
||||
<div><p>Note that if you interact with the button, you might find that its description changes, loosing your custom-set description above. This is just the way this particular object works.</p>
|
||||
</div></blockquote>
|
||||
</section>
|
||||
<section id="interactive-mode">
|
||||
<h2>Interactive mode<a class="headerlink" href="#interactive-mode" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Interactive mode allows you to more step-wise control over how the batch file is executed. This is
|
||||
useful for debugging and also if you have a large batch file and is only updating a small part of it
|
||||
– running the entire file again would be a waste of time (and in the case of <code class="docutils literal notranslate"><span class="pre">@create</span></code>-ing objects
|
||||
you would to end up with multiple copies of same-named objects, for example). Use <code class="docutils literal notranslate"><span class="pre">@batchcommand</span></code>
|
||||
with the <code class="docutils literal notranslate"><span class="pre">/interactive</span></code> flag to enter interactive mode.</p>
|
||||
<p>Interactive mode allows you to more step-wise control over how the batch file is executed. This is useful for debugging and also if you have a large batch file and is only updating a small part of it – running the entire file again would be a waste of time (and in the case of <code class="docutils literal notranslate"><span class="pre">create</span></code>-ing objects you would to end up with multiple copies of same-named objects, for example). Use <code class="docutils literal notranslate"><span class="pre">batchcommand</span></code> with the <code class="docutils literal notranslate"><span class="pre">/interactive</span></code> flag to enter interactive mode.</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > @batchcommand/interactive tutorial_examples.batch_cmds
|
||||
</pre></div>
|
||||
</div>
|
||||
|
|
@ -225,62 +205,30 @@ with the <code class="docutils literal notranslate"><span class="pre">/interacti
|
|||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>01/04: @create button:tutorial_examples.red_button.RedButton (hh for help)
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This shows that you are on the <code class="docutils literal notranslate"><span class="pre">@create</span></code> command, the first out of only four commands in this batch
|
||||
file. Observe that the command <code class="docutils literal notranslate"><span class="pre">@create</span></code> has <em>not</em> been actually processed at this point!</p>
|
||||
<p>This shows that you are on the <code class="docutils literal notranslate"><span class="pre">@create</span></code> command, the first out of only four commands in this batch file. Observe that the command <code class="docutils literal notranslate"><span class="pre">@create</span></code> has <em>not</em> been actually processed at this point!</p>
|
||||
<p>To take a look at the full command you are about to run, use <code class="docutils literal notranslate"><span class="pre">ll</span></code> (a batch-processor version of
|
||||
<code class="docutils literal notranslate"><span class="pre">look</span></code>). Use <code class="docutils literal notranslate"><span class="pre">pp</span></code> to actually process the current command (this will actually <code class="docutils literal notranslate"><span class="pre">@create</span></code> the button)
|
||||
– and make sure it worked as planned. Use <code class="docutils literal notranslate"><span class="pre">nn</span></code> (next) to go to the next command. Use <code class="docutils literal notranslate"><span class="pre">hh</span></code> for a
|
||||
list of commands.</p>
|
||||
<p>If there are errors, fix them in the batch file, then use <code class="docutils literal notranslate"><span class="pre">rr</span></code> to reload the file. You will still be
|
||||
at the same command and can rerun it easily with <code class="docutils literal notranslate"><span class="pre">pp</span></code> as needed. This makes for a simple debug
|
||||
cycle. It also allows you to rerun individual troublesome commands - as mentioned, in a large batch
|
||||
file this can be very useful. Do note that in many cases, commands depend on the previous ones (e.g.
|
||||
if <code class="docutils literal notranslate"><span class="pre">@create</span></code> in the example above had failed, the following commands would have had nothing to
|
||||
operate on).</p>
|
||||
<p>Use <code class="docutils literal notranslate"><span class="pre">nn</span></code> and <code class="docutils literal notranslate"><span class="pre">bb</span></code> (next and back) to step through the file; e.g. <code class="docutils literal notranslate"><span class="pre">nn</span> <span class="pre">12</span></code> will jump 12 steps forward
|
||||
(without processing any command in between). All normal commands of Evennia should work too while
|
||||
working in interactive mode.</p>
|
||||
<code class="docutils literal notranslate"><span class="pre">look</span></code>). Use <code class="docutils literal notranslate"><span class="pre">pp</span></code> to actually process the current command (this will actually <code class="docutils literal notranslate"><span class="pre">@create</span></code> the button) – and make sure it worked as planned. Use <code class="docutils literal notranslate"><span class="pre">nn</span></code> (next) to go to the next command. Use <code class="docutils literal notranslate"><span class="pre">hh</span></code> for a list of commands.</p>
|
||||
<p>If there are errors, fix them in the batch file, then use <code class="docutils literal notranslate"><span class="pre">rr</span></code> to reload the file. You will still be at the same command and can rerun it easily with <code class="docutils literal notranslate"><span class="pre">pp</span></code> as needed. This makes for a simple debug cycle. It also allows you to rerun individual troublesome commands - as mentioned, in a large batch file this can be very useful. Do note that in many cases, commands depend on the previous ones (e.g. if <code class="docutils literal notranslate"><span class="pre">create</span></code> in the example above had failed, the following commands would have had nothing to operate on).</p>
|
||||
<p>Use <code class="docutils literal notranslate"><span class="pre">nn</span></code> and <code class="docutils literal notranslate"><span class="pre">bb</span></code> (next and back) to step through the file; e.g. <code class="docutils literal notranslate"><span class="pre">nn</span> <span class="pre">12</span></code> will jump 12 steps forward (without processing any command in between). All normal commands of Evennia should work too while working in interactive mode.</p>
|
||||
</section>
|
||||
<section id="limitations-and-caveats">
|
||||
<h2>Limitations and Caveats<a class="headerlink" href="#limitations-and-caveats" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The batch-command processor is great for automating smaller builds or for testing new commands and
|
||||
objects repeatedly without having to write so much. There are several caveats you have to be aware
|
||||
of when using the batch-command processor for building larger, complex worlds though.</p>
|
||||
<p>The batch-command processor is great for automating smaller builds or for testing new commands and objects repeatedly without having to write so much. There are several caveats you have to be aware of when using the batch-command processor for building larger, complex worlds though.</p>
|
||||
<p>The main issue is that when you run a batch-command script you (<em>you</em>, as in your superuser
|
||||
character) are actually moving around in the game creating and building rooms in sequence, just as
|
||||
if you had been entering those commands manually, one by one. You have to take this into account
|
||||
when creating the file, so that you can ‘walk’ (or teleport) to the right places in order.</p>
|
||||
<p>This also means there are several pitfalls when designing and adding certain types of objects. Here
|
||||
are some examples:</p>
|
||||
character) are actually moving around in the game creating and building rooms in sequence, just as if you had been entering those commands manually, one by one. You have to take this into account when creating the file, so that you can ‘walk’ (or teleport) to the right places in order.</p>
|
||||
<p>This also means there are several pitfalls when designing and adding certain types of objects. Here are some examples:</p>
|
||||
<ul class="simple">
|
||||
<li><p><em>Rooms that change your <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">Command Set</span></a></em>: Imagine that you build a ‘dark’ room, which
|
||||
severely limits the cmdsets of those entering it (maybe you have to find the light switch to
|
||||
proceed). In your batch script you would create this room, then teleport to it - and promptly be
|
||||
shifted into the dark state where none of your normal build commands work …</p></li>
|
||||
<li><p><em>Auto-teleportation</em>: Rooms that automatically teleport those that enter them to another place
|
||||
(like a trap room, for example). You would be teleported away too.</p></li>
|
||||
<li><p><em>Mobiles</em>: If you add aggressive mobs, they might attack you, drawing you into combat. If they
|
||||
have AI they might even follow you around when building - or they might move away from you before
|
||||
you’ve had time to finish describing and equipping them!</p></li>
|
||||
<li><p><em>Rooms that change your <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">Command Set</span></a></em>: Imagine that you build a ‘dark’ room, which severely limits the cmdsets of those entering it (maybe you have to find the light switch to proceed). In your batch script you would create this room, then teleport to it - and promptly be shifted into the dark state where none of your normal build commands work …</p></li>
|
||||
<li><p><em>Auto-teleportation</em>: Rooms that automatically teleport those that enter them to another place (like a trap room, for example). You would be teleported away too.</p></li>
|
||||
<li><p><em>Mobiles</em>: If you add aggressive mobs, they might attack you, drawing you into combat. If they have AI they might even follow you around when building - or they might move away from you before you’ve had time to finish describing and equipping them!</p></li>
|
||||
</ul>
|
||||
<p>The solution to all these is to plan ahead. Make sure that superusers are never affected by whatever
|
||||
effects are in play. Add an on/off switch to objects and make sure it’s always set to <em>off</em> upon
|
||||
creation. It’s all doable, one just needs to keep it in mind.</p>
|
||||
<p>The solution to all these is to plan ahead. Make sure that superusers are never affected by whatever effects are in play. Add an on/off switch to objects and make sure it’s always set to <em>off</em> upon creation. It’s all doable, one just needs to keep it in mind.</p>
|
||||
</section>
|
||||
<section id="assorted-notes">
|
||||
<h2>Assorted notes<a class="headerlink" href="#assorted-notes" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The fact that you build as ‘yourself’ can also be considered an advantage however, should you ever
|
||||
decide to change the default command to allow others than superusers to call the processor. Since
|
||||
normal access-checks are still performed, a malevolent builder with access to the processor should
|
||||
not be able to do all that much damage (this is the main drawback of the <a class="reference internal" href="Batch-Code-Processor.html"><span class="doc std std-doc">Batch Code
|
||||
Processor</span></a>)</p>
|
||||
<section id="editor-highlighting-for-ev-files">
|
||||
<h2>Editor highlighting for .ev files<a class="headerlink" href="#editor-highlighting-for-ev-files" title="Permalink to this headline">¶</a></h2>
|
||||
<ul class="simple">
|
||||
<li><p><a class="reference external" href="https://www.gnu.org/software/emacs/">GNU Emacs</a> users might find it interesting to use emacs’
|
||||
<em>evennia mode</em>. This is an Emacs major mode found in <code class="docutils literal notranslate"><span class="pre">evennia/utils/evennia-mode.el</span></code>. It offers
|
||||
correct syntax highlighting and indentation with <code class="docutils literal notranslate"><span class="pre"><tab></span></code> when editing <code class="docutils literal notranslate"><span class="pre">.ev</span></code> files in Emacs. See the
|
||||
header of that file for installation instructions.</p></li>
|
||||
<li><p><a class="reference external" href="https://www.vim.org/">VIM</a> users can use amfl’s <a class="reference external" href="https://github.com/amfl/vim-evennia">vim-evennia</a>
|
||||
mode instead, see its readme for install instructions.</p></li>
|
||||
<li><p><a class="reference external" href="https://www.gnu.org/software/emacs/">GNU Emacs</a> users might find it interesting to use emacs’ <em>evennia mode</em>. This is an Emacs major mode found in <code class="docutils literal notranslate"><span class="pre">evennia/utils/evennia-mode.el</span></code>. It offers correct syntax highlighting and indentation with <code class="docutils literal notranslate"><span class="pre"><tab></span></code> when editing <code class="docutils literal notranslate"><span class="pre">.ev</span></code> files in Emacs. See the header of that file for installation instructions.</p></li>
|
||||
<li><p><a class="reference external" href="https://www.vim.org/">VIM</a> users can use amfl’s <a class="reference external" href="https://github.com/amfl/vim-evennia">vim-evennia</a> mode instead, see its readme for install instructions.</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
|
|
@ -301,13 +249,14 @@ mode instead, see its readme for install instructions.</p></li>
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Inputfuncs.html" title="Inputfuncs"
|
||||
<a href="Batch-Code-Processor.html" title="Batch Code Processor"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Batch-Code-Processor.html" title="Batch Code Processor"
|
||||
<a href="Batch-Processors.html" title="Batch Processors"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" >Core Components</a> »</li>
|
||||
<li class="nav-item nav-item-2"><a href="Batch-Processors.html" >Batch Processors</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Batch Command Processor</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
<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="Batch Code Processor" href="Batch-Code-Processor.html" />
|
||||
<link rel="prev" title="Connection Screen" href="Connection-Screen.html" />
|
||||
<link rel="next" title="Batch Command Processor" href="Batch-Command-Processor.html" />
|
||||
<link rel="prev" title="Default Commands" href="Default-Commands.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
|
|
@ -30,10 +30,10 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Batch-Code-Processor.html" title="Batch Code Processor"
|
||||
<a href="Batch-Command-Processor.html" title="Batch Command Processor"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Connection-Screen.html" title="Connection Screen"
|
||||
<a href="Default-Commands.html" title="Default Commands"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" accesskey="U">Core Components</a> »</li>
|
||||
|
|
@ -69,11 +69,11 @@
|
|||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Connection-Screen.html"
|
||||
title="previous chapter">Connection Screen</a></p>
|
||||
<p class="topless"><a href="Default-Commands.html"
|
||||
title="previous chapter">Default Commands</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Batch-Code-Processor.html"
|
||||
title="next chapter">Batch Code Processor</a></p>
|
||||
<p class="topless"><a href="Batch-Command-Processor.html"
|
||||
title="next chapter">Batch Command Processor</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
|
|
@ -106,74 +106,51 @@
|
|||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="batch-processors">
|
||||
<h1>Batch Processors<a class="headerlink" href="#batch-processors" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Building a game world is a lot of work, especially when starting out. Rooms should be created,
|
||||
descriptions have to be written, objects must be detailed and placed in their proper places. In many
|
||||
<div class="toctree-wrapper compound">
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Batch-Command-Processor.html">Batch Command Processor</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Batch-Command-Processor.html#the-batch-file">The batch file</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Batch-Command-Processor.html#interactive-mode">Interactive mode</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Batch-Command-Processor.html#limitations-and-caveats">Limitations and Caveats</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Batch-Command-Processor.html#editor-highlighting-for-ev-files">Editor highlighting for .ev files</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Batch-Code-Processor.html">Batch Code Processor</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Batch-Code-Processor.html#the-batch-file">The batch file</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Batch-Code-Processor.html#debug-mode">Debug mode</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Batch-Code-Processor.html#interactive-mode">Interactive mode</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Batch-Code-Processor.html#limitations-and-caveats">Limitations and Caveats</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>Building a game world is a lot of work, especially when starting out. Rooms should be created, descriptions have to be written, objects must be detailed and placed in their proper places. In many
|
||||
traditional MUD setups you had to do all this online, line by line, over a telnet session.</p>
|
||||
<p>Evennia already moves away from much of this by shifting the main coding work to external Python
|
||||
modules. But also building would be helped if one could do some or all of it externally. Enter
|
||||
Evennia’s <em>batch processors</em> (there are two of them). The processors allows you, as a game admin, to
|
||||
build your game completely offline in normal text files (<em>batch files</em>) that the processors
|
||||
understands. Then, when you are ready, you use the processors to read it all into Evennia (and into
|
||||
the database) in one go.</p>
|
||||
<p>You can of course still build completely online should you want to - this is certainly the easiest
|
||||
way to go when learning and for small build projects. But for major building work, the advantages of
|
||||
using the batch-processors are many:</p>
|
||||
<p>Evennia already moves away from much of this by shifting the main coding work to external Python modules. But also building would be helped if one could do some or all of it externally. Enter Evennia’s <em>batch processors</em> (there are two of them). The processors allows you, as a game admin, to build your game completely offline in normal text files (<em>batch files</em>) that the processors understands. Then, when you are ready, you use the processors to read it all into Evennia (and into the database) in one go.</p>
|
||||
<p>You can of course still build completely online should you want to - this is certainly the easiest way to go when learning and for small build projects. But for major building work, the advantages of using the batch-processors are many:</p>
|
||||
<ul class="simple">
|
||||
<li><p>It’s hard to compete with the comfort of a modern desktop text editor; Compared to a traditional
|
||||
MUD line input, you can get much better overview and many more features. Also, accidentally pressing
|
||||
Return won’t immediately commit things to the database.</p></li>
|
||||
<li><p>You might run external spell checkers on your batch files. In the case of one of the batch-
|
||||
processors (the one that deals with Python code), you could also run external debuggers and code
|
||||
analyzers on your file to catch problems before feeding it to Evennia.</p></li>
|
||||
<li><p>The batch files (as long as you keep them) are records of your work. They make a natural starting
|
||||
point for quickly re-building your world should you ever decide to start over.</p></li>
|
||||
<li><p>If you are an Evennia developer, using a batch file is a fast way to setup a test-game after
|
||||
having reset the database.</p></li>
|
||||
<li><p>The batch files might come in useful should you ever decide to distribute all or part of your
|
||||
world to others.</p></li>
|
||||
<li><p>It’s hard to compete with the comfort of a modern desktop text editor; Compared to a traditional MUD line input, you can get much better overview and many more features. Also, accidentally pressing Return won’t immediately commit things to the database.</p></li>
|
||||
<li><p>You might run external spell checkers on your batch files. In the case of one of the batch- processors (the one that deals with Python code), you could also run external debuggers and code analyzers on your file to catch problems before feeding it to Evennia.</p></li>
|
||||
<li><p>The batch files (as long as you keep them) are records of your work. They make a natural starting point for quickly re-building your world should you ever decide to start over.</p></li>
|
||||
<li><p>If you are an Evennia developer, using a batch file is a fast way to setup a test-game after having reset the database.</p></li>
|
||||
<li><p>The batch files might come in useful should you ever decide to distribute all or part of your world to others.</p></li>
|
||||
</ul>
|
||||
<p>There are two batch processors, the Batch-<em>command</em> processor and the Batch-<em>code</em> processor. The
|
||||
first one is the simpler of the two. It doesn’t require any programming knowledge - you basically
|
||||
just list in-game commands in a text file. The code-processor on the other hand is much more
|
||||
powerful but also more complex - it lets you use Evennia’s API to code your world in full-fledged
|
||||
Python code.</p>
|
||||
<ul class="simple">
|
||||
<li><p>The <a class="reference internal" href="Batch-Command-Processor.html"><span class="doc std std-doc">Batch Command Processor</span></a></p></li>
|
||||
<li><p>The <a class="reference internal" href="Batch-Code-Processor.html"><span class="doc std std-doc">Batch Code Processor</span></a></p></li>
|
||||
</ul>
|
||||
<p>If you plan to use international characters in your batchfiles you are wise to read about <em>file
|
||||
encodings</em> below.</p>
|
||||
<section id="a-note-on-file-encodings">
|
||||
<h2>A note on File Encodings<a class="headerlink" href="#a-note-on-file-encodings" title="Permalink to this headline">¶</a></h2>
|
||||
<p>As mentioned, both the processors take text files as input and then proceed to process them. As long
|
||||
as you stick to the standard <a class="reference external" href="https://en.wikipedia.org/wiki/Ascii">ASCII</a> character set (which means
|
||||
the normal English characters, basically) you should not have to worry much about this section.</p>
|
||||
<p>Many languages however use characters outside the simple <code class="docutils literal notranslate"><span class="pre">ASCII</span></code> table. Common examples are various
|
||||
apostrophes and umlauts but also completely different symbols like those of the greek or cyrillic
|
||||
alphabets.</p>
|
||||
<p>First, we should make it clear that Evennia itself handles international characters just fine. It
|
||||
(and Django) uses <a class="reference external" href="https://en.wikipedia.org/wiki/Unicode">unicode</a> strings internally.</p>
|
||||
<p>The problem is that when reading a text file like the batchfile, we need to know how to decode the
|
||||
byte-data stored therein to universal unicode. That means we need an <em>encoding</em> (a mapping) for how
|
||||
the file stores its data. There are many, many byte-encodings used around the world, with opaque
|
||||
names such as <code class="docutils literal notranslate"><span class="pre">Latin-1</span></code>, <code class="docutils literal notranslate"><span class="pre">ISO-8859-3</span></code> or <code class="docutils literal notranslate"><span class="pre">ARMSCII-8</span></code> to pick just a few examples. Problem is that
|
||||
it’s practially impossible to determine which encoding was used to save a file just by looking at it
|
||||
(it’s just a bunch of bytes!). You have to <em>know</em>.</p>
|
||||
<p>With this little introduction it should be clear that Evennia can’t guess but has to <em>assume</em> an
|
||||
encoding when trying to load a batchfile. The text editor and Evennia must speak the same “language”
|
||||
so to speak. Evennia will by default first try the international <code class="docutils literal notranslate"><span class="pre">UTF-8</span></code> encoding, but you can have
|
||||
Evennia try any sequence of different encodings by customizing the <code class="docutils literal notranslate"><span class="pre">ENCODINGS</span></code> list in your settings
|
||||
file. Evennia will use the first encoding in the list that do not raise any errors. Only if none
|
||||
work will the server give up and return an error message.</p>
|
||||
<p>You can often change the text editor encoding (this depends on your editor though), otherwise you
|
||||
need to add the editor’s encoding to Evennia’s <code class="docutils literal notranslate"><span class="pre">ENCODINGS</span></code> list. If you are unsure, write a test
|
||||
file with lots of non-ASCII letters in the editor of your choice, then import to make sure it works
|
||||
as it should.</p>
|
||||
<p>More help with encodings can be found in the entry <a class="reference internal" href="../Concepts/Text-Encodings.html"><span class="doc std std-doc">Text Encodings</span></a> and also in the
|
||||
Wikipedia article <a class="reference external" href="https://en.wikipedia.org/wiki/Text_encodings">here</a>.</p>
|
||||
<p>As mentioned, both the processors take text files as input and then proceed to process them. As long as you stick to the standard <a class="reference external" href="https://en.wikipedia.org/wiki/Ascii">ASCII</a> character set (which means the normal English characters, basically) you should not have to worry much about this section.</p>
|
||||
<p>Many languages however use characters outside the simple <code class="docutils literal notranslate"><span class="pre">ASCII</span></code> table. Common examples are various apostrophes and umlauts but also completely different symbols like those of the greek or cyrillic alphabets.</p>
|
||||
<p>First, we should make it clear that Evennia itself handles international characters just fine. It (and Django) uses <a class="reference external" href="https://en.wikipedia.org/wiki/Unicode">unicode</a> strings internally.</p>
|
||||
<p>The problem is that when reading a text file like the batchfile, we need to know how to decode the byte-data stored therein to universal unicode. That means we need an <em>encoding</em> (a mapping) for how the file stores its data. There are many, many byte-encodings used around the world, with opaque names such as <code class="docutils literal notranslate"><span class="pre">Latin-1</span></code>, <code class="docutils literal notranslate"><span class="pre">ISO-8859-3</span></code> or <code class="docutils literal notranslate"><span class="pre">ARMSCII-8</span></code> to pick just a few examples. Problem is that it’s practially impossible to determine which encoding was used to save a file just by looking at it (it’s just a bunch of bytes!). You have to <em>know</em>.</p>
|
||||
<p>With this little introduction it should be clear that Evennia can’t guess but has to <em>assume</em> an encoding when trying to load a batchfile. The text editor and Evennia must speak the same “language” so to speak. Evennia will by default first try the international <code class="docutils literal notranslate"><span class="pre">UTF-8</span></code> encoding, but you can have Evennia try any sequence of different encodings by customizing the <code class="docutils literal notranslate"><span class="pre">ENCODINGS</span></code> list in your settings file. Evennia will use the first encoding in the list that do not raise any errors. Only if none work will the server give up and return an error message.</p>
|
||||
<p>You can often change the text editor encoding (this depends on your editor though), otherwise you need to add the editor’s encoding to Evennia’s <code class="docutils literal notranslate"><span class="pre">ENCODINGS</span></code> list. If you are unsure, write a test file with lots of non-ASCII letters in the editor of your choice, then import to make sure it works as it should.</p>
|
||||
<p>More help with encodings can be found in the entry <a class="reference internal" href="../Concepts/Text-Encodings.html"><span class="doc std std-doc">Text Encodings</span></a> and also in the Wikipedia article <a class="reference external" href="https://en.wikipedia.org/wiki/Text_encodings">here</a>.</p>
|
||||
<p><strong>A footnote for the batch-code processor</strong>: Just because <em>Evennia</em> can parse your file and your
|
||||
fancy special characters, doesn’t mean that <em>Python</em> allows their use. Python syntax only allows
|
||||
international characters inside <em>strings</em>. In all other source code only <code class="docutils literal notranslate"><span class="pre">ASCII</span></code> set characters are
|
||||
fancy special characters, doesn’t mean that <em>Python</em> allows their use. Python syntax only allows international characters inside <em>strings</em>. In all other source code only <code class="docutils literal notranslate"><span class="pre">ASCII</span></code> set characters are
|
||||
allowed.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
|
@ -194,10 +171,10 @@ allowed.</p>
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Batch-Code-Processor.html" title="Batch Code Processor"
|
||||
<a href="Batch-Command-Processor.html" title="Batch Command Processor"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Connection-Screen.html" title="Connection Screen"
|
||||
<a href="Default-Commands.html" title="Default Commands"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" >Core Components</a> »</li>
|
||||
|
|
|
|||
|
|
@ -63,19 +63,20 @@
|
|||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Channels</a><ul>
|
||||
<li><a class="reference internal" href="#using-channels-in-game">Using channels in-game</a><ul>
|
||||
<li><a class="reference internal" href="#working-with-channels">Working with channels</a><ul>
|
||||
<li><a class="reference internal" href="#viewing-and-joining-channels">Viewing and joining channels</a></li>
|
||||
<li><a class="reference internal" href="#chat-on-channels">Chat on channels</a></li>
|
||||
<li><a class="reference internal" href="#talk-on-channels">Talk on channels</a></li>
|
||||
<li><a class="reference internal" href="#channel-administration">Channel administration</a><ul>
|
||||
<li><a class="reference internal" href="#restricting-channel-administration">Restricting channel administration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#using-channels-in-code">Using channels in code</a><ul>
|
||||
<li><a class="reference internal" href="#allowing-characters-to-use-channels">Allowing Characters to use Channels</a></li>
|
||||
<li><a class="reference internal" href="#customizing-channel-output-and-behavior">Customizing channel output and behavior</a></li>
|
||||
<li><a class="reference internal" href="#channels-in-code">Channels in code</a></li>
|
||||
<li><a class="reference internal" href="#channel-logging">Channel logging</a><ul>
|
||||
<li><a class="reference internal" href="#channel-class">Channel class</a></li>
|
||||
<li><a class="reference internal" href="#channel-logging">Channel logging</a></li>
|
||||
<li><a class="reference internal" href="#properties-on-channels">Properties on Channels</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
|
@ -143,15 +144,12 @@ it to every other subscriber.</p>
|
|||
<p><span class="versionmodified changed">Changed in version 1.0: </span>Channel system changed to use a central ‘channel’ command and nicks instead of
|
||||
auto-generated channel-commands and -cmdset. ChannelHandler was removed.</p>
|
||||
</div>
|
||||
<section id="using-channels-in-game">
|
||||
<h2>Using channels in-game<a class="headerlink" href="#using-channels-in-game" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In the default command set, channels are all handled via the mighty
|
||||
<a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdChannel" title="evennia.commands.default.comms.CmdChannel"><span class="xref myst py py-class">channel
|
||||
command</span></a>, <code class="docutils literal notranslate"><span class="pre">channel</span></code> (or
|
||||
<code class="docutils literal notranslate"><span class="pre">chan</span></code>). By default, this command will assume all entities dealing with
|
||||
channels are <code class="docutils literal notranslate"><span class="pre">Accounts</span></code>.</p>
|
||||
<section id="working-with-channels">
|
||||
<h2>Working with channels<a class="headerlink" href="#working-with-channels" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="viewing-and-joining-channels">
|
||||
<h3>Viewing and joining channels<a class="headerlink" href="#viewing-and-joining-channels" title="Permalink to this headline">¶</a></h3>
|
||||
<p>In the default command set, channels are all handled via the mighty <a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdChannel" title="evennia.commands.default.comms.CmdChannel"><span class="xref myst py py-class">channel command</span></a>, <code class="docutils literal notranslate"><span class="pre">channel</span></code> (or <code class="docutils literal notranslate"><span class="pre">chan</span></code>). By default, this command will assume all entities dealing with channels are <code class="docutils literal notranslate"><span class="pre">Accounts</span></code>.</p>
|
||||
<p>Viewing channels</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>channel - shows your subscriptions
|
||||
channel/all - shows all subs available to you
|
||||
channel/who - shows who subscribes to this channel
|
||||
|
|
@ -169,8 +167,8 @@ channel/unmute channelname
|
|||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="chat-on-channels">
|
||||
<h3>Chat on channels<a class="headerlink" href="#chat-on-channels" title="Permalink to this headline">¶</a></h3>
|
||||
<section id="talk-on-channels">
|
||||
<h3>Talk on channels<a class="headerlink" href="#talk-on-channels" title="Permalink to this headline">¶</a></h3>
|
||||
<p>To speak on a channel, do</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>channel public Hello world!
|
||||
</pre></div>
|
||||
|
|
@ -255,8 +253,7 @@ channel/unban mychannel = annoyinguser123
|
|||
<p>Banning adds the user to the channels blacklist. This means they will not be
|
||||
able to <em>rejoin</em> if you boot them. You will need to run <code class="docutils literal notranslate"><span class="pre">channel/boot</span></code> to
|
||||
actually kick them out.</p>
|
||||
<p>See the <a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdChannel" title="evennia.commands.default.comms.CmdChannel"><span class="xref myst py py-class">Channel command</span></a> api
|
||||
docs (and in-game help) for more details.</p>
|
||||
<p>See the <a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdChannel" title="evennia.commands.default.comms.CmdChannel"><span class="xref myst py py-class">Channel command</span></a> api docs (and in-game help) for more details.</p>
|
||||
<p>Admin-level users can also modify channel’s <a class="reference internal" href="Locks.html"><span class="doc std std-doc">locks</span></a>:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>channel/lock buildchannel = listen:all();send:perm(Builders)
|
||||
</pre></div>
|
||||
|
|
@ -271,11 +268,7 @@ control over the channel you can edit it, boot users and do other management tas
|
|||
</ul>
|
||||
<section id="restricting-channel-administration">
|
||||
<h4>Restricting channel administration<a class="headerlink" href="#restricting-channel-administration" title="Permalink to this headline">¶</a></h4>
|
||||
<p>By default everyone can use the channel command (<a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdChannel" title="evennia.commands.default.comms.CmdChannel"><span class="xref myst py py-class">evennia.commands.default.comms.CmdChannel</span></a>)
|
||||
to create channels and will then control the channels they created (to boot/ban
|
||||
people etc). If you as a developer does not want regular players to do this
|
||||
(perhaps you want only staff to be able to spawn new channels), you can
|
||||
override the <code class="docutils literal notranslate"><span class="pre">channel</span></code> command and change its <code class="docutils literal notranslate"><span class="pre">locks</span></code> property.</p>
|
||||
<p>By default everyone can use the channel command (<a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdChannel" title="evennia.commands.default.comms.CmdChannel"><span class="xref myst py py-class">evennia.commands.default.comms.CmdChannel</span></a>) to create channels and will then control the channels they created (to boot/ban people etc). If you as a developer does not want regular players to do this (perhaps you want only staff to be able to spawn new channels), you can override the <code class="docutils literal notranslate"><span class="pre">channel</span></code> command and change its <code class="docutils literal notranslate"><span class="pre">locks</span></code> property.</p>
|
||||
<p>The default <code class="docutils literal notranslate"><span class="pre">help</span></code> command has the following <code class="docutils literal notranslate"><span class="pre">locks</span></code> property:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">locks</span> <span class="o">=</span> <span class="s2">"cmd:not perm(channel_banned); admin:all(); manage:all(); changelocks: perm(Admin)"</span>
|
||||
</pre></div>
|
||||
|
|
@ -313,19 +306,18 @@ access-denied error when trying to use use these switches.</p>
|
|||
</section>
|
||||
</section>
|
||||
</section>
|
||||
<section id="using-channels-in-code">
|
||||
<h2>Using channels in code<a class="headerlink" href="#using-channels-in-code" title="Permalink to this headline">¶</a></h2>
|
||||
<p>For most common changes, the default channel, the recipient hooks and possibly
|
||||
overriding the <code class="docutils literal notranslate"><span class="pre">channel</span></code> command will get you very far. But you can also tweak
|
||||
channels themselves.</p>
|
||||
<section id="allowing-characters-to-use-channels">
|
||||
<h2>Allowing Characters to use Channels<a class="headerlink" href="#allowing-characters-to-use-channels" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The default <code class="docutils literal notranslate"><span class="pre">channel</span></code> command (<a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdChannel" title="evennia.commands.default.comms.CmdChannel"><span class="xref myst py py-class">evennia.commands.default.comms.CmdChannel</span></a>)
|
||||
sits in the <code class="docutils literal notranslate"><span class="pre">Account</span></code> <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">command set</span></a>. It is set up such that it will
|
||||
always operate on <code class="docutils literal notranslate"><span class="pre">Accounts</span></code>, even if you were to add it to the
|
||||
<code class="docutils literal notranslate"><span class="pre">CharacterCmdSet</span></code>.</p>
|
||||
<p>It’s a one-line change to make this command accept non-account callers. But for
|
||||
convenience we provide a version for Characters/Objects. Just import
|
||||
<a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdObjectChannel" title="evennia.commands.default.comms.CmdObjectChannel"><span class="xref myst py py-class">evennia.commands.default.comms.CmdObjectChannel</span></a>
|
||||
and inherit from that instead.</p>
|
||||
<h3>Allowing Characters to use Channels<a class="headerlink" href="#allowing-characters-to-use-channels" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The default <code class="docutils literal notranslate"><span class="pre">channel</span></code> command (<a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdChannel" title="evennia.commands.default.comms.CmdChannel"><span class="xref myst py py-class">evennia.commands.default.comms.CmdChannel</span></a>) sits in the <code class="docutils literal notranslate"><span class="pre">Account</span></code> <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">command set</span></a>. It is set up such that it will always operate on <code class="docutils literal notranslate"><span class="pre">Accounts</span></code>, even if you were to add it to the <code class="docutils literal notranslate"><span class="pre">CharacterCmdSet</span></code>.</p>
|
||||
<p>It’s a one-line change to make this command accept non-account callers. But for convenience we provide a version for Characters/Objects. Just import <a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdObjectChannel" title="evennia.commands.default.comms.CmdObjectChannel"><span class="xref myst py py-class">evennia.commands.default.comms.CmdObjectChannel</span></a> and inherit from that instead.</p>
|
||||
</section>
|
||||
<section id="customizing-channel-output-and-behavior">
|
||||
<h2>Customizing channel output and behavior<a class="headerlink" href="#customizing-channel-output-and-behavior" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Customizing channel output and behavior<a class="headerlink" href="#customizing-channel-output-and-behavior" title="Permalink to this headline">¶</a></h3>
|
||||
<p>When distributing a message, the channel will call a series of hooks on itself
|
||||
and (more importantly) on each recipient. So you can customize things a lot by
|
||||
just modifying hooks on your normal Object/Account typeclasses.</p>
|
||||
|
|
@ -354,19 +346,10 @@ recipient is skipped.</p></li>
|
|||
So make sure you modify the set actually used by your subcribers (or both).
|
||||
Default channels all use <code class="docutils literal notranslate"><span class="pre">Account</span></code> subscribers.</p>
|
||||
</section>
|
||||
<section id="channels-in-code">
|
||||
<h2>Channels in code<a class="headerlink" href="#channels-in-code" title="Permalink to this headline">¶</a></h2>
|
||||
<p>For most common changes, the default channel, the recipient hooks and possibly
|
||||
overriding the <code class="docutils literal notranslate"><span class="pre">channel</span></code> command will get you very far. But you can also tweak
|
||||
channels themselves.</p>
|
||||
<p>Channels are <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclassed</span></a> entities. This means they are
|
||||
persistent in the database, can have <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">attributes</span></a> and <a class="reference internal" href="Tags.html"><span class="doc std std-doc">Tags</span></a>
|
||||
and can be easily extended.</p>
|
||||
<p>To change which channel typeclass Evennia uses for default commands, change
|
||||
<code class="docutils literal notranslate"><span class="pre">settings.BASE_CHANNEL_TYPECLASS</span></code>. The base command class is
|
||||
<a class="reference internal" href="../api/evennia.comms.comms.html#evennia.comms.comms.DefaultChannel" title="evennia.comms.comms.DefaultChannel"><span class="xref myst py py-class"><code class="docutils literal notranslate"><span class="pre">evennia.comms.comms.DefaultChannel</span></code></span></a>.
|
||||
There is an empty child class in <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/channels.py</span></code>, same
|
||||
as for other typelass-bases.</p>
|
||||
<section id="channel-class">
|
||||
<h3>Channel class<a class="headerlink" href="#channel-class" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Channels are <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclassed</span></a> entities. This means they are persistent in the database, can have <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">attributes</span></a> and <a class="reference internal" href="Tags.html"><span class="doc std std-doc">Tags</span></a> and can be easily extended.</p>
|
||||
<p>To change which channel typeclass Evennia uses for default commands, change <code class="docutils literal notranslate"><span class="pre">settings.BASE_CHANNEL_TYPECLASS</span></code>. The base command class is <a class="reference internal" href="../api/evennia.comms.comms.html#evennia.comms.comms.DefaultChannel" title="evennia.comms.comms.DefaultChannel"><span class="xref myst py py-class"><code class="docutils literal notranslate"><span class="pre">evennia.comms.comms.DefaultChannel</span></code></span></a>. There is an empty child class in <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/channels.py</span></code>, same as for other typelass-bases.</p>
|
||||
<p>In code you create a new channel with <code class="docutils literal notranslate"><span class="pre">evennia.create_channel</span></code> or
|
||||
<code class="docutils literal notranslate"><span class="pre">Channel.create</span></code>:</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_channel</span><span class="p">,</span> <span class="n">search_object</span>
|
||||
|
|
@ -399,28 +382,24 @@ as for other typelass-bases.</p>
|
|||
</div>
|
||||
<p>The Channel’s <code class="docutils literal notranslate"><span class="pre">.connect</span></code> method will accept both <code class="docutils literal notranslate"><span class="pre">Account</span></code> and <code class="docutils literal notranslate"><span class="pre">Object</span></code> subscribers
|
||||
and will handle them transparently.</p>
|
||||
<p>The channel has many more hooks, both hooks shared with all typeclasses as well
|
||||
as special ones related to muting/banning etc. See the channel class for
|
||||
<p>The channel has many more hooks, both hooks shared with all typeclasses as well as special ones related to muting/banning etc. See the channel class for
|
||||
details.</p>
|
||||
</section>
|
||||
<section id="channel-logging">
|
||||
<h2>Channel logging<a class="headerlink" href="#channel-logging" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Channel logging<a class="headerlink" href="#channel-logging" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="versionchanged">
|
||||
<p><span class="versionmodified changed">Changed in version 0.7: </span>Channels changed from using Msg to TmpMsg and optional log files.</p>
|
||||
</div>
|
||||
<div class="versionchanged">
|
||||
<p><span class="versionmodified changed">Changed in version 1.0: </span>Channels stopped supporting Msg and TmpMsg, using only log files.</p>
|
||||
</div>
|
||||
<p>The channel messages are not stored in the database. A channel is instead
|
||||
always logged to a regular text log-file
|
||||
<code class="docutils literal notranslate"><span class="pre">mygame/server/logs/channel_<channelname>.log</span></code>. This is where <code class="docutils literal notranslate"><span class="pre">channels/history</span> <span class="pre">channelname</span></code>
|
||||
gets its data from. A channel’s log will rotate when it grows too big, which
|
||||
thus also automatically limits the max amount of history a user can view with
|
||||
<p>The channel messages are not stored in the database. A channel is instead always logged to a regular text log-file <code class="docutils literal notranslate"><span class="pre">mygame/server/logs/channel_<channelname>.log</span></code>. This is where <code class="docutils literal notranslate"><span class="pre">channels/history</span> <span class="pre">channelname</span></code> gets its data from. A channel’s log will rotate when it grows too big, which thus also automatically limits the max amount of history a user can view with
|
||||
<code class="docutils literal notranslate"><span class="pre">/history</span></code>.</p>
|
||||
<p>The log file name is set on the channel class as the <code class="docutils literal notranslate"><span class="pre">log_file</span></code> property. This
|
||||
is a string that takes the formatting token <code class="docutils literal notranslate"><span class="pre">{channelname}</span></code> to be replaced with
|
||||
the (lower-case) name of the channel. By default the log is written to in the
|
||||
channel’s <code class="docutils literal notranslate"><span class="pre">at_post_channel_msg</span></code> method.</p>
|
||||
</section>
|
||||
<section id="properties-on-channels">
|
||||
<h3>Properties on Channels<a class="headerlink" href="#properties-on-channels" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Channels have all the standard properties of a Typeclassed entity (<code class="docutils literal notranslate"><span class="pre">key</span></code>,
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@
|
|||
<li><a class="reference internal" href="#utils-delay">utils.delay()</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#object-classes">Object Classes</a><ul>
|
||||
<li><a class="reference internal" href="#finding-classes">Finding Classes</a><ul>
|
||||
<li><a class="reference internal" href="#utils-inherits-from">utils.inherits_from()</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
|
@ -81,12 +81,6 @@
|
|||
<li><a class="reference internal" href="#utils-crop">utils.crop()</a></li>
|
||||
<li><a class="reference internal" href="#utils-dedent">utils.dedent()</a></li>
|
||||
<li><a class="reference internal" href="#to-str-and-to-bytes">to_str() and to_bytes()</a></li>
|
||||
<li><a class="reference internal" href="#ansi-coloring-tools">Ansi Coloring Tools</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#display-utilities">Display utilities</a><ul>
|
||||
<li><a class="reference internal" href="#making-ascii-tables">Making ascii tables</a></li>
|
||||
<li><a class="reference internal" href="#menus">Menus</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
@ -133,6 +127,9 @@
|
|||
<h1>Coding Utils<a class="headerlink" href="#coding-utils" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Evennia comes with many utilities to help with common coding tasks. Most are accessible directly
|
||||
from the flat API, otherwise you can find them in the <code class="docutils literal notranslate"><span class="pre">evennia/utils/</span></code> folder.</p>
|
||||
<blockquote>
|
||||
<div><p>This is just a small selection of the tools in <code class="docutils literal notranslate"><span class="pre">evennia/utils</span></code>. It’s worth to browse <a class="reference internal" href="../api/evennia.utils.html#evennia-utils"><span class="std std-ref">the directory</span></a> and in particular the content of <a class="reference internal" href="../api/evennia.utils.utils.html#evennia-utils-utils"><span class="std std-ref">evennia/utils/utils.py</span></a> directly to find more useful stuff.</p>
|
||||
</div></blockquote>
|
||||
<section id="searching">
|
||||
<h2>Searching<a class="headerlink" href="#searching" title="Permalink to this headline">¶</a></h2>
|
||||
<p>A common thing to do is to search for objects. There it’s easiest to use the <code class="docutils literal notranslate"><span class="pre">search</span></code> method defined
|
||||
|
|
@ -140,11 +137,8 @@ on all objects. This will search for objects in the same location and inside the
|
|||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">obj</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="n">objname</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The most common time one needs to do this is inside a command body. <code class="docutils literal notranslate"><span class="pre">obj</span> <span class="pre">=</span> <span class="pre">self.caller.search(objname)</span></code> will search inside the caller’s (typically, the character that typed
|
||||
the command) <code class="docutils literal notranslate"><span class="pre">.contents</span></code> (their “inventory”) and <code class="docutils literal notranslate"><span class="pre">.location</span></code> (their “room”).</p>
|
||||
<p>Give the keyword <code class="docutils literal notranslate"><span class="pre">global_search=True</span></code> to extend search to encompass entire database. Aliases will
|
||||
also be matched by this search. You will find multiple examples of this functionality in the default
|
||||
command set.</p>
|
||||
<p>The most common time one needs to do this is inside a command body. <code class="docutils literal notranslate"><span class="pre">obj</span> <span class="pre">=</span> <span class="pre">self.caller.search(objname)</span></code> will search inside the caller’s (typically, the character that typed the command) <code class="docutils literal notranslate"><span class="pre">.contents</span></code> (their “inventory”) and <code class="docutils literal notranslate"><span class="pre">.location</span></code> (their “room”).</p>
|
||||
<p>Give the keyword <code class="docutils literal notranslate"><span class="pre">global_search=True</span></code> to extend search to encompass entire database. Aliases will also be matched by this search. You will find multiple examples of this functionality in the default command set.</p>
|
||||
<p>If you need to search for objects in a code module you can use the functions in
|
||||
<code class="docutils literal notranslate"><span class="pre">evennia.utils.search</span></code>. You can access these as shortcuts <code class="docutils literal notranslate"><span class="pre">evennia.search_*</span></code>.</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">search_object</span>
|
||||
|
|
@ -152,42 +146,38 @@ command set.</p>
|
|||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p><a class="reference internal" href="../api/evennia.accounts.manager.html#evennia.accounts.manager.AccountDBManager.search_account" title="evennia.accounts.manager.AccountDBManager.search_account"><span class="xref myst py py-meth"><code class="docutils literal notranslate"><span class="pre">evennia.search_account</span></code></span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.objects.manager.html#evennia.objects.manager.ObjectDBManager.search_object" title="evennia.objects.manager.ObjectDBManager.search_object"><span class="xref myst py py-meth"><code class="docutils literal notranslate"><span class="pre">evennia.search_object</span></code></span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.utils.search.html#evennia.utils.search.search_tag" title="evennia.utils.search.search_tag"><span class="xref myst py py-func"><code class="docutils literal notranslate"><span class="pre">evennia.search(object)_by_tag</span></code></span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.scripts.manager.html#evennia.scripts.manager.ScriptDBManager.search_script" title="evennia.scripts.manager.ScriptDBManager.search_script"><span class="xref myst py py-meth"><code class="docutils literal notranslate"><span class="pre">evennia.search_script</span></code></span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.comms.managers.html#evennia.comms.managers.ChannelDBManager.search_channel" title="evennia.comms.managers.ChannelDBManager.search_channel"><span class="xref myst py py-meth"><code class="docutils literal notranslate"><span class="pre">evennia.search_channel</span></code></span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.comms.managers.html#evennia.comms.managers.MsgManager.search_message" title="evennia.comms.managers.MsgManager.search_message"><span class="xref myst py py-meth"><code class="docutils literal notranslate"><span class="pre">evennia.search_message</span></code></span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.help.manager.html#evennia.help.manager.HelpEntryManager.search_help" title="evennia.help.manager.HelpEntryManager.search_help"><span class="xref myst py py-meth"><code class="docutils literal notranslate"><span class="pre">evennia.search_help</span></code></span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.accounts.manager.html#evennia.accounts.manager.AccountDBManager.search_account" title="evennia.accounts.manager.AccountDBManager.search_account"><span class="xref myst py py-meth">evennia.search_account</span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.objects.manager.html#evennia.objects.manager.ObjectDBManager.search_object" title="evennia.objects.manager.ObjectDBManager.search_object"><span class="xref myst py py-meth">evennia.search_object</span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.utils.search.html#evennia.utils.search.search_tag" title="evennia.utils.search.search_tag"><span class="xref myst py py-func">evennia.search(object)_by_tag</span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.scripts.manager.html#evennia.scripts.manager.ScriptDBManager.search_script" title="evennia.scripts.manager.ScriptDBManager.search_script"><span class="xref myst py py-meth">evennia.search_script</span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.comms.managers.html#evennia.comms.managers.ChannelDBManager.search_channel" title="evennia.comms.managers.ChannelDBManager.search_channel"><span class="xref myst py py-meth">evennia.search_channel</span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.comms.managers.html#evennia.comms.managers.MsgManager.search_message" title="evennia.comms.managers.MsgManager.search_message"><span class="xref myst py py-meth">evennia.search_message</span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.help.manager.html#evennia.help.manager.HelpEntryManager.search_help" title="evennia.help.manager.HelpEntryManager.search_help"><span class="xref myst py py-meth">evennia.search_help</span></a></p></li>
|
||||
</ul>
|
||||
<p>Note that these latter methods will always return a <code class="docutils literal notranslate"><span class="pre">list</span></code> of results, even if the list has one or
|
||||
zero entries.</p>
|
||||
<p>Note that these latter methods will always return a <code class="docutils literal notranslate"><span class="pre">list</span></code> of results, even if the list has one or zero entries.</p>
|
||||
</section>
|
||||
<section id="create">
|
||||
<h2>Create<a class="headerlink" href="#create" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Apart from the in-game build commands (<code class="docutils literal notranslate"><span class="pre">@create</span></code> etc), you can also build all of Evennia’s game
|
||||
entities directly in code (for example when defining new create commands).</p>
|
||||
<p>Apart from the in-game build commands (<code class="docutils literal notranslate"><span class="pre">@create</span></code> etc), you can also build all of Evennia’s game entities directly in code (for example when defining new create commands).</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="kn">import</span> <span class="nn">evennia</span>
|
||||
|
||||
<span class="n">myobj</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">create_objects</span><span class="p">(</span><span class="s2">"game.gamesrc.objects.myobj.MyObj"</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">"MyObj"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p><a class="reference internal" href="../api/evennia.utils.create.html#evennia.utils.create.create_account" title="evennia.utils.create.create_account"><span class="xref myst py py-func"><code class="docutils literal notranslate"><span class="pre">evennia.create_account</span></code></span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.utils.create.html#evennia.utils.create.create_object" title="evennia.utils.create.create_object"><span class="xref myst py py-func"><code class="docutils literal notranslate"><span class="pre">evennia.create_object</span></code></span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.utils.create.html#evennia.utils.create.create_script" title="evennia.utils.create.create_script"><span class="xref myst py py-func"><code class="docutils literal notranslate"><span class="pre">evennia.create_script</span></code></span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.utils.create.html#evennia.utils.create.create_channel" title="evennia.utils.create.create_channel"><span class="xref myst py py-func"><code class="docutils literal notranslate"><span class="pre">evennia.create_channel</span></code></span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.utils.create.html#evennia.utils.create.create_help_entry" title="evennia.utils.create.create_help_entry"><span class="xref myst py py-func"><code class="docutils literal notranslate"><span class="pre">evennia.create_help_entry</span></code></span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.utils.create.html#evennia.utils.create.create_message" title="evennia.utils.create.create_message"><span class="xref myst py py-func"><code class="docutils literal notranslate"><span class="pre">evennia.create_message</span></code></span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.utils.create.html#evennia.utils.create.create_account" title="evennia.utils.create.create_account"><span class="xref myst py py-func">evennia.create_account</span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.utils.create.html#evennia.utils.create.create_object" title="evennia.utils.create.create_object"><span class="xref myst py py-func">evennia.create_object</span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.utils.create.html#evennia.utils.create.create_script" title="evennia.utils.create.create_script"><span class="xref myst py py-func">evennia.create_script</span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.utils.create.html#evennia.utils.create.create_channel" title="evennia.utils.create.create_channel"><span class="xref myst py py-func">evennia.create_channel</span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.utils.create.html#evennia.utils.create.create_help_entry" title="evennia.utils.create.create_help_entry"><span class="xref myst py py-func">evennia.create_help_entry</span></a></p></li>
|
||||
<li><p><a class="reference internal" href="../api/evennia.utils.create.html#evennia.utils.create.create_message" title="evennia.utils.create.create_message"><span class="xref myst py py-func">evennia.create_message</span></a></p></li>
|
||||
</ul>
|
||||
<p>Each of these create-functions have a host of arguments to further customize the created entity. See
|
||||
<code class="docutils literal notranslate"><span class="pre">evennia/utils/create.py</span></code> for more information.</p>
|
||||
<p>Each of these create-functions have a host of arguments to further customize the created entity. See <code class="docutils literal notranslate"><span class="pre">evennia/utils/create.py</span></code> for more information.</p>
|
||||
</section>
|
||||
<section id="logging">
|
||||
<h2>Logging<a class="headerlink" href="#logging" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Normally you can use Python <code class="docutils literal notranslate"><span class="pre">print</span></code> statements to see output to the terminal/log. The <code class="docutils literal notranslate"><span class="pre">print</span></code>
|
||||
statement should only be used for debugging though. For producion output, use the <code class="docutils literal notranslate"><span class="pre">logger</span></code> which
|
||||
will create proper logs either to terminal or to file.</p>
|
||||
statement should only be used for debugging though. For producion output, use the <code class="docutils literal notranslate"><span class="pre">logger</span></code> which will create proper logs either to terminal or to file.</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">logger</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">log_err</span><span class="p">(</span><span class="s2">"This is an Error!"</span><span class="p">)</span>
|
||||
|
|
@ -196,8 +186,7 @@ will create proper logs either to terminal or to file.</p>
|
|||
<span class="n">logger</span><span class="o">.</span><span class="n">log_dep</span><span class="p">(</span><span class="s2">"This feature is deprecated"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>There is a special log-message type, <code class="docutils literal notranslate"><span class="pre">log_trace()</span></code> that is intended to be called from inside a
|
||||
traceback - this can be very useful for relaying the traceback message back to log without having it
|
||||
<p>There is a special log-message type, <code class="docutils literal notranslate"><span class="pre">log_trace()</span></code> that is intended to be called from inside a traceback - this can be very useful for relaying the traceback message back to log without having it
|
||||
kill the server.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="k">try</span><span class="p">:</span>
|
||||
<span class="c1"># [some code that may fail...]</span>
|
||||
|
|
@ -205,24 +194,18 @@ kill the server.</p>
|
|||
<span class="n">logger</span><span class="o">.</span><span class="n">log_trace</span><span class="p">(</span><span class="s2">"This text will show beneath the traceback itself."</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">log_file</span></code> logger, finally, is a very useful logger for outputting arbitrary log messages. This
|
||||
is a heavily optimized asynchronous log mechanism using
|
||||
<a class="reference external" href="https://en.wikipedia.org/wiki/Thread_%28computing%29">threads</a> to avoid overhead. You should be
|
||||
able to use it for very heavy custom logging without fearing disk-write delays.</p>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">log_file</span></code> logger, finally, is a very useful logger for outputting arbitrary log messages. This is a heavily optimized asynchronous log mechanism using <a class="reference external" href="https://en.wikipedia.org/wiki/Thread_%28computing%29">threads</a> to avoid overhead. You should be able to use it for very heavy custom logging without fearing disk-write delays.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">logger</span><span class="o">.</span><span class="n">log_file</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="n">filename</span><span class="o">=</span><span class="s2">"mylog.log"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>If not an absolute path is given, the log file will appear in the <code class="docutils literal notranslate"><span class="pre">mygame/server/logs/</span></code> directory.
|
||||
If the file already exists, it will be appended to. Timestamps on the same format as the normal
|
||||
Evennia logs will be automatically added to each entry. If a filename is not specified, output will
|
||||
be written to a file <code class="docutils literal notranslate"><span class="pre">game/logs/game.log</span></code>.</p>
|
||||
<p>If not an absolute path is given, the log file will appear in the <code class="docutils literal notranslate"><span class="pre">mygame/server/logs/</span></code> directory. If the file already exists, it will be appended to. Timestamps on the same format as the normal Evennia logs will be automatically added to each entry. If a filename is not specified, output will be written to a file <code class="docutils literal notranslate"><span class="pre">game/logs/game.log</span></code>.</p>
|
||||
<p>See also the <a class="reference internal" href="../Coding/Debugging.html"><span class="doc std std-doc">Debugging</span></a> documentation for help with finding elusive bugs.</p>
|
||||
</section>
|
||||
<section id="time-utilities">
|
||||
<h2>Time Utilities<a class="headerlink" href="#time-utilities" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="game-time">
|
||||
<h3>Game time<a class="headerlink" href="#game-time" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Evennia tracks the current server time. You can access this time via the <code class="docutils literal notranslate"><span class="pre">evennia.gametime</span></code>
|
||||
shortcut:</p>
|
||||
<p>Evennia tracks the current server time. You can access this time via the <code class="docutils literal notranslate"><span class="pre">evennia.gametime</span></code> shortcut:</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">gametime</span>
|
||||
|
||||
<span class="c1"># all the functions below return times in seconds).</span>
|
||||
|
|
@ -247,12 +230,8 @@ shortcut:</p>
|
|||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The setting <code class="docutils literal notranslate"><span class="pre">TIME_FACTOR</span></code> determines how fast/slow in-game time runs compared to the real world. The
|
||||
setting <code class="docutils literal notranslate"><span class="pre">TIME_GAME_EPOCH</span></code> sets the starting game epoch (in seconds). The functions from the
|
||||
<code class="docutils literal notranslate"><span class="pre">gametime</span></code> module all return their times in seconds. You can convert this to whatever units of time
|
||||
you desire for your game. You can use the <code class="docutils literal notranslate"><span class="pre">@time</span></code> command to view the server time info.</p>
|
||||
<p>You can also <em>schedule</em> things to happen at specific in-game times using the
|
||||
<a class="reference internal" href="../api/evennia.utils.gametime.html#evennia.utils.gametime.schedule" title="evennia.utils.gametime.schedule"><span class="xref myst py py-func">gametime.schedule</span></a> function:</p>
|
||||
<p>The setting <code class="docutils literal notranslate"><span class="pre">TIME_FACTOR</span></code> determines how fast/slow in-game time runs compared to the real world. The setting <code class="docutils literal notranslate"><span class="pre">TIME_GAME_EPOCH</span></code> sets the starting game epoch (in seconds). The functions from the <code class="docutils literal notranslate"><span class="pre">gametime</span></code> module all return their times in seconds. You can convert this to whatever units of time you desire for your game. You can use the <code class="docutils literal notranslate"><span class="pre">@time</span></code> command to view the server time info.
|
||||
You can also <em>schedule</em> things to happen at specific in-game times using the <a class="reference internal" href="../api/evennia.utils.gametime.html#evennia.utils.gametime.schedule" title="evennia.utils.gametime.schedule"><span class="xref myst py py-func">gametime.schedule</span></a> function:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">evennia</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">church_clock</span><span class="p">:</span>
|
||||
|
|
@ -265,9 +244,7 @@ you desire for your game. You can use the <code class="docutils literal notransl
|
|||
</section>
|
||||
<section id="utils-time-format">
|
||||
<h3>utils.time_format()<a class="headerlink" href="#utils-time-format" title="Permalink to this headline">¶</a></h3>
|
||||
<p>This function takes a number of seconds as input (e.g. from the <code class="docutils literal notranslate"><span class="pre">gametime</span></code> module above) and
|
||||
converts it to a nice text output in days, hours etc. It’s useful when you want to show how old
|
||||
something is. It converts to four different styles of output using the <em>style</em> keyword:</p>
|
||||
<p>This function takes a number of seconds as input (e.g. from the <code class="docutils literal notranslate"><span class="pre">gametime</span></code> module above) and converts it to a nice text output in days, hours etc. It’s useful when you want to show how old something is. It converts to four different styles of output using the <em>style</em> keyword:</p>
|
||||
<ul class="simple">
|
||||
<li><p>style 0 - <code class="docutils literal notranslate"><span class="pre">5d:45m:12s</span></code> (standard colon output)</p></li>
|
||||
<li><p>style 1 - <code class="docutils literal notranslate"><span class="pre">5d</span></code> (shows only the longest time unit)</p></li>
|
||||
|
|
@ -277,50 +254,30 @@ something is. It converts to four different styles of output using the <em>style
|
|||
</section>
|
||||
<section id="utils-delay">
|
||||
<h3>utils.delay()<a class="headerlink" href="#utils-delay" title="Permalink to this headline">¶</a></h3>
|
||||
<p>This allows for making a delayed call.</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">utils</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_callback</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">text</span><span class="p">):</span>
|
||||
<span class="n">obj</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># wait 10 seconds before sending "Echo!" to obj (which we assume is defined)</span>
|
||||
<span class="n">deferred</span> <span class="o">=</span> <span class="n">utils</span><span class="o">.</span><span class="n">delay</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="n">_callback</span><span class="p">,</span> <span class="n">obj</span><span class="p">,</span> <span class="s2">"Echo!"</span><span class="p">,</span> <span class="n">persistent</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||||
<span class="n">utils</span><span class="o">.</span><span class="n">delay</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="n">_callback</span><span class="p">,</span> <span class="n">obj</span><span class="p">,</span> <span class="s2">"Echo!"</span><span class="p">,</span> <span class="n">persistent</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># code here will run immediately, not waiting for the delay to fire!</span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This creates an asynchronous delayed call. It will fire the given callback function after the given
|
||||
number of seconds. This is a very light wrapper over a Twisted
|
||||
<a class="reference external" href="https://twistedmatrix.com/documents/current/core/howto/defer.html">Deferred</a>. Normally this is run
|
||||
non-persistently, which means that if the server is <code class="docutils literal notranslate"><span class="pre">@reload</span></code>ed before the delay is over, the
|
||||
callback will never run (the server forgets it). If setting <code class="docutils literal notranslate"><span class="pre">persistent</span></code> to True, the delay will be
|
||||
stored in the database and survive a <code class="docutils literal notranslate"><span class="pre">@reload</span></code> - but for this to work it is susceptible to the same
|
||||
limitations incurred when saving to an <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attribute</span></a>.</p>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">deferred</span></code> return object can usually be ignored, but calling its <code class="docutils literal notranslate"><span class="pre">.cancel()</span></code> method will abort
|
||||
the delay prematurely.</p>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">utils.delay</span></code> is the lightest form of delayed call in Evennia. For other way to create time-bound
|
||||
tasks, see the <a class="reference internal" href="TickerHandler.html"><span class="doc std std-doc">TickerHandler</span></a> and <a class="reference internal" href="Scripts.html"><span class="doc std std-doc">Scripts</span></a>.</p>
|
||||
<blockquote>
|
||||
<div><p>Note that many delayed effects can be achieved without any need for an active timer. For example
|
||||
if you have a trait that should recover a point every 5 seconds you might just need its value when
|
||||
it’s needed, but checking the current time and calculating on the fly what value it should have.</p>
|
||||
</div></blockquote>
|
||||
<p>See <span class="xref myst">The Asynchronous process</span> for more information.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="object-classes">
|
||||
<h2>Object Classes<a class="headerlink" href="#object-classes" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="finding-classes">
|
||||
<h2>Finding Classes<a class="headerlink" href="#finding-classes" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="utils-inherits-from">
|
||||
<h3>utils.inherits_from()<a class="headerlink" href="#utils-inherits-from" title="Permalink to this headline">¶</a></h3>
|
||||
<p>This useful function takes two arguments - an object to check and a parent. It returns <code class="docutils literal notranslate"><span class="pre">True</span></code> if
|
||||
object inherits from parent <em>at any distance</em> (as opposed to Python’s in-built <code class="docutils literal notranslate"><span class="pre">is_instance()</span></code> that
|
||||
<p>This useful function takes two arguments - an object to check and a parent. It returns <code class="docutils literal notranslate"><span class="pre">True</span></code> if object inherits from parent <em>at any distance</em> (as opposed to Python’s in-built <code class="docutils literal notranslate"><span class="pre">is_instance()</span></code> that
|
||||
will only catch immediate dependence). This function also accepts as input any combination of
|
||||
classes, instances or python-paths-to-classes.</p>
|
||||
<p>Note that Python code should usually work with <a class="reference external" href="https://en.wikipedia.org/wiki/Duck_typing">duck
|
||||
typing</a>. But in Evennia’s case it can sometimes be useful
|
||||
to check if an object inherits from a given <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclass</span></a> as a way of identification. Say
|
||||
for example that we have a typeclass <em>Animal</em>. This has a subclass <em>Felines</em> which in turn has a
|
||||
subclass <em>HouseCat</em>. Maybe there are a bunch of other animal types too, like horses and dogs. Using
|
||||
<code class="docutils literal notranslate"><span class="pre">inherits_from</span></code> will allow you to check for all animals in one go:</p>
|
||||
<p>Note that Python code should usually work with <a class="reference external" href="https://en.wikipedia.org/wiki/Duck_typing">duck typing</a>. But in Evennia’s case it can sometimes be useful to check if an object inherits from a given <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclass</span></a> as a way of identification. Say for example that we have a typeclass <em>Animal</em>. This has a subclass <em>Felines</em> which in turn has a subclass <em>HouseCat</em>. Maybe there are a bunch of other animal types too, like horses and dogs. Using <code class="docutils literal notranslate"><span class="pre">inherits_from</span></code> will allow you to check for all animals in one go:</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">utils</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="n">utils</span><span class="o">.</span><span class="n">inherits_from</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="s2">"typeclasses.objects.animals.Animal"</span><span class="p">):</span>
|
||||
<span class="n">obj</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"The bouncer stops you in the door. He says: 'No talking animals allowed.'"</span><span class="p">)</span>
|
||||
|
|
@ -335,8 +292,7 @@ complete</em> selection of text utilities found in <code class="docutils literal
|
|||
If nothing else it can be good to look here before starting to develop a solution of your own.</p>
|
||||
<section id="utils-fill">
|
||||
<h3>utils.fill()<a class="headerlink" href="#utils-fill" title="Permalink to this headline">¶</a></h3>
|
||||
<p>This flood-fills a text to a given width (shuffles the words to make each line evenly wide). It also
|
||||
indents as needed.</p>
|
||||
<p>This flood-fills a text to a given width (shuffles the words to make each line evenly wide). It also indents as needed.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">outtxt</span> <span class="o">=</span> <span class="n">fill</span><span class="p">(</span><span class="n">intxt</span><span class="p">,</span> <span class="n">width</span><span class="o">=</span><span class="mi">78</span><span class="p">,</span> <span class="n">indent</span><span class="o">=</span><span class="mi">4</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
|
|
@ -353,13 +309,7 @@ can be useful in listings when showing multiple lines would mess up things.</p>
|
|||
</section>
|
||||
<section id="utils-dedent">
|
||||
<h3>utils.dedent()<a class="headerlink" href="#utils-dedent" title="Permalink to this headline">¶</a></h3>
|
||||
<p>This solves what may at first glance appear to be a trivial problem with text - removing
|
||||
indentations. It is used to shift entire paragraphs to the left, without disturbing any further
|
||||
formatting they may have. A common case for this is when using Python triple-quoted strings in code</p>
|
||||
<ul class="simple">
|
||||
<li><p>they will retain whichever indentation they have in the code, and to make easily-readable source
|
||||
code one usually don’t want to shift the string to the left edge.</p></li>
|
||||
</ul>
|
||||
<p>This solves what may at first glance appear to be a trivial problem with text - removing indentations. It is used to shift entire paragraphs to the left, without disturbing any further formatting they may have. A common case for this is when using Python triple-quoted strings in code - they will retain whichever indentation they have in the code, and to make easily-readable source code one usually don’t want to shift the string to the left edge.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1">#python code is entered at a given indentation</span>
|
||||
<span class="n">intxt</span> <span class="o">=</span> <span class="s2">"""</span>
|
||||
<span class="s2"> This is an example text that will end</span>
|
||||
|
|
@ -376,40 +326,8 @@ help entries).</p>
|
|||
</section>
|
||||
<section id="to-str-and-to-bytes">
|
||||
<h3>to_str() and to_bytes()<a class="headerlink" href="#to-str-and-to-bytes" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Evennia supplies two utility functions for converting text to the correct
|
||||
encodings. <code class="docutils literal notranslate"><span class="pre">to_str()</span></code> and <code class="docutils literal notranslate"><span class="pre">to_bytes()</span></code>. Unless you are adding a custom protocol and
|
||||
need to send byte-data over the wire, <code class="docutils literal notranslate"><span class="pre">to_str</span></code> is the only one you’ll need.</p>
|
||||
<p>The difference from Python’s in-built <code class="docutils literal notranslate"><span class="pre">str()</span></code> and <code class="docutils literal notranslate"><span class="pre">bytes()</span></code> operators are that
|
||||
the Evennia ones makes use of the <code class="docutils literal notranslate"><span class="pre">ENCODINGS</span></code> setting and will try very hard to
|
||||
never raise a traceback but instead echo errors through logging. See
|
||||
<a class="reference internal" href="../Concepts/Text-Encodings.html"><span class="doc std std-doc">here</span></a> for more info.</p>
|
||||
</section>
|
||||
<section id="ansi-coloring-tools">
|
||||
<h3>Ansi Coloring Tools<a class="headerlink" href="#ansi-coloring-tools" title="Permalink to this headline">¶</a></h3>
|
||||
<ul class="simple">
|
||||
<li><p><a class="reference internal" href="../api/evennia.utils.ansi.html#evennia-utils-ansi"><span class="std std-ref">evennia.utils.ansi</span></a></p></li>
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
<section id="display-utilities">
|
||||
<h2>Display utilities<a class="headerlink" href="#display-utilities" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="making-ascii-tables">
|
||||
<h3>Making ascii tables<a class="headerlink" href="#making-ascii-tables" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The <a class="reference internal" href="../api/evennia.utils.evtable.html#evennia.utils.evtable.EvTable" title="evennia.utils.evtable.EvTable"><span class="xref myst py py-class">EvTable</span></a> class (<code class="docutils literal notranslate"><span class="pre">evennia/utils/evtable.py</span></code>) can be used
|
||||
to create correctly formatted text tables. There is also
|
||||
<a class="reference internal" href="../api/evennia.utils.evform.html#evennia.utils.evform.EvForm" title="evennia.utils.evform.EvForm"><span class="xref myst py py-class">EvForm</span></a> (<code class="docutils literal notranslate"><span class="pre">evennia/utils/evform.py</span></code>). This reads a fixed-format
|
||||
text template from a file in order to create any level of sophisticated ascii layout. Both evtable
|
||||
and evform have lots of options and inputs so see the header of each module for help.</p>
|
||||
<p>The third-party <a class="reference external" href="https://code.google.com/p/prettytable/">PrettyTable</a> module is also included in
|
||||
Evennia. PrettyTable is considered deprecated in favor of EvTable since PrettyTable cannot handle
|
||||
ANSI colour. PrettyTable can be found in <code class="docutils literal notranslate"><span class="pre">evennia/utils/prettytable/</span></code>. See its homepage above for
|
||||
instructions.</p>
|
||||
</section>
|
||||
<section id="menus">
|
||||
<h3>Menus<a class="headerlink" href="#menus" title="Permalink to this headline">¶</a></h3>
|
||||
<ul class="simple">
|
||||
<li><p><a class="reference internal" href="../api/evennia.utils.evmenu.html#evennia.utils.evmenu.EvMenu" title="evennia.utils.evmenu.EvMenu"><span class="xref myst py py-class">evennia.EvMenu</span></a></p></li>
|
||||
</ul>
|
||||
<p>Evennia supplies two utility functions for converting text to the correct encodings. <code class="docutils literal notranslate"><span class="pre">to_str()</span></code> and <code class="docutils literal notranslate"><span class="pre">to_bytes()</span></code>. Unless you are adding a custom protocol and need to send byte-data over the wire, <code class="docutils literal notranslate"><span class="pre">to_str</span></code> is the only one you’ll need.</p>
|
||||
<p>The difference from Python’s in-built <code class="docutils literal notranslate"><span class="pre">str()</span></code> and <code class="docutils literal notranslate"><span class="pre">bytes()</span></code> operators are that the Evennia ones makes use of the <code class="docutils literal notranslate"><span class="pre">ENCODINGS</span></code> setting and will try very hard to never raise a traceback but instead echo errors through logging. See <a class="reference internal" href="../Concepts/Text-Encodings.html"><span class="doc std std-doc">here</span></a> for more info.</p>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Command Sets" href="Command-Sets.html" />
|
||||
<link rel="prev" title="Portal And Server" href="Portal-And-Server.html" />
|
||||
<link rel="prev" title="Locks" href="Locks.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
|
|
@ -33,7 +33,7 @@
|
|||
<a href="Command-Sets.html" title="Command Sets"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Portal-And-Server.html" title="Portal And Server"
|
||||
<a href="Locks.html" title="Locks"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" accesskey="U">Core Components</a> »</li>
|
||||
|
|
@ -91,8 +91,8 @@
|
|||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Portal-And-Server.html"
|
||||
title="previous chapter">Portal And Server</a></p>
|
||||
<p class="topless"><a href="Locks.html"
|
||||
title="previous chapter">Locks</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Command-Sets.html"
|
||||
title="next chapter">Command Sets</a></p>
|
||||
|
|
@ -137,8 +137,7 @@ be familiar with how the command system works. The two pages were split for easy
|
|||
<li><p>A <em>Command</em> is a python class containing all the functioning code for what a command does - for example, a <em>get</em> command would contain code for picking up objects.</p></li>
|
||||
<li><p>A <em>Command Set</em> (often referred to as a CmdSet or cmdset) is like a container for one or more Commands. A given Command can go into any number of different command sets. Only by putting the command set on a character object you will make all the commands therein available to use by that character. You can also store command sets on normal objects if you want users to be able to use the object in various ways. Consider a “Tree” object with a cmdset defining the commands <em>climb</em> and <em>chop down</em>. Or a “Clock” with a cmdset containing the single command <em>check time</em>.</p></li>
|
||||
</ol>
|
||||
<p>This page goes into full detail about how to use Commands. To fully use them you must also read the page detailing <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">Command Sets</span></a>. There is also a step-by-step <a class="reference internal" href="../Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Adding-Commands.html"><span class="doc std std-doc">Adding Command Tutorial</span></a> that will get you started quickly without the
|
||||
extra explanations.</p>
|
||||
<p>This page goes into full detail about how to use Commands. To fully use them you must also read the page detailing <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">Command Sets</span></a>. There is also a step-by-step <a class="reference internal" href="../Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Adding-Commands.html"><span class="doc std std-doc">Adding Command Tutorial</span></a> that will get you started quickly without the extra explanations.</p>
|
||||
<section id="defining-commands">
|
||||
<h2>Defining Commands<a class="headerlink" href="#defining-commands" title="Permalink to this headline">¶</a></h2>
|
||||
<p>All commands are implemented as normal Python classes inheriting from the base class <code class="docutils literal notranslate"><span class="pre">Command</span></code>
|
||||
|
|
@ -230,7 +229,7 @@ NPC).</p>
|
|||
<li><p><code class="docutils literal notranslate"><span class="pre">cmdstring</span></code> - the matched key for the command. This would be <em>look</em> in our example.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">args</span></code> - this is the rest of the string, except the command name. So if the string entered was <em>look at sword</em>, <code class="docutils literal notranslate"><span class="pre">args</span></code> would be ” <em>at sword</em>”. Note the space kept - Evennia would correctly interpret <code class="docutils literal notranslate"><span class="pre">lookat</span> <span class="pre">sword</span></code> too. This is useful for things like <code class="docutils literal notranslate"><span class="pre">/switches</span></code> that should not use space. In the <code class="docutils literal notranslate"><span class="pre">MuxCommand</span></code> class used for default commands, this space is stripped. Also see the <code class="docutils literal notranslate"><span class="pre">arg_regex</span></code> property if you want to enforce a space to make <code class="docutils literal notranslate"><span class="pre">lookat</span> <span class="pre">sword</span></code> give a command-not-found error.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">obj</span></code> - the game <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Object</span></a> on which this command is defined. This need not be the caller, but since <code class="docutils literal notranslate"><span class="pre">look</span></code> is a common (default) command, this is probably defined directly on <em>BigGuy</em> - so <code class="docutils literal notranslate"><span class="pre">obj</span></code> will point to BigGuy. Otherwise <code class="docutils literal notranslate"><span class="pre">obj</span></code> could be an Account or any interactive object with commands defined on it, like in the example of the “check time” command defined on a “Clock” object. - <code class="docutils literal notranslate"><span class="pre">cmdset</span></code> - this is a reference to the merged CmdSet (see below) from which this command was
|
||||
matched. This variable is rarely used, it’s main use is for the <a class="reference internal" href="Help-System.html#command-auto-help-system"><span class="std std-doc">auto-help system</span></a> (<em>Advanced note: the merged cmdset need NOT be the same as <code class="docutils literal notranslate"><span class="pre">BigGuy.cmdset</span></code>. The merged set can be a combination of the cmdsets from other objects in the room, for example</em>).</p></li>
|
||||
matched. This variable is rarely used, it’s main use is for the <span class="xref myst">auto-help system</span> (<em>Advanced note: the merged cmdset need NOT be the same as <code class="docutils literal notranslate"><span class="pre">BigGuy.cmdset</span></code>. The merged set can be a combination of the cmdsets from other objects in the room, for example</em>).</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">raw_string</span></code> - this is the raw input coming from the user, without stripping any surrounding
|
||||
whitespace. The only thing that is stripped is the ending newline marker.</p></li>
|
||||
</ul>
|
||||
|
|
@ -254,7 +253,7 @@ truthfully report this value - that case the <code class="docutils literal notra
|
|||
<li><p><code class="docutils literal notranslate"><span class="pre">help_category</span></code> (optional string) - setting this helps to structure the auto-help into categories. If none is set, this will be set to <em>General</em>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">save_for_next</span></code> (optional boolean). This defaults to <code class="docutils literal notranslate"><span class="pre">False</span></code>. If <code class="docutils literal notranslate"><span class="pre">True</span></code>, a copy of this command object (along with any changes you have done to it) will be stored by the system and can be accessed by the next command by retrieving <code class="docutils literal notranslate"><span class="pre">self.caller.ndb.last_cmd</span></code>. The next run command will either clear or replace the storage.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">arg_regex</span></code> (optional raw string): Used to force the parser to limit itself and tell it when the command-name ends and arguments begin (such as requiring this to be a space or a /switch). This is done with a regular expression. <a class="reference internal" href="#arg-regex"><span class="std std-doc">See the arg_regex section</span></a> for the details.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">auto_help</span></code> (optional boolean). Defaults to <code class="docutils literal notranslate"><span class="pre">True</span></code>. This allows for turning off the <a class="reference internal" href="Help-System.html#command-auto-help-system"><span class="std std-doc">auto-help system</span></a> on a per-command basis. This could be useful if you either want to write your help entries manually or hide the existence of a command from <code class="docutils literal notranslate"><span class="pre">help</span></code>’s generated list.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">auto_help</span></code> (optional boolean). Defaults to <code class="docutils literal notranslate"><span class="pre">True</span></code>. This allows for turning off the <span class="xref myst">auto-help system</span> on a per-command basis. This could be useful if you either want to write your help entries manually or hide the existence of a command from <code class="docutils literal notranslate"><span class="pre">help</span></code>’s generated list.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">is_exit</span></code> (bool) - this marks the command as being used for an in-game exit. This is, by default, set by all Exit objects and you should not need to set it manually unless you make your own Exit system. It is used for optimization and allows the cmdhandler to easily disregard this command when the cmdset has its <code class="docutils literal notranslate"><span class="pre">no_exits</span></code> flag set.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">is_channel</span></code> (bool)- this marks the command as being used for an in-game channel. This is, by default, set by all Channel objects and you should not need to set it manually unless you make your own Channel system. is used for optimization and allows the cmdhandler to easily disregard this command when its cmdset has its <code class="docutils literal notranslate"><span class="pre">no_channels</span></code> flag set.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">msg_all_sessions</span></code> (bool): This affects the behavior of the <code class="docutils literal notranslate"><span class="pre">Command.msg</span></code> method. If unset (default), calling <code class="docutils literal notranslate"><span class="pre">self.msg(text)</span></code> from the Command will always only send text to the Session that actually triggered this Command. If set however, <code class="docutils literal notranslate"><span class="pre">self.msg(text)</span></code> will send to all Sessions relevant to the object this Command sits on. Just which Sessions receives the text depends on the object and the server’s <code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE</span></code>.</p></li>
|
||||
|
|
@ -599,7 +598,7 @@ thus do so asynchronously, using callbacks.</p>
|
|||
<a href="Command-Sets.html" title="Command Sets"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Portal-And-Server.html" title="Portal And Server"
|
||||
<a href="Locks.html" title="Locks"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" >Core Components</a> »</li>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<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="Typeclasses" href="Typeclasses.html" />
|
||||
<link rel="next" title="Portal And Server" href="Portal-And-Server.html" />
|
||||
<link rel="prev" title="Tutorial for basic MUSH like game" href="../Howtos/Tutorial-for-basic-MUSH-like-game.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Typeclasses.html" title="Typeclasses"
|
||||
<a href="Portal-And-Server.html" title="Portal And Server"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="../Howtos/Tutorial-for-basic-MUSH-like-game.html" title="Tutorial for basic MUSH like game"
|
||||
|
|
@ -62,7 +62,7 @@
|
|||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Core Components</a><ul>
|
||||
<li><a class="reference internal" href="#basic-entites">Basic entites</a></li>
|
||||
<li><a class="reference internal" href="#base-components">Base components</a></li>
|
||||
<li><a class="reference internal" href="#commands">Commands</a></li>
|
||||
<li><a class="reference internal" href="#utils-and-tools">Utils and tools</a></li>
|
||||
<li><a class="reference internal" href="#web-components">Web components</a></li>
|
||||
|
|
@ -74,8 +74,8 @@
|
|||
<p class="topless"><a href="../Howtos/Tutorial-for-basic-MUSH-like-game.html"
|
||||
title="previous chapter">Tutorial for basic MUSH like game</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Typeclasses.html"
|
||||
title="next chapter">Typeclasses</a></p>
|
||||
<p class="topless"><a href="Portal-And-Server.html"
|
||||
title="next chapter">Portal And Server</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
|
|
@ -109,75 +109,54 @@
|
|||
<section class="tex2jax_ignore mathjax_ignore" id="core-components">
|
||||
<h1>Core Components<a class="headerlink" href="#core-components" title="Permalink to this headline">¶</a></h1>
|
||||
<p>These are the ‘building blocks’ out of which Evennia is built. This documentation is complementary to, and often goes deeper than, the doc-strings of each component in the <a class="reference internal" href="../Evennia-API.html"><span class="doc std std-doc">API</span></a>.</p>
|
||||
<section id="basic-entites">
|
||||
<h2>Basic entites<a class="headerlink" href="#basic-entites" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="base-components">
|
||||
<h2>Base components<a class="headerlink" href="#base-components" title="Permalink to this headline">¶</a></h2>
|
||||
<p>These are base pieces used to make an Evennia game. Most are long-lived and are persisted in the database.</p>
|
||||
<div class="toctree-wrapper compound">
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Portal-And-Server.html">Portal And Server</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Sessions.html">Sessions</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Sessions.html#working-with-sessions">Working with Sessions</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Sessions.html#portal-and-server-sessions">Portal and Server Sessions</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Typeclasses.html">Typeclasses</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Typeclasses.html#difference-between-typeclasses-and-classes">Difference between typeclasses and classes</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Typeclasses.html#creating-a-new-typeclass">Creating a new typeclass</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Typeclasses.html#about-typeclass-properties">About typeclass properties</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Typeclasses.html#overloading-hooks">Overloading hooks</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Typeclasses.html#querying-for-typeclasses">Querying for typeclasses</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Typeclasses.html#updating-existing-typeclass-instances">Updating existing typeclass instances</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Typeclasses.html#swap-typeclass">Swap typeclass</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Typeclasses.html#working-with-typeclasses">Working with typeclasses</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Typeclasses.html#how-typeclasses-actually-work">How typeclasses actually work</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Typeclasses.html#caveats">Caveats</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Typeclasses.html#will-i-run-out-of-dbrefs">Will I run out of dbrefs?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Sessions.html">Sessions</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Sessions.html#properties-on-sessions">Properties on Sessions</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Sessions.html#multisession-mode">Multisession mode</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Sessions.html#returning-data-to-the-session">Returning data to the session</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Sessions.html#customizing-the-session-object">Customizing the Session object</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Sessions.html#portal-and-server-sessions">Portal and Server Sessions</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Sessions.html#sessionhandlers">Sessionhandlers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Accounts.html">Accounts</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Accounts.html#how-to-customize-your-own-account-types">How to customize your own Account types</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Accounts.html#properties-on-accounts">Properties on Accounts</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Accounts.html#working-with-accounts">Working with Accounts</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Objects.html">Objects</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Objects.html#how-to-create-your-own-object-types">How to create your own object types</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Objects.html#working-with-objects">Working with Objects</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Objects.html#characters">Characters</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Objects.html#rooms">Rooms</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Objects.html#exits">Exits</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Objects.html#adding-common-functionality">Adding common functionality</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Objects.html#properties-and-functions-on-objects">Properties and functions on Objects</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Objects.html#subclasses-of-object">Subclasses of <code class="docutils literal notranslate"><span class="pre">Object</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Scripts.html">Scripts</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Scripts.html#in-game-command-examples">In-game command examples</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Scripts.html#code-examples">Code examples</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Scripts.html#defining-new-scripts">Defining new Scripts</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Scripts.html#timed-scripts">Timed Scripts</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Scripts.html#script-attached-to-another-object">Script attached to another object</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Scripts.html#other-script-methods">Other Script methods</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Scripts.html#the-global-scripts-container">The GLOBAL_SCRIPTS container</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Scripts.html#hints-dealing-with-script-errors">Hints: Dealing with Script Errors</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Scripts.html#working-with-scripts">Working with Scripts</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Scripts.html#using-global-scripts">Using GLOBAL_SCRIPTS</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Channels.html">Channels</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Channels.html#using-channels-in-game">Using channels in-game</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Channels.html#allowing-characters-to-use-channels">Allowing Characters to use Channels</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Channels.html#customizing-channel-output-and-behavior">Customizing channel output and behavior</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Channels.html#channels-in-code">Channels in code</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Channels.html#channel-logging">Channel logging</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Channels.html#working-with-channels">Working with channels</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Channels.html#using-channels-in-code">Using channels in code</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Msg.html">Msg</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Msg.html#msg-in-code">Msg in code</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Msg.html#working-with-msg">Working with Msg</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Msg.html#tempmsg">TempMsg</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Attributes.html">Attributes</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Attributes.html#managing-attributes-in-code">Managing Attributes in Code</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Attributes.html#managing-attributes-in-game">Managing Attributes in-game</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Attributes.html#locking-and-checking-attributes">Locking and checking Attributes</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Attributes.html#working-with-attributes">Working with Attributes</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Attributes.html#what-types-of-data-can-i-save-in-an-attribute">What types of data can I save in an Attribute?</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Attributes.html#properties-of-attributes">Properties of Attributes</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Attributes.html#in-memory-attributes-nattributes">In-memory Attributes (NAttributes)</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
|
@ -187,40 +166,35 @@
|
|||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Tags.html">Tags</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Tags.html#properties-of-tags-and-aliases-and-permissions">Properties of Tags (and Aliases and Permissions)</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Tags.html#adding-removing-tags">Adding/Removing Tags</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Tags.html#searching-for-objects-with-a-given-tag">Searching for objects with a given tag</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Tags.html#using-aliases-and-permissions">Using Aliases and Permissions</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Tags.html#assorted-notes">Assorted notes</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Tags.html#working-with-tags">Working with Tags</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Tags.html#aliases-and-permissions">Aliases and Permissions</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Prototypes.html">Spawner and Prototypes</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Prototypes.html#using-the-olc">Using the OLC</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Prototypes.html#the-prototype">The prototype</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Prototypes.html#storing-prototypes">Storing prototypes</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Prototypes.html#using-spawn">Using @spawn</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Prototypes.html#using-evennia-prototypes-spawner">Using evennia.prototypes.spawner()</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Prototypes.html#working-with-prototypes">Working with Prototypes</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Prototypes.html#database-prototypes">Database prototypes</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Prototypes.html#module-based-prototypes">Module-based prototypes</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Prototypes.html#spawning">Spawning</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Help-System.html">Help System</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Help-System.html#using-the-help-system-from-in-game">Using the help system from in-game</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Help-System.html#sources-of-help-entries">Sources of help entries</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Help-System.html#entry-priority">Entry priority</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Help-System.html#locking-help-entries">Locking help entries</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Help-System.html#customizing-the-look-of-the-help-system">Customizing the look of the help system</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Help-System.html#working-with-three-types-of-help-entries">Working with three types of help entries</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Help-System.html#subtopics">Subtopics</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Help-System.html#technical-notes">Technical notes</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Permissions.html">Permissions</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Permissions.html#the-super-user">The super user</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Permissions.html#managing-permissions">Managing Permissions</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Permissions.html#the-permission-hierarchy">The permission hierarchy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Permissions.html#checking-permissions">Checking permissions</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Permissions.html#superusers">Superusers</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Permissions.html#working-with-permissions">Working with Permissions</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Permissions.html#quelling">Quelling</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Portal-And-Server.html">Portal And Server</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Locks.html">Locks</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Locks.html#working-with-locks">Working with locks</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Locks.html#more-lock-definition-examples">More Lock definition examples</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Locks.html#on-djangos-permission-system">On Django’s permission system</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -249,34 +223,15 @@
|
|||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Default-Commands.html">Default Commands</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Connection-Screen.html">Connection Screen</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Connection-Screen.html#commands-available-at-the-connection-screen">Commands available at the Connection Screen</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Batch-Processors.html">Batch Processors</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Batch-Command-Processor.html">Batch Command Processor</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Batch-Code-Processor.html">Batch Code Processor</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Batch-Processors.html#a-note-on-file-encodings">A note on File Encodings</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Batch-Code-Processor.html">Batch Code Processor</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Batch-Code-Processor.html#basic-usage">Basic Usage</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Batch-Code-Processor.html#the-batch-file">The batch file</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Batch-Code-Processor.html#debug-mode">Debug mode</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Batch-Code-Processor.html#interactive-mode">Interactive mode</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Batch-Code-Processor.html#limitations-and-caveats">Limitations and Caveats</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Batch-Command-Processor.html">Batch Command Processor</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Batch-Command-Processor.html#basic-usage">Basic Usage</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Batch-Command-Processor.html#the-batch-file">The batch file</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Batch-Command-Processor.html#interactive-mode">Interactive mode</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Batch-Command-Processor.html#limitations-and-caveats">Limitations and Caveats</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Batch-Command-Processor.html#assorted-notes">Assorted notes</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Inputfuncs.html">Inputfuncs</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Inputfuncs.html#adding-your-own-inputfuncs">Adding your own inputfuncs</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Inputfuncs.html#default-inputfuncs">Default inputfuncs</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Inputfuncs.html#unmonitor">unmonitor</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
@ -292,43 +247,31 @@
|
|||
<li class="toctree-l2"><a class="reference internal" href="Coding-Utils.html#create">Create</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Coding-Utils.html#logging">Logging</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Coding-Utils.html#time-utilities">Time Utilities</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Coding-Utils.html#object-classes">Object Classes</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Coding-Utils.html#finding-classes">Finding Classes</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Coding-Utils.html#text-utilities">Text utilities</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Coding-Utils.html#display-utilities">Display utilities</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="EvEditor.html">EvEditor</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="EvEditor.html#launching-the-editor">Launching the editor</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="EvEditor.html#example-of-usage">Example of usage</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="EvEditor.html#persistent-editor">Persistent editor</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="EvEditor.html#line-editor-usage">Line editor usage</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="EvEditor.html#the-eveditor-to-edit-code">The EvEditor to edit code</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="EvEditor.html#working-with-eveditor">Working with EvEditor</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="EvForm.html">EvForm</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="EvMenu.html">EvMenu</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="EvMenu.html#introduction">Introduction</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="EvMenu.html#launching-the-menu">Launching the menu</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="EvMenu.html#the-menu-nodes">The Menu nodes</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="EvMenu.html#temporary-storage">Temporary storage</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="EvMenu.html#customizing-menu-formatting">Customizing Menu formatting</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="EvMenu.html#evmenu-templating-language">EvMenu templating language</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="EvMenu.html#id1">Examples:</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="EvMenu.html#ask-for-simple-input">Ask for simple input</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="EvMenu.html#asking-for-one-line-input">Asking for one-line input</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="EvMenu.html#the-list-node-decorator">The <code class="docutils literal notranslate"><span class="pre">@list_node</span></code> decorator</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="EvMenu.html#assorted-notes">Assorted notes</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="EvMore.html">EvMore</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="EvMore.html#using-evmore">Using EvMore</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="EvMenu.html#example-menus">Example Menus</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="EvMore.html">EvMore</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="EvTable.html">EvTable</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="FuncParser.html">The Inline Function Parser</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="FuncParser.html#uses-in-default-evennia">Uses in default Evennia</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="FuncParser.html#using-the-funcparser">Using the FuncParser</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="FuncParser.html">FuncParser inline text parsing</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="FuncParser.html#working-with-funcparser">Working with FuncParser</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="FuncParser.html#defining-custom-callables">Defining custom callables</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="FuncParser.html#default-callables">Default callables</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="FuncParser.html#default-funcparser-callables">Default funcparser callables</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="MonitorHandler.html">MonitorHandler</a><ul>
|
||||
|
|
@ -339,19 +282,8 @@
|
|||
<li class="toctree-l2"><a class="reference internal" href="TickerHandler.html#about-tickers">About Tickers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Locks.html">Locks</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Locks.html#setting-and-checking-a-lock">Setting and checking a lock</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Locks.html#defining-locks">Defining locks</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Locks.html#checking-simple-strings">Checking simple strings</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Locks.html#default-locks">Default locks</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Locks.html#more-lock-definition-examples">More Lock definition examples</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Locks.html#a-complete-example-of-setting-locks-on-an-object">A complete example of setting locks on an object</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Locks.html#on-djangos-permission-system">On Django’s permission system</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="Signals.html">Signals</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Signals.html#attaching-a-handler-to-a-signal">Attaching a handler to a signal</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Signals.html#available-signals">Available signals</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Signals.html#working-with-signals">Working with Signals</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
@ -419,7 +351,7 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Typeclasses.html" title="Typeclasses"
|
||||
<a href="Portal-And-Server.html" title="Portal And Server"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="../Howtos/Tutorial-for-basic-MUSH-like-game.html" title="Tutorial for basic MUSH like game"
|
||||
|
|
|
|||
|
|
@ -1,175 +0,0 @@
|
|||
|
||||
<!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>Connection Screen — 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>
|
||||
<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="Batch Processors" href="Batch-Processors.html" />
|
||||
<link rel="prev" title="Default Commands" href="Default-Commands.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="Batch-Processors.html" title="Batch Processors"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Default-Commands.html" title="Default Commands"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" accesskey="U">Core Components</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Connection Screen</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
|
||||
<div class="documentwrapper">
|
||||
<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>
|
||||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Connection Screen</a><ul>
|
||||
<li><a class="reference internal" href="#commands-available-at-the-connection-screen">Commands available at the Connection Screen</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Default-Commands.html"
|
||||
title="previous chapter">Default Commands</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Batch-Processors.html"
|
||||
title="next chapter">Batch Processors</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Components/Connection-Screen.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="Connection-Screen.html">1.0-dev (develop branch)</a></li>
|
||||
<ul>
|
||||
<li><a href="../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="connection-screen">
|
||||
<h1>Connection Screen<a class="headerlink" href="#connection-screen" title="Permalink to this headline">¶</a></h1>
|
||||
<p>When you first connect to your game you are greeted by Evennia’s default connection screen.</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>==============================================================
|
||||
Welcome to Evennia, version Beta-ra4d24e8a3cab+!
|
||||
|
||||
If you have an existing account, connect to it by typing:
|
||||
connect <username> <password>
|
||||
If you need to create an account, type (without the <>'s):
|
||||
create <username> <password>
|
||||
|
||||
If you have spaces in your username, enclose it in quotes.
|
||||
Enter help for more info. look will re-show this screen.
|
||||
==============================================================
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Effective, but not very exciting. You will most likely want to change this to be more unique for
|
||||
your game. This is simple:</p>
|
||||
<ol class="simple">
|
||||
<li><p>Edit <code class="docutils literal notranslate"><span class="pre">mygame/server/conf/connection_screens.py</span></code>.</p></li>
|
||||
<li><p><a class="reference internal" href="../Setup/Running-Evennia.html"><span class="doc std std-doc">Reload</span></a> Evennia.</p></li>
|
||||
</ol>
|
||||
<p>Evennia will look into this module and locate all <em>globally defined strings</em> in it. These strings
|
||||
are used as the text in your connection screen and are shown to the user at startup. If more than
|
||||
one such string/screen is defined in the module, a <em>random</em> screen will be picked from among those
|
||||
available.</p>
|
||||
<section id="commands-available-at-the-connection-screen">
|
||||
<h2>Commands available at the Connection Screen<a class="headerlink" href="#commands-available-at-the-connection-screen" title="Permalink to this headline">¶</a></h2>
|
||||
<p>You can also customize the <a class="reference internal" href="Commands.html"><span class="doc std std-doc">Commands</span></a> available to use while the connection screen is
|
||||
shown (<code class="docutils literal notranslate"><span class="pre">connect</span></code>, <code class="docutils literal notranslate"><span class="pre">create</span></code> etc). These commands are a bit special since when the screen is running
|
||||
the account is not yet logged in. A command is made available at the login screen by adding them to
|
||||
<code class="docutils literal notranslate"><span class="pre">UnloggedinCmdSet</span></code> in <code class="docutils literal notranslate"><span class="pre">mygame/commands/default_cmdset.py</span></code>. See <a class="reference internal" href="Commands.html"><span class="doc std std-doc">Commands</span></a> and the
|
||||
tutorial section on how to add new commands to a default command set.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</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="Batch-Processors.html" title="Batch Processors"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Default-Commands.html" title="Default Commands"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" >Core Components</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Connection Screen</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2022, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
<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="Connection Screen" href="Connection-Screen.html" />
|
||||
<link rel="next" title="Batch Processors" href="Batch-Processors.html" />
|
||||
<link rel="prev" title="Command Sets" href="Command-Sets.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Connection-Screen.html" title="Connection Screen"
|
||||
<a href="Batch-Processors.html" title="Batch Processors"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Command-Sets.html" title="Command Sets"
|
||||
|
|
@ -64,8 +64,8 @@
|
|||
<p class="topless"><a href="Command-Sets.html"
|
||||
title="previous chapter">Command Sets</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Connection-Screen.html"
|
||||
title="next chapter">Connection Screen</a></p>
|
||||
<p class="topless"><a href="Batch-Processors.html"
|
||||
title="next chapter">Batch Processors</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
|
|
@ -211,7 +211,7 @@ with <a class="reference internal" href="EvEditor.html"><span class="doc std std
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Connection-Screen.html" title="Connection Screen"
|
||||
<a href="Batch-Processors.html" title="Batch Processors"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Command-Sets.html" title="Command Sets"
|
||||
|
|
|
|||
|
|
@ -64,12 +64,14 @@
|
|||
<ul>
|
||||
<li><a class="reference internal" href="#">EvEditor</a><ul>
|
||||
<li><a class="reference internal" href="#launching-the-editor">Launching the editor</a></li>
|
||||
<li><a class="reference internal" href="#example-of-usage">Example of usage</a></li>
|
||||
<li><a class="reference internal" href="#working-with-eveditor">Working with EvEditor</a><ul>
|
||||
<li><a class="reference internal" href="#persistent-editor">Persistent editor</a></li>
|
||||
<li><a class="reference internal" href="#line-editor-usage">Line editor usage</a></li>
|
||||
<li><a class="reference internal" href="#the-eveditor-to-edit-code">The EvEditor to edit code</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
|
|
@ -137,8 +139,8 @@ It has no other mechanical function.</p></li>
|
|||
<li><p><code class="docutils literal notranslate"><span class="pre">persistent</span></code> (default <code class="docutils literal notranslate"><span class="pre">False</span></code>): if set to <code class="docutils literal notranslate"><span class="pre">True</span></code>, the editor will survive a reboot.</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section id="example-of-usage">
|
||||
<h2>Example of usage<a class="headerlink" href="#example-of-usage" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="working-with-eveditor">
|
||||
<h2>Working with EvEditor<a class="headerlink" href="#working-with-eveditor" title="Permalink to this headline">¶</a></h2>
|
||||
<p>This is an example command for setting a specific Attribute using the editor.</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">Command</span>
|
||||
<span class="kn">from</span> <span class="nn">evennia.utils</span> <span class="kn">import</span> <span class="n">eveditor</span>
|
||||
|
|
@ -171,9 +173,8 @@ It has no other mechanical function.</p></li>
|
|||
<span class="n">key</span><span class="o">=</span><span class="n">key</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="persistent-editor">
|
||||
<h2>Persistent editor<a class="headerlink" href="#persistent-editor" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Persistent editor<a class="headerlink" href="#persistent-editor" title="Permalink to this headline">¶</a></h3>
|
||||
<p>If you set the <code class="docutils literal notranslate"><span class="pre">persistent</span></code> keyword to <code class="docutils literal notranslate"><span class="pre">True</span></code> when creating the editor, it will remain open even
|
||||
when reloading the game. In order to be persistent, an editor needs to have its callback functions
|
||||
(<code class="docutils literal notranslate"><span class="pre">loadfunc</span></code>, <code class="docutils literal notranslate"><span class="pre">savefunc</span></code> and <code class="docutils literal notranslate"><span class="pre">quitfunc</span></code>) as top-level functions defined in the module. Since these
|
||||
|
|
@ -214,7 +215,7 @@ functions will be stored, Python will need to find them.</p>
|
|||
</div>
|
||||
</section>
|
||||
<section id="line-editor-usage">
|
||||
<h2>Line editor usage<a class="headerlink" href="#line-editor-usage" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Line editor usage<a class="headerlink" href="#line-editor-usage" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The editor mimics the <code class="docutils literal notranslate"><span class="pre">VIM</span></code> editor as best as possible. The below is an excerpt of the return from
|
||||
the in-editor help command (<code class="docutils literal notranslate"><span class="pre">:h</span></code>).</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <txt> - any non-command is appended to the end of the buffer.
|
||||
|
|
@ -260,29 +261,21 @@ the in-editor help command (<code class="docutils literal notranslate"><span cla
|
|||
</div>
|
||||
</section>
|
||||
<section id="the-eveditor-to-edit-code">
|
||||
<h2>The EvEditor to edit code<a class="headerlink" href="#the-eveditor-to-edit-code" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">EvEditor</span></code> is also used to edit some Python code in Evennia. The <code class="docutils literal notranslate"><span class="pre">@py</span></code> command supports an
|
||||
<code class="docutils literal notranslate"><span class="pre">/edit</span></code> switch that will open the EvEditor in code mode. This mode isn’t significantly different
|
||||
from the standard one, except it handles automatic indentation of blocks and a few options to
|
||||
control this behavior.</p>
|
||||
<h3>The EvEditor to edit code<a class="headerlink" href="#the-eveditor-to-edit-code" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">EvEditor</span></code> is also used to edit some Python code in Evennia. The <code class="docutils literal notranslate"><span class="pre">py</span></code> command supports an <code class="docutils literal notranslate"><span class="pre">/edit</span></code> switch that will open the EvEditor in code mode. This mode isn’t significantly different from the standard one, except it handles automatic indentation of blocks and a few options to control this behavior.</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">:<</span></code> to remove a level of indentation for the future lines.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">:+</span></code> to add a level of indentation for the future lines.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">:=</span></code> to disable automatic indentation altogether.</p></li>
|
||||
</ul>
|
||||
<p>Automatic indentation is there to make code editing more simple. Python needs correct indentation,
|
||||
not as an aesthetic addition, but as a requirement to determine beginning and ending of blocks. The
|
||||
EvEditor will try to guess the next level of indentation. If you type a block “if”, for instance,
|
||||
the EvEditor will propose you an additional level of indentation at the next line. This feature
|
||||
cannot be perfect, however, and sometimes, you will have to use the above options to handle
|
||||
indentation.</p>
|
||||
<p>Automatic indentation is there to make code editing more simple. Python needs correct indentation, not as an aesthetic addition, but as a requirement to determine beginning and ending of blocks. The EvEditor will try to guess the next level of indentation. If you type a block “if”, for instance, the EvEditor will propose you an additional level of indentation at the next line. This feature cannot be perfect, however, and sometimes, you will have to use the above options to handle indentation.</p>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">:=</span></code> can be used to turn automatic indentation off completely. This can be very useful when trying
|
||||
to paste several lines of code that are already correctly indented, for instance.</p>
|
||||
<p>To see the EvEditor in code mode, you can use the <code class="docutils literal notranslate"><span class="pre">@py/edit</span></code> command. Type in your code (on one or
|
||||
several lines). You can then use the <code class="docutils literal notranslate"><span class="pre">:w</span></code> option (save without quitting) and the code you have
|
||||
<p>To see the EvEditor in code mode, you can use the <code class="docutils literal notranslate"><span class="pre">@py/edit</span></code> command. Type in your code (on one or several lines). You can then use the <code class="docutils literal notranslate"><span class="pre">:w</span></code> option (save without quitting) and the code you have
|
||||
typed will be executed. The <code class="docutils literal notranslate"><span class="pre">:!</span></code> will do the same thing. Executing code while not closing the
|
||||
editor can be useful if you want to test the code you have typed but add new lines after your test.</p>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -63,10 +63,6 @@
|
|||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">EvMenu</a><ul>
|
||||
<li><a class="reference internal" href="#introduction">Introduction</a><ul>
|
||||
<li><a class="reference internal" href="#examples">Examples</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#launching-the-menu">Launching the menu</a></li>
|
||||
<li><a class="reference internal" href="#the-menu-nodes">The Menu nodes</a><ul>
|
||||
<li><a class="reference internal" href="#input-arguments-to-the-node">Input arguments to the node</a></li>
|
||||
|
|
@ -80,16 +76,25 @@
|
|||
<li><a class="reference internal" href="#option-key-goto">option-key ‘goto’</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#temporary-storage">Temporary storage</a></li>
|
||||
<li><a class="reference internal" href="#customizing-menu-formatting">Customizing Menu formatting</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#evmenu-templating-language">EvMenu templating language</a><ul>
|
||||
<li><a class="reference internal" href="#template-options">Template Options</a></li>
|
||||
<li><a class="reference internal" href="#templating-example">Templating example</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#id1">Examples:</a><ul>
|
||||
<li><a class="reference internal" href="#asking-for-one-line-input">Asking for one-line input</a><ul>
|
||||
<li><a class="reference internal" href="#the-yield-way">The <code class="docutils literal notranslate"><span class="pre">yield</span></code> way</a></li>
|
||||
<li><a class="reference internal" href="#the-get-input-way">The <code class="docutils literal notranslate"><span class="pre">get_input</span></code> way</a><ul>
|
||||
<li><a class="reference internal" href="#example-yes-no-prompt">Example: Yes/No prompt</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#the-list-node-decorator">The <code class="docutils literal notranslate"><span class="pre">@list_node</span></code> decorator</a></li>
|
||||
<li><a class="reference internal" href="#example-menus">Example Menus</a><ul>
|
||||
<li><a class="reference internal" href="#example-simple-branching-menu">Example: Simple branching menu</a></li>
|
||||
<li><a class="reference internal" href="#example-dynamic-goto">Example: Dynamic goto</a></li>
|
||||
<li><a class="reference internal" href="#example-set-caller-properties">Example: Set caller properties</a></li>
|
||||
|
|
@ -99,16 +104,6 @@
|
|||
<li><a class="reference internal" href="#defining-nodes-in-a-dictionary">Defining nodes in a dictionary</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#ask-for-simple-input">Ask for simple input</a><ul>
|
||||
<li><a class="reference internal" href="#the-yield-way">The <code class="docutils literal notranslate"><span class="pre">yield</span></code> way</a></li>
|
||||
<li><a class="reference internal" href="#the-get-input-way">The <code class="docutils literal notranslate"><span class="pre">get_input</span></code> way</a><ul>
|
||||
<li><a class="reference internal" href="#example-yes-no-prompt">Example: Yes/No prompt</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#the-list-node-decorator">The <code class="docutils literal notranslate"><span class="pre">@list_node</span></code> decorator</a></li>
|
||||
<li><a class="reference internal" href="#assorted-notes">Assorted notes</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
@ -151,37 +146,25 @@
|
|||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="evmenu">
|
||||
<h1>EvMenu<a class="headerlink" href="#evmenu" title="Permalink to this headline">¶</a></h1>
|
||||
<p>EvMenu is used for generate branching multi-choice menus. Each menu ‘node’ can
|
||||
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>Is your answer yes or no?
|
||||
_________________________________________
|
||||
<span class="o">[</span>Y<span class="o">]</span>es! - Answer yes.
|
||||
<span class="o">[</span>N<span class="o">]</span>o! - Answer no.
|
||||
<span class="o">[</span>A<span class="o">]</span>bort - Answer neither, and abort.
|
||||
|
||||
> Y
|
||||
You chose yes!
|
||||
|
||||
Thanks <span class="k">for</span> your answer. Goodbye!
|
||||
</pre></div>
|
||||
</div>
|
||||
<p><em>EvMenu</em> is used for generate branching multi-choice menus. Each menu ‘node’ can
|
||||
accepts specific options as input or free-form input. Depending what the player
|
||||
chooses, they are forwarded to different nodes in the menu.</p>
|
||||
<section id="introduction">
|
||||
<h2>Introduction<a class="headerlink" href="#introduction" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> utility class is located in <a class="reference internal" href="../api/evennia.utils.evmenu.html#evennia-utils-evmenu"><span class="std std-ref">evennia/utils/evmenu.py</span></a>.
|
||||
It allows for easily adding interactive menus to the game; for example to implement Character
|
||||
creation, building commands or similar. Below is an example of offering NPC conversation choices:</p>
|
||||
<section id="examples">
|
||||
<h3>Examples<a class="headerlink" href="#examples" title="Permalink to this headline">¶</a></h3>
|
||||
<p>This section gives some examples of how menus work in-game. A menu is a state
|
||||
(it’s actually a custom cmdset) where menu-specific commands are made available
|
||||
to you. An EvMenu is usually started from inside a command, but could also
|
||||
just be put in a file and run with <code class="docutils literal notranslate"><span class="pre">py</span></code>.</p>
|
||||
<p>This is how the example menu will look in-game:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>Is your answer yes or no?
|
||||
_________________________________________
|
||||
[Y]es! - Answer yes.
|
||||
[N]o! - Answer no.
|
||||
[A]bort - Answer neither, and abort.
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>If you pick (for example) Y(es), you will see</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>You chose yes!
|
||||
|
||||
Thanks for your answer. Goodbye!
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>After which the menu will end (in this example at least - it could also continue
|
||||
on to other questions and choices or even repeat the same node over and over!)</p>
|
||||
<p>Here’s the full EvMenu code for this example:</p>
|
||||
<p>This is how the example menu at the top of this page will look in code:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.utils</span> <span class="kn">import</span> <span class="n">evmenu</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_handle_answer</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">raw_input</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||||
|
|
@ -317,8 +300,6 @@ uses the template-string and a mapping of callables (we must add
|
|||
means depends on your game) to decide if your approach succeeded. It may then
|
||||
choose to point you to nodes that continue the conversation or maybe dump you
|
||||
into combat!</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="launching-the-menu">
|
||||
<h2>Launching the menu<a class="headerlink" href="#launching-the-menu" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Initializing the menu is done using a call to the <code class="docutils literal notranslate"><span class="pre">evennia.utils.evmenu.EvMenu</span></code> class. This is the
|
||||
|
|
@ -354,39 +335,14 @@ most common way to do so - from inside a <a class="reference internal" href="Com
|
|||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">caller</span></code> (Object or Account): is a reference to the object using the menu. This object will get a
|
||||
new <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">CmdSet</span></a> assigned to it, for handling the menu.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">menu_data</span></code> (str, module or dict): is a module or python path to a module where the global-level
|
||||
functions will each be considered to be a menu node. Their names in the module will be the names
|
||||
by which they are referred to in the module. Importantly, function names starting with an
|
||||
underscore
|
||||
<code class="docutils literal notranslate"><span class="pre">_</span></code> will be ignored by the loader. Alternatively, this can be a direct mapping
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">caller</span></code> (Object or Account): is a reference to the object using the menu. This object will get a new <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">CmdSet</span></a> assigned to it, for handling the menu.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">menu_data</span></code> (str, module or dict): is a module or python path to a module where the global-level functions will each be considered to be a menu node. Their names in the module will be the names by which they are referred to in the module. Importantly, function names starting with an underscore <code class="docutils literal notranslate"><span class="pre">_</span></code> will be ignored by the loader. Alternatively, this can be a direct mapping
|
||||
<code class="docutils literal notranslate"><span class="pre">{"nodename":function,</span> <span class="pre">...}</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">startnode</span></code> (str): is the name of the menu-node to start the menu at. Changing this means that
|
||||
you can jump into a menu tree at different positions depending on circumstance and thus possibly
|
||||
re-use menu entries.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">cmdset_mergetype</span></code> (str): This is usually one of “Replace” or “Union” (see [CmdSets](Command-
|
||||
Sets).
|
||||
The first means that the menu is exclusive - the user has no access to any other commands while
|
||||
in the menu. The Union mergetype means the menu co-exists with previous commands (and may
|
||||
overload
|
||||
them, so be careful as to what to name your menu entries in this case).</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">cmdset_priority</span></code> (int): The priority with which to merge in the menu cmdset. This allows for
|
||||
advanced usage.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">auto_quit</span></code>, <code class="docutils literal notranslate"><span class="pre">auto_look</span></code>, <code class="docutils literal notranslate"><span class="pre">auto_help</span></code> (bool): If either of these are <code class="docutils literal notranslate"><span class="pre">True</span></code>, the menu
|
||||
automatically makes a <code class="docutils literal notranslate"><span class="pre">quit</span></code>, <code class="docutils literal notranslate"><span class="pre">look</span></code> or <code class="docutils literal notranslate"><span class="pre">help</span></code> command available to the user. The main reason why
|
||||
you’d want to turn this off is if you want to use the aliases “q”, “l” or “h” for something in
|
||||
your
|
||||
menu. Nevertheless, at least <code class="docutils literal notranslate"><span class="pre">quit</span></code> is highly recommend - if <code class="docutils literal notranslate"><span class="pre">False</span></code>, the menu <em>must</em> itself
|
||||
supply
|
||||
an “exit node” (a node without any options), or the user will be stuck in the menu until the
|
||||
server
|
||||
reloads (or eternally if the menu is <code class="docutils literal notranslate"><span class="pre">persistent</span></code>)!</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">cmd_on_exit</span></code> (str): This command string will be executed right <em>after</em> the menu has closed down.
|
||||
From experience, it’s useful to trigger a “look” command to make sure the user is aware of the
|
||||
change of state; but any command can be used. If set to <code class="docutils literal notranslate"><span class="pre">None</span></code>, no command will be triggered
|
||||
after
|
||||
exiting the menu.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">startnode</span></code> (str): is the name of the menu-node to start the menu at. Changing this means that you can jump into a menu tree at different positions depending on circumstance and thus possibly re-use menu entries.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">cmdset_mergetype</span></code> (str): This is usually one of “Replace” or “Union” (see [CmdSets](Command- Sets). The first means that the menu is exclusive - the user has no access to any other commands while in the menu. The Union mergetype means the menu co-exists with previous commands (and may overload them, so be careful as to what to name your menu entries in this case).</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">cmdset_priority</span></code> (int): The priority with which to merge in the menu cmdset. This allows for advanced usage.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">auto_quit</span></code>, <code class="docutils literal notranslate"><span class="pre">auto_look</span></code>, <code class="docutils literal notranslate"><span class="pre">auto_help</span></code> (bool): If either of these are <code class="docutils literal notranslate"><span class="pre">True</span></code>, the menu automatically makes a <code class="docutils literal notranslate"><span class="pre">quit</span></code>, <code class="docutils literal notranslate"><span class="pre">look</span></code> or <code class="docutils literal notranslate"><span class="pre">help</span></code> command available to the user. The main reason why you’d want to turn this off is if you want to use the aliases “q”, “l” or “h” for something in your menu. Nevertheless, at least <code class="docutils literal notranslate"><span class="pre">quit</span></code> is highly recommend - if <code class="docutils literal notranslate"><span class="pre">False</span></code>, the menu <em>must</em> itself supply an “exit node” (a node without any options), or the user will be stuck in the menu until the server reloads (or eternally if the menu is <code class="docutils literal notranslate"><span class="pre">persistent</span></code>)!</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">cmd_on_exit</span></code> (str): This command string will be executed right <em>after</em> the menu has closed down. From experience, it’s useful to trigger a “look” command to make sure the user is aware of the change of state; but any command can be used. If set to <code class="docutils literal notranslate"><span class="pre">None</span></code>, no command will be triggered after exiting the menu.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">persistent</span></code> (bool) - if <code class="docutils literal notranslate"><span class="pre">True</span></code>, the menu will survive a reload (so the user will not be kicked
|
||||
out by the reload - make sure they can exit on their own!)</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">startnode_input</span></code> (str or (str, dict) tuple): Pass an input text or a input text + kwargs to the
|
||||
|
|
@ -397,9 +353,7 @@ start a menu differently depending on the Command’s arguments in which it was
|
|||
<li><p><code class="docutils literal notranslate"><span class="pre">debug</span></code> (bool): If set, the <code class="docutils literal notranslate"><span class="pre">menudebug</span></code> command will be made available in the menu. Use it to
|
||||
list the current state of the menu and use <code class="docutils literal notranslate"><span class="pre">menudebug</span> <span class="pre"><variable></span></code> to inspect a specific state
|
||||
variable from the list.</p></li>
|
||||
<li><p>All other keyword arguments will be available as initial data for the nodes. They will be
|
||||
available in all nodes as properties on <code class="docutils literal notranslate"><span class="pre">caller.ndb._evmenu</span></code> (see below). These will also
|
||||
survive a <code class="docutils literal notranslate"><span class="pre">@reload</span></code> if the menu is <code class="docutils literal notranslate"><span class="pre">persistent</span></code>.</p></li>
|
||||
<li><p>All other keyword arguments will be available as initial data for the nodes. They will be available in all nodes as properties on <code class="docutils literal notranslate"><span class="pre">caller.ndb._evmenu</span></code> (see below). These will also survive a <code class="docutils literal notranslate"><span class="pre">reload</span></code> if the menu is <code class="docutils literal notranslate"><span class="pre">persistent</span></code>.</p></li>
|
||||
</ul>
|
||||
<p>You don’t need to store the EvMenu instance anywhere - the very act of initializing it will store it
|
||||
as <code class="docutils literal notranslate"><span class="pre">caller.ndb._evmenu</span></code> on the <code class="docutils literal notranslate"><span class="pre">caller</span></code>. This object will be deleted automatically when the menu
|
||||
|
|
@ -601,9 +555,8 @@ goto-callable. This functionality comes from a time before goto could be a calla
|
|||
</div></blockquote>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
<section id="temporary-storage">
|
||||
<h2>Temporary storage<a class="headerlink" href="#temporary-storage" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Temporary storage<a class="headerlink" href="#temporary-storage" title="Permalink to this headline">¶</a></h3>
|
||||
<p>When the menu starts, the EvMenu instance is stored on the caller as <code class="docutils literal notranslate"><span class="pre">caller.ndb._evmenu</span></code>. Through
|
||||
this object you can in principle reach the menu’s internal state if you know what you are doing.
|
||||
This is also a good place to store temporary, more global variables that may be cumbersome to keep
|
||||
|
|
@ -614,7 +567,7 @@ that this will remain after the menu closes though, so you need to handle any ne
|
|||
yourself.</p>
|
||||
</section>
|
||||
<section id="customizing-menu-formatting">
|
||||
<h2>Customizing Menu formatting<a class="headerlink" href="#customizing-menu-formatting" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Customizing Menu formatting<a class="headerlink" href="#customizing-menu-formatting" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> display of nodes, options etc are controlled by a series of formatting methods on the
|
||||
<code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> class. To customize these, simply create a new child class of <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> and override as
|
||||
needed. Here is an example:</p>
|
||||
|
|
@ -678,6 +631,7 @@ needed. Here is an example:</p>
|
|||
</div>
|
||||
<p>See <code class="docutils literal notranslate"><span class="pre">evennia/utils/evmenu.py</span></code> for the details of their default implementations.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="evmenu-templating-language">
|
||||
<h2>EvMenu templating language<a class="headerlink" href="#evmenu-templating-language" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In <a class="reference external" href="http://evmenu.py">evmenu.py</a> are two helper functions <code class="docutils literal notranslate"><span class="pre">parse_menu_template</span></code> and <code class="docutils literal notranslate"><span class="pre">template2menu</span></code>
|
||||
|
|
@ -827,8 +781,171 @@ myfunc(foo) # error!
|
|||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="id1">
|
||||
<h2>Examples:<a class="headerlink" href="#id1" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="asking-for-one-line-input">
|
||||
<h2>Asking for one-line input<a class="headerlink" href="#asking-for-one-line-input" title="Permalink to this headline">¶</a></h2>
|
||||
<p>This describes two ways for asking for simple questions from the user. Using Python’s <code class="docutils literal notranslate"><span class="pre">input</span></code>
|
||||
will <em>not</em> work in Evennia. <code class="docutils literal notranslate"><span class="pre">input</span></code> will <em>block</em> the entire server for <em>everyone</em> until that one
|
||||
player has entered their text, which is not what you want.</p>
|
||||
<section id="the-yield-way">
|
||||
<h3>The <code class="docutils literal notranslate"><span class="pre">yield</span></code> way<a class="headerlink" href="#the-yield-way" title="Permalink to this headline">¶</a></h3>
|
||||
<p>In the <code class="docutils literal notranslate"><span class="pre">func</span></code> method of your Commands (only) you can use Python’s built-in <code class="docutils literal notranslate"><span class="pre">yield</span></code> command to
|
||||
request input in a similar way to <code class="docutils literal notranslate"><span class="pre">input</span></code>. It looks like this:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">result</span> <span class="o">=</span> <span class="k">yield</span><span class="p">(</span><span class="s2">"Please enter your answer:"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This will send “Please enter your answer” to the Command’s <code class="docutils literal notranslate"><span class="pre">self.caller</span></code> and then pause at that
|
||||
point. All other players at the server will be unaffected. Once caller enteres a reply, the code
|
||||
execution will continue and you can do stuff with the <code class="docutils literal notranslate"><span class="pre">result</span></code>. Here is an example:</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">Command</span>
|
||||
<span class="k">class</span> <span class="nc">CmdTestInput</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
|
||||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"test"</span>
|
||||
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="n">result</span> <span class="o">=</span> <span class="k">yield</span><span class="p">(</span><span class="s2">"Please enter something:"</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="sa">f</span><span class="s2">"You entered </span><span class="si">{</span><span class="n">result</span><span class="si">}</span><span class="s2">."</span><span class="p">)</span>
|
||||
<span class="n">result2</span> <span class="o">=</span> <span class="k">yield</span><span class="p">(</span><span class="s2">"Now enter something else:"</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="sa">f</span><span class="s2">"You now entered </span><span class="si">{</span><span class="n">result2</span><span class="si">}</span><span class="s2">."</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Using <code class="docutils literal notranslate"><span class="pre">yield</span></code> is simple and intuitive, but it will only access input from <code class="docutils literal notranslate"><span class="pre">self.caller</span></code> and you
|
||||
cannot abort or time out the pause until the player has responded. Under the hood, it is actually
|
||||
just a wrapper calling <code class="docutils literal notranslate"><span class="pre">get_input</span></code> described in the following section.</p>
|
||||
<blockquote>
|
||||
<div><p>Important Note: In Python you <em>cannot mix <code class="docutils literal notranslate"><span class="pre">yield</span></code> and <code class="docutils literal notranslate"><span class="pre">return</span> <span class="pre"><value></span></code> in the same method</em>. It has
|
||||
to do with <code class="docutils literal notranslate"><span class="pre">yield</span></code> turning the method into a
|
||||
<a class="reference external" href="https://www.learnpython.org/en/Generators">generator</a>. A <code class="docutils literal notranslate"><span class="pre">return</span></code> without an argument works, you
|
||||
can just not do <code class="docutils literal notranslate"><span class="pre">return</span> <span class="pre"><value></span></code>. This is usually not something you need to do in <code class="docutils literal notranslate"><span class="pre">func()</span></code> anyway,
|
||||
but worth keeping in mind.</p>
|
||||
</div></blockquote>
|
||||
</section>
|
||||
<section id="the-get-input-way">
|
||||
<h3>The <code class="docutils literal notranslate"><span class="pre">get_input</span></code> way<a class="headerlink" href="#the-get-input-way" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The evmenu module offers a helper function named <code class="docutils literal notranslate"><span class="pre">get_input</span></code>. This is wrapped by the <code class="docutils literal notranslate"><span class="pre">yield</span></code>
|
||||
statement which is often easier and more intuitive to use. But <code class="docutils literal notranslate"><span class="pre">get_input</span></code> offers more flexibility
|
||||
and power if you need it. While in the same module as <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code>, <code class="docutils literal notranslate"><span class="pre">get_input</span></code> is technically unrelated
|
||||
to it. The <code class="docutils literal notranslate"><span class="pre">get_input</span></code> allows you to ask and receive simple one-line input from the user without
|
||||
launching the full power of a menu to do so. To use, call <code class="docutils literal notranslate"><span class="pre">get_input</span></code> like this:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">get_input</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">prompt</span><span class="p">,</span> <span class="n">callback</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Here <code class="docutils literal notranslate"><span class="pre">caller</span></code> is the entity that should receive the prompt for input given as <code class="docutils literal notranslate"><span class="pre">prompt</span></code>. The
|
||||
<code class="docutils literal notranslate"><span class="pre">callback</span></code> is a callable <code class="docutils literal notranslate"><span class="pre">function(caller,</span> <span class="pre">prompt,</span> <span class="pre">user_input)</span></code> that you define to handle the answer
|
||||
from the user. When run, the caller will see <code class="docutils literal notranslate"><span class="pre">prompt</span></code> appear on their screens and <em>any</em> text they
|
||||
enter will be sent into the callback for whatever processing you want.</p>
|
||||
<p>Below is a fully explained callback and example call:</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">Command</span>
|
||||
<span class="kn">from</span> <span class="nn">evennia.utils.evmenu</span> <span class="kn">import</span> <span class="n">get_input</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">callback</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">prompt</span><span class="p">,</span> <span class="n">user_input</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> This is a callback you define yourself.</span>
|
||||
|
||||
<span class="sd"> Args:</span>
|
||||
<span class="sd"> caller (Account or Object): The one being asked</span>
|
||||
<span class="sd"> for input</span>
|
||||
<span class="sd"> prompt (str): A copy of the current prompt</span>
|
||||
<span class="sd"> user_input (str): The input from the account.</span>
|
||||
|
||||
<span class="sd"> Returns:</span>
|
||||
<span class="sd"> repeat (bool): If not set or False, exit the</span>
|
||||
<span class="sd"> input prompt and clean up. If returning anything</span>
|
||||
<span class="sd"> True, stay in the prompt, which means this callback</span>
|
||||
<span class="sd"> will be called again with the next user input.</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="sa">f</span><span class="s2">"When asked '</span><span class="si">{</span><span class="n">prompt</span><span class="si">}</span><span class="s2">', you answered '</span><span class="si">{</span><span class="n">user_input</span><span class="si">}</span><span class="s2">'."</span><span class="p">)</span>
|
||||
|
||||
<span class="n">get_input</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s2">"Write something! "</span><span class="p">,</span> <span class="n">callback</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This will show as</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>Write something!
|
||||
> Hello
|
||||
When asked 'Write something!', you answered 'Hello'.
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Normally, the <code class="docutils literal notranslate"><span class="pre">get_input</span></code> function quits after any input, but as seen in the example docs, you could
|
||||
return True from the callback to repeat the prompt until you pass whatever check you want.</p>
|
||||
<blockquote>
|
||||
<div><p>Note: You <em>cannot</em> link consecutive questions by putting a new <code class="docutils literal notranslate"><span class="pre">get_input</span></code> call inside the
|
||||
callback If you want that you should use an EvMenu instead (see the <a class="reference internal" href="#example-repeating-the-same-node"><span class="std std-doc">Repeating the same
|
||||
node</span></a> example above). Otherwise you can either peek at the
|
||||
implementation of <code class="docutils literal notranslate"><span class="pre">get_input</span></code> and implement your own mechanism (it’s just using cmdset nesting) or
|
||||
you can look at <a class="reference external" href="https://groups.google.com/forum/#%21category-topic/evennia/evennia-questions/16pi0SfMO5U">this extension suggested on the mailing
|
||||
list</a>.</p>
|
||||
</div></blockquote>
|
||||
<section id="example-yes-no-prompt">
|
||||
<h4>Example: Yes/No prompt<a class="headerlink" href="#example-yes-no-prompt" title="Permalink to this headline">¶</a></h4>
|
||||
<p>Below is an example of a Yes/No prompt using the <code class="docutils literal notranslate"><span class="pre">get_input</span></code> function:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">yesno</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">prompt</span><span class="p">,</span> <span class="n">result</span><span class="p">):</span>
|
||||
<span class="k">if</span> <span class="n">result</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="ow">in</span> <span class="p">(</span><span class="s2">"y"</span><span class="p">,</span> <span class="s2">"yes"</span><span class="p">,</span> <span class="s2">"n"</span><span class="p">,</span> <span class="s2">"no"</span><span class="p">):</span>
|
||||
<span class="c1"># do stuff to handle the yes/no answer</span>
|
||||
<span class="c1"># ...</span>
|
||||
<span class="c1"># if we return None/False the prompt state</span>
|
||||
<span class="c1"># will quit after this</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="c1"># the answer is not on the right yes/no form</span>
|
||||
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"Please answer Yes or No. </span><span class="se">\n</span><span class="si">{prompt}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="o">@</span> <span class="c1"># returning True will make sure the prompt state is not exited</span>
|
||||
<span class="k">return</span> <span class="kc">True</span>
|
||||
|
||||
<span class="c1"># ask the question</span>
|
||||
<span class="n">get_input</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s2">"Is Evennia great (Yes/No)?"</span><span class="p">,</span> <span class="n">yesno</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
<section id="the-list-node-decorator">
|
||||
<h2>The <code class="docutils literal notranslate"><span class="pre">@list_node</span></code> decorator<a class="headerlink" href="#the-list-node-decorator" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">evennia.utils.evmenu.list_node</span></code> is an advanced decorator for use with <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> node functions.
|
||||
It is used to quickly create menus for manipulating large numbers of items.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">text</span> <span class="n">here</span>
|
||||
<span class="n">______________________________________________</span>
|
||||
|
||||
<span class="mf">1.</span> <span class="n">option1</span> <span class="mf">7.</span> <span class="n">option7</span> <span class="mf">13.</span> <span class="n">option13</span>
|
||||
<span class="mf">2.</span> <span class="n">option2</span> <span class="mf">8.</span> <span class="n">option8</span> <span class="mf">14.</span> <span class="n">option14</span>
|
||||
<span class="mf">3.</span> <span class="n">option3</span> <span class="mf">9.</span> <span class="n">option9</span> <span class="p">[</span><span class="n">p</span><span class="p">]</span><span class="n">revius</span> <span class="n">page</span>
|
||||
<span class="mf">4.</span> <span class="n">option4</span> <span class="mf">10.</span> <span class="n">option10</span> <span class="n">page</span> <span class="mi">2</span>
|
||||
<span class="mf">5.</span> <span class="n">option5</span> <span class="mf">11.</span> <span class="n">option11</span> <span class="p">[</span><span class="n">n</span><span class="p">]</span><span class="n">ext</span> <span class="n">page</span>
|
||||
<span class="mf">6.</span> <span class="n">option6</span> <span class="mf">12.</span> <span class="n">option12</span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The menu will automatically create an multi-page option listing that one can flip through. One can
|
||||
inpect each entry and then select them with prev/next. This is how it is used:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.utils.evmenu</span> <span class="kn">import</span> <span class="n">list_node</span>
|
||||
|
||||
|
||||
<span class="o">...</span>
|
||||
|
||||
<span class="n">_options</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="p">[</span><span class="s1">'option1'</span><span class="p">,</span> <span class="s1">'option2'</span><span class="p">,</span> <span class="o">...</span> <span class="s1">'option100'</span><span class="p">]</span>
|
||||
|
||||
<span class="n">_select</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">menuchoice</span><span class="p">,</span> <span class="n">available_choices</span><span class="p">):</span>
|
||||
<span class="c1"># analyze choice</span>
|
||||
<span class="k">return</span> <span class="s2">"next_node"</span>
|
||||
|
||||
<span class="nd">@list_node</span><span class="p">(</span><span class="n">options</span><span class="p">,</span> <span class="n">select</span><span class="o">=</span><span class="n">_select</span><span class="p">,</span> <span class="n">pagesize</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>
|
||||
<span class="k">def</span> <span class="nf">node_mylist</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||||
<span class="o">...</span>
|
||||
|
||||
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">options</span></code> argument to <code class="docutils literal notranslate"><span class="pre">list_node</span></code> is either a list, a generator or a callable returning a list
|
||||
of strings for each option that should be displayed in the node.</p>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">select</span></code> is a callable in the example above but could also be the name of a menu node. If a
|
||||
callable, the <code class="docutils literal notranslate"><span class="pre">menuchoice</span></code> argument holds the selection done and <code class="docutils literal notranslate"><span class="pre">available_choices</span></code> holds all the
|
||||
options available. The callable should return the menu to go to depending on the selection (or
|
||||
<code class="docutils literal notranslate"><span class="pre">None</span></code> to rerun the same node). If the name of a menu node, the selection will be passed as
|
||||
<code class="docutils literal notranslate"><span class="pre">selection</span></code> kwarg to that node.</p>
|
||||
<p>The decorated node itself should return <code class="docutils literal notranslate"><span class="pre">text</span></code> to display in the node. It must return at least an
|
||||
empty dictionary for its options. It returning options, those will supplement the options
|
||||
auto-created by the <code class="docutils literal notranslate"><span class="pre">list_node</span></code> decorator.</p>
|
||||
</section>
|
||||
<section id="example-menus">
|
||||
<h2>Example Menus<a class="headerlink" href="#example-menus" title="Permalink to this headline">¶</a></h2>
|
||||
<ul class="simple">
|
||||
<li><p><strong><a class="reference internal" href="#example-simple-branching-menu"><span class="std std-doc">Simple branching menu</span></a></strong> - choose from options</p></li>
|
||||
<li><p><strong><a class="reference internal" href="#example-dynamic-goto"><span class="std std-doc">Dynamic goto</span></a></strong> - jumping to different nodes based on response</p></li>
|
||||
|
|
@ -844,8 +961,7 @@ helper function accessed as <code class="docutils literal notranslate"><span cla
|
|||
</ul>
|
||||
<section id="example-simple-branching-menu">
|
||||
<h3>Example: Simple branching menu<a class="headerlink" href="#example-simple-branching-menu" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Below is an example of a simple branching menu node leading to different other nodes depending on
|
||||
choice:</p>
|
||||
<p>Below is an example of a simple branching menu node leading to different other nodes depending on choice:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/world/mychargen.py</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">define_character</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
||||
|
|
@ -1064,9 +1180,7 @@ when the user exits the menu.</p>
|
|||
</section>
|
||||
<section id="example-repeating-the-same-node">
|
||||
<h3>Example: Repeating the same node<a class="headerlink" href="#example-repeating-the-same-node" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Sometimes you want to make a chain of menu nodes one after another, but you don’t want the user to
|
||||
be able to continue to the next node until you have verified that what they input in the previous
|
||||
node is ok. A common example is a login menu:</p>
|
||||
<p>Sometimes you want to make a chain of menu nodes one after another, but you don’t want the user to be able to continue to the next node until you have verified that what they input in the previous node is ok. A common example is a login menu:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
|
||||
<span class="k">def</span> <span class="nf">_check_username</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||||
<span class="c1"># we assume lookup_username() exists</span>
|
||||
|
|
@ -1177,178 +1291,6 @@ probably more work than it’s worth: You can create dynamic menus by instead ma
|
|||
function more clever. See the <a class="reference internal" href="../Howtos/Tutorial-NPC-Merchants.html"><span class="doc std std-doc">NPC shop tutorial</span></a> for an example of this.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="ask-for-simple-input">
|
||||
<h2>Ask for simple input<a class="headerlink" href="#ask-for-simple-input" title="Permalink to this headline">¶</a></h2>
|
||||
<p>This describes two ways for asking for simple questions from the user. Using Python’s <code class="docutils literal notranslate"><span class="pre">input</span></code>
|
||||
will <em>not</em> work in Evennia. <code class="docutils literal notranslate"><span class="pre">input</span></code> will <em>block</em> the entire server for <em>everyone</em> until that one
|
||||
player has entered their text, which is not what you want.</p>
|
||||
<section id="the-yield-way">
|
||||
<h3>The <code class="docutils literal notranslate"><span class="pre">yield</span></code> way<a class="headerlink" href="#the-yield-way" title="Permalink to this headline">¶</a></h3>
|
||||
<p>In the <code class="docutils literal notranslate"><span class="pre">func</span></code> method of your Commands (only) you can use Python’s built-in <code class="docutils literal notranslate"><span class="pre">yield</span></code> command to
|
||||
request input in a similar way to <code class="docutils literal notranslate"><span class="pre">input</span></code>. It looks like this:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">result</span> <span class="o">=</span> <span class="k">yield</span><span class="p">(</span><span class="s2">"Please enter your answer:"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This will send “Please enter your answer” to the Command’s <code class="docutils literal notranslate"><span class="pre">self.caller</span></code> and then pause at that
|
||||
point. All other players at the server will be unaffected. Once caller enteres a reply, the code
|
||||
execution will continue and you can do stuff with the <code class="docutils literal notranslate"><span class="pre">result</span></code>. Here is an example:</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">Command</span>
|
||||
<span class="k">class</span> <span class="nc">CmdTestInput</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
|
||||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"test"</span>
|
||||
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="n">result</span> <span class="o">=</span> <span class="k">yield</span><span class="p">(</span><span class="s2">"Please enter something:"</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="sa">f</span><span class="s2">"You entered </span><span class="si">{</span><span class="n">result</span><span class="si">}</span><span class="s2">."</span><span class="p">)</span>
|
||||
<span class="n">result2</span> <span class="o">=</span> <span class="k">yield</span><span class="p">(</span><span class="s2">"Now enter something else:"</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="sa">f</span><span class="s2">"You now entered </span><span class="si">{</span><span class="n">result2</span><span class="si">}</span><span class="s2">."</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Using <code class="docutils literal notranslate"><span class="pre">yield</span></code> is simple and intuitive, but it will only access input from <code class="docutils literal notranslate"><span class="pre">self.caller</span></code> and you
|
||||
cannot abort or time out the pause until the player has responded. Under the hood, it is actually
|
||||
just a wrapper calling <code class="docutils literal notranslate"><span class="pre">get_input</span></code> described in the following section.</p>
|
||||
<blockquote>
|
||||
<div><p>Important Note: In Python you <em>cannot mix <code class="docutils literal notranslate"><span class="pre">yield</span></code> and <code class="docutils literal notranslate"><span class="pre">return</span> <span class="pre"><value></span></code> in the same method</em>. It has
|
||||
to do with <code class="docutils literal notranslate"><span class="pre">yield</span></code> turning the method into a
|
||||
<a class="reference external" href="https://www.learnpython.org/en/Generators">generator</a>. A <code class="docutils literal notranslate"><span class="pre">return</span></code> without an argument works, you
|
||||
can just not do <code class="docutils literal notranslate"><span class="pre">return</span> <span class="pre"><value></span></code>. This is usually not something you need to do in <code class="docutils literal notranslate"><span class="pre">func()</span></code> anyway,
|
||||
but worth keeping in mind.</p>
|
||||
</div></blockquote>
|
||||
</section>
|
||||
<section id="the-get-input-way">
|
||||
<h3>The <code class="docutils literal notranslate"><span class="pre">get_input</span></code> way<a class="headerlink" href="#the-get-input-way" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The evmenu module offers a helper function named <code class="docutils literal notranslate"><span class="pre">get_input</span></code>. This is wrapped by the <code class="docutils literal notranslate"><span class="pre">yield</span></code>
|
||||
statement which is often easier and more intuitive to use. But <code class="docutils literal notranslate"><span class="pre">get_input</span></code> offers more flexibility
|
||||
and power if you need it. While in the same module as <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code>, <code class="docutils literal notranslate"><span class="pre">get_input</span></code> is technically unrelated
|
||||
to it. The <code class="docutils literal notranslate"><span class="pre">get_input</span></code> allows you to ask and receive simple one-line input from the user without
|
||||
launching the full power of a menu to do so. To use, call <code class="docutils literal notranslate"><span class="pre">get_input</span></code> like this:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">get_input</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">prompt</span><span class="p">,</span> <span class="n">callback</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Here <code class="docutils literal notranslate"><span class="pre">caller</span></code> is the entity that should receive the prompt for input given as <code class="docutils literal notranslate"><span class="pre">prompt</span></code>. The
|
||||
<code class="docutils literal notranslate"><span class="pre">callback</span></code> is a callable <code class="docutils literal notranslate"><span class="pre">function(caller,</span> <span class="pre">prompt,</span> <span class="pre">user_input)</span></code> that you define to handle the answer
|
||||
from the user. When run, the caller will see <code class="docutils literal notranslate"><span class="pre">prompt</span></code> appear on their screens and <em>any</em> text they
|
||||
enter will be sent into the callback for whatever processing you want.</p>
|
||||
<p>Below is a fully explained callback and example call:</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">Command</span>
|
||||
<span class="kn">from</span> <span class="nn">evennia.utils.evmenu</span> <span class="kn">import</span> <span class="n">get_input</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">callback</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">prompt</span><span class="p">,</span> <span class="n">user_input</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> This is a callback you define yourself.</span>
|
||||
|
||||
<span class="sd"> Args:</span>
|
||||
<span class="sd"> caller (Account or Object): The one being asked</span>
|
||||
<span class="sd"> for input</span>
|
||||
<span class="sd"> prompt (str): A copy of the current prompt</span>
|
||||
<span class="sd"> user_input (str): The input from the account.</span>
|
||||
|
||||
<span class="sd"> Returns:</span>
|
||||
<span class="sd"> repeat (bool): If not set or False, exit the</span>
|
||||
<span class="sd"> input prompt and clean up. If returning anything</span>
|
||||
<span class="sd"> True, stay in the prompt, which means this callback</span>
|
||||
<span class="sd"> will be called again with the next user input.</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="sa">f</span><span class="s2">"When asked '</span><span class="si">{</span><span class="n">prompt</span><span class="si">}</span><span class="s2">', you answered '</span><span class="si">{</span><span class="n">user_input</span><span class="si">}</span><span class="s2">'."</span><span class="p">)</span>
|
||||
|
||||
<span class="n">get_input</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s2">"Write something! "</span><span class="p">,</span> <span class="n">callback</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This will show as</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>Write something!
|
||||
> Hello
|
||||
When asked 'Write something!', you answered 'Hello'.
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Normally, the <code class="docutils literal notranslate"><span class="pre">get_input</span></code> function quits after any input, but as seen in the example docs, you could
|
||||
return True from the callback to repeat the prompt until you pass whatever check you want.</p>
|
||||
<blockquote>
|
||||
<div><p>Note: You <em>cannot</em> link consecutive questions by putting a new <code class="docutils literal notranslate"><span class="pre">get_input</span></code> call inside the
|
||||
callback If you want that you should use an EvMenu instead (see the <a class="reference internal" href="#example-repeating-the-same-node"><span class="std std-doc">Repeating the same
|
||||
node</span></a> example above). Otherwise you can either peek at the
|
||||
implementation of <code class="docutils literal notranslate"><span class="pre">get_input</span></code> and implement your own mechanism (it’s just using cmdset nesting) or
|
||||
you can look at <a class="reference external" href="https://groups.google.com/forum/#%21category-topic/evennia/evennia-questions/16pi0SfMO5U">this extension suggested on the mailing
|
||||
list</a>.</p>
|
||||
</div></blockquote>
|
||||
<section id="example-yes-no-prompt">
|
||||
<h4>Example: Yes/No prompt<a class="headerlink" href="#example-yes-no-prompt" title="Permalink to this headline">¶</a></h4>
|
||||
<p>Below is an example of a Yes/No prompt using the <code class="docutils literal notranslate"><span class="pre">get_input</span></code> function:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">yesno</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">prompt</span><span class="p">,</span> <span class="n">result</span><span class="p">):</span>
|
||||
<span class="k">if</span> <span class="n">result</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="ow">in</span> <span class="p">(</span><span class="s2">"y"</span><span class="p">,</span> <span class="s2">"yes"</span><span class="p">,</span> <span class="s2">"n"</span><span class="p">,</span> <span class="s2">"no"</span><span class="p">):</span>
|
||||
<span class="c1"># do stuff to handle the yes/no answer</span>
|
||||
<span class="c1"># ...</span>
|
||||
<span class="c1"># if we return None/False the prompt state</span>
|
||||
<span class="c1"># will quit after this</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="c1"># the answer is not on the right yes/no form</span>
|
||||
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"Please answer Yes or No. </span><span class="se">\n</span><span class="si">{prompt}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="o">@</span> <span class="c1"># returning True will make sure the prompt state is not exited</span>
|
||||
<span class="k">return</span> <span class="kc">True</span>
|
||||
|
||||
<span class="c1"># ask the question</span>
|
||||
<span class="n">get_input</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s2">"Is Evennia great (Yes/No)?"</span><span class="p">,</span> <span class="n">yesno</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
<section id="the-list-node-decorator">
|
||||
<h2>The <code class="docutils literal notranslate"><span class="pre">@list_node</span></code> decorator<a class="headerlink" href="#the-list-node-decorator" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">evennia.utils.evmenu.list_node</span></code> is an advanced decorator for use with <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> node functions.
|
||||
It is used to quickly create menus for manipulating large numbers of items.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">text</span> <span class="n">here</span>
|
||||
<span class="n">______________________________________________</span>
|
||||
|
||||
<span class="mf">1.</span> <span class="n">option1</span> <span class="mf">7.</span> <span class="n">option7</span> <span class="mf">13.</span> <span class="n">option13</span>
|
||||
<span class="mf">2.</span> <span class="n">option2</span> <span class="mf">8.</span> <span class="n">option8</span> <span class="mf">14.</span> <span class="n">option14</span>
|
||||
<span class="mf">3.</span> <span class="n">option3</span> <span class="mf">9.</span> <span class="n">option9</span> <span class="p">[</span><span class="n">p</span><span class="p">]</span><span class="n">revius</span> <span class="n">page</span>
|
||||
<span class="mf">4.</span> <span class="n">option4</span> <span class="mf">10.</span> <span class="n">option10</span> <span class="n">page</span> <span class="mi">2</span>
|
||||
<span class="mf">5.</span> <span class="n">option5</span> <span class="mf">11.</span> <span class="n">option11</span> <span class="p">[</span><span class="n">n</span><span class="p">]</span><span class="n">ext</span> <span class="n">page</span>
|
||||
<span class="mf">6.</span> <span class="n">option6</span> <span class="mf">12.</span> <span class="n">option12</span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The menu will automatically create an multi-page option listing that one can flip through. One can
|
||||
inpect each entry and then select them with prev/next. This is how it is used:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.utils.evmenu</span> <span class="kn">import</span> <span class="n">list_node</span>
|
||||
|
||||
|
||||
<span class="o">...</span>
|
||||
|
||||
<span class="n">_options</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="p">[</span><span class="s1">'option1'</span><span class="p">,</span> <span class="s1">'option2'</span><span class="p">,</span> <span class="o">...</span> <span class="s1">'option100'</span><span class="p">]</span>
|
||||
|
||||
<span class="n">_select</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">menuchoice</span><span class="p">,</span> <span class="n">available_choices</span><span class="p">):</span>
|
||||
<span class="c1"># analyze choice</span>
|
||||
<span class="k">return</span> <span class="s2">"next_node"</span>
|
||||
|
||||
<span class="nd">@list_node</span><span class="p">(</span><span class="n">options</span><span class="p">,</span> <span class="n">select</span><span class="o">=</span><span class="n">_select</span><span class="p">,</span> <span class="n">pagesize</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>
|
||||
<span class="k">def</span> <span class="nf">node_mylist</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||||
<span class="o">...</span>
|
||||
|
||||
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">options</span></code> argument to <code class="docutils literal notranslate"><span class="pre">list_node</span></code> is either a list, a generator or a callable returning a list
|
||||
of strings for each option that should be displayed in the node.</p>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">select</span></code> is a callable in the example above but could also be the name of a menu node. If a
|
||||
callable, the <code class="docutils literal notranslate"><span class="pre">menuchoice</span></code> argument holds the selection done and <code class="docutils literal notranslate"><span class="pre">available_choices</span></code> holds all the
|
||||
options available. The callable should return the menu to go to depending on the selection (or
|
||||
<code class="docutils literal notranslate"><span class="pre">None</span></code> to rerun the same node). If the name of a menu node, the selection will be passed as
|
||||
<code class="docutils literal notranslate"><span class="pre">selection</span></code> kwarg to that node.</p>
|
||||
<p>The decorated node itself should return <code class="docutils literal notranslate"><span class="pre">text</span></code> to display in the node. It must return at least an
|
||||
empty dictionary for its options. It returning options, those will supplement the options
|
||||
auto-created by the <code class="docutils literal notranslate"><span class="pre">list_node</span></code> decorator.</p>
|
||||
</section>
|
||||
<section id="assorted-notes">
|
||||
<h2>Assorted notes<a class="headerlink" href="#assorted-notes" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The EvMenu is implemented using <a class="reference internal" href="Commands.html"><span class="doc std std-doc">Commands</span></a>. When you start a new EvMenu, the user of the
|
||||
menu will be assigned a <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">CmdSet</span></a> with the commands they need to navigate the menu.
|
||||
This means that if you were to, from inside the menu, assign a new command set to the caller, <em>you
|
||||
may override the Menu Cmdset and kill the menu</em>. If you want to assign cmdsets to the caller as part
|
||||
of the menu, you should store the cmdset on <code class="docutils literal notranslate"><span class="pre">caller.ndb._evmenu</span></code> and wait to actually assign it
|
||||
until the exit node.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -60,14 +60,6 @@
|
|||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">EvMore</a><ul>
|
||||
<li><a class="reference internal" href="#using-evmore">Using EvMore</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="EvMenu.html"
|
||||
title="previous chapter">EvMenu</a></p>
|
||||
|
|
@ -110,8 +102,6 @@
|
|||
window. The <code class="docutils literal notranslate"><span class="pre">evennia.utils.evmore.EvMore</span></code> class gives the user the in-game ability to only view one
|
||||
page of text at a time. It is usually used via its access function, <code class="docutils literal notranslate"><span class="pre">evmore.msg</span></code>.</p>
|
||||
<p>The name comes from the famous unix pager utility <em>more</em> which performs just this function.</p>
|
||||
<section id="using-evmore">
|
||||
<h2>Using EvMore<a class="headerlink" href="#using-evmore" title="Permalink to this headline">¶</a></h2>
|
||||
<p>To use the pager, just pass the long text through it:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.utils</span> <span class="kn">import</span> <span class="n">evmore</span>
|
||||
|
||||
|
|
@ -136,7 +126,6 @@ commands to jump to previous pages, to the top or bottom of the document as well
|
|||
paging.</p>
|
||||
<p>The pager takes several more keyword arguments for controlling the message output. See the
|
||||
<a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia.utils.evmore">evmore-API</a> for more info.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<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="The Inline Function Parser" href="FuncParser.html" />
|
||||
<link rel="next" title="FuncParser inline text parsing" href="FuncParser.html" />
|
||||
<link rel="prev" title="EvMore" href="EvMore.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="FuncParser.html" title="The Inline Function Parser"
|
||||
<a href="FuncParser.html" title="FuncParser inline text parsing"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="EvMore.html" title="EvMore"
|
||||
|
|
@ -65,7 +65,7 @@
|
|||
title="previous chapter">EvMore</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="FuncParser.html"
|
||||
title="next chapter">The Inline Function Parser</a></p>
|
||||
title="next chapter">FuncParser inline text parsing</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
|
|
@ -117,7 +117,7 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="FuncParser.html" title="The Inline Function Parser"
|
||||
<a href="FuncParser.html" title="FuncParser inline text parsing"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="EvMore.html" title="EvMore"
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<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>The Inline Function Parser — Evennia 1.0-dev documentation</title>
|
||||
<title>FuncParser inline text parsing — 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>
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" accesskey="U">Core Components</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">The Inline Function Parser</a></li>
|
||||
<li class="nav-item nav-item-this"><a href="">FuncParser inline text parsing</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
|
|
@ -62,15 +62,14 @@
|
|||
<script>$('#searchbox').show(0);</script>
|
||||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">The Inline Function Parser</a><ul>
|
||||
<li><a class="reference internal" href="#uses-in-default-evennia">Uses in default Evennia</a></li>
|
||||
<li><a class="reference internal" href="#using-the-funcparser">Using the FuncParser</a></li>
|
||||
<li><a class="reference internal" href="#">FuncParser inline text parsing</a><ul>
|
||||
<li><a class="reference internal" href="#working-with-funcparser">Working with FuncParser</a></li>
|
||||
<li><a class="reference internal" href="#defining-custom-callables">Defining custom callables</a><ul>
|
||||
<li><a class="reference internal" href="#escaping-special-character">Escaping special character</a></li>
|
||||
<li><a class="reference internal" href="#safe-convertion-of-inputs">Safe convertion of inputs</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#default-callables">Default callables</a><ul>
|
||||
<li><a class="reference internal" href="#default-funcparser-callables">Default funcparser callables</a><ul>
|
||||
<li><a class="reference internal" href="#evennia-utils-funcparser-funcparser-callables"><code class="docutils literal notranslate"><span class="pre">evennia.utils.funcparser.FUNCPARSER_CALLABLES</span></code></a></li>
|
||||
<li><a class="reference internal" href="#evennia-utils-funcparser-searching-callables"><code class="docutils literal notranslate"><span class="pre">evennia.utils.funcparser.SEARCHING_CALLABLES</span></code></a></li>
|
||||
<li><a class="reference internal" href="#evennia-utils-funcparser-actor-stance-callables"><code class="docutils literal notranslate"><span class="pre">evennia.utils.funcparser.ACTOR_STANCE_CALLABLES</span></code></a></li>
|
||||
|
|
@ -117,8 +116,8 @@
|
|||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="the-inline-function-parser">
|
||||
<h1>The Inline Function Parser<a class="headerlink" href="#the-inline-function-parser" title="Permalink to this headline">¶</a></h1>
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="funcparser-inline-text-parsing">
|
||||
<h1>FuncParser inline text parsing<a class="headerlink" href="#funcparser-inline-text-parsing" title="Permalink to this headline">¶</a></h1>
|
||||
<p>The <a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.FuncParser" title="evennia.utils.funcparser.FuncParser"><span class="xref myst py py-class">FuncParser</span></a> extracts and executes ‘inline functions’ embedded in a string on the form <code class="docutils literal notranslate"><span class="pre">$funcname(args,</span> <span class="pre">kwargs)</span></code>. Under the hood, this will lead to a call to a Python function you control. The inline function call will be replaced by the return from the function.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.utils.funcparser</span> <span class="kn">import</span> <span class="n">FuncParser</span>
|
||||
|
||||
|
|
@ -147,32 +146,20 @@
|
|||
<span class="s2">"This is an escaped $pow(4) and so is this $pow(3)"</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<section id="uses-in-default-evennia">
|
||||
<h2>Uses in default Evennia<a class="headerlink" href="#uses-in-default-evennia" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="working-with-funcparser">
|
||||
<h2>Working with FuncParser<a class="headerlink" href="#working-with-funcparser" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The FuncParser can be applied to any string. Out of the box it’s applied in a few situations:</p>
|
||||
<ul class="simple">
|
||||
<li><p><em>Outgoing messages</em>. All messages sent from the server is processed through FuncParser and every
|
||||
callable is provided the <a class="reference internal" href="Sessions.html"><span class="doc std std-doc">Session</span></a> of the object receiving the message. This potentially
|
||||
allows a message to be modified on the fly to look different for different recipients.</p></li>
|
||||
<li><p><em>Prototype values</em>. A <a class="reference internal" href="Prototypes.html"><span class="doc std std-doc">Prototype</span></a> dict’s values are run through the parser such that every
|
||||
callable gets a reference to the rest of the prototype. In the Prototype ORM, this would allow builders
|
||||
to safely call functions to set non-string values to prototype values, get random values, reference
|
||||
<li><p><em>Outgoing messages</em>. All messages sent from the server is processed through FuncParser and every callable is provided the <a class="reference internal" href="Sessions.html"><span class="doc std std-doc">Session</span></a> of the object receiving the message. This potentially allows a message to be modified on the fly to look different for different recipients.</p></li>
|
||||
<li><p><em>Prototype values</em>. A <a class="reference internal" href="Prototypes.html"><span class="doc std std-doc">Prototype</span></a> dict’s values are run through the parser such that every callable gets a reference to the rest of the prototype. In the Prototype ORM, this would allow builders to safely call functions to set non-string values to prototype values, get random values, reference
|
||||
other fields of the prototype, and more.</p></li>
|
||||
<li><p><em>Actor-stance in messages to others</em>. In the
|
||||
<a class="reference internal" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultObject.msg_contents" title="evennia.objects.objects.DefaultObject.msg_contents"><span class="xref myst py py-meth">Object.msg_contents</span></a> method,
|
||||
the outgoing string is parsed for special <code class="docutils literal notranslate"><span class="pre">$You()</span></code> and <code class="docutils literal notranslate"><span class="pre">$conj()</span></code> callables to decide if a given recipient
|
||||
<li><p><em>Actor-stance in messages to others</em>. In the <a class="reference internal" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultObject.msg_contents" title="evennia.objects.objects.DefaultObject.msg_contents"><span class="xref myst py py-meth">Object.msg_contents</span></a> method, the outgoing string is parsed for special <code class="docutils literal notranslate"><span class="pre">$You()</span></code> and <code class="docutils literal notranslate"><span class="pre">$conj()</span></code> callables to decide if a given recipient
|
||||
should see “You” or the character’s name.</p></li>
|
||||
</ul>
|
||||
<div class="admonition important">
|
||||
<p class="admonition-title">Important</p>
|
||||
<p>The inline-function parser is not intended as a ‘softcode’ programming language. It does not
|
||||
have things like loops and conditionals, for example. While you could in principle extend it to
|
||||
do very advanced things and allow builders a lot of power, all-out coding is something
|
||||
Evennia expects you to do in a proper text editor, outside of the game, not from inside it.</p>
|
||||
<p>The inline-function parser is not intended as a ‘softcode’ programming language. It does not have things like loops and conditionals, for example. While you could in principle extend it to do very advanced things and allow builders a lot of power, all-out coding is something Evennia expects you to do in a proper text editor, outside of the game, not from inside it.</p>
|
||||
</div>
|
||||
</section>
|
||||
<section id="using-the-funcparser">
|
||||
<h2>Using the FuncParser<a class="headerlink" href="#using-the-funcparser" title="Permalink to this headline">¶</a></h2>
|
||||
<p>You can apply inline function parsing to any string. The
|
||||
<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.FuncParser" title="evennia.utils.funcparser.FuncParser"><span class="xref myst py py-class">FuncParser</span></a> is imported as <code class="docutils literal notranslate"><span class="pre">evennia.utils.funcparser</span></code>.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.utils</span> <span class="kn">import</span> <span class="n">funcparser</span>
|
||||
|
|
@ -237,8 +224,7 @@ is the <code class="docutils literal notranslate"><span class="pre">raise_errors
|
|||
<span class="n">funcparser</span><span class="o">=<</span><span class="n">FuncParser</span><span class="o">></span><span class="p">,</span> <span class="n">raise_errors</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">mydefault=2</span></code> kwarg could be overwritten if we made the call as <code class="docutils literal notranslate"><span class="pre">$test(mydefault=...)</span></code>
|
||||
but <code class="docutils literal notranslate"><span class="pre">myreserved=[1,</span> <span class="pre">2,</span> <span class="pre">3]</span></code> will <em>always</em> be sent as-is and will override a call <code class="docutils literal notranslate"><span class="pre">$test(myreserved=...)</span></code>.
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">mydefault=2</span></code> kwarg could be overwritten if we made the call as <code class="docutils literal notranslate"><span class="pre">$test(mydefault=...)</span></code> but <code class="docutils literal notranslate"><span class="pre">myreserved=[1,</span> <span class="pre">2,</span> <span class="pre">3]</span></code> will <em>always</em> be sent as-is and will override a call <code class="docutils literal notranslate"><span class="pre">$test(myreserved=...)</span></code>.
|
||||
The <code class="docutils literal notranslate"><span class="pre">funcparser</span></code>/<code class="docutils literal notranslate"><span class="pre">raise_errors</span></code> kwargs are also always included as reserved kwargs.</p>
|
||||
</section>
|
||||
<section id="defining-custom-callables">
|
||||
|
|
@ -250,20 +236,15 @@ The <code class="docutils literal notranslate"><span class="pre">funcparser</spa
|
|||
</pre></div>
|
||||
</div>
|
||||
<blockquote>
|
||||
<div><p>The <code class="docutils literal notranslate"><span class="pre">*args</span></code> and <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> must always be included. If you are unsure how <code class="docutils literal notranslate"><span class="pre">*args</span></code> and <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> work in Python,
|
||||
<a class="reference external" href="https://www.digitalocean.com/community/tutorials/how-to-use-args-and-kwargs-in-python-3">read about them here</a>.</p>
|
||||
<div><p>The <code class="docutils literal notranslate"><span class="pre">*args</span></code> and <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> must always be included. If you are unsure how <code class="docutils literal notranslate"><span class="pre">*args</span></code> and <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> work in Python, <a class="reference external" href="https://www.digitalocean.com/community/tutorials/how-to-use-args-and-kwargs-in-python-3">read about them here</a>.</p>
|
||||
</div></blockquote>
|
||||
<p>The input from the innermost <code class="docutils literal notranslate"><span class="pre">$funcname(...)</span></code> call in your callable will always be a <code class="docutils literal notranslate"><span class="pre">str</span></code>. Here’s
|
||||
an example of an <code class="docutils literal notranslate"><span class="pre">$toint</span></code> function; it converts numbers to integers.</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>"There's a $toint(22.0)% chance of survival."
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>What will enter the <code class="docutils literal notranslate"><span class="pre">$toint</span></code> callable (as <code class="docutils literal notranslate"><span class="pre">args[0]</span></code>) is the <em>string</em> <code class="docutils literal notranslate"><span class="pre">"22.0"</span></code>. The function is responsible
|
||||
for converting this to a number so that we can convert it to an integer. We must also properly handle invalid
|
||||
inputs (like non-numbers).</p>
|
||||
<p>If you want to mark an error, raise <code class="docutils literal notranslate"><span class="pre">evennia.utils.funcparser.ParsingError</span></code>. This stops the entire parsing
|
||||
of the string and may or may not raise the exception depending on what you set <code class="docutils literal notranslate"><span class="pre">raise_errors</span></code> to when you
|
||||
created the parser.</p>
|
||||
<p>What will enter the <code class="docutils literal notranslate"><span class="pre">$toint</span></code> callable (as <code class="docutils literal notranslate"><span class="pre">args[0]</span></code>) is the <em>string</em> <code class="docutils literal notranslate"><span class="pre">"22.0"</span></code>. The function is responsible for converting this to a number so that we can convert it to an integer. We must also properly handle invalid inputs (like non-numbers).</p>
|
||||
<p>If you want to mark an error, raise <code class="docutils literal notranslate"><span class="pre">evennia.utils.funcparser.ParsingError</span></code>. This stops the entire parsing of the string and may or may not raise the exception depending on what you set <code class="docutils literal notranslate"><span class="pre">raise_errors</span></code> to when you created the parser.</p>
|
||||
<p>However, if you <em>nest</em> functions, the return of the innermost function may be something other than
|
||||
a string. Let’s introduce the <code class="docutils literal notranslate"><span class="pre">$eval</span></code> function, which evaluates simple expressions using
|
||||
Python’s <code class="docutils literal notranslate"><span class="pre">literal_eval</span></code> and/or <code class="docutils literal notranslate"><span class="pre">simple_eval</span></code>. It returns whatever data type it
|
||||
|
|
@ -275,18 +256,14 @@ evaluates to.</p>
|
|||
It evaluates this and returns the <code class="docutils literal notranslate"><span class="pre">float</span></code> <code class="docutils literal notranslate"><span class="pre">22.0</span></code>. This time the outermost <code class="docutils literal notranslate"><span class="pre">$toint</span></code> will be called with
|
||||
this <code class="docutils literal notranslate"><span class="pre">float</span></code> instead of with a string.</p>
|
||||
<blockquote>
|
||||
<div><p>It’s important to safely validate your inputs since users may end up nesting your callables in any order.
|
||||
See the next section for useful tools to help with this.</p>
|
||||
<div><p>It’s important to safely validate your inputs since users may end up nesting your callables in any order. See the next section for useful tools to help with this.</p>
|
||||
</div></blockquote>
|
||||
<p>In these examples, the result will be embedded in the larger string, so the result of the entire parsing
|
||||
will be a string:</p>
|
||||
<p>In these examples, the result will be embedded in the larger string, so the result of the entire parsing will be a string:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">parser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">above_string</span><span class="p">)</span>
|
||||
<span class="s2">"There's a 22</span><span class="si">% c</span><span class="s2">hance of survival."</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>However, if you use the <code class="docutils literal notranslate"><span class="pre">parse_to_any</span></code> (or <code class="docutils literal notranslate"><span class="pre">parse(...,</span> <span class="pre">return_str=False)</span></code>) and
|
||||
<em>don’t add any extra string around the outermost function call</em>,
|
||||
you’ll get the return type of the outermost callable back:</p>
|
||||
<p>However, if you use the <code class="docutils literal notranslate"><span class="pre">parse_to_any</span></code> (or <code class="docutils literal notranslate"><span class="pre">parse(...,</span> <span class="pre">return_str=False)</span></code>) and <em>don’t add any extra string around the outermost function call</em>, you’ll get the return type of the outermost callable back:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">parser</span><span class="o">.</span><span class="n">parse_to_any</span><span class="p">(</span><span class="s2">"$toint($eval(10 * 2.2)"</span><span class="p">)</span>
|
||||
<span class="mi">22</span>
|
||||
<span class="n">parser</span><span class="o">.</span><span class="n">parse_to_any</span><span class="p">(</span><span class="s2">"the number $toint($eval(10 * 2.2)."</span><span class="p">)</span>
|
||||
|
|
@ -342,9 +319,7 @@ can support. This is because FunctionParser strings can be used by
|
|||
non-developer players/builders and some things (such as complex
|
||||
classes/callables etc) are just not safe/possible to convert from string
|
||||
representation.</p>
|
||||
<p>In <code class="docutils literal notranslate"><span class="pre">evennia.utils.utils</span></code> is a helper called
|
||||
<a class="reference internal" href="../api/evennia.utils.utils.html#evennia.utils.utils.safe_convert_to_types" title="evennia.utils.utils.safe_convert_to_types"><span class="xref myst py py-func">safe_convert_to_types</span></a>. This function
|
||||
automates the conversion of simple data types in a safe way:</p>
|
||||
<p>In <code class="docutils literal notranslate"><span class="pre">evennia.utils.utils</span></code> is a helper called <a class="reference internal" href="../api/evennia.utils.utils.html#evennia.utils.utils.safe_convert_to_types" title="evennia.utils.utils.safe_convert_to_types"><span class="xref myst py py-func">safe_convert_to_types</span></a>. This function automates the conversion of simple data types in a safe way:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.utils.utils</span> <span class="kn">import</span> <span class="n">safe_convert_to_types</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_process_callable</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||||
|
|
@ -360,43 +335,24 @@ automates the conversion of simple data types in a safe way:</p>
|
|||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>In other words, in the callable <code class="docutils literal notranslate"><span class="pre">$process(expression,</span> <span class="pre">local,</span> <span class="pre">extra1=..,</span> <span class="pre">extra2=...)</span></code>, the first argument will be handled by the ‘py’ converter
|
||||
(described below), the second will passed through regular Python <code class="docutils literal notranslate"><span class="pre">str</span></code>,
|
||||
kwargs will be handled by <code class="docutils literal notranslate"><span class="pre">int</span></code> and <code class="docutils literal notranslate"><span class="pre">str</span></code> respectively. You can supply
|
||||
your own converter function as long as it takes one argument and returns
|
||||
the converted result.</p>
|
||||
<p>In other words,</p>
|
||||
<p>In other words, in the callable <code class="docutils literal notranslate"><span class="pre">$process(expression,</span> <span class="pre">local,</span> <span class="pre">extra1=..,</span> <span class="pre">extra2=...)</span></code>, the first argument will be handled by the ‘py’ converter (described below), the second will passed through regular Python <code class="docutils literal notranslate"><span class="pre">str</span></code>, kwargs will be handled by <code class="docutils literal notranslate"><span class="pre">int</span></code> and <code class="docutils literal notranslate"><span class="pre">str</span></code> respectively. You can supply your own converter function as long as it takes one argument and returns the converted result.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span> <span class="o">=</span> <span class="n">safe_convert_to_type</span><span class="p">(</span>
|
||||
<span class="p">(</span><span class="n">tuple_of_arg_converters</span><span class="p">,</span> <span class="n">dict_of_kwarg_converters</span><span class="p">),</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The special converter <code class="docutils literal notranslate"><span class="pre">"py"</span></code> will try to convert a string argument to a Python structure with the help of the
|
||||
following tools (which you may also find useful to experiment with on your own):</p>
|
||||
<p>The special converter <code class="docutils literal notranslate"><span class="pre">"py"</span></code> will try to convert a string argument to a Python structure with the help of the following tools (which you may also find useful to experiment with on your own):</p>
|
||||
<ul class="simple">
|
||||
<li><p><a class="reference external" href="https://docs.python.org/3.8/library/ast.html#ast.literal_eval">ast.literal_eval</a> is an in-built Python
|
||||
function. It
|
||||
<em>only</em> supports strings, bytes, numbers, tuples, lists, dicts, sets, booleans and <code class="docutils literal notranslate"><span class="pre">None</span></code>. That’s
|
||||
it - no arithmetic or modifications of data is allowed. This is good for converting individual values and
|
||||
lists/dicts from the input line to real Python objects.</p></li>
|
||||
<li><p><a class="reference external" href="https://pypi.org/project/simpleeval/">simpleeval</a> is a third-party tool included with Evennia. This
|
||||
allows for evaluation of simple (and thus safe) expressions. One can operate on numbers and strings
|
||||
with <code class="docutils literal notranslate"><span class="pre">+-/*</span></code> as well as do simple comparisons like <code class="docutils literal notranslate"><span class="pre">4</span> <span class="pre">></span> <span class="pre">3</span></code> and more. It does <em>not</em> accept more complex
|
||||
containers like lists/dicts etc, so this and <code class="docutils literal notranslate"><span class="pre">literal_eval</span></code> are complementary to each other.</p></li>
|
||||
<li><p><a class="reference external" href="https://docs.python.org/3.8/library/ast.html#ast.literal_eval">ast.literal_eval</a> is an in-built Python function. It <em>only</em> supports strings, bytes, numbers, tuples, lists, dicts, sets, booleans and <code class="docutils literal notranslate"><span class="pre">None</span></code>. That’s it - no arithmetic or modifications of data is allowed. This is good for converting individual values and lists/dicts from the input line to real Python objects.</p></li>
|
||||
<li><p><a class="reference external" href="https://pypi.org/project/simpleeval/">simpleeval</a> is a third-party tool included with Evennia. This allows for evaluation of simple (and thus safe) expressions. One can operate on numbers and strings with <code class="docutils literal notranslate"><span class="pre">+-/*</span></code> as well as do simple comparisons like <code class="docutils literal notranslate"><span class="pre">4</span> <span class="pre">></span> <span class="pre">3</span></code> and more. It does <em>not</em> accept more complex containers like lists/dicts etc, so this and <code class="docutils literal notranslate"><span class="pre">literal_eval</span></code> are complementary to each other.</p></li>
|
||||
</ul>
|
||||
<div class="admonition warning">
|
||||
<p class="admonition-title">Warning</p>
|
||||
<p>It may be tempting to run use Python’s in-built <code class="docutils literal notranslate"><span class="pre">eval()</span></code> or <code class="docutils literal notranslate"><span class="pre">exec()</span></code> functions as converters since
|
||||
these are able to convert any valid Python source code to Python. NEVER DO THIS unless you really, really
|
||||
know that ONLY developers will ever modify the string going into the callable. The parser is intended
|
||||
for untrusted users (if you were trusted you’d have access to Python already). Letting untrusted users
|
||||
pass strings to <code class="docutils literal notranslate"><span class="pre">eval</span></code>/<code class="docutils literal notranslate"><span class="pre">exec</span></code> is a MAJOR security risk. It allows the caller to run arbitrary
|
||||
Python code on your server. This is the path to maliciously deleted hard drives. Just don’t do it and
|
||||
sleep better at night.</p>
|
||||
<p>It may be tempting to run use Python’s in-built <code class="docutils literal notranslate"><span class="pre">eval()</span></code> or <code class="docutils literal notranslate"><span class="pre">exec()</span></code> functions as converters since these are able to convert any valid Python source code to Python. NEVER DO THIS unless you really, really know that ONLY developers will ever modify the string going into the callable. The parser is intended for untrusted users (if you were trusted you’d have access to Python already). Letting untrusted users pass strings to <code class="docutils literal notranslate"><span class="pre">eval</span></code>/<code class="docutils literal notranslate"><span class="pre">exec</span></code> is a MAJOR security risk. It allows the caller to run arbitrary Python code on your server. This is the path to maliciously deleted hard drives. Just don’t do it and sleep better at night.</p>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="default-callables">
|
||||
<h2>Default callables<a class="headerlink" href="#default-callables" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="default-funcparser-callables">
|
||||
<h2>Default funcparser callables<a class="headerlink" href="#default-funcparser-callables" title="Permalink to this headline">¶</a></h2>
|
||||
<p>These are some example callables you can import and add your parser. They are divided into
|
||||
global-level dicts in <code class="docutils literal notranslate"><span class="pre">evennia.utils.funcparser</span></code>. Just import the dict(s) and merge/add one or
|
||||
more to them when you create your <code class="docutils literal notranslate"><span class="pre">FuncParser</span></code> instance to have those callables be available.</p>
|
||||
|
|
@ -404,47 +360,28 @@ more to them when you create your <code class="docutils literal notranslate"><sp
|
|||
<h3><code class="docutils literal notranslate"><span class="pre">evennia.utils.funcparser.FUNCPARSER_CALLABLES</span></code><a class="headerlink" href="#evennia-utils-funcparser-funcparser-callables" title="Permalink to this headline">¶</a></h3>
|
||||
<p>These are the ‘base’ callables.</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$eval(expression)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_eval" title="evennia.utils.funcparser.funcparser_callable_eval"><span class="xref myst py py-func">code</span></a>) -
|
||||
this uses <code class="docutils literal notranslate"><span class="pre">literal_eval</span></code> and <code class="docutils literal notranslate"><span class="pre">simple_eval</span></code> (see previous section) attemt to convert a string expression
|
||||
to a python object. This handles e.g. lists of literals <code class="docutils literal notranslate"><span class="pre">[1,</span> <span class="pre">2,</span> <span class="pre">3]</span></code> and simple expressions like <code class="docutils literal notranslate"><span class="pre">"1</span> <span class="pre">+</span> <span class="pre">2"</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$toint(number)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_toint" title="evennia.utils.funcparser.funcparser_callable_toint"><span class="xref myst py py-func">code</span></a>) -
|
||||
always converts an output to an integer, if possible.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$eval(expression)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_eval" title="evennia.utils.funcparser.funcparser_callable_eval"><span class="xref myst py py-func">code</span></a>) - this uses <code class="docutils literal notranslate"><span class="pre">literal_eval</span></code> and <code class="docutils literal notranslate"><span class="pre">simple_eval</span></code> (see previous section) attemt to convert a string expression to a python object. This handles e.g. lists of literals <code class="docutils literal notranslate"><span class="pre">[1,</span> <span class="pre">2,</span> <span class="pre">3]</span></code> and simple expressions like <code class="docutils literal notranslate"><span class="pre">"1</span> <span class="pre">+</span> <span class="pre">2"</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$toint(number)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_toint" title="evennia.utils.funcparser.funcparser_callable_toint"><span class="xref myst py py-func">code</span></a>) - always converts an output to an integer, if possible.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$add/sub/mult/div(obj1,</span> <span class="pre">obj2)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_add" title="evennia.utils.funcparser.funcparser_callable_add"><span class="xref myst py py-func">code</span></a>) -
|
||||
this adds/subtracts/multiplies and divides to elements together. While simple addition could be done with
|
||||
<code class="docutils literal notranslate"><span class="pre">$eval</span></code>, this could for example be used also to add two lists together, which is not possible with <code class="docutils literal notranslate"><span class="pre">eval</span></code>;
|
||||
for example <code class="docutils literal notranslate"><span class="pre">$add($eval([1,2,3]),</span> <span class="pre">$eval([4,5,6]))</span> <span class="pre">-></span> <span class="pre">[1,</span> <span class="pre">2,</span> <span class="pre">3,</span> <span class="pre">4,</span> <span class="pre">5,</span> <span class="pre">6]</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$round(float,</span> <span class="pre">significant)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_round" title="evennia.utils.funcparser.funcparser_callable_round"><span class="xref myst py py-func">code</span></a>) -
|
||||
rounds an input float into the number of provided significant digits. For example <code class="docutils literal notranslate"><span class="pre">$round(3.54343,</span> <span class="pre">3)</span> <span class="pre">-></span> <span class="pre">3.543</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$random([start,</span> <span class="pre">[end]])</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_random" title="evennia.utils.funcparser.funcparser_callable_random"><span class="xref myst py py-func">code</span></a>) -
|
||||
this works like the Python <code class="docutils literal notranslate"><span class="pre">random()</span></code> function, but will randomize to an integer value if both start/end are
|
||||
this adds/subtracts/multiplies and divides to elements together. While simple addition could be done with <code class="docutils literal notranslate"><span class="pre">$eval</span></code>, this could for example be used also to add two lists together, which is not possible with <code class="docutils literal notranslate"><span class="pre">eval</span></code>; for example <code class="docutils literal notranslate"><span class="pre">$add($eval([1,2,3]),</span> <span class="pre">$eval([4,5,6]))</span> <span class="pre">-></span> <span class="pre">[1,</span> <span class="pre">2,</span> <span class="pre">3,</span> <span class="pre">4,</span> <span class="pre">5,</span> <span class="pre">6]</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$round(float,</span> <span class="pre">significant)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_round" title="evennia.utils.funcparser.funcparser_callable_round"><span class="xref myst py py-func">code</span></a>) - rounds an input float into the number of provided significant digits. For example <code class="docutils literal notranslate"><span class="pre">$round(3.54343,</span> <span class="pre">3)</span> <span class="pre">-></span> <span class="pre">3.543</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$random([start,</span> <span class="pre">[end]])</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_random" title="evennia.utils.funcparser.funcparser_callable_random"><span class="xref myst py py-func">code</span></a>) - this works like the Python <code class="docutils literal notranslate"><span class="pre">random()</span></code> function, but will randomize to an integer value if both start/end are
|
||||
integers. Without argument, will return a float between 0 and 1.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$randint([start,</span> <span class="pre">[end]])</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_randint" title="evennia.utils.funcparser.funcparser_callable_randint"><span class="xref myst py py-func">code</span></a>) -
|
||||
works like the <code class="docutils literal notranslate"><span class="pre">randint()</span></code> python function and always returns an integer.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$choice(list)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_choice" title="evennia.utils.funcparser.funcparser_callable_choice"><span class="xref myst py py-func">code</span></a>) -
|
||||
the input will automatically be parsed the same way as <code class="docutils literal notranslate"><span class="pre">$eval</span></code> and is expected to be an iterable. A random
|
||||
element of this list will be returned.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$pad(text[,</span> <span class="pre">width,</span> <span class="pre">align,</span> <span class="pre">fillchar])</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_pad" title="evennia.utils.funcparser.funcparser_callable_pad"><span class="xref myst py py-func">code</span></a>) -
|
||||
this will pad content. <code class="docutils literal notranslate"><span class="pre">$pad("Hello",</span> <span class="pre">30,</span> <span class="pre">c,</span> <span class="pre">-)</span></code> will lead to a text centered in a 30-wide block surrounded by <code class="docutils literal notranslate"><span class="pre">-</span></code>
|
||||
characters.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$crop(text,</span> <span class="pre">width=78,</span> <span class="pre">suffix='[...]')</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_crop" title="evennia.utils.funcparser.funcparser_callable_crop"><span class="xref myst py py-func">code</span></a>) -
|
||||
this will crop a text longer than the width, by default ending it with a <code class="docutils literal notranslate"><span class="pre">[...]</span></code>-suffix that also fits within
|
||||
the width. If no width is given, the client width or <code class="docutils literal notranslate"><span class="pre">settings.DEFAULT_CLIENT_WIDTH</span></code> will be used.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$space(num)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_space" title="evennia.utils.funcparser.funcparser_callable_space"><span class="xref myst py py-func">code</span></a>) -
|
||||
this will insert <code class="docutils literal notranslate"><span class="pre">num</span></code> spaces.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$just(string,</span> <span class="pre">width=40,</span> <span class="pre">align=c,</span> <span class="pre">indent=2)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_justify" title="evennia.utils.funcparser.funcparser_callable_justify"><span class="xref myst py py-func">code</span></a>) -
|
||||
justifies the text to a given width, aligning it left/right/center or ‘f’ for full (spread text across width).</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$randint([start,</span> <span class="pre">[end]])</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_randint" title="evennia.utils.funcparser.funcparser_callable_randint"><span class="xref myst py py-func">code</span></a>) - works like the <code class="docutils literal notranslate"><span class="pre">randint()</span></code> python function and always returns an integer.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$choice(list)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_choice" title="evennia.utils.funcparser.funcparser_callable_choice"><span class="xref myst py py-func">code</span></a>) - the input will automatically be parsed the same way as <code class="docutils literal notranslate"><span class="pre">$eval</span></code> and is expected to be an iterable. A random element of this list will be returned.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$pad(text[,</span> <span class="pre">width,</span> <span class="pre">align,</span> <span class="pre">fillchar])</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_pad" title="evennia.utils.funcparser.funcparser_callable_pad"><span class="xref myst py py-func">code</span></a>) - this will pad content. <code class="docutils literal notranslate"><span class="pre">$pad("Hello",</span> <span class="pre">30,</span> <span class="pre">c,</span> <span class="pre">-)</span></code> will lead to a text centered in a 30-wide block surrounded by <code class="docutils literal notranslate"><span class="pre">-</span></code> characters.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$crop(text,</span> <span class="pre">width=78,</span> <span class="pre">suffix='[...]')</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_crop" title="evennia.utils.funcparser.funcparser_callable_crop"><span class="xref myst py py-func">code</span></a>) - this will crop a text longer than the width, by default ending it with a <code class="docutils literal notranslate"><span class="pre">[...]</span></code>-suffix that also fits within the width. If no width is given, the client width or <code class="docutils literal notranslate"><span class="pre">settings.DEFAULT_CLIENT_WIDTH</span></code> will be used.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$space(num)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_space" title="evennia.utils.funcparser.funcparser_callable_space"><span class="xref myst py py-func">code</span></a>) - this will insert <code class="docutils literal notranslate"><span class="pre">num</span></code> spaces.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$just(string,</span> <span class="pre">width=40,</span> <span class="pre">align=c,</span> <span class="pre">indent=2)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_justify" title="evennia.utils.funcparser.funcparser_callable_justify"><span class="xref myst py py-func">code</span></a>) - justifies the text to a given width, aligning it left/right/center or ‘f’ for full (spread text across width).</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$ljust</span></code> - shortcut to justify-left. Takes all other kwarg of <code class="docutils literal notranslate"><span class="pre">$just</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$rjust</span></code> - shortcut to right justify.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$cjust</span></code> - shortcut to center justify.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$clr(startcolor,</span> <span class="pre">text[,</span> <span class="pre">endcolor])</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_clr" title="evennia.utils.funcparser.funcparser_callable_clr"><span class="xref myst py py-func">code</span></a>) -
|
||||
color text. The color is given with one or two characters without the preceeding <code class="docutils literal notranslate"><span class="pre">|</span></code>. If no endcolor is
|
||||
given, the string will go back to neutral, so <code class="docutils literal notranslate"><span class="pre">$clr(r,</span> <span class="pre">Hello)</span></code> is equivalent to <code class="docutils literal notranslate"><span class="pre">|rHello|n</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$clr(startcolor,</span> <span class="pre">text[,</span> <span class="pre">endcolor])</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_clr" title="evennia.utils.funcparser.funcparser_callable_clr"><span class="xref myst py py-func">code</span></a>) - color text. The color is given with one or two characters without the preceeding <code class="docutils literal notranslate"><span class="pre">|</span></code>. If no endcolor is given, the string will go back to neutral, so <code class="docutils literal notranslate"><span class="pre">$clr(r,</span> <span class="pre">Hello)</span></code> is equivalent to <code class="docutils literal notranslate"><span class="pre">|rHello|n</span></code>.</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section id="evennia-utils-funcparser-searching-callables">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">evennia.utils.funcparser.SEARCHING_CALLABLES</span></code><a class="headerlink" href="#evennia-utils-funcparser-searching-callables" title="Permalink to this headline">¶</a></h3>
|
||||
<p>These are callables that requires access-checks in order to search for objects. So they require some
|
||||
extra reserved kwargs to be passed when running the parser:</p>
|
||||
<p>These are callables that requires access-checks in order to search for objects. So they require some extra reserved kwargs to be passed when running the parser:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
|
||||
<span class="n">parser</span><span class="o">.</span><span class="n">parse_to_any</span><span class="p">(</span><span class="n">string</span><span class="p">,</span> <span class="n">caller</span><span class="o">=<</span><span class="nb">object</span> <span class="ow">or</span> <span class="n">account</span><span class="o">></span><span class="p">,</span> <span class="n">access</span><span class="o">=</span><span class="s2">"control"</span><span class="p">,</span> <span class="o">...</span><span class="p">)</span>
|
||||
|
||||
|
|
@ -453,27 +390,20 @@ extra reserved kwargs to be passed when running the parser:</p>
|
|||
<p>The <code class="docutils literal notranslate"><span class="pre">caller</span></code> is required, it’s the the object to do the access-check for. The <code class="docutils literal notranslate"><span class="pre">access</span></code> kwarg is the
|
||||
<a class="reference internal" href="Locks.html"><span class="doc std std-doc">lock type</span></a> to check, default being <code class="docutils literal notranslate"><span class="pre">"control"</span></code>.</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$search(query,type=account|script,return_list=False)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_search" title="evennia.utils.funcparser.funcparser_callable_search"><span class="xref myst py py-func">code</span></a>) -
|
||||
this will look up and try to match an object by key or alias. Use the <code class="docutils literal notranslate"><span class="pre">type</span></code> kwarg to
|
||||
search for <code class="docutils literal notranslate"><span class="pre">account</span></code> or <code class="docutils literal notranslate"><span class="pre">script</span></code> instead. By default this will return nothing if there are more than one
|
||||
match; if <code class="docutils literal notranslate"><span class="pre">return_list</span></code> is <code class="docutils literal notranslate"><span class="pre">True</span></code> a list of 0, 1 or more matches will be returned instead.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$search(query,type=account|script,return_list=False)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_search" title="evennia.utils.funcparser.funcparser_callable_search"><span class="xref myst py py-func">code</span></a>) - this will look up and try to match an object by key or alias. Use the <code class="docutils literal notranslate"><span class="pre">type</span></code> kwarg to search for <code class="docutils literal notranslate"><span class="pre">account</span></code> or <code class="docutils literal notranslate"><span class="pre">script</span></code> instead. By default this will return nothing if there are more than one match; if <code class="docutils literal notranslate"><span class="pre">return_list</span></code> is <code class="docutils literal notranslate"><span class="pre">True</span></code> a list of 0, 1 or more matches will be returned instead.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$obj(query)</span></code>, <code class="docutils literal notranslate"><span class="pre">$dbref(query)</span></code> - legacy aliases for <code class="docutils literal notranslate"><span class="pre">$search</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$objlist(query)</span></code> - legacy alias for <code class="docutils literal notranslate"><span class="pre">$search</span></code>, always returning a list.</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section id="evennia-utils-funcparser-actor-stance-callables">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">evennia.utils.funcparser.ACTOR_STANCE_CALLABLES</span></code><a class="headerlink" href="#evennia-utils-funcparser-actor-stance-callables" title="Permalink to this headline">¶</a></h3>
|
||||
<p>These are used to implement actor-stance emoting. They are used by the
|
||||
<a class="reference internal" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultObject.msg_contents" title="evennia.objects.objects.DefaultObject.msg_contents"><span class="xref myst py py-meth">DefaultObject.msg_contents</span></a> method
|
||||
by default. You can read a lot more about this on the page
|
||||
<p>These are used to implement actor-stance emoting. They are used by the <a class="reference internal" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultObject.msg_contents" title="evennia.objects.objects.DefaultObject.msg_contents"><span class="xref myst py py-meth">DefaultObject.msg_contents</span></a> method by default. You can read a lot more about this on the page
|
||||
<a class="reference internal" href="../Concepts/Change-Message-Per-Receiver.html"><span class="doc std std-doc">Change messages per receiver</span></a>.</p>
|
||||
<p>On the parser side, all these inline functions require extra kwargs be passed into the parser
|
||||
(done by <code class="docutils literal notranslate"><span class="pre">msg_contents</span></code> by default):</p>
|
||||
<p>On the parser side, all these inline functions require extra kwargs be passed into the parser (done by <code class="docutils literal notranslate"><span class="pre">msg_contents</span></code> by default):</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">parser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">string</span><span class="p">,</span> <span class="n">caller</span><span class="o">=<</span><span class="n">obj</span><span class="o">></span><span class="p">,</span> <span class="n">receiver</span><span class="o">=<</span><span class="n">obj</span><span class="o">></span><span class="p">,</span> <span class="n">mapping</span><span class="o">=</span><span class="p">{</span><span class="s1">'key'</span><span class="p">:</span> <span class="o"><</span><span class="n">obj</span><span class="o">></span><span class="p">,</span> <span class="o">...</span><span class="p">})</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Here the <code class="docutils literal notranslate"><span class="pre">caller</span></code> is the one sending the message and <code class="docutils literal notranslate"><span class="pre">receiver</span></code> the one to see it. The <code class="docutils literal notranslate"><span class="pre">mapping</span></code> contains
|
||||
references to other objects accessible via these callables.</p>
|
||||
<p>Here the <code class="docutils literal notranslate"><span class="pre">caller</span></code> is the one sending the message and <code class="docutils literal notranslate"><span class="pre">receiver</span></code> the one to see it. The <code class="docutils literal notranslate"><span class="pre">mapping</span></code> contains references to other objects accessible via these callables.</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">$you([key])</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_you" title="evennia.utils.funcparser.funcparser_callable_you"><span class="xref myst py py-func">code</span></a>) -
|
||||
if no <code class="docutils literal notranslate"><span class="pre">key</span></code> is given, this represents the <code class="docutils literal notranslate"><span class="pre">caller</span></code>, otherwise an object from <code class="docutils literal notranslate"><span class="pre">mapping</span></code>
|
||||
|
|
@ -555,7 +485,7 @@ all the defaults (like <code class="docutils literal notranslate"><span class="p
|
|||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" >Core Components</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">The Inline Function Parser</a></li>
|
||||
<li class="nav-item nav-item-this"><a href="">FuncParser inline text parsing</a></li>
|
||||
</ul>
|
||||
<div class="develop">develop branch</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -63,21 +63,22 @@
|
|||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Help System</a><ul>
|
||||
<li><a class="reference internal" href="#using-the-help-system-from-in-game">Using the help system from in-game</a></li>
|
||||
<li><a class="reference internal" href="#sources-of-help-entries">Sources of help entries</a><ul>
|
||||
<li><a class="reference internal" href="#the-help-entry">The Help Entry</a><ul>
|
||||
<li><a class="reference internal" href="#subtopics">Subtopics</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#command-auto-help-system">Command Auto-help system</a></li>
|
||||
<li><a class="reference internal" href="#database-help-entries">Database-help entries</a></li>
|
||||
<li><a class="reference internal" href="#file-help-entries">File-help entries</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#entry-priority">Entry priority</a></li>
|
||||
<li><a class="reference internal" href="#working-with-three-types-of-help-entries">Working with three types of help entries</a><ul>
|
||||
<li><a class="reference internal" href="#database-stored-help-entries">Database-stored help entries</a></li>
|
||||
<li><a class="reference internal" href="#file-stored-help-entries">File-stored help entries</a></li>
|
||||
<li><a class="reference internal" href="#command-help-entries">Command-help entries</a></li>
|
||||
<li><a class="reference internal" href="#locking-help-entries">Locking help entries</a></li>
|
||||
<li><a class="reference internal" href="#customizing-the-look-of-the-help-system">Customizing the look of the help system</a></li>
|
||||
<li><a class="reference internal" href="#technical-notes">Technical notes</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#subtopics">Subtopics</a></li>
|
||||
<li><a class="reference internal" href="#technical-notes">Technical notes</a><ul>
|
||||
<li><a class="reference internal" href="#help-entry-clashes">Help-entry clashes</a></li>
|
||||
<li><a class="reference internal" href="#the-help-entry-container">The Help Entry container</a></li>
|
||||
<li><a class="reference internal" href="#help-pagination">Help pagination</a></li>
|
||||
<li><a class="reference internal" href="#search-engine">Search engine</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
@ -120,47 +121,52 @@
|
|||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="help-system">
|
||||
<h1>Help System<a class="headerlink" href="#help-system" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Evennia has an extensive help system covering both command-help and regular
|
||||
free-form help documentation. It supports subtopics and if failing to find a
|
||||
match it will provide suggestsions, first from alternative topics and then by
|
||||
finding mentions of the search term in help entries.</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> help theatre
|
||||
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>> <span class="nb">help</span> theatre
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">------------------------------------------------------------------------------</span>
|
||||
<span class="n">Help</span> <span class="k">for</span> <span class="n">The</span> <span class="n">theatre</span> <span class="p">(</span><span class="n">aliases</span><span class="p">:</span> <span class="n">the</span> <span class="n">hub</span><span class="p">,</span> <span class="n">curtains</span><span class="p">)</span>
|
||||
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>------------------------------------------------------------------------------
|
||||
Help <span class="k">for</span> The theatre <span class="o">(</span>aliases: the hub, curtains<span class="o">)</span>
|
||||
|
||||
<span class="n">The</span> <span class="n">theatre</span> <span class="ow">is</span> <span class="n">at</span> <span class="n">the</span> <span class="n">centre</span> <span class="n">of</span> <span class="n">the</span> <span class="n">city</span><span class="p">,</span> <span class="n">both</span> <span class="n">literally</span> <span class="ow">and</span> <span class="n">figuratively</span> <span class="o">...</span>
|
||||
<span class="p">(</span><span class="n">A</span> <span class="n">lot</span> <span class="n">more</span> <span class="n">text</span> <span class="n">about</span> <span class="n">it</span> <span class="n">follows</span> <span class="o">...</span><span class="p">)</span>
|
||||
The theatre is at the centre of the city, both literally and figuratively ...
|
||||
<span class="o">(</span>A lot more text about it follows ...<span class="o">)</span>
|
||||
|
||||
<span class="n">Subtopics</span><span class="p">:</span>
|
||||
<span class="n">theatre</span><span class="o">/</span><span class="n">lore</span>
|
||||
<span class="n">theatre</span><span class="o">/</span><span class="n">layout</span>
|
||||
<span class="n">theatre</span><span class="o">/</span><span class="n">dramatis</span> <span class="n">personae</span>
|
||||
<span class="o">------------------------------------------------------------------------------</span>
|
||||
Subtopics:
|
||||
theatre/lore
|
||||
theatre/layout
|
||||
theatre/dramatis personae
|
||||
------------------------------------------------------------------------------
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> help evennia
|
||||
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>> <span class="nb">help</span> evennia
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">------------------------------------------------------------------------------</span>
|
||||
<span class="n">No</span> <span class="n">help</span> <span class="n">found</span>
|
||||
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>------------------------------------------------------------------------------
|
||||
No <span class="nb">help</span> found
|
||||
|
||||
<span class="n">There</span> <span class="ow">is</span> <span class="n">no</span> <span class="n">help</span> <span class="n">topic</span> <span class="n">matching</span> <span class="s1">'evennia'</span><span class="o">.</span>
|
||||
<span class="o">...</span> <span class="n">But</span> <span class="n">matches</span> <span class="n">where</span> <span class="n">found</span> <span class="n">within</span> <span class="n">the</span> <span class="n">help</span> <span class="n">texts</span> <span class="n">of</span> <span class="n">the</span> <span class="n">suggestions</span> <span class="n">below</span><span class="o">.</span>
|
||||
There is no <span class="nb">help</span> topic matching <span class="s1">'evennia'</span>.
|
||||
... But matches where found within the <span class="nb">help</span> texts of the suggestions below.
|
||||
|
||||
<span class="n">Suggestions</span><span class="p">:</span>
|
||||
<span class="n">grapevine2chan</span><span class="p">,</span> <span class="n">about</span><span class="p">,</span> <span class="n">irc2chan</span>
|
||||
<span class="o">-----------------------------------------------------------------------------</span>
|
||||
Suggestions:
|
||||
grapevine2chan, about, irc2chan
|
||||
-----------------------------------------------------------------------------
|
||||
</pre></div>
|
||||
</div>
|
||||
<section id="using-the-help-system-from-in-game">
|
||||
<h2>Using the help system from in-game<a class="headerlink" href="#using-the-help-system-from-in-game" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Evennia has an extensive help system covering both command-help and regular free-form help documentation. It supports subtopics and if failing to find a match it will provide suggestsions, first from alternative topics and then by finding mentions of the search term in help entries.</p>
|
||||
<p>The help system is accessed in-game by use of the <code class="docutils literal notranslate"><span class="pre">help</span></code> command:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>help <topic>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Sub-topics are accessed as <code class="docutils literal notranslate"><span class="pre">help</span> <span class="pre"><topic>/<subtopic>/...</span></code>.</p>
|
||||
<section id="working-with-three-types-of-help-entries">
|
||||
<h2>Working with three types of help entries<a class="headerlink" href="#working-with-three-types-of-help-entries" title="Permalink to this headline">¶</a></h2>
|
||||
<p>There are three ways to generate help entries:</p>
|
||||
<ul class="simple">
|
||||
<li><p>In the database</p></li>
|
||||
<li><p>As Python modules</p></li>
|
||||
<li><p>From Command doc strings</p></li>
|
||||
</ul>
|
||||
<section id="database-stored-help-entries">
|
||||
<h3>Database-stored help entries<a class="headerlink" href="#database-stored-help-entries" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Creating a new help entry from in-game is done with</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>sethelp <topic>[;aliases] [,category] [,lockstring] = <text>
|
||||
</pre></div>
|
||||
|
|
@ -169,194 +175,22 @@ finding mentions of the search term in help entries.</p>
|
|||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>sethelp The Gods;pantheon, Lore = In the beginning all was dark ...
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Use the <code class="docutils literal notranslate"><span class="pre">/edit</span></code> switch to open the EvEditor for more convenient in-game writing
|
||||
(but note that devs can also create help entries outside the game using their
|
||||
regular code editor, see below).</p>
|
||||
<blockquote>
|
||||
<div><p>You can also create help entries as Python modules, outside of the game. See
|
||||
<em>FileHelp</em> entries below.</p>
|
||||
</div></blockquote>
|
||||
</section>
|
||||
<section id="sources-of-help-entries">
|
||||
<h2>Sources of help entries<a class="headerlink" href="#sources-of-help-entries" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Evennia collects help entries from three sources:</p>
|
||||
<ul class="simple">
|
||||
<li><p><em>Auto-generated command help</em> - this is literally the doc-strings of
|
||||
the <a class="reference internal" href="Commands.html"><span class="doc std std-doc">Command classes</span></a>. The idea is that the command docs are
|
||||
easier to maintain and keep up-to-date if the developer can change them at the
|
||||
same time as they do the code.</p></li>
|
||||
<li><p><em>Database-stored help entries</em> - These are created in-game (using the
|
||||
default <code class="docutils literal notranslate"><span class="pre">sethelp</span></code> command as exemplified in the previous section).</p></li>
|
||||
<li><p><em>File-stored help entries</em> - These are created outside the game, as dicts in
|
||||
normal Python modules. They allows developers to write and maintain their help
|
||||
files using a proper text editor.</p></li>
|
||||
</ul>
|
||||
<section id="the-help-entry">
|
||||
<h3>The Help Entry<a class="headerlink" href="#the-help-entry" title="Permalink to this headline">¶</a></h3>
|
||||
<p>All help entries (no matter the source) have the following properties:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">key</span></code> - This is the main topic-name. For Commands, this is literally the
|
||||
command’s <code class="docutils literal notranslate"><span class="pre">key</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">aliases</span></code> - Alternate names for the help entry. This can be useful if the main
|
||||
name is hard to remember.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">help_category</span></code> - The general grouping of the entry. This is optional. If not
|
||||
given it will use the default category given by
|
||||
<code class="docutils literal notranslate"><span class="pre">settings.COMMAND_DEFAULT_HELP_CATEGORY</span></code> for Commands and
|
||||
<code class="docutils literal notranslate"><span class="pre">settings.DEFAULT_HELP_CATEGORY</span></code> for file+db help entries.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">locks</span></code> - Lock string (for commands) or LockHandler (all help entries).
|
||||
This defines who may read this entry. See the next section.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">tags</span></code> - This is not used by default, but could be used to further organize
|
||||
help entries.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">text</span></code> - The actual help entry text. This will be dedented and stripped of
|
||||
extra space at beginning and end.</p></li>
|
||||
</ul>
|
||||
<p>A <code class="docutils literal notranslate"><span class="pre">text</span></code> that scrolls off the screen will automatically be paginated by
|
||||
the <a class="reference internal" href="EvMore.html"><span class="doc std std-doc">EvMore</span></a> pager (you can control this with
|
||||
<code class="docutils literal notranslate"><span class="pre">settings.HELP_MORE_ENABLED=False</span></code>). If you use EvMore and want to control
|
||||
exactly where the pager should break the page, mark the break with the control
|
||||
character <code class="docutils literal notranslate"><span class="pre">\f</span></code>.</p>
|
||||
<section id="subtopics">
|
||||
<h4>Subtopics<a class="headerlink" href="#subtopics" title="Permalink to this headline">¶</a></h4>
|
||||
<div class="versionadded">
|
||||
<p><span class="versionmodified added">New in version 1.0.</span></p>
|
||||
</div>
|
||||
<p>Rather than making a very long help entry, the <code class="docutils literal notranslate"><span class="pre">text</span></code> may also be broken up
|
||||
into <em>subtopics</em>. A list of the next level of subtopics are shown below the
|
||||
main help text and allows the user to read more about some particular detail
|
||||
that wouldn’t fit in the main text.</p>
|
||||
<p>Subtopics use a markup slightly similar to markdown headings. The top level
|
||||
heading must be named <code class="docutils literal notranslate"><span class="pre">#</span> <span class="pre">subtopics</span></code> (non case-sensitive) and the following
|
||||
headers must be sub-headings to this (so <code class="docutils literal notranslate"><span class="pre">##</span> <span class="pre">subtopic</span> <span class="pre">name</span></code> etc). All headings
|
||||
are non-case sensitive (the help command will format them). The topics can be
|
||||
nested at most to a depth of 5 (which is probably too many levels already). The
|
||||
parser uses fuzzy matching to find the subtopic, so one does not have to type
|
||||
it all out exactly.</p>
|
||||
<p>Below is an example of a <code class="docutils literal notranslate"><span class="pre">text</span></code> with sub topics.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>The theatre is the heart of the city, here you can find ...
|
||||
(This is the main help text, what you get with `help theatre`)
|
||||
|
||||
# subtopics
|
||||
|
||||
## lore
|
||||
|
||||
The theatre holds many mysterious things...
|
||||
(`help theatre/lore`)
|
||||
|
||||
### the grand opening
|
||||
|
||||
The grand opening is the name for a mysterious event where ghosts appeared ...
|
||||
(`this is a subsub-topic to lore, accessible as `help theatre/lore/grand` or
|
||||
any other partial match).
|
||||
|
||||
### the Phantom
|
||||
|
||||
Deep under the theatre, rumors has it a monster hides ...
|
||||
(another subsubtopic, accessible as `help theatre/lore/phantom`)
|
||||
|
||||
## layout
|
||||
|
||||
The theatre is a two-story building situated at ...
|
||||
(`help theatre/layout`)
|
||||
|
||||
## dramatis personae
|
||||
|
||||
There are many interesting people prowling the halls of the theatre ...
|
||||
(`help theatre/dramatis` or `help theathre/drama` or `help theatre/personae` would work)
|
||||
|
||||
### Primadonna Ada
|
||||
|
||||
Everyone knows the primadonna! She is ...
|
||||
(A subtopic under dramatis personae, accessible as `help theatre/drama/ada` etc)
|
||||
|
||||
### The gatekeeper
|
||||
|
||||
He always keeps an eye on the door and ...
|
||||
(`help theatre/drama/gate`)
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="command-auto-help-system">
|
||||
<h3>Command Auto-help system<a class="headerlink" href="#command-auto-help-system" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The auto-help system uses the <code class="docutils literal notranslate"><span class="pre">__doc__</span></code> strings of your command classes and
|
||||
formats this to a nice- looking help entry. This makes for a very easy way to
|
||||
keep the help updated - just document your commands well and updating the help
|
||||
file is just a <code class="docutils literal notranslate"><span class="pre">reload</span></code> away.</p>
|
||||
<p>Example (from a module with command definitions):</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="k">class</span> <span class="nc">CmdMyCmd</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> mycmd - my very own command</span>
|
||||
|
||||
<span class="sd"> Usage:</span>
|
||||
<span class="sd"> mycmd[/switches] <args></span>
|
||||
|
||||
<span class="sd"> Switches:</span>
|
||||
<span class="sd"> test - test the command</span>
|
||||
<span class="sd"> run - do something else</span>
|
||||
|
||||
<span class="sd"> This is my own command that does this and that.</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="c1"># [...]</span>
|
||||
|
||||
<span class="n">locks</span> <span class="o">=</span> <span class="s2">"cmd:all();read:all()"</span> <span class="c1"># default</span>
|
||||
<span class="n">help_category</span> <span class="o">=</span> <span class="s2">"General"</span> <span class="c1"># default</span>
|
||||
<span class="n">auto_help</span> <span class="o">=</span> <span class="kc">True</span> <span class="c1"># default</span>
|
||||
|
||||
<span class="c1"># [...]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The text at the very top of the command class definition is the class’
|
||||
<code class="docutils literal notranslate"><span class="pre">__doc__</span></code>-string and will be shown to users looking for help. Try to use a
|
||||
consistent format - all default commands are using the structure shown above.</p>
|
||||
<p>You can limit access to the help entry by the <code class="docutils literal notranslate"><span class="pre">view</span></code> and/or <code class="docutils literal notranslate"><span class="pre">read</span></code> locks on the
|
||||
Command. See <a class="reference internal" href="#locking-help-entries"><span class="std std-doc">the section below</span></a> for details.</p>
|
||||
<p>You should also supply the <code class="docutils literal notranslate"><span class="pre">help_category</span></code> class property if you can; this helps
|
||||
to group help entries together for people to more easily find them. See the
|
||||
<code class="docutils literal notranslate"><span class="pre">help</span></code> command in-game to see the default categories. If you don’t specify the
|
||||
category, <code class="docutils literal notranslate"><span class="pre">settings.COMMAND_DEFAULT_HELP_CATEGORY</span></code> (default is “General”) is
|
||||
used.</p>
|
||||
<p>If you don’t want your command to be picked up by the auto-help system at all
|
||||
(like if you want to write its docs manually using the info in the next section
|
||||
or you use a <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">cmdset</span></a> that has its own help functionality) you
|
||||
can explicitly set <code class="docutils literal notranslate"><span class="pre">auto_help</span></code> class property to <code class="docutils literal notranslate"><span class="pre">False</span></code> in your command
|
||||
definition.</p>
|
||||
<p>Alternatively, you can keep the advantages of <em>auto-help</em> in commands, but
|
||||
control the display of command helps. You can do so by overriding the command’s
|
||||
<code class="docutils literal notranslate"><span class="pre">get_help(caller,</span> <span class="pre">cmdset)</span></code> method. By default, this method will return the
|
||||
class docstring. You could modify it to add custom behavior: the text returned
|
||||
by this method will be displayed to the character asking for help in this
|
||||
command.</p>
|
||||
</section>
|
||||
<section id="database-help-entries">
|
||||
<h3>Database-help entries<a class="headerlink" href="#database-help-entries" title="Permalink to this headline">¶</a></h3>
|
||||
<p>These are most commonly created in-game using the <code class="docutils literal notranslate"><span class="pre">sethelp</span></code> command. If you need to create one
|
||||
manually, you can do so with <code class="docutils literal notranslate"><span class="pre">evennia.create_help_entry()</span></code>:</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_help_entry</span>
|
||||
<p>This will create a new help entry in the database. Use the <code class="docutils literal notranslate"><span class="pre">/edit</span></code> switch to open the EvEditor for more convenient in-game writing (but note that devs can also create help entries outside the game using their regular code editor, see below).</p>
|
||||
<p>The <a class="reference internal" href="../api/evennia.help.models.html#evennia.help.models.HelpEntry" title="evennia.help.models.HelpEntry"><span class="xref myst py py-class">HelpEntry</span></a> stores database help. It is <em>not</em> a Typeclassed entity and can’t be extended using the typeclass mechanism.</p>
|
||||
<p>Here’s how to create a database-help entry in code:</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_help_entry</span>
|
||||
<span class="n">entry</span> <span class="o">=</span> <span class="n">create_help_entry</span><span class="p">(</span><span class="s2">"emote"</span><span class="p">,</span>
|
||||
<span class="s2">"Emoting is important because ..."</span><span class="p">,</span>
|
||||
<span class="n">category</span><span class="o">=</span><span class="s2">"Roleplaying"</span><span class="p">,</span> <span class="n">locks</span><span class="o">=</span><span class="s2">"view:all()"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The entity being created is a <a class="reference internal" href="../api/evennia.help.models.html#evennia.help.models.HelpEntry" title="evennia.help.models.HelpEntry"><span class="xref myst py py-class">evennia.help.models.HelpEntry</span></a>
|
||||
object. This is <em>not</em> a <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclassed</span></a> entity and is not meant to
|
||||
be modified to any great degree. It holds the properties listed earlier. The
|
||||
text is stored in a field <code class="docutils literal notranslate"><span class="pre">entrytext</span></code>. It does not provide a <code class="docutils literal notranslate"><span class="pre">get_help</span></code> method
|
||||
like commands, stores and returns the <code class="docutils literal notranslate"><span class="pre">entrytext</span></code> directly.</p>
|
||||
<p>You can search for (db-)-<code class="docutils literal notranslate"><span class="pre">HelpEntry</span></code> objects using <code class="docutils literal notranslate"><span class="pre">evennia.search_help</span></code> but note that
|
||||
this will not return the two other types of help entries.</p>
|
||||
</section>
|
||||
<section id="file-help-entries">
|
||||
<h3>File-help entries<a class="headerlink" href="#file-help-entries" title="Permalink to this headline">¶</a></h3>
|
||||
<section id="file-stored-help-entries">
|
||||
<h3>File-stored help entries<a class="headerlink" href="#file-stored-help-entries" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="versionadded">
|
||||
<p><span class="versionmodified added">New in version 1.0.</span></p>
|
||||
</div>
|
||||
<p>File-help entries are created by the game development team outside of the game. The
|
||||
help entries are defined in normal Python modules (<code class="docutils literal notranslate"><span class="pre">.py</span></code> file ending) containing
|
||||
a <code class="docutils literal notranslate"><span class="pre">dict</span></code> to represent each entry. They require a server <code class="docutils literal notranslate"><span class="pre">reload</span></code> before any changes
|
||||
apply.</p>
|
||||
<p>File-help entries are created by the game development team outside of the game. The help entries are defined in normal Python modules (<code class="docutils literal notranslate"><span class="pre">.py</span></code> file ending) containing a <code class="docutils literal notranslate"><span class="pre">dict</span></code> to represent each entry. They require a server <code class="docutils literal notranslate"><span class="pre">reload</span></code> before any changes apply.</p>
|
||||
<ul class="simple">
|
||||
<li><p>Evennia will look through all modules given by
|
||||
<code class="docutils literal notranslate"><span class="pre">settings.FILE_HELP_ENTRY_MODULES</span></code>. This should be a list of python-paths for
|
||||
|
|
@ -411,26 +245,36 @@ Here’s an example of a help module:</p>
|
|||
to keep your strings a reasonable width (it will look better). Just reload the
|
||||
server and the file-based help entries will be available to view.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="entry-priority">
|
||||
<h2>Entry priority<a class="headerlink" href="#entry-priority" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Should you have clashing help-entries between the three types of available
|
||||
entries, the priority is</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Command-auto-help > Db-help > File-help
|
||||
<section id="command-help-entries">
|
||||
<h3>Command-help entries<a class="headerlink" href="#command-help-entries" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">__docstring__</span></code> of <a class="reference internal" href="Commands.html"><span class="doc std std-doc">Command classes</span></a> are automatically extracted into a help entry. You set <code class="docutils literal notranslate"><span class="pre">help_category</span></code> directly on the class.</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">Command</span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">MyCommand</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
|
||||
<span class="sd">""" </span>
|
||||
<span class="sd"> This command is great! </span>
|
||||
|
||||
<span class="sd"> Usage: </span>
|
||||
<span class="sd"> mycommand [argument]</span>
|
||||
|
||||
<span class="sd"> When this command is called, great things happen. If you </span>
|
||||
<span class="sd"> pass an argument, even GREATER things HAPPEN!</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"mycommand"</span>
|
||||
|
||||
<span class="n">locks</span><span class="p">:</span> <span class="s2">"cmd:all();read:all()"</span> <span class="c1"># default </span>
|
||||
<span class="n">help_category</span> <span class="o">=</span> <span class="s2">"General"</span> <span class="c1"># default</span>
|
||||
<span class="n">auto_help</span> <span class="o">=</span> <span class="kc">True</span> <span class="c1"># default </span>
|
||||
|
||||
<span class="c1"># ...</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>So if you create a db-help entry ‘foo’, it will replace any file-based help
|
||||
entry ‘foo’. But if there is a Command ‘foo’, that’s the help you’ll get when
|
||||
you enter <code class="docutils literal notranslate"><span class="pre">help</span> <span class="pre">foo</span></code>.</p>
|
||||
<p>The reasoning for this is that commands must always be understood in order to
|
||||
play the game. Meanwhile db-based help can be kept up-to-date from in-game
|
||||
builders and may be less ‘static’ than the file-based ones.</p>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">sethelp</span></code> command (which only deals with creating db-based help entries)
|
||||
will warn you if a new help entry might shadow/be shadowed by a
|
||||
same/similar-named command or file-based help entry.</p>
|
||||
<p>When you update your code, the command’s help will follow. The idea is that the command docs are easier to maintain and keep up-to-date if the developer can change them at the same time as they do the code.</p>
|
||||
</section>
|
||||
<section id="locking-help-entries">
|
||||
<h2>Locking help entries<a class="headerlink" href="#locking-help-entries" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Locking help entries<a class="headerlink" href="#locking-help-entries" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The default <code class="docutils literal notranslate"><span class="pre">help</span></code> command gather all available commands and help entries
|
||||
together so they can be searched or listed. By setting locks on the command/help
|
||||
entry one can limit who can read help about it.</p>
|
||||
|
|
@ -473,32 +317,100 @@ the new ‘read’ lock-type to control access to the entry itself.</p>
|
|||
</div>
|
||||
</section>
|
||||
<section id="customizing-the-look-of-the-help-system">
|
||||
<h2>Customizing the look of the help system<a class="headerlink" href="#customizing-the-look-of-the-help-system" title="Permalink to this headline">¶</a></h2>
|
||||
<p>This is done almost exclusively by overriding the <code class="docutils literal notranslate"><span class="pre">help</span></code> command
|
||||
<a class="reference internal" href="../api/evennia.commands.default.help.html#evennia.commands.default.help.CmdHelp" title="evennia.commands.default.help.CmdHelp"><span class="xref myst py py-class">evennia.commands.default.help.CmdHelp</span></a>.</p>
|
||||
<p>Since the available commands may vary from moment to moment, <code class="docutils literal notranslate"><span class="pre">help</span></code> is
|
||||
responsible for collating the three sources of help-entries (commands/db/file)
|
||||
together and search through them on the fly. It also does all the formatting of
|
||||
the output.</p>
|
||||
<p>To make it easier to tweak the look, the parts of the code that changes the
|
||||
visual presentation and entity searching has been broken out into separate
|
||||
methods on the command class. Override these in your version of <code class="docutils literal notranslate"><span class="pre">help</span></code> to change
|
||||
the display or tweak as you please. See the api link above for details.</p>
|
||||
<h3>Customizing the look of the help system<a class="headerlink" href="#customizing-the-look-of-the-help-system" title="Permalink to this headline">¶</a></h3>
|
||||
<p>This is done almost exclusively by overriding the <code class="docutils literal notranslate"><span class="pre">help</span></code> command <a class="reference internal" href="../api/evennia.commands.default.help.html#evennia.commands.default.help.CmdHelp" title="evennia.commands.default.help.CmdHelp"><span class="xref myst py py-class">evennia.commands.default.help.CmdHelp</span></a>.</p>
|
||||
<p>Since the available commands may vary from moment to moment, <code class="docutils literal notranslate"><span class="pre">help</span></code> is responsible for collating the three sources of help-entries (commands/db/file) together and search through them on the fly. It also does all the formatting of the output.</p>
|
||||
<p>To make it easier to tweak the look, the parts of the code that changes the visual presentation and entity searching has been broken out into separate methods on the command class. Override these in your version of <code class="docutils literal notranslate"><span class="pre">help</span></code> to change the display or tweak as you please. See the api link above for details.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="subtopics">
|
||||
<h2>Subtopics<a class="headerlink" href="#subtopics" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="versionadded">
|
||||
<p><span class="versionmodified added">New in version 1.0.</span></p>
|
||||
</div>
|
||||
<p>Rather than making a very long help entry, the <code class="docutils literal notranslate"><span class="pre">text</span></code> may also be broken up into <em>subtopics</em>. A list of the next level of subtopics are shown below the main help text and allows the user to read more about some particular detail that wouldn’t fit in the main text.</p>
|
||||
<p>Subtopics use a markup slightly similar to markdown headings. The top level heading must be named <code class="docutils literal notranslate"><span class="pre">#</span> <span class="pre">subtopics</span></code> (non case-sensitive) and the following headers must be sub-headings to this (so <code class="docutils literal notranslate"><span class="pre">##</span> <span class="pre">subtopic</span> <span class="pre">name</span></code> etc). All headings are non-case sensitive (the help command will format them). The topics can be nested at most to a depth of 5 (which is probably too many levels already). The parser uses fuzzy matching to find the subtopic, so one does not have to type it all out exactly.</p>
|
||||
<p>Below is an example of a <code class="docutils literal notranslate"><span class="pre">text</span></code> with sub topics.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>The theatre is the heart of the city, here you can find ...
|
||||
(This is the main help text, what you get with `help theatre`)
|
||||
|
||||
# subtopics
|
||||
|
||||
## lore
|
||||
|
||||
The theatre holds many mysterious things...
|
||||
(`help theatre/lore`)
|
||||
|
||||
### the grand opening
|
||||
|
||||
The grand opening is the name for a mysterious event where ghosts appeared ...
|
||||
(`this is a subsub-topic to lore, accessible as `help theatre/lore/grand` or
|
||||
any other partial match).
|
||||
|
||||
### the Phantom
|
||||
|
||||
Deep under the theatre, rumors has it a monster hides ...
|
||||
(another subsubtopic, accessible as `help theatre/lore/phantom`)
|
||||
|
||||
## layout
|
||||
|
||||
The theatre is a two-story building situated at ...
|
||||
(`help theatre/layout`)
|
||||
|
||||
## dramatis personae
|
||||
|
||||
There are many interesting people prowling the halls of the theatre ...
|
||||
(`help theatre/dramatis` or `help theathre/drama` or `help theatre/personae` would work)
|
||||
|
||||
### Primadonna Ada
|
||||
|
||||
Everyone knows the primadonna! She is ...
|
||||
(A subtopic under dramatis personae, accessible as `help theatre/drama/ada` etc)
|
||||
|
||||
### The gatekeeper
|
||||
|
||||
He always keeps an eye on the door and ...
|
||||
(`help theatre/drama/gate`)
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="technical-notes">
|
||||
<h2>Technical notes<a class="headerlink" href="#technical-notes" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Since it needs to search so different types of data, the help system has to
|
||||
collect all possibilities in memory before searching through the entire set. It
|
||||
uses the <a class="reference external" href="https://github.com/yeraydiazdiaz/lunr.py">Lunr</a> search engine to
|
||||
search through the main bulk of help entries. Lunr is a mature engine used for
|
||||
web-pages and produces much more sensible results than previous solutions.</p>
|
||||
<p>Once the main entry has been found, subtopics are then searched with
|
||||
simple <code class="docutils literal notranslate"><span class="pre">==</span></code>, <code class="docutils literal notranslate"><span class="pre">startswith</span></code> and <code class="docutils literal notranslate"><span class="pre">in</span></code> matching (there are so relatively few of them
|
||||
at that point).</p>
|
||||
<section id="help-entry-clashes">
|
||||
<h3>Help-entry clashes<a class="headerlink" href="#help-entry-clashes" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Should you have clashing help-entries (of the same name) between the three types of available entries, the priority is</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Command-auto-help > Db-help > File-help
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">sethelp</span></code> command (which only deals with creating db-based help entries) will warn you if a new help entry might shadow/be shadowed by a same/similar-named command or file-based help entry.</p>
|
||||
</section>
|
||||
<section id="the-help-entry-container">
|
||||
<h3>The Help Entry container<a class="headerlink" href="#the-help-entry-container" title="Permalink to this headline">¶</a></h3>
|
||||
<p>All help entries (no matter the source) are parsed into an object with the following properties:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">key</span></code> - This is the main topic-name. For Commands, this is literally the command’s <code class="docutils literal notranslate"><span class="pre">key</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">aliases</span></code> - Alternate names for the help entry. This can be useful if the main name is hard to remember.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">help_category</span></code> - The general grouping of the entry. This is optional. If not given it will use the default category given by <code class="docutils literal notranslate"><span class="pre">settings.COMMAND_DEFAULT_HELP_CATEGORY</span></code> for Commands and
|
||||
<code class="docutils literal notranslate"><span class="pre">settings.DEFAULT_HELP_CATEGORY</span></code> for file+db help entries.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">locks</span></code> - Lock string (for commands) or LockHandler (all help entries). This defines who may read this entry. See the next section.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">tags</span></code> - This is not used by default, but could be used to further organize help entries.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">text</span></code> - The actual help entry text. This will be dedented and stripped of extra space at beginning and end.</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section id="help-pagination">
|
||||
<h3>Help pagination<a class="headerlink" href="#help-pagination" title="Permalink to this headline">¶</a></h3>
|
||||
<p>A <code class="docutils literal notranslate"><span class="pre">text</span></code> that scrolls off the screen will automatically be paginated by the <a class="reference internal" href="EvMore.html"><span class="doc std std-doc">EvMore</span></a> pager (you can control this with <code class="docutils literal notranslate"><span class="pre">settings.HELP_MORE_ENABLED=False</span></code>). If you use EvMore and want to control exactly where the pager should break the page, mark the break with the control character <code class="docutils literal notranslate"><span class="pre">\f</span></code>.</p>
|
||||
</section>
|
||||
<section id="search-engine">
|
||||
<h3>Search engine<a class="headerlink" href="#search-engine" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Since it needs to search so different types of data, the help system has to collect all possibilities in memory before searching through the entire set. It uses the <a class="reference external" href="https://github.com/yeraydiazdiaz/lunr.py">Lunr</a> search engine to search through the main bulk of help entries. Lunr is a mature engine used for web-pages and produces much more sensible results than previous solutions.</p>
|
||||
<p>Once the main entry has been found, subtopics are then searched with simple <code class="docutils literal notranslate"><span class="pre">==</span></code>, <code class="docutils literal notranslate"><span class="pre">startswith</span></code> and <code class="docutils literal notranslate"><span class="pre">in</span></code> matching (there are so relatively few of them at that point).</p>
|
||||
<div class="versionchanged">
|
||||
<p><span class="versionmodified changed">Changed in version 1.0: </span>Replaced the old bag-of-words algorithm with lunr package.</p>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Coding Utils" href="Coding-Utils.html" />
|
||||
<link rel="prev" title="Batch Command Processor" href="Batch-Command-Processor.html" />
|
||||
<link rel="prev" title="Batch Code Processor" href="Batch-Code-Processor.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
|
|
@ -33,7 +33,7 @@
|
|||
<a href="Coding-Utils.html" title="Coding Utils"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Batch-Command-Processor.html" title="Batch Command Processor"
|
||||
<a href="Batch-Code-Processor.html" title="Batch Code Processor"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" accesskey="U">Core Components</a> »</li>
|
||||
|
|
@ -76,16 +76,16 @@
|
|||
<li><a class="reference internal" href="#repeat">repeat</a></li>
|
||||
<li><a class="reference internal" href="#unrepeat">unrepeat</a></li>
|
||||
<li><a class="reference internal" href="#monitor">monitor</a></li>
|
||||
<li><a class="reference internal" href="#unmonitor">unmonitor</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#unmonitor">unmonitor</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Batch-Command-Processor.html"
|
||||
title="previous chapter">Batch Command Processor</a></p>
|
||||
<p class="topless"><a href="Batch-Code-Processor.html"
|
||||
title="previous chapter">Batch Code Processor</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Coding-Utils.html"
|
||||
title="next chapter">Coding Utils</a></p>
|
||||
|
|
@ -121,29 +121,45 @@
|
|||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="inputfuncs">
|
||||
<h1>Inputfuncs<a class="headerlink" href="#inputfuncs" title="Permalink to this headline">¶</a></h1>
|
||||
<p>An <em>inputfunc</em> is an Evennia function that handles a particular input (an <a class="reference internal" href="../Concepts/OOB.html"><span class="doc std std-doc">inputcommand</span></a>) from
|
||||
the client. The inputfunc is the last destination for the inputcommand along the <span class="xref myst">ingoing message
|
||||
path</span>. The inputcommand always has the form <code class="docutils literal notranslate"><span class="pre">(commandname,</span> <span class="pre">(args),</span> <span class="pre">{kwargs})</span></code> and Evennia will use this to try to find and call an inputfunc on the form</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="k">def</span> <span class="nf">commandname</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||||
<span class="c1"># ...</span>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> Internet│
|
||||
┌─────┐ │ ┌────────┐
|
||||
┌──────┐ │Text │ │ ┌────────────┐ ┌─────────┐ │Command │
|
||||
│Client├────┤JSON ├─┼──►commandtuple├────►Inputfunc├────►DB query│
|
||||
└──────┘ │etc │ │ └────────────┘ └─────────┘ │etc │
|
||||
└─────┘ │ └────────┘
|
||||
│Evennia
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The Inputfunc is the last fixed step on the <a class="reference internal" href="../Concepts/Messagepath.html#ingoing-message-path"><span class="std std-doc">Ingoing message path</span></a>. The available Inputfuncs are looked up and called using <code class="docutils literal notranslate"><span class="pre">commandtuple</span></code> structures sent from the client. The job of the Inputfunc is to perform whatever action is requested, by firing a Command, performing a database query or whatever is needed.</p>
|
||||
<p>Given a <code class="docutils literal notranslate"><span class="pre">commandtuple</span></code> on the form</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>(commandname, (args), {kwargs})
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Evennia will try to find and call an Inputfunc on the form</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">commandname</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||||
<span class="c1"># ...</span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Or, if no match was found, it will call an inputfunc named “default” on this form</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="k">def</span> <span class="nf">default</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">cmdname</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||||
<span class="c1"># cmdname is the name of the mismatched inputcommand</span>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">default</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">cmdname</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||||
<span class="c1"># cmdname is the name of the mismatched inputcommand</span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The default inputfuncs are found in <a class="reference internal" href="../api/evennia.server.inputfuncs.html#evennia-server-inputfuncs"><span class="std std-ref">evennia/server/inputfuncs.py</span></a>.</p>
|
||||
<section id="adding-your-own-inputfuncs">
|
||||
<h2>Adding your own inputfuncs<a class="headerlink" href="#adding-your-own-inputfuncs" title="Permalink to this headline">¶</a></h2>
|
||||
<p>This is simple. Add a function on the above form to <code class="docutils literal notranslate"><span class="pre">mygame/server/conf/inputfuncs.py</span></code>. Your
|
||||
function must be in the global, outermost scope of that module and not start with an underscore
|
||||
(<code class="docutils literal notranslate"><span class="pre">_</span></code>) to be recognized as an inputfunc. Reload the server. That’s it. To overload a default
|
||||
inputfunc (see below), just add a function with the same name.</p>
|
||||
<p>The modules Evennia looks into for inputfuncs are defined in the list <code class="docutils literal notranslate"><span class="pre">settings.INPUT_FUNC_MODULES</span></code>.
|
||||
This list will be imported from left to right and later imported functions will replace earlier
|
||||
ones.</p>
|
||||
<ol class="simple">
|
||||
<li><p>Add a function on the above form to <code class="docutils literal notranslate"><span class="pre">mygame/server/conf/inputfuncs.py</span></code>. Your function must be in the global, outermost scope of that module and not start with an underscore (<code class="docutils literal notranslate"><span class="pre">_</span></code>) to be recognized as an inputfunc. i</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">reload</span></code> the server.</p></li>
|
||||
</ol>
|
||||
<p>To overload a default inputfunc (see below), just add a function with the same name. You can also extend the settings-list <code class="docutils literal notranslate"><span class="pre">INPUT_FUNC_MODULES</span></code>.</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>INPUT_FUNC_MODULES += ["path.to.my.inputfunc.module"]
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>All global-level functions with a name not starting with <code class="docutils literal notranslate"><span class="pre">_</span></code> in these module(s) will be used by Evennia as an inputfunc. The list is imported from left to right, so latter imported functions will replace earlier ones.</p>
|
||||
</section>
|
||||
<section id="default-inputfuncs">
|
||||
<h2>Default inputfuncs<a class="headerlink" href="#default-inputfuncs" title="Permalink to this headline">¶</a></h2>
|
||||
|
|
@ -155,10 +171,8 @@ ones.</p>
|
|||
<li><p>Input: <code class="docutils literal notranslate"><span class="pre">("text",</span> <span class="pre">(textstring,),</span> <span class="pre">{})</span></code></p></li>
|
||||
<li><p>Output: Depends on Command triggered</p></li>
|
||||
</ul>
|
||||
<p>This is the most common of inputcommands, and the only one supported by every traditional mud. The
|
||||
argument is usually what the user sent from their command line. Since all text input from the user
|
||||
like this is considered a <a class="reference internal" href="Commands.html"><span class="doc std std-doc">Command</span></a>, this inputfunc will do things like nick-replacement
|
||||
and then pass on the input to the central Commandhandler.</p>
|
||||
<p>This is the most common of inputs, and the only one supported by every traditional mud. The argument is usually what the user sent from their command line. Since all text input from the user
|
||||
like this is considered a <a class="reference internal" href="Commands.html"><span class="doc std std-doc">Command</span></a>, this inputfunc will do things like nick-replacement and then pass on the input to the central Commandhandler.</p>
|
||||
</section>
|
||||
<section id="echo">
|
||||
<h3>echo<a class="headerlink" href="#echo" title="Permalink to this headline">¶</a></h3>
|
||||
|
|
@ -166,13 +180,11 @@ and then pass on the input to the central Commandhandler.</p>
|
|||
<li><p>Input: <code class="docutils literal notranslate"><span class="pre">("echo",</span> <span class="pre">(args),</span> <span class="pre">{})</span></code></p></li>
|
||||
<li><p>Output: <code class="docutils literal notranslate"><span class="pre">("text",</span> <span class="pre">("Echo</span> <span class="pre">returns:</span> <span class="pre">%s"</span> <span class="pre">%</span> <span class="pre">args),</span> <span class="pre">{})</span></code></p></li>
|
||||
</ul>
|
||||
<p>This is a test input, which just echoes the argument back to the session as text. Can be used for
|
||||
testing custom client input.</p>
|
||||
<p>This is a test input, which just echoes the argument back to the session as text. Can be used for testing custom client input.</p>
|
||||
</section>
|
||||
<section id="default">
|
||||
<h3>default<a class="headerlink" href="#default" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The default function, as mentioned above, absorbs all non-recognized inputcommands. The default one
|
||||
will just log an error.</p>
|
||||
<p>The default function, as mentioned above, absorbs all non-recognized inputcommands. The default one will just log an error.</p>
|
||||
</section>
|
||||
<section id="client-options">
|
||||
<h3>client_options<a class="headerlink" href="#client-options" title="Permalink to this headline">¶</a></h3>
|
||||
|
|
@ -203,8 +215,7 @@ as an outputcommand <code class="docutils literal notranslate"><span class="pre"
|
|||
<li><p>raw (bool): Leave text tags unparsed</p></li>
|
||||
</ul>
|
||||
<blockquote>
|
||||
<div><p>Note that there are two GMCP aliases to this inputfunc - <code class="docutils literal notranslate"><span class="pre">hello</span></code> and <code class="docutils literal notranslate"><span class="pre">supports_set</span></code>, which means
|
||||
it will be accessed via the GMCP <code class="docutils literal notranslate"><span class="pre">Hello</span></code> and <code class="docutils literal notranslate"><span class="pre">Supports.Set</span></code> instructions assumed by some clients.</p>
|
||||
<div><p>Note that there are two GMCP aliases to this inputfunc - <code class="docutils literal notranslate"><span class="pre">hello</span></code> and <code class="docutils literal notranslate"><span class="pre">supports_set</span></code>, which means it will be accessed via the GMCP <code class="docutils literal notranslate"><span class="pre">Hello</span></code> and <code class="docutils literal notranslate"><span class="pre">Supports.Set</span></code> instructions assumed by some clients.</p>
|
||||
</div></blockquote>
|
||||
</section>
|
||||
<section id="get-client-options">
|
||||
|
|
@ -213,8 +224,7 @@ it will be accessed via the GMCP <code class="docutils literal notranslate"><spa
|
|||
<li><p>Input: <code class="docutils literal notranslate"><span class="pre">("get_client_options,</span> <span class="pre">(),</span> <span class="pre">{key:value,</span> <span class="pre">...})</span></code></p></li>
|
||||
<li><p>Output: <code class="docutils literal notranslate"><span class="pre">("client_options,</span> <span class="pre">(),</span> <span class="pre">{key:value,</span> <span class="pre">...})</span></code></p></li>
|
||||
</ul>
|
||||
<p>This is a convenience wrapper that retrieves the current options by sending “get” to
|
||||
<code class="docutils literal notranslate"><span class="pre">client_options</span></code> above.</p>
|
||||
<p>This is a convenience wrapper that retrieves the current options by sending “get” to <code class="docutils literal notranslate"><span class="pre">client_options</span></code> above.</p>
|
||||
</section>
|
||||
<section id="get-inputfuncs">
|
||||
<h3>get_inputfuncs<a class="headerlink" href="#get-inputfuncs" title="Permalink to this headline">¶</a></h3>
|
||||
|
|
@ -222,8 +232,7 @@ it will be accessed via the GMCP <code class="docutils literal notranslate"><spa
|
|||
<li><p>Input: <code class="docutils literal notranslate"><span class="pre">("get_inputfuncs",</span> <span class="pre">(),</span> <span class="pre">{})</span></code></p></li>
|
||||
<li><p>Output: <code class="docutils literal notranslate"><span class="pre">("get_inputfuncs",</span> <span class="pre">(),</span> <span class="pre">{funcname:docstring,</span> <span class="pre">...})</span></code></p></li>
|
||||
</ul>
|
||||
<p>Returns an outputcommand on the form <code class="docutils literal notranslate"><span class="pre">("get_inputfuncs",</span> <span class="pre">(),</span> <span class="pre">{funcname:docstring,</span> <span class="pre">...})</span></code> - a list of
|
||||
all the available inputfunctions along with their docstrings.</p>
|
||||
<p>Returns an outputcommand on the form <code class="docutils literal notranslate"><span class="pre">("get_inputfuncs",</span> <span class="pre">(),</span> <span class="pre">{funcname:docstring,</span> <span class="pre">...})</span></code> - a list of all the available inputfunctions along with their docstrings.</p>
|
||||
</section>
|
||||
<section id="login">
|
||||
<h3>login<a class="headerlink" href="#login" title="Permalink to this headline">¶</a></h3>
|
||||
|
|
@ -234,15 +243,13 @@ all the available inputfunctions along with their docstrings.</p>
|
|||
<li><p>Input: <code class="docutils literal notranslate"><span class="pre">("login",</span> <span class="pre">(username,</span> <span class="pre">password),</span> <span class="pre">{})</span></code></p></li>
|
||||
<li><p>Output: Depends on login hooks</p></li>
|
||||
</ul>
|
||||
<p>This performs the inputfunc version of a login operation on the current Session.</p>
|
||||
<p>This performs the inputfunc version of a login operation on the current Session. It’s meant to be used by custom client setups.</p>
|
||||
</section>
|
||||
<section id="get-value">
|
||||
<h3>get_value<a class="headerlink" href="#get-value" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Input: <code class="docutils literal notranslate"><span class="pre">("get_value",</span> <span class="pre">(name,</span> <span class="pre">),</span> <span class="pre">{})</span></code>
|
||||
Output: <code class="docutils literal notranslate"><span class="pre">("get_value",</span> <span class="pre">(value,</span> <span class="pre">),</span> <span class="pre">{})</span></code></p>
|
||||
<p>Retrieves a value from the Character or Account currently controlled by this Session. Takes one
|
||||
argument, This will only accept particular white-listed names, you’ll need to overload the function
|
||||
to expand. By default the following values can be retrieved:</p>
|
||||
<p>Retrieves a value from the Character or Account currently controlled by this Session. Takes one argument, This will only accept particular white-listed names, you’ll need to overload the function to expand. By default the following values can be retrieved:</p>
|
||||
<ul class="simple">
|
||||
<li><p>“name” or “key”: The key of the Account or puppeted Character.</p></li>
|
||||
<li><p>“location”: Name of the current location, or “None”.</p></li>
|
||||
|
|
@ -252,16 +259,11 @@ to expand. By default the following values can be retrieved:</p>
|
|||
<section id="repeat">
|
||||
<h3>repeat<a class="headerlink" href="#repeat" title="Permalink to this headline">¶</a></h3>
|
||||
<ul class="simple">
|
||||
<li><p>Input: <code class="docutils literal notranslate"><span class="pre">("repeat",</span> <span class="pre">(),</span> <span class="pre">{"callback":funcname,</span>                      <span class="pre">"interval":</span> <span class="pre">secs,</span> <span class="pre">"stop":</span> <span class="pre">False})</span></code></p></li>
|
||||
<li><p>Input: <code class="docutils literal notranslate"><span class="pre">("repeat",</span> <span class="pre">(),</span> <span class="pre">{"callback":funcname,</span>  <span class="pre">"interval":</span> <span class="pre">secs,</span> <span class="pre">"stop":</span> <span class="pre">False})</span></code></p></li>
|
||||
<li><p>Output: Depends on the repeated function. Will return <code class="docutils literal notranslate"><span class="pre">("text",</span> <span class="pre">(repeatlist),{}</span></code> with a list of
|
||||
accepted names if given an unfamiliar callback name.</p></li>
|
||||
</ul>
|
||||
<p>This will tell evennia to repeatedly call a named function at a given interval. Behind the scenes
|
||||
this will set up a <a class="reference internal" href="TickerHandler.html"><span class="doc std std-doc">Ticker</span></a>. Only previously acceptable functions are possible to
|
||||
repeat-call in this way, you’ll need to overload this inputfunc to add the ones you want to offer.
|
||||
By default only two example functions are allowed, “test1” and “test2”, which will just echo a text
|
||||
back at the given interval. Stop the repeat by sending <code class="docutils literal notranslate"><span class="pre">"stop":</span> <span class="pre">True</span></code> (note that you must include
|
||||
both the callback name and interval for Evennia to know what to stop).</p>
|
||||
<p>This will tell evennia to repeatedly call a named function at a given interval. Behind the scenes this will set up a <a class="reference internal" href="TickerHandler.html"><span class="doc std std-doc">Ticker</span></a>. Only previously acceptable functions are possible to repeat-call in this way, you’ll need to overload this inputfunc to add the ones you want to offer. By default only two example functions are allowed, “test1” and “test2”, which will just echo a text back at the given interval. Stop the repeat by sending <code class="docutils literal notranslate"><span class="pre">"stop":</span> <span class="pre">True</span></code> (note that you must include both the callback name and interval for Evennia to know what to stop).</p>
|
||||
</section>
|
||||
<section id="unrepeat">
|
||||
<h3>unrepeat<a class="headerlink" href="#unrepeat" title="Permalink to this headline">¶</a></h3>
|
||||
|
|
@ -277,28 +279,23 @@ both the callback name and interval for Evennia to know what to stop).</p>
|
|||
<li><p>Input: <code class="docutils literal notranslate"><span class="pre">("monitor",</span> <span class="pre">(),</span> <span class="pre">("name":field_or_argname,</span> <span class="pre">stop=False)</span></code></p></li>
|
||||
<li><p>Output (on change): <code class="docutils literal notranslate"><span class="pre">("monitor",</span> <span class="pre">(),</span> <span class="pre">{"name":name,</span> <span class="pre">"value":value})</span></code></p></li>
|
||||
</ul>
|
||||
<p>This sets up on-object monitoring of Attributes or database fields. Whenever the field or Attribute
|
||||
changes in any way, the outputcommand will be sent. This is using the
|
||||
<a class="reference internal" href="MonitorHandler.html"><span class="doc std std-doc">MonitorHandler</span></a> behind the scenes. Pass the “stop” key to stop monitoring. Note
|
||||
that you must supply the name also when stopping to let the system know which monitor should be
|
||||
cancelled.</p>
|
||||
<p>Only fields/attributes in a whitelist are allowed to be used, you have to overload this function to
|
||||
add more. By default the following fields/attributes can be monitored:</p>
|
||||
<p>This sets up on-object monitoring of Attributes or database fields. Whenever the field or Attribute changes in any way, the outputcommand will be sent. This is using the <a class="reference internal" href="MonitorHandler.html"><span class="doc std std-doc">MonitorHandler</span></a> behind the scenes. Pass the “stop” key to stop monitoring. Note that you must supply the name also when stopping to let the system know which monitor should be cancelled.</p>
|
||||
<p>Only fields/attributes in a whitelist are allowed to be used, you have to overload this function to add more. By default the following fields/attributes can be monitored:</p>
|
||||
<ul class="simple">
|
||||
<li><p>“name”: The current character name</p></li>
|
||||
<li><p>“location”: The current location</p></li>
|
||||
<li><p>“desc”: The description Argument</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
<section id="unmonitor">
|
||||
<h2>unmonitor<a class="headerlink" href="#unmonitor" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>unmonitor<a class="headerlink" href="#unmonitor" title="Permalink to this headline">¶</a></h3>
|
||||
<ul class="simple">
|
||||
<li><p>Input: <code class="docutils literal notranslate"><span class="pre">("unmonitor",</span> <span class="pre">(),</span> <span class="pre">{"name":name})</span></code></p></li>
|
||||
<li><p>Output: None</p></li>
|
||||
</ul>
|
||||
<p>A convenience wrapper that sends “stop” to the <code class="docutils literal notranslate"><span class="pre">monitor</span></code> function.</p>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
|
|
@ -320,7 +317,7 @@ add more. By default the following fields/attributes can be monitored:</p>
|
|||
<a href="Coding-Utils.html" title="Coding Utils"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Batch-Command-Processor.html" title="Batch Command Processor"
|
||||
<a href="Batch-Code-Processor.html" title="Batch Code Processor"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" >Core Components</a> »</li>
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
<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="Signals" href="Signals.html" />
|
||||
<link rel="prev" title="TickerHandler" href="TickerHandler.html" />
|
||||
<link rel="next" title="Commands" href="Commands.html" />
|
||||
<link rel="prev" title="Permissions" href="Permissions.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
|
|
@ -30,10 +30,10 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Signals.html" title="Signals"
|
||||
<a href="Commands.html" title="Commands"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="TickerHandler.html" title="TickerHandler"
|
||||
<a href="Permissions.html" title="Permissions"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" accesskey="U">Core Components</a> »</li>
|
||||
|
|
@ -63,28 +63,30 @@
|
|||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Locks</a><ul>
|
||||
<li><a class="reference internal" href="#setting-and-checking-a-lock">Setting and checking a lock</a></li>
|
||||
<li><a class="reference internal" href="#defining-locks">Defining locks</a><ul>
|
||||
<li><a class="reference internal" href="#working-with-locks">Working with locks</a><ul>
|
||||
<li><a class="reference internal" href="#defining-locks">Defining locks</a></li>
|
||||
<li><a class="reference internal" href="#valid-access-types">Valid access_types</a></li>
|
||||
<li><a class="reference internal" href="#custom-access-types">Custom access_types</a></li>
|
||||
<li><a class="reference internal" href="#lock-functions">Lock functions</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#checking-simple-strings">Checking simple strings</a></li>
|
||||
<li><a class="reference internal" href="#default-locks">Default locks</a></li>
|
||||
<li><a class="reference internal" href="#more-lock-definition-examples">More Lock definition examples</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#more-lock-definition-examples">More Lock definition examples</a><ul>
|
||||
<li><a class="reference internal" href="#a-complete-example-of-setting-locks-on-an-object">A complete example of setting locks on an object</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#on-djangos-permission-system">On Django’s permission system</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="TickerHandler.html"
|
||||
title="previous chapter">TickerHandler</a></p>
|
||||
<p class="topless"><a href="Permissions.html"
|
||||
title="previous chapter">Permissions</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Signals.html"
|
||||
title="next chapter">Signals</a></p>
|
||||
<p class="topless"><a href="Commands.html"
|
||||
title="next chapter">Commands</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
|
|
@ -118,21 +120,18 @@
|
|||
<section class="tex2jax_ignore mathjax_ignore" id="locks">
|
||||
<h1>Locks<a class="headerlink" href="#locks" title="Permalink to this headline">¶</a></h1>
|
||||
<p>For most games it is a good idea to restrict what people can do. In Evennia such restrictions are
|
||||
applied and checked by something called <em>locks</em>. All Evennia entities (<a class="reference internal" href="Commands.html"><span class="doc std std-doc">Commands</span></a>,
|
||||
<a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a>, <a class="reference internal" href="Scripts.html"><span class="doc std std-doc">Scripts</span></a>, <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a>, <a class="reference internal" href="Help-System.html"><span class="doc std std-doc">Help System</span></a>,
|
||||
<a class="reference internal" href="Msg.html"><span class="doc std std-doc">messages</span></a> and <a class="reference internal" href="Channels.html"><span class="doc std std-doc">channels</span></a>) are accessed through locks.</p>
|
||||
applied and checked by something called <em>locks</em>. All Evennia entities (<a class="reference internal" href="Commands.html"><span class="doc std std-doc">Commands</span></a>, <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a>, <a class="reference internal" href="Scripts.html"><span class="doc std std-doc">Scripts</span></a>, <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a>, <a class="reference internal" href="Help-System.html"><span class="doc std std-doc">Help System</span></a>, <a class="reference internal" href="Msg.html"><span class="doc std std-doc">messages</span></a> and <a class="reference internal" href="Channels.html"><span class="doc std std-doc">channels</span></a>) are accessed through locks.</p>
|
||||
<p>A lock can be thought of as an “access rule” restricting a particular use of an Evennia entity.
|
||||
Whenever another entity wants that kind of access the lock will analyze that entity in different
|
||||
ways to determine if access should be granted or not. Evennia implements a “lockdown” philosophy -
|
||||
all entities are inaccessible unless you explicitly define a lock that allows some or full access.</p>
|
||||
ways to determine if access should be granted or not. Evennia implements a “lockdown” philosophy - all entities are inaccessible unless you explicitly define a lock that allows some or full access.</p>
|
||||
<p>Let’s take an example: An object has a lock on itself that restricts how people may “delete” that
|
||||
object. Apart from knowing that it restricts deletion, the lock also knows that only players with
|
||||
the specific ID of, say, <code class="docutils literal notranslate"><span class="pre">34</span></code> are allowed to delete it. So whenever a player tries to run <code class="docutils literal notranslate"><span class="pre">delete</span></code>
|
||||
on the object, the <code class="docutils literal notranslate"><span class="pre">delete</span></code> command makes sure to check if this player is really allowed to do so.
|
||||
It calls the lock, which in turn checks if the player’s id is <code class="docutils literal notranslate"><span class="pre">34</span></code>. Only then will it allow <code class="docutils literal notranslate"><span class="pre">delete</span></code>
|
||||
to go on with its job.</p>
|
||||
<section id="setting-and-checking-a-lock">
|
||||
<h2>Setting and checking a lock<a class="headerlink" href="#setting-and-checking-a-lock" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="working-with-locks">
|
||||
<h2>Working with locks<a class="headerlink" href="#working-with-locks" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The in-game command for setting locks on objects is <code class="docutils literal notranslate"><span class="pre">lock</span></code>:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > lock obj = <lockstring>
|
||||
</pre></div>
|
||||
|
|
@ -154,9 +153,8 @@ command:</p>
|
|||
<span class="k">return</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="defining-locks">
|
||||
<h2>Defining locks<a class="headerlink" href="#defining-locks" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Defining locks<a class="headerlink" href="#defining-locks" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Defining a lock (i.e. an access restriction) in Evennia is done by adding simple strings of lock
|
||||
definitions to the object’s <code class="docutils literal notranslate"><span class="pre">locks</span></code> property using <code class="docutils literal notranslate"><span class="pre">obj.locks.add()</span></code>.</p>
|
||||
<p>Here are some examples of lock strings (not including the quotes):</p>
|
||||
|
|
@ -181,6 +179,7 @@ the lockstring. The string below yields the same result as the previous example:
|
|||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>delete:id(34);edit:all();get: not attr(very_weak) or perm(Admin)
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="valid-access-types">
|
||||
<h3>Valid access_types<a class="headerlink" href="#valid-access-types" title="Permalink to this headline">¶</a></h3>
|
||||
<p>An <code class="docutils literal notranslate"><span class="pre">access_type</span></code>, the first part of a lockstring, defines what kind of capability a lock controls,
|
||||
|
|
@ -198,13 +197,8 @@ the default command set) actually checks for, as in the example of <code class="
|
|||
</li>
|
||||
<li><p><a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a>:</p>
|
||||
<ul>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">control</span></code> - who is the “owner” of the object. Can set locks, delete it etc. Defaults to the
|
||||
creator of the object.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">call</span></code> - who may call Object-commands stored on this Object except for the Object itself. By
|
||||
default, Objects share their Commands with anyone in the same location (e.g. so you can ‘press’ a
|
||||
<code class="docutils literal notranslate"><span class="pre">Button</span></code> object in the room). For Characters and Mobs (who likely only use those Commands for
|
||||
themselves and don’t want to share them) this should usually be turned off completely, using
|
||||
something like <code class="docutils literal notranslate"><span class="pre">call:false()</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">control</span></code> - who is the “owner” of the object. Can set locks, delete it etc. Defaults to the creator of the object.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">call</span></code> - who may call Object-commands stored on this Object except for the Object itself. By default, Objects share their Commands with anyone in the same location (e.g. so you can ‘press’ a <code class="docutils literal notranslate"><span class="pre">Button</span></code> object in the room). For Characters and Mobs (who likely only use those Commands for themselves and don’t want to share them) this should usually be turned off completely, using something like <code class="docutils literal notranslate"><span class="pre">call:false()</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">examine</span></code> - who may examine this object’s properties.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">delete</span></code> - who may delete the object.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">edit</span></code> - who may edit properties and attributes of the object.</p></li>
|
||||
|
|
@ -264,14 +258,11 @@ boot listeners etc.</p></li>
|
|||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p>So to take an example, whenever an exit is to be traversed, a lock of the type <em>traverse</em> will be
|
||||
checked. Defining a suitable lock type for an exit object would thus involve a lockstring <code class="docutils literal notranslate"><span class="pre">traverse:</span> <span class="pre"><lock</span> <span class="pre">functions></span></code>.</p>
|
||||
<p>So to take an example, whenever an exit is to be traversed, a lock of the type <em>traverse</em> will be checked. Defining a suitable lock type for an exit object would thus involve a lockstring <code class="docutils literal notranslate"><span class="pre">traverse:</span> <span class="pre"><lock</span> <span class="pre">functions></span></code>.</p>
|
||||
</section>
|
||||
<section id="custom-access-types">
|
||||
<h3>Custom access_types<a class="headerlink" href="#custom-access-types" title="Permalink to this headline">¶</a></h3>
|
||||
<p>As stated above, the <code class="docutils literal notranslate"><span class="pre">access_type</span></code> part of the lock is simply the ‘name’ or ‘type’ of the lock. The
|
||||
text is an arbitrary string that must be unique for an object. If adding a lock with the same
|
||||
<code class="docutils literal notranslate"><span class="pre">access_type</span></code> as one that already exists on the object, the new one override the old one.</p>
|
||||
<p>As stated above, the <code class="docutils literal notranslate"><span class="pre">access_type</span></code> part of the lock is simply the ‘name’ or ‘type’ of the lock. The text is an arbitrary string that must be unique for an object. If adding a lock with the same <code class="docutils literal notranslate"><span class="pre">access_type</span></code> as one that already exists on the object, the new one override the old one.</p>
|
||||
<p>For example, if you wanted to create a bulletin board system and wanted to restrict who can either
|
||||
read a board or post to a board. You could then define locks such as:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">obj</span><span class="o">.</span><span class="n">locks</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">"read:perm(Player);post:perm(Admin)"</span><span class="p">)</span>
|
||||
|
|
@ -290,7 +281,7 @@ trying to read the board):</p>
|
|||
</section>
|
||||
<section id="lock-functions">
|
||||
<h3>Lock functions<a class="headerlink" href="#lock-functions" title="Permalink to this headline">¶</a></h3>
|
||||
<p>A lock function is a normal Python function put in a place Evennia looks for such functions. The
|
||||
<p>A <em>lock function</em> is a normal Python function put in a place Evennia looks for such functions. The
|
||||
modules Evennia looks at is the list <code class="docutils literal notranslate"><span class="pre">settings.LOCK_FUNC_MODULES</span></code>. <em>All functions</em> in any of those
|
||||
modules will automatically be considered a valid lock function. The default ones are found in
|
||||
<code class="docutils literal notranslate"><span class="pre">evennia/locks/lockfuncs.py</span></code> and you can start adding your own in <code class="docutils literal notranslate"><span class="pre">mygame/server/conf/lockfuncs.py</span></code>.
|
||||
|
|
@ -352,9 +343,8 @@ permissions and dbrefs of <em>Accounts</em>, not on Characters.</p></li>
|
|||
setting set to a given value.</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
<section id="checking-simple-strings">
|
||||
<h2>Checking simple strings<a class="headerlink" href="#checking-simple-strings" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Checking simple strings<a class="headerlink" href="#checking-simple-strings" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Sometimes you don’t really need to look up a certain lock, you just want to check a lockstring. A
|
||||
common use is inside Commands, in order to check if a user has a certain permission. The lockhandler
|
||||
has a method <code class="docutils literal notranslate"><span class="pre">check_lockstring(accessing_obj,</span> <span class="pre">lockstring,</span> <span class="pre">bypass_superuser=False)</span></code> that allows this.</p>
|
||||
|
|
@ -364,11 +354,10 @@ has a method <code class="docutils literal notranslate"><span class="pre">check_
|
|||
<span class="k">return</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Note here that the <code class="docutils literal notranslate"><span class="pre">access_type</span></code> can be left to a dummy value since this method does not actually do
|
||||
a Lock lookup.</p>
|
||||
<p>Note here that the <code class="docutils literal notranslate"><span class="pre">access_type</span></code> can be left to a dummy value since this method does not actually do a Lock lookup.</p>
|
||||
</section>
|
||||
<section id="default-locks">
|
||||
<h2>Default locks<a class="headerlink" href="#default-locks" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Default locks<a class="headerlink" href="#default-locks" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Evennia sets up a few basic locks on all new objects and accounts (if we didn’t, noone would have
|
||||
any access to anything from the start). This is all defined in the root <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclasses</span></a>
|
||||
of the respective entity, in the hook method <code class="docutils literal notranslate"><span class="pre">basetype_setup()</span></code> (which you usually don’t want to
|
||||
|
|
@ -378,6 +367,7 @@ child object to change the default. Also creation commands like <code class="doc
|
|||
objects you create - for example it sets the <code class="docutils literal notranslate"><span class="pre">control</span></code> lock_type so as to allow you, its creator, to
|
||||
control and delete the object.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="more-lock-definition-examples">
|
||||
<h2>More Lock definition examples<a class="headerlink" href="#more-lock-definition-examples" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>examine: attr(eyesight, excellent) or perm(Builders)
|
||||
|
|
@ -414,9 +404,8 @@ would be be added as a lock string to the <code class="docutils literal notransl
|
|||
<p>This is how the <code class="docutils literal notranslate"><span class="pre">create</span></code> command sets up new objects. In sequence, this permission string sets the
|
||||
owner of this object be the creator (the one running <code class="docutils literal notranslate"><span class="pre">create</span></code>). Builders may examine the object
|
||||
whereas only Admins and the creator may delete it. Everyone can pick it up.</p>
|
||||
</section>
|
||||
<section id="a-complete-example-of-setting-locks-on-an-object">
|
||||
<h2>A complete example of setting locks on an object<a class="headerlink" href="#a-complete-example-of-setting-locks-on-an-object" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>A complete example of setting locks on an object<a class="headerlink" href="#a-complete-example-of-setting-locks-on-an-object" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Assume we have two objects - one is ourselves (not superuser) and the other is an <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Object</span></a>
|
||||
called <code class="docutils literal notranslate"><span class="pre">box</span></code>.</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > create/drop box
|
||||
|
|
@ -475,20 +464,11 @@ strength above 50 however and you’ll pick it up no problem. Done! A very heavy
|
|||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="on-djangos-permission-system">
|
||||
<h2>On Django’s permission system<a class="headerlink" href="#on-djangos-permission-system" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Django also implements a comprehensive permission/security system of its own. The reason we don’t
|
||||
use that is because it is app-centric (app in the Django sense). Its permission strings are of the
|
||||
form <code class="docutils literal notranslate"><span class="pre">appname.permstring</span></code> and it automatically adds three of them for each database model in the app</p>
|
||||
<ul class="simple">
|
||||
<li><p>for the app evennia/object this would be for example ‘object.create’, ‘object.admin’ and
|
||||
‘object.edit’. This makes a lot of sense for a web application, not so much for a MUD, especially
|
||||
when we try to hide away as much of the underlying architecture as possible.</p></li>
|
||||
</ul>
|
||||
<p>The django permissions are not completely gone however. We use it for validating passwords during
|
||||
login. It is also used exclusively for managing Evennia’s web-based admin site, which is a graphical
|
||||
front-end for the database of Evennia. You edit and assign such permissions directly from the web
|
||||
interface. It’s stand-alone from the permissions described above.</p>
|
||||
<p>Django also implements a comprehensive permission/security system of its own. The reason we don’t use that is because it is app-centric (app in the Django sense). Its permission strings are of the form <code class="docutils literal notranslate"><span class="pre">appname.permstring</span></code> and it automatically adds three of them for each database model in the app - for the app evennia/object this would be for example ‘object.create’, ‘object.admin’ and ‘object.edit’. This makes a lot of sense for a web application, not so much for a MUD, especially when we try to hide away as much of the underlying architecture as possible.</p>
|
||||
<p>The django permissions are not completely gone however. We use it for validating passwords during login. It is also used exclusively for managing Evennia’s web-based admin site, which is a graphical front-end for the database of Evennia. You edit and assign such permissions directly from the web interface. It’s stand-alone from the permissions described above.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
|
@ -508,10 +488,10 @@ interface. It’s stand-alone from the permissions described above.</p>
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Signals.html" title="Signals"
|
||||
<a href="Commands.html" title="Commands"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="TickerHandler.html" title="TickerHandler"
|
||||
<a href="Permissions.html" title="Permissions"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" >Core Components</a> »</li>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="TickerHandler" href="TickerHandler.html" />
|
||||
<link rel="prev" title="The Inline Function Parser" href="FuncParser.html" />
|
||||
<link rel="prev" title="FuncParser inline text parsing" href="FuncParser.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
|
|
@ -33,7 +33,7 @@
|
|||
<a href="TickerHandler.html" title="TickerHandler"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="FuncParser.html" title="The Inline Function Parser"
|
||||
<a href="FuncParser.html" title="FuncParser inline text parsing"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" accesskey="U">Core Components</a> »</li>
|
||||
|
|
@ -70,7 +70,7 @@
|
|||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="FuncParser.html"
|
||||
title="previous chapter">The Inline Function Parser</a></p>
|
||||
title="previous chapter">FuncParser inline text parsing</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="TickerHandler.html"
|
||||
title="next chapter">TickerHandler</a></p>
|
||||
|
|
@ -194,7 +194,7 @@ the monitor to remove:</p>
|
|||
<a href="TickerHandler.html" title="TickerHandler"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="FuncParser.html" title="The Inline Function Parser"
|
||||
<a href="FuncParser.html" title="FuncParser inline text parsing"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" >Core Components</a> »</li>
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@
|
|||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Msg</a><ul>
|
||||
<li><a class="reference internal" href="#msg-in-code">Msg in code</a><ul>
|
||||
<li><a class="reference internal" href="#working-with-msg">Working with Msg</a><ul>
|
||||
<li><a class="reference internal" href="#properties-on-msg">Properties on Msg</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
|
@ -110,13 +110,8 @@
|
|||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="msg">
|
||||
<h1>Msg<a class="headerlink" href="#msg" title="Permalink to this headline">¶</a></h1>
|
||||
<p>The <a class="reference internal" href="../api/evennia.comms.models.html#evennia.comms.models.Msg" title="evennia.comms.models.Msg"><span class="xref myst py py-class">Msg</span></a> object represents a database-saved
|
||||
piece of communication. Think of it as a discrete piece of email - it contains
|
||||
a message, some metadata and will always have a sender and one or more
|
||||
recipients.</p>
|
||||
<p>Once created, a Msg is normally not changed. It is persitently saved in the
|
||||
database. This allows for comprehensive logging of communications. Here are some
|
||||
good uses for <code class="docutils literal notranslate"><span class="pre">Msg</span></code> objects:</p>
|
||||
<p>The <a class="reference internal" href="../api/evennia.comms.models.html#evennia.comms.models.Msg" title="evennia.comms.models.Msg"><span class="xref myst py py-class">Msg</span></a> object represents a database-saved piece of communication. Think of it as a discrete piece of email - it contains a message, some metadata and will always have a sender and one or more recipients.</p>
|
||||
<p>Once created, a Msg is normally not changed. It is persitently saved in the database. This allows for comprehensive logging of communications. Here are some good uses for <code class="docutils literal notranslate"><span class="pre">Msg</span></code> objects:</p>
|
||||
<ul class="simple">
|
||||
<li><p>page/tells (the <code class="docutils literal notranslate"><span class="pre">page</span></code> command is how Evennia uses them out of the box)</p></li>
|
||||
<li><p>messages in a bulletin board</p></li>
|
||||
|
|
@ -133,13 +128,10 @@ actual in-game letter-object based on the Msg)</p>
|
|||
<div class="versionchanged">
|
||||
<p><span class="versionmodified changed">Changed in version 1.0: </span>Channels dropped Msg-support. Now only used in <code class="docutils literal notranslate"><span class="pre">page</span></code> command by default.</p>
|
||||
</div>
|
||||
<section id="msg-in-code">
|
||||
<h2>Msg in code<a class="headerlink" href="#msg-in-code" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The Msg is intended to be used exclusively in code, to build other game systems. It is <em>not</em>
|
||||
a <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclassed</span></a> entity, which means it cannot (easily) be overridden. It
|
||||
doesn’t support Attributes (but it <em>does</em> support <a class="reference internal" href="Tags.html"><span class="doc std std-doc">Tags</span></a>). It tries to be lean
|
||||
and small since a new one is created for every message.</p>
|
||||
<p>You create a new message with <code class="docutils literal notranslate"><span class="pre">evennia.create_message</span></code>:</p>
|
||||
<section id="working-with-msg">
|
||||
<h2>Working with Msg<a class="headerlink" href="#working-with-msg" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The Msg is intended to be used exclusively in code, to build other game systems. It is <em>not</em> a <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclassed</span></a> entity, which means it cannot (easily) be overridden. It doesn’t support Attributes (but it <em>does</em> support <a class="reference internal" href="Tags.html"><span class="doc std std-doc">Tags</span></a>). It tries to be lean and small since a new one is created for every message.
|
||||
You create a new message with <code class="docutils literal notranslate"><span class="pre">evennia.create_message</span></code>:</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_message</span>
|
||||
<span class="n">message</span> <span class="o">=</span> <span class="n">create_message</span><span class="p">(</span><span class="n">senders</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">receivers</span><span class="p">,</span>
|
||||
<span class="n">locks</span><span class="o">=...</span><span class="p">,</span> <span class="n">tags</span><span class="o">=...</span><span class="p">,</span> <span class="n">header</span><span class="o">=...</span><span class="p">)</span>
|
||||
|
|
@ -188,11 +180,7 @@ target.</p></li>
|
|||
</section>
|
||||
<section id="tempmsg">
|
||||
<h2>TempMsg<a class="headerlink" href="#tempmsg" title="Permalink to this headline">¶</a></h2>
|
||||
<p><a class="reference internal" href="../api/evennia.comms.models.html#evennia.comms.models.TempMsg" title="evennia.comms.models.TempMsg"><span class="xref myst py py-class">evennia.comms.models.TempMsg</span></a> is an object
|
||||
that implements the same API as the regular <code class="docutils literal notranslate"><span class="pre">Msg</span></code>, but which has no database
|
||||
component (and thus cannot be searched). It’s meant to plugged into systems
|
||||
expecting a <code class="docutils literal notranslate"><span class="pre">Msg</span></code> but where you just want to process the message without saving
|
||||
it.</p>
|
||||
<p><a class="reference internal" href="../api/evennia.comms.models.html#evennia.comms.models.TempMsg" title="evennia.comms.models.TempMsg"><span class="xref myst py py-class">evennia.comms.models.TempMsg</span></a> is an object that implements the same API as the regular <code class="docutils literal notranslate"><span class="pre">Msg</span></code>, but which has no database component (and thus cannot be searched). It’s meant to plugged into systems expecting a <code class="docutils literal notranslate"><span class="pre">Msg</span></code> but where you just want to process the message without saving it.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
|
|
|||
|
|
@ -63,15 +63,17 @@
|
|||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Objects</a><ul>
|
||||
<li><a class="reference internal" href="#how-to-create-your-own-object-types">How to create your own object types</a></li>
|
||||
<li><a class="reference internal" href="#adding-common-functionality">Adding common functionality</a></li>
|
||||
<li><a class="reference internal" href="#working-with-objects">Working with Objects</a><ul>
|
||||
<li><a class="reference internal" href="#properties-and-functions-on-objects">Properties and functions on Objects</a></li>
|
||||
<li><a class="reference internal" href="#subclasses-of-object">Subclasses of <code class="docutils literal notranslate"><span class="pre">Object</span></code></a><ul>
|
||||
<li><a class="reference internal" href="#characters">Characters</a></li>
|
||||
<li><a class="reference internal" href="#rooms">Rooms</a></li>
|
||||
<li><a class="reference internal" href="#exits">Exits</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#characters">Characters</a></li>
|
||||
<li><a class="reference internal" href="#rooms">Rooms</a></li>
|
||||
<li><a class="reference internal" href="#exits">Exits</a><ul>
|
||||
<li><a class="reference internal" href="#exit-details">Exit details</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#adding-common-functionality">Adding common functionality</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
@ -159,8 +161,8 @@ spend most time working with. Objects are <a class="reference internal" href="Ty
|
|||
<li><p><code class="docutils literal notranslate"><span class="pre">mygame.typeclasses.rooms.Room</span></code> (inherits from <code class="docutils literal notranslate"><span class="pre">DefaultRoom</span></code>)</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">mygame.typeclasses.exits.Exit</span></code> (inherits from <code class="docutils literal notranslate"><span class="pre">DefaultExit</span></code>)</p></li>
|
||||
</ul>
|
||||
<section id="how-to-create-your-own-object-types">
|
||||
<h2>How to create your own object types<a class="headerlink" href="#how-to-create-your-own-object-types" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="working-with-objects">
|
||||
<h2>Working with Objects<a class="headerlink" href="#working-with-objects" title="Permalink to this headline">¶</a></h2>
|
||||
<p>You can easily add your own in-game behavior by either modifying one of the typeclasses in your game dir or by inheriting from them.</p>
|
||||
<p>You can put your new typeclass directly in the relevant module, or you could organize your code in some other way. Here we assume we make a new module <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/flowers.py</span></code>:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># mygame/typeclasses/flowers.py</span>
|
||||
|
|
@ -178,13 +180,11 @@ spend most time working with. Objects are <a class="reference internal" href="Ty
|
|||
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">desc</span> <span class="o">=</span> <span class="s2">"This is a pretty rose with thorns."</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Now you just need to point to the class <em>Rose</em> with the <code class="docutils literal notranslate"><span class="pre">create</span></code> command
|
||||
to make a new rose:</p>
|
||||
<p>Now you just need to point to the class <em>Rose</em> with the <code class="docutils literal notranslate"><span class="pre">create</span></code> command to make a new rose:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> create/drop MyRose:flowers.Rose
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>What the <code class="docutils literal notranslate"><span class="pre">create</span></code> command actually <em>does</em> is to use the <a class="reference internal" href="../api/evennia.utils.create.html#evennia.utils.create.create_object" title="evennia.utils.create.create_object"><span class="xref myst py py-func">evennia.create_object</span></a>
|
||||
function. You can do the same thing yourself in code:</p>
|
||||
<p>What the <code class="docutils literal notranslate"><span class="pre">create</span></code> command actually <em>does</em> is to use the <a class="reference internal" href="../api/evennia.utils.create.html#evennia.utils.create.create_object" title="evennia.utils.create.create_object"><span class="xref myst py py-func">evennia.create_object</span></a> function. You can do the same thing yourself in code:</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">new_rose</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span><span class="s2">"typeclasses.flowers.Rose"</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">"MyRose"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
|
|
@ -195,29 +195,9 @@ powerful and should be used for all coded object creating (so this is what you u
|
|||
your own building commands).</p>
|
||||
<p>This particular Rose class doesn’t really do much, all it does it make sure the attribute
|
||||
<code class="docutils literal notranslate"><span class="pre">desc</span></code>(which is what the <code class="docutils literal notranslate"><span class="pre">look</span></code> command looks for) is pre-set, which is pretty pointless since you
|
||||
will usually want to change this at build time (using the <code class="docutils literal notranslate"><span class="pre">desc</span></code> command or using the
|
||||
<a class="reference internal" href="Prototypes.html"><span class="doc std std-doc">Spawner</span></a>).</p>
|
||||
</section>
|
||||
<section id="adding-common-functionality">
|
||||
<h2>Adding common functionality<a class="headerlink" href="#adding-common-functionality" title="Permalink to this headline">¶</a></h2>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">Object</span></code>, <code class="docutils literal notranslate"><span class="pre">Character</span></code>, <code class="docutils literal notranslate"><span class="pre">Room</span></code> and <code class="docutils literal notranslate"><span class="pre">Exit</span></code> also inherit from <code class="docutils literal notranslate"><span class="pre">mygame.typeclasses.objects.ObjectParent</span></code>.
|
||||
This is an empty ‘mixin’ class. Optionally, you can modify this class if you want to easily add some <em>common</em> functionality to all your Objects, Characters, Rooms and Exits at once. You can still customize each subclass separately (see the Python docs on <a class="reference external" href="https://docs.python.org/3/tutorial/classes.html#multiple-inheritance">multiple inheritance</a> for details).</p>
|
||||
<p>Here is an example:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/typeclasses/objects.py</span>
|
||||
<span class="c1"># ... </span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">evennia.objects.objects</span> <span class="kn">import</span> <span class="n">DefaultObject</span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">ObjectParent</span><span class="p">:</span>
|
||||
<span class="k">def</span> <span class="nf">at_pre_get</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">getter</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||||
<span class="c1"># make all entities by default un-pickable</span>
|
||||
<span class="k">return</span> <span class="kc">False</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Now all of <code class="docutils literal notranslate"><span class="pre">Object</span></code>, <code class="docutils literal notranslate"><span class="pre">Exit</span></code>. <code class="docutils literal notranslate"><span class="pre">Room</span></code> and <code class="docutils literal notranslate"><span class="pre">Character</span></code> default to not being able to be picked up using the <code class="docutils literal notranslate"><span class="pre">get</span></code> command.</p>
|
||||
</section>
|
||||
will usually want to change this at build time (using the <code class="docutils literal notranslate"><span class="pre">desc</span></code> command or using the <a class="reference internal" href="Prototypes.html"><span class="doc std std-doc">Spawner</span></a>).</p>
|
||||
<section id="properties-and-functions-on-objects">
|
||||
<h2>Properties and functions on Objects<a class="headerlink" href="#properties-and-functions-on-objects" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Properties and functions on Objects<a class="headerlink" href="#properties-and-functions-on-objects" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Beyond the properties assigned to all <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">typeclassed</span></a> objects (see that page for a list
|
||||
of those), the Object also has the following custom properties:</p>
|
||||
<ul class="simple">
|
||||
|
|
@ -250,21 +230,39 @@ of those), the Object also has the following custom properties:</p>
|
|||
</ul>
|
||||
<p>The Object Typeclass defines many more <em>hook methods</em> beyond <code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code>. Evennia calls these hooks at various points. When implementing your custom objects, you will inherit from the base parent and overload these hooks with your own custom code. See <code class="docutils literal notranslate"><span class="pre">evennia.objects.objects</span></code> for an updated list of all the available hooks or the <a class="reference internal" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultObject" title="evennia.objects.objects.DefaultObject"><span class="xref myst py py-class">API for DefaultObject here</span></a>.</p>
|
||||
</section>
|
||||
<section id="subclasses-of-object">
|
||||
<h2>Subclasses of <code class="docutils literal notranslate"><span class="pre">Object</span></code><a class="headerlink" href="#subclasses-of-object" title="Permalink to this headline">¶</a></h2>
|
||||
<p>There are three special subclasses of <em>Object</em> in default Evennia - <em>Characters</em>, <em>Rooms</em> and <em>Exits</em>. The reason they are separated is because these particular object types are fundamental, something you will always need and in some cases requires some extra attention in order to be recognized by the game engine (there is nothing stopping you from redefining them though). In practice they are all pretty similar to the base Object.</p>
|
||||
</section>
|
||||
<section id="characters">
|
||||
<h3>Characters<a class="headerlink" href="#characters" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Characters are objects controlled by <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a>. When a new Account logs in to Evennia for the first time, a new <code class="docutils literal notranslate"><span class="pre">Character</span></code> object is created and the Account object is assigned to the <code class="docutils literal notranslate"><span class="pre">account</span></code> attribute. A <code class="docutils literal notranslate"><span class="pre">Character</span></code> object must have a <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">Default Commandset</span></a> set on itself at creation, or the account will not be able to issue any commands! If you just inherit your own class from <code class="docutils literal notranslate"><span class="pre">evennia.DefaultCharacter</span></code> and make sure to use <code class="docutils literal notranslate"><span class="pre">super()</span></code> to call the parent methods you should be fine. In <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/characters.py</span></code> is an empty <code class="docutils literal notranslate"><span class="pre">Character</span></code> class ready for you to modify.</p>
|
||||
<h2>Characters<a class="headerlink" href="#characters" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The <a class="reference internal" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultCharacter" title="evennia.objects.objects.DefaultCharacter"><span class="xref myst py py-class">DefaultCharacters</span></a> is the root class for player in-game entities. They are usually <em>puppeted</em> by <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a>.</p>
|
||||
<p>When a new Account logs in to Evennia for the first time, a new <code class="docutils literal notranslate"><span class="pre">Character</span></code> object is created and the Account object is assigned to the <code class="docutils literal notranslate"><span class="pre">account</span></code> attribute (but Evennia supports <a class="reference internal" href="../Concepts/Connection-Styles.html"><span class="doc std std-doc">alternative connection-styles</span></a> if so desired).</p>
|
||||
<p>A <code class="docutils literal notranslate"><span class="pre">Character</span></code> object must have a <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">Default Commandset</span></a> set on itself at creation, or the account will not be able to issue any commands!</p>
|
||||
<p>If you want to change the default character created by the default commands, you can change it in settings:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>BASE_CHARACTER_TYPECLASS = "typeclasses.characters.Character"
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This deafult points at the empty class in <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/characters.py</span></code> , ready for you to modify as you please.</p>
|
||||
</section>
|
||||
<section id="rooms">
|
||||
<h3>Rooms<a class="headerlink" href="#rooms" title="Permalink to this headline">¶</a></h3>
|
||||
<p><em>Rooms</em> are the root containers of all other objects. The only thing really separating a room from any other object is that they have no <code class="docutils literal notranslate"><span class="pre">location</span></code> of their own and that default commands like <code class="docutils literal notranslate"><span class="pre">@dig</span></code> creates objects of this class - so if you want to expand your rooms with more functionality, just inherit from <code class="docutils literal notranslate"><span class="pre">ev.DefaultRoom</span></code>. In <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/rooms.py</span></code> is an empty <code class="docutils literal notranslate"><span class="pre">Room</span></code> class ready for you to modify.</p>
|
||||
<h2>Rooms<a class="headerlink" href="#rooms" title="Permalink to this headline">¶</a></h2>
|
||||
<p><a class="reference internal" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultRoom" title="evennia.objects.objects.DefaultRoom"><span class="xref myst py py-class">Rooms</span></a> are the root containers of all other objects.</p>
|
||||
<p>The only thing really separating a room from any other object is that they have no <code class="docutils literal notranslate"><span class="pre">location</span></code> of their own and that default commands like <code class="docutils literal notranslate"><span class="pre">dig</span></code> creates objects of this class - so if you want to expand your rooms with more functionality, just inherit from <code class="docutils literal notranslate"><span class="pre">evennia.DefaultRoom</span></code>.</p>
|
||||
<p>To change the default room created by <code class="docutils literal notranslate"><span class="pre">dig</span></code>, <code class="docutils literal notranslate"><span class="pre">tunnel</span></code> and other commands, change it in settings:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>BASE_ROOM_TYPECLASS = "typeclases.rooms.Room"
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The empty class in <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/rooms.py</span></code> is a good place to start!</p>
|
||||
</section>
|
||||
<section id="exits">
|
||||
<h3>Exits<a class="headerlink" href="#exits" title="Permalink to this headline">¶</a></h3>
|
||||
<h2>Exits<a class="headerlink" href="#exits" title="Permalink to this headline">¶</a></h2>
|
||||
<p><em>Exits</em> are objects connecting other objects (usually <em>Rooms</em>) together. An object named <em>North</em> or <em>in</em> might be an exit, as well as <em>door</em>, <em>portal</em> or <em>jump out the window</em>. An exit has two things that separate them from other objects. Firstly, their <em>destination</em> property is set and points to a valid object. This fact makes it easy and fast to locate exits in the database. Secondly, exits define a special <a class="reference internal" href="Commands.html"><span class="doc std std-doc">Transit Command</span></a> on themselves when they are created. This command is named the same as the exit object and will, when called, handle the practicalities of moving the character to the Exits’s <em>destination</em> - this allows you to just enter the name of the exit on its own to move around, just as you would expect.</p>
|
||||
<p>The exit functionality is all defined on the Exit typeclass, so you could in principle completely change how exits work in your game (it’s not recommended though, unless you really know what you are doing). Exits are <a class="reference internal" href="Locks.html"><span class="doc std std-doc">locked</span></a> using an access_type called <em>traverse</em> and also make use of a few hook methods for giving feedback if the traversal fails. See <code class="docutils literal notranslate"><span class="pre">evennia.DefaultExit</span></code> for more info. In <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/exits.py</span></code> there is an empty <code class="docutils literal notranslate"><span class="pre">Exit</span></code> class for you to modify.</p>
|
||||
<p>The exit functionality is all defined on the Exit typeclass, so you could in principle completely change how exits work in your game (it’s not recommended though, unless you really know what you are doing). Exits are <a class="reference internal" href="Locks.html"><span class="doc std std-doc">locked</span></a> using an access_type called <em>traverse</em> and also make use of a few hook methods for giving feedback if the traversal fails. See <code class="docutils literal notranslate"><span class="pre">evennia.DefaultExit</span></code> for more info.</p>
|
||||
<p>Exits are normally overridden on a case-by-case basis, but if you want to change the default exit createad by rooms like <code class="docutils literal notranslate"><span class="pre">dig</span></code> , <code class="docutils literal notranslate"><span class="pre">tunnel</span></code> or <code class="docutils literal notranslate"><span class="pre">open</span></code> you can change it in settings:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>BASE_EXIT_TYPECLASS = "typeclasses.exits.Exit"
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>In <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/exits.py</span></code> there is an empty <code class="docutils literal notranslate"><span class="pre">Exit</span></code> class for you to modify.</p>
|
||||
<section id="exit-details">
|
||||
<h3>Exit details<a class="headerlink" href="#exit-details" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The process of traversing an exit is as follows:</p>
|
||||
<ol class="simple">
|
||||
<li><p>The traversing <code class="docutils literal notranslate"><span class="pre">obj</span></code> sends a command that matches the Exit-command name on the Exit object. The <a class="reference internal" href="Commands.html"><span class="doc std std-doc">cmdhandler</span></a> detects this and triggers the command defined on the Exit. Traversal always involves the “source” (the current location) and the <code class="docutils literal notranslate"><span class="pre">destination</span></code> (this is stored on the Exit object).</p></li>
|
||||
|
|
@ -286,6 +284,24 @@ of those), the Object also has the following custom properties:</p>
|
|||
<p>If the move fails for whatever reason, the Exit will look for an Attribute <code class="docutils literal notranslate"><span class="pre">err_traverse</span></code> on itself and display this as an error message. If this is not found, the Exit will instead call <code class="docutils literal notranslate"><span class="pre">at_failed_traverse(obj)</span></code> on itself.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="adding-common-functionality">
|
||||
<h2>Adding common functionality<a class="headerlink" href="#adding-common-functionality" title="Permalink to this headline">¶</a></h2>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">Object</span></code>, <code class="docutils literal notranslate"><span class="pre">Character</span></code>, <code class="docutils literal notranslate"><span class="pre">Room</span></code> and <code class="docutils literal notranslate"><span class="pre">Exit</span></code> also inherit from <code class="docutils literal notranslate"><span class="pre">mygame.typeclasses.objects.ObjectParent</span></code>.
|
||||
This is an empty ‘mixin’ class. Optionally, you can modify this class if you want to easily add some <em>common</em> functionality to all your Objects, Characters, Rooms and Exits at once. You can still customize each subclass separately (see the Python docs on <a class="reference external" href="https://docs.python.org/3/tutorial/classes.html#multiple-inheritance">multiple inheritance</a> for details).</p>
|
||||
<p>Here is an example:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/typeclasses/objects.py</span>
|
||||
<span class="c1"># ... </span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">evennia.objects.objects</span> <span class="kn">import</span> <span class="n">DefaultObject</span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">ObjectParent</span><span class="p">:</span>
|
||||
<span class="k">def</span> <span class="nf">at_pre_get</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">getter</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||||
<span class="c1"># make all entities by default un-pickable</span>
|
||||
<span class="k">return</span> <span class="kc">False</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Now all of <code class="docutils literal notranslate"><span class="pre">Object</span></code>, <code class="docutils literal notranslate"><span class="pre">Exit</span></code>. <code class="docutils literal notranslate"><span class="pre">Room</span></code> and <code class="docutils literal notranslate"><span class="pre">Character</span></code> default to not being able to be picked up using the <code class="docutils literal notranslate"><span class="pre">get</span></code> command.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<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="Portal And Server" href="Portal-And-Server.html" />
|
||||
<link rel="next" title="Locks" href="Locks.html" />
|
||||
<link rel="prev" title="Help System" href="Help-System.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Portal-And-Server.html" title="Portal And Server"
|
||||
<a href="Locks.html" title="Locks"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Help-System.html" title="Help System"
|
||||
|
|
@ -64,15 +64,14 @@
|
|||
<ul>
|
||||
<li><a class="reference internal" href="#">Permissions</a><ul>
|
||||
<li><a class="reference internal" href="#the-super-user">The super user</a></li>
|
||||
<li><a class="reference internal" href="#managing-permissions">Managing Permissions</a></li>
|
||||
<li><a class="reference internal" href="#working-with-permissions">Working with Permissions</a><ul>
|
||||
<li><a class="reference internal" href="#the-permission-hierarchy">The permission hierarchy</a></li>
|
||||
<li><a class="reference internal" href="#checking-permissions">Checking permissions</a><ul>
|
||||
<li><a class="reference internal" href="#checking-permissions">Checking permissions</a></li>
|
||||
<li><a class="reference internal" href="#checking-with-obj-permissions-check">Checking with obj.permissions.check()</a></li>
|
||||
<li><a class="reference internal" href="#lock-funcs">Lock funcs</a></li>
|
||||
<li><a class="reference internal" href="#some-examples">Some examples</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#superusers">Superusers</a></li>
|
||||
<li><a class="reference internal" href="#quelling">Quelling</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
|
@ -82,8 +81,8 @@
|
|||
<p class="topless"><a href="Help-System.html"
|
||||
title="previous chapter">Help System</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Portal-And-Server.html"
|
||||
title="next chapter">Portal And Server</a></p>
|
||||
<p class="topless"><a href="Locks.html"
|
||||
title="next chapter">Locks</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
|
|
@ -129,8 +128,8 @@ entirely.</p>
|
|||
test the game’s locks and restrictions with (see <code class="docutils literal notranslate"><span class="pre">quell</span></code> below). Usually there is no need to have
|
||||
but one superuser.</p>
|
||||
</section>
|
||||
<section id="managing-permissions">
|
||||
<h2>Managing Permissions<a class="headerlink" href="#managing-permissions" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="working-with-permissions">
|
||||
<h2>Working with Permissions<a class="headerlink" href="#working-with-permissions" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In-game, you use the <code class="docutils literal notranslate"><span class="pre">perm</span></code> command to add and remove permissions</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > perm/account Tommy = Builders
|
||||
> perm/account/del Tommy = Builders
|
||||
|
|
@ -156,9 +155,8 @@ typeclassed entities as the property <code class="docutils literal notranslate">
|
|||
<span class="n">obj</span><span class="o">.</span><span class="n">permissions</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s2">"Blacksmith"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="the-permission-hierarchy">
|
||||
<h2>The permission hierarchy<a class="headerlink" href="#the-permission-hierarchy" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>The permission hierarchy<a class="headerlink" href="#the-permission-hierarchy" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Selected permission strings can be organized in a <em>permission hierarchy</em> by editing the tuple
|
||||
<code class="docutils literal notranslate"><span class="pre">settings.PERMISSION_HIERARCHY</span></code>. Evennia’s default permission hierarchy is as follows
|
||||
(in increasing order of power):</p>
|
||||
|
|
@ -176,8 +174,9 @@ typeclassed entities as the property <code class="docutils literal notranslate">
|
|||
<p>When checking a hierarchical permission (using one of the methods to follow), you will pass checks for your level and all <em>below</em> you. That is, even if the check explicitly checks for “Builder” level access, you will actually pass if you have one of “Builder”, “Admin” or “Developer”. By contrast, if you check for a non-hierarchical permission, like “Blacksmith” you <em>must</em> have exactly that permission to pass.</p>
|
||||
</section>
|
||||
<section id="checking-permissions">
|
||||
<h2>Checking permissions<a class="headerlink" href="#checking-permissions" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Checking permissions<a class="headerlink" href="#checking-permissions" title="Permalink to this headline">¶</a></h3>
|
||||
<p>It’s important to note that you check for the permission of a <em>puppeted</em> <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Object</span></a> (like a Character), the check will always first use the permissions of any <code class="docutils literal notranslate"><span class="pre">Account</span></code> connected to that Object before checking for permissions on the Object. In the case of hierarchical permissions (Admins, Builders etc), the Account permission will always be used (this stops an Account from escalating their permission by puppeting a high-level Character). If the permission looked for is not in the hierarchy, an exact match is required, first on the Account and if not found there (or if no Account is connected), then on the Object itself.</p>
|
||||
</section>
|
||||
<section id="checking-with-obj-permissions-check">
|
||||
<h3>Checking with obj.permissions.check()<a class="headerlink" href="#checking-with-obj-permissions-check" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The simplest way to check if an entity has a permission is to check its <em>PermissionHandler</em>, stored as <code class="docutils literal notranslate"><span class="pre">.permissions</span></code> on all typeclassed entities.</p>
|
||||
|
|
@ -268,17 +267,6 @@ objects (regardless of hierarchical perm or not).</p></li>
|
|||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="superusers">
|
||||
<h2>Superusers<a class="headerlink" href="#superusers" title="Permalink to this headline">¶</a></h2>
|
||||
<p>There is normally only one <em>superuser</em> account and that is the one first created
|
||||
when starting Evennia (User #1). This is sometimes known as the “Owner” or “God”
|
||||
user. A superuser has more than full access - it completely <em>bypasses</em> all
|
||||
locks and will always pass the <code class="docutils literal notranslate"><span class="pre">PermissionHandler.check()</span></code> check. This allows
|
||||
for the superuser to always have access to everything in an emergency. But it
|
||||
could also hide any eventual errors you might have made in your lock definitions. So
|
||||
when trying out game systems you should either use quelling (see below) or make
|
||||
a second Developer-level character that does not bypass such checks.</p>
|
||||
</section>
|
||||
<section id="quelling">
|
||||
<h2>Quelling<a class="headerlink" href="#quelling" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">quell</span></code> command can be used to enforce the <code class="docutils literal notranslate"><span class="pre">perm()</span></code> lockfunc to ignore
|
||||
|
|
@ -308,7 +296,7 @@ affectable by locks.</p>
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Portal-And-Server.html" title="Portal And Server"
|
||||
<a href="Locks.html" title="Locks"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Help-System.html" title="Help System"
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
<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="Commands" href="Commands.html" />
|
||||
<link rel="prev" title="Permissions" href="Permissions.html" />
|
||||
<link rel="next" title="Sessions" href="Sessions.html" />
|
||||
<link rel="prev" title="Core Components" href="Components-Overview.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
|
|
@ -30,10 +30,10 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Commands.html" title="Commands"
|
||||
<a href="Sessions.html" title="Sessions"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Permissions.html" title="Permissions"
|
||||
<a href="Components-Overview.html" title="Core Components"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" accesskey="U">Core Components</a> »</li>
|
||||
|
|
@ -61,11 +61,11 @@
|
|||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Permissions.html"
|
||||
title="previous chapter">Permissions</a></p>
|
||||
<p class="topless"><a href="Components-Overview.html"
|
||||
title="previous chapter">Core Components</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Commands.html"
|
||||
title="next chapter">Commands</a></p>
|
||||
<p class="topless"><a href="Sessions.html"
|
||||
title="next chapter">Sessions</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
|
|
@ -98,11 +98,6 @@
|
|||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="portal-and-server">
|
||||
<h1>Portal And Server<a class="headerlink" href="#portal-and-server" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Evennia consists of two processes, known as <em>Portal</em> and <em>Server</em>. They can be controlled from
|
||||
inside the game or from the command line as described <a class="reference internal" href="../Setup/Running-Evennia.html"><span class="doc std std-doc">in the Running-Evennia doc</span></a>.</p>
|
||||
<p>In short, the Portal knows everything about internet protocols (telnet, websockets etc), but knows very little about the game.</p>
|
||||
<p>In contrast, the Server knows everything about the game. It knows that a player has connected but now <em>how</em> they connected.</p>
|
||||
<p>The effect of this is that you can fully <code class="docutils literal notranslate"><span class="pre">reload</span></code> the Server and have players still connected to the game. One the server comes back up, it will re-connect to the Portal and re-sync all players as if nothing happened.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>Internet│ ┌──────────┐ ┌─┐ ┌─┐ ┌─────────┐
|
||||
│ │Portal │ │S│ ┌───┐ │S│ │Server │
|
||||
P │ │ │ │e│ │AMP│ │e│ │ │
|
||||
|
|
@ -116,7 +111,14 @@ inside the game or from the command line as described <a class="reference intern
|
|||
│Evennia
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The Server and Portal are glued together via an AMP (Asynchronous Messaging Protocol) connection. This allows the two programs to communicate seamlessly on the same machine.</p>
|
||||
<p>The <em>Portal</em> and <em>Server</em> consitutes the two main halves of Evennia.</p>
|
||||
<p>These are two separate <code class="docutils literal notranslate"><span class="pre">twistd</span></code> processes and can be controlled from inside the game or from the command line as described <a class="reference internal" href="../Setup/Running-Evennia.html"><span class="doc std std-doc">in the Running-Evennia doc</span></a>.</p>
|
||||
<ul class="simple">
|
||||
<li><p>The Portal knows everything about internet protocols (telnet, websockets etc), but knows very little about the game.</p></li>
|
||||
<li><p>The Server knows everything about the game. It knows that a player has connected but now <em>how</em> they connected.</p></li>
|
||||
</ul>
|
||||
<p>The effect of this is that you can fully <code class="docutils literal notranslate"><span class="pre">reload</span></code> the Server and have players still connected to the game. One the server comes back up, it will re-connect to the Portal and re-sync all players as if nothing happened.</p>
|
||||
<p>The Portal and Server are intended to always run on the same machine. They are glued together via an AMP (Asynchronous Messaging Protocol) connection. This allows the two programs to communicate seamlessly.</p>
|
||||
</section>
|
||||
|
||||
|
||||
|
|
@ -135,10 +137,10 @@ inside the game or from the command line as described <a class="reference intern
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Commands.html" title="Commands"
|
||||
<a href="Sessions.html" title="Sessions"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Permissions.html" title="Permissions"
|
||||
<a href="Components-Overview.html" title="Core Components"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" >Core Components</a> »</li>
|
||||
|
|
|
|||
|
|
@ -63,8 +63,9 @@
|
|||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Spawner and Prototypes</a><ul>
|
||||
<li><a class="reference internal" href="#working-with-prototypes">Working with Prototypes</a><ul>
|
||||
<li><a class="reference internal" href="#using-the-olc">Using the OLC</a></li>
|
||||
<li><a class="reference internal" href="#the-prototype">The prototype</a><ul>
|
||||
<li><a class="reference internal" href="#the-prototype">The prototype</a></li>
|
||||
<li><a class="reference internal" href="#prototype-keys">Prototype keys</a><ul>
|
||||
<li><a class="reference internal" href="#more-on-prototype-inheritance">More on prototype inheritance</a></li>
|
||||
</ul>
|
||||
|
|
@ -75,13 +76,12 @@
|
|||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#storing-prototypes">Storing prototypes</a><ul>
|
||||
<li><a class="reference internal" href="#database-prototypes">Database prototypes</a></li>
|
||||
<li><a class="reference internal" href="#module-based-prototypes">Module-based prototypes</a></li>
|
||||
<li><a class="reference internal" href="#spawning">Spawning</a><ul>
|
||||
<li><a class="reference internal" href="#using-evennia-prototypes-spawner">Using evennia.prototypes.spawner()</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#using-spawn">Using @spawn</a></li>
|
||||
<li><a class="reference internal" href="#using-evennia-prototypes-spawner">Using evennia.prototypes.spawner()</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
@ -124,47 +124,30 @@
|
|||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="spawner-and-prototypes">
|
||||
<h1>Spawner and Prototypes<a class="headerlink" href="#spawner-and-prototypes" title="Permalink to this headline">¶</a></h1>
|
||||
<p>The <em>spawner</em> is a system for defining and creating individual objects from a base template called a
|
||||
<em>prototype</em>. It is only designed for use with in-game <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a>, not any other type of
|
||||
entity.</p>
|
||||
<p>The normal way to create a custom object in Evennia is to make a <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclass</span></a>. If you
|
||||
haven’t read up on Typeclasses yet, think of them as normal Python classes that save to the database
|
||||
behind the scenes. Say you wanted to create a “Goblin” enemy. A common way to do this would be to
|
||||
first create a <code class="docutils literal notranslate"><span class="pre">Mobile</span></code> typeclass that holds everything common to mobiles in the game, like generic
|
||||
AI, combat code and various movement methods. A <code class="docutils literal notranslate"><span class="pre">Goblin</span></code> subclass is then made to inherit from
|
||||
<code class="docutils literal notranslate"><span class="pre">Mobile</span></code>. The <code class="docutils literal notranslate"><span class="pre">Goblin</span></code> class adds stuff unique to goblins, like group-based AI (because goblins are
|
||||
smarter in a group), the ability to panic, dig for gold etc.</p>
|
||||
<p>But now it’s time to actually start to create some goblins and put them in the world. What if we
|
||||
wanted those goblins to not all look the same? Maybe we want grey-skinned and green-skinned goblins
|
||||
or some goblins that can cast spells or which wield different weapons? We <em>could</em> make subclasses of
|
||||
<code class="docutils literal notranslate"><span class="pre">Goblin</span></code>, like <code class="docutils literal notranslate"><span class="pre">GreySkinnedGoblin</span></code> and <code class="docutils literal notranslate"><span class="pre">GoblinWieldingClub</span></code>. But that seems a bit excessive (and a
|
||||
lot of Python code for every little thing). Using classes can also become impractical when wanting
|
||||
to combine them - what if we want a grey-skinned goblin shaman wielding a spear - setting up a web
|
||||
of classes inheriting each other with multiple inheritance can be tricky.</p>
|
||||
<p>This is what the <em>prototype</em> is for. It is a Python dictionary that describes these per-instance
|
||||
changes to an object. The prototype also has the advantage of allowing an in-game builder to
|
||||
customize an object without access to the Python backend. Evennia also allows for saving and
|
||||
searching prototypes so other builders can find and use (and tweak) them later. Having a library of
|
||||
interesting prototypes is a good reasource for builders. The OLC system allows for creating, saving,
|
||||
loading and manipulating prototypes using a menu system.</p>
|
||||
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>> spawn goblin
|
||||
|
||||
Spawned Goblin Grunt<span class="o">(</span><span class="c1">#45)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The <em>spawner</em> is a system for defining and creating individual objects from a base template called a <em>prototype</em>. It is only designed for use with in-game <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a>, not any other type of entity.</p>
|
||||
<p>The normal way to create a custom object in Evennia is to make a <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclass</span></a>. If you haven’t read up on Typeclasses yet, think of them as normal Python classes that save to the database behind the scenes. Say you wanted to create a “Goblin” enemy. A common way to do this would be to first create a <code class="docutils literal notranslate"><span class="pre">Mobile</span></code> typeclass that holds everything common to mobiles in the game, like generic AI, combat code and various movement methods. A <code class="docutils literal notranslate"><span class="pre">Goblin</span></code> subclass is then made to inherit from <code class="docutils literal notranslate"><span class="pre">Mobile</span></code>. The <code class="docutils literal notranslate"><span class="pre">Goblin</span></code> class adds stuff unique to goblins, like group-based AI (because goblins are smarter in a group), the ability to panic, dig for gold etc.</p>
|
||||
<p>But now it’s time to actually start to create some goblins and put them in the world. What if we wanted those goblins to not all look the same? Maybe we want grey-skinned and green-skinned goblins or some goblins that can cast spells or which wield different weapons? We <em>could</em> make subclasses of <code class="docutils literal notranslate"><span class="pre">Goblin</span></code>, like <code class="docutils literal notranslate"><span class="pre">GreySkinnedGoblin</span></code> and <code class="docutils literal notranslate"><span class="pre">GoblinWieldingClub</span></code>. But that seems a bit excessive (and a lot of Python code for every little thing). Using classes can also become impractical when wanting to combine them - what if we want a grey-skinned goblin shaman wielding a spear - setting up a web of classes inheriting each other with multiple inheritance can be tricky.</p>
|
||||
<p>This is what the <em>prototype</em> is for. It is a Python dictionary that describes these per-instance changes to an object. The prototype also has the advantage of allowing an in-game builder to customize an object without access to the Python backend. Evennia also allows for saving and searching prototypes so other builders can find and use (and tweak) them later. Having a library of interesting prototypes is a good reasource for builders. The OLC system allows for creating, saving, loading and manipulating prototypes using a menu system.</p>
|
||||
<p>The <em>spawner</em> takes a prototype and uses it to create (spawn) new, custom objects.</p>
|
||||
<section id="working-with-prototypes">
|
||||
<h2>Working with Prototypes<a class="headerlink" href="#working-with-prototypes" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="using-the-olc">
|
||||
<h2>Using the OLC<a class="headerlink" href="#using-the-olc" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Enter the <code class="docutils literal notranslate"><span class="pre">olc</span></code> command or <code class="docutils literal notranslate"><span class="pre">@spawn/olc</span></code> to enter the prototype wizard. This is a menu system for
|
||||
<h3>Using the OLC<a class="headerlink" href="#using-the-olc" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Enter the <code class="docutils literal notranslate"><span class="pre">olc</span></code> command or <code class="docutils literal notranslate"><span class="pre">spawn/olc</span></code> to enter the prototype wizard. This is a menu system for
|
||||
creating, loading, saving and manipulating prototypes. It’s intended to be used by in-game builders
|
||||
and will give a better understanding of prototypes in general. Use <code class="docutils literal notranslate"><span class="pre">help</span></code> on each node of the menu
|
||||
for more information. Below are further details about how prototypes work and how they are used.</p>
|
||||
</section>
|
||||
<section id="the-prototype">
|
||||
<h2>The prototype<a class="headerlink" href="#the-prototype" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The prototype dictionary can either be created for you by the OLC (see above), be written manually
|
||||
in a Python module (and then referenced by the <code class="docutils literal notranslate"><span class="pre">@spawn</span></code> command/OLC), or created on-the-fly and
|
||||
manually loaded into the spawner function or <code class="docutils literal notranslate"><span class="pre">@spawn</span></code> command.</p>
|
||||
<p>The dictionary defines all possible database-properties of an Object. It has a fixed set of allowed
|
||||
keys. When preparing to store the prototype in the database (or when using the OLC), some
|
||||
of these keys are mandatory. When just passing a one-time prototype-dict to the spawner the system
|
||||
is
|
||||
more lenient and will use defaults for keys not explicitly provided.</p>
|
||||
<h3>The prototype<a class="headerlink" href="#the-prototype" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The prototype dictionary can either be created for you by the OLC (see above), be written manually in a Python module (and then referenced by the <code class="docutils literal notranslate"><span class="pre">spawn</span></code> command/OLC), or created on-the-fly and
|
||||
manually loaded into the spawner function or <code class="docutils literal notranslate"><span class="pre">spawn</span></code> command.</p>
|
||||
<p>The dictionary defines all possible database-properties of an Object. It has a fixed set of allowed keys. When preparing to store the prototype in the database (or when using the OLC), some of these keys are mandatory. When just passing a one-time prototype-dict to the spawner the system is more lenient and will use defaults for keys not explicitly provided.</p>
|
||||
<p>In dictionary form, a prototype can look something like this:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="p">{</span>
|
||||
<span class="s2">"prototype_key"</span><span class="p">:</span> <span class="s2">"house"</span>
|
||||
|
|
@ -174,18 +157,13 @@ more lenient and will use defaults for keys not explicitly provided.</p>
|
|||
</pre></div>
|
||||
</div>
|
||||
<p>If you wanted to load it into the spawner in-game you could just put all on one line:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>@spawn {"prototype_key="house", "key": "Large house", ...}
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>spawn {"prototype_key="house", "key": "Large house", ...}
|
||||
</pre></div>
|
||||
</div>
|
||||
<blockquote>
|
||||
<div><p>Note that the prototype dict as given on the command line must be a valid Python structure -
|
||||
so you need to put quotes around strings etc. For security reasons, a dict inserted from-in game
|
||||
cannot have any
|
||||
other advanced Python functionality, such as executable code, <code class="docutils literal notranslate"><span class="pre">lambda</span></code> etc. If builders are supposed
|
||||
to be able to use such features, you need to offer them through [$protfuncs](Spawner-and-
|
||||
Prototypes#protfuncs), embedded runnable functions that you have full control to check and vet
|
||||
before running.</p>
|
||||
<div><p>Note that the prototype dict as given on the command line must be a valid Python structure - so you need to put quotes around strings etc. For security reasons, a dict inserted from-in game cannot have any other advanced Python functionality, such as executable code, <code class="docutils literal notranslate"><span class="pre">lambda</span></code> etc. If builders are supposed to be able to use such features, you need to offer them through [$protfuncs](Spawner-and- Prototypes#protfuncs), embedded runnable functions that you have full control to check and vet before running.</p>
|
||||
</div></blockquote>
|
||||
</section>
|
||||
<section id="prototype-keys">
|
||||
<h3>Prototype keys<a class="headerlink" href="#prototype-keys" title="Permalink to this headline">¶</a></h3>
|
||||
<p>All keys starting with <code class="docutils literal notranslate"><span class="pre">prototype_</span></code> are for book keeping.</p>
|
||||
|
|
@ -200,53 +178,31 @@ left-right inheritance. If this is not given, a <code class="docutils literal no
|
|||
<li><p><code class="docutils literal notranslate"><span class="pre">prototype_desc</span></code> - this is optional and used when listing the prototype in in-game listings.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">protototype_tags</span></code> - this is optional and allows for tagging the prototype in order to find it
|
||||
easier later.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">prototype_locks</span></code> - two lock types are supported: <code class="docutils literal notranslate"><span class="pre">edit</span></code> and <code class="docutils literal notranslate"><span class="pre">spawn</span></code>. The first lock restricts
|
||||
the copying and editing of the prototype when loaded through the OLC. The second determines who
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">prototype_locks</span></code> - two lock types are supported: <code class="docutils literal notranslate"><span class="pre">edit</span></code> and <code class="docutils literal notranslate"><span class="pre">spawn</span></code>. The first lock restricts the copying and editing of the prototype when loaded through the OLC. The second determines who
|
||||
may use the prototype to create new objects.</p></li>
|
||||
</ul>
|
||||
<p>The remaining keys determine actual aspects of the objects to spawn from this prototype:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">key</span></code> - the main object identifier. Defaults to “Spawned Object <em>X</em>”, where <em>X</em> is a random
|
||||
integer.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">typeclass</span></code> - A full python-path (from your gamedir) to the typeclass you want to use. If not
|
||||
set, the <code class="docutils literal notranslate"><span class="pre">prototype_parent</span></code> should be
|
||||
defined, with <code class="docutils literal notranslate"><span class="pre">typeclass</span></code> defined somewhere in the parent chain. When creating a one-time
|
||||
prototype
|
||||
dict just for spawning, one could omit this - <code class="docutils literal notranslate"><span class="pre">settings.BASE_OBJECT_TYPECLASS</span></code> will be used
|
||||
instead.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">key</span></code> - the main object identifier. Defaults to “Spawned Object <em>X</em>”, where <em>X</em> is a random integer.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">typeclass</span></code> - A full python-path (from your gamedir) to the typeclass you want to use. If not set, the <code class="docutils literal notranslate"><span class="pre">prototype_parent</span></code> should be defined, with <code class="docutils literal notranslate"><span class="pre">typeclass</span></code> defined somewhere in the parent chain. When creating a one-time prototype dict just for spawning, one could omit this - <code class="docutils literal notranslate"><span class="pre">settings.BASE_OBJECT_TYPECLASS</span></code> will be used instead.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">location</span></code> - this should be a <code class="docutils literal notranslate"><span class="pre">#dbref</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">home</span></code> - a valid <code class="docutils literal notranslate"><span class="pre">#dbref</span></code>. Defaults to <code class="docutils literal notranslate"><span class="pre">location</span></code> or <code class="docutils literal notranslate"><span class="pre">settings.DEFAULT_HOME</span></code> if location does not
|
||||
exist.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">home</span></code> - a valid <code class="docutils literal notranslate"><span class="pre">#dbref</span></code>. Defaults to <code class="docutils literal notranslate"><span class="pre">location</span></code> or <code class="docutils literal notranslate"><span class="pre">settings.DEFAULT_HOME</span></code> if location does not exist.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">destination</span></code> - a valid <code class="docutils literal notranslate"><span class="pre">#dbref</span></code>. Only used by exits.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">permissions</span></code> - list of permission strings, like <code class="docutils literal notranslate"><span class="pre">["Accounts",</span> <span class="pre">"may_use_red_door"]</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">locks</span></code> - a <a class="reference internal" href="Locks.html"><span class="doc std std-doc">lock-string</span></a> like <code class="docutils literal notranslate"><span class="pre">"edit:all();control:perm(Builder)"</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">aliases</span></code> - list of strings for use as aliases</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">tags</span></code> - list <a class="reference internal" href="Tags.html"><span class="doc std std-doc">Tags</span></a>. These are given as tuples <code class="docutils literal notranslate"><span class="pre">(tag,</span> <span class="pre">category,</span> <span class="pre">data)</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">attrs</span></code> - list of <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attributes</span></a>. These are given as tuples <code class="docutils literal notranslate"><span class="pre">(attrname,</span> <span class="pre">value,</span> <span class="pre">category,</span> <span class="pre">lockstring)</span></code></p></li>
|
||||
<li><p>Any other keywords are interpreted as non-category <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attributes</span></a> and their values.
|
||||
This is convenient for simple Attributes - use <code class="docutils literal notranslate"><span class="pre">attrs</span></code> for full control of Attributes.</p></li>
|
||||
<li><p>Any other keywords are interpreted as non-category <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attributes</span></a> and their values. This is convenient for simple Attributes - use <code class="docutils literal notranslate"><span class="pre">attrs</span></code> for full control of Attributes.</p></li>
|
||||
</ul>
|
||||
<section id="more-on-prototype-inheritance">
|
||||
<h4>More on prototype inheritance<a class="headerlink" href="#more-on-prototype-inheritance" title="Permalink to this headline">¶</a></h4>
|
||||
<ul class="simple">
|
||||
<li><p>A prototype can inherit by defining a <code class="docutils literal notranslate"><span class="pre">prototype_parent</span></code> pointing to the name
|
||||
(<code class="docutils literal notranslate"><span class="pre">prototype_key</span></code> of another prototype). If a list of <code class="docutils literal notranslate"><span class="pre">prototype_keys</span></code>, this
|
||||
will be stepped through from left to right, giving priority to the first in
|
||||
the list over those appearing later. That is, if your inheritance is
|
||||
<code class="docutils literal notranslate"><span class="pre">prototype_parent</span> <span class="pre">=</span> <span class="pre">('A',</span> <span class="pre">'B,'</span> <span class="pre">'C')</span></code>, and all parents contain colliding keys,
|
||||
then the one from <code class="docutils literal notranslate"><span class="pre">A</span></code> will apply.</p></li>
|
||||
<li><p>The prototype keys that start with <code class="docutils literal notranslate"><span class="pre">prototype_*</span></code> are all unique to each
|
||||
prototype. They are <em>never</em> inherited from parent to child.</p></li>
|
||||
<li><p>The prototype fields <code class="docutils literal notranslate"><span class="pre">'attr':</span> <span class="pre">[(key,</span> <span class="pre">value,</span> <span class="pre">category,</span> <span class="pre">lockstring),...]</span></code>
|
||||
and <code class="docutils literal notranslate"><span class="pre">'tags':</span> <span class="pre">[(key,</span> <span class="pre">category,</span> <span class="pre">data),</span> <span class="pre">...]</span></code> are inherited in a <em>complementary</em>
|
||||
fashion. That means that only colliding key+category matches will be replaced, not the entire list.
|
||||
Remember that the category <code class="docutils literal notranslate"><span class="pre">None</span></code> is also considered a valid category!</p></li>
|
||||
<li><p>Adding an Attribute as a simple <code class="docutils literal notranslate"><span class="pre">key:value</span></code> will under the hood be translated
|
||||
into an Attribute tuple <code class="docutils literal notranslate"><span class="pre">(key,</span> <span class="pre">value,</span> <span class="pre">None,</span> <span class="pre">'')</span></code> and may replace an Attribute
|
||||
in the parent if it the same key and a <code class="docutils literal notranslate"><span class="pre">None</span></code> category.</p></li>
|
||||
<li><p>All other keys (<code class="docutils literal notranslate"><span class="pre">permissions</span></code>, <code class="docutils literal notranslate"><span class="pre">destination</span></code>, <code class="docutils literal notranslate"><span class="pre">aliases</span></code> etc) are completely
|
||||
<em>replaced</em> by the child’s value if given. For the parent’s value to be
|
||||
retained, the child must not define these keys at all.</p></li>
|
||||
<li><p>A prototype can inherit by defining a <code class="docutils literal notranslate"><span class="pre">prototype_parent</span></code> pointing to the name (<code class="docutils literal notranslate"><span class="pre">prototype_key</span></code> of another prototype). If a list of <code class="docutils literal notranslate"><span class="pre">prototype_keys</span></code>, this will be stepped through from left to right, giving priority to the first in the list over those appearing later. That is, if your inheritance is <code class="docutils literal notranslate"><span class="pre">prototype_parent</span> <span class="pre">=</span> <span class="pre">('A',</span> <span class="pre">'B,'</span> <span class="pre">'C')</span></code>, and all parents contain colliding keys, then the one from <code class="docutils literal notranslate"><span class="pre">A</span></code> will apply.</p></li>
|
||||
<li><p>The prototype keys that start with <code class="docutils literal notranslate"><span class="pre">prototype_*</span></code> are all unique to each prototype. They are <em>never</em> inherited from parent to child.</p></li>
|
||||
<li><p>The prototype fields <code class="docutils literal notranslate"><span class="pre">'attr':</span> <span class="pre">[(key,</span> <span class="pre">value,</span> <span class="pre">category,</span> <span class="pre">lockstring),...]</span></code> and <code class="docutils literal notranslate"><span class="pre">'tags':</span> <span class="pre">[(key,</span> <span class="pre">category,</span> <span class="pre">data),</span> <span class="pre">...]</span></code> are inherited in a <em>complementary</em> fashion. That means that only colliding key+category matches will be replaced, not the entire list. Remember that the category <code class="docutils literal notranslate"><span class="pre">None</span></code> is also considered a valid category!</p></li>
|
||||
<li><p>Adding an Attribute as a simple <code class="docutils literal notranslate"><span class="pre">key:value</span></code> will under the hood be translated into an Attribute tuple <code class="docutils literal notranslate"><span class="pre">(key,</span> <span class="pre">value,</span> <span class="pre">None,</span> <span class="pre">'')</span></code> and may replace an Attribute in the parent if it the same key and a <code class="docutils literal notranslate"><span class="pre">None</span></code> category.</p></li>
|
||||
<li><p>All other keys (<code class="docutils literal notranslate"><span class="pre">permissions</span></code>, <code class="docutils literal notranslate"><span class="pre">destination</span></code>, <code class="docutils literal notranslate"><span class="pre">aliases</span></code> etc) are completely <em>replaced</em> by the child’s value if given. For the parent’s value to be retained, the child must not define these keys at all.</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
|
|
@ -258,32 +214,26 @@ retained, the child must not define these keys at all.</p></li>
|
|||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>It can also be a <em>callable</em>. This callable is called without arguments whenever the prototype is
|
||||
used to
|
||||
spawn a new object:</p>
|
||||
<p>It can also be a <em>callable</em>. This callable is called without arguments whenever the prototype is used to spawn a new object:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="p">{</span><span class="s2">"key"</span><span class="p">:</span> <span class="n">_get_a_random_goblin_name</span><span class="p">,</span> <span class="o">...</span><span class="p">}</span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>By use of Python <code class="docutils literal notranslate"><span class="pre">lambda</span></code> one can wrap the callable so as to make immediate settings in the
|
||||
prototype:</p>
|
||||
<p>By use of Python <code class="docutils literal notranslate"><span class="pre">lambda</span></code> one can wrap the callable so as to make immediate settings in the prototype:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="p">{</span><span class="s2">"key"</span><span class="p">:</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">((</span><span class="s2">"Urfgar"</span><span class="p">,</span> <span class="s2">"Rick the smelly"</span><span class="p">,</span> <span class="s2">"Blargh the foul"</span><span class="p">,</span> <span class="o">...</span><span class="p">)),</span> <span class="o">...</span><span class="p">}</span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<section id="protfuncs">
|
||||
<h4>Protfuncs<a class="headerlink" href="#protfuncs" title="Permalink to this headline">¶</a></h4>
|
||||
<p>Finally, the value can be a <em>prototype function</em> (<em>Protfunc</em>). These look like simple function calls
|
||||
that you embed in strings and that has a <code class="docutils literal notranslate"><span class="pre">$</span></code> in front, like</p>
|
||||
<p>Finally, the value can be a <em>prototype function</em> (<em>Protfunc</em>). These look like simple function calls that you embed in strings and that has a <code class="docutils literal notranslate"><span class="pre">$</span></code> in front, like</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="p">{</span><span class="s2">"key"</span><span class="p">:</span> <span class="s2">"$choice(Urfgar, Rick the smelly, Blargh the foul)"</span><span class="p">,</span>
|
||||
<span class="s2">"attrs"</span><span class="p">:</span> <span class="p">{</span><span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"This is a large $red(and very red) demon. "</span>
|
||||
<span class="s2">"He has $randint(2,5) skulls in a chain around his neck."</span><span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>At execution time, the place of the protfunc will be replaced with the result of that protfunc being
|
||||
called (this is always a string). A protfunc is a <a class="reference internal" href="FuncParser.html"><span class="doc std std-doc">FuncParser function</span></a> run
|
||||
every time the prototype is used to spawn a new object.</p>
|
||||
<p>Here is how a protfunc is defined (same as an inlinefunc).</p>
|
||||
<p>At execution time, the place of the protfunc will be replaced with the result of that protfunc being called (this is always a string). A protfunc is a <a class="reference internal" href="FuncParser.html"><span class="doc std std-doc">FuncParser function</span></a> run every time the prototype is used to spawn a new object.</p>
|
||||
<p>Here is how a protfunc is defined (same as other funcparser functions).</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># this is a silly example, you can just color the text red with |r directly!</span>
|
||||
<span class="k">def</span> <span class="nf">red</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
|
|
@ -296,23 +246,17 @@ every time the prototype is used to spawn a new object.</p>
|
|||
</pre></div>
|
||||
</div>
|
||||
<blockquote>
|
||||
<div><p>Note that we must make sure to validate input and raise <code class="docutils literal notranslate"><span class="pre">ValueError</span></code> if that fails. Also, it is
|
||||
<em>not</em> possible to use keywords in the call to the protfunc (so something like <code class="docutils literal notranslate"><span class="pre">$echo(text,</span> <span class="pre">align=left)</span></code> is invalid). The <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> requred is for internal evennia use and not used at all for
|
||||
protfuncs (only by inlinefuncs).</p>
|
||||
<div><p>Note that we must make sure to validate input and raise <code class="docutils literal notranslate"><span class="pre">ValueError</span></code> if that fails. Also, it is <em>not</em> possible to use keywords in the call to the protfunc (so something like <code class="docutils literal notranslate"><span class="pre">$echo(text,</span> <span class="pre">align=left)</span></code> is invalid). The <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> requred is for internal evennia use and not used at all for protfuncs (only by inlinefuncs).</p>
|
||||
</div></blockquote>
|
||||
<p>To make this protfunc available to builders in-game, add it to a new module and add the path to that
|
||||
module to <code class="docutils literal notranslate"><span class="pre">settings.PROT_FUNC_MODULES</span></code>:</p>
|
||||
<p>To make this protfunc available to builders in-game, add it to a new module and add the path to that module to <code class="docutils literal notranslate"><span class="pre">settings.PROT_FUNC_MODULES</span></code>:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/server/conf/settings.py</span>
|
||||
|
||||
<span class="n">PROT_FUNC_MODULES</span> <span class="o">+=</span> <span class="p">[</span><span class="s2">"world.myprotfuncs"</span><span class="p">]</span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>All <em>global callables</em> in your added module will be considered a new protfunc. To avoid this (e.g.
|
||||
to have helper functions that are not protfuncs on their own), name your function something starting
|
||||
with <code class="docutils literal notranslate"><span class="pre">_</span></code>.</p>
|
||||
<p>The default protfuncs available out of the box are defined in <code class="docutils literal notranslate"><span class="pre">evennia/prototypes/profuncs.py</span></code>. To
|
||||
override the ones available, just add the same-named function in your own protfunc module.</p>
|
||||
<p>All <em>global callables</em> in your added module will be considered a new protfunc. To avoid this (e.g. to have helper functions that are not protfuncs on their own), name your function something starting with <code class="docutils literal notranslate"><span class="pre">_</span></code>.</p>
|
||||
<p>The default protfuncs available out of the box are defined in <code class="docutils literal notranslate"><span class="pre">evennia/prototypes/profuncs.py</span></code>. To override the ones available, just add the same-named function in your own protfunc module.</p>
|
||||
<table class="colwidths-auto docutils align-default">
|
||||
<thead>
|
||||
<tr class="row-odd"><th class="head"><p>Protfunc</p></th>
|
||||
|
|
@ -370,31 +314,17 @@ override the ones available, just add the same-named function in your own protfu
|
|||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>For developers with access to Python, using protfuncs in prototypes is generally not useful. Passing
|
||||
real Python functions is a lot more powerful and flexible. Their main use is to allow in-game
|
||||
builders to
|
||||
do limited coding/scripting for their prototypes without giving them direct access to raw Python.</p>
|
||||
<p>For developers with access to Python, using protfuncs in prototypes is generally not useful. Passing real Python functions is a lot more powerful and flexible. Their main use is to allow in-game builders to do limited coding/scripting for their prototypes without giving them direct access to raw Python.</p>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
<section id="storing-prototypes">
|
||||
<h2>Storing prototypes<a class="headerlink" href="#storing-prototypes" title="Permalink to this headline">¶</a></h2>
|
||||
<p>A prototype can be defined and stored in two ways, either in the database or as a dict in a module.</p>
|
||||
<section id="database-prototypes">
|
||||
<h3>Database prototypes<a class="headerlink" href="#database-prototypes" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Stored as <a class="reference internal" href="Scripts.html"><span class="doc std std-doc">Scripts</span></a> in the database. These are sometimes referred to as <em>database-
|
||||
prototypes</em> This is the only way for in-game builders to modify and add prototypes. They have the
|
||||
advantage of being easily modifiable and sharable between builders but you need to work with them
|
||||
using in-game tools.</p>
|
||||
<h2>Database prototypes<a class="headerlink" href="#database-prototypes" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Stored as <a class="reference internal" href="Scripts.html"><span class="doc std std-doc">Scripts</span></a> in the database. These are sometimes referred to as <em>database- prototypes</em> This is the only way for in-game builders to modify and add prototypes. They have the advantage of being easily modifiable and sharable between builders but you need to work with them using in-game tools.</p>
|
||||
</section>
|
||||
<section id="module-based-prototypes">
|
||||
<h3>Module-based prototypes<a class="headerlink" href="#module-based-prototypes" title="Permalink to this headline">¶</a></h3>
|
||||
<p>These prototypes are defined as dictionaries assigned to global variables in one of the modules
|
||||
defined in <code class="docutils literal notranslate"><span class="pre">settings.PROTOTYPE_MODULES</span></code>. They can only be modified from outside the game so they are
|
||||
are necessarily “read-only” from in-game and cannot be modified (but copies of them could be made
|
||||
into database-prototypes). These were the only prototypes available before Evennia 0.8. Module based
|
||||
prototypes can be useful in order for developers to provide read-only “starting” or “base”
|
||||
prototypes to build from or if they just prefer to work offline in an external code editor.</p>
|
||||
<h2>Module-based prototypes<a class="headerlink" href="#module-based-prototypes" title="Permalink to this headline">¶</a></h2>
|
||||
<p>These prototypes are defined as dictionaries assigned to global variables in one of the modules defined in <code class="docutils literal notranslate"><span class="pre">settings.PROTOTYPE_MODULES</span></code>. They can only be modified from outside the game so they are are necessarily “read-only” from in-game and cannot be modified (but copies of them could be made into database-prototypes). These were the only prototypes available before Evennia 0.8. Module based prototypes can be useful in order for developers to provide read-only “starting” or “base” prototypes to build from or if they just prefer to work offline in an external code editor.</p>
|
||||
<p>By default <code class="docutils literal notranslate"><span class="pre">mygame/world/prototypes.py</span></code> is set up for you to add your own prototypes. <em>All global
|
||||
dicts</em> in this module will be considered by Evennia to be a prototype. You could also tell Evennia
|
||||
to look for prototypes in more modules if you want:</p>
|
||||
|
|
@ -423,17 +353,14 @@ was given explicitly, that would take precedence. This is a legacy behavior and
|
|||
that you always add <code class="docutils literal notranslate"><span class="pre">prototype_key</span></code> to be consistent.</p>
|
||||
</div></blockquote>
|
||||
</section>
|
||||
</section>
|
||||
<section id="using-spawn">
|
||||
<h2>Using @spawn<a class="headerlink" href="#using-spawn" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The spawner can be used from inside the game through the Builder-only <code class="docutils literal notranslate"><span class="pre">@spawn</span></code> command. Assuming the
|
||||
“goblin” typeclass is available to the system (either as a database-prototype or read from module),
|
||||
you can spawn a new goblin with</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>@spawn goblin
|
||||
<section id="spawning">
|
||||
<h2>Spawning<a class="headerlink" href="#spawning" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The spawner can be used from inside the game through the Builder-only <code class="docutils literal notranslate"><span class="pre">@spawn</span></code> command. Assuming the “goblin” typeclass is available to the system (either as a database-prototype or read from module), you can spawn a new goblin with</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>spawn goblin
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>You can also specify the prototype directly as a valid Python dictionary:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>@spawn {"prototype_key": "shaman", \
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>spawn {"prototype_key": "shaman", \
|
||||
"key":"Orc shaman", \
|
||||
"prototype_parent": "goblin", \
|
||||
"weapon": "wooden staff", \
|
||||
|
|
@ -441,14 +368,10 @@ you can spawn a new goblin with</p>
|
|||
</pre></div>
|
||||
</div>
|
||||
<blockquote>
|
||||
<div><p>Note: The <code class="docutils literal notranslate"><span class="pre">@spawn</span></code> command is more lenient about the prototype dictionary than shown here. So you
|
||||
can for example skip the <code class="docutils literal notranslate"><span class="pre">prototype_key</span></code> if you are just testing a throw-away prototype. A random
|
||||
hash will be used to please the validation. You could also skip <code class="docutils literal notranslate"><span class="pre">prototype_parent/typeclass</span></code> - then
|
||||
the typeclass given by <code class="docutils literal notranslate"><span class="pre">settings.BASE_OBJECT_TYPECLASS</span></code> will be used.</p>
|
||||
<div><p>Note: The @spawn<code class="docutils literal notranslate"><span class="pre">command</span> <span class="pre">is</span> <span class="pre">more</span> <span class="pre">lenient</span> <span class="pre">about</span> <span class="pre">the</span> <span class="pre">prototype</span> <span class="pre">dictionary</span> <span class="pre">than</span> <span class="pre">shown</span> <span class="pre">here.</span> <span class="pre">So</span> <span class="pre">you</span> <span class="pre">can</span> <span class="pre">for</span> <span class="pre">example</span> <span class="pre">skip</span> <span class="pre">the</span></code>prototype_key<code class="docutils literal notranslate"><span class="pre">if</span> <span class="pre">you</span> <span class="pre">are</span> <span class="pre">just</span> <span class="pre">testing</span> <span class="pre">a</span> <span class="pre">throw-away</span> <span class="pre">prototype.</span> <span class="pre">A</span> <span class="pre">random</span> <span class="pre">hash</span> <span class="pre">will</span> <span class="pre">be</span> <span class="pre">used</span> <span class="pre">to</span> <span class="pre">please</span> <span class="pre">the</span> <span class="pre">validation.</span> <span class="pre">You</span> <span class="pre">could</span> <span class="pre">also</span> <span class="pre">skip</span> </code>prototype_parent/typeclass<code class="docutils literal notranslate"><span class="pre">-</span> <span class="pre">then</span> <span class="pre">the</span> <span class="pre">typeclass</span> <span class="pre">given</span> <span class="pre">by</span></code>settings.BASE_OBJECT_TYPECLASS` will be used.</p>
|
||||
</div></blockquote>
|
||||
</section>
|
||||
<section id="using-evennia-prototypes-spawner">
|
||||
<h2>Using evennia.prototypes.spawner()<a class="headerlink" href="#using-evennia-prototypes-spawner" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Using evennia.prototypes.spawner()<a class="headerlink" href="#using-evennia-prototypes-spawner" title="Permalink to this headline">¶</a></h3>
|
||||
<p>In code you access the spawner mechanism directly via the call</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">new_objects</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">prototypes</span><span class="o">.</span><span class="n">spawner</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="o">*</span><span class="n">prototypes</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
|
|
@ -460,18 +383,10 @@ matching list of created objects. Example:</p>
|
|||
</pre></div>
|
||||
</div>
|
||||
<blockquote>
|
||||
<div><p>Hint: Same as when using <code class="docutils literal notranslate"><span class="pre">@spawn</span></code>, when spawning from a one-time prototype dict like this, you can
|
||||
skip otherwise required keys, like <code class="docutils literal notranslate"><span class="pre">prototype_key</span></code> or <code class="docutils literal notranslate"><span class="pre">typeclass</span></code>/<code class="docutils literal notranslate"><span class="pre">prototype_parent</span></code>. Defaults will
|
||||
be used.</p>
|
||||
<div><p>Hint: Same as when using <code class="docutils literal notranslate"><span class="pre">spawn</span></code>, when spawning from a one-time prototype dict like this, you can skip otherwise required keys, like <code class="docutils literal notranslate"><span class="pre">prototype_key</span></code> or <code class="docutils literal notranslate"><span class="pre">typeclass</span></code>/<code class="docutils literal notranslate"><span class="pre">prototype_parent</span></code>. Defaults will be used.</p>
|
||||
</div></blockquote>
|
||||
<p>Note that no <code class="docutils literal notranslate"><span class="pre">location</span></code> will be set automatically when using <code class="docutils literal notranslate"><span class="pre">evennia.prototypes.spawner.spawn()</span></code>,
|
||||
you
|
||||
have to specify <code class="docutils literal notranslate"><span class="pre">location</span></code> explicitly in the prototype dict.</p>
|
||||
<p>If the prototypes you supply are using <code class="docutils literal notranslate"><span class="pre">prototype_parent</span></code> keywords, the spawner will read prototypes
|
||||
from modules
|
||||
in <code class="docutils literal notranslate"><span class="pre">settings.PROTOTYPE_MODULES</span></code> as well as those saved to the database to determine the body of
|
||||
available parents. The <code class="docutils literal notranslate"><span class="pre">spawn</span></code> command takes many optional keywords, you can find its definition <a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia.prototypes.spawner#spawn">in
|
||||
the api docs</a>.</p>
|
||||
<p>Note that no <code class="docutils literal notranslate"><span class="pre">location</span></code> will be set automatically when using <code class="docutils literal notranslate"><span class="pre">evennia.prototypes.spawner.spawn()</span></code>, you have to specify <code class="docutils literal notranslate"><span class="pre">location</span></code> explicitly in the prototype dict. If the prototypes you supply are using <code class="docutils literal notranslate"><span class="pre">prototype_parent</span></code> keywords, the spawner will read prototypes from modules in <code class="docutils literal notranslate"><span class="pre">settings.PROTOTYPE_MODULES</span></code> as well as those saved to the database to determine the body of available parents. The <code class="docutils literal notranslate"><span class="pre">spawn</span></code> command takes many optional keywords, you can find its definition <a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia.prototypes.spawner#spawn">in the api docs</a>.</p>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
|
|
|||
|
|
@ -63,20 +63,20 @@
|
|||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Scripts</a><ul>
|
||||
<li><a class="reference internal" href="#in-game-command-examples">In-game command examples</a></li>
|
||||
<li><a class="reference internal" href="#working-with-scripts">Working with Scripts</a><ul>
|
||||
<li><a class="reference internal" href="#code-examples">Code examples</a></li>
|
||||
<li><a class="reference internal" href="#defining-new-scripts">Defining new Scripts</a><ul>
|
||||
<li><a class="reference internal" href="#simple-storage-script">Simple storage script</a></li>
|
||||
<li><a class="reference internal" href="#timed-script">Timed Script</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#timed-scripts">Timed Scripts</a><ul>
|
||||
<li><a class="reference internal" href="#script-timers-vs-delay-repeat">Script timers vs delay/repeat</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#script-attached-to-another-object">Script attached to another object</a></li>
|
||||
<li><a class="reference internal" href="#other-script-methods">Other Script methods</a></li>
|
||||
<li><a class="reference internal" href="#the-global-scripts-container">The GLOBAL_SCRIPTS container</a></li>
|
||||
<li><a class="reference internal" href="#hints-dealing-with-script-errors">Hints: Dealing with Script Errors</a></li>
|
||||
<li><a class="reference internal" href="#dealing-with-script-errors">Dealing with Script Errors</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#using-global-scripts">Using GLOBAL_SCRIPTS</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
@ -120,39 +120,20 @@
|
|||
<section class="tex2jax_ignore mathjax_ignore" id="scripts">
|
||||
<h1>Scripts<a class="headerlink" href="#scripts" title="Permalink to this headline">¶</a></h1>
|
||||
<p><a class="reference internal" href="../api/evennia.scripts.scripts.html#evennia-scripts-scripts"><span class="std std-ref">Script API reference</span></a></p>
|
||||
<p><em>Scripts</em> are the out-of-character siblings to the in-character
|
||||
<a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a>. Scripts are so flexible that the name “Script” is a bit limiting
|
||||
in itself - but we had to pick <em>something</em> to name them. Other possible names
|
||||
(depending on what you’d use them for) would be <code class="docutils literal notranslate"><span class="pre">OOBObjects</span></code>, <code class="docutils literal notranslate"><span class="pre">StorageContainers</span></code> or <code class="docutils literal notranslate"><span class="pre">TimerObjects</span></code>.</p>
|
||||
<p>If you ever consider creating an <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Object</span></a> with a <code class="docutils literal notranslate"><span class="pre">None</span></code>-location just to store some game data,
|
||||
you should really be using a Script instead.</p>
|
||||
<p><em>Scripts</em> are the out-of-character siblings to the in-character <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a>. Scripts are so flexible that the name “Script” is a bit limiting in itself - but we had to pick <em>something</em> to name them. Other possible names (depending on what you’d use them for) would be <code class="docutils literal notranslate"><span class="pre">OOBObjects</span></code>, <code class="docutils literal notranslate"><span class="pre">StorageContainers</span></code> or <code class="docutils literal notranslate"><span class="pre">TimerObjects</span></code>.</p>
|
||||
<p>If you ever consider creating an <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Object</span></a> with a <code class="docutils literal notranslate"><span class="pre">None</span></code>-location just to store some game data, you should really be using a Script instead.</p>
|
||||
<ul class="simple">
|
||||
<li><p>Scripts are full <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclassed</span></a> entities - they have <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attributes</span></a> and
|
||||
can be modified in the same way. But they have <em>no in-game existence</em>, so no
|
||||
location or command-execution like <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a> and no connection to a particular
|
||||
player/session like <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a>. This means they are perfectly suitable for acting
|
||||
as database-storage backends for game <em>systems</em>: Storing the current state of the economy,
|
||||
who is involved in the current fight, tracking an ongoing barter and so on. They are great as
|
||||
persistent system handlers.</p></li>
|
||||
<li><p>Scripts have an optional <em>timer component</em>. This means that you can set up the script
|
||||
to tick the <code class="docutils literal notranslate"><span class="pre">at_repeat</span></code> hook on the Script at a certain interval. The timer can be controlled
|
||||
independently of the rest of the script as needed. This component is optional
|
||||
and complementary to other timing functions in Evennia, like
|
||||
<a class="reference internal" href="../api/evennia.utils.utils.html#evennia.utils.utils.delay" title="evennia.utils.utils.delay"><span class="xref myst py py-func">evennia.utils.delay</span></a> and
|
||||
<a class="reference internal" href="../api/evennia.utils.utils.html#evennia.utils.utils.repeat" title="evennia.utils.utils.repeat"><span class="xref myst py py-func">evennia.utils.repeat</span></a>.</p></li>
|
||||
<li><p>Scripts can <em>attach</em> to Objects and Accounts via e.g. <code class="docutils literal notranslate"><span class="pre">obj.scripts.add/remove</span></code>. In the
|
||||
script you can then access the object/account as <code class="docutils literal notranslate"><span class="pre">self.obj</span></code> or <code class="docutils literal notranslate"><span class="pre">self.account</span></code>. This can be used to
|
||||
dynamically extend other typeclasses but also to use the timer component to affect the parent object
|
||||
in various ways. For historical reasons, a Script <em>not</em> attached to an object is referred to as a
|
||||
<em>Global</em> Script.</p></li>
|
||||
<li><p>Scripts are full <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclassed</span></a> entities - they have <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attributes</span></a> and can be modified in the same way. But they have <em>no in-game existence</em>, so no location or command-execution like <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a> and no connection to a particular player/session like <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a>. This means they are perfectly suitable for acting as database-storage backends for game <em>systems</em>: Storing the current state of the economy, who is involved in the current fight, tracking an ongoing barter and so on. They are great as persistent system handlers.</p></li>
|
||||
<li><p>Scripts have an optional <em>timer component</em>. This means that you can set up the script to tick the <code class="docutils literal notranslate"><span class="pre">at_repeat</span></code> hook on the Script at a certain interval. The timer can be controlled independently of the rest of the script as needed. This component is optional and complementary to other timing functions in Evennia, like <a class="reference internal" href="../api/evennia.utils.utils.html#evennia.utils.utils.delay" title="evennia.utils.utils.delay"><span class="xref myst py py-func">evennia.utils.delay</span></a> and <a class="reference internal" href="../api/evennia.utils.utils.html#evennia.utils.utils.repeat" title="evennia.utils.utils.repeat"><span class="xref myst py py-func">evennia.utils.repeat</span></a>.</p></li>
|
||||
<li><p>Scripts can <em>attach</em> to Objects and Accounts via e.g. <code class="docutils literal notranslate"><span class="pre">obj.scripts.add/remove</span></code>. In the script you can then access the object/account as <code class="docutils literal notranslate"><span class="pre">self.obj</span></code> or <code class="docutils literal notranslate"><span class="pre">self.account</span></code>. This can be used to dynamically extend other typeclasses but also to use the timer component to affect the parent object in various ways. For historical reasons, a Script <em>not</em> attached to an object is referred to as a <em>Global</em> Script.</p></li>
|
||||
</ul>
|
||||
<div class="versionchanged">
|
||||
<p><span class="versionmodified changed">Changed in version 1.0: </span>In previus Evennia versions, stopping the Script’s timer also meant deleting the Script object.
|
||||
Starting with this version, the timer can be start/stopped separately and <code class="docutils literal notranslate"><span class="pre">.delete()</span></code> must be called
|
||||
on the Script explicitly to delete it.</p>
|
||||
</div>
|
||||
<section id="in-game-command-examples">
|
||||
<h2>In-game command examples<a class="headerlink" href="#in-game-command-examples" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="working-with-scripts">
|
||||
<h2>Working with Scripts<a class="headerlink" href="#working-with-scripts" title="Permalink to this headline">¶</a></h2>
|
||||
<p>There are two main commands controlling scripts in the default cmdset:</p>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">addscript</span></code> command is used for attaching scripts to existing objects:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> addscript obj = bodyfunctions.BodyFunctions
|
||||
|
|
@ -169,9 +150,8 @@ on the Script explicitly to delete it.</p>
|
|||
<div class="versionchanged">
|
||||
<p><span class="versionmodified changed">Changed in version 1.0: </span>The <code class="docutils literal notranslate"><span class="pre">addscript</span></code> command used to be only <code class="docutils literal notranslate"><span class="pre">script</span></code> which was easy to confuse with <code class="docutils literal notranslate"><span class="pre">scripts</span></code>.</p>
|
||||
</div>
|
||||
</section>
|
||||
<section id="code-examples">
|
||||
<h2>Code examples<a class="headerlink" href="#code-examples" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Code examples<a class="headerlink" href="#code-examples" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Here are some examples of working with Scripts in-code (more details to follow in later
|
||||
sections).</p>
|
||||
<p>Create a new script:</p>
|
||||
|
|
@ -217,11 +197,11 @@ sections).</p>
|
|||
</div>
|
||||
</section>
|
||||
<section id="defining-new-scripts">
|
||||
<h2>Defining new Scripts<a class="headerlink" href="#defining-new-scripts" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Defining new Scripts<a class="headerlink" href="#defining-new-scripts" title="Permalink to this headline">¶</a></h3>
|
||||
<p>A Script is defined as a class and is created in the same way as other
|
||||
<a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">typeclassed</span></a> entities. The parent class is <code class="docutils literal notranslate"><span class="pre">evennia.DefaultScript</span></code>.</p>
|
||||
<section id="simple-storage-script">
|
||||
<h3>Simple storage script<a class="headerlink" href="#simple-storage-script" title="Permalink to this headline">¶</a></h3>
|
||||
<h4>Simple storage script<a class="headerlink" href="#simple-storage-script" title="Permalink to this headline">¶</a></h4>
|
||||
<p>In <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/scripts.py</span></code> is an empty <code class="docutils literal notranslate"><span class="pre">Script</span></code> class already set up. You
|
||||
can use this as a base for your own scripts.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/typeclasses/scripts.py</span>
|
||||
|
|
@ -259,13 +239,10 @@ you set in your <code class="docutils literal notranslate"><span class="pre">at_
|
|||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>See the <a class="reference internal" href="../api/evennia.utils.create.html#evennia.utils.create.create_script" title="evennia.utils.create.create_script"><span class="xref myst py py-func">create_script</span></a> and
|
||||
<a class="reference internal" href="../api/evennia.utils.search.html#evennia.utils.search.search_script" title="evennia.utils.search.search_script"><span class="xref myst py py-func">search_script</span></a> API documentation for more options
|
||||
on creating and finding Scripts.</p>
|
||||
<p>See the <a class="reference internal" href="../api/evennia.utils.create.html#evennia.utils.create.create_script" title="evennia.utils.create.create_script"><span class="xref myst py py-func">create_script</span></a> and <a class="reference internal" href="../api/evennia.utils.search.html#evennia.utils.search.search_script" title="evennia.utils.search.search_script"><span class="xref myst py py-func">search_script</span></a> API documentation for more options on creating and finding Scripts.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="timed-scripts">
|
||||
<h2>Timed Scripts<a class="headerlink" href="#timed-scripts" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="timed-script">
|
||||
<h4>Timed Script<a class="headerlink" href="#timed-script" title="Permalink to this headline">¶</a></h4>
|
||||
<p>There are several properties one can set on the Script to control its timer component.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/typeclasses/scripts.py</span>
|
||||
|
||||
|
|
@ -293,8 +270,7 @@ to help identifying what does what.</p></li>
|
|||
<li><p><code class="docutils literal notranslate"><span class="pre">interval</span></code> (int): The amount of time (in seconds) between every ‘tick’ of the timer. Note that
|
||||
it’s generally bad practice to use sub-second timers for anything in a text-game - the player will
|
||||
not be able to appreciate the precision (and if you print it, it will just spam the screen). For
|
||||
calculations you can pretty much always do them on-demand, or at a much slower interval without the
|
||||
player being the wiser.</p></li>
|
||||
calculations you can pretty much always do them on-demand, or at a much slower interval without the player being the wiser.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">start_delay</span></code> (bool): If timer should start right away or wait <code class="docutils literal notranslate"><span class="pre">interval</span></code> seconds first.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">repeats</span></code> (int): If >0, the timer will only run this many times before stopping. Otherwise the
|
||||
number of repeats are infinite. If set to 1, the Script mimics a <code class="docutils literal notranslate"><span class="pre">delay</span></code> action.</p></li>
|
||||
|
|
@ -320,30 +296,18 @@ at which time the <code class="docutils literal notranslate"><span class="pre">m
|
|||
<li><p><code class="docutils literal notranslate"><span class="pre">.time_until_next_repeat()</span></code> - get the time until next time the timer fires.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">.remaining_repeats()</span></code> - get the number of repeats remaining, or <code class="docutils literal notranslate"><span class="pre">None</span></code> if repeats are infinite.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">.reset_callcount()</span></code> - this resets the repeat counter to start over from 0. Only useful if <code class="docutils literal notranslate"><span class="pre">repeats>0</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">.force_repeat()</span></code> - this prematurely forces <code class="docutils literal notranslate"><span class="pre">at_repeat</span></code> to be called right away. Doing so will reset the
|
||||
countdown so that next call will again happen after <code class="docutils literal notranslate"><span class="pre">interval</span></code> seconds.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">.force_repeat()</span></code> - this prematurely forces <code class="docutils literal notranslate"><span class="pre">at_repeat</span></code> to be called right away. Doing so will reset the countdown so that next call will again happen after <code class="docutils literal notranslate"><span class="pre">interval</span></code> seconds.</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
<section id="script-timers-vs-delay-repeat">
|
||||
<h3>Script timers vs delay/repeat<a class="headerlink" href="#script-timers-vs-delay-repeat" title="Permalink to this headline">¶</a></h3>
|
||||
<p>If the <em>only</em> goal is to get a repeat/delay effect, the
|
||||
<a class="reference internal" href="../api/evennia.utils.utils.html#evennia.utils.utils.delay" title="evennia.utils.utils.delay"><span class="xref myst py py-func">evennia.utils.delay</span></a> and
|
||||
<a class="reference internal" href="../api/evennia.utils.utils.html#evennia.utils.utils.repeat" title="evennia.utils.utils.repeat"><span class="xref myst py py-func">evennia.utils.repeat</span></a> functions
|
||||
should generally be considered first. A Script is a lot ‘heavier’ to create/delete on the fly.
|
||||
In fact, for making a single delayed call (<code class="docutils literal notranslate"><span class="pre">script.repeats==1</span></code>), the <code class="docutils literal notranslate"><span class="pre">utils.delay</span></code> call is
|
||||
probably always the better choice.</p>
|
||||
<p>For repeating tasks, the <code class="docutils literal notranslate"><span class="pre">utils.repeat</span></code> is optimized for quick repeating of a large number of objects. It
|
||||
uses the TickerHandler under the hood. Its subscription-based model makes it very efficient to
|
||||
start/stop the repeating action for an object. The side effect is however that all objects set to tick
|
||||
at a given interval will <em>all do so at the same time</em>. This may or may not look strange in-game depending
|
||||
on the situation. By contrast the Script uses its own ticker that will operate independently from the
|
||||
tickers of all other Scripts.</p>
|
||||
<p>It’s also worth noting that once the script object has <em>already been created</em>,
|
||||
starting/stopping/pausing/unpausing the timer has very little overhead. The pause/unpause and update
|
||||
methods of the script also offers a bit more fine-control than using <code class="docutils literal notranslate"><span class="pre">utils.delays/repeat</span></code>.</p>
|
||||
</section>
|
||||
<p>If the <em>only</em> goal is to get a repeat/delay effect, the <a class="reference internal" href="../api/evennia.utils.utils.html#evennia.utils.utils.delay" title="evennia.utils.utils.delay"><span class="xref myst py py-func">evennia.utils.delay</span></a> and <a class="reference internal" href="../api/evennia.utils.utils.html#evennia.utils.utils.repeat" title="evennia.utils.utils.repeat"><span class="xref myst py py-func">evennia.utils.repeat</span></a> functions should generally be considered first. A Script is a lot ‘heavier’ to create/delete on the fly. In fact, for making a single delayed call (<code class="docutils literal notranslate"><span class="pre">script.repeats==1</span></code>), the <code class="docutils literal notranslate"><span class="pre">utils.delay</span></code> call is probably always the better choice.</p>
|
||||
<p>For repeating tasks, the <code class="docutils literal notranslate"><span class="pre">utils.repeat</span></code> is optimized for quick repeating of a large number of objects. It uses the TickerHandler under the hood. Its subscription-based model makes it very efficient to start/stop the repeating action for an object. The side effect is however that all objects set to tick at a given interval will <em>all do so at the same time</em>. This may or may not look strange in-game depending on the situation. By contrast the Script uses its own ticker that will operate independently from the tickers of all other Scripts.</p>
|
||||
<p>It’s also worth noting that once the script object has <em>already been created</em>, starting/stopping/pausing/unpausing the timer has very little overhead. The pause/unpause and update methods of the script also offers a bit more fine-control than using <code class="docutils literal notranslate"><span class="pre">utils.delays/repeat</span></code>.</p>
|
||||
</section>
|
||||
<section id="script-attached-to-another-object">
|
||||
<h2>Script attached to another object<a class="headerlink" href="#script-attached-to-another-object" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Script attached to another object<a class="headerlink" href="#script-attached-to-another-object" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Scripts can be attached to an <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Account</span></a> or (more commonly) an <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Object</span></a>.
|
||||
If so, the ‘parent object’ will be available to the script as either <code class="docutils literal notranslate"><span class="pre">.obj</span></code> or <code class="docutils literal notranslate"><span class="pre">.account</span></code>.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># mygame/typeclasses/scripts.py</span>
|
||||
|
|
@ -392,20 +356,16 @@ but only <code class="docutils literal notranslate"><span class="pre">scripts.We
|
|||
</div>
|
||||
</section>
|
||||
<section id="other-script-methods">
|
||||
<h2>Other Script methods<a class="headerlink" href="#other-script-methods" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Other Script methods<a class="headerlink" href="#other-script-methods" title="Permalink to this headline">¶</a></h3>
|
||||
<p>A Script has all the properties of a typeclassed object, such as <code class="docutils literal notranslate"><span class="pre">db</span></code> and <code class="docutils literal notranslate"><span class="pre">ndb</span></code>(see
|
||||
<a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclasses</span></a>). Setting <code class="docutils literal notranslate"><span class="pre">key</span></code> is useful in order to manage scripts (delete them by name
|
||||
etc). These are usually set up in the Script’s typeclass, but can also be assigned on the fly as
|
||||
keyword arguments to <code class="docutils literal notranslate"><span class="pre">evennia.create_script</span></code>.</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">at_script_creation()</span></code> - this is only called once - when the script is first created.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">at_server_reload()</span></code> - this is called whenever the server is warm-rebooted (e.g. with the
|
||||
<code class="docutils literal notranslate"><span class="pre">reload</span></code> command). It’s a good place to save non-persistent data you might want to survive a
|
||||
reload.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">at_server_reload()</span></code> - this is called whenever the server is warm-rebooted (e.g. with the <code class="docutils literal notranslate"><span class="pre">reload</span></code> command). It’s a good place to save non-persistent data you might want to survive a reload.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">at_server_shutdown()</span></code> - this is called when a system reset or systems shutdown is invoked.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">at_server_start()</span></code> - this is called when the server comes back (from reload/shutdown/reboot). It
|
||||
can be usuful for initializations and caching of non-persistent data when starting up a script’s
|
||||
functionality.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">at_server_start()</span></code> - this is called when the server comes back (from reload/shutdown/reboot). It can be usuful for initializations and caching of non-persistent data when starting up a script’s functionality.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">at_repeat()</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">at_start()</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">at_pause()</span></code></p></li>
|
||||
|
|
@ -413,12 +373,33 @@ functionality.</p></li>
|
|||
<li><p><code class="docutils literal notranslate"><span class="pre">delete()</span></code> - same as for other typeclassed entities, this will delete the Script. Of note is that
|
||||
it will also stop the timer (if it runs), leading to the <code class="docutils literal notranslate"><span class="pre">at_stop</span></code> hook being called.</p></li>
|
||||
</ul>
|
||||
<p>In addition, Scripts support <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attributes</span></a>, <a class="reference internal" href="Tags.html"><span class="doc std std-doc">Tags</span></a> and <a class="reference internal" href="Locks.html"><span class="doc std std-doc">Locks</span></a> etc like other
|
||||
Typeclassed entities.</p>
|
||||
<p>See also the methods involved in controlling a <a class="reference internal" href="#timed-scripts"><span class="std std-doc">Timed Script</span></a> above.</p>
|
||||
<p>In addition, Scripts support <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attributes</span></a>, <a class="reference internal" href="Tags.html"><span class="doc std std-doc">Tags</span></a> and <a class="reference internal" href="Locks.html"><span class="doc std std-doc">Locks</span></a> etc like other Typeclassed entities.</p>
|
||||
<p>See also the methods involved in controlling a <a class="reference internal" href="#timed-script"><span class="std std-doc">Timed Script</span></a> above.</p>
|
||||
</section>
|
||||
<section id="the-global-scripts-container">
|
||||
<h2>The GLOBAL_SCRIPTS container<a class="headerlink" href="#the-global-scripts-container" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="dealing-with-script-errors">
|
||||
<h3>Dealing with Script Errors<a class="headerlink" href="#dealing-with-script-errors" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Errors inside a timed, executing script can sometimes be rather terse or point to parts of the execution mechanism that is hard to interpret. One way to make it easier to debug scripts is to import Evennia’s native logger and wrap your functions in a try/catch block. Evennia’s logger can show you where the traceback occurred in your script.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
|
||||
<span class="kn">from</span> <span class="nn">evennia.utils</span> <span class="kn">import</span> <span class="n">logger</span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">Weather</span><span class="p">(</span><span class="n">Script</span><span class="p">):</span>
|
||||
|
||||
<span class="c1"># [...]</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">at_repeat</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="c1"># [...]</span>
|
||||
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">log_trace</span><span class="p">()</span>
|
||||
<span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">github</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">evennia</span><span class="o">/</span><span class="n">evennia</span><span class="o">/</span><span class="n">blob</span><span class="o">/</span><span class="n">master</span><span class="o">/</span><span class="n">evennia</span><span class="o">/</span><span class="n">contrib</span><span class="o">/</span><span class="n">tutorial_examples</span><span class="o">/</span><span class="n">example_batch_cmds</span><span class="o">.</span><span class="n">ev</span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="using-global-scripts">
|
||||
<h2>Using GLOBAL_SCRIPTS<a class="headerlink" href="#using-global-scripts" title="Permalink to this headline">¶</a></h2>
|
||||
<p>A Script not attached to another entity is commonly referred to as a <em>Global</em> script since it’t available
|
||||
to access from anywhere. This means they need to be searched for in order to be used.</p>
|
||||
<p>Evennia supplies a convenient “container” <code class="docutils literal notranslate"><span class="pre">evennia.GLOBAL_SCRIPTS</span></code> to help organize your global
|
||||
|
|
@ -438,13 +419,7 @@ scripts. All you need is the Script’s <code class="docutils literal notranslat
|
|||
</div>
|
||||
<div class="admonition warning">
|
||||
<p class="admonition-title">Warning</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Note that global scripts appear as properties on `GLOBAL_SCRIPTS` based on their `key`.
|
||||
If you were to create two global scripts with the same `key` (even with different typeclasses),
|
||||
the `GLOBAL_SCRIPTS` container will only return one of them (which one depends on order in
|
||||
the database). Best is to organize your scripts so that this does not happen. Otherwise, use
|
||||
`evennia.search_scripts` to get exactly the script you want.
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Note that global scripts appear as properties on <code class="docutils literal notranslate"><span class="pre">GLOBAL_SCRIPTS</span></code> based on their <code class="docutils literal notranslate"><span class="pre">key</span></code>. If you were to create two global scripts with the same <code class="docutils literal notranslate"><span class="pre">key</span></code> (even with different typeclasses), the <code class="docutils literal notranslate"><span class="pre">GLOBAL_SCRIPTS</span></code> container will only return one of them (which one depends on order in the database). Best is to organize your scripts so that this does not happen. Otherwise, use <code class="docutils literal notranslate"><span class="pre">evennia.search_scripts</span></code> to get exactly the script you want.</p>
|
||||
</div>
|
||||
<p>There are two ways to make a script appear as a property on <code class="docutils literal notranslate"><span class="pre">GLOBAL_SCRIPTS</span></code>:</p>
|
||||
<ol class="simple">
|
||||
|
|
@ -469,18 +444,10 @@ script keys are globally unique.</p></li>
|
|||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Above we add two scripts with keys <code class="docutils literal notranslate"><span class="pre">myscript</span></code> and <code class="docutils literal notranslate"><span class="pre">storagescript</span></code>respectively. The following dict
|
||||
can be empty - the <code class="docutils literal notranslate"><span class="pre">settings.BASE_SCRIPT_TYPECLASS</span></code> will then be used. Under the hood, the provided
|
||||
dict (along with the <code class="docutils literal notranslate"><span class="pre">key</span></code>) will be passed into <code class="docutils literal notranslate"><span class="pre">create_script</span></code> automatically, so
|
||||
all the <a class="reference internal" href="../api/evennia.utils.create.html#evennia.utils.create.create_script" title="evennia.utils.create.create_script"><span class="xref myst py py-func">same keyword arguments as for create_script</span></a> are
|
||||
supported here.</p>
|
||||
<p>Above we add two scripts with keys <code class="docutils literal notranslate"><span class="pre">myscript</span></code> and <code class="docutils literal notranslate"><span class="pre">storagescript</span></code>respectively. The following dict can be empty - the <code class="docutils literal notranslate"><span class="pre">settings.BASE_SCRIPT_TYPECLASS</span></code> will then be used. Under the hood, the provided dict (along with the <code class="docutils literal notranslate"><span class="pre">key</span></code>) will be passed into <code class="docutils literal notranslate"><span class="pre">create_script</span></code> automatically, so all the <a class="reference internal" href="../api/evennia.utils.create.html#evennia.utils.create.create_script" title="evennia.utils.create.create_script"><span class="xref myst py py-func">same keyword arguments as for create_script</span></a> are supported here.</p>
|
||||
<div class="admonition warning">
|
||||
<p class="admonition-title">Warning</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Before setting up Evennia to manage your script like this, make sure that your Script typeclass
|
||||
does not have any critical errors (test it separately). If there are, you'll see errors in your log
|
||||
and your Script will temporarily fall back to being a `DefaultScript` type.
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Before setting up Evennia to manage your script like this, make sure that your Script typeclass does not have any critical errors (test it separately). If there are, you’ll see errors in your log and your Script will temporarily fall back to being a <code class="docutils literal notranslate"><span class="pre">DefaultScript</span></code> type.</p>
|
||||
</div>
|
||||
<p>Moreover, a script defined this way is <em>guaranteed</em> to exist when you try to access it:</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">GLOBAL_SCRIPTS</span>
|
||||
|
|
@ -494,29 +461,6 @@ and your Script will temporarily fall back to being a `DefaultScript` type.
|
|||
<p>That is, if the script is deleted, next time you get it from <code class="docutils literal notranslate"><span class="pre">GLOBAL_SCRIPTS</span></code>, Evennia will use the
|
||||
information in settings to recreate it for you on the fly.</p>
|
||||
</section>
|
||||
<section id="hints-dealing-with-script-errors">
|
||||
<h2>Hints: Dealing with Script Errors<a class="headerlink" href="#hints-dealing-with-script-errors" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Errors inside a timed, executing script can sometimes be rather terse or point to
|
||||
parts of the execution mechanism that is hard to interpret. One way to make it
|
||||
easier to debug scripts is to import Evennia’s native logger and wrap your
|
||||
functions in a try/catch block. Evennia’s logger can show you where the
|
||||
traceback occurred in your script.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
|
||||
<span class="kn">from</span> <span class="nn">evennia.utils</span> <span class="kn">import</span> <span class="n">logger</span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">Weather</span><span class="p">(</span><span class="n">Script</span><span class="p">):</span>
|
||||
|
||||
<span class="c1"># [...]</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">at_repeat</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="c1"># [...]</span>
|
||||
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">log_trace</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
<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="Accounts" href="Accounts.html" />
|
||||
<link rel="prev" title="Typeclasses" href="Typeclasses.html" />
|
||||
<link rel="next" title="Typeclasses" href="Typeclasses.html" />
|
||||
<link rel="prev" title="Portal And Server" href="Portal-And-Server.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
|
|
@ -30,10 +30,10 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Accounts.html" title="Accounts"
|
||||
<a href="Typeclasses.html" title="Typeclasses"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Typeclasses.html" title="Typeclasses"
|
||||
<a href="Portal-And-Server.html" title="Portal And Server"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" accesskey="U">Core Components</a> »</li>
|
||||
|
|
@ -63,22 +63,26 @@
|
|||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Sessions</a><ul>
|
||||
<li><a class="reference internal" href="#working-with-sessions">Working with Sessions</a><ul>
|
||||
<li><a class="reference internal" href="#properties-on-sessions">Properties on Sessions</a></li>
|
||||
<li><a class="reference internal" href="#multisession-mode">Multisession mode</a></li>
|
||||
<li><a class="reference internal" href="#returning-data-to-the-session">Returning data to the session</a></li>
|
||||
<li><a class="reference internal" href="#customizing-the-session-object">Customizing the Session object</a></li>
|
||||
<li><a class="reference internal" href="#portal-and-server-sessions">Portal and Server Sessions</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#portal-and-server-sessions">Portal and Server Sessions</a><ul>
|
||||
<li><a class="reference internal" href="#sessionhandlers">Sessionhandlers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Typeclasses.html"
|
||||
title="previous chapter">Typeclasses</a></p>
|
||||
<p class="topless"><a href="Portal-And-Server.html"
|
||||
title="previous chapter">Portal And Server</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Accounts.html"
|
||||
title="next chapter">Accounts</a></p>
|
||||
<p class="topless"><a href="Typeclasses.html"
|
||||
title="next chapter">Typeclasses</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
|
|
@ -122,17 +126,17 @@ Evennia session, it is possible for a person to connect multiple times, for exam
|
|||
clients in multiple windows. Each such connection is represented by a session object.</p>
|
||||
<p>A session object has its own <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">cmdset</span></a>, usually the “unloggedin” cmdset. This is what is used to show the login screen and to handle commands to create a new account (or <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Account</span></a> in evennia lingo) read initial help and to log into the game with an existing account. A session object can either be “logged in” or not. Logged in means that the user has authenticated. When this happens the session is associated with an Account object (which is what holds account-centric stuff). The account can then in turn puppet any number of objects/characters.</p>
|
||||
<p>A Session is not <em>persistent</em> - it is not a <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclass</span></a> and has no connection to the database. The Session will go away when a user disconnects and you will lose any custom data on it if the server reloads. The <code class="docutils literal notranslate"><span class="pre">.db</span></code> handler on Sessions is there to present a uniform API (so you can assume <code class="docutils literal notranslate"><span class="pre">.db</span></code> exists even if you don’t know if you receive an Object or a Session), but this is just an alias to <code class="docutils literal notranslate"><span class="pre">.ndb</span></code>. So don’t store any data on Sessions that you can’t afford to lose in a reload.</p>
|
||||
<section id="working-with-sessions">
|
||||
<h2>Working with Sessions<a class="headerlink" href="#working-with-sessions" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="properties-on-sessions">
|
||||
<h2>Properties on Sessions<a class="headerlink" href="#properties-on-sessions" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Properties on Sessions<a class="headerlink" href="#properties-on-sessions" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Here are some important properties available on (Server-)Sessions</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">sessid</span></code> - The unique session-id. This is an integer starting from 1.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">address</span></code> - The connected client’s address. Different protocols give different information here.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">logged_in</span></code> - <code class="docutils literal notranslate"><span class="pre">True</span></code> if the user authenticated to this session.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">account</span></code> - The <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Account</span></a> this Session is attached to. If not logged in yet, this is
|
||||
<code class="docutils literal notranslate"><span class="pre">None</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">puppet</span></code> - The <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Character/Object</span></a> currently puppeted by this Account/Session combo. If
|
||||
not logged in or in OOC mode, this is <code class="docutils literal notranslate"><span class="pre">None</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">account</span></code> - The <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Account</span></a> this Session is attached to. If not logged in yet, this is <code class="docutils literal notranslate"><span class="pre">None</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">puppet</span></code> - The <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Character/Object</span></a> currently puppeted by this Account/Session combo. If not logged in or in OOC mode, this is <code class="docutils literal notranslate"><span class="pre">None</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">ndb</span></code> - The <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Non-persistent Attribute</span></a> handler.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">db</span></code> - As noted above, Sessions don’t have regular Attributes. This is an alias to <code class="docutils literal notranslate"><span class="pre">ndb</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">cmdset</span></code> - The Session’s <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">CmdSetHandler</span></a></p></li>
|
||||
|
|
@ -146,67 +150,8 @@ last time this session was truly visibly active.</p></li>
|
|||
<li><p><code class="docutils literal notranslate"><span class="pre">cmd_total</span></code> - Total number of Commands passed through this Session.</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section id="multisession-mode">
|
||||
<h2>Multisession mode<a class="headerlink" href="#multisession-mode" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The number of sessions possible to connect to a given account at the same time and how it works is given by the <code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE</span></code> setting:</p>
|
||||
<ul>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE=0</span></code>: One session per account. When connecting with a new session the old one is disconnected. This is the default mode and emulates many classic mud code bases.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>┌──────┐ │ ┌───────┐ ┌───────┐ ┌─────────┐
|
||||
│Client├─┼──►│Session├───►│Account├──►│Character│
|
||||
└──────┘ │ └───────┘ └───────┘ └─────────┘
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE=1</span></code>: Many sessions per account, input/output from/to each session is treated the same. For the player this means they can connect to the game from multiple clients and see the same output in all of them. The result of a command given in one client (that is, through one Session) will be returned to <em>all</em> connected Sessions/clients with no distinction.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> │
|
||||
┌──────┐ │ ┌───────┐
|
||||
│Client├─┼──►│Session├──┐
|
||||
└──────┘ │ └───────┘ └──►┌───────┐ ┌─────────┐
|
||||
│ │Account├──►│Character│
|
||||
┌──────┐ │ ┌───────┐ ┌──►└───────┘ └─────────┘
|
||||
│Client├─┼──►│Session├──┘
|
||||
└──────┘ │ └───────┘
|
||||
│
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE=2</span></code>: Many sessions per account, one character per session. In this mode, puppeting an Object/Character will link the puppet back only to the particular Session doing the puppeting. That is, input from that Session will make use of the CmdSet of that Object/Character and outgoing messages (such as the result of a <code class="docutils literal notranslate"><span class="pre">look</span></code>) will be passed back only to that puppeting Session. If another Session tries to puppet the same Character, the old Session will automatically un-puppet it. From the player’s perspective, this will mean that they can open separate game clients and play a different Character in each using one game account.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> │ ┌───────┐
|
||||
┌──────┐ │ ┌───────┐ │Account│ ┌─────────┐
|
||||
│Client├─┼──►│Session├──┐ │ │ ┌►│Character│
|
||||
└──────┘ │ └───────┘ └──┼───────┼──┘ └─────────┘
|
||||
│ │ │
|
||||
┌──────┐ │ ┌───────┐ ┌──┼───────┼──┐ ┌─────────┐
|
||||
│Client├─┼──►│Session├──┘ │ │ └►│Character│
|
||||
└──────┘ │ └───────┘ │ │ └─────────┘
|
||||
│ └───────┘
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE=3</span></code>: Many sessions per account <em>and</em> character. This is the full multi-puppeting mode, where multiple sessions may not only connect to the player account but multiple sessions may also puppet a single character at the same time. From the user’s perspective it means one can open multiple client windows, some for controlling different Characters and some that share a Character’s input/output like in mode 1. This mode otherwise works the same as mode 2.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> │ ┌───────┐
|
||||
┌──────┐ │ ┌───────┐ │Account│ ┌─────────┐
|
||||
│Client├─┼──►│Session├──┐ │ │ ┌►│Character│
|
||||
└──────┘ │ └───────┘ └──┼───────┼──┘ └─────────┘
|
||||
│ │ │
|
||||
┌──────┐ │ ┌───────┐ ┌──┼───────┼──┐
|
||||
│Client├─┼──►│Session├──┘ │ │ └►┌─────────┐
|
||||
└──────┘ │ └───────┘ │ │ │Character│
|
||||
│ │ │ ┌►└─────────┘
|
||||
┌──────┐ │ ┌───────┐ ┌──┼───────┼──┘ ▼
|
||||
│Client├─┼──►│Session├──┘ │ │
|
||||
└──────┘ │ └───────┘ └───────┘
|
||||
│
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<blockquote>
|
||||
<div><p>Note that even if multiple Sessions puppet one Character, there is only ever one instance of that Character.</p>
|
||||
</div></blockquote>
|
||||
</section>
|
||||
<section id="returning-data-to-the-session">
|
||||
<h2>Returning data to the session<a class="headerlink" href="#returning-data-to-the-session" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Returning data to the session<a class="headerlink" href="#returning-data-to-the-session" title="Permalink to this headline">¶</a></h3>
|
||||
<p>When you use <code class="docutils literal notranslate"><span class="pre">msg()</span></code> to return data to a user, the object on which you call the <code class="docutils literal notranslate"><span class="pre">msg()</span></code> matters. The
|
||||
<code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE</span></code> also matters, especially if greater than 1.</p>
|
||||
<p>For example, if you use <code class="docutils literal notranslate"><span class="pre">account.msg("hello")</span></code> there is no way for evennia to know which session it
|
||||
|
|
@ -231,44 +176,23 @@ script triggers the Command.</p></li>
|
|||
</ul>
|
||||
</section>
|
||||
<section id="customizing-the-session-object">
|
||||
<h2>Customizing the Session object<a class="headerlink" href="#customizing-the-session-object" title="Permalink to this headline">¶</a></h2>
|
||||
<p>When would one want to customize the Session object? Consider for example a character creation
|
||||
system: You might decide to keep this on the out-of-character level. This would mean that you create
|
||||
the character at the end of some sort of menu choice. The actual char-create cmdset would then
|
||||
normally be put on the account. This works fine as long as you are <code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE</span></code> below 2.
|
||||
For higher modes, replacing the Account cmdset will affect <em>all</em> your connected sessions, also those
|
||||
not involved in character creation. In this case you want to instead put the char-create cmdset on
|
||||
the Session level - then all other sessions will keep working normally despite you creating a new
|
||||
character in one of them.</p>
|
||||
<p>By default, the session object gets the <code class="docutils literal notranslate"><span class="pre">commands.default_cmdsets.UnloggedinCmdSet</span></code> when the user
|
||||
first connects. Once the session is authenticated it has <em>no</em> default sets. To add a “logged-in”
|
||||
cmdset to the Session, give the path to the cmdset class with <code class="docutils literal notranslate"><span class="pre">settings.CMDSET_SESSION</span></code>. This set
|
||||
<h3>Customizing the Session object<a class="headerlink" href="#customizing-the-session-object" title="Permalink to this headline">¶</a></h3>
|
||||
<p>When would one want to customize the Session object? Consider for example a character creation system: You might decide to keep this on the out-of-character level. This would mean that you create the character at the end of some sort of menu choice. The actual char-create cmdset would then normally be put on the account. This works fine as long as you are <code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE</span></code> below 2. For higher modes, replacing the Account cmdset will affect <em>all</em> your connected sessions, also those not involved in character creation. In this case you want to instead put the char-create cmdset on the Session level - then all other sessions will keep working normally despite you creating a new character in one of them.</p>
|
||||
<p>By default, the session object gets the <code class="docutils literal notranslate"><span class="pre">commands.default_cmdsets.UnloggedinCmdSet</span></code> when the user first connects. Once the session is authenticated it has <em>no</em> default sets. To add a “logged-in” cmdset to the Session, give the path to the cmdset class with <code class="docutils literal notranslate"><span class="pre">settings.CMDSET_SESSION</span></code>. This set
|
||||
will then henceforth always be present as soon as the account logs in.</p>
|
||||
<p>To customize further you can completely override the Session with your own subclass. To replace the
|
||||
default Session class, change <code class="docutils literal notranslate"><span class="pre">settings.SERVER_SESSION_CLASS</span></code> to point to your custom class. This is
|
||||
a dangerous practice and errors can easily make your game unplayable. Make sure to take heed of the
|
||||
<a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/server/session.py">original</a> and make your
|
||||
changes carefully.</p>
|
||||
<p>To customize further you can completely override the Session with your own subclass. To replace the default Session class, change <code class="docutils literal notranslate"><span class="pre">settings.SERVER_SESSION_CLASS</span></code> to point to your custom class. This is a dangerous practice and errors can easily make your game unplayable. Make sure to take heed of the <a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/server/session.py">original</a> and make your changes carefully.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="portal-and-server-sessions">
|
||||
<h2>Portal and Server Sessions<a class="headerlink" href="#portal-and-server-sessions" title="Permalink to this headline">¶</a></h2>
|
||||
<p><em>Note: This is considered an advanced topic. You don’t need to know this on a first read-through.</em></p>
|
||||
<p>Evennia is split into two parts, the <a class="reference internal" href="Portal-And-Server.html"><span class="doc std std-doc">Portal and the Server</span></a>. Each side tracks
|
||||
its own Sessions, syncing them to each other.</p>
|
||||
<p>Evennia is split into two parts, the <a class="reference internal" href="Portal-And-Server.html"><span class="doc std std-doc">Portal and the Server</span></a>. Each side tracks its own Sessions, syncing them to each other.</p>
|
||||
<p>The “Session” we normally refer to is actually the <code class="docutils literal notranslate"><span class="pre">ServerSession</span></code>. Its counter-part on the Portal
|
||||
side is the <code class="docutils literal notranslate"><span class="pre">PortalSession</span></code>. Whereas the server sessions deal with game states, the portal session
|
||||
deals with details of the connection-protocol itself. The two are also acting as backups of critical
|
||||
data such as when the server reboots.</p>
|
||||
<p>New Account connections are listened for and handled by the Portal using the [protocols](Portal-And-
|
||||
Server) it understands (such as telnet, ssh, webclient etc). When a new connection is established, a
|
||||
<code class="docutils literal notranslate"><span class="pre">PortalSession</span></code> is created on the Portal side. This session object looks different depending on
|
||||
which protocol is used to connect, but all still have a minimum set of attributes that are generic
|
||||
to all
|
||||
sessions.</p>
|
||||
<p>These common properties are piped from the Portal, through the AMP connection, to the Server, which
|
||||
is now informed a new connection has been established. On the Server side, a <code class="docutils literal notranslate"><span class="pre">ServerSession</span></code> object
|
||||
is created to represent this. There is only one type of <code class="docutils literal notranslate"><span class="pre">ServerSession</span></code>; It looks the same
|
||||
regardless of how the Account connects.</p>
|
||||
<p>New Account connections are listened for and handled by the Portal using the [protocols](Portal-And- Server) it understands (such as telnet, ssh, webclient etc). When a new connection is established, a <code class="docutils literal notranslate"><span class="pre">PortalSession</span></code> is created on the Portal side. This session object looks different depending on which protocol is used to connect, but all still have a minimum set of attributes that are generic to all sessions.</p>
|
||||
<p>These common properties are piped from the Portal, through the AMP connection, to the Server, which is now informed a new connection has been established. On the Server side, a <code class="docutils literal notranslate"><span class="pre">ServerSession</span></code> object is created to represent this. There is only one type of <code class="docutils literal notranslate"><span class="pre">ServerSession</span></code>; It looks the same regardless of how the Account connects.</p>
|
||||
<p>From now on, there is a one-to-one match between the <code class="docutils literal notranslate"><span class="pre">ServerSession</span></code> on one side of the AMP
|
||||
connection and the <code class="docutils literal notranslate"><span class="pre">PortalSession</span></code> on the other. Data arriving to the Portal Session is sent on to
|
||||
its mirror Server session and vice versa.</p>
|
||||
|
|
@ -284,26 +208,21 @@ Portal side. When the Server comes back up, this data is returned by the Portal
|
|||
in sync. This way an Account’s login status and other connection-critical things can survive a
|
||||
server reboot (assuming the Portal is not stopped at the same time, obviously).</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section id="sessionhandlers">
|
||||
<h2>Sessionhandlers<a class="headerlink" href="#sessionhandlers" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Sessionhandlers<a class="headerlink" href="#sessionhandlers" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Both the Portal and Server each have a <em>sessionhandler</em> to manage the connections. These handlers
|
||||
are global entities contain all methods for relaying data across the AMP bridge. All types of
|
||||
Sessions hold a reference to their respective Sessionhandler (the property is called
|
||||
<code class="docutils literal notranslate"><span class="pre">sessionhandler</span></code>) so they can relay data. See <a class="reference internal" href="../Concepts/Protocols.html"><span class="doc std std-doc">protocols</span></a> for more info
|
||||
on building new protocols.</p>
|
||||
<p>To get all Sessions in the game (i.e. all currently connected clients), you access the server-side
|
||||
Session handler, which you get by</p>
|
||||
<code class="docutils literal notranslate"><span class="pre">sessionhandler</span></code>) so they can relay data. See <a class="reference internal" href="../Concepts/Protocols.html"><span class="doc std std-doc">protocols</span></a> for more info on building new protocols.</p>
|
||||
<p>To get all Sessions in the game (i.e. all currently connected clients), you access the server-side Session handler, which you get by</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.server.sessionhandler</span> <span class="kn">import</span> <span class="n">SESSION_HANDLER</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<blockquote>
|
||||
<div><p>Note: The <code class="docutils literal notranslate"><span class="pre">SESSION_HANDLER</span></code> singleton has an older alias <code class="docutils literal notranslate"><span class="pre">SESSIONS</span></code> that is commonly seen in
|
||||
various places as well.</p>
|
||||
<div><p>Note: The <code class="docutils literal notranslate"><span class="pre">SESSION_HANDLER</span></code> singleton has an older alias <code class="docutils literal notranslate"><span class="pre">SESSIONS</span></code> that is commonly seen in various places as well.</p>
|
||||
</div></blockquote>
|
||||
<p>See the
|
||||
<a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/server/sessionhandler.py">sessionhandler.py</a>
|
||||
module for details on the capabilities of the <code class="docutils literal notranslate"><span class="pre">ServerSessionHandler</span></code>.</p>
|
||||
<p>See the <a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/server/sessionhandler.py">sessionhandler.py</a> module for details on the capabilities of the <code class="docutils literal notranslate"><span class="pre">ServerSessionHandler</span></code>.</p>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
|
@ -323,10 +242,10 @@ module for details on the capabilities of the <code class="docutils literal notr
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Accounts.html" title="Accounts"
|
||||
<a href="Typeclasses.html" title="Typeclasses"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Typeclasses.html" title="Typeclasses"
|
||||
<a href="Portal-And-Server.html" title="Portal And Server"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" >Core Components</a> »</li>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Game website" href="Website.html" />
|
||||
<link rel="prev" title="Locks" href="Locks.html" />
|
||||
<link rel="prev" title="TickerHandler" href="TickerHandler.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
|
|
@ -33,7 +33,7 @@
|
|||
<a href="Website.html" title="Game website"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Locks.html" title="Locks"
|
||||
<a href="TickerHandler.html" title="TickerHandler"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" accesskey="U">Core Components</a> »</li>
|
||||
|
|
@ -63,15 +63,17 @@
|
|||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Signals</a><ul>
|
||||
<li><a class="reference internal" href="#attaching-a-handler-to-a-signal">Attaching a handler to a signal</a></li>
|
||||
<li><a class="reference internal" href="#working-with-signals">Working with Signals</a><ul>
|
||||
<li><a class="reference internal" href="#available-signals">Available signals</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Locks.html"
|
||||
title="previous chapter">Locks</a></p>
|
||||
<p class="topless"><a href="TickerHandler.html"
|
||||
title="previous chapter">TickerHandler</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Website.html"
|
||||
title="next chapter">Game website</a></p>
|
||||
|
|
@ -119,8 +121,8 @@ you can “attach” any number of event-handlers to these signals. You can atta
|
|||
any number of handlers and they’ll all fire whenever any entity triggers the
|
||||
signal.</p>
|
||||
<p>Evennia uses the <a class="reference external" href="https://docs.djangoproject.com/en/2.2/topics/signals/">Django Signal system</a>.</p>
|
||||
<section id="attaching-a-handler-to-a-signal">
|
||||
<h2>Attaching a handler to a signal<a class="headerlink" href="#attaching-a-handler-to-a-signal" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="working-with-signals">
|
||||
<h2>Working with Signals<a class="headerlink" href="#working-with-signals" title="Permalink to this headline">¶</a></h2>
|
||||
<p>First you create your handler</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
|
||||
<span class="k">def</span> <span class="nf">myhandler</span><span class="p">(</span><span class="n">sender</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||||
|
|
@ -146,9 +148,8 @@ like this:</p>
|
|||
<span class="n">signals</span><span class="o">.</span><span class="n">SIGNAL_ACCOUNT_POST_CONNECT</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">myhandler</span><span class="p">,</span> <span class="n">account</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="available-signals">
|
||||
<h2>Available signals<a class="headerlink" href="#available-signals" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Available signals<a class="headerlink" href="#available-signals" title="Permalink to this headline">¶</a></h3>
|
||||
<p>All signals (including some django-specific defaults) are available in the module
|
||||
<code class="docutils literal notranslate"><span class="pre">evennia.server.signals</span></code>
|
||||
(with a shortcut <code class="docutils literal notranslate"><span class="pre">evennia.signals</span></code>). Signals are named by the sender type. So <code class="docutils literal notranslate"><span class="pre">SIGNAL_ACCOUNT_*</span></code>
|
||||
|
|
@ -216,6 +217,7 @@ decorator (only relevant for unit testing)</p></li>
|
|||
<li><p><code class="docutils literal notranslate"><span class="pre">connection_creation</span></code> - sent when making initial connection to database.</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
|
|
@ -237,7 +239,7 @@ decorator (only relevant for unit testing)</p></li>
|
|||
<a href="Website.html" title="Game website"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Locks.html" title="Locks"
|
||||
<a href="TickerHandler.html" title="TickerHandler"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" >Core Components</a> »</li>
|
||||
|
|
|
|||
|
|
@ -63,11 +63,13 @@
|
|||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Tags</a><ul>
|
||||
<li><a class="reference internal" href="#working-with-tags">Working with Tags</a><ul>
|
||||
<li><a class="reference internal" href="#properties-of-tags-and-aliases-and-permissions">Properties of Tags (and Aliases and Permissions)</a></li>
|
||||
<li><a class="reference internal" href="#adding-removing-tags">Adding/Removing Tags</a></li>
|
||||
<li><a class="reference internal" href="#searching-for-objects-with-a-given-tag">Searching for objects with a given tag</a></li>
|
||||
<li><a class="reference internal" href="#using-aliases-and-permissions">Using Aliases and Permissions</a></li>
|
||||
<li><a class="reference internal" href="#assorted-notes">Assorted notes</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#aliases-and-permissions">Aliases and Permissions</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
@ -137,8 +139,10 @@
|
|||
<p>Above, the tags inform us that the <code class="docutils literal notranslate"><span class="pre">Sword</span></code> is both sharp and can be wielded. If that’s all they do, they could just be a normal Python flag. When tags become important is if there are a lot of objects with different combinations of tags. Maybe you have a magical spell that dulls <em>all</em> sharp-edged objects in the castle - whether sword, dagger, spear or kitchen knife! You can then just grab all objects with the <code class="docutils literal notranslate"><span class="pre">has_sharp_edge</span></code> tag.
|
||||
Another example would be a weather script affecting all rooms tagged as <code class="docutils literal notranslate"><span class="pre">outdoors</span></code> or finding all characters tagged with <code class="docutils literal notranslate"><span class="pre">belongs_to_fighter_guild</span></code>.</p>
|
||||
<p>In Evennia, Tags are technically also used to implement <code class="docutils literal notranslate"><span class="pre">Aliases</span></code> (alternative names for objects) and <code class="docutils literal notranslate"><span class="pre">Permissions</span></code> (simple strings for <a class="reference internal" href="Locks.html"><span class="doc std std-doc">Locks</span></a> to check for).</p>
|
||||
<section id="working-with-tags">
|
||||
<h2>Working with Tags<a class="headerlink" href="#working-with-tags" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="properties-of-tags-and-aliases-and-permissions">
|
||||
<h2>Properties of Tags (and Aliases and Permissions)<a class="headerlink" href="#properties-of-tags-and-aliases-and-permissions" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Properties of Tags (and Aliases and Permissions)<a class="headerlink" href="#properties-of-tags-and-aliases-and-permissions" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Tags are <em>unique</em>. This means that there is only ever one Tag object with a given key and category.</p>
|
||||
<blockquote>
|
||||
<div><p>Not specifying a category (default) gives the tag a category of <code class="docutils literal notranslate"><span class="pre">None</span></code>, which is also considered a
|
||||
|
|
@ -172,10 +176,8 @@ free up the <em>category</em> property for any use you desire.</p></li>
|
|||
</ul>
|
||||
</section>
|
||||
<section id="adding-removing-tags">
|
||||
<h2>Adding/Removing Tags<a class="headerlink" href="#adding-removing-tags" title="Permalink to this headline">¶</a></h2>
|
||||
<p>You can tag any <em>typeclassed</em> object, namely <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a>, <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a>,
|
||||
<a class="reference internal" href="Scripts.html"><span class="doc std std-doc">Scripts</span></a> and <a class="reference internal" href="Channels.html"><span class="doc std std-doc">Channels</span></a>. General tags are added by the <em>Taghandler</em>. The
|
||||
tag handler is accessed as a property <code class="docutils literal notranslate"><span class="pre">tags</span></code> on the relevant entity:</p>
|
||||
<h3>Adding/Removing Tags<a class="headerlink" href="#adding-removing-tags" title="Permalink to this headline">¶</a></h3>
|
||||
<p>You can tag any <em>typeclassed</em> object, namely <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a>, <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a>, <a class="reference internal" href="Scripts.html"><span class="doc std std-doc">Scripts</span></a> and <a class="reference internal" href="Channels.html"><span class="doc std std-doc">Channels</span></a>. General tags are added by the <em>Taghandler</em>. The tag handler is accessed as a property <code class="docutils literal notranslate"><span class="pre">tags</span></code> on the relevant entity:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">mychair</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">"furniture"</span><span class="p">)</span>
|
||||
<span class="n">mychair</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">"furniture"</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">"luxurious"</span><span class="p">)</span>
|
||||
<span class="n">myroom</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">"dungeon#01"</span><span class="p">)</span>
|
||||
|
|
@ -198,7 +200,7 @@ You can also use the default <code class="docutils literal notranslate"><span cl
|
|||
<p>This tags the chair with a ‘furniture’ Tag (the one with a <code class="docutils literal notranslate"><span class="pre">None</span></code> category).</p>
|
||||
</section>
|
||||
<section id="searching-for-objects-with-a-given-tag">
|
||||
<h2>Searching for objects with a given tag<a class="headerlink" href="#searching-for-objects-with-a-given-tag" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Searching for objects with a given tag<a class="headerlink" href="#searching-for-objects-with-a-given-tag" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Usually tags are used as a quick way to find tagged database entities. You can retrieve all objects
|
||||
with a given Tag like this in code:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="kn">import</span> <span class="nn">evennia</span>
|
||||
|
|
@ -222,14 +224,9 @@ with a given Tag like this in code:</p>
|
|||
</pre></div>
|
||||
</div>
|
||||
<blockquote>
|
||||
<div><p>Note that searching for just “furniture” will only return the objects tagged with the “furniture”
|
||||
tag that
|
||||
has a category of <code class="docutils literal notranslate"><span class="pre">None</span></code>. We must explicitly give the category to get the “luxurious” furniture.</p>
|
||||
<div><p>Note that searching for just “furniture” will only return the objects tagged with the “furniture” tag that has a category of <code class="docutils literal notranslate"><span class="pre">None</span></code>. We must explicitly give the category to get the “luxurious” furniture.</p>
|
||||
</div></blockquote>
|
||||
<p>Using any of the <code class="docutils literal notranslate"><span class="pre">search_tag</span></code> variants will all return <a class="reference external" href="https://docs.djangoproject.com/en/2.1/ref/models/querysets/">Django
|
||||
Querysets</a>, including if you only have
|
||||
one match. You can treat querysets as lists and iterate over them, or continue building search
|
||||
queries with them.</p>
|
||||
<p>Using any of the <code class="docutils literal notranslate"><span class="pre">search_tag</span></code> variants will all return <a class="reference external" href="https://docs.djangoproject.com/en/2.1/ref/models/querysets/">Django Querysets</a>, including if you only have one match. You can treat querysets as lists and iterate over them, or continue building search queries with them.</p>
|
||||
<p>Remember when searching that not setting a category means setting it to <code class="docutils literal notranslate"><span class="pre">None</span></code> - this does <em>not</em>
|
||||
mean that category is undefined, rather <code class="docutils literal notranslate"><span class="pre">None</span></code> is considered the default, unnamed category.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">evennia</span>
|
||||
|
|
@ -244,16 +241,16 @@ mean that category is undefined, rather <code class="docutils literal notranslat
|
|||
<span class="n">objs</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_tag</span><span class="p">(</span><span class="s2">"foo"</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">"bar"</span><span class="p">)</span>
|
||||
<span class="c1"># or</span>
|
||||
<span class="n">objs</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_tag</span><span class="p">(</span><span class="n">category</span><span class="o">=</span><span class="s2">"bar"</span><span class="p">)</span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>There is also an in-game command that deals with assigning and using (<a class="reference internal" href="Objects.html"><span class="doc std std-doc">Object-</span></a>) tags:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> @tag/search furniture
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> tag/search furniture
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="using-aliases-and-permissions">
|
||||
<h2>Using Aliases and Permissions<a class="headerlink" href="#using-aliases-and-permissions" title="Permalink to this headline">¶</a></h2>
|
||||
</section>
|
||||
<section id="aliases-and-permissions">
|
||||
<h2>Aliases and Permissions<a class="headerlink" href="#aliases-and-permissions" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Aliases and Permissions are implemented using normal TagHandlers that simply save Tags with a
|
||||
different <code class="docutils literal notranslate"><span class="pre">tagtype</span></code>. These handlers are named <code class="docutils literal notranslate"><span class="pre">aliases</span></code> and <code class="docutils literal notranslate"><span class="pre">permissions</span></code> on all Objects. They are
|
||||
used in the same way as Tags above:</p>
|
||||
|
|
@ -267,17 +264,6 @@ used in the same way as Tags above:</p>
|
|||
<p>and so on. Similarly to how <code class="docutils literal notranslate"><span class="pre">@tag</span></code> works in-game, there is also the <code class="docutils literal notranslate"><span class="pre">@perm</span></code> command for assigning
|
||||
permissions and <code class="docutils literal notranslate"><span class="pre">@alias</span></code> command for aliases.</p>
|
||||
</section>
|
||||
<section id="assorted-notes">
|
||||
<h2>Assorted notes<a class="headerlink" href="#assorted-notes" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Generally, tags are enough on their own for grouping objects. Having no tag <code class="docutils literal notranslate"><span class="pre">category</span></code> is perfectly
|
||||
fine and the normal operation. Simply adding a new Tag for grouping objects is often better than
|
||||
making a new category. So think hard before deciding you really need to categorize your Tags.</p>
|
||||
<p>That said, tag categories can be useful if you build some game system that uses tags. You can then
|
||||
use tag categories to make sure to separate tags created with this system from any other tags
|
||||
created elsewhere. You can then supply custom search methods that <em>only</em> find objects tagged with
|
||||
tags of that category. An example of this
|
||||
is found in the <a class="reference internal" href="../Concepts/Zones.html"><span class="doc std std-doc">Zone tutorial</span></a>.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<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="Locks" href="Locks.html" />
|
||||
<link rel="next" title="Signals" href="Signals.html" />
|
||||
<link rel="prev" title="MonitorHandler" href="MonitorHandler.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Locks.html" title="Locks"
|
||||
<a href="Signals.html" title="Signals"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="MonitorHandler.html" title="MonitorHandler"
|
||||
|
|
@ -75,8 +75,8 @@
|
|||
<p class="topless"><a href="MonitorHandler.html"
|
||||
title="previous chapter">MonitorHandler</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Locks.html"
|
||||
title="next chapter">Locks</a></p>
|
||||
<p class="topless"><a href="Signals.html"
|
||||
title="next chapter">Signals</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
|
|
@ -237,7 +237,7 @@ same time without input from something else.</p>
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Locks.html" title="Locks"
|
||||
<a href="Signals.html" title="Signals"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="MonitorHandler.html" title="MonitorHandler"
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
<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="Sessions" href="Sessions.html" />
|
||||
<link rel="prev" title="Core Components" href="Components-Overview.html" />
|
||||
<link rel="next" title="Accounts" href="Accounts.html" />
|
||||
<link rel="prev" title="Sessions" href="Sessions.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="related navigation">
|
||||
<h3>Navigation</h3>
|
||||
|
|
@ -30,10 +30,10 @@
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Sessions.html" title="Sessions"
|
||||
<a href="Accounts.html" title="Accounts"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Components-Overview.html" title="Core Components"
|
||||
<a href="Sessions.html" title="Sessions"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" accesskey="U">Core Components</a> »</li>
|
||||
|
|
@ -64,25 +64,29 @@
|
|||
<ul>
|
||||
<li><a class="reference internal" href="#">Typeclasses</a><ul>
|
||||
<li><a class="reference internal" href="#difference-between-typeclasses-and-classes">Difference between typeclasses and classes</a></li>
|
||||
<li><a class="reference internal" href="#working-with-typeclasses">Working with typeclasses</a><ul>
|
||||
<li><a class="reference internal" href="#creating-a-new-typeclass">Creating a new typeclass</a></li>
|
||||
<li><a class="reference internal" href="#about-typeclass-properties">About typeclass properties</a></li>
|
||||
<li><a class="reference internal" href="#overloading-hooks">Overloading hooks</a></li>
|
||||
<li><a class="reference internal" href="#querying-for-typeclasses">Querying for typeclasses</a></li>
|
||||
<li><a class="reference internal" href="#updating-existing-typeclass-instances">Updating existing typeclass instances</a></li>
|
||||
<li><a class="reference internal" href="#swap-typeclass">Swap typeclass</a></li>
|
||||
<li><a class="reference internal" href="#how-typeclasses-actually-work">How typeclasses actually work</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#how-typeclasses-actually-work">How typeclasses actually work</a><ul>
|
||||
<li><a class="reference internal" href="#caveats">Caveats</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#will-i-run-out-of-dbrefs">Will I run out of dbrefs?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="Components-Overview.html"
|
||||
title="previous chapter">Core Components</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Sessions.html"
|
||||
title="next chapter">Sessions</a></p>
|
||||
title="previous chapter">Sessions</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="Accounts.html"
|
||||
title="next chapter">Accounts</a></p>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
|
|
@ -115,57 +119,52 @@
|
|||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="typeclasses">
|
||||
<h1>Typeclasses<a class="headerlink" href="#typeclasses" title="Permalink to this headline">¶</a></h1>
|
||||
<p><em>Typeclasses</em> form the core of Evennia’s data storage. It allows Evennia to represent any number of
|
||||
different game entities as Python classes, without having to modify the database schema for every
|
||||
new type.</p>
|
||||
<p><em>Typeclasses</em> form the core of Evennia’s data storage. It allows Evennia to represent any number of different game entities as Python classes, without having to modify the database schema for every new type.</p>
|
||||
<p>In Evennia the most important game entities, <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a>, <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a>, <a class="reference internal" href="Scripts.html"><span class="doc std std-doc">Scripts</span></a> and <a class="reference internal" href="Channels.html"><span class="doc std std-doc">Channels</span></a> are all Python classes inheriting, at varying distance, from <code class="docutils literal notranslate"><span class="pre">evennia.typeclasses.models.TypedObject</span></code>. In the documentation we refer to these objects as being “typeclassed” or even “being a typeclass”.</p>
|
||||
<p>This is how the inheritance looks for the typeclasses in Evennia:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">TypedObject</span>
|
||||
<span class="n">_________________</span><span class="o">|</span><span class="n">_________________________________</span>
|
||||
<span class="o">|</span> <span class="o">|</span> <span class="o">|</span> <span class="o">|</span>
|
||||
<span class="mi">1</span><span class="p">:</span> <span class="n">AccountDB</span> <span class="n">ObjectDB</span> <span class="n">ScriptDB</span> <span class="n">ChannelDB</span>
|
||||
<span class="o">|</span> <span class="o">|</span> <span class="o">|</span> <span class="o">|</span>
|
||||
<span class="mi">2</span><span class="p">:</span> <span class="n">DefaultAccount</span> <span class="n">DefaultObject</span> <span class="n">DefaultScript</span> <span class="n">DefaultChannel</span>
|
||||
<span class="o">|</span> <span class="n">DefaultCharacter</span> <span class="o">|</span> <span class="o">|</span>
|
||||
<span class="o">|</span> <span class="n">DefaultRoom</span> <span class="o">|</span> <span class="o">|</span>
|
||||
<span class="o">|</span> <span class="n">DefaultExit</span> <span class="o">|</span> <span class="o">|</span>
|
||||
<span class="o">|</span> <span class="o">|</span> <span class="o">|</span> <span class="o">|</span>
|
||||
<span class="mi">3</span><span class="p">:</span> <span class="n">Account</span> <span class="n">Object</span> <span class="n">Script</span> <span class="n">Channel</span>
|
||||
<span class="n">Character</span>
|
||||
<span class="n">Room</span>
|
||||
<span class="n">Exit</span>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> ┌───────────┐
|
||||
│TypedObject│
|
||||
└─────▲─────┘
|
||||
┌───────────────┬────────┴──────┬────────────────┐
|
||||
┌────┴────┐ ┌────┴───┐ ┌────┴────┐ ┌────┴───┐
|
||||
1: │AccountDB│ │ScriptDB│ │ChannelDB│ │ObjectDB│
|
||||
└────▲────┘ └────▲───┘ └────▲────┘ └────▲───┘
|
||||
┌───────┴──────┐ ┌──────┴──────┐ ┌──────┴───────┐ ┌──────┴──────┐
|
||||
2: │DefaultAccount│ │DefaultScript│ │DefaultChannel│ │DefaultObject│
|
||||
└───────▲──────┘ └──────▲──────┘ └──────▲───────┘ └──────▲──────┘
|
||||
│ │ │ │ Evennia
|
||||
────────┼───────────────┼───────────────┼────────────────┼─────────
|
||||
│ │ │ │ Gamedir
|
||||
┌───┴───┐ ┌───┴──┐ ┌───┴───┐ ┌──────┐ │
|
||||
3: │Account│ │Script│ │Channel│ │Object├─┤
|
||||
└───────┘ └──────┘ └───────┘ └──────┘ │
|
||||
┌─────────┐ │
|
||||
│Character├─┤
|
||||
└─────────┘ │
|
||||
┌────┐ │
|
||||
│Room├─┤
|
||||
└────┘ │
|
||||
┌────┐ │
|
||||
│Exit├─┘
|
||||
└────┘
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p><strong>Level 1</strong> above is the “database model” level. This describes the database tables and fields
|
||||
(this is technically a <a class="reference external" href="https://docs.djangoproject.com/en/2.2/topics/db/models/">Django model</a>).</p></li>
|
||||
<li><p><strong>Level 2</strong> is where we find Evennia’s default implementations of the various game entities, on
|
||||
top of the database. These classes define all the hook methods that Evennia calls in various
|
||||
situations. <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> is a little special since it’s the parent for <code class="docutils literal notranslate"><span class="pre">DefaultCharacter</span></code>,
|
||||
<code class="docutils literal notranslate"><span class="pre">DefaultRoom</span></code> and <code class="docutils literal notranslate"><span class="pre">DefaultExit</span></code>. They are all grouped under level 2 because they all represents
|
||||
defaults to build from.</p></li>
|
||||
<li><p><strong>Level 3</strong>, finally, holds empty template classes created in your game directory. This is the
|
||||
level you are meant to modify and tweak as you please, overloading the defaults as befits your game.
|
||||
The templates inherit directly from their defaults, so <code class="docutils literal notranslate"><span class="pre">Object</span></code> inherits from <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> and
|
||||
<code class="docutils literal notranslate"><span class="pre">Room</span></code> inherits from <code class="docutils literal notranslate"><span class="pre">DefaultRoom</span></code>.</p></li>
|
||||
<li><p><strong>Level 1</strong> above is the “database model” level. This describes the database tables and fields (this is technically a <a class="reference external" href="https://docs.djangoproject.com/en/2.2/topics/db/models/">Django model</a>).</p></li>
|
||||
<li><p><strong>Level 2</strong> is where we find Evennia’s default implementations of the various game entities, on top of the database. These classes define all the hook methods that Evennia calls in various situations. <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> is a little special since it’s the parent for <code class="docutils literal notranslate"><span class="pre">DefaultCharacter</span></code>, <code class="docutils literal notranslate"><span class="pre">DefaultRoom</span></code> and <code class="docutils literal notranslate"><span class="pre">DefaultExit</span></code>. They are all grouped under level 2 because they all represents defaults to build from.</p></li>
|
||||
<li><p><strong>Level 3</strong>, finally, holds empty template classes created in your game directory. This is the level you are meant to modify and tweak as you please, overloading the defaults as befits your game. The templates inherit directly from their defaults, so <code class="docutils literal notranslate"><span class="pre">Object</span></code> inherits from <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> and <code class="docutils literal notranslate"><span class="pre">Room</span></code> inherits from <code class="docutils literal notranslate"><span class="pre">DefaultRoom</span></code>.</p></li>
|
||||
</ul>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">typeclass/list</span></code> command will provide a list of all typeclasses known to
|
||||
Evennia. This can be useful for getting a feel for what is available. Note
|
||||
however that if you add a new module with a class in it but do not import that
|
||||
module from anywhere, the <code class="docutils literal notranslate"><span class="pre">typeclass/list</span></code> will not find it. To make it known
|
||||
to Evennia you must import that module from somewhere.</p>
|
||||
<blockquote>
|
||||
<div><p>This diagram doesn’t include the <code class="docutils literal notranslate"><span class="pre">ObjectParent</span></code> mixin for <code class="docutils literal notranslate"><span class="pre">Object</span></code>, <code class="docutils literal notranslate"><span class="pre">Character</span></code>, <code class="docutils literal notranslate"><span class="pre">Room</span></code> and <code class="docutils literal notranslate"><span class="pre">Exit</span></code>. This establishes a common parent for those classes, for shared properties. See <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a> for more details.</p>
|
||||
</div></blockquote>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">typeclass/list</span></code> command will provide a list of all typeclasses known to Evennia. This can be useful for getting a feel for what is available. Note however that if you add a new module with a class in it but do not import that module from anywhere, the <code class="docutils literal notranslate"><span class="pre">typeclass/list</span></code> will not find it. To make it known to Evennia you must import that module from somewhere.</p>
|
||||
<section id="difference-between-typeclasses-and-classes">
|
||||
<h2>Difference between typeclasses and classes<a class="headerlink" href="#difference-between-typeclasses-and-classes" title="Permalink to this headline">¶</a></h2>
|
||||
<p>All Evennia classes inheriting from class in the table above share one important feature and two
|
||||
important limitations. This is why we don’t simply call them “classes” but “typeclasses”.</p>
|
||||
<span class="xref myst"></span>important limitations. This is why we don’t simply call them “classes” but “typeclasses”.</p>
|
||||
<ol>
|
||||
<li><p>A typeclass can save itself to the database. This means that some properties (actually not that
|
||||
many) on the class actually represents database fields and can only hold very specific data types.
|
||||
This is detailed <a class="reference internal" href="#about-typeclass-properties"><span class="std std-doc">below</span></a>.</p></li>
|
||||
<li><p>Due to its connection to the database, the typeclass’ name must be <em>unique</em> across the <em>entire</em>
|
||||
server namespace. That is, there must never be two same-named classes defined anywhere. So the below
|
||||
code would give an error (since <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> is now globally found both in this module and in the
|
||||
default library):</p>
|
||||
<li><p>A typeclass can save itself to the database. This means that some properties (actually not that many) on the class actually represents database fields and can only hold very specific data types.</p></li>
|
||||
<li><p>Due to its connection to the database, the typeclass’ name must be <em>unique</em> across the <em>entire</em> server namespace. That is, there must never be two same-named classes defined anywhere. So the below code would give an error (since <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> is now globally found both in this module and in the default library):</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">DefaultObject</span> <span class="k">as</span> <span class="n">BaseObject</span>
|
||||
<span class="k">class</span> <span class="nc">DefaultObject</span><span class="p">(</span><span class="n">BaseObject</span><span class="p">):</span>
|
||||
<span class="k">pass</span>
|
||||
|
|
@ -184,8 +183,10 @@ default library):</p>
|
|||
<p>Apart from this, a typeclass works like any normal Python class and you can
|
||||
treat it as such.</p>
|
||||
</section>
|
||||
<section id="working-with-typeclasses">
|
||||
<h2>Working with typeclasses<a class="headerlink" href="#working-with-typeclasses" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="creating-a-new-typeclass">
|
||||
<h2>Creating a new typeclass<a class="headerlink" href="#creating-a-new-typeclass" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Creating a new typeclass<a class="headerlink" href="#creating-a-new-typeclass" title="Permalink to this headline">¶</a></h3>
|
||||
<p>It’s easy to work with Typeclasses. Either you use an existing typeclass or you create a new Python class inheriting from an existing typeclass. Here is an example of creating a new type of Object:</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">DefaultObject</span>
|
||||
|
||||
|
|
@ -222,9 +223,6 @@ could point to it as <code class="docutils literal notranslate"><span class="pre
|
|||
functions take a lot of extra keywords allowing you to set things like <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attributes</span></a> and
|
||||
<a class="reference internal" href="Tags.html"><span class="doc std std-doc">Tags</span></a> all in one go. These keywords don’t use the <code class="docutils literal notranslate"><span class="pre">db_*</span></code> prefix. This will also automatically
|
||||
save the new instance to the database, so you don’t need to call <code class="docutils literal notranslate"><span class="pre">save()</span></code> explicitly.</p>
|
||||
</section>
|
||||
<section id="about-typeclass-properties">
|
||||
<h2>About typeclass properties<a class="headerlink" href="#about-typeclass-properties" title="Permalink to this headline">¶</a></h2>
|
||||
<p>An example of a database field is <code class="docutils literal notranslate"><span class="pre">db_key</span></code>. This stores the “name” of the entity you are modifying
|
||||
and can thus only hold a string. This is one way of making sure to update the <code class="docutils literal notranslate"><span class="pre">db_key</span></code>:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">chair</span><span class="o">.</span><span class="n">db_key</span> <span class="o">=</span> <span class="s2">"Table"</span>
|
||||
|
|
@ -282,14 +280,11 @@ entities using <a class="reference internal" href="../Evennia-API.html"><span cl
|
|||
available.</p>
|
||||
</section>
|
||||
<section id="overloading-hooks">
|
||||
<h2>Overloading hooks<a class="headerlink" href="#overloading-hooks" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The way to customize typeclasses is usually to overload <em>hook methods</em> on them. Hooks are methods
|
||||
that Evennia call in various situations. An example is the <code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code> hook on <code class="docutils literal notranslate"><span class="pre">Objects</span></code>,
|
||||
which is only called once, the very first time this object is saved to the database. Other examples
|
||||
are the <code class="docutils literal notranslate"><span class="pre">at_login</span></code> hook of Accounts and the <code class="docutils literal notranslate"><span class="pre">at_repeat</span></code> hook of Scripts.</p>
|
||||
<h3>Overloading hooks<a class="headerlink" href="#overloading-hooks" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The way to customize typeclasses is usually to overload <em>hook methods</em> on them. Hooks are methods that Evennia call in various situations. An example is the <code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code> hook on <code class="docutils literal notranslate"><span class="pre">Objects</span></code>, which is only called once, the very first time this object is saved to the database. Other examples are the <code class="docutils literal notranslate"><span class="pre">at_login</span></code> hook of Accounts and the <code class="docutils literal notranslate"><span class="pre">at_repeat</span></code> hook of Scripts.</p>
|
||||
</section>
|
||||
<section id="querying-for-typeclasses">
|
||||
<h2>Querying for typeclasses<a class="headerlink" href="#querying-for-typeclasses" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Querying for typeclasses<a class="headerlink" href="#querying-for-typeclasses" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Most of the time you search for objects in the database by using convenience methods like the
|
||||
<code class="docutils literal notranslate"><span class="pre">caller.search()</span></code> of <a class="reference internal" href="Commands.html"><span class="doc std std-doc">Commands</span></a> or the search functions like <code class="docutils literal notranslate"><span class="pre">evennia.search_objects</span></code>.</p>
|
||||
<p>You can however also query for them directly using <a class="reference external" href="https://docs.djangoproject.com/en/1.7/topics/db/queries/">Django’s query
|
||||
|
|
@ -323,7 +318,7 @@ example for Scripts:</p>
|
|||
you will always query all children on the database model.</p>
|
||||
</section>
|
||||
<section id="updating-existing-typeclass-instances">
|
||||
<h2>Updating existing typeclass instances<a class="headerlink" href="#updating-existing-typeclass-instances" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Updating existing typeclass instances<a class="headerlink" href="#updating-existing-typeclass-instances" title="Permalink to this headline">¶</a></h3>
|
||||
<p>If you already have created instances of Typeclasses, you can modify the <em>Python code</em> at any time -
|
||||
due to how Python inheritance works your changes will automatically be applied to all children once you have reloaded the server.</p>
|
||||
<p>However, database-saved data, like <code class="docutils literal notranslate"><span class="pre">db_*</span></code> fields, <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attributes</span></a>, <a class="reference internal" href="Tags.html"><span class="doc std std-doc">Tags</span></a> etc, are
|
||||
|
|
@ -359,7 +354,7 @@ line break, that’s only for readability in the wiki):</p>
|
|||
retroactively update objects more than necessary.</p>
|
||||
</section>
|
||||
<section id="swap-typeclass">
|
||||
<h2>Swap typeclass<a class="headerlink" href="#swap-typeclass" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Swap typeclass<a class="headerlink" href="#swap-typeclass" title="Permalink to this headline">¶</a></h3>
|
||||
<p>If you want to swap an already existing typeclass, there are two ways to do so: From in-game and via code. From inside the game you can use the default <code class="docutils literal notranslate"><span class="pre">@typeclass</span></code> command:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">typeclass</span> <span class="n">objname</span> <span class="o">=</span> <span class="n">path</span><span class="o">.</span><span class="n">to</span><span class="o">.</span><span class="n">new</span><span class="o">.</span><span class="n">typeclass</span>
|
||||
</pre></div>
|
||||
|
|
@ -376,20 +371,21 @@ retroactively update objects more than necessary.</p>
|
|||
</div>
|
||||
<p>The arguments to this method are described <a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia.typeclasses.models#typedobjectswap_typeclass">in the API docs here</a>.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="how-typeclasses-actually-work">
|
||||
<h2>How typeclasses actually work<a class="headerlink" href="#how-typeclasses-actually-work" title="Permalink to this headline">¶</a></h2>
|
||||
<p><em>This is considered an advanced section.</em></p>
|
||||
<p>Technically, typeclasses are <a class="reference external" href="https://docs.djangoproject.com/en/1.7/topics/db/models/#proxy-models">Django proxy models</a>. The only database
|
||||
models that are “real” in the typeclass system (that is, are represented by actual tables in the database) are <code class="docutils literal notranslate"><span class="pre">AccountDB</span></code>, <code class="docutils literal notranslate"><span class="pre">ObjectDB</span></code>, <code class="docutils literal notranslate"><span class="pre">ScriptDB</span></code> and <code class="docutils literal notranslate"><span class="pre">ChannelDB</span></code> (there are also <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attributes</span></a> and <a class="reference internal" href="Tags.html"><span class="doc std std-doc">Tags</span></a> but they are not typeclasses themselves). All the subclasses of them are “proxies”, extending them with Python code without actually modifying the database layout.</p>
|
||||
<p>Evennia modifies Django’s proxy model in various ways to allow them to work without any boiler plate (for example you don’t need to set the Django “proxy” property in the model <code class="docutils literal notranslate"><span class="pre">Meta</span></code> subclass, Evennia handles this for you using metaclasses). Evennia also makes sure you can query subclasses as well as patches django to allow multiple inheritance from the same base class.</p>
|
||||
</section>
|
||||
<section id="caveats">
|
||||
<h2>Caveats<a class="headerlink" href="#caveats" title="Permalink to this headline">¶</a></h2>
|
||||
<h3>Caveats<a class="headerlink" href="#caveats" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Evennia uses the <em>idmapper</em> to cache its typeclasses (Django proxy models) in memory. The idmapper allows things like on-object handlers and properties to be stored on typeclass instances and to not get lost as long as the server is running (they will only be cleared on a Server reload). Django does not work like this by default; by default every time you search for an object in the database you’ll get a <em>different</em> instance of that object back and anything you stored on it that was not in the database would be lost. The bottom line is that Evennia’s Typeclass instances subside in memory a lot longer than vanilla Django model instance do.</p>
|
||||
<p>There is one caveat to consider with this, and that relates to [making your own models](New-
|
||||
Models): Foreign relationships to typeclasses are cached by Django and that means that if you were to change an object in a foreign relationship via some other means than via that relationship, the object seeing the relationship may not reliably update but will still see its old cached version. Due to typeclasses staying so long in memory, stale caches of such relationships could be more
|
||||
visible than common in Django. See the <a class="reference external" href="https://github.com/evennia/evennia/issues/1098">closed issue #1098 and its comments</a> for examples and solutions.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="will-i-run-out-of-dbrefs">
|
||||
<h2>Will I run out of dbrefs?<a class="headerlink" href="#will-i-run-out-of-dbrefs" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Evennia does not re-use its <code class="docutils literal notranslate"><span class="pre">#dbrefs</span></code>. This means new objects get an ever-increasing <code class="docutils literal notranslate"><span class="pre">#dbref</span></code>, also if you delete older objects. There are technical and safety reasons for this. But you may wonder if this means you have to worry about a big game ‘running out’ of dbref integers eventually.</p>
|
||||
|
|
@ -415,10 +411,10 @@ visible than common in Django. See the <a class="reference external" href="https
|
|||
<a href="../py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Sessions.html" title="Sessions"
|
||||
<a href="Accounts.html" title="Accounts"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="Components-Overview.html" title="Core Components"
|
||||
<a href="Sessions.html" title="Sessions"
|
||||
>previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" >Core Components</a> »</li>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue