mirror of
https://github.com/evennia/evennia.git
synced 2026-04-05 15:37:17 +02:00
Updated HTML docs
This commit is contained in:
parent
a551188691
commit
781788f2e5
2063 changed files with 215958 additions and 250783 deletions
212
docs/1.0-dev/Components/Accounts.html
Normal file
212
docs/1.0-dev/Components/Accounts.html
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Accounts — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Accounts</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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
|
||||
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>
|
||||
<p>Exactly how many Sessions can interact with an Account and its Puppets at once is determined by
|
||||
Evennia’s <a class="reference external" href="Components/Sessions.html#Multisession-mode">MULTISESSION_MODE</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
|
||||
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>
|
||||
<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
|
||||
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
|
||||
permissions on the Account level - this will overrule permissions set on the Character level. For
|
||||
the permissions of the Character to come into play the default <code class="docutils literal notranslate"><span class="pre">quell</span></code> command can be used. This
|
||||
allows for exploring the game using a different permission set (but you can’t escalate your
|
||||
permissions this way - for hierarchical permissions like <code class="docutils literal notranslate"><span class="pre">Builder</span></code>, <code class="docutils literal notranslate"><span class="pre">Admin</span></code> etc, the <em>lower</em> of the
|
||||
permissions on the Character/Account will always be used).</p>
|
||||
<div class="section" id="how-to-create-your-own-account-types">
|
||||
<h2>How to create your own Account types<a class="headerlink" href="#how-to-create-your-own-account-types" title="Permalink to this headline">¶</a></h2>
|
||||
<p>You will usually not want more than one Account typeclass for all new accounts (but you could in
|
||||
principle create a system that changes an account’s typeclass dynamically).</p>
|
||||
<p>An Evennia Account is, per definition, a Python class that includes <code class="docutils literal notranslate"><span class="pre">evennia.DefaultAccount</span></code> among
|
||||
its parents. In <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/accounts.py</span></code> there is an empty class ready for you to modify.
|
||||
Evennia defaults to using this (it inherits directly from <code class="docutils literal notranslate"><span class="pre">DefaultAccount</span></code>).</p>
|
||||
<p>Here’s an example of modifying the default Account class in code:</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12</pre></div></td><td class="code"><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>
|
||||
|
||||
<span class="k">class</span> <span class="nc">Account</span><span class="p">(</span><span class="n">DefaultAccount</span><span class="p">):</span> <span class="c1"># [...]</span>
|
||||
|
||||
<span class="n">at_account_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="s2">"this is called only once, when account is first created"</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">real_name</span> <span class="o">=</span> <span class="bp">None</span> <span class="c1"># this is set later self.db.real_address = None # "</span>
|
||||
<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="bp">True</span> <span class="c1"># default config self.db.config_2 = False # "</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"># "</span>
|
||||
|
||||
<span class="c1"># ... whatever else our game needs to know ``` Reload the server with `reload`. </span>
|
||||
</pre></div>
|
||||
</td></tr></table></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 won’t 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
|
||||
(any new Accounts that connect will see them though). To update yourself you need to make sure to
|
||||
re-fire the hook on all the Accounts you have already created. Here is an example of how to do this
|
||||
using <code class="docutils literal notranslate"><span class="pre">py</span></code>:</p>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">py</span> <span class="pre">[account.at_account_creation()</span> <span class="pre">for</span> <span class="pre">account</span> <span class="pre">in</span> <span class="pre">evennia.managers.accounts.all()]</span></code></p>
|
||||
<p>You should now see the Attributes on yourself.</p>
|
||||
<blockquote>
|
||||
<div><p>If you wanted Evennia to default to a completely <em>different</em> Account class located elsewhere, you
|
||||
must point Evennia to it. Add <code class="docutils literal notranslate"><span class="pre">BASE_ACCOUNT_TYPECLASS</span></code> to your settings file, and give the python
|
||||
path to your custom class as its value. By default this points to <code class="docutils literal notranslate"><span class="pre">typeclasses.accounts.Account</span></code>,
|
||||
the empty template we used above.</p>
|
||||
</div></blockquote>
|
||||
</div>
|
||||
<div class="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
|
||||
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>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">obj</span></code> - an alias for <code class="docutils literal notranslate"><span class="pre">character</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">name</span></code> - an alias for <code class="docutils literal notranslate"><span class="pre">user.username</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">sessions</span></code> - an instance of
|
||||
<a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia.objects.objects#objectsessionhandler">ObjectSessionHandler</a>
|
||||
managing all connected Sessions (physical connections) this object listens to (Note: In older
|
||||
versions of Evennia, this was a list). The so-called <code class="docutils literal notranslate"><span class="pre">session-id</span></code> (used in many places) is found
|
||||
as
|
||||
a property <code class="docutils literal notranslate"><span class="pre">sessid</span></code> on each Session instance.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">is_superuser</span></code> (bool: True/False) - if this account is a superuser.</p></li>
|
||||
</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
|
||||
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.
|
||||
For Accounts, nicks are primarily used to store custom aliases for
|
||||
<a class="reference external" href="Components/Communications.html#Channels">Channels</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">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">get_puppet</span></code> - get a currently puppeted object connected to the Account and a given session id, if
|
||||
any.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">puppet_object</span></code> - connect a session to a puppetable Object.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">unpuppet_object</span></code> - disconnect a session from a puppetable Object.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">msg</span></code> - send text to the Account</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">execute_cmd</span></code> - runs a command as if this Account did it.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">search</span></code> - search for Accounts.</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Accounts</a><ul>
|
||||
<li><a class="reference internal" href="#how-to-create-your-own-account-types">How to create your own Account types</a></li>
|
||||
<li><a class="reference internal" href="#properties-on-accounts">Properties on Accounts</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/Accounts.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Accounts.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Accounts</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
541
docs/1.0-dev/Components/Attributes.html
Normal file
541
docs/1.0-dev/Components/Attributes.html
Normal file
|
|
@ -0,0 +1,541 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Attributes — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Attributes</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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
|
||||
combattant’s 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.
|
||||
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 couldn’t 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>
|
||||
<div class="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. Let’s
|
||||
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>1
|
||||
2
|
||||
3
|
||||
4</pre></div></td><td class="code"><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="bp">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>
|
||||
<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>1
|
||||
2
|
||||
3
|
||||
4</pre></div></td><td class="code"><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="bp">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>
|
||||
<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
|
||||
use <code class="docutils literal notranslate"><span class="pre">ndb</span></code> to store data rather than to just store variables direct on entities - <code class="docutils literal notranslate"><span class="pre">ndb</span></code>-stored data
|
||||
is tracked by the server and will not be purged in various cache-cleanup operations Evennia may do
|
||||
while it runs. Data stored on <code class="docutils literal notranslate"><span class="pre">ndb</span></code> (as well as <code class="docutils literal notranslate"><span class="pre">db</span></code>) will also be easily listed by example the
|
||||
<code class="docutils literal notranslate"><span class="pre">@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>1</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>
|
||||
</pre></div>
|
||||
</td></tr></table></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>1
|
||||
2</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>
|
||||
<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>
|
||||
<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>
|
||||
</div>
|
||||
<div class="section" id="the-attributehandler">
|
||||
<h2>The AttributeHandler<a class="headerlink" href="#the-attributehandler" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">.db</span></code> and <code class="docutils literal notranslate"><span class="pre">.ndb</span></code> properties are very convenient but if you don’t know the name of the Attribute
|
||||
beforehand they cannot be used. Behind the scenes <code class="docutils literal notranslate"><span class="pre">.db</span></code> actually accesses the <code class="docutils literal notranslate"><span class="pre">AttributeHandler</span></code>
|
||||
which sits on typeclassed entities as the <code class="docutils literal notranslate"><span class="pre">.attributes</span></code> property. <code class="docutils literal notranslate"><span class="pre">.ndb</span></code> does the same for the
|
||||
<code class="docutils literal notranslate"><span class="pre">.nattributes</span></code> property.</p>
|
||||
<p>The handlers have normal access methods that allow you to manage and retrieve <code class="docutils literal notranslate"><span class="pre">Attributes</span></code> and
|
||||
<code class="docutils literal notranslate"><span class="pre">NAttributes</span></code>:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">has('attrname')</span></code> - this checks if the object has an Attribute with this key. This is equivalent
|
||||
to doing <code class="docutils literal notranslate"><span class="pre">obj.db.attrname</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">get(...)</span></code> - this retrieves the given Attribute. Normally the <code class="docutils literal notranslate"><span class="pre">value</span></code> property of the Attribute is
|
||||
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
|
||||
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
|
||||
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>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8</pre></div></td><td class="code"><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">"MyObject"</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">"test"</span><span class="p">,</span> <span class="s2">"testvalue"</span><span class="p">)</span>
|
||||
<span class="k">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">test</span><span class="p">)</span> <span class="c1"># prints "testvalue"</span>
|
||||
<span class="k">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">get</span><span class="p">(</span><span class="s2">"test"</span><span class="p">))</span> <span class="c1"># "</span>
|
||||
<span class="k">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 [<AttributeObject>]</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">"test"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
</div>
|
||||
<div class="section" id="properties-of-attributes">
|
||||
<h2>Properties of Attributes<a class="headerlink" href="#properties-of-attributes" title="Permalink to this headline">¶</a></h2>
|
||||
<p>An Attribute object is stored in the database. It has the following properties:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">key</span></code> - the name of the Attribute. When doing e.g. <code class="docutils literal notranslate"><span class="pre">obj.db.attrname</span> <span class="pre">=</span> <span class="pre">value</span></code>, this property is set
|
||||
to <code class="docutils literal notranslate"><span class="pre">attrname</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">value</span></code> - this is the value of the Attribute. This value can be anything which can be pickled -
|
||||
objects, lists, numbers or what have you (see
|
||||
<a class="reference external" href="Components/Attributes.html#What_types_of_data_can_I_save_in_an_Attribute">this section</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
|
||||
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>
|
||||
<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>
|
||||
</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
|
||||
use Attributes behind the scenes).</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">model</span></code> - this is a <em>natural-key</em> describing the model this Attribute is attached to. This is on
|
||||
the form <em>appname.modelclass</em>, like <code class="docutils literal notranslate"><span class="pre">objects.objectdb</span></code>. It is used by the Attribute and
|
||||
NickHandler to quickly sort matches in the database. Neither this nor <code class="docutils literal notranslate"><span class="pre">attrtype</span></code> should normally
|
||||
need to be modified.</p></li>
|
||||
</ul>
|
||||
<p>Non-database attributes have no equivalence to <code class="docutils literal notranslate"><span class="pre">category</span></code> nor <code class="docutils literal notranslate"><span class="pre">strvalue</span></code>, <code class="docutils literal notranslate"><span class="pre">attrtype</span></code> or <code class="docutils literal notranslate"><span class="pre">model</span></code>.</p>
|
||||
</div>
|
||||
<div class="section" id="persistent-vs-non-persistent">
|
||||
<h2>Persistent vs non-persistent<a class="headerlink" href="#persistent-vs-non-persistent" title="Permalink to this headline">¶</a></h2>
|
||||
<p>So <em>persistent</em> data means that your data will survive a server reboot, whereas with
|
||||
<em>non-persistent</em> data it will not …</p>
|
||||
<p>… So why would you ever want to use non-persistent data? The answer is, you don’t have to. Most of
|
||||
the time you really want to save as much as you possibly can. Non-persistent data is potentially
|
||||
useful in a few situations though.</p>
|
||||
<ul class="simple">
|
||||
<li><p>You are worried about database performance. Since Evennia caches Attributes very aggressively,
|
||||
this is not an issue unless you are reading <em>and</em> writing to your Attribute very often (like many
|
||||
times per second). Reading from an already cached Attribute is as fast as reading any Python
|
||||
property. But even then this is not likely something to worry about: Apart from Evennia’s own
|
||||
caching, modern database systems themselves also cache data very efficiently for speed. Our
|
||||
default
|
||||
database even runs completely in RAM if possible, alleviating much of the need to write to disk
|
||||
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
|
||||
does potentially harmful stuff to your character object. With non-persistent storage you can be
|
||||
sure
|
||||
that whatever is messed up, it’s nothing a server reboot can’t clear up.</p></li>
|
||||
<li><p>NAttributes have no restrictions at all on what they can store (see next section), since they
|
||||
don’t need to worry about being saved to the database - they work very well for temporary storage.</p></li>
|
||||
<li><p>You want to implement a fully or partly <em>non-persistent world</em>. Who are we to argue with your
|
||||
grand vision!</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="what-types-of-data-can-i-save-in-an-attribute">
|
||||
<h2>What types of data can I save in an Attribute?<a class="headerlink" href="#what-types-of-data-can-i-save-in-an-attribute" title="Permalink to this headline">¶</a></h2>
|
||||
<blockquote>
|
||||
<div><p>None of the following affects NAttributes, which does not invoke the database at all. There are no
|
||||
restrictions to what can be stored in a NAttribute.</p>
|
||||
</div></blockquote>
|
||||
<p>The database doesn’t know anything about Python objects, so Evennia must <em>serialize</em> Attribute
|
||||
values into a string representation in order to store it to the database. This is done using the
|
||||
<code class="docutils literal notranslate"><span class="pre">pickle</span></code> module of Python (the only exception is if you use the <code class="docutils literal notranslate"><span class="pre">strattr</span></code> keyword of the
|
||||
AttributeHandler to save to the <code class="docutils literal notranslate"><span class="pre">strvalue</span></code> field of the Attribute. In that case you can only save
|
||||
<em>strings</em> which will not be pickled).</p>
|
||||
<p>It’s important to note that when you access the data in an Attribute you are <em>always</em> de-serializing
|
||||
it from the database representation every time. This is because we allow for storing
|
||||
database-entities in Attributes too. If we cached it as its Python form, we might end up with
|
||||
situations where the database entity was deleted since we last accessed the Attribute.
|
||||
De-serializing data with a database-entity in it means querying the database for that object and
|
||||
making sure it still exists (otherwise it will be set to <code class="docutils literal notranslate"><span class="pre">None</span></code>). Performance-wise this is usually
|
||||
not a big deal. But if you are accessing the Attribute as part of some big loop or doing a large
|
||||
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
|
||||
below.</p>
|
||||
<div class="section" id="storing-single-objects">
|
||||
<h3>Storing single objects<a class="headerlink" href="#storing-single-objects" title="Permalink to this headline">¶</a></h3>
|
||||
<p>With a single object, we mean anything that is <em>not iterable</em>, like numbers, strings or custom class
|
||||
instances without the <code class="docutils literal notranslate"><span class="pre">__iter__</span></code> method.</p>
|
||||
<ul class="simple">
|
||||
<li><p>You can generally store any non-iterable Python entity that can be
|
||||
<a class="reference external" href="http://docs.python.org/library/pickle.html">pickled</a>.</p></li>
|
||||
<li><p>Single database objects/typeclasses can be stored as any other in the Attribute. These can
|
||||
normally <em>not</em> be pickled, but Evennia will behind the scenes convert them to an internal
|
||||
representation using their classname, database-id and creation-date with a microsecond precision,
|
||||
guaranteeing you get the same object back when you access the Attribute later.</p></li>
|
||||
<li><p>If you <em>hide</em> a database object inside a non-iterable custom class (like stored as a variable
|
||||
inside it), Evennia will not know it’s there and won’t 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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13</pre></div></td><td class="code"><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="bp">False</span>
|
||||
<span class="c1"># a database object (will be stored as an internal representation)</span>
|
||||
<span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">test2</span> <span class="o">=</span> <span class="n">myobj</span>
|
||||
|
||||
<span class="c1"># example of an invalid, "hidden" dbobject</span>
|
||||
<span class="k">class</span> <span class="nc">Invalid</span><span class="p">(</span><span class="nb">object</span><span class="p">):</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="n">dbobj</span><span class="p">):</span>
|
||||
<span class="c1"># no way for Evennia to know this is a dbobj</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">dbobj</span> <span class="o">=</span> <span class="n">dbobj</span>
|
||||
<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>
|
||||
<div class="section" id="storing-multiple-objects">
|
||||
<h3>Storing multiple objects<a class="headerlink" href="#storing-multiple-objects" title="Permalink to this headline">¶</a></h3>
|
||||
<p>This means storing objects in a collection of some kind and are examples of <em>iterables</em>, pickle-able
|
||||
entities you can loop over in a for-loop. Attribute-saving supports the following iterables:</p>
|
||||
<ul class="simple">
|
||||
<li><p><a class="reference external" href="https://docs.python.org/2/library/functions.html#tuple">Tuples</a>, like <code class="docutils literal notranslate"><span class="pre">(1,2,"test",</span> <span class="pre"><dbobj>)</span></code>.</p></li>
|
||||
<li><p><a class="reference external" href="https://docs.python.org/2/tutorial/datastructures.html#more-on-lists">Lists</a>, like <code class="docutils literal notranslate"><span class="pre">[1,2,"test",</span> <span class="pre"><dbobj>]</span></code>.</p></li>
|
||||
<li><p><a class="reference external" href="https://docs.python.org/2/tutorial/datastructures.html#dictionaries">Dicts</a>, like <code class="docutils literal notranslate"><span class="pre">{1:2,</span> <span class="pre">"test":<dbobj>]</span></code>.</p></li>
|
||||
<li><p><a class="reference external" href="https://docs.python.org/2/tutorial/datastructures.html#sets">Sets</a>, like <code class="docutils literal notranslate"><span class="pre">{1,2,"test",<dbobj>}</span></code>.</p></li>
|
||||
<li></li>
|
||||
</ul>
|
||||
<p><a class="reference external" href="https://docs.python.org/2/library/collections.html#collections.OrderedDict">collections.OrderedDict</a>,
|
||||
like <code class="docutils literal notranslate"><span class="pre">OrderedDict((1,2),</span> <span class="pre">("test",</span> <span class="pre"><dbobj>))</span></code>.</p>
|
||||
<ul class="simple">
|
||||
<li><p><a class="reference external" href="https://docs.python.org/2/library/collections.html#collections.deque">collections.Deque</a>, like
|
||||
<code class="docutils literal notranslate"><span class="pre">deque((1,2,"test",<dbobj>))</span></code>.</p></li>
|
||||
<li><p><em>Nestings</em> of any combinations of the above, like lists in dicts or an OrderedDict of tuples, each
|
||||
containing dicts, etc.</p></li>
|
||||
<li><p>All other iterables (i.e. entities with the <code class="docutils literal notranslate"><span class="pre">__iter__</span></code> method) will be converted to a <em>list</em>.
|
||||
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
|
||||
stored in the iterable.</p>
|
||||
<blockquote>
|
||||
<div><p>As mentioned in the previous section, database entities (aka typeclasses) are not possible to
|
||||
pickle. So when storing an iterable, Evennia must recursively traverse the iterable <em>and all its
|
||||
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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15</pre></div></td><td class="code"><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">'str'</span><span class="p">:</span><span class="mi">34</span><span class="p">,</span> <span class="s1">'dex'</span><span class="p">:</span><span class="mi">56</span><span class="p">,</span> <span class="s1">'agi'</span><span class="p">:</span><span class="mi">22</span><span class="p">,</span> <span class="s1">'int'</span><span class="p">:</span><span class="mi">77</span><span class="p">}</span>
|
||||
<span class="c1"># a mixed dictionary/list</span>
|
||||
<span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">test5</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'members'</span><span class="p">:</span> <span class="p">[</span><span class="n">obj1</span><span class="p">,</span><span class="n">obj2</span><span class="p">,</span><span class="n">obj3</span><span class="p">],</span> <span class="s1">'enemies'</span><span class="p">:[</span><span class="n">obj4</span><span class="p">,</span><span class="n">obj5</span><span class="p">]}</span>
|
||||
<span class="c1"># a tuple with a list in it</span>
|
||||
<span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">test6</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</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="mi">8</span><span class="p">,</span> <span class="p">[</span><span class="s2">"test"</span><span class="p">,</span> <span class="s2">"test2"</span><span class="p">],</span> <span class="mi">9</span><span class="p">)</span>
|
||||
<span class="c1"># a set</span>
|
||||
<span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">test7</span> <span class="o">=</span> <span class="nb">set</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="mi">5</span><span class="p">])</span>
|
||||
<span class="c1"># in-situ manipulation</span>
|
||||
<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="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="s2">"test"</span><span class="p">:</span><span class="mi">1</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">test8</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">4</span>
|
||||
<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">"test"</span><span class="p">]</span> <span class="o">=</span> <span class="mi">5</span>
|
||||
<span class="c1"># test8 is now [4,2,{"test":5}]</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
</div>
|
||||
<div class="section" id="retrieving-mutable-objects">
|
||||
<h3>Retrieving Mutable objects<a class="headerlink" href="#retrieving-mutable-objects" title="Permalink to this headline">¶</a></h3>
|
||||
<p>A side effect of the way Evennia stores Attributes is that <em>mutable</em> iterables (iterables that can
|
||||
be modified in-place after they were created, which is everything except tuples) are handled by
|
||||
custom objects called <code class="docutils literal notranslate"><span class="pre">_SaverList</span></code>, <code class="docutils literal notranslate"><span class="pre">_SaverDict</span></code> etc. These <code class="docutils literal notranslate"><span class="pre">_Saver...</span></code> classes behave just like the
|
||||
normal variant except that they are aware of the database and saves to it whenever new data gets
|
||||
assigned to them. This is what allows you to do things like <code class="docutils literal notranslate"><span class="pre">self.db.mylist[7]</span> <span class="pre">=</span> <span class="pre">val</span></code> and be sure
|
||||
that the new version of list is saved. Without this you would have to load the list into a temporary
|
||||
variable, change it and then re-assign it to the Attribute in order for it to save.</p>
|
||||
<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>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5</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>
|
||||
<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="k">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="k">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>
|
||||
<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>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5</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>
|
||||
<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="k">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="k">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>
|
||||
<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
|
||||
sure you disonnect a nested structure entirely from the database, Evennia provides a special
|
||||
function <code class="docutils literal notranslate"><span class="pre">evennia.utils.dbserialize.deserialize</span></code>:</p>
|
||||
<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="k">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>
|
||||
instead of <code class="docutils literal notranslate"><span class="pre">_SaverList</span></code> and so on).</p>
|
||||
<p>Remember, this is only valid for <em>mutable</em> iterables.
|
||||
<a class="reference external" href="http://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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10</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>
|
||||
<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>
|
||||
<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">2</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">5</span>
|
||||
<span class="k">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">mytup</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">1</span><span class="p">])</span> <span class="c1"># this still returns 4, not 5</span>
|
||||
|
||||
<span class="n">mytup1</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">mytup</span> <span class="c1"># mytup1 is already disconnected from database since outermost</span>
|
||||
<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>
|
||||
<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
|
||||
or dict) you should make sure to “disconnect” the Attribute’s value first and operate on this
|
||||
rather than on the Attribute. You can gain dramatic speed improvements to big loops this
|
||||
way.</p>
|
||||
</div></blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="locking-and-checking-attributes">
|
||||
<h2>Locking and checking Attributes<a class="headerlink" href="#locking-and-checking-attributes" title="Permalink to this headline">¶</a></h2>
|
||||
<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>.
|
||||
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>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">attredit</span></code> - limits who may set/change this Attribute</p></li>
|
||||
</ul>
|
||||
<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 Attribute’s <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>1
|
||||
2</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">lockstring</span> <span class="o">=</span> <span class="s2">"attread:all();attredit:perm(Admins)"</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">"myattr"</span><span class="p">,</span> <span class="n">return_obj</span><span class="o">=</span><span class="bp">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>
|
||||
<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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11</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>
|
||||
<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="bp">True</span><span class="p">,</span>
|
||||
<span class="n">accessing_obj</span><span class="o">=</span><span class="n">caller</span><span class="p">,</span>
|
||||
<span class="n">default</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span>
|
||||
<span class="n">default_access</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">attr</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">"You cannot edit that Attribute!"</span><span class="p">)</span>
|
||||
<span class="k">return</span>
|
||||
<span class="c1"># edit the Attribute here</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Attributes</a><ul>
|
||||
<li><a class="reference internal" href="#the-db-and-ndb-shortcuts">The .db and .ndb shortcuts</a></li>
|
||||
<li><a class="reference internal" href="#the-attributehandler">The AttributeHandler</a></li>
|
||||
<li><a class="reference internal" href="#properties-of-attributes">Properties of Attributes</a></li>
|
||||
<li><a class="reference internal" href="#persistent-vs-non-persistent">Persistent vs non-persistent</a></li>
|
||||
<li><a class="reference internal" href="#what-types-of-data-can-i-save-in-an-attribute">What types of data can I save in an Attribute?</a><ul>
|
||||
<li><a class="reference internal" href="#storing-single-objects">Storing single objects</a></li>
|
||||
<li><a class="reference internal" href="#storing-multiple-objects">Storing multiple objects</a></li>
|
||||
<li><a class="reference internal" href="#retrieving-mutable-objects">Retrieving Mutable objects</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#locking-and-checking-attributes">Locking and checking Attributes</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/Attributes.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Attributes.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Attributes</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
398
docs/1.0-dev/Components/Batch-Code-Processor.html
Normal file
398
docs/1.0-dev/Components/Batch-Code-Processor.html
Normal file
|
|
@ -0,0 +1,398 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Batch Code Processor — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Batch Code Processor</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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
|
||||
page describes the Batch-<em>code</em> processor. The Batch-<em>command</em> one is covered [here](Batch-Command-
|
||||
Processor).</p>
|
||||
<div class="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">></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>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Where <code class="docutils literal notranslate"><span class="pre">path.to.batchcodefile</span></code> is the path to a <em>batch-code file</em>. Such a file should have a name
|
||||
ending in “<code class="docutils literal notranslate"><span class="pre">.py</span></code>” (but you shouldn’t include that in the path). The path is given like a python path
|
||||
relative to a folder you define to hold your batch files, set by <code class="docutils literal notranslate"><span class="pre">BATCH_IMPORT_PATH</span></code> in your
|
||||
settings. Default folder is (assuming your game is called “mygame”) <code class="docutils literal notranslate"><span class="pre">mygame/world/</span></code>. So if you want
|
||||
to run the example batch file in <code class="docutils literal notranslate"><span class="pre">mygame/world/batch_code.py</span></code>, you could simply use</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="o">></span> <span class="nd">@batchcode</span> <span class="n">batch_code</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This will try to run through the entire batch file in one go. For more gradual, <em>interactive</em>
|
||||
control you can use the <code class="docutils literal notranslate"><span class="pre">/interactive</span></code> switch. The switch <code class="docutils literal notranslate"><span class="pre">/debug</span></code> will put the processor in
|
||||
<em>debug</em> mode. Read below for more info.</p>
|
||||
</div>
|
||||
<div class="section" id="the-batch-file">
|
||||
<h2>The batch file<a class="headerlink" href="#the-batch-file" title="Permalink to this headline">¶</a></h2>
|
||||
<p>A batch-code file is a normal Python file. The difference is that since the batch processor loads
|
||||
and executes the file rather than importing it, you can reliably update the file, then call it
|
||||
again, over and over and see your changes without needing to <code class="docutils literal notranslate"><span class="pre">@reload</span></code> the server. This makes for
|
||||
easy testing. In the batch-code file you have also access to the following global variables:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">caller</span></code> - This is a reference to the object running the batchprocessor.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">DEBUG</span></code> - This is a boolean that lets you determine if this file is currently being run in debug-
|
||||
mode or not. See below how this can be useful.</p></li>
|
||||
</ul>
|
||||
<p>Running a plain Python file through the processor will just execute the file from beginning to end.
|
||||
If you want to get more control over the execution you can use the processor’s <em>interactive</em> mode.
|
||||
This runs certain code blocks on their own, rerunning only that part until you are happy with it. In
|
||||
order to do this you need to add special markers to your file to divide it up into smaller chunks.
|
||||
These take the form of comments, so the file remains valid Python.</p>
|
||||
<p>Here are the rules of syntax of the batch-code <code class="docutils literal notranslate"><span class="pre">*.py</span></code> file.</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">#CODE</span></code> as the first on a line marks the start of a <em>code</em> block. It will last until the beginning
|
||||
of another marker or the end of the file. Code blocks contain functional python code. Each <code class="docutils literal notranslate"><span class="pre">#CODE</span></code>
|
||||
block will be run in complete isolation from other parts of the file, so make sure it’s self-
|
||||
contained.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">#HEADER</span></code> as the first on a line marks the start of a <em>header</em> block. It lasts until the next
|
||||
marker or the end of the file. This is intended to hold imports and variables you will need for all
|
||||
other blocks .All python code defined in a header block will always be inserted at the top of every
|
||||
<code class="docutils literal notranslate"><span class="pre">#CODE</span></code> blocks in the file. You may have more than one <code class="docutils literal notranslate"><span class="pre">#HEADER</span></code> block, but that is equivalent to
|
||||
having one big one. Note that you can’t exchange data between code blocks, so editing a header-
|
||||
variable in one code block won’t affect that variable in any other code block!</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">#INSERT</span> <span class="pre">path.to.file</span></code> will insert another batchcode (Python) file at that position.</p></li>
|
||||
<li><p>A <code class="docutils literal notranslate"><span class="pre">#</span></code> that is not starting a <code class="docutils literal notranslate"><span class="pre">#HEADER</span></code>, <code class="docutils literal notranslate"><span class="pre">#CODE</span></code> or <code class="docutils literal notranslate"><span class="pre">#INSERT</span></code> instruction is considered a comment.</p></li>
|
||||
<li><p>Inside a block, normal Python syntax rules apply. For the sake of indentation, each block acts as
|
||||
a separate python module.</p></li>
|
||||
</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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15
|
||||
16
|
||||
17
|
||||
18
|
||||
19
|
||||
20
|
||||
21
|
||||
22
|
||||
23
|
||||
24
|
||||
25
|
||||
26
|
||||
27
|
||||
28
|
||||
29
|
||||
30
|
||||
31
|
||||
32
|
||||
33
|
||||
34
|
||||
35
|
||||
36
|
||||
37
|
||||
38</pre></div></td><td class="code"><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>
|
||||
|
||||
<span class="c1">#HEADER</span>
|
||||
|
||||
<span class="c1"># This will be included in all other #CODE blocks</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">create_object</span><span class="p">,</span> <span class="n">search_object</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>
|
||||
|
||||
<span class="n">limbo</span> <span class="o">=</span> <span class="n">search_object</span><span class="p">(</span><span class="s1">'Limbo'</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
|
||||
|
||||
|
||||
<span class="c1">#CODE </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="n">key</span><span class="o">=</span><span class="s2">"Red button"</span><span class="p">,</span>
|
||||
<span class="n">location</span><span class="o">=</span><span class="n">limbo</span><span class="p">,</span> <span class="n">aliases</span><span class="o">=</span><span class="p">[</span><span class="s2">"button"</span><span class="p">])</span>
|
||||
|
||||
<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">"A red button was created."</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># importing more code from another batch-code file</span>
|
||||
<span class="c1">#INSERT batch_code_insert</span>
|
||||
|
||||
<span class="c1">#CODE</span>
|
||||
|
||||
<span class="n">table</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span><span class="n">Object</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">"Blue Table"</span><span class="p">,</span> <span class="n">location</span><span class="o">=</span><span class="n">limbo</span><span class="p">)</span>
|
||||
<span class="n">chair</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span><span class="n">Object</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">"Blue Chair"</span><span class="p">,</span> <span class="n">location</span><span class="o">=</span><span class="n">limbo</span><span class="p">)</span>
|
||||
|
||||
<span class="n">string</span> <span class="o">=</span> <span class="s2">"A </span><span class="si">%s</span><span class="s2"> and </span><span class="si">%s</span><span class="s2"> were created."</span>
|
||||
<span class="k">if</span> <span class="n">DEBUG</span><span class="p">:</span>
|
||||
<span class="n">table</span><span class="o">.</span><span class="n">delete</span><span class="p">()</span>
|
||||
<span class="n">chair</span><span class="o">.</span><span class="n">delete</span><span class="p">()</span>
|
||||
<span class="n">string</span> <span class="o">+=</span> <span class="s2">" Since debug was active, "</span> \
|
||||
<span class="s2">"they were deleted again."</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="o">%</span> <span class="p">(</span><span class="n">table</span><span class="p">,</span> <span class="n">chair</span><span class="p">))</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<p>This uses Evennia’s Python API to create three objects in sequence.</p>
|
||||
</div>
|
||||
<div class="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">></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>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The batch script will run to the end and tell you it completed. You will also get messages that the
|
||||
button and the two pieces of furniture were created. Look around and you should see the button
|
||||
there. But you won’t see any chair nor a table! This is because we ran this with the <code class="docutils literal notranslate"><span class="pre">/debug</span></code>
|
||||
switch, which is directly visible as <code class="docutils literal notranslate"><span class="pre">DEBUG==True</span></code> inside the script. In the above example we
|
||||
handled this state by deleting the chair and table again.</p>
|
||||
<p>The debug mode is intended to be used when you test out a batchscript. Maybe you are looking for
|
||||
bugs in your code or try to see if things behave as they should. Running the script over and over
|
||||
would then create an ever-growing stack of chairs and tables, all with the same name. You would have
|
||||
to go back and painstakingly delete them later.</p>
|
||||
</div>
|
||||
<div class="section" id="interactive-mode">
|
||||
<h2>Interactive mode<a class="headerlink" href="#interactive-mode" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Interactive mode works very similar to the [batch-command processor counterpart](Batch-Command-
|
||||
Processor). It allows you more step-wise control over how the batch file is executed. This is useful
|
||||
for debugging or for picking and choosing only particular blocks to run. Use <code class="docutils literal notranslate"><span class="pre">@batchcode</span></code> with the
|
||||
<code class="docutils literal notranslate"><span class="pre">/interactive</span></code> flag to enter interactive mode.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="o">></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>
|
||||
</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>
|
||||
</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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11</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>
|
||||
<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>
|
||||
|
||||
<span class="n">limbo</span> <span class="o">=</span> <span class="n">search</span><span class="o">.</span><span class="n">objects</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s1">'Limbo'</span><span class="p">,</span> <span class="n">global_search</span><span class="o">=</span><span class="bp">True</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
|
||||
|
||||
<span class="n">red_button</span> <span class="o">=</span> <span class="n">create</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="n">key</span><span class="o">=</span><span class="s2">"Red button"</span><span class="p">,</span>
|
||||
<span class="n">location</span><span class="o">=</span><span class="n">limbo</span><span class="p">,</span> <span class="n">aliases</span><span class="o">=</span><span class="p">[</span><span class="s2">"button"</span><span class="p">])</span>
|
||||
|
||||
<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">"A red button was created."</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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>
|
||||
<p>If there are tracebacks, fix them in the batch file, then use <code class="docutils literal notranslate"><span class="pre">rr</span></code> to reload the file. You will
|
||||
still be at the same code block and can rerun it easily with <code class="docutils literal notranslate"><span class="pre">pp</span></code> as needed. This makes for a simple
|
||||
debug cycle. It also allows you to rerun individual troublesome blocks - as mentioned, in a large
|
||||
batch file this can be very useful (don’t forget the <code class="docutils literal notranslate"><span class="pre">/debug</span></code> mode either).</p>
|
||||
<p>Use <code class="docutils literal notranslate"><span class="pre">nn</span></code> and <code class="docutils literal notranslate"><span class="pre">bb</span></code> (next and back) to step through the file; e.g. <code class="docutils literal notranslate"><span class="pre">nn</span> <span class="pre">12</span></code> will jump 12 steps forward
|
||||
(without processing any blocks in between). All normal commands of Evennia should work too while
|
||||
working in interactive mode.</p>
|
||||
</div>
|
||||
<div class="section" id="limitations-and-caveats">
|
||||
<h2>Limitations and Caveats<a class="headerlink" href="#limitations-and-caveats" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The batch-code processor is by far the most flexible way to build a world in Evennia. There are
|
||||
however some caveats you need to keep in mind.</p>
|
||||
<div class="section" id="safety">
|
||||
<h3>Safety<a class="headerlink" href="#safety" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Or rather the lack of it. There is a reason only <em>superusers</em> are allowed to run the batch-code
|
||||
processor by default. The code-processor runs <strong>without any Evennia security checks</strong> and allows
|
||||
full access to Python. If an untrusted party could run the code-processor they could execute
|
||||
arbitrary python code on your machine, which is potentially a very dangerous thing. If you want to
|
||||
allow other users to access the batch-code processor you should make sure to run Evennia as a
|
||||
separate and very limited-access user on your machine (i.e. in a ‘jail’). By comparison, the batch-
|
||||
command processor is much safer since the user running it is still ‘inside’ the game and can’t
|
||||
really do anything outside what the game commands allow them to.</p>
|
||||
</div>
|
||||
<div class="section" id="no-communication-between-code-blocks">
|
||||
<h3>No communication between code blocks<a class="headerlink" href="#no-communication-between-code-blocks" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Global variables won’t work in code batch files, each block is executed as stand-alone environments.
|
||||
<code class="docutils literal notranslate"><span class="pre">#HEADER</span></code> blocks are literally pasted on top of each <code class="docutils literal notranslate"><span class="pre">#CODE</span></code> block so updating some header-variable
|
||||
in your block will not make that change available in another block. Whereas a python execution
|
||||
limitation, allowing this would also lead to very hard-to-debug code when using the interactive mode</p>
|
||||
<ul class="simple">
|
||||
<li><p>this would be a classical example of “spaghetti code”.</p></li>
|
||||
</ul>
|
||||
<p>The main practical issue with this is when building e.g. a room in one code block and later want to
|
||||
connect that room with a room you built in the current block. There are two ways to do this:</p>
|
||||
<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
|
||||
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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12</pre></div></td><td class="code"><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="bp">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>
|
||||
|
||||
<span class="c1">#CODE </span>
|
||||
<span class="c1"># create and store the castle</span>
|
||||
<span class="n">castle</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span><span class="s2">"rooms.Room"</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">"Castle"</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="p">[</span><span class="s2">"castle"</span><span class="p">]</span> <span class="o">=</span> <span class="n">castle</span>
|
||||
|
||||
<span class="c1">#CODE </span>
|
||||
<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">"castle"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Note how we check in <code class="docutils literal notranslate"><span class="pre">#HEADER</span></code> if <code class="docutils literal notranslate"><span class="pre">caller.ndb.all_rooms</span></code> doesn’t already exist before creating the
|
||||
dict. Remember that <code class="docutils literal notranslate"><span class="pre">#HEADER</span></code> is copied in front of every <code class="docutils literal notranslate"><span class="pre">#CODE</span></code> block. Without that <code class="docutils literal notranslate"><span class="pre">if</span></code> statement
|
||||
we’d be wiping the dict every block!</p>
|
||||
</div>
|
||||
<div class="section" id="don-t-treat-a-batchcode-file-like-any-python-file">
|
||||
<h3>Don’t 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>
|
||||
<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>
|
||||
</div>
|
||||
<div class="section" id="don-t-let-code-rely-on-the-batch-file-s-real-file-path">
|
||||
<h3>Don’t let code rely on the batch-file’s 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>
|
||||
<p>When you import things into your batchcode file, don’t use relative imports but always import with
|
||||
paths starting from the root of your game directory or evennia library. Code that relies on the
|
||||
batch file’s “actual” location <em>will fail</em>. Batch code files are read as text and the strings
|
||||
executed. When the code runs it has no knowledge of what file those strings where once a part of.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Batch Code Processor</a><ul>
|
||||
<li><a class="reference internal" href="#basic-usage">Basic Usage</a></li>
|
||||
<li><a class="reference internal" href="#the-batch-file">The batch file</a></li>
|
||||
<li><a class="reference internal" href="#debug-mode">Debug mode</a></li>
|
||||
<li><a class="reference internal" href="#interactive-mode">Interactive mode</a></li>
|
||||
<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">Don’t 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">Don’t let code rely on the batch-file’s real file path</a></li>
|
||||
</ul>
|
||||
</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/Batch-Code-Processor.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Batch-Code-Processor.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Batch Code Processor</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
322
docs/1.0-dev/Components/Batch-Command-Processor.html
Normal file
322
docs/1.0-dev/Components/Batch-Command-Processor.html
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Batch Command Processor — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Batch Command Processor</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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
|
||||
page describes the Batch-<em>command</em> processor. The Batch-<em>code</em> one is covered [here](Batch-Code-
|
||||
Processor).</p>
|
||||
<div class="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">></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>
|
||||
</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.
|
||||
This path is given like a python path relative to a folder you define to hold your batch files, set
|
||||
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">></span> <span class="nd">@batchcommand</span> <span class="n">batch_cmds</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>A batch-command file contains a list of Evennia in-game commands separated by comments. The
|
||||
processor will run the batch file from beginning to end. Note that <em>it will not stop if commands in
|
||||
it fail</em> (there is no universal way for the processor to know what a failure looks like for all
|
||||
different commands). So keep a close watch on the output, or use <em>Interactive mode</em> (see below) to
|
||||
run the file in a more controlled, gradual manner.</p>
|
||||
</div>
|
||||
<div class="section" id="the-batch-file">
|
||||
<h2>The batch file<a class="headerlink" href="#the-batch-file" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The batch file is a simple plain-text file containing Evennia commands. Just like you would write
|
||||
them in-game, except you have more freedom with line breaks.</p>
|
||||
<p>Here are the rules of syntax of an <code class="docutils literal notranslate"><span class="pre">*.ev</span></code> file. You’ll find it’s really, really simple:</p>
|
||||
<ul class="simple">
|
||||
<li><p>All lines having the <code class="docutils literal notranslate"><span class="pre">#</span></code> (hash)-symbol <em>as the first one on the line</em> are considered <em>comments</em>.
|
||||
All non-comment lines are treated as a command and/or their arguments.</p></li>
|
||||
<li><p>Comment lines have an actual function – they mark the <em>end of the previous command definition</em>.
|
||||
So never put two commands directly after one another in the file - separate them with a comment, or
|
||||
the second of the two will be considered an argument to the first one. Besides, using plenty of
|
||||
comments is good practice anyway.</p></li>
|
||||
<li><p>A line that starts with the word <code class="docutils literal notranslate"><span class="pre">#INSERT</span></code> is a comment line but also signifies a special
|
||||
instruction. The syntax is <code class="docutils literal notranslate"><span class="pre">#INSERT</span> <span class="pre"><path.batchfile></span></code> and tries to import a given batch-cmd file
|
||||
into this one. The inserted batch file (file ending <code class="docutils literal notranslate"><span class="pre">.ev</span></code>) will run normally from the point of the
|
||||
<code class="docutils literal notranslate"><span class="pre">#INSERT</span></code> instruction.</p></li>
|
||||
<li><p>Extra whitespace in a command definition is <em>ignored</em>. - A completely empty line translates in to
|
||||
a line break in texts. Two empty lines thus means a new paragraph (this is obviously only relevant
|
||||
for commands accepting such formatting, such as the <code class="docutils literal notranslate"><span class="pre">@desc</span></code> command).</p></li>
|
||||
<li><p>The very last command in the file is not required to end with a comment.</p></li>
|
||||
<li><p>You <em>cannot</em> nest another <code class="docutils literal notranslate"><span class="pre">@batchcommand</span></code> statement into your batch file. If you want to link many
|
||||
batch-files together, use the <code class="docutils literal notranslate"><span class="pre">#INSERT</span></code> batch instruction instead. You also cannot launch the
|
||||
<code class="docutils literal notranslate"><span class="pre">@batchcode</span></code> command from your batch file, the two batch processors are not compatible.</p></li>
|
||||
</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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15
|
||||
16
|
||||
17
|
||||
18
|
||||
19
|
||||
20
|
||||
21
|
||||
22
|
||||
23
|
||||
24
|
||||
25
|
||||
26
|
||||
27
|
||||
28
|
||||
29
|
||||
30
|
||||
31
|
||||
32
|
||||
33
|
||||
34
|
||||
35
|
||||
36
|
||||
37
|
||||
38
|
||||
39
|
||||
40</pre></div></td><td class="code"><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>
|
||||
|
||||
<span class="c1"># This creates a red button</span>
|
||||
@create button:tutorial_examples.red_button.RedButton
|
||||
<span class="c1"># (This comment ends input for @create)</span>
|
||||
<span class="c1"># Next command. Let's create something. </span>
|
||||
@set button/desc <span class="o">=</span>
|
||||
This is a large red button. Now and <span class="k">then</span>
|
||||
it flashes in an evil, yet strangely tantalizing way.
|
||||
|
||||
A big sign sits next to it. It says:
|
||||
|
||||
|
||||
-----------
|
||||
|
||||
Press me!
|
||||
|
||||
-----------
|
||||
|
||||
|
||||
... It really begs to be pressed! You
|
||||
know you want to!
|
||||
|
||||
<span class="c1"># This inserts the commands from another batch-cmd file named</span>
|
||||
<span class="c1"># batch_insert_file.ev.</span>
|
||||
<span class="c1">#INSERT examples.batch_insert_file</span>
|
||||
|
||||
|
||||
<span class="c1"># (This ends the @set command). Note that single line breaks </span>
|
||||
<span class="c1"># and extra whitespace in the argument are ignored. Empty lines </span>
|
||||
<span class="c1"># translate into line breaks in the output.</span>
|
||||
<span class="c1"># Now let's place the button where it belongs (let's say limbo #2 is </span>
|
||||
<span class="c1"># the evil lair in our example)</span>
|
||||
@teleport <span class="c1">#2</span>
|
||||
<span class="c1"># (This comments ends the @teleport command.) </span>
|
||||
<span class="c1"># Now we drop it so others can see it. </span>
|
||||
<span class="c1"># The very last command in the file needs not be ended with #.</span>
|
||||
drop button
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<p>To test this, run <code class="docutils literal notranslate"><span class="pre">@batchcommand</span></code> on the file:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">></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>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>A button will be created, described and dropped in Limbo. All commands will be executed by the user
|
||||
calling the command.</p>
|
||||
<blockquote>
|
||||
<div><p>Note that if you interact with the button, you might find that its description changes, loosing
|
||||
your custom-set description above. This is just the way this particular object works.</p>
|
||||
</div></blockquote>
|
||||
</div>
|
||||
<div class="section" id="interactive-mode">
|
||||
<h2>Interactive mode<a class="headerlink" href="#interactive-mode" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Interactive mode allows you to more step-wise control over how the batch file is executed. This is
|
||||
useful for debugging and also if you have a large batch file and is only updating a small part of it
|
||||
– running the entire file again would be a waste of time (and in the case of <code class="docutils literal notranslate"><span class="pre">@create</span></code>-ing objects
|
||||
you would to end up with multiple copies of same-named objects, for example). Use <code class="docutils literal notranslate"><span class="pre">@batchcommand</span></code>
|
||||
with the <code class="docutils literal notranslate"><span class="pre">/interactive</span></code> flag to enter interactive mode.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="o">></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>
|
||||
</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>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This shows that you are on the <code class="docutils literal notranslate"><span class="pre">@create</span></code> command, the first out of only four commands in this batch
|
||||
file. Observe that the command <code class="docutils literal notranslate"><span class="pre">@create</span></code> has <em>not</em> been actually processed at this point!</p>
|
||||
<p>To take a look at the full command you are about to run, use <code class="docutils literal notranslate"><span class="pre">ll</span></code> (a batch-processor version of
|
||||
<code class="docutils literal notranslate"><span class="pre">look</span></code>). Use <code class="docutils literal notranslate"><span class="pre">pp</span></code> to actually process the current command (this will actually <code class="docutils literal notranslate"><span class="pre">@create</span></code> the button)
|
||||
– and make sure it worked as planned. Use <code class="docutils literal notranslate"><span class="pre">nn</span></code> (next) to go to the next command. Use <code class="docutils literal notranslate"><span class="pre">hh</span></code> for a
|
||||
list of commands.</p>
|
||||
<p>If there are errors, fix them in the batch file, then use <code class="docutils literal notranslate"><span class="pre">rr</span></code> to reload the file. You will still be
|
||||
at the same command and can rerun it easily with <code class="docutils literal notranslate"><span class="pre">pp</span></code> as needed. This makes for a simple debug
|
||||
cycle. It also allows you to rerun individual troublesome commands - as mentioned, in a large batch
|
||||
file this can be very useful. Do note that in many cases, commands depend on the previous ones (e.g.
|
||||
if <code class="docutils literal notranslate"><span class="pre">@create</span></code> in the example above had failed, the following commands would have had nothing to
|
||||
operate on).</p>
|
||||
<p>Use <code class="docutils literal notranslate"><span class="pre">nn</span></code> and <code class="docutils literal notranslate"><span class="pre">bb</span></code> (next and back) to step through the file; e.g. <code class="docutils literal notranslate"><span class="pre">nn</span> <span class="pre">12</span></code> will jump 12 steps forward
|
||||
(without processing any command in between). All normal commands of Evennia should work too while
|
||||
working in interactive mode.</p>
|
||||
</div>
|
||||
<div class="section" id="limitations-and-caveats">
|
||||
<h2>Limitations and Caveats<a class="headerlink" href="#limitations-and-caveats" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The batch-command processor is great for automating smaller builds or for testing new commands and
|
||||
objects repeatedly without having to write so much. There are several caveats you have to be aware
|
||||
of when using the batch-command processor for building larger, complex worlds though.</p>
|
||||
<p>The main issue is that when you run a batch-command script you (<em>you</em>, as in your superuser
|
||||
character) are actually moving around in the game creating and building rooms in sequence, just as
|
||||
if you had been entering those commands manually, one by one. You have to take this into account
|
||||
when creating the file, so that you can ‘walk’ (or teleport) to the right places in order.</p>
|
||||
<p>This also means there are several pitfalls when designing and adding certain types of objects. Here
|
||||
are some examples:</p>
|
||||
<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
|
||||
severely limits the cmdsets of those entering it (maybe you have to find the light switch to
|
||||
proceed). In your batch script you would create this room, then teleport to it - and promptly be
|
||||
shifted into the dark state where none of your normal build commands work …</p></li>
|
||||
<li><p><em>Auto-teleportation</em>: Rooms that automatically teleport those that enter them to another place
|
||||
(like a trap room, for example). You would be teleported away too.</p></li>
|
||||
<li><p><em>Mobiles</em>: If you add aggressive mobs, they might attack you, drawing you into combat. If they
|
||||
have AI they might even follow you around when building - or they might move away from you before
|
||||
you’ve had time to finish describing and equipping them!</p></li>
|
||||
</ul>
|
||||
<p>The solution to all these is to plan ahead. Make sure that superusers are never affected by whatever
|
||||
effects are in play. Add an on/off switch to objects and make sure it’s always set to <em>off</em> upon
|
||||
creation. It’s all doable, one just needs to keep it in mind.</p>
|
||||
</div>
|
||||
<div class="section" id="assorted-notes">
|
||||
<h2>Assorted notes<a class="headerlink" href="#assorted-notes" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The fact that you build as ‘yourself’ can also be considered an advantage however, should you ever
|
||||
decide to change the default command to allow others than superusers to call the processor. Since
|
||||
normal access-checks are still performed, a malevolent builder with access to the processor should
|
||||
not be able to do all that much damage (this is the main drawback of the <a class="reference internal" href="Batch-Code-Processor.html"><span class="doc">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’
|
||||
<em>evennia mode</em>. This is an Emacs major mode found in <code class="docutils literal notranslate"><span class="pre">evennia/utils/evennia-mode.el</span></code>. It offers
|
||||
correct syntax highlighting and indentation with <code class="docutils literal notranslate"><span class="pre"><tab></span></code> when editing <code class="docutils literal notranslate"><span class="pre">.ev</span></code> files in Emacs. See the
|
||||
header of that file for installation instructions.</p></li>
|
||||
<li><p><a class="reference external" href="http://www.vim.org/">VIM</a> users can use amfl’s <a class="reference external" href="https://github.com/amfl/vim-evennia">vim-evennia</a>
|
||||
mode instead, see its readme for install instructions.</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Batch Command Processor</a><ul>
|
||||
<li><a class="reference internal" href="#basic-usage">Basic Usage</a></li>
|
||||
<li><a class="reference internal" href="#the-batch-file">The batch file</a></li>
|
||||
<li><a class="reference internal" href="#interactive-mode">Interactive mode</a></li>
|
||||
<li><a class="reference internal" href="#limitations-and-caveats">Limitations and Caveats</a></li>
|
||||
<li><a class="reference internal" href="#assorted-notes">Assorted notes</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Components/Batch-Command-Processor.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Batch-Command-Processor.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Batch Command Processor</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
176
docs/1.0-dev/Components/Batch-Processors.html
Normal file
176
docs/1.0-dev/Components/Batch-Processors.html
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Batch Processors — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Batch Processors</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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
|
||||
traditional MUD setups you had to do all this online, line by line, over a telnet session.</p>
|
||||
<p>Evennia already moves away from much of this by shifting the main coding work to external Python
|
||||
modules. But also building would be helped if one could do some or all of it externally. Enter
|
||||
Evennia’s <em>batch processors</em> (there are two of them). The processors allows you, as a game admin, to
|
||||
build your game completely offline in normal text files (<em>batch files</em>) that the processors
|
||||
understands. Then, when you are ready, you use the processors to read it all into Evennia (and into
|
||||
the database) in one go.</p>
|
||||
<p>You can of course still build completely online should you want to - this is certainly the easiest
|
||||
way to go when learning and for small build projects. But for major building work, the advantages of
|
||||
using the batch-processors are many:</p>
|
||||
<ul class="simple">
|
||||
<li><p>It’s hard to compete with the comfort of a modern desktop text editor; Compared to a traditional
|
||||
MUD line input, you can get much better overview and many more features. Also, accidentally pressing
|
||||
Return won’t immediately commit things to the database.</p></li>
|
||||
<li><p>You might run external spell checkers on your batch files. In the case of one of the batch-
|
||||
processors (the one that deals with Python code), you could also run external debuggers and code
|
||||
analyzers on your file to catch problems before feeding it to Evennia.</p></li>
|
||||
<li><p>The batch files (as long as you keep them) are records of your work. They make a natural starting
|
||||
point for quickly re-building your world should you ever decide to start over.</p></li>
|
||||
<li><p>If you are an Evennia developer, using a batch file is a fast way to setup a test-game after
|
||||
having reset the database.</p></li>
|
||||
<li><p>The batch files might come in useful should you ever decide to distribute all or part of your
|
||||
world to others.</p></li>
|
||||
</ul>
|
||||
<p>There are two batch processors, the Batch-<em>command</em> processor and the Batch-<em>code</em> processor. The
|
||||
first one is the simpler of the two. It doesn’t require any programming knowledge - you basically
|
||||
just list in-game commands in a text file. The code-processor on the other hand is much more
|
||||
powerful but also more complex - it lets you use Evennia’s API to code your world in full-fledged
|
||||
Python code.</p>
|
||||
<ul class="simple">
|
||||
<li><p>The <a class="reference internal" href="Batch-Command-Processor.html"><span class="doc">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>
|
||||
</ul>
|
||||
<p>If you plan to use international characters in your batchfiles you are wise to read about <em>file
|
||||
encodings</em> below.</p>
|
||||
<div class="section" id="a-note-on-file-encodings">
|
||||
<h2>A note on File Encodings<a class="headerlink" href="#a-note-on-file-encodings" title="Permalink to this headline">¶</a></h2>
|
||||
<p>As mentioned, both the processors take text files as input and then proceed to process them. As long
|
||||
as you stick to the standard <a class="reference external" href="http://en.wikipedia.org/wiki/Ascii">ASCII</a> character set (which means
|
||||
the normal English characters, basically) you should not have to worry much about this section.</p>
|
||||
<p>Many languages however use characters outside the simple <code class="docutils literal notranslate"><span class="pre">ASCII</span></code> table. Common examples are various
|
||||
apostrophes and umlauts but also completely different symbols like those of the greek or cyrillic
|
||||
alphabets.</p>
|
||||
<p>First, we should make it clear that Evennia itself handles international characters just fine. It
|
||||
(and Django) uses <a class="reference external" href="http://en.wikipedia.org/wiki/Unicode">unicode</a> strings internally.</p>
|
||||
<p>The problem is that when reading a text file like the batchfile, we need to know how to decode the
|
||||
byte-data stored therein to universal unicode. That means we need an <em>encoding</em> (a mapping) for how
|
||||
the file stores its data. There are many, many byte-encodings used around the world, with opaque
|
||||
names such as <code class="docutils literal notranslate"><span class="pre">Latin-1</span></code>, <code class="docutils literal notranslate"><span class="pre">ISO-8859-3</span></code> or <code class="docutils literal notranslate"><span class="pre">ARMSCII-8</span></code> to pick just a few examples. Problem is that
|
||||
it’s practially impossible to determine which encoding was used to save a file just by looking at it
|
||||
(it’s just a bunch of bytes!). You have to <em>know</em>.</p>
|
||||
<p>With this little introduction it should be clear that Evennia can’t guess but has to <em>assume</em> an
|
||||
encoding when trying to load a batchfile. The text editor and Evennia must speak the same “language”
|
||||
so to speak. Evennia will by default first try the international <code class="docutils literal notranslate"><span class="pre">UTF-8</span></code> encoding, but you can have
|
||||
Evennia try any sequence of different encodings by customizing the <code class="docutils literal notranslate"><span class="pre">ENCODINGS</span></code> list in your settings
|
||||
file. Evennia will use the first encoding in the list that do not raise any errors. Only if none
|
||||
work will the server give up and return an error message.</p>
|
||||
<p>You can often change the text editor encoding (this depends on your editor though), otherwise you
|
||||
need to add the editor’s encoding to Evennia’s <code class="docutils literal notranslate"><span class="pre">ENCODINGS</span></code> list. If you are unsure, write a test
|
||||
file with lots of non-ASCII letters in the editor of your choice, then import to make sure it works
|
||||
as it should.</p>
|
||||
<p>More help with encodings can be found in the entry <a class="reference internal" href="../Concepts/Text-Encodings.html"><span class="doc">Text Encodings</span></a> and also in the
|
||||
Wikipedia article <a class="reference external" href="http://en.wikipedia.org/wiki/Text_encodings">here</a>.</p>
|
||||
<p><strong>A footnote for the batch-code processor</strong>: Just because <em>Evennia</em> can parse your file and your
|
||||
fancy special characters, doesn’t mean that <em>Python</em> allows their use. Python syntax only allows
|
||||
international characters inside <em>strings</em>. In all other source code only <code class="docutils literal notranslate"><span class="pre">ASCII</span></code> set characters are
|
||||
allowed.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Batch Processors</a><ul>
|
||||
<li><a class="reference internal" href="#a-note-on-file-encodings">A note on File Encodings</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/Batch-Processors.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Batch-Processors.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Batch Processors</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
210
docs/1.0-dev/Components/Bootstrap-Components-and-Utilities.html
Normal file
210
docs/1.0-dev/Components/Bootstrap-Components-and-Utilities.html
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Bootstrap Components and Utilities — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Bootstrap Components and Utilities</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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 Evennia’s web
|
||||
presence. We’ll 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>
|
||||
to get a feel for how to add pages to Evennia’s website to test these examples.</p>
|
||||
</div></blockquote>
|
||||
<div class="section" id="general-styling">
|
||||
<h2>General Styling<a class="headerlink" href="#general-styling" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Bootstrap provides base styles for your site. These can be customized through CSS, but the default
|
||||
styles are intended to provide a consistent, clean look for sites.</p>
|
||||
<div class="section" id="color">
|
||||
<h3>Color<a class="headerlink" href="#color" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Most elements can be styled with default colors. <a class="reference external" href="https://getbootstrap.com/docs/4.0/utilities/colors/">Take a look at the documentation</a> to learn more about these colors</p>
|
||||
<ul class="simple">
|
||||
<li><p>suffice to say, adding a class of text-* or bg-*, for instance, text-primary, sets the text color
|
||||
or background color.</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="borders">
|
||||
<h3>Borders<a class="headerlink" href="#borders" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Simply adding a class of ‘border’ to an element adds a border to the element. For more in-depth
|
||||
info, please <a class="reference external" href="https://getbootstrap.com/docs/4.0/utilities/borders/">read the documentation on borders.</a>.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o"><</span><span class="n">span</span> <span class="n">class</span><span class="o">=</span><span class="s2">"border border-dark"</span><span class="o">></</span><span class="n">span</span><span class="o">></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>You can also easily round corners just by adding a class.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o"><</span><span class="n">img</span> <span class="n">src</span><span class="o">=</span><span class="s2">"..."</span> <span class="n">class</span><span class="o">=</span><span class="s2">"rounded"</span> <span class="o">/></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="spacing">
|
||||
<h3>Spacing<a class="headerlink" href="#spacing" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Bootstrap provides classes to easily add responsive margin and padding. Most of the time, you might
|
||||
like to add margins or padding through CSS itself - however these classes are used in the default
|
||||
Evennia site. <a class="reference external" href="https://getbootstrap.com/docs/4.0/utilities/spacing/">Take a look at the docs</a> to
|
||||
learn more.</p>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="docutils" />
|
||||
<div class="section" id="components">
|
||||
<h2>Components<a class="headerlink" href="#components" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="section" id="buttons">
|
||||
<h3>Buttons<a class="headerlink" href="#buttons" title="Permalink to this headline">¶</a></h3>
|
||||
<p><a class="reference external" href="https://getbootstrap.com/docs/4.0/components/buttons/">Buttons</a> in Bootstrap are very easy to use -
|
||||
button styling can be added to <code class="docutils literal notranslate"><span class="pre"><button></span></code>, <code class="docutils literal notranslate"><span class="pre"><a></span></code>, and <code class="docutils literal notranslate"><span class="pre"><input></span></code> elements.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><a class="btn btn-primary" href="#" role="button">I'm a Button</a>
|
||||
<button class="btn btn-primary" type="submit">Me too!</button>
|
||||
<input class="btn btn-primary" type="button" value="Button">
|
||||
<input class="btn btn-primary" type="submit" value="Also a Button">
|
||||
<input class="btn btn-primary" type="reset" value="Button as Well">
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="cards">
|
||||
<h3>Cards<a class="headerlink" href="#cards" title="Permalink to this headline">¶</a></h3>
|
||||
<p><a class="reference external" href="https://getbootstrap.com/docs/4.0/components/card/">Cards</a> provide a container for other elements
|
||||
that stands out from the rest of the page. The “Accounts”, “Recently Connected”, and “Database
|
||||
Stats” on the default webpage are all in cards. Cards provide quite a bit of formatting options -
|
||||
the following is a simple example, but read the documentation or look at the site’s source for more.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o"><</span><span class="n">div</span> <span class="n">class</span><span class="o">=</span><span class="s2">"card"</span><span class="o">></span>
|
||||
<span class="o"><</span><span class="n">div</span> <span class="n">class</span><span class="o">=</span><span class="s2">"card-body"</span><span class="o">></span>
|
||||
<span class="o"><</span><span class="n">h4</span> <span class="n">class</span><span class="o">=</span><span class="s2">"card-title"</span><span class="o">></span><span class="n">Card</span> <span class="n">title</span><span class="o"></</span><span class="n">h4</span><span class="o">></span>
|
||||
<span class="o"><</span><span class="n">h6</span> <span class="n">class</span><span class="o">=</span><span class="s2">"card-subtitle mb-2 text-muted"</span><span class="o">></span><span class="n">Card</span> <span class="n">subtitle</span><span class="o"></</span><span class="n">h6</span><span class="o">></span>
|
||||
<span class="o"><</span><span class="n">p</span> <span class="n">class</span><span class="o">=</span><span class="s2">"card-text"</span><span class="o">></span><span class="n">Fancy</span><span class="p">,</span> <span class="n">isn</span><span class="s1">'t it?</p></span>
|
||||
<span class="o"><</span><span class="n">a</span> <span class="n">href</span><span class="o">=</span><span class="s2">"#"</span> <span class="n">class</span><span class="o">=</span><span class="s2">"card-link"</span><span class="o">></span><span class="n">Card</span> <span class="n">link</span><span class="o"></</span><span class="n">a</span><span class="o">></span>
|
||||
<span class="o"></</span><span class="n">div</span><span class="o">></span>
|
||||
<span class="o"></</span><span class="n">div</span><span class="o">></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="jumbotron">
|
||||
<h3>Jumbotron<a class="headerlink" href="#jumbotron" title="Permalink to this headline">¶</a></h3>
|
||||
<p><a class="reference external" href="https://getbootstrap.com/docs/4.0/components/jumbotron/">Jumbotrons</a> are useful for featuring an
|
||||
image or tagline for your game. They can flow with the rest of your content or take up the full
|
||||
width of the page - Evennia’s base site uses the former.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o"><</span><span class="n">div</span> <span class="n">class</span><span class="o">=</span><span class="s2">"jumbotron jumbotron-fluid"</span><span class="o">></span>
|
||||
<span class="o"><</span><span class="n">div</span> <span class="n">class</span><span class="o">=</span><span class="s2">"container"</span><span class="o">></span>
|
||||
<span class="o"><</span><span class="n">h1</span> <span class="n">class</span><span class="o">=</span><span class="s2">"display-3"</span><span class="o">></span><span class="n">Full</span> <span class="n">Width</span> <span class="n">Jumbotron</span><span class="o"></</span><span class="n">h1</span><span class="o">></span>
|
||||
<span class="o"><</span><span class="n">p</span> <span class="n">class</span><span class="o">=</span><span class="s2">"lead"</span><span class="o">></span><span class="n">Look</span> <span class="n">at</span> <span class="n">the</span> <span class="n">source</span> <span class="n">of</span> <span class="n">the</span> <span class="n">default</span> <span class="n">Evennia</span> <span class="n">page</span> <span class="k">for</span> <span class="n">a</span> <span class="n">regular</span> <span class="n">Jumbotron</span><span class="o"></</span><span class="n">p</span><span class="o">></span>
|
||||
<span class="o"></</span><span class="n">div</span><span class="o">></span>
|
||||
<span class="o"></</span><span class="n">div</span><span class="o">></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="forms">
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Bootstrap Components and Utilities</a><ul>
|
||||
<li><a class="reference internal" href="#general-styling">General Styling</a><ul>
|
||||
<li><a class="reference internal" href="#color">Color</a></li>
|
||||
<li><a class="reference internal" href="#borders">Borders</a></li>
|
||||
<li><a class="reference internal" href="#spacing">Spacing</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#components">Components</a><ul>
|
||||
<li><a class="reference internal" href="#buttons">Buttons</a></li>
|
||||
<li><a class="reference internal" href="#cards">Cards</a></li>
|
||||
<li><a class="reference internal" href="#jumbotron">Jumbotron</a></li>
|
||||
<li><a class="reference internal" href="#forms">Forms</a></li>
|
||||
</ul>
|
||||
</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/Bootstrap-Components-and-Utilities.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Bootstrap-Components-and-Utilities.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Bootstrap Components and Utilities</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
99
docs/1.0-dev/Components/Channels.html
Normal file
99
docs/1.0-dev/Components/Channels.html
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Channels — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Channels</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" id="channels">
|
||||
<h1>Channels<a class="headerlink" href="#channels" title="Permalink to this headline">¶</a></h1>
|
||||
<p>TODO: Channels are covered in <a class="reference internal" href="Communications.html"><span class="doc">Communications</span></a> right now.</p>
|
||||
</div>
|
||||
|
||||
|
||||
<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>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Components/Channels.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Channels.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Channels</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
467
docs/1.0-dev/Components/Coding-Utils.html
Normal file
467
docs/1.0-dev/Components/Coding-Utils.html
Normal file
|
|
@ -0,0 +1,467 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Coding Utils — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Coding Utils</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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>
|
||||
<div class="section" id="searching">
|
||||
<h2>Searching<a class="headerlink" href="#searching" title="Permalink to this headline">¶</a></h2>
|
||||
<p>A common thing to do is to search for objects. There it’s easiest to use the <code class="docutils literal notranslate"><span class="pre">search</span></code> method defined
|
||||
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>1</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>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<p>The most common time one needs to do this is inside a command body. <code class="docutils literal notranslate"><span class="pre">obj</span> <span class="pre">=</span> <span class="pre">self.caller.search(objname)</span></code> will search inside the caller’s (typically, the character that typed
|
||||
the command) <code class="docutils literal notranslate"><span class="pre">.contents</span></code> (their “inventory”) and <code class="docutils literal notranslate"><span class="pre">.location</span></code> (their “room”).</p>
|
||||
<p>Give the keyword <code class="docutils literal notranslate"><span class="pre">global_search=True</span></code> to extend search to encompass entire database. Aliases will
|
||||
also be matched by this search. You will find multiple examples of this functionality in the default
|
||||
command set.</p>
|
||||
<p>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>1
|
||||
2</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>
|
||||
<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>
|
||||
<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>
|
||||
</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>
|
||||
</div>
|
||||
<div class="section" id="create">
|
||||
<h2>Create<a class="headerlink" href="#create" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Apart from the in-game build commands (<code class="docutils literal notranslate"><span class="pre">@create</span></code> etc), you can also build all of Evennia’s game
|
||||
entities directly in code (for example when defining new create commands).</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||||
2
|
||||
3</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="kn">import</span> <span class="nn">evennia</span>
|
||||
|
||||
<span class="n">myobj</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">create_objects</span><span class="p">(</span><span class="s2">"game.gamesrc.objects.myobj.MyObj"</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">"MyObj"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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>
|
||||
</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>
|
||||
</div>
|
||||
<div class="section" id="logging">
|
||||
<h2>Logging<a class="headerlink" href="#logging" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Normally you can use Python <code class="docutils literal notranslate"><span class="pre">print</span></code> statements to see output to the terminal/log. The <code class="docutils literal notranslate"><span class="pre">print</span></code>
|
||||
statement should only be used for debugging though. For producion output, use the <code class="docutils literal notranslate"><span class="pre">logger</span></code> which
|
||||
will create proper logs either to terminal or to file.</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6</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>
|
||||
<span class="c1">#</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">log_err</span><span class="p">(</span><span class="s2">"This is an Error!"</span><span class="p">)</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">log_warn</span><span class="p">(</span><span class="s2">"This is a Warning!"</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">"This is normal information"</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">"This feature is deprecated"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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>1
|
||||
2
|
||||
3
|
||||
4</pre></div></td><td class="code"><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">"This text will show beneath the traceback itself."</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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>1</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">"mylog.log"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<p>If not an absolute path is given, the log file will appear in the <code class="docutils literal notranslate"><span class="pre">mygame/server/logs/</span></code> directory.
|
||||
If the file already exists, it will be appended to. Timestamps on the same format as the normal
|
||||
Evennia logs will be automatically added to each entry. If a filename is not specified, output will
|
||||
be written to a file <code class="docutils literal notranslate"><span class="pre">game/logs/game.log</span></code>.</p>
|
||||
</div>
|
||||
<div class="section" id="time-utilities">
|
||||
<h2>Time Utilities<a class="headerlink" href="#time-utilities" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="section" id="game-time">
|
||||
<h3>Game time<a class="headerlink" href="#game-time" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Evennia tracks the current server time. You can access this time via the <code class="docutils literal notranslate"><span class="pre">evennia.gametime</span></code>
|
||||
shortcut:</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15
|
||||
16
|
||||
17
|
||||
18
|
||||
19
|
||||
20
|
||||
21</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>
|
||||
|
||||
<span class="c1"># all the functions below return times in seconds).</span>
|
||||
|
||||
<span class="c1"># total running time of the server</span>
|
||||
<span class="n">runtime</span> <span class="o">=</span> <span class="n">gametime</span><span class="o">.</span><span class="n">runtime</span><span class="p">()</span>
|
||||
<span class="c1"># time since latest hard reboot (not including reloads)</span>
|
||||
<span class="n">uptime</span> <span class="o">=</span> <span class="n">gametime</span><span class="o">.</span><span class="n">uptime</span><span class="p">()</span>
|
||||
<span class="c1"># server epoch (its start time)</span>
|
||||
<span class="n">server_epoch</span> <span class="o">=</span> <span class="n">gametime</span><span class="o">.</span><span class="n">server_epoch</span><span class="p">()</span>
|
||||
|
||||
<span class="c1"># in-game epoch (this can be set by `settings.TIME_GAME_EPOCH`.</span>
|
||||
<span class="c1"># If not, the server epoch is used.</span>
|
||||
<span class="n">game_epoch</span> <span class="o">=</span> <span class="n">gametime</span><span class="o">.</span><span class="n">game_epoch</span><span class="p">()</span>
|
||||
<span class="c1"># in-game time passed since time started running</span>
|
||||
<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="c1"># in-game time plus game epoch (i.e. the current in-game</span>
|
||||
<span class="c1"># time stamp)</span>
|
||||
<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="bp">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>
|
||||
<p>The setting <code class="docutils literal notranslate"><span class="pre">TIME_FACTOR</span></code> determines how fast/slow in-game time runs compared to the real world. The
|
||||
setting <code class="docutils literal notranslate"><span class="pre">TIME_GAME_EPOCH</span></code> sets the starting game epoch (in seconds). The functions from the
|
||||
<code class="docutils literal notranslate"><span class="pre">gametime</span></code> module all return their times in seconds. You can convert this to whatever units of time
|
||||
you desire for your game. You can use the <code class="docutils literal notranslate"><span class="pre">@time</span></code> command to view the server time info.</p>
|
||||
<p>You can also <em>schedule</em> things to happen at specific in-game times using the
|
||||
<a class="reference 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>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7</pre></div></td><td class="code"><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">"Limbo"</span><span class="p">)</span>
|
||||
<span class="n">limbo</span><span class="o">.</span><span class="n">msg_contents</span><span class="p">(</span><span class="s2">"The church clock chimes two."</span><span class="p">)</span>
|
||||
|
||||
<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>
|
||||
<div class="section" id="utils-time-format">
|
||||
<h3>utils.time_format()<a class="headerlink" href="#utils-time-format" title="Permalink to this headline">¶</a></h3>
|
||||
<p>This function takes a number of seconds as input (e.g. from the <code class="docutils literal notranslate"><span class="pre">gametime</span></code> module above) and
|
||||
converts it to a nice text output in days, hours etc. It’s useful when you want to show how old
|
||||
something is. It converts to four different styles of output using the <em>style</em> keyword:</p>
|
||||
<ul class="simple">
|
||||
<li><p>style 0 - <code class="docutils literal notranslate"><span class="pre">5d:45m:12s</span></code> (standard colon output)</p></li>
|
||||
<li><p>style 1 - <code class="docutils literal notranslate"><span class="pre">5d</span></code> (shows only the longest time unit)</p></li>
|
||||
<li><p>style 2 - <code class="docutils literal notranslate"><span class="pre">5</span> <span class="pre">days,</span> <span class="pre">45</span> <span class="pre">minutes</span></code> (full format, ignores seconds)</p></li>
|
||||
<li><p>style 3 - <code class="docutils literal notranslate"><span class="pre">5</span> <span class="pre">days,</span> <span class="pre">45</span> <span class="pre">minutes,</span> <span class="pre">12</span> <span class="pre">seconds</span></code> (full format, with seconds)</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="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>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9</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>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_callback</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">text</span><span class="p">):</span>
|
||||
<span class="n">obj</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># wait 10 seconds before sending "Echo!" to obj (which we assume is defined)</span>
|
||||
<span class="n">deferred</span> <span class="o">=</span> <span class="n">utils</span><span class="o">.</span><span class="n">delay</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="n">_callback</span><span class="p">,</span> <span class="n">obj</span><span class="p">,</span> <span class="s2">"Echo!"</span><span class="p">,</span> <span class="n">persistent</span><span class="o">=</span><span class="bp">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>
|
||||
<p>This creates an asynchronous delayed call. It will fire the given callback function after the given
|
||||
number of seconds. This is a very light wrapper over a Twisted
|
||||
<a class="reference external" href="https://twistedmatrix.com/documents/current/core/howto/defer.html">Deferred</a>. Normally this is run
|
||||
non-persistently, which means that if the server is <code class="docutils literal notranslate"><span class="pre">@reload</span></code>ed before the delay is over, the
|
||||
callback will never run (the server forgets it). If setting <code class="docutils literal notranslate"><span class="pre">persistent</span></code> to True, the delay will be
|
||||
stored in the database and survive a <code class="docutils literal notranslate"><span class="pre">@reload</span></code> - but for this to work it is susceptible to the same
|
||||
limitations incurred when saving to an <a class="reference internal" href="Attributes.html"><span class="doc">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>
|
||||
<blockquote>
|
||||
<div><p>Note that many delayed effects can be achieved without any need for an active timer. For example
|
||||
if you have a trait that should recover a point every 5 seconds you might just need its value when
|
||||
it’s needed, but checking the current time and calculating on the fly what value it should have.</p>
|
||||
</div></blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="object-classes">
|
||||
<h2>Object Classes<a class="headerlink" href="#object-classes" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="section" id="utils-inherits-from">
|
||||
<h3>utils.inherits_from()<a class="headerlink" href="#utils-inherits-from" title="Permalink to this headline">¶</a></h3>
|
||||
<p>This useful function takes two arguments - an object to check and a parent. It returns <code class="docutils literal notranslate"><span class="pre">True</span></code> if
|
||||
object inherits from parent <em>at any distance</em> (as opposed to Python’s in-built <code class="docutils literal notranslate"><span class="pre">is_instance()</span></code> that
|
||||
will only catch immediate dependence). This function also accepts as input any combination of
|
||||
classes, instances or python-paths-to-classes.</p>
|
||||
<p>Note that Python code should usually work with <a class="reference external" href="http://en.wikipedia.org/wiki/Duck_typing">duck
|
||||
typing</a>. But in Evennia’s case it can sometimes be useful
|
||||
to check if an object inherits from a given <a class="reference internal" href="Typeclasses.html"><span class="doc">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>1
|
||||
2
|
||||
3</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>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="n">utils</span><span class="o">.</span><span class="n">inherits_from</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="s2">"typeclasses.objects.animals.Animal"</span><span class="p">):</span>
|
||||
<span class="n">obj</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"The bouncer stops you in the door. He says: 'No talking animals allowed.'"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="text-utilities">
|
||||
<h2>Text utilities<a class="headerlink" href="#text-utilities" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In a text game, you are naturally doing a lot of work shuffling text back and forth. Here is a <em>non-
|
||||
complete</em> selection of text utilities found in <code class="docutils literal notranslate"><span class="pre">evennia/utils/utils.py</span></code> (shortcut <code class="docutils literal notranslate"><span class="pre">evennia.utils</span></code>).
|
||||
If nothing else it can be good to look here before starting to develop a solution of your own.</p>
|
||||
<div class="section" id="utils-fill">
|
||||
<h3>utils.fill()<a class="headerlink" href="#utils-fill" title="Permalink to this headline">¶</a></h3>
|
||||
<p>This flood-fills a text to a given width (shuffles the words to make each line evenly wide). It also
|
||||
indents as needed.</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1</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>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
</div>
|
||||
<div class="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>1
|
||||
2
|
||||
3</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">intxt</span> <span class="o">=</span> <span class="s2">"This is a long text that we want to crop."</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">"[...]"</span><span class="p">)</span>
|
||||
<span class="c1"># outtxt is now "This is a long text[...]"</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
</div>
|
||||
<div class="section" id="utils-dedent">
|
||||
<h3>utils.dedent()<a class="headerlink" href="#utils-dedent" title="Permalink to this headline">¶</a></h3>
|
||||
<p>This solves what may at first glance appear to be a trivial problem with text - removing
|
||||
indentations. It is used to shift entire paragraphs to the left, without disturbing any further
|
||||
formatting they may have. A common case for this is when using Python triple-quoted strings in code</p>
|
||||
<ul class="simple">
|
||||
<li><p>they will retain whichever indentation they have in the code, and to make easily-readable source
|
||||
code one usually don’t want to shift the string to the left edge.</p></li>
|
||||
</ul>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1">#python code is entered at a given indentation</span>
|
||||
<span class="n">intxt</span> <span class="o">=</span> <span class="s2">"""</span>
|
||||
<span class="s2"> This is an example text that will end</span>
|
||||
<span class="s2"> up with a lot of whitespace on the left.</span>
|
||||
<span class="s2"> It also has indentations of</span>
|
||||
<span class="s2"> its own."""</span>
|
||||
<span class="n">outtxt</span> <span class="o">=</span> <span class="n">dedent</span><span class="p">(</span><span class="n">intxt</span><span class="p">)</span>
|
||||
<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>
|
||||
<p>Normally you do the dedent in the display code (this is for example how the help system homogenizes
|
||||
help entries).</p>
|
||||
</div>
|
||||
<div class="section" id="to-str-and-to-bytes">
|
||||
<h3>to_str() and to_bytes()<a class="headerlink" href="#to-str-and-to-bytes" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Evennia supplies two utility functions for converting text to the correct
|
||||
encodings. <code class="docutils literal notranslate"><span class="pre">to_str()</span></code> and <code class="docutils literal notranslate"><span class="pre">to_bytes()</span></code>. Unless you are adding a custom protocol and
|
||||
need to send byte-data over the wire, <code class="docutils literal notranslate"><span class="pre">to_str</span></code> is the only one you’ll need.</p>
|
||||
<p>The difference from Python’s in-built <code class="docutils literal notranslate"><span class="pre">str()</span></code> and <code class="docutils literal notranslate"><span class="pre">bytes()</span></code> operators are that
|
||||
the Evennia ones makes use of the <code class="docutils literal notranslate"><span class="pre">ENCODINGS</span></code> setting and will try very hard to
|
||||
never raise a traceback but instead echo errors through logging. See
|
||||
<a class="reference internal" href="../Concepts/Text-Encodings.html"><span class="doc">here</span></a> for more info.</p>
|
||||
</div>
|
||||
<div class="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>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="display-utilities">
|
||||
<h2>Display utilities<a class="headerlink" href="#display-utilities" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="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
|
||||
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
|
||||
text template from a file in order to create any level of sophisticated ascii layout. Both evtable
|
||||
and evform have lots of options and inputs so see the header of each module for help.</p>
|
||||
<p>The third-party <a class="reference external" href="https://code.google.com/p/prettytable/">PrettyTable</a> module is also included in
|
||||
Evennia. PrettyTable is considered deprecated in favor of EvTable since PrettyTable cannot handle
|
||||
ANSI colour. PrettyTable can be found in <code class="docutils literal notranslate"><span class="pre">evennia/utils/prettytable/</span></code>. See its homepage above for
|
||||
instructions.</p>
|
||||
</div>
|
||||
<div class="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>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Coding Utils</a><ul>
|
||||
<li><a class="reference internal" href="#searching">Searching</a></li>
|
||||
<li><a class="reference internal" href="#create">Create</a></li>
|
||||
<li><a class="reference internal" href="#logging">Logging</a></li>
|
||||
<li><a class="reference internal" href="#time-utilities">Time Utilities</a><ul>
|
||||
<li><a class="reference internal" href="#game-time">Game time</a></li>
|
||||
<li><a class="reference internal" href="#utils-time-format">utils.time_format()</a></li>
|
||||
<li><a class="reference internal" href="#utils-delay">utils.delay()</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#object-classes">Object Classes</a><ul>
|
||||
<li><a class="reference internal" href="#utils-inherits-from">utils.inherits_from()</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#text-utilities">Text utilities</a><ul>
|
||||
<li><a class="reference internal" href="#utils-fill">utils.fill()</a></li>
|
||||
<li><a class="reference internal" href="#utils-crop">utils.crop()</a></li>
|
||||
<li><a class="reference internal" href="#utils-dedent">utils.dedent()</a></li>
|
||||
<li><a class="reference internal" href="#to-str-and-to-bytes">to_str() and to_bytes()</a></li>
|
||||
<li><a class="reference internal" href="#ansi-coloring-tools">Ansi Coloring Tools</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#display-utilities">Display utilities</a><ul>
|
||||
<li><a class="reference internal" href="#making-ascii-tables">Making ascii tables</a></li>
|
||||
<li><a class="reference internal" href="#menus">Menus</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Components/Coding-Utils.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Coding-Utils.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Coding Utils</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
512
docs/1.0-dev/Components/Command-Sets.html
Normal file
512
docs/1.0-dev/Components/Command-Sets.html
Normal file
|
|
@ -0,0 +1,512 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Command Sets — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Command Sets</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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
|
||||
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
|
||||
classes in a command set is the way to make commands available to use in your game.</p>
|
||||
<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">@dig</span></code> and <code class="docutils literal notranslate"><span class="pre">@reload</span></code>
|
||||
(<a class="reference external" href="Components/Locks.html#Permissions">permissions</a> then limit which players may use them, but that’s 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
|
||||
create a single “merged” cmdset, representing the pool of commands available at that very moment.</p>
|
||||
<p>An example would be a <code class="docutils literal notranslate"><span class="pre">Window</span></code> object that has a cmdset with two commands in it: <code class="docutils literal notranslate"><span class="pre">look</span> <span class="pre">through</span> <span class="pre">window</span></code> and <code class="docutils literal notranslate"><span class="pre">open</span> <span class="pre">window</span></code>. The command set would be visible to players in the room with the window,
|
||||
allowing them to use those commands only there. You could imagine all sorts of clever uses of this,
|
||||
like a <code class="docutils literal notranslate"><span class="pre">Television</span></code> object which had multiple commands for looking at it, switching channels and so
|
||||
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
|
||||
without the explanations.</p>
|
||||
<div class="section" id="defining-command-sets">
|
||||
<h2>Defining Command Sets<a class="headerlink" href="#defining-command-sets" title="Permalink to this headline">¶</a></h2>
|
||||
<p>A CmdSet is, as most things in Evennia, defined as a Python class inheriting from the correct parent
|
||||
(<code class="docutils literal notranslate"><span class="pre">evennia.CmdSet</span></code>, which is a shortcut to <code class="docutils literal notranslate"><span class="pre">evennia.commands.cmdset.CmdSet</span></code>). The CmdSet class only
|
||||
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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15
|
||||
16
|
||||
17</pre></div></td><td class="code"><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>
|
||||
|
||||
<span class="c1"># this is a theoretical custom module with commands we </span>
|
||||
<span class="c1"># created previously: mygame/commands/mycommands.py</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>
|
||||
<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="sd">"""</span>
|
||||
<span class="sd"> The only thing this method should need</span>
|
||||
<span class="sd"> to do is to add commands to the set.</span>
|
||||
<span class="sd"> """</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">MyCommand1</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">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>
|
||||
<p>The CmdSet’s <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>1
|
||||
2
|
||||
3
|
||||
4</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>
|
||||
<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>
|
||||
<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>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>You should now be able to use the command.</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">@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>1</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">'commands.mycmdset.MyCmdSet'</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<p>This will stay with you until you <code class="docutils literal notranslate"><span class="pre">@reset</span></code> or <code class="docutils literal notranslate"><span class="pre">@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>1</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">'commands.mycmdset.MyCmdSet'</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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>
|
||||
<div><p>Note: Command sets added using <code class="docutils literal notranslate"><span class="pre">cmdset.add</span></code> are, by default, <em>not</em> persistent in the database.</p>
|
||||
</div></blockquote>
|
||||
<p>If you want the cmdset to survive a reload, you can do:</p>
|
||||
<div class="highlight-default 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="n">commands</span><span class="o">.</span><span class="n">mycmdset</span><span class="o">.</span><span class="n">MyCmdSet</span><span class="p">,</span> <span class="n">permanent</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Or you could add the cmdset as the <em>default</em> cmdset:</p>
|
||||
<div class="highlight-default 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_default</span><span class="p">(</span><span class="n">commands</span><span class="o">.</span><span class="n">mycmdset</span><span class="o">.</span><span class="n">MyCmdSet</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>An object can only have one “default” cmdset (but can also have none). This is meant as a safe fall-
|
||||
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
|
||||
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
|
||||
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
|
||||
your own. Otherwise, you may accidentally “hide” your own command in your command set when adding a
|
||||
new one that has a matching alias.</p>
|
||||
</div></blockquote>
|
||||
<div class="section" id="properties-on-command-sets">
|
||||
<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-
|
||||
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
|
||||
for display in lists, but also to identify special merging behaviours using the <code class="docutils literal notranslate"><span class="pre">key_mergetype</span></code>
|
||||
dictionary below.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">mergetype</span></code> (string) - allows for one of the following string values: “<em>Union</em>”, “<em>Intersect</em>”,
|
||||
“<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
|
||||
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>
|
||||
<ul>
|
||||
<li><p>EmptySet: <code class="docutils literal notranslate"><span class="pre">-101</span></code> (should be lower than all other sets)</p></li>
|
||||
<li><p>SessionCmdSet: <code class="docutils literal notranslate"><span class="pre">-20</span></code></p></li>
|
||||
<li><p>AccountCmdSet: <code class="docutils literal notranslate"><span class="pre">-10</span></code></p></li>
|
||||
<li><p>CharacterCmdSet: <code class="docutils literal notranslate"><span class="pre">0</span></code></p></li>
|
||||
<li><p>ExitCmdSet: <code class="docutils literal notranslate"> <span class="pre">101</span></code> (generally should always be available)</p></li>
|
||||
<li><p>ChannelCmdSet: <code class="docutils literal notranslate"><span class="pre">101</span></code> (should usually always be available) - since exits never accept
|
||||
arguments, there is no collision between exits named the same as a channel even though the commands
|
||||
“collide”.</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
<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
|
||||
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
|
||||
the cmdset with this option onto one other cmdset with the same priority. The resulting cmdset will
|
||||
<em>not</em> retain this <code class="docutils literal notranslate"><span class="pre">duplicate</span></code> setting.</p>
|
||||
<ul>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">None</span></code> (default): No duplicates are allowed and the cmdset being merged “onto” the old one
|
||||
will take precedence. The result will be unique commands. <em>However</em>, the system will assume this
|
||||
value to be <code class="docutils literal notranslate"><span class="pre">True</span></code> for cmdsets on Objects, to avoid dangerous clashes. This is usually the safe bet.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">False</span></code>: Like <code class="docutils literal notranslate"><span class="pre">None</span></code> except the system will not auto-assume any value for cmdsets defined on
|
||||
Objects.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">True</span></code>: Same-named, same-prio commands will merge into the same cmdset. This will lead to a
|
||||
multimatch error (the user will get a list of possibilities in order to specify which command they
|
||||
meant). This is is useful e.g. for on-object cmdsets (example: There is a <code class="docutils literal notranslate"><span class="pre">red</span> <span class="pre">button</span></code> and a <code class="docutils literal notranslate"><span class="pre">green</span> <span class="pre">button</span></code> in the room. Both have a <code class="docutils literal notranslate"><span class="pre">press</span> <span class="pre">button</span></code> command, in cmdsets with the same priority. This
|
||||
flag makes sure that just writing <code class="docutils literal notranslate"><span class="pre">press</span> <span class="pre">button</span></code> will force the Player to define just which object’s
|
||||
command was intended).</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">no_objs</span></code> this is a flag for the cmdhandler that builds the set of commands available at every
|
||||
moment. It tells the handler not to include cmdsets from objects around the account (nor from rooms
|
||||
or inventory) when building the merged set. Exit commands will still be included. This option can
|
||||
have three values:</p>
|
||||
<ul>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">None</span></code> (default): Passthrough of any value set explicitly earlier in the merge stack. If never
|
||||
set explicitly, this acts as <code class="docutils literal notranslate"><span class="pre">False</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">True</span></code>/<code class="docutils literal notranslate"><span class="pre">False</span></code>: Explicitly turn on/off. If two sets with explicit <code class="docutils literal notranslate"><span class="pre">no_objs</span></code> are merged,
|
||||
priority determines what is used.</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">no_exits</span></code> - this is a flag for the cmdhandler that builds the set of commands available at every
|
||||
moment. It tells the handler not to include cmdsets from exits. This flag can have three values:</p>
|
||||
<ul>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">None</span></code> (default): Passthrough of any value set explicitly earlier in the merge stack. If
|
||||
never set explicitly, this acts as <code class="docutils literal notranslate"><span class="pre">False</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">True</span></code>/<code class="docutils literal notranslate"><span class="pre">False</span></code>: Explicitly turn on/off. If two sets with explicit <code class="docutils literal notranslate"><span class="pre">no_exits</span></code> are merged,
|
||||
priority determines what is used.</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">no_channels</span></code> (bool) - this is a flag for the cmdhandler that builds the set of commands available
|
||||
at every moment. It tells the handler not to include cmdsets from available in-game channels. This
|
||||
flag can have three values:</p>
|
||||
<ul>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">None</span></code> (default): Passthrough of any value set explicitly earlier in the merge stack. If
|
||||
never set explicitly, this acts as <code class="docutils literal notranslate"><span class="pre">False</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">True</span></code>/<code class="docutils literal notranslate"><span class="pre">False</span></code>: Explicitly turn on/off. If two sets with explicit <code class="docutils literal notranslate"><span class="pre">no_channels</span></code> are merged,
|
||||
priority determines what is used.</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="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-
|
||||
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
|
||||
<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
|
||||
<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>
|
||||
<li><p>The cmdsets of all objects carried by the puppeted Character (checks the <code class="docutils literal notranslate"><span class="pre">call</span></code> lock). Will not be
|
||||
included if <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 the Character’s current location (checks the <code class="docutils literal notranslate"><span class="pre">call</span></code> lock). Will not be included if
|
||||
<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 objects in the current location (checks the <code class="docutils literal notranslate"><span class="pre">call</span></code> lock). Will not be included if
|
||||
<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
|
||||
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 Character’s
|
||||
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
|
||||
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>
|
||||
</div>
|
||||
<div class="section" id="adding-and-merging-command-sets">
|
||||
<h2>Adding and Merging Command Sets<a class="headerlink" href="#adding-and-merging-command-sets" title="Permalink to this headline">¶</a></h2>
|
||||
<p><em>Note: This is an advanced topic. It’s very useful to know about, but you might want to skip it if
|
||||
this is your first time learning about commands.</em></p>
|
||||
<p>CmdSets have the special ability that they can be <em>merged</em> together into new sets. Which of the
|
||||
ingoing commands end up in the merged set is defined by the <em>merge rule</em> and the relative
|
||||
<em>priorities</em> of the two sets. Removing the latest added set will restore things back to the way it
|
||||
was before the addition.</p>
|
||||
<p>CmdSets are non-destructively stored in a stack inside the cmdset handler on the object. This stack
|
||||
is parsed to create the “combined” cmdset active at the moment. CmdSets from other sources are also
|
||||
included in the merger such as those on objects in the same room (like buttons to press) or those
|
||||
introduced by state changes (such as when entering a menu). The cmdsets are all ordered after
|
||||
priority and then merged together in <em>reverse order</em>. That is, the higher priority will be merged
|
||||
“onto” lower-prio ones. By defining a cmdset with a merge-priority between that of two other sets,
|
||||
you will make sure it will be merged in between them.
|
||||
The very first cmdset in this stack is called the <em>Default cmdset</em> and is protected from accidental
|
||||
deletion. Running <code class="docutils literal notranslate"><span class="pre">obj.cmdset.delete()</span></code> will never delete the default set. Instead one should add
|
||||
new cmdsets on top of the default to “hide” it, as described below. Use the special
|
||||
<code class="docutils literal notranslate"><span class="pre">obj.cmdset.delete_default()</span></code> only if you really know what you are doing.</p>
|
||||
<p>CmdSet merging is an advanced feature useful for implementing powerful game effects. Imagine for
|
||||
example a player entering a dark room. You don’t want the player to be able to find everything in
|
||||
the room at a glance - maybe you even want them to have a hard time to find stuff in their backpack!
|
||||
You can then define a different CmdSet with commands that override the normal ones. While they are
|
||||
in the dark room, maybe the <code class="docutils literal notranslate"><span class="pre">look</span></code> and <code class="docutils literal notranslate"><span class="pre">inv</span></code> commands now just tell the player they cannot see
|
||||
anything! Another example would be to offer special combat commands only when the player is in
|
||||
combat. Or when being on a boat. Or when having taken the super power-up. All this can be done on
|
||||
the fly by merging command sets.</p>
|
||||
<div class="section" id="merge-rules">
|
||||
<h3>Merge Rules<a class="headerlink" href="#merge-rules" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Basic rule is that command sets are merged in <em>reverse priority order</em>. That is, lower-prio sets are
|
||||
merged first and higher prio sets are merged “on top” of them. Think of it like a layered cake with
|
||||
the highest priority on top.</p>
|
||||
<p>To further understand how sets merge, we need to define some examples. Let’s call the first command
|
||||
set <strong>A</strong> and the second <strong>B</strong>. We assume <strong>B</strong> is the command set already active on our object and
|
||||
we will merge <strong>A</strong> onto <strong>B</strong>. In code terms this would be done by <code class="docutils literal notranslate"><span class="pre">object.cdmset.add(A)</span></code>.
|
||||
Remember, B is already active on <code class="docutils literal notranslate"><span class="pre">object</span></code> from before.</p>
|
||||
<p>We let the <strong>A</strong> set have higher priority than <strong>B</strong>. A priority is simply an integer number. As
|
||||
seen in the list above, Evennia’s default cmdsets have priorities in the range <code class="docutils literal notranslate"><span class="pre">-101</span></code> to <code class="docutils literal notranslate"><span class="pre">120</span></code>. You
|
||||
are usually safe to use a priority of <code class="docutils literal notranslate"><span class="pre">0</span></code> or <code class="docutils literal notranslate"><span class="pre">1</span></code> for most game effects.</p>
|
||||
<p>In our examples, both sets contain a number of commands which we’ll identify by numbers, like <code class="docutils literal notranslate"><span class="pre">A1,</span> <span class="pre">A2</span></code> for set <strong>A</strong> and <code class="docutils literal notranslate"><span class="pre">B1,</span> <span class="pre">B2,</span> <span class="pre">B3,</span> <span class="pre">B4</span></code> for <strong>B</strong>. So for that example both sets contain commands
|
||||
with the same keys (or aliases) “1” and “2” (this could for example be “look” and “get” in the real
|
||||
game), whereas commands 3 and 4 are unique to <strong>B</strong>. To describe a merge between these sets, we
|
||||
would write <code class="docutils literal notranslate"><span class="pre">A1,A2</span> <span class="pre">+</span> <span class="pre">B1,B2,B3,B4</span> <span class="pre">=</span> <span class="pre">?</span></code> where <code class="docutils literal notranslate"><span class="pre">?</span></code> is a list of commands that depend on which merge
|
||||
type <strong>A</strong> has, and which relative priorities the two sets have. By convention, we read this
|
||||
statement as “New command set <strong>A</strong> is merged onto the old command set <strong>B</strong> to form <strong>?</strong>”.</p>
|
||||
<p>Below are the available merge types and how they work. Names are partly borrowed from <a class="reference external" href="http://en.wikipedia.org/wiki/Set_theory">Set
|
||||
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>
|
||||
</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 one’s 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>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p><strong>Replace</strong> - The commands of the higher-prio cmdset completely replaces the lower-priority
|
||||
cmdset’s 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>
|
||||
</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>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Besides <code class="docutils literal notranslate"><span class="pre">priority</span></code> and <code class="docutils literal notranslate"><span class="pre">mergetype</span></code>, a command-set also takes a few other variables to control how
|
||||
they merge:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">duplicates</span></code> (bool) - determines what happens when two sets of equal priority merge. Default is
|
||||
that the new set in the merger (i.e. <strong>A</strong> above) automatically takes precedence. But if
|
||||
<em>duplicates</em> is true, the result will be a merger with more than one of each name match. This will
|
||||
usually lead to the player receiving a multiple-match error higher up the road, but can be good for
|
||||
things like cmdsets on non-player objects in a room, to allow the system to warn that more than one
|
||||
‘ball’ in the room has the same ‘kick’ command defined on it and offer a chance to select which
|
||||
ball to kick … Allowing duplicates only makes sense for <em>Union</em> and <em>Intersect</em>, the setting is
|
||||
ignored for the other mergetypes.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">key_mergetypes</span></code> (dict) - allows the cmdset to define a unique mergetype for particular cmdsets,
|
||||
identified by their cmdset <code class="docutils literal notranslate"><span class="pre">key</span></code>. Format is <code class="docutils literal notranslate"><span class="pre">{CmdSetkey:mergetype}</span></code>. Example:
|
||||
<code class="docutils literal notranslate"><span class="pre">{'Myevilcmdset','Replace'}</span></code> which would make sure for this set to always use ‘Replace’ on the
|
||||
cmdset with the key <code class="docutils literal notranslate"><span class="pre">Myevilcmdset</span></code> only, no matter what the main <code class="docutils literal notranslate"><span class="pre">mergetype</span></code> is set to.</p></li>
|
||||
</ul>
|
||||
<blockquote>
|
||||
<div><p>Warning: The <code class="docutils literal notranslate"><span class="pre">key_mergetypes</span></code> dictionary <em>can only work on the cmdset we merge onto</em>. When using
|
||||
<code class="docutils literal notranslate"><span class="pre">key_mergetypes</span></code> it is thus important to consider the merge priorities - you must make sure that you
|
||||
pick a priority <em>between</em> the cmdset you want to detect and the next higher one, if any. That is, if
|
||||
we define a cmdset with a high priority and set it to affect a cmdset that is far down in the merge
|
||||
stack, we would not “see” that set when it’s time for us to merge. Example: Merge stack is
|
||||
<code class="docutils literal notranslate"><span class="pre">A(prio=-10),</span> <span class="pre">B(prio=-5),</span> <span class="pre">C(prio=0),</span> <span class="pre">D(prio=5)</span></code>. We now merge a cmdset <code class="docutils literal notranslate"><span class="pre">E(prio=10)</span></code> onto this stack,
|
||||
with a <code class="docutils literal notranslate"><span class="pre">key_mergetype={"B":"Replace"}</span></code>. But priorities dictate that we won’t be merged onto B, we
|
||||
will be merged onto E (which is a merger of the lower-prio sets at this point). Since we are merging
|
||||
onto E and not B, our <code class="docutils literal notranslate"><span class="pre">key_mergetype</span></code> directive won’t trigger. To make sure it works we must make
|
||||
sure we merge onto B. Setting E’s priority to, say, -4 will make sure to merge it onto B and affect
|
||||
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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15
|
||||
16
|
||||
17</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>
|
||||
|
||||
<span class="k">class</span> <span class="nc">MyCmdSet</span><span class="p">(</span><span class="n">CmdSet</span><span class="p">):</span>
|
||||
|
||||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"MyCmdSet"</span>
|
||||
<span class="n">priority</span> <span class="o">=</span> <span class="mi">4</span>
|
||||
<span class="n">mergetype</span> <span class="o">=</span> <span class="s2">"Replace"</span>
|
||||
<span class="n">key_mergetypes</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'MyOtherCmdSet'</span><span class="p">:</span><span class="s1">'Union'</span><span class="p">}</span>
|
||||
|
||||
<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="sd">"""</span>
|
||||
<span class="sd"> The only thing this method should need</span>
|
||||
<span class="sd"> to do is to add commands to the set.</span>
|
||||
<span class="sd"> """</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">MyCommand1</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">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>
|
||||
<div class="section" id="assorted-notes">
|
||||
<h3>Assorted Notes<a class="headerlink" href="#assorted-notes" title="Permalink to this headline">¶</a></h3>
|
||||
<p>It is very important to remember that two commands are compared <em>both</em> by their <code class="docutils literal notranslate"><span class="pre">key</span></code> properties
|
||||
<em>and</em> by their <code class="docutils literal notranslate"><span class="pre">aliases</span></code> properties. If either keys or one of their aliases match, the two commands
|
||||
are considered the <em>same</em>. So consider these two Commands:</p>
|
||||
<ul class="simple">
|
||||
<li><p>A Command with key “kick” and alias “fight”</p></li>
|
||||
<li><p>A Command with key “punch” also with an alias “fight”</p></li>
|
||||
</ul>
|
||||
<p>During the cmdset merging (which happens all the time since also things like channel commands and
|
||||
exits are merged in), these two commands will be considered <em>identical</em> since they share alias. It
|
||||
means only one of them will remain after the merger. Each will also be compared with all other
|
||||
commands having any combination of the keys and/or aliases “kick”, “punch” or “fight”.</p>
|
||||
<p>… So avoid duplicate aliases, it will only cause confusion.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Command Sets</a><ul>
|
||||
<li><a class="reference internal" href="#defining-command-sets">Defining Command Sets</a><ul>
|
||||
<li><a class="reference internal" href="#properties-on-command-sets">Properties on Command Sets</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#command-sets-searched">Command Sets Searched</a></li>
|
||||
<li><a class="reference internal" href="#adding-and-merging-command-sets">Adding and Merging Command Sets</a><ul>
|
||||
<li><a class="reference internal" href="#merge-rules">Merge Rules</a></li>
|
||||
<li><a class="reference internal" href="#assorted-notes">Assorted Notes</a></li>
|
||||
</ul>
|
||||
</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/Command-Sets.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Command-Sets.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Command Sets</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
108
docs/1.0-dev/Components/Command-System.html
Normal file
108
docs/1.0-dev/Components/Command-System.html
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Command System — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Command System</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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>
|
||||
</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>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
<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>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Components/Command-System.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Command-System.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Command System</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
885
docs/1.0-dev/Components/Commands.html
Normal file
885
docs/1.0-dev/Components/Commands.html
Normal file
|
|
@ -0,0 +1,885 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Commands — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Commands</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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
|
||||
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>@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 @
|
||||
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>
|
||||
<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>
|
||||
<li><p>A <em>Command Set</em> (often referred to as a CmdSet or cmdset) is like a container for one or more
|
||||
Commands. A given Command can go into any number of different command sets. Only by putting the
|
||||
command set on a character object you will make all the commands therein available to use by that
|
||||
character. You can also store command sets on normal objects if you want users to be able to use the
|
||||
object in various ways. Consider a “Tree” object with a cmdset defining the commands <em>climb</em> and
|
||||
<em>chop down</em>. Or a “Clock” with a cmdset containing the single command <em>check time</em>.</p></li>
|
||||
</ol>
|
||||
<p>This page goes into full detail about how to use Commands. To fully use them you must also read the
|
||||
page detailing <a class="reference internal" href="Command-Sets.html"><span class="doc">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
|
||||
extra explanations.</p>
|
||||
<div class="section" id="defining-commands">
|
||||
<h2>Defining Commands<a class="headerlink" href="#defining-commands" title="Permalink to this headline">¶</a></h2>
|
||||
<p>All commands are implemented as normal Python classes inheriting from the base class <code class="docutils literal notranslate"><span class="pre">Command</span></code>
|
||||
(<code class="docutils literal notranslate"><span class="pre">evennia.Command</span></code>). You will find that this base class is very “bare”. The default commands of
|
||||
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 we’ll 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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12</pre></div></td><td class="code"><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>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> This is the help-text for the command</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"mycommand"</span>
|
||||
<span class="k">def</span> <span class="nf">parse</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="c1"># parsing the command line here</span>
|
||||
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="c1"># executing the command here</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8</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>
|
||||
|
||||
<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">"echo"</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="c1"># echo the caller'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="s2">"Echo: {}"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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
|
||||
instance of this class and uses that instance whenever you use this command - it also dynamically
|
||||
assigns the new command instance a few useful properties that you can assume to always be available.</p>
|
||||
<div class="section" id="who-is-calling-the-command">
|
||||
<h3>Who is calling the command?<a class="headerlink" href="#who-is-calling-the-command" title="Permalink to this headline">¶</a></h3>
|
||||
<p>In Evennia there are three types of objects that may call the command. It is important to be aware
|
||||
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
|
||||
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
|
||||
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">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>
|
||||
</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
|
||||
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
|
||||
Session info this can only be determined in <code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE=0</span></code> or <code class="docutils literal notranslate"><span class="pre">1</span></code>). If no puppet is found,
|
||||
this is equal to <code class="docutils literal notranslate"><span class="pre">account</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">session</span></code> - <code class="docutils literal notranslate"><span class="pre">None*</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">sessid</span></code> - <code class="docutils literal notranslate"><span class="pre">None*</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">account</span></code> - 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
|
||||
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>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">session</span></code> - <code class="docutils literal notranslate"><span class="pre">None*</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">sessid</span></code> - <code class="docutils literal notranslate"><span class="pre">None*</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">account</span></code> - <code class="docutils literal notranslate"><span class="pre">None</span></code></p></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<blockquote>
|
||||
<div><p><code class="docutils literal notranslate"><span class="pre">*)</span></code>: There is a way to make the Session available also inside tests run directly on Accounts and
|
||||
Objects, and that is to pass it to <code class="docutils literal notranslate"><span class="pre">execute_cmd</span></code> like so: <code class="docutils literal notranslate"><span class="pre">account.execute_cmd("...",</span> <span class="pre">session=<Session>)</span></code>. Doing so <em>will</em> make the <code class="docutils literal notranslate"><span class="pre">.session</span></code> and <code class="docutils literal notranslate"><span class="pre">.sessid</span></code> properties available in the
|
||||
command.</p>
|
||||
</div></blockquote>
|
||||
</div>
|
||||
<div class="section" id="properties-assigned-to-the-command-instance-at-run-time">
|
||||
<h3>Properties assigned to the command instance at run-time<a class="headerlink" href="#properties-assigned-to-the-command-instance-at-run-time" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Let’s say account <em>Bob</em> with a character <em>BigGuy</em> enters the command <em>look at sword</em>. After the
|
||||
system having successfully identified this as the “look” command and determined that BigGuy really
|
||||
has access to a command named <code class="docutils literal notranslate"><span class="pre">look</span></code>, it chugs the <code class="docutils literal notranslate"><span class="pre">look</span></code> command class out of storage and either
|
||||
loads an existing Command instance from cache or creates one. After some more checks it then assigns
|
||||
it the following properties:</p>
|
||||
<ul class="simple">
|
||||
<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
|
||||
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">cmdstring</span></code> - the matched key for the command. This would be <em>look</em> in our example.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">args</span></code> - this is the rest of the string, except the command name. So if the string entered was
|
||||
<em>look at sword</em>, <code class="docutils literal notranslate"><span class="pre">args</span></code> would be “ <em>at sword</em>”. Note the space kept - Evennia would correctly
|
||||
interpret <code class="docutils literal notranslate"><span class="pre">lookat</span> <span class="pre">sword</span></code> too. This is useful for things like <code class="docutils literal notranslate"><span class="pre">/switches</span></code> that should not use space.
|
||||
In the <code class="docutils literal notranslate"><span class="pre">MuxCommand</span></code> class used for default commands, this space is stripped. Also see the
|
||||
<code class="docutils literal notranslate"><span class="pre">arg_regex</span></code> property if you want to enforce a space to make <code class="docutils literal notranslate"><span class="pre">lookat</span> <span class="pre">sword</span></code> give a command-not-found
|
||||
error.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">obj</span></code> - the game <a class="reference internal" href="Objects.html"><span class="doc">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>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">cmdset</span></code> - this is a reference to the merged CmdSet (see below) from which this command was
|
||||
matched. This variable is rarely used, it’s main use is for the [auto-help system](Help-
|
||||
System#command-auto-help-system) (<em>Advanced note: the merged cmdset need NOT be the same as
|
||||
<code class="docutils literal notranslate"><span class="pre">BigGuy.cmdset</span></code>. The merged set can be a combination of the cmdsets from other objects in the room,
|
||||
for example</em>).</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">raw_string</span></code> - this is the raw input coming from the user, without stripping any surrounding
|
||||
whitespace. The only thing that is stripped is the ending newline marker.</p></li>
|
||||
</ul>
|
||||
<div class="section" id="other-useful-utility-methods">
|
||||
<h4>Other useful utility methods:<a class="headerlink" href="#other-useful-utility-methods" title="Permalink to this headline">¶</a></h4>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">.get_help(caller,</span> <span class="pre">cmdset)</span></code> - Get the help entry for this command. By default the arguments are
|
||||
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 client’s 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-
|
||||
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>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">.styled_header</span></code>, <code class="docutils literal notranslate"><span class="pre">_footer</span></code>, <code class="docutils literal notranslate"><span class="pre">separator</span></code> - These will produce styled decorations for
|
||||
display to the user. They are useful for creating listings and forms with colors adjustable per-
|
||||
user.</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="defining-your-own-command-classes">
|
||||
<h3>Defining your own command classes<a class="headerlink" href="#defining-your-own-command-classes" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Beyond the properties Evennia always assigns to the command at run-time (listed above), your job is
|
||||
to define the following class properties:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">key</span></code> (string) - the identifier for the command, like <code class="docutils literal notranslate"><span class="pre">look</span></code>. This should (ideally) be unique. A
|
||||
key can consist of more than one word, like “press button” or “pull left lever”. Note that <em>both</em>
|
||||
<code class="docutils literal notranslate"><span class="pre">key</span></code> and <code class="docutils literal notranslate"><span class="pre">aliases</span></code> below determine the identity of a command. So two commands are considered if
|
||||
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">["glance",</span> <span class="pre">"see",</span> <span class="pre">"l"]</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:<lockfuncs></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">"cmd:all()"</span></code>
|
||||
to make the command available to everyone (if you don’t provide a lock string, this will be assigned
|
||||
for you).</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">help_category</span></code> (optional string) - setting this helps to structure the auto-help into categories.
|
||||
If none is set, this will be set to <em>General</em>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">save_for_next</span></code> (optional boolean). This defaults to <code class="docutils literal notranslate"><span class="pre">False</span></code>. If <code class="docutils literal notranslate"><span class="pre">True</span></code>, a copy of this command
|
||||
object (along with any changes you have done to it) will be stored by the system and can be accessed
|
||||
by the next command by retrieving <code class="docutils literal notranslate"><span class="pre">self.caller.ndb.last_cmd</span></code>. The next run command will either clear
|
||||
or replace the storage.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">arg_regex</span></code> (optional raw string): Used to force the parser to limit itself and tell it when the
|
||||
command-name ends and arguments begin (such as requiring this to be a space or a /switch). This is
|
||||
done with a regular expression. <a class="reference external" href="Components/Commands.html#on-arg_regex">See the arg_regex section</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
|
||||
either want to write your help entries manually or hide the existence of a command from <code class="docutils literal notranslate"><span class="pre">help</span></code>’s
|
||||
generated list.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">is_exit</span></code> (bool) - this marks the command as being used for an in-game exit. This is, by default,
|
||||
set by all Exit objects and you should not need to set it manually unless you make your own Exit
|
||||
system. It is used for optimization and allows the cmdhandler to easily disregard this command when
|
||||
the cmdset has its <code class="docutils literal notranslate"><span class="pre">no_exits</span></code> flag set.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">is_channel</span></code> (bool)- this marks the command as being used for an in-game channel. This is, by
|
||||
default, set by all Channel objects and you should not need to set it manually unless you make your
|
||||
own Channel system. is used for optimization and allows the cmdhandler to easily disregard this
|
||||
command when its cmdset has its <code class="docutils literal notranslate"><span class="pre">no_channels</span></code> flag set.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">msg_all_sessions</span></code> (bool): This affects the behavior of the <code class="docutils literal notranslate"><span class="pre">Command.msg</span></code> method. If unset
|
||||
(default), calling <code class="docutils literal notranslate"><span class="pre">self.msg(text)</span></code> from the Command will always only send text to the Session that
|
||||
actually triggered this Command. If set however, <code class="docutils literal notranslate"><span class="pre">self.msg(text)</span></code> will send to all Sessions relevant
|
||||
to the object this Command sits on. Just which Sessions receives the text depends on the object and
|
||||
the server’s <code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE</span></code>.</p></li>
|
||||
</ul>
|
||||
<p>You should also implement at least two methods, <code class="docutils literal notranslate"><span class="pre">parse()</span></code> and <code class="docutils literal notranslate"><span class="pre">func()</span></code> (You could also implement
|
||||
<code class="docutils literal notranslate"><span class="pre">perm()</span></code>, but that’s not needed unless you want to fundamentally change how access checks work).</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">at_pre_cmd()</span></code> is called very first on the command. If this function returns anything that
|
||||
evaluates to <code class="docutils literal notranslate"><span class="pre">True</span></code> the command execution is aborted at this point.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">parse()</span></code> is intended to parse the arguments (<code class="docutils literal notranslate"><span class="pre">self.args</span></code>) of the function. You can do this in any
|
||||
way you like, then store the result(s) in variable(s) on the command object itself (i.e. on <code class="docutils literal notranslate"><span class="pre">self</span></code>).
|
||||
To take an example, the default mux-like system uses this method to detect “command switches” and
|
||||
store them as a list in <code class="docutils literal notranslate"><span class="pre">self.switches</span></code>. Since the parsing is usually quite similar inside a command
|
||||
scheme you should make <code class="docutils literal notranslate"><span class="pre">parse()</span></code> as generic as possible and then inherit from it rather than re-
|
||||
implementing it over and over. In this way, the default <code class="docutils literal notranslate"><span class="pre">MuxCommand</span></code> class implements a <code class="docutils literal notranslate"><span class="pre">parse()</span></code>
|
||||
for all child commands to use.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">func()</span></code> is called right after <code class="docutils literal notranslate"><span class="pre">parse()</span></code> and should make use of the pre-parsed input to actually
|
||||
do whatever the command is supposed to do. This is the main body of the command. The return value
|
||||
from this method will be returned from the execution as a Twisted Deferred.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">at_post_cmd()</span></code> is called after <code class="docutils literal notranslate"><span class="pre">func()</span></code> to handle eventual cleanup.</p></li>
|
||||
</ul>
|
||||
<p>Finally, you should always make an informative <a class="reference external" href="http://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 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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15
|
||||
16
|
||||
17
|
||||
18
|
||||
19
|
||||
20
|
||||
21
|
||||
22
|
||||
23
|
||||
24
|
||||
25
|
||||
26
|
||||
27
|
||||
28
|
||||
29
|
||||
30
|
||||
31
|
||||
32
|
||||
33
|
||||
34
|
||||
35
|
||||
36
|
||||
37
|
||||
38
|
||||
39
|
||||
40</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>
|
||||
|
||||
<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">"""</span>
|
||||
<span class="sd"> A smile command</span>
|
||||
|
||||
<span class="sd"> Usage:</span>
|
||||
<span class="sd"> smile [at] [<someone>]</span>
|
||||
<span class="sd"> grin [at] [<someone>]</span>
|
||||
|
||||
<span class="sd"> Smiles to someone in your vicinity or to the room</span>
|
||||
<span class="sd"> in general.</span>
|
||||
|
||||
<span class="sd"> (This initial string (the __doc__ string)</span>
|
||||
<span class="sd"> is also used to auto-generate the help</span>
|
||||
<span class="sd"> for this command)</span>
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"smile"</span>
|
||||
<span class="n">aliases</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"smile at"</span><span class="p">,</span> <span class="s2">"grin"</span><span class="p">,</span> <span class="s2">"grin at"</span><span class="p">]</span>
|
||||
<span class="n">locks</span> <span class="o">=</span> <span class="s2">"cmd:all()"</span>
|
||||
<span class="n">help_category</span> <span class="o">=</span> <span class="s2">"General"</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">parse</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="s2">"Very trivial parser"</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">target</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="s2">"This actually does things"</span>
|
||||
<span class="n">caller</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span>
|
||||
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">target</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">target</span> <span class="o">==</span> <span class="s2">"here"</span><span class="p">:</span>
|
||||
<span class="n">string</span> <span class="o">=</span> <span class="n">f</span><span class="s2">"{caller.key} smiles"</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="n">string</span> <span class="o">=</span> <span class="n">f</span><span class="s2">"{caller.key} smiles at {target.key}"</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>
|
||||
<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
|
||||
inherit from <code class="docutils literal notranslate"><span class="pre">MuxCommand</span></code>. <code class="docutils literal notranslate"><span class="pre">MuxCommand</span></code> implements its own version of <code class="docutils literal notranslate"><span class="pre">parse()</span></code>
|
||||
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>
|
||||
</div>
|
||||
<div class="section" id="on-arg-regex">
|
||||
<h3>On arg_regex<a class="headerlink" href="#on-arg-regex" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The command parser is very general and does not require a space to end your command name. This means
|
||||
that the alias <code class="docutils literal notranslate"><span class="pre">:</span></code> to <code class="docutils literal notranslate"><span class="pre">emote</span></code> can be used like <code class="docutils literal notranslate"><span class="pre">:smiles</span></code> without modification. It also means
|
||||
<code class="docutils literal notranslate"><span class="pre">getstone</span></code> will get you the stone (unless there is a command specifically named <code class="docutils literal notranslate"><span class="pre">getstone</span></code>, then
|
||||
that will be used). If you want to tell the parser to require a certain separator between the
|
||||
command name and its arguments (so that <code class="docutils literal notranslate"><span class="pre">get</span> <span class="pre">stone</span></code> works but <code class="docutils literal notranslate"><span class="pre">getstone</span></code> gives you a ‘command not
|
||||
found’ error) you can do so with the <code class="docutils literal notranslate"><span class="pre">arg_regex</span></code> property.</p>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">arg_regex</span></code> is a <a class="reference external" href="http://docs.python.org/library/re.html">raw regular expression string</a>. The
|
||||
regex will be compiled by the system at runtime. This allows you to customize how the part
|
||||
<em>immediately following</em> the command name (or alias) must look in order for the parser to match for
|
||||
this command. Some examples:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">commandname</span> <span class="pre">argument</span></code> (<code class="docutils literal notranslate"><span class="pre">arg_regex</span> <span class="pre">=</span> <span class="pre">r"\s.+"</span></code>): This forces the parser to require the command name
|
||||
to be followed by one or more spaces. Whatever is entered after the space will be treated as an
|
||||
argument. However, if you’d forget the space (like a command having no arguments), this would <em>not</em>
|
||||
match <code class="docutils literal notranslate"><span class="pre">commandname</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">commandname</span></code> or <code class="docutils literal notranslate"><span class="pre">commandname</span> <span class="pre">argument</span></code> (<code class="docutils literal notranslate"><span class="pre">arg_regex</span> <span class="pre">=</span> <span class="pre">r"\s.+|$"</span></code>): This makes both <code class="docutils literal notranslate"><span class="pre">look</span></code> and
|
||||
<code class="docutils literal notranslate"><span class="pre">look</span> <span class="pre">me</span></code> work but <code class="docutils literal notranslate"><span class="pre">lookme</span></code> will not.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">commandname/switches</span> <span class="pre">arguments</span></code> (<code class="docutils literal notranslate"><span class="pre">arg_regex</span> <span class="pre">=</span> <span class="pre">r"(?:^(?:\s+|\/).*$)|^$"</span></code>. If you are using
|
||||
Evennia’s <code class="docutils literal notranslate"><span class="pre">MuxCommand</span></code> Command parent, you may wish to use this since it will allow <code class="docutils literal notranslate"><span class="pre">/switche</span></code>s to
|
||||
work as well as having or not having a space.</p></li>
|
||||
</ul>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">arg_regex</span></code> allows you to customize the behavior of your commands. You can put it in the parent
|
||||
class of your command to customize all children of your Commands. However, you can also change the
|
||||
base default behavior for all Commands by modifying <code class="docutils literal notranslate"><span class="pre">settings.COMMAND_DEFAULT_ARG_REGEX</span></code>.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="exiting-a-command">
|
||||
<h2>Exiting a command<a class="headerlink" href="#exiting-a-command" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Normally you just use <code class="docutils literal notranslate"><span class="pre">return</span></code> in one of your Command class’ hook methods to exit that method. That
|
||||
will however still fire the other hook methods of the Command in sequence. That’s usually what you
|
||||
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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11</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>
|
||||
|
||||
<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="c1"># ...</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">parse</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="c1"># ...</span>
|
||||
<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>
|
||||
<div class="section" id="pauses-in-commands">
|
||||
<h2>Pauses in commands<a class="headerlink" href="#pauses-in-commands" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Sometimes you want to pause the execution of your command for a little while before continuing -
|
||||
maybe you want to simulate a heavy swing taking some time to finish, maybe you want the echo of your
|
||||
voice to return to you with an ever-longer delay. Since Evennia is running asynchronously, you
|
||||
cannot use <code class="docutils literal notranslate"><span class="pre">time.sleep()</span></code> in your commands (or anywhere, really). If you do, the <em>entire game</em> will
|
||||
be frozen for everyone! So don’t do that. Fortunately, Evennia offers a really quick syntax for
|
||||
making pauses in commands.</p>
|
||||
<p>In your <code class="docutils literal notranslate"><span class="pre">func()</span></code> method, you can use the <code class="docutils literal notranslate"><span class="pre">yield</span></code> keyword. This is a Python keyword that will freeze
|
||||
the current execution of your command and wait for more before processing.</p>
|
||||
<blockquote>
|
||||
<div><p>Note that you <em>cannot</em> just drop <code class="docutils literal notranslate"><span class="pre">yield</span></code> into any code and expect it to pause. Evennia will only
|
||||
pause for you if you <code class="docutils literal notranslate"><span class="pre">yield</span></code> inside the Command’s <code class="docutils literal notranslate"><span class="pre">func()</span></code> method. Don’t expect it to work anywhere
|
||||
else.</p>
|
||||
</div></blockquote>
|
||||
<p>Here’s 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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15
|
||||
16
|
||||
17
|
||||
18
|
||||
19
|
||||
20
|
||||
21
|
||||
22</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>
|
||||
|
||||
<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">"""</span>
|
||||
<span class="sd"> A dummy command to show how to wait</span>
|
||||
|
||||
<span class="sd"> Usage:</span>
|
||||
<span class="sd"> wait</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"wait"</span>
|
||||
<span class="n">locks</span> <span class="o">=</span> <span class="s2">"cmd:all()"</span>
|
||||
<span class="n">help_category</span> <span class="o">=</span> <span class="s2">"General"</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Command execution."""</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"Starting to wait ..."</span><span class="p">)</span>
|
||||
<span class="k">yield</span> <span class="mi">5</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"... This shows after 5 seconds. Waiting ..."</span><span class="p">)</span>
|
||||
<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">"... And now another 2 seconds have passed."</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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 Command’s <code class="docutils literal notranslate"><span class="pre">func</span></code> method:</p>
|
||||
<ol class="simple">
|
||||
<li><p>The paused state produced by the <code class="docutils literal notranslate"><span class="pre">yield</span></code> is not saved anywhere. So if the server reloads in the
|
||||
middle of your command pausing, it will <em>not</em> resume when the server comes back up - the remainder
|
||||
of the command will never fire. So be careful that you are not freezing the character or account in
|
||||
a way that will not be cleared on reload.</p></li>
|
||||
<li><p>If you use <code class="docutils literal notranslate"><span class="pre">yield</span></code> you may not also use <code class="docutils literal notranslate"><span class="pre">return</span> <span class="pre"><values></span></code> in your <code class="docutils literal notranslate"><span class="pre">func</span></code> method. You’ll get an
|
||||
error explaining this. This is due to how Python generators work. You can however use a “naked”
|
||||
<code class="docutils literal notranslate"><span class="pre">return</span></code> just fine. Usually there is no need for <code class="docutils literal notranslate"><span class="pre">func</span></code> to return a value, but if you ever do need
|
||||
to mix <code class="docutils literal notranslate"><span class="pre">yield</span></code> with a final return value in the same <code class="docutils literal notranslate"><span class="pre">func</span></code>, look at
|
||||
<a class="reference external" href="https://twistedmatrix.com/documents/current/api/twisted.internet.defer.html#returnValue">twisted.internet.defer.returnValue</a>.</p></li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="section" id="asking-for-user-input">
|
||||
<h2>Asking for user input<a class="headerlink" href="#asking-for-user-input" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">yield</span></code> keyword can also be used to ask for user input. Again you can’t
|
||||
use Python’s <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 Command’s
|
||||
<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>1</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">"Your question"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<p>Here’s a very simple example:</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15
|
||||
16
|
||||
17
|
||||
18</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>
|
||||
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> A dummy command to show confirmation.</span>
|
||||
|
||||
<span class="sd"> Usage:</span>
|
||||
<span class="sd"> confirm</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"confirm"</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="n">answer</span> <span class="o">=</span> <span class="k">yield</span><span class="p">(</span><span class="s2">"Are you sure you want to go on?"</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">answer</span><span class="o">.</span><span class="n">strip</span><span class="p">()</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">"yes"</span><span class="p">,</span> <span class="s2">"y"</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">"Yes!"</span><span class="p">)</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"No!"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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>
|
||||
</div></blockquote>
|
||||
</div>
|
||||
<div class="section" id="system-commands">
|
||||
<h2>System commands<a class="headerlink" href="#system-commands" title="Permalink to this headline">¶</a></h2>
|
||||
<p><em>Note: This is an advanced topic. Skip it if this is your first time learning about commands.</em></p>
|
||||
<p>There are several command-situations that are exceptional in the eyes of the server. What happens if
|
||||
the account enters an empty string? What if the ‘command’ given is infact the name of a channel the
|
||||
user wants to send a message to? Or if there are multiple command possibilities?</p>
|
||||
<p>Such ‘special cases’ are handled by what’s called <em>system commands</em>. A system command is defined
|
||||
in the same way as other commands, except that their name (key) must be set to one reserved by the
|
||||
engine (the names are defined at the top of <code class="docutils literal notranslate"><span class="pre">evennia/commands/cmdhandler.py</span></code>). You can find (unused)
|
||||
implementations of the system commands in <code class="docutils literal notranslate"><span class="pre">evennia/commands/default/system_commands.py</span></code>. Since these
|
||||
are not (by default) included in any <code class="docutils literal notranslate"><span class="pre">CmdSet</span></code> they are not actually used, they are just there for
|
||||
show. When the special situation occurs, Evennia will look through all valid <code class="docutils literal notranslate"><span class="pre">CmdSet</span></code>s for your
|
||||
custom system command. Only after that will it resort to its own, hard-coded implementation.</p>
|
||||
<p>Here are the exceptional situations that triggers system commands. You can find the command keys
|
||||
they use as properties on <code class="docutils literal notranslate"><span class="pre">evennia.syscmdkeys</span></code>:</p>
|
||||
<ul class="simple">
|
||||
<li><p>No input (<code class="docutils literal notranslate"><span class="pre">syscmdkeys.CMD_NOINPUT</span></code>) - the account just pressed return without any input. Default
|
||||
is to do nothing, but it can be useful to do something here for certain implementations such as line
|
||||
editors that interpret non-commands as text input (an empty line in the editing buffer).</p></li>
|
||||
<li><p>Command not found (<code class="docutils literal notranslate"><span class="pre">syscmdkeys.CMD_NOMATCH</span></code>) - No matching command was found. Default is to
|
||||
display the “Huh?” error message.</p></li>
|
||||
<li><p>Several matching commands where found (<code class="docutils literal notranslate"><span class="pre">syscmdkeys.CMD_MULTIMATCH</span></code>) - Default is to show a list of
|
||||
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
|
||||
subscribing to - Default is to relay the command’s 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
|
||||
<code class="docutils literal notranslate"><span class="pre">settings.CMDSET_UNLOGGEDIN</span></code>. Whenever a new connection is established, this command is always
|
||||
called on the server (default is to show the login screen).</p></li>
|
||||
</ul>
|
||||
<p>Below is an example of redefining what happens when the account doesn’t 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>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7</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>
|
||||
|
||||
<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">"Usage: Just press return, I dare you"</span>
|
||||
<span class="n">key</span> <span class="o">=</span> <span class="n">syscmdkeys</span><span class="o">.</span><span class="n">CMD_NOINPUT</span>
|
||||
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="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">"Don't just press return like that, talk to me!"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
</div>
|
||||
<div class="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>
|
||||
<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>1
|
||||
2
|
||||
3
|
||||
4</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">"newname"</span><span class="p">,</span>
|
||||
<span class="n">aliases</span><span class="o">=</span><span class="p">[</span><span class="s2">"test"</span><span class="p">,</span> <span class="s2">"test2"</span><span class="p">],</span>
|
||||
<span class="n">locks</span><span class="o">=</span><span class="s2">"cmd:all()"</span><span class="p">,</span>
|
||||
<span class="o">...</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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.
|
||||
But you could in principle also send method objects (like <code class="docutils literal notranslate"><span class="pre">func</span></code>) as keyword arguments in order to
|
||||
make your command completely customized at run-time.</p>
|
||||
</div>
|
||||
<div class="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
|
||||
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 exit’s
|
||||
destination.
|
||||
Whereas you could customize the Exit object and its command to achieve completely different
|
||||
behaviour, you will usually be fine just using the appropriate <code class="docutils literal notranslate"><span class="pre">traverse_*</span></code> hooks on the Exit
|
||||
object. But if you are interested in really changing how things work under the hood, check out
|
||||
<code class="docutils literal notranslate"><span class="pre">evennia/objects/objects.py</span></code> for how the <code class="docutils literal notranslate"><span class="pre">Exit</span></code> typeclass is set up.</p>
|
||||
</div>
|
||||
<div class="section" id="command-instances-are-re-used">
|
||||
<h2>Command instances are re-used<a class="headerlink" href="#command-instances-are-re-used" title="Permalink to this headline">¶</a></h2>
|
||||
<p><em>Note: This is an advanced topic that can be skipped when first learning about Commands.</em></p>
|
||||
<p>A Command class sitting on an object is instantiated once and then re-used. So if you run a command
|
||||
from object1 over and over you are in fact running the same command instance over and over (if you
|
||||
run the same command but sitting on object2 however, it will be a different instance). This is
|
||||
usually not something you’ll notice, since every time the Command-instance is used, all the relevant
|
||||
properties on it will be overwritten. But armed with this knowledge you can implement some of the
|
||||
more exotic command mechanism out there, like the command having a ‘memory’ of what you last entered
|
||||
so that you can back-reference the previous arguments etc.</p>
|
||||
<blockquote>
|
||||
<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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10</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>
|
||||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"testid"</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">"xval"</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">xval</span> <span class="o">=</span> <span class="mi">0</span>
|
||||
<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="s2">"Command memory ID: {} (xval={})"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">id</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">xval</span><span class="p">))</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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">></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>
|
||||
<span class="o">></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">2</span><span class="p">)</span>
|
||||
<span class="o">></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">3</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Note how the in-memory address of the <code class="docutils literal notranslate"><span class="pre">testid</span></code> command never changes, but <code class="docutils literal notranslate"><span class="pre">xval</span></code> keeps ticking up.</p>
|
||||
</div>
|
||||
<div class="section" id="dynamically-created-commands">
|
||||
<h2>Dynamically created commands<a class="headerlink" href="#dynamically-created-commands" title="Permalink to this headline">¶</a></h2>
|
||||
<p><em>This is also an advanced topic.</em></p>
|
||||
<p>Commands can also be created and added to a cmdset on the fly. Creating a class instance with a
|
||||
keyword argument, will assign that keyword argument as a property on this paricular command:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">MyCmdSet</span><span class="p">(</span><span class="n">CmdSet</span><span class="p">):</span>
|
||||
|
||||
<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">"test"</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>
|
||||
and <code class="docutils literal notranslate"><span class="pre">self.foo</span></code>). How they are used is up to the Command. Remember however the discussion from the
|
||||
previous section - since the Command instance is re-used, those properties will <em>remain</em> on the
|
||||
command as long as this cmdset and the object it sits is in memory (i.e. until the next reload).
|
||||
Unless <code class="docutils literal notranslate"><span class="pre">myvar</span></code> and <code class="docutils literal notranslate"><span class="pre">foo</span></code> are somehow reset when the command runs, they can be modified and that
|
||||
change will be remembered for subsequent uses of the command.</p>
|
||||
</div>
|
||||
<div class="section" id="how-commands-actually-work">
|
||||
<h2>How commands actually work<a class="headerlink" href="#how-commands-actually-work" title="Permalink to this headline">¶</a></h2>
|
||||
<p><em>Note: This is an advanced topic mainly of interest to server developers.</em></p>
|
||||
<p>Any time the user sends text to Evennia, the server tries to figure out if the text entered
|
||||
corresponds to a known command. This is how the command handler sequence looks for a logged-in user:</p>
|
||||
<ol class="simple">
|
||||
<li><p>A user enters a string of text and presses enter.</p></li>
|
||||
<li><p>The user’s Session determines the text is not some protocol-specific control sequence or OOB
|
||||
command, but sends it on to the command handler.</p></li>
|
||||
<li><p>Evennia’s <em>command handler</em> analyzes the Session and grabs eventual references to Account and
|
||||
eventual puppeted Characters (these will be stored on the command object later). The <em>caller</em>
|
||||
property is set appropriately.</p></li>
|
||||
<li><p>If input is an empty string, resend command as <code class="docutils literal notranslate"><span class="pre">CMD_NOINPUT</span></code>. If no such command is found in
|
||||
cmdset, ignore.</p></li>
|
||||
<li><p>If command.key matches <code class="docutils literal notranslate"><span class="pre">settings.IDLE_COMMAND</span></code>, update timers but don’t do anything more.</p></li>
|
||||
<li><p>The command handler gathers the CmdSets available to <em>caller</em> at this time:</p>
|
||||
<ul class="simple">
|
||||
<li><p>The caller’s own currently active CmdSet.</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>
|
||||
<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>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p>All CmdSets <em>of the same priority</em> are merged together in groups. Grouping avoids order-
|
||||
dependent issues of merging multiple same-prio sets onto lower ones.</p></li>
|
||||
<li><p>All the grouped CmdSets are <em>merged</em> in reverse priority into one combined CmdSet according to
|
||||
each set’s merge rules.</p></li>
|
||||
<li><p>Evennia’s <em>command parser</em> takes the merged cmdset and matches each of its commands (using its
|
||||
key and aliases) against the beginning of the string entered by <em>caller</em>. This produces a set of
|
||||
candidates.</p></li>
|
||||
<li><p>The <em>cmd parser</em> next rates the matches by how many characters they have and how many percent
|
||||
matches the respective known command. Only if candidates cannot be separated will it return multiple
|
||||
matches.</p>
|
||||
<ul class="simple">
|
||||
<li><p>If multiple matches were returned, resend as <code class="docutils literal notranslate"><span class="pre">CMD_MULTIMATCH</span></code>. If no such command is found in
|
||||
cmdset, return hard-coded list of matches.</p></li>
|
||||
<li><p>If no match was found, resend as <code class="docutils literal notranslate"><span class="pre">CMD_NOMATCH</span></code>. If no such command is found in cmdset, give
|
||||
hard-coded error message.</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p>If a single command was found by the parser, the correct command object is plucked out of
|
||||
storage. This usually doesn’t mean a re-initialization.</p></li>
|
||||
<li><p>It is checked that the caller actually has access to the command by validating the <em>lockstring</em>
|
||||
of the command. If not, it is not considered as a suitable match and <code class="docutils literal notranslate"><span class="pre">CMD_NOMATCH</span></code> is triggered.</p></li>
|
||||
<li><p>If the new command is tagged as a channel-command, resend as <code class="docutils literal notranslate"><span class="pre">CMD_CHANNEL</span></code>. If no such command
|
||||
is found in cmdset, use hard-coded implementation.</p></li>
|
||||
<li><p>Assign several useful variables to the command instance (see previous sections).</p></li>
|
||||
<li><p>Call <code class="docutils literal notranslate"><span class="pre">at_pre_command()</span></code> on the command instance.</p></li>
|
||||
<li><p>Call <code class="docutils literal notranslate"><span class="pre">parse()</span></code> on the command instance. This is fed the remainder of the string, after the name
|
||||
of the command. It’s intended to pre-parse the string into a form useful for the <code class="docutils literal notranslate"><span class="pre">func()</span></code> method.</p></li>
|
||||
<li><p>Call <code class="docutils literal notranslate"><span class="pre">func()</span></code> on the command instance. This is the functional body of the command, actually
|
||||
doing useful things.</p></li>
|
||||
<li><p>Call <code class="docutils literal notranslate"><span class="pre">at_post_command()</span></code> on the command instance.</p></li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="section" id="assorted-notes">
|
||||
<h2>Assorted notes<a class="headerlink" href="#assorted-notes" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The return value of <code class="docutils literal notranslate"><span class="pre">Command.func()</span></code> is a Twisted
|
||||
<a class="reference external" href="http://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>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5</pre></div></td><td class="code"><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="s2">"Returned is </span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="n">ret</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">"longrunning"</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>
|
||||
<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
|
||||
it can make a command operate on “it”, where it is determined by what the previous command operated
|
||||
on.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Commands</a><ul>
|
||||
<li><a class="reference internal" href="#defining-commands">Defining Commands</a><ul>
|
||||
<li><a class="reference internal" href="#who-is-calling-the-command">Who is calling the command?</a></li>
|
||||
<li><a class="reference internal" href="#properties-assigned-to-the-command-instance-at-run-time">Properties assigned to the command instance at run-time</a><ul>
|
||||
<li><a class="reference internal" href="#other-useful-utility-methods">Other useful utility methods:</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#defining-your-own-command-classes">Defining your own command classes</a></li>
|
||||
<li><a class="reference internal" href="#on-arg-regex">On arg_regex</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#exiting-a-command">Exiting a command</a></li>
|
||||
<li><a class="reference internal" href="#pauses-in-commands">Pauses in commands</a></li>
|
||||
<li><a class="reference internal" href="#asking-for-user-input">Asking for user input</a></li>
|
||||
<li><a class="reference internal" href="#system-commands">System commands</a></li>
|
||||
<li><a class="reference internal" href="#dynamic-commands">Dynamic Commands</a></li>
|
||||
<li><a class="reference internal" href="#exits">Exits</a></li>
|
||||
<li><a class="reference internal" href="#command-instances-are-re-used">Command instances are re-used</a></li>
|
||||
<li><a class="reference internal" href="#dynamically-created-commands">Dynamically created commands</a></li>
|
||||
<li><a class="reference internal" href="#how-commands-actually-work">How commands actually work</a></li>
|
||||
<li><a class="reference internal" href="#assorted-notes">Assorted notes</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/Commands.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Commands.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Commands</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
223
docs/1.0-dev/Components/Communications.html
Normal file
223
docs/1.0-dev/Components/Communications.html
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Communications — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Communications</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" id="communications">
|
||||
<h1>Communications<a class="headerlink" href="#communications" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Apart from moving around in the game world and talking, players might need other forms of
|
||||
communication. This is offered by Evennia’s <code class="docutils literal notranslate"><span class="pre">Comm</span></code> system. Stock evennia implements a ‘MUX-like’
|
||||
system of channels, but there is nothing stopping you from changing things to better suit your
|
||||
taste.</p>
|
||||
<p>Comms rely on two main database objects - <code class="docutils literal notranslate"><span class="pre">Msg</span></code> and <code class="docutils literal notranslate"><span class="pre">Channel</span></code>. There is also the <code class="docutils literal notranslate"><span class="pre">TempMsg</span></code> which
|
||||
mimics the API of a <code class="docutils literal notranslate"><span class="pre">Msg</span></code> but has no connection to the database.</p>
|
||||
<div class="section" id="msg">
|
||||
<h2>Msg<a class="headerlink" href="#msg" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">Msg</span></code> object is the basic unit of communication in Evennia. A message works a little like an
|
||||
e-mail; it always has a sender (a <a class="reference internal" href="Accounts.html"><span class="doc">Account</span></a>) and one or more recipients. The recipients
|
||||
may be either other Accounts, or a <em>Channel</em> (see below). You can mix recipients to send the message
|
||||
to both Channels and Accounts if you like.</p>
|
||||
<p>Once created, a <code class="docutils literal notranslate"><span class="pre">Msg</span></code> is normally not changed. It is peristently saved in the database. This allows
|
||||
for comprehensive logging of communications. This could be useful for allowing senders/receivers to
|
||||
have ‘mailboxes’ with the messages they want to keep.</p>
|
||||
<div class="section" id="properties-defined-on-msg">
|
||||
<h3>Properties defined on <code class="docutils literal notranslate"><span class="pre">Msg</span></code><a class="headerlink" href="#properties-defined-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> - this is a reference to one or many <a class="reference internal" href="Accounts.html"><span class="doc">Account</span></a> or <a class="reference internal" href="Objects.html"><span class="doc">Objects</span></a> (normally
|
||||
<em>Characters</em>) sending the message. This could also be an <em>External Connection</em> such as a message
|
||||
coming in over IRC/IMC2 (see below). There is usually only one sender, but the types can also be
|
||||
mixed in any combination.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">receivers</span></code> - a list of target <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> (usually <em>Characters</em>) or
|
||||
<em>Channels</em> to send the message to. The types of receivers can be mixed in any combination.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">header</span></code> - this is a text field for storing a title or header for the message.</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> - when message was sent (auto-created).</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 definition</span></a>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">hide_from</span></code> - this can optionally hold a list of objects, accounts or channels to hide this <code class="docutils literal notranslate"><span class="pre">Msg</span></code>
|
||||
from. This relationship is stored in the database primarily for optimization reasons, allowing for
|
||||
quickly post-filter out messages not intended for a given target. There is no in-game methods for
|
||||
setting this, it’s intended to be done in code.</p></li>
|
||||
</ul>
|
||||
<p>You create new messages in code using <code class="docutils literal notranslate"><span class="pre">evennia.create_message</span></code> (or
|
||||
<code class="docutils literal notranslate"><span class="pre">evennia.utils.create.create_message.</span></code>)</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="tempmsg">
|
||||
<h2>TempMsg<a class="headerlink" href="#tempmsg" title="Permalink to this headline">¶</a></h2>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">evennia.comms.models</span></code> also has <code class="docutils literal notranslate"><span class="pre">TempMsg</span></code> which mimics the API of <code class="docutils literal notranslate"><span class="pre">Msg</span></code> but is not connected to the
|
||||
database. TempMsgs are used by Evennia for channel messages by default. They can be used for any
|
||||
system expecting a <code class="docutils literal notranslate"><span class="pre">Msg</span></code> but when you don’t actually want to save anything.</p>
|
||||
</div>
|
||||
<div class="section" id="channels">
|
||||
<h2>Channels<a class="headerlink" href="#channels" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Channels are <a class="reference internal" href="Typeclasses.html"><span class="doc">Typeclassed</span></a> entities, which mean they can be easily extended and their
|
||||
functionality modified. To change which channel typeclass Evennia uses, change
|
||||
settings.BASE_CHANNEL_TYPECLASS.</p>
|
||||
<p>Channels act as generic distributors of messages. Think of them as “switch boards” redistributing
|
||||
<code class="docutils literal notranslate"><span class="pre">Msg</span></code> or <code class="docutils literal notranslate"><span class="pre">TempMsg</span></code> objects. Internally they hold a list of “listening” objects and any <code class="docutils literal notranslate"><span class="pre">Msg</span></code> (or
|
||||
<code class="docutils literal notranslate"><span class="pre">TempMsg</span></code>) sent to the channel will be distributed out to all channel listeners. Channels have
|
||||
<a class="reference internal" href="Locks.html"><span class="doc">Locks</span></a> to limit who may listen and/or send messages through them.</p>
|
||||
<p>The <em>sending</em> of text to a channel is handled by a dynamically created <a class="reference internal" href="Commands.html"><span class="doc">Command</span></a> that
|
||||
always have the same name as the channel. This is created for each channel by the global
|
||||
<code class="docutils literal notranslate"><span class="pre">ChannelHandler</span></code>. The Channel command is added to the Account’s cmdset and normal command locks are
|
||||
used to determine which channels are possible to write to. When subscribing to a channel, you can
|
||||
then just write the channel name and the text to send.</p>
|
||||
<p>The default ChannelCommand (which can be customized by pointing <code class="docutils literal notranslate"><span class="pre">settings.CHANNEL_COMMAND_CLASS</span></code> to
|
||||
your own command), implements a few convenient features:</p>
|
||||
<ul>
|
||||
<li><p>It only sends <code class="docutils literal notranslate"><span class="pre">TempMsg</span></code> objects. Instead of storing individual entries in the database it instead
|
||||
dumps channel output a file log in <code class="docutils literal notranslate"><span class="pre">server/logs/channel_<channelname>.log</span></code>. This is mainly for
|
||||
practical reasons - we find one rarely need to query individual Msg objects at a later date. Just
|
||||
stupidly dumping the log to a file also means a lot less database overhead.</p></li>
|
||||
<li><p>It adds a <code class="docutils literal notranslate"><span class="pre">/history</span></code> switch to view the 20 last messages in the channel. These are read from the
|
||||
end of the log file. One can also supply a line number to start further back in the file (but always
|
||||
20 entries at a time). It’s used like this:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="o">></span> <span class="n">public</span><span class="o">/</span><span class="n">history</span>
|
||||
<span class="o">></span> <span class="n">public</span><span class="o">/</span><span class="n">history</span> <span class="mi">35</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<p>There are two default channels created in stock Evennia - <code class="docutils literal notranslate"><span class="pre">MudInfo</span></code> and <code class="docutils literal notranslate"><span class="pre">Public</span></code>. <code class="docutils literal notranslate"><span class="pre">MudInfo</span></code>
|
||||
receives server-related messages meant for Admins whereas <code class="docutils literal notranslate"><span class="pre">Public</span></code> is open to everyone to chat on
|
||||
(all new accounts are automatically joined to it when logging in, it is useful for asking
|
||||
questions). The default channels are defined by the <code class="docutils literal notranslate"><span class="pre">DEFAULT_CHANNELS</span></code> list (see
|
||||
<code class="docutils literal notranslate"><span class="pre">evennia/settings_default.py</span></code> for more details).</p>
|
||||
<p>You create new channels with <code class="docutils literal notranslate"><span class="pre">evennia.create_channel</span></code> (or <code class="docutils literal notranslate"><span class="pre">evennia.utils.create.create_channel</span></code>).</p>
|
||||
<p>In code, messages are sent to a channel using the <code class="docutils literal notranslate"><span class="pre">msg</span></code> or <code class="docutils literal notranslate"><span class="pre">tempmsg</span></code> methods of channels:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">channel</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">msgobj</span><span class="p">,</span> <span class="n">header</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">senders</span><span class="o">=</span><span class="kc">None</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>
|
||||
</div>
|
||||
<p>The argument <code class="docutils literal notranslate"><span class="pre">msgobj</span></code> can be either a string, a previously constructed <code class="docutils literal notranslate"><span class="pre">Msg</span></code> or a <code class="docutils literal notranslate"><span class="pre">TempMsg</span></code> - in the
|
||||
latter cases all the following keywords are ignored since the message objects already contains all
|
||||
this information. If <code class="docutils literal notranslate"><span class="pre">msgobj</span></code> is a string, the other keywords are used for creating a new <code class="docutils literal notranslate"><span class="pre">Msg</span></code> or
|
||||
<code class="docutils literal notranslate"><span class="pre">TempMsg</span></code> on the fly, depending on if <code class="docutils literal notranslate"><span class="pre">persistent</span></code> is set or not. By default, a <code class="docutils literal notranslate"><span class="pre">TempMsg</span></code> is emitted
|
||||
for channel communication (since the default ChannelCommand instead logs to a file).</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||||
2
|
||||
3
|
||||
4</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># assume we have a 'sender' object and a channel named 'mychan'</span>
|
||||
|
||||
<span class="c1"># manually sending a message to a channel</span>
|
||||
<span class="n">mychan</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"Hello!"</span><span class="p">,</span> <span class="n">senders</span><span class="o">=</span><span class="p">[</span><span class="n">sender</span><span class="p">])</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<div class="section" id="properties-defined-on-channel">
|
||||
<h3>Properties defined on <code class="docutils literal notranslate"><span class="pre">Channel</span></code><a class="headerlink" href="#properties-defined-on-channel" title="Permalink to this headline">¶</a></h3>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">key</span></code> - main name for channel</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">aliases</span></code> - alternative native names for channels</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">desc</span></code> - optional description of channel (seen in listings)</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">keep_log</span></code> (bool) - if the channel should store messages (default)</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 definition</span></a>. Channels normally use the access_types <code class="docutils literal notranslate"><span class="pre">send,</span> <span class="pre">control</span></code> and
|
||||
<code class="docutils literal notranslate"><span class="pre">listen</span></code>.</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Communications</a><ul>
|
||||
<li><a class="reference internal" href="#msg">Msg</a><ul>
|
||||
<li><a class="reference internal" href="#properties-defined-on-msg">Properties defined on <code class="docutils literal notranslate"><span class="pre">Msg</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#tempmsg">TempMsg</a></li>
|
||||
<li><a class="reference internal" href="#channels">Channels</a><ul>
|
||||
<li><a class="reference internal" href="#properties-defined-on-channel">Properties defined on <code class="docutils literal notranslate"><span class="pre">Channel</span></code></a></li>
|
||||
</ul>
|
||||
</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/Communications.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Communications.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Communications</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
189
docs/1.0-dev/Components/Components-Overview.html
Normal file
189
docs/1.0-dev/Components/Components-Overview.html
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Core Components — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Core Components</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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>
|
||||
<div class="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>
|
||||
<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>
|
||||
<ul>
|
||||
<li><p><a class="reference internal" href="../Concepts/Guest-Logins.html"><span class="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>
|
||||
</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="Spawner-and-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>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="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>
|
||||
<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>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p><a class="reference internal" href="Batch-Processors.html"><span class="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>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="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>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="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>
|
||||
<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>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p><a class="reference internal" href="Server.html"><span class="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>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p><a class="reference internal" href="Webserver.html"><span class="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>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p><a class="reference internal" href="Signals.html"><span class="doc">Signals</span></a></p></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Core Components</a><ul>
|
||||
<li><a class="reference internal" href="#database-entites">Database entites</a></li>
|
||||
<li><a class="reference internal" href="#commands">Commands</a></li>
|
||||
<li><a class="reference internal" href="#utils-and-tools">Utils and tools</a></li>
|
||||
<li><a class="reference internal" href="#server-and-network">Server and network</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/Components-Overview.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Components-Overview.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Core Components</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
138
docs/1.0-dev/Components/Connection-Screen.html
Normal file
138
docs/1.0-dev/Components/Connection-Screen.html
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Connection Screen — Evennia 1.0-dev documentation</title>
|
||||
<link rel="stylesheet" href="../_static/nature.css" type="text/css" />
|
||||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<script src="../_static/language_data.js"></script>
|
||||
<link rel="shortcut icon" href="../_static/favicon.ico"/>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
</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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Connection Screen</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" id="connection-screen">
|
||||
<h1>Connection Screen<a class="headerlink" href="#connection-screen" title="Permalink to this headline">¶</a></h1>
|
||||
<p>When you first connect to your game you are greeted by Evennia’s default connection screen.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>==============================================================
|
||||
Welcome to Evennia, version Beta-ra4d24e8a3cab+!
|
||||
|
||||
If you have an existing account, connect to it by typing:
|
||||
connect <username> <password>
|
||||
If you need to create an account, type (without the <>'s):
|
||||
create <username> <password>
|
||||
|
||||
If you have spaces in your username, enclose it in quotes.
|
||||
Enter help for more info. look will re-show this screen.
|
||||
==============================================================
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Effective, but not very exciting. You will most likely want to change this to be more unique for
|
||||
your game. This is simple:</p>
|
||||
<ol class="simple">
|
||||
<li><p>Edit <code class="docutils literal notranslate"><span class="pre">mygame/server/conf/connection_screens.py</span></code>.</p></li>
|
||||
<li><p><a class="reference internal" href="../Setup/Start-Stop-Reload.html"><span class="doc">Reload</span></a> Evennia.</p></li>
|
||||
</ol>
|
||||
<p>Evennia will look into this module and locate all <em>globally defined strings</em> in it. These strings
|
||||
are used as the text in your connection screen and are shown to the user at startup. If more than
|
||||
one such string/screen is defined in the module, a <em>random</em> screen will be picked from among those
|
||||
available.</p>
|
||||
<div class="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
|
||||
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
|
||||
tutorial section on how to add new commands to a default command set.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Connection Screen</a><ul>
|
||||
<li><a class="reference internal" href="#commands-available-at-the-connection-screen">Commands available at the Connection Screen</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Components/Connection-Screen.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Connection-Screen.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Connection Screen</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
346
docs/1.0-dev/Components/EvEditor.html
Normal file
346
docs/1.0-dev/Components/EvEditor.html
Normal file
|
|
@ -0,0 +1,346 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>EvEditor — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">EvEditor</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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,
|
||||
search/replace, fill, dedent and more.</p>
|
||||
<div class="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>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5</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>
|
||||
|
||||
<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="bp">None</span><span class="p">,</span> <span class="n">savefunc</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">quitfunc</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span>
|
||||
<span class="n">key</span><span class="o">=</span><span class="s2">""</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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
|
||||
is called with <code class="docutils literal notranslate"><span class="pre">caller</span></code> as its only argument. The return value from this function is used as the
|
||||
starting text in the editor buffer.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">savefunc</span></code> (callable, optional): This is called when the user saves their buffer in the editor is
|
||||
called with two arguments, <code class="docutils literal notranslate"><span class="pre">caller</span></code> and <code class="docutils literal notranslate"><span class="pre">buffer</span></code>, where <code class="docutils literal notranslate"><span class="pre">buffer</span></code> is the current buffer.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">quitfunc</span></code> (callable, optional): This is called when the user quits the editor. If given, all
|
||||
cleanup and exit messages to the user must be handled by this function.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">key</span></code> (str, optional): This text will be displayed as an identifier and reminder while editing.
|
||||
It has no other mechanical function.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">persistent</span></code> (default <code class="docutils literal notranslate"><span class="pre">False</span></code>): if set to <code class="docutils literal notranslate"><span class="pre">True</span></code>, the editor will survive a reboot.</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15
|
||||
16
|
||||
17
|
||||
18
|
||||
19
|
||||
20
|
||||
21
|
||||
22
|
||||
23
|
||||
24
|
||||
25
|
||||
26
|
||||
27
|
||||
28
|
||||
29</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>
|
||||
<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">"""</span>
|
||||
<span class="sd"> Set the "test" Attribute using </span>
|
||||
<span class="sd"> the line editor.</span>
|
||||
|
||||
<span class="sd"> Usage:</span>
|
||||
<span class="sd"> settestattr</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"settestattr"</span>
|
||||
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="s2">"Set up the callbacks and launch the editor"</span>
|
||||
<span class="k">def</span> <span class="nf">load</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
||||
<span class="s2">"get the current value"</span>
|
||||
<span class="k">return</span> <span class="n">caller</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">"test"</span><span class="p">)</span>
|
||||
<span class="k">def</span> <span class="nf">save</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="nb">buffer</span><span class="p">):</span>
|
||||
<span class="s2">"save the buffer"</span>
|
||||
<span class="n">caller</span><span class="o">.</span><span class="n">attributes</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">"test"</span><span class="p">,</span> <span class="nb">buffer</span><span class="p">)</span>
|
||||
<span class="k">def</span> <span class="nf">quit</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
||||
<span class="s2">"Since we define it, we must handle messages"</span>
|
||||
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"Editor exited"</span><span class="p">)</span>
|
||||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"</span><span class="si">%s</span><span class="s2">/test"</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</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>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
</div>
|
||||
<div class="section" id="persistent-editor">
|
||||
<h2>Persistent editor<a class="headerlink" href="#persistent-editor" title="Permalink to this headline">¶</a></h2>
|
||||
<p>If you set the <code class="docutils literal notranslate"><span class="pre">persistent</span></code> keyword to <code class="docutils literal notranslate"><span class="pre">True</span></code> when creating the editor, it will remain open even
|
||||
when reloading the game. In order to be persistent, an editor needs to have its callback functions
|
||||
(<code class="docutils literal notranslate"><span class="pre">loadfunc</span></code>, <code class="docutils literal notranslate"><span class="pre">savefunc</span></code> and <code class="docutils literal notranslate"><span class="pre">quitfunc</span></code>) as top-level functions defined in the module. Since these
|
||||
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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15
|
||||
16
|
||||
17
|
||||
18
|
||||
19
|
||||
20
|
||||
21
|
||||
22
|
||||
23
|
||||
24
|
||||
25
|
||||
26
|
||||
27
|
||||
28
|
||||
29
|
||||
30
|
||||
31
|
||||
32</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>
|
||||
<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>
|
||||
<span class="s2">"get the current value"</span>
|
||||
<span class="k">return</span> <span class="n">caller</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">"test"</span><span class="p">)</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">save</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="nb">buffer</span><span class="p">):</span>
|
||||
<span class="s2">"save the buffer"</span>
|
||||
<span class="n">caller</span><span class="o">.</span><span class="n">attributes</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s2">"test"</span><span class="p">,</span> <span class="nb">buffer</span><span class="p">)</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">quit</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
||||
<span class="s2">"Since we define it, we must handle messages"</span>
|
||||
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"Editor exited"</span><span class="p">)</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">"""</span>
|
||||
<span class="sd"> Set the "test" Attribute using </span>
|
||||
<span class="sd"> the line editor.</span>
|
||||
|
||||
<span class="sd"> Usage:</span>
|
||||
<span class="sd"> settestattr</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"settestattr"</span>
|
||||
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="s2">"Set up the callbacks and launch the editor"</span>
|
||||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"</span><span class="si">%s</span><span class="s2">/test"</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</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="bp">True</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
</div>
|
||||
<div class="section" id="line-editor-usage">
|
||||
<h2>Line editor usage<a class="headerlink" href="#line-editor-usage" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The editor mimics the <code class="docutils literal notranslate"><span class="pre">VIM</span></code> editor as best as possible. The below is an excerpt of the return from
|
||||
the in-editor help command (<code class="docutils literal notranslate"><span class="pre">:h</span></code>).</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <txt> - any non-command is appended to the end of the buffer.
|
||||
: <l> - view buffer or only line <l>
|
||||
:: <l> - view buffer without line numbers or other parsing
|
||||
::: - print a ':' as the only character on the line...
|
||||
:h - this help.
|
||||
|
||||
:w - save the buffer (don't quit)
|
||||
:wq - save buffer and quit
|
||||
:q - quit (will be asked to save if buffer was changed)
|
||||
:q! - quit without saving, no questions asked
|
||||
|
||||
:u - (undo) step backwards in undo history
|
||||
:uu - (redo) step forward in undo history
|
||||
:UU - reset all changes back to initial state
|
||||
|
||||
:dd <l> - delete line <n>
|
||||
:dw <l> <w> - delete word or regex <w> in entire buffer or on line <l>
|
||||
:DD - clear buffer
|
||||
|
||||
:y <l> - yank (copy) line <l> to the copy buffer
|
||||
:x <l> - cut line <l> and store it in the copy buffer
|
||||
:p <l> - put (paste) previously copied line directly after <l>
|
||||
:i <l> <txt> - insert new text <txt> at line <l>. Old line will move down
|
||||
:r <l> <txt> - replace line <l> with text <txt>
|
||||
:I <l> <txt> - insert text at the beginning of line <l>
|
||||
:A <l> <txt> - append text after the end of line <l>
|
||||
|
||||
:s <l> <w> <txt> - search/replace word or regex <w> in buffer or on line <l>
|
||||
|
||||
:f <l> - flood-fill entire buffer or line <l>
|
||||
:fi <l> - indent entire buffer or line <l>
|
||||
:fd <l> - de-indent entire buffer or line <l>
|
||||
|
||||
:echo - turn echoing of the input on/off (helpful for some clients)
|
||||
|
||||
Legend:
|
||||
<l> - line numbers, or range lstart:lend, e.g. '3:7'.
|
||||
<w> - one word or several enclosed in quotes.
|
||||
<txt> - longer string, usually not needed to be enclosed in quotes.
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="the-eveditor-to-edit-code">
|
||||
<h2>The EvEditor to edit code<a class="headerlink" href="#the-eveditor-to-edit-code" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">EvEditor</span></code> is also used to edit some Python code in Evennia. The <code class="docutils literal notranslate"><span class="pre">@py</span></code> command supports an
|
||||
<code class="docutils literal notranslate"><span class="pre">/edit</span></code> switch that will open the EvEditor in code mode. This mode isn’t significantly different
|
||||
from the standard one, except it handles automatic indentation of blocks and a few options to
|
||||
control this behavior.</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">:<</span></code> to remove a level of indentation for the future lines.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">:+</span></code> to add a level of indentation for the future lines.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">:=</span></code> to disable automatic indentation altogether.</p></li>
|
||||
</ul>
|
||||
<p>Automatic indentation is there to make code editing more simple. Python needs correct indentation,
|
||||
not as an aesthetic addition, but as a requirement to determine beginning and ending of blocks. The
|
||||
EvEditor will try to guess the next level of indentation. If you type a block “if”, for instance,
|
||||
the EvEditor will propose you an additional level of indentation at the next line. This feature
|
||||
cannot be perfect, however, and sometimes, you will have to use the above options to handle
|
||||
indentation.</p>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">:=</span></code> can be used to turn automatic indentation off completely. This can be very useful when trying
|
||||
to paste several lines of code that are already correctly indented, for instance.</p>
|
||||
<p>To see the EvEditor in code mode, you can use the <code class="docutils literal notranslate"><span class="pre">@py/edit</span></code> command. Type in your code (on one or
|
||||
several lines). You can then use the <code class="docutils literal notranslate"><span class="pre">:w</span></code> option (save without quitting) and the code you have
|
||||
typed will be executed. The <code class="docutils literal notranslate"><span class="pre">:!</span></code> will do the same thing. Executing code while not closing the
|
||||
editor can be useful if you want to test the code you have typed but add new lines after your test.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">EvEditor</a><ul>
|
||||
<li><a class="reference internal" href="#launching-the-editor">Launching the editor</a></li>
|
||||
<li><a class="reference internal" href="#example-of-usage">Example of usage</a></li>
|
||||
<li><a class="reference internal" href="#persistent-editor">Persistent editor</a></li>
|
||||
<li><a class="reference internal" href="#line-editor-usage">Line editor usage</a></li>
|
||||
<li><a class="reference internal" href="#the-eveditor-to-edit-code">The EvEditor to edit code</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Components/EvEditor.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="EvEditor.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">EvEditor</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
1376
docs/1.0-dev/Components/EvMenu.html
Normal file
1376
docs/1.0-dev/Components/EvMenu.html
Normal file
File diff suppressed because it is too large
Load diff
139
docs/1.0-dev/Components/EvMore.html
Normal file
139
docs/1.0-dev/Components/EvMore.html
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>EvMore — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">EvMore</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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
|
||||
page of text at a time. It is usually used via its access function, <code class="docutils literal notranslate"><span class="pre">evmore.msg</span></code>.</p>
|
||||
<p>The name comes from the famous unix pager utility <em>more</em> which performs just this function.</p>
|
||||
<div 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>1
|
||||
2
|
||||
3</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>
|
||||
|
||||
<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
|
||||
client’s 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>
|
||||
<div><p>[…]
|
||||
aute irure dolor in reprehenderit in voluptate velit
|
||||
esse cillum dolore eu fugiat nulla pariatur. Excepteur
|
||||
sint occaecat cupidatat non proident, sunt in culpa qui
|
||||
officia deserunt mollit anim id est laborum.</p>
|
||||
</div></blockquote>
|
||||
<blockquote>
|
||||
<div><p>(<strong>more</strong> [1/6] retur<strong>n</strong>|<strong>b</strong>ack|<strong>t</strong>op|<strong>e</strong>nd|<strong>a</strong>bort)</p>
|
||||
</div></blockquote>
|
||||
<p>where the user will be able to hit the return key to move to the next page, or use the suggested
|
||||
commands to jump to previous pages, to the top or bottom of the document as well as abort the
|
||||
paging.</p>
|
||||
<p>The pager takes several more keyword arguments for controlling the message output. See the
|
||||
<a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia.utils.evmore">evmore-API</a> for more info.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">EvMore</a><ul>
|
||||
<li><a class="reference internal" href="#using-evmore">Using EvMore</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/EvMore.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="EvMore.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">EvMore</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
238
docs/1.0-dev/Components/Help-System.html
Normal file
238
docs/1.0-dev/Components/Help-System.html
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Help System — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Help System</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" id="help-system">
|
||||
<h1>Help System<a class="headerlink" href="#help-system" title="Permalink to this headline">¶</a></h1>
|
||||
<p>An important part of Evennia is the online help system. This allows the players and staff alike to
|
||||
learn how to use the game’s commands as well as other information pertinent to the game. The help
|
||||
system has many different aspects, from the normal editing of help entries from inside the game, to
|
||||
auto-generated help entries during code development using the <em>auto-help system</em>.</p>
|
||||
<div class="section" id="viewing-the-help-database">
|
||||
<h2>Viewing the help database<a class="headerlink" href="#viewing-the-help-database" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The main command is <code class="docutils literal notranslate"><span class="pre">help</span></code>:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">help</span> <span class="p">[</span><span class="n">searchstring</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This will show a list of help entries, ordered after categories. You will find two sections,
|
||||
<em>Command help entries</em> and <em>Other help entries</em> (initially you will only have the first one). You
|
||||
can use help to get more info about an entry; you can also give partial matches to get suggestions.
|
||||
If you give category names you will only be shown the topics in that category.</p>
|
||||
</div>
|
||||
<div class="section" id="command-auto-help-system">
|
||||
<h2>Command Auto-help system<a class="headerlink" href="#command-auto-help-system" title="Permalink to this headline">¶</a></h2>
|
||||
<p>A common item that requires help entries are in-game commands. Keeping these entries up-to-date with
|
||||
the actual source code functionality can be a chore. Evennia’s commands are therefore auto-
|
||||
documenting straight from the sources through its <em>auto-help system</em>. Only commands that you and
|
||||
your character can actually currently use are picked up by the auto-help system. That means an admin
|
||||
will see a considerably larger amount of help topics than a normal player when using the default
|
||||
<code class="docutils literal notranslate"><span class="pre">help</span></code> command.</p>
|
||||
<p>The auto-help system uses the <code class="docutils literal notranslate"><span class="pre">__doc__</span></code> strings of your command classes and formats this to a nice-
|
||||
looking help entry. This makes for a very easy way to keep the help updated - just document your
|
||||
commands well and updating the help file is just a <code class="docutils literal notranslate"><span class="pre">@reload</span></code> away. There is no need to manually
|
||||
create and maintain help database entries for commands; as long as you keep the docstrings updated
|
||||
your help will be dynamically updated for you as well.</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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15
|
||||
16
|
||||
17
|
||||
18
|
||||
19
|
||||
20</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>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> mycmd - my very own command</span>
|
||||
<span class="sd"> </span>
|
||||
<span class="sd"> Usage: </span>
|
||||
<span class="sd"> mycmd[/switches] <args></span>
|
||||
<span class="sd"> </span>
|
||||
<span class="sd"> Switches:</span>
|
||||
<span class="sd"> test - test the command</span>
|
||||
<span class="sd"> run - do something else</span>
|
||||
<span class="sd"> </span>
|
||||
<span class="sd"> This is my own command that does this and that.</span>
|
||||
<span class="sd"> </span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="c1"># [...]</span>
|
||||
|
||||
<span class="n">help_category</span> <span class="o">=</span> <span class="s2">"General"</span> <span class="c1"># default</span>
|
||||
<span class="n">auto_help</span> <span class="o">=</span> <span class="bp">True</span> <span class="c1"># default</span>
|
||||
|
||||
<span class="c1"># [...]</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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 should also supply the <code class="docutils literal notranslate"><span class="pre">help_category</span></code> class property if you can; this helps to group help
|
||||
entries together for people to more easily find them. See the <code class="docutils literal notranslate"><span class="pre">help</span></code> command in-game to see the
|
||||
default categories. If you don’t specify the category, “General” is assumed.</p>
|
||||
<p>If you don’t want your command to be picked up by the auto-help system at all (like if you want to
|
||||
write its docs manually using the info in the next section or you use a <a class="reference internal" href="Command-Sets.html"><span class="doc">cmdset</span></a> that
|
||||
has its own help functionality) you can explicitly set <code class="docutils literal notranslate"><span class="pre">auto_help</span></code> class property to <code class="docutils literal notranslate"><span class="pre">False</span></code> in your
|
||||
command definition.</p>
|
||||
<p>Alternatively, you can keep the advantages of <em>auto-help</em> in commands, but control the display of
|
||||
command helps. You can do so by overriding the command’s <code class="docutils literal notranslate"><span class="pre">get_help()</span></code> method. By default, this
|
||||
method will return the class docstring. You could modify it to add custom behavior: the text
|
||||
returned by this method will be displayed to the character asking for help in this command.</p>
|
||||
</div>
|
||||
<div class="section" id="database-help-entries">
|
||||
<h2>Database help entries<a class="headerlink" href="#database-help-entries" title="Permalink to this headline">¶</a></h2>
|
||||
<p>These are all help entries not involving commands (this is handled automatically by the <a class="reference external" href="Components/Help-System.html#command-auto-help-system">Command
|
||||
Auto-help system</a>). Non-automatic help entries describe how
|
||||
your particular game is played - its rules, world descriptions and so on.</p>
|
||||
<p>A help entry consists of four parts:</p>
|
||||
<ul class="simple">
|
||||
<li><p>The <em>topic</em>. This is the name of the help entry. This is what players search for when they are
|
||||
looking for help. The topic can contain spaces and also partial matches will be found.</p></li>
|
||||
<li><p>The <em>help category</em>. Examples are <em>Administration</em>, <em>Building</em>, <em>Comms</em> or <em>General</em>. This is an
|
||||
overall grouping of similar help topics, used by the engine to give a better overview.</p></li>
|
||||
<li><p>The <em>text</em> - the help text itself, of any length.</p></li>
|
||||
<li><p>locks - a <a class="reference internal" href="Locks.html"><span class="doc">lock definition</span></a>. This can be used to limit access to this help entry, maybe
|
||||
because it’s staff-only or otherwise meant to be restricted. Help commands check for <code class="docutils literal notranslate"><span class="pre">access_type</span></code>s
|
||||
<code class="docutils literal notranslate"><span class="pre">view</span></code> and <code class="docutils literal notranslate"><span class="pre">edit</span></code>. An example of a lock string would be <code class="docutils literal notranslate"><span class="pre">view:perm(Builders)</span></code>.</p></li>
|
||||
</ul>
|
||||
<p>You can create new help entries in code by using <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>1
|
||||
2
|
||||
3
|
||||
4</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_help_entry</span>
|
||||
<span class="n">entry</span> <span class="o">=</span> <span class="n">create_help_entry</span><span class="p">(</span><span class="s2">"emote"</span><span class="p">,</span>
|
||||
<span class="s2">"Emoting is important because ..."</span><span class="p">,</span>
|
||||
<span class="n">category</span><span class="o">=</span><span class="s2">"Roleplaying"</span><span class="p">,</span> <span class="n">locks</span><span class="o">=</span><span class="s2">"view:all()"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<p>From inside the game those with the right permissions can use the <code class="docutils literal notranslate"><span class="pre">@sethelp</span></code> command to add and
|
||||
modify help entries.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">></span> <span class="nd">@sethelp</span><span class="o">/</span><span class="n">add</span> <span class="n">emote</span> <span class="o">=</span> <span class="n">The</span> <span class="n">emote</span> <span class="n">command</span> <span class="ow">is</span> <span class="o">...</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Using <code class="docutils literal notranslate"><span class="pre">@sethelp</span></code> you can add, delete and append text to existing entries. By default new entries
|
||||
will go in the <em>General</em> help category. You can change this using a different form of the <code class="docutils literal notranslate"><span class="pre">@sethelp</span></code>
|
||||
command:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">></span> <span class="nd">@sethelp</span><span class="o">/</span><span class="n">add</span> <span class="n">emote</span><span class="p">,</span> <span class="n">Roleplaying</span> <span class="o">=</span> <span class="n">Emoting</span> <span class="ow">is</span> <span class="n">important</span> <span class="n">because</span> <span class="o">...</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>If the category <em>Roleplaying</em> did not already exist, it is created and will appear in the help
|
||||
index.</p>
|
||||
<p>You can, finally, define a lock for the help entry by following the category with a <a class="reference internal" href="Locks.html"><span class="doc">lock
|
||||
definition</span></a>:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">></span> <span class="nd">@sethelp</span><span class="o">/</span><span class="n">add</span> <span class="n">emote</span><span class="p">,</span> <span class="n">Roleplaying</span><span class="p">,</span> <span class="n">view</span><span class="p">:</span><span class="nb">all</span><span class="p">()</span> <span class="o">=</span> <span class="n">Emoting</span> <span class="ow">is</span> <span class="o">...</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Help System</a><ul>
|
||||
<li><a class="reference internal" href="#viewing-the-help-database">Viewing the help database</a></li>
|
||||
<li><a class="reference internal" href="#command-auto-help-system">Command Auto-help system</a></li>
|
||||
<li><a class="reference internal" href="#database-help-entries">Database help entries</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Components/Help-System.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Help-System.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Help System</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
299
docs/1.0-dev/Components/Inputfuncs.html
Normal file
299
docs/1.0-dev/Components/Inputfuncs.html
Normal file
|
|
@ -0,0 +1,299 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Inputfuncs — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Inputfuncs</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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>1
|
||||
2</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>
|
||||
<span class="c1"># ...</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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>1
|
||||
2</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>
|
||||
<span class="c1"># cmdname is the name of the mismatched inputcommand</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<div class="section" id="adding-your-own-inputfuncs">
|
||||
<h2>Adding your own inputfuncs<a class="headerlink" href="#adding-your-own-inputfuncs" title="Permalink to this headline">¶</a></h2>
|
||||
<p>This is simple. Add a function on the above form to <code class="docutils literal notranslate"><span class="pre">mygame/server/conf/inputfuncs.py</span></code>. Your
|
||||
function must be in the global, outermost scope of that module and not start with an underscore
|
||||
(<code class="docutils literal notranslate"><span class="pre">_</span></code>) to be recognized as an inputfunc. Reload the server. That’s it. To overload a default
|
||||
inputfunc (see below), just add a function with the same name.</p>
|
||||
<p>The modules Evennia looks into for inputfuncs are defined in the list <code class="docutils literal notranslate"><span class="pre">settings.INPUT_FUNC_MODULES</span></code>.
|
||||
This list will be imported from left to right and later imported functions will replace earlier
|
||||
ones.</p>
|
||||
</div>
|
||||
<div class="section" id="default-inputfuncs">
|
||||
<h2>Default inputfuncs<a class="headerlink" href="#default-inputfuncs" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Evennia defines a few default inputfuncs to handle the common cases. These are defined in
|
||||
<code class="docutils literal notranslate"><span class="pre">evennia/server/inputfuncs.py</span></code>.</p>
|
||||
<div class="section" id="text">
|
||||
<h3>text<a class="headerlink" href="#text" title="Permalink to this headline">¶</a></h3>
|
||||
<ul class="simple">
|
||||
<li><p>Input: <code class="docutils literal notranslate"><span class="pre">("text",</span> <span class="pre">(textstring,),</span> <span class="pre">{})</span></code></p></li>
|
||||
<li><p>Output: Depends on Command triggered</p></li>
|
||||
</ul>
|
||||
<p>This is the most common of inputcommands, and the only one supported by every traditional mud. The
|
||||
argument is usually what the user sent from their command line. Since all text input from the user
|
||||
like this is considered a <a class="reference internal" href="Commands.html"><span class="doc">Command</span></a>, this inputfunc will do things like nick-replacement
|
||||
and then pass on the input to the central Commandhandler.</p>
|
||||
</div>
|
||||
<div class="section" id="echo">
|
||||
<h3>echo<a class="headerlink" href="#echo" title="Permalink to this headline">¶</a></h3>
|
||||
<ul class="simple">
|
||||
<li><p>Input: <code class="docutils literal notranslate"><span class="pre">("echo",</span> <span class="pre">(args),</span> <span class="pre">{})</span></code></p></li>
|
||||
<li><p>Output: <code class="docutils literal notranslate"><span class="pre">("text",</span> <span class="pre">("Echo</span> <span class="pre">returns:</span> <span class="pre">%s"</span> <span class="pre">%</span> <span class="pre">args),</span> <span class="pre">{})</span></code></p></li>
|
||||
</ul>
|
||||
<p>This is a test input, which just echoes the argument back to the session as text. Can be used for
|
||||
testing custom client input.</p>
|
||||
</div>
|
||||
<div class="section" id="default">
|
||||
<h3>default<a class="headerlink" href="#default" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The default function, as mentioned above, absorbs all non-recognized inputcommands. The default one
|
||||
will just log an error.</p>
|
||||
</div>
|
||||
<div class="section" id="client-options">
|
||||
<h3>client_options<a class="headerlink" href="#client-options" title="Permalink to this headline">¶</a></h3>
|
||||
<ul class="simple">
|
||||
<li><p>Input: <code class="docutils literal notranslate"><span class="pre">("client_options,</span> <span class="pre">(),</span> <span class="pre">{key:value,</span> <span class="pre">...})</span></code></p></li>
|
||||
<li><p>Output:</p></li>
|
||||
<li><p>normal: None</p></li>
|
||||
<li><p>get: <code class="docutils literal notranslate"><span class="pre">("client_options",</span> <span class="pre">(),</span> <span class="pre">{key:value,</span> <span class="pre">...})</span></code></p></li>
|
||||
</ul>
|
||||
<p>This is a direct command for setting protocol options. These are settable with the <code class="docutils literal notranslate"><span class="pre">@option</span></code>
|
||||
command, but this offers a client-side way to set them. Not all connection protocols makes use of
|
||||
all flags, but here are the possible keywords:</p>
|
||||
<ul class="simple">
|
||||
<li><p>get (bool): If this is true, ignore all other kwargs and immediately return the current settings
|
||||
as an outputcommand <code class="docutils literal notranslate"><span class="pre">("client_options",</span> <span class="pre">(),</span> <span class="pre">{key=value,</span> <span class="pre">...})</span></code>-</p></li>
|
||||
<li><p>client (str): A client identifier, like “mushclient”.</p></li>
|
||||
<li><p>version (str): A client version</p></li>
|
||||
<li><p>ansi (bool): Supports ansi colors</p></li>
|
||||
<li><p>xterm256 (bool): Supports xterm256 colors or not</p></li>
|
||||
<li><p>mxp (bool): Supports MXP or not</p></li>
|
||||
<li><p>utf-8 (bool): Supports UTF-8 or not</p></li>
|
||||
<li><p>screenreader (bool): Screen-reader mode on/off</p></li>
|
||||
<li><p>mccp (bool): MCCP compression on/off</p></li>
|
||||
<li><p>screenheight (int): Screen height in lines</p></li>
|
||||
<li><p>screenwidth (int): Screen width in characters</p></li>
|
||||
<li><p>inputdebug (bool): Debug input functions</p></li>
|
||||
<li><p>nomarkup (bool): Strip all text tags</p></li>
|
||||
<li><p>raw (bool): Leave text tags unparsed</p></li>
|
||||
</ul>
|
||||
<blockquote>
|
||||
<div><p>Note that there are two GMCP aliases to this inputfunc - <code class="docutils literal notranslate"><span class="pre">hello</span></code> and <code class="docutils literal notranslate"><span class="pre">supports_set</span></code>, which means
|
||||
it will be accessed via the GMCP <code class="docutils literal notranslate"><span class="pre">Hello</span></code> and <code class="docutils literal notranslate"><span class="pre">Supports.Set</span></code> instructions assumed by some clients.</p>
|
||||
</div></blockquote>
|
||||
</div>
|
||||
<div class="section" id="get-client-options">
|
||||
<h3>get_client_options<a class="headerlink" href="#get-client-options" title="Permalink to this headline">¶</a></h3>
|
||||
<ul class="simple">
|
||||
<li><p>Input: <code class="docutils literal notranslate"><span class="pre">("get_client_options,</span> <span class="pre">(),</span> <span class="pre">{key:value,</span> <span class="pre">...})</span></code></p></li>
|
||||
<li><p>Output: <code class="docutils literal notranslate"><span class="pre">("client_options,</span> <span class="pre">(),</span> <span class="pre">{key:value,</span> <span class="pre">...})</span></code></p></li>
|
||||
</ul>
|
||||
<p>This is a convenience wrapper that retrieves the current options by sending “get” to
|
||||
<code class="docutils literal notranslate"><span class="pre">client_options</span></code> above.</p>
|
||||
</div>
|
||||
<div class="section" id="get-inputfuncs">
|
||||
<h3>get_inputfuncs<a class="headerlink" href="#get-inputfuncs" title="Permalink to this headline">¶</a></h3>
|
||||
<ul class="simple">
|
||||
<li><p>Input: <code class="docutils literal notranslate"><span class="pre">("get_inputfuncs",</span> <span class="pre">(),</span> <span class="pre">{})</span></code></p></li>
|
||||
<li><p>Output: <code class="docutils literal notranslate"><span class="pre">("get_inputfuncs",</span> <span class="pre">(),</span> <span class="pre">{funcname:docstring,</span> <span class="pre">...})</span></code></p></li>
|
||||
</ul>
|
||||
<p>Returns an outputcommand on the form <code class="docutils literal notranslate"><span class="pre">("get_inputfuncs",</span> <span class="pre">(),</span> <span class="pre">{funcname:docstring,</span> <span class="pre">...})</span></code> - a list of
|
||||
all the available inputfunctions along with their docstrings.</p>
|
||||
</div>
|
||||
<div class="section" id="login">
|
||||
<h3>login<a class="headerlink" href="#login" title="Permalink to this headline">¶</a></h3>
|
||||
<blockquote>
|
||||
<div><p>Note: this is currently experimental and not very well tested.</p>
|
||||
</div></blockquote>
|
||||
<ul class="simple">
|
||||
<li><p>Input: <code class="docutils literal notranslate"><span class="pre">("login",</span> <span class="pre">(username,</span> <span class="pre">password),</span> <span class="pre">{})</span></code></p></li>
|
||||
<li><p>Output: Depends on login hooks</p></li>
|
||||
</ul>
|
||||
<p>This performs the inputfunc version of a login operation on the current Session.</p>
|
||||
</div>
|
||||
<div class="section" id="get-value">
|
||||
<h3>get_value<a class="headerlink" href="#get-value" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Input: <code class="docutils literal notranslate"><span class="pre">("get_value",</span> <span class="pre">(name,</span> <span class="pre">),</span> <span class="pre">{})</span></code>
|
||||
Output: <code class="docutils literal notranslate"><span class="pre">("get_value",</span> <span class="pre">(value,</span> <span class="pre">),</span> <span class="pre">{})</span></code></p>
|
||||
<p>Retrieves a value from the Character or Account currently controlled by this Session. Takes one
|
||||
argument, This will only accept particular white-listed names, you’ll need to overload the function
|
||||
to expand. By default the following values can be retrieved:</p>
|
||||
<ul class="simple">
|
||||
<li><p>“name” or “key”: The key of the Account or puppeted Character.</p></li>
|
||||
<li><p>“location”: Name of the current location, or “None”.</p></li>
|
||||
<li><p>“servername”: Name of the Evennia server connected to.</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="repeat">
|
||||
<h3>repeat<a class="headerlink" href="#repeat" title="Permalink to this headline">¶</a></h3>
|
||||
<ul class="simple">
|
||||
<li><p>Input: <code class="docutils literal notranslate"><span class="pre">("repeat",</span> <span class="pre">(),</span> <span class="pre">{"callback":funcname,</span>  <span class="pre">"interval":</span> <span class="pre">secs,</span> <span class="pre">"stop":</span> <span class="pre">False})</span></code></p></li>
|
||||
<li><p>Output: Depends on the repeated function. Will return <code class="docutils literal notranslate"><span class="pre">("text",</span> <span class="pre">(repeatlist),{}</span></code> with a list of
|
||||
accepted names if given an unfamiliar callback name.</p></li>
|
||||
</ul>
|
||||
<p>This will tell evennia to repeatedly call a named function at a given interval. Behind the scenes
|
||||
this will set up a <a class="reference internal" href="TickerHandler.html"><span class="doc">Ticker</span></a>. Only previously acceptable functions are possible to
|
||||
repeat-call in this way, you’ll need to overload this inputfunc to add the ones you want to offer.
|
||||
By default only two example functions are allowed, “test1” and “test2”, which will just echo a text
|
||||
back at the given interval. Stop the repeat by sending <code class="docutils literal notranslate"><span class="pre">"stop":</span> <span class="pre">True</span></code> (note that you must include
|
||||
both the callback name and interval for Evennia to know what to stop).</p>
|
||||
</div>
|
||||
<div class="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">("unrepeat",</span> <span class="pre">(),</span> <span class="pre">("callback":funcname,</span>  <span class="pre">"interval":</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>
|
||||
</div>
|
||||
<div class="section" id="monitor">
|
||||
<h3>monitor<a class="headerlink" href="#monitor" title="Permalink to this headline">¶</a></h3>
|
||||
<ul class="simple">
|
||||
<li><p>Input: <code class="docutils literal notranslate"><span class="pre">("monitor",</span> <span class="pre">(),</span> <span class="pre">("name":field_or_argname,</span> <span class="pre">stop=False)</span></code></p></li>
|
||||
<li><p>Output (on change): <code class="docutils literal notranslate"><span class="pre">("monitor",</span> <span class="pre">(),</span> <span class="pre">{"name":name,</span> <span class="pre">"value":value})</span></code></p></li>
|
||||
</ul>
|
||||
<p>This sets up on-object monitoring of Attributes or database fields. Whenever the field or Attribute
|
||||
changes in any way, the outputcommand will be sent. This is using the
|
||||
<a class="reference internal" href="MonitorHandler.html"><span class="doc">MonitorHandler</span></a> behind the scenes. Pass the “stop” key to stop monitoring. Note
|
||||
that you must supply the name also when stopping to let the system know which monitor should be
|
||||
cancelled.</p>
|
||||
<p>Only fields/attributes in a whitelist are allowed to be used, you have to overload this function to
|
||||
add more. By default the following fields/attributes can be monitored:</p>
|
||||
<ul class="simple">
|
||||
<li><p>“name”: The current character name</p></li>
|
||||
<li><p>“location”: The current location</p></li>
|
||||
<li><p>“desc”: The description Argument</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="unmonitor">
|
||||
<h2>unmonitor<a class="headerlink" href="#unmonitor" title="Permalink to this headline">¶</a></h2>
|
||||
<ul class="simple">
|
||||
<li><p>Input: <code class="docutils literal notranslate"><span class="pre">("unmonitor",</span> <span class="pre">(),</span> <span class="pre">{"name":name})</span></code></p></li>
|
||||
<li><p>Output: None</p></li>
|
||||
</ul>
|
||||
<p>A convenience wrapper that sends “stop” to the <code class="docutils literal notranslate"><span class="pre">monitor</span></code> function.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Inputfuncs</a><ul>
|
||||
<li><a class="reference internal" href="#adding-your-own-inputfuncs">Adding your own inputfuncs</a></li>
|
||||
<li><a class="reference internal" href="#default-inputfuncs">Default inputfuncs</a><ul>
|
||||
<li><a class="reference internal" href="#text">text</a></li>
|
||||
<li><a class="reference internal" href="#echo">echo</a></li>
|
||||
<li><a class="reference internal" href="#default">default</a></li>
|
||||
<li><a class="reference internal" href="#client-options">client_options</a></li>
|
||||
<li><a class="reference internal" href="#get-client-options">get_client_options</a></li>
|
||||
<li><a class="reference internal" href="#get-inputfuncs">get_inputfuncs</a></li>
|
||||
<li><a class="reference internal" href="#login">login</a></li>
|
||||
<li><a class="reference internal" href="#get-value">get_value</a></li>
|
||||
<li><a class="reference internal" href="#repeat">repeat</a></li>
|
||||
<li><a class="reference internal" href="#unrepeat">unrepeat</a></li>
|
||||
<li><a class="reference internal" href="#monitor">monitor</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#unmonitor">unmonitor</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/Inputfuncs.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Inputfuncs.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Inputfuncs</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
649
docs/1.0-dev/Components/Locks.html
Normal file
649
docs/1.0-dev/Components/Locks.html
Normal file
|
|
@ -0,0 +1,649 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Locks — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Locks</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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>
|
||||
<p>A lock can be thought of as an “access rule” restricting a particular use of an Evennia entity.
|
||||
Whenever another entity wants that kind of access the lock will analyze that entity in different
|
||||
ways to determine if access should be granted or not. Evennia implements a “lockdown” philosophy -
|
||||
all entities are inaccessible unless you explicitly define a lock that allows some or full access.</p>
|
||||
<p>Let’s take an example: An object has a lock on itself that restricts how people may “delete” that
|
||||
object. Apart from knowing that it restricts deletion, the lock also knows that only players with
|
||||
the specific ID of, say, <code class="docutils literal notranslate"><span class="pre">34</span></code> are allowed to delete it. So whenever a player tries to run <code class="docutils literal notranslate"><span class="pre">delete</span></code>
|
||||
on the object, the <code class="docutils literal notranslate"><span class="pre">delete</span></code> command makes sure to check if this player is really allowed to do so.
|
||||
It calls the lock, which in turn checks if the player’s id is <code class="docutils literal notranslate"><span class="pre">34</span></code>. Only then will it allow <code class="docutils literal notranslate"><span class="pre">delete</span></code>
|
||||
to go on with its job.</p>
|
||||
<div class="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">></span> <span class="n">lock</span> <span class="n">obj</span> <span class="o">=</span> <span class="o"><</span><span class="n">lockstring</span><span class="o">></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre"><lockstring></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"><lockstring></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>1</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"><</span><span class="n">lockstring</span><span class="o">></span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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>1
|
||||
2
|
||||
3</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">'delete'</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">"Sorry, you may not delete that."</span><span class="p">)</span>
|
||||
<span class="k">return</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
</div>
|
||||
<div class="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 object’s <code class="docutils literal notranslate"><span class="pre">locks</span></code> property using <code class="docutils literal notranslate"><span class="pre">obj.locks.add()</span></code>.</p>
|
||||
<p>Here are some examples of lock strings (not including the quotes):</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||||
2
|
||||
3
|
||||
4</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>
|
||||
<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 "very_weak" 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>
|
||||
<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>1</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>
|
||||
</pre></div>
|
||||
</td></tr></table></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
|
||||
expression involving function calls that determine what is needed to pass the lock. Each function
|
||||
returns either <code class="docutils literal notranslate"><span class="pre">True</span></code> or <code class="docutils literal notranslate"><span class="pre">False</span></code>. <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> work as they do normally in Python. If the
|
||||
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>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="section" id="valid-access-types">
|
||||
<h3>Valid access_types<a class="headerlink" href="#valid-access-types" title="Permalink to this headline">¶</a></h3>
|
||||
<p>An <code class="docutils literal notranslate"><span class="pre">access_type</span></code>, the first part of a lockstring, defines what kind of capability a lock controls,
|
||||
such as “delete” or “edit”. You may in principle name your <code class="docutils literal notranslate"><span class="pre">access_type</span></code> anything as long as it is
|
||||
unique for the particular object. The name of the access types is not case-sensitive.</p>
|
||||
<p>If you want to make sure the lock is used however, you should pick <code class="docutils literal notranslate"><span class="pre">access_type</span></code> names that you (or
|
||||
the default command set) actually checks for, as in the example of <code class="docutils literal notranslate"><span class="pre">delete</span></code> above that uses the
|
||||
‘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>
|
||||
<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>
|
||||
<ul>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">control</span></code> - who is the “owner” of the object. Can set locks, delete it etc. Defaults to the
|
||||
creator of the object.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">call</span></code> - who may call Object-commands stored on this Object except for the Object itself. By
|
||||
default, Objects share their Commands with anyone in the same location (e.g. so you can ‘press’ a
|
||||
<code class="docutils literal notranslate"><span class="pre">Button</span></code> object in the room). For Characters and Mobs (who likely only use those Commands for
|
||||
themselves and don’t want to share them) this should usually be turned off completely, using
|
||||
something like <code class="docutils literal notranslate"><span class="pre">call:false()</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">examine</span></code> - who may examine this object’s properties.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">delete</span></code> - who may delete the object.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">edit</span></code> - who may edit properties and attributes of the object.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">view</span></code> - if the <code class="docutils literal notranslate"><span class="pre">look</span></code> command will display/list this object</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">get</span></code>- who may pick up the object and carry it around.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">puppet</span></code> - who may “become” this object and control it as their “character”.</p></li>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<ul>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">examine</span></code> - who may examine the account’s properties.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">delete</span></code> - who may delete the account.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">edit</span></code> - who may edit the account’s attributes and properties.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">msg</span></code> - who may send messages to the account.</p></li>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">send</span></code> - who may send to the channel.</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>
|
||||
<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>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p>So to take an example, whenever an exit is to be traversed, a lock of the type <em>traverse</em> will be
|
||||
checked. Defining a suitable lock type for an exit object would thus involve a lockstring <code class="docutils literal notranslate"><span class="pre">traverse:</span> <span class="pre"><lock</span> <span class="pre">functions></span></code>.</p>
|
||||
</div>
|
||||
<div class="section" id="custom-access-types">
|
||||
<h3>Custom access_types<a class="headerlink" href="#custom-access-types" title="Permalink to this headline">¶</a></h3>
|
||||
<p>As stated above, the <code class="docutils literal notranslate"><span class="pre">access_type</span></code> part of the lock is simply the ‘name’ or ‘type’ of the lock. The
|
||||
text is an arbitrary string that must be unique for an object. If adding a lock with the same
|
||||
<code class="docutils literal notranslate"><span class="pre">access_type</span></code> as one that already exists on the object, the new one override the old one.</p>
|
||||
<p>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>1</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">"read:perm(Player);post:perm(Admin)"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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>1
|
||||
2
|
||||
3</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">'read'</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">"Sorry, you may not read that."</span><span class="p">)</span>
|
||||
<span class="k">return</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
</div>
|
||||
<div class="section" id="lock-functions">
|
||||
<h3>Lock functions<a class="headerlink" href="#lock-functions" title="Permalink to this headline">¶</a></h3>
|
||||
<p>A lock function is a normal Python function put in a place Evennia looks for such functions. The
|
||||
modules Evennia looks at is the list <code class="docutils literal notranslate"><span class="pre">settings.LOCK_FUNC_MODULES</span></code>. <em>All functions</em> in any of those
|
||||
modules will automatically be considered a valid lock function. The default ones are found in
|
||||
<code class="docutils literal notranslate"><span class="pre">evennia/locks/lockfuncs.py</span></code> and you can start adding your own in <code class="docutils literal notranslate"><span class="pre">mygame/server/conf/lockfuncs.py</span></code>.
|
||||
You can append the setting to add more module paths. To replace a default lock function, just add
|
||||
your own with the same name.</p>
|
||||
<p>A lock function must always accept at least two arguments - the <em>accessing object</em> (this is the
|
||||
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>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8</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>
|
||||
<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>
|
||||
<span class="k">if</span> <span class="n">args</span><span class="p">:</span>
|
||||
<span class="n">wanted_id</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<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="bp">False</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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>1
|
||||
2</pre></div></td><td class="code"><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="s2">"edit: id(</span><span class="si">%i</span><span class="s2">)"</span> <span class="o">%</span> <span class="n">owner_object</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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>1
|
||||
2
|
||||
3
|
||||
4</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># as part of a Command'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">"edit"</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">"You don't have access to edit this!"</span><span class="p">)</span>
|
||||
<span class="k">return</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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
|
||||
<code class="docutils literal notranslate"><span class="pre">args</span></code> and all keyword arguments into a dictionary <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> respectively. If you are unfamiliar with
|
||||
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, see the Python manuals).</p>
|
||||
</div></blockquote>
|
||||
<p>Some useful default lockfuncs (see <code class="docutils literal notranslate"><span class="pre">src/locks/lockfuncs.py</span></code> for more):</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">true()/all()</span></code> - give access to everyone</p></li>
|
||||
<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>
|
||||
<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> <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">></span></code>) than the given
|
||||
value.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">attr_ge,</span> <span class="pre">attr_lt,</span> <span class="pre">attr_le,</span> <span class="pre">attr_ne</span></code> - corresponding for <code class="docutils literal notranslate"><span class="pre">>=</span></code>, <code class="docutils literal notranslate"><span class="pre"><</span></code>, <code class="docutils literal notranslate"><span class="pre"><=</span></code> and <code class="docutils literal notranslate"><span class="pre">!=</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">holds(objid)</span></code> - checks so the accessing objects contains an object of given name or dbref.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">inside()</span></code> - checks so the accessing object is inside the accessed object (the inverse of
|
||||
<code class="docutils literal notranslate"><span class="pre">holds()</span></code>).</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">pperm(perm)</span></code>, <code class="docutils literal notranslate"><span class="pre">pid(num)/pdbref(num)</span></code> - same as <code class="docutils literal notranslate"><span class="pre">perm</span></code>, <code class="docutils literal notranslate"><span class="pre">id/dbref</span></code> but always looks for
|
||||
permissions and dbrefs of <em>Accounts</em>, not on Characters.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">serversetting(settingname,</span> <span class="pre">value)</span></code> - Only returns True if Evennia has a given setting or a
|
||||
setting set to a given value.</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="checking-simple-strings">
|
||||
<h2>Checking simple strings<a class="headerlink" href="#checking-simple-strings" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Sometimes you don’t really need to look up a certain lock, you just want to check a lockstring. A
|
||||
common use is inside Commands, in order to check if a user has a certain permission. The lockhandler
|
||||
has a method <code class="docutils literal notranslate"><span class="pre">check_lockstring(accessing_obj,</span> <span class="pre">lockstring,</span> <span class="pre">bypass_superuser=False)</span></code> that allows this.</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||||
2
|
||||
3
|
||||
4</pre></div></td><td class="code"><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">"dummy:perm(Admin)"</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">"You must be an Admin or higher to do this!"</span><span class="p">)</span>
|
||||
<span class="k">return</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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>
|
||||
</div>
|
||||
<div class="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 didn’t, noone would have
|
||||
any access to anything from the start). This is all defined in the root <a class="reference internal" href="Typeclasses.html"><span class="doc">Typeclasses</span></a>
|
||||
of the respective entity, in the hook method <code class="docutils literal notranslate"><span class="pre">basetype_setup()</span></code> (which you usually don’t want to
|
||||
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
|
||||
child object to change the default. Also creation commands like <code class="docutils literal notranslate"><span class="pre">create</span></code> changes the locks of
|
||||
objects you create - for example it sets the <code class="docutils literal notranslate"><span class="pre">control</span></code> lock_type so as to allow you, its creator, to
|
||||
control and delete the object.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="permissions">
|
||||
<h1>Permissions<a class="headerlink" href="#permissions" title="Permalink to this headline">¶</a></h1>
|
||||
<blockquote>
|
||||
<div><p>This section covers the underlying code use of permissions. If you just want to learn how to
|
||||
practically assign permissions in-game, refer to the <a class="reference internal" href="../Concepts/Building-Permissions.html"><span class="doc">Building Permissions</span></a>
|
||||
page, which details how you use the <code class="docutils literal notranslate"><span class="pre">perm</span></code> command.</p>
|
||||
</div></blockquote>
|
||||
<p>A <em>permission</em> is simply a list of text strings 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>. Permissions can be 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. Permissions are especially handled by the <code class="docutils literal notranslate"><span class="pre">perm()</span></code> and
|
||||
<code class="docutils literal notranslate"><span class="pre">pperm()</span></code> lock functions listed above.</p>
|
||||
<p>Let’s 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>
|
||||
</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>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>What this lock will expect is to the fed the actual key object. The <code class="docutils literal notranslate"><span class="pre">perm()</span></code> lock function will
|
||||
check the permissions set on the key and only return true if the permission is the one given.</p>
|
||||
<p>Finally we need to actually check this lock somehow. Let’s say the chest has an command <code class="docutils literal notranslate"><span class="pre">open</span> <span class="pre"><key></span></code>
|
||||
sitting on itself. Somewhere in its code the command needs to figure out which key you are using and
|
||||
test if this key has the correct permission:</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># self.obj is the chest </span>
|
||||
<span class="c1"># and used_key is the key we used as argument to</span>
|
||||
<span class="c1"># the command. The self.caller is the one trying</span>
|
||||
<span class="c1"># to unlock the chest</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">obj</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">used_key</span><span class="p">,</span> <span class="s2">"unlock"</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">"The key does not fit!"</span><span class="p">)</span>
|
||||
<span class="k">return</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<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>
|
||||
<p>Selected permission strings can be organized in a <em>permission hierarchy</em> by editing the tuple
|
||||
<code class="docutils literal notranslate"><span class="pre">settings.PERMISSION_HIERARCHY</span></code>. Evennia’s default permission hierarchy is as follows:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">Developer</span> <span class="c1"># like superuser but affected by locks</span>
|
||||
<span class="n">Admin</span> <span class="c1"># can administrate accounts</span>
|
||||
<span class="n">Builder</span> <span class="c1"># can edit the world</span>
|
||||
<span class="n">Helper</span> <span class="c1"># can edit help files</span>
|
||||
<span class="n">Player</span> <span class="c1"># can chat and send tells (default level)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>(Also the plural form works, so you could use <code class="docutils literal notranslate"><span class="pre">Developers</span></code> etc too).</p>
|
||||
<blockquote>
|
||||
<div><p>There is also a <code class="docutils literal notranslate"><span class="pre">Guest</span></code> level below <code class="docutils literal notranslate"><span class="pre">Player</span></code> that is only active if <code class="docutils literal notranslate"><span class="pre">settings.GUEST_ENABLED</span></code> is
|
||||
set. This is never part of <code class="docutils literal notranslate"><span class="pre">settings.PERMISSION_HIERARCHY</span></code>.</p>
|
||||
</div></blockquote>
|
||||
<p>The main use of this is that if you use the lock function <code class="docutils literal notranslate"><span class="pre">perm()</span></code> mentioned above, a lock check for
|
||||
a particular permission in the hierarchy will <em>also</em> grant access to those with <em>higher</em> hierarchy
|
||||
access. So if you have the permission “Admin” you will also pass a lock defined as <code class="docutils literal notranslate"><span class="pre">perm(Builder)</span></code>
|
||||
or any of those levels below “Admin”.</p>
|
||||
<p>When doing an access check from an <a class="reference internal" href="Objects.html"><span class="doc">Object</span></a> or Character, the <code class="docutils literal notranslate"><span class="pre">perm()</span></code> lock function will
|
||||
always first use the permissions of any Account connected to that Object before checking for
|
||||
permissions on the Object. In the case of hierarchical permissions (Admins, Builders etc), the
|
||||
Account permission will always be used (this stops an Account from escalating their permission by
|
||||
puppeting a high-level Character). If the permission looked for is not in the hierarchy, an exact
|
||||
match is required, first on the Account and if not found there (or if no Account is connected), then
|
||||
on the Object itself.</p>
|
||||
<p>Here is how you use <code class="docutils literal notranslate"><span class="pre">perm</span></code> to give an account more 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> <span class="c1"># remove it again</span>
|
||||
</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 happens to be named
|
||||
“Tommy”.</p>
|
||||
<p>Putting permissions on the <em>Account</em> guarantees that they are kept, <em>regardless</em> of which Character
|
||||
they are currently puppeting. This is especially important to remember when assigning permissions
|
||||
from the <em>hierarchy tree</em> - as mentioned above, an Account’s 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>
|
||||
<p>Below is an example of an object without any connected account</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||||
2
|
||||
3
|
||||
4</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">obj1</span><span class="o">.</span><span class="n">permissions</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"Builders"</span><span class="p">,</span> <span class="s2">"cool_guy"</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">"enter:perm_above(Accounts) and perm(cool_guy)"</span><span class="p">)</span>
|
||||
|
||||
<span class="n">obj2</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">"enter"</span><span class="p">)</span> <span class="c1"># this returns True!</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<p>And one 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>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5</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">"Accounts"</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">"Builders"</span><span class="p">,</span> <span class="s2">"cool_guy"</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">"enter:perm_above(Accounts) and perm(cool_guy)"</span><span class="p">)</span>
|
||||
|
||||
<span class="n">obj2</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">puppet</span><span class="p">,</span> <span class="s2">"enter"</span><span class="p">)</span> <span class="c1"># this returns False!</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<div class="section" id="superusers">
|
||||
<h2>Superusers<a class="headerlink" href="#superusers" title="Permalink to this headline">¶</a></h2>
|
||||
<p>There is normally only one <em>superuser</em> account and that is the one first created when starting
|
||||
Evennia (User #1). This is sometimes known as the “Owner” or “God” user. A superuser has more than
|
||||
full access - it completely <em>bypasses</em> all locks so no checks are even run. This allows for the
|
||||
superuser to always have access to everything in an emergency. But it also hides any eventual errors
|
||||
you might have made in your lock definitions. So when trying out game systems you should either use
|
||||
quelling (see below) or make a second Developer-level character so your locks get tested correctly.</p>
|
||||
</div>
|
||||
<div class="section" id="quelling">
|
||||
<h2>Quelling<a class="headerlink" href="#quelling" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">quell</span></code> command can be used to enforce the <code class="docutils literal notranslate"><span class="pre">perm()</span></code> lockfunc to ignore permissions on the
|
||||
Account and instead use the permissions on the Character only. This can be used e.g. by staff to
|
||||
test out things with a lower permission level. Return to the normal operation with <code class="docutils literal notranslate"><span class="pre">unquell</span></code>. Note
|
||||
that quelling will use the smallest of any hierarchical permission on the Account or Character, so
|
||||
one cannot escalate one’s Account permission by quelling to a high-permission Character. Also the
|
||||
superuser can quell their powers this way, making them affectable by locks.</p>
|
||||
</div>
|
||||
<div class="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>
|
||||
</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">'the green key'</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>
|
||||
</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>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Evennia’s 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 don’t 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>
|
||||
</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>1
|
||||
2
|
||||
3
|
||||
4</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>
|
||||
<span class="n">lockstring</span> <span class="o">=</span> <span class="s2">"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()"</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>
|
||||
<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>
|
||||
</div>
|
||||
<div class="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>
|
||||
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">></span> <span class="n">create</span><span class="o">/</span><span class="n">drop</span> <span class="n">box</span>
|
||||
<span class="o">></span> <span class="n">desc</span> <span class="n">box</span> <span class="o">=</span> <span class="s2">"This is a very big and heavy box."</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>We want to limit which objects can pick up this heavy box. Let’s 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">></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>
|
||||
</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>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6</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">'get'</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">"You can't get that."</span><span class="p">)</span>
|
||||
<span class="k">return</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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
|
||||
error message. Sounds good! Let’s start by setting that on the box:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="o">></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>
|
||||
</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
|
||||
object has the attribute <em>strength</em> of the right value. For this we would need to create a lock
|
||||
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>
|
||||
</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 you’ll 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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15</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>
|
||||
|
||||
<span class="c1"># create, then set the lock</span>
|
||||
<span class="n">box</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span><span class="bp">None</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">"box"</span><span class="p">)</span>
|
||||
<span class="n">box</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">"get:attr_gt(strength, 50)"</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># or we can assign locks in one go right away</span>
|
||||
<span class="n">box</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span><span class="bp">None</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">"box"</span><span class="p">,</span> <span class="n">locks</span><span class="o">=</span><span class="s2">"get:attr_gt(strength, 50)"</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># set the attributes</span>
|
||||
<span class="n">box</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">desc</span> <span class="o">=</span> <span class="s2">"This is a very big and heavy box."</span>
|
||||
<span class="n">box</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">get_err_msg</span> <span class="o">=</span> <span class="s2">"You are not strong enough to lift this box."</span>
|
||||
|
||||
<span class="c1"># one heavy box, ready to withstand all but the strongest...</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
</div>
|
||||
<div class="section" id="on-django-s-permission-system">
|
||||
<h2>On Django’s permission system<a class="headerlink" href="#on-django-s-permission-system" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Django also implements a comprehensive permission/security system of its own. The reason we don’t
|
||||
use that is because it is app-centric (app in the Django sense). Its permission strings are of the
|
||||
form <code class="docutils literal notranslate"><span class="pre">appname.permstring</span></code> and it automatically adds three of them for each database model in the app</p>
|
||||
<ul class="simple">
|
||||
<li><p>for the app evennia/object this would be for example ‘object.create’, ‘object.admin’ and
|
||||
‘object.edit’. This makes a lot of sense for a web application, not so much for a MUD, especially
|
||||
when we try to hide away as much of the underlying architecture as possible.</p></li>
|
||||
</ul>
|
||||
<p>The django permissions are not completely gone however. We use it for validating passwords during
|
||||
login. It is also used exclusively for managing Evennia’s web-based admin site, which is a graphical
|
||||
front-end for the database of Evennia. You edit and assign such permissions directly from the web
|
||||
interface. It’s stand-alone from the permissions described above.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Locks</a><ul>
|
||||
<li><a class="reference internal" href="#setting-and-checking-a-lock">Setting and checking a lock</a></li>
|
||||
<li><a class="reference internal" href="#defining-locks">Defining locks</a><ul>
|
||||
<li><a class="reference internal" href="#valid-access-types">Valid access_types</a></li>
|
||||
<li><a class="reference internal" href="#custom-access-types">Custom access_types</a></li>
|
||||
<li><a class="reference internal" href="#lock-functions">Lock functions</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#checking-simple-strings">Checking simple strings</a></li>
|
||||
<li><a class="reference internal" href="#default-locks">Default locks</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#permissions">Permissions</a><ul>
|
||||
<li><a class="reference internal" href="#superusers">Superusers</a></li>
|
||||
<li><a class="reference internal" href="#quelling">Quelling</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 Django’s permission system</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/Locks.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Locks.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Locks</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
196
docs/1.0-dev/Components/MonitorHandler.html
Normal file
196
docs/1.0-dev/Components/MonitorHandler.html
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>MonitorHandler — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">MonitorHandler</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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>
|
||||
<p>The main use for the MonitorHandler is to report changes to the client; for example the client
|
||||
Session may ask Evennia to monitor the value of the Characer’s <code class="docutils literal notranslate"><span class="pre">health</span></code> attribute and report
|
||||
whenever it changes. This way the client could for example update its health bar graphic as needed.</p>
|
||||
<div class="section" id="using-the-monitorhandler">
|
||||
<h2>Using the MonitorHandler<a class="headerlink" href="#using-the-monitorhandler" title="Permalink to this headline">¶</a></h2>
|
||||
<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>Here’s how to add a new monitor:</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||||
2
|
||||
3
|
||||
4</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="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">""</span><span class="p">,</span> <span class="n">persistent</span><span class="o">=</span><span class="bp">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>
|
||||
<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 can’t monitor changes on <a class="reference internal" href="Sessions.html"><span class="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
|
||||
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
|
||||
the <code class="docutils literal notranslate"><span class="pre">db_value</span></code> field of the Attribute.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">callback</span></code>(callable) - This will be called as <code class="docutils literal notranslate"><span class="pre">callback(fieldname=fieldname,</span> <span class="pre">obj=obj,</span> <span class="pre">**kwargs)</span></code>
|
||||
when the field updates.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">idstring</span></code> (str) - this is used to separate multiple monitors on the same object and fieldname.
|
||||
This is required in order to properly identify and remove the monitor later. It’s also used for
|
||||
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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15
|
||||
16
|
||||
17
|
||||
18
|
||||
19
|
||||
20
|
||||
21</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>
|
||||
|
||||
<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">""</span><span class="p">,</span> <span class="n">obj</span><span class="o">=</span><span class="bp">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>
|
||||
<span class="c1"># for db-fields and Attributes</span>
|
||||
<span class="k">if</span> <span class="n">fieldname</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"db_"</span><span class="p">):</span>
|
||||
<span class="n">new_value</span> <span class="o">=</span> <span class="nb">getattr</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="k">else</span><span class="p">:</span> <span class="c1"># an attribute </span>
|
||||
<span class="n">new_value</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">fieldname</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">"</span><span class="si">%s</span><span class="s2">.</span><span class="si">%s</span><span class="s2"> changed to '</span><span class="si">%s</span><span class="s2">'."</span> <span class="o">%</span> \
|
||||
<span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">key</span><span class="p">,</span> <span class="n">fieldname</span><span class="p">,</span> <span class="n">new_value</span><span class="p">))</span>
|
||||
|
||||
<span class="c1"># (we could add _some_other_monitor_callback here too)</span>
|
||||
|
||||
<span class="c1"># monitor Attribute (assume we have obj from before)</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">"desc"</span><span class="p">,</span> <span class="n">_monitor_callback</span><span class="p">)</span>
|
||||
|
||||
<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">"db_key"</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">"foo"</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">"db_key"</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">"bar"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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>
|
||||
<p>So to “un-monitor” the above you need to supply enough information for the system to uniquely find
|
||||
the monitor to remove:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">monitorhandler</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="s2">"desc"</span><span class="p">)</span>
|
||||
<span class="n">monitorhandler</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="s2">"db_key"</span><span class="p">,</span> <span class="n">idstring</span><span class="o">=</span><span class="s2">"foo"</span><span class="p">)</span>
|
||||
<span class="n">monitorhandler</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="s2">"db_key"</span><span class="p">,</span> <span class="n">idstring</span><span class="o">=</span><span class="s2">"bar"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">MonitorHandler</a><ul>
|
||||
<li><a class="reference internal" href="#using-the-monitorhandler">Using the MonitorHandler</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/MonitorHandler.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="MonitorHandler.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">MonitorHandler</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
235
docs/1.0-dev/Components/Nicks.html
Normal file
235
docs/1.0-dev/Components/Nicks.html
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Nicks — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Nicks</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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
|
||||
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
|
||||
address the entity thereafter. A <em>Nick</em> on the other hand, is used to map a different way <em>you
|
||||
alone</em> can refer to that entity. Nicks are also commonly used to replace your input text which means
|
||||
you can create your own aliases to default commands.</p>
|
||||
<p>Default Evennia use Nicks in three flavours that determine when Evennia actually tries to do the
|
||||
substitution.</p>
|
||||
<ul class="simple">
|
||||
<li><p>inputline - replacement is attempted whenever you write anything on the command line. This is the
|
||||
default.</p></li>
|
||||
<li><p>objects - replacement is only attempted when referring to an object</p></li>
|
||||
<li><p>accounts - replacement is only attempted when referring an account</p></li>
|
||||
</ul>
|
||||
<p>Here’s 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>
|
||||
</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>
|
||||
</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>
|
||||
</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>
|
||||
</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>
|
||||
</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>
|
||||
</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>
|
||||
</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
|
||||
</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
|
||||
inserted in the replacement string. This example allows you to do <code class="docutils literal notranslate"><span class="pre">build</span> <span class="pre">box</span> <span class="pre">crate</span></code> and have Evennia
|
||||
see <code class="docutils literal notranslate"><span class="pre">@create/drop</span> <span class="pre">box;crate</span></code>. You may use any <code class="docutils literal notranslate"><span class="pre">$</span></code> numbers between 1 and 99, but the markers must
|
||||
match between the nick pattern and the replacement.</p>
|
||||
<blockquote>
|
||||
<div><p>If you want to catch “the rest” of a command argument, make sure to put a <code class="docutils literal notranslate"><span class="pre">$</span></code> tag <em>with no spaces
|
||||
to the right of it</em> - it will then receive everything up until the end of the line.</p>
|
||||
</div></blockquote>
|
||||
<p>You can also use <a class="reference external" href="http://www.linfo.org/wildcard.html">shell-type wildcards</a>:</p>
|
||||
<ul class="simple">
|
||||
<li><p>* - matches everything.</p></li>
|
||||
<li><p>? - matches a single character.</p></li>
|
||||
<li><p>[seq] - matches everything in the sequence, e.g. [xyz] will match both x, y and z</p></li>
|
||||
<li><p>[!seq] - matches everything <em>not</em> in the sequence. e.g. [!xyz] will match all but x,y z.</p></li>
|
||||
</ul>
|
||||
<div class="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
|
||||
offers effective error checking, searches and conversion.</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15
|
||||
16
|
||||
17</pre></div></td><td class="code"><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">"greetjack"</span><span class="p">,</span> <span class="s2">"tell Jack = Hello pal!"</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># An object 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">"rose"</span><span class="p">,</span> <span class="s2">"The red flower"</span><span class="p">,</span> <span class="n">nick_type</span><span class="o">=</span><span class="s2">"object"</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># An account 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">"tom"</span><span class="p">,</span> <span class="s2">"Tommy Hill"</span><span class="p">,</span> <span class="n">nick_type</span><span class="o">=</span><span class="s2">"account"</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># My own custom nick type (handled by my own game code somehow):</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">"hood"</span><span class="p">,</span> <span class="s2">"The hooded man"</span><span class="p">,</span> <span class="n">nick_type</span><span class="o">=</span><span class="s2">"my_identsystem"</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># get back the translated nick:</span>
|
||||
<span class="n">full_name</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">"rose"</span><span class="p">,</span> <span class="n">nick_type</span><span class="o">=</span><span class="s2">"object"</span><span class="p">)</span>
|
||||
|
||||
<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">"rose"</span><span class="p">,</span> <span class="n">nick_type</span><span class="o">=</span><span class="s2">"object"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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
|
||||
<code class="docutils literal notranslate"><span class="pre">nick_type="channel"</span></code> in order to allow users to create their own custom aliases to channels.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" 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
|
||||
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
|
||||
representation of the <code class="docutils literal notranslate"><span class="pre">raw_nick</span></code> and the <code class="docutils literal notranslate"><span class="pre">template-string</span></code> is a version of the <code class="docutils literal notranslate"><span class="pre">raw_template</span></code>
|
||||
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, here’s how:</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||||
2
|
||||
3</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">"nickname"</span><span class="p">,</span> <span class="n">return_tuple</span><span class="o">=</span><span class="bp">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">"nickname"</span><span class="p">,</span> <span class="n">return_obj</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span><span class="o">.</span><span class="n">value</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Nicks</a><ul>
|
||||
<li><a class="reference internal" href="#coding-with-nicks">Coding with nicks</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#advanced-note">Advanced note</a></li>
|
||||
</ul>
|
||||
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Components/Nicks.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Nicks.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Nicks</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
304
docs/1.0-dev/Components/Objects.html
Normal file
304
docs/1.0-dev/Components/Objects.html
Normal file
|
|
@ -0,0 +1,304 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Objects — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Objects</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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 you’ll
|
||||
spend most time working with. Objects are <a class="reference internal" href="Typeclasses.html"><span class="doc">Typeclassed</span></a> entities.</p>
|
||||
<div class="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
|
||||
parents. In <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/objects.py</span></code> there is already a class <code class="docutils literal notranslate"><span class="pre">Object</span></code> that inherits from
|
||||
<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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13</pre></div></td><td class="code"><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>
|
||||
|
||||
<span class="k">class</span> <span class="nc">Rose</span><span class="p">(</span><span class="n">Object</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> This creates a simple rose object </span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">def</span> <span class="nf">at_object_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="s2">"this is called only once, when object is first created"</span>
|
||||
<span class="c1"># add a persistent attribute 'desc' </span>
|
||||
<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">"This is a pretty rose with thorns."</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<p>You could save this in the <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/objects.py</span></code> (then you’d not need to import <code class="docutils literal notranslate"><span class="pre">Object</span></code>)
|
||||
or you can put it in a new module. Let’s 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">@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>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>What the <code class="docutils literal notranslate"><span class="pre">@create</span></code> command actually <em>does</em> is to use <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>1
|
||||
2</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>
|
||||
<span class="n">new_rose</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span><span class="s2">"typeclasses.flowers.Rose"</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">"MyRose"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<p>(The <code class="docutils literal notranslate"><span class="pre">@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>
|
||||
<p>This particular Rose class doesn’t really do much, all it does it make sure the attribute
|
||||
<code class="docutils literal notranslate"><span class="pre">desc</span></code>(which is what the <code class="docutils literal notranslate"><span class="pre">look</span></code> command looks for) is pre-set, which is pretty pointless since you
|
||||
will usually want to change this at build time (using the <code class="docutils literal notranslate"><span class="pre">@desc</span></code> command or using the
|
||||
<a class="reference internal" href="Spawner-and-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
|
||||
to use though - see next section.</p>
|
||||
</div>
|
||||
<div class="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
|
||||
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
|
||||
<code class="docutils literal notranslate"><span class="pre">aliases.add()</span></code> to add a new alias and <code class="docutils literal notranslate"><span class="pre">aliases.remove()</span></code> to remove one.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">location</span></code> - a reference to the object currently containing this object.</p></li>
|
||||
<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>, it’s 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
|
||||
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
|
||||
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
|
||||
sessions (server connections) to contact them through (it may be more than one if multiple
|
||||
connections are allowed in settings).</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">has_account</span></code> - a shorthand for checking if an <em>online</em> account is currently connected to this
|
||||
object.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">contents</span></code> - this returns a list referencing all objects ‘inside’ this object (i,e. which has this
|
||||
object set as their <code class="docutils literal notranslate"><span class="pre">location</span></code>).</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">exits</span></code> - this returns all objects inside this object that are <em>Exits</em>, that is, has the
|
||||
<code class="docutils literal notranslate"><span class="pre">destination</span></code> property set.</p></li>
|
||||
</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
|
||||
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>
|
||||
</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>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">msg()</span></code> - this function is used to send messages from the server to an account connected to this
|
||||
object.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">msg_contents()</span></code> - calls <code class="docutils literal notranslate"><span class="pre">msg</span></code> on all objects inside this object.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">search()</span></code> - this is a convenient shorthand to search for a specific object, at a given location
|
||||
or globally. It’s mainly useful when defining commands (in which case the object executing the
|
||||
command is named <code class="docutils literal notranslate"><span class="pre">caller</span></code> and one can do <code class="docutils literal notranslate"><span class="pre">caller.search()</span></code> to find objects in the room to operate
|
||||
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_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
|
||||
<code class="docutils literal notranslate"><span class="pre">clear_contents()</span></code>.</p></li>
|
||||
</ul>
|
||||
<p>The Object Typeclass defines many more <em>hook methods</em> beyond <code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code>. Evennia calls
|
||||
these hooks at various points. When implementing your custom objects, you will inherit from the
|
||||
base parent and overload these hooks with your own custom code. See <code class="docutils literal notranslate"><span class="pre">evennia.objects.objects</span></code> for an
|
||||
updated list of all the available hooks or the <a class="reference external" href="../api/evennia.objects.objects.html#defaultobject">API for DefaultObject
|
||||
here</a>.</p>
|
||||
</div>
|
||||
<div class="section" id="subclasses-of-object">
|
||||
<h2>Subclasses of <code class="docutils literal notranslate"><span class="pre">Object</span></code><a class="headerlink" href="#subclasses-of-object" title="Permalink to this headline">¶</a></h2>
|
||||
<p>There are three special subclasses of <em>Object</em> in default Evennia - <em>Characters</em>, <em>Rooms</em> and
|
||||
<em>Exits</em>. The reason they are separated is because these particular object types are fundamental,
|
||||
something you will always need and in some cases requires some extra attention in order to be
|
||||
recognized by the game engine (there is nothing stopping you from redefining them though). In
|
||||
practice they are all pretty similar to the base Object.</p>
|
||||
<div class="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
|
||||
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
|
||||
creation, or the account will not be able to issue any commands! If you just
|
||||
inherit your own class from <code class="docutils literal notranslate"><span class="pre">evennia.DefaultCharacter</span></code> and make sure to use
|
||||
<code class="docutils literal notranslate"><span class="pre">super()</span></code> to call the parent methods you should be fine. In
|
||||
<code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/characters.py</span></code> is an empty <code class="docutils literal notranslate"><span class="pre">Character</span></code> class ready for you
|
||||
to modify.</p>
|
||||
</div>
|
||||
<div class="section" id="rooms">
|
||||
<h3>Rooms<a class="headerlink" href="#rooms" title="Permalink to this headline">¶</a></h3>
|
||||
<p><em>Rooms</em> are the root containers of all other objects. The only thing really separating a room from
|
||||
any other object is that they have no <code class="docutils literal notranslate"><span class="pre">location</span></code> of their own and that default commands like <code class="docutils literal notranslate"><span class="pre">@dig</span></code>
|
||||
creates objects of this class - so if you want to expand your rooms with more functionality, just
|
||||
inherit from <code class="docutils literal notranslate"><span class="pre">ev.DefaultRoom</span></code>. In <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/rooms.py</span></code> is an empty <code class="docutils literal notranslate"><span class="pre">Room</span></code> class ready for
|
||||
you to modify.</p>
|
||||
</div>
|
||||
<div class="section" id="exits">
|
||||
<h3>Exits<a class="headerlink" href="#exits" title="Permalink to this headline">¶</a></h3>
|
||||
<p><em>Exits</em> are objects connecting other objects (usually <em>Rooms</em>) together. An object named <em>North</em> or
|
||||
<em>in</em> might be an exit, as well as <em>door</em>, <em>portal</em> or <em>jump out the window</em>. An exit has two things
|
||||
that separate them from other objects. Firstly, their <em>destination</em> property is set and points to a
|
||||
valid object. This fact makes it easy and fast to locate exits in the database. Secondly, exits
|
||||
define a special <a class="reference internal" href="Commands.html"><span class="doc">Transit Command</span></a> on themselves when they are created. This command is
|
||||
named the same as the exit object and will, when called, handle the practicalities of moving the
|
||||
character to the Exits’s <em>destination</em> - this allows you to just enter the name of the exit on its
|
||||
own to move around, just as you would expect.</p>
|
||||
<p>The exit functionality is all defined on the Exit typeclass, so you could in principle completely
|
||||
change how exits work in your game (it’s not recommended though, unless you really know what you are
|
||||
doing). Exits are <a class="reference internal" href="Locks.html"><span class="doc">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
|
||||
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>
|
||||
<li><p>The Exit command triggers <code class="docutils literal notranslate"><span class="pre">at_traverse(obj,</span> <span class="pre">destination)</span></code> on the Exit object.</p></li>
|
||||
<li><p>In <code class="docutils literal notranslate"><span class="pre">at_traverse</span></code>, <code class="docutils literal notranslate"><span class="pre">object.move_to(destination)</span></code> is triggered. This triggers the following hooks,
|
||||
in order:</p>
|
||||
<ol class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">obj.at_before_move(destination)</span></code> - if this returns False, move is aborted.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">origin.at_before_leave(obj,</span> <span class="pre">destination)</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">obj.announce_move_from(destination)</span></code></p></li>
|
||||
<li><p>Move is performed by changing <code class="docutils literal notranslate"><span class="pre">obj.location</span></code> from source location to <code class="docutils literal notranslate"><span class="pre">destination</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">obj.announce_move_to(source)</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">destination.at_object_receive(obj,</span> <span class="pre">source)</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">obj.at_after_move(source)</span></code></p></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><p>On the Exit object, <code class="docutils literal notranslate"><span class="pre">at_after_traverse(obj,</span> <span class="pre">source)</span></code> is triggered.</p></li>
|
||||
</ol>
|
||||
<p>If the move fails for whatever reason, the Exit will look for an Attribute <code class="docutils literal notranslate"><span class="pre">err_traverse</span></code> on itself
|
||||
and display this as an error message. If this is not found, the Exit will instead call
|
||||
<code class="docutils literal notranslate"><span class="pre">at_failed_traverse(obj)</span></code> on itself.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Objects</a><ul>
|
||||
<li><a class="reference internal" href="#how-to-create-your-own-object-types">How to create your own object types</a></li>
|
||||
<li><a class="reference internal" href="#properties-and-functions-on-objects">Properties and functions on Objects</a></li>
|
||||
<li><a class="reference internal" href="#subclasses-of-object">Subclasses of <code class="docutils literal notranslate"><span class="pre">Object</span></code></a><ul>
|
||||
<li><a class="reference internal" href="#characters">Characters</a></li>
|
||||
<li><a class="reference internal" href="#rooms">Rooms</a></li>
|
||||
<li><a class="reference internal" href="#exits">Exits</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Components/Objects.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Objects.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Objects</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
99
docs/1.0-dev/Components/Outputfuncs.html
Normal file
99
docs/1.0-dev/Components/Outputfuncs.html
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Outputfuncs — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Outputfuncs</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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>
|
||||
</div>
|
||||
|
||||
|
||||
<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>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Components/Outputfuncs.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Outputfuncs.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Outputfuncs</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
107
docs/1.0-dev/Components/Portal-And-Server.html
Normal file
107
docs/1.0-dev/Components/Portal-And-Server.html
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Portal And Server — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Portal And Server</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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>
|
||||
<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></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>
|
||||
</div>
|
||||
|
||||
|
||||
<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>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Components/Portal-And-Server.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Portal-And-Server.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Portal And Server</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
537
docs/1.0-dev/Components/Scripts.html
Normal file
537
docs/1.0-dev/Components/Scripts.html
Normal file
|
|
@ -0,0 +1,537 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Scripts — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Scripts</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" id="scripts">
|
||||
<h1>Scripts<a class="headerlink" href="#scripts" title="Permalink to this headline">¶</a></h1>
|
||||
<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 “Script” is a bit limiting</p>
|
||||
<ul class="simple">
|
||||
<li><p>we had to pick something to name them after all. Other possible names
|
||||
(depending on what you’d use them for) would be <code class="docutils literal notranslate"><span class="pre">OOBObjects</span></code>,
|
||||
<code class="docutils literal notranslate"><span class="pre">StorageContainers</span></code> or <code class="docutils literal notranslate"><span class="pre">TimerObjects</span></code>.</p></li>
|
||||
</ul>
|
||||
<p>Scripts can be used for many different things in Evennia:</p>
|
||||
<ul class="simple">
|
||||
<li><p>They can attach to Objects to influence them in various ways - or exist
|
||||
independently of any one in-game entity (so-called <em>Global Scripts</em>).</p></li>
|
||||
<li><p>They can work as timers and tickers - anything that may change with Time. But
|
||||
they can also have no time dependence at all. Note though that if all you want
|
||||
is just to have an object method called repeatedly, you should consider using
|
||||
the <a class="reference internal" href="TickerHandler.html"><span class="doc">TickerHandler</span></a> which is more limited but is specialized on
|
||||
just this task.</p></li>
|
||||
<li><p>They can describe State changes. A Script is an excellent platform for
|
||||
hosting a persistent, but unique system handler. For example, a Script could be
|
||||
used as the base to track the state of a turn-based combat system. Since
|
||||
Scripts can also operate on a timer they can also update themselves regularly
|
||||
to perform various actions.</p></li>
|
||||
<li><p>They can act as data stores for storing game data persistently in the database
|
||||
(thanks to its ability to have <a class="reference internal" href="Attributes.html"><span class="doc">Attributes</span></a>).</p></li>
|
||||
<li><p>They can be used as OOC stores for sharing data between groups of objects, for
|
||||
example for tracking the turns in a turn-based combat system or barter exchange.</p></li>
|
||||
</ul>
|
||||
<p>Scripts are <a class="reference internal" href="Typeclasses.html"><span class="doc">Typeclassed</span></a> entities and are manipulated in a similar
|
||||
way to how it works for other such Evennia entities:</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># create a new script </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">"myscript"</span><span class="p">,</span> <span class="n">typeclass</span><span class="o">=...</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># search (this is always a list, also if there is only one match)</span>
|
||||
<span class="n">list_of_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">"myscript"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<div class="section" id="defining-new-scripts">
|
||||
<h2>Defining new Scripts<a class="headerlink" href="#defining-new-scripts" title="Permalink to this headline">¶</a></h2>
|
||||
<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 class has several properties
|
||||
to control the timer-component of the scripts. These are all <em>optional</em> -
|
||||
leaving them out will just create a Script with no timer components (useful to act as
|
||||
a database store or to hold a persistent game system, for example).</p>
|
||||
<p>This you can do for example in the module
|
||||
<code class="docutils literal notranslate"><span class="pre">evennia/typeclasses/scripts.py</span></code>. Below is an example Script
|
||||
Typeclass.</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10</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">DefaultScript</span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">MyScript</span><span class="p">(</span><span class="n">DefaultScript</span><span class="p">):</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">at_script_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">key</span> <span class="o">=</span> <span class="s2">"myscript"</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">interval</span> <span class="o">=</span> <span class="mi">60</span> <span class="c1"># 1 min repeat</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">at_repeat</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="c1"># do stuff every minute </span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<p>In <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/scripts.py</span></code> is the <code class="docutils literal notranslate"><span class="pre">Script</span></code> class which inherits from <code class="docutils literal notranslate"><span class="pre">DefaultScript</span></code>
|
||||
already. This is provided as your own base class to do with what you like: You can tweak <code class="docutils literal notranslate"><span class="pre">Script</span></code> if
|
||||
you want to change the default behavior and it is usually convenient to inherit from this instead.
|
||||
Here’s an example:</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15
|
||||
16
|
||||
17
|
||||
18
|
||||
19
|
||||
20
|
||||
21
|
||||
22
|
||||
23
|
||||
24
|
||||
25
|
||||
26
|
||||
27
|
||||
28
|
||||
29</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># for example in 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>
|
||||
|
||||
<span class="k">class</span> <span class="nc">Weather</span><span class="p">(</span><span class="n">Script</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> A timer script that displays weather info. Meant to </span>
|
||||
<span class="sd"> be attached to a room. </span>
|
||||
<span class="sd"> </span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">def</span> <span class="nf">at_script_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">key</span> <span class="o">=</span> <span class="s2">"weather_script"</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">desc</span> <span class="o">=</span> <span class="s2">"Gives random weather messages."</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">interval</span> <span class="o">=</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">5</span> <span class="c1"># every 5 minutes</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">persistent</span> <span class="o">=</span> <span class="bp">True</span> <span class="c1"># will survive reload</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">at_repeat</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="s2">"called every self.interval seconds."</span>
|
||||
<span class="n">rand</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">()</span>
|
||||
<span class="k">if</span> <span class="n">rand</span> <span class="o"><</span> <span class="mf">0.5</span><span class="p">:</span>
|
||||
<span class="n">weather</span> <span class="o">=</span> <span class="s2">"A faint breeze is felt."</span>
|
||||
<span class="k">elif</span> <span class="n">rand</span> <span class="o"><</span> <span class="mf">0.7</span><span class="p">:</span>
|
||||
<span class="n">weather</span> <span class="o">=</span> <span class="s2">"Clouds sweep across the sky."</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">weather</span> <span class="o">=</span> <span class="s2">"There is a light drizzle of rain."</span>
|
||||
<span class="c1"># send this message to everyone inside the object this</span>
|
||||
<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>
|
||||
<p>If we put this script on a room, it will randomly report some weather
|
||||
to everyone in the room every 5 minutes.</p>
|
||||
<p>To activate it, just add it to the script handler (<code class="docutils literal notranslate"><span class="pre">scripts</span></code>) on an
|
||||
<a class="reference internal" href="Objects.html"><span class="doc">Room</span></a>. That object becomes <code class="docutils literal notranslate"><span class="pre">self.obj</span></code> in the example above. Here we
|
||||
put it on a room called <code class="docutils literal notranslate"><span class="pre">myroom</span></code>:</p>
|
||||
<div class="highlight-default 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>
|
||||
</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 don’t 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 create scripts using the <code class="docutils literal notranslate"><span class="pre">evennia.create_script</span></code> function:</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||||
2</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_script</span>
|
||||
<span class="n">create_script</span><span class="p">(</span><span class="s1">'typeclasses.weather.Weather'</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>
|
||||
<p>Note that if you were to give a keyword argument to <code class="docutils literal notranslate"><span class="pre">create_script</span></code>, that would
|
||||
override the default value in your Typeclass. So for example, here is an instance
|
||||
of the weather script that runs every 10 minutes instead (and also not survive
|
||||
a server reload):</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||||
2</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">'typeclasses.weather.Weather'</span><span class="p">,</span> <span class="n">obj</span><span class="o">=</span><span class="n">myroom</span><span class="p">,</span>
|
||||
<span class="n">persistent</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="mi">10</span><span class="o">*</span><span class="mi">60</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<p>From in-game you can use the <code class="docutils literal notranslate"><span class="pre">@script</span></code> command to launch the Script on things:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="nd">@script</span> <span class="n">here</span> <span class="o">=</span> <span class="n">typeclasses</span><span class="o">.</span><span class="n">scripts</span><span class="o">.</span><span class="n">Weather</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>You can conveniently view and kill running Scripts by using the <code class="docutils literal notranslate"><span class="pre">@scripts</span></code>
|
||||
command in-game.</p>
|
||||
</div>
|
||||
<div class="section" id="properties-and-functions-defined-on-scripts">
|
||||
<h2>Properties and functions defined on Scripts<a class="headerlink" href="#properties-and-functions-defined-on-scripts" title="Permalink to this headline">¶</a></h2>
|
||||
<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
|
||||
etc). These are usually set up in the Script’s typeclass, but can also be assigned on the fly as
|
||||
keyword arguments to <code class="docutils literal notranslate"><span class="pre">evennia.create_script</span></code>.</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">desc</span></code> - an optional description of the script’s function. Seen in script listings.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">interval</span></code> - how often the script should run. If <code class="docutils literal notranslate"><span class="pre">interval</span> <span class="pre">==</span> <span class="pre">0</span></code> (default), this script has no
|
||||
timing component, will not repeat and will exist forever. This is useful for Scripts used for
|
||||
storage or acting as bases for various non-time dependent game systems.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">start_delay</span></code> - (bool), if we should wait <code class="docutils literal notranslate"><span class="pre">interval</span></code> seconds before firing for the first time or
|
||||
not.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">repeats</span></code> - How many times we should repeat, assuming <code class="docutils literal notranslate"><span class="pre">interval</span> <span class="pre">></span> <span class="pre">0</span></code>. If repeats is set to <code class="docutils literal notranslate"><span class="pre"><=</span> <span class="pre">0</span></code>,
|
||||
the script will repeat indefinitely. Note that <em>each</em> firing of the script (including the first one)
|
||||
counts towards this value. So a <code class="docutils literal notranslate"><span class="pre">Script</span></code> with <code class="docutils literal notranslate"><span class="pre">start_delay=False</span></code> and <code class="docutils literal notranslate"><span class="pre">repeats=1</span></code> will start,
|
||||
immediately fire and shut down right away.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">persistent</span></code>- if this script should survive a server <em>reset</em> or server <em>shutdown</em>. (You don’t need
|
||||
to set this for it to survive a normal reload - the script will be paused and seamlessly restart
|
||||
after the reload is complete).</p></li>
|
||||
</ul>
|
||||
<p>There is one special property:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">obj</span></code> - the <a class="reference internal" href="Objects.html"><span class="doc">Object</span></a> this script is attached to (if any). You should not need to set
|
||||
this manually. If you add the script to the Object with <code class="docutils literal notranslate"><span class="pre">myobj.scripts.add(myscriptpath)</span></code> or give
|
||||
<code class="docutils literal notranslate"><span class="pre">myobj</span></code> as an argument to the <code class="docutils literal notranslate"><span class="pre">utils.create.create_script</span></code> function, the <code class="docutils literal notranslate"><span class="pre">obj</span></code> property will be set
|
||||
to <code class="docutils literal notranslate"><span class="pre">myobj</span></code> for you.</p></li>
|
||||
</ul>
|
||||
<p>It’s also imperative to know the hook functions. Normally, overriding
|
||||
these are all the customization you’ll need to do in Scripts. You can
|
||||
find longer descriptions of these in <code class="docutils literal notranslate"><span class="pre">src/scripts/scripts.py</span></code>.</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">at_script_creation()</span></code> - this is usually where the script class sets things like <code class="docutils literal notranslate"><span class="pre">interval</span></code> and
|
||||
<code class="docutils literal notranslate"><span class="pre">repeats</span></code>; things that control how the script runs. It is only called once - when the script is
|
||||
first created.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">is_valid()</span></code> - determines if the script should still be running or not. This is called when
|
||||
running <code class="docutils literal notranslate"><span class="pre">obj.scripts.validate()</span></code>, which you can run manually, but which is also called by Evennia
|
||||
during certain situations such as reloads. This is also useful for using scripts as state managers.
|
||||
If the method returns <code class="docutils literal notranslate"><span class="pre">False</span></code>, the script is stopped and cleanly removed.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">at_start()</span></code> - this is called when the script starts or is unpaused. For persistent scripts this
|
||||
is at least once ever server startup. Note that this will <em>always</em> be called right away, also if
|
||||
<code class="docutils literal notranslate"><span class="pre">start_delay</span></code> is <code class="docutils literal notranslate"><span class="pre">True</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">at_repeat()</span></code> - this is called every <code class="docutils literal notranslate"><span class="pre">interval</span></code> seconds, or not at all. It is called right away at
|
||||
startup, unless <code class="docutils literal notranslate"><span class="pre">start_delay</span></code> is <code class="docutils literal notranslate"><span class="pre">True</span></code>, in which case the system will wait <code class="docutils literal notranslate"><span class="pre">interval</span></code> seconds
|
||||
before calling.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">at_stop()</span></code> - this is called when the script stops for whatever reason. It’s a good place to do
|
||||
custom cleanup.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">at_server_reload()</span></code> - this is called whenever the server is warm-rebooted (e.g. with the
|
||||
<code class="docutils literal notranslate"><span class="pre">@reload</span></code> command). It’s a good place to save non-persistent data you might want to survive a
|
||||
reload.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">at_server_shutdown()</span></code> - this is called when a system reset or systems shutdown is invoked.</p></li>
|
||||
</ul>
|
||||
<p>Running methods (usually called automatically by the engine, but possible to also invoke manually)</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">start()</span></code> - this will start the script. This is called automatically whenever you add a new script
|
||||
to a handler. <code class="docutils literal notranslate"><span class="pre">at_start()</span></code> will be called.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">stop()</span></code> - this will stop the script and delete it. Removing a script from a handler will stop it
|
||||
automatically. <code class="docutils literal notranslate"><span class="pre">at_stop()</span></code> will be called.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">pause()</span></code> - this pauses a running script, rendering it inactive, but not deleting it. All
|
||||
properties are saved and timers can be resumed. This is called automatically when the server reloads
|
||||
and will <em>not</em> lead to the <em>at_stop()</em> hook being called. This is a suspension of the script, not a
|
||||
change of state.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">unpause()</span></code> - resumes a previously paused script. The <code class="docutils literal notranslate"><span class="pre">at_start()</span></code> hook <em>will</em> be called to allow
|
||||
it to reclaim its internal state. Timers etc are restored to what they were before pause. The server
|
||||
automatically unpauses all paused scripts after a server reload.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">force_repeat()</span></code> - this will forcibly step the script, regardless of when it would otherwise have
|
||||
fired. The timer will reset and the <code class="docutils literal notranslate"><span class="pre">at_repeat()</span></code> hook is called as normal. This also counts towards
|
||||
the total number of repeats, if limited.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">time_until_next_repeat()</span></code> - for timed scripts, this returns the time in seconds until it next
|
||||
fires. Returns <code class="docutils literal notranslate"><span class="pre">None</span></code> if <code class="docutils literal notranslate"><span class="pre">interval==0</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">remaining_repeats()</span></code> - if the Script should run a limited amount of times, this tells us how many
|
||||
are currently left.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">reset_callcount(value=0)</span></code> - this allows you to reset the number of times the Script has fired. It
|
||||
only makes sense if <code class="docutils literal notranslate"><span class="pre">repeats</span> <span class="pre">></span> <span class="pre">0</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">restart(interval=None,</span> <span class="pre">repeats=None,</span> <span class="pre">start_delay=None)</span></code> - this method allows you to restart the
|
||||
Script in-place with different run settings. If you do, the <code class="docutils literal notranslate"><span class="pre">at_stop</span></code> hook will be called and the
|
||||
Script brought to a halt, then the <code class="docutils literal notranslate"><span class="pre">at_start</span></code> hook will be called as the Script starts up with your
|
||||
(possibly changed) settings. Any keyword left at <code class="docutils literal notranslate"><span class="pre">None</span></code> means to not change the original setting.</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="global-scripts">
|
||||
<h2>Global Scripts<a class="headerlink" href="#global-scripts" title="Permalink to this headline">¶</a></h2>
|
||||
<p>A script does not have to be connected to an in-game object. If not it is
|
||||
called a <em>Global script</em>. You can create global scripts by simply not supplying an object to store
|
||||
it on:</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||||
2
|
||||
3
|
||||
4</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># adding a global script</span>
|
||||
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">create_script</span>
|
||||
<span class="n">create_script</span><span class="p">(</span><span class="s2">"typeclasses.globals.MyGlobalEconomy"</span><span class="p">,</span>
|
||||
<span class="n">key</span><span class="o">=</span><span class="s2">"economy"</span><span class="p">,</span> <span class="n">persistent</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">obj</span><span class="o">=</span><span class="bp">None</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<p>Henceforth you can then get it back by searching for its key or other identifier with
|
||||
<code class="docutils literal notranslate"><span class="pre">evennia.search_script</span></code>. In-game, the <code class="docutils literal notranslate"><span class="pre">scripts</span></code> command will show all scripts.</p>
|
||||
<p>Evennia supplies a convenient “container” called <code class="docutils literal notranslate"><span class="pre">GLOBAL_SCRIPTS</span></code> that can offer an easy
|
||||
way to access global scripts. If you know the name (key) of the script you can get it like so:</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9</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>
|
||||
|
||||
<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>
|
||||
<span class="c1"># needed if there are spaces in name or name determined on the fly</span>
|
||||
<span class="n">another_script</span> <span class="o">=</span> <span class="n">GLOBAL_SCRIPTS</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"another script"</span><span class="p">)</span>
|
||||
<span class="c1"># get all global scripts (this returns a Queryset)</span>
|
||||
<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">"Cloudy"</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<blockquote>
|
||||
<div><p>Note that global scripts appear as properties on <code class="docutils literal notranslate"><span class="pre">GLOBAL_SCRIPTS</span></code> based on their <code class="docutils literal notranslate"><span class="pre">key</span></code>.
|
||||
If you were to create two global scripts with the same <code class="docutils literal notranslate"><span class="pre">key</span></code> (even with different typeclasses),
|
||||
the <code class="docutils literal notranslate"><span class="pre">GLOBAL_SCRIPTS</span></code> container will only return one of them (which one depends on order in
|
||||
the database). Best is to organize your scripts so that this does not happen. Otherwise, use
|
||||
<code class="docutils literal notranslate"><span class="pre">evennia.search_script</span></code> to get exactly the script you want.</p>
|
||||
</div></blockquote>
|
||||
<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>. The first is
|
||||
to manually create a new global script with <code class="docutils literal notranslate"><span class="pre">create_script</span></code> as mentioned above. Often you want this
|
||||
to happen automatically when the server starts though. For this you can use the setting
|
||||
<code class="docutils literal notranslate"><span class="pre">GLOBAL_SCRIPTS</span></code>:</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">GLOBAL_SCRIPTS</span> <span class="o">=</span> <span class="p">{</span>
|
||||
<span class="s2">"my_script"</span><span class="p">:</span> <span class="p">{</span>
|
||||
<span class="s2">"typeclass"</span><span class="p">:</span> <span class="s2">"scripts.Weather"</span><span class="p">,</span>
|
||||
<span class="s2">"repeats"</span><span class="p">:</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span>
|
||||
<span class="s2">"interval"</span><span class="p">:</span> <span class="mi">50</span><span class="p">,</span>
|
||||
<span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"Weather script"</span>
|
||||
<span class="s2">"persistent"</span><span class="p">:</span> <span class="bp">True</span>
|
||||
<span class="p">},</span>
|
||||
<span class="s2">"storagescript"</span><span class="p">:</span> <span class="p">{</span>
|
||||
<span class="s2">"typeclass"</span><span class="p">:</span> <span class="s2">"scripts.Storage"</span><span class="p">,</span>
|
||||
<span class="s2">"persistent"</span><span class="p">:</span> <span class="bp">True</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<p>Here the key (<code class="docutils literal notranslate"><span class="pre">myscript</span></code> and <code class="docutils literal notranslate"><span class="pre">storagescript</span></code> above) is required, all other fields are optional. If
|
||||
<code class="docutils literal notranslate"><span class="pre">typeclass</span></code> is not given, a script of type <code class="docutils literal notranslate"><span class="pre">settings.BASE_SCRIPT_TYPECLASS</span></code> is assumed. The keys
|
||||
related to timing and intervals are only needed if the script is timed.</p>
|
||||
<p>Evennia will use the information in <code class="docutils literal notranslate"><span class="pre">settings.GLOBAL_SCRIPTS</span></code> to automatically create and start
|
||||
these
|
||||
scripts when the server starts (unless they already exist, based on their <code class="docutils literal notranslate"><span class="pre">key</span></code>). You need to reload
|
||||
the server before the setting is read and new scripts become available. You can then find the <code class="docutils literal notranslate"><span class="pre">key</span></code>
|
||||
you gave as properties on <code class="docutils literal notranslate"><span class="pre">evennia.GLOBAL_SCRIPTS</span></code>
|
||||
(such as <code class="docutils literal notranslate"><span class="pre">evennia.GLOBAL_SCRIPTS.storagescript</span></code>).</p>
|
||||
<blockquote>
|
||||
<div><p>Note: Make sure that your Script typeclass does not have any critical errors. If so, you’ll see
|
||||
errors in your log and your Script will temporarily fall back to being a <code class="docutils literal notranslate"><span class="pre">DefaultScript</span></code> type.</p>
|
||||
</div></blockquote>
|
||||
<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>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6</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>
|
||||
<span class="c1"># first stop 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">stop</span><span class="p">()</span>
|
||||
<span class="c1"># running the `scripts` command now will show no storagescript</span>
|
||||
<span class="c1"># but below now it's 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>
|
||||
<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>, it will use the
|
||||
information
|
||||
in settings to recreate it for you.</p>
|
||||
<blockquote>
|
||||
<div><p>Note that if your goal with the Script is to store persistent data, you should set it as
|
||||
<code class="docutils literal notranslate"><span class="pre">persistent=True</span></code>, either in <code class="docutils literal notranslate"><span class="pre">settings.GLOBAL_SCRIPTS</span></code> or in the Scripts typeclass. Otherwise any
|
||||
data you wanted to store on it will be gone (since a new script of the same name is restarted
|
||||
instead).</p>
|
||||
</div></blockquote>
|
||||
</div>
|
||||
<div class="section" id="dealing-with-errors">
|
||||
<h2>Dealing with Errors<a class="headerlink" href="#dealing-with-errors" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Errors inside an timed, executing script can sometimes be rather terse or point to
|
||||
parts of the execution mechanism that is hard to interpret. One way to make it
|
||||
easier to debug scripts is to import Evennia’s native logger and wrap your
|
||||
functions in a try/catch block. Evennia’s logger can show you where the
|
||||
traceback occurred in your script.</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15</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">logger</span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">Weather</span><span class="p">(</span><span class="n">DefaultScript</span><span class="p">):</span>
|
||||
|
||||
<span class="c1"># [...]</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">at_repeat</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="c1"># [...] code as above</span>
|
||||
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
|
||||
<span class="c1"># logs the error </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>
|
||||
</div>
|
||||
<div class="section" id="example-of-a-timed-script">
|
||||
<h2>Example of a timed script<a class="headerlink" href="#example-of-a-timed-script" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In-game you can try out scripts using the <code class="docutils literal notranslate"><span class="pre">@script</span></code> command. In the
|
||||
<code class="docutils literal notranslate"><span class="pre">evennia/contrib/tutorial_examples/bodyfunctions.py</span></code> is a little example script
|
||||
that makes you do little ‘sounds’ at random intervals. Try the following to apply an
|
||||
example time-based script to your character.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">></span> <span class="nd">@script</span> <span class="bp">self</span> <span class="o">=</span> <span class="n">bodyfunctions</span><span class="o">.</span><span class="n">BodyFunctions</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<blockquote>
|
||||
<div><p>Note: Since <code class="docutils literal notranslate"><span class="pre">evennia/contrib/tutorial_examples</span></code> is in the default setting
|
||||
<code class="docutils literal notranslate"><span class="pre">TYPECLASS_PATHS</span></code>, we only need to specify the final part of the path,
|
||||
that is, <code class="docutils literal notranslate"><span class="pre">bodyfunctions.BodyFunctions</span></code>.</p>
|
||||
</div></blockquote>
|
||||
<p>If you want to inflict your flatulence script on another person, place or
|
||||
thing, try something like the following:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">></span> <span class="nd">@py</span> <span class="bp">self</span><span class="o">.</span><span class="n">location</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s1">'matt'</span><span class="p">)</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="s1">'bodyfunctions.BodyFunctions'</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Here’s how you stop it on yourself.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">></span> <span class="nd">@script</span><span class="o">/</span><span class="n">stop</span> <span class="bp">self</span> <span class="o">=</span> <span class="n">bodyfunctions</span><span class="o">.</span><span class="n">BodyFunctions</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This will kill the script again. You can use the <code class="docutils literal notranslate"><span class="pre">@scripts</span></code> command to list all
|
||||
active scripts in the game, if any (there are none by default).</p>
|
||||
<p>For another example of a Script in use, check out the <a class="reference external" href="https://github.com/evennia/evennia/wiki/Turn%20based%20Combat%20System">Turn Based Combat System
|
||||
tutorial</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Scripts</a><ul>
|
||||
<li><a class="reference internal" href="#defining-new-scripts">Defining new Scripts</a></li>
|
||||
<li><a class="reference internal" href="#properties-and-functions-defined-on-scripts">Properties and functions defined on Scripts</a></li>
|
||||
<li><a class="reference internal" href="#global-scripts">Global Scripts</a></li>
|
||||
<li><a class="reference internal" href="#dealing-with-errors">Dealing with Errors</a></li>
|
||||
<li><a class="reference internal" href="#example-of-a-timed-script">Example of a timed script</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/Scripts.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Scripts.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Scripts</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
209
docs/1.0-dev/Components/Server-Conf.html
Normal file
209
docs/1.0-dev/Components/Server-Conf.html
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Server Conf — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Server Conf</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="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>
|
||||
<div class="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. Evennia’s 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 & 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&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 don’t 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 didn’t
|
||||
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>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5</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>
|
||||
</div>
|
||||
<div class="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. It’s 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 Evennia’s <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="http://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="http://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 Evennia’s 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>
|
||||
</div>
|
||||
<div class="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. It’s rarely of use outside the server core itself but may be good to
|
||||
know about if you are an Evennia developer.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Server-Conf.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Server Conf</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
99
docs/1.0-dev/Components/Server.html
Normal file
99
docs/1.0-dev/Components/Server.html
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Server component — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Server component</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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>
|
||||
</div>
|
||||
|
||||
|
||||
<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>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Components/Server.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Server.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Server component</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
289
docs/1.0-dev/Components/Sessions.html
Normal file
289
docs/1.0-dev/Components/Sessions.html
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Sessions — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Sessions</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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
|
||||
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
|
||||
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
|
||||
connection to the database. The Session will go away when a user disconnects and you will lose any
|
||||
custom data on it if the server reloads. The <code class="docutils literal notranslate"><span class="pre">.db</span></code> handler on Sessions is there to present a uniform
|
||||
API (so you can assume <code class="docutils literal notranslate"><span class="pre">.db</span></code> exists even if you don’t know if you receive an Object or a Session),
|
||||
but this is just an alias to <code class="docutils literal notranslate"><span class="pre">.ndb</span></code>. So don’t store any data on Sessions that you can’t afford to
|
||||
lose in a reload. You have been warned.</p>
|
||||
</div></blockquote>
|
||||
<div class="section" id="properties-on-sessions">
|
||||
<h2>Properties on Sessions<a class="headerlink" href="#properties-on-sessions" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Here are some important properties available on (Server-)Sessions</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">sessid</span></code> - The unique session-id. This is an integer starting from 1.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">address</span></code> - The connected client’s address. Different protocols give different information here.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">logged_in</span></code> - <code class="docutils literal notranslate"><span class="pre">True</span></code> if the user authenticated to this session.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">account</span></code> - The <a class="reference internal" href="Accounts.html"><span class="doc">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
|
||||
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">db</span></code> - As noted above, Sessions don’t have regular Attributes. This is an alias to <code class="docutils literal notranslate"><span class="pre">ndb</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">cmdset</span></code> - The Session’s <a class="reference internal" href="Command-Sets.html"><span class="doc">CmdSetHandler</span></a></p></li>
|
||||
</ul>
|
||||
<p>Session statistics are mainly used internally by Evennia.</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">conn_time</span></code> - How long this Session has been connected</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">cmd_last</span></code> - Last active time stamp. This will be reset by sending <code class="docutils literal notranslate"><span class="pre">idle</span></code> keepalives.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">cmd_last_visible</span></code> - last active time stamp. This ignores <code class="docutils literal notranslate"><span class="pre">idle</span></code> keepalives and representes the
|
||||
last time this session was truly visibly active.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">cmd_total</span></code> - Total number of Commands passed through this Session.</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="multisession-mode">
|
||||
<h2>Multisession mode<a class="headerlink" href="#multisession-mode" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The number of sessions possible to connect to a given account at the same time and how it works is
|
||||
given by the <code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE</span></code> setting:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE=0</span></code>: One session per account. When connecting with a new session the old one is
|
||||
disconnected. This is the default mode and emulates many classic mud code bases. In default Evennia,
|
||||
this mode also changes how the <code class="docutils literal notranslate"><span class="pre">create</span> <span class="pre">account</span></code> Command works - it will automatically create a
|
||||
Character with the <em>same name</em> as the Account. When logging in, the login command is also modified
|
||||
to have the player automatically puppet that Character. This makes the distinction between Account
|
||||
and Character minimal from the player’s perspective.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE=1</span></code>: Many sessions per account, input/output from/to each session is treated the
|
||||
same. For the player this means they can connect to the game from multiple clients and see the same
|
||||
output in all of them. The result of a command given in one client (that is, through one Session)
|
||||
will be returned to <em>all</em> connected Sessions/clients with no distinction. This mode will have the
|
||||
Session(s) auto-create and puppet a Character in the same way as mode 0.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE=2</span></code>: Many sessions per account, one character per session. In this mode,
|
||||
puppeting an Object/Character will link the puppet back only to the particular Session doing the
|
||||
puppeting. That is, input from that Session will make use of the CmdSet of that Object/Character and
|
||||
outgoing messages (such as the result of a <code class="docutils literal notranslate"><span class="pre">look</span></code>) will be passed back only to that puppeting
|
||||
Session. If another Session tries to puppet the same Character, the old Session will automatically
|
||||
un-puppet it. From the player’s perspective, this will mean that they can open separate game clients
|
||||
and play a different Character in each using one game account.
|
||||
This mode will <em>not</em> auto-create a Character and <em>not</em> auto-puppet on login like in modes 0 and 1.
|
||||
Instead it changes how the account-cmdsets’s <code class="docutils literal notranslate"><span class="pre">OOCLook</span></code> command works so as to show a simple
|
||||
‘character select’ menu.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE=3</span></code>: Many sessions per account <em>and</em> character. This is the full multi-puppeting
|
||||
mode, where multiple sessions may not only connect to the player account but multiple sessions may
|
||||
also puppet a single character at the same time. From the user’s perspective it means one can open
|
||||
multiple client windows, some for controlling different Characters and some that share a Character’s
|
||||
input/output like in mode 1. This mode otherwise works the same as mode 2.</p></li>
|
||||
</ul>
|
||||
<blockquote>
|
||||
<div><p>Note that even if multiple Sessions puppet one Character, there is only ever one instance of that
|
||||
Character.</p>
|
||||
</div></blockquote>
|
||||
</div>
|
||||
<div class="section" id="returning-data-to-the-session">
|
||||
<h2>Returning data to the session<a class="headerlink" href="#returning-data-to-the-session" title="Permalink to this headline">¶</a></h2>
|
||||
<p>When you use <code class="docutils literal notranslate"><span class="pre">msg()</span></code> to return data to a user, the object on which you call the <code class="docutils literal notranslate"><span class="pre">msg()</span></code> matters. The
|
||||
<code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE</span></code> also matters, especially if greater than 1.</p>
|
||||
<p>For example, if you use <code class="docutils literal notranslate"><span class="pre">account.msg("hello")</span></code> there is no way for evennia to know which session it
|
||||
should send the greeting to. In this case it will send it to all sessions. If you want a specific
|
||||
session you need to supply its session to the <code class="docutils literal notranslate"><span class="pre">msg</span></code> call (<code class="docutils literal notranslate"><span class="pre">account.msg("hello",</span> <span class="pre">session=mysession)</span></code>).</p>
|
||||
<p>On the other hand, if you call the <code class="docutils literal notranslate"><span class="pre">msg()</span></code> message on a puppeted object, like
|
||||
<code class="docutils literal notranslate"><span class="pre">character.msg("hello")</span></code>, the character already knows the session that controls it - it will
|
||||
cleverly auto-add this for you (you can specify a different session if you specifically want to send
|
||||
stuff to another session).</p>
|
||||
<p>Finally, there is a wrapper for <code class="docutils literal notranslate"><span class="pre">msg()</span></code> on all command classes: <code class="docutils literal notranslate"><span class="pre">command.msg()</span></code>. This will
|
||||
transparently detect which session was triggering the command (if any) and redirects to that session
|
||||
(this is most often what you want). If you are having trouble redirecting to a given session,
|
||||
<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.
|
||||
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
|
||||
it (it’s always a single one). It will be <code class="docutils literal notranslate"><span class="pre">None</span></code> if no session is involved, like when a mob or
|
||||
script triggers the Command.</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="customizing-the-session-object">
|
||||
<h2>Customizing the Session object<a class="headerlink" href="#customizing-the-session-object" title="Permalink to this headline">¶</a></h2>
|
||||
<p>When would one want to customize the Session object? Consider for example a character creation
|
||||
system: You might decide to keep this on the out-of-character level. This would mean that you create
|
||||
the character at the end of some sort of menu choice. The actual char-create cmdset would then
|
||||
normally be put on the account. This works fine as long as you are <code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE</span></code> below 2.
|
||||
For higher modes, replacing the Account cmdset will affect <em>all</em> your connected sessions, also those
|
||||
not involved in character creation. In this case you want to instead put the char-create cmdset on
|
||||
the Session level - then all other sessions will keep working normally despite you creating a new
|
||||
character in one of them.</p>
|
||||
<p>By default, the session object gets the <code class="docutils literal notranslate"><span class="pre">commands.default_cmdsets.UnloggedinCmdSet</span></code> when the user
|
||||
first connects. Once the session is authenticated it has <em>no</em> default sets. To add a “logged-in”
|
||||
cmdset to the Session, give the path to the cmdset class with <code class="docutils literal notranslate"><span class="pre">settings.CMDSET_SESSION</span></code>. This set
|
||||
will then henceforth always be present as soon as the account logs in.</p>
|
||||
<p>To customize further you can completely override the Session with your own subclass. To replace the
|
||||
default Session class, change <code class="docutils literal notranslate"><span class="pre">settings.SERVER_SESSION_CLASS</span></code> to point to your custom class. This is
|
||||
a dangerous practice and errors can easily make your game unplayable. Make sure to take heed of the
|
||||
<a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/server/session.py">original</a> and make your
|
||||
changes carefully.</p>
|
||||
</div>
|
||||
<div class="section" id="portal-and-server-sessions">
|
||||
<h2>Portal and Server Sessions<a class="headerlink" href="#portal-and-server-sessions" title="Permalink to this headline">¶</a></h2>
|
||||
<p><em>Note: This is considered an advanced topic. You don’t need to know this on a first read-through.</em></p>
|
||||
<p>Evennia is split into two parts, the <a class="reference internal" href="Portal-And-Server.html"><span class="doc">Portal and the Server</span></a>. Each side tracks
|
||||
its own Sessions, syncing them to each other.</p>
|
||||
<p>The “Session” we normally refer to is actually the <code class="docutils literal notranslate"><span class="pre">ServerSession</span></code>. Its counter-part on the Portal
|
||||
side is the <code class="docutils literal notranslate"><span class="pre">PortalSession</span></code>. Whereas the server sessions deal with game states, the portal session
|
||||
deals with details of the connection-protocol itself. The two are also acting as backups of critical
|
||||
data such as when the server reboots.</p>
|
||||
<p>New Account connections are listened for and handled by the Portal using the [protocols](Portal-And-
|
||||
Server) it understands (such as telnet, ssh, webclient etc). When a new connection is established, a
|
||||
<code class="docutils literal notranslate"><span class="pre">PortalSession</span></code> is created on the Portal side. This session object looks different depending on
|
||||
which protocol is used to connect, but all still have a minimum set of attributes that are generic
|
||||
to all
|
||||
sessions.</p>
|
||||
<p>These common properties are piped from the Portal, through the AMP connection, to the Server, which
|
||||
is now informed a new connection has been established. On the Server side, a <code class="docutils literal notranslate"><span class="pre">ServerSession</span></code> object
|
||||
is created to represent this. There is only one type of <code class="docutils literal notranslate"><span class="pre">ServerSession</span></code>; It looks the same
|
||||
regardless of how the Account connects.</p>
|
||||
<p>From now on, there is a one-to-one match between the <code class="docutils literal notranslate"><span class="pre">ServerSession</span></code> on one side of the AMP
|
||||
connection and the <code class="docutils literal notranslate"><span class="pre">PortalSession</span></code> on the other. Data arriving to the Portal Session is sent on to
|
||||
its mirror Server session and vice versa.</p>
|
||||
<p>During certain situations, the portal- and server-side sessions are
|
||||
“synced” with each other:</p>
|
||||
<ul class="simple">
|
||||
<li><p>The Player closes their client, killing the Portal Session. The Portal syncs with the Server to
|
||||
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
|
||||
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 Account’s login status and other connection-critical things can survive a
|
||||
server reboot (assuming the Portal is not stopped at the same time, obviously).</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="sessionhandlers">
|
||||
<h2>Sessionhandlers<a class="headerlink" href="#sessionhandlers" title="Permalink to this headline">¶</a></h2>
|
||||
<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
|
||||
on building new protocols.</p>
|
||||
<p>To get all Sessions in the game (i.e. all currently connected clients), you access the server-side
|
||||
Session handler, which you get by</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.server.sessionhandler</span> <span class="k">import</span> <span class="n">SESSION_HANDLER</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<blockquote>
|
||||
<div><p>Note: The <code class="docutils literal notranslate"><span class="pre">SESSION_HANDLER</span></code> singleton has an older alias <code class="docutils literal notranslate"><span class="pre">SESSIONS</span></code> that is commonly seen in
|
||||
various places as well.</p>
|
||||
</div></blockquote>
|
||||
<p>See the
|
||||
<a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/server/sessionhandler.py">sessionhandler.py</a>
|
||||
module for details on the capabilities of the <code class="docutils literal notranslate"><span class="pre">ServerSessionHandler</span></code>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Sessions</a><ul>
|
||||
<li><a class="reference internal" href="#properties-on-sessions">Properties on Sessions</a></li>
|
||||
<li><a class="reference internal" href="#multisession-mode">Multisession mode</a></li>
|
||||
<li><a class="reference internal" href="#returning-data-to-the-session">Returning data to the session</a></li>
|
||||
<li><a class="reference internal" href="#customizing-the-session-object">Customizing the Session object</a></li>
|
||||
<li><a class="reference internal" href="#portal-and-server-sessions">Portal and Server Sessions</a></li>
|
||||
<li><a class="reference internal" href="#sessionhandlers">Sessionhandlers</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/Sessions.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Sessions.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Sessions</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
222
docs/1.0-dev/Components/Signals.html
Normal file
222
docs/1.0-dev/Components/Signals.html
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Signals — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Signals</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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.
|
||||
The most common way to do so is through <em>hooks</em> - methods on typeclasses that
|
||||
gets called at particular events. Hooks are great when you want a game entity
|
||||
to behave a certain way when something happens to it. <em>Signals</em> complements
|
||||
hooks for cases when you want to easily attach new functionality without
|
||||
overriding things on the typeclass.</p>
|
||||
<p>When certain events happen in Evennia, a <em>Signal</em> is fired. The idea is that
|
||||
you can “attach” any number of event-handlers to these signals. You can attach
|
||||
any number of handlers and they’ll all fire whenever any entity triggers the
|
||||
signal.</p>
|
||||
<p>Evennia uses the <a class="reference external" href="https://docs.djangoproject.com/en/2.2/topics/signals/">Django Signal system</a>.</p>
|
||||
<div class="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>1
|
||||
2
|
||||
3</pre></div></td><td class="code"><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>
|
||||
<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>1
|
||||
2
|
||||
3</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>
|
||||
|
||||
<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>
|
||||
<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>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5</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>
|
||||
<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">"foo"</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>
|
||||
<div class="section" id="available-signals">
|
||||
<h2>Available signals<a class="headerlink" href="#available-signals" title="Permalink to this headline">¶</a></h2>
|
||||
<p>All signals (including some django-specific defaults) are available in the module
|
||||
<code class="docutils literal notranslate"><span class="pre">evennia.server.signals</span></code>
|
||||
(with a shortcut <code class="docutils literal notranslate"><span class="pre">evennia.signals</span></code>). Signals are named by the sender type. So <code class="docutils literal notranslate"><span class="pre">SIGNAL_ACCOUNT_*</span></code>
|
||||
returns
|
||||
<code class="docutils literal notranslate"><span class="pre">Account</span></code> instances as senders, <code class="docutils literal notranslate"><span class="pre">SIGNAL_OBJECT_*</span></code> returns <code class="docutils literal notranslate"><span class="pre">Object</span></code>s etc. Extra keywords (kwargs)
|
||||
should
|
||||
be extracted from the <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> dict in the signal handler.</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_ACCOUNT_POST_CREATE</span></code> - this is triggered at the very end of <code class="docutils literal notranslate"><span class="pre">Account.create()</span></code>. Note that
|
||||
calling <code class="docutils literal notranslate"><span class="pre">evennia.create.create_account</span></code> (which is called internally by <code class="docutils literal notranslate"><span class="pre">Account.create</span></code>) will
|
||||
<em>not</em>
|
||||
trigger this signal. This is because using <code class="docutils literal notranslate"><span class="pre">Account.create()</span></code> is expected to be the most commonly
|
||||
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>
|
||||
<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
|
||||
passes the <code class="docutils literal notranslate"><span class="pre">session</span></code> along as a kwarg.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_ACCOUNT_POST_LOGIN_FAIL</span></code> - sent when someone tried to log into an account by failed.
|
||||
Passes
|
||||
the <code class="docutils literal notranslate"><span class="pre">session</span></code> as an extra kwarg.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_ACCOUNT_POST_LOGOUT</span></code> - always fires when an account logs off, no matter if other sessions
|
||||
remain or not. Passes the disconnecting <code class="docutils literal notranslate"><span class="pre">session</span></code> along as a kwarg.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_ACCOUNT_POST_LAST_LOGOUT</span></code> - fires before <code class="docutils literal notranslate"><span class="pre">SIGNAL_ACCOUNT_POST_LOGOUT</span></code>, but only if this is
|
||||
the <em>last</em> Session to disconnect for that account. Passes the <code class="docutils literal notranslate"><span class="pre">session</span></code> as a kwarg.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_OBJECT_POST_PUPPET</span></code> - fires when an account puppets this object. Extra kwargs <code class="docutils literal notranslate"><span class="pre">session</span></code>
|
||||
and <code class="docutils literal notranslate"><span class="pre">account</span></code> represent the puppeting entities.
|
||||
<code class="docutils literal notranslate"><span class="pre">SIGNAL_OBJECT_POST_UNPUPPET</span></code> - fires when the sending object is unpuppeted. Extra kwargs are
|
||||
<code class="docutils literal notranslate"><span class="pre">session</span></code> and <code class="docutils literal notranslate"><span class="pre">account</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_ACCOUNT_POST_RENAME</span></code> - triggered by the setting of <code class="docutils literal notranslate"><span class="pre">Account.username</span></code>. Passes extra
|
||||
kwargs <code class="docutils literal notranslate"><span class="pre">old_name</span></code>, <code class="docutils literal notranslate"><span class="pre">new_name</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_TYPED_OBJECT_POST_RENAME</span></code> - triggered when any Typeclassed entity’s <code class="docutils literal notranslate"><span class="pre">key</span></code> is changed.
|
||||
Extra
|
||||
kwargs passed are <code class="docutils literal notranslate"><span class="pre">old_key</span></code> and <code class="docutils literal notranslate"><span class="pre">new_key</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_SCRIPT_POST_CREATE</span></code> - fires when a script is first created, after any hooks.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_CHANNEL_POST_CREATE</span></code> - fires when a Channel is first created, after any hooks.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_HELPENTRY_POST_CREATE</span></code> - fires when a help entry is first created.</p></li>
|
||||
</ul>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">evennia.signals</span></code> module also gives you conveneient access to the default Django signals (these
|
||||
use a
|
||||
different naming convention).</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">pre_save</span></code> - fired when any database entitiy’s <code class="docutils literal notranslate"><span class="pre">.save</span></code> method fires, before any saving has
|
||||
happened.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">post_save</span></code> - fires after saving a database entity.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">pre_delete</span></code> - fires just before a database entity is deleted.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">post_delete</span></code> - fires after a database entity was deleted.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">pre_init</span></code> - fires before a typeclass’ <code class="docutils literal notranslate"><span class="pre">__init__</span></code> method (which in turn
|
||||
happens before the <code class="docutils literal notranslate"><span class="pre">at_init</span></code> hook fires).</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">post_init</span></code> - triggers at the end of <code class="docutils literal notranslate"><span class="pre">__init__</span></code> (still before the <code class="docutils literal notranslate"><span class="pre">at_init</span></code> hook).</p></li>
|
||||
</ul>
|
||||
<p>These are highly specialized Django signals that are unlikely to be useful to most users. But
|
||||
they are included here for completeness.</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">m2m_changed</span></code> - fires after a Many-to-Many field (like <code class="docutils literal notranslate"><span class="pre">db_attributes</span></code>) changes.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">pre_migrate</span></code> - fires before database migration starts with <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">migrate</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">post_migrate</span></code> - fires after database migration finished.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">request_started</span></code> - sent when HTTP request begins.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">request_finished</span></code> - sent when HTTP request ends.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">settings_changed</span></code> - sent when changing settings due to <code class="docutils literal notranslate"><span class="pre">@override_settings</span></code>
|
||||
decorator (only relevant for unit testing)</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">template_rendered</span></code> - sent when test system renders http template (only useful for unit tests).</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">connection_creation</span></code> - sent when making initial connection to database.</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Signals</a><ul>
|
||||
<li><a class="reference internal" href="#attaching-a-handler-to-a-signal">Attaching a handler to a signal</a></li>
|
||||
<li><a class="reference internal" href="#available-signals">Available signals</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/Signals.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Signals.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Signals</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
436
docs/1.0-dev/Components/Spawner-and-Prototypes.html
Normal file
436
docs/1.0-dev/Components/Spawner-and-Prototypes.html
Normal file
|
|
@ -0,0 +1,436 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Spawner and Prototypes — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Spawner and Prototypes</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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
|
||||
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
|
||||
haven’t read up on Typeclasses yet, think of them as normal Python classes that save to the database
|
||||
behind the scenes. Say you wanted to create a “Goblin” enemy. A common way to do this would be to
|
||||
first create a <code class="docutils literal notranslate"><span class="pre">Mobile</span></code> typeclass that holds everything common to mobiles in the game, like generic
|
||||
AI, combat code and various movement methods. A <code class="docutils literal notranslate"><span class="pre">Goblin</span></code> subclass is then made to inherit from
|
||||
<code class="docutils literal notranslate"><span class="pre">Mobile</span></code>. The <code class="docutils literal notranslate"><span class="pre">Goblin</span></code> class adds stuff unique to goblins, like group-based AI (because goblins are
|
||||
smarter in a group), the ability to panic, dig for gold etc.</p>
|
||||
<p>But now it’s time to actually start to create some goblins and put them in the world. What if we
|
||||
wanted those goblins to not all look the same? Maybe we want grey-skinned and green-skinned goblins
|
||||
or some goblins that can cast spells or which wield different weapons? We <em>could</em> make subclasses of
|
||||
<code class="docutils literal notranslate"><span class="pre">Goblin</span></code>, like <code class="docutils literal notranslate"><span class="pre">GreySkinnedGoblin</span></code> and <code class="docutils literal notranslate"><span class="pre">GoblinWieldingClub</span></code>. But that seems a bit excessive (and a
|
||||
lot of Python code for every little thing). Using classes can also become impractical when wanting
|
||||
to combine them - what if we want a grey-skinned goblin shaman wielding a spear - setting up a web
|
||||
of classes inheriting each other with multiple inheritance can be tricky.</p>
|
||||
<p>This is what the <em>prototype</em> is for. It is a Python dictionary that describes these per-instance
|
||||
changes to an object. The prototype also has the advantage of allowing an in-game builder to
|
||||
customize an object without access to the Python backend. Evennia also allows for saving and
|
||||
searching prototypes so other builders can find and use (and tweak) them later. Having a library of
|
||||
interesting prototypes is a good reasource for builders. The OLC system allows for creating, saving,
|
||||
loading and manipulating prototypes using a menu system.</p>
|
||||
<p>The <em>spawner</em> takes a prototype and uses it to create (spawn) new, custom objects.</p>
|
||||
<div class="section" id="using-the-olc">
|
||||
<h2>Using the OLC<a class="headerlink" href="#using-the-olc" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Enter the <code class="docutils literal notranslate"><span class="pre">olc</span></code> command or <code class="docutils literal notranslate"><span class="pre">@spawn/olc</span></code> to enter the prototype wizard. This is a menu system for
|
||||
creating, loading, saving and manipulating prototypes. It’s intended to be used by in-game builders
|
||||
and will give a better understanding of prototypes in general. Use <code class="docutils literal notranslate"><span class="pre">help</span></code> on each node of the menu
|
||||
for more information. Below are further details about how prototypes work and how they are used.</p>
|
||||
</div>
|
||||
<div class="section" id="the-prototype">
|
||||
<h2>The prototype<a class="headerlink" href="#the-prototype" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The prototype dictionary can either be created for you by the OLC (see above), be written manually
|
||||
in a Python module (and then referenced by the <code class="docutils literal notranslate"><span class="pre">@spawn</span></code> command/OLC), or created on-the-fly and
|
||||
manually loaded into the spawner function or <code class="docutils literal notranslate"><span class="pre">@spawn</span></code> command.</p>
|
||||
<p>The dictionary defines all possible database-properties of an Object. It has a fixed set of allowed
|
||||
keys. When preparing to store the prototype in the database (or when using the OLC), some
|
||||
of these keys are mandatory. When just passing a one-time prototype-dict to the spawner the system
|
||||
is
|
||||
more lenient and will use defaults for keys not explicitly provided.</p>
|
||||
<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>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="p">{</span>
|
||||
<span class="s2">"prototype_key"</span><span class="p">:</span> <span class="s2">"house"</span>
|
||||
<span class="s2">"key"</span><span class="p">:</span> <span class="s2">"Large house"</span>
|
||||
<span class="s2">"typeclass"</span><span class="p">:</span> <span class="s2">"typeclasses.rooms.house.House"</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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">"prototype_key="</span><span class="n">house</span><span class="s2">", "</span><span class="n">key</span><span class="s2">": "</span><span class="n">Large</span> <span class="n">house</span><span class="s2">", ...}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<blockquote>
|
||||
<div><p>Note that the prototype dict as given on the command line must be a valid Python structure -
|
||||
so you need to put quotes around strings etc. For security reasons, a dict inserted from-in game
|
||||
cannot have any
|
||||
other advanced Python functionality, such as executable code, <code class="docutils literal notranslate"><span class="pre">lambda</span></code> etc. If builders are supposed
|
||||
to be able to use such features, you need to offer them through [$protfuncs](Spawner-and-
|
||||
Prototypes#protfuncs), embedded runnable functions that you have full control to check and vet
|
||||
before running.</p>
|
||||
</div></blockquote>
|
||||
<div class="section" id="prototype-keys">
|
||||
<h3>Prototype keys<a class="headerlink" href="#prototype-keys" title="Permalink to this headline">¶</a></h3>
|
||||
<p>All keys starting with <code class="docutils literal notranslate"><span class="pre">prototype_</span></code> are for book keeping.</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">prototype_key</span></code> - the ‘name’ of the prototype. While this can sometimes be skipped (such as when
|
||||
defining a prototype in a module or feeding a prototype-dict manually to the spawner function),
|
||||
it’s good
|
||||
practice to try to include this. It is used for book-keeping and storing of the prototype so you
|
||||
can find it later.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">prototype_parent</span></code> - If given, this should be the <code class="docutils literal notranslate"><span class="pre">prototype_key</span></code> of another prototype stored in
|
||||
the system or available in a module. This makes this prototype <em>inherit</em> the keys from the
|
||||
parent and only override what is needed. Give a tuple <code class="docutils literal notranslate"><span class="pre">(parent1,</span> <span class="pre">parent2,</span> <span class="pre">...)</span></code> for multiple
|
||||
left-right inheritance. If this is not given, a <code class="docutils literal notranslate"><span class="pre">typeclass</span></code> should usually be defined (below).</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">prototype_desc</span></code> - this is optional and used when listing the prototype in in-game listings.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">protototype_tags</span></code> - this is optional and allows for tagging the prototype in order to find it
|
||||
easier later.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">prototype_locks</span></code> - two lock types are supported: <code class="docutils literal notranslate"><span class="pre">edit</span></code> and <code class="docutils literal notranslate"><span class="pre">spawn</span></code>. The first lock restricts
|
||||
the copying and editing of the prototype when loaded through the OLC. The second determines who
|
||||
may use the prototype to create new objects.</p></li>
|
||||
</ul>
|
||||
<p>The remaining keys determine actual aspects of the objects to spawn from this prototype:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">key</span></code> - the main object identifier. Defaults to “Spawned Object <em>X</em>”, where <em>X</em> is a random
|
||||
integer.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">typeclass</span></code> - A full python-path (from your gamedir) to the typeclass you want to use. If not
|
||||
set, the <code class="docutils literal notranslate"><span class="pre">prototype_parent</span></code> should be
|
||||
defined, with <code class="docutils literal notranslate"><span class="pre">typeclass</span></code> defined somewhere in the parent chain. When creating a one-time
|
||||
prototype
|
||||
dict just for spawning, one could omit this - <code class="docutils literal notranslate"><span class="pre">settings.BASE_OBJECT_TYPECLASS</span></code> will be used
|
||||
instead.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">location</span></code> - this should be a <code class="docutils literal notranslate"><span class="pre">#dbref</span></code>.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">home</span></code> - a valid <code class="docutils literal notranslate"><span class="pre">#dbref</span></code>. Defaults to <code class="docutils literal notranslate"><span class="pre">location</span></code> or <code class="docutils literal notranslate"><span class="pre">settings.DEFAULT_HOME</span></code> if location does not
|
||||
exist.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">destination</span></code> - a valid <code class="docutils literal notranslate"><span class="pre">#dbref</span></code>. Only used by exits.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">permissions</span></code> - list of permission strings, like <code class="docutils literal notranslate"><span class="pre">["Accounts",</span> <span class="pre">"may_use_red_door"]</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">locks</span></code> - a <a class="reference internal" href="Locks.html"><span class="doc">lock-string</span></a> like <code class="docutils literal notranslate"><span class="pre">"edit:all();control:perm(Builder)"</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">aliases</span></code> - list of strings for use as aliases</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">tags</span></code> - list <a class="reference internal" href="Tags.html"><span class="doc">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.
|
||||
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>
|
||||
<p>Deprecated as of Evennia 0.8:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">ndb_<name></span></code> - sets the value of a non-persistent attribute (<code class="docutils literal notranslate"><span class="pre">"ndb_"</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/Spawner-and-Prototypes.html#protfuncs">$protfuncs</a> instead (see below).</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="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>1</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="p">{</span><span class="s2">"key"</span><span class="p">:</span> <span class="s2">"An ugly goblin"</span><span class="p">,</span> <span class="o">...</span><span class="p">}</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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>1</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="p">{</span><span class="s2">"key"</span><span class="p">:</span> <span class="n">_get_a_random_goblin_name</span><span class="p">,</span> <span class="o">...</span><span class="p">}</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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>1</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="p">{</span><span class="s2">"key"</span><span class="p">:</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">((</span><span class="s2">"Urfgar"</span><span class="p">,</span> <span class="s2">"Rick the smelly"</span><span class="p">,</span> <span class="s2">"Blargh the foul"</span><span class="p">,</span> <span class="o">...</span><span class="p">)),</span> <span class="o">...</span><span class="p">}</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<div class="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>1
|
||||
2
|
||||
3</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="p">{</span><span class="s2">"key"</span><span class="p">:</span> <span class="s2">"$choice(Urfgar, Rick the smelly, Blargh the foul)"</span><span class="p">,</span>
|
||||
<span class="s2">"attrs"</span><span class="p">:</span> <span class="p">{</span><span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"This is a large $red(and very red) demon. "</span>
|
||||
<span class="s2">"He has $randint(2,5) skulls in a chain around his neck."</span><span class="p">}</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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>
|
||||
<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>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9</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>
|
||||
<span class="k">def</span> <span class="nf">red</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> Usage: $red(<text>)</span>
|
||||
<span class="sd"> Returns the same text you entered, but red.</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">args</span> <span class="ow">or</span> <span class="nb">len</span><span class="p">(</span><span class="n">args</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Must have one argument, the text to color red!"</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="s2">"|r{}|n"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<blockquote>
|
||||
<div><p>Note that we must make sure to validate input and raise <code class="docutils literal notranslate"><span class="pre">ValueError</span></code> if that fails. Also, it is
|
||||
<em>not</em> possible to use keywords in the call to the protfunc (so something like <code class="docutils literal notranslate"><span class="pre">$echo(text,</span> <span class="pre">align=left)</span></code> is invalid). The <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> requred is for internal evennia use and not used at all for
|
||||
protfuncs (only by inlinefuncs).</p>
|
||||
</div></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>1
|
||||
2
|
||||
3</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in mygame/server/conf/settings.py</span>
|
||||
|
||||
<span class="n">PROT_FUNC_MODULES</span> <span class="o">+=</span> <span class="p">[</span><span class="s2">"world.myprotfuncs"</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<p>All <em>global callables</em> in your added module will be considered a new protfunc. To avoid this (e.g.
|
||||
to have helper functions that are not protfuncs on their own), name your function something starting
|
||||
with <code class="docutils literal notranslate"><span class="pre">_</span></code>.</p>
|
||||
<p>The default protfuncs available out of the box are defined in <code class="docutils literal notranslate"><span class="pre">evennia/prototypes/profuncs.py</span></code>. To
|
||||
override the ones available, just add the same-named function in your own protfunc module.</p>
|
||||
<p>| Protfunc | Description |</p>
|
||||
<p>| <code class="docutils literal notranslate"><span class="pre">$random()</span></code> | Returns random value in range [0, 1) |
|
||||
| <code class="docutils literal notranslate"><span class="pre">$randint(start,</span> <span class="pre">end)</span></code> | Returns random value in range [start, end] |
|
||||
| <code class="docutils literal notranslate"><span class="pre">$left_justify(<text>)</span></code> | Left-justify text |
|
||||
| <code class="docutils literal notranslate"><span class="pre">$right_justify(<text>)</span></code> | Right-justify text to screen width |
|
||||
| <code class="docutils literal notranslate"><span class="pre">$center_justify(<text>)</span></code> | Center-justify text to screen width |
|
||||
| <code class="docutils literal notranslate"><span class="pre">$full_justify(<text>)</span></code> | Spread text across screen width by adding spaces |
|
||||
| <code class="docutils literal notranslate"><span class="pre">$protkey(<name>)</span></code> | Returns value of another key in this prototype (self-reference) |
|
||||
| <code class="docutils literal notranslate"><span class="pre">$add(<value1>,</span> <span class="pre"><value2>)</span></code> | Returns value1 + value2. Can also be lists, dicts etc |
|
||||
| <code class="docutils literal notranslate"><span class="pre">$sub(<value1>,</span> <span class="pre"><value2>)</span></code> | Returns value1 - value2 |
|
||||
| <code class="docutils literal notranslate"><span class="pre">$mult(<value1>,</span> <span class="pre"><value2>)</span></code> | Returns value1 * value2 |
|
||||
| <code class="docutils literal notranslate"><span class="pre">$div(<value1>,</span> <span class="pre"><value2>)</span></code> | Returns value2 / value1 |
|
||||
| <code class="docutils literal notranslate"><span class="pre">$toint(<value>)</span></code> | Returns value converted to integer (or value if not possible) |
|
||||
| <code class="docutils literal notranslate"><span class="pre">$eval(<code>)</span></code> | Returns result of <a class="reference external" href="https://docs.python.org/2/library/ast.html#ast.literal_eval">literal-
|
||||
eval</a> of code string. Only simple
|
||||
python expressions. |
|
||||
| <code class="docutils literal notranslate"><span class="pre">$obj(<query>)</span></code> | Returns object #dbref searched globally by key, tag or #dbref. Error if more
|
||||
than one found.” |
|
||||
| <code class="docutils literal notranslate"><span class="pre">$objlist(<query>)</span></code> | Like <code class="docutils literal notranslate"><span class="pre">$obj</span></code>, except always returns a list of zero, one or more results. |
|
||||
| <code class="docutils literal notranslate"><span class="pre">$dbref(dbref)</span></code> | Returns argument if it is formed as a #dbref (e.g. #1234), otherwise error.</p>
|
||||
<p>For developers with access to Python, using protfuncs in prototypes is generally not useful. Passing
|
||||
real Python functions is a lot more powerful and flexible. Their main use is to allow in-game
|
||||
builders to
|
||||
do limited coding/scripting for their prototypes without giving them direct access to raw Python.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="storing-prototypes">
|
||||
<h2>Storing prototypes<a class="headerlink" href="#storing-prototypes" title="Permalink to this headline">¶</a></h2>
|
||||
<p>A prototype can be defined and stored in two ways, either in the database or as a dict in a module.</p>
|
||||
<div class="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-
|
||||
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>
|
||||
</div>
|
||||
<div class="section" id="module-based-prototypes">
|
||||
<h3>Module-based prototypes<a class="headerlink" href="#module-based-prototypes" title="Permalink to this headline">¶</a></h3>
|
||||
<p>These prototypes are defined as dictionaries assigned to global variables in one of the modules
|
||||
defined in <code class="docutils literal notranslate"><span class="pre">settings.PROTOTYPE_MODULES</span></code>. They can only be modified from outside the game so they are
|
||||
are necessarily “read-only” from in-game and cannot be modified (but copies of them could be made
|
||||
into database-prototypes). These were the only prototypes available before Evennia 0.8. Module based
|
||||
prototypes can be useful in order for developers to provide read-only “starting” or “base”
|
||||
prototypes to build from or if they just prefer to work offline in an external code editor.</p>
|
||||
<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>1
|
||||
2
|
||||
3</pre></div></td><td class="code"><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">"world.myownprototypes"</span><span class="p">,</span> <span class="s2">"combat.prototypes"</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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
|
||||
# in a module Evennia looks at for prototypes,
|
||||
# (like mygame/world/prototypes.py)
|
||||
|
||||
ORC_SHAMAN = {"key":"Orc shaman",
|
||||
"typeclass": "typeclasses.monsters.Orc",
|
||||
"weapon": "wooden staff",
|
||||
"health": 20}
|
||||
```
|
||||
</pre></div>
|
||||
</div>
|
||||
<blockquote>
|
||||
<div><p>Note that in the example above, <code class="docutils literal notranslate"><span class="pre">"ORC_SHAMAN"</span></code> will become the <code class="docutils literal notranslate"><span class="pre">prototype_key</span></code> of this prototype.
|
||||
It’s the only case when <code class="docutils literal notranslate"><span class="pre">prototype_key</span></code> can be skipped in a prototype. However, if <code class="docutils literal notranslate"><span class="pre">prototype_key</span></code>
|
||||
was given explicitly, that would take precedence. This is a legacy behavior and it’s recommended
|
||||
that you always add <code class="docutils literal notranslate"><span class="pre">prototype_key</span></code> to be consistent.</p>
|
||||
</div></blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="using-spawn">
|
||||
<h2>Using @spawn<a class="headerlink" href="#using-spawn" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The spawner can be used from inside the game through the Builder-only <code class="docutils literal notranslate"><span class="pre">@spawn</span></code> command. Assuming the
|
||||
“goblin” typeclass is available to the system (either as a database-prototype or read from module),
|
||||
you can spawn a new goblin with</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@spawn</span> <span class="n">goblin</span>
|
||||
</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">"prototype_key"</span><span class="p">:</span> <span class="s2">"shaman"</span><span class="p">,</span> \
|
||||
<span class="s2">"key"</span><span class="p">:</span><span class="s2">"Orc shaman"</span><span class="p">,</span> \
|
||||
<span class="s2">"prototype_parent"</span><span class="p">:</span> <span class="s2">"goblin"</span><span class="p">,</span> \
|
||||
<span class="s2">"weapon"</span><span class="p">:</span> <span class="s2">"wooden staff"</span><span class="p">,</span> \
|
||||
<span class="s2">"health"</span><span class="p">:</span> <span class="mi">20</span><span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<blockquote>
|
||||
<div><p>Note: The <code class="docutils literal notranslate"><span class="pre">@spawn</span></code> command is more lenient about the prototype dictionary than shown here. So you
|
||||
can for example skip the <code class="docutils literal notranslate"><span class="pre">prototype_key</span></code> if you are just testing a throw-away prototype. A random
|
||||
hash will be used to please the validation. You could also skip <code class="docutils literal notranslate"><span class="pre">prototype_parent/typeclass</span></code> - then
|
||||
the typeclass given by <code class="docutils literal notranslate"><span class="pre">settings.BASE_OBJECT_TYPECLASS</span></code> will be used.</p>
|
||||
</div></blockquote>
|
||||
</div>
|
||||
<div class="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>1</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>
|
||||
</pre></div>
|
||||
</td></tr></table></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>1
|
||||
2</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">"key"</span><span class="p">:</span> <span class="s2">"Obj1"</span><span class="p">,</span> <span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"A test"</span><span class="p">},</span>
|
||||
<span class="p">{</span><span class="s2">"key"</span><span class="p">:</span> <span class="s2">"Obj2"</span><span class="p">,</span> <span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"Another test"</span><span class="p">})</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<blockquote>
|
||||
<div><p>Hint: Same as when using <code class="docutils literal notranslate"><span class="pre">@spawn</span></code>, when spawning from a one-time prototype dict like this, you can
|
||||
skip otherwise required keys, like <code class="docutils literal notranslate"><span class="pre">prototype_key</span></code> or <code class="docutils literal notranslate"><span class="pre">typeclass</span></code>/<code class="docutils literal notranslate"><span class="pre">prototype_parent</span></code>. Defaults will
|
||||
be used.</p>
|
||||
</div></blockquote>
|
||||
<p>Note that no <code class="docutils literal notranslate"><span class="pre">location</span></code> will be set automatically when using <code class="docutils literal notranslate"><span class="pre">evennia.prototypes.spawner.spawn()</span></code>,
|
||||
you
|
||||
have to specify <code class="docutils literal notranslate"><span class="pre">location</span></code> explicitly in the prototype dict.</p>
|
||||
<p>If the prototypes you supply are using <code class="docutils literal notranslate"><span class="pre">prototype_parent</span></code> keywords, the spawner will read prototypes
|
||||
from modules
|
||||
in <code class="docutils literal notranslate"><span class="pre">settings.PROTOTYPE_MODULES</span></code> as well as those saved to the database to determine the body of
|
||||
available parents. The <code class="docutils literal notranslate"><span class="pre">spawn</span></code> command takes many optional keywords, you can find its definition <a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia.prototypes.spawner#spawn">in
|
||||
the api docs</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Spawner and Prototypes</a><ul>
|
||||
<li><a class="reference internal" href="#using-the-olc">Using the OLC</a></li>
|
||||
<li><a class="reference internal" href="#the-prototype">The prototype</a><ul>
|
||||
<li><a class="reference internal" href="#prototype-keys">Prototype keys</a></li>
|
||||
<li><a class="reference internal" href="#prototype-values">Prototype values</a><ul>
|
||||
<li><a class="reference internal" href="#protfuncs">Protfuncs</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#storing-prototypes">Storing prototypes</a><ul>
|
||||
<li><a class="reference internal" href="#database-prototypes">Database prototypes</a></li>
|
||||
<li><a class="reference internal" href="#module-based-prototypes">Module-based prototypes</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#using-spawn">Using @spawn</a></li>
|
||||
<li><a class="reference internal" href="#using-evennia-prototypes-spawner">Using evennia.prototypes.spawner()</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Components/Spawner-and-Prototypes.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Spawner-and-Prototypes.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Spawner and Prototypes</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
302
docs/1.0-dev/Components/Tags.html
Normal file
302
docs/1.0-dev/Components/Tags.html
Normal file
|
|
@ -0,0 +1,302 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Tags — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Tags</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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
|
||||
a player casting a magic spell that affects every location “in the dungeon”, but not those
|
||||
“outside”. Another would be to quickly find everyone joined with a particular guild or everyone
|
||||
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>
|
||||
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>
|
||||
<div class="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>
|
||||
<blockquote>
|
||||
<div><p>Not specifying a category (default) gives the tag a category of <code class="docutils literal notranslate"><span class="pre">None</span></code>, which is also considered a
|
||||
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
|
||||
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">
|
||||
<li><p><strong>key</strong> - the name of the Tag. This is the main property to search for when looking up a Tag.</p></li>
|
||||
<li><p><strong>category</strong> - this category allows for retrieving only specific subsets of tags used for
|
||||
different purposes. You could have one category of tags for “zones”, another for “outdoor
|
||||
locations”, for example. If not given, the category will be <code class="docutils literal notranslate"><span class="pre">None</span></code>, which is also considered a
|
||||
separate, default, category.</p></li>
|
||||
<li><p><strong>data</strong> - this is an optional text field with information about the tag. Remember that Tags are
|
||||
shared between entities, so this field cannot hold any object-specific information. Usually it would
|
||||
be used to hold info about the group of entities the Tag is tagging - possibly used for contextual
|
||||
help like a tool tip. It is not used by default.</p></li>
|
||||
</ul>
|
||||
<p>There are also two special properties. These should usually not need to be changed or set, it is
|
||||
used internally by Evennia to implement various other uses it makes of the <code class="docutils literal notranslate"><span class="pre">Tag</span></code> object:</p>
|
||||
<ul class="simple">
|
||||
<li><p><strong>model</strong> - this holds a <em>natural-key</em> description of the model object that this tag deals with,
|
||||
on the form <em>application.modelclass</em>, for example <code class="docutils literal notranslate"><span class="pre">objects.objectdb</span></code>. It used by the TagHandler of
|
||||
each entity type for correctly storing the data behind the scenes.</p></li>
|
||||
<li><p><strong>tagtype</strong> - this is a “top-level category” of sorts for the inbuilt children of Tags, namely
|
||||
<em>Aliases</em> and <em>Permissions</em>. The Taghandlers using this special field are especially intended to
|
||||
free up the <em>category</em> property for any use you desire.</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="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
|
||||
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>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9</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">"furniture"</span><span class="p">)</span>
|
||||
<span class="n">mychair</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">"furniture"</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">"luxurious"</span><span class="p">)</span>
|
||||
<span class="n">myroom</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">"dungeon#01"</span><span class="p">)</span>
|
||||
<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">"weather"</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">"climate"</span><span class="p">)</span>
|
||||
<span class="n">myaccount</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">"guestaccount"</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">all</span><span class="p">()</span> <span class="c1"># returns a list of Tags</span>
|
||||
<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">"furniture"</span><span class="p">)</span>
|
||||
<span class="n">mychair</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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">@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>
|
||||
</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>
|
||||
</div>
|
||||
<div class="section" id="searching-for-objects-with-a-given-tag">
|
||||
<h2>Searching for objects with a given tag<a class="headerlink" href="#searching-for-objects-with-a-given-tag" title="Permalink to this headline">¶</a></h2>
|
||||
<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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15
|
||||
16
|
||||
17
|
||||
18</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="kn">import</span> <span class="nn">evennia</span>
|
||||
|
||||
<span class="c1"># all methods return Querysets</span>
|
||||
|
||||
<span class="c1"># search for objects </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="s2">"furniture"</span><span class="p">)</span>
|
||||
<span class="n">objs2</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">"furniture"</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">"luxurious"</span><span class="p">)</span>
|
||||
<span class="n">dungeon</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">"dungeon#01"</span><span class="p">)</span>
|
||||
<span class="n">forest_rooms</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">"forest"</span><span class="p">)</span>
|
||||
<span class="n">forest_meadows</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">"meadow"</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">"forest"</span><span class="p">)</span>
|
||||
<span class="n">magic_meadows</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">"meadow"</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">"magical"</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># search for scripts</span>
|
||||
<span class="n">weather</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_tag_script</span><span class="p">(</span><span class="s2">"weather"</span><span class="p">)</span>
|
||||
<span class="n">climates</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_tag_script</span><span class="p">(</span><span class="n">category</span><span class="o">=</span><span class="s2">"climate"</span><span class="p">)</span>
|
||||
|
||||
<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">"guestaccount"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<blockquote>
|
||||
<div><p>Note that searching for just “furniture” will only return the objects tagged with the “furniture”
|
||||
tag that
|
||||
has a category of <code class="docutils literal notranslate"><span class="pre">None</span></code>. We must explicitly give the category to get the “luxurious” furniture.</p>
|
||||
</div></blockquote>
|
||||
<p>Using any of the <code class="docutils literal notranslate"><span class="pre">search_tag</span></code> variants will all return <a class="reference external" href="https://docs.djangoproject.com/en/2.1/ref/models/querysets/">Django
|
||||
Querysets</a>, including if you only have
|
||||
one match. You can treat querysets as lists and iterate over them, or continue building search
|
||||
queries with them.</p>
|
||||
<p>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> 1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12</pre></div></td><td class="code"><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">"foo"</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">"foo"</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">"bar"</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># this returns a queryset with *only* myobj1 </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="s2">"foo"</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># these return a queryset with *only* myobj2</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="s2">"foo"</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">"bar"</span><span class="p">)</span>
|
||||
<span class="c1"># or</span>
|
||||
<span class="n">objs</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_tag</span><span class="p">(</span><span class="n">category</span><span class="o">=</span><span class="s2">"bar"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</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>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="using-aliases-and-permissions">
|
||||
<h2>Using Aliases and Permissions<a class="headerlink" href="#using-aliases-and-permissions" title="Permalink to this headline">¶</a></h2>
|
||||
<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>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5</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">"rascal"</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">"Builders"</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">"Builders"</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>
|
||||
<p>and so on. Similarly to how <code class="docutils literal notranslate"><span class="pre">@tag</span></code> works in-game, there is also the <code class="docutils literal notranslate"><span class="pre">@perm</span></code> command for assigning
|
||||
permissions and <code class="docutils literal notranslate"><span class="pre">@alias</span></code> command for aliases.</p>
|
||||
</div>
|
||||
<div class="section" id="assorted-notes">
|
||||
<h2>Assorted notes<a class="headerlink" href="#assorted-notes" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Generally, tags are enough on their own for grouping objects. Having no tag <code class="docutils literal notranslate"><span class="pre">category</span></code> is perfectly
|
||||
fine and the normal operation. Simply adding a new Tag for grouping objects is often better than
|
||||
making a new category. So think hard before deciding you really need to categorize your Tags.</p>
|
||||
<p>That said, tag categories can be useful if you build some game system that uses tags. You can then
|
||||
use tag categories to make sure to separate tags created with this system from any other tags
|
||||
created elsewhere. You can then supply custom search methods that <em>only</em> find objects tagged with
|
||||
tags of that category. An example of this
|
||||
is found in the <a class="reference internal" href="../Concepts/Zones.html"><span class="doc">Zone tutorial</span></a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Tags</a><ul>
|
||||
<li><a class="reference internal" href="#properties-of-tags-and-aliases-and-permissions">Properties of Tags (and Aliases and Permissions)</a></li>
|
||||
<li><a class="reference internal" href="#adding-removing-tags">Adding/Removing Tags</a></li>
|
||||
<li><a class="reference internal" href="#searching-for-objects-with-a-given-tag">Searching for objects with a given tag</a></li>
|
||||
<li><a class="reference internal" href="#using-aliases-and-permissions">Using Aliases and Permissions</a></li>
|
||||
<li><a class="reference internal" href="#assorted-notes">Assorted notes</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Components/Tags.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Tags.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Tags</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
229
docs/1.0-dev/Components/TickerHandler.html
Normal file
229
docs/1.0-dev/Components/TickerHandler.html
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>TickerHandler — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">TickerHandler</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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>
|
||||
<div class="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
|
||||
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
|
||||
triggered at the same interval, unsubscribing when the updating is no longer desired.</p>
|
||||
<p>Evennia offers an optimized implementation of the subscription model - the <em>TickerHandler</em>. This is
|
||||
a singleton global handler reachable from <code class="docutils literal notranslate"><span class="pre">evennia.TICKER_HANDLER</span></code>. You can assign any <em>callable</em> (a
|
||||
function or, more commonly, a method on a database object) to this handler. The TickerHandler will
|
||||
then call this callable at an interval you specify, and with the arguments you supply when adding
|
||||
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>1
|
||||
2
|
||||
3
|
||||
4</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># we assume that obj has a hook "at_tick" 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>
|
||||
<p>That’s 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>1
|
||||
2
|
||||
3
|
||||
4</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>
|
||||
<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>
|
||||
<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>1
|
||||
2</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>
|
||||
<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>
|
||||
<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>1
|
||||
2</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>
|
||||
<span class="n">idstring</span><span class="o">=</span><span class="s2">""</span><span class="p">,</span> <span class="n">persistent</span><span class="o">=</span><span class="bp">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>
|
||||
<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 ticker’s 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>1
|
||||
2</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">"ticker1"</span><span class="p">,</span> <span class="bp">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">"ticker2"</span><span class="p">,</span> <span class="bp">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>
|
||||
<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>1</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>
|
||||
</pre></div>
|
||||
</td></tr></table></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>1
|
||||
2</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">"ticker1"</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">"ticker2"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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
|
||||
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>
|
||||
<div class="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.
|
||||
Even if you are used to habitually relying on tickers for everything in other code bases, stop and
|
||||
think about what you really need it for. This is the main point:</p>
|
||||
<blockquote>
|
||||
<div><p>You should <em>never</em> use a ticker to catch <em>changes</em>.</p>
|
||||
</div></blockquote>
|
||||
<p>Think about it - you might have to run the ticker every second to react to the change fast enough.
|
||||
Most likely nothing will have changed at a given moment. So you are doing pointless calls (since
|
||||
skipping the call gives the same result as doing it). Making sure nothing’s changed might even be
|
||||
computationally expensive depending on the complexity of your system. Not to mention that you might
|
||||
need to run the check <em>on every object in the database</em>. Every second. Just to maintain status quo
|
||||
…</p>
|
||||
<p>Rather than checking over and over on the off-chance that something changed, consider a more
|
||||
proactive approach. Could you implement your rarely changing system to <em>itself</em> report when its
|
||||
status changes? It’s almost always much cheaper/efficient if you can do things “on demand”. Evennia
|
||||
itself uses hook methods for this very reason.</p>
|
||||
<p>So, if you consider a ticker that will fire very often but which you expect to have no effect 99% of
|
||||
the time, consider handling things things some other way. A self-reporting on-demand solution is
|
||||
usually cheaper also for fast-updating properties. Also remember that some things may not need to be
|
||||
updated until someone actually is examining or using them - any interim changes happening up to that
|
||||
moment are pointless waste of computing time.</p>
|
||||
<p>The main reason for needing a ticker is when you want things to happen to multiple objects at the
|
||||
same time without input from something else.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">TickerHandler</a><ul>
|
||||
<li><a class="reference internal" href="#about-tickers">About Tickers</a><ul>
|
||||
<li><a class="reference internal" href="#when-not-to-use-tickerhandler">When <em>not</em> to use TickerHandler</a></li>
|
||||
</ul>
|
||||
</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/TickerHandler.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="TickerHandler.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">TickerHandler</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
454
docs/1.0-dev/Components/Typeclasses.html
Normal file
454
docs/1.0-dev/Components/Typeclasses.html
Normal file
|
|
@ -0,0 +1,454 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Typeclasses — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Typeclasses</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" 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
|
||||
varying distance, from <code class="docutils literal notranslate"><span class="pre">evennia.typeclasses.models.TypedObject</span></code>. In the documentation we refer to
|
||||
these objects as being “typeclassed” or even “being a typeclass”.</p>
|
||||
<p>This is how the inheritance looks for the typeclasses in Evennia:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">TypedObject</span>
|
||||
<span class="n">_________________</span><span class="o">|</span><span class="n">_________________________________</span>
|
||||
<span class="o">|</span> <span class="o">|</span> <span class="o">|</span> <span class="o">|</span>
|
||||
<span class="mi">1</span><span class="p">:</span> <span class="n">AccountDB</span> <span class="n">ObjectDB</span> <span class="n">ScriptDB</span> <span class="n">ChannelDB</span>
|
||||
<span class="o">|</span> <span class="o">|</span> <span class="o">|</span> <span class="o">|</span>
|
||||
<span class="mi">2</span><span class="p">:</span> <span class="n">DefaultAccount</span> <span class="n">DefaultObject</span> <span class="n">DefaultScript</span> <span class="n">DefaultChannel</span>
|
||||
<span class="o">|</span> <span class="n">DefaultCharacter</span> <span class="o">|</span> <span class="o">|</span>
|
||||
<span class="o">|</span> <span class="n">DefaultRoom</span> <span class="o">|</span> <span class="o">|</span>
|
||||
<span class="o">|</span> <span class="n">DefaultExit</span> <span class="o">|</span> <span class="o">|</span>
|
||||
<span class="o">|</span> <span class="o">|</span> <span class="o">|</span> <span class="o">|</span>
|
||||
<span class="mi">3</span><span class="p">:</span> <span class="n">Account</span> <span class="n">Object</span> <span class="n">Script</span> <span class="n">Channel</span>
|
||||
<span class="n">Character</span>
|
||||
<span class="n">Room</span>
|
||||
<span class="n">Exit</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p><strong>Level 1</strong> above is the “database model” level. This describes the database tables and fields
|
||||
(this is technically a <a class="reference external" href="https://docs.djangoproject.com/en/2.2/topics/db/models/">Django model</a>).</p></li>
|
||||
<li><p><strong>Level 2</strong> is where we find Evennia’s default implementations of the various game entities, on
|
||||
top of the database. These classes define all the hook methods that Evennia calls in various
|
||||
situations. <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> is a little special since it’s the parent for <code class="docutils literal notranslate"><span class="pre">DefaultCharacter</span></code>,
|
||||
<code class="docutils literal notranslate"><span class="pre">DefaultRoom</span></code> and <code class="docutils literal notranslate"><span class="pre">DefaultExit</span></code>. They are all grouped under level 2 because they all represents
|
||||
defaults to build from.</p></li>
|
||||
<li><p><strong>Level 3</strong>, finally, holds empty template classes created in your game directory. This is the
|
||||
level you are meant to modify and tweak as you please, overloading the defaults as befits your game.
|
||||
The templates inherit directly from their defaults, so <code class="docutils literal notranslate"><span class="pre">Object</span></code> inherits from <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> and
|
||||
<code class="docutils literal notranslate"><span class="pre">Room</span></code> inherits from <code class="docutils literal notranslate"><span class="pre">DefaultRoom</span></code>.</p></li>
|
||||
</ul>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">typeclass/list</span></code> command will provide a list of all typeclasses known to
|
||||
Evennia. This can be useful for getting a feel for what is available. Note
|
||||
however that if you add a new module with a class in it but do not import that
|
||||
module from anywhere, the <code class="docutils literal notranslate"><span class="pre">typeclass/list</span></code> will not find it. To make it known
|
||||
to Evennia you must import that module from somewhere.</p>
|
||||
<div class="section" id="difference-between-typeclasses-and-classes">
|
||||
<h2>Difference between typeclasses and classes<a class="headerlink" href="#difference-between-typeclasses-and-classes" title="Permalink to this headline">¶</a></h2>
|
||||
<p>All Evennia classes inheriting from class in the table above share one important feature and two
|
||||
important limitations. This is why we don’t simply call them “classes” but “typeclasses”.</p>
|
||||
<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>
|
||||
<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>1
|
||||
2
|
||||
3</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>
|
||||
<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>
|
||||
</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
|
||||
the <code class="docutils literal notranslate"><span class="pre">at_*_creation</span></code> hooks (like <code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code> for Objects) for setting things the very first
|
||||
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>1
|
||||
2
|
||||
3
|
||||
4</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>
|
||||
<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>
|
||||
</li>
|
||||
</ol>
|
||||
<p>Apart from this, a typeclass works like any normal Python class and you can
|
||||
treat it as such.</p>
|
||||
</div>
|
||||
<div class="section" id="creating-a-new-typeclass">
|
||||
<h2>Creating a new typeclass<a class="headerlink" href="#creating-a-new-typeclass" title="Permalink to this headline">¶</a></h2>
|
||||
<p>It’s easy to work with Typeclasses. Either you use an existing typeclass or you create a new Python
|
||||
class inheriting from an existing typeclass. Here is an example of creating a new type of Object:</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6</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">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 'furniture' 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>
|
||||
<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>1
|
||||
2</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">"Chair"</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>
|
||||
<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>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5</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>
|
||||
|
||||
<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">"Chair"</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">"furniture.Furniture"</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">"Chair"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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 don’t use the <code class="docutils literal notranslate"><span class="pre">db_*</span></code> prefix. This will also automatically
|
||||
save the new instance to the database, so you don’t need to call <code class="docutils literal notranslate"><span class="pre">save()</span></code> explicitly.</p>
|
||||
<div class="section" id="about-typeclass-properties">
|
||||
<h3>About typeclass properties<a class="headerlink" href="#about-typeclass-properties" title="Permalink to this headline">¶</a></h3>
|
||||
<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>1
|
||||
2
|
||||
3
|
||||
4
|
||||
5</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">"Table"</span>
|
||||
<span class="n">chair</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
|
||||
|
||||
<span class="k">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"><<<</span> <span class="n">Table</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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>1
|
||||
2
|
||||
3
|
||||
4</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">"Table"</span>
|
||||
|
||||
<span class="k">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"><<<</span> <span class="n">Table</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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>
|
||||
<p>Each typeclass entity has some unique fields relevant to that type. But all also share the
|
||||
following fields (the wrapper name without <code class="docutils literal notranslate"><span class="pre">db_</span></code> is given):</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">key</span></code> (str): The main identifier for the entity, like “Rose”, “myscript” or “Paul”. <code class="docutils literal notranslate"><span class="pre">name</span></code> is an
|
||||
alias.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">date_created</span></code> (datetime): Time stamp when this object was created.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">typeclass_path</span></code> (str): A python path pointing to the location of this (type)class</p></li>
|
||||
</ul>
|
||||
<p>There is one special field that doesn’t use the <code class="docutils literal notranslate"><span class="pre">db_</span></code> prefix (it’s defined by Django):</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">id</span></code> (int): the database id (database ref) of the object. This is an ever-increasing, unique
|
||||
integer. It can also be accessed as <code class="docutils literal notranslate"><span class="pre">dbid</span></code> (database ID) or <code class="docutils literal notranslate"><span class="pre">pk</span></code> (primary key). The <code class="docutils literal notranslate"><span class="pre">dbref</span></code> property
|
||||
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>,
|
||||
<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
|
||||
<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
|
||||
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. It’s also recommended that you explore the available
|
||||
entities using <a class="reference internal" href="../Evennia-API.html"><span class="doc">Evennia’s flat API</span></a> to explore which properties and methods they have
|
||||
available.</p>
|
||||
</div>
|
||||
<div class="section" id="overloading-hooks">
|
||||
<h3>Overloading hooks<a class="headerlink" href="#overloading-hooks" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The way to customize typeclasses is usually to overload <em>hook methods</em> on them. Hooks are methods
|
||||
that Evennia call in various situations. An example is the <code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code> hook on <code class="docutils literal notranslate"><span class="pre">Objects</span></code>,
|
||||
which is only called once, the very first time this object is saved to the database. Other examples
|
||||
are the <code class="docutils literal notranslate"><span class="pre">at_login</span></code> hook of Accounts and the <code class="docutils literal notranslate"><span class="pre">at_repeat</span></code> hook of Scripts.</p>
|
||||
</div>
|
||||
<div class="section" id="querying-for-typeclasses">
|
||||
<h3>Querying for typeclasses<a class="headerlink" href="#querying-for-typeclasses" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Most of the time you search for objects in the database by using convenience methods like the
|
||||
<code class="docutils literal notranslate"><span class="pre">caller.search()</span></code> of <a class="reference internal" href="Commands.html"><span class="doc">Commands</span></a> or the search functions like <code class="docutils literal notranslate"><span class="pre">evennia.search_objects</span></code>.</p>
|
||||
<p>You can however also query for them directly using <a class="reference external" href="https://docs.djangoproject.com/en/1.7/topics/db/queries/">Django’s query
|
||||
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>1</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">"Chair"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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>1
|
||||
2
|
||||
3</pre></div></td><td class="code"><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 "Chair"</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">"Chair"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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. Here’s an
|
||||
example for Scripts:</p>
|
||||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||||
2</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>
|
||||
<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">"Combat"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></div>
|
||||
<p>When querying from the database model parent you don’t 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>
|
||||
</div>
|
||||
</div>
|
||||
<div class="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>
|
||||
<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
|
||||
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>1
|
||||
2
|
||||
3
|
||||
4</pre></div></td><td class="code"><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>
|
||||
<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 won’t 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>1
|
||||
2
|
||||
3
|
||||
4</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>
|
||||
<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>
|
||||
<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">@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
|
||||
comprehensions</a>, like this (ignore the
|
||||
line break, that’s only for readability in the wiki):</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@py</span> <span class="kn">from</span> <span class="nn">typeclasses.furniture</span> <span class="k">import</span> <span class="n">Furniture</span><span class="p">;</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> <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>
|
||||
</pre></div>
|
||||
</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>
|
||||
</div>
|
||||
<div class="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
|
||||
code. From inside the game you can use the default <code class="docutils literal notranslate"><span class="pre">@typeclass</span></code> command:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@typeclass</span> <span class="n">objname</span> <span class="o">=</span> <span class="n">path</span><span class="o">.</span><span class="n">to</span><span class="o">.</span><span class="n">new</span><span class="o">.</span><span class="n">typeclass</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>There are two important switches to this command:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">/reset</span></code> - This will purge all existing Attributes on the object and re-run the creation hook
|
||||
(like <code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code> for Objects). This assures you get an object which is purely of this new
|
||||
class.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">/force</span></code> - This is required if you are changing the class to be <em>the same</em> class the object
|
||||
already has - it’s a safety check to avoid user errors. This is usually used together with <code class="docutils literal notranslate"><span class="pre">/reset</span></code>
|
||||
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>1
|
||||
2</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="bp">False</span><span class="p">,</span>
|
||||
<span class="n">run_start_hooks</span><span class="o">=</span><span class="s2">"all"</span><span class="p">,</span> <span class="n">no_default</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">clean_cmdsets</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</td></tr></table></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>
|
||||
</div>
|
||||
<div class="section" id="how-typeclasses-actually-work">
|
||||
<h2>How typeclasses actually work<a class="headerlink" href="#how-typeclasses-actually-work" title="Permalink to this headline">¶</a></h2>
|
||||
<p><em>This is considered an advanced section.</em></p>
|
||||
<p>Technically, typeclasses are <a class="reference external" href="https://docs.djangoproject.com/en/1.7/topics/db/models/#proxy-models">Django proxy
|
||||
models</a>. The only database
|
||||
models that are “real” in the typeclass system (that is, are represented by actual tables in the
|
||||
database) are <code class="docutils literal notranslate"><span class="pre">AccountDB</span></code>, <code class="docutils literal notranslate"><span class="pre">ObjectDB</span></code>, <code class="docutils literal notranslate"><span class="pre">ScriptDB</span></code> and <code class="docutils literal notranslate"><span class="pre">ChannelDB</span></code> (there are also
|
||||
<a class="reference internal" href="Attributes.html"><span class="doc">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
|
||||
subclasses of them are “proxies”, extending them with Python code without actually modifying the
|
||||
database layout.</p>
|
||||
<p>Evennia modifies Django’s proxy model in various ways to allow them to work without any boiler plate
|
||||
(for example you don’t need to set the Django “proxy” property in the model <code class="docutils literal notranslate"><span class="pre">Meta</span></code> subclass, Evennia
|
||||
handles this for you using metaclasses). Evennia also makes sure you can query subclasses as well as
|
||||
patches django to allow multiple inheritance from the same base class.</p>
|
||||
<div class="section" id="caveats">
|
||||
<h3>Caveats<a class="headerlink" href="#caveats" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Evennia uses the <em>idmapper</em> to cache its typeclasses (Django proxy models) in memory. The idmapper
|
||||
allows things like on-object handlers and properties to be stored on typeclass instances and to not
|
||||
get lost as long as the server is running (they will only be cleared on a Server reload). Django
|
||||
does not work like this by default; by default every time you search for an object in the database
|
||||
you’ll get a <em>different</em> instance of that object back and anything you stored on it that was not in
|
||||
the database would be lost. The bottom line is that Evennia’s Typeclass instances subside in memory
|
||||
a lot longer than vanilla Django model instance do.</p>
|
||||
<p>There is one caveat to consider with this, and that relates to [making your own models](New-
|
||||
Models): Foreign relationships to typeclasses are cached by Django and that means that if you were
|
||||
to change an object in a foreign relationship via some other means than via that relationship, the
|
||||
object seeing the relationship may not reliably update but will still see its old cached version.
|
||||
Due to typeclasses staying so long in memory, stale caches of such relationships could be more
|
||||
visible than common in Django. See the <a class="reference external" href="https://github.com/evennia/evennia/issues/1098">closed issue #1098 and its
|
||||
comments</a> for examples and solutions.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">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="#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="#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>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Components/Typeclasses.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Typeclasses.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Typeclasses</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
444
docs/1.0-dev/Components/Webclient.html
Normal file
444
docs/1.0-dev/Components/Webclient.html
Normal file
|
|
@ -0,0 +1,444 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Webclient — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Webclient</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" id="webclient">
|
||||
<h1>Webclient<a class="headerlink" href="#webclient" title="Permalink to this headline">¶</a></h1>
|
||||
</div>
|
||||
<div class="section" id="web-client">
|
||||
<h1><strong>Web client</strong><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
|
||||
<code class="docutils literal notranslate"><span class="pre">evennia/web/webclient/</span></code>:</p>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">templates/webclient/webclient.html</span></code> and <code class="docutils literal notranslate"><span class="pre">templates/webclient/base.html</span></code> are the very simplistic
|
||||
django html templates describing the webclient layout.</p>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">static/webclient/js/evennia.js</span></code> is the main evennia javascript library. This handles all
|
||||
communication between Evennia and the client over websockets and via AJAX/COMET if the browser can’t
|
||||
handle websockets. It will make the Evennia object available to the javascript namespace, which
|
||||
offers methods for sending and receiving data to/from the server transparently. This is intended to
|
||||
be used also if swapping out the gui front end.</p>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">static/webclient/js/webclient_gui.js</span></code> is the default plugin manager. It adds the <code class="docutils literal notranslate"><span class="pre">plugins</span></code> and
|
||||
<code class="docutils literal notranslate"><span class="pre">plugin_manager</span></code> objects to the javascript namespace, coordinates the GUI operations between the
|
||||
various plugins, and uses the Evennia object library for all in/out.</p>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">static/webclient/js/plugins</span></code> provides a default set of plugins that implement a “telnet-like”
|
||||
interface.</p>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">static/webclient/css/webclient.css</span></code> is the CSS file for the client; it also defines things like how
|
||||
to display ANSI/Xterm256 colors etc.</p>
|
||||
<p>The server-side webclient protocols are found in <code class="docutils literal notranslate"><span class="pre">evennia/server/portal/webclient.py</span></code> and
|
||||
<code class="docutils literal notranslate"><span class="pre">webclient_ajax.py</span></code> for the two types of connections. You can’t (and should not need to) modify
|
||||
these.</p>
|
||||
<div class="section" id="customizing-the-web-client">
|
||||
<h2>Customizing the web client<a class="headerlink" href="#customizing-the-web-client" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Like was the case for the website, you override the webclient from your game directory. You need to
|
||||
add/modify a file in the matching directory location within one of the _overrides directories.
|
||||
These _override directories are NOT directly used by the web server when the game is running, the
|
||||
server copies everything web related in the Evennia folder over to <code class="docutils literal notranslate"><span class="pre">mygame/web/static/</span></code> and then
|
||||
copies in all of your _overrides. This can cause some cases were you edit a file, but it doesn’t
|
||||
seem to make any difference in the servers behavior. <strong>Before doing anything else, try shutting
|
||||
down the game and running <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">collectstatic</span></code> from the command line then start it back up, clear
|
||||
your browser cache, and see if your edit shows up.</strong></p>
|
||||
<p>Example: To change the utilized plugin list, you need to override base.html by copying
|
||||
<code class="docutils literal notranslate"><span class="pre">evennia/web/webclient/templates/webclient/base.html</span></code> to
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" 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>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">Evennia.connect()</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">Evennia.isConnected()</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">Evennia.msg(</span> <span class="pre">cmdname,</span> <span class="pre">args,</span> <span class="pre">kwargs,</span> <span class="pre">callback</span> <span class="pre">)</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">Evennia.emit(</span> <span class="pre">cmdname,</span> <span class="pre">args,</span> <span class="pre">kwargs</span> <span class="pre">)</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">log()</span></code></p></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" 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>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">plugins</span></code> Object, key/value list of the all the loaded plugins.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">plugin_handler</span></code> Object</p>
|
||||
<ul>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">plugin_handler.add("name",</span> <span class="pre">plugin)</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">plugin_handler.onSend(string)</span></code></p></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" 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>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">boolean</span> <span class="pre">onKeydown(event)</span></code> This plugin listens for Keydown events</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">onBeforeUnload()</span></code> This plugin does something special just before the webclient page/tab is
|
||||
closed.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">onLoggedIn(args,</span> <span class="pre">kwargs)</span></code> This plugin does something when the webclient first logs in.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">onGotOptions(args,</span> <span class="pre">kwargs)</span></code> This plugin does something with options sent from the server.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">boolean</span> <span class="pre">onText(args,</span> <span class="pre">kwargs)</span></code> This plugin does something with messages sent from the server.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">boolean</span> <span class="pre">onPrompt(args,</span> <span class="pre">kwargs)</span></code> This plugin does something when the server sends a prompt.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">boolean</span> <span class="pre">onUnknownCmd(cmdname,</span> <span class="pre">args,</span> <span class="pre">kwargs)</span></code> This plugin does something with “unknown commands”.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">onConnectionClose(args,</span> <span class="pre">kwargs)</span></code> This plugin does something when the webclient disconnects from
|
||||
the server.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">newstring</span> <span class="pre">onSend(string)</span></code> This plugin examines/alters text that other plugins generate. <strong>Use
|
||||
with caution</strong></p></li>
|
||||
</ul>
|
||||
<p>The order of the plugins defined in <code class="docutils literal notranslate"><span class="pre">base.html</span></code> is important. All the callbacks for each plugin
|
||||
will be executed in that order. Functions marked “boolean” above must return true/false. Returning
|
||||
true will short-circuit the execution, so no other plugins lower in the base.html list will have
|
||||
their callback for this event called. This enables things like the up/down arrow keys for the
|
||||
history.js plugin to always occur before the default_in.js plugin adds that key to the current input
|
||||
buffer.</p>
|
||||
</div>
|
||||
<div class="section" 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
|
||||
add some “How To” information for your game.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">default_in.js</span></code> Defines onKeydown. <enter> key or mouse clicking the arrow will send the currently
|
||||
typed text.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">default_out.js</span></code> Defines onText, onPrompt, and onUnknownCmd. Generates HTML output for the user.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">default_unload.js</span></code> Defines onBeforeUnload. Prompts the user to confirm that they meant to
|
||||
leave/close the game.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">font.js</span></code> Defines onOptionsUI. The plugin adds the ability to select your font and font size.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">goldenlayout_default_config.js</span></code> Not actually a plugin, defines a global variable that
|
||||
goldenlayout uses to determine its window layout, known tag routing, etc.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">goldenlayout.js</span></code> Defines onKeydown, onText and custom functions. A very powerful “tabbed” window
|
||||
manager for drag-n-drop windows, text routing and more.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">history.js</span></code> Defines onKeydown and onSend. Creates a history of past sent commands, and uses arrow
|
||||
keys to peruse.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">hotbuttons.js</span></code> Defines onGotOptions. A Disabled-by-default plugin that defines a button bar with
|
||||
user-assignable commands.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">iframe.js</span></code> Defines onOptionsUI. A goldenlayout-only plugin to create a restricted browsing sub-
|
||||
window for a side-by-side web/text interface, mostly an example of how to build new HTML
|
||||
“components” for goldenlayout.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">message_routing.js</span></code> Defines onOptionsUI, onText, onKeydown. This goldenlayout-only plugin
|
||||
implements regex matching to allow users to “tag” arbitrary text that matches, so that it gets
|
||||
routed to proper windows. Similar to “Spawn” functions for other clients.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">multimedia.js</span></code> An basic plugin to allow the client to handle “image” “audio” and “video” messages
|
||||
from the server and display them as inline HTML.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">notifications.js</span></code> Defines onText. Generates browser notification events for each new message
|
||||
while the tab is hidden.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">oob.js</span></code> Defines onSend. Allows the user to test/send Out Of Band json messages to the server.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">options.js</span></code> Defines most callbacks. Provides a popup-based UI to coordinate options settings with
|
||||
the server.</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">options2.js</span></code> Defines most callbacks. Provides a goldenlayout-based version of the
|
||||
options/settings tab. Integrates with other plugins via the custom onOptionsUI callback.</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>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">splithandler.js</span></code> Defines onText. Provides an older, less-flexible alternative to goldenlayout for
|
||||
multi-window UI to automatically separate out screen real-estate by type of message.</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" 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. There are two plugins to help with this. The
|
||||
Goldenlayout plugin framework, and the older Splithandler framework.</p>
|
||||
<div class="section" id="goldenlayout">
|
||||
<h2>GoldenLayout<a class="headerlink" href="#goldenlayout" title="Permalink to this headline">¶</a></h2>
|
||||
<p>GoldenLayout is a web framework that allows web developers and their users to create their own
|
||||
tabbed/windowed layouts. Windows/tabs can be click-and-dragged from location to location by
|
||||
clicking on their titlebar and dragging until the “frame lines” appear. Dragging a window onto
|
||||
another window’s titlebar will create a tabbed “Stack”. The Evennia goldenlayout plugin defines 3
|
||||
basic types of window: The Main window, input windows and non-main text output windows. The Main
|
||||
window and the first input window are unique in that they can’t be “closed”.</p>
|
||||
<p>The most basic customization is to provide your users with a default layout other than just one Main
|
||||
output and the one starting input window. This is done by modifying your server’s
|
||||
goldenlayout_default_config.js.</p>
|
||||
<p>Start by creating a new
|
||||
<code class="docutils literal notranslate"><span class="pre">mygame/web/static_overrides/webclient/js/plugins/goldenlayout_default_config.js</span></code> file, and adding
|
||||
the following JSON variable:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">var</span> <span class="n">goldenlayout_config</span> <span class="o">=</span> <span class="p">{</span>
|
||||
<span class="n">content</span><span class="p">:</span> <span class="p">[{</span>
|
||||
<span class="nb">type</span><span class="p">:</span> <span class="s1">'column'</span><span class="p">,</span>
|
||||
<span class="n">content</span><span class="p">:</span> <span class="p">[{</span>
|
||||
<span class="nb">type</span><span class="p">:</span> <span class="s1">'row'</span><span class="p">,</span>
|
||||
<span class="n">content</span><span class="p">:</span> <span class="p">[{</span>
|
||||
<span class="nb">type</span><span class="p">:</span> <span class="s1">'column'</span><span class="p">,</span>
|
||||
<span class="n">content</span><span class="p">:</span> <span class="p">[{</span>
|
||||
<span class="nb">type</span><span class="p">:</span> <span class="s1">'component'</span><span class="p">,</span>
|
||||
<span class="n">componentName</span><span class="p">:</span> <span class="s1">'Main'</span><span class="p">,</span>
|
||||
<span class="n">isClosable</span><span class="p">:</span> <span class="n">false</span><span class="p">,</span>
|
||||
<span class="n">tooltip</span><span class="p">:</span> <span class="s1">'Main - drag to desired position.'</span><span class="p">,</span>
|
||||
<span class="n">componentState</span><span class="p">:</span> <span class="p">{</span>
|
||||
<span class="n">cssClass</span><span class="p">:</span> <span class="s1">'content'</span><span class="p">,</span>
|
||||
<span class="n">types</span><span class="p">:</span> <span class="s1">'untagged'</span><span class="p">,</span>
|
||||
<span class="n">updateMethod</span><span class="p">:</span> <span class="s1">'newlines'</span><span class="p">,</span>
|
||||
<span class="p">},</span>
|
||||
<span class="p">},</span> <span class="p">{</span>
|
||||
<span class="nb">type</span><span class="p">:</span> <span class="s1">'component'</span><span class="p">,</span>
|
||||
<span class="n">componentName</span><span class="p">:</span> <span class="s1">'input'</span><span class="p">,</span>
|
||||
<span class="nb">id</span><span class="p">:</span> <span class="s1">'inputComponent'</span><span class="p">,</span>
|
||||
<span class="n">height</span><span class="p">:</span> <span class="mi">10</span><span class="p">,</span>
|
||||
<span class="n">tooltip</span><span class="p">:</span> <span class="s1">'Input - The last input in the layout is always the default.'</span><span class="p">,</span>
|
||||
<span class="p">},</span> <span class="p">{</span>
|
||||
<span class="nb">type</span><span class="p">:</span> <span class="s1">'component'</span><span class="p">,</span>
|
||||
<span class="n">componentName</span><span class="p">:</span> <span class="s1">'input'</span><span class="p">,</span>
|
||||
<span class="nb">id</span><span class="p">:</span> <span class="s1">'inputComponent'</span><span class="p">,</span>
|
||||
<span class="n">height</span><span class="p">:</span> <span class="mi">10</span><span class="p">,</span>
|
||||
<span class="n">isClosable</span><span class="p">:</span> <span class="n">false</span><span class="p">,</span>
|
||||
<span class="n">tooltip</span><span class="p">:</span> <span class="s1">'Input - The last input in the layout is always the default.'</span><span class="p">,</span>
|
||||
<span class="p">}]</span>
|
||||
<span class="p">},{</span>
|
||||
<span class="nb">type</span><span class="p">:</span> <span class="s1">'column'</span><span class="p">,</span>
|
||||
<span class="n">content</span><span class="p">:</span> <span class="p">[{</span>
|
||||
<span class="nb">type</span><span class="p">:</span> <span class="s1">'component'</span><span class="p">,</span>
|
||||
<span class="n">componentName</span><span class="p">:</span> <span class="s1">'evennia'</span><span class="p">,</span>
|
||||
<span class="n">componentId</span><span class="p">:</span> <span class="s1">'evennia'</span><span class="p">,</span>
|
||||
<span class="n">title</span><span class="p">:</span> <span class="s1">'example'</span><span class="p">,</span>
|
||||
<span class="n">height</span><span class="p">:</span> <span class="mi">60</span><span class="p">,</span>
|
||||
<span class="n">isClosable</span><span class="p">:</span> <span class="n">false</span><span class="p">,</span>
|
||||
<span class="n">componentState</span><span class="p">:</span> <span class="p">{</span>
|
||||
<span class="n">types</span><span class="p">:</span> <span class="s1">'some-tag-here'</span><span class="p">,</span>
|
||||
<span class="n">updateMethod</span><span class="p">:</span> <span class="s1">'newlines'</span><span class="p">,</span>
|
||||
<span class="p">},</span>
|
||||
<span class="p">},</span> <span class="p">{</span>
|
||||
<span class="nb">type</span><span class="p">:</span> <span class="s1">'component'</span><span class="p">,</span>
|
||||
<span class="n">componentName</span><span class="p">:</span> <span class="s1">'evennia'</span><span class="p">,</span>
|
||||
<span class="n">componentId</span><span class="p">:</span> <span class="s1">'evennia'</span><span class="p">,</span>
|
||||
<span class="n">title</span><span class="p">:</span> <span class="s1">'sheet'</span><span class="p">,</span>
|
||||
<span class="n">isClosable</span><span class="p">:</span> <span class="n">false</span><span class="p">,</span>
|
||||
<span class="n">componentState</span><span class="p">:</span> <span class="p">{</span>
|
||||
<span class="n">types</span><span class="p">:</span> <span class="s1">'sheet'</span><span class="p">,</span>
|
||||
<span class="n">updateMethod</span><span class="p">:</span> <span class="s1">'replace'</span><span class="p">,</span>
|
||||
<span class="p">},</span>
|
||||
<span class="p">}],</span>
|
||||
<span class="p">}],</span>
|
||||
<span class="p">}]</span>
|
||||
<span class="p">}]</span>
|
||||
<span class="p">};</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This is a bit ugly, but hopefully, from the indentation, you can see that it creates a side-by-side
|
||||
(2-column) interface with 3 windows down the left side (The Main and 2 inputs) and a pair of windows
|
||||
on the right side for extra outputs. Any text tagged with “some-tag-here” will flow to the bottom
|
||||
of the “example” window, and any text tagged “sheet” will replace the text already in the “sheet”
|
||||
window.</p>
|
||||
<p>Note: GoldenLayout gets VERY confused and will break if you create two windows with the “Main”
|
||||
componentName.</p>
|
||||
<p>Now, let’s say you want to display text on each window using different CSS. This is where new
|
||||
goldenlayout “components” come in. Each component is like a blueprint that gets stamped out when
|
||||
you create a new instance of that component, once it is defined, it won’t be easily altered. You
|
||||
will need to define a new component, preferably in a new plugin file, and then add that into your
|
||||
page (either dynamically to the DOM via javascript, or by including the new plugin file into the
|
||||
base.html).</p>
|
||||
<p>First up, follow the directions in Customizing the Web Client section above to override the
|
||||
base.html.</p>
|
||||
<p>Next, add the new plugin to your copy of base.html:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o"><</span><span class="n">script</span> <span class="n">src</span><span class="o">=</span><span class="p">{</span><span class="o">%</span> <span class="n">static</span> <span class="s2">"webclient/js/plugins/myplugin.js"</span> <span class="o">%</span><span class="p">}</span> <span class="n">language</span><span class="o">=</span><span class="s2">"javascript"</span>
|
||||
<span class="nb">type</span><span class="o">=</span><span class="s2">"text/javascript"</span><span class="o">></</span><span class="n">script</span><span class="o">></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Remember, plugins are load-order dependent, so make sure the new <code class="docutils literal notranslate"><span class="pre"><script></span></code> tag comes before the
|
||||
goldenlayout.js</p>
|
||||
<p>Next, create a new plugin file <code class="docutils literal notranslate"><span class="pre">mygame/web/static_overrides/webclient/js/plugins/myplugin.js</span></code> and
|
||||
edit it.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>let myplugin = (function () {
|
||||
//
|
||||
//
|
||||
var postInit = function() {
|
||||
var myLayout = window.plugins['goldenlayout'].getGL();
|
||||
|
||||
// register our component and replace the default messagewindow
|
||||
myLayout.registerComponent( 'mycomponent', function (container, componentState) {
|
||||
let mycssdiv = $('<div>').addClass('myCSS');
|
||||
mycssdiv.attr('types', 'mytag');
|
||||
mycssdiv.attr('update_method', 'newlines');
|
||||
mycssdiv.appendTo( container.getElement() );
|
||||
});
|
||||
|
||||
console.log("MyPlugin Initialized.");
|
||||
}
|
||||
|
||||
return {
|
||||
init: function () {},
|
||||
postInit: postInit,
|
||||
}
|
||||
})();
|
||||
window.plugin_handler.add("myplugin", myplugin);
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>You can then add “mycomponent” to an item’s componentName in your goldenlayout_default_config.js.</p>
|
||||
<p>Make sure to stop your server, evennia collectstatic, and restart your server. Then make sure to
|
||||
clear your browser cache before loading the webclient page.</p>
|
||||
</div>
|
||||
<div class="section" id="older-splithandler">
|
||||
<h2>Older Splithandler<a class="headerlink" href="#older-splithandler" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The splithandler.js plugin provides a means to do this, but you don’t want to have to force every
|
||||
player to set up their own layout every time they use the client.</p>
|
||||
<p>Let’s create a <code class="docutils literal notranslate"><span class="pre">mygame/web/static_overrides/webclient/js/plugins/layout.js</span></code> plugin!</p>
|
||||
<p>First up, follow the directions in Customizing the Web Client section above to override the
|
||||
base.html.</p>
|
||||
<p>Next, add the new plugin to your copy of base.html:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o"><</span><span class="n">script</span> <span class="n">src</span><span class="o">=</span><span class="p">{</span><span class="o">%</span> <span class="n">static</span> <span class="s2">"webclient/js/plugins/layout.js"</span> <span class="o">%</span><span class="p">}</span> <span class="n">language</span><span class="o">=</span><span class="s2">"javascript"</span>
|
||||
<span class="nb">type</span><span class="o">=</span><span class="s2">"text/javascript"</span><span class="o">></</span><span class="n">script</span><span class="o">></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Remember, plugins are load-order dependent, so make sure the new <code class="docutils literal notranslate"><span class="pre"><script></span></code> tag comes after the
|
||||
splithandler.js</p>
|
||||
<p>And finally create the layout.js file and add the minimum skeleton of a plugin to it:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">//</span> <span class="n">my</span> <span class="n">new</span> <span class="n">plugin</span>
|
||||
<span class="n">var</span> <span class="n">my_plugin</span> <span class="o">=</span> <span class="p">(</span><span class="n">function</span> <span class="p">()</span> <span class="p">{</span>
|
||||
<span class="n">let</span> <span class="n">init</span> <span class="o">=</span> <span class="n">function</span> <span class="p">()</span> <span class="p">{</span>
|
||||
<span class="n">console</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"myplugin! Hello World!"</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="k">return</span> <span class="p">{</span>
|
||||
<span class="n">init</span><span class="p">:</span> <span class="n">init</span><span class="p">,</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">})();</span>
|
||||
<span class="n">plugin_handler</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">"myplugin"</span><span class="p">,</span> <span class="n">my_plugin</span><span class="p">);</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Now, <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">stop</span></code>, <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">collectstatic</span></code>, and <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">start</span></code> and then load the webclient up in
|
||||
your browser.
|
||||
Enable developer options and look in the console, and you should see the message ‘myplugin! Hello
|
||||
World!’</p>
|
||||
<p>Since our layout.js plugin is going to use the splithandler, let’s enhance this by adding a check to
|
||||
make sure the splithandler.js plugin has been loaded:</p>
|
||||
<p>change the above init function to:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">let</span> <span class="n">init</span> <span class="o">=</span> <span class="n">function</span> <span class="p">()</span> <span class="p">{</span>
|
||||
<span class="n">let</span> <span class="n">splithandler</span> <span class="o">=</span> <span class="n">plugins</span><span class="p">[</span><span class="s1">'splithandler'</span><span class="p">];</span>
|
||||
<span class="k">if</span><span class="p">(</span> <span class="n">splithandler</span> <span class="p">)</span> <span class="p">{</span>
|
||||
<span class="n">console</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"MyPlugin initialized"</span><span class="p">);</span>
|
||||
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
||||
<span class="n">alert</span><span class="p">(</span><span class="s1">'MyPlugin requires the splithandler.js plugin. Please contact the game maintainer to</span>
|
||||
<span class="n">correct</span> <span class="n">this</span><span class="s1">');</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>And finally, the splithandler.js provides provides two functions to cut up the screen real-estate:
|
||||
<code class="docutils literal notranslate"><span class="pre">dynamic_split(</span> <span class="pre">pane_name_to_cut_apart,</span> <span class="pre">direction_of_split,</span> <span class="pre">new_pane_name1,</span> <span class="pre">new_pane_name2,</span> <span class="pre">text_flow_pane1,</span> <span class="pre">text_flow_pane2,</span> <span class="pre">array_of_split_percentages</span> <span class="pre">)</span></code>
|
||||
and
|
||||
<code class="docutils literal notranslate"><span class="pre">set_pane_types(</span> <span class="pre">pane_to_set,</span> <span class="pre">array_of_known_message_types_to_assign)</span></code></p>
|
||||
<p>In this case, we’ll cut it into 3 panes, 1 bigger, two smaller, and assign ‘help’ messages to the
|
||||
top-right pane:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">let</span> <span class="n">init</span> <span class="o">=</span> <span class="n">function</span> <span class="p">()</span> <span class="p">{</span>
|
||||
<span class="n">let</span> <span class="n">splithandler</span> <span class="o">=</span> <span class="n">plugins</span><span class="p">[</span><span class="s1">'splithandler'</span><span class="p">];</span>
|
||||
<span class="k">if</span><span class="p">(</span> <span class="n">splithandler</span> <span class="p">)</span> <span class="p">{</span>
|
||||
<span class="n">splithandler</span><span class="o">.</span><span class="n">dynamic_split</span><span class="p">(</span><span class="s2">"main"</span><span class="p">,</span><span class="s2">"horizontal"</span><span class="p">,</span><span class="s2">"left"</span><span class="p">,</span><span class="s2">"right"</span><span class="p">,</span><span class="s2">"linefeed"</span><span class="p">,</span><span class="s2">"linefeed"</span><span class="p">,[</span><span class="mi">50</span><span class="p">,</span><span class="mi">50</span><span class="p">]);</span>
|
||||
<span class="n">splithandler</span><span class="o">.</span><span class="n">dynamic_split</span><span class="p">(</span><span class="s2">"right"</span><span class="p">,</span><span class="s2">"vertical"</span><span class="p">,</span><span class="s2">"help"</span><span class="p">,</span><span class="s2">"misc"</span><span class="p">,</span><span class="s2">"replace"</span><span class="p">,</span><span class="s2">"replace"</span><span class="p">,[</span><span class="mi">50</span><span class="p">,</span><span class="mi">50</span><span class="p">]);</span>
|
||||
<span class="n">splithandler</span><span class="o">.</span><span class="n">set_pane_types</span><span class="p">(</span><span class="s1">'help'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'help'</span><span class="p">]);</span>
|
||||
|
||||
<span class="n">console</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"MyPlugin initialized"</span><span class="p">);</span>
|
||||
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
||||
<span class="n">alert</span><span class="p">(</span><span class="s1">'MyPlugin requires the splithandler.js plugin. Please contact the game maintainer to</span>
|
||||
<span class="n">correct</span> <span class="n">this</span><span class="s1">');</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">stop</span></code>, <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">collectstatic</span></code>, and <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">start</span></code> once more, and force-reload your
|
||||
browser page to clear any cached version. You should now have a nicely split layout.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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="#">Webclient</a></li>
|
||||
<li><a class="reference internal" href="#web-client"><strong>Web client</strong></a><ul>
|
||||
<li><a class="reference internal" href="#customizing-the-web-client">Customizing the web client</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#evennia-web-client-api-from-evennia-js">Evennia Web Client API (from evennia.js)</a></li>
|
||||
<li><a class="reference internal" href="#plugin-manager-api-from-webclient-gui-js">Plugin Manager API (from webclient_gui.js)</a></li>
|
||||
<li><a class="reference internal" href="#plugin-callbacks-api">Plugin callbacks API</a></li>
|
||||
<li><a class="reference internal" href="#example-default-plugins-plugins-js">Example/Default Plugins (plugins/*.js)</a></li>
|
||||
<li><a class="reference internal" href="#writing-your-own-plugins">Writing your own Plugins</a><ul>
|
||||
<li><a class="reference internal" href="#goldenlayout">GoldenLayout</a></li>
|
||||
<li><a class="reference internal" href="#older-splithandler">Older Splithandler</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/Webclient.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Webclient.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Webclient</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
99
docs/1.0-dev/Components/Webserver.html
Normal file
99
docs/1.0-dev/Components/Webserver.html
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Webserver — 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Webserver</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" id="webserver">
|
||||
<h1>Webserver<a class="headerlink" href="#webserver" title="Permalink to this headline">¶</a></h1>
|
||||
<p>TODO: There is no central docs for this component yet.</p>
|
||||
</div>
|
||||
|
||||
|
||||
<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>
|
||||
<div role="note" aria-label="source link">
|
||||
<!--h3>This Page</h3-->
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="../_sources/Components/Webserver.md.txt"
|
||||
rel="nofollow">Show Page Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<h3>Versions</h3>
|
||||
<ul>
|
||||
<li><a href="Webserver.html">1.0-dev (develop branch)</a></li>
|
||||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Webserver</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
© Copyright 2020, The Evennia developer community.
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue