Updated HTML docs.

This commit is contained in:
Evennia docbuilder action 2022-11-25 22:54:04 +00:00
parent e078081850
commit fd348593b2
38 changed files with 484 additions and 660 deletions

View file

@ -63,7 +63,7 @@
<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="#how-to-customize-your-own-account-types">How to customize your own Account types</a></li>
<li><a class="reference internal" href="#properties-on-accounts">Properties on Accounts</a></li>
</ul>
</li>
@ -107,94 +107,76 @@
<section class="tex2jax_ignore mathjax_ignore" id="accounts">
<h1>Accounts<a class="headerlink" href="#accounts" title="Permalink to this headline"></a></h1>
<p>All <em>users</em> (real people) that starts a game <a class="reference internal" href="Sessions.html"><span class="doc std std-doc">Session</span></a> on Evennia are doing so through an
object called <em>Account</em>. The Account object has no in-game representation, it represents a unique
game account. In order to actually get on the game the Account must <em>puppet</em> an <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Object</span></a>
(normally a <a class="reference internal" href="Objects.html#characters"><span class="std std-doc">Character</span></a>).</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>┌──────┐ │ ┌───────┐ ┌───────┐ ┌──────┐
│Client├─┼──►│Session├───►│Account├──►│Object│
└──────┘ │ └───────┘ └───────┘ └──────┘
^
</pre></div>
</div>
<p>An <em>Account</em> represents a unique game account - one player playing the game. Whereas a player can potentially connect to the game from several Clients/Sessions, they will normally have only one Account.</p>
<p>The Account object has no in-game representation. In order to actually get on the game the Account must <em>puppet</em> an <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Object</span></a> (normally a <a class="reference internal" href="Objects.html#characters"><span class="std std-doc">Character</span></a>).</p>
<p>Exactly how many Sessions can interact with an Account and its Puppets at once is determined by
Evennias <a class="reference internal" href="Sessions.html#multisession-mode"><span class="std std-doc">MULTISESSION_MODE</span></a> setting.</p>
<p>Apart from storing login information and other account-specific data, the Account object is what is
chatting on <a class="reference internal" href="Channels.html"><span class="doc std std-doc">Channels</span></a>. It is also a good place to store <a class="reference internal" href="Locks.html"><span class="doc std std-doc">Permissions</span></a> to be
consistent between different in-game characters as well as configuration options. The Account
object also has its own <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">CmdSet</span></a>, the <code class="docutils literal notranslate"><span class="pre">AccountCmdSet</span></code>.</p>
<p>Logged into default evennia, you can use the <code class="docutils literal notranslate"><span class="pre">ooc</span></code> command to leave your current
<a class="reference internal" href="Objects.html"><span class="doc std std-doc">character</span></a> and go into OOC mode. You are quite limited in this mode, basically it works
like a simple chat program. It acts as a staging area for switching between Characters (if your
game supports that) or as a safety mode if your Character gets deleted. Use <code class="docutils literal notranslate"><span class="pre">ic</span></code> to attempt to
(re)puppet a Character.</p>
<p>Note that the Account object can have, and often does have, a different set of
<a class="reference internal" href="Permissions.html"><span class="doc std std-doc">Permissions</span></a> from the Character they control. Normally you should put your
permissions on the Account level - this will overrule permissions set on the Character level. For
the permissions of the Character to come into play the default <code class="docutils literal notranslate"><span class="pre">quell</span></code> command can be used. This
allows for exploring the game using a different permission set (but you cant escalate your
permissions this way - for hierarchical permissions like <code class="docutils literal notranslate"><span class="pre">Builder</span></code>, <code class="docutils literal notranslate"><span class="pre">Admin</span></code> etc, the <em>lower</em> of the
permissions on the Character/Account will always be used).</p>
<section id="how-to-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 accounts 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>Apart from storing login information and other account-specific data, the Account object is what is chatting on Evennias default <a class="reference internal" href="Channels.html"><span class="doc std std-doc">Channels</span></a>. It is also a good place to store <a class="reference internal" href="Locks.html"><span class="doc std std-doc">Permissions</span></a> to be consistent between different in-game characters. It can also hold player-level configuration options.</p>
<p>The Account object has its own default <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">CmdSet</span></a>, the <code class="docutils literal notranslate"><span class="pre">AccountCmdSet</span></code>. The commands in this set are available to the player no matter which character they are puppeting. Most notably the default games <code class="docutils literal notranslate"><span class="pre">exit</span></code>, <code class="docutils literal notranslate"><span class="pre">who</span></code> and chat-channel commands are in the Account cmdset.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; ooc
</pre></div>
</div>
<p>The default <code class="docutils literal notranslate"><span class="pre">ooc</span></code> command causes you to leave your current puppet and go into OOC mode. In this mode you have no location and have only the Account-cmdset available. It acts a staging area for switching characters (if your game supports that) as well as a safety fallback if your character gets accidentally deleted.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; ic
</pre></div>
</div>
<p>This re-puppets the latest character.</p>
<p>Note that the Account object can have, and often does have, a different set of <a class="reference internal" href="Permissions.html"><span class="doc std std-doc">Permissions</span></a> from the Character they control. Normally you should put your permissions on the Account level - this will overrule permissions set on the Character level. For the permissions of the Character to come into play the default <code class="docutils literal notranslate"><span class="pre">quell</span></code> command can be used. This allows for exploring the game using a different permission set (but you cant escalate your permissions this way - for hierarchical permissions like <code class="docutils literal notranslate"><span class="pre">Builder</span></code>, <code class="docutils literal notranslate"><span class="pre">Admin</span></code> etc, the <em>lower</em> of the permissions on the Character/Account will always be used).</p>
<section id="how-to-customize-your-own-account-types">
<h2>How to customize your own Account types<a class="headerlink" href="#how-to-customize-your-own-account-types" title="Permalink to this headline"></a></h2>
<p>You will usually not want more than one Account typeclass for all new accounts.</p>
<p>An Evennia Account is, per definition, a Python class that includes <code class="docutils literal notranslate"><span class="pre">evennia.DefaultAccount</span></code> among its parents. In <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/accounts.py</span></code> there is an empty class ready for you to modify. Evennia defaults to using this (it inherits directly from <code class="docutils literal notranslate"><span class="pre">DefaultAccount</span></code>).</p>
<p>Heres an example of modifying the default Account class in code:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># in mygame/typeclasses/accounts.py</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">DefaultAccount</span>
<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">&quot;this is called only once, when account is first created&quot;</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="kc">None</span> <span class="c1"># this is set later self.db.real_address = None # &quot;</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="kc">True</span> <span class="c1"># default config self.db.config_2 = False # &quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">config_3</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1"># &quot;</span>
<span class="c1"># ... whatever else our game needs to know ``` Reload the server with `reload`.</span>
<span class="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="k">def</span> <span class="nf">at_account_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="s2">&quot;this is called only once, when account is first created&quot;</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="kc">None</span> <span class="c1"># this is set later </span>
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">real_address</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># &quot;</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="kc">True</span> <span class="c1"># default config </span>
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">config_2</span> <span class="o">=</span> <span class="kc">False</span> <span class="c1"># &quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">config_3</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1"># &quot;</span>
<span class="c1"># ... whatever else our game needs to know </span>
</pre></div>
</div>
<p>… However, if you use <code class="docutils literal notranslate"><span class="pre">examine</span> <span class="pre">*self</span></code> (the asterisk makes you examine your Account object rather
than your Character), you wont see your new Attributes yet. This is because <code class="docutils literal notranslate"><span class="pre">at_account_creation</span></code>
is only called the very <em>first</em> time the Account is called and your Account object already exists
(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>Reload the server with <code class="docutils literal notranslate"><span class="pre">reload</span></code>.</p>
<p>… However, if you use <code class="docutils literal notranslate"><span class="pre">examine</span> <span class="pre">*self</span></code> (the asterisk makes you examine your Account object rather than your Character), you wont see your new Attributes yet. This is because <code class="docutils literal notranslate"><span class="pre">at_account_creation</span></code> is only called the very <em>first</em> time the Account is called and your Account object already exists (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><p>If you wanted Evennia to default to a completely <em>different</em> Account class located elsewhere, you &gt; must point Evennia to it. Add <code class="docutils literal notranslate"><span class="pre">BASE_ACCOUNT_TYPECLASS</span></code> to your settings file, and give the python path to your custom class as its value. By default this points to <code class="docutils literal notranslate"><span class="pre">typeclasses.accounts.Account</span></code>, the empty template we used above.</p>
</div></blockquote>
</section>
<section id="properties-on-accounts">
<h2>Properties on Accounts<a class="headerlink" href="#properties-on-accounts" title="Permalink to this headline"></a></h2>
<p>Beyond those properties assigned to all typeclassed objects (see <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclasses</span></a>), the
Account also has the following custom properties:</p>
<p>Beyond those properties assigned to all typeclassed objects (see <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclasses</span></a>), the Account also has the following custom properties:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">user</span></code> - a unique link to a <code class="docutils literal notranslate"><span class="pre">User</span></code> Django object, representing the logged-in user.</p></li>
<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">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 std std-doc">Commands</span></a> of this Account. By default these are
the commands found in the cmdset defined by <code class="docutils literal notranslate"><span class="pre">settings.CMDSET_ACCOUNT</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">nicks</span></code> - This stores and handles <a class="reference internal" href="Nicks.html"><span class="doc std std-doc">Nicks</span></a>, in the same way as nicks it works on Objects.
For Accounts, nicks are primarily used to store custom aliases for
<a class="reference internal" href="Channels.html"><span class="doc std std-doc">Channels</span></a>.</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 std std-doc">Nicks</span></a>, in the same way as nicks it works on Objects. For Accounts, nicks are primarily used to store custom aliases for <a class="reference internal" href="Channels.html"><span class="doc std std-doc">Channels</span></a>.</p></li>
</ul>
<p>Selection of special methods (see <code class="docutils literal notranslate"><span class="pre">evennia.DefaultAccount</span></code> for details):</p>
<ul class="simple">
<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">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>

View file

@ -137,7 +137,7 @@
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="Accounts.html">Accounts</a><ul>
<li class="toctree-l2"><a class="reference internal" href="Accounts.html#how-to-create-your-own-account-types">How to create your own Account types</a></li>
<li class="toctree-l2"><a class="reference internal" href="Accounts.html#how-to-customize-your-own-account-types">How to customize your own Account types</a></li>
<li class="toctree-l2"><a class="reference internal" href="Accounts.html#properties-on-accounts">Properties on Accounts</a></li>
</ul>
</li>

View file

@ -114,22 +114,50 @@
<section class="tex2jax_ignore mathjax_ignore" id="objects">
<h1>Objects<a class="headerlink" href="#objects" title="Permalink to this headline"></a></h1>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>┌──────┐ │ ┌───────┐ ┌───────┐ ┌──────┐
│Client├─┼──►│Session├───►│Account├──►│Object│
└──────┘ │ └───────┘ └───────┘ └──────┘
^
</pre></div>
</div>
<p>All in-game objects in Evennia, be it characters, chairs, monsters, rooms or hand grenades are
represented by an Evennia <em>Object</em>. Objects form the core of Evennia and is probably what youll
spend most time working with. Objects are <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclassed</span></a> entities.</p>
<p>An Evennia Object is, by definition, a Python class that includes
<a class="reference internal" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultObject" title="evennia.objects.objects.DefaultObject"><span class="xref myst py py-class">evennia.objects.objects.DefaultObject</span></a> among its
parents. Evennia defines several subclasses of <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code>:</p>
<p>An Evennia Object is, by definition, a Python class that includes <a class="reference internal" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultObject" title="evennia.objects.objects.DefaultObject"><span class="xref myst py py-class">evennia.objects.objects.DefaultObject</span></a> among its parents. Evennia defines several subclasses of <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> in the following inheritance tree:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> ┌────────────┐
Evennia│ │ObjectParent│
library│ └──────▲─────┘
│ │
┌─────────────┐ │ ┌──────┐ │
│DefaultObject◄────────────────────┼────┤Object├──────┤
└──────▲──────┘ │ └──────┘ │
│ │ │
│ ┌────────────────┐ │ ┌─────────┐ │
├────────┤DefaultCharacter◄─┼────┤Character├───┤
│ └────────────────┘ │ └─────────┘ │
│ │ │
│ ┌────────────────┐ │ ┌────┐ │
├────────┤DefaultRoom ◄─┼────┤Room├────────┤
│ └────────────────┘ │ └────┘ │
│ │ │
│ ┌────────────────┐ │ ┌────┐ │
└────────┤DefaultExit ◄─┼────┤Exit├────────┘
└────────────────┘ │ └────┘
│Game-dir
</pre></div>
</div>
<p>Here, arrows indicate inheritance and point from-child-to-parent.</p>
<p>So, for example <code class="docutils literal notranslate"><span class="pre">DefaultObjet</span></code> is a child of <code class="docutils literal notranslate"><span class="pre">DefaultCharacter</span></code> (in the Evennia library), which is a parent of <code class="docutils literal notranslate"><span class="pre">Character</span></code> (in the game dir). The class in the game-dir is the one you should modify for your game.</p>
<blockquote>
<div><p>Note the <code class="docutils literal notranslate"><span class="pre">ObjectParent</span></code> class. This is an empty mix-in that all classes in the game-dir inherits from. Its where you put things you want <em>all</em> these classes to have.</p>
</div></blockquote>
<ul class="simple">
<li><p><a class="reference internal" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultCharacter" title="evennia.objects.objects.DefaultCharacter"><span class="xref myst py py-class">evennia.objects.objects.DefaultCharacter</span></a> -
the normal in-game Character, controlled by a player.</p></li>
<li><p><a class="reference internal" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultCharacter" title="evennia.objects.objects.DefaultCharacter"><span class="xref myst py py-class">evennia.objects.objects.DefaultCharacter</span></a> - the normal in-game Character, controlled by a player.</p></li>
<li><p><a class="reference internal" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultRoom" title="evennia.objects.objects.DefaultRoom"><span class="xref myst py py-class">evennia.objects.objects.DefaultRoom</span></a> - a location in the game world.</p></li>
<li><p><a class="reference internal" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultExit" title="evennia.objects.objects.DefaultExit"><span class="xref myst py py-class">evennia.objects.objects.DefaultExit</span></a> - an entity that (usually) sits
in a room and represents a one-way connection to another location.</p></li>
<li><p><a class="reference internal" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultExit" title="evennia.objects.objects.DefaultExit"><span class="xref myst py py-class">evennia.objects.objects.DefaultExit</span></a> - an entity that in a location (usually a Room). It represents a one-way connection to another location.</p></li>
</ul>
<p>You will usually not use the <code class="docutils literal notranslate"><span class="pre">Default*</span></code> parents themselves. In <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/</span></code> there are
convenient subclasses to use. They are empty, and thus identical to
the defaults. Tweaking them is one of the main ways to customize you game!</p>
<p>Here are the import paths for the relevant child classes in the game dir</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">mygame.typeclasses.objects.Object</span></code> (inherits from <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code>)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">mygame.typeclasses.characters.Character</span></code> (inherits from <code class="docutils literal notranslate"><span class="pre">DefaultCharacter</span></code>)</p></li>
@ -138,11 +166,8 @@ the defaults. Tweaking them is one of the main ways to customize you game!</p>
</ul>
<section id="how-to-create-your-own-object-types">
<h2>How to create your own object types<a class="headerlink" href="#how-to-create-your-own-object-types" title="Permalink to this headline"></a></h2>
<p>You can easily add your own in-game behavior by either modifying one of the typeclasses in
your game dir or by inheriting from them.</p>
<p>You can put your new typeclass directly in the relevant parent
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>
<p>You can easily add your own in-game behavior by either modifying one of the typeclasses in your game dir or by inheriting from them.</p>
<p>You can put your new typeclass directly in the relevant module, or you could organize your code in some other way. Here we assume we make a new module <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/flowers.py</span></code>:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># mygame/typeclasses/flowers.py</span>
<span class="kn">from</span> <span class="nn">typeclasses.objects</span> <span class="kn">import</span> <span class="n">Object</span>
@ -160,7 +185,7 @@ module, or you could organize your code in some other way. Here we assume we mak
</div>
<p>Now you just need to point to the class <em>Rose</em> with the <code class="docutils literal notranslate"><span class="pre">create</span></code> command
to make a new rose:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> @create/drop MyRose:flowers.Rose
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> create/drop MyRose:flowers.Rose
</pre></div>
</div>
<p>What the <code class="docutils literal notranslate"><span class="pre">create</span></code> command actually <em>does</em> is to use the <a class="reference internal" href="../api/evennia.utils.create.html#evennia.utils.create.create_object" title="evennia.utils.create.create_object"><span class="xref myst py py-func">evennia.create_object</span></a>
@ -181,10 +206,8 @@ will usually want to change this at build time (using the <code class="docutils
<section id="adding-common-functionality">
<h2>Adding common functionality<a class="headerlink" href="#adding-common-functionality" title="Permalink to this headline"></a></h2>
<p><code class="docutils literal notranslate"><span class="pre">Object</span></code>, <code class="docutils literal notranslate"><span class="pre">Character</span></code>, <code class="docutils literal notranslate"><span class="pre">Room</span></code> and <code class="docutils literal notranslate"><span class="pre">Exit</span></code> also inherit from <code class="docutils literal notranslate"><span class="pre">mygame.typeclasses.objects.ObjectParent</span></code>.
This is an empty mixin class. Optionally, you can modify this class if you want to easily add some <em>common</em> functionality to all
your Objects, Characters, Rooms and Exits at once. You can still customize each subclass separately (see the Python
docs on <a class="reference external" href="https://docs.python.org/3/tutorial/classes.html#multiple-inheritance">multiple inheritance</a> for details).</p>
<p>For example:</p>
This is an empty mixin class. Optionally, you can modify this class if you want to easily add some <em>common</em> functionality to all your Objects, Characters, Rooms and Exits at once. You can still customize each subclass separately (see the Python docs on <a class="reference external" href="https://docs.python.org/3/tutorial/classes.html#multiple-inheritance">multiple inheritance</a> for details).</p>
<p>Here is an example:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/typeclasses/objects.py</span>
<span class="c1"># ... </span>
@ -194,137 +217,65 @@ docs on <a class="reference external" href="https://docs.python.org/3/tutorial/c
<span class="k">def</span> <span class="nf">at_pre_get</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">getter</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="c1"># make all entities by default un-pickable</span>
<span class="k">return</span> <span class="kc">False</span>
<span class="k">class</span> <span class="nc">Object</span><span class="p">(</span><span class="n">ObjectParent</span><span class="p">,</span> <span class="n">DefaultObject</span><span class="p">):</span>
<span class="c1"># replaces at_pre_get with its own</span>
<span class="k">def</span> <span class="nf">at_pre_get</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">getter</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="k">return</span> <span class="kc">True</span>
<span class="c1"># each in their respective modules ...</span>
<span class="k">class</span> <span class="nc">Character</span><span class="p">(</span><span class="n">ObjectParent</span><span class="p">,</span> <span class="n">DefaultCharacter</span><span class="p">):</span>
<span class="c1"># will inherit at_pre_get from ObjectParent</span>
<span class="k">pass</span>
<span class="k">class</span> <span class="nc">Exit</span><span class="p">(</span><span class="n">ObjectParent</span><span class="p">,</span> <span class="n">DefaultExit</span><span class="p">):</span>
<span class="c1"># Overrides and uses the DefaultExit version of at_pre_get instead</span>
<span class="k">def</span> <span class="nf">at_pre_get</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">getter</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="k">return</span> <span class="n">DefaultExit</span><span class="o">.</span><span class="n">at_pre_get</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">getter</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
</pre></div>
</div>
<p>Now all of <code class="docutils literal notranslate"><span class="pre">Object</span></code>, <code class="docutils literal notranslate"><span class="pre">Exit</span></code>. <code class="docutils literal notranslate"><span class="pre">Room</span></code> and <code class="docutils literal notranslate"><span class="pre">Character</span></code> default to not being able to be picked up using the <code class="docutils literal notranslate"><span class="pre">get</span></code> command.</p>
</section>
<section 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 std std-doc">typeclassed</span></a> objects (see that page for a list
of those), the Object also has the following custom properties:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">aliases</span></code> - a handler that allows you to add and remove aliases from this object. Use
<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">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 internal" href="#exits"><span class="std std-doc">Exits</span></a>, its otherwise usually unset.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">nicks</span></code> - as opposed to aliases, a <a class="reference internal" href="Nicks.html"><span class="doc std std-doc">Nick</span></a> holds a convenient nickname replacement for a
real name, word or sequence, only valid for this object. This mainly makes sense if the Object is
used as a game character - it can then store briefer shorts, example so as to quickly reference game
commands or other characters. Use nicks.add(alias, realname) to add a new one.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">account</span></code> - this holds a reference to a connected <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Account</span></a> controlling this object (if
any). Note that this is set also if the controlling account is <em>not</em> currently online - to test if
an account is online, use the <code class="docutils literal notranslate"><span class="pre">has_account</span></code> property instead.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">sessions</span></code> - if <code class="docutils literal notranslate"><span class="pre">account</span></code> field is set <em>and the account is online</em>, this is a list of all active
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>
<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 internal" href="#exits"><span class="std std-doc">Exits</span></a>, its otherwise usually unset.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">nicks</span></code> - as opposed to aliases, a <a class="reference internal" href="Nicks.html"><span class="doc std std-doc">Nick</span></a> holds a convenient nickname replacement for a real name, word or sequence, only valid for this object. This mainly makes sense if the Object is used as a game character - it can then store briefer shorts, example so as to quickly reference game commands or other characters. Use nicks.add(alias, realname) to add a new one.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">account</span></code> - this holds a reference to a connected <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Account</span></a> controlling this object (if any). Note that this is set also if the controlling account is <em>not</em> currently online - to test if an account is online, use the <code class="docutils literal notranslate"><span class="pre">has_account</span></code> property instead.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">sessions</span></code> - if <code class="docutils literal notranslate"><span class="pre">account</span></code> field is set <em>and the account is online</em>, this is a list of all active 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 internal" href="Command-Sets.html"><span class="doc std std-doc">command sets</span></a> defined on the
object (if any).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">cmdset</span></code> - this is a handler that stores all <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">command sets</span></a> defined on the object (if any).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">scripts</span></code> - this is a handler that manages <a class="reference internal" href="Scripts.html"><span class="doc std std-doc">Scripts</span></a> attached to the object (if any).</p></li>
</ul>
<p>The Object also has a host of useful utility functions. See the function headers in
<code class="docutils literal notranslate"><span class="pre">src/objects/objects.py</span></code> for their arguments and more details.</p>
<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()</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. Its 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">search()</span></code> - this is a convenient shorthand to search for a specific object, at a given location or globally. Its 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">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 internal" href="#exits"><span class="std std-doc">Exits</span></a> to <em>and</em> from this object.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">clear_contents()</span></code> - this will not delete anything, but rather move all contents (except Exits) to
their designated <code class="docutils literal notranslate"><span class="pre">Home</span></code> locations.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">delete()</span></code> - deletes this object, first calling <code class="docutils literal notranslate"><span class="pre">clear_exits()</span></code> and
<code class="docutils literal notranslate"><span class="pre">clear_contents()</span></code>.</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 internal" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultObject" title="evennia.objects.objects.DefaultObject"><span class="xref myst py py-class">API for DefaultObject here</span></a>.</p>
<p>The Object Typeclass defines many more <em>hook methods</em> beyond <code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code>. Evennia calls these hooks at various points. When implementing your custom objects, you will inherit from the base parent and overload these hooks with your own custom code. See <code class="docutils literal notranslate"><span class="pre">evennia.objects.objects</span></code> for an updated list of all the available hooks or the <a class="reference internal" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultObject" title="evennia.objects.objects.DefaultObject"><span class="xref myst py py-class">API for DefaultObject here</span></a>.</p>
</section>
<section id="subclasses-of-object">
<h2>Subclasses of <code class="docutils literal notranslate"><span class="pre">Object</span></code><a class="headerlink" href="#subclasses-of-object" title="Permalink to this headline"></a></h2>
<p>There are three special subclasses of <em>Object</em> in default Evennia - <em>Characters</em>, <em>Rooms</em> and
<em>Exits</em>. The reason they are separated is because these particular object types are fundamental,
something you will always need and in some cases requires some extra attention in order to be
recognized by the game engine (there is nothing stopping you from redefining them though). In
practice they are all pretty similar to the base Object.</p>
<p>There are three special subclasses of <em>Object</em> in default Evennia - <em>Characters</em>, <em>Rooms</em> and <em>Exits</em>. The reason they are separated is because these particular object types are fundamental, something you will always need and in some cases requires some extra attention in order to be recognized by the game engine (there is nothing stopping you from redefining them though). In practice they are all pretty similar to the base Object.</p>
<section id="characters">
<h3>Characters<a class="headerlink" href="#characters" title="Permalink to this headline"></a></h3>
<p>Characters are objects controlled by <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a>. When a new Account
logs in to Evennia for the first time, a new <code class="docutils literal notranslate"><span class="pre">Character</span></code> object is created and
the Account object is assigned to the <code class="docutils literal notranslate"><span class="pre">account</span></code> attribute. A <code class="docutils literal notranslate"><span class="pre">Character</span></code> object
must have a <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">Default Commandset</span></a> set on itself at
creation, or the account will not be able to issue any commands! If you just
inherit your own class from <code class="docutils literal notranslate"><span class="pre">evennia.DefaultCharacter</span></code> and make sure to use
<code class="docutils literal notranslate"><span class="pre">super()</span></code> to call the parent methods you should be fine. In
<code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/characters.py</span></code> is an empty <code class="docutils literal notranslate"><span class="pre">Character</span></code> class ready for you
to modify.</p>
<p>Characters are objects controlled by <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a>. When a new Account logs in to Evennia for the first time, a new <code class="docutils literal notranslate"><span class="pre">Character</span></code> object is created and the Account object is assigned to the <code class="docutils literal notranslate"><span class="pre">account</span></code> attribute. A <code class="docutils literal notranslate"><span class="pre">Character</span></code> object must have a <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">Default Commandset</span></a> set on itself at creation, or the account will not be able to issue any commands! If you just inherit your own class from <code class="docutils literal notranslate"><span class="pre">evennia.DefaultCharacter</span></code> and make sure to use <code class="docutils literal notranslate"><span class="pre">super()</span></code> to call the parent methods you should be fine. In <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/characters.py</span></code> is an empty <code class="docutils literal notranslate"><span class="pre">Character</span></code> class ready for you to modify.</p>
</section>
<section id="rooms">
<h3>Rooms<a class="headerlink" href="#rooms" title="Permalink to this headline"></a></h3>
<p><em>Rooms</em> are the root containers of all other objects. The only thing really separating a room from
any other object is that they have no <code class="docutils literal notranslate"><span class="pre">location</span></code> of their own and that default commands like <code class="docutils literal notranslate"><span class="pre">&#64;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>
<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">&#64;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>
</section>
<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 std std-doc">Transit Command</span></a> on themselves when they are created. This command is
named the same as the exit object and will, when called, handle the practicalities of moving the
character to the Exitss <em>destination</em> - this allows you to just enter the name of the exit on its
own to move around, just as you would expect.</p>
<p>The exit functionality is all defined on the Exit typeclass, so you could in principle completely
change how exits work in your game (its not recommended though, unless you really know what you are
doing). Exits are <a class="reference internal" href="Locks.html"><span class="doc std std-doc">locked</span></a> using an access_type called <em>traverse</em> and also make use of a few
hook methods for giving feedback if the traversal fails. See <code class="docutils literal notranslate"><span class="pre">evennia.DefaultExit</span></code> for more info.
In <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/exits.py</span></code> there is an empty <code class="docutils literal notranslate"><span class="pre">Exit</span></code> class for you to modify.</p>
<p><em>Exits</em> are objects connecting other objects (usually <em>Rooms</em>) together. An object named <em>North</em> or <em>in</em> might be an exit, as well as <em>door</em>, <em>portal</em> or <em>jump out the window</em>. An exit has two things that separate them from other objects. Firstly, their <em>destination</em> property is set and points to a valid object. This fact makes it easy and fast to locate exits in the database. Secondly, exits define a special <a class="reference internal" href="Commands.html"><span class="doc std std-doc">Transit Command</span></a> on themselves when they are created. This command is named the same as the exit object and will, when called, handle the practicalities of moving the character to the Exitss <em>destination</em> - this allows you to just enter the name of the exit on its own to move around, just as you would expect.</p>
<p>The exit functionality is all defined on the Exit typeclass, so you could in principle completely change how exits work in your game (its not recommended though, unless you really know what you are doing). Exits are <a class="reference internal" href="Locks.html"><span class="doc std std-doc">locked</span></a> using an access_type called <em>traverse</em> and also make use of a few hook methods for giving feedback if the traversal fails. See <code class="docutils literal notranslate"><span class="pre">evennia.DefaultExit</span></code> for more info. In <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/exits.py</span></code> there is an empty <code class="docutils literal notranslate"><span class="pre">Exit</span></code> class for you to modify.</p>
<p>The process of traversing an exit is as follows:</p>
<ol class="simple">
<li><p>The traversing <code class="docutils literal notranslate"><span class="pre">obj</span></code> sends a command that matches the Exit-command name on the Exit object. The
<a class="reference internal" href="Commands.html"><span class="doc std std-doc">cmdhandler</span></a> detects this and triggers the command defined on the Exit. Traversal always
involves the “source” (the current location) and the <code class="docutils literal notranslate"><span class="pre">destination</span></code> (this is stored on the Exit
object).</p></li>
<li><p>The traversing <code class="docutils literal notranslate"><span class="pre">obj</span></code> sends a command that matches the Exit-command name on the Exit object. The <a class="reference internal" href="Commands.html"><span class="doc std std-doc">cmdhandler</span></a> detects this and triggers the command defined on the Exit. Traversal always involves the “source” (the current location) and the <code class="docutils literal notranslate"><span class="pre">destination</span></code> (this is stored on the Exit object).</p></li>
<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>
<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_pre_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_pre_leave(obj,</span> <span class="pre">destination)</span></code></p></li>
@ -337,9 +288,7 @@ in order:</p>
</li>
<li><p>On the Exit object, <code class="docutils literal notranslate"><span class="pre">at_post_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>
<p>If the move fails for whatever reason, the Exit will look for an Attribute <code class="docutils literal notranslate"><span class="pre">err_traverse</span></code> on itself and display this as an error message. If this is not found, the Exit will instead call <code class="docutils literal notranslate"><span class="pre">at_failed_traverse(obj)</span></code> on itself.</p>
</section>
</section>
</section>

View file

@ -111,23 +111,17 @@
<section class="tex2jax_ignore mathjax_ignore" id="sessions">
<h1>Sessions<a class="headerlink" href="#sessions" title="Permalink to this headline"></a></h1>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>┌──────┐ │ ┌───────┐ ┌───────┐ ┌──────┐
│Client├─┼──►│Session├───►│Account├──►│Object│
└──────┘ │ └───────┘ └───────┘ └──────┘
^
</pre></div>
</div>
<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 std std-doc">cmdset</span></a>, usually the “unloggedin” cmdset. This is what
is used to show the login screen and to handle commands to create a new account (or
<a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Account</span></a> in evennia lingo) read initial help and to log into the game with an existing
account. A session object can either be “logged in” or not. Logged in means that the user has
authenticated. When this happens the session is associated with an Account object (which is what
holds account-centric stuff). The account can then in turn puppet any number of objects/characters.</p>
<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 std std-doc">Typeclass</span></a> and has no
connection to the database. The Session will go away when a user disconnects and you will lose any
custom data on it if the server reloads. The <code class="docutils literal notranslate"><span class="pre">.db</span></code> handler on Sessions is there to present a uniform
API (so you can assume <code class="docutils literal notranslate"><span class="pre">.db</span></code> exists even if you dont know if you receive an Object or a Session),
but this is just an alias to <code class="docutils literal notranslate"><span class="pre">.ndb</span></code>. So dont store any data on Sessions that you cant afford to
lose in a reload. You have been warned.</p>
</div></blockquote>
<p>A session object has its own <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">cmdset</span></a>, usually the “unloggedin” cmdset. This is what is used to show the login screen and to handle commands to create a new account (or <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Account</span></a> in evennia lingo) read initial help and to log into the game with an existing account. A session object can either be “logged in” or not. Logged in means that the user has authenticated. When this happens the session is associated with an Account object (which is what holds account-centric stuff). The account can then in turn puppet any number of objects/characters.</p>
<p>A Session is not <em>persistent</em> - it is not a <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclass</span></a> and has no connection to the database. The Session will go away when a user disconnects and you will lose any custom data on it if the server reloads. The <code class="docutils literal notranslate"><span class="pre">.db</span></code> handler on Sessions is there to present a uniform API (so you can assume <code class="docutils literal notranslate"><span class="pre">.db</span></code> exists even if you dont 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 dont store any data on Sessions that you cant afford to lose in a reload.</p>
<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>
@ -154,39 +148,61 @@ last time this session was truly visibly active.</p></li>
</section>
<section id="multisession-mode">
<h2>Multisession mode<a class="headerlink" href="#multisession-mode" title="Permalink to this headline"></a></h2>
<p>The number of sessions possible to connect to a given account at the same time and how it works is
given by the <code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE</span></code> setting:</p>
<ul 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 players 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 players 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-cmdsetss <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 users perspective it means one can open
multiple client windows, some for controlling different Characters and some that share a Characters
input/output like in mode 1. This mode otherwise works the same as mode 2.</p></li>
<p>The number of sessions possible to connect to a given account at the same time and how it works is given by the <code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE</span></code> setting:</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE=0</span></code>: One session per account. When connecting with a new session the old one is disconnected. This is the default mode and emulates many classic mud code bases.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>┌──────┐ │ ┌───────┐ ┌───────┐ ┌─────────┐
│Client├─┼──►│Session├───►│Account├──►│Character│
└──────┘ │ └───────┘ └───────┘ └─────────┘
</pre></div>
</div>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE=1</span></code>: Many sessions per account, input/output from/to each session is treated the same. For the player this means they can connect to the game from multiple clients and see the same output in all of them. The result of a command given in one client (that is, through one Session) will be returned to <em>all</em> connected Sessions/clients with no distinction.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
┌──────┐ │ ┌───────┐
│Client├─┼──►│Session├──┐
└──────┘ │ └───────┘ └──►┌───────┐ ┌─────────┐
│ │Account├──►│Character│
┌──────┐ │ ┌───────┐ ┌──►└───────┘ └─────────┘
│Client├─┼──►│Session├──┘
└──────┘ │ └───────┘
</pre></div>
</div>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE=2</span></code>: Many sessions per account, one character per session. In this mode, puppeting an Object/Character will link the puppet back only to the particular Session doing the puppeting. That is, input from that Session will make use of the CmdSet of that Object/Character and outgoing messages (such as the result of a <code class="docutils literal notranslate"><span class="pre">look</span></code>) will be passed back only to that puppeting Session. If another Session tries to puppet the same Character, the old Session will automatically un-puppet it. From the players perspective, this will mean that they can open separate game clients and play a different Character in each using one game account.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> │ ┌───────┐
┌──────┐ │ ┌───────┐ │Account│ ┌─────────┐
│Client├─┼──►│Session├──┐ │ │ ┌►│Character│
└──────┘ │ └───────┘ └──┼───────┼──┘ └─────────┘
│ │ │
┌──────┐ │ ┌───────┐ ┌──┼───────┼──┐ ┌─────────┐
│Client├─┼──►│Session├──┘ │ │ └►│Character│
└──────┘ │ └───────┘ │ │ └─────────┘
│ └───────┘
</pre></div>
</div>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE=3</span></code>: Many sessions per account <em>and</em> character. This is the full multi-puppeting mode, where multiple sessions may not only connect to the player account but multiple sessions may also puppet a single character at the same time. From the users perspective it means one can open multiple client windows, some for controlling different Characters and some that share a Characters input/output like in mode 1. This mode otherwise works the same as mode 2.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> │ ┌───────┐
┌──────┐ │ ┌───────┐ │Account│ ┌─────────┐
│Client├─┼──►│Session├──┐ │ │ ┌►│Character│
└──────┘ │ └───────┘ └──┼───────┼──┘ └─────────┘
│ │ │
┌──────┐ │ ┌───────┐ ┌──┼───────┼──┐
│Client├─┼──►│Session├──┘ │ │ └►┌─────────┐
└──────┘ │ └───────┘ │ │ │Character│
│ │ │ ┌►└─────────┘
┌──────┐ │ ┌───────┐ ┌──┼───────┼──┘ ▼
│Client├─┼──►│Session├──┘ │ │
└──────┘ │ └───────┘ └───────┘
</pre></div>
</div>
</li>
</ul>
<blockquote>
<div><p>Note that even if multiple Sessions puppet one Character, there is only ever one instance of that
Character.</p>
<div><p>Note that even if multiple Sessions puppet one Character, there is only ever one instance of that Character.</p>
</div></blockquote>
</section>
<section id="returning-data-to-the-session">

View file

@ -118,10 +118,7 @@
<p><em>Typeclasses</em> form the core of Evennias data storage. It allows Evennia to represent any number of
different game entities as Python classes, without having to modify the database schema for every
new type.</p>
<p>In Evennia the most important game entities, <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a>, <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a>,
<a class="reference internal" href="Scripts.html"><span class="doc std std-doc">Scripts</span></a> and <a class="reference internal" href="Channels.html"><span class="doc std std-doc">Channels</span></a> are all Python classes inheriting, at
varying distance, from <code class="docutils literal notranslate"><span class="pre">evennia.typeclasses.models.TypedObject</span></code>. In the documentation we refer to
these objects as being “typeclassed” or even “being a typeclass”.</p>
<p>In Evennia the most important game entities, <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a>, <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a>, <a class="reference internal" href="Scripts.html"><span class="doc std std-doc">Scripts</span></a> and <a class="reference internal" href="Channels.html"><span class="doc std std-doc">Channels</span></a> are all Python classes inheriting, at varying distance, from <code class="docutils literal notranslate"><span class="pre">evennia.typeclasses.models.TypedObject</span></code>. In the documentation we refer to these objects as being “typeclassed” or even “being a typeclass”.</p>
<p>This is how the inheritance looks for the typeclasses in Evennia:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">TypedObject</span>
<span class="n">_________________</span><span class="o">|</span><span class="n">_________________________________</span>
@ -175,12 +172,7 @@ default library):</p>
</pre></div>
</div>
</li>
<li><p>A typeclass <code class="docutils literal notranslate"><span class="pre">__init__</span></code> method should normally not be overloaded. This has mostly to do with the
fact that the <code class="docutils literal notranslate"><span class="pre">__init__</span></code> method is not called in a predictable way. Instead Evennia suggest you use
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>
<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"><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>
@ -194,8 +186,7 @@ treat it as such.</p>
</section>
<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>Its easy to work with Typeclasses. Either you use an existing typeclass or you create a new Python
class inheriting from an existing typeclass. Here is an example of creating a new type of Object:</p>
<p>Its easy to work with Typeclasses. Either you use an existing typeclass or you create a new Python class inheriting from an existing typeclass. Here is an example of creating a new type of Object:</p>
<div class="highlight-python notranslate"><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>
@ -334,8 +325,7 @@ you will always query all children on the database model.</p>
<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>
due to how Python inheritance works your changes will automatically be applied to all children once you have reloaded the server.</p>
<p>However, database-saved data, like <code class="docutils literal notranslate"><span class="pre">db_*</span></code> fields, <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attributes</span></a>, <a class="reference internal" href="Tags.html"><span class="doc std std-doc">Tags</span></a> etc, are
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>
@ -361,7 +351,7 @@ it all in-game using <code class="docutils literal notranslate"><span class="pre
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, thats 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="kn">import</span> <span class="n">Furniture</span><span class="p">;</span>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">py</span> <span class="kn">from</span> <span class="nn">typeclasses.furniture</span> <span class="kn">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>
@ -370,59 +360,35 @@ retroactively update objects more than necessary.</p>
</section>
<section id="swap-typeclass">
<h2>Swap typeclass<a class="headerlink" href="#swap-typeclass" title="Permalink to this headline"></a></h2>
<p>If you want to swap an already existing typeclass, there are two ways to do so: From in-game and via
code. From inside the game you can use the default <code class="docutils literal notranslate"><span class="pre">&#64;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>
<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">&#64;typeclass</span></code> command:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">typeclass</span> <span class="n">objname</span> <span class="o">=</span> <span class="n">path</span><span class="o">.</span><span class="n">to</span><span class="o">.</span><span class="n">new</span><span class="o">.</span><span class="n">typeclass</span>
</pre></div>
</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 - its 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>
<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 - its 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"><div class="highlight"><pre><span></span><span class="n">obj_to_change</span><span class="o">.</span><span class="n">swap_typeclass</span><span class="p">(</span><span class="n">new_typeclass_path</span><span class="p">,</span> <span class="n">clean_attributes</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">run_start_hooks</span><span class="o">=</span><span class="s2">&quot;all&quot;</span><span class="p">,</span> <span class="n">no_default</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">clean_cmdsets</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
</pre></div>
</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>
<p>The arguments to this method are described <a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia.typeclasses.models#typedobjectswap_typeclass">in the API docs here</a>.</p>
</section>
<section id="how-typeclasses-actually-work">
<h2>How typeclasses actually work<a class="headerlink" href="#how-typeclasses-actually-work" title="Permalink to this headline"></a></h2>
<p><em>This is considered an advanced section.</em></p>
<p>Technically, typeclasses are <a class="reference external" href="https://docs.djangoproject.com/en/1.7/topics/db/models/#proxy-models">Django proxy
models</a>. The only database
models that are “real” in the typeclass system (that is, are represented by actual tables in the
database) are <code class="docutils literal notranslate"><span class="pre">AccountDB</span></code>, <code class="docutils literal notranslate"><span class="pre">ObjectDB</span></code>, <code class="docutils literal notranslate"><span class="pre">ScriptDB</span></code> and <code class="docutils literal notranslate"><span class="pre">ChannelDB</span></code> (there are also
<a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attributes</span></a> and <a class="reference internal" href="Tags.html"><span class="doc std std-doc">Tags</span></a> but they are not typeclasses themselves). All the
subclasses of them are “proxies”, extending them with Python code without actually modifying the
database layout.</p>
<p>Evennia modifies Djangos proxy model in various ways to allow them to work without any boiler plate
(for example you dont 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>
<p>Technically, typeclasses are <a class="reference external" href="https://docs.djangoproject.com/en/1.7/topics/db/models/#proxy-models">Django proxy models</a>. The only database
models that are “real” in the typeclass system (that is, are represented by actual tables in the database) are <code class="docutils literal notranslate"><span class="pre">AccountDB</span></code>, <code class="docutils literal notranslate"><span class="pre">ObjectDB</span></code>, <code class="docutils literal notranslate"><span class="pre">ScriptDB</span></code> and <code class="docutils literal notranslate"><span class="pre">ChannelDB</span></code> (there are also <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attributes</span></a> and <a class="reference internal" href="Tags.html"><span class="doc std std-doc">Tags</span></a> but they are not typeclasses themselves). All the subclasses of them are “proxies”, extending them with Python code without actually modifying the database layout.</p>
<p>Evennia modifies Djangos proxy model in various ways to allow them to work without any boiler plate (for example you dont need to set the Django “proxy” property in the model <code class="docutils literal notranslate"><span class="pre">Meta</span></code> subclass, Evennia handles this for you using metaclasses). Evennia also makes sure you can query subclasses as well as patches django to allow multiple inheritance from the same base class.</p>
</section>
<section id="caveats">
<h2>Caveats<a class="headerlink" href="#caveats" title="Permalink to this headline"></a></h2>
<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
youll 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 Evennias Typeclass instances subside in memory
a lot longer than vanilla Django model instance do.</p>
<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 youll 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 Evennias 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>
Models): Foreign relationships to typeclasses are cached by Django and that means that if you were to change an object in a foreign relationship via some other means than via that relationship, the object seeing the relationship may not reliably update but will still see its old cached version. Due to typeclasses staying so long in memory, stale caches of such relationships could be more
visible than common in Django. See the <a class="reference external" href="https://github.com/evennia/evennia/issues/1098">closed issue #1098 and its comments</a> for examples and solutions.</p>
</section>
<section id="will-i-run-out-of-dbrefs">
<h2>Will I run out of dbrefs?<a class="headerlink" href="#will-i-run-out-of-dbrefs" title="Permalink to this headline"></a></h2>