evennia/docs/6.x/Components/Signals.html
2026-02-15 19:06:04 +01:00

283 lines
No EOL
20 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 lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Signals &#8212; Evennia latest documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=d75fae25" />
<link rel="stylesheet" type="text/css" href="../_static/nature.css?v=279e0f84" />
<link rel="stylesheet" type="text/css" href="../_static/custom.css?v=e4a91a55" />
<script src="../_static/documentation_options.js?v=c6e86fd7"></script>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<link rel="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="Game website" href="Website.html" />
<link rel="prev" title="TickerHandler" href="TickerHandler.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<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="Website.html" title="Game website"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="TickerHandler.html" title="TickerHandler"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Evennia</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="Components-Overview.html" accesskey="U">Core Components</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Signals</a></li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section class="tex2jax_ignore mathjax_ignore" id="signals">
<h1>Signals<a class="headerlink" href="#signals" title="Link to this heading"></a></h1>
<p><em>This is feature available from evennia 0.9 and onward</em>.</p>
<p>There are multiple ways for you to plug in your own functionality into Evennia.
The most common way to do so is through <em>hooks</em> - methods on typeclasses that
gets called at particular events. Hooks are great when you want a game entity
to behave a certain way when something happens to it. <em>Signals</em> complements
hooks for cases when you want to easily attach new functionality without
overriding things on the typeclass.</p>
<p>When certain events happen in Evennia, a <em>Signal</em> is fired. The idea is that
you can “attach” any number of event-handlers to these signals. You can attach
any number of handlers and theyll all fire whenever any entity triggers the
signal.</p>
<p>Evennia uses the <a class="reference external" href="https://docs.djangoproject.com/en/4.1/topics/signals/">Django Signal system</a>.</p>
<section id="working-with-signals">
<h2>Working with Signals<a class="headerlink" href="#working-with-signals" title="Link to this heading"></a></h2>
<p>First you create your handler</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
<span class="k">def</span><span class="w"> </span><span class="nf">myhandler</span><span class="p">(</span><span class="n">sender</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="c1"># do stuff</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> is mandatory. Then you attach it to the signal of your choice:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">evennia.server</span><span class="w"> </span><span class="kn">import</span> <span class="n">signals</span>
<span class="n">signals</span><span class="o">.</span><span class="n">SIGNAL_OBJECT_POST_CREATE</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">myhandler</span><span class="p">)</span>
</pre></div>
</div>
<p>This particular signal fires after (post) an Account has connected to the game.
When that happens, <code class="docutils literal notranslate"><span class="pre">myhandler</span></code> will fire with the <code class="docutils literal notranslate"><span class="pre">sender</span></code> being the Account that just connected.</p>
<p>If you want to respond only to the effects of a specific entity you can do so
like this:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">evennia</span><span class="w"> </span><span class="kn">import</span> <span class="n">search_account</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">evennia</span><span class="w"> </span><span class="kn">import</span> <span class="n">signals</span>
<span class="n">account</span> <span class="o">=</span> <span class="n">search_account</span><span class="p">(</span><span class="s2">&quot;foo&quot;</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">signals</span><span class="o">.</span><span class="n">SIGNAL_ACCOUNT_POST_CONNECT</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">myhandler</span><span class="p">,</span> <span class="n">account</span><span class="p">)</span>
</pre></div>
</div>
<section id="available-signals">
<h3>Available signals<a class="headerlink" href="#available-signals" title="Link to this heading"></a></h3>
<p>All signals (including some django-specific defaults) are available in the module
<code class="docutils literal notranslate"><span class="pre">evennia.server.signals</span></code>
(with a shortcut <code class="docutils literal notranslate"><span class="pre">evennia.signals</span></code>). Signals are named by the sender type. So <code class="docutils literal notranslate"><span class="pre">SIGNAL_ACCOUNT_*</span></code>
returns
<code class="docutils literal notranslate"><span class="pre">Account</span></code> instances as senders, <code class="docutils literal notranslate"><span class="pre">SIGNAL_OBJECT_*</span></code> returns <code class="docutils literal notranslate"><span class="pre">Object</span></code>s etc. Extra keywords (kwargs)
should
be extracted from the <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> dict in the signal handler.</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_ACCOUNT_POST_CREATE</span></code> - this is triggered at the very end of <code class="docutils literal notranslate"><span class="pre">Account.create()</span></code>. Note that
calling <code class="docutils literal notranslate"><span class="pre">evennia.create.create_account</span></code> (which is called internally by <code class="docutils literal notranslate"><span class="pre">Account.create</span></code>) will
<em>not</em>
trigger this signal. This is because using <code class="docutils literal notranslate"><span class="pre">Account.create()</span></code> is expected to be the most commonly
used way for users to themselves create accounts during login. It passes and extra kwarg <code class="docutils literal notranslate"><span class="pre">ip</span></code> with
the client IP of the connecting account.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_ACCOUNT_POST_LOGIN</span></code> - this will always fire when the account has authenticated. Sends
extra kwarg <code class="docutils literal notranslate"><span class="pre">session</span></code> with the new <a class="reference internal" href="Sessions.html"><span class="std std-doc">Session</span></a> object involved.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_ACCCOUNT_POST_FIRST_LOGIN</span></code> - this fires just before <code class="docutils literal notranslate"><span class="pre">SIGNAL_ACCOUNT_POST_LOGIN</span></code> but only
if
this is the <em>first</em> connection done (that is, if there are no previous sessions connected). Also
passes the <code class="docutils literal notranslate"><span class="pre">session</span></code> along as a kwarg.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_ACCOUNT_POST_LOGIN_FAIL</span></code> - sent when someone tried to log into an account by failed.
Passes
the <code class="docutils literal notranslate"><span class="pre">session</span></code> as an extra kwarg.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_ACCOUNT_POST_LOGOUT</span></code> - always fires when an account logs off, no matter if other sessions
remain or not. Passes the disconnecting <code class="docutils literal notranslate"><span class="pre">session</span></code> along as a kwarg.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_ACCOUNT_POST_LAST_LOGOUT</span></code> - fires before <code class="docutils literal notranslate"><span class="pre">SIGNAL_ACCOUNT_POST_LOGOUT</span></code>, but only if this is
the <em>last</em> Session to disconnect for that account. Passes the <code class="docutils literal notranslate"><span class="pre">session</span></code> as a kwarg.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_OBJECT_POST_PUPPET</span></code> - fires when an account puppets this object. Extra kwargs <code class="docutils literal notranslate"><span class="pre">session</span></code>
and <code class="docutils literal notranslate"><span class="pre">account</span></code> represent the puppeting entities.
<code class="docutils literal notranslate"><span class="pre">SIGNAL_OBJECT_POST_UNPUPPET</span></code> - fires when the sending object is unpuppeted. Extra kwargs are
<code class="docutils literal notranslate"><span class="pre">session</span></code> and <code class="docutils literal notranslate"><span class="pre">account</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_ACCOUNT_POST_RENAME</span></code> - triggered by the setting of <code class="docutils literal notranslate"><span class="pre">Account.username</span></code>. Passes extra
kwargs <code class="docutils literal notranslate"><span class="pre">old_name</span></code>, <code class="docutils literal notranslate"><span class="pre">new_name</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_TYPED_OBJECT_POST_RENAME</span></code> - triggered when any Typeclassed entitys <code class="docutils literal notranslate"><span class="pre">key</span></code> is changed.
Extra
kwargs passed are <code class="docutils literal notranslate"><span class="pre">old_key</span></code> and <code class="docutils literal notranslate"><span class="pre">new_key</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_SCRIPT_POST_CREATE</span></code> - fires when a script is first created, after any hooks.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_CHANNEL_POST_CREATE</span></code> - fires when a Channel is first created, after any hooks.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_HELPENTRY_POST_CREATE</span></code> - fires when a help entry is first created.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">SIGNAL_EXIT_TRAVERSED</span></code> - fires when an exit is traversed, just after <code class="docutils literal notranslate"><span class="pre">at_traverse</span></code> hook. The <code class="docutils literal notranslate"><span class="pre">sender</span></code> is the exit itself, <code class="docutils literal notranslate"><span class="pre">traverser=</span></code> keyword hold the one traversing the exit.</p></li>
</ul>
<p>The <code class="docutils literal notranslate"><span class="pre">evennia.signals</span></code> module also gives you conveneient access to the default Django signals (these
use a
different naming convention).</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">pre_save</span></code> - fired when any database entitiys <code class="docutils literal notranslate"><span class="pre">.save</span></code> method fires, before any saving has
happened.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">post_save</span></code> - fires after saving a database entity.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">pre_delete</span></code> - fires just before a database entity is deleted.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">post_delete</span></code> - fires after a database entity was deleted.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">pre_init</span></code> - fires before a typeclass <code class="docutils literal notranslate"><span class="pre">__init__</span></code> method (which in turn
happens before the <code class="docutils literal notranslate"><span class="pre">at_init</span></code> hook fires).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">post_init</span></code> - triggers at the end of <code class="docutils literal notranslate"><span class="pre">__init__</span></code> (still before the <code class="docutils literal notranslate"><span class="pre">at_init</span></code> hook).</p></li>
</ul>
<p>These are highly specialized Django signals that are unlikely to be useful to most users. But
they are included here for completeness.</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">m2m_changed</span></code> - fires after a Many-to-Many field (like <code class="docutils literal notranslate"><span class="pre">db_attributes</span></code>) changes.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">pre_migrate</span></code> - fires before database migration starts with <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">migrate</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">post_migrate</span></code> - fires after database migration finished.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">request_started</span></code> - sent when HTTP request begins.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">request_finished</span></code> - sent when HTTP request ends.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">settings_changed</span></code> - sent when changing settings due to <code class="docutils literal notranslate"><span class="pre">&#64;override_settings</span></code>
decorator (only relevant for unit testing)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">template_rendered</span></code> - sent when test system renders http template (only useful for unit tests).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">connection_creation</span></code> - sent when making initial connection to database.</p></li>
</ul>
</section>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/evennia_logo.png" alt="Logo of Evennia"/>
</a></p>
<search 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" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script>
<h3><a href="../index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Signals</a><ul>
<li><a class="reference internal" href="#working-with-signals">Working with Signals</a><ul>
<li><a class="reference internal" href="#available-signals">Available signals</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="TickerHandler.html"
title="previous chapter">TickerHandler</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="Website.html"
title="next chapter">Game website</a></p>
</div>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="../_sources/Components/Signals.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div><h3>Links</h3>
<ul>
<li><a href="https://www.evennia.com/docs/latest/index.html">Documentation Top</a> </li>
<li><a href="https://www.evennia.com">Evennia Home</a> </li>
<li><a href="https://github.com/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>Doc Versions</h3>
<ul>
<li>
<a href="https://www.evennia.com/docs/latest/index.html">latest (main branch)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/5.x/index.html">v5.0.0 branch (outdated)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/4.x/index.html">v4.0.0 branch (outdated)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/3.x/index.html">v3.0.0 branch (outdated)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/2.x/index.html">v2.0.0 branch (outdated)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/1.x/index.html">v1.0.0 branch (outdated)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/0.x/index.html">v0.9.5 branch (outdated)</a>
</li>
</ul>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="Related">
<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="Website.html" title="Game website"
>next</a> |</li>
<li class="right" >
<a href="TickerHandler.html" title="TickerHandler"
>previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Evennia</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="Components-Overview.html" >Core Components</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Signals</a></li>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2024, The Evennia developer community.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.2.3.
</div>
</body>
</html>