<p>In Evennia the most important game entities, <aclass="reference internal"href="Accounts.html"><spanclass="doc std std-doc">Accounts</span></a>, <aclass="reference internal"href="Objects.html"><spanclass="doc std std-doc">Objects</span></a>,
<aclass="reference internal"href="Scripts.html"><spanclass="doc std std-doc">Scripts</span></a> and <aclass="reference internal"href="Communications.html#channels"><spanclass="std std-doc">Channels</span></a> are all Python classes inheriting, at
varying distance, from <codeclass="docutils literal notranslate"><spanclass="pre">evennia.typeclasses.models.TypedObject</span></code>. In the documentation we refer to
these objects as being “typeclassed” or even “being a typeclass”.</p>
<li><p><strong>Level 1</strong> above is the “database model” level. This describes the database tables and fields
(this is technically a <aclass="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. <codeclass="docutils literal notranslate"><spanclass="pre">DefaultObject</span></code> is a little special since it’s the parent for <codeclass="docutils literal notranslate"><spanclass="pre">DefaultCharacter</span></code>,
<codeclass="docutils literal notranslate"><spanclass="pre">DefaultRoom</span></code> and <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">Object</span></code> inherits from <codeclass="docutils literal notranslate"><spanclass="pre">DefaultObject</span></code> and
<codeclass="docutils literal notranslate"><spanclass="pre">Room</span></code> inherits from <codeclass="docutils literal notranslate"><spanclass="pre">DefaultRoom</span></code>.</p></li>
<h2>Difference between typeclasses and classes<aclass="headerlink"href="#difference-between-typeclasses-and-classes"title="Permalink to this headline">¶</a></h2>
<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 <codeclass="docutils literal notranslate"><spanclass="pre">DefaultObject</span></code> is now globally found both in this module and in the
<li><p>A typeclass’<codeclass="docutils literal notranslate"><spanclass="pre">__init__</span></code> method should normally not be overloaded. This has mostly to do with the
fact that the <codeclass="docutils literal notranslate"><spanclass="pre">__init__</span></code> method is not called in a predictable way. Instead Evennia suggest you use
the <codeclass="docutils literal notranslate"><spanclass="pre">at_*_creation</span></code> hooks (like <codeclass="docutils literal notranslate"><spanclass="pre">at_object_creation</span></code> for Objects) for setting things the very first
time the typeclass is saved to the database or the <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">__init__</span></code>, it <em>must</em>
both accept arbitrary keyword arguments and use <codeclass="docutils literal notranslate"><spanclass="pre">super</span></code> to call its parent::</p>
<p>You can now create a new <codeclass="docutils literal notranslate"><spanclass="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>
<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 <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">create_*</span></code> functions to create typeclassed entities:</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">create_object</span></code> (<codeclass="docutils literal notranslate"><spanclass="pre">create_account</span></code>, <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">Furniture</span></code> typeclass sits in <codeclass="docutils literal notranslate"><spanclass="pre">mygame/typeclasses/furniture.py</span></code>, you
could point to it as <codeclass="docutils literal notranslate"><spanclass="pre">typeclasses.furniture.Furniture</span></code>. Since Evennia will itself look in
<codeclass="docutils literal notranslate"><spanclass="pre">mygame/typeclasses</span></code>, you can shorten this even further to just <codeclass="docutils literal notranslate"><spanclass="pre">furniture.Furniture</span></code>. The create-
functions take a lot of extra keywords allowing you to set things like <aclass="reference internal"href="Attributes.html"><spanclass="doc std std-doc">Attributes</span></a> and
<aclass="reference internal"href="Tags.html"><spanclass="doc std std-doc">Tags</span></a> all in one go. These keywords don’t use the <codeclass="docutils literal notranslate"><spanclass="pre">db_*</span></code> prefix. This will also automatically
save the new instance to the database, so you don’t need to call <codeclass="docutils literal notranslate"><spanclass="pre">save()</span></code> explicitly.</p>
<p>An example of a database field is <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">db_key</span></code>:</p>
<p>That is, we change the chair object to have the <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">db_</span></code> part:</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">db_key</span></code> you should use <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">db_</span></code> is given):</p>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> (str): The main identifier for the entity, like “Rose”, “myscript” or “Paul”. <codeclass="docutils literal notranslate"><spanclass="pre">name</span></code> is an
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">date_created</span></code> (datetime): Time stamp when this object was created.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">db_</span></code> prefix (it’s defined by Django):</p>
<li><p><codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">dbid</span></code> (database ID) or <codeclass="docutils literal notranslate"><spanclass="pre">pk</span></code> (primary key). The <codeclass="docutils literal notranslate"><spanclass="pre">dbref</span></code> property
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">attributes</span></code> - the <aclass="reference internal"href="Attributes.html"><spanclass="doc std std-doc">AttributeHandler</span></a> that manages Attributes on the object. Use
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">db</span></code> (DataBase) - a shortcut property to the AttributeHandler; allowing <codeclass="docutils literal notranslate"><spanclass="pre">obj.db.attrname</span><spanclass="pre">=</span><spanclass="pre">value</span></code></p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">nattributes</span></code> - the <aclass="reference internal"href="Attributes.html"><spanclass="doc std std-doc">Non-persistent AttributeHandler</span></a> for attributes not saved in the
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">ndb</span></code> (NotDataBase) - a shortcut property to the Non-peristent AttributeHandler. Allows
respective pages for <aclass="reference internal"href="Objects.html"><spanclass="doc std std-doc">Objects</span></a>, <aclass="reference internal"href="Scripts.html"><spanclass="doc std std-doc">Scripts</span></a>, <aclass="reference internal"href="Accounts.html"><spanclass="doc std std-doc">Accounts</span></a> and
<aclass="reference internal"href="Communications.html"><spanclass="doc std std-doc">Channels</span></a> for more info. It’s also recommended that you explore the available
entities using <aclass="reference internal"href="Evennia-API.html"><spanclass="doc std std-doc">Evennia’s flat API</span></a> to explore which properties and methods they have
<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 <codeclass="docutils literal notranslate"><spanclass="pre">at_object_creation</span></code> hook on <codeclass="docutils literal notranslate"><spanclass="pre">Objects</span></code>,
which is only called once, the very first time this object is saved to the database. Other examples
are the <codeclass="docutils literal notranslate"><spanclass="pre">at_login</span></code> hook of Accounts and the <codeclass="docutils literal notranslate"><spanclass="pre">at_repeat</span></code> hook of Scripts.</p>
<codeclass="docutils literal notranslate"><spanclass="pre">caller.search()</span></code> of <aclass="reference internal"href="Commands.html"><spanclass="doc std std-doc">Commands</span></a> or the search functions like <codeclass="docutils literal notranslate"><spanclass="pre">evennia.search_objects</span></code>.</p>
<p>You can however also query for them directly using <aclass="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 <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">db_key</span></code>) to search:</p>
<p>It is important that this will <em>only</em> find objects inheriting directly from <codeclass="docutils literal notranslate"><spanclass="pre">Furniture</span></code> in your
database. If there was a subclass of <codeclass="docutils literal notranslate"><spanclass="pre">Furniture</span></code> named <codeclass="docutils literal notranslate"><spanclass="pre">Sitables</span></code> you would not find any chairs
derived from <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">get_family</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">filter_family</span></code> query
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># search for all furnitures and subclasses of furnitures</span>
<p>To make sure to search, say, all <codeclass="docutils literal notranslate"><spanclass="pre">Scripts</span></code><em>regardless</em> of typeclass, you need to query from the
database model itself. So for Objects, this would be <codeclass="docutils literal notranslate"><spanclass="pre">ObjectDB</span></code> in the diagram above. Here’s an
<p>When querying from the database model parent you don’t need to use <codeclass="docutils literal notranslate"><spanclass="pre">filter_family</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">get_family</span></code> -
you will always query all children on the database model.</p>
<h2>Updating existing typeclass instances<aclass="headerlink"href="#updating-existing-typeclass-instances"title="Permalink to this headline">¶</a></h2>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># add a worth Attribute to all existing Furniture</span>
<p>A common use case is putting all Attributes in the <codeclass="docutils literal notranslate"><spanclass="pre">at_*_creation</span></code> hook of the entity, such as
<codeclass="docutils literal notranslate"><spanclass="pre">at_object_creation</span></code> for <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="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>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># Re-run at_object_creation only on those objects not having the new Attribute</span>
<p>The above examples can be run in the command prompt created by <codeclass="docutils literal notranslate"><spanclass="pre">evennia</span><spanclass="pre">shell</span></code>. You could also run
it all in-game using <codeclass="docutils literal notranslate"><spanclass="pre">@py</span></code>. That however requires you to put the code (including imports) as one
single line using <codeclass="docutils literal notranslate"><spanclass="pre">;</span></code> and <aclass="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>
<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 <codeclass="docutils literal notranslate"><spanclass="pre">@typeclass</span></code> command:</p>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">/reset</span></code> - This will purge all existing Attributes on the object and re-run the creation hook
(like <codeclass="docutils literal notranslate"><spanclass="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><codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">/reset</span></code>
to re-run the creation hook on an existing class.</p></li>
<p>In code you instead use the <codeclass="docutils literal notranslate"><spanclass="pre">swap_typeclass</span></code> method which you can find on all typeclassed entities:</p>
<p>The arguments to this method are described <aclass="reference external"href="https://github.com/evennia/evennia/blob/master/evennia.typeclasses.models#typedobjectswap_typeclass">in the API docs
<p>Technically, typeclasses are <aclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">AccountDB</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">ObjectDB</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">ScriptDB</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">ChannelDB</span></code> (there are also
<aclass="reference internal"href="Attributes.html"><spanclass="doc std std-doc">Attributes</span></a> and <aclass="reference internal"href="Tags.html"><spanclass="doc std std-doc">Tags</span></a> but they are not typeclasses themselves). All the
subclasses of them are “proxies”, extending them with Python code without actually modifying the
database layout.</p>
<p>Evennia modifies Django’s proxy model in various ways to allow them to work without any boiler plate
(for example you don’t need to set the Django “proxy” property in the model <codeclass="docutils literal notranslate"><spanclass="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>