Updated HTML docs

This commit is contained in:
Griatch 2021-10-26 21:41:11 +02:00
parent 66d0ad0bc9
commit 7900aad365
2073 changed files with 32986 additions and 41197 deletions

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,25 +40,25 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="accounts">
<section class="tex2jax_ignore mathjax_ignore" id="accounts">
<h1>Accounts<a class="headerlink" href="#accounts" title="Permalink to this headline"></a></h1>
<p>All <em>users</em> (real people) that starts a game <a class="reference internal" href="Sessions.html"><span class="doc">Session</span></a> on Evennia are doing so through an
<p>All <em>users</em> (real people) that starts a game <a class="reference internal" href="Sessions.html"><span class="doc std std-doc">Session</span></a> on Evennia are doing so through an
object called <em>Account</em>. The Account object has no in-game representation, it represents a unique
game account. 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">Object</span></a>
(normally a <a class="reference external" href="Components/Objects.html#Character">Character</a>).</p>
game account. 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
Evennias <a class="reference external" href="Components/Sessions.html#Multisession-mode">MULTISESSION_MODE</a> setting.</p>
Evennias <a class="reference internal" href="Sessions.html#multisession-mode"><span class="std std-doc">MULTISESSION_MODE</span></a> setting.</p>
<p>Apart from storing login information and other account-specific data, the Account object is what is
chatting on <a class="reference internal" href="Communications.html"><span class="doc">Channels</span></a>. It is also a good place to store <a class="reference internal" href="Locks.html"><span class="doc">Permissions</span></a> to be
chatting on <a class="reference internal" href="Communications.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 as well as configuration options. The Account
object also has its own <a class="reference internal" href="Command-Sets.html"><span class="doc">CmdSet</span></a>, the <code class="docutils literal notranslate"><span class="pre">AccountCmdSet</span></code>.</p>
object also has its own <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>.</p>
<p>Logged into default evennia, you can use the <code class="docutils literal notranslate"><span class="pre">ooc</span></code> command to leave your current
<a class="reference internal" href="Objects.html"><span class="doc">character</span></a> and go into OOC mode. You are quite limited in this mode, basically it works
<a class="reference internal" href="Objects.html"><span class="doc std std-doc">character</span></a> and go into OOC mode. You are quite limited in this mode, basically it works
like a simple chat program. It acts as a staging area for switching between Characters (if your
game supports that) or as a safety mode if your Character gets deleted. Use <code class="docutils literal notranslate"><span class="pre">ic</span></code> to attempt to
(re)puppet a Character.</p>
<p>Note that the Account object can have, and often does have, a different set of
<a class="reference external" href="Components/Locks.html#Permissions">Permissions</a> from the Character they control. Normally you should put your
<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 cant escalate your
@ -70,18 +72,7 @@ principle create a system that changes an accounts typeclass dynamically).</p
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>Heres an example of modifying the default Account class in code:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># in mygame/typeclasses/accounts.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># in mygame/typeclasses/accounts.py</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">DefaultAccount</span>
@ -92,9 +83,10 @@ Evennia defaults to using this (it inherits directly from <code class="docutils
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">config_1</span> <span class="o">=</span> <span class="kc">True</span> <span class="c1"># default config self.db.config_2 = False # &quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">config_3</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1"># &quot;</span>
<span class="c1"># ... whatever else our game needs to know ``` Reload the server with `reload`. </span>
<span class="c1"># ... whatever else our game needs to know ``` Reload the server with `reload`.</span>
</pre></div>
</td></tr></table></div>
</div>
<p>… However, if you use <code class="docutils literal notranslate"><span class="pre">examine</span> <span class="pre">*self</span></code> (the asterisk makes you examine your Account object rather
than your Character), you wont see your new Attributes yet. This is because <code class="docutils literal notranslate"><span class="pre">at_account_creation</span></code>
is only called the very <em>first</em> time the Account is called and your Account object already exists
@ -112,7 +104,7 @@ the empty template we used above.</p>
</section>
<section id="properties-on-accounts">
<h2>Properties on Accounts<a class="headerlink" href="#properties-on-accounts" title="Permalink to this headline"></a></h2>
<p>Beyond those properties assigned to all typeclassed objects (see <a class="reference internal" href="Typeclasses.html"><span class="doc">Typeclasses</span></a>), the
<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>
@ -128,11 +120,11 @@ a property <code class="docutils literal notranslate"><span class="pre">sessid</
</ul>
<p>Special handlers:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">cmdset</span></code> - This holds all the current <a class="reference internal" href="Commands.html"><span class="doc">Commands</span></a> of this Account. By default these are
<li><p><code class="docutils literal notranslate"><span class="pre">cmdset</span></code> - This holds all the current <a class="reference internal" href="Commands.html"><span class="doc std std-doc">Commands</span></a> of this Account. By default these are
the commands found in the cmdset defined by <code class="docutils literal notranslate"><span class="pre">settings.CMDSET_ACCOUNT</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">nicks</span></code> - This stores and handles <a class="reference internal" href="Nicks.html"><span class="doc">Nicks</span></a>, in the same way as nicks it works on Objects.
<li><p><code class="docutils literal notranslate"><span class="pre">nicks</span></code> - This stores and handles <a class="reference internal" href="Nicks.html"><span class="doc std std-doc">Nicks</span></a>, in the same way as nicks it works on Objects.
For Accounts, nicks are primarily used to store custom aliases for
<a class="reference external" href="Components/Communications.html#Channels">Channels</a>.</p></li>
<a class="reference internal" href="Channels.html"><span class="doc std std-doc">Channels</span></a>.</p></li>
</ul>
<p>Selection of special methods (see <code class="docutils literal notranslate"><span class="pre">evennia.DefaultAccount</span></code> for details):</p>
<ul class="simple">
@ -196,7 +188,7 @@ any.</p></li>
<h3>Versions</h3>
<ul>
<li><a href="Accounts.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,49 +40,44 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="attributes">
<section class="tex2jax_ignore mathjax_ignore" id="attributes">
<h1>Attributes<a class="headerlink" href="#attributes" title="Permalink to this headline"></a></h1>
<p>When performing actions in Evennia it is often important that you store data for later. If you write
a menu system, you have to keep track of the current location in the menu tree so that the player
can give correct subsequent commands. If you are writing a combat system, you might have a
combattants next roll get easier dependent on if their opponent failed. Your characters will
probably need to store roleplaying-attributes like strength and agility. And so on.</p>
<p><a class="reference internal" href="Typeclasses.html"><span class="doc">Typeclassed</span></a> game entities (<a class="reference internal" href="Accounts.html"><span class="doc">Accounts</span></a>, <a class="reference internal" href="Objects.html"><span class="doc">Objects</span></a>,
<a class="reference internal" href="Scripts.html"><span class="doc">Scripts</span></a> and <a class="reference internal" href="Communications.html"><span class="doc">Channels</span></a>) always have <em>Attributes</em> associated with them.
<p><a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclassed</span></a> 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="Communications.html"><span class="doc std std-doc">Channels</span></a>) always have <em>Attributes</em> associated with them.
Attributes are used to store any type of data on such entities. This is different from storing
data in properties already defined on entities (such as <code class="docutils literal notranslate"><span class="pre">key</span></code> or <code class="docutils literal notranslate"><span class="pre">location</span></code>) - these have very
specific names and require very specific types of data (for example you couldnt assign a python
<em>list</em> to the <code class="docutils literal notranslate"><span class="pre">key</span></code> property no matter how hard you tried). <code class="docutils literal notranslate"><span class="pre">Attributes</span></code> come into play when you
want to assign arbitrary data to arbitrary names.</p>
<p><strong>Attributes are <em>not</em> secure by default and any player may be able to change them unless you
<a class="reference external" href="Components/Attributes.html#locking-and-checking-attributes">prevent this behavior</a>.</strong></p>
<a class="reference internal" href="#locking-and-checking-attributes"><span class="std std-doc">prevent this behavior</span></a>.</strong></p>
<section id="the-db-and-ndb-shortcuts">
<h2>The .db and .ndb shortcuts<a class="headerlink" href="#the-db-and-ndb-shortcuts" title="Permalink to this headline"></a></h2>
<p>To save persistent data on a Typeclassed object you normally use the <code class="docutils literal notranslate"><span class="pre">db</span></code> (DataBase) operator. Lets
try to save some data to a <em>Rose</em> (an <a class="reference internal" href="Objects.html"><span class="doc">Object</span></a>):</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># saving</span>
try to save some data to a <em>Rose</em> (an <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Object</span></a>):</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># saving</span>
<span class="n">rose</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">has_thorns</span> <span class="o">=</span> <span class="kc">True</span>
<span class="c1"># getting it back</span>
<span class="n">is_ouch</span> <span class="o">=</span> <span class="n">rose</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">has_thorns</span>
</pre></div>
</td></tr></table></div>
</div>
<p>This looks like any normal Python assignment, but that <code class="docutils literal notranslate"><span class="pre">db</span></code> makes sure that an <em>Attribute</em> is
created behind the scenes and is stored in the database. Your rose will continue to have thorns
throughout the life of the server now, until you deliberately remove them.</p>
<p>To be sure to save <strong>non-persistently</strong>, i.e. to make sure NOT to create a database entry, you use
<code class="docutils literal notranslate"><span class="pre">ndb</span></code> (NonDataBase). It works in the same way:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># saving</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># saving</span>
<span class="n">rose</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">has_thorns</span> <span class="o">=</span> <span class="kc">True</span>
<span class="c1"># getting it back</span>
<span class="n">is_ouch</span> <span class="o">=</span> <span class="n">rose</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">has_thorns</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Technically, <code class="docutils literal notranslate"><span class="pre">ndb</span></code> has nothing to do with <code class="docutils literal notranslate"><span class="pre">Attributes</span></code>, despite how similar they look. No
<code class="docutils literal notranslate"><span class="pre">Attribute</span></code> object is created behind the scenes when using <code class="docutils literal notranslate"><span class="pre">ndb</span></code>. In fact the database is not
invoked at all since we are not interested in persistence. There is however an important reason to
@ -90,16 +87,15 @@ while it runs. Data stored on <code class="docutils literal notranslate"><span c
<code class="docutils literal notranslate"><span class="pre">&#64;examine</span></code> command.</p>
<p>You can also <code class="docutils literal notranslate"><span class="pre">del</span></code> properties on <code class="docutils literal notranslate"><span class="pre">db</span></code> and <code class="docutils literal notranslate"><span class="pre">ndb</span></code> as normal. This will for example delete an
<code class="docutils literal notranslate"><span class="pre">Attribute</span></code>:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="k">del</span> <span class="n">rose</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">has_thorns</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="k">del</span> <span class="n">rose</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">has_thorns</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Both <code class="docutils literal notranslate"><span class="pre">db</span></code> and <code class="docutils literal notranslate"><span class="pre">ndb</span></code> defaults to offering an <code class="docutils literal notranslate"><span class="pre">all</span></code> property on themselves. This returns all
associated attributes or non-persistent properties.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">list_of_all_rose_attributes</span> <span class="o">=</span> <span class="n">rose</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">all</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">list_of_all_rose_attributes</span> <span class="o">=</span> <span class="n">rose</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">all</span>
<span class="n">list_of_all_rose_ndb_attrs</span> <span class="o">=</span> <span class="n">rose</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">all</span>
</pre></div>
</td></tr></table></div>
</div>
<p>If you use <code class="docutils literal notranslate"><span class="pre">all</span></code> as the name of an attribute, this will be used instead. Later deleting your custom
<code class="docutils literal notranslate"><span class="pre">all</span></code> will return the default behaviour.</p>
</section>
@ -118,23 +114,16 @@ to doing <code class="docutils literal notranslate"><span class="pre">obj.db.att
returned, but the method takes keywords for returning the Attribute object itself. By supplying an
<code class="docutils literal notranslate"><span class="pre">accessing_object</span></code> to the call one can also make sure to check permissions before modifying
anything.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">add(...)</span></code> - this adds a new Attribute to the object. An optional <a class="reference internal" href="Locks.html"><span class="doc">lockstring</span></a> can be
<li><p><code class="docutils literal notranslate"><span class="pre">add(...)</span></code> - this adds a new Attribute to the object. An optional <a class="reference internal" href="Locks.html"><span class="doc std std-doc">lockstring</span></a> can be
supplied here to restrict future access and also the call itself may be checked against locks.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">remove(...)</span></code> - Remove the given Attribute. This can optionally be made to check for permission
before performing the deletion. - <code class="docutils literal notranslate"><span class="pre">clear(...)</span></code> - removes all Attributes from object.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">all(...)</span></code> - returns all Attributes (of the given category) attached to this object.</p></li>
</ul>
<p>See <a class="reference external" href="Components/Attributes.html#locking-and-checking-attributes">this section</a> for more about locking down Attribute
<p>See <a class="reference internal" href="#locking-and-checking-attributes"><span class="std std-doc">this section</span></a> for more about locking down Attribute
access and editing. The <code class="docutils literal notranslate"><span class="pre">Nattribute</span></code> offers no concept of access control.</p>
<p>Some examples:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="kn">import</span> <span class="nn">evennia</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="kn">import</span> <span class="nn">evennia</span>
<span class="n">obj</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_object</span><span class="p">(</span><span class="s2">&quot;MyObject&quot;</span><span class="p">)</span>
<span class="n">obj</span><span class="o">.</span><span class="n">attributes</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;test&quot;</span><span class="p">,</span> <span class="s2">&quot;testvalue&quot;</span><span class="p">)</span>
@ -143,7 +132,7 @@ access and editing. The <code class="docutils literal notranslate"><span class="
<span class="nb">print</span><span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">attributes</span><span class="o">.</span><span class="n">all</span><span class="p">())</span> <span class="c1"># prints [&lt;AttributeObject&gt;]</span>
<span class="n">obj</span><span class="o">.</span><span class="n">attributes</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s2">&quot;test&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
</section>
<section id="properties-of-attributes">
<h2>Properties of Attributes<a class="headerlink" href="#properties-of-attributes" title="Permalink to this headline"></a></h2>
@ -153,23 +142,23 @@ access and editing. The <code class="docutils literal notranslate"><span class="
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 external" href="Components/Attributes.html#What_types_of_data_can_I_save_in_an_Attribute">this section</a> for more info). In the
<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">Nicks</span></a> is an example of using
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 external" href="Components/Attributes.html#The_Attribute_Handler">Attribute
Handler</a>.</p></li>
in this way). To modify this property you need to use the
<a class="reference internal" href="#the-attributehandler"><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">Nicks</span></a> use it). It is only
accessible via the <a class="reference external" href="Components/Attributes.html#The_Attribute_Handler">Attribute Handler</a>.</p></li>
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="#the-attributehandler"><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">Nicks</span></a>, from Attributes (Nicks
<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
@ -196,7 +185,7 @@ database even runs completely in RAM if possible, alleviating much of the need t
during heavy loads.</p></li>
<li><p>A more valid reason for using non-persistent data is if you <em>want</em> to lose your state when logging
off. Maybe you are storing throw-away data that are re-initialized at server startup. Maybe you
are implementing some caching of your own. Or maybe you are testing a buggy <a class="reference internal" href="Scripts.html"><span class="doc">Script</span></a> that
are implementing some caching of your own. Or maybe you are testing a buggy <a class="reference internal" href="Scripts.html"><span class="doc std std-doc">Script</span></a> that
does potentially harmful stuff to your character object. With non-persistent storage you can be
sure
that whatever is messed up, its nothing a server reboot cant clear up.</p></li>
@ -227,7 +216,7 @@ not a big deal. But if you are accessing the Attribute as part of some big loop
amount of reads/writes you should first extract it to a temporary variable, operate on <em>that</em> and
then save the result back to the Attribute. If you are storing a more complex structure like a
<code class="docutils literal notranslate"><span class="pre">dict</span></code> or a <code class="docutils literal notranslate"><span class="pre">list</span></code> you should make sure to “disconnect” it from the database before looping over it,
as mentioned in the <a class="reference external" href="Components/Attributes.html#retrieving-mutable-objects">Retrieving Mutable Objects</a> section
as mentioned in the <a class="reference internal" href="#retrieving-mutable-objects"><span class="std std-doc">Retrieving Mutable Objects</span></a> section
below.</p>
<section id="storing-single-objects">
<h3>Storing single objects<a class="headerlink" href="#storing-single-objects" title="Permalink to this headline"></a></h3>
@ -244,19 +233,7 @@ guaranteeing you get the same object back when you access the Attribute later.</
inside it), Evennia will not know its there and wont convert it safely. Storing classes with
such hidden database objects is <em>not</em> supported and will lead to errors!</p></li>
</ul>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># Examples of valid single-value attribute data:</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># Examples of valid single-value attribute data:</span>
<span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">test1</span> <span class="o">=</span> <span class="mi">23</span>
<span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">test1</span> <span class="o">=</span> <span class="kc">False</span>
<span class="c1"># a database object (will be stored as an internal representation)</span>
@ -270,7 +247,7 @@ such hidden database objects is <em>not</em> supported and will lead to errors!<
<span class="n">invalid</span> <span class="o">=</span> <span class="n">Invalid</span><span class="p">(</span><span class="n">myobj</span><span class="p">)</span>
<span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">invalid</span> <span class="o">=</span> <span class="n">invalid</span> <span class="c1"># will cause error!</span>
</pre></div>
</td></tr></table></div>
</div>
</section>
<section id="storing-multiple-objects">
<h3>Storing multiple objects<a class="headerlink" href="#storing-multiple-objects" title="Permalink to this headline"></a></h3>
@ -294,7 +271,7 @@ containing dicts, etc.</p></li>
Since you can use any combination of the above iterables, this is generally not much of a
limitation.</p></li>
</ul>
<p>Any entity listed in the <a class="reference external" href="Components/Attributes.html#Storing-Single-Objects">Single object</a> section above can be
<p>Any entity listed in the <a class="reference internal" href="#storing-single-objects"><span class="std std-doc">Single object</span></a> section above can be
stored in the iterable.</p>
<blockquote>
<div><p>As mentioned in the previous section, database entities (aka typeclasses) are not possible to
@ -302,21 +279,7 @@ pickle. So when storing an iterable, Evennia must recursively traverse the itera
nested sub-iterables</em> in order to find eventual database objects to convert. This is a very fast
process but for efficiency you may want to avoid too deeply nested structures if you can.</p>
</div></blockquote>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># examples of valid iterables to store</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># examples of valid iterables to store</span>
<span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">test3</span> <span class="o">=</span> <span class="p">[</span><span class="n">obj1</span><span class="p">,</span> <span class="mi">45</span><span class="p">,</span> <span class="n">obj2</span><span class="p">,</span> <span class="mi">67</span><span class="p">]</span>
<span class="c1"># a dictionary</span>
<span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">test4</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;str&#39;</span><span class="p">:</span><span class="mi">34</span><span class="p">,</span> <span class="s1">&#39;dex&#39;</span><span class="p">:</span><span class="mi">56</span><span class="p">,</span> <span class="s1">&#39;agi&#39;</span><span class="p">:</span><span class="mi">22</span><span class="p">,</span> <span class="s1">&#39;int&#39;</span><span class="p">:</span><span class="mi">77</span><span class="p">}</span>
@ -332,7 +295,7 @@ process but for efficiency you may want to avoid too deeply nested structures if
<span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">test8</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="s2">&quot;test&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="mi">5</span>
<span class="c1"># test8 is now [4,2,{&quot;test&quot;:5}]</span>
</pre></div>
</td></tr></table></div>
</div>
</section>
<section id="retrieving-mutable-objects">
<h3>Retrieving Mutable objects<a class="headerlink" href="#retrieving-mutable-objects" title="Permalink to this headline"></a></h3>
@ -346,31 +309,23 @@ variable, change it and then re-assign it to the Attribute in order for it to sa
<p>There is however an important thing to remember. If you retrieve your mutable iterable into another
variable, e.g. <code class="docutils literal notranslate"><span class="pre">mylist2</span> <span class="pre">=</span> <span class="pre">obj.db.mylist</span></code>, your new variable (<code class="docutils literal notranslate"><span class="pre">mylist2</span></code>) will <em>still</em> be a
<code class="docutils literal notranslate"><span class="pre">_SaverList</span></code>. This means it will continue to save itself to the database whenever it is updated!</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">mylist</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">mylist</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span>
<span class="n">mylist</span> <span class="o">=</span> <span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">mylist</span>
<span class="n">mylist</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="mi">5</span> <span class="c1"># this will also update database</span>
<span class="nb">print</span><span class="p">(</span><span class="n">mylist</span><span class="p">)</span> <span class="c1"># this is now [1,2,3,5]</span>
<span class="nb">print</span><span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">mylist</span><span class="p">)</span> <span class="c1"># this is also [1,2,3,5]</span>
</pre></div>
</td></tr></table></div>
</div>
<p>To “disconnect” your extracted mutable variable from the database you simply need to convert the
<code class="docutils literal notranslate"><span class="pre">_Saver...</span></code> iterable to a normal Python structure. So to convert a <code class="docutils literal notranslate"><span class="pre">_SaverList</span></code>, you use the
<code class="docutils literal notranslate"><span class="pre">list()</span></code> function, for a <code class="docutils literal notranslate"><span class="pre">_SaverDict</span></code> you use <code class="docutils literal notranslate"><span class="pre">dict()</span></code> and so on.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">mylist</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">mylist</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span>
<span class="n">mylist</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">mylist</span><span class="p">)</span> <span class="c1"># convert to normal list</span>
<span class="n">mylist</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="mi">5</span>
<span class="nb">print</span><span class="p">(</span><span class="n">mylist</span><span class="p">)</span> <span class="c1"># this is now [1,2,3,5]</span>
<span class="nb">print</span><span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">mylist</span><span class="p">)</span> <span class="c1"># this is still [1,2,3,4]</span>
</pre></div>
</td></tr></table></div>
</div>
<p>A further problem comes with <em>nested mutables</em>, like a dict containing lists of dicts or something
like that. Each of these nested mutables would be <code class="docutils literal notranslate"><span class="pre">_Saver*</span></code> structures connected to the database and
disconnecting the outermost one of them would not disconnect those nested within. To make really
@ -379,6 +334,7 @@ function <code class="docutils literal notranslate"><span class="pre">evennia.ut
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.utils.dbserialize</span> <span class="kn">import</span> <span class="n">deserialize</span>
<span class="n">decoupled_mutables</span> <span class="o">=</span> <span class="n">deserialize</span><span class="p">(</span><span class="n">nested_mutables</span><span class="p">)</span>
</pre></div>
</div>
<p>The result of this operation will be a structure only consisting of normal Python mutables (<code class="docutils literal notranslate"><span class="pre">list</span></code>
@ -386,16 +342,7 @@ instead of <code class="docutils literal notranslate"><span class="pre">_SaverLi
<p>Remember, this is only valid for <em>mutable</em> iterables.
<a class="reference external" href="https://en.wikipedia.org/wiki/Immutable">Immutable</a> objects (strings, numbers, tuples etc) are
already disconnected from the database from the onset.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">mytup</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,[</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">])</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">mytup</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,[</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">])</span>
<span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">mytup</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">5</span> <span class="c1"># this fails since tuples are immutable</span>
<span class="c1"># this works but will NOT update database since outermost is a tuple</span>
@ -406,7 +353,7 @@ already disconnected from the database from the onset.</p>
<span class="c1"># iterable is a tuple, so we can edit the internal list as we want</span>
<span class="c1"># without affecting the database.</span>
</pre></div>
</td></tr></table></div>
</div>
<blockquote>
<div><p>Attributes will fetch data fresh from the database whenever you read them, so
if you are performing big operations on a mutable Attribute property (such as looping over a list
@ -420,7 +367,7 @@ way.</p>
<h2>Locking and checking Attributes<a class="headerlink" href="#locking-and-checking-attributes" title="Permalink to this headline"></a></h2>
<p>Attributes are normally not locked down by default, but you can easily change that for individual
Attributes (like those that may be game-sensitive in games with user-level building).</p>
<p>First you need to set a <em>lock string</em> on your Attribute. Lock strings are specified <a class="reference internal" href="Locks.html"><span class="doc">Locks</span></a>.
<p>First you need to set a <em>lock string</em> on your Attribute. Lock strings are specified <a class="reference internal" href="Locks.html"><span class="doc std std-doc">Locks</span></a>.
The relevant lock types are</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">attrread</span></code> - limits who may read the value of the Attribute</p></li>
@ -429,27 +376,16 @@ The relevant lock types are</p>
<p>You cannot use the <code class="docutils literal notranslate"><span class="pre">db</span></code> handler to modify Attribute object (such as setting a lock on them) - The
<code class="docutils literal notranslate"><span class="pre">db</span></code> handler will return the Attributes <em>value</em>, not the Attribute object itself. Instead you use
the AttributeHandler and set it to return the object instead of the value:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">lockstring</span> <span class="o">=</span> <span class="s2">&quot;attread:all();attredit:perm(Admins)&quot;</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">lockstring</span> <span class="o">=</span> <span class="s2">&quot;attread:all();attredit:perm(Admins)&quot;</span>
<span class="n">obj</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">&quot;myattr&quot;</span><span class="p">,</span> <span class="n">return_obj</span><span class="o">=</span><span class="kc">True</span><span class="p">)</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="n">lockstring</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Note the <code class="docutils literal notranslate"><span class="pre">return_obj</span></code> keyword which makes sure to return the <code class="docutils literal notranslate"><span class="pre">Attribute</span></code> object so its LockHandler
could be accessed.</p>
<p>A lock is no good if nothing checks it and by default Evennia does not check locks on Attributes.
You have to add a check to your commands/code wherever it fits (such as before setting an
Attribute).</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># in some command code where we want to limit</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># in some command code where we want to limit</span>
<span class="c1"># setting of a given attribute name on an object</span>
<span class="n">attr</span> <span class="o">=</span> <span class="n">obj</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="n">attrname</span><span class="p">,</span>
<span class="n">return_obj</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
@ -461,7 +397,7 @@ Attribute).</p>
<span class="k">return</span>
<span class="c1"># edit the Attribute here</span>
</pre></div>
</td></tr></table></div>
</div>
<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>
@ -525,7 +461,7 @@ those will check for the <code class="docutils literal notranslate"><span class=
<h3>Versions</h3>
<ul>
<li><a href="Attributes.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,15 +40,15 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="batch-code-processor">
<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">here</span></a>. This
<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>The batch-code processor is a superuser-only function, invoked by</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="o">&gt;</span> <span class="nd">@batchcode</span> <span class="n">path</span><span class="o">.</span><span class="n">to</span><span class="o">.</span><span class="n">batchcodefile</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> &gt; @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
@ -54,7 +56,7 @@ ending in “<code class="docutils literal notranslate"><span class="pre">.py</s
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-default notranslate"><div class="highlight"><pre><span></span> <span class="o">&gt;</span> <span class="nd">@batchcode</span> <span class="n">batch_code</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> &gt; @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>
@ -95,43 +97,7 @@ variable in one code block wont affect that variable in any other code block!
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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1">#</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1">#</span>
<span class="c1"># This is an example batch-code build file for Evennia. </span>
<span class="c1">#</span>
@ -169,13 +135,13 @@ a separate python module.</p></li>
<span class="n">string</span> <span class="o">+=</span> <span class="s2">&quot; Since debug was active, they were deleted again.&quot;</span>
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">string</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>This uses Evennias Python API to create three objects in sequence.</p>
</section>
<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-default notranslate"><div class="highlight"><pre><span></span> <span class="o">&gt;</span> <span class="nd">@batchcode</span><span class="o">/</span><span class="n">debug</span> <span class="n">tutorial_examples</span><span class="o">.</span><span class="n">example_batch_code</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> &gt; @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
@ -194,28 +160,18 @@ to go back and painstakingly delete them later.</p>
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">&#64;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-default notranslate"><div class="highlight"><pre><span></span> <span class="o">&gt;</span> <span class="nd">@batchcode</span><span class="o">/</span><span class="n">interactive</span> <span class="n">tutorial_examples</span><span class="o">.</span><span class="n">batch_code</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> &gt; @batchcode/interactive tutorial_examples.batch_code
</pre></div>
</div>
<p>You should see the following:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">01</span><span class="o">/</span><span class="mi">02</span><span class="p">:</span> <span class="n">red_button</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span><span class="n">red_button</span><span class="o">.</span><span class="n">RedButton</span><span class="p">,</span> <span class="p">[</span><span class="o">...</span><span class="p">]</span> <span class="p">(</span><span class="n">hh</span> <span class="k">for</span> <span class="n">help</span><span class="p">)</span>
<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>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><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>
<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>
@ -227,7 +183,7 @@ file. Observe that the block has <em>not</em> actually been executed at this poi
<span class="c1"># caller points to the one running the script</span>
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;A red button was created.&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></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
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>
@ -268,24 +224,13 @@ connect that room with a room you built in the current block. There are two ways
<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">Tags</span></a> or <em>Aliases</em>. You
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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1">#HEADER </span>
<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>
@ -298,22 +243,22 @@ dictionary of room references in an <code class="docutils literal notranslate"><
<span class="c1"># in another node we want to access the castle</span>
<span class="n">castle</span> <span class="o">=</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="n">get</span><span class="p">(</span><span class="s2">&quot;castle&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</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> doesnt 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
wed be wiping the dict every block!</p>
</section>
<section id="don-t-treat-a-batchcode-file-like-any-python-file">
<h3>Dont treat a batchcode file like any Python file<a class="headerlink" href="#don-t-treat-a-batchcode-file-like-any-python-file" title="Permalink to this headline"></a></h3>
<section id="dont-treat-a-batchcode-file-like-any-python-file">
<h3>Dont 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>
</section>
<section id="don-t-let-code-rely-on-the-batch-file-s-real-file-path">
<h3>Dont let code rely on the batch-files real file path<a class="headerlink" href="#don-t-let-code-rely-on-the-batch-file-s-real-file-path" title="Permalink to this headline"></a></h3>
<section id="dont-let-code-rely-on-the-batch-files-real-file-path">
<h3>Dont let code rely on the batch-files 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, dont 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 files “actual” location <em>will fail</em>. Batch code files are read as text and the strings
@ -352,8 +297,8 @@ executed. When the code runs it has no knowledge of what file those strings wher
<li><a class="reference internal" href="#limitations-and-caveats">Limitations and Caveats</a><ul>
<li><a class="reference internal" href="#safety">Safety</a></li>
<li><a class="reference internal" href="#no-communication-between-code-blocks">No communication between code blocks</a></li>
<li><a class="reference internal" href="#don-t-treat-a-batchcode-file-like-any-python-file">Dont treat a batchcode file like any Python file</a></li>
<li><a class="reference internal" href="#don-t-let-code-rely-on-the-batch-file-s-real-file-path">Dont let code rely on the batch-files real file path</a></li>
<li><a class="reference internal" href="#dont-treat-a-batchcode-file-like-any-python-file">Dont treat a batchcode file like any Python file</a></li>
<li><a class="reference internal" href="#dont-let-code-rely-on-the-batch-files-real-file-path">Dont let code rely on the batch-files real file path</a></li>
</ul>
</li>
</ul>
@ -380,7 +325,7 @@ executed. When the code runs it has no knowledge of what file those strings wher
<h3>Versions</h3>
<ul>
<li><a href="Batch-Code-Processor.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,15 +40,15 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="batch-command-processor">
<section class="tex2jax_ignore mathjax_ignore" id="batch-command-processor">
<h1>Batch Command Processor<a class="headerlink" href="#batch-command-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">here</span></a>. This
<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-default notranslate"><div class="highlight"><pre><span></span> <span class="o">&gt;</span> <span class="nd">@batchcommand</span> <span class="n">path</span><span class="o">.</span><span class="n">to</span><span class="o">.</span><span class="n">batchcmdfile</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> &gt; @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.
@ -54,7 +56,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-default notranslate"><div class="highlight"><pre><span></span> <span class="o">&gt;</span> <span class="nd">@batchcommand</span> <span class="n">batch_cmds</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> &gt; @batchcommand batch_cmds
</pre></div>
</div>
<p>A batch-command file contains a list of Evennia in-game commands separated by comments. The
@ -88,46 +90,7 @@ batch-files together, use the <code class="docutils literal notranslate"><span c
<code class="docutils literal notranslate"><span class="pre">&#64;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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1">#</span>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span> <span class="c1">#</span>
<span class="c1"># This is an example batch build file for Evennia. </span>
<span class="c1">#</span>
@ -168,9 +131,9 @@ batch-files together, use the <code class="docutils literal notranslate"><span c
<span class="c1"># The very last command in the file needs not be ended with #.</span>
drop button
</pre></div>
</td></tr></table></div>
</div>
<p>To test this, run <code class="docutils literal notranslate"><span class="pre">&#64;batchcommand</span></code> on the file:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="nd">@batchcommand</span> <span class="n">contrib</span><span class="o">.</span><span class="n">tutorial_examples</span><span class="o">.</span><span class="n">batch_cmds</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; @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
@ -187,11 +150,11 @@ useful for debugging and also if you have a large batch file and is only updatin
running the entire file again would be a waste of time (and in the case of <code class="docutils literal notranslate"><span class="pre">&#64;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">&#64;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-default notranslate"><div class="highlight"><pre><span></span> <span class="o">&gt;</span> <span class="nd">@batchcommand</span><span class="o">/</span><span class="n">interactive</span> <span class="n">tutorial_examples</span><span class="o">.</span><span class="n">batch_cmds</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> &gt; @batchcommand/interactive tutorial_examples.batch_cmds
</pre></div>
</div>
<p>You will see this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">01</span><span class="o">/</span><span class="mi">04</span><span class="p">:</span> <span class="nd">@create</span> <span class="n">button</span><span class="p">:</span><span class="n">tutorial_examples</span><span class="o">.</span><span class="n">red_button</span><span class="o">.</span><span class="n">RedButton</span> <span class="p">(</span><span class="n">hh</span> <span class="k">for</span> <span class="n">help</span><span class="p">)</span>
<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">&#64;create</span></code> command, the first out of only four commands in this batch
@ -222,7 +185,7 @@ when creating the file, so that you can walk (or teleport) to the right pl
<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">Command Set</span></a></em>: Imagine that you build a dark room, which
<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>
@ -241,7 +204,7 @@ creation. Its all doable, one just needs to keep it in mind.</p>
<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">Batch Code
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>
<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
@ -306,7 +269,7 @@ mode instead, see its readme for install instructions.</p></li>
<h3>Versions</h3>
<ul>
<li><a href="Batch-Command-Processor.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,7 +40,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="batch-processors">
<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
@ -72,8 +74,8 @@ just list in-game commands in a text file. The code-processor on the other hand
powerful but also more complex - it lets you use Evennias 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">Batch Command Processor</span></a></p></li>
<li><p>The <a class="reference internal" href="Batch-Code-Processor.html"><span class="doc">Batch Code Processor</span></a></p></li>
<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>
@ -103,7 +105,7 @@ work will the server give up and return an error message.</p>
need to add the editors encoding to Evennias <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">Text Encodings</span></a> and also in the
<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, doesnt mean that <em>Python</em> allows their use. Python syntax only allows
@ -160,7 +162,7 @@ allowed.</p>
<h3>Versions</h3>
<ul>
<li><a href="Batch-Processors.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,13 +40,13 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="bootstrap-components-and-utilities">
<section class="tex2jax_ignore mathjax_ignore" id="bootstrap-components-and-utilities">
<h1>Bootstrap Components and Utilities<a class="headerlink" href="#bootstrap-components-and-utilities" title="Permalink to this headline"></a></h1>
<p>Bootstrap provides many utilities and components you can use when customizing Evennias web
presence. Well go over a few examples here that you might find useful.</p>
<blockquote>
<div><p>Please take a look at either <a class="reference internal" href="../Howto/Starting/Part5/Add-a-simple-new-web-page.html"><span class="doc">the basic web tutorial</span></a> or
<a class="reference internal" href="../Howto/Web-Character-View-Tutorial.html"><span class="doc">the web character view tutorial</span></a>
<div><p>Please take a look at either <a class="reference internal" href="../Howto/Starting/Part5/Add-a-simple-new-web-page.html"><span class="doc std std-doc">the basic web tutorial</span></a> or
<a class="reference internal" href="../Howto/Web-Character-View-Tutorial.html"><span class="doc std std-doc">the web character view tutorial</span></a>
to get a feel for how to add pages to Evennias website to test these examples.</p>
</div></blockquote>
<section id="general-styling">
@ -129,7 +131,7 @@ width of the page - Evennias base site uses the former.</p>
<h3>Forms<a class="headerlink" href="#forms" title="Permalink to this headline"></a></h3>
<p><a class="reference external" href="https://getbootstrap.com/docs/4.0/components/forms/">Forms</a> are highly customizable with Bootstrap.
For a more in-depth look at how to use forms and their styles in your own Evennia site, please read
over <a class="reference internal" href="../Howto/Web-Character-Generation.html"><span class="doc">the web character gen tutorial.</span></a></p>
over <a class="reference internal" href="../Howto/Web-Character-Generation.html"><span class="doc std std-doc">the web character gen tutorial.</span></a></p>
</section>
</section>
</section>
@ -194,7 +196,7 @@ over <a class="reference internal" href="../Howto/Web-Character-Generation.html"
<h3>Versions</h3>
<ul>
<li><a href="Bootstrap-Components-and-Utilities.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,15 +40,15 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="channels">
<section class="tex2jax_ignore mathjax_ignore" id="channels">
<h1>Channels<a class="headerlink" href="#channels" title="Permalink to this headline"></a></h1>
<p>In a multiplayer game, players often need other means of in-game communication
than moving to the same room and use <code class="docutils literal notranslate"><span class="pre">say</span></code> or <code class="docutils literal notranslate"><span class="pre">emote</span></code>.</p>
<p><em>Channels</em> allows Evennias to act as a fancy chat program. When a player is
connected to a channel, sending a message to it will automatically distribute
it to every other subscriber.</p>
<p>Channels can be used both for chats between <a class="reference internal" href="Accounts.html"><span class="doc">Accounts</span></a> and between
<a class="reference internal" href="Objects.html"><span class="doc">Objects</span></a> (usually Characters). Chats could be both OOC
<p>Channels can be used both for chats between <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a> and between
<a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a> (usually Characters). Chats could be both OOC
(out-of-character) or IC (in-charcter) in nature. Some examples:</p>
<ul class="simple">
<li><p>A support channel for contacting staff (OOC)</p></li>
@ -65,41 +67,42 @@ auto-generated channel-commands and -cmdset. ChannelHandler was removed.</p>
<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 external" href="../api/evennia.commands.default.comms.CmdChannel.html">channel command</a>, <code class="docutils literal notranslate"><span class="pre">channel</span></code> (or
<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="viewing-and-joining-channels">
<h3>Viewing and joining channels<a class="headerlink" href="#viewing-and-joining-channels" title="Permalink to this headline"></a></h3>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">channel</span> <span class="o">-</span> <span class="n">shows</span> <span class="n">your</span> <span class="n">subscriptions</span>
<span class="n">channel</span><span class="o">/</span><span class="nb">all</span> <span class="o">-</span> <span class="n">shows</span> <span class="nb">all</span> <span class="n">subs</span> <span class="n">available</span> <span class="n">to</span> <span class="n">you</span>
<span class="n">channel</span><span class="o">/</span><span class="n">who</span> <span class="o">-</span> <span class="n">shows</span> <span class="n">who</span> <span class="n">subscribes</span> <span class="n">to</span> <span class="n">this</span> <span class="n">channel</span>
<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
</pre></div>
</div>
<p>To join/unsub a channel do</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">channel</span><span class="o">/</span><span class="n">sub</span> <span class="n">channelname</span>
<span class="n">channel</span><span class="o">/</span><span class="n">unsub</span> <span class="n">channelname</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>channel/sub channelname
channel/unsub channelname
</pre></div>
</div>
<p>If you temporarily dont want to hear the channel for a while (without actually
unsubscribing), you can mute it:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">channel</span><span class="o">/</span><span class="n">mute</span> <span class="n">channelname</span>
<span class="n">channel</span><span class="o">/</span><span class="n">unmute</span> <span class="n">channelname</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>channel/mute channelname
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>
<p>To speak on a channel, do</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>channel public Hello world!
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>channel public Hello world!
</pre></div>
</div>
<p>If the channel-name has spaces in it, you need to use a <code class="docutils literal notranslate"><span class="pre">=</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>channel rest room = Hello world!
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>channel rest room = Hello world!
</pre></div>
</div>
<p>Now, this is more to type than wed like, so when you join a channel, the
system automatically sets up an personal alias so you can do this instead:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">public</span> <span class="n">Hello</span> <span class="n">world</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>public Hello world
</pre></div>
</div>
<div class="admonition warning">
@ -109,25 +112,25 @@ So channels with long names should make sure to provide a one-word alias as
well.</p>
</div>
<p>Any user can make up their own channel aliases:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">channel</span><span class="o">/</span><span class="n">alias</span> <span class="n">public</span> <span class="o">=</span> <span class="n">foo</span><span class="p">;</span><span class="n">bar</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>channel/alias public = foo;bar
</pre></div>
</div>
<p>You can now just do</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>foo Hello world!
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>foo Hello world!
bar Hello again!
</pre></div>
</div>
<p>And even remove the default one if they dont want to use it</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">channel</span><span class="o">/</span><span class="n">unalias</span> <span class="n">public</span>
<span class="n">public</span> <span class="n">Hello</span> <span class="p">(</span><span class="n">gives</span> <span class="n">a</span> <span class="n">command</span><span class="o">-</span><span class="ow">not</span><span class="o">-</span><span class="n">found</span> <span class="n">error</span> <span class="n">now</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>channel/unalias public
public Hello (gives a command-not-found error now)
</pre></div>
</div>
<p>But you can also use your alias with the <code class="docutils literal notranslate"><span class="pre">channel</span></code> command:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>channel foo Hello world!
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>channel foo Hello world!
</pre></div>
</div>
<blockquote>
<div><p>What happens when aliasing is that a <a class="reference internal" href="Nicks.html"><span class="doc">nick</span></a> is created that maps your
<div><p>What happens when aliasing is that a <a class="reference internal" href="Nicks.html"><span class="doc std std-doc">nick</span></a> is created that maps your
alias + argument onto calling the <code class="docutils literal notranslate"><span class="pre">channel</span></code> command. So when you enter <code class="docutils literal notranslate"><span class="pre">foo</span> <span class="pre">hello</span></code>,
what the server sees is actually <code class="docutils literal notranslate"><span class="pre">channel</span> <span class="pre">foo</span> <span class="pre">=</span> <span class="pre">hello</span></code>. The system is also
clever enough to know that whenever you search for channels, your channel-nicks
@ -135,12 +138,12 @@ should also be considered so as to convert your input to an existing channel nam
</div></blockquote>
<p>You can check if you missed channel conversations by viewing the channels
scrollback with</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">channel</span><span class="o">/</span><span class="n">history</span> <span class="n">public</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>channel/history public
</pre></div>
</div>
<p>This retrieves the last 20 lines of text (also from a time when you were
offline). You can step further back by specifying how many lines back to start:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">channel</span><span class="o">/</span><span class="n">history</span> <span class="n">public</span> <span class="o">=</span> <span class="mi">30</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>channel/history public = 30
</pre></div>
</div>
<p>This again retrieve 20 lines, but starting 30 lines back (so youll get lines
@ -149,8 +152,8 @@ offline). You can step further back by specifying how many lines back to start:<
<section id="channel-administration">
<h3>Channel administration<a class="headerlink" href="#channel-administration" title="Permalink to this headline"></a></h3>
<p>To create/destroy a new channel you can do</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">channel</span><span class="o">/</span><span class="n">create</span> <span class="n">channelname</span><span class="p">;</span><span class="n">alias</span><span class="p">;</span><span class="n">alias</span> <span class="o">=</span> <span class="n">description</span>
<span class="n">channel</span><span class="o">/</span><span class="n">destroy</span> <span class="n">channelname</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>channel/create channelname;alias;alias = description
channel/destroy channelname
</pre></div>
</div>
<p>Aliases are optional but can be good for obvious shortcuts everyone may want to
@ -158,25 +161,25 @@ use. The description is used in channel-listings. You will automatically join a
channel you created and will be controlling it. You can also use <code class="docutils literal notranslate"><span class="pre">channel/desc</span></code> to
change the description on a channel you wnn later.</p>
<p>If you control a channel you can also kick people off it:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>channel/boot mychannel = annoyinguser123 : stop spamming!
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>channel/boot mychannel = annoyinguser123 : stop spamming!
</pre></div>
</div>
<p>The last part is an optional reason to send to the user before they are booted.
You can give a comma-separated list of channels to kick the same user from all
those channels at once. The user will be unsubbed from the channel and all
their aliases will be wiped. But they can still rejoin if they like.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">channel</span><span class="o">/</span><span class="n">ban</span> <span class="n">mychannel</span> <span class="o">=</span> <span class="n">annoyinguser123</span>
<span class="n">channel</span><span class="o">/</span><span class="n">ban</span> <span class="o">-</span> <span class="n">view</span> <span class="n">bans</span>
<span class="n">channel</span><span class="o">/</span><span class="n">unban</span> <span class="n">mychannel</span> <span class="o">=</span> <span class="n">annoyinguser123</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>channel/ban mychannel = annoyinguser123
channel/ban - view bans
channel/unban mychannel = annoyinguser123
</pre></div>
</div>
<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 external" href="../api/evennia.commands.default.comms.CmdChannel.html">Channel command</a> api
<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 channels <a class="reference internal" href="Locks.html"><span class="doc">locks</span></a>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">channel</span><span class="o">/</span><span class="n">lock</span> <span class="n">buildchannel</span> <span class="o">=</span> <span class="n">listen</span><span class="p">:</span><span class="nb">all</span><span class="p">();</span><span class="n">send</span><span class="p">:</span><span class="n">perm</span><span class="p">(</span><span class="n">Builders</span><span class="p">)</span>
<p>Admin-level users can also modify channels <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>
</div>
<p>Channels use three lock-types by default:</p>
@ -189,16 +192,16 @@ 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 external" href="../api/evennia.commands.default.comms.CmdChannel.html">evennia.commands.default.comms.CmdChannel</a>)
<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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">locks</span> <span class="o">=</span> <span class="s2">&quot;cmd:not perm(channel_banned); admin:all(); manage:all(); changelocks: perm(Admin)&quot;</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">locks</span> <span class="o">=</span> <span class="s2">&quot;cmd:not perm(channel_banned); admin:all(); manage:all(); changelocks: perm(Admin)&quot;</span>
</pre></div>
</td></tr></table></div>
<p>This is a regular <a class="reference internal" href="Locks.html"><span class="doc">lockstring</span></a>.</p>
</div>
<p>This is a regular <a class="reference internal" href="Locks.html"><span class="doc std std-doc">lockstring</span></a>.</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">cmd:</span> <span class="pre">pperm(channel_banned)</span></code> - The <code class="docutils literal notranslate"><span class="pre">cmd</span></code> locktype is the standard one used for all Commands.
an accessing object failing this will not even know that the command exists. The <code class="docutils literal notranslate"><span class="pre">pperm()</span></code> lockfunc
@ -217,19 +220,15 @@ will still only be able to admin or destroy channels they actually control!</p>
</div></blockquote>
<p>If you only want (say) Builders and higher to be able to create and admin
channels you could override the <code class="docutils literal notranslate"><span class="pre">help</span></code> command and change the lockstring to:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># in for example mygame/commands/commands.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># in for example mygame/commands/commands.py</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">default_cmds</span>
<span class="k">class</span> <span class="nc">MyCustomChannelCmd</span><span class="p">(</span><span class="n">default_cmds</span><span class="o">.</span><span class="n">CmdChannel</span><span class="p">):</span>
<span class="n">locks</span> <span class="o">=</span> <span class="s2">&quot;cmd: not pperm(channel_banned);admin:perm(Builder);manage:perm(Builder);changelocks:perm(Admin)&quot;</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Add this custom command to your default cmdset and regular users wil now get an
access-denied error when trying to use use these switches.</p>
</section>
@ -237,13 +236,13 @@ access-denied error when trying to use use these switches.</p>
</section>
<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 external" href="../api/evennia.commands.default.comms.CmdChannel.html">evennia.commands.default.comms.CmdChannel</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">command set</span></a>. It is set up such that it will
<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>Its 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 external" href="../api/evennia.commands.default.comms.CmdObjectChannel.html">evennia.commands.default.comms.CmdObjectChannel</a>
<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">
@ -281,41 +280,17 @@ Default channels all use <code class="docutils literal notranslate"><span class=
<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">Typeclassed</span></a> entities. This means they are
persistent in the database, can have <a class="reference internal" href="Attributes.html"><span class="doc">attributes</span></a> and <a class="reference internal" href="Tags.html"><span class="doc">Tags</span></a>
<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 external" href="api:evennia.comms.comms.DefaultChannel"><code class="docutils literal notranslate"><span class="pre">evennia.comms.comms.DefaultChannel</span></code></a>.
<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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span></pre></div></td><td class="code"><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>
<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>
<span class="kn">from</span> <span class="nn">typeclasses.channels</span> <span class="kn">import</span> <span class="n">Channel</span>
<span class="n">channel</span> <span class="o">=</span> <span class="n">create_channel</span><span class="p">(</span><span class="s2">&quot;my channel&quot;</span><span class="p">,</span> <span class="n">aliases</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;mychan&quot;</span><span class="p">],</span> <span class="n">locks</span><span class="o">=...</span><span class="p">,</span> <span class="n">typeclass</span><span class="o">=...</span><span class="p">)</span>
@ -340,8 +315,9 @@ as for other typelass-bases.</p>
<span class="c1"># permanently delete channel (will unsub everyone)</span>
<span class="n">channel</span><span class="o">.</span><span class="n">delete</span><span class="p">()</span>
</pre></div>
</td></tr></table></div>
</div>
<p>The Channels <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
@ -370,7 +346,7 @@ channels <code class="docutils literal notranslate"><span class="pre">at_post
<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>,
<code class="docutils literal notranslate"><span class="pre">aliases</span></code>, <code class="docutils literal notranslate"><span class="pre">attributes</span></code>, <code class="docutils literal notranslate"><span class="pre">tags</span></code>, <code class="docutils literal notranslate"><span class="pre">locks</span></code> etc). This is not an exhaustive list;
see the <a class="reference external" href="../api/evennia.comms.comms.DefaultChannel.html">Channel api docs</a> for details.</p>
see the <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">Channel api docs</span></a> for details.</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">send_to_online_only</span></code> - this class boolean defaults to <code class="docutils literal notranslate"><span class="pre">True</span></code> and is a
sensible optimization since people offline people will not see the message anyway.</p></li>
@ -379,8 +355,8 @@ is <code class="docutils literal notranslate"><span class="pre">&quot;channel_{c
<code class="docutils literal notranslate"><span class="pre">mygame/server/logs/</span></code>). You should usually not change this.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">channel_prefix_string</span></code> - this property is a string to easily change how
the channel is prefixed. It takes the <code class="docutils literal notranslate"><span class="pre">channelname</span></code> format key. Default is <code class="docutils literal notranslate"><span class="pre">&quot;[{channelname}]</span> <span class="pre">&quot;</span></code>
and produces output like `[public] …``.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">subscriptions</span></code> - this is the <a class="reference external" href="../api/evennia.comms.comms.html#SubscriptionHandler">SubscriptionHandler</a>, which
and produces output like <code class="docutils literal notranslate"><span class="pre">[public]</span> <span class="pre">...</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">subscriptions</span></code> - this is the <a class="reference internal" href="../api/evennia.comms.models.html#evennia.comms.models.SubscriptionHandler" title="evennia.comms.models.SubscriptionHandler"><span class="xref myst py py-class">SubscriptionHandler</span></a>, which
has methods <code class="docutils literal notranslate"><span class="pre">has</span></code>, <code class="docutils literal notranslate"><span class="pre">add</span></code>, <code class="docutils literal notranslate"><span class="pre">remove</span></code>, <code class="docutils literal notranslate"><span class="pre">all</span></code>, <code class="docutils literal notranslate"><span class="pre">clear</span></code> and also <code class="docutils literal notranslate"><span class="pre">online</span></code> (to get
only actually online channel-members).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">wholist</span></code>, <code class="docutils literal notranslate"><span class="pre">mutelist</span></code>, <code class="docutils literal notranslate"><span class="pre">banlist</span></code> are properties that return a list of subscribers,
@ -390,7 +366,7 @@ replacement (detect that <code class="docutils literal notranslate"><span class=
This pattern accepts an <code class="docutils literal notranslate"><span class="pre">{alias}</span></code> formatting marker. Dont mess with this unless you really
want to change how channels work.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">channel_msg_nick_replacement</span></code> - this is a string on the [nick replacement</p></li>
<li><p>form](Nicks). It accepts the <code class="docutils literal notranslate"><span class="pre">{channelname}</span></code> formatting tag. This is strongly tied to the
<li><p>form](./Nicks.md). It accepts the <code class="docutils literal notranslate"><span class="pre">{channelname}</span></code> formatting tag. This is strongly tied to the
<code class="docutils literal notranslate"><span class="pre">channel</span></code> command and is by default <code class="docutils literal notranslate"><span class="pre">channel</span> <span class="pre">{channelname}</span> <span class="pre">=</span> <span class="pre">$1</span></code>.</p></li>
</ul>
<p>Notable <code class="docutils literal notranslate"><span class="pre">Channel</span></code> hooks:</p>
@ -489,7 +465,7 @@ subscribers (and thus wipe all their aliases).</p></li>
<h3>Versions</h3>
<ul>
<li><a href="Channels.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,7 +40,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="coding-utils">
<section class="tex2jax_ignore mathjax_ignore" id="coding-utils">
<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>
@ -46,9 +48,9 @@ from the flat API, otherwise you can find them in the <code class="docutils lite
<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 its easiest to use the <code class="docutils literal notranslate"><span class="pre">search</span></code> method defined
on all objects. This will search for objects in the same location and inside the self object:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><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>
<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>
</td></tr></table></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 callers (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
@ -56,19 +58,18 @@ also be matched by this search. You will find multiple examples of this function
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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><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>
<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>
<span class="n">obj</span> <span class="o">=</span> <span class="n">search_object</span><span class="p">(</span><span class="n">objname</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<ul class="simple">
<li><p><a class="reference external" href="wiki/evennia.accounts.manager#accountdbmanagersearch_account">evennia.search_account</a></p></li>
<li><p><a class="reference external" href="wiki/evennia.objects.manager#objectdbmanagersearch_object">evennia.search_object</a></p></li>
<li><p><a class="reference external" href="wiki/evennia.utils.search#search_object_by_tag">evennia.search_object_by_tag</a></p></li>
<li><p><a class="reference external" href="wiki/evennia.scripts.manager#scriptdbmanagersearch_script">evennia.search_script</a></p></li>
<li><p><a class="reference external" href="wiki/evennia.comms.managers#channeldbmanagersearch_channel">evennia.search_channel</a></p></li>
<li><p><a class="reference external" href="wiki/evennia.comms.managers#msgmanagersearch_message">evennia.search_message</a></p></li>
<li><p><a class="reference external" href="wiki/evennia.help.manager#helpentrymanagersearch_help">evennia.search_help</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"><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>
</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>
@ -77,20 +78,18 @@ zero entries.</p>
<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">&#64;create</span></code> etc), you can also build all of Evennias game
entities directly in code (for example when defining new create commands).</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="kn">import</span> <span class="nn">evennia</span>
<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">&quot;game.gamesrc.objects.myobj.MyObj&quot;</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">&quot;MyObj&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<ul class="simple">
<li><p><a class="reference external" href="wiki/evennia.utils.create#create_account">evennia.create_account</a></p></li>
<li><p><a class="reference external" href="wiki/evennia.utils.create#create_object">evennia.create_object</a></p></li>
<li><p><a class="reference external" href="wiki/evennia.utils.create#create_script">evennia.create_script</a></p></li>
<li><p><a class="reference external" href="wiki/evennia.utils.create#create_channel">evennia.create_channel</a></p></li>
<li><p><a class="reference external" href="wiki/evennia.utils.create#create_help_entry">evennia.create_help_entry</a></p></li>
<li><p><a class="reference external" href="wiki/evennia.utils.create#create_message">evennia.create_message</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"><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>
</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>
@ -100,38 +99,30 @@ entities directly in code (for example when defining new create commands).</p>
<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>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span></pre></div></td><td class="code"><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>
<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">&quot;This is an Error!&quot;</span><span class="p">)</span>
<span class="n">logger</span><span class="o">.</span><span class="n">log_warn</span><span class="p">(</span><span class="s2">&quot;This is a Warning!&quot;</span><span class="p">)</span>
<span class="n">logger</span><span class="o">.</span><span class="n">log_info</span><span class="p">(</span><span class="s2">&quot;This is normal information&quot;</span><span class="p">)</span>
<span class="n">logger</span><span class="o">.</span><span class="n">log_dep</span><span class="p">(</span><span class="s2">&quot;This feature is deprecated&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></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
kill the server.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="k">try</span><span class="p">:</span>
<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>
<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="s2">&quot;This text will show beneath the traceback itself.&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></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>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><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">&quot;mylog.log&quot;</span><span class="p">)</span>
<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">&quot;mylog.log&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></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
@ -143,27 +134,7 @@ be written to a file <code class="docutils literal notranslate"><span class="pre
<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>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span></pre></div></td><td class="code"><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>
<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>
@ -184,21 +155,16 @@ shortcut:</p>
<span class="n">gametime</span> <span class="o">=</span> <span class="n">gametime</span><span class="o">.</span><span class="n">gametime</span><span class="p">(</span><span class="n">absolute</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="c1"># reset the game time (back to game epoch)</span>
<span class="n">gametime</span><span class="o">.</span><span class="n">reset_gametime</span><span class="p">()</span>
</pre></div>
</td></tr></table></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">&#64;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 external" href="https://github.com/evennia/evennia/blob/master/evennia.utils.gametime#schedule">gametime.schedule</a> function:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">evennia</span>
<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>
<span class="n">limbo</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_object</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="s2">&quot;Limbo&quot;</span><span class="p">)</span>
@ -206,7 +172,7 @@ you desire for your game. You can use the <code class="docutils literal notransl
<span class="n">gametime</span><span class="o">.</span><span class="n">schedule</span><span class="p">(</span><span class="n">church_clock</span><span class="p">,</span> <span class="n">hour</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
</section>
<section id="utils-time-format">
<h3>utils.time_format()<a class="headerlink" href="#utils-time-format" title="Permalink to this headline"></a></h3>
@ -222,15 +188,7 @@ 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>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><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>
<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>
@ -239,19 +197,20 @@ something is. It converts to four different styles of output using the <em>style
<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">&quot;Echo!&quot;</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>
</td></tr></table></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">&#64;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">&#64;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">Attribute</span></a>.</p>
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">TickerHandler</span></a> and <a class="reference internal" href="Scripts.html"><span class="doc">Scripts</span></a>.</p>
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
@ -269,17 +228,15 @@ will only catch immediate dependence). This function also accepts as input any c
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 Evennias 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">Typeclass</span></a> as a way of identification. Say
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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><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>
<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">&quot;typeclasses.objects.animals.Animal&quot;</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">&quot;The bouncer stops you in the door. He says: &#39;No talking animals allowed.&#39;&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
</section>
</section>
<section id="text-utilities">
@ -291,21 +248,19 @@ If nothing else it can be good to look here before starting to develop a solutio
<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>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><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>
<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>
</td></tr></table></div>
</div>
</section>
<section id="utils-crop">
<h3>utils.crop()<a class="headerlink" href="#utils-crop" title="Permalink to this headline"></a></h3>
<p>This function will crop a very long line, adding a suffix to show the line actually continues. This
can be useful in listings when showing multiple lines would mess up things.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">intxt</span> <span class="o">=</span> <span class="s2">&quot;This is a long text that we want to crop.&quot;</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">intxt</span> <span class="o">=</span> <span class="s2">&quot;This is a long text that we want to crop.&quot;</span>
<span class="n">outtxt</span> <span class="o">=</span> <span class="n">crop</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">19</span><span class="p">,</span> <span class="n">suffix</span><span class="o">=</span><span class="s2">&quot;[...]&quot;</span><span class="p">)</span>
<span class="c1"># outtxt is now &quot;This is a long text[...]&quot;</span>
</pre></div>
</td></tr></table></div>
</div>
</section>
<section id="utils-dedent">
<h3>utils.dedent()<a class="headerlink" href="#utils-dedent" title="Permalink to this headline"></a></h3>
@ -316,15 +271,7 @@ formatting they may have. A common case for this is when using Python triple-quo
<li><p>they will retain whichever indentation they have in the code, and to make easily-readable source
code one usually dont want to shift the string to the left edge.</p></li>
</ul>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1">#python code is entered at a given indentation</span>
<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">&quot;&quot;&quot;</span>
<span class="s2"> This is an example text that will end</span>
<span class="s2"> up with a lot of whitespace on the left.</span>
@ -334,7 +281,7 @@ code one usually dont want to shift the string to the left edge.</p></li>
<span class="c1"># outtxt will now retain all internal indentation</span>
<span class="c1"># but be shifted all the way to the left.</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Normally you do the dedent in the display code (this is for example how the help system homogenizes
help entries).</p>
</section>
@ -346,12 +293,12 @@ need to send byte-data over the wire, <code class="docutils literal notranslate"
<p>The difference from Pythons 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">here</span></a> for more info.</p>
<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 external" href="../api/evennia.utils.ansi.html">evennia.ansi</a></p></li>
<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>
@ -359,9 +306,9 @@ never raise a traceback but instead echo errors through logging. See
<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 external" href="https://github.com/evennia/evennia/blob/master/evennia.utils.evtable#evtable">EvTable</a> class (<code class="docutils literal notranslate"><span class="pre">evennia/utils/evtable.py</span></code>) can be used
<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 external" href="https://github.com/evennia/evennia/blob/master/evennia.utils.evform#evform">EvForm</a> (<code class="docutils literal notranslate"><span class="pre">evennia/utils/evform.py</span></code>). This reads a fixed-format
<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
@ -372,7 +319,7 @@ instructions.</p>
<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 external" href="https://github.com/evennia/evennia/blob/master/evennia.utils.evmenu#evmenu">evennia.EvMenu</a></p></li>
<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>
</section>
</section>
@ -451,7 +398,7 @@ instructions.</p>
<h3>Versions</h3>
<ul>
<li><a href="Coding-Utils.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,9 +40,9 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="command-sets">
<section class="tex2jax_ignore mathjax_ignore" id="command-sets">
<h1>Command Sets<a class="headerlink" href="#command-sets" title="Permalink to this headline"></a></h1>
<p>Command Sets are intimately linked with <a class="reference internal" href="Commands.html"><span class="doc">Commands</span></a> and you should be familiar with
<p>Command Sets are intimately linked with <a class="reference internal" href="Commands.html"><span class="doc std std-doc">Commands</span></a> and you should be familiar with
Commands before reading this page. The two pages were split for ease of reading.</p>
<p>A <em>Command Set</em> (often referred to as a CmdSet or cmdset) is the basic unit for storing one or more
<em>Commands</em>. A given Command can go into any number of different command sets. Storing Command
@ -48,7 +50,7 @@ classes in a command set is the way to make commands available to use in your ga
<p>When storing a CmdSet on an object, you will make the commands in that command set available to the
object. An example is the default command set stored on new Characters. This command set contains
all the useful commands, from <code class="docutils literal notranslate"><span class="pre">look</span></code> and <code class="docutils literal notranslate"><span class="pre">inventory</span></code> to <code class="docutils literal notranslate"><span class="pre">&#64;dig</span></code> and <code class="docutils literal notranslate"><span class="pre">&#64;reload</span></code>
(<a class="reference external" href="Components/Locks.html#Permissions">permissions</a> then limit which players may use them, but thats a separate
(<a class="reference internal" href="Permissions.html"><span class="doc std std-doc">permissions</span></a> then limit which players may use them, but thats a separate
topic).</p>
<p>When an account enters a command, cmdsets from the Account, Character, its location, and elsewhere
are pulled together into a <em>merge stack</em>. This stack is merged together in a specific order to
@ -59,7 +61,7 @@ like a <code class="docutils literal notranslate"><span class="pre">Television</
on. The tutorial world included with Evennia showcases a dark room that replaces certain critical
commands with its own versions because the Character cannot see.</p>
<p>If you want a quick start into defining your first commands and using them with command sets, you
can head over to the <a class="reference internal" href="../Howto/Starting/Part1/Adding-Commands.html"><span class="doc">Adding Command Tutorial</span></a> which steps through things
can head over to the <a class="reference internal" href="../Howto/Starting/Part1/Adding-Commands.html"><span class="doc std std-doc">Adding Command Tutorial</span></a> which steps through things
without the explanations.</p>
<section id="defining-command-sets">
<h2>Defining Command Sets<a class="headerlink" href="#defining-command-sets" title="Permalink to this headline"></a></h2>
@ -68,23 +70,7 @@ without the explanations.</p>
needs to define one method, called <code class="docutils literal notranslate"><span class="pre">at_cmdset_creation()</span></code>. All other class parameters are optional,
but are used for more advanced set manipulation and coding (see the [merge rules](Command-
Sets#merge-rules) section).</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># file mygame/commands/mycmdset.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># file mygame/commands/mycmdset.py</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">CmdSet</span>
@ -102,18 +88,15 @@ Sets#merge-rules) section).</p>
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">mycommands</span><span class="o">.</span><span class="n">MyCommand2</span><span class="p">())</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">mycommands</span><span class="o">.</span><span class="n">MyCommand3</span><span class="p">())</span>
</pre></div>
</td></tr></table></div>
</div>
<p>The CmdSets <code class="docutils literal notranslate"><span class="pre">add()</span></code> method can also take another CmdSet as input. In this case all the commands
from that CmdSet will be appended to this one as if you added them line by line:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="k">def</span> <span class="nf">at_cmdset_creation</span><span class="p">():</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="k">def</span> <span class="nf">at_cmdset_creation</span><span class="p">():</span>
<span class="o">...</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">AdditionalCmdSet</span><span class="p">)</span> <span class="c1"># adds all command from this set</span>
<span class="o">...</span>
</pre></div>
</td></tr></table></div>
</div>
<p>If you added your command to an existing cmdset (like to the default cmdset), that set is already
loaded into memory. You need to make the server aware of the code changes:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@reload</span>
@ -123,13 +106,13 @@ loaded into memory. You need to make the server aware of the code changes:</p>
<p>If you created a new, fresh cmdset, this must be added to an object in order to make the commands
within available. A simple way to temporarily test a cmdset on yourself is use the <code class="docutils literal notranslate"><span class="pre">&#64;py</span></code> command to
execute a python snippet:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="nd">@py</span> <span class="bp">self</span><span class="o">.</span><span class="n">cmdset</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s1">&#39;commands.mycmdset.MyCmdSet&#39;</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="nd">@py</span> <span class="bp">self</span><span class="o">.</span><span class="n">cmdset</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s1">&#39;commands.mycmdset.MyCmdSet&#39;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>This will stay with you until you <code class="docutils literal notranslate"><span class="pre">&#64;reset</span></code> or <code class="docutils literal notranslate"><span class="pre">&#64;shutdown</span></code> the server, or you run</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="nd">@py</span> <span class="bp">self</span><span class="o">.</span><span class="n">cmdset</span><span class="o">.</span><span class="n">delete</span><span class="p">(</span><span class="s1">&#39;commands.mycmdset.MyCmdSet&#39;</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="nd">@py</span> <span class="bp">self</span><span class="o">.</span><span class="n">cmdset</span><span class="o">.</span><span class="n">delete</span><span class="p">(</span><span class="s1">&#39;commands.mycmdset.MyCmdSet&#39;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>In the example above, a specific Cmdset class is removed. Calling <code class="docutils literal notranslate"><span class="pre">delete</span></code> without arguments will
remove the latest added cmdset.</p>
<blockquote>
@ -147,11 +130,11 @@ remove the latest added cmdset.</p>
back even if all other cmdsets fail or are removed. It is always persistent and will not be affected
by <code class="docutils literal notranslate"><span class="pre">cmdset.delete()</span></code>. To remove a default cmdset you must explicitly call <code class="docutils literal notranslate"><span class="pre">cmdset.remove_default()</span></code>.</p>
<p>Command sets are often added to an object in its <code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code> method. For more examples of
adding commands, read the <a class="reference internal" href="../Howto/Starting/Part1/Adding-Commands.html"><span class="doc">Step by step tutorial</span></a>. Generally you can
adding commands, read the <a class="reference internal" href="../Howto/Starting/Part1/Adding-Commands.html"><span class="doc std std-doc">Step by step tutorial</span></a>. Generally you can
customize which command sets are added to your objects by using <code class="docutils literal notranslate"><span class="pre">self.cmdset.add()</span></code> or
<code class="docutils literal notranslate"><span class="pre">self.cmdset.add_default()</span></code>.</p>
<blockquote>
<div><p>Important: Commands are identified uniquely by key <em>or</em> alias (see <a class="reference internal" href="Commands.html"><span class="doc">Commands</span></a>). If any
<div><p>Important: Commands are identified uniquely by key <em>or</em> alias (see <a class="reference internal" href="Commands.html"><span class="doc std std-doc">Commands</span></a>). If any
overlap exists, two commands are considered identical. Adding a Command to a command set that
already has an identical command will <em>replace</em> the previous command. This is very important. You
must take this behavior into account when attempting to overload any default Evennia commands with
@ -162,7 +145,7 @@ new one that has a matching alias.</p>
<h3>Properties on Command Sets<a class="headerlink" href="#properties-on-command-sets" title="Permalink to this headline"></a></h3>
<p>There are several extra flags that you can set on CmdSets in order to modify how they work. All are
optional and will be set to defaults otherwise. Since many of these relate to <em>merging</em> cmdsets,
you might want to read the [Adding and Merging Command Sets](./Command-Sets#adding-and-merging-
you might want to read the [Adding and Merging Command Sets](./Command-Sets.md#adding-and-merging-
command-sets) section for some of these to make sense.</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">key</span></code> (string) - an identifier for the cmdset. This is optional, but should be unique. It is used
@ -172,8 +155,8 @@ dictionary below.</p></li>
<em>Replace</em>”, or “<em>Remove</em>”.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">priority</span></code> (int) - This defines the merge order of the merge stack - cmdsets will merge in rising
order of priority with the highest priority set merging last. During a merger, the commands from the
set with the higher priority will have precedence (just what happens depends on the <a class="reference external" href="Components/Command-Sets.html#adding-and-merging-command-sets">merge
type</a>). If priority is identical, the order in the
set with the higher priority will have precedence (just what happens depends on the <a class="reference internal" href="#adding-and-merging-command-sets"><span class="std std-doc">merge
type</span></a>). If priority is identical, the order in the
merge stack determines preference. The priority value must be greater or equal to <code class="docutils literal notranslate"><span class="pre">-100</span></code>. Most in-
game sets should usually have priorities between <code class="docutils literal notranslate"><span class="pre">0</span></code> and <code class="docutils literal notranslate"><span class="pre">100</span></code>. Evennia default sets have priorities
as follows (these can be changed if you want a different distribution):</p>
@ -191,8 +174,8 @@ arguments, there is no collision between exits named the same as a channel even
<li><p><code class="docutils literal notranslate"><span class="pre">key_mergetype</span></code> (dict) - a dict of <code class="docutils literal notranslate"><span class="pre">key:mergetype</span></code> pairs. This allows this cmdset to merge
differently with certain named cmdsets. If the cmdset to merge with has a <code class="docutils literal notranslate"><span class="pre">key</span></code> matching an entry in
<code class="docutils literal notranslate"><span class="pre">key_mergetype</span></code>, it will not be merged according to the setting in <code class="docutils literal notranslate"><span class="pre">mergetype</span></code> but according to the
mode in this dict. Please note that this is more complex than it may seem due to the <a class="reference external" href="Components/Command-Sets.html#adding-and-merging-command-sets">merge
order</a> of command sets. Please review that section
mode in this dict. Please note that this is more complex than it may seem due to the <a class="reference internal" href="#adding-and-merging-command-sets"><span class="std std-doc">merge
order</span></a> of command sets. Please review that section
before using <code class="docutils literal notranslate"><span class="pre">key_mergetype</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">duplicates</span></code> (bool/None default <code class="docutils literal notranslate"><span class="pre">None</span></code>) - this determines what happens when merging same-priority
cmdsets containing same-key commands together. The<code class="docutils literal notranslate"><span class="pre">dupicate</span></code> option will <em>only</em> apply when merging
@ -246,14 +229,14 @@ priority determines what is used.</p></li>
</section>
<section id="command-sets-searched">
<h2>Command Sets Searched<a class="headerlink" href="#command-sets-searched" title="Permalink to this headline"></a></h2>
<p>When a user issues a command, it is matched against the [merged](./Command-Sets#adding-and-merging-
<p>When a user issues a command, it is matched against the [merged](./Command-Sets.md#adding-and-merging-
command-sets) command sets available to the player at the moment. Which those are may change at any
time (such as when the player walks into the room with the <code class="docutils literal notranslate"><span class="pre">Window</span></code> object described earlier).</p>
<p>The currently valid command sets are collected from the following sources:</p>
<ul class="simple">
<li><p>The cmdsets stored on the currently active <a class="reference internal" href="Sessions.html"><span class="doc">Session</span></a>. Default is the empty
<li><p>The cmdsets stored on the currently active <a class="reference internal" href="Sessions.html"><span class="doc std std-doc">Session</span></a>. Default is the empty
<code class="docutils literal notranslate"><span class="pre">SessionCmdSet</span></code> with merge priority <code class="docutils literal notranslate"><span class="pre">-20</span></code>.</p></li>
<li><p>The cmdsets defined on the <a class="reference internal" href="Accounts.html"><span class="doc">Account</span></a>. Default is the AccountCmdSet with merge priority
<li><p>The cmdsets defined on the <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Account</span></a>. Default is the AccountCmdSet with merge priority
<code class="docutils literal notranslate"><span class="pre">-10</span></code>.</p></li>
<li><p>All cmdsets on the Character/Object (assuming the Account is currently puppeting such a
Character/Object). Merge priority <code class="docutils literal notranslate"><span class="pre">0</span></code>.</p></li>
@ -265,14 +248,14 @@ included if <code class="docutils literal notranslate"><span class="pre">no_objs
<code class="docutils literal notranslate"><span class="pre">no_objs</span></code> option is active in the merge stack.</p></li>
<li><p>The cmdsets of Exits in the location. Merge priority <code class="docutils literal notranslate"><span class="pre">+101</span></code>. Will not be included if <code class="docutils literal notranslate"><span class="pre">no_exits</span></code>
<em>or</em> <code class="docutils literal notranslate"><span class="pre">no_objs</span></code> option is active in the merge stack.</p></li>
<li><p>The <a class="reference internal" href="Communications.html"><span class="doc">channel</span></a> cmdset containing commands for posting to all channels the account
<li><p>The <a class="reference internal" href="Communications.html"><span class="doc std std-doc">channel</span></a> cmdset containing commands for posting to all channels the account
or character is currently connected to. Merge priority <code class="docutils literal notranslate"><span class="pre">+101</span></code>. Will not be included if <code class="docutils literal notranslate"><span class="pre">no_channels</span></code>
option is active in the merge stack.</p></li>
</ul>
<p>Note that an object does not <em>have</em> to share its commands with its surroundings. A Characters
cmdsets should not be shared for example, or all other Characters would get multi-match errors just
by being in the same room. The ability of an object to share its cmdsets is managed by its <code class="docutils literal notranslate"><span class="pre">call</span></code>
<a class="reference internal" href="Locks.html"><span class="doc">lock</span></a>. For example, <a class="reference internal" href="Objects.html"><span class="doc">Character objects</span></a> defaults to <code class="docutils literal notranslate"><span class="pre">call:false()</span></code> so that any
<a class="reference internal" href="Locks.html"><span class="doc std std-doc">lock</span></a>. For example, <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Character objects</span></a> defaults to <code class="docutils literal notranslate"><span class="pre">call:false()</span></code> so that any
cmdsets on them can only be accessed by themselves, not by other objects around them. Another
example might be to lock an object with <code class="docutils literal notranslate"><span class="pre">call:inside()</span></code> to only make their commands available to
objects inside them, or <code class="docutils literal notranslate"><span class="pre">cmd:holds()</span></code> to make their commands available only if they are held.</p>
@ -327,30 +310,30 @@ theory</a>.</p>
<ul>
<li><p><strong>Union</strong> (default) - The two cmdsets are merged so that as many commands as possible from each
cmdset ends up in the merged cmdset. Same-key commands are merged by priority.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="c1"># Union</span>
<span class="n">A1</span><span class="p">,</span><span class="n">A2</span> <span class="o">+</span> <span class="n">B1</span><span class="p">,</span><span class="n">B2</span><span class="p">,</span><span class="n">B3</span><span class="p">,</span><span class="n">B4</span> <span class="o">=</span> <span class="n">A1</span><span class="p">,</span><span class="n">A2</span><span class="p">,</span><span class="n">B3</span><span class="p">,</span><span class="n">B4</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> # Union
A1,A2 + B1,B2,B3,B4 = A1,A2,B3,B4
</pre></div>
</div>
</li>
<li><p><strong>Intersect</strong> - Only commands found in <em>both</em> cmdsets (i.e. which have the same keys) end up in
the merged cmdset, with the higher-priority cmdset replacing the lower ones commands.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="c1"># Intersect</span>
<span class="n">A1</span><span class="p">,</span><span class="n">A3</span><span class="p">,</span><span class="n">A5</span> <span class="o">+</span> <span class="n">B1</span><span class="p">,</span><span class="n">B2</span><span class="p">,</span><span class="n">B4</span><span class="p">,</span><span class="n">B5</span> <span class="o">=</span> <span class="n">A1</span><span class="p">,</span><span class="n">A5</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> # Intersect
A1,A3,A5 + B1,B2,B4,B5 = A1,A5
</pre></div>
</div>
</li>
<li><p><strong>Replace</strong> - The commands of the higher-prio cmdset completely replaces the lower-priority
cmdsets commands, regardless of if same-key commands exist or not.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="c1"># Replace</span>
<span class="n">A1</span><span class="p">,</span><span class="n">A3</span> <span class="o">+</span> <span class="n">B1</span><span class="p">,</span><span class="n">B2</span><span class="p">,</span><span class="n">B4</span><span class="p">,</span><span class="n">B5</span> <span class="o">=</span> <span class="n">A1</span><span class="p">,</span><span class="n">A3</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> # Replace
A1,A3 + B1,B2,B4,B5 = A1,A3
</pre></div>
</div>
</li>
<li><p><strong>Remove</strong> - The high-priority command sets removes same-key commands from the lower-priority
cmdset. They are not replaced with anything, so this is a sort of filter that prunes the low-prio
set using the high-prio one as a template.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="c1"># Remove</span>
<span class="n">A1</span><span class="p">,</span><span class="n">A3</span> <span class="o">+</span> <span class="n">B1</span><span class="p">,</span><span class="n">B2</span><span class="p">,</span><span class="n">B3</span><span class="p">,</span><span class="n">B4</span><span class="p">,</span><span class="n">B5</span> <span class="o">=</span> <span class="n">B2</span><span class="p">,</span><span class="n">B4</span><span class="p">,</span><span class="n">B5</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> # Remove
A1,A3 + B1,B2,B3,B4,B5 = B2,B4,B5
</pre></div>
</div>
</li>
@ -385,23 +368,7 @@ sure we merge onto B. Setting Es priority to, say, -4 will make sure to merg
it appropriately.</p>
</div></blockquote>
<p>More advanced cmdset example:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">commands</span> <span class="kn">import</span> <span class="n">mycommands</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">commands</span> <span class="kn">import</span> <span class="n">mycommands</span>
<span class="k">class</span> <span class="nc">MyCmdSet</span><span class="p">(</span><span class="n">CmdSet</span><span class="p">):</span>
@ -419,7 +386,7 @@ it appropriately.</p>
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">mycommands</span><span class="o">.</span><span class="n">MyCommand2</span><span class="p">())</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">mycommands</span><span class="o">.</span><span class="n">MyCommand3</span><span class="p">())</span>
</pre></div>
</td></tr></table></div>
</div>
</section>
<section id="assorted-notes">
<h3>Assorted Notes<a class="headerlink" href="#assorted-notes" title="Permalink to this headline"></a></h3>
@ -496,7 +463,7 @@ commands having any combination of the keys and/or aliases “kick”, “punch
<h3>Versions</h3>
<ul>
<li><a href="Command-Sets.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,17 +40,17 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="command-system">
<section class="tex2jax_ignore mathjax_ignore" id="command-system">
<h1>Command System<a class="headerlink" href="#command-system" title="Permalink to this headline"></a></h1>
<ul class="simple">
<li><p><a class="reference internal" href="Commands.html"><span class="doc">Commands</span></a></p></li>
<li><p><a class="reference internal" href="Command-Sets.html"><span class="doc">Command Sets</span></a></p></li>
<li><p><a class="reference external" href="Components/Help-System.html#command-auto-help-system">Command Auto-help</a></p></li>
<li><p><a class="reference internal" href="Commands.html"><span class="doc std std-doc">Commands</span></a></p></li>
<li><p><a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">Command Sets</span></a></p></li>
<li><p><a class="reference internal" href="Help-System.html#command-auto-help-system"><span class="std std-doc">Command Auto-help</span></a></p></li>
</ul>
<p>See also:</p>
<ul class="simple">
<li><p><a class="reference external" href="../api/evennia.commands.default.html#modules">Default Command Help</a></p></li>
<li><p><a class="reference internal" href="../Howto/Starting/Part1/Adding-Commands.html"><span class="doc">Adding Command Tutorial</span></a></p></li>
<li><p><a class="reference internal" href="Default-Commands.html"><span class="doc std std-doc">Default Commands</span></a></p></li>
<li><p><a class="reference internal" href="../Howto/Starting/Part1/Adding-Commands.html"><span class="doc std std-doc">Adding Command Tutorial</span></a></p></li>
</ul>
</section>
@ -92,7 +94,7 @@
<h3>Versions</h3>
<ul>
<li><a href="Command-System.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,21 +40,21 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="commands">
<section class="tex2jax_ignore mathjax_ignore" id="commands">
<h1>Commands<a class="headerlink" href="#commands" title="Permalink to this headline"></a></h1>
<p>Commands are intimately linked to <a class="reference internal" href="Command-Sets.html"><span class="doc">Command Sets</span></a> and you need to read that page too to
<p>Commands are intimately linked to <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">Command Sets</span></a> and you need to read that page too to
be familiar with how the command system works. The two pages were split for easy reading.</p>
<p>The basic way for users to communicate with the game is through <em>Commands</em>. These can be commands
directly related to the game world such as <em>look</em>, <em>get</em>, <em>drop</em> and so on, or administrative
commands such as <em>examine</em> or <em>&#64;dig</em>.</p>
<p>The <a class="reference external" href="../api/evennia.commands.default.html#modules">default commands</a> coming with Evennia are MUX-like in that they use &#64;
<p>The <a class="reference internal" href="Default-Commands.html"><span class="doc std std-doc">default commands</span></a> coming with Evennia are MUX-like in that they use &#64;
for admin commands, support things like switches, syntax with the = symbol etc, but there is
nothing that prevents you from implementing a completely different command scheme for your game. You
can find the default commands in <code class="docutils literal notranslate"><span class="pre">evennia/commands/default</span></code>. You should not edit these directly -
they will be updated by the Evennia team as new features are added. Rather you should look to them
for inspiration and inherit your own designs from them.</p>
<p>There are two components to having a command running - the <em>Command</em> class and the
<a class="reference internal" href="Command-Sets.html"><span class="doc">Command Set</span></a> (command sets were split into a separate wiki page for ease of reading).</p>
<a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">Command Set</span></a> (command sets were split into a separate wiki page for ease of reading).</p>
<ol class="simple">
<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>
@ -64,8 +66,8 @@ object in various ways. Consider a “Tree” object with a cmdset defining the
<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">Command Sets</span></a>. There is also a step-by-step
<a class="reference internal" href="../Howto/Starting/Part1/Adding-Commands.html"><span class="doc">Adding Command Tutorial</span></a> that will get you started quickly without 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="../Howto/Starting/Part1/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>
@ -74,18 +76,7 @@ extra explanations.</p>
Evennia actually inherit from a child of <code class="docutils literal notranslate"><span class="pre">Command</span></code> called <code class="docutils literal notranslate"><span class="pre">MuxCommand</span></code> - this is the class that
knows all the mux-like syntax like <code class="docutils literal notranslate"><span class="pre">/switches</span></code>, splitting by “=” etc. Below well avoid mux-
specifics and use the base <code class="docutils literal notranslate"><span class="pre">Command</span></code> class directly.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># basic Command definition</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># basic Command definition</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">MyCmd</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
@ -98,16 +89,9 @@ specifics and use the base <code class="docutils literal notranslate"><span clas
<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="c1"># executing the command here</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Here is a minimalistic command with no custom parsing:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><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>
<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">CmdEcho</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">&quot;echo&quot;</span>
@ -115,8 +99,9 @@ specifics and use the base <code class="docutils literal notranslate"><span clas
<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="c1"># echo the caller&#39;s input back to the caller</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">&quot;Echo: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>You define a new command by assigning a few class-global properties on your inherited class and
overloading one or two hook functions. The full gritty mechanic behind how commands work are found
towards the end of this page; for now you only need to know that the command handler creates an
@ -128,18 +113,18 @@ assigns the new command instance a few useful properties that you can assume to
of this since this will also assign appropriate <code class="docutils literal notranslate"><span class="pre">caller</span></code>, <code class="docutils literal notranslate"><span class="pre">session</span></code>, <code class="docutils literal notranslate"><span class="pre">sessid</span></code> and <code class="docutils literal notranslate"><span class="pre">account</span></code>
properties on the command body at runtime. Most often the calling type is <code class="docutils literal notranslate"><span class="pre">Session</span></code>.</p>
<ul class="simple">
<li><p>A <a class="reference internal" href="Sessions.html"><span class="doc">Session</span></a>. This is by far the most common case when a user is entering a command in
<li><p>A <a class="reference internal" href="Sessions.html"><span class="doc std std-doc">Session</span></a>. This is by far the most common case when a user is entering a command in
their client.</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">caller</span></code> - this is set to the puppeted <a class="reference internal" href="Objects.html"><span class="doc">Object</span></a> if such an object exists. If no
<li><p><code class="docutils literal notranslate"><span class="pre">caller</span></code> - this is set to the puppeted <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Object</span></a> if such an object exists. If no
puppet is found, <code class="docutils literal notranslate"><span class="pre">caller</span></code> is set equal to <code class="docutils literal notranslate"><span class="pre">account</span></code>. Only if an Account is not found either (such as
before being logged in) will this be set to the Session object itself.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">session</span></code> - a reference to the <a class="reference internal" href="Sessions.html"><span class="doc">Session</span></a> object itself.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">session</span></code> - a reference to the <a class="reference internal" href="Sessions.html"><span class="doc std std-doc">Session</span></a> object itself.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">sessid</span></code> - <code class="docutils literal notranslate"><span class="pre">sessid.id</span></code>, a unique integer identifier of the 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">Account</span></a> object connected to this Session. None if not logged in.</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> object connected to this Session. None if not logged in.</p></li>
</ul>
</li>
<li><p>An <a class="reference internal" href="Accounts.html"><span class="doc">Account</span></a>. This only happens if <code class="docutils literal notranslate"><span class="pre">account.execute_cmd()</span></code> was used. No Session
<li><p>An <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Account</span></a>. This only happens if <code class="docutils literal notranslate"><span class="pre">account.execute_cmd()</span></code> was used. No Session
information can be obtained in this case.</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">caller</span></code> - this is set to the puppeted Object if such an object can be determined (without
@ -150,7 +135,7 @@ this is equal to <code class="docutils literal notranslate"><span class="pre">ac
<li><p><code class="docutils literal notranslate"><span class="pre">account</span></code> - Set to the Account object.</p></li>
</ul>
</li>
<li><p>An <a class="reference internal" href="Objects.html"><span class="doc">Object</span></a>. This only happens if <code class="docutils literal notranslate"><span class="pre">object.execute_cmd()</span></code> was used (for example by an
<li><p>An <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Object</span></a>. This only happens if <code class="docutils literal notranslate"><span class="pre">object.execute_cmd()</span></code> was used (for example by an
NPC).</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">caller</span></code> - This is set to the calling Object in question.</p></li>
@ -177,18 +162,18 @@ it the following properties:</p>
<li><p><code class="docutils literal notranslate"><span class="pre">caller</span></code> - The character BigGuy, in this example. This is a reference to the object executing the
command. The value of this depends on what type of object is calling the command; see the previous
section.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">session</span></code> - the <a class="reference internal" href="Sessions.html"><span class="doc">Session</span></a> Bob uses to connect to the game and control BigGuy (see also
<li><p><code class="docutils literal notranslate"><span class="pre">session</span></code> - the <a class="reference internal" href="Sessions.html"><span class="doc std std-doc">Session</span></a> Bob uses to connect to the game and control BigGuy (see also
previous section).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">sessid</span></code> - the unique id of <code class="docutils literal notranslate"><span class="pre">self.session</span></code>, for quick lookup.</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">Account</span></a> Bob (see previous section).</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> Bob (see previous section).</p></li>
<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
<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">Object</span></a> on which this command is defined. This need not be the caller,
<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.</p></li>
@ -208,7 +193,7 @@ not
used, but they could be used to implement alternate help-display systems.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">.client_width()</span></code> - Shortcut for getting the clients screen-width. Note that not all clients will
truthfully report this value - that case the <code class="docutils literal notranslate"><span class="pre">settings.DEFAULT_SCREEN_WIDTH</span></code> will be returned.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">.styled_table(*args,</span> <span class="pre">**kwargs)</span></code> - This returns an [EvTable](api:evennia.utils#module-
<li><p><code class="docutils literal notranslate"><span class="pre">.styled_table(*args,</span> <span class="pre">**kwargs)</span></code> - This returns an [EvTable](module-
evennia.utils.evtable) styled based on the
session calling this command. The args/kwargs are the same as for EvTable, except styling defaults
are set.</p></li>
@ -229,7 +214,7 @@ key can consist of more than one word, like “press button” or “pull left l
either matches. This is important for merging cmdsets described below.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">aliases</span></code> (optional list) - a list of alternate names for the command (<code class="docutils literal notranslate"><span class="pre">[&quot;glance&quot;,</span> <span class="pre">&quot;see&quot;,</span> <span class="pre">&quot;l&quot;]</span></code>).
Same name rules as for <code class="docutils literal notranslate"><span class="pre">key</span></code> applies.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">locks</span></code> (string) - a <a class="reference internal" href="Locks.html"><span class="doc">lock definition</span></a>, usually on the form <code class="docutils literal notranslate"><span class="pre">cmd:&lt;lockfuncs&gt;</span></code>. Locks is a
<li><p><code class="docutils literal notranslate"><span class="pre">locks</span></code> (string) - a <a class="reference internal" href="Locks.html"><span class="doc std std-doc">lock definition</span></a>, usually on the form <code class="docutils literal notranslate"><span class="pre">cmd:&lt;lockfuncs&gt;</span></code>. Locks is a
rather big topic, so until you learn more about locks, stick to giving the lockstring <code class="docutils literal notranslate"><span class="pre">&quot;cmd:all()&quot;</span></code>
to make the command available to everyone (if you dont provide a lock string, this will be assigned
for you).</p></li>
@ -241,9 +226,9 @@ by the next command by retrieving <code class="docutils literal notranslate"><sp
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 external" href="Components/Commands.html#on-arg_regex">See the arg_regex section</a> for the details.</p></li>
done with a regular expression. <a class="reference internal" href="#on-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 external" href="Components/Help-System.html#command-auto-help-system">auto-help system</a> on a per-command basis. This could be useful if you
<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">is_exit</span></code> (bool) - this marks the command as being used for an in-game exit. This is, by default,
@ -279,49 +264,10 @@ from this method will be returned from the execution as a Twisted Deferred.</p><
</ul>
<p>Finally, you should always make an informative <a class="reference external" href="https://www.python.org/dev/peps/pep-0257/#what-is-a-docstring">doc
string</a> (<code class="docutils literal notranslate"><span class="pre">__doc__</span></code>) at the top of
your class. This string is dynamically read by the <a class="reference internal" href="Help-System.html"><span class="doc">Help System</span></a> to create the help
your class. This string is dynamically read by the <a class="reference internal" href="Help-System.html"><span class="doc std std-doc">Help System</span></a> to create the help
entry for this command. You should decide on a way to format your help and stick to that.</p>
<p>Below is how you define a simple alternative “<code class="docutils literal notranslate"><span class="pre">smile</span></code>” command:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span></pre></div></td><td class="code"><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>
<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">CmdSmile</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
@ -356,13 +302,14 @@ entry for this command. You should decide on a way to format your help and stick
<span class="n">string</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">caller</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2"> smiles&quot;</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">target</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">target</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">target</span><span class="p">:</span>
<span class="k">return</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">target</span><span class="p">:</span>
<span class="k">return</span>
<span class="n">string</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">caller</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2"> smiles at </span><span class="si">{</span><span class="n">target</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2">&quot;</span>
<span class="n">caller</span><span class="o">.</span><span class="n">location</span><span class="o">.</span><span class="n">msg_contents</span><span class="p">(</span><span class="n">string</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>The power of having commands as classes and to separate <code class="docutils literal notranslate"><span class="pre">parse()</span></code> and <code class="docutils literal notranslate"><span class="pre">func()</span></code>
lies in the ability to inherit functionality without having to parse every
command individually. For example, as mentioned the default commands all
@ -371,7 +318,7 @@ that understands all the specifics of MUX-like commands. Almost none of the
default commands thus need to implement <code class="docutils literal notranslate"><span class="pre">parse()</span></code> at all, but can assume the
incoming string is already split up and parsed in suitable ways by its parent.</p>
<p>Before you can actually use the command in your game, you must now store it
within a <em>command set</em>. See the <a class="reference internal" href="Command-Sets.html"><span class="doc">Command Sets</span></a> page.</p>
within a <em>command set</em>. See the <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">Command Sets</span></a> page.</p>
</section>
<section id="on-arg-regex">
<h3>On arg_regex<a class="headerlink" href="#on-arg-regex" title="Permalink to this headline"></a></h3>
@ -408,17 +355,7 @@ will however still fire the other hook methods of the Command in sequence. That
want but sometimes it may be useful to just abort the command, for example if you find some
unacceptable input in your parse method. To exit the command this way you can raise
<code class="docutils literal notranslate"><span class="pre">evennia.InterruptCommand</span></code>:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">InterruptCommand</span>
<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">InterruptCommand</span>
<span class="k">class</span> <span class="nc">MyCommand</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
@ -429,8 +366,9 @@ unacceptable input in your parse method. To exit the command this way you can ra
<span class="c1"># if this fires, `func()` and `at_post_cmd` will not</span>
<span class="c1"># be called at all</span>
<span class="k">raise</span> <span class="n">InterruptCommand</span><span class="p">()</span>
</pre></div>
</td></tr></table></div>
</div>
</section>
<section id="pauses-in-commands">
<h2>Pauses in commands<a class="headerlink" href="#pauses-in-commands" title="Permalink to this headline"></a></h2>
@ -448,28 +386,7 @@ pause for you if you <code class="docutils literal notranslate"><span class="pre
else.</p>
</div></blockquote>
<p>Heres an example of a command using a small pause of five seconds between messages:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span></pre></div></td><td class="code"><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>
<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">CmdWait</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
@ -492,7 +409,7 @@ else.</p>
<span class="k">yield</span> <span class="mi">2</span>
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;... And now another 2 seconds have passed.&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>The important line is the <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">5</span></code> and <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">2</span></code> lines. It will tell Evennia to pause execution
here and not continue until the number of seconds given has passed.</p>
<p>There are two things to remember when using <code class="docutils literal notranslate"><span class="pre">yield</span></code> in your Commands <code class="docutils literal notranslate"><span class="pre">func</span></code> method:</p>
@ -514,28 +431,11 @@ to mix <code class="docutils literal notranslate"><span class="pre">yield</span>
use Pythons <code class="docutils literal notranslate"><span class="pre">input</span></code> in your command, for it would freeze Evennia for
everyone while waiting for that user to input their text. Inside a Commands
<code class="docutils literal notranslate"><span class="pre">func</span></code> method, the following syntax can also be used:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">answer</span> <span class="o">=</span> <span class="k">yield</span><span class="p">(</span><span class="s2">&quot;Your question&quot;</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">answer</span> <span class="o">=</span> <span class="k">yield</span><span class="p">(</span><span class="s2">&quot;Your question&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Heres a very simple example:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">CmdConfirm</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">CmdConfirm</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> A dummy command to show confirmation.</span>
@ -554,14 +454,14 @@ everyone while waiting for that user to input their text. Inside a Commands
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;No!&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>This time, when the user enters the confirm command, she will be asked if she wants to go on.
Entering yes or “y” (regardless of case) will give the first reply, otherwise the second reply
will show.</p>
<blockquote>
<div><p>Note again that the <code class="docutils literal notranslate"><span class="pre">yield</span></code> keyword does not store state. If the game reloads while waiting for
the user to answer, the user will have to start over. It is not a good idea to use <code class="docutils literal notranslate"><span class="pre">yield</span></code> for
important or complex choices, a persistent <a class="reference internal" href="EvMenu.html"><span class="doc">EvMenu</span></a> might be more appropriate in this case.</p>
important or complex choices, a persistent <a class="reference internal" href="EvMenu.html"><span class="doc std std-doc">EvMenu</span></a> might be more appropriate in this case.</p>
</div></blockquote>
</section>
<section id="system-commands">
@ -589,7 +489,7 @@ display the “Huh?” error message.</p></li>
matches.</p></li>
<li><p>User is not allowed to execute the command (<code class="docutils literal notranslate"><span class="pre">syscmdkeys.CMD_NOPERM</span></code>) - Default is to display the
“Huh?” error message.</p></li>
<li><p>Channel (<code class="docutils literal notranslate"><span class="pre">syscmdkeys.CMD_CHANNEL</span></code>) - This is a <a class="reference internal" href="Communications.html"><span class="doc">Channel</span></a> name of a channel you are
<li><p>Channel (<code class="docutils literal notranslate"><span class="pre">syscmdkeys.CMD_CHANNEL</span></code>) - This is a <a class="reference internal" href="Communications.html"><span class="doc std std-doc">Channel</span></a> name of a channel you are
subscribing to - Default is to relay the commands argument to that channel. Such commands are
created by the Comm system on the fly depending on your subscriptions.</p></li>
<li><p>New session connection (<code class="docutils literal notranslate"><span class="pre">syscmdkeys.CMD_LOGINSTART</span></code>). This command name should be put in the
@ -599,13 +499,7 @@ called on the server (default is to show the login screen).</p></li>
<p>Below is an example of redefining what happens when the account doesnt provide any input (e.g. just
presses return). Of course the new system command must be added to a cmdset as well before it will
work.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">syscmdkeys</span><span class="p">,</span> <span class="n">Command</span>
<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">syscmdkeys</span><span class="p">,</span> <span class="n">Command</span>
<span class="k">class</span> <span class="nc">MyNoInputCommand</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="s2">&quot;Usage: Just press return, I dare you&quot;</span>
@ -613,26 +507,23 @@ work.</p>
<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="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="s2">&quot;Don&#39;t just press return like that, talk to me!&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
</section>
<section id="dynamic-commands">
<h2>Dynamic Commands<a class="headerlink" href="#dynamic-commands" title="Permalink to this headline"></a></h2>
<p><em>Note: This is an advanced topic.</em></p>
<p>Normally Commands are created as fixed classes and used without modification. There are however
situations when the exact key, alias or other properties is not possible (or impractical) to pre-
code (<a class="reference external" href="Components/Commands.html#Exits">Exits</a> is an example of this).</p>
code (<a class="reference internal" href="#exits"><span class="std std-doc">Exits</span></a> is an example of this).</p>
<p>To create a command with a dynamic call signature, first define the command body normally in a class
(set your <code class="docutils literal notranslate"><span class="pre">key</span></code>, <code class="docutils literal notranslate"><span class="pre">aliases</span></code> to default values), then use the following call (assuming the command
class you created is named <code class="docutils literal notranslate"><span class="pre">MyCommand</span></code>):</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">cmd</span> <span class="o">=</span> <span class="n">MyCommand</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="s2">&quot;newname&quot;</span><span class="p">,</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">cmd</span> <span class="o">=</span> <span class="n">MyCommand</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="s2">&quot;newname&quot;</span><span class="p">,</span>
<span class="n">aliases</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;test&quot;</span><span class="p">,</span> <span class="s2">&quot;test2&quot;</span><span class="p">],</span>
<span class="n">locks</span><span class="o">=</span><span class="s2">&quot;cmd:all()&quot;</span><span class="p">,</span>
<span class="o">...</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p><em>All</em> keyword arguments you give to the Command constructor will be stored as a property on the
command object. This will overload existing properties defined on the parent class.</p>
<p>Normally you would define your class and only overload things like <code class="docutils literal notranslate"><span class="pre">key</span></code> and <code class="docutils literal notranslate"><span class="pre">aliases</span></code> at run-time.
@ -642,9 +533,9 @@ make your command completely customized at run-time.</p>
<section id="exits">
<h2>Exits<a class="headerlink" href="#exits" title="Permalink to this headline"></a></h2>
<p><em>Note: This is an advanced topic.</em></p>
<p>Exits are examples of the use of a <a class="reference external" href="Components/Commands.html#Dynamic_Commands">Dynamic Command</a>.</p>
<p>The functionality of <a class="reference internal" href="Objects.html"><span class="doc">Exit</span></a> objects in Evennia is not hard-coded in the engine. Instead
Exits are normal <a class="reference internal" href="Typeclasses.html"><span class="doc">typeclassed</span></a> objects that auto-create a <a class="reference external" href="Components/Commands.html#CmdSets">CmdSet</a> on
<p>Exits are examples of the use of a <a class="reference internal" href="#dynamic-commands"><span class="std std-doc">Dynamic Command</span></a>.</p>
<p>The functionality of <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Exit</span></a> objects in Evennia is not hard-coded in the engine. Instead
Exits are normal <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">typeclassed</span></a> objects that auto-create a <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">CmdSet</span></a> on
themselves when they load. This cmdset has a single dynamically created Command with the same
properties (key, aliases and locks) as the Exit object itself. When entering the name of the exit,
this dynamic exit-command is triggered and (after access checks) moves the Character to the exits
@ -668,16 +559,7 @@ so that you can back-reference the previous arguments etc.</p>
<div><p>Note: On a server reload, all Commands are rebuilt and memory is flushed.</p>
</div></blockquote>
<p>To show this in practice, consider this command:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">CmdTestID</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">CmdTestID</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">&quot;testid&quot;</span>
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
@ -687,8 +569,9 @@ so that you can back-reference the previous arguments etc.</p>
<span class="bp">self</span><span class="o">.</span><span class="n">xval</span> <span class="o">+=</span> <span class="mi">1</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">&quot;Command memory ID: </span><span class="si">{</span><span class="nb">id</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span><span class="si">}</span><span class="s2"> (xval=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">xval</span><span class="si">}</span><span class="s2">)&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Adding this to the default character cmdset gives a result like this in-game:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">testid</span>
<span class="n">Command</span> <span class="n">memory</span> <span class="n">ID</span><span class="p">:</span> <span class="mi">140313967648552</span> <span class="p">(</span><span class="n">xval</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
@ -710,6 +593,7 @@ keyword argument, will assign that keyword argument as a property on this paricu
<span class="k">def</span> <span class="nf">at_cmdset_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">MyCommand</span><span class="p">(</span><span class="n">myvar</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">foo</span><span class="o">=</span><span class="s2">&quot;test&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>This will start the <code class="docutils literal notranslate"><span class="pre">MyCommand</span></code> with <code class="docutils literal notranslate"><span class="pre">myvar</span></code> and <code class="docutils literal notranslate"><span class="pre">foo</span></code> set as properties (accessable as <code class="docutils literal notranslate"><span class="pre">self.myvar</span></code>
@ -740,9 +624,9 @@ cmdset, ignore.</p></li>
<li><p>CmdSets defined on the current account, if caller is a puppeted object.</p></li>
<li><p>CmdSets defined on the Session itself.</p></li>
<li><p>The active CmdSets of eventual objects in the same location (if any). This includes commands
on <a class="reference external" href="Components/Objects.html#Exits">Exits</a>.</p></li>
on <a class="reference internal" href="Objects.html#exits"><span class="std std-doc">Exits</span></a>.</p></li>
<li><p>Sets of dynamically created <em>System commands</em> representing available
<a class="reference external" href="Components/Communications.html#Channels">Communications</a>.</p></li>
<a class="reference internal" href="Channels.html"><span class="doc std std-doc">Communications</span></a></p></li>
</ul>
</li>
<li><p>All CmdSets <em>of the same priority</em> are merged together in groups. Grouping avoids order-
@ -783,17 +667,13 @@ doing useful things.</p></li>
<a class="reference external" href="https://twistedmatrix.com/documents/current/core/howto/defer.html">deferred</a>.
Evennia does not use this return value at all by default. If you do, you must
thus do so asynchronously, using callbacks.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># in command class func()</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># in command class func()</span>
<span class="k">def</span> <span class="nf">callback</span><span class="p">(</span><span class="n">ret</span><span class="p">,</span> <span class="n">caller</span><span class="p">):</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">&quot;Returned is </span><span class="si">{</span><span class="n">ret</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="n">deferred</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">execute_command</span><span class="p">(</span><span class="s2">&quot;longrunning&quot;</span><span class="p">)</span>
<span class="n">deferred</span><span class="o">.</span><span class="n">addCallback</span><span class="p">(</span><span class="n">callback</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>This is probably not relevant to any but the most advanced/exotic designs (one might use it to
create a “nested” command structure for example).</p>
<p>The <code class="docutils literal notranslate"><span class="pre">save_for_next</span></code> class variable can be used to implement state-persistent commands. For example
@ -869,7 +749,7 @@ on.</p>
<h3>Versions</h3>
<ul>
<li><a href="Commands.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,12 +40,12 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="communications">
<section class="tex2jax_ignore mathjax_ignore" id="communications">
<h1>Communications<a class="headerlink" href="#communications" title="Permalink to this headline"></a></h1>
<p>TODO: Remove this page?</p>
<ul class="simple">
<li><p><a class="reference internal" href="Channels.html"><span class="doc">Channels</span></a> - are used for implementing in-game chat rooms.</p></li>
<li><p><a class="reference internal" href="Msg.html"><span class="doc">Msg</span></a>-objects are used for storing messages in the database (email-like)
<li><p><a class="reference internal" href="Channels.html"><span class="doc std std-doc">Channels</span></a> - are used for implementing in-game chat rooms.</p></li>
<li><p><a class="reference internal" href="Msg.html"><span class="doc std std-doc">Msg</span></a>-objects are used for storing messages in the database (email-like)
and is a building block for implementing other game systems. Its used by the
<code class="docutils literal notranslate"><span class="pre">page</span></code> command by default.</p></li>
</ul>
@ -89,7 +91,7 @@ and is a building block for implementing other game systems. Its used by the
<h3>Versions</h3>
<ul>
<li><a href="Communications.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -46,48 +48,48 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="core-components">
<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">API</span></a>.</p>
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="database-entites">
<h2>Database entites<a class="headerlink" href="#database-entites" title="Permalink to this headline"></a></h2>
<ul class="simple">
<li><p><a class="reference internal" href="Typeclasses.html"><span class="doc">Typeclasses</span></a></p>
<li><p><a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclasses</span></a></p>
<ul>
<li><p><a class="reference internal" href="Sessions.html"><span class="doc">Sessions</span></a></p></li>
<li><p><a class="reference internal" href="Accounts.html"><span class="doc">Acccounts</span></a></p>
<li><p><a class="reference internal" href="Sessions.html"><span class="doc std std-doc">Sessions</span></a></p></li>
<li><p><a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Acccounts</span></a></p>
<ul>
<li><p><a class="reference internal" href="../Concepts/Guest-Logins.html"><span class="doc">Guests</span></a></p></li>
<li><p><a class="reference internal" href="../Concepts/Guest-Logins.html"><span class="doc std std-doc">Guests</span></a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="Objects.html"><span class="doc">Objects</span></a></p></li>
<li><p><a class="reference internal" href="Scripts.html"><span class="doc">Scripts</span></a></p></li>
<li><p><a class="reference internal" href="Communications.html"><span class="doc">Channels and Messages</span></a></p></li>
<li><p><a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a></p></li>
<li><p><a class="reference internal" href="Scripts.html"><span class="doc std std-doc">Scripts</span></a></p></li>
<li><p><a class="reference internal" href="Communications.html"><span class="doc std std-doc">Channels and Messages</span></a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="Attributes.html"><span class="doc">Attributes</span></a></p></li>
<li><p><a class="reference internal" href="Nicks.html"><span class="doc">Nicks</span></a></p></li>
<li><p><a class="reference internal" href="Tags.html"><span class="doc">Tags</span></a></p></li>
<li><p><a class="reference internal" href="Prototypes.html"><span class="doc">Spawner and prototypes</span></a></p></li>
<li><p><a class="reference internal" href="Help-System.html"><span class="doc">Help entries</span></a></p></li>
<li><p><a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attributes</span></a></p></li>
<li><p><a class="reference internal" href="Nicks.html"><span class="doc std std-doc">Nicks</span></a></p></li>
<li><p><a class="reference internal" href="Tags.html"><span class="doc std std-doc">Tags</span></a></p></li>
<li><p><a class="reference internal" href="Prototypes.html"><span class="doc std std-doc">Spawner and prototypes</span></a></p></li>
<li><p><a class="reference internal" href="Help-System.html"><span class="doc std std-doc">Help entries</span></a></p></li>
</ul>
</section>
<section id="commands">
<h2>Commands<a class="headerlink" href="#commands" title="Permalink to this headline"></a></h2>
<ul class="simple">
<li><p><a class="reference internal" href="Command-System.html"><span class="doc">Command system</span></a></p>
<li><p><a class="reference internal" href="Default-Commands.html"><span class="doc std std-doc">Available Default Commands</span></a></p></li>
<li><p><a class="reference internal" href="Command-System.html"><span class="doc std std-doc">Command system</span></a></p>
<ul>
<li><p><a class="reference internal" href="Commands.html"><span class="doc">Commands</span></a></p></li>
<li><p><a class="reference internal" href="Command-Sets.html"><span class="doc">Command-Sets</span></a></p></li>
<li><p><a class="reference internal" href="Connection-Screen.html"><span class="doc">The Connection Screen</span></a></p></li>
<li><p><a class="reference external" href="../api/evennia.commands.default.html#modules">Available default Commands</a></p></li>
<li><p><a class="reference internal" href="Commands.html"><span class="doc std std-doc">Commands</span></a></p></li>
<li><p><a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">Command-Sets</span></a></p></li>
<li><p><a class="reference internal" href="Connection-Screen.html"><span class="doc std std-doc">The Connection Screen</span></a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="Batch-Processors.html"><span class="doc">Batch-Processors</span></a></p>
<li><p><a class="reference internal" href="Batch-Processors.html"><span class="doc std std-doc">Batch-Processors</span></a></p>
<ul>
<li><p><a class="reference internal" href="Batch-Code-Processor.html"><span class="doc">Batch-Code-Processor</span></a></p></li>
<li><p><a class="reference internal" href="Batch-Command-Processor.html"><span class="doc">Batch-Command-Processor</span></a></p></li>
<li><p><a class="reference internal" href="Batch-Code-Processor.html"><span class="doc std std-doc">Batch-Code-Processor</span></a></p></li>
<li><p><a class="reference internal" href="Batch-Command-Processor.html"><span class="doc std std-doc">Batch-Command-Processor</span></a></p></li>
</ul>
</li>
</ul>
@ -95,38 +97,38 @@ than, the doc-strings of each component in the <a class="reference internal" hre
<section id="utils-and-tools">
<h2>Utils and tools<a class="headerlink" href="#utils-and-tools" title="Permalink to this headline"></a></h2>
<ul class="simple">
<li><p><a class="reference internal" href="Coding-Utils.html"><span class="doc">Misc Utils</span></a></p></li>
<li><p><a class="reference internal" href="EvEditor.html"><span class="doc">EvEditor</span></a></p></li>
<li><p><a class="reference internal" href="EvMenu.html"><span class="doc">EvMenu</span></a></p></li>
<li><p><a class="reference internal" href="EvMore.html"><span class="doc">EvMore</span></a></p></li>
<li><p><a class="reference internal" href="MonitorHandler.html"><span class="doc">MonitorHandler</span></a></p></li>
<li><p><a class="reference internal" href="TickerHandler.html"><span class="doc">TickerHandler</span></a></p></li>
<li><p><a class="reference internal" href="Locks.html"><span class="doc">Lock system</span></a></p></li>
<li><p><a class="reference internal" href="FuncParser.html"><span class="doc">FuncParser</span></a></p></li>
<li><p><a class="reference internal" href="Coding-Utils.html"><span class="doc std std-doc">Misc Utils</span></a></p></li>
<li><p><a class="reference internal" href="EvEditor.html"><span class="doc std std-doc">EvEditor</span></a></p></li>
<li><p><a class="reference internal" href="EvMenu.html"><span class="doc std std-doc">EvMenu</span></a></p></li>
<li><p><a class="reference internal" href="EvMore.html"><span class="doc std std-doc">EvMore</span></a></p></li>
<li><p><a class="reference internal" href="MonitorHandler.html"><span class="doc std std-doc">MonitorHandler</span></a></p></li>
<li><p><a class="reference internal" href="TickerHandler.html"><span class="doc std std-doc">TickerHandler</span></a></p></li>
<li><p><a class="reference internal" href="Locks.html"><span class="doc std std-doc">Lock system</span></a></p></li>
<li><p><a class="reference internal" href="FuncParser.html"><span class="doc std std-doc">FuncParser</span></a></p></li>
</ul>
</section>
<section id="server-and-network">
<h2>Server and network<a class="headerlink" href="#server-and-network" title="Permalink to this headline"></a></h2>
<ul class="simple">
<li><p><a class="reference internal" href="Portal-And-Server.html"><span class="doc">Portal</span></a></p>
<li><p><a class="reference internal" href="Portal-And-Server.html"><span class="doc std std-doc">Portal</span></a></p>
<ul>
<li><p><a class="reference internal" href="Inputfuncs.html"><span class="doc">Inputfuncs</span></a></p></li>
<li><p><a class="reference internal" href="Outputfuncs.html"><span class="doc">Outputfuncs</span></a></p></li>
<li><p><a class="reference internal" href="../Concepts/Custom-Protocols.html"><span class="doc">Protocols</span></a></p></li>
<li><p><a class="reference internal" href="Inputfuncs.html"><span class="doc std std-doc">Inputfuncs</span></a></p></li>
<li><p><a class="reference internal" href="Outputfuncs.html"><span class="doc std std-doc">Outputfuncs</span></a></p></li>
<li><p><a class="reference internal" href="../Concepts/Custom-Protocols.html"><span class="doc std std-doc">Protocols</span></a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="Server.html"><span class="doc">Server</span></a></p>
<li><p><a class="reference internal" href="Server.html"><span class="doc std std-doc">Server</span></a></p>
<ul>
<li><p><a class="reference internal" href="Server-Conf.html"><span class="doc">Server conf object</span></a></p></li>
<li><p><a class="reference internal" href="../Setup/Server-Conf.html"><span class="doc std std-doc">Server conf object</span></a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="Webserver.html"><span class="doc">Webserver</span></a></p>
<li><p><a class="reference internal" href="Webserver.html"><span class="doc std std-doc">Webserver</span></a></p>
<ul>
<li><p><a class="reference internal" href="Webclient.html"><span class="doc">Webclient</span></a></p></li>
<li><p><a class="reference internal" href="Bootstrap-Components-and-Utilities.html"><span class="doc">Bootstrap</span></a></p></li>
<li><p><a class="reference internal" href="Webclient.html"><span class="doc std std-doc">Webclient</span></a></p></li>
<li><p><a class="reference internal" href="Bootstrap-Components-and-Utilities.html"><span class="doc std std-doc">Bootstrap</span></a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="Signals.html"><span class="doc">Signals</span></a></p></li>
<li><p><a class="reference internal" href="Signals.html"><span class="doc std std-doc">Signals</span></a></p></li>
</ul>
</section>
</section>
@ -188,7 +190,7 @@ than, the doc-strings of each component in the <a class="reference internal" hre
<h3>Versions</h3>
<ul>
<li><a href="Components-Overview.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,10 +40,10 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="connection-screen">
<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 Evennias default connection screen.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>==============================================================
<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:
@ -58,7 +60,7 @@
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/Start-Stop-Reload.html"><span class="doc">Reload</span></a> Evennia.</p></li>
<li><p><a class="reference internal" href="../Setup/Start-Stop-Reload.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
@ -66,10 +68,10 @@ one such string/screen is defined in the module, a <em>random</em> screen will b
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">Commands</span></a> available to use while the connection screen is
<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">Commands</span></a> and the
<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>
@ -122,7 +124,7 @@ tutorial section on how to add new commands to a default command set.</p>
<h3>Versions</h3>
<ul>
<li><a href="Connection-Screen.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -0,0 +1,235 @@
<!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>Default Commands &#8212; Evennia 1.0-dev documentation</title>
<link rel="stylesheet" href="../_static/nature.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Coding and development help" href="../Coding/Coding-Overview.html" />
<link rel="prev" title="API Summary" href="../Evennia-API.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="../Coding/Coding-Overview.html" title="Coding and development help"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="../Evennia-API.html" title="API Summary"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Default Commands</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section class="tex2jax_ignore mathjax_ignore" id="default-commands">
<h1>Default Commands<a class="headerlink" href="#default-commands" title="Permalink to this headline"></a></h1>
<p>The full set of default Evennia commands currently contains 97 commands in 9 source
files. Our policy for adding default commands is outlined <a class="reference internal" href="../Concepts/Using-MUX-as-a-Standard.html"><span class="doc std std-doc">here</span></a>. The
<a class="reference internal" href="Commands.html"><span class="doc std std-doc">Commands</span></a> documentation explains how Commands work as well as make new or customize
existing ones. Note that this page is auto-generated. Report problems to the <a class="reference external" href="https://github.com/evennia/evennia/blob/master/issues">issue
tracker</a>.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Some game-states adds their own Commands which are not listed here. Examples include editing a text
with <a class="reference internal" href="EvEditor.html"><span class="doc std std-doc">EvEditor</span></a>, flipping pages in <a class="reference internal" href="EvMore.html"><span class="doc std std-doc">EvMore</span></a> or using the
<a class="reference internal" href="Batch-Processors.html"><span class="doc std std-doc">Batch-Processor</span></a>s interactive mode.</p>
</div>
<ul class="simple">
<li><p><a class="reference internal" href="../api/evennia.commands.default.unloggedin.html#evennia.commands.default.unloggedin.CmdUnconnectedLook" title="evennia.commands.default.unloggedin.CmdUnconnectedLook"><span class="xref myst py py-class"><strong>__unloggedin_look_command</strong> [l, look]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_unloggedin.html#evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet" title="evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet"><span class="xref myst py py-class">UnloggedinCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.system.html#evennia.commands.default.system.CmdAbout" title="evennia.commands.default.system.CmdAbout"><span class="xref myst py py-class"><strong>about</strong> [version]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>System</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.general.html#evennia.commands.default.general.CmdAccess" title="evennia.commands.default.general.CmdAccess"><span class="xref myst py py-class"><strong>access</strong> [groups, hierarchy]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.system.html#evennia.commands.default.system.CmdAccounts" title="evennia.commands.default.system.CmdAccounts"><span class="xref myst py py-class"><strong>accounts</strong> [listaccounts, account]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>System</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdAddCom" title="evennia.commands.default.comms.CmdAddCom"><span class="xref myst py py-class"><strong>addcom</strong> [chanalias, aliaschan]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>Comms</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdSetObjAlias" title="evennia.commands.default.building.CmdSetObjAlias"><span class="xref myst py py-class"><strong>alias</strong> [setobjalias]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdAllCom" title="evennia.commands.default.comms.CmdAllCom"><span class="xref myst py py-class"><strong>allcom</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>Comms</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.batchprocess.html#evennia.commands.default.batchprocess.CmdBatchCode" title="evennia.commands.default.batchprocess.CmdBatchCode"><span class="xref myst py py-class"><strong>batchcode</strong> [batchcodes]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.batchprocess.html#evennia.commands.default.batchprocess.CmdBatchCommands" title="evennia.commands.default.batchprocess.CmdBatchCommands"><span class="xref myst py py-class"><strong>batchcommands</strong> [batchcmd, batchcommand]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdCBoot" title="evennia.commands.default.comms.CmdCBoot"><span class="xref myst py py-class"><strong>cboot</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>Comms</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdChannelCreate" title="evennia.commands.default.comms.CmdChannelCreate"><span class="xref myst py py-class"><strong>ccreate</strong> [channelcreate]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>Comms</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdCdesc" title="evennia.commands.default.comms.CmdCdesc"><span class="xref myst py py-class"><strong>cdesc</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>Comms</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdCdestroy" title="evennia.commands.default.comms.CmdCdestroy"><span class="xref myst py py-class"><strong>cdestroy</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>Comms</em>)</p></li>
<li><p><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"><strong>channel</strong> [chan, channels]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>Comms</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.account.html#evennia.commands.default.account.CmdCharCreate" title="evennia.commands.default.account.CmdCharCreate"><span class="xref myst py py-class"><strong>charcreate</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.account.html#evennia.commands.default.account.CmdCharDelete" title="evennia.commands.default.account.CmdCharDelete"><span class="xref myst py py-class"><strong>chardelete</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdClock" title="evennia.commands.default.comms.CmdClock"><span class="xref myst py py-class"><strong>clock</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>Comms</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdListCmdSets" title="evennia.commands.default.building.CmdListCmdSets"><span class="xref myst py py-class"><strong>cmdsets</strong> [listcmsets]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.account.html#evennia.commands.default.account.CmdColorTest" title="evennia.commands.default.account.CmdColorTest"><span class="xref myst py py-class"><strong>color</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.unloggedin.html#evennia.commands.default.unloggedin.CmdUnconnectedConnect" title="evennia.commands.default.unloggedin.CmdUnconnectedConnect"><span class="xref myst py py-class"><strong>connect</strong> [conn, co, con]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_unloggedin.html#evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet" title="evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet"><span class="xref myst py py-class">UnloggedinCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdCopy" title="evennia.commands.default.building.CmdCopy"><span class="xref myst py py-class"><strong>copy</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdCpAttr" title="evennia.commands.default.building.CmdCpAttr"><span class="xref myst py py-class"><strong>cpattr</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdCreate" title="evennia.commands.default.building.CmdCreate"><span class="xref myst py py-class"><strong>create</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.unloggedin.html#evennia.commands.default.unloggedin.CmdUnconnectedCreate" title="evennia.commands.default.unloggedin.CmdUnconnectedCreate"><span class="xref myst py py-class"><strong>create</strong> [cr, cre]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_unloggedin.html#evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet" title="evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet"><span class="xref myst py py-class">UnloggedinCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdCWho" title="evennia.commands.default.comms.CmdCWho"><span class="xref myst py py-class"><strong>cwho</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>Comms</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdDelCom" title="evennia.commands.default.comms.CmdDelCom"><span class="xref myst py py-class"><strong>delcom</strong> [delchanalias, delaliaschan]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>Comms</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdDesc" title="evennia.commands.default.building.CmdDesc"><span class="xref myst py py-class"><strong>desc</strong> [describe]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdDestroy" title="evennia.commands.default.building.CmdDestroy"><span class="xref myst py py-class"><strong>destroy</strong> [del, delete]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdDig" title="evennia.commands.default.building.CmdDig"><span class="xref myst py py-class"><strong>dig</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.general.html#evennia.commands.default.general.CmdDrop" title="evennia.commands.default.general.CmdDrop"><span class="xref myst py py-class"><strong>drop</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.unloggedin.html#evennia.commands.default.unloggedin.CmdUnconnectedEncoding" title="evennia.commands.default.unloggedin.CmdUnconnectedEncoding"><span class="xref myst py py-class"><strong>encoding</strong> [encode]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_unloggedin.html#evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet" title="evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet"><span class="xref myst py py-class">UnloggedinCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdExamine" title="evennia.commands.default.building.CmdExamine"><span class="xref myst py py-class"><strong>examine</strong> [ex, exam]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdFind" title="evennia.commands.default.building.CmdFind"><span class="xref myst py py-class"><strong>find</strong> [locate, search]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.general.html#evennia.commands.default.general.CmdGet" title="evennia.commands.default.general.CmdGet"><span class="xref myst py py-class"><strong>get</strong> [grab]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.general.html#evennia.commands.default.general.CmdGive" title="evennia.commands.default.general.CmdGive"><span class="xref myst py py-class"><strong>give</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdGrapevine2Chan" title="evennia.commands.default.comms.CmdGrapevine2Chan"><span class="xref myst py py-class"><strong>grapevine2chan</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>Comms</em>)</p></li>
<li><p><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"><strong>help</strong> [?]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.unloggedin.html#evennia.commands.default.unloggedin.CmdUnconnectedHelp" title="evennia.commands.default.unloggedin.CmdUnconnectedHelp"><span class="xref myst py py-class"><strong>help</strong> [h, ?]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_unloggedin.html#evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet" title="evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet"><span class="xref myst py py-class">UnloggedinCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.general.html#evennia.commands.default.general.CmdHome" title="evennia.commands.default.general.CmdHome"><span class="xref myst py py-class"><strong>home</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.account.html#evennia.commands.default.account.CmdIC" title="evennia.commands.default.account.CmdIC"><span class="xref myst py py-class"><strong>ic</strong> [puppet]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.unloggedin.html#evennia.commands.default.unloggedin.CmdUnconnectedInfo" title="evennia.commands.default.unloggedin.CmdUnconnectedInfo"><span class="xref myst py py-class"><strong>info</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_unloggedin.html#evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet" title="evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet"><span class="xref myst py py-class">UnloggedinCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.general.html#evennia.commands.default.general.CmdInventory" title="evennia.commands.default.general.CmdInventory"><span class="xref myst py py-class"><strong>inventory</strong> [i, inv]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdIRC2Chan" title="evennia.commands.default.comms.CmdIRC2Chan"><span class="xref myst py py-class"><strong>irc2chan</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>Comms</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdIRCStatus" title="evennia.commands.default.comms.CmdIRCStatus"><span class="xref myst py py-class"><strong>ircstatus</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>Comms</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdLink" title="evennia.commands.default.building.CmdLink"><span class="xref myst py py-class"><strong>link</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdLock" title="evennia.commands.default.building.CmdLock"><span class="xref myst py py-class"><strong>lock</strong> [locks]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.account.html#evennia.commands.default.account.CmdOOCLook" title="evennia.commands.default.account.CmdOOCLook"><span class="xref myst py py-class"><strong>look</strong> [ls, l]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.general.html#evennia.commands.default.general.CmdLook" title="evennia.commands.default.general.CmdLook"><span class="xref myst py py-class"><strong>look</strong> [ls, l]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdMvAttr" title="evennia.commands.default.building.CmdMvAttr"><span class="xref myst py py-class"><strong>mvattr</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdName" title="evennia.commands.default.building.CmdName"><span class="xref myst py py-class"><strong>name</strong> [rename]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.general.html#evennia.commands.default.general.CmdNick" title="evennia.commands.default.general.CmdNick"><span class="xref myst py py-class"><strong>nick</strong> [nickname, nicks]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdObjects" title="evennia.commands.default.building.CmdObjects"><span class="xref myst py py-class"><strong>objects</strong> [listobjs, listobjects, db, stats]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>System</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.account.html#evennia.commands.default.account.CmdOOC" title="evennia.commands.default.account.CmdOOC"><span class="xref myst py py-class"><strong>ooc</strong> [unpuppet]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdOpen" title="evennia.commands.default.building.CmdOpen"><span class="xref myst py py-class"><strong>open</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.account.html#evennia.commands.default.account.CmdOption" title="evennia.commands.default.account.CmdOption"><span class="xref myst py py-class"><strong>option</strong> [options]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdPage" title="evennia.commands.default.comms.CmdPage"><span class="xref myst py py-class"><strong>page</strong> [tell]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>Comms</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.account.html#evennia.commands.default.account.CmdPassword" title="evennia.commands.default.account.CmdPassword"><span class="xref myst py py-class"><strong>password</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.general.html#evennia.commands.default.general.CmdPose" title="evennia.commands.default.general.CmdPose"><span class="xref myst py py-class"><strong>pose</strong> [:, emote]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.system.html#evennia.commands.default.system.CmdPy" title="evennia.commands.default.system.CmdPy"><span class="xref myst py py-class"><strong>py</strong> [!]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>System</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.account.html#evennia.commands.default.account.CmdQuell" title="evennia.commands.default.account.CmdQuell"><span class="xref myst py py-class"><strong>quell</strong> [unquell]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.account.html#evennia.commands.default.account.CmdQuit" title="evennia.commands.default.account.CmdQuit"><span class="xref myst py py-class"><strong>quit</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.unloggedin.html#evennia.commands.default.unloggedin.CmdUnconnectedQuit" title="evennia.commands.default.unloggedin.CmdUnconnectedQuit"><span class="xref myst py py-class"><strong>quit</strong> [qu, q]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_unloggedin.html#evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet" title="evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet"><span class="xref myst py py-class">UnloggedinCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.system.html#evennia.commands.default.system.CmdReload" title="evennia.commands.default.system.CmdReload"><span class="xref myst py py-class"><strong>reload</strong> [restart]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>System</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.system.html#evennia.commands.default.system.CmdReset" title="evennia.commands.default.system.CmdReset"><span class="xref myst py py-class"><strong>reset</strong> [reboot]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>System</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdRSS2Chan" title="evennia.commands.default.comms.CmdRSS2Chan"><span class="xref myst py py-class"><strong>rss2chan</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>Comms</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.general.html#evennia.commands.default.general.CmdSay" title="evennia.commands.default.general.CmdSay"><span class="xref myst py py-class"><strong>say</strong> [”, ]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.unloggedin.html#evennia.commands.default.unloggedin.CmdUnconnectedScreenreader" title="evennia.commands.default.unloggedin.CmdUnconnectedScreenreader"><span class="xref myst py py-class"><strong>screenreader</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_unloggedin.html#evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet" title="evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet"><span class="xref myst py py-class">UnloggedinCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdScripts" title="evennia.commands.default.building.CmdScripts"><span class="xref myst py py-class"><strong>scripts</strong> [script]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>System</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.system.html#evennia.commands.default.system.CmdServerLoad" title="evennia.commands.default.system.CmdServerLoad"><span class="xref myst py py-class"><strong>server</strong> [serverload, serverprocess]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>System</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.system.html#evennia.commands.default.system.CmdService" title="evennia.commands.default.system.CmdService"><span class="xref myst py py-class"><strong>service</strong> [services]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>System</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.account.html#evennia.commands.default.account.CmdSessions" title="evennia.commands.default.account.CmdSessions"><span class="xref myst py py-class"><strong>sessions</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_session.html#evennia.commands.default.cmdset_session.SessionCmdSet" title="evennia.commands.default.cmdset_session.SessionCmdSet"><span class="xref myst py py-class">SessionCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdSetAttribute" title="evennia.commands.default.building.CmdSetAttribute"><span class="xref myst py py-class"><strong>set</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.general.html#evennia.commands.default.general.CmdSetDesc" title="evennia.commands.default.general.CmdSetDesc"><span class="xref myst py py-class"><strong>setdesc</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.help.html#evennia.commands.default.help.CmdSetHelp" title="evennia.commands.default.help.CmdSetHelp"><span class="xref myst py py-class"><strong>sethelp</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdSetHome" title="evennia.commands.default.building.CmdSetHome"><span class="xref myst py py-class"><strong>sethome</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.system.html#evennia.commands.default.system.CmdShutdown" title="evennia.commands.default.system.CmdShutdown"><span class="xref myst py py-class"><strong>shutdown</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>System</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdSpawn" title="evennia.commands.default.building.CmdSpawn"><span class="xref myst py py-class"><strong>spawn</strong> [olc]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.account.html#evennia.commands.default.account.CmdStyle" title="evennia.commands.default.account.CmdStyle"><span class="xref myst py py-class"><strong>style</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdTag" title="evennia.commands.default.building.CmdTag"><span class="xref myst py py-class"><strong>tag</strong> [tags]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.system.html#evennia.commands.default.system.CmdTasks" title="evennia.commands.default.system.CmdTasks"><span class="xref myst py py-class"><strong>tasks</strong> [task, delays]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>System</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdTeleport" title="evennia.commands.default.building.CmdTeleport"><span class="xref myst py py-class"><strong>tel</strong> [teleport]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.system.html#evennia.commands.default.system.CmdTickers" title="evennia.commands.default.system.CmdTickers"><span class="xref myst py py-class"><strong>tickers</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>System</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.system.html#evennia.commands.default.system.CmdTime" title="evennia.commands.default.system.CmdTime"><span class="xref myst py py-class"><strong>time</strong> [uptime]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>System</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdTunnel" title="evennia.commands.default.building.CmdTunnel"><span class="xref myst py py-class"><strong>tunnel</strong> [tun]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdTypeclass" title="evennia.commands.default.building.CmdTypeclass"><span class="xref myst py py-class"><strong>typeclass</strong> [swap, type, update, typeclasses, parent]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdUnLink" title="evennia.commands.default.building.CmdUnLink"><span class="xref myst py py-class"><strong>unlink</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.general.html#evennia.commands.default.general.CmdWhisper" title="evennia.commands.default.general.CmdWhisper"><span class="xref myst py py-class"><strong>whisper</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.account.html#evennia.commands.default.account.CmdWho" title="evennia.commands.default.account.CmdWho"><span class="xref myst py py-class"><strong>who</strong> [doing]</span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_account.html#evennia.commands.default.cmdset_account.AccountCmdSet" title="evennia.commands.default.cmdset_account.AccountCmdSet"><span class="xref myst py py-class">AccountCmdSet</span></a>, help-category: <em>General</em>)</p></li>
<li><p><a class="reference internal" href="../api/evennia.commands.default.building.html#evennia.commands.default.building.CmdWipe" title="evennia.commands.default.building.CmdWipe"><span class="xref myst py py-class"><strong>wipe</strong></span></a> (cmdset: <a class="reference internal" href="../api/evennia.commands.default.cmdset_character.html#evennia.commands.default.cmdset_character.CharacterCmdSet" title="evennia.commands.default.cmdset_character.CharacterCmdSet"><span class="xref myst py py-class">CharacterCmdSet</span></a>, help-category: <em>Building</em>)</p></li>
</ul>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/evennia_logo.png" alt="Logo"/>
</a></p>
<div id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" />
<input type="submit" value="Go" />
</form>
</div>
</div>
<script>$('#searchbox').show(0);</script>
<h4>Previous topic</h4>
<p class="topless"><a href="../Evennia-API.html"
title="previous chapter">API Summary</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="../Coding/Coding-Overview.html"
title="next chapter">Coding and development help</a></p>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="../_sources/Components/Default-Commands.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="Default-Commands.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="../Coding/Coding-Overview.html" title="Coding and development help"
>next</a> |</li>
<li class="right" >
<a href="../Evennia-API.html" title="API Summary"
>previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Default Commands</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2020, The Evennia developer community.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
</div>
</body>
</html>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,7 +40,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="eveditor">
<section class="tex2jax_ignore mathjax_ignore" id="eveditor">
<h1>EvEditor<a class="headerlink" href="#eveditor" title="Permalink to this headline"></a></h1>
<p>Evennia offers a powerful in-game line editor in <code class="docutils literal notranslate"><span class="pre">evennia.utils.eveditor.EvEditor</span></code>. This editor,
mimicking the well-known VI line editor. It offers line-by-line editing, undo/redo, line deletes,
@ -46,17 +48,13 @@ search/replace, fill, dedent and more.</p>
<section id="launching-the-editor">
<h2>Launching the editor<a class="headerlink" href="#launching-the-editor" title="Permalink to this headline"></a></h2>
<p>The editor is created as follows:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.utils.eveditor</span> <span class="kn">import</span> <span class="n">EvEditor</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.utils.eveditor</span> <span class="kn">import</span> <span class="n">EvEditor</span>
<span class="n">EvEditor</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span>
<span class="n">loadfunc</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">savefunc</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">quitfunc</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">EvEditor</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span>
<span class="n">loadfunc</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">savefunc</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">quitfunc</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">key</span><span class="o">=</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">caller</span></code> (Object or Account): The user of the editor.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">loadfunc</span></code> (callable, optional): This is a function called when the editor is first started. It
@ -74,40 +72,12 @@ It has no other mechanical function.</p></li>
<section id="example-of-usage">
<h2>Example of usage<a class="headerlink" href="#example-of-usage" 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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span></pre></div></td><td class="code"><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>
<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>
<span class="k">class</span> <span class="nc">CmdSetTestAttr</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Set the &quot;test&quot; Attribute using </span>
<span class="sd"> Set the &quot;test&quot; Attribute using</span>
<span class="sd"> the line editor.</span>
<span class="sd"> Usage:</span>
@ -128,11 +98,11 @@ It has no other mechanical function.</p></li>
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;Editor exited&quot;</span><span class="p">)</span>
<span class="n">key</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="si">}</span><span class="s2">/test&quot;</span>
<span class="c1"># launch the editor</span>
<span class="n">eveditor</span><span class="o">.</span><span class="n">EvEditor</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="p">,</span>
<span class="n">loadfunc</span><span class="o">=</span><span class="n">load</span><span class="p">,</span> <span class="n">savefunc</span><span class="o">=</span><span class="n">save</span><span class="p">,</span> <span class="n">quitfunc</span><span class="o">=</span><span class="n">quit</span><span class="p">,</span>
<span class="n">key</span><span class="o">=</span><span class="n">key</span><span class="p">)</span>
<span class="n">eveditor</span><span class="o">.</span><span class="n">EvEditor</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="p">,</span>
<span class="n">loadfunc</span><span class="o">=</span><span class="n">load</span><span class="p">,</span> <span class="n">savefunc</span><span class="o">=</span><span class="n">save</span><span class="p">,</span> <span class="n">quitfunc</span><span class="o">=</span><span class="n">quit</span><span class="p">,</span>
<span class="n">key</span><span class="o">=</span><span class="n">key</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
</section>
<section id="persistent-editor">
<h2>Persistent editor<a class="headerlink" href="#persistent-editor" title="Permalink to this headline"></a></h2>
@ -140,38 +110,7 @@ It has no other mechanical function.</p></li>
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
functions will be stored, Python will need to find them.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span></pre></div></td><td class="code"><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>
<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>
<span class="k">def</span> <span class="nf">load</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
@ -188,7 +127,7 @@ functions will be stored, Python will need to find them.</p>
<span class="k">class</span> <span class="nc">CmdSetTestAttr</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Set the &quot;test&quot; Attribute using </span>
<span class="sd"> Set the &quot;test&quot; Attribute using</span>
<span class="sd"> the line editor.</span>
<span class="sd"> Usage:</span>
@ -200,11 +139,11 @@ functions will be stored, Python will need to find them.</p>
<span class="s2">&quot;Set up the callbacks and launch the editor&quot;</span>
<span class="n">key</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="si">}</span><span class="s2">/test&quot;</span>
<span class="c1"># launch the editor</span>
<span class="n">eveditor</span><span class="o">.</span><span class="n">EvEditor</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="p">,</span>
<span class="n">loadfunc</span><span class="o">=</span><span class="n">load</span><span class="p">,</span> <span class="n">savefunc</span><span class="o">=</span><span class="n">save</span><span class="p">,</span> <span class="n">quitfunc</span><span class="o">=</span><span class="n">quit</span><span class="p">,</span>
<span class="n">key</span><span class="o">=</span><span class="n">key</span><span class="p">,</span> <span class="n">persistent</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="n">eveditor</span><span class="o">.</span><span class="n">EvEditor</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="p">,</span>
<span class="n">loadfunc</span><span class="o">=</span><span class="n">load</span><span class="p">,</span> <span class="n">savefunc</span><span class="o">=</span><span class="n">save</span><span class="p">,</span> <span class="n">quitfunc</span><span class="o">=</span><span class="n">quit</span><span class="p">,</span>
<span class="n">key</span><span class="o">=</span><span class="n">key</span><span class="p">,</span> <span class="n">persistent</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</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>
@ -330,7 +269,7 @@ editor can be useful if you want to test the code you have typed but add new lin
<h3>Versions</h3>
<ul>
<li><a href="EvEditor.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,7 +40,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="evmenu">
<section class="tex2jax_ignore mathjax_ignore" id="evmenu">
<h1>EvMenu<a class="headerlink" href="#evmenu" title="Permalink to this headline"></a></h1>
<section id="introduction">
<h2>Introduction<a class="headerlink" href="#introduction" title="Permalink to this headline"></a></h2>
@ -55,6 +57,7 @@ creation, building commands or similar. Below is an example of offering NPC conv
<span class="mf">3.</span> <span class="n">Appeal</span> <span class="n">to</span> <span class="n">his</span> <span class="n">vanity</span> <span class="p">[</span><span class="n">Cha</span><span class="p">]</span>
<span class="mf">4.</span> <span class="n">Try</span> <span class="n">to</span> <span class="n">knock</span> <span class="n">him</span> <span class="n">out</span> <span class="p">[</span><span class="n">Luck</span> <span class="o">+</span> <span class="n">Dex</span><span class="p">]</span>
<span class="mf">5.</span> <span class="n">Try</span> <span class="n">to</span> <span class="n">run</span> <span class="n">away</span> <span class="p">[</span><span class="n">Dex</span><span class="p">]</span>
</pre></div>
</div>
<p>This is an example of a menu <em>node</em>. Think of a node as a point where the menu stops printing text
@ -67,18 +70,8 @@ said functions, like <code class="docutils literal notranslate"><span class="pre
<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
most common way to do so - from inside a <a class="reference internal" href="Commands.html"><span class="doc">Command</span></a>:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in, for example gamedir/commands/command.py</span>
most common way to do so - from inside a <a class="reference internal" href="Commands.html"><span class="doc std std-doc">Command</span></a>:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in, for example gamedir/commands/command.py</span>
<span class="kn">from</span> <span class="nn">evennia.utils.evmenu</span> <span class="kn">import</span> <span class="n">EvMenu</span>
@ -89,21 +82,13 @@ most common way to do so - from inside a <a class="reference internal" href="Com
<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">EvMenu</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s2">&quot;world.mymenu&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>When running this command, the menu will start using the menu nodes loaded from
<code class="docutils literal notranslate"><span class="pre">mygame/world/mymenu.py</span></code>. See next section on how to define menu nodes.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> has the following optional callsign:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">EvMenu</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">menu_data</span><span class="p">,</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">EvMenu</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">menu_data</span><span class="p">,</span>
<span class="n">startnode</span><span class="o">=</span><span class="s2">&quot;start&quot;</span><span class="p">,</span>
<span class="n">cmdset_mergetype</span><span class="o">=</span><span class="s2">&quot;Replace&quot;</span><span class="p">,</span> <span class="n">cmdset_priority</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span>
<span class="n">auto_quit</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">auto_look</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">auto_help</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
@ -113,11 +98,12 @@ most common way to do so - from inside a <a class="reference internal" href="Com
<span class="n">session</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">debug</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
</pre></div>
</td></tr></table></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">CmdSet</span></a> assigned to it, for handling the menu.</p></li>
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
@ -154,7 +140,7 @@ 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
start node as if it was entered on a fictional previous node. This can be very useful in order to
start a menu differently depending on the Commands arguments in which it was initialized.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">session</span></code> (Session): Useful when calling the menu from an <a class="reference internal" href="Accounts.html"><span class="doc">Account</span></a> in
<li><p><code class="docutils literal notranslate"><span class="pre">session</span></code> (Session): Useful when calling the menu from an <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Account</span></a> in
<code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODDE</span></code> higher than 2, to make sure only the right Session sees the menu output.</p></li>
<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">&lt;variable&gt;</span></code> to inspect a specific state
@ -172,17 +158,7 @@ menu. Temporary variables you store on a persistent <code class="docutils litera
<section id="the-menu-nodes">
<h2>The Menu nodes<a class="headerlink" href="#the-menu-nodes" title="Permalink to this headline"></a></h2>
<p>The EvMenu nodes consist of functions on one of these forms.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">menunodename1</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">menunodename1</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
<span class="c1"># code</span>
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
@ -193,8 +169,9 @@ menu. Temporary variables you store on a persistent <code class="docutils litera
<span class="k">def</span> <span class="nf">menunodename3</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"># code</span>
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
</pre></div>
</td></tr></table></div>
</div>
<blockquote>
<div><p>While all of the above forms are okay, its recommended to stick to the third and last form since
it
@ -224,9 +201,9 @@ node.</p></li>
<p>The <code class="docutils literal notranslate"><span class="pre">text</span></code> variable is a string or tuple. This text is what will be displayed when the user reaches
this node. If this is a tuple, then the first element of the tuple will be considered the displayed
text and the second the help-text to display when the user enters the <code class="docutils literal notranslate"><span class="pre">help</span></code> command on this node.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">text</span> <span class="o">=</span> <span class="p">(</span><span class="s2">&quot;This is the text to display&quot;</span><span class="p">,</span> <span class="s2">&quot;This is the help text for this node&quot;</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">text</span> <span class="o">=</span> <span class="p">(</span><span class="s2">&quot;This is the text to display&quot;</span><span class="p">,</span> <span class="s2">&quot;This is the help text for this node&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Returning a <code class="docutils literal notranslate"><span class="pre">None</span></code> text is allowed and simply leads to a node with no text and only options. If the
help text is not given, the menu will give a generic error message when using <code class="docutils literal notranslate"><span class="pre">help</span></code>.</p>
</section>
@ -239,19 +216,7 @@ menu immediately exits, running the <code class="docutils literal notranslate"><
<p>Otherwise, <code class="docutils literal notranslate"><span class="pre">options</span></code> should be a list (or tuple) of dictionaries, one for each option. If only one
option is
available, a single dictionary can also be returned. This is how it could look:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">node_test</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>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">node_test</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="n">text</span> <span class="o">=</span> <span class="s2">&quot;A goblin attacks you!&quot;</span>
@ -264,14 +229,16 @@ available, a single dictionary can also be returned. This is how it could look:<
<span class="s2">&quot;goto&quot;</span><span class="p">:</span> <span class="p">(</span><span class="n">_defend</span><span class="p">,</span> <span class="p">{</span><span class="s2">&quot;str&quot;</span><span class="p">:</span> <span class="mi">10</span><span class="p">,</span> <span class="s2">&quot;enemyname&quot;</span><span class="p">:</span> <span class="s2">&quot;Goblin&quot;</span><span class="p">})})</span>
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
</pre></div>
</td></tr></table></div>
</div>
<p>This will produce a menu node looking like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>A goblin attacks you!
________________________________
Attack: Strike the enemy with all your might
Defend: Hold back and defend yourself
</pre></div>
</div>
<section id="option-key-key">
@ -292,6 +259,7 @@ ________________________________
1: Strike the enemy with all your might
2: Hold back and defend yourself
</pre></div>
</div>
<p>Whether you want to use a key or rely on numbers is mostly
@ -299,21 +267,16 @@ a matter of style and the type of menu.</p>
<p>EvMenu accepts one important special <code class="docutils literal notranslate"><span class="pre">key</span></code> given only as <code class="docutils literal notranslate"><span class="pre">&quot;_default&quot;</span></code>. This key is used when a user
enters something that does not match any other fixed keys. It is particularly useful for getting
user input:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">node_readuser</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>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">node_readuser</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="n">text</span> <span class="o">=</span> <span class="s2">&quot;Please enter your name&quot;</span>
<span class="n">options</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;key&quot;</span><span class="p">:</span> <span class="s2">&quot;_default&quot;</span><span class="p">,</span>
<span class="s2">&quot;goto&quot;</span><span class="p">:</span> <span class="s2">&quot;node_parse_input&quot;</span><span class="p">}</span>
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
</pre></div>
</td></tr></table></div>
</div>
<p>A <code class="docutils literal notranslate"><span class="pre">&quot;_default&quot;</span></code> option does not show up in the menu, so the above will just be a node saying
<code class="docutils literal notranslate"><span class="pre">&quot;Please</span> <span class="pre">enter</span> <span class="pre">your</span> <span class="pre">name&quot;</span></code>. The name they entered will appear as <code class="docutils literal notranslate"><span class="pre">raw_string</span></code> in the next node.</p>
</section>
@ -328,29 +291,7 @@ usually its better to keep the <code class="docutils literal notranslate"><sp
<h4>option-key goto<a class="headerlink" href="#option-key-goto" title="Permalink to this headline"></a></h4>
<p>This is the operational part of the option and fires only when the user chooses said option. Here
are three ways to write it</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
<span class="k">def</span> <span class="nf">_action_two</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"># do things ...</span>
<span class="k">return</span> <span class="s2">&quot;calculated_node_to_go_to&quot;</span>
@ -373,14 +314,15 @@ are three ways to write it</p>
<span class="p">)</span>
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
</pre></div>
</td></tr></table></div>
</div>
<p>As seen above, <code class="docutils literal notranslate"><span class="pre">goto</span></code> could just be pointing to a single <code class="docutils literal notranslate"><span class="pre">nodename</span></code> string - the name of the node to
go to. When given like this, EvMenu will look for a node named like this and call its associated
function as</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">nodename</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>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">nodename</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>
</pre></div>
</td></tr></table></div>
</div>
<p>Here, <code class="docutils literal notranslate"><span class="pre">raw_string</span></code> is always the input the user entered to make that choice and <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> are the
same as those <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> that already entered the <em>current</em> node (they are passed on).</p>
<p>Alternatively the <code class="docutils literal notranslate"><span class="pre">goto</span></code> could point to a “goto-callable”. Such callables are usually defined in the
@ -424,61 +366,7 @@ yourself.</p>
<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>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span>
<span class="normal">47</span>
<span class="normal">48</span>
<span class="normal">49</span>
<span class="normal">50</span>
<span class="normal">51</span>
<span class="normal">52</span>
<span class="normal">53</span>
<span class="normal">54</span>
<span class="normal">55</span></pre></div></td><td class="code"><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">EvMenu</span>
<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">EvMenu</span>
<span class="k">class</span> <span class="nc">MyEvMenu</span><span class="p">(</span><span class="n">EvMenu</span><span class="p">):</span>
@ -533,23 +421,23 @@ needed. Here is an example:</p>
<span class="sd"> node (str): The formatted node to display.</span>
<span class="sd"> &quot;&quot;&quot;</span>
</pre></div>
</td></tr></table></div>
</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 id="examples">
<h2>Examples:<a class="headerlink" href="#examples" title="Permalink to this headline"></a></h2>
<ul class="simple">
<li><p><strong><a class="reference external" href="Components/EvMenu.html#example-simple-branching-menu">Simple branching menu</a></strong> - choose from options</p></li>
<li><p><strong><a class="reference external" href="Components/EvMenu.html#example-dynamic-goto">Dynamic goto</a></strong> - jumping to different nodes based on response</p></li>
<li><p><strong><a class="reference external" href="Components/EvMenu.html#example-set-caller-properties">Set caller properties</a></strong> - a menu that changes things</p></li>
<li><p><strong><a class="reference external" href="Components/EvMenu.html#example-get-arbitrary-input">Getting arbitrary input</a></strong> - entering text</p></li>
<li><p><strong><a class="reference external" href="Components/EvMenu.html#example-storing-data-between-nodes">Storing data between nodes</a></strong> - keeping states and
<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>
<li><p><strong><a class="reference internal" href="#example-set-caller-properties"><span class="std std-doc">Set caller properties</span></a></strong> - a menu that changes things</p></li>
<li><p><strong><a class="reference internal" href="#example-get-arbitrary-input"><span class="std std-doc">Getting arbitrary input</span></a></strong> - entering text</p></li>
<li><p><strong><a class="reference internal" href="#example-storing-data-between-nodes"><span class="std std-doc">Storing data between nodes</span></a></strong> - keeping states and
information while in the menu</p></li>
<li><p><strong><a class="reference external" href="Components/EvMenu.html#example-repeating-the-same-node">Repeating the same node</a></strong> - validating within the node
<li><p><strong><a class="reference internal" href="#example-repeating-the-same-node"><span class="std std-doc">Repeating the same node</span></a></strong> - validating within the node
before moving to the next</p></li>
<li><p><strong><a class="reference external" href="Components/EvMenu.html#example-full-menu">Full Menu</a>:</strong> a complete example</p></li>
<li><p><strong><a class="reference external" href="Components/EvMenu.html#example-yesno-prompt">Yes/No prompt</a></strong> - entering text with limited possible responses
<li><p><strong><a class="reference internal" href="#example-yes-no-prompt"><span class="std std-doc">Yes/No prompt</span></a></strong> - entering text with limited possible responses
(this is <em>not</em> using EvMenu but the conceptually similar yet technically unrelated <code class="docutils literal notranslate"><span class="pre">get_input</span></code>
helper function accessed as <code class="docutils literal notranslate"><span class="pre">evennia.utils.evmenu.get_input</span></code>).</p></li>
</ul>
@ -557,21 +445,7 @@ helper function accessed as <code class="docutils literal notranslate"><span cla
<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>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in mygame/world/mychargen.py</span>
<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>
<span class="n">text</span> <span class="o">=</span> \
@ -586,8 +460,9 @@ choice:</p>
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
<span class="n">EvMenu</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s2">&quot;world.mychargen&quot;</span><span class="p">,</span> <span class="n">startnode</span><span class="o">=</span><span class="s2">&quot;define_character&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>This will result in the following node display:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>What aspect of your character do you want
to change next?
@ -600,26 +475,14 @@ _________________________
the following examples we will not include the <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> call but just show nodes running inside the
menu. Also, since <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> also takes a dictionary to describe the menu, we could have called it
like this instead in the example:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">EvMenu</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="p">{</span><span class="s2">&quot;define_character&quot;</span><span class="p">:</span> <span class="n">define_character</span><span class="p">},</span> <span class="n">startnode</span><span class="o">=</span><span class="s2">&quot;define_character&quot;</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">EvMenu</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="p">{</span><span class="s2">&quot;define_character&quot;</span><span class="p">:</span> <span class="n">define_character</span><span class="p">},</span> <span class="n">startnode</span><span class="o">=</span><span class="s2">&quot;define_character&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
</section>
<section id="example-dynamic-goto">
<h3>Example: Dynamic goto<a class="headerlink" href="#example-dynamic-goto" title="Permalink to this headline"></a></h3>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
<span class="k">def</span> <span class="nf">_is_in_mage_guild</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="k">if</span> <span class="n">caller</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;mage&#39;</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">&quot;guild_member&quot;</span><span class="p">):</span>
<span class="k">return</span> <span class="s2">&quot;mage_guild_welcome&quot;</span>
@ -634,10 +497,10 @@ like this instead in the example:</p>
<span class="s1">&#39;goto&#39;</span><span class="p">:</span> <span class="s1">&#39;end_conversation&#39;</span><span class="p">})</span>
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
</pre></div>
</td></tr></table></div>
</div>
<p>This simple callable goto will analyse what happens depending on who the <code class="docutils literal notranslate"><span class="pre">caller</span></code> is. The
<code class="docutils literal notranslate"><span class="pre">enter_guild</span></code> node will give you a choice of what to say to the guard. If you try to enter, you will
end up in different nodes depending on (in this example) if you have the right <a class="reference internal" href="Tags.html"><span class="doc">Tag</span></a> set on
end up in different nodes depending on (in this example) if you have the right <a class="reference internal" href="Tags.html"><span class="doc std std-doc">Tag</span></a> set on
yourself or not. Note that since we dont include any keys in the option dictionary, you will just
get to pick between numbers.</p>
</section>
@ -645,34 +508,7 @@ get to pick between numbers.</p>
<h3>Example: Set caller properties<a class="headerlink" href="#example-set-caller-properties" title="Permalink to this headline"></a></h3>
<p>Here is an example of passing arguments into the <code class="docutils literal notranslate"><span class="pre">goto</span></code> callable and use that to influence
which node it should go to next:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
<span class="k">def</span> <span class="nf">_set_attribute</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="s2">&quot;Get which attribute to modify and set it&quot;</span>
@ -701,13 +537,14 @@ which node it should go to next:</p>
<span class="s2">&quot;next_node&quot;</span><span class="p">:</span> <span class="s2">&quot;node_betrayal_background&quot;</span><span class="p">})})</span>
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
</pre></div>
</td></tr></table></div>
</div>
<p>This will give the following output:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>Kovash the magnificent experienced a traumatic event
in their childhood. What was it?
____________________________________________________
death: A violent death in the family
betrayal: The betrayal of a trusted grown-up
</pre></div>
</div>
<p>Note above how we use the <code class="docutils literal notranslate"><span class="pre">_set_attribute</span></code> helper function to set the attribute depending on the
@ -718,41 +555,7 @@ We could also imagine the helper function analyzing what other choices</p>
<section id="example-get-arbitrary-input">
<h3>Example: Get arbitrary input<a class="headerlink" href="#example-get-arbitrary-input" title="Permalink to this headline"></a></h3>
<p>An example of the menu asking the user for input - any input.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
<span class="k">def</span> <span class="nf">_set_name</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="n">inp</span> <span class="o">=</span> <span class="n">raw_string</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
@ -787,8 +590,9 @@ We could also imagine the helper function analyzing what other choices</p>
<span class="s2">&quot;goto&quot;</span><span class="p">:</span> <span class="p">(</span><span class="n">_set_name</span><span class="p">,</span> <span class="p">{</span><span class="s2">&quot;prev_entry&quot;</span><span class="p">:</span> <span class="n">prev_entry</span><span class="p">})}</span>
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
</pre></div>
</td></tr></table></div>
</div>
<p>This will display as</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Enter</span> <span class="n">your</span> <span class="n">character</span><span class="s1">&#39;s name or &lt;return&gt; to abort.</span>
@ -800,6 +604,7 @@ We could also imagine the helper function analyzing what other choices</p>
<span class="o">&gt;</span>
<span class="n">Set</span> <span class="n">name</span> <span class="n">to</span> <span class="n">Gandalf</span><span class="o">.</span>
</pre></div>
</div>
<p>Here we re-use the same node twice for reading the input data from the user. Whatever we enter will
@ -814,33 +619,7 @@ previous node, but updating its ingoing kwargs to tell it to display a different
<p>A convenient way to store data is to store it on the <code class="docutils literal notranslate"><span class="pre">caller.ndb._menutree</span></code> which you can reach from
every node. The advantage of doing this is that the <code class="docutils literal notranslate"><span class="pre">_menutree</span></code> NAttribute will be deleted
automatically when you exit the menu.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
<span class="k">def</span> <span class="nf">_set_name</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="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_menutree</span><span class="o">.</span><span class="n">charactersheet</span> <span class="o">=</span> <span class="p">{}</span>
@ -867,8 +646,9 @@ automatically when you exit the menu.</p>
<span class="s2">&quot;goto&quot;</span><span class="p">:</span> <span class="s2">&quot;start_over&quot;</span><span class="p">})</span>
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Instead of passing the character sheet along from node to node through the <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> we instead
set it up temporarily on <code class="docutils literal notranslate"><span class="pre">caller.ndb._menutree.charactersheet</span></code>. This makes it easy to reach from
all nodes. At the end we look at it and, if we accept the character the menu will likely save the
@ -886,43 +666,7 @@ when the user exits the menu.</p>
<p>Sometimes you want to make a chain of menu nodes one after another, but you dont 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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<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>
<span class="k">if</span> <span class="ow">not</span> <span class="n">lookup_username</span><span class="p">(</span><span class="n">raw_string</span><span class="p">):</span>
@ -959,8 +703,9 @@ node is ok. A common example is a login menu:</p>
<span class="n">options</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;key&quot;</span><span class="p">:</span> <span class="s2">&quot;_default&quot;</span><span class="p">,</span>
<span class="s2">&quot;goto&quot;</span><span class="p">:</span> <span class="n">_check_password</span><span class="p">}</span>
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
</pre></div>
</td></tr></table></div>
</div>
<p>This will display something like</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">---------------------------</span>
<span class="n">Please</span> <span class="n">enter</span> <span class="n">your</span> <span class="n">username</span><span class="o">.</span>
@ -995,24 +740,7 @@ to iteration until too many attempts have been made.</p>
<section id="defining-nodes-in-a-dictionary">
<h3>Defining nodes in a dictionary<a class="headerlink" href="#defining-nodes-in-a-dictionary" title="Permalink to this headline"></a></h3>
<p>You can also define your nodes directly in a dictionary to feed into the <code class="docutils literal notranslate"><span class="pre">EvMenu</span></code> creator.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">mynode</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">mynode</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
<span class="c1"># a normal menu node function</span>
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
@ -1030,8 +758,9 @@ to iteration until too many attempts have been made.</p>
<span class="c1"># start menu, assuming &#39;caller&#39; is available from earlier</span>
<span class="n">EvMenu</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">menu_data</span><span class="p">,</span> <span class="n">startnode</span><span class="o">=</span><span class="s2">&quot;node1&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>The keys of the dictionary become the node identifiers. You can use any callable on the right form
to describe each node. If you use Python <code class="docutils literal notranslate"><span class="pre">lambda</span></code> expressions you can make nodes really on the fly.
If you do, the lambda expression must accept one or two arguments and always return a tuple with two
@ -1044,7 +773,7 @@ function - for example you cant use other Python keywords like <code class="d
<code class="docutils literal notranslate"><span class="pre">lambda</span></code>.</p>
<p>Unless you are dealing with a relatively simple dynamic menu, defining menus with lambdas is
probably more work than its worth: You can create dynamic menus by instead making each node
function more clever. See the <a class="reference internal" href="../Howto/NPC-shop-Tutorial.html"><span class="doc">NPC shop tutorial</span></a> for an example of this.</p>
function more clever. See the <a class="reference internal" href="../Howto/NPC-shop-Tutorial.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">
@ -1056,20 +785,13 @@ player has entered their text, which is not what you want.</p>
<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 Pythons 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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><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">&quot;Please enter your answer:&quot;</span><span class="p">)</span>
<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">&quot;Please enter your answer:&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>This will send “Please enter your answer” to the Commands <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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><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>
<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">&quot;test&quot;</span>
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
@ -1078,7 +800,7 @@ execution will continue and you can do stuff with the <code class="docutils lite
<span class="n">result2</span> <span class="o">=</span> <span class="k">yield</span><span class="p">(</span><span class="s2">&quot;Now enter something else:&quot;</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">&quot;You now entered </span><span class="si">{</span><span class="n">result2</span><span class="si">}</span><span class="s2">.&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></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>
@ -1097,36 +819,15 @@ statement which is often easier and more intuitive to use. But <code class="docu
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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><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>
<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>
</td></tr></table></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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span></pre></div></td><td class="code"><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>
<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>
@ -1149,19 +850,20 @@ enter will be sent into the callback for whatever processing you want.</p>
<span class="n">get_input</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s2">&quot;Write something! &quot;</span><span class="p">,</span> <span class="n">callback</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>This will show as</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>Write something!
&gt; Hello
When asked &#39;Write something!&#39;, you answered &#39;Hello&#39;.
</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 external" href="Components/EvMenu.html#example-repeating-the-same-node">Repeating the same
node</a> example above). Otherwise you can either peek at 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 (its 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>
@ -1169,20 +871,7 @@ list</a>.</p>
<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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span></pre></div></td><td class="code"><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>
<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">&quot;y&quot;</span><span class="p">,</span> <span class="s2">&quot;yes&quot;</span><span class="p">,</span> <span class="s2">&quot;n&quot;</span><span class="p">,</span> <span class="s2">&quot;no&quot;</span><span class="p">):</span>
<span class="c1"># do stuff to handle the yes/no answer</span>
<span class="c1"># ...</span>
@ -1197,7 +886,7 @@ list</a>.</p>
<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">&quot;Is Evennia great (Yes/No)?&quot;</span><span class="p">,</span> <span class="n">yesno</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
</section>
</section>
</section>
@ -1214,27 +903,12 @@ It is used to quickly create menus for manipulating large numbers of items.</p>
<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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span></pre></div></td><td class="code"><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>
<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>
@ -1251,8 +925,9 @@ inpect each entry and then select them with prev/next. This is how it is used:</
<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>
</td></tr></table></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
@ -1266,8 +941,8 @@ auto-created by the <code class="docutils literal notranslate"><span class="pre"
</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">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">CmdSet</span></a> with the commands they need to navigate the menu.
<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._menutree</span></code> and wait to actually assign it
@ -1360,7 +1035,7 @@ until the exit node.</p>
<h3>Versions</h3>
<ul>
<li><a href="EvMenu.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,7 +40,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="evmore">
<section class="tex2jax_ignore mathjax_ignore" id="evmore">
<h1>EvMore<a class="headerlink" href="#evmore" title="Permalink to this headline"></a></h1>
<p>When sending a very long text to a user client, it might scroll beyond of the height of the client
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
@ -47,14 +49,12 @@ page of text at a time. It is usually used via its access function, <code class=
<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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><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>
<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>
<span class="n">evmore</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">receiver</span><span class="p">,</span> <span class="n">long_text</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
<p>Where receiver is an <a class="reference internal" href="Objects.html"><span class="doc">Object</span></a> or a <a class="reference internal" href="Accounts.html"><span class="doc">Account</span></a>. If the text is longer than the
</div>
<p>Where receiver is an <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Object</span></a> or a <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Account</span></a>. If the text is longer than the
clients screen height (as determined by the NAWS handshake or by <code class="docutils literal notranslate"><span class="pre">settings.CLIENT_DEFAULT_HEIGHT</span></code>)
the pager will show up, something like this:</p>
<blockquote>
@ -123,7 +123,7 @@ paging.</p>
<h3>Versions</h3>
<ul>
<li><a href="EvMore.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,24 +40,14 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="the-inline-function-parser">
<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>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
</pre></div>
</div>
<p>The <a class="reference external" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.FuncParser">FuncParser</a> extracts and executes
<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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><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>
<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>
<span class="k">def</span> <span class="nf">_power_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>
<span class="sd">&quot;&quot;&quot;This will be callable as $square(number, power=&lt;num&gt;) in string&quot;&quot;&quot;</span>
@ -63,39 +55,37 @@ the return from the function.</p>
<span class="k">return</span> <span class="nb">float</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">**</span> <span class="nb">pow</span>
<span class="n">parser</span> <span class="o">=</span> <span class="n">FuncParser</span><span class="p">({</span><span class="s2">&quot;pow&quot;</span><span class="p">:</span> <span class="n">_power_callable</span><span class="p">})</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Next, just pass a string into the parser, optionally containing <code class="docutils literal notranslate"><span class="pre">$func(...)</span></code> markers:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><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="s2">&quot;We have that 4 x 4 x 4 is $pow(4, power=3).&quot;</span><span class="p">)</span>
<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="s2">&quot;We have that 4 x 4 x 4 is $pow(4, power=3).&quot;</span><span class="p">)</span>
<span class="s2">&quot;We have that 4 x 4 x 4 is 64.&quot;</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Normally the return is always converted to a string but you can also get the actual data type from the call:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><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">&quot;$pow(4)&quot;</span><span class="p">)</span>
<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">&quot;$pow(4)&quot;</span><span class="p">)</span>
<span class="mi">16</span>
</pre></div>
</td></tr></table></div>
</div>
<p>To show a <code class="docutils literal notranslate"><span class="pre">$func()</span></code> verbatim in your code without parsing it, escape it as either <code class="docutils literal notranslate"><span class="pre">$$func()</span></code> or <code class="docutils literal notranslate"><span class="pre">\$func()</span></code>:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><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="s2">&quot;This is an escaped $$pow(4) and so is this \$pow(3)&quot;</span><span class="p">)</span>
<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="s2">&quot;This is an escaped $$pow(4) and so is this \$pow(3)&quot;</span><span class="p">)</span>
<span class="s2">&quot;This is an escaped $pow(4) and so is this $pow(3)&quot;</span>
</pre></div>
</td></tr></table></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>
<p>The FuncParser can be applied to any string. Out of the box its 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">Session</span></a> of the object receiving the message. This potentially
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">Prototype</span></a> dicts values are run through the parser such that every
<li><p><em>Prototype values</em>. A <a class="reference internal" href="Prototypes.html"><span class="doc std std-doc">Prototype</span></a> dicts 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 external" href="../api/evennia.objects.objects.html#DefaultObject.msg_contents">Object.msg_contents</a> method,
<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 characters name.</p></li>
</ul>
@ -110,26 +100,18 @@ Evennia expects you to do in a proper text editor, outside of the game, not from
<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 external" href="../api/evennia.utils.funcparser.FuncParser.html">FuncParser</a> is imported as <code class="docutils literal notranslate"><span class="pre">evennia.utils.funcparser</span></code>.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><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>
<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>
<span class="n">parser</span> <span class="o">=</span> <span class="n">FuncParser</span><span class="p">(</span><span class="n">callables</span><span class="p">,</span> <span class="o">**</span><span class="n">default_kwargs</span><span class="p">)</span>
<span class="n">parsed_string</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parser</span><span class="p">(</span><span class="n">input_string</span><span class="p">,</span> <span class="n">raise_errors</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">escape</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">strip</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">parsed_string</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parser</span><span class="p">(</span><span class="n">input_string</span><span class="p">,</span> <span class="n">raise_errors</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">escape</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">strip</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">return_str</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="o">**</span><span class="n">reserved_kwargs</span><span class="p">)</span>
<span class="c1"># callables can also be passed as paths to modules</span>
<span class="n">parser</span> <span class="o">=</span> <span class="n">FuncParser</span><span class="p">([</span><span class="s2">&quot;game.myfuncparser_callables&quot;</span><span class="p">,</span> <span class="s2">&quot;game.more_funcparser_callables&quot;</span><span class="p">])</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Here, <code class="docutils literal notranslate"><span class="pre">callables</span></code> points to a collection of normal Python functions (see next section) for you to make
available to the parser as you parse strings with it. It can either be</p>
<ul class="simple">
@ -162,25 +144,19 @@ reserved kwargs are always passed - the first is a back-reference to the <code c
is the <code class="docutils literal notranslate"><span class="pre">raise_errors</span></code> boolean passed into <code class="docutils literal notranslate"><span class="pre">FuncParser.parse</span></code>.</p></li>
</ul>
<p>Heres an example of using the default/reserved keywords:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">_test</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>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">_test</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"># do stuff</span>
<span class="k">return</span> <span class="n">something</span>
<span class="n">parser</span> <span class="o">=</span> <span class="n">funcparser</span><span class="o">.</span><span class="n">FuncParser</span><span class="p">({</span><span class="s2">&quot;test&quot;</span><span class="p">:</span> <span class="n">_test</span><span class="p">},</span> <span class="n">mydefault</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">&quot;$test(foo, bar=4)&quot;</span><span class="p">,</span> <span class="n">myreserved</span><span class="o">=</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">])</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Here the callable will be called as</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">_test</span><span class="p">(</span><span class="s1">&#39;foo&#39;</span><span class="p">,</span> <span class="n">bar</span><span class="o">=</span><span class="s1">&#39;4&#39;</span><span class="p">,</span> <span class="n">mydefault</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">myreserved</span><span class="o">=</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">],</span>
<span class="n">funcparser</span><span class="o">=&lt;</span><span class="n">FuncParser</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">raise_errors</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">_test</span><span class="p">(</span><span class="s1">&#39;foo&#39;</span><span class="p">,</span> <span class="n">bar</span><span class="o">=</span><span class="s1">&#39;4&#39;</span><span class="p">,</span> <span class="n">mydefault</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">myreserved</span><span class="o">=</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">],</span>
<span class="n">funcparser</span><span class="o">=&lt;</span><span class="n">FuncParser</span><span class="o">&gt;</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>
</td></tr></table></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>.
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>
@ -188,20 +164,18 @@ The <code class="docutils literal notranslate"><span class="pre">funcparser</spa
<section id="defining-custom-callables">
<h2>Defining custom callables<a class="headerlink" href="#defining-custom-callables" title="Permalink to this headline"></a></h2>
<p>All callables made available to the parser must have the following signature:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">funcname</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>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">funcname</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>
<span class="k">return</span> <span class="n">something</span>
</pre></div>
</td></tr></table></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></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>. Heres
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-default notranslate"><div class="highlight"><pre><span></span><span class="s2">&quot;There&#39;s a $toint(22.0)</span><span class="si">% c</span><span class="s2">hance of survival.&quot;</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&quot;There&#39;s a $toint(22.0)% chance of survival.&quot;
</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">&quot;22.0&quot;</span></code>. The function is responsible
@ -213,7 +187,7 @@ 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. Lets introduce the <code class="docutils literal notranslate"><span class="pre">$eval</span></code> function, which evaluates simple expressions using
Pythons <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>.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="s2">&quot;There&#39;s a $toint($eval(10 * 2.2))</span><span class="si">% c</span><span class="s2">hance of survival.&quot;</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&quot;There&#39;s a $toint($eval(10 * 2.2))% chance of survival.&quot;
</pre></div>
</div>
<p>Since the <code class="docutils literal notranslate"><span class="pre">$eval</span></code> is the innermost call, it will get a string as input - the string <code class="docutils literal notranslate"><span class="pre">&quot;10</span> <span class="pre">*</span> <span class="pre">2.2&quot;</span></code>.
@ -225,22 +199,18 @@ 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>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><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>
<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">&quot;There&#39;s a 22</span><span class="si">% c</span><span class="s2">hance of survival.&quot;</span>
</pre></div>
</td></tr></table></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=True)</span></code>) and <em>dont add any extra string around the outermost function call</em>,
youll get the return type of the outermost callable back:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><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">&quot;$toint($eval(10 * 2.2)%&quot;</span><span class="p">)</span>
<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">&quot;$toint($eval(10 * 2.2)%&quot;</span><span class="p">)</span>
<span class="s2">&quot;22%&quot;</span>
<span class="n">parser</span><span class="o">.</span><span class="n">parse_to_any</span><span class="p">(</span><span class="s2">&quot;$toint($eval(10 * 2.2)&quot;</span><span class="p">)</span>
<span class="mi">22</span>
</pre></div>
</td></tr></table></div>
</div>
<section id="safe-convertion-of-inputs">
<h3>Safe convertion of inputs<a class="headerlink" href="#safe-convertion-of-inputs" title="Permalink to this headline"></a></h3>
<p>Since you dont know in which order users may use your callables, they should always check the types
@ -249,43 +219,30 @@ there are limits what inputs you can support. This is because FunctionParser str
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 external" href="../api/evennia.utils.utils.html#evennia.utils.utils.safe_convert_to_types">safe_convert_to_types</a>. This function
<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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span></pre></div></td><td class="code"><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>
<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>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> A callable with a lot of custom options </span>
<span class="sd"> </span>
<span class="sd"> $process(expression, local, extra=34, extra2=foo) </span>
<span class="sd"> </span>
<span class="sd"> A callable with a lot of custom options</span>
<span class="sd"> $process(expression, local, extra=34, extra2=foo)</span>
<span class="sd"> &quot;&quot;&quot;</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="s1">&#39;py&#39;</span><span class="p">,</span> <span class="s1">&#39;py&#39;</span><span class="p">),</span> <span class="p">{</span><span class="s1">&#39;extra1&#39;</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="s1">&#39;extra2&#39;</span><span class="p">:</span> <span class="nb">str</span><span class="p">}),</span>
<span class="p">((</span><span class="s1">&#39;py&#39;</span><span class="p">,</span> <span class="s1">&#39;py&#39;</span><span class="p">),</span> <span class="p">{</span><span class="s1">&#39;extra1&#39;</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="s1">&#39;extra2&#39;</span><span class="p">:</span> <span class="nb">str</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"># args/kwargs should be correct types now </span>
<span class="c1"># args/kwargs should be correct types now</span>
</pre></div>
</td></tr></table></div>
</div>
<p>In other words,</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><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>
<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>
</td></tr></table></div>
</div>
<p>Each converter should be a callable taking one argument - this will be the arg/kwarg-value to convert. The
special converter <code class="docutils literal notranslate"><span class="pre">&quot;py&quot;</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>
@ -297,7 +254,7 @@ it - no arithmetic or modifications of data is allowed. This is good for convert
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 +-/* as well as do simple comparisons like <code class="docutils literal notranslate"><span class="pre">4</span> <span class="pre">&gt;</span> <span class="pre">3</span></code> and more. It does <em>not</em> accept more complex
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">&gt;</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">
@ -321,39 +278,39 @@ 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 external" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_eval">code</a>) -
<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">&quot;1</span> <span class="pre">+</span> <span class="pre">2&quot;</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">$toint(number)</span></code> (<a class="reference external" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_toint">code</a>) -
<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 external" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_add">code</a>) -
<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">-&gt;</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 external" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_round">code</a>) -
<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">-&gt;</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 external" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_random">code</a>) -
<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 external" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_randint">code</a>) -
<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 external" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_choice">code</a>) -
<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 external" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_pad">code</a>) -
<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(&quot;Hello&quot;,</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 external" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_crop">code</a>) -
<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 external" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_space">code</a>) -
<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 external" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_justify">code</a>) -
<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 external" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_clr">code</a>) -
<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>
@ -362,13 +319,15 @@ given, the string will go back to neutral, so <code class="docutils literal notr
<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>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><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">=&lt;</span><span class="nb">object</span> <span class="ow">or</span> <span class="n">account</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">access</span><span class="o">=</span><span class="s2">&quot;control&quot;</span><span class="p">,</span> <span class="o">...</span><span class="p">)</span><span class="err">`</span>
<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">=&lt;</span><span class="nb">object</span> <span class="ow">or</span> <span class="n">account</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">access</span><span class="o">=</span><span class="s2">&quot;control&quot;</span><span class="p">,</span> <span class="o">...</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">caller</span></code> is required, its 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">lock type</span></a> to check, default being <code class="docutils literal notranslate"><span class="pre">&quot;control&quot;</span></code>.</p>
<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">&quot;control&quot;</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 external" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_search">code</a>) -
<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>
@ -379,54 +338,32 @@ match; if <code class="docutils literal notranslate"><span class="pre">return_li
<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 external" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultObject.msg_contents">DefaultObject.msg_contents</a> method
<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.</p>
<p>These all require extra kwargs be passed into the parser:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><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">=&lt;</span><span class="n">obj</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">receiver</span><span class="o">=&lt;</span><span class="n">obj</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">mapping</span><span class="o">=</span><span class="p">{</span><span class="s1">&#39;key&#39;</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">obj</span><span class="o">&gt;</span><span class="p">,</span> <span class="o">...</span><span class="p">})</span>
<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">=&lt;</span><span class="n">obj</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">receiver</span><span class="o">=&lt;</span><span class="n">obj</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">mapping</span><span class="o">=</span><span class="p">{</span><span class="s1">&#39;key&#39;</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">obj</span><span class="o">&gt;</span><span class="p">,</span> <span class="o">...</span><span class="p">})</span>
</pre></div>
</td></tr></table></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>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">$you([key])</span></code> (<a class="reference external" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_you">code</a>) -
<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>
will be used. As this message is sent to different recipients, the <code class="docutils literal notranslate"><span class="pre">receiver</span></code> will change and this will
be replaced either with the string <code class="docutils literal notranslate"><span class="pre">you</span></code> (if you and the receiver is the same entity) or with the
result of <code class="docutils literal notranslate"><span class="pre">you_obj.get_display_name(looker=receiver)</span></code>. This allows for a single string to echo differently
depending on who sees it, and also to reference other people in the same way.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">$You([key])</span></code> - same as <code class="docutils literal notranslate"><span class="pre">$you</span></code> but always capitalized.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">$conj(verb)</span></code> (<a class="reference external" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_conjugate">code</a>) conjugates a verb between 4nd person presens to 3rd person presence depending on who
<li><p><code class="docutils literal notranslate"><span class="pre">$conj(verb)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_conjugate" title="evennia.utils.funcparser.funcparser_callable_conjugate"><span class="xref myst py py-func">code</span></a>) conjugates a verb between 4nd person presens to 3rd person presence depending on who
sees the string. For example <code class="docutils literal notranslate"><span class="pre">&quot;$You()</span> <span class="pre">$conj(smiles)&quot;.</span></code> will show as “You smile.” and “Tom smiles.” depending
on who sees it. This makes use of the tools in <a class="reference external" href="../api/evennia.utils.verb_conjugation.html">evennia.utils.verb_conjugation</a>
on who sees it. This makes use of the tools in <a class="reference internal" href="../api/evennia.utils.verb_conjugation.html#evennia-utils-verb-conjugation"><span class="std std-ref">evennia.utils.verb_conjugation</span></a>
to do this, and only works for English verbs.</p></li>
</ul>
</section>
<section id="example">
<h3>Example<a class="headerlink" href="#example" title="Permalink to this headline"></a></h3>
<p>Heres an example of including the default callables together with two custom ones.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span></pre></div></td><td class="code"><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>
<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>
<span class="kn">from</span> <span class="nn">evennia.utils</span> <span class="kn">import</span> <span class="n">gametime</span>
<span class="k">def</span> <span class="nf">_dashline</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>
@ -449,14 +386,15 @@ to do this, and only works for English verbs.</p></li>
<span class="n">string</span> <span class="o">=</span> <span class="s2">&quot;This is the current uptime:$dashline($toint($uptime()) seconds)&quot;</span>
<span class="n">result</span> <span class="o">=</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>
</pre></div>
</td></tr></table></div>
</div>
<p>Above we define two callables <code class="docutils literal notranslate"><span class="pre">_dashline</span></code> and <code class="docutils literal notranslate"><span class="pre">_uptime</span></code> and map them to names <code class="docutils literal notranslate"><span class="pre">&quot;dashline&quot;</span></code> and <code class="docutils literal notranslate"><span class="pre">&quot;uptime&quot;</span></code>,
which is what we then can call as <code class="docutils literal notranslate"><span class="pre">$header</span></code> and <code class="docutils literal notranslate"><span class="pre">$uptime</span></code> in the string. We also have access to
all the defaults (like <code class="docutils literal notranslate"><span class="pre">$toint()</span></code>).</p>
<p>The parsed result of the above would be something like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">This</span> <span class="ow">is</span> <span class="n">the</span> <span class="n">current</span> <span class="n">uptime</span><span class="p">:</span>
<span class="o">-------</span> <span class="mi">343</span> <span class="n">seconds</span> <span class="o">-------</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>This is the current uptime:
------- 343 seconds -------
</pre></div>
</div>
</section>
@ -523,7 +461,7 @@ all the defaults (like <code class="docutils literal notranslate"><span class="p
<h3>Versions</h3>
<ul>
<li><a href="FuncParser.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,13 +40,13 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="help-system">
<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-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">help</span> <span class="n">theatre</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; help theatre
</pre></div>
</div>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">------------------------------------------------------------------------------</span>
@ -60,7 +62,7 @@ finding mentions of the search term in help entries.</p>
<span class="o">------------------------------------------------------------------------------</span>
</pre></div>
</div>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">help</span> <span class="n">evennia</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; help evennia
</pre></div>
</div>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">------------------------------------------------------------------------------</span>
@ -77,16 +79,16 @@ finding mentions of the search term in help entries.</p>
<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>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-default notranslate"><div class="highlight"><pre><span></span><span class="n">help</span> <span class="o">&lt;</span><span class="n">topic</span><span class="o">&gt;</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>help &lt;topic&gt;
</pre></div>
</div>
<p>Sub-topics are accessed as <code class="docutils literal notranslate"><span class="pre">help</span> <span class="pre">&lt;topic&gt;/&lt;subtopic&gt;/...</span></code>.</p>
<p>Creating a new help entry from in-game is done with</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">sethelp</span> <span class="o">&lt;</span><span class="n">topic</span><span class="o">&gt;</span><span class="p">[;</span><span class="n">aliases</span><span class="p">]</span> <span class="p">[,</span><span class="n">category</span><span class="p">]</span> <span class="p">[,</span><span class="n">lockstring</span><span class="p">]</span> <span class="o">=</span> <span class="o">&lt;</span><span class="n">text</span><span class="o">&gt;</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>sethelp &lt;topic&gt;[;aliases] [,category] [,lockstring] = &lt;text&gt;
</pre></div>
</div>
<p>For example</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">sethelp</span> <span class="n">The</span> <span class="n">Gods</span><span class="p">;</span><span class="n">pantheon</span><span class="p">,</span> <span class="n">Lore</span> <span class="o">=</span> <span class="n">In</span> <span class="n">the</span> <span class="n">beginning</span> <span class="nb">all</span> <span class="n">was</span> <span class="n">dark</span> <span class="o">...</span>
<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
@ -102,7 +104,7 @@ regular code editor, see below).</p>
<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">Command classes</span></a>. The idea is that the command docs are
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
@ -131,7 +133,7 @@ help entries.</p></li>
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">EvMore</span></a> pager (you can control this with
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>
@ -192,6 +194,7 @@ Everyone knows the primadonna! She is ...
He always keeps an eye on the door and ...
(`help theatre/drama/gate`)
</pre></div>
</div>
</section>
@ -203,27 +206,7 @@ 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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span></pre></div></td><td class="code"><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>
<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">&quot;&quot;&quot;</span>
<span class="sd"> mycmd - my very own command</span>
@ -245,12 +228,12 @@ file is just a <code class="docutils literal notranslate"><span class="pre">relo
<span class="c1"># [...]</span>
</pre></div>
</td></tr></table></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 external" href="#Locking-help-entries">the section below</a> for details.</p>
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 dont specify the
@ -258,7 +241,7 @@ category, <code class="docutils literal notranslate"><span class="pre">settings.
used.</p>
<p>If you dont 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">cmdset</span></a> that has its own help functionality) you
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
@ -272,19 +255,15 @@ command.</p>
<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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<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">&quot;emote&quot;</span><span class="p">,</span>
<span class="s2">&quot;Emoting is important because ...&quot;</span><span class="p">,</span>
<span class="n">category</span><span class="o">=</span><span class="s2">&quot;Roleplaying&quot;</span><span class="p">,</span> <span class="n">locks</span><span class="o">=</span><span class="s2">&quot;view:all()&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
<p>The entity being created is a <a class="reference external" href="../api/evennia.help.models.HelpEntry.html">evennia.help.models.HelpEntry</a>
object. This is <em>not</em> a <a class="reference internal" href="Typeclasses.html"><span class="doc">Typeclassed</span></a> entity and is not meant to
</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>
@ -314,39 +293,7 @@ be ignored in this case.</p></li>
the list will override coming before.</p>
<p>Each entry dict must define keys to match that needed by all help entries.
Heres an example of a help module:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
<span class="c1"># in a module pointed to by settings.FILE_HELP_ENTRY_MODULES</span>
<span class="n">HELP_ENTRY_DICTS</span> <span class="o">=</span> <span class="p">[</span>
@ -379,8 +326,9 @@ Heres an example of a help module:</p>
<span class="p">}</span>
<span class="p">]</span>
</pre></div>
</td></tr></table></div>
</div>
<p>The help entry text will be dedented and will retain paragraphs. You should try
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>
@ -390,7 +338,7 @@ server and the file-based help entries will be available to view.</p>
<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-default notranslate"><div class="highlight"><pre><span></span><span class="n">Command</span><span class="o">-</span><span class="n">auto</span><span class="o">-</span><span class="n">help</span> <span class="o">&gt;</span> <span class="n">Db</span><span class="o">-</span><span class="n">help</span> <span class="o">&gt;</span> <span class="n">File</span><span class="o">-</span><span class="n">help</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Command-auto-help &gt; Db-help &gt; File-help
</pre></div>
</div>
<p>So if you create a db-help entry foo, it will replace any file-based help
@ -420,14 +368,7 @@ also not show up in the index). If <code class="docutils literal notranslate"><s
everyone can read the help entry.</p></li>
</ul>
<p>For Commands you set the help-related locks the same way you would any lock:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">MyCommand</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></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">&quot;&quot;&quot;</span>
<span class="sd"> &lt;docstring for command&gt;</span>
<span class="sd"> &quot;&quot;&quot;</span>
@ -435,21 +376,19 @@ everyone can read the help entry.</p></li>
<span class="c1"># everyone can use the command, builders can view it in the help index</span>
<span class="c1"># but only devs can actually read the help (a weird setup for sure!)</span>
<span class="n">locks</span> <span class="o">=</span> <span class="s2">&quot;cmd:all();view:perm(Builders);read:perm(Developers)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Db-help entries and File-Help entries work the same way (except the <code class="docutils literal notranslate"><span class="pre">cmd</span></code>-type
lock is not used. A file-help example:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">help_entry</span> <span class="o">=</span> <span class="p">{</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">help_entry</span> <span class="o">=</span> <span class="p">{</span>
<span class="c1"># ...</span>
<span class="n">locks</span> <span class="o">=</span> <span class="s2">&quot;read:perm(Developer)&quot;</span><span class="p">,</span>
<span class="c1"># ...</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
</div>
<div class="versionchanged">
<p><span class="versionmodified changed">Changed in version 1.0: </span>Changed the old view lock to control the help-index inclusion and added
the new read lock-type to control access to the entry itself.</p>
@ -458,7 +397,7 @@ the new read lock-type to control access to the entry itself.</p>
<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 external" href="../api/evennia.commands.default.help.html#CmdHelp">evennia.commands.default.help.CmdHelp</a>.</p>
<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
@ -546,7 +485,7 @@ at that point).</p>
<h3>Versions</h3>
<ul>
<li><a href="Help-System.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,22 +40,22 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="inputfuncs">
<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">inputcommand</span></a>) from
the client. The inputfunc is the last destination for the inputcommand along the <a class="reference external" href="Components/Messagepath#the-ingoing-message-path">ingoing message
path</a>. 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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><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>
<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 <a class="reference internal" href="../Concepts/Messagepath.html#the-ingoing-message-path"><span class="std std-doc">ingoing message
path</span></a>. 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>
</pre></div>
</td></tr></table></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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><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>
<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>
</td></tr></table></div>
</div>
<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
@ -76,7 +78,7 @@ ones.</p>
</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">Command</span></a>, this inputfunc will do things like nick-replacement
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">
@ -171,12 +173,12 @@ 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">(&quot;repeat&quot;,</span> <span class="pre">(),</span> <span class="pre">{&quot;callback&quot;:funcname,</span>&#160; <span class="pre">&quot;interval&quot;:</span> <span class="pre">secs,</span> <span class="pre">&quot;stop&quot;:</span> <span class="pre">False})</span></code></p></li>
<li><p>Input: <code class="docutils literal notranslate"><span class="pre">(&quot;repeat&quot;,</span> <span class="pre">(),</span> <span class="pre">{&quot;callback&quot;:funcname,</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span class="pre">&quot;interval&quot;:</span> <span class="pre">secs,</span> <span class="pre">&quot;stop&quot;:</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">(&quot;text&quot;,</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">Ticker</span></a>. Only previously acceptable functions are possible to
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, youll 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">&quot;stop&quot;:</span> <span class="pre">True</span></code> (note that you must include
@ -185,7 +187,7 @@ both the callback name and interval for Evennia to know what to stop).</p>
<section id="unrepeat">
<h3>unrepeat<a class="headerlink" href="#unrepeat" title="Permalink to this headline"></a></h3>
<ul class="simple">
<li><p>Input: <code class="docutils literal notranslate"><span class="pre">(&quot;unrepeat&quot;,</span> <span class="pre">(),</span> <span class="pre">(&quot;callback&quot;:funcname,</span>&#160; <span class="pre">&quot;interval&quot;:</span> <span class="pre">secs)</span></code></p></li>
<li><p>Input: <code class="docutils literal notranslate"><span class="pre">(&quot;unrepeat&quot;,</span> <span class="pre">(),</span> <span class="pre">(&quot;callback&quot;:funcname,</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span class="pre">&quot;interval&quot;:</span> <span class="pre">secs)</span></code></p></li>
<li><p>Output: None</p></li>
</ul>
<p>This is a convenience wrapper for sending “stop” to the <code class="docutils literal notranslate"><span class="pre">repeat</span></code> inputfunc.</p>
@ -198,7 +200,7 @@ both the callback name and interval for Evennia to know what to stop).</p>
</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">MonitorHandler</span></a> behind the scenes. Pass the “stop” key to stop monitoring. Note
<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
@ -283,7 +285,7 @@ add more. By default the following fields/attributes can be monitored:</p>
<h3>Versions</h3>
<ul>
<li><a href="Inputfuncs.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,12 +40,12 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="locks">
<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">Commands</span></a>,
<a class="reference internal" href="Objects.html"><span class="doc">Objects</span></a>, <a class="reference internal" href="Scripts.html"><span class="doc">Scripts</span></a>, <a class="reference internal" href="Accounts.html"><span class="doc">Accounts</span></a>, <a class="reference internal" href="Help-System.html"><span class="doc">Help System</span></a>,
<a class="reference external" href="Components/Communications.html#Msg">messages</a> and <a class="reference external" href="Components/Communications.html#Channels">channels</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 -
@ -57,47 +59,42 @@ 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>
<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-default notranslate"><div class="highlight"><pre><span></span> <span class="o">&gt;</span> <span class="n">lock</span> <span class="n">obj</span> <span class="o">=</span> <span class="o">&lt;</span><span class="n">lockstring</span><span class="o">&gt;</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> &gt; lock obj = &lt;lockstring&gt;
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">&lt;lockstring&gt;</span></code> is a string of a certain form that defines the behaviour of the lock. We will go
into more detail on how <code class="docutils literal notranslate"><span class="pre">&lt;lockstring&gt;</span></code> should look in the next section.</p>
<p>Code-wise, Evennia handles locks through what is usually called <code class="docutils literal notranslate"><span class="pre">locks</span></code> on all relevant entities.
This is a handler that allows you to add, delete and check locks.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">myobj</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="o">&lt;</span><span class="n">lockstring</span><span class="o">&gt;</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">myobj</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="o">&lt;</span><span class="n">lockstring</span><span class="o">&gt;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>One can call <code class="docutils literal notranslate"><span class="pre">locks.check()</span></code> to perform a lock check, but to hide the underlying implementation all
objects also have a convenience function called <code class="docutils literal notranslate"><span class="pre">access</span></code>. This should preferably be used. In the
example below, <code class="docutils literal notranslate"><span class="pre">accessing_obj</span></code> is the object requesting the delete access whereas <code class="docutils literal notranslate"><span class="pre">obj</span></code> is the
object that might get deleted. This is how it would look (and does look) from inside the <code class="docutils literal notranslate"><span class="pre">delete</span></code>
command:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="k">if</span> <span class="ow">not</span> <span class="n">obj</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">accessing_obj</span><span class="p">,</span> <span class="s1">&#39;delete&#39;</span><span class="p">):</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="k">if</span> <span class="ow">not</span> <span class="n">obj</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">accessing_obj</span><span class="p">,</span> <span class="s1">&#39;delete&#39;</span><span class="p">):</span>
<span class="n">accessing_obj</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;Sorry, you may not delete that.&quot;</span><span class="p">)</span>
<span class="k">return</span>
</pre></div>
</td></tr></table></div>
</div>
</section>
<section id="defining-locks">
<h2>Defining locks<a class="headerlink" href="#defining-locks" title="Permalink to this headline"></a></h2>
<p>Defining a lock (i.e. an access restriction) in Evennia is done by adding simple strings of lock
definitions to the objects <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>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">delete</span><span class="p">:</span><span class="nb">id</span><span class="p">(</span><span class="mi">34</span><span class="p">)</span> <span class="c1"># only allow obj #34 to delete</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">delete</span><span class="p">:</span><span class="nb">id</span><span class="p">(</span><span class="mi">34</span><span class="p">)</span> <span class="c1"># only allow obj #34 to delete</span>
<span class="n">edit</span><span class="p">:</span><span class="nb">all</span><span class="p">()</span> <span class="c1"># let everyone edit</span>
<span class="c1"># only those who are not &quot;very_weak&quot; or are Admins may pick this up</span>
<span class="n">get</span><span class="p">:</span> <span class="ow">not</span> <span class="n">attr</span><span class="p">(</span><span class="n">very_weak</span><span class="p">)</span> <span class="ow">or</span> <span class="n">perm</span><span class="p">(</span><span class="n">Admin</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Formally, a lockstring has the following syntax:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">access_type</span><span class="p">:</span> <span class="p">[</span><span class="n">NOT</span><span class="p">]</span> <span class="n">lockfunc1</span><span class="p">([</span><span class="n">arg1</span><span class="p">,</span><span class="o">..</span><span class="p">])</span> <span class="p">[</span><span class="n">AND</span><span class="o">|</span><span class="n">OR</span><span class="p">]</span> <span class="p">[</span><span class="n">NOT</span><span class="p">]</span> <span class="n">lockfunc2</span><span class="p">([</span><span class="n">arg1</span><span class="p">,</span><span class="o">...</span><span class="p">])</span> <span class="p">[</span><span class="o">...</span><span class="p">]</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">access_type</span><span class="p">:</span> <span class="p">[</span><span class="n">NOT</span><span class="p">]</span> <span class="n">lockfunc1</span><span class="p">([</span><span class="n">arg1</span><span class="p">,</span><span class="o">..</span><span class="p">])</span> <span class="p">[</span><span class="n">AND</span><span class="o">|</span><span class="n">OR</span><span class="p">]</span> <span class="p">[</span><span class="n">NOT</span><span class="p">]</span> <span class="n">lockfunc2</span><span class="p">([</span><span class="n">arg1</span><span class="p">,</span><span class="o">...</span><span class="p">])</span> <span class="p">[</span><span class="o">...</span><span class="p">]</span>
</pre></div>
</td></tr></table></div>
</div>
<p>where <code class="docutils literal notranslate"><span class="pre">[]</span></code> marks optional parts. <code class="docutils literal notranslate"><span class="pre">AND</span></code>, <code class="docutils literal notranslate"><span class="pre">OR</span></code> and <code class="docutils literal notranslate"><span class="pre">NOT</span></code> are not case sensitive and excess spaces are
ignored. <code class="docutils literal notranslate"><span class="pre">lockfunc1,</span> <span class="pre">lockfunc2</span></code> etc are special <em>lock functions</em> available to the lock system.</p>
<p>So, a lockstring consists of the type of restriction (the <code class="docutils literal notranslate"><span class="pre">access_type</span></code>), a colon (<code class="docutils literal notranslate"><span class="pre">:</span></code>) and then an
@ -106,7 +103,7 @@ returns either <code class="docutils literal notranslate"><span class="pre">True
total result is <code class="docutils literal notranslate"><span class="pre">True</span></code>, the lock is passed.</p>
<p>You can create several lock types one after the other by separating them with a semicolon (<code class="docutils literal notranslate"><span class="pre">;</span></code>) in
the lockstring. The string below yields the same result as the previous example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">delete</span><span class="p">:</span><span class="nb">id</span><span class="p">(</span><span class="mi">34</span><span class="p">);</span><span class="n">edit</span><span class="p">:</span><span class="nb">all</span><span class="p">();</span><span class="n">get</span><span class="p">:</span> <span class="ow">not</span> <span class="n">attr</span><span class="p">(</span><span class="n">very_weak</span><span class="p">)</span> <span class="ow">or</span> <span class="n">perm</span><span class="p">(</span><span class="n">Admin</span><span class="p">)</span>
<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 id="valid-access-types">
@ -119,12 +116,12 @@ the default command set) actually checks for, as in the example of <code class="
delete <code class="docutils literal notranslate"><span class="pre">access_type</span></code>.</p>
<p>Below are the access_types checked by the default commandset.</p>
<ul class="simple">
<li><p><a class="reference internal" href="Commands.html"><span class="doc">Commands</span></a></p>
<li><p><a class="reference internal" href="Commands.html"><span class="doc std std-doc">Commands</span></a></p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">cmd</span></code> - this defines who may call this command at all.</p></li>
</ul>
</li>
<li><p><a class="reference internal" href="Objects.html"><span class="doc">Objects</span></a>:</p>
<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>
@ -142,18 +139,18 @@ something like <code class="docutils literal notranslate"><span class="pre">call
<li><p><code class="docutils literal notranslate"><span class="pre">attrcreate</span></code> - who may create new attributes on the object (default True)</p></li>
</ul>
</li>
<li><p><a class="reference external" href="Components/Objects.html#Characters">Characters</a>:</p>
<li><p><a class="reference internal" href="Objects.html#characters"><span class="std std-doc">Characters</span></a>:</p>
<ul>
<li><p>Same as for Objects</p></li>
</ul>
</li>
<li><p><a class="reference external" href="Components/Objects.html#Exits">Exits</a>:</p>
<li><p><a class="reference internal" href="Objects.html#exits"><span class="std std-doc">Exits</span></a>:</p>
<ul>
<li><p>Same as for Objects</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">traverse</span></code> - who may pass the exit.</p></li>
</ul>
</li>
<li><p><a class="reference internal" href="Accounts.html"><span class="doc">Accounts</span></a>:</p>
<li><p><a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a>:</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">examine</span></code> - who may examine the accounts properties.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">delete</span></code> - who may delete the account.</p></li>
@ -162,13 +159,13 @@ something like <code class="docutils literal notranslate"><span class="pre">call
<li><p><code class="docutils literal notranslate"><span class="pre">boot</span></code> - who may boot the account.</p></li>
</ul>
</li>
<li><p><a class="reference internal" href="Attributes.html"><span class="doc">Attributes</span></a>: (only checked by <code class="docutils literal notranslate"><span class="pre">obj.secure_attr</span></code>)</p>
<li><p><a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attributes</span></a>: (only checked by <code class="docutils literal notranslate"><span class="pre">obj.secure_attr</span></code>)</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">attrread</span></code> - see/access attribute</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">attredit</span></code> - change/delete attribute</p></li>
</ul>
</li>
<li><p><a class="reference external" href="Components/Communications.html#Channels">Channels</a>:</p>
<li><p><a class="reference internal" href="Channels.html"><span class="doc std std-doc">Channels</span></a>:</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">control</span></code> - who is administrating the channel. This means the ability to delete the channel,
boot listeners etc.</p></li>
@ -176,7 +173,7 @@ boot listeners etc.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">listen</span></code> - who may subscribe and listen to the channel.</p></li>
</ul>
</li>
<li><p><a class="reference internal" href="Help-System.html"><span class="doc">HelpEntry</span></a>:</p>
<li><p><a class="reference internal" href="Help-System.html"><span class="doc std std-doc">HelpEntry</span></a>:</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">examine</span></code> - who may view this help entry (usually everyone)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">edit</span></code> - who may edit this help entry.</p></li>
@ -193,21 +190,19 @@ text is an arbitrary string that must be unique for an object. If adding a lock
<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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><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">&quot;read:perm(Player);post:perm(Admin)&quot;</span><span class="p">)</span>
<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">&quot;read:perm(Player);post:perm(Admin)&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>This will create a read access type for Characters having the <code class="docutils literal notranslate"><span class="pre">Player</span></code> permission or above and a
post access type for those with <code class="docutils literal notranslate"><span class="pre">Admin</span></code> permissions or above (see below how the <code class="docutils literal notranslate"><span class="pre">perm()</span></code> lock
function works). When it comes time to test these permissions, simply check like this (in this
example, the <code class="docutils literal notranslate"><span class="pre">obj</span></code> may be a board on the bulletin board system and <code class="docutils literal notranslate"><span class="pre">accessing_obj</span></code> is the player
trying to read the board):</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="k">if</span> <span class="ow">not</span> <span class="n">obj</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">accessing_obj</span><span class="p">,</span> <span class="s1">&#39;read&#39;</span><span class="p">):</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="k">if</span> <span class="ow">not</span> <span class="n">obj</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">accessing_obj</span><span class="p">,</span> <span class="s1">&#39;read&#39;</span><span class="p">):</span>
<span class="n">accessing_obj</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;Sorry, you may not read that.&quot;</span><span class="p">)</span>
<span class="k">return</span>
</pre></div>
</td></tr></table></div>
</div>
</section>
<section id="lock-functions">
<h3>Lock functions<a class="headerlink" href="#lock-functions" title="Permalink to this headline"></a></h3>
@ -221,14 +216,7 @@ your own with the same name.</p>
object wanting to get access) and the <em>accessed object</em> (this is the object with the lock). Those
two are fed automatically as the first two arguments to the function when the lock is checked. Any
arguments explicitly given in the lock definition will appear as extra arguments.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># A simple example lock function. Called with e.g. `id(34)`. This is</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># A simple example lock function. Called with e.g. `id(34)`. This is</span>
<span class="c1"># defined in, say mygame/server/conf/lockfuncs.py</span>
<span class="k">def</span> <span class="nf">id</span><span class="p">(</span><span class="n">accessing_obj</span><span class="p">,</span> <span class="n">accessed_obj</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>
@ -237,23 +225,19 @@ arguments explicitly given in the lock definition will appear as extra arguments
<span class="k">return</span> <span class="n">accessing_obj</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">wanted_id</span>
<span class="k">return</span> <span class="kc">False</span>
</pre></div>
</td></tr></table></div>
</div>
<p>The above could for example be used in a lock function like this:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># we have `obj` and `owner_object` from before</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># we have `obj` and `owner_object` from before</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="sa">f</span><span class="s2">&quot;edit: id(</span><span class="si">{</span><span class="n">owner_object</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2">)&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>We could check if the “edit” lock is passed with something like this:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># as part of a Command&#39;s func() method, for example</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># as part of a Command&#39;s func() method, for example</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">obj</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s2">&quot;edit&quot;</span><span class="p">):</span>
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;You don&#39;t have access to edit this!&quot;</span><span class="p">)</span>
<span class="k">return</span>
</pre></div>
</td></tr></table></div>
</div>
<p>In this example, everyone except the <code class="docutils literal notranslate"><span class="pre">caller</span></code> with the right <code class="docutils literal notranslate"><span class="pre">id</span></code> will get the error.</p>
<blockquote>
<div><p>(Using the <code class="docutils literal notranslate"><span class="pre">*</span></code> and <code class="docutils literal notranslate"><span class="pre">**</span></code> syntax causes Python to magically put all extra arguments into a list
@ -266,10 +250,10 @@ how <code class="docutils literal notranslate"><span class="pre">*args</span></c
<li><p><code class="docutils literal notranslate"><span class="pre">false()/none()/superuser()</span></code> - give access to none. Superusers bypass the check entirely and are
thus the only ones who will pass this check.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">perm(perm)</span></code> - this tries to match a given <code class="docutils literal notranslate"><span class="pre">permission</span></code> property, on an Account firsthand, on a
Character second. See <a class="reference external" href="Components/Locks.html#permissions">below</a>.</p></li>
Character second. See <a class="reference internal" href="Permissions.html"><span class="doc std std-doc">below</span></a>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">perm_above(perm)</span></code> - like <code class="docutils literal notranslate"><span class="pre">perm</span></code> but requires a “higher” permission level than the one given.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">id(num)/dbref(num)</span></code> - checks so the access_object has a certain dbref/id.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">attr(attrname)</span></code> - checks if a certain <a class="reference internal" href="Attributes.html"><span class="doc">Attribute</span></a> exists on accessing_object.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">attr(attrname)</span></code> - checks if a certain <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attribute</span></a> exists on accessing_object.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">attr(attrname,</span> <span class="pre">value)</span></code> - checks so an attribute exists on accessing_object <em>and</em> has the given
value.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">attr_gt(attrname,</span> <span class="pre">value)</span></code> - checks so accessing_object has a value larger (<code class="docutils literal notranslate"><span class="pre">&gt;</span></code>) than the given
@ -290,22 +274,19 @@ setting set to a given value.</p></li>
<p>Sometimes you dont 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>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># inside command definition</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># inside command definition</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">locks</span><span class="o">.</span><span class="n">check_lockstring</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="p">,</span> <span class="s2">&quot;dummy:perm(Admin)&quot;</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="s2">&quot;You must be an Admin or higher to do this!&quot;</span><span class="p">)</span>
<span class="k">return</span>
</pre></div>
</td></tr></table></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>
</section>
<section id="default-locks">
<h2>Default locks<a class="headerlink" href="#default-locks" title="Permalink to this headline"></a></h2>
<p>Evennia sets up a few basic locks on all new objects and accounts (if we didnt, 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">Typeclasses</span></a>
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 dont want to
edit unless you want to change how basic stuff like rooms and exits store their internal variables).
This is called once, before <code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code>, so just put them in the latter method on your
@ -315,78 +296,70 @@ control and delete the object.</p>
</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-default notranslate"><div class="highlight"><pre><span></span><span class="n">examine</span><span class="p">:</span> <span class="n">attr</span><span class="p">(</span><span class="n">eyesight</span><span class="p">,</span> <span class="n">excellent</span><span class="p">)</span> <span class="ow">or</span> <span class="n">perm</span><span class="p">(</span><span class="n">Builders</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>examine: attr(eyesight, excellent) or perm(Builders)
</pre></div>
</div>
<p>You are only allowed to do <em>examine</em> on this object if you have excellent eyesight (that is, has
an Attribute <code class="docutils literal notranslate"><span class="pre">eyesight</span></code> with the value <code class="docutils literal notranslate"><span class="pre">excellent</span></code> defined on yourself) or if you have the
“Builders” permission string assigned to you.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">open</span><span class="p">:</span> <span class="n">holds</span><span class="p">(</span><span class="s1">&#39;the green key&#39;</span><span class="p">)</span> <span class="ow">or</span> <span class="n">perm</span><span class="p">(</span><span class="n">Builder</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>open: holds(&#39;the green key&#39;) or perm(Builder)
</pre></div>
</div>
<p>This could be called by the <code class="docutils literal notranslate"><span class="pre">open</span></code> command on a “door” object. The check is passed if you are a
Builder or has the right key in your inventory.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">cmd</span><span class="p">:</span> <span class="n">perm</span><span class="p">(</span><span class="n">Builders</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>cmd: perm(Builders)
</pre></div>
</div>
<p>Evennias command handler looks for a lock of type <code class="docutils literal notranslate"><span class="pre">cmd</span></code> to determine if a user is allowed to even
call upon a particular command or not. When you define a command, this is the kind of lock you must
set. See the default command set for lots of examples. If a character/account dont pass the <code class="docutils literal notranslate"><span class="pre">cmd</span></code>
lock type the command will not even appear in their <code class="docutils literal notranslate"><span class="pre">help</span></code> list.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">cmd</span><span class="p">:</span> <span class="ow">not</span> <span class="n">perm</span><span class="p">(</span><span class="n">no_tell</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>cmd: not perm(no_tell)
</pre></div>
</div>
<p>“Permissions” can also be used to block users or implement highly specific bans. The above example
would be be added as a lock string to the <code class="docutils literal notranslate"><span class="pre">tell</span></code> command. This will allow everyone <em>not</em> having the
“permission” <code class="docutils literal notranslate"><span class="pre">no_tell</span></code> to use the <code class="docutils literal notranslate"><span class="pre">tell</span></code> command. You could easily give an account the “permission”
<code class="docutils literal notranslate"><span class="pre">no_tell</span></code> to disable their use of this particular command henceforth.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">dbref</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">id</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">dbref</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">id</span>
<span class="n">lockstring</span> <span class="o">=</span> <span class="s2">&quot;control:id(</span><span class="si">%s</span><span class="s2">);examine:perm(Builders);delete:id(</span><span class="si">%s</span><span class="s2">) or perm(Admin);get:all()&quot;</span> <span class="o">%</span>
<span class="p">(</span><span class="n">dbref</span><span class="p">,</span> <span class="n">dbref</span><span class="p">)</span>
<span class="n">new_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="n">lockstring</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<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>
<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">Object</span></a>
<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-default notranslate"><div class="highlight"><pre><span></span> <span class="o">&gt;</span> <span class="n">create</span><span class="o">/</span><span class="n">drop</span> <span class="n">box</span>
<span class="o">&gt;</span> <span class="n">desc</span> <span class="n">box</span> <span class="o">=</span> <span class="s2">&quot;This is a very big and heavy box.&quot;</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> &gt; create/drop box
&gt; desc box = &quot;This is a very big and heavy box.&quot;
</pre></div>
</div>
<p>We want to limit which objects can pick up this heavy box. Lets say that to do that we require the
would-be lifter to to have an attribute <em>strength</em> on themselves, with a value greater than 50. We
assign it to ourselves to begin with.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="o">&gt;</span> <span class="nb">set</span> <span class="bp">self</span><span class="o">/</span><span class="n">strength</span> <span class="o">=</span> <span class="mi">45</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> &gt; set self/strength = 45
</pre></div>
</div>
<p>Ok, so for testing we made ourselves strong, but not strong enough. Now we need to look at what
happens when someone tries to pick up the the box - they use the <code class="docutils literal notranslate"><span class="pre">get</span></code> command (in the default set).
This is defined in <code class="docutils literal notranslate"><span class="pre">evennia/commands/default/general.py</span></code>. In its code we find this snippet:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="k">if</span> <span class="ow">not</span> <span class="n">obj</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s1">&#39;get&#39;</span><span class="p">):</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="k">if</span> <span class="ow">not</span> <span class="n">obj</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s1">&#39;get&#39;</span><span class="p">):</span>
<span class="k">if</span> <span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">get_err_msg</span><span class="p">:</span>
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">get_err_msg</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;You can&#39;t get that.&quot;</span><span class="p">)</span>
<span class="k">return</span>
</pre></div>
</td></tr></table></div>
</div>
<p>So the <code class="docutils literal notranslate"><span class="pre">get</span></code> command looks for a lock with the type <em>get</em> (not so surprising). It also looks for an
<a class="reference internal" href="Attributes.html"><span class="doc">Attribute</span></a> on the checked object called <em>get_err_msg</em> in order to return a customized
<a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attribute</span></a> on the checked object called <em>get_err_msg</em> in order to return a customized
error message. Sounds good! Lets start by setting that on the box:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="o">&gt;</span> <span class="nb">set</span> <span class="n">box</span><span class="o">/</span><span class="n">get_err_msg</span> <span class="o">=</span> <span class="n">You</span> <span class="n">are</span> <span class="ow">not</span> <span class="n">strong</span> <span class="n">enough</span> <span class="n">to</span> <span class="n">lift</span> <span class="n">this</span> <span class="n">box</span><span class="o">.</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> &gt; set box/get_err_msg = You are not strong enough to lift this box.
</pre></div>
</div>
<p>Next we need to craft a Lock of type <em>get</em> on our box. We want it to only be passed if the accessing
@ -394,27 +367,13 @@ object has the attribute <em>strength</em> of the right value. For this we would
function that checks if attributes have a value greater than a given value. Luckily there is already
such a one included in evennia (see <code class="docutils literal notranslate"><span class="pre">evennia/locks/lockfuncs.py</span></code>), called <code class="docutils literal notranslate"><span class="pre">attr_gt</span></code>.</p>
<p>So the lock string will look like this: <code class="docutils literal notranslate"><span class="pre">get:attr_gt(strength,</span> <span class="pre">50)</span></code>. We put this on the box now:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">lock</span> <span class="n">box</span> <span class="o">=</span> <span class="n">get</span><span class="p">:</span><span class="n">attr_gt</span><span class="p">(</span><span class="n">strength</span><span class="p">,</span> <span class="mi">50</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> lock box = get:attr_gt(strength, 50)
</pre></div>
</div>
<p>Try to <code class="docutils literal notranslate"><span class="pre">get</span></code> the object and you should get the message that we are not strong enough. Increase your
strength above 50 however and youll pick it up no problem. Done! A very heavy box!</p>
<p>If you wanted to set this up in python code, it would look something like this:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<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="c1"># create, then set the lock</span>
@ -430,10 +389,10 @@ strength above 50 however and youll pick it up no problem. Done! A very heavy
<span class="c1"># one heavy box, ready to withstand all but the strongest...</span>
</pre></div>
</td></tr></table></div>
</div>
</section>
<section id="on-django-s-permission-system">
<h2>On Djangos permission system<a class="headerlink" href="#on-django-s-permission-system" title="Permalink to this headline"></a></h2>
<section id="on-djangos-permission-system">
<h2>On Djangos 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 dont
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>
@ -483,7 +442,7 @@ interface. Its stand-alone from the permissions described above.</p>
<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>
<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>
<li><a class="reference internal" href="#on-django-s-permission-system">On Djangos permission system</a></li>
<li><a class="reference internal" href="#on-djangos-permission-system">On Djangos permission system</a></li>
</ul>
</li>
</ul>
@ -508,7 +467,7 @@ interface. Its stand-alone from the permissions described above.</p>
<h3>Versions</h3>
<ul>
<li><a href="Locks.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,7 +40,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="monitorhandler">
<section class="tex2jax_ignore mathjax_ignore" id="monitorhandler">
<h1>MonitorHandler<a class="headerlink" href="#monitorhandler" title="Permalink to this headline"></a></h1>
<p>The <em>MonitorHandler</em> is a system for watching changes in properties or Attributes on objects. A
monitor can be thought of as a sort of trigger that responds to change.</p>
@ -50,20 +52,18 @@ whenever it changes. This way the client could for example update its health bar
<p>The MontorHandler is accessed from the singleton <code class="docutils literal notranslate"><span class="pre">evennia.MONITOR_HANDLER</span></code>. The code for the handler
is in <code class="docutils literal notranslate"><span class="pre">evennia.scripts.monitorhandler</span></code>.</p>
<p>Heres how to add a new monitor:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">MONITOR_HANDLER</span>
<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">MONITOR_HANDLER</span>
<span class="n">MONITOR_HANDLER</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">fieldname</span><span class="p">,</span> <span class="n">callback</span><span class="p">,</span>
<span class="n">idstring</span><span class="o">=</span><span class="s2">&quot;&quot;</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="o">**</span><span class="n">kwargs</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">obj</span></code> (<a class="reference internal" href="Typeclasses.html"><span class="doc">Typeclassed</span></a> entity) - the object to monitor. Since this must be
typeclassed, it means you cant monitor changes on <a class="reference internal" href="Sessions.html"><span class="doc">Sessions</span></a> with the monitorhandler, for
<li><p><code class="docutils literal notranslate"><span class="pre">obj</span></code> (<a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclassed</span></a> entity) - the object to monitor. Since this must be
typeclassed, it means you cant monitor changes on <a class="reference internal" href="Sessions.html"><span class="doc std std-doc">Sessions</span></a> with the monitorhandler, for
example.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">fieldname</span></code> (str) - the name of a field or <a class="reference internal" href="Attributes.html"><span class="doc">Attribute</span></a> on <code class="docutils literal notranslate"><span class="pre">obj</span></code>. If you want to
<li><p><code class="docutils literal notranslate"><span class="pre">fieldname</span></code> (str) - the name of a field or <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attribute</span></a> on <code class="docutils literal notranslate"><span class="pre">obj</span></code>. If you want to
monitor a database field you must specify its full name, including the starting <code class="docutils literal notranslate"><span class="pre">db_</span></code> (like
<code class="docutils literal notranslate"><span class="pre">db_key</span></code>, <code class="docutils literal notranslate"><span class="pre">db_location</span></code> etc). Any names not starting with <code class="docutils literal notranslate"><span class="pre">db_</span></code> are instead assumed to be the names
of Attributes. This difference matters, since the MonitorHandler will automatically know to watch
@ -76,25 +76,7 @@ saving it.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">persistent</span></code> (bool) - if True, the monitor will survive a server reboot.</p></li>
</ul>
<p>Example:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">MONITOR_HANDLER</span> <span class="k">as</span> <span class="n">monitorhandler</span>
<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">MONITOR_HANDLER</span> <span class="k">as</span> <span class="n">monitorhandler</span>
<span class="k">def</span> <span class="nf">_monitor_callback</span><span class="p">(</span><span class="n">fieldname</span><span class="o">=</span><span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="n">obj</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="c1"># reporting callback that works both</span>
@ -113,8 +95,9 @@ saving it.</p></li>
<span class="c1"># monitor same db-field with two different callbacks (must separate by id_string)</span>
<span class="n">monitorhandler</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="s2">&quot;db_key&quot;</span><span class="p">,</span> <span class="n">_monitor_callback</span><span class="p">,</span> <span class="n">id_string</span><span class="o">=</span><span class="s2">&quot;foo&quot;</span><span class="p">)</span>
<span class="n">monitorhandler</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="s2">&quot;db_key&quot;</span><span class="p">,</span> <span class="n">_some_other_monitor_callback</span><span class="p">,</span> <span class="n">id_string</span><span class="o">=</span><span class="s2">&quot;bar&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>A monitor is uniquely identified by the combination of the <em>object instance</em> it is monitoring, the
<em>name</em> of the field/attribute to monitor on that object and its <code class="docutils literal notranslate"><span class="pre">idstring</span></code> (<code class="docutils literal notranslate"><span class="pre">obj</span></code> + <code class="docutils literal notranslate"><span class="pre">fieldname</span></code> +
<code class="docutils literal notranslate"><span class="pre">idstring</span></code>). The <code class="docutils literal notranslate"><span class="pre">idstring</span></code> will be the empty string unless given explicitly.</p>
@ -176,7 +159,7 @@ the monitor to remove:</p>
<h3>Versions</h3>
<ul>
<li><a href="MonitorHandler.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,9 +40,9 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="msg">
<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 external" href="../api/evennia.comms.models.Msg.html">Msg</a> object represents a database-saved
<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>
@ -54,38 +56,29 @@ good uses for <code class="docutils literal notranslate"><span class="pre">Msg</
</ul>
<div class="admonition important">
<p class="admonition-title">Important</p>
<p>A <cite>Msg</cite> does not have any in-game representation. So if you want to use them
<p>A <code class="docutils literal notranslate"><span class="pre">Msg</span></code> does not have any in-game representation. So if you want to use them
to represent in-game mail/letters, the physical letters would never be
visible in a room (possible to steal, spy on etc) unless you make your
spy-system access the Msgs directly (or go to the trouble of spawning an
actual in-game letter-object based on the Msg)</p>
</div>
<div class="versionchanged">
<p><span class="versionmodified changed">Changed in version 1.0: </span>Channels dropped Msg-support. Now only used in <cite>page</cite> command by default.</p>
<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">Typeclassed</span></a> entity, which means it cannot (easily) be overridden. It
doesnt support Attributes (but it <em>does</em> support <a class="reference internal" href="Tags.html"><span class="doc">Tags</span></a>). It tries to be lean
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
doesnt 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>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><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>
<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>
</pre></div>
</td></tr></table></div>
</div>
<p>You can search for <code class="docutils literal notranslate"><span class="pre">Msg</span></code> objects in various ways:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><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_message</span><span class="p">,</span> <span class="n">Msg</span>
<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_message</span><span class="p">,</span> <span class="n">Msg</span>
<span class="c1"># args are optional. Only a single sender/receiver should be passed</span>
<span class="n">messages</span> <span class="o">=</span> <span class="n">search_message</span><span class="p">(</span><span class="n">sender</span><span class="o">=...</span><span class="p">,</span> <span class="n">receiver</span><span class="o">=...</span><span class="p">,</span> <span class="n">freetext</span><span class="o">=...</span><span class="p">,</span> <span class="n">dbref</span><span class="o">=...</span><span class="p">)</span>
@ -93,13 +86,14 @@ and small since a new one is created for every message.</p>
<span class="c1"># get all messages for a given sender/receiver</span>
<span class="n">messages</span> <span class="o">=</span> <span class="n">Msg</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get_msg_by_sender</span><span class="p">(</span><span class="n">sender</span><span class="p">)</span>
<span class="n">messages</span> <span class="o">=</span> <span class="n">Msg</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get_msg_by_receiver</span><span class="p">(</span><span class="n">recipient</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<section id="properties-on-msg">
<h3>Properties on Msg<a class="headerlink" href="#properties-on-msg" title="Permalink to this headline"></a></h3>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">senders</span></code> - there must always be at least one sender. This is a set of</p></li>
<li><p><a class="reference internal" href="Accounts.html"><span class="doc">Account</span></a>, <a class="reference internal" href="Objects.html"><span class="doc">Object</span></a>, <a class="reference internal" href="Scripts.html"><span class="doc">Script</span></a>
<li><p><a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Account</span></a>, <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Object</span></a>, <a class="reference internal" href="Scripts.html"><span class="doc std std-doc">Script</span></a>
or <code class="docutils literal notranslate"><span class="pre">str</span></code> in any combination (but usually a message only targets one type).
Using a <code class="docutils literal notranslate"><span class="pre">str</span></code> for a sender indicates its an external sender and
and can be used to point to a sender that is not a typeclassed entity. This is not used by default
@ -107,17 +101,17 @@ and what this would be depends on the system (it could be a unique id or a
python-path, for example). While most systems expect a single sender, its
possible to have any number of them.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">receivers</span></code> - these are the ones to see the Msg. These are again any combination of
<a class="reference internal" href="Accounts.html"><span class="doc">Account</span></a>, <a class="reference internal" href="Objects.html"><span class="doc">Object</span></a> or <a class="reference internal" href="Scripts.html"><span class="doc">Script</span></a> or <code class="docutils literal notranslate"><span class="pre">str</span></code> (an external receiver).
<a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Account</span></a>, <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Object</span></a> or <a class="reference internal" href="Scripts.html"><span class="doc std std-doc">Script</span></a> or <code class="docutils literal notranslate"><span class="pre">str</span></code> (an external receiver).
Its in principle possible to have zero receivers but most usages of Msg expects one or more.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">header</span></code> - this is an optional text field that can contain meta-information about the message. For
an email-like system it would be the subject line. This can be independently searched, making
this a powerful place for quickly finding messages.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">message</span></code> - the actual text being sent.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">date_sent</span></code> - this is auto-set to the time the Msg was created (and thus presumably sent).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">locks</span></code> - the Evennia <a class="reference internal" href="Locks.html"><span class="doc">lock handler</span></a>. Use with <code class="docutils literal notranslate"><span class="pre">locks.add()</span></code> etc and check locks with <code class="docutils literal notranslate"><span class="pre">msg.access()</span></code>
<li><p><code class="docutils literal notranslate"><span class="pre">locks</span></code> - the Evennia <a class="reference internal" href="Locks.html"><span class="doc std std-doc">lock handler</span></a>. Use with <code class="docutils literal notranslate"><span class="pre">locks.add()</span></code> etc and check locks with <code class="docutils literal notranslate"><span class="pre">msg.access()</span></code>
like for all other lockable entities. This can be used to limit access to the contents
of the Msg. The default lock-type to check is <code class="docutils literal notranslate"><span class="pre">'read'</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">hide_from</span></code> - this is an optional list of <a class="reference internal" href="Accounts.html"><span class="doc">Accounts</span></a> or <a class="reference internal" href="Objects.html"><span class="doc">Objects</span></a> that
<li><p><code class="docutils literal notranslate"><span class="pre">hide_from</span></code> - this is an optional list of <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a> or <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a> that
will not see this Msg. This relationship is available mainly for optimization
reasons since it allows quick filtering of messages not intended for a given
target.</p></li>
@ -126,7 +120,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 external" href="../api/evennia.comms.models.TempMsg.html">evennia.comms.models.TempMsg</a> is an object
<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). Its 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
@ -186,7 +180,7 @@ it.</p>
<h3>Versions</h3>
<ul>
<li><a href="Msg.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,9 +40,9 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="nicks">
<section class="tex2jax_ignore mathjax_ignore" id="nicks">
<h1>Nicks<a class="headerlink" href="#nicks" title="Permalink to this headline"></a></h1>
<p><em>Nicks</em>, short for <em>Nicknames</em> is a system allowing an object (usually a <a class="reference internal" href="Accounts.html"><span class="doc">Account</span></a>) to
<p><em>Nicks</em>, short for <em>Nicknames</em> is a system allowing an object (usually a <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Account</span></a>) to
assign custom replacement names for other game entities.</p>
<p>Nicks are not to be confused with <em>Aliases</em>. Setting an Alias on a game entity actually changes an
inherent attribute on that entity, and everyone in the game will be able to use that alias to
@ -56,38 +58,38 @@ default.</p></li>
<li><p>accounts - replacement is only attempted when referring an account</p></li>
</ul>
<p>Heres how to use it in the default command set (using the <code class="docutils literal notranslate"><span class="pre">nick</span></code> command):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">nick</span> <span class="n">ls</span> <span class="o">=</span> <span class="n">look</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> nick ls = look
</pre></div>
</div>
<p>This is a good one for unix/linux users who are accustomed to using the <code class="docutils literal notranslate"><span class="pre">ls</span></code> command in their daily
life. It is equivalent to <code class="docutils literal notranslate"><span class="pre">nick/inputline</span> <span class="pre">ls</span> <span class="pre">=</span> <span class="pre">look</span></code>.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">nick</span><span class="o">/</span><span class="nb">object</span> <span class="n">mycar2</span> <span class="o">=</span> <span class="n">The</span> <span class="n">red</span> <span class="n">sports</span> <span class="n">car</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> nick/object mycar2 = The red sports car
</pre></div>
</div>
<p>With this example, substitutions will only be done specifically for commands expecting an object
reference, such as</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">look</span> <span class="n">mycar2</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> look mycar2
</pre></div>
</div>
<p>becomes equivalent to “<code class="docutils literal notranslate"><span class="pre">look</span> <span class="pre">The</span> <span class="pre">red</span> <span class="pre">sports</span> <span class="pre">car</span></code>”.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">nick</span><span class="o">/</span><span class="n">accounts</span> <span class="n">tom</span> <span class="o">=</span> <span class="n">Thomas</span> <span class="n">Johnsson</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> nick/accounts tom = Thomas Johnsson
</pre></div>
</div>
<p>This is useful for commands searching for accounts explicitly:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="nd">@find</span> <span class="o">*</span><span class="n">tom</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> @find *tom
</pre></div>
</div>
<p>One can use nicks to speed up input. Below we add ourselves a quicker way to build red buttons. In
the future just writing <em>rb</em> will be enough to execute that whole long string.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">nick</span> <span class="n">rb</span> <span class="o">=</span> <span class="nd">@create</span> <span class="n">button</span><span class="p">:</span><span class="n">examples</span><span class="o">.</span><span class="n">red_button</span><span class="o">.</span><span class="n">RedButton</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> nick rb = @create button:examples.red_button.RedButton
</pre></div>
</div>
<p>Nicks could also be used as the start for building a “recog” system suitable for an RP mud.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">nick</span><span class="o">/</span><span class="n">account</span> <span class="n">Arnold</span> <span class="o">=</span> <span class="n">The</span> <span class="n">mysterious</span> <span class="n">hooded</span> <span class="n">man</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> nick/account Arnold = The mysterious hooded man
</pre></div>
</div>
<p>The nick replacer also supports unix-style <em>templating</em>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> nick build $1 $2 = @create/drop $1;$2
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> nick build $1 $2 = @create/drop $1;$2
</pre></div>
</div>
<p>This will catch space separated arguments and store them in the the tags <code class="docutils literal notranslate"><span class="pre">$1</span></code> and <code class="docutils literal notranslate"><span class="pre">$2</span></code>, to be
@ -108,25 +110,9 @@ to the right of it</em> - it will then receive everything up until the end of th
<section id="coding-with-nicks">
<h2>Coding with nicks<a class="headerlink" href="#coding-with-nicks" title="Permalink to this headline"></a></h2>
<p>Nicks are stored as the <code class="docutils literal notranslate"><span class="pre">Nick</span></code> database model and are referred from the normal Evennia
<a class="reference internal" href="Objects.html"><span class="doc">object</span></a> through the <code class="docutils literal notranslate"><span class="pre">nicks</span></code> property - this is known as the <em>NickHandler</em>. The NickHandler
<a class="reference internal" href="Objects.html"><span class="doc std std-doc">object</span></a> through the <code class="docutils literal notranslate"><span class="pre">nicks</span></code> property - this is known as the <em>NickHandler</em>. The NickHandler
offers effective error checking, searches and conversion.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># A command/channel nick:</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># A command/channel nick:</span>
<span class="n">obj</span><span class="o">.</span><span class="n">nicks</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;greetjack&quot;</span><span class="p">,</span> <span class="s2">&quot;tell Jack = Hello pal!&quot;</span><span class="p">)</span>
<span class="c1"># An object nick: </span>
@ -144,16 +130,16 @@ offers effective error checking, searches and conversion.</p>
<span class="c1"># delete a previous set nick</span>
<span class="nb">object</span><span class="o">.</span><span class="n">nicks</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s2">&quot;rose&quot;</span><span class="p">,</span> <span class="n">nick_type</span><span class="o">=</span><span class="s2">&quot;object&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>In a command definition you can reach the nick handler through <code class="docutils literal notranslate"><span class="pre">self.caller.nicks</span></code>. See the <code class="docutils literal notranslate"><span class="pre">nick</span></code>
command in <code class="docutils literal notranslate"><span class="pre">evennia/commands/default/general.py</span></code> for more examples.</p>
<p>As a last note, The Evennia <a class="reference internal" href="Communications.html"><span class="doc">channel</span></a> alias systems are using nicks with the
<p>As a last note, The Evennia <a class="reference internal" href="Communications.html"><span class="doc std std-doc">channel</span></a> alias systems are using nicks with the
<code class="docutils literal notranslate"><span class="pre">nick_type=&quot;channel&quot;</span></code> in order to allow users to create their own custom aliases to channels.</p>
</section>
</section>
<section id="advanced-note">
<section class="tex2jax_ignore mathjax_ignore" id="advanced-note">
<h1>Advanced note<a class="headerlink" href="#advanced-note" title="Permalink to this headline"></a></h1>
<p>Internally, nicks are <a class="reference internal" href="Attributes.html"><span class="doc">Attributes</span></a> saved with the <code class="docutils literal notranslate"><span class="pre">db_attrype</span></code> set to “nick” (normal
<p>Internally, nicks are <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attributes</span></a> saved with the <code class="docutils literal notranslate"><span class="pre">db_attrype</span></code> set to “nick” (normal
Attributes has this set to <code class="docutils literal notranslate"><span class="pre">None</span></code>).</p>
<p>The nick stores the replacement data in the Attribute.db_value field as a tuple with four fields
<code class="docutils literal notranslate"><span class="pre">(regex_nick,</span> <span class="pre">template_string,</span> <span class="pre">raw_nick,</span> <span class="pre">raw_template)</span></code>. Here <code class="docutils literal notranslate"><span class="pre">regex_nick</span></code> is the converted regex
@ -161,13 +147,11 @@ representation of the <code class="docutils literal notranslate"><span class="pr
prepared for efficient replacement of any <code class="docutils literal notranslate"><span class="pre">$</span></code>- type markers. The <code class="docutils literal notranslate"><span class="pre">raw_nick</span></code> and <code class="docutils literal notranslate"><span class="pre">raw_template</span></code> are
basically the unchanged strings you enter to the <code class="docutils literal notranslate"><span class="pre">nick</span></code> command (with unparsed <code class="docutils literal notranslate"><span class="pre">$</span></code> etc).</p>
<p>If you need to access the tuple for some reason, heres how:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="nb">tuple</span> <span class="o">=</span> <span class="n">obj</span><span class="o">.</span><span class="n">nicks</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;nickname&quot;</span><span class="p">,</span> <span class="n">return_tuple</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="nb">tuple</span> <span class="o">=</span> <span class="n">obj</span><span class="o">.</span><span class="n">nicks</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;nickname&quot;</span><span class="p">,</span> <span class="n">return_tuple</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="c1"># or, alternatively</span>
<span class="nb">tuple</span> <span class="o">=</span> <span class="n">obj</span><span class="o">.</span><span class="n">nicks</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;nickname&quot;</span><span class="p">,</span> <span class="n">return_obj</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span><span class="o">.</span><span class="n">value</span>
</pre></div>
</td></tr></table></div>
</div>
</section>
@ -219,7 +203,7 @@ basically the unchanged strings you enter to the <code class="docutils literal n
<h3>Versions</h3>
<ul>
<li><a href="Nicks.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,11 +40,11 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="objects">
<section class="tex2jax_ignore mathjax_ignore" id="objects">
<h1>Objects<a class="headerlink" href="#objects" title="Permalink to this headline"></a></h1>
<p>All in-game objects in Evennia, be it characters, chairs, monsters, rooms or hand grenades are
represented by an Evennia <em>Object</em>. Objects form the core of Evennia and is probably what youll
spend most time working with. Objects are <a class="reference internal" href="Typeclasses.html"><span class="doc">Typeclassed</span></a> entities.</p>
spend most time working with. Objects are <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclassed</span></a> entities.</p>
<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>
<p>An Evennia Object is, per definition, a Python class that includes <code class="docutils literal notranslate"><span class="pre">evennia.DefaultObject</span></code> among its
@ -50,19 +52,7 @@ parents. In <code class="docutils literal notranslate"><span class="pre">mygame/
<code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> and that you can inherit from. You can put your new typeclass directly in that
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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># mygame/typeclasses/flowers.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># mygame/typeclasses/flowers.py</span>
<span class="kn">from</span> <span class="nn">typeclasses.objects</span> <span class="kn">import</span> <span class="n">Object</span>
@ -76,35 +66,34 @@ module or you could organize your code in some other way. Here we assume we make
<span class="c1"># to object (silly example).</span>
<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">&quot;This is a pretty rose with thorns.&quot;</span>
</pre></div>
</td></tr></table></div>
</div>
<p>You could save this in the <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/objects.py</span></code> (then youd not need to import <code class="docutils literal notranslate"><span class="pre">Object</span></code>)
or you can put it in a new module. Lets say we do the latter, making a module
<code class="docutils literal notranslate"><span class="pre">typeclasses/flowers.py</span></code>. Now you just need to point to the class <em>Rose</em> with the <code class="docutils literal notranslate"><span class="pre">&#64;create</span></code> command
to make a new rose:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="nd">@create</span><span class="o">/</span><span class="n">drop</span> <span class="n">MyRose</span><span class="p">:</span><span class="n">flowers</span><span class="o">.</span><span class="n">Rose</span>
<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">&#64;create</span></code> command actually <em>does</em> is to use <code class="docutils literal notranslate"><span class="pre">evennia.create_object</span></code>. You can do the same
thing yourself in code:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><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>
<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">&quot;typeclasses.flowers.Rose&quot;</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">&quot;MyRose&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>(The <code class="docutils literal notranslate"><span class="pre">&#64;create</span></code> command will auto-append the most likely path to your typeclass, if you enter the
call manually you have to give the full path to the class. The <code class="docutils literal notranslate"><span class="pre">create.create_object</span></code> function is
powerful and should be used for all coded object creating (so this is what you use when defining
your own building commands). Check out the <code class="docutils literal notranslate"><span class="pre">ev.create_*</span></code> functions for how to build other entities
like <a class="reference internal" href="Scripts.html"><span class="doc">Scripts</span></a>).</p>
like <a class="reference internal" href="Scripts.html"><span class="doc std std-doc">Scripts</span></a>).</p>
<p>This particular Rose class doesnt 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">&#64;desc</span></code> command or using the
<a class="reference internal" href="Prototypes.html"><span class="doc">Spawner</span></a>). The <code class="docutils literal notranslate"><span class="pre">Object</span></code> typeclass offers many more hooks that is available
<a class="reference internal" href="Prototypes.html"><span class="doc std std-doc">Spawner</span></a>). The <code class="docutils literal notranslate"><span class="pre">Object</span></code> typeclass offers many more hooks that is available
to use though - see next section.</p>
</section>
<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>
<p>Beyond the properties assigned to all <a class="reference internal" href="Typeclasses.html"><span class="doc">typeclassed</span></a> objects (see that page for a list
<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">
<li><p><code class="docutils literal notranslate"><span class="pre">aliases</span></code> - a handler that allows you to add and remove aliases from this object. Use
@ -113,12 +102,12 @@ of those), the Object also has the following custom properties:</p>
<li><p><code class="docutils literal notranslate"><span class="pre">home</span></code> is a backup location. The main motivation is to have a safe place to move the object to if
its <code class="docutils literal notranslate"><span class="pre">location</span></code> is destroyed. All objects should usually have a home location for safety.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">destination</span></code> - this holds a reference to another object this object links to in some way. Its
main use is for <a class="reference external" href="Components/Objects.html#Exits">Exits</a>, its otherwise usually unset.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">nicks</span></code> - as opposed to aliases, a <a class="reference internal" href="Nicks.html"><span class="doc">Nick</span></a> holds a convenient nickname replacement for a
main use is for <a class="reference internal" href="#exits"><span class="std std-doc">Exits</span></a>, its otherwise usually unset.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">nicks</span></code> - as opposed to aliases, a <a class="reference internal" href="Nicks.html"><span class="doc std std-doc">Nick</span></a> holds a convenient nickname replacement for a
real name, word or sequence, only valid for this object. This mainly makes sense if the Object is
used as a game character - it can then store briefer shorts, example so as to quickly reference game
commands or other characters. Use nicks.add(alias, realname) to add a new one.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">account</span></code> - this holds a reference to a connected <a class="reference internal" href="Accounts.html"><span class="doc">Account</span></a> controlling this object (if
<li><p><code class="docutils literal notranslate"><span class="pre">account</span></code> - this holds a reference to a connected <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Account</span></a> controlling this object (if
any). Note that this is set also if the controlling account is <em>not</em> currently online - to test if
an account is online, use the <code class="docutils literal notranslate"><span class="pre">has_account</span></code> property instead.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">sessions</span></code> - if <code class="docutils literal notranslate"><span class="pre">account</span></code> field is set <em>and the account is online</em>, this is a list of all active
@ -133,9 +122,9 @@ object set as their <code class="docutils literal notranslate"><span class="pre"
</ul>
<p>The last two properties are special:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">cmdset</span></code> - this is a handler that stores all <a class="reference external" href="Components/Commands.html#Command_Sets">command sets</a> defined on the
<li><p><code class="docutils literal notranslate"><span class="pre">cmdset</span></code> - this is a handler that stores all <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">command sets</span></a> defined on the
object (if any).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">scripts</span></code> - this is a handler that manages <a class="reference internal" href="Scripts.html"><span class="doc">Scripts</span></a> attached to the object (if any).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">scripts</span></code> - this is a handler that manages <a class="reference internal" href="Scripts.html"><span class="doc std std-doc">Scripts</span></a> attached to the object (if any).</p></li>
</ul>
<p>The Object also has a host of useful utility functions. See the function headers in
<code class="docutils literal notranslate"><span class="pre">src/objects/objects.py</span></code> for their arguments and more details.</p>
@ -150,7 +139,7 @@ on).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">execute_cmd()</span></code> - Lets the object execute the given string as if it was given on the command line.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">move_to</span></code> - perform a full move of this object to a new location. This is the main move method
and will call all relevant hooks, do all checks etc.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">clear_exits()</span></code> - will delete all <a class="reference external" href="Components/Objects.html#Exits">Exits</a> to <em>and</em> from this object.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">clear_exits()</span></code> - will delete all <a class="reference internal" href="#exits"><span class="std std-doc">Exits</span></a> to <em>and</em> from this object.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">clear_contents()</span></code> - this will not delete anything, but rather move all contents (except Exits) to
their designated <code class="docutils literal notranslate"><span class="pre">Home</span></code> locations.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">delete()</span></code> - deletes this object, first calling <code class="docutils literal notranslate"><span class="pre">clear_exits()</span></code> and
@ -159,8 +148,7 @@ their designated <code class="docutils literal notranslate"><span class="pre">Ho
<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 external" href="../api/evennia.objects.objects.html#defaultobject">API for DefaultObject
here</a>.</p>
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>
@ -171,10 +159,10 @@ recognized by the game engine (there is nothing stopping you from redefining the
practice they are all pretty similar to the base Object.</p>
<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">Accounts</span></a>. When a new Account
<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 external" href="Components/Commands.html#Command_Sets">Default Commandset</a> set on itself at
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
@ -195,19 +183,19 @@ you to modify.</p>
<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">Transit Command</span></a> on themselves when they are created. This command is
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 Exitss <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 (its not recommended though, unless you really know what you are
doing). Exits are <a class="reference internal" href="Locks.html"><span class="doc">locked</span></a> using an access_type called <em>traverse</em> and also make use of a few
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 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">cmdhandler</span></a> detects this and triggers the command defined on the Exit. Traversal always
<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>
<li><p>The Exit command checks the <code class="docutils literal notranslate"><span class="pre">traverse</span></code> lock on the Exit object</p></li>
@ -288,7 +276,7 @@ and display this as an error message. If this is not found, the Exit will instea
<h3>Versions</h3>
<ul>
<li><a href="Objects.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,9 +40,9 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="outputfuncs">
<section class="tex2jax_ignore mathjax_ignore" id="outputfuncs">
<h1>Outputfuncs<a class="headerlink" href="#outputfuncs" title="Permalink to this headline"></a></h1>
<p>TODO. For now info about outputfuncs are found in <a class="reference internal" href="../Concepts/OOB.html"><span class="doc">OOB</span></a>.</p>
<p>TODO. For now info about outputfuncs are found in <a class="reference internal" href="../Concepts/OOB.html"><span class="doc std std-doc">OOB</span></a>.</p>
</section>
@ -83,7 +85,7 @@
<h3>Versions</h3>
<ul>
<li><a href="Outputfuncs.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,28 +40,28 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="permissions">
<section class="tex2jax_ignore mathjax_ignore" id="permissions">
<h1>Permissions<a class="headerlink" href="#permissions" title="Permalink to this headline"></a></h1>
<p>A <em>permission</em> is simply a text string stored in the handler <code class="docutils literal notranslate"><span class="pre">permissions</span></code> on <code class="docutils literal notranslate"><span class="pre">Objects</span></code>
and <code class="docutils literal notranslate"><span class="pre">Accounts</span></code>. Think of it as a specialized sort of <a class="reference internal" href="Tags.html"><span class="doc">Tag</span></a> - one specifically dedicated
to access checking. They are thus often tightly coupled to <a class="reference internal" href="Locks.html"><span class="doc">Locks</span></a>.
and <code class="docutils literal notranslate"><span class="pre">Accounts</span></code>. Think of it as a specialized sort of <a class="reference internal" href="Tags.html"><span class="doc std std-doc">Tag</span></a> - one specifically dedicated
to access checking. They are thus often tightly coupled to <a class="reference internal" href="Locks.html"><span class="doc std std-doc">Locks</span></a>.
Permission strings are not case-sensitive, so “Builder” is the same as “builder”
etc.</p>
<p>Permissions are used as a convenient way to structure access levels and
hierarchies. It is set by the <code class="docutils literal notranslate"><span class="pre">perm</span></code> command and checked by the
<code class="docutils literal notranslate"><span class="pre">PermissionHandler.check</span></code> method as well as by the specially the <code class="docutils literal notranslate"><span class="pre">perm()</span></code> and
<code class="docutils literal notranslate"><span class="pre">pperm()</span></code> <a class="reference internal" href="Locks.html"><span class="doc">lock functions</span></a>.</p>
<code class="docutils literal notranslate"><span class="pre">pperm()</span></code> <a class="reference internal" href="Locks.html"><span class="doc std std-doc">lock functions</span></a>.</p>
<p>All new accounts are given a default set of permissions defined by
<code class="docutils literal notranslate"><span class="pre">settings.PERMISSION_ACCOUNT_DEFAULT</span></code>.</p>
<section id="managing-permissions">
<h2>Managing Permissions<a class="headerlink" href="#managing-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-default notranslate"><div class="highlight"><pre><span></span> <span class="n">perm</span><span class="o">/</span><span class="n">account</span> <span class="n">Tommy</span> <span class="o">=</span> <span class="n">Builders</span>
<span class="n">perm</span><span class="o">/</span><span class="n">account</span><span class="o">/</span><span class="k">del</span> <span class="n">Tommy</span> <span class="o">=</span> <span class="n">Builders</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> perm/account Tommy = Builders
perm/account/del Tommy = Builders
</pre></div>
</div>
<p>Note the use of the <code class="docutils literal notranslate"><span class="pre">/account</span></code> switch. It means you assign the permission to the
<a class="reference internal" href="Accounts.html"><span class="doc">Accounts</span></a> Tommy instead of any <a class="reference internal" href="Objects.html"><span class="doc">Character</span></a> that also
<a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a> Tommy instead of any <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Character</span></a> that also
happens to be named “Tommy”.</p>
<p>There can be reasons for putting permissions on Objects (especially NPCS), but
for granting powers to players, you should usually put the permission on the
@ -68,29 +70,26 @@ of which Character they are currently puppeting. This is especially important to
remember when assigning permissions from the <em>hierarchy tree</em> (see below), as an
Accounts permissions will overrule that of its character. So to be sure to
avoid confusion you should generally put hierarchy permissions on the Account,
not on their Characters (but see also <a class="reference external" href="Components/Locks.html#Quelling">quelling</a>).</p>
not on their Characters (but see also <a class="reference internal" href="#quelling"><span class="std std-doc">quelling</span></a>).</p>
<p>In code, you add/remove Permissions via the <code class="docutils literal notranslate"><span class="pre">PermissionHandler</span></code>, which sits on all
typeclassed entities as the property <code class="docutils literal notranslate"><span class="pre">.permissions</span></code>:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">account</span><span class="o">.</span><span class="n">permissions</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;Builders&quot;</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">account</span><span class="o">.</span><span class="n">permissions</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;Builders&quot;</span><span class="p">)</span>
<span class="n">account</span><span class="o">.</span><span class="n">permissions</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;cool_guy&quot;</span><span class="p">)</span>
<span class="n">obj</span><span class="o">.</span><span class="n">permissions</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;Blacksmith&quot;</span><span class="p">)</span>
<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">&quot;Blacksmith&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></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>
<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>. Evennias default permission hierarchy is as follows
(in increasing order of power):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">Player</span> <span class="c1"># can chat and send tells (default level) (lowest)</span>
<span class="n">Helper</span> <span class="c1"># can edit help files</span>
<span class="n">Builder</span> <span class="c1"># can edit the world</span>
<span class="n">Admin</span> <span class="c1"># can administrate accounts</span>
<span class="n">Developer</span> <span class="c1"># like superuser but affected by locks (highest)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> Player # can chat and send tells (default level) (lowest)
Helper # can edit help files
Builder # can edit the world
Admin # can administrate accounts
Developer # like superuser but affected by locks (highest)
</pre></div>
</div>
<p>(Besides being case-insensitive, hierarchical permissions also understand the
@ -109,7 +108,7 @@ that permission to pass.</p>
<section id="checking-permissions">
<h2>Checking permissions<a class="headerlink" href="#checking-permissions" title="Permalink to this headline"></a></h2>
<p>Its important to note that you check for the permission of a <em>puppeted</em>
<a class="reference internal" href="Objects.html"><span class="doc">Object</span></a> (like a Character), the check will always first use the
<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
@ -121,61 +120,46 @@ the Object itself.</p>
<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>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">obj</span><span class="o">.</span><span class="n">permissions</span><span class="o">.</span><span class="n">check</span><span class="p">(</span><span class="s2">&quot;Builder&quot;</span><span class="p">):</span>
<span class="c1"># allow builder to do stuff</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>if obj.permissions.check(&quot;Builder&quot;):
# allow builder to do stuff
<span class="k">if</span> <span class="n">obj</span><span class="o">.</span><span class="n">permissions</span><span class="o">.</span><span class="n">check</span><span class="p">(</span><span class="s2">&quot;Blacksmith&quot;</span><span class="p">,</span> <span class="s2">&quot;Warrior&quot;</span><span class="p">):</span>
<span class="c1"># do stuff for blacksmiths OR warriors</span>
if obj.permissions.check(&quot;Blacksmith&quot;, &quot;Warrior&quot;):
# do stuff for blacksmiths OR warriors
<span class="k">if</span> <span class="n">obj</span><span class="o">.</span><span class="n">permissions</span><span class="o">.</span><span class="n">check</span><span class="p">(</span><span class="s2">&quot;Blacksmith&quot;</span><span class="p">,</span> <span class="s2">&quot;Warrior&quot;</span><span class="p">,</span> <span class="n">require_all</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
<span class="c1"># only for those that are both blacksmiths AND warriors</span>
if obj.permissions.check(&quot;Blacksmith&quot;, &quot;Warrior&quot;, require_all=True):
# only for those that are both blacksmiths AND warriors
</pre></div>
</div>
<p>Using the <code class="docutils literal notranslate"><span class="pre">.check</span></code> method is the way to go, it will take hierarchical
permissions into account, check accounts/sessions etc.</p>
<div class="highlight-warning notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>
Don&#39;t confuse `.permissions.check()` with `.permissions.has()`. The .has()
method checks if a string is defined specifically on that PermissionHandler.
It will not consider permission-hierarchy, puppeting etc. `.has` can be useful
if you are manipulating permissions, but use `.check` for access checking.
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Don&#39;t confuse `.permissions.check()` with `.permissions.has()`. The .has()
method checks if a string is defined specifically on that PermissionHandler.
It will not consider permission-hierarchy, puppeting etc. `.has` can be useful
if you are manipulating permissions, but use `.check` for access checking.
</pre></div>
</td></tr></table></div>
</div>
</div>
</section>
<section id="lock-funcs">
<h3>Lock funcs<a class="headerlink" href="#lock-funcs" title="Permalink to this headline"></a></h3>
<p>While the <code class="docutils literal notranslate"><span class="pre">PermissionHandler</span></code> offers a simple way to check perms, <a class="reference internal" href="Locks.html"><span class="doc">Lock
<p>While the <code class="docutils literal notranslate"><span class="pre">PermissionHandler</span></code> offers a simple way to check perms, <a class="reference internal" href="Locks.html"><span class="doc std std-doc">Lock
strings</span></a> offers a mini-language for describing how something is accessed.
The <code class="docutils literal notranslate"><span class="pre">perm()</span></code> <em>lock function</em> is the main tool for using Permissions in locks.</p>
<p>Lets say we have a <code class="docutils literal notranslate"><span class="pre">red_key</span></code> object. We also have red chests that we want to
unlock with this key.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">perm</span> <span class="n">red_key</span> <span class="o">=</span> <span class="n">unlocks_red_chests</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>perm red_key = unlocks_red_chests
</pre></div>
</div>
<p>This gives the <code class="docutils literal notranslate"><span class="pre">red_key</span></code> object the permission “unlocks_red_chests”. Next we
lock our red chests:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">lock</span> <span class="n">red</span> <span class="n">chest</span> <span class="o">=</span> <span class="n">unlock</span><span class="p">:</span><span class="n">perm</span><span class="p">(</span><span class="n">unlocks_red_chests</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>lock red chest = unlock:perm(unlocks_red_chests)
</pre></div>
</div>
<p>When trying to unlock the red chest with this key, the chest Typeclass could
then take the key and do an access check:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in some typeclass file where chest is defined</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in some typeclass file where chest is defined</span>
<span class="k">class</span> <span class="nc">TreasureChest</span><span class="p">(</span><span class="n">Object</span><span class="p">):</span>
@ -189,8 +173,9 @@ then take the key and do an access check:</p>
<span class="k">else</span><span class="p">:</span>
<span class="n">who</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;The key fits! The chest opens.&quot;</span><span class="p">)</span>
<span class="c1"># ...</span>
</pre></div>
</td></tr></table></div>
</div>
<p>There are several variations to the default <code class="docutils literal notranslate"><span class="pre">perm</span></code> lockfunc:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">perm_above</span></code> - requires a hierarchical permission <em>higher</em> than the one
@ -203,24 +188,14 @@ objects (regardless of hierarchical perm or not).</p></li>
<section id="some-examples">
<h3>Some examples<a class="headerlink" href="#some-examples" title="Permalink to this headline"></a></h3>
<p>Adding permissions and checking with locks</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">account</span><span class="o">.</span><span class="n">permissions</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;Builder&quot;</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">account</span><span class="o">.</span><span class="n">permissions</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;Builder&quot;</span><span class="p">)</span>
<span class="n">account</span><span class="o">.</span><span class="n">permissions</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;cool_guy&quot;</span><span class="p">)</span>
<span class="n">account</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">&quot;enter:perm_above(Player) and perm(cool_guy)&quot;</span><span class="p">)</span>
<span class="n">account</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">obj1</span><span class="p">,</span> <span class="s2">&quot;enter&quot;</span><span class="p">)</span> <span class="c1"># this returns True!</span>
</pre></div>
</td></tr></table></div>
</div>
<p>An example of a puppet with a connected account:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">account</span><span class="o">.</span><span class="n">permissions</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;Player&quot;</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">account</span><span class="o">.</span><span class="n">permissions</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;Player&quot;</span><span class="p">)</span>
<span class="n">puppet</span><span class="o">.</span><span class="n">permissions</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;Builders&quot;</span><span class="p">)</span>
<span class="n">puppet</span><span class="o">.</span><span class="n">permissions</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;cool_guy&quot;</span><span class="p">)</span>
<span class="n">obj2</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">&quot;enter:perm_above(Accounts) and perm(cool_guy)&quot;</span><span class="p">)</span>
@ -229,7 +204,7 @@ objects (regardless of hierarchical perm or not).</p></li>
<span class="c1"># is lower than Account&#39;s perm, and perm takes</span>
<span class="c1"># precedence.</span>
</pre></div>
</td></tr></table></div>
</div>
</section>
</section>
<section id="superusers">
@ -313,7 +288,7 @@ affectable by locks.</p>
<h3>Versions</h3>
<ul>
<li><a href="Permissions.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,15 +40,15 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="portal-and-server">
<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/Start-Stop-Reload.html"><span class="doc">here</span></a>.</p>
inside the game or from the command line as described <a class="reference internal" href="../Setup/Start-Stop-Reload.html"><span class="doc std std-doc">here</span></a>.</p>
<p>If you are new to the concept, the main purpose of separating the two is to have accounts connect to
the Portal but keep the MUD running on the Server. This way one can restart/reload the game (the
Server part) without Accounts getting disconnected.</p>
<p>![portal and server layout](https://474a3b9f-a-62cb3a1a-s-
sites.googlegroups.com/site/evenniaserver/file-cabinet/evennia_server_portal.png)</p>
<a class="reference external" href="http://sites.googlegroups.com/site/evenniaserver/file-cabinet/evennia_server_portal.png">sites.googlegroups.com/site/evenniaserver/file-cabinet/evennia_server_portal.png</a>)</p>
<p>The Server and Portal are glued together via an AMP (Asynchronous Messaging Protocol) connection.
This allows the two programs to communicate seamlessly.</p>
</section>
@ -91,7 +93,7 @@ This allows the two programs to communicate seamlessly.</p>
<h3>Versions</h3>
<ul>
<li><a href="Portal-And-Server.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,12 +40,12 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="spawner-and-prototypes">
<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">Objects</span></a>, not any other type of
<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">Typeclass</span></a>. If you
<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
havent 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
@ -82,19 +84,15 @@ of these keys are mandatory. When just passing a one-time prototype-dict to the
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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="p">{</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="p">{</span>
<span class="s2">&quot;prototype_key&quot;</span><span class="p">:</span> <span class="s2">&quot;house&quot;</span>
<span class="s2">&quot;key&quot;</span><span class="p">:</span> <span class="s2">&quot;Large house&quot;</span>
<span class="s2">&quot;typeclass&quot;</span><span class="p">:</span> <span class="s2">&quot;typeclasses.rooms.house.House&quot;</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></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-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@spawn</span> <span class="p">{</span><span class="s2">&quot;prototype_key=&quot;</span><span class="n">house</span><span class="s2">&quot;, &quot;</span><span class="n">key</span><span class="s2">&quot;: &quot;</span><span class="n">Large</span> <span class="n">house</span><span class="s2">&quot;, ...}</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>@spawn {&quot;prototype_key=&quot;house&quot;, &quot;key&quot;: &quot;Large house&quot;, ...}
</pre></div>
</div>
<blockquote>
@ -141,11 +139,11 @@ instead.</p></li>
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">[&quot;Accounts&quot;,</span> <span class="pre">&quot;may_use_red_door&quot;]</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">lock-string</span></a> like <code class="docutils literal notranslate"><span class="pre">&quot;edit:all();control:perm(Builder)&quot;</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">&quot;edit:all();control:perm(Builder)&quot;</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">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">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">Attributes</span></a> and their values.
<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>
</ul>
@ -154,53 +152,44 @@ convenient for simple Attributes - use <code class="docutils literal notranslate
<li><p><code class="docutils literal notranslate"><span class="pre">ndb_&lt;name&gt;</span></code> - sets the value of a non-persistent attribute (<code class="docutils literal notranslate"><span class="pre">&quot;ndb_&quot;</span></code> is stripped from the name).
This is simply not useful in a prototype and is deprecated.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">exec</span></code> - This accepts a code snippet or a list of code snippets to run. This should not be used -
use callables or <a class="reference external" href="Components/Prototypes.html#protfuncs">$protfuncs</a> instead (see below).</p></li>
use callables or <a class="reference internal" href="#protfuncs"><span class="std std-doc">$protfuncs</span></a> instead (see below).</p></li>
</ul>
</section>
<section id="prototype-values">
<h3>Prototype values<a class="headerlink" href="#prototype-values" title="Permalink to this headline"></a></h3>
<p>The prototype supports values of several different types.</p>
<p>It can be a hard-coded value:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="p">{</span><span class="s2">&quot;key&quot;</span><span class="p">:</span> <span class="s2">&quot;An ugly goblin&quot;</span><span class="p">,</span> <span class="o">...</span><span class="p">}</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="p">{</span><span class="s2">&quot;key&quot;</span><span class="p">:</span> <span class="s2">&quot;An ugly goblin&quot;</span><span class="p">,</span> <span class="o">...</span><span class="p">}</span>
</pre></div>
</td></tr></table></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>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="p">{</span><span class="s2">&quot;key&quot;</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>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="p">{</span><span class="s2">&quot;key&quot;</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>
</td></tr></table></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>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="p">{</span><span class="s2">&quot;key&quot;</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">&quot;Urfgar&quot;</span><span class="p">,</span> <span class="s2">&quot;Rick the smelly&quot;</span><span class="p">,</span> <span class="s2">&quot;Blargh the foul&quot;</span><span class="p">,</span> <span class="o">...</span><span class="p">)),</span> <span class="o">...</span><span class="p">}</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="p">{</span><span class="s2">&quot;key&quot;</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">&quot;Urfgar&quot;</span><span class="p">,</span> <span class="s2">&quot;Rick the smelly&quot;</span><span class="p">,</span> <span class="s2">&quot;Blargh the foul&quot;</span><span class="p">,</span> <span class="o">...</span><span class="p">)),</span> <span class="o">...</span><span class="p">}</span>
</pre></div>
</td></tr></table></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>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="p">{</span><span class="s2">&quot;key&quot;</span><span class="p">:</span> <span class="s2">&quot;$choice(Urfgar, Rick the smelly, Blargh the foul)&quot;</span><span class="p">,</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="p">{</span><span class="s2">&quot;key&quot;</span><span class="p">:</span> <span class="s2">&quot;$choice(Urfgar, Rick the smelly, Blargh the foul)&quot;</span><span class="p">,</span>
<span class="s2">&quot;attrs&quot;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&quot;desc&quot;</span><span class="p">:</span> <span class="s2">&quot;This is a large $red(and very red) demon. &quot;</span>
<span class="s2">&quot;He has $randint(2,5) skulls in a chain around his neck.&quot;</span><span class="p">}</span>
</pre></div>
</td></tr></table></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 works in much the same way as an
<a class="reference external" href="Concepts/TextTags.html#inline-functions">InlineFunc</a> - they are actually
parsed using the same parser - except protfuncs are run every time the prototype is used to spawn a
new object (whereas an inlinefunc is called when a text is returned to the user).</p>
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>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><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>
<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">&quot;&quot;&quot;</span>
<span class="sd"> Usage: $red(&lt;text&gt;)</span>
@ -210,7 +199,7 @@ new object (whereas an inlinefunc is called when a text is returned to the user)
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Must have one argument, the text to color red!&quot;</span><span class="p">)</span>
<span class="k">return</span> <span class="sa">f</span><span class="s2">&quot;|r</span><span class="si">{</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="si">}</span><span class="s2">|n&quot;</span>
</pre></div>
</td></tr></table></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
@ -218,13 +207,12 @@ 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>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in mygame/server/conf/settings.py</span>
<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">&quot;world.myprotfuncs&quot;</span><span class="p">]</span>
</pre></div>
</td></tr></table></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>
@ -262,7 +250,7 @@ do limited coding/scripting for their prototypes without giving them direct acce
<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">Scripts</span></a> in the database. These are sometimes referred to as <em>database-
<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>
@ -278,15 +266,14 @@ prototypes to build from or if they just prefer to work offline in an external c
<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>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in mygame/server/conf.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/server/conf.py</span>
<span class="n">PROTOTYPE_MODULES</span> <span class="o">=</span> <span class="o">+=</span> <span class="p">[</span><span class="s2">&quot;world.myownprototypes&quot;</span><span class="p">,</span> <span class="s2">&quot;combat.prototypes&quot;</span><span class="p">]</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Here is an example of a prototype defined in a module:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>```python
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>```python
# in a module Evennia looks at for prototypes,
# (like mygame/world/prototypes.py)
@ -310,15 +297,15 @@ that you always add <code class="docutils literal notranslate"><span class="pre"
<p>The spawner can be used from inside the game through the Builder-only <code class="docutils literal notranslate"><span class="pre">&#64;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-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@spawn</span> <span class="n">goblin</span>
<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-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@spawn</span> <span class="p">{</span><span class="s2">&quot;prototype_key&quot;</span><span class="p">:</span> <span class="s2">&quot;shaman&quot;</span><span class="p">,</span> \
<span class="s2">&quot;key&quot;</span><span class="p">:</span><span class="s2">&quot;Orc shaman&quot;</span><span class="p">,</span> \
<span class="s2">&quot;prototype_parent&quot;</span><span class="p">:</span> <span class="s2">&quot;goblin&quot;</span><span class="p">,</span> \
<span class="s2">&quot;weapon&quot;</span><span class="p">:</span> <span class="s2">&quot;wooden staff&quot;</span><span class="p">,</span> \
<span class="s2">&quot;health&quot;</span><span class="p">:</span> <span class="mi">20</span><span class="p">}</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>@spawn {&quot;prototype_key&quot;: &quot;shaman&quot;, \
&quot;key&quot;:&quot;Orc shaman&quot;, \
&quot;prototype_parent&quot;: &quot;goblin&quot;, \
&quot;weapon&quot;: &quot;wooden staff&quot;, \
&quot;health&quot;: 20}
</pre></div>
</div>
<blockquote>
@ -331,16 +318,15 @@ the typeclass given by <code class="docutils literal notranslate"><span class="p
<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>
<p>In code you access the spawner mechanism directly via the call</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><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>
<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>
</td></tr></table></div>
</div>
<p>All arguments are prototype dictionaries. The function will return a
matching list of created objects. Example:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">obj1</span><span class="p">,</span> <span class="n">obj2</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="s2">&quot;key&quot;</span><span class="p">:</span> <span class="s2">&quot;Obj1&quot;</span><span class="p">,</span> <span class="s2">&quot;desc&quot;</span><span class="p">:</span> <span class="s2">&quot;A test&quot;</span><span class="p">},</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">obj1</span><span class="p">,</span> <span class="n">obj2</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="s2">&quot;key&quot;</span><span class="p">:</span> <span class="s2">&quot;Obj1&quot;</span><span class="p">,</span> <span class="s2">&quot;desc&quot;</span><span class="p">:</span> <span class="s2">&quot;A test&quot;</span><span class="p">},</span>
<span class="p">{</span><span class="s2">&quot;key&quot;</span><span class="p">:</span> <span class="s2">&quot;Obj2&quot;</span><span class="p">,</span> <span class="s2">&quot;desc&quot;</span><span class="p">:</span> <span class="s2">&quot;Another test&quot;</span><span class="p">})</span>
</pre></div>
</td></tr></table></div>
</div>
<blockquote>
<div><p>Hint: Same as when using <code class="docutils literal notranslate"><span class="pre">&#64;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
@ -420,7 +406,7 @@ the api docs</a>.</p>
<h3>Versions</h3>
<ul>
<li><a href="Prototypes.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,20 +40,20 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="scripts">
<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 external" href="../api/evennia.scripts.scripts.html">Script API reference</a></p>
<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">Objects</span></a>. Scripts are so flexible that the name “Script” is a bit limiting
<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 youd 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">Object</span></a> with a <code class="docutils literal notranslate"><span class="pre">None</span></code>-location just to store some game data,
<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">Typeclassed</span></a> entities - they have <a class="reference internal" href="Attributes.html"><span class="doc">Attributes</span></a> and
<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">Objects</span></a> and no connection to a particular
player/session like <a class="reference internal" href="Accounts.html"><span class="doc">Accounts</span></a>. This means they are perfectly suitable for acting
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>
@ -59,8 +61,8 @@ persistent system handlers.</p></li>
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 external" href="../api/evennia.utils.utils.html#evennia.utils.utils.delay">evennia.utils.delay</a> and
<a class="reference external" href="../api/evennia.utils.utils.html#evennia.utils.utils.repeat">evennia.utils.repeat</a>.</p></li>
<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
@ -69,26 +71,26 @@ in various ways. For historical reasons, a Script <em>not</em> attached to an ob
</ul>
<div class="versionchanged">
<p><span class="versionmodified changed">Changed in version 1.0: </span>In previus Evennia versions, stopping the Scripts timer also meant deleting the Script object.
Starting with this version, the timer can be start/stopped separately and <cite>.delete()</cite> must be called
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>
<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-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">addscript</span> <span class="n">obj</span> <span class="o">=</span> <span class="n">bodyfunctions</span><span class="o">.</span><span class="n">BodyFunctions</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; addscript obj = bodyfunctions.BodyFunctions
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">scripts</span></code> command is used to view all scripts and perform operations on them:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">scripts</span>
<span class="o">&gt;</span> <span class="n">scripts</span><span class="o">/</span><span class="n">stop</span> <span class="n">bodyfunctions</span><span class="o">.</span><span class="n">BodyFunctions</span>
<span class="o">&gt;</span> <span class="n">scripts</span><span class="o">/</span><span class="n">start</span> <span class="c1">#244</span>
<span class="o">&gt;</span> <span class="n">scripts</span><span class="o">/</span><span class="n">pause</span> <span class="c1">#11</span>
<span class="o">&gt;</span> <span class="n">scripts</span><span class="o">/</span><span class="n">delete</span> <span class="c1">#566</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; scripts
&gt; scripts/stop bodyfunctions.BodyFunctions
&gt; scripts/start #244
&gt; scripts/pause #11
&gt; scripts/delete #566
</pre></div>
</div>
<div class="versionchanged">
<p><span class="versionmodified changed">Changed in version 1.0: </span>The <cite>addscript</cite> command used to be only <cite>script</cite> which was easy to confuse with <cite>scripts</cite>.</p>
<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">
@ -96,21 +98,11 @@ on the Script explicitly to delete it.</p>
<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>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">new_script</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">create_script</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="s2">&quot;myscript&quot;</span><span class="p">,</span> <span class="n">typeclass</span><span class="o">=...</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">new_script</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">create_script</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="s2">&quot;myscript&quot;</span><span class="p">,</span> <span class="n">typeclass</span><span class="o">=...</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Create script with timer component:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># (note that this will call `timed_script.at_repeat` which is empty by default)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># (note that this will call `timed_script.at_repeat` which is empty by default)</span>
<span class="n">timed_script</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">create_script</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="s2">&quot;Timed script&quot;</span><span class="p">,</span>
<span class="n">interval</span><span class="o">=</span><span class="mi">34</span><span class="p">,</span> <span class="c1"># seconds &lt;=0 means off</span>
<span class="n">start_delay</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="c1"># wait interval before first call</span>
@ -122,25 +114,15 @@ sections).</p>
<span class="n">timed_script</span><span class="o">.</span><span class="n">pause</span><span class="p">()</span>
<span class="n">timed_script</span><span class="o">.</span><span class="n">unpause</span><span class="p">()</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Attach script to another object:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">myobj</span><span class="o">.</span><span class="n">scripts</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">new_script</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">myobj</span><span class="o">.</span><span class="n">scripts</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">new_script</span><span class="p">)</span>
<span class="n">myobj</span><span class="o">.</span><span class="n">scripts</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">evennia</span><span class="o">.</span><span class="n">DefaultScript</span><span class="p">)</span>
<span class="n">all_scripts_on_obj</span> <span class="o">=</span> <span class="n">myobj</span><span class="o">.</span><span class="n">scripts</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Search/find scripts in various ways:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># regular search (this is always a list, also if there is only one match)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># regular search (this is always a list, also if there is only one match)</span>
<span class="n">list_of_myscripts</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_script</span><span class="p">(</span><span class="s2">&quot;myscript&quot;</span><span class="p">)</span>
<span class="c1"># search through Evennia&#39;s GLOBAL_SCRIPTS container (based on</span>
@ -150,34 +132,23 @@ sections).</p>
<span class="n">myscript</span> <span class="o">=</span> <span class="n">GLOBAL_SCRIPTS</span><span class="o">.</span><span class="n">myscript</span>
<span class="n">GLOBAL_SCRIPTS</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;Timed script&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">foo</span> <span class="o">=</span> <span class="s2">&quot;bar&quot;</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Delete the Script (this will also stop its timer):</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">new_script</span><span class="o">.</span><span class="n">delete</span><span class="p">()</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">new_script</span><span class="o">.</span><span class="n">delete</span><span class="p">()</span>
<span class="n">timed_script</span><span class="o">.</span><span class="n">delete</span><span class="p">()</span>
</pre></div>
</td></tr></table></div>
</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>
</section>
<section class="tex2jax_ignore mathjax_ignore" id="defining-new-scripts">
<h1>Defining new Scripts<a class="headerlink" href="#defining-new-scripts" title="Permalink to this headline"></a></h1>
<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">typeclassed</span></a> entities. The parent class is <code class="docutils literal notranslate"><span class="pre">evennia.DefaultScript</span></code>.</p>
<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>
<h2>Simple storage script<a class="headerlink" href="#simple-storage-script" title="Permalink to this headline"></a></h2>
<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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in mygame/typeclasses/scripts.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/typeclasses/scripts.py</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">DefaultScript</span>
@ -189,53 +160,37 @@ can use this as a base for your own scripts.</p>
<span class="sd">&quot;&quot;&quot;Called once, when script is first created&quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;myscript&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">foo</span> <span class="o">=</span> <span class="s2">&quot;bar&quot;</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Once created, this simple Script could act as a global storage:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">evennia</span><span class="o">.</span><span class="n">create_script</span><span class="p">(</span><span class="s1">&#39;typeclasses.scripts.MyScript&#39;</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">evennia</span><span class="o">.</span><span class="n">create_script</span><span class="p">(</span><span class="s1">&#39;typeclasses.scripts.MyScript&#39;</span><span class="p">)</span>
<span class="c1"># from somewhere else</span>
<span class="n">myscript</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_script</span><span class="p">(</span><span class="s2">&quot;myscript&quot;</span><span class="p">)</span>
<span class="n">bar</span> <span class="o">=</span> <span class="n">myscript</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">foo</span>
<span class="n">myscript</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">something_else</span> <span class="o">=</span> <span class="mi">1000</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Note that if you give keyword arguments to <code class="docutils literal notranslate"><span class="pre">create_script</span></code> you can override the values
you set in your <code class="docutils literal notranslate"><span class="pre">at_script_creation</span></code>:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
<span class="n">evennia</span><span class="o">.</span><span class="n">create_script</span><span class="p">(</span><span class="s1">&#39;typeclasses.scripts.MyScript&#39;</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">&quot;another name&quot;</span><span class="p">,</span>
<span class="n">attributes</span><span class="o">=</span><span class="p">[(</span><span class="s2">&quot;foo&quot;</span><span class="p">,</span> <span class="s2">&quot;bar-alternative&quot;</span><span class="p">)])</span>
</pre></div>
</td></tr></table></div>
<p>See the <a class="reference external" href="../api/evennia.utils.create.html#evennia.utils.create.create_script">create_script</a> and
<a class="reference external" href="../api/evennia.utils.search.html#evennia.utils.search.search_script">search_script</a> API documentation for more options
</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>
</section>
<section id="timed-scripts">
<h3>Timed Scripts<a class="headerlink" href="#timed-scripts" title="Permalink to this headline"></a></h3>
<h2>Timed Scripts<a class="headerlink" href="#timed-scripts" title="Permalink to this headline"></a></h2>
<p>There are several properties one can set on the Script to control its timer component.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in mygame/typeclasses/scripts.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/typeclasses/scripts.py</span>
<span class="k">class</span> <span class="nc">TimerScript</span><span class="p">(</span><span class="n">Script</span><span class="p">):</span>
@ -246,8 +201,9 @@ on creating and finding Scripts.</p>
<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="c1"># do stuff every minute</span>
</pre></div>
</td></tr></table></div>
</div>
<p>This example will call <code class="docutils literal notranslate"><span class="pre">at_repeat</span></code> every minute. The <code class="docutils literal notranslate"><span class="pre">create_script</span></code> function has an <code class="docutils literal notranslate"><span class="pre">autostart=True</span></code> keyword
set by default - this means the scripts timer component will be started automatically. Otherwise
<code class="docutils literal notranslate"><span class="pre">.start()</span></code> must be called separately.</p>
@ -291,10 +247,10 @@ at which time the <code class="docutils literal notranslate"><span class="pre">m
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 id="script-timers-vs-delay-repeat">
<h4>Script timers vs delay/repeat<a class="headerlink" href="#script-timers-vs-delay-repeat" title="Permalink to this headline"></a></h4>
<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 external" href="../api/evennia.utils.utils.html#evennia.utils.utils.delay">evennia.utils.delay</a> and
<a class="reference external" href="../api/evennia.utils.utils.html#evennia.utils.utils.repeat">evennia.utils.repeat</a> functions
<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>
@ -310,37 +266,10 @@ methods of the script also offers a bit more fine-control than using <code class
</section>
</section>
<section id="script-attached-to-another-object">
<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">Account</span></a> or (more commonly) an <a class="reference internal" href="Objects.html"><span class="doc">Object</span></a>.
<h2>Script attached to another object<a class="headerlink" href="#script-attached-to-another-object" title="Permalink to this headline"></a></h2>
<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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># mygame/typeclasses/scripts.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># mygame/typeclasses/scripts.py</span>
<span class="c1"># Script class is defined at the top of this module</span>
<span class="kn">import</span> <span class="nn">random</span>
@ -369,27 +298,27 @@ If so, the parent object will be available to the script as either <code c
<span class="c1"># script is attached to (likely a room)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">obj</span><span class="o">.</span><span class="n">msg_contents</span><span class="p">(</span><span class="n">weather</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>If attached to a room, this Script will randomly report some weather
to everyone in the room every 5 minutes.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">myroom</span><span class="o">.</span><span class="n">scripts</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">scripts</span><span class="o">.</span><span class="n">Weather</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">myroom</span><span class="o">.</span><span class="n">scripts</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">scripts</span><span class="o">.</span><span class="n">Weather</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<blockquote>
<div><p>Note that <code class="docutils literal notranslate"><span class="pre">typeclasses</span></code> in your game dir is added to the setting <code class="docutils literal notranslate"><span class="pre">TYPECLASS_PATHS</span></code>.
Therefore we dont need to give the full path (<code class="docutils literal notranslate"><span class="pre">typeclasses.scripts.Weather</span></code>
but only <code class="docutils literal notranslate"><span class="pre">scripts.Weather</span></code> above.</p>
</div></blockquote>
<p>You can also attach the script as part of creating it:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">create_script</span><span class="p">(</span><span class="s1">&#39;typeclasses.weather.Weather&#39;</span><span class="p">,</span> <span class="n">obj</span><span class="o">=</span><span class="n">myroom</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">create_script</span><span class="p">(</span><span class="s1">&#39;typeclasses.weather.Weather&#39;</span><span class="p">,</span> <span class="n">obj</span><span class="o">=</span><span class="n">myroom</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
</section>
</section>
<section id="other-script-methods">
<h2>Other Script methods<a class="headerlink" href="#other-script-methods" title="Permalink to this headline"></a></h2>
<section class="tex2jax_ignore mathjax_ignore" id="other-script-methods">
<h1>Other Script methods<a class="headerlink" href="#other-script-methods" title="Permalink to this headline"></a></h1>
<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">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
<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 Scripts 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">
@ -408,26 +337,17 @@ 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">Attributes</span></a>, <a class="reference internal" href="Tags.html"><span class="doc">Tags</span></a> and <a class="reference internal" href="Locks.html"><span class="doc">Locks</span></a> etc like other
<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 external" href="#Timed_Scripts">Timed Script</a> above.</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>
</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 class="tex2jax_ignore mathjax_ignore" id="the-global-scripts-container">
<h1>The GLOBAL_SCRIPTS container<a class="headerlink" href="#the-global-scripts-container" title="Permalink to this headline"></a></h1>
<p>A Script not attached to another entity is commonly referred to as a <em>Global</em> script since itt 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
scripts. All you need is the Scripts <code class="docutils literal notranslate"><span class="pre">key</span></code>.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><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>
<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>
<span class="c1"># access as a property on the container, named the same as the key</span>
<span class="n">my_script</span> <span class="o">=</span> <span class="n">GLOBAL_SCRIPTS</span><span class="o">.</span><span class="n">my_script</span>
@ -437,15 +357,18 @@ scripts. All you need is the Scripts <code class="docutils literal notranslat
<span class="n">all_scripts</span> <span class="o">=</span> <span class="n">GLOBAL_SCRIPTS</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
<span class="c1"># you can operate directly on the script</span>
<span class="n">GLOBAL_SCRIPTS</span><span class="o">.</span><span class="n">weather</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">current_weather</span> <span class="o">=</span> <span class="s2">&quot;Cloudy&quot;</span>
</pre></div>
</td></tr></table></div>
</div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>Note that global scripts appear as properties on <cite>GLOBAL_SCRIPTS</cite> based on their <cite>key</cite>.
If you were to create two global scripts with the same <cite>key</cite> (even with different typeclasses),
the <cite>GLOBAL_SCRIPTS</cite> container will only return one of them (which one depends on order in
<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
<cite>evennia.search_scripts</cite> to get exactly the script you want.</p>
`evennia.search_scripts` to get exactly the script you want.
</pre></div>
</div>
</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">
@ -457,17 +380,7 @@ when your server restarts. If you use this method, you must make sure all
script keys are globally unique.</p></li>
</ol>
<p>Heres how to tell Evennia to manage the script in settings:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in mygame/server/conf/settings.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/server/conf/settings.py</span>
<span class="n">GLOBAL_SCRIPTS</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">&quot;my_script&quot;</span><span class="p">:</span> <span class="p">{</span>
@ -479,55 +392,40 @@ script keys are globally unique.</p></li>
<span class="s2">&quot;storagescript&quot;</span><span class="p">:</span> <span class="p">{}</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></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 external" href="../api/evennia.utils.create.create_script.html">same keyword arguments as for create_script</a> are
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>
<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, youll see errors in your log
and your Script will temporarily fall back to being a <cite>DefaultScript</cite> type.</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&#39;ll see errors in your log
and your Script will temporarily fall back to being a `DefaultScript` type.
</pre></div>
</div>
</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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span></pre></div></td><td class="code"><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>
<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>
<span class="c1"># Delete the script</span>
<span class="n">GLOBAL_SCRIPTS</span><span class="o">.</span><span class="n">storagescript</span><span class="o">.</span><span class="n">delete</span><span class="p">()</span>
<span class="c1"># running the `scripts` command now will show no storagescript</span>
<span class="c1"># but below it&#39;s automatically recreated again!</span>
<span class="n">storage</span> <span class="o">=</span> <span class="n">GLOBAL_SCRIPTS</span><span class="o">.</span><span class="n">storagescript</span>
</pre></div>
</td></tr></table></div>
</div>
<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>
<section class="tex2jax_ignore mathjax_ignore" id="hints-dealing-with-script-errors">
<h1>Hints: Dealing with Script Errors<a class="headerlink" href="#hints-dealing-with-script-errors" title="Permalink to this headline"></a></h1>
<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 Evennias native logger and wrap your
functions in a try/catch block. Evennias logger can show you where the
traceback occurred in your script.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<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>
@ -541,8 +439,7 @@ traceback occurred in your script.</p>
<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>
</td></tr></table></div>
</section>
</div>
</section>
@ -570,6 +467,8 @@ traceback occurred in your script.</p>
<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="#code-examples">Code examples</a></li>
</ul>
</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-scripts">Timed Scripts</a><ul>
@ -582,8 +481,6 @@ traceback occurred in your script.</p>
<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>
</ul>
</li>
</ul>
<div role="note" aria-label="source link">
@ -606,7 +503,7 @@ traceback occurred in your script.</p>
<h3>Versions</h3>
<ul>
<li><a href="Scripts.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -1,222 +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>Server Conf &#8212; Evennia 1.0-dev documentation</title>
<link rel="stylesheet" href="../_static/nature.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.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="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Server Conf</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="server-conf">
<h1>Server Conf<a class="headerlink" href="#server-conf" title="Permalink to this headline"></a></h1>
<p>Evennia runs out of the box without any changes to its settings. But there are several important
ways to customize the server and expand it with your own plugins.</p>
<section id="settings-file">
<h2>Settings file<a class="headerlink" href="#settings-file" title="Permalink to this headline"></a></h2>
<p>The “Settings” file referenced throughout the documentation is the file
<code class="docutils literal notranslate"><span class="pre">mygame/server/conf/settings.py</span></code>. This is automatically created on the first run of <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">--init</span></code>
(see the <a class="reference internal" href="../Setup/Setup-Quickstart.html"><span class="doc">Setup Quickstart</span></a> page).</p>
<p>Your new <code class="docutils literal notranslate"><span class="pre">settings.py</span></code> is relatively bare out of the box. Evennias core settings file is actually
<a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/settings_default.py">evennia/settings_default.py</a>
and is considerably more extensive (it is also heavily documented so you should refer to this file
directly for the available settings).</p>
<p>Since <code class="docutils literal notranslate"><span class="pre">mygame/server/conf/settings.py</span></code> is a normal Python module, it simply imports
<code class="docutils literal notranslate"><span class="pre">evennia/settings_default.py</span></code> into itself at the top.</p>
<p>This means that if any setting you want to change were to depend on some <em>other</em> default setting,
you might need to copy &amp; paste both in order to change them and get the effect you want (for most
commonly changed settings, this is not something you need to worry about).</p>
<p>You should never edit <code class="docutils literal notranslate"><span class="pre">evennia/settings_default.py</span></code>. Rather you should copy&amp;paste the select
variables you want to change into your <code class="docutils literal notranslate"><span class="pre">settings.py</span></code> and edit them there. This will overload the
previously imported defaults.</p>
<blockquote>
<div><p>Warning: It may be tempting to copy everything from <code class="docutils literal notranslate"><span class="pre">settings_default.py</span></code> into your own settings
file. There is a reason we dont do this out of the box though: it makes it directly clear what
changes you did. Also, if you limit your copying to the things you really need you will directly be
able to take advantage of upstream changes and additions to Evennia for anything you didnt
customize.</p>
</div></blockquote>
<p>In code, the settings is accessed through</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="kn">from</span> <span class="nn">django.conf</span> <span class="kn">import</span> <span class="n">settings</span>
<span class="c1"># or (shorter):</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">settings</span>
<span class="c1"># example:</span>
<span class="n">servername</span> <span class="o">=</span> <span class="n">settings</span><span class="o">.</span><span class="n">SERVER_NAME</span>
</pre></div>
</td></tr></table></div>
<p>Each setting appears as a property on the imported <code class="docutils literal notranslate"><span class="pre">settings</span></code> object. You can also explore all
possible options with <code class="docutils literal notranslate"><span class="pre">evennia.settings_full</span></code> (this also includes advanced Django defaults that are
not touched in default Evennia).</p>
<blockquote>
<div><p>It should be pointed out that when importing <code class="docutils literal notranslate"><span class="pre">settings</span></code> into your code like this, it will be <em>read
only</em>. You <em>cannot</em> edit your settings from your code! The only way to change an Evennia setting is
to edit <code class="docutils literal notranslate"><span class="pre">mygame/server/conf/settings.py</span></code> directly. You also generally need to restart the server
(possibly also the Portal) before a changed setting becomes available.</p>
</div></blockquote>
</section>
<section id="other-files-in-the-server-conf-directory">
<h2>Other files in the <code class="docutils literal notranslate"><span class="pre">server/conf</span></code> directory<a class="headerlink" href="#other-files-in-the-server-conf-directory" title="Permalink to this headline"></a></h2>
<p>Apart from the main <code class="docutils literal notranslate"><span class="pre">settings.py</span></code> file,</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">at_initial_setup.py</span></code> - this allows you to add a custom startup method to be called (only) the
very first time Evennia starts (at the same time as user #1 and Limbo is created). It can be made to
start your own global scripts or set up other system/world-related things your game needs to have
running from the start.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">at_server_startstop.py</span></code> - this module contains two functions that Evennia will call every time
the Server starts and stops respectively - this includes stopping due to reloading and resetting as
well as shutting down completely. Its a useful place to put custom startup code for handlers and
other things that must run in your game but which has no database persistence.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">connection_screens.py</span></code> - all global string variables in this module are interpreted by Evennia as
a greeting screen to show when an Account first connects. If more than one string variable is
present in the module a random one will be picked.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">inlinefuncs.py</span></code> - this is where you can define custom <a class="reference external" href="Concepts/TextTags.html#inlinefuncs">Inline functions</a>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">inputfuncs.py</span></code> - this is where you define custom <a class="reference internal" href="Inputfuncs.html"><span class="doc">Input functions</span></a> to handle data
from the client.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">lockfuncs.py</span></code> - this is one of many possible modules to hold your own “safe” <em>lock functions</em> to
make available to Evennias <a class="reference internal" href="Locks.html"><span class="doc">Locks</span></a>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">mssp.py</span></code> - this holds meta information about your game. It is used by MUD search engines (which
you often have to register with) in order to display what kind of game you are running along with
statistics such as number of online accounts and online status.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">oobfuncs.py</span></code> - in here you can define custom <a class="reference internal" href="../Concepts/OOB.html"><span class="doc">OOB functions</span></a>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">portal_services_plugin.py</span></code> - this allows for adding your own custom services/protocols to the
Portal. It must define one particular function that will be called by Evennia at startup. There can
be any number of service plugin modules, all will be imported and used if defined. More info can be
found <a class="reference external" href="https://code.google.com/p/evennia/wiki/SessionProtocols#Adding_custom_Protocols">here</a>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">server_services_plugin.py</span></code> - this is equivalent to the previous one, but used for adding new
services to the Server instead. More info can be found
<a class="reference external" href="https://code.google.com/p/evennia/wiki/SessionProtocols#Adding_custom_Protocols">here</a>.</p></li>
</ul>
<p>Some other Evennia systems can be customized by plugin modules but has no explicit template in
<code class="docutils literal notranslate"><span class="pre">conf/</span></code>:</p>
<ul class="simple">
<li><p><em>cmdparser.py</em> - a custom module can be used to totally replace Evennias default command parser.
All this does is to split the incoming string into “command name” and “the rest”. It also handles
things like error messages for no-matches and multiple-matches among other things that makes this
more complex than it sounds. The default parser is <em>very</em> generic, so you are most often best served
by modifying things further down the line (on the command parse level) than here.</p></li>
<li><p><em>at_search.py</em> - this allows for replacing the way Evennia handles search results. It allows to
change how errors are echoed and how multi-matches are resolved and reported (like how the default
understands that “2-ball” should match the second “ball” object if there are two of them in the
room).</p></li>
</ul>
</section>
<section id="serverconf">
<h2>ServerConf<a class="headerlink" href="#serverconf" title="Permalink to this headline"></a></h2>
<p>There is a special database model called <code class="docutils literal notranslate"><span class="pre">ServerConf</span></code> that stores server internal data and settings
such as current account count (for interfacing with the webserver), startup status and many other
things. Its rarely of use outside the server core itself but may be good to
know about if you are an Evennia developer.</p>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/evennia_logo.png" alt="Logo"/>
</a></p>
<div id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" />
<input type="submit" value="Go" />
</form>
</div>
</div>
<script>$('#searchbox').show(0);</script>
<p><h3><a href="../index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Server Conf</a><ul>
<li><a class="reference internal" href="#settings-file">Settings file</a></li>
<li><a class="reference internal" href="#other-files-in-the-server-conf-directory">Other files in the <code class="docutils literal notranslate"><span class="pre">server/conf</span></code> directory</a></li>
<li><a class="reference internal" href="#serverconf">ServerConf</a></li>
</ul>
</li>
</ul>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="../_sources/Components/Server-Conf.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="Server-Conf.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
</ul>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Server Conf</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2020, The Evennia developer community.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
</div>
</body>
</html>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,9 +40,9 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="server-component">
<section class="tex2jax_ignore mathjax_ignore" id="server-component">
<h1>Server component<a class="headerlink" href="#server-component" title="Permalink to this headline"></a></h1>
<p>TODO: This is currently in <a class="reference internal" href="Portal-And-Server.html"><span class="doc">Portal-and-Server</span></a>.</p>
<p>TODO: This is currently in <a class="reference internal" href="Portal-And-Server.html"><span class="doc std std-doc">Portal-and-Server</span></a>.</p>
</section>
@ -83,7 +85,7 @@
<h3>Versions</h3>
<ul>
<li><a href="Server.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,19 +40,19 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="sessions">
<section class="tex2jax_ignore mathjax_ignore" id="sessions">
<h1>Sessions<a class="headerlink" href="#sessions" title="Permalink to this headline"></a></h1>
<p>An Evennia <em>Session</em> represents one single established connection to the server. Depending on the
Evennia session, it is possible for a person to connect multiple times, for example using different
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">cmdset</span></a>, usually the “unloggedin” cmdset. This is what
<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">Account</span></a> in evennia lingo) read initial help and to log into the game with an existing
<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>
<blockquote>
<div><p>Warning: A Session is not <em>persistent</em> - it is not a <a class="reference internal" href="Typeclasses.html"><span class="doc">Typeclass</span></a> and has no
<div><p>Warning: 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 dont know if you receive an Object or a Session),
@ -64,13 +66,13 @@ lose in a reload. You have been warned.</p>
<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 clients 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">Account</span></a> this Session is attached to. If not logged in yet, this is
<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">Character/Object</span></a> currently puppeted by this Account/Session combo. If
<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">Non-persistent Attribute</span></a> handler.</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 dont 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 Sessions <a class="reference internal" href="Command-Sets.html"><span class="doc">CmdSetHandler</span></a></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">cmdset</span></code> - The Sessions <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">CmdSetHandler</span></a></p></li>
</ul>
<p>Session statistics are mainly used internally by Evennia.</p>
<ul class="simple">
@ -135,7 +137,7 @@ transparently detect which session was triggering the command (if any) and redir
<code class="docutils literal notranslate"><span class="pre">command.msg()</span></code> is often the safest bet.</p>
<p>You can get the <code class="docutils literal notranslate"><span class="pre">session</span></code> in two main ways:</p>
<ul class="simple">
<li><p><a class="reference internal" href="Accounts.html"><span class="doc">Accounts</span></a> and <a class="reference internal" href="Objects.html"><span class="doc">Objects</span></a> (including Characters) have a <code class="docutils literal notranslate"><span class="pre">sessions</span></code> property.
<li><p><a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a> and <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a> (including Characters) have a <code class="docutils literal notranslate"><span class="pre">sessions</span></code> property.
This is a <em>handler</em> that tracks all Sessions attached to or puppeting them. Use e.g.
<code class="docutils literal notranslate"><span class="pre">accounts.sessions.get()</span></code> to get a list of Sessions attached to that entity.</p></li>
<li><p>A Command instance has a <code class="docutils literal notranslate"><span class="pre">session</span></code> property that always points back to the Session that triggered
@ -166,7 +168,7 @@ changes carefully.</p>
<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 dont 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">Portal and the Server</span></a>. Each side tracks
<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
@ -192,7 +194,7 @@ its mirror Server session and vice versa.</p>
make sure the corresponding Server Session is also deleted.</p></li>
<li><p>The Player quits from inside the game, killing the Server Session. The Server then syncs with the
Portal to make sure to close the Portal connection cleanly.</p></li>
<li><p>The Server is rebooted/reset/shutdown - The Server Sessions are copied over (saved”) to the
<li><p>The Server is rebooted/reset/shutdown - The Server Sessions are copied over (saved”) to the
Portal side. When the Server comes back up, this data is returned by the Portal so the two are again
in sync. This way an Accounts 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>
@ -203,7 +205,7 @@ server reboot (assuming the Portal is not stopped at the same time, obviously).<
<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/Custom-Protocols.html"><span class="doc">protocols</span></a> for more info
<code class="docutils literal notranslate"><span class="pre">sessionhandler</span></code>) so they can relay data. See <a class="reference internal" href="../Concepts/Custom-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>
@ -273,7 +275,7 @@ module for details on the capabilities of the <code class="docutils literal notr
<h3>Versions</h3>
<ul>
<li><a href="Sessions.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,7 +40,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="signals">
<section class="tex2jax_ignore mathjax_ignore" id="signals">
<h1>Signals<a class="headerlink" href="#signals" title="Permalink to this headline"></a></h1>
<p><em>This is feature available from evennia 0.9 and onward</em>.</p>
<p>There are multiple ways for you to plug in your own functionality into Evennia.
@ -55,36 +57,30 @@ signal.</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>
<p>First you create your handler</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<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>
<span class="c1"># do stuff</span>
</pre></div>
</td></tr></table></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> is mandatory. Then you attach it to the signal of your choice:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.server</span> <span class="kn">import</span> <span class="n">signals</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.server</span> <span class="kn">import</span> <span class="n">signals</span>
<span class="n">signals</span><span class="o">.</span><span class="n">SIGNAL_OBJECT_POST_CREATE</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">myhandler</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>This particular signal fires after (post) an Account has connected to the game.
When that happens, <code class="docutils literal notranslate"><span class="pre">myhandler</span></code> will fire with the <code class="docutils literal notranslate"><span class="pre">sender</span></code> being the Account that just connected.</p>
<p>If you want to respond only to the effects of a specific entity you can do so
like this:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><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_account</span>
<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_account</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">signals</span>
<span class="n">account</span> <span class="o">=</span> <span class="n">search_account</span><span class="p">(</span><span class="s2">&quot;foo&quot;</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<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>
</td></tr></table></div>
</div>
</section>
<section id="available-signals">
<h2>Available signals<a class="headerlink" href="#available-signals" title="Permalink to this headline"></a></h2>
@ -103,7 +99,7 @@ trigger this signal. This is because using <code class="docutils literal notrans
used way for users to themselves create accounts during login. It passes and extra kwarg <code class="docutils literal notranslate"><span class="pre">ip</span></code> with
the client IP of the connecting account.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_ACCOUNT_POST_LOGIN</span></code> - this will always fire when the account has authenticated. Sends
extra kwarg <code class="docutils literal notranslate"><span class="pre">session</span></code> with the new <a class="reference internal" href="Sessions.html"><span class="doc">Session</span></a> object involved.</p></li>
extra kwarg <code class="docutils literal notranslate"><span class="pre">session</span></code> with the new <a class="reference internal" href="Sessions.html"><span class="doc std std-doc">Session</span></a> object involved.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_ACCCOUNT_POST_FIRST_LOGIN</span></code> - this fires just before <code class="docutils literal notranslate"><span class="pre">SIGNAL_ACCOUNT_POST_LOGIN</span></code> but only
if
this is the <em>first</em> connection done (that is, if there are no previous sessions connected). Also
@ -206,7 +202,7 @@ decorator (only relevant for unit testing)</p></li>
<h3>Versions</h3>
<ul>
<li><a href="Signals.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,7 +40,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="tags">
<section class="tex2jax_ignore mathjax_ignore" id="tags">
<h1>Tags<a class="headerlink" href="#tags" title="Permalink to this headline"></a></h1>
<p>A common task of a game designer is to organize and find groups of objects and do operations on
them. A classic example is to have a weather script affect all “outside” rooms. Another would be for
@ -48,10 +50,10 @@ currently dead.</p>
<p><em>Tags</em> are short text labels that you attach to objects so as to easily be able to retrieve and
group them. An Evennia entity can be tagged with any number of Tags. On the database side, Tag
entities are <em>shared</em> between all objects with that tag. This makes them very efficient but also
fundamentally different from <a class="reference internal" href="Attributes.html"><span class="doc">Attributes</span></a>, each of which always belongs to one <em>single</em>
fundamentally different from <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attributes</span></a>, each of which always belongs to one <em>single</em>
object.</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">Locks</span></a> to check for).</p>
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="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>
<p>Tags are <em>unique</em>. This means that there is only ever one Tag object with a given key and category.</p>
@ -61,7 +63,7 @@ unique key + category combination.</p>
</div></blockquote>
<p>When Tags are assigned to game entities, these entities are actually sharing the same Tag. This
means that Tags are not suitable for storing information about a single object - use an
<a class="reference internal" href="Attributes.html"><span class="doc">Attribute</span></a> for this instead. Tags are a lot more limited than Attributes but this also
<a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attribute</span></a> for this instead. Tags are a lot more limited than Attributes but this also
makes them very quick to lookup in the database - this is the whole point.</p>
<p>Tags have the following properties, stored in the database:</p>
<ul class="simple">
@ -88,18 +90,10 @@ free up the <em>category</em> property for any use you desire.</p></li>
</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">Objects</span></a>, <a class="reference internal" href="Accounts.html"><span class="doc">Accounts</span></a>,
<a class="reference internal" href="Scripts.html"><span class="doc">Scripts</span></a> and <a class="reference internal" href="Communications.html"><span class="doc">Channels</span></a>. General tags are added by the <em>Taghandler</em>. The
<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="Communications.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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><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">&quot;furniture&quot;</span><span class="p">)</span>
<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">&quot;furniture&quot;</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">&quot;furniture&quot;</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">&quot;luxurious&quot;</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">&quot;dungeon#01&quot;</span><span class="p">)</span>
<span class="n">myscript</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">&quot;weather&quot;</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">&quot;climate&quot;</span><span class="p">)</span>
@ -109,13 +103,13 @@ tag handler is accessed as a property <code class="docutils literal notranslate"
<span class="n">mychair</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s2">&quot;furniture&quot;</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">clear</span><span class="p">()</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Adding a new tag will either create a new Tag or re-use an already existing one. Note that there are
<em>two</em> “furniture” tags, one with a <code class="docutils literal notranslate"><span class="pre">None</span></code> category, and one with the “luxurious” category.</p>
<p>When using <code class="docutils literal notranslate"><span class="pre">remove</span></code>, the <code class="docutils literal notranslate"><span class="pre">Tag</span></code> is not deleted but are just disconnected from the tagged object. This
makes for very quick operations. The <code class="docutils literal notranslate"><span class="pre">clear</span></code> method removes (disconnects) all Tags from the object.
You can also use the default <code class="docutils literal notranslate"><span class="pre">&#64;tag</span></code> command:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="nd">@tag</span> <span class="n">mychair</span> <span class="o">=</span> <span class="n">furniture</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> @tag mychair = furniture
</pre></div>
</div>
<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>
@ -124,24 +118,7 @@ You can also use the default <code class="docutils literal notranslate"><span cl
<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>
<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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="kn">import</span> <span class="nn">evennia</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="kn">import</span> <span class="nn">evennia</span>
<span class="c1"># all methods return Querysets</span>
@ -160,7 +137,7 @@ with a given Tag like this in code:</p>
<span class="c1"># search for accounts</span>
<span class="n">accounts</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_tag_account</span><span class="p">(</span><span class="s2">&quot;guestaccount&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<blockquote>
<div><p>Note that searching for just “furniture” will only return the objects tagged with the “furniture”
tag that
@ -172,18 +149,7 @@ one match. You can treat querysets as lists and iterate over them, or continue b
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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">evennia</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">evennia</span>
<span class="n">myobj1</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">&quot;foo&quot;</span><span class="p">)</span> <span class="c1"># implies category=None</span>
<span class="n">myobj2</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">&quot;foo&quot;</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">&quot;bar&quot;</span><span class="p">)</span>
@ -195,10 +161,11 @@ 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">&quot;foo&quot;</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">&quot;bar&quot;</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">&quot;bar&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></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">Object-</span></a>) tags:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="nd">@tag</span><span class="o">/</span><span class="n">search</span> <span class="n">furniture</span>
</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
</pre></div>
</div>
</section>
@ -207,17 +174,13 @@ mean that category is undefined, rather <code class="docutils literal notranslat
<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>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">boy</span><span class="o">.</span><span class="n">aliases</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;rascal&quot;</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">boy</span><span class="o">.</span><span class="n">aliases</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;rascal&quot;</span><span class="p">)</span>
<span class="n">boy</span><span class="o">.</span><span class="n">permissions</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;Builders&quot;</span><span class="p">)</span>
<span class="n">boy</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">&quot;Builders&quot;</span><span class="p">)</span>
<span class="n">all_aliases</span> <span class="o">=</span> <span class="n">boy</span><span class="o">.</span><span class="n">aliases</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
</pre></div>
</td></tr></table></div>
</div>
<p>and so on. Similarly to how <code class="docutils literal notranslate"><span class="pre">&#64;tag</span></code> works in-game, there is also the <code class="docutils literal notranslate"><span class="pre">&#64;perm</span></code> command for assigning
permissions and <code class="docutils literal notranslate"><span class="pre">&#64;alias</span></code> command for aliases.</p>
</section>
@ -230,7 +193,7 @@ making a new category. So think hard before deciding you really need to categori
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">Zone tutorial</span></a>.</p>
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>
@ -286,7 +249,7 @@ is found in the <a class="reference internal" href="../Concepts/Zones.html"><spa
<h3>Versions</h3>
<ul>
<li><a href="Tags.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,17 +40,17 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="tickerhandler">
<section class="tex2jax_ignore mathjax_ignore" id="tickerhandler">
<h1>TickerHandler<a class="headerlink" href="#tickerhandler" title="Permalink to this headline"></a></h1>
<p>One way to implement a dynamic MUD is by using “tickers”, also known as “heartbeats”. A ticker is a
timer that fires (ticks”) at a given interval. The tick triggers updates in various game systems.</p>
timer that fires (ticks”) at a given interval. The tick triggers updates in various game systems.</p>
<section id="about-tickers">
<h2>About Tickers<a class="headerlink" href="#about-tickers" title="Permalink to this headline"></a></h2>
<p>Tickers are very common or even unavoidable in other mud code bases. Certain code bases are even
hard-coded to rely on the concept of the global tick. Evennia has no such notion - the decision to
use tickers is very much up to the need of your game and which requirements you have. The “ticker
recipe” is just one way of cranking the wheels.</p>
<p>The most fine-grained way to manage the flow of time is of course to use <a class="reference internal" href="Scripts.html"><span class="doc">Scripts</span></a>. Many
<p>The most fine-grained way to manage the flow of time is of course to use <a class="reference internal" href="Scripts.html"><span class="doc std std-doc">Scripts</span></a>. Many
types of operations (weather being the classic example) are however done on multiple objects in the
same way at regular intervals, and for this, storing separate Scripts on each object is inefficient.
The way to do this is to use a ticker with a “subscription model” - let objects sign up to be
@ -60,79 +62,69 @@ then call this callable at an interval you specify, and with the arguments you s
it. This continues until the callable un-subscribes from the ticker. The handler survives a reboot
and is highly optimized in resource usage.</p>
<p>Here is an example of importing <code class="docutils literal notranslate"><span class="pre">TICKER_HANDLER</span></code> and using it:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># we assume that obj has a hook &quot;at_tick&quot; defined on itself</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># we assume that obj has a hook &quot;at_tick&quot; defined on itself</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">TICKER_HANDLER</span> <span class="k">as</span> <span class="n">tickerhandler</span>
<span class="n">tickerhandler</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">at_tick</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Thats it - from now on, <code class="docutils literal notranslate"><span class="pre">obj.at_tick()</span></code> will be called every 20 seconds.</p>
<p>You can also import function and tick that:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">TICKER_HANDLER</span> <span class="k">as</span> <span class="n">tickerhandler</span>
<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">TICKER_HANDLER</span> <span class="k">as</span> <span class="n">tickerhandler</span>
<span class="kn">from</span> <span class="nn">mymodule</span> <span class="kn">import</span> <span class="n">myfunc</span>
<span class="n">tickerhandler</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="mi">30</span><span class="p">,</span> <span class="n">myfunc</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Removing (stopping) the ticker works as expected:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">tickerhandler</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">at_tick</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">tickerhandler</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">at_tick</span><span class="p">)</span>
<span class="n">tickerhandler</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="mi">30</span><span class="p">,</span> <span class="n">myfunc</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Note that you have to also supply <code class="docutils literal notranslate"><span class="pre">interval</span></code> to identify which subscription to remove. This is
because the TickerHandler maintains a pool of tickers and a given callable can subscribe to be
ticked at any number of different intervals.</p>
<p>The full definition of the <code class="docutils literal notranslate"><span class="pre">tickerhandler.add</span></code> method is</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">tickerhandler</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">interval</span><span class="p">,</span> <span class="n">callback</span><span class="p">,</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">tickerhandler</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">interval</span><span class="p">,</span> <span class="n">callback</span><span class="p">,</span>
<span class="n">idstring</span><span class="o">=</span><span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="n">persistent</span><span class="o">=</span><span class="kc">True</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>
</td></tr></table></div>
</div>
<p>Here <code class="docutils literal notranslate"><span class="pre">*args</span></code> and <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> will be passed to <code class="docutils literal notranslate"><span class="pre">callback</span></code> every <code class="docutils literal notranslate"><span class="pre">interval</span></code> seconds. If <code class="docutils literal notranslate"><span class="pre">persistent</span></code>
is <code class="docutils literal notranslate"><span class="pre">False</span></code>, this subscription will not survive a server reload.</p>
<p>Tickers are identified and stored by making a key of the callable itself, the ticker-interval, the
<code class="docutils literal notranslate"><span class="pre">persistent</span></code> flag and the <code class="docutils literal notranslate"><span class="pre">idstring</span></code> (the latter being an empty string when not given explicitly).</p>
<p>Since the arguments are not included in the tickers identification, the <code class="docutils literal notranslate"><span class="pre">idstring</span></code> must be used to
have a specific callback triggered multiple times on the same interval but with different arguments:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">tickerhandler</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">update</span><span class="p">,</span> <span class="s2">&quot;ticker1&quot;</span><span class="p">,</span> <span class="kc">True</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">tickerhandler</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">update</span><span class="p">,</span> <span class="s2">&quot;ticker1&quot;</span><span class="p">,</span> <span class="kc">True</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
<span class="n">tickerhandler</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">update</span><span class="p">,</span> <span class="s2">&quot;ticker2&quot;</span><span class="p">,</span> <span class="kc">True</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<blockquote>
<div><p>Note that, when we want to send arguments to our callback within a ticker handler, we need to
specify <code class="docutils literal notranslate"><span class="pre">idstring</span></code> and <code class="docutils literal notranslate"><span class="pre">persistent</span></code> before, unless we call our arguments as keywords, which would
often be more readable:</p>
</div></blockquote>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">tickerhandler</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">update</span><span class="p">,</span> <span class="n">caller</span><span class="o">=</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="mi">118</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">tickerhandler</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">update</span><span class="p">,</span> <span class="n">caller</span><span class="o">=</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="mi">118</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>If you add a ticker with exactly the same combination of callback, interval and idstring, it will
overload the existing ticker. This identification is also crucial for later removing (stopping) the
subscription:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">tickerhandler</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">update</span><span class="p">,</span> <span class="n">idstring</span><span class="o">=</span><span class="s2">&quot;ticker1&quot;</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">tickerhandler</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">update</span><span class="p">,</span> <span class="n">idstring</span><span class="o">=</span><span class="s2">&quot;ticker1&quot;</span><span class="p">)</span>
<span class="n">tickerhandler</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">update</span><span class="p">,</span> <span class="n">idstring</span><span class="o">=</span><span class="s2">&quot;ticker2&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">callable</span></code> can be on any form as long as it accepts the arguments you give to send to it in
<code class="docutils literal notranslate"><span class="pre">TickerHandler.add</span></code>.</p>
<blockquote>
<div><p>Note that everything you supply to the TickerHandler will need to be pickled at some point to be
saved into the database. Most of the time the handler will correctly store things like database
objects, but the same restrictions as for <a class="reference internal" href="Attributes.html"><span class="doc">Attributes</span></a> apply to what the TickerHandler
objects, but the same restrictions as for <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attributes</span></a> apply to what the TickerHandler
may store.</p>
</div></blockquote>
<p>When testing, you can stop all tickers in the entire game with <code class="docutils literal notranslate"><span class="pre">tickerhandler.clear()</span></code>. You can also
view the currently subscribed objects with <code class="docutils literal notranslate"><span class="pre">tickerhandler.all()</span></code>.</p>
<p>See the <a class="reference internal" href="../Howto/Weather-Tutorial.html"><span class="doc">Weather Tutorial</span></a> for an example of using the TickerHandler.</p>
<p>See the <a class="reference internal" href="../Howto/Weather-Tutorial.html"><span class="doc std std-doc">Weather Tutorial</span></a> for an example of using the TickerHandler.</p>
<section id="when-not-to-use-tickerhandler">
<h3>When <em>not</em> to use TickerHandler<a class="headerlink" href="#when-not-to-use-tickerhandler" title="Permalink to this headline"></a></h3>
<p>Using the TickerHandler may sound very useful but it is important to consider when not to use it.
@ -213,7 +205,7 @@ same time without input from something else.</p>
<h3>Versions</h3>
<ul>
<li><a href="TickerHandler.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,13 +40,13 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="typeclasses">
<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 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">Accounts</span></a>, <a class="reference internal" href="Objects.html"><span class="doc">Objects</span></a>,
<a class="reference internal" href="Scripts.html"><span class="doc">Scripts</span></a> and <a class="reference external" href="Components/Communications.html#Channels">Channels</a> are all Python classes inheriting, at
<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>
@ -89,18 +91,16 @@ important limitations. This is why we dont simply call them “classes” but
<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 external" href="Components/Typeclasses.html#about-typeclass-properties">below</a>.</p></li>
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>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><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>
<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>
</pre></div>
</td></tr></table></div>
</div>
</li>
<li><p>A typeclass <code class="docutils literal notranslate"><span class="pre">__init__</span></code> method should normally not be overloaded. This has mostly to do with the
fact that the <code class="docutils literal notranslate"><span class="pre">__init__</span></code> method is not called in a predictable way. Instead Evennia suggest you use
@ -108,15 +108,12 @@ the <code class="docutils literal notranslate"><span class="pre">at_*_creation</
time the typeclass is saved to the database or the <code class="docutils literal notranslate"><span class="pre">at_init</span></code> hook which is called every time the
object is cached to memory. If you know what you are doing and want to use <code class="docutils literal notranslate"><span class="pre">__init__</span></code>, it <em>must</em>
both accept arbitrary keyword arguments and use <code class="docutils literal notranslate"><span class="pre">super</span></code> to call its parent::</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="c1"># my content</span>
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
<span class="c1"># my content</span>
</pre></div>
</td></tr></table></div>
</div>
</li>
</ol>
<p>Apart from this, a typeclass works like any normal Python class and you can
@ -126,76 +123,63 @@ treat it as such.</p>
<h2>Creating a new typeclass<a class="headerlink" href="#creating-a-new-typeclass" title="Permalink to this headline"></a></h2>
<p>Its 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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span></pre></div></td><td class="code"><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>
<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">class</span> <span class="nc">Furniture</span><span class="p">(</span><span class="n">DefaultObject</span><span class="p">):</span>
<span class="c1"># this defines what &#39;furniture&#39; is, like</span>
<span class="c1"># storing who sits on it or something.</span>
<span class="k">pass</span>
</pre></div>
</td></tr></table></div>
</div>
<p>You can now create a new <code class="docutils literal notranslate"><span class="pre">Furniture</span></code> object in two ways. First (and usually not the most
convenient) way is to create an instance of the class and then save it manually to the database:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">chair</span> <span class="o">=</span> <span class="n">Furniture</span><span class="p">(</span><span class="n">db_key</span><span class="o">=</span><span class="s2">&quot;Chair&quot;</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">chair</span> <span class="o">=</span> <span class="n">Furniture</span><span class="p">(</span><span class="n">db_key</span><span class="o">=</span><span class="s2">&quot;Chair&quot;</span><span class="p">)</span>
<span class="n">chair</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
</pre></div>
</td></tr></table></div>
</div>
<p>To use this you must give the database field names as keywords to the call. Which are available
depends on the entity you are creating, but all start with <code class="docutils literal notranslate"><span class="pre">db_*</span></code> in Evennia. This is a method you
may be familiar with if you know Django from before.</p>
<p>It is recommended that you instead use the <code class="docutils literal notranslate"><span class="pre">create_*</span></code> functions to create typeclassed entities:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><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>
<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">chair</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span><span class="n">Furniture</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">&quot;Chair&quot;</span><span class="p">)</span>
<span class="c1"># or (if your typeclass is in a module furniture.py)</span>
<span class="n">chair</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span><span class="s2">&quot;furniture.Furniture&quot;</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">&quot;Chair&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">create_object</span></code> (<code class="docutils literal notranslate"><span class="pre">create_account</span></code>, <code class="docutils literal notranslate"><span class="pre">create_script</span></code> etc) takes the typeclass as its first
argument; this can both be the actual class or the python path to the typeclass as found under your
game directory. So if your <code class="docutils literal notranslate"><span class="pre">Furniture</span></code> typeclass sits in <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/furniture.py</span></code>, you
could point to it as <code class="docutils literal notranslate"><span class="pre">typeclasses.furniture.Furniture</span></code>. Since Evennia will itself look in
<code class="docutils literal notranslate"><span class="pre">mygame/typeclasses</span></code>, you can shorten this even further to just <code class="docutils literal notranslate"><span class="pre">furniture.Furniture</span></code>. The create-
functions take a lot of extra keywords allowing you to set things like <a class="reference internal" href="Attributes.html"><span class="doc">Attributes</span></a> and
<a class="reference internal" href="Tags.html"><span class="doc">Tags</span></a> all in one go. These keywords dont use the <code class="docutils literal notranslate"><span class="pre">db_*</span></code> prefix. This will also automatically
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 dont 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 dont need to call <code class="docutils literal notranslate"><span class="pre">save()</span></code> explicitly.</p>
</section>
<section id="about-typeclass-properties">
<h3>About typeclass properties<a class="headerlink" href="#about-typeclass-properties" title="Permalink to this headline"></a></h3>
<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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><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">&quot;Table&quot;</span>
<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">&quot;Table&quot;</span>
<span class="n">chair</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
<span class="nb">print</span><span class="p">(</span><span class="n">chair</span><span class="o">.</span><span class="n">db_key</span><span class="p">)</span>
<span class="o">&lt;&lt;&lt;</span> <span class="n">Table</span>
</pre></div>
</td></tr></table></div>
</div>
<p>That is, we change the chair object to have the <code class="docutils literal notranslate"><span class="pre">db_key</span></code> “Table”, then save this to the database.
However, you almost never do things this way; Evennia defines property wrappers for all the database
fields. These are named the same as the field, but without the <code class="docutils literal notranslate"><span class="pre">db_</span></code> part:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">chair</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;Table&quot;</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">chair</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;Table&quot;</span>
<span class="nb">print</span><span class="p">(</span><span class="n">chair</span><span class="o">.</span><span class="n">key</span><span class="p">)</span>
<span class="o">&lt;&lt;&lt;</span> <span class="n">Table</span>
</pre></div>
</td></tr></table></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">key</span></code> wrapper is not only shorter to write, it will make sure to save the field for you, and
does so more efficiently by levering sql update mechanics under the hood. So whereas it is good to
be aware that the field is named <code class="docutils literal notranslate"><span class="pre">db_key</span></code> you should use <code class="docutils literal notranslate"><span class="pre">key</span></code> as much as you can.</p>
@ -215,98 +199,91 @@ returns the string form “#id”.</p></li>
</ul>
<p>The typeclassed entity has several common handlers:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">tags</span></code> - the <a class="reference internal" href="Tags.html"><span class="doc">TagHandler</span></a> that handles tagging. Use <code class="docutils literal notranslate"><span class="pre">tags.add()</span></code> , <code class="docutils literal notranslate"><span class="pre">tags.get()</span></code> etc.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">locks</span></code> - the <a class="reference internal" href="Locks.html"><span class="doc">LockHandler</span></a> that manages access restrictions. Use <code class="docutils literal notranslate"><span class="pre">locks.add()</span></code>,
<li><p><code class="docutils literal notranslate"><span class="pre">tags</span></code> - the <a class="reference internal" href="Tags.html"><span class="doc std std-doc">TagHandler</span></a> that handles tagging. Use <code class="docutils literal notranslate"><span class="pre">tags.add()</span></code> , <code class="docutils literal notranslate"><span class="pre">tags.get()</span></code> etc.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">locks</span></code> - the <a class="reference internal" href="Locks.html"><span class="doc std std-doc">LockHandler</span></a> that manages access restrictions. Use <code class="docutils literal notranslate"><span class="pre">locks.add()</span></code>,
<code class="docutils literal notranslate"><span class="pre">locks.get()</span></code> etc.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">attributes</span></code> - the <a class="reference internal" href="Attributes.html"><span class="doc">AttributeHandler</span></a> that manages Attributes on the object. Use
<li><p><code class="docutils literal notranslate"><span class="pre">attributes</span></code> - the <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">AttributeHandler</span></a> that manages Attributes on the object. Use
<code class="docutils literal notranslate"><span class="pre">attributes.add()</span></code>
etc.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">db</span></code> (DataBase) - a shortcut property to the AttributeHandler; allowing <code class="docutils literal notranslate"><span class="pre">obj.db.attrname</span> <span class="pre">=</span> <span class="pre">value</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">nattributes</span></code> - the <a class="reference internal" href="Attributes.html"><span class="doc">Non-persistent AttributeHandler</span></a> for attributes not saved in the
<li><p><code class="docutils literal notranslate"><span class="pre">nattributes</span></code> - the <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Non-persistent AttributeHandler</span></a> for attributes not saved in the
database.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">ndb</span></code> (NotDataBase) - a shortcut property to the Non-peristent AttributeHandler. Allows
<code class="docutils literal notranslate"><span class="pre">obj.ndb.attrname</span> <span class="pre">=</span> <span class="pre">value</span></code></p></li>
</ul>
<p>Each of the typeclassed entities then extend this list with their own properties. Go to the
respective pages for <a class="reference internal" href="Objects.html"><span class="doc">Objects</span></a>, <a class="reference internal" href="Scripts.html"><span class="doc">Scripts</span></a>, <a class="reference internal" href="Accounts.html"><span class="doc">Accounts</span></a> and
<a class="reference internal" href="Communications.html"><span class="doc">Channels</span></a> for more info. Its also recommended that you explore the available
entities using <a class="reference internal" href="../Evennia-API.html"><span class="doc">Evennias flat API</span></a> to explore which properties and methods they have
respective pages for <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> and
<a class="reference internal" href="Communications.html"><span class="doc std std-doc">Channels</span></a> for more info. Its also recommended that you explore the available
entities using <a class="reference internal" href="../Evennia-API.html"><span class="doc std std-doc">Evennias flat API</span></a> to explore which properties and methods they have
available.</p>
</section>
<section id="overloading-hooks">
<h3>Overloading hooks<a class="headerlink" href="#overloading-hooks" title="Permalink to this headline"></a></h3>
<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>
</section>
<section id="querying-for-typeclasses">
<h3>Querying for typeclasses<a class="headerlink" href="#querying-for-typeclasses" title="Permalink to this headline"></a></h3>
<h2>Querying for typeclasses<a class="headerlink" href="#querying-for-typeclasses" title="Permalink to this headline"></a></h2>
<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">Commands</span></a> or the search functions like <code class="docutils literal notranslate"><span class="pre">evennia.search_objects</span></code>.</p>
<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/">Djangos query
language</a>. This makes use of a <em>database
manager</em> that sits on all typeclasses, named <code class="docutils literal notranslate"><span class="pre">objects</span></code>. This manager holds methods that allow
database searches against that particular type of object (this is the way Django normally works
too). When using Django queries, you need to use the full field names (like <code class="docutils literal notranslate"><span class="pre">db_key</span></code>) to search:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">matches</span> <span class="o">=</span> <span class="n">Furniture</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">db_key</span><span class="o">=</span><span class="s2">&quot;Chair&quot;</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">matches</span> <span class="o">=</span> <span class="n">Furniture</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">db_key</span><span class="o">=</span><span class="s2">&quot;Chair&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>It is important that this will <em>only</em> find objects inheriting directly from <code class="docutils literal notranslate"><span class="pre">Furniture</span></code> in your
database. If there was a subclass of <code class="docutils literal notranslate"><span class="pre">Furniture</span></code> named <code class="docutils literal notranslate"><span class="pre">Sitables</span></code> you would not find any chairs
derived from <code class="docutils literal notranslate"><span class="pre">Sitables</span></code> with this query (this is not a Django feature but special to Evennia). To
find objects from subclasses Evennia instead makes the <code class="docutils literal notranslate"><span class="pre">get_family</span></code> and <code class="docutils literal notranslate"><span class="pre">filter_family</span></code> query
methods available:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># search for all furnitures and subclasses of furnitures</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># search for all furnitures and subclasses of furnitures</span>
<span class="c1"># whose names starts with &quot;Chair&quot;</span>
<span class="n">matches</span> <span class="o">=</span> <span class="n">Furniture</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter_family</span><span class="p">(</span><span class="n">db_key__startswith</span><span class="o">=</span><span class="s2">&quot;Chair&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>To make sure to search, say, all <code class="docutils literal notranslate"><span class="pre">Scripts</span></code> <em>regardless</em> of typeclass, you need to query from the
database model itself. So for Objects, this would be <code class="docutils literal notranslate"><span class="pre">ObjectDB</span></code> in the diagram above. Heres an
example for Scripts:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">ScriptDB</span>
<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">ScriptDB</span>
<span class="n">matches</span> <span class="o">=</span> <span class="n">ScriptDB</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">db_key__contains</span><span class="o">=</span><span class="s2">&quot;Combat&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>When querying from the database model parent you dont need to use <code class="docutils literal notranslate"><span class="pre">filter_family</span></code> or <code class="docutils literal notranslate"><span class="pre">get_family</span></code> -
you will always query all children on the database model.</p>
</section>
</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>
<section class="tex2jax_ignore mathjax_ignore" id="updating-existing-typeclass-instances">
<h1>Updating existing typeclass instances<a class="headerlink" href="#updating-existing-typeclass-instances" title="Permalink to this headline"></a></h1>
<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">Attributes</span></a>, <a class="reference internal" href="Tags.html"><span class="doc">Tags</span></a> etc, are
<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
not themselves embedded into the class and will <em>not</em> be updated automatically. This you need to
manage yourself, by searching for all relevant objects and updating or adding the data:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># add a worth Attribute to all existing Furniture</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># add a worth Attribute to all existing Furniture</span>
<span class="k">for</span> <span class="n">obj</span> <span class="ow">in</span> <span class="n">Furniture</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">all</span><span class="p">():</span>
<span class="c1"># this will loop over all Furniture instances</span>
<span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">worth</span> <span class="o">=</span> <span class="mi">100</span>
</pre></div>
</td></tr></table></div>
</div>
<p>A common use case is putting all Attributes in the <code class="docutils literal notranslate"><span class="pre">at_*_creation</span></code> hook of the entity, such as
<code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code> for <code class="docutils literal notranslate"><span class="pre">Objects</span></code>. This is called every time an object is created - and only then.
This is usually what you want but it does mean already existing objects wont get updated if you
change the contents of <code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code> later. You can fix this in a similar way as above
(manually setting each Attribute) or with something like this:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># Re-run at_object_creation only on those objects not having the new Attribute</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># Re-run at_object_creation only on those objects not having the new Attribute</span>
<span class="k">for</span> <span class="n">obj</span> <span class="ow">in</span> <span class="n">Furniture</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">all</span><span class="p">():</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">worth</span><span class="p">:</span>
<span class="n">obj</span><span class="o">.</span><span class="n">at_object_creation</span><span class="p">()</span>
</pre></div>
</td></tr></table></div>
</div>
<p>The above examples can be run in the command prompt created by <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">shell</span></code>. You could also run
it all in-game using <code class="docutils literal notranslate"><span class="pre">&#64;py</span></code>. That however requires you to put the code (including imports) as one
single line using <code class="docutils literal notranslate"><span class="pre">;</span></code> and <a class="reference external" href="http://www.secnetix.de/olli/Python/list_comprehensions.hawk">list
@ -318,7 +295,6 @@ line break, thats only for readability in the wiki):</p>
</div>
<p>It is recommended that you plan your game properly before starting to build, to avoid having to
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>
<p>If you want to swap an already existing typeclass, there are two ways to do so: From in-game and via
@ -336,22 +312,22 @@ already has - its a safety check to avoid user errors. This is usually used t
to re-run the creation hook on an existing class.</p></li>
</ul>
<p>In code you instead use the <code class="docutils literal notranslate"><span class="pre">swap_typeclass</span></code> method which you can find on all typeclassed entities:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">obj_to_change</span><span class="o">.</span><span class="n">swap_typeclass</span><span class="p">(</span><span class="n">new_typeclass_path</span><span class="p">,</span> <span class="n">clean_attributes</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">obj_to_change</span><span class="o">.</span><span class="n">swap_typeclass</span><span class="p">(</span><span class="n">new_typeclass_path</span><span class="p">,</span> <span class="n">clean_attributes</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">run_start_hooks</span><span class="o">=</span><span class="s2">&quot;all&quot;</span><span class="p">,</span> <span class="n">no_default</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">clean_cmdsets</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</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 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>
</section>
<section class="tex2jax_ignore mathjax_ignore" id="how-typeclasses-actually-work">
<h1>How typeclasses actually work<a class="headerlink" href="#how-typeclasses-actually-work" title="Permalink to this headline"></a></h1>
<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">Attributes</span></a> and <a class="reference internal" href="Tags.html"><span class="doc">Tags</span></a> but they are not typeclasses themselves). All the
<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 Djangos proxy model in various ways to allow them to work without any boiler plate
@ -359,7 +335,7 @@ database layout.</p>
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 id="caveats">
<h3>Caveats<a class="headerlink" href="#caveats" title="Permalink to this headline"></a></h3>
<h2>Caveats<a class="headerlink" href="#caveats" title="Permalink to this headline"></a></h2>
<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
@ -375,7 +351,6 @@ Due to typeclasses staying so long in memory, stale caches of such relationships
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>
@ -402,18 +377,18 @@ comments</a> for examples and solutions.</p>
<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="#creating-a-new-typeclass">Creating a new typeclass</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>
</ul>
</li>
<li><a class="reference internal" href="#updating-existing-typeclass-instances">Updating existing typeclass instances</a></li>
<li><a class="reference internal" href="#updating-existing-typeclass-instances">Updating existing typeclass instances</a><ul>
<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><ul>
<li><a class="reference internal" href="#caveats">Caveats</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>
</ul>
@ -438,7 +413,7 @@ comments</a> for examples and solutions.</p>
<h3>Versions</h3>
<ul>
<li><a href="Typeclasses.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,7 +40,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="evennia-rest-api">
<section class="tex2jax_ignore mathjax_ignore" id="evennia-rest-api">
<h1>Evennia REST API<a class="headerlink" href="#evennia-rest-api" title="Permalink to this headline"></a></h1>
<p>Evennia makes its database accessible via a REST API found on
<a class="reference external" href="http://localhost:4001/api">http://localhost:4001/api</a> if running locally with
@ -49,44 +51,44 @@ meant to be accessed in code, by other programs.</p>
<p>The API is using <a class="reference external" href="https://www.django-rest-framework.org/">Django Rest Framework</a>. This automates the process
of setting up <em>views</em> (Python code) to process the result of web requests.
The process of retrieving data is similar to that explained on the
<a class="reference internal" href="Webserver.html"><span class="doc">Webserver</span></a> page, except the views will here return <a class="reference external" href="https://en.wikipedia.org/wiki/JSON">JSON</a>
<a class="reference internal" href="Webserver.html"><span class="doc std std-doc">Webserver</span></a> page, except the views will here return <a class="reference external" href="https://en.wikipedia.org/wiki/JSON">JSON</a>
data for the resource you want. You can also <em>send</em> such JSON data
in order to update the database from the outside.</p>
<section id="usage">
<h2>Usage<a class="headerlink" href="#usage" title="Permalink to this headline"></a></h2>
<p>To activate the API, add this to your settings file.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">REST_API_ENABLED</span> <span class="o">=</span> <span class="kc">True</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>REST_API_ENABLED = True
</pre></div>
</div>
<p>The main controlling setting is <code class="docutils literal notranslate"><span class="pre">REST_FRAMEWORK</span></code>, which is a dict. The keys
<code class="docutils literal notranslate"><span class="pre">DEFAULT_LIST_PERMISSION</span></code> and <code class="docutils literal notranslate"><span class="pre">DEFAULT_CREATE_PERMISSIONS</span></code> control who may
view and create new objects via the api respectively. By default, users with
<a class="reference internal" href="Permissions.html"><span class="doc">Builder-level permission</span></a> or higher may access both actions.</p>
<a class="reference internal" href="Permissions.html"><span class="doc std std-doc">Builder-level permission</span></a> or higher may access both actions.</p>
<p>While the api is meant to be expanded upon, Evennia supplies several operations
out of the box. If you click the <code class="docutils literal notranslate"><span class="pre">Autodoc</span></code> button in the upper right of the <code class="docutils literal notranslate"><span class="pre">/api</span></code>
website youll get a fancy graphical presentation of the available endpoints.</p>
<p>Here is an example of calling the api in Python using the standard <code class="docutils literal notranslate"><span class="pre">requests</span></code> library.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">requests</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;https://www.mygame.com/api&quot;</span><span class="p">,</span> <span class="n">auth</span><span class="o">=</span><span class="p">(</span><span class="s2">&quot;MyUsername&quot;</span><span class="p">,</span> <span class="s2">&quot;password123&quot;</span><span class="p">))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
<span class="go">{&#39;accounts&#39;: &#39;http://www.mygame.com/api/accounts/&#39;,</span>
<span class="go"> &#39;objects&#39;: &#39;http://www.mygame.com/api/objects/&#39;,</span>
<span class="go">&#39;characters&#39;: &#39;http://www.mygame.comg/api/characters/&#39;,</span>
<span class="go">&#39;exits&#39;: &#39;http://www.mygame.com/api/exits/&#39;,</span>
<span class="go">&#39;rooms&#39;: &#39;http://www.mygame.com/api/rooms/&#39;,</span>
<span class="go">&#39;scripts&#39;: &#39;http://www.mygame.com/api/scripts/&#39;</span>
<span class="go">&#39;helpentries&#39;: &#39;http://www.mygame.com/api/helpentries/&#39; }</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt;&gt;&gt; import requests
&gt;&gt;&gt; response = requests.get(&quot;https://www.mygame.com/api&quot;, auth=(&quot;MyUsername&quot;, &quot;password123&quot;))
&gt;&gt;&gt; response.json()
{&#39;accounts&#39;: &#39;http://www.mygame.com/api/accounts/&#39;,
&#39;objects&#39;: &#39;http://www.mygame.com/api/objects/&#39;,
&#39;characters&#39;: &#39;http://www.mygame.comg/api/characters/&#39;,
&#39;exits&#39;: &#39;http://www.mygame.com/api/exits/&#39;,
&#39;rooms&#39;: &#39;http://www.mygame.com/api/rooms/&#39;,
&#39;scripts&#39;: &#39;http://www.mygame.com/api/scripts/&#39;
&#39;helpentries&#39;: &#39;http://www.mygame.com/api/helpentries/&#39; }
</pre></div>
</div>
<p>To list a specific type of object:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;https://www.mygame.com/api/objects&quot;</span><span class="p">,</span>
<span class="go"> auth=(&quot;Myusername&quot;, &quot;password123&quot;))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
<span class="go">{</span>
<span class="go">&quot;count&quot;: 125,</span>
<span class="go">&quot;next&quot;: &quot;https://www.mygame.com/api/objects/?limit=25&amp;offset=25&quot;,</span>
<span class="go">&quot;previous&quot;: null,</span>
<span class="go">&quot;results&quot; : [{&quot;db_key&quot;: &quot;A rusty longsword&quot;, &quot;id&quot;: 57, &quot;db_location&quot;: 213, ...}]}</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt;&gt;&gt; response = requests.get(&quot;https://www.mygame.com/api/objects&quot;,
auth=(&quot;Myusername&quot;, &quot;password123&quot;))
&gt;&gt;&gt; response.json()
{
&quot;count&quot;: 125,
&quot;next&quot;: &quot;https://www.mygame.com/api/objects/?limit=25&amp;offset=25&quot;,
&quot;previous&quot;: null,
&quot;results&quot; : [{&quot;db_key&quot;: &quot;A rusty longsword&quot;, &quot;id&quot;: 57, &quot;db_location&quot;: 213, ...}]}
</pre></div>
</div>
<p>In the above example, it now displays the objects inside the “results” array,
@ -97,21 +99,21 @@ parameters that can be added to the url to control the output.</p>
<p>Other query parameters can be defined as <a class="reference external" href="https://www.django-rest-framework.org/api-guide/filtering/#filtering">filters</a> which allow you to
further narrow the results. For example, to only get accounts with developer
permissions:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;https://www.mygame.com/api/accounts/?permission=developer&quot;</span><span class="p">,</span>
<span class="go"> auth=(&quot;MyUserName&quot;, &quot;password123&quot;))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
<span class="go">{</span>
<span class="go">&quot;count&quot;: 1,</span>
<span class="go">&quot;results&quot;: [{&quot;username&quot;: &quot;bob&quot;,...}]</span>
<span class="go">}</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt;&gt;&gt; response = requests.get(&quot;https://www.mygame.com/api/accounts/?permission=developer&quot;,
auth=(&quot;MyUserName&quot;, &quot;password123&quot;))
&gt;&gt;&gt; response.json()
{
&quot;count&quot;: 1,
&quot;results&quot;: [{&quot;username&quot;: &quot;bob&quot;,...}]
}
</pre></div>
</div>
<p>Now suppose that you want to use the API to create an <a class="reference internal" href="Objects.html"><span class="doc">Object</span></a>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">data</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;db_key&quot;</span><span class="p">:</span> <span class="s2">&quot;A shiny sword&quot;</span><span class="p">}</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="s2">&quot;https://www.mygame.com/api/objects&quot;</span><span class="p">,</span>
<span class="go"> data=data, auth=(&quot;Anotherusername&quot;, &quot;mypassword&quot;))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
<span class="go">{&quot;db_key&quot;: &quot;A shiny sword&quot;, &quot;id&quot;: 214, &quot;db_location&quot;: None, ...}</span>
<p>Now suppose that you want to use the API to create an <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Object</span></a>:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt;&gt;&gt; data = {&quot;db_key&quot;: &quot;A shiny sword&quot;}
&gt;&gt;&gt; response = requests.post(&quot;https://www.mygame.com/api/objects&quot;,
data=data, auth=(&quot;Anotherusername&quot;, &quot;mypassword&quot;))
&gt;&gt;&gt; response.json()
{&quot;db_key&quot;: &quot;A shiny sword&quot;, &quot;id&quot;: 214, &quot;db_location&quot;: None, ...}
</pre></div>
</div>
<p>Here we made a HTTP POST request to the <code class="docutils literal notranslate"><span class="pre">/api/objects</span></code> endpoint with the <code class="docutils literal notranslate"><span class="pre">db_key</span></code>
@ -119,11 +121,11 @@ we wanted. We got back info for the newly created object. You can now make
another request with PUT (replace everything) or PATCH (replace only what you
provide). By providing the id to the endpoint (<code class="docutils literal notranslate"><span class="pre">/api/objects/214</span></code>),
we make sure to update the right sword:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">data</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;db_key&quot;</span><span class="p">:</span> <span class="s2">&quot;An even SHINIER sword&quot;</span><span class="p">,</span> <span class="s2">&quot;db_location&quot;</span><span class="p">:</span> <span class="mi">50</span><span class="p">}</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="s2">&quot;https://www.mygame.com/api/objects/214&quot;</span><span class="p">,</span>
<span class="go"> data=data, auth=(&quot;Anotherusername&quot;, &quot;mypassword&quot;))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
<span class="go">{&quot;db_key&quot;: &quot;An even SHINIER sword&quot;, &quot;id&quot;: 214, &quot;db_location&quot;: 50, ...}</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt;&gt;&gt; data = {&quot;db_key&quot;: &quot;An even SHINIER sword&quot;, &quot;db_location&quot;: 50}
&gt;&gt;&gt; response = requests.put(&quot;https://www.mygame.com/api/objects/214&quot;,
data=data, auth=(&quot;Anotherusername&quot;, &quot;mypassword&quot;))
&gt;&gt;&gt; response.json()
{&quot;db_key&quot;: &quot;An even SHINIER sword&quot;, &quot;id&quot;: 214, &quot;db_location&quot;: 50, ...}
</pre></div>
</div>
<p>In most cases, you wont be making API requests to the backend with Python,
@ -137,7 +139,7 @@ the native <a class="reference external" href="https://developer.mozilla.org/en-
<p>Overall, reading up on <a class="reference external" href="https://www.django-rest-framework.org/api-guide/viewsets">Django Rest Framework ViewSets</a> and
other parts of their documentation is required for expanding and
customizing the API.</p>
<p>Check out the <a class="reference internal" href="Website.html"><span class="doc">Website</span></a> page for help on how to override code, templates
<p>Check out the <a class="reference internal" href="Website.html"><span class="doc std std-doc">Website</span></a> page for help on how to override code, templates
and static files.</p>
<ul class="simple">
<li><p>API templates (for the web-display) is located in <code class="docutils literal notranslate"><span class="pre">evennia/web/api/templates/rest_framework/</span></code> (it must
@ -146,7 +148,7 @@ be named such to allow override of the original REST framework templates).</p></
<li><p>The api code is located in <code class="docutils literal notranslate"><span class="pre">evennia/web/api/</span></code> - the <code class="docutils literal notranslate"><span class="pre">url.py</span></code> file here is responsible for
collecting all view-classes.</p></li>
</ul>
<p>Contrary to other web components, there is no pre-made urls.py set up for
<p>Contrary to other web components, there is no pre-made <a class="reference external" href="http://urls.py">urls.py</a> set up for
<code class="docutils literal notranslate"><span class="pre">mygame/web/api/</span></code>. This is because the registration of models with the api is
strongly integrated with the REST api functionality. Easiest is probably to
copy over <code class="docutils literal notranslate"><span class="pre">evennia/web/api/urls.py</span></code> and modify it in place.</p>
@ -202,7 +204,7 @@ copy over <code class="docutils literal notranslate"><span class="pre">evennia/w
<h3>Versions</h3>
<ul>
<li><a href="Web-API.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,7 +40,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="the-web-admin">
<section class="tex2jax_ignore mathjax_ignore" id="the-web-admin">
<h1>The Web Admin<a class="headerlink" href="#the-web-admin" title="Permalink to this headline"></a></h1>
<p>The Evennia <em>Web admin</em> is a customized <a class="reference external" href="https://docs.djangoproject.com/en/3.2/ref/contrib/admin/">Django admin site</a>
used for manipulating the game database using a graphical interface. You
@ -63,7 +65,7 @@ objects are actually stored as a <code class="docutils literal notranslate"><spa
<ol>
<li><p>Find the object you want to add to the Attribute. At the bottom of the first section
youll find the field <em>Serialized string</em>. This string shows a Python tuple like</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="s1">&#39;__packed_dbobj__&#39;</span><span class="p">,</span> <span class="p">(</span><span class="s1">&#39;objects&#39;</span><span class="p">,</span> <span class="s1">&#39;objectdb&#39;</span><span class="p">),</span> <span class="s1">&#39;2021:05:15-08:59:30:624660&#39;</span><span class="p">,</span> <span class="mi">358</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>(&#39;__packed_dbobj__&#39;, (&#39;objects&#39;, &#39;objectdb&#39;), &#39;2021:05:15-08:59:30:624660&#39;, 358)
</pre></div>
</div>
<p>Mark and copy this tuple-string to your clipboard exactly as it stands (parentheses and all).</p>
@ -128,7 +130,7 @@ link on the web page. The staff-status has no in-game equivalence.</p>
permissions to accounts. The superuser is the only permission level that is
also relevant in-game. <code class="docutils literal notranslate"><span class="pre">User</span> <span class="pre">Permissions</span></code> and <code class="docutils literal notranslate"><span class="pre">Groups</span></code> found on the <code class="docutils literal notranslate"><span class="pre">Account</span></code>
admin page <em>only</em> affects the admin - they have no connection to the in-game
<a class="reference internal" href="Permissions.html"><span class="doc">Permissions</span></a> (Player, Builder, Admin etc).</p>
<a class="reference internal" href="Permissions.html"><span class="doc std std-doc">Permissions</span></a> (Player, Builder, Admin etc).</p>
<p>For a staffer with <code class="docutils literal notranslate"><span class="pre">Staff</span> <span class="pre">status</span></code> to be able to actually do anything, the
superuser must grant at least some permissions for them on their Account. This
can also be good in order to limit mistakes. It can be a good idea to not allow
@ -140,11 +142,13 @@ access the admins content, try reloading the server.</p>
</div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>If a staff member has access to the in-game <code class="docutils literal notranslate"><span class="pre">py</span></code> command, they can just as
well have their admin <code class="docutils literal notranslate"><span class="pre">Superuser</span> <span class="pre">status</span></code> set too. The reason is that <code class="docutils literal notranslate"><span class="pre">py</span></code>
grants them all the power they need to set the <code class="docutils literal notranslate"><span class="pre">is_superuser</span></code> flag on their
account manually. There is a reason access to the <code class="docutils literal notranslate"><span class="pre">py</span></code> command must be
considered carefully …</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>If a staff member has access to the in-game ``py`` command, they can just as
well have their admin ``Superuser status`` set too. The reason is that ``py``
grants them all the power they need to set the ``is_superuser`` flag on their
account manually. There is a reason access to the ``py`` command must be
considered carefully ...
</pre></div>
</div>
</div>
</section>
<section id="customizing-the-web-admin">
@ -152,7 +156,7 @@ considered carefully …</p>
<p>Customizing the admin is a big topic and something beyond the scope of this
documentation. See the <a class="reference external" href="https://docs.djangoproject.com/en/3.2/ref/contrib/admin/">official Django docs</a> for
the details. This is just a brief summary.</p>
<p>See the <a class="reference internal" href="Website.html"><span class="doc">Website</span></a> page for an overview of the components going into
<p>See the <a class="reference internal" href="Website.html"><span class="doc std std-doc">Website</span></a> page for an overview of the components going into
generating a web page. The Django admin uses the same principle except that
Django provides a lot of tools to automate the admin-generation for us.</p>
<p>Admin templates are found in <code class="docutils literal notranslate"><span class="pre">evennia/web/templates/admin/</span></code> but youll find
@ -171,16 +175,7 @@ is found in <code class="docutils literal notranslate"><span class="pre">evennia
<h3>Change the title of the admin<a class="headerlink" href="#change-the-title-of-the-admin" title="Permalink to this headline"></a></h3>
<p>By default the admins title is <code class="docutils literal notranslate"><span class="pre">Evennia</span> <span class="pre">web</span> <span class="pre">admin</span></code>. To change this, add the
following to your <code class="docutils literal notranslate"><span class="pre">mygame/web/urls.py</span></code>:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in mygame/web/urls.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/web/urls.py</span>
<span class="c1"># ...</span>
@ -190,8 +185,9 @@ following to your <code class="docutils literal notranslate"><span class="pre">m
<span class="n">site</span><span class="o">.</span><span class="n">site_header</span> <span class="o">=</span> <span class="s2">&quot;My great game admin&quot;</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Reload the server and the admins title header will have changed.</p>
</section>
</section>
@ -255,7 +251,7 @@ following to your <code class="docutils literal notranslate"><span class="pre">m
<h3>Versions</h3>
<ul>
<li><a href="Web-Admin.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,7 +40,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="web-client">
<section class="tex2jax_ignore mathjax_ignore" id="web-client">
<h1>Web Client<a class="headerlink" href="#web-client" title="Permalink to this headline"></a></h1>
<p>Evennia comes with a MUD client accessible from a normal web browser. During development you can try
it at <code class="docutils literal notranslate"><span class="pre">http://localhost:4001/webclient</span></code>. The client consists of several parts, all under
@ -75,7 +77,7 @@ your browser cache, and see if your edit shows up.</strong></p>
<code class="docutils literal notranslate"><span class="pre">mygame/web/template_overrides/webclient/base.html</span></code> and editing it to add your new plugin.</p>
</section>
</section>
<section id="evennia-web-client-api-from-evennia-js">
<section class="tex2jax_ignore mathjax_ignore" id="evennia-web-client-api-from-evennia-js">
<h1>Evennia Web Client API (from evennia.js)<a class="headerlink" href="#evennia-web-client-api-from-evennia-js" title="Permalink to this headline"></a></h1>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">Evennia.init(</span> <span class="pre">opts</span> <span class="pre">)</span></code></p></li>
@ -86,7 +88,7 @@ your browser cache, and see if your edit shows up.</strong></p>
<li><p><code class="docutils literal notranslate"><span class="pre">log()</span></code></p></li>
</ul>
</section>
<section id="plugin-manager-api-from-webclient-gui-js">
<section class="tex2jax_ignore mathjax_ignore" id="plugin-manager-api-from-webclient-gui-js">
<h1>Plugin Manager API (from webclient_gui.js)<a class="headerlink" href="#plugin-manager-api-from-webclient-gui-js" title="Permalink to this headline"></a></h1>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">options</span></code> Object, Stores key/value state that can be used by plugins to coordinate behavior.</p></li>
@ -99,7 +101,7 @@ your browser cache, and see if your edit shows up.</strong></p>
</li>
</ul>
</section>
<section id="plugin-callbacks-api">
<section class="tex2jax_ignore mathjax_ignore" id="plugin-callbacks-api">
<h1>Plugin callbacks API<a class="headerlink" href="#plugin-callbacks-api" title="Permalink to this headline"></a></h1>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">init()</span></code> The only required callback</p></li>
@ -123,7 +125,7 @@ their callback for this event called. This enables things like the up/down arro
history.js plugin to always occur before the default_in.js plugin adds that key to the current input
buffer.</p>
</section>
<section id="example-default-plugins-plugins-js">
<section class="tex2jax_ignore mathjax_ignore" id="example-default-plugins-plugins-js">
<h1>Example/Default Plugins (plugins/*.js)<a class="headerlink" href="#example-default-plugins-plugins-js" title="Permalink to this headline"></a></h1>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">clienthelp.js</span></code> Defines onOptionsUI from the options2 plugin. This is a mostly empty plugin to
@ -158,7 +160,7 @@ while the tab is hidden.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">popups.js</span></code> Provides default popups/Dialog UI for other plugins to use.</p></li>
</ul>
</section>
<section id="writing-your-own-plugins">
<section class="tex2jax_ignore mathjax_ignore" id="writing-your-own-plugins">
<h1>Writing your own Plugins<a class="headerlink" href="#writing-your-own-plugins" title="Permalink to this headline"></a></h1>
<p>So, you love the functionality of the webclient, but your game has specific
types of text that need to be separated out into their own space, visually.
@ -348,7 +350,7 @@ window.plugin_handler.add(&quot;myplugin&quot;, myplugin);
<h3>Versions</h3>
<ul>
<li><a href="Webclient.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,29 +40,29 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="webserver">
<section class="tex2jax_ignore mathjax_ignore" id="webserver">
<h1>Webserver<a class="headerlink" href="#webserver" title="Permalink to this headline"></a></h1>
<p>When Evennia starts it also spins up its own Twisted-based web server. The
webserver is responsible for serving the html pages of the games website. It
can also serve static resources like images and music.</p>
<p>The webclient runs as part of the <a class="reference internal" href="Portal-And-Server.html"><span class="doc">Server</span></a> process of
<p>The webclient runs as part of the <a class="reference internal" href="Portal-And-Server.html"><span class="doc std std-doc">Server</span></a> process of
Evennia. This means that it can directly access cached objects modified
in-game, and there is no risk of working with objects that are temporarily
out-of-sync in the database.</p>
<p>The webserver runs on Twisted and is meant to be used in a production
environment. It leverages the Django web framework and provides:</p>
<ul class="simple">
<li><p>A <a class="reference internal" href="Website.html"><span class="doc">Game Website</span></a> - this is what you see when you go to
<li><p>A <a class="reference internal" href="Website.html"><span class="doc std std-doc">Game Website</span></a> - this is what you see when you go to
<code class="docutils literal notranslate"><span class="pre">localhost:4001</span></code>. The look of the website is meant to be customized to your
game. Users logged into the website will be auto-logged into the game if they
do so with the webclient since they share the same login credentials (there
is no way to safely do auto-login with telnet clients).</p></li>
<li><p>The <a class="reference internal" href="Web-Admin.html"><span class="doc">Web Admin</span></a> is based on the Django web admin and allows you to
<li><p>The <a class="reference internal" href="Web-Admin.html"><span class="doc std std-doc">Web Admin</span></a> is based on the Django web admin and allows you to
edit the game database in a graphical interface.</p></li>
<li><p>The <a class="reference internal" href="Webclient.html"><span class="doc">Webclient</span></a> page is served by the webserver, but the actual
<li><p>The <a class="reference internal" href="Webclient.html"><span class="doc std std-doc">Webclient</span></a> page is served by the webserver, but the actual
game communication (sending/receiving data) is done by the javascript client
on the page opening a websocket connection directly to Evennias Portal.</p></li>
<li><p>The <a class="reference internal" href="Web-API.html"><span class="doc">Evennia REST-API</span></a> allows for accessing the database from outside the game
<li><p>The <a class="reference internal" href="Web-API.html"><span class="doc std std-doc">Evennia REST-API</span></a> allows for accessing the database from outside the game
(only if `REST_API_ENABLED=True).</p></li>
</ul>
<section id="basic-webserver-data-flow">
@ -99,7 +101,7 @@ browsers understand). Executing Javascript is something the web browser does,
it operates independently from Evennia. Small snippets of javascript can be
used on a page to have buttons react, make small animations etc that doesnt
require the server.</p>
<p>In the case of the <a class="reference internal" href="Webclient.html"><span class="doc">Webclient</span></a>, Evennia will load the Webclient page
<p>In the case of the <a class="reference internal" href="Webclient.html"><span class="doc std std-doc">Webclient</span></a>, Evennia will load the Webclient page
as above, but the page then initiates Javascript code (a lot of it) responsible
for actually displaying the client GUI, allows you to resize windows etc.</p>
<p>After it starts, the webclient calls home and spins up a
@ -162,7 +164,7 @@ come back or you reload it manually in your browser.</p>
<h3>Versions</h3>
<ul>
<li><a href="Webserver.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,16 +40,16 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="game-website">
<section class="tex2jax_ignore mathjax_ignore" id="game-website">
<h1>Game website<a class="headerlink" href="#game-website" title="Permalink to this headline"></a></h1>
<p>When Evennia starts it will also start a <a class="reference internal" href="Webserver.html"><span class="doc">Webserver</span></a> as part of the
<a class="reference internal" href="Portal-And-Server.html"><span class="doc">Server</span></a> process. This uses <a class="reference external" href="https://docs.djangoproject.com">Django</a>
<p>When Evennia starts it will also start a <a class="reference internal" href="Webserver.html"><span class="doc std std-doc">Webserver</span></a> as part of the
<a class="reference internal" href="Portal-And-Server.html"><span class="doc std std-doc">Server</span></a> process. This uses <a class="reference external" href="https://docs.djangoproject.com">Django</a>
to present a simple but functional default game website. With the default setup,
open your browser to <a class="reference external" href="http://localhost:4001">localhost:4001</a> or <a class="reference external" href="http://127.0.0.1:4001">127.0.0.1:4001</a>
to see it.</p>
<p>The website allows existing players to log in using an account-name and
password they previously used to register with the game. If a user logs in with
the <a class="reference internal" href="Webclient.html"><span class="doc">Webclient</span></a> they will also log into the website and vice-versa.
the <a class="reference internal" href="Webclient.html"><span class="doc std std-doc">Webclient</span></a> they will also log into the website and vice-versa.
So if you are logged into the website, opening the webclient will automatically
log you into the game as that account.</p>
<p>The default website shows a “Welcome!” page with a few links to useful
@ -66,11 +68,11 @@ users.</p></li>
show a list of all channels available to you and allow you to view the latest
discussions. Most channels require logging in, but the <code class="docutils literal notranslate"><span class="pre">Public</span></code> channel can
also be viewed by non-loggedin users.</p></li>
<li><p><em>Help</em> - This ties the in-game <a class="reference internal" href="Help-System.html"><span class="doc">Help system</span></a> to the website. All
<li><p><em>Help</em> - This ties the in-game <a class="reference internal" href="Help-System.html"><span class="doc std std-doc">Help system</span></a> to the website. All
database-based help entries that are publicly available or accessible to your
account can be read. This is a good way to present a body of help for people
to read outside of the game.</p></li>
<li><p><em>Play Online</em> - This opens the <a class="reference internal" href="Webclient.html"><span class="doc">Webclient</span></a> in the browser.</p></li>
<li><p><em>Play Online</em> - This opens the <a class="reference internal" href="Webclient.html"><span class="doc std std-doc">Webclient</span></a> in the browser.</p></li>
<li><p><em>Admin</em> The [Web admin](Web admin) will only show if you are logged in.</p></li>
<li><p><em>Log in/out</em> - Allows you to authenticate using the same credentials you use
in the game.</p></li>
@ -90,7 +92,7 @@ in your browser instead of generic 404 or 500 error pages. Just remember that
DEBUG mode leaks memory (for retaining debug info) and is <em>not</em> safe to use
for a production game!</p>
</div></blockquote>
<p>As explained on the <a class="reference internal" href="Webserver.html"><span class="doc">Webserver</span></a> page, the process for getting a web
<p>As explained on the <a class="reference internal" href="Webserver.html"><span class="doc std std-doc">Webserver</span></a> page, the process for getting a web
page is</p>
<ol class="simple">
<li><p>Web browser sends HTTP request to server with an URL</p></li>
@ -124,6 +126,7 @@ structure (leaving out stuff not relevant to the website):</p>
<span class="p">(</span><span class="n">python</span> <span class="n">files</span> <span class="n">related</span> <span class="n">to</span> <span class="n">website</span><span class="p">)</span>
<span class="n">urls</span><span class="o">.</span><span class="n">py</span>
</pre></div>
</div>
<p>The top-level <code class="docutils literal notranslate"><span class="pre">web/urls.py</span></code> file includes the <code class="docutils literal notranslate"><span class="pre">web/website/urls.py</span></code> file -
@ -144,13 +147,14 @@ that way all the website-related url-handling is kept in the same place.</p>
<span class="n">views</span><span class="o">/</span>
<span class="n">urls</span><span class="o">.</span><span class="n">py</span>
</pre></div>
</div>
<div class="versionchanged">
<p><span class="versionmodified changed">Changed in version 1.0: </span>Game folders created with older versions of Evennia will lack most of this
convenient <cite>mygame/web/</cite> layout. If you use a game dir from an older version,
you should copy over the missing <cite>evennia/game_template/web/</cite> folders from
there, as well as the main urls.py file.</p>
convenient <code class="docutils literal notranslate"><span class="pre">mygame/web/</span></code> layout. If you use a game dir from an older version,
you should copy over the missing <code class="docutils literal notranslate"><span class="pre">evennia/game_template/web/</span></code> folders from
there, as well as the main <a class="reference external" href="http://urls.py">urls.py</a> file.</p>
</div>
<p>As you can see, the <code class="docutils literal notranslate"><span class="pre">mygame/web/</span></code> folder is a copy of the <code class="docutils literal notranslate"><span class="pre">evennia/web/</span></code> folder
structure except the <code class="docutils literal notranslate"><span class="pre">mygame</span></code> folders are mostly empty.</p>
@ -176,8 +180,8 @@ So these examples only serve as a first primer to get you started.</p>
<p>The websites title and blurb are simply changed by tweaking
<code class="docutils literal notranslate"><span class="pre">settings.SERVERNAME</span></code> and <code class="docutils literal notranslate"><span class="pre">settings.GAME_SLOGAN</span></code>. Your settings file is in
<code class="docutils literal notranslate"><span class="pre">mygame/server/conf/settings.py</span></code>, just set/add</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">SERVERNAME</span> <span class="o">=</span> <span class="s2">&quot;My Awesome Game&quot;</span>
<span class="n">GAME_SLOGAN</span> <span class="o">=</span> <span class="s2">&quot;The best game in the world&quot;</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>SERVERNAME = &quot;My Awesome Game&quot;
GAME_SLOGAN = &quot;The best game in the world&quot;
</pre></div>
</div>
</section>
@ -241,7 +245,7 @@ be easier to revert your changes if you only add things to <code class="docutils
Modify it and reload the server to see your changes.</p>
<p>You can also apply static files without reloading, but running this in the
terminal:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">evennia</span> <span class="n">collectstatic</span> <span class="o">--</span><span class="n">no</span><span class="o">-</span><span class="nb">input</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia collectstatic --no-input
</pre></div>
</div>
<p>(this is run automatically when reloading the server).</p>
@ -251,13 +255,7 @@ browser without cache (Ctrl-F5 in Firefox, for example).</p>
</div></blockquote>
<p>As an example, add/copy <code class="docutils literal notranslate"><span class="pre">custom.css</span></code> to <code class="docutils literal notranslate"><span class="pre">mygame/web/static/website/css/</span></code> and
add the following:</p>
<div class="highlight-css notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="p">.</span><span class="nc">navbar</span> <span class="p">{</span>
<div class="highlight-css notranslate"><div class="highlight"><pre><span></span><span class="p">.</span><span class="nc">navbar</span> <span class="p">{</span>
<span class="k">background-color</span><span class="p">:</span> <span class="mh">#7a3d54</span><span class="p">;</span>
<span class="p">}</span>
@ -265,7 +263,7 @@ add the following:</p>
<span class="k">background-color</span><span class="p">:</span> <span class="mh">#7a3d54</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Reload and your website now has a red theme!</p>
<blockquote>
<div><p>Hint: Learn to use your web browsers <a class="reference external" href="https://torquemag.io/2020/06/browser-developer-tools-tutorial/">Developer tools</a>.
@ -277,35 +275,21 @@ the .css file only when you want to make the changes permanent.</p>
<h3>Change front page functionality<a class="headerlink" href="#change-front-page-functionality" title="Permalink to this headline"></a></h3>
<p>The logic is all in the view. To find where the index-page view is found, we
look in <code class="docutils literal notranslate"><span class="pre">evennia/web/website/urls.py</span></code>. Here we find the following line:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in evennia/web/website/urls.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in evennia/web/website/urls.py</span>
<span class="o">...</span>
<span class="c1"># website front page</span>
<span class="n">path</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="n">index</span><span class="o">.</span><span class="n">EvenniaIndexView</span><span class="o">.</span><span class="n">as_view</span><span class="p">(),</span> <span class="n">name</span><span class="o">=</span><span class="s2">&quot;index&quot;</span><span class="p">),</span>
<span class="o">...</span>
</pre></div>
</td></tr></table></div>
</div>
<p>The first <code class="docutils literal notranslate"><span class="pre">&quot;&quot;</span></code> is the empty url - root - what you get if you just enter <code class="docutils literal notranslate"><span class="pre">localhost:4001/</span></code>
with no extra path. As expected, this leads to the index page. By looking at the imports
we find the view is in in <code class="docutils literal notranslate"><span class="pre">evennia/web/website/views/index.py</span></code>.</p>
<p>Copy this file to the corresponding location in <code class="docutils literal notranslate"><span class="pre">mygame/web</span></code>. Then tweak your <code class="docutils literal notranslate"><span class="pre">mygame/web/website/urls.py</span></code>
file to point to the new file:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in mygame/web/website/urls.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/web/website/urls.py</span>
<span class="c1"># ...</span>
@ -316,8 +300,9 @@ file to point to the new file:</p>
<span class="p">]</span>
<span class="c1"># ...</span>
</pre></div>
</td></tr></table></div>
</div>
<p>So we just import <code class="docutils literal notranslate"><span class="pre">index</span></code> from the new location and point to it. After a reload
the front page will now redirect to use your copy rather than the original.</p>
<p>The frontpage view is a class <code class="docutils literal notranslate"><span class="pre">EvenniaIndexView</span></code>. This is a <a class="reference external" href="https://docs.djangoproject.com/en/3.2/topics/class-based-views/">Django class-based view</a>.
@ -344,7 +329,7 @@ your copy. Just remember to reload.</p>
<section id="using-flat-pages">
<h3>Using Flat Pages<a class="headerlink" href="#using-flat-pages" title="Permalink to this headline"></a></h3>
<p>The absolutely simplest way to add a new web page is to use the <code class="docutils literal notranslate"><span class="pre">Flat</span> <span class="pre">Pages</span></code>
app available in the <a class="reference internal" href="Web-Admin.html"><span class="doc">Web Admin</span></a>. The page will appear with the same
app available in the <a class="reference internal" href="Web-Admin.html"><span class="doc std std-doc">Web Admin</span></a>. The page will appear with the same
styling as the rest of the site.</p>
<p>For the <code class="docutils literal notranslate"><span class="pre">Flat</span> <span class="pre">pages</span></code> module to work you must first set up a <em>Site</em> (or
domain) to use. You only need to this once.</p>
@ -380,33 +365,19 @@ get the same styling as the rest of your site.</p></li>
<li><p>Add a new view <code class="docutils literal notranslate"><span class="pre">testview.py</span></code> under <code class="docutils literal notranslate"><span class="pre">mygame/web/website/views/</span></code> (dont name it <code class="docutils literal notranslate"><span class="pre">test.py</span></code> or
Django/Evennia will think it contains unit tests). Add a view there to process
your page. This is a minimal view to start from (read much more <a class="reference external" href="https://docs.djangoproject.com/en/3.2/topics/class-based-views/">in the Django docs</a>):</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># mygame/web/website/views/testview.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># mygame/web/website/views/testview.py</span>
<span class="kn">from</span> <span class="nn">django.views.generic</span> <span class="kn">import</span> <span class="n">TemplateView</span>
<span class="k">class</span> <span class="nc">MyTestView</span><span class="p">(</span><span class="n">TemplateView</span><span class="p">):</span>
<span class="n">template_name</span> <span class="o">=</span> <span class="s2">&quot;website/test.html&quot;</span>
</pre></div>
</td></tr></table></div>
</div>
</li>
<li><p>Finally, point to your view from the <code class="docutils literal notranslate"><span class="pre">mygame/web/website/urls.py</span></code>:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in mygame/web/website/urls.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/web/website/urls.py</span>
<span class="c1"># ...</span>
<span class="kn">from</span> <span class="nn">web.website.views</span> <span class="kn">import</span> <span class="n">testview</span>
@ -416,8 +387,9 @@ your page. This is a minimal view to start from (read much more <a class="refere
<span class="c1"># we can skip the initial / here</span>
<span class="n">path</span><span class="p">(</span><span class="s2">&quot;test/&quot;</span><span class="p">,</span> <span class="n">testview</span><span class="o">.</span><span class="n">MyTestView</span><span class="o">.</span><span class="n">as_view</span><span class="p">())</span>
<span class="p">]</span>
</pre></div>
</td></tr></table></div>
</div>
</li>
<li><p>Reload the server and your new page is available. You can now continue to add
all sorts of advanced dynamic content through your view and template!</p></li>
@ -513,7 +485,7 @@ on the Django website - it covers all you need.</p>
<h3>Versions</h3>
<ul>
<li><a href="Website.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>