evennia/docs/1.0-dev/Contribs/Contrib-Ingame-Python.html
Evennia docbuilder action d339a9deb3 Updated HTML docs.
2022-11-15 20:00:58 +00:00

1051 lines
No EOL
87 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Evennia in-game Python system &#8212; Evennia 1.0-dev documentation</title>
<link rel="stylesheet" href="../_static/nature.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Dialogues in events" href="Contrib-Ingame-Python-Tutorial-Dialogue.html" />
<link rel="prev" title="Email-based login system" href="Contrib-Email-Login.html" />
</head><body>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="Contrib-Ingame-Python-Tutorial-Dialogue.html" title="Dialogues in events"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="Contrib-Email-Login.html" title="Email-based login system"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="Contribs-Overview.html" accesskey="U">Contribs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Evennia in-game Python system</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/evennia_logo.png" alt="Logo"/>
</a></p>
<div id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" />
<input type="submit" value="Go" />
</form>
</div>
</div>
<script>$('#searchbox').show(0);</script>
<h3><a href="../index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Evennia in-game Python system</a><ul>
<li><a class="reference internal" href="#a-warning-regarding-security">A WARNING REGARDING SECURITY</a></li>
<li><a class="reference internal" href="#extra-tutorials">Extra tutorials</a></li>
<li><a class="reference internal" href="#basic-structure-and-vocabulary">Basic structure and vocabulary</a></li>
<li><a class="reference internal" href="#installation">Installation</a><ul>
<li><a class="reference internal" href="#starting-the-event-script">Starting the event script</a></li>
<li><a class="reference internal" href="#editing-permissions">Editing permissions</a></li>
<li><a class="reference internal" href="#adding-the-call-command">Adding the <code class="docutils literal notranslate"><span class="pre">call</span></code> command</a></li>
<li><a class="reference internal" href="#changing-parent-classes-of-typeclasses">Changing parent classes of typeclasses</a></li>
</ul>
</li>
<li><a class="reference internal" href="#using-the-call-command">Using the <code class="docutils literal notranslate"><span class="pre">call</span></code> command</a><ul>
<li><a class="reference internal" href="#examining-callbacks-and-events">Examining callbacks and events</a></li>
<li><a class="reference internal" href="#creating-a-new-callback">Creating a new callback</a></li>
<li><a class="reference internal" href="#editing-and-removing-a-callback">Editing and removing a callback</a></li>
<li><a class="reference internal" href="#the-code-editor">The code editor</a></li>
</ul>
</li>
<li><a class="reference internal" href="#using-events">Using events</a><ul>
<li><a class="reference internal" href="#the-eventfuncs">The eventfuncs</a><ul>
<li><a class="reference internal" href="#deny">deny</a></li>
<li><a class="reference internal" href="#get">get</a></li>
<li><a class="reference internal" href="#call-event">call_event</a></li>
</ul>
</li>
<li><a class="reference internal" href="#variables-in-callbacks">Variables in callbacks</a></li>
<li><a class="reference internal" href="#callbacks-with-parameters">Callbacks with parameters</a></li>
<li><a class="reference internal" href="#time-related-events">Time-related events</a></li>
<li><a class="reference internal" href="#chained-events">Chained events</a></li>
</ul>
</li>
<li><a class="reference internal" href="#using-events-in-code">Using events in code</a><ul>
<li><a class="reference internal" href="#adding-new-events">Adding new events</a></li>
<li><a class="reference internal" href="#calling-an-event-in-code">Calling an event in code</a></li>
<li><a class="reference internal" href="#see-it-all-work">See it all work</a></li>
<li><a class="reference internal" href="#adding-new-eventfuncs">Adding new eventfuncs</a></li>
<li><a class="reference internal" href="#creating-events-with-parameters">Creating events with parameters</a></li>
</ul>
</li>
<li><a class="reference internal" href="#disabling-all-events-at-once">Disabling all events at once</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="Contrib-Email-Login.html"
title="previous chapter">Email-based login system</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="Contrib-Ingame-Python-Tutorial-Dialogue.html"
title="next chapter">Dialogues in events</a></p>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="../_sources/Contribs/Contrib-Ingame-Python.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div><h3>Links</h3>
<ul>
<li><a href="https://www.evennia.com">Home page</a> </li>
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
<li><a href="http://games.evennia.com">Game Index</a> </li>
<li>
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
<a href="https://evennia.blogspot.com/">Blog</a>
</li>
</ul>
<h3>Versions</h3>
<ul>
<li><a href="Contrib-Ingame-Python.html">1.0-dev (develop branch)</a></li>
<ul>
<li><a href="../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
</ul>
</div>
</div>
<div class="bodywrapper">
<div class="body" role="main">
<section class="tex2jax_ignore mathjax_ignore" id="evennia-in-game-python-system">
<h1>Evennia in-game Python system<a class="headerlink" href="#evennia-in-game-python-system" title="Permalink to this headline"></a></h1>
<p>Contrib by Vincent Le Goff 2017</p>
<p>This contrib adds the ability to script with Python in-game. It allows trusted
staff/builders to dynamically add features and triggers to individual objects
without needing to do it in external Python modules. Using custom Python in-game,
specific rooms, exits, characters, objects etc can be made to behave differently from
its “cousins”. This is similar to how softcode works for MU or MudProgs for DIKU.
Keep in mind, however, that allowing Python in-game comes with <em>severe</em>
security concerns (you must trust your builders deeply), so read the warnings in
this module carefully before continuing.</p>
<section id="a-warning-regarding-security">
<h2>A WARNING REGARDING SECURITY<a class="headerlink" href="#a-warning-regarding-security" title="Permalink to this headline"></a></h2>
<p>Evennias in-game Python system will run arbitrary Python code without much
restriction. Such a system is as powerful as potentially dangerous, and you
will have to keep in mind these points before deciding to install it:</p>
<ol class="simple">
<li><p>Untrusted people can run Python code on your game server with this system.
Be careful about who can use this system (see the permissions below).</p></li>
<li><p>You can do all of this in Python outside the game. The in-game Python system
is not to replace all your game feature.</p></li>
</ol>
</section>
<section id="extra-tutorials">
<h2>Extra tutorials<a class="headerlink" href="#extra-tutorials" title="Permalink to this headline"></a></h2>
<p>These tutorials cover examples of using ingame python. Once you have the system
installed (see below) they may be an easier way to learn than reading the full
documentation from beginning to end.</p>
<ul class="simple">
<li><p><a class="reference internal" href="Contrib-Ingame-Python-Tutorial-Dialogue.html"><span class="doc std std-doc">Dialogue events</span></a>, where
NPCs react to things said.</p></li>
<li><p><a class="reference internal" href="Contrib-Ingame-Python-Tutorial-Elevator.html"><span class="doc std std-doc">A voice operated elevator</span></a>
using ingame-python events.</p></li>
</ul>
</section>
<section id="basic-structure-and-vocabulary">
<h2>Basic structure and vocabulary<a class="headerlink" href="#basic-structure-and-vocabulary" title="Permalink to this headline"></a></h2>
<ul class="simple">
<li><p>At the basis of the in-game Python system are <strong>events</strong>. An <strong>event</strong>
defines the context in which we would like to call some arbitrary code. For
instance, one event is defined on exits and will fire every time a character
traverses through this exit. Events are described on a <a class="reference internal" href="../Components/Typeclasses.html"><span class="doc std std-doc">typeclass</span></a>
(<a class="reference internal" href="../Components/Objects.html#exits"><span class="std std-doc">exits</span></a> in our example). All objects inheriting from this
typeclass will have access to this event.</p></li>
<li><p><strong>Callbacks</strong> can be set on individual objects, on events defined in code.
These <strong>callbacks</strong> can contain arbitrary code and describe a specific
behavior for an object. When the event fires, all callbacks connected to this
objects event are executed.</p></li>
</ul>
<p>To see the system in context, when an object is picked up (using the default
<code class="docutils literal notranslate"><span class="pre">get</span></code> command), a specific event is fired:</p>
<ol class="simple">
<li><p>The event “get” is set on objects (on the <code class="docutils literal notranslate"><span class="pre">Object</span></code> typeclass).</p></li>
<li><p>When using the “get” command to pick up an object, this objects <code class="docutils literal notranslate"><span class="pre">at_get</span></code>
hook is called.</p></li>
<li><p>A modified hook of DefaultObject is set by the event system. This hook will
execute (or call) the “get” event on this object.</p></li>
<li><p>All callbacks tied to this objects “get” event will be executed in order.
These callbacks act as functions containing Python code that you can write
in-game, using specific variables that will be listed when you edit the callback
itself.</p></li>
<li><p>In individual callbacks, you can add multiple lines of Python code that will
be fired at this point. In this example, the <code class="docutils literal notranslate"><span class="pre">character</span></code> variable will
contain the character who has picked up the object, while <code class="docutils literal notranslate"><span class="pre">obj</span></code> will contain the
object that was picked up.</p></li>
</ol>
<p>Following this example, if you create a callback “get” on the object “a sword”,
and put in it:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">character</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;You have picked up </span><span class="si">{}</span><span class="s2"> and have completed this quest!&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">get_display_name</span><span class="p">(</span><span class="n">character</span><span class="p">)))</span>
</pre></div>
</div>
<p>When you pick up this object you should see something like:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>You pick up a sword.
You have picked up a sword and have completed this quest!
</pre></div>
</div>
</section>
<section id="installation">
<h2>Installation<a class="headerlink" href="#installation" title="Permalink to this headline"></a></h2>
<p>Being in a separate contrib, the in-game Python system isnt installed by
default. You need to do it manually, following these steps:</p>
<p>This is the quick summary. Scroll down for more detailed help on each step.</p>
<ol>
<li><p>Launch the main script (important!):</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> py evennia.create_script(&quot;evennia.contrib.base_systems.ingame_python.scripts.EventHandler&quot;)
</pre></div>
</div>
</li>
<li><p>Set the permissions (optional):</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">EVENTS_WITH_VALIDATION</span></code>: a group that can edit callbacks, but will need approval (default to
<code class="docutils literal notranslate"><span class="pre">None</span></code>).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">EVENTS_WITHOUT_VALIDATION</span></code>: a group with permission to edit callbacks without need of
validation (default to <code class="docutils literal notranslate"><span class="pre">&quot;immortals&quot;</span></code>).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">EVENTS_VALIDATING</span></code>: a group that can validate callbacks (default to <code class="docutils literal notranslate"><span class="pre">&quot;immortals&quot;</span></code>).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">EVENTS_CALENDAR</span></code>: type of the calendar to be used (either <code class="docutils literal notranslate"><span class="pre">None</span></code>, <code class="docutils literal notranslate"><span class="pre">&quot;standard&quot;</span></code> or <code class="docutils literal notranslate"><span class="pre">&quot;custom&quot;</span></code>,
default to <code class="docutils literal notranslate"><span class="pre">None</span></code>).</p></li>
</ul>
</li>
<li><p>Add the <code class="docutils literal notranslate"><span class="pre">call</span></code> command.</p></li>
<li><p>Inherit from the custom typeclasses of the in-game Python system.</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">evennia.contrib.base_systems.ingame_python.typeclasses.EventCharacter</span></code>: to replace <code class="docutils literal notranslate"><span class="pre">DefaultCharacter</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">evennia.contrib.base_systems.ingame_python.typeclasses.EventExit</span></code>: to replace <code class="docutils literal notranslate"><span class="pre">DefaultExit</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">evennia.contrib.base_systems.ingame_python.typeclasses.EventObject</span></code>: to replace <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">evennia.contrib.base_systems.ingame_python.typeclasses.EventRoom</span></code>: to replace <code class="docutils literal notranslate"><span class="pre">DefaultRoom</span></code>.</p></li>
</ul>
</li>
</ol>
<p>The following sections describe in details each step of the installation.</p>
<blockquote>
<div><p>Note: If you were to start the game without having started the main script (such as when
resetting your database) you will most likely face a traceback when logging in, telling you
that a callback property is not defined. After performing step <code class="docutils literal notranslate"><span class="pre">1</span></code> the error will go away.</p>
</div></blockquote>
<section id="starting-the-event-script">
<h3>Starting the event script<a class="headerlink" href="#starting-the-event-script" title="Permalink to this headline"></a></h3>
<p>To start the event script, you only need a single command, using <code class="docutils literal notranslate"><span class="pre">&#64;py</span></code>.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>py evennia.create_script(&quot;evennia.contrib.base_systems.ingame_python.scripts.EventHandler&quot;)
</pre></div>
</div>
<p>This command will create a global script (that is, a script independent from any object). This
script will hold basic configuration, individual callbacks and so on. You may access it directly,
but you will probably use the callback handler. Creating this script will also create a <code class="docutils literal notranslate"><span class="pre">callback</span></code>
handler on all objects (see below for details).</p>
</section>
<section id="editing-permissions">
<h3>Editing permissions<a class="headerlink" href="#editing-permissions" title="Permalink to this headline"></a></h3>
<p>This contrib comes with its own set of permissions. They define who can edit callbacks without
validation, and who can edit callbacks but needs validation. Validation is a process in which an
administrator (or somebody trusted as such) will check the callbacks produced by others and will
accept or reject them. If accepted, the callbacks are connected, otherwise they are never run.</p>
<p>By default, callbacks can only be created by immortals: no one except the immortals can edit
callbacks, and immortals dont need validation. It can easily be changed, either through settings
or dynamically by changing permissions of users.</p>
<p>The ingame-python contrib adds three <a class="reference internal" href="../Components/Permissions.html"><span class="doc std std-doc">permissions</span></a>) in the settings. You can
override them by changing the settings into your <code class="docutils literal notranslate"><span class="pre">server/conf/settings.py</span></code> file (see below for an
example). The settings defined in the events contrib are:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">EVENTS_WITH_VALIDATION</span></code>: this defines a permission that can edit callbacks, but will need
approval. If you set this to <code class="docutils literal notranslate"><span class="pre">&quot;wizards&quot;</span></code>, for instance, users with the permission <code class="docutils literal notranslate"><span class="pre">&quot;wizards&quot;</span></code>
will be able to edit callbacks. These callbacks will not be connected, though, and will need to be
checked and approved by an administrator. This setting can contain <code class="docutils literal notranslate"><span class="pre">None</span></code>, meaning that no user is
allowed to edit callbacks with validation.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">EVENTS_WITHOUT_VALIDATION</span></code>: this setting defines a permission allowing editing of callbacks
without needing validation. By default, this setting is set to <code class="docutils literal notranslate"><span class="pre">&quot;immortals&quot;</span></code>. It means that
immortals can edit callbacks, and they will be connected when they leave the editor, without needing
approval.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">EVENTS_VALIDATING</span></code>: this last setting defines who can validate callbacks. By default, this is
set to <code class="docutils literal notranslate"><span class="pre">&quot;immortals&quot;</span></code>, meaning only immortals can see callbacks needing validation, accept or
reject them.</p></li>
</ul>
<p>You can override all these settings in your <code class="docutils literal notranslate"><span class="pre">server/conf/settings.py</span></code> file. For instance:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># ... other settings ...</span>
<span class="c1"># Event settings</span>
<span class="n">EVENTS_WITH_VALIDATION</span> <span class="o">=</span> <span class="s2">&quot;wizards&quot;</span>
<span class="n">EVENTS_WITHOUT_VALIDATION</span> <span class="o">=</span> <span class="s2">&quot;immortals&quot;</span>
<span class="n">EVENTS_VALIDATING</span> <span class="o">=</span> <span class="s2">&quot;immortals&quot;</span>
</pre></div>
</div>
<p>In addition, there is another setting that must be set if you plan on using the time-related events
(events that are scheduled at specific, in-game times). You would need to specify the type of
calendar you are using. By default, time-related events are disabled. You can change the
<code class="docutils literal notranslate"><span class="pre">EVENTS_CALENDAR</span></code> to set it to:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">&quot;standard&quot;</span></code>: the standard calendar, with standard days, months, years and so on.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">&quot;custom&quot;</span></code>: a custom calendar that will use the <code class="docutils literal notranslate"><span class="pre">custom_gametime</span></code> contrib to schedule events.</p></li>
</ul>
<p>This contrib defines two additional permissions that can be set on individual users:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">events_without_validation</span></code>: this would give this user the rights to edit callbacks but not
require validation before they are connected.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">events_validating</span></code>: this permission allows this user to run validation checks on callbacks
needing to be validated.</p></li>
</ul>
<p>For instance, to give the right to edit callbacks without needing approval to the player kaldara,
you might do something like:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>perm *kaldara = events_without_validation
</pre></div>
</div>
<p>To remove this same permission, just use the <code class="docutils literal notranslate"><span class="pre">/del</span></code> switch:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>perm/del *kaldara = events_without_validation
</pre></div>
</div>
<p>The rights to use the <code class="docutils literal notranslate"><span class="pre">call</span></code> command are directly related to these permissions: by default, only
users who have the <code class="docutils literal notranslate"><span class="pre">events_without_validation</span></code> permission or are in (or above) the group defined in
the <code class="docutils literal notranslate"><span class="pre">EVENTS_WITH_VALIDATION</span></code> setting will be able to call the command (with different switches).</p>
</section>
<section id="adding-the-call-command">
<h3>Adding the <code class="docutils literal notranslate"><span class="pre">call</span></code> command<a class="headerlink" href="#adding-the-call-command" title="Permalink to this headline"></a></h3>
<p>You also have to add the <code class="docutils literal notranslate"><span class="pre">&#64;call</span></code> command to your Character CmdSet. This command allows your users
to add, edit and delete callbacks in-game. In your <code class="docutils literal notranslate"><span class="pre">commands/default_cmdsets</span></code>, it might look like
this:</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">default_cmds</span>
<span class="kn">from</span> <span class="nn">evennia.contrib.base_systems.ingame_python.commands</span> <span class="kn">import</span> <span class="n">CmdCallback</span>
<span class="k">class</span> <span class="nc">CharacterCmdSet</span><span class="p">(</span><span class="n">default_cmds</span><span class="o">.</span><span class="n">CharacterCmdSet</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> The `CharacterCmdSet` contains general in-game commands like `look`,</span>
<span class="sd"> `get`, etc available on in-game Character objects. It is merged with</span>
<span class="sd"> the `PlayerCmdSet` when a Player puppets a Character.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;DefaultCharacter&quot;</span>
<span class="k">def</span> <span class="nf">at_cmdset_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Populates the cmdset</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">at_cmdset_creation</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">CmdCallback</span><span class="p">())</span>
</pre></div>
</div>
</section>
<section id="changing-parent-classes-of-typeclasses">
<h3>Changing parent classes of typeclasses<a class="headerlink" href="#changing-parent-classes-of-typeclasses" title="Permalink to this headline"></a></h3>
<p>Finally, to use the in-game Python system, you need to have your typeclasses inherit from the modified event
classes. For instance, in your <code class="docutils literal notranslate"><span class="pre">typeclasses/characters.py</span></code> module, you should change inheritance
like this:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.contrib.base_systems.ingame_python.typeclasses</span> <span class="kn">import</span> <span class="n">EventCharacter</span>
<span class="k">class</span> <span class="nc">Character</span><span class="p">(</span><span class="n">EventCharacter</span><span class="p">):</span>
<span class="c1"># ...</span>
</pre></div>
</div>
<p>You should do the same thing for your rooms, exits and objects. Note that the
in-game Python system works by overriding some hooks. Some of these features
might not be accessible in your game if you dont call the parent methods when
overriding hooks.</p>
</section>
</section>
<section id="using-the-call-command">
<h2>Using the <code class="docutils literal notranslate"><span class="pre">call</span></code> command<a class="headerlink" href="#using-the-call-command" title="Permalink to this headline"></a></h2>
<p>The in-game Python system relies, to a great extent, on its <code class="docutils literal notranslate"><span class="pre">call</span></code> command.
Who can execute this command, and who can do what with it, will depend on your
set of permissions.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">call</span></code> command allows to add, edit and delete callbacks on specific objects events. The event
system can be used on most Evennia objects, mostly typeclassed objects (excluding players). The
first argument of the <code class="docutils literal notranslate"><span class="pre">call</span></code> command is the name of the object you want to edit. It can also be
used to know what events are available for this specific object.</p>
<section id="examining-callbacks-and-events">
<h3>Examining callbacks and events<a class="headerlink" href="#examining-callbacks-and-events" title="Permalink to this headline"></a></h3>
<p>To see the events connected to an object, use the <code class="docutils literal notranslate"><span class="pre">call</span></code> command and give the name or ID of the
object to examine. For instance, <code class="docutils literal notranslate"><span class="pre">call</span> <span class="pre">here</span></code> to examine the events on your current location. Or
<code class="docutils literal notranslate"><span class="pre">call</span> <span class="pre">self</span></code> to see the events on yourself.</p>
<p>This command will display a table, containing:</p>
<ul class="simple">
<li><p>The name of each event in the first column.</p></li>
<li><p>The number of callbacks of this name, and the number of total lines of these callbacks in the
second column.</p></li>
<li><p>A short help to tell you when the event is triggered in the third column.</p></li>
</ul>
<p>If you execute <code class="docutils literal notranslate"><span class="pre">call</span> <span class="pre">#1</span></code> for instance, you might see a table like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>+------------------+---------+-----------------------------------------------+
| Event name | Number | Description |
+~~~~~~~~~~~~~~~~~~+~~~~~~~~~+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| can_delete | 0 (0) | Can the character be deleted? |
| can_move | 0 (0) | Can the character move? |
| can_part | 0 (0) | Can the departing character leave this room? |
| delete | 0 (0) | Before deleting the character. |
| greet | 0 (0) | A new character arrives in the location of |
| | | this character. |
| move | 0 (0) | After the character has moved into its new |
| | | room. |
| puppeted | 0 (0) | When the character has been puppeted by a |
| | | player. |
| time | 0 (0) | A repeated event to be called regularly. |
| unpuppeted | 0 (0) | When the character is about to be un- |
| | | puppeted. |
+------------------+---------+-----------------------------------------------+
</pre></div>
</div>
</section>
<section id="creating-a-new-callback">
<h3>Creating a new callback<a class="headerlink" href="#creating-a-new-callback" title="Permalink to this headline"></a></h3>
<p>The <code class="docutils literal notranslate"><span class="pre">/add</span></code> switch should be used to add a callback. It takes two arguments beyond the objects
name/DBREF:</p>
<ol class="simple">
<li><p>After an = sign, the name of the event to be edited (if not supplied, will display the list of
possible events, like above).</p></li>
<li><p>The parameters (optional).</p></li>
</ol>
<p>Well see callbacks with parameters later. For the time being, lets try to prevent a character
from going through the “north” exit of this room:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>call north
+------------------+---------+-----------------------------------------------+
| Event name | Number | Description |
+~~~~~~~~~~~~~~~~~~+~~~~~~~~~+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| can_traverse | 0 (0) | Can the character traverse through this exit? |
| msg_arrive | 0 (0) | Customize the message when a character |
| | | arrives through this exit. |
| msg_leave | 0 (0) | Customize the message when a character leaves |
| | | through this exit. |
| time | 0 (0) | A repeated event to be called regularly. |
| traverse | 0 (0) | After the character has traversed through |
| | | this exit. |
+------------------+---------+-----------------------------------------------+
</pre></div>
</div>
<p>If we want to prevent a character from traversing through this exit, the best event for us would be
“can_traverse”.</p>
<blockquote>
<div><p>Why not “traverse”? If you read the description of both events, you will see “traverse” is called
<strong>after</strong> the character has traversed through this exit. It would be too late to prevent it. On
the other hand, “can_traverse” is obviously checked before the character traverses.</p>
</div></blockquote>
<p>When we edit the event, we have some more information:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>call/add north = can_traverse
</pre></div>
</div>
<p>Can the character traverse through this exit?
This event is called when a character is about to traverse this
exit. You can use the deny() eventfunc to deny the character from
exiting for this time.</p>
<p>Variables you can use in this event:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>- character: the character that wants to traverse this exit.
- exit: the exit to be traversed.
- room: the room in which stands the character before moving.
</pre></div>
</div>
<p>The section dedicated to <a class="reference internal" href="#the-eventfuncs"><span class="std std-doc">eventfuncs</span></a> will elaborate on the <code class="docutils literal notranslate"><span class="pre">deny()</span></code> function and
other eventfuncs. Let us say, for the time being, that it can prevent an action (in this case, it
can prevent the character from traversing through this exit). In the editor that opened when you
used <code class="docutils literal notranslate"><span class="pre">call/add</span></code>, you can type something like:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">character</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">character</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;You&#39;re the superuser, &#39;course I&#39;ll let you pass.&quot;</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">character</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;Hold on, what do you think you&#39;re doing?&quot;</span><span class="p">)</span>
<span class="n">deny</span><span class="p">()</span>
</pre></div>
</div>
<p>You can now enter <code class="docutils literal notranslate"><span class="pre">:wq</span></code> to leave the editor by saving the callback.</p>
<p>If you enter <code class="docutils literal notranslate"><span class="pre">call</span> <span class="pre">north</span></code>, you should see that “can_traverse” now has an active callback. You can
use <code class="docutils literal notranslate"><span class="pre">call</span> <span class="pre">north</span> <span class="pre">=</span> <span class="pre">can_traverse</span></code> to see more details on the connected callbacks:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">call</span> <span class="n">north</span> <span class="o">=</span> <span class="n">can_traverse</span>
<span class="o">+--------------+--------------+----------------+--------------+--------------+</span>
<span class="o">|</span> <span class="n">Number</span> <span class="o">|</span> <span class="n">Author</span> <span class="o">|</span> <span class="n">Updated</span> <span class="o">|</span> <span class="n">Param</span> <span class="o">|</span> <span class="n">Valid</span> <span class="o">|</span>
<span class="o">+~~~~~~~~~~~~~~+~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~+~~~~~~~~~~~~~~+</span>
<span class="o">|</span> <span class="mi">1</span> <span class="o">|</span> <span class="n">XXXXX</span> <span class="o">|</span> <span class="mi">5</span> <span class="n">seconds</span> <span class="n">ago</span> <span class="o">|</span> <span class="o">|</span> <span class="n">Yes</span> <span class="o">|</span>
<span class="o">+--------------+--------------+----------------+--------------+--------------+</span>
</pre></div>
</div>
<p>The left column contains callback numbers. You can use them to have even more information on a
specific event. Here, for instance:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">call</span> <span class="n">north</span> <span class="o">=</span> <span class="n">can_traverse</span> <span class="mi">1</span>
<span class="n">Callback</span> <span class="n">can_traverse</span> <span class="mi">1</span> <span class="n">of</span> <span class="n">north</span><span class="p">:</span>
<span class="n">Created</span> <span class="n">by</span> <span class="n">XXXXX</span> <span class="n">on</span> <span class="mi">2017</span><span class="o">-</span><span class="mi">04</span><span class="o">-</span><span class="mi">02</span> <span class="mi">17</span><span class="p">:</span><span class="mi">58</span><span class="p">:</span><span class="mf">05.</span>
<span class="n">Updated</span> <span class="n">by</span> <span class="n">XXXXX</span> <span class="n">on</span> <span class="mi">2017</span><span class="o">-</span><span class="mi">04</span><span class="o">-</span><span class="mi">02</span> <span class="mi">18</span><span class="p">:</span><span class="mi">02</span><span class="p">:</span><span class="mi">50</span>
<span class="n">This</span> <span class="n">callback</span> <span class="ow">is</span> <span class="n">connected</span> <span class="ow">and</span> <span class="n">active</span><span class="o">.</span>
<span class="n">Callback</span> <span class="n">code</span><span class="p">:</span>
<span class="k">if</span> <span class="n">character</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">character</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;You&#39;re the superuser, &#39;course I&#39;ll let you pass.&quot;</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">character</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;Hold on, what do you think you&#39;re doing?&quot;</span><span class="p">)</span>
<span class="n">deny</span><span class="p">()</span>
</pre></div>
</div>
<p>Then try to walk through this exit. Do it with another character if possible, too, to see the
difference.</p>
</section>
<section id="editing-and-removing-a-callback">
<h3>Editing and removing a callback<a class="headerlink" href="#editing-and-removing-a-callback" title="Permalink to this headline"></a></h3>
<p>You can use the <code class="docutils literal notranslate"><span class="pre">/edit</span></code> switch to the <code class="docutils literal notranslate"><span class="pre">&#64;call</span></code> command to edit a callback. You should provide, after
the name of the object to edit and the equal sign:</p>
<ol class="simple">
<li><p>The name of the event (as seen above).</p></li>
<li><p>A number, if several callbacks are connected at this location.</p></li>
</ol>
<p>You can type <code class="docutils literal notranslate"><span class="pre">call/edit</span> <span class="pre">&lt;object&gt;</span> <span class="pre">=</span> <span class="pre">&lt;event</span> <span class="pre">name&gt;</span></code> to see the callbacks that are linked at this
location. If there is only one callback, it will be opened in the editor; if more are defined, you
will be asked for a number to provide (for instance, <code class="docutils literal notranslate"><span class="pre">call/edit</span> <span class="pre">north</span> <span class="pre">=</span> <span class="pre">can_traverse</span> <span class="pre">2</span></code>).</p>
<p>The command <code class="docutils literal notranslate"><span class="pre">call</span></code> also provides a <code class="docutils literal notranslate"><span class="pre">/del</span></code> switch to remove a callback. It takes the same arguments
as the <code class="docutils literal notranslate"><span class="pre">/edit</span></code> switch.</p>
<p>When removed, callbacks are logged, so an administrator can retrieve its content, assuming the
<code class="docutils literal notranslate"><span class="pre">/del</span></code> was an error.</p>
</section>
<section id="the-code-editor">
<h3>The code editor<a class="headerlink" href="#the-code-editor" title="Permalink to this headline"></a></h3>
<p>When adding or editing a callback, the event editor should open in code mode. The additional
options supported by the editor in this mode are describe in <a class="reference external" href="https://github.com/evennia/evennia/wiki/EvEditor#the-eveditor-to-edit-code">a dedicated section of the EvEditors
documentation</a>.</p>
</section>
</section>
<section id="using-events">
<h2>Using events<a class="headerlink" href="#using-events" title="Permalink to this headline"></a></h2>
<p>The following sections describe how to use events for various tasks, from the most simple to the
most complex.</p>
<section id="the-eventfuncs">
<h3>The eventfuncs<a class="headerlink" href="#the-eventfuncs" title="Permalink to this headline"></a></h3>
<p>In order to make development a little easier, the in-game Python system provides eventfuncs to be used in
callbacks themselves. You dont have to use them, they are just shortcuts. An eventfunc is just a
simple function that can be used inside of your callback code.</p>
<table class="colwidths-auto docutils align-default">
<thead>
<tr class="row-odd"><th class="head"><p>Function</p></th>
<th class="head"><p>Argument</p></th>
<th class="head"><p>Description</p></th>
<th class="head"><p>Example</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p>deny</p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">()</span></code></p></td>
<td><p>Prevent an action from happening.</p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">deny()</span></code></p></td>
</tr>
<tr class="row-odd"><td><p>get</p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">(**kwargs)</span></code></p></td>
<td><p>Get a single object.</p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">char</span> <span class="pre">=</span> <span class="pre">get(id=1)</span></code></p></td>
</tr>
<tr class="row-even"><td><p>call_event</p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">(obj,</span> <span class="pre">name,</span> <span class="pre">seconds=0)</span></code></p></td>
<td><p>Call another event.</p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">call_event(char,</span> <span class="pre">&quot;chain_1&quot;,</span> <span class="pre">20)</span></code></p></td>
</tr>
</tbody>
</table>
<section id="deny">
<h4>deny<a class="headerlink" href="#deny" title="Permalink to this headline"></a></h4>
<p>The <code class="docutils literal notranslate"><span class="pre">deny()</span></code> function allows to interrupt the callback and the action that called it. In the
<code class="docutils literal notranslate"><span class="pre">can_*</span></code> events, it can be used to prevent the action from happening. For instance, in <code class="docutils literal notranslate"><span class="pre">can_say</span></code> on
rooms, it can prevent the character from saying something in the room. One could have a <code class="docutils literal notranslate"><span class="pre">can_eat</span></code>
event set on food that would prevent this character from eating this food.</p>
<p>Behind the scenes, the <code class="docutils literal notranslate"><span class="pre">deny()</span></code> function raises an exception that is being intercepted by the
handler of events. The handler will then report that the action was cancelled.</p>
</section>
<section id="get">
<h4>get<a class="headerlink" href="#get" title="Permalink to this headline"></a></h4>
<p>The <code class="docutils literal notranslate"><span class="pre">get</span></code> eventfunc is a shortcut to get a single object with a specific identity. Its often used
to retrieve an object with a given ID. In the section dedicated to <a class="reference internal" href="#chained-events"><span class="std std-doc">chained
events</span></a>, you will see a concrete example of this function in action.</p>
</section>
<section id="call-event">
<h4>call_event<a class="headerlink" href="#call-event" title="Permalink to this headline"></a></h4>
<p>Some callbacks will call other events. It is particularly useful for <a class="reference internal" href="#chained-events"><span class="std std-doc">chained
events</span></a> that are described in a dedicated section. This eventfunc is used to call
another event, immediately or in a defined time.</p>
<p>You need to specify as first parameter the object containing the event. The second parameter is the
name of the event to call. The third parameter is the number of seconds before calling this event.
By default, this parameter is set to 0 (the event is called immediately).</p>
</section>
</section>
<section id="variables-in-callbacks">
<h3>Variables in callbacks<a class="headerlink" href="#variables-in-callbacks" title="Permalink to this headline"></a></h3>
<p>In the Python code you will enter in individual callbacks, you will have access to variables in your
locals. These variables will depend on the event, and will be clearly listed when you add or edit a
callback. As youve seen in the previous example, when we manipulate characters or character
actions, we often have a <code class="docutils literal notranslate"><span class="pre">character</span></code> variable that holds the character doing the action.</p>
<p>In most cases, when an event is fired, all callbacks from this event are called. Variables are
created for each event. Sometimes, however, the callback will execute and then ask for a variable
in your locals: in other words, some callbacks can alter the actions being performed by changing
values of variables. This is always clearly specified in the help of the event.</p>
<p>One example that will illustrate this system is the “msg_leave” event that can be set on exits.
This event can alter the message that will be sent to other characters when someone leaves through
this exit.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>call/add down = msg_leave
</pre></div>
</div>
<p>Which should display:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Customize</span> <span class="n">the</span> <span class="n">message</span> <span class="n">when</span> <span class="n">a</span> <span class="n">character</span> <span class="n">leaves</span> <span class="n">through</span> <span class="n">this</span> <span class="n">exit</span><span class="o">.</span>
<span class="n">This</span> <span class="n">event</span> <span class="ow">is</span> <span class="n">called</span> <span class="n">when</span> <span class="n">a</span> <span class="n">character</span> <span class="n">leaves</span> <span class="n">through</span> <span class="n">this</span> <span class="n">exit</span><span class="o">.</span>
<span class="n">To</span> <span class="n">customize</span> <span class="n">the</span> <span class="n">message</span> <span class="n">that</span> <span class="n">will</span> <span class="n">be</span> <span class="n">sent</span> <span class="n">to</span> <span class="n">the</span> <span class="n">room</span> <span class="n">where</span> <span class="n">the</span>
<span class="n">character</span> <span class="n">came</span> <span class="n">from</span><span class="p">,</span> <span class="n">change</span> <span class="n">the</span> <span class="n">value</span> <span class="n">of</span> <span class="n">the</span> <span class="n">variable</span> <span class="s2">&quot;message&quot;</span>
<span class="n">to</span> <span class="n">give</span> <span class="n">it</span> <span class="n">your</span> <span class="n">custom</span> <span class="n">message</span><span class="o">.</span> <span class="n">The</span> <span class="n">character</span> <span class="n">itself</span> <span class="n">will</span> <span class="ow">not</span> <span class="n">be</span>
<span class="n">notified</span><span class="o">.</span> <span class="n">You</span> <span class="n">can</span> <span class="n">use</span> <span class="n">mapping</span> <span class="n">between</span> <span class="n">braces</span><span class="p">,</span> <span class="n">like</span> <span class="n">this</span><span class="p">:</span>
<span class="n">message</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="si">{character}</span><span class="s2"> falls into a hole!&quot;</span>
<span class="n">In</span> <span class="n">your</span> <span class="n">mapping</span><span class="p">,</span> <span class="n">you</span> <span class="n">can</span> <span class="n">use</span> <span class="p">{</span><span class="n">character</span><span class="p">}</span> <span class="p">(</span><span class="n">the</span> <span class="n">character</span> <span class="n">who</span> <span class="ow">is</span>
<span class="n">about</span> <span class="n">to</span> <span class="n">leave</span><span class="p">),</span> <span class="p">{</span><span class="n">exit</span><span class="p">}</span> <span class="p">(</span><span class="n">the</span> <span class="n">exit</span><span class="p">),</span> <span class="p">{</span><span class="n">origin</span><span class="p">}</span> <span class="p">(</span><span class="n">the</span> <span class="n">room</span> <span class="ow">in</span> <span class="n">which</span>
<span class="n">the</span> <span class="n">character</span> <span class="ow">is</span><span class="p">),</span> <span class="ow">and</span> <span class="p">{</span><span class="n">destination</span><span class="p">}</span> <span class="p">(</span><span class="n">the</span> <span class="n">room</span> <span class="ow">in</span> <span class="n">which</span> <span class="n">the</span> <span class="n">character</span>
<span class="ow">is</span> <span class="n">heading</span> <span class="k">for</span><span class="p">)</span><span class="o">.</span> <span class="n">If</span> <span class="n">you</span> <span class="n">need</span> <span class="n">to</span> <span class="n">customize</span> <span class="n">the</span> <span class="n">message</span> <span class="k">with</span> <span class="n">other</span>
<span class="n">information</span><span class="p">,</span> <span class="n">you</span> <span class="n">can</span> <span class="n">also</span> <span class="nb">set</span> <span class="s2">&quot;message&quot;</span> <span class="n">to</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">send</span> <span class="n">something</span>
<span class="k">else</span> <span class="n">instead</span><span class="o">.</span>
<span class="n">Variables</span> <span class="n">you</span> <span class="n">can</span> <span class="n">use</span> <span class="ow">in</span> <span class="n">this</span> <span class="n">event</span><span class="p">:</span>
<span class="n">character</span><span class="p">:</span> <span class="n">the</span> <span class="n">character</span> <span class="n">who</span> <span class="ow">is</span> <span class="n">leaving</span> <span class="n">through</span> <span class="n">this</span> <span class="n">exit</span><span class="o">.</span>
<span class="n">exit</span><span class="p">:</span> <span class="n">the</span> <span class="n">exit</span> <span class="n">being</span> <span class="n">traversed</span><span class="o">.</span>
<span class="n">origin</span><span class="p">:</span> <span class="n">the</span> <span class="n">location</span> <span class="n">of</span> <span class="n">the</span> <span class="n">character</span><span class="o">.</span>
<span class="n">destination</span><span class="p">:</span> <span class="n">the</span> <span class="n">destination</span> <span class="n">of</span> <span class="n">the</span> <span class="n">character</span><span class="o">.</span>
<span class="n">message</span><span class="p">:</span> <span class="n">the</span> <span class="n">message</span> <span class="n">to</span> <span class="n">be</span> <span class="n">displayed</span> <span class="ow">in</span> <span class="n">the</span> <span class="n">location</span><span class="o">.</span>
<span class="n">mapping</span><span class="p">:</span> <span class="n">a</span> <span class="n">dictionary</span> <span class="n">containing</span> <span class="n">additional</span> <span class="n">mapping</span><span class="o">.</span>
</pre></div>
</div>
<p>If you write something like this in your event:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">message</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="si">{character}</span><span class="s2"> falls into a hole in the ground!&quot;</span>
</pre></div>
</div>
<p>And if the character Wilfred takes this exit, others in the room will see:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Wildred falls into a hole in the ground!
</pre></div>
</div>
<p>In this case, the in-game Python system placed the variable “message” in the callback locals, but will read
from it when the event has been executed.</p>
</section>
<section id="callbacks-with-parameters">
<h3>Callbacks with parameters<a class="headerlink" href="#callbacks-with-parameters" title="Permalink to this headline"></a></h3>
<p>Some callbacks are called without parameter. It has been the case for all examples we have seen
before. In some cases, you can create callbacks that are triggered under only some conditions. A
typical example is the rooms “say” event. This event is triggered when somebody says something in
the room. Individual callbacks set on this event can be configured to fire only when some words are
used in the sentence.</p>
<p>For instance, lets say we want to create a cool voice-operated elevator. You enter into the
elevator and say the floor number… and the elevator moves in the right direction. In this case,
we could create an callback with the parameter “one”:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>call/add here = say one
</pre></div>
</div>
<p>This callback will only fire when the user says a sentence that contains “one”.</p>
<p>But what if we want to have a callback that would fire if the user says 1 or one? We can provide
several parameters, separated by a comma.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>call/add here = say 1, one
</pre></div>
</div>
<p>Or, still more keywords:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>call/add here = say 1, one, ground
</pre></div>
</div>
<p>This time, the user could say something like “take me to the ground floor” (“ground” is one of our
keywords defined in the above callback).</p>
<p>Not all events can take parameters, and these who do have different ways of handling them. There
isnt a single meaning to parameters that could apply to all events. Refer to the event
documentation for details.</p>
<blockquote>
<div><p>If you get confused between callback variables and parameters, think of parameters as checks
performed before the callback is run. Event with parameters will only fire some specific
callbacks, not all of them.</p>
</div></blockquote>
</section>
<section id="time-related-events">
<h3>Time-related events<a class="headerlink" href="#time-related-events" title="Permalink to this headline"></a></h3>
<p>Events are usually linked to commands, as we saw before. However, this is not always the case.
Events can be triggered by other actions and, as well see later, could even be called from inside
other events!</p>
<p>There is a specific event, on all objects, that can trigger at a specific time. Its an event with
a mandatory parameter, which is the time you expect this event to fire.</p>
<p>For instance, lets add an event on this room that should trigger every day, at precisely 12:00 PM
(the time is given as game time, not real time):</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>call here = time 12:00
</pre></div>
</div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># This will be called every MUD day at 12:00 PM</span>
<span class="n">room</span><span class="o">.</span><span class="n">msg_contents</span><span class="p">(</span><span class="s2">&quot;It&#39;s noon, time to have lunch!&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>Now, at noon every MUD day, this event will fire and this callback will be executed. You can use
this event on every kind of typeclassed object, to have a specific action done every MUD day at the
same time.</p>
<p>Time-related events can be much more complex than this. They can trigger every in-game hour or more
often (it might not be a good idea to have events trigger that often on a lot of objects). You can
have events that run every in-game week or month or year. It will greatly vary depending on the
type of calendar used in your game. The number of time units is described in the game
configuration.</p>
<p>With a standard calendar, for instance, you have the following units: minutes, hours, days, months
and years. You will specify them as numbers separated by either a colon (:), a space ( ), or a dash
(-). Pick whatever feels more appropriate (usually, we separate hours and minutes with a colon, the
other units with a dash).</p>
<p>Some examples of syntax:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">18:30</span></code>: every day at 6:30 PM.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">01</span> <span class="pre">12:00</span></code>: every month, the first day, at 12 PM.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">06-15</span> <span class="pre">09:58</span></code>: every year, on the 15th of June (month comes before day), at 9:58 AM.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">2025-01-01</span> <span class="pre">00:00</span></code>: January 1st, 2025 at midnight (obviously, this will trigger only once).</p></li>
</ul>
<p>Notice that we specify units in the reverse order (year, month, day, hour and minute) and separate
them with logical separators. The smallest unit that is not defined is going to set how often the
event should fire. Thats why, if you use <code class="docutils literal notranslate"><span class="pre">12:00</span></code>, the smallest unit that is not defined is “day”:
the event will fire every day at the specified time.</p>
<blockquote>
<div><p>You can use chained events (see below) in conjunction with time-related events to create more
random or frequent actions in events.</p>
</div></blockquote>
</section>
<section id="chained-events">
<h3>Chained events<a class="headerlink" href="#chained-events" title="Permalink to this headline"></a></h3>
<p>Callbacks can call other events, either now or a bit later. It is potentially very powerful.</p>
<p>To use chained events, just use the <code class="docutils literal notranslate"><span class="pre">call_event</span></code> eventfunc. It takes 2-3 arguments:</p>
<ul class="simple">
<li><p>The object containing the event.</p></li>
<li><p>The name of the event to call.</p></li>
<li><p>Optionally, the number of seconds to wait before calling this event.</p></li>
</ul>
<p>All objects have events that are not triggered by commands or game-related operations. They are
called “chain_X”, like “chain_1”, “chain_2”, “chain_3” and so on. You can give them more specific
names, as long as it begins by “chain_”, like “chain_flood_room”.</p>
<p>Rather than a long explanation, lets look at an example: a subway that will go from one place to
the next at regular times. Connecting exits (opening its doors), waiting a bit, closing them,
rolling around and stopping at a different station. Thats quite a complex set of callbacks, as it
is, but lets only look at the part that opens and closes the doors:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>call/add here = time 10:00
</pre></div>
</div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># At 10:00 AM, the subway arrives in the room of ID 22.</span>
<span class="c1"># Notice that exit #23 and #24 are respectively the exit leading</span>
<span class="c1"># on the platform and back in the subway.</span>
<span class="n">station</span> <span class="o">=</span> <span class="n">get</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="mi">22</span><span class="p">)</span>
<span class="n">to_exit</span> <span class="o">=</span> <span class="n">get</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="mi">23</span><span class="p">)</span>
<span class="n">back_exit</span> <span class="o">=</span> <span class="n">get</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="mi">24</span><span class="p">)</span>
<span class="c1"># Open the door</span>
<span class="n">to_exit</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="s2">&quot;platform&quot;</span>
<span class="n">to_exit</span><span class="o">.</span><span class="n">aliases</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;p&quot;</span><span class="p">]</span>
<span class="n">to_exit</span><span class="o">.</span><span class="n">location</span> <span class="o">=</span> <span class="n">room</span>
<span class="n">to_exit</span><span class="o">.</span><span class="n">destination</span> <span class="o">=</span> <span class="n">station</span>
<span class="n">back_exit</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="s2">&quot;subway&quot;</span>
<span class="n">back_exit</span><span class="o">.</span><span class="n">location</span> <span class="o">=</span> <span class="n">station</span>
<span class="n">back_exit</span><span class="o">.</span><span class="n">destination</span> <span class="o">=</span> <span class="n">room</span>
<span class="c1"># Display some messages</span>
<span class="n">room</span><span class="o">.</span><span class="n">msg_contents</span><span class="p">(</span><span class="s2">&quot;The doors open and wind gushes in the subway&quot;</span><span class="p">)</span>
<span class="n">station</span><span class="o">.</span><span class="n">msg_contents</span><span class="p">(</span><span class="s2">&quot;The doors of the subway open with a dull clank.&quot;</span><span class="p">)</span>
<span class="c1"># Set the doors to close in 20 seconds</span>
<span class="n">call_event</span><span class="p">(</span><span class="n">room</span><span class="p">,</span> <span class="s2">&quot;chain_1&quot;</span><span class="p">,</span> <span class="mi">20</span><span class="p">)</span>
</pre></div>
</div>
<p>This callback will:</p>
<ol class="simple">
<li><p>Be called at 10:00 AM (specify 22:00 to set it to 10:00 PM).</p></li>
<li><p>Set an exit between the subway and the station. Notice that the exits already exist (you will
not have to create them), but they dont need to have specific location and destination.</p></li>
<li><p>Display a message both in the subway and on the platform.</p></li>
<li><p>Call the event “chain_1” to execute in 20 seconds.</p></li>
</ol>
<p>And now, what should we have in “chain_1”?</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>call/add here = chain_1
</pre></div>
</div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># Close the doors</span>
<span class="n">to_exit</span><span class="o">.</span><span class="n">location</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">to_exit</span><span class="o">.</span><span class="n">destination</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">back_exit</span><span class="o">.</span><span class="n">location</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">back_exit</span><span class="o">.</span><span class="n">destination</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">room</span><span class="o">.</span><span class="n">msg_content</span><span class="p">(</span><span class="s2">&quot;After a short warning signal, the doors close and the subway begins moving.&quot;</span><span class="p">)</span>
<span class="n">station</span><span class="o">.</span><span class="n">msg_content</span><span class="p">(</span><span class="s2">&quot;After a short warning signal, the doors close and the subway begins moving.&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>Behind the scenes, the <code class="docutils literal notranslate"><span class="pre">call_event</span></code> function freezes all variables (“room”, “station”, “to_exit”,
“back_exit” in our example), so you dont need to define them again.</p>
<p>A word of caution on callbacks that call chained events: it isnt impossible for a callback to call
itself at some recursion level. If <code class="docutils literal notranslate"><span class="pre">chain_1</span></code> calls <code class="docutils literal notranslate"><span class="pre">chain_2</span></code> that calls <code class="docutils literal notranslate"><span class="pre">chain_3</span></code> that calls
<code class="docutils literal notranslate"><span class="pre">chain_</span></code>, particularly if theres no pause between them, you might run into an infinite loop.</p>
<p>Be also careful when it comes to handling characters or objects that may very well move during your
pause between event calls. When you use <code class="docutils literal notranslate"><span class="pre">call_event()</span></code>, the MUD doesnt pause and commands can be
entered by players, fortunately. It also means that, a character could start an event that pauses
for awhile, but be gone when the chained event is called. You need to check that, even lock the
character into place while you are pausing (some actions should require locking) or at least,
checking that the character is still in the room, for it might create illogical situations if you
dont.</p>
<blockquote>
<div><p>Chained events are a special case: contrary to standard events, they are created in-game, not
through code. They usually contain only one callback, although nothing prevents you from creating
several chained events in the same object.</p>
</div></blockquote>
</section>
</section>
<section id="using-events-in-code">
<h2>Using events in code<a class="headerlink" href="#using-events-in-code" title="Permalink to this headline"></a></h2>
<p>This section describes callbacks and events from code, how to create new events, how to call them in
a command, and how to handle specific cases like parameters.</p>
<p>Along this section, we will see how to implement the following example: we would like to create a
“push” command that could be used to push objects. Objects could react to this command and have
specific events fired.</p>
<section id="adding-new-events">
<h3>Adding new events<a class="headerlink" href="#adding-new-events" title="Permalink to this headline"></a></h3>
<p>Adding new events should be done in your typeclasses. Events are contained in the <code class="docutils literal notranslate"><span class="pre">_events</span></code> class
variable, a dictionary of event names as keys, and tuples to describe these events as values. You
also need to register this class, to tell the in-game Python system that it contains events to be added to
this typeclass.</p>
<p>Here, we want to add a “push” event on objects. In your <code class="docutils literal notranslate"><span class="pre">typeclasses/objects.py</span></code> file, you should
write something like:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.contrib.base_systems.ingame_python.utils</span> <span class="kn">import</span> <span class="n">register_events</span>
<span class="kn">from</span> <span class="nn">evennia.contrib.base_systems.ingame_python.typeclasses</span> <span class="kn">import</span> <span class="n">EventObject</span>
<span class="n">EVENT_PUSH</span> <span class="o">=</span> <span class="s2">&quot;&quot;&quot;</span>
<span class="s2">A character push the object.</span>
<span class="s2">This event is called when a character uses the &quot;push&quot; command on</span>
<span class="s2">an object in the same room.</span>
<span class="s2">Variables you can use in this event:</span>
<span class="s2"> character: the character that pushes this object.</span>
<span class="s2"> obj: the object connected to this event.</span>
<span class="s2">&quot;&quot;&quot;</span>
<span class="nd">@register_events</span>
<span class="k">class</span> <span class="nc">Object</span><span class="p">(</span><span class="n">EventObject</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Class representing objects.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">_events</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">&quot;push&quot;</span><span class="p">:</span> <span class="p">([</span><span class="s2">&quot;character&quot;</span><span class="p">,</span> <span class="s2">&quot;obj&quot;</span><span class="p">],</span> <span class="n">EVENT_PUSH</span><span class="p">),</span>
<span class="p">}</span>
</pre></div>
</div>
<ul class="simple">
<li><p>Line 1-2: we import several things we will need from the in-game Python system. Note that we use
<code class="docutils literal notranslate"><span class="pre">EventObject</span></code> as a parent instead of <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code>, as explained in the installation.</p></li>
<li><p>Line 4-12: we usually define the help of the event in a separate variable, this is more readable,
though theres no rule against doing it another way. Usually, the help should contain a short
explanation on a single line, a longer explanation on several lines, and then the list of variables
with explanations.</p></li>
<li><p>Line 14: we call a decorator on the class to indicate it contains events. If youre not familiar
with decorators, you dont really have to worry about it, just remember to put this line just
above the class definition if your class contains events.</p></li>
<li><p>Line 15: we create the class inheriting from <code class="docutils literal notranslate"><span class="pre">EventObject</span></code>.</p></li>
<li><p>Line 20-22: we define the events of our objects in an <code class="docutils literal notranslate"><span class="pre">_events</span></code> class variable. It is a
dictionary. Keys are event names. Values are a tuple containing:</p>
<ul>
<li><p>The list of variable names (list of str). This will determine what variables are needed when
the event triggers. These variables will be used in callbacks (as well see below).</p></li>
<li><p>The event help (a str, the one we have defined above).</p></li>
</ul>
</li>
</ul>
<p>If you add this code and reload your game, create an object and examine its events with <code class="docutils literal notranslate"><span class="pre">&#64;call</span></code>, you
should see the “push” event with its help. Of course, right now, the event exists, but its not
fired.</p>
</section>
<section id="calling-an-event-in-code">
<h3>Calling an event in code<a class="headerlink" href="#calling-an-event-in-code" title="Permalink to this headline"></a></h3>
<p>The in-game Python system is accessible through a handler on all objects. This handler is named <code class="docutils literal notranslate"><span class="pre">callbacks</span></code>
and can be accessed from any typeclassed object (your character, a room, an exit…). This handler
offers several methods to examine and call an event or callback on this object.</p>
<p>To call an event, use the <code class="docutils literal notranslate"><span class="pre">callbacks.call</span></code> method in an object. It takes as argument:</p>
<ul class="simple">
<li><p>The name of the event to call.</p></li>
<li><p>All variables that will be accessible in the event as positional arguments. They should be
specified in the order chosen when <a class="reference internal" href="#adding-new-events"><span class="std std-doc">creating new events</span></a>.</p></li>
</ul>
<p>Following the same example, so far, we have created an event on all objects, called “push”. This
event is never fired for the time being. We could add a “push” command, taking as argument the name
of an object. If this object is valid, it will call its “push” event.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">commands.command</span> <span class="kn">import</span> <span class="n">Command</span>
<span class="k">class</span> <span class="nc">CmdPush</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Push something.</span>
<span class="sd"> Usage:</span>
<span class="sd"> push &lt;something&gt;</span>
<span class="sd"> Push something where you are, like an elevator button.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;push&quot;</span>
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Called when pushing something.&quot;&quot;&quot;</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">strip</span><span class="p">():</span>
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;Usage: push &lt;something&gt;&quot;</span><span class="p">)</span>
<span class="k">return</span>
<span class="c1"># Search for this object</span>
<span class="n">obj</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">obj</span><span class="p">:</span>
<span class="k">return</span>
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;You push </span><span class="si">{}</span><span class="s2">.&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">get_display_name</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="p">)))</span>
<span class="c1"># Call the &quot;push&quot; event of this object</span>
<span class="n">obj</span><span class="o">.</span><span class="n">callbacks</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="s2">&quot;push&quot;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="p">,</span> <span class="n">obj</span><span class="p">)</span>
</pre></div>
</div>
<p>Here we use <code class="docutils literal notranslate"><span class="pre">callbacks.call</span></code> with the following arguments:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">&quot;push&quot;</span></code>: the name of the event to be called.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">self.caller</span></code>: the one who pushed the button (this is our first variable, <code class="docutils literal notranslate"><span class="pre">character</span></code>).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">obj</span></code>: the object being pushed (our second variable, <code class="docutils literal notranslate"><span class="pre">obj</span></code>).</p></li>
</ul>
<p>In the “push” callbacks of our objects, we then can use the “character” variable (containing the one
who pushed the object), and the “obj” variable (containing the object that was pushed).</p>
</section>
<section id="see-it-all-work">
<h3>See it all work<a class="headerlink" href="#see-it-all-work" title="Permalink to this headline"></a></h3>
<p>To see the effect of the two modifications above (the added event and the “push” command), let us
create a simple object:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>@create/drop rock
@desc rock = It&#39;s a single rock, apparently pretty heavy. Perhaps you can try to push it though.
@call/add rock = push
</pre></div>
</div>
<p>In the callback you could write:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">random</span> <span class="kn">import</span> <span class="n">randint</span>
<span class="n">number</span> <span class="o">=</span> <span class="n">randint</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">)</span>
<span class="n">character</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;You push a rock... is... it... going... to... move?&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">number</span> <span class="o">==</span> <span class="mi">6</span><span class="p">:</span>
<span class="n">character</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;The rock topples over to reveal a beautiful ant-hill!&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>You can now try to “push rock”. Youll try to push the rock, and once out of six times, you will
see a message about a “beautiful ant-hill”.</p>
</section>
<section id="adding-new-eventfuncs">
<h3>Adding new eventfuncs<a class="headerlink" href="#adding-new-eventfuncs" title="Permalink to this headline"></a></h3>
<p>Eventfuncs, like <code class="docutils literal notranslate"><span class="pre">deny()</span></code>, are defined in
<code class="docutils literal notranslate"><span class="pre">contrib/base_systesm/ingame_python/eventfuncs.py</span></code>. You can add your own
eventfuncs by creating a file named <code class="docutils literal notranslate"><span class="pre">eventfuncs.py</span></code> in your <code class="docutils literal notranslate"><span class="pre">world</span></code> directory.
The functions defined in this file will be added as helpers.</p>
<p>You can also decide to create your eventfuncs in another location, or even in
several locations. To do so, edit the <code class="docutils literal notranslate"><span class="pre">EVENTFUNCS_LOCATION</span></code> setting in your
<code class="docutils literal notranslate"><span class="pre">server/conf/settings.py</span></code> file, specifying either a python path or a list of
Python paths in which your helper functions are defined. For instance:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">EVENTFUNCS_LOCATIONS</span> <span class="o">=</span> <span class="p">[</span>
<span class="s2">&quot;world.events.functions&quot;</span><span class="p">,</span>
<span class="p">]</span>
</pre></div>
</div>
</section>
<section id="creating-events-with-parameters">
<h3>Creating events with parameters<a class="headerlink" href="#creating-events-with-parameters" title="Permalink to this headline"></a></h3>
<p>If you want to create events with parameters (if you create a “whisper” or “ask” command, for
instance, and need to have some characters automatically react to words), you can set an additional
argument in the tuple of events in your typeclass <code class="docutils literal notranslate"><span class="pre">_events</span></code> class variable. This third argument
must contain a callback that will be called to filter through the list of callbacks when the event
fires. Two types of parameters are commonly used (but you can define more parameter types, although
this is out of the scope of this documentation).</p>
<ul class="simple">
<li><p>Keyword parameters: callbacks of this event will be filtered based on specific keywords. This is
useful if you want the user to specify a word and compare this word to a list.</p></li>
<li><p>Phrase parameters: callbacks will be filtered using an entire phrase and checking all its words.
The “say” command uses phrase parameters (you can set a “say” callback to fires if a phrase
contains one specific word).</p></li>
</ul>
<p>In both cases, you need to import a function from
<code class="docutils literal notranslate"><span class="pre">evennia.contrib.base_systems.ingame_python.utils</span></code> and use it as third parameter in your
event definition.</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">keyword_event</span></code> should be used for keyword parameters.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">phrase_event</span></code> should be used for phrase parameters.</p></li>
</ul>
<p>For example, here is the definition of the “say” event:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.contrib.base_systems.ingame_python.utils</span> <span class="kn">import</span> <span class="n">register_events</span><span class="p">,</span> <span class="n">phrase_event</span>
<span class="c1"># ...</span>
<span class="nd">@register_events</span>
<span class="k">class</span> <span class="nc">SomeTypeclass</span><span class="p">:</span>
<span class="n">_events</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">&quot;say&quot;</span><span class="p">:</span> <span class="p">([</span><span class="s2">&quot;speaker&quot;</span><span class="p">,</span> <span class="s2">&quot;character&quot;</span><span class="p">,</span> <span class="s2">&quot;message&quot;</span><span class="p">],</span> <span class="n">CHARACTER_SAY</span><span class="p">,</span> <span class="n">phrase_event</span><span class="p">),</span>
<span class="p">}</span>
</pre></div>
</div>
<p>When you call an event using the <code class="docutils literal notranslate"><span class="pre">obj.callbacks.call</span></code> method, you should also provide the parameter,
using the <code class="docutils literal notranslate"><span class="pre">parameters</span></code> keyword:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">obj</span><span class="o">.</span><span class="n">callbacks</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="o">...</span><span class="p">,</span> <span class="n">parameters</span><span class="o">=</span><span class="s2">&quot;&lt;put parameters here&gt;&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>It is necessary to specifically call the event with parameters, otherwise the system will not be
able to know how to filter down the list of callbacks.</p>
</section>
</section>
<section id="disabling-all-events-at-once">
<h2>Disabling all events at once<a class="headerlink" href="#disabling-all-events-at-once" title="Permalink to this headline"></a></h2>
<p>When callbacks are running in an infinite loop, for instance, or sending unwanted information to
players or other sources, you, as the game administrator, have the power to restart without events.
The best way to do this is to use a custom setting, in your setting file
(<code class="docutils literal notranslate"><span class="pre">server/conf/settings.py</span></code>):</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># Disable all events</span>
<span class="n">EVENTS_DISABLED</span> <span class="o">=</span> <span class="kc">True</span>
</pre></div>
</div>
<p>The in-game Python system will still be accessible (you will have access to the <code class="docutils literal notranslate"><span class="pre">call</span></code> command, to debug),
but no event will be called automatically.</p>
<div class="toctree-wrapper compound">
</div>
<hr class="docutils" />
<p><small>This document page is generated from <code class="docutils literal notranslate"><span class="pre">evennia/contrib/base_systems/ingame_python/README.md</span></code>. Changes to this
file will be overwritten, so edit that file rather than this one.</small></p>
</section>
</section>
</div>
</div>
</div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="Contrib-Ingame-Python-Tutorial-Dialogue.html" title="Dialogues in events"
>next</a> |</li>
<li class="right" >
<a href="Contrib-Email-Login.html" title="Email-based login system"
>previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="Contribs-Overview.html" >Contribs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Evennia in-game Python system</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2022, The Evennia developer community.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
</div>
</body>
</html>