evennia/docs/latest/_modules/evennia/scripts/scripts.html
Evennia docbuilder action ce899c6430 Updated HTML docs.
2024-08-11 18:07:20 +00:00

1040 lines
No EOL
98 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>evennia.scripts.scripts &#8212; Evennia latest documentation</title>
<link rel="stylesheet" href="../../../_static/nature.css" type="text/css" />
<link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
<script id="documentation_options" data-url_root="../../../" src="../../../_static/documentation_options.js"></script>
<script src="../../../_static/jquery.js"></script>
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
</head><body>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../../../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../../../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="nav-item nav-item-0"><a href="../../../index.html">Evennia latest</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="../../index.html" >Module code</a> &#187;</li>
<li class="nav-item nav-item-2"><a href="../../evennia.html" accesskey="U">evennia</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">evennia.scripts.scripts</a></li>
</ul>
</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>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="scripts.html">latest (main branch)</a></li>
<li><a href="../4.x/index.html">v4.0.0 branch (outdated)</a></li>
<li><a href="../3.x/index.html">v3.0.0 branch (outdated)</a></li>
<li><a href="../2.x/index.html">v2.0.0 branch (outdated)</a></li>
<li><a href="../1.x/index.html">v1.0.0 branch (outdated)</a></li>
<li><a href="../0.x/index.html">v0.9.5 branch (outdated)</a></li>
</ul>
</div>
</div>
<div class="bodywrapper">
<div class="body" role="main">
<h1>Source code for evennia.scripts.scripts</h1><div class="highlight"><pre>
<span></span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">This module defines Scripts, out-of-character entities that can store</span>
<span class="sd">data both on themselves and on other objects while also having the</span>
<span class="sd">ability to run timers.</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">gettext</span> <span class="k">as</span> <span class="n">_</span>
<span class="kn">from</span> <span class="nn">evennia.scripts.manager</span> <span class="kn">import</span> <span class="n">ScriptManager</span>
<span class="kn">from</span> <span class="nn">evennia.scripts.models</span> <span class="kn">import</span> <span class="n">ScriptDB</span>
<span class="kn">from</span> <span class="nn">evennia.typeclasses.models</span> <span class="kn">import</span> <span class="n">TypeclassBase</span>
<span class="kn">from</span> <span class="nn">evennia.utils</span> <span class="kn">import</span> <span class="n">create</span><span class="p">,</span> <span class="n">logger</span>
<span class="kn">from</span> <span class="nn">twisted.internet.defer</span> <span class="kn">import</span> <span class="n">Deferred</span><span class="p">,</span> <span class="n">maybeDeferred</span>
<span class="kn">from</span> <span class="nn">twisted.internet.task</span> <span class="kn">import</span> <span class="n">LoopingCall</span>
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;DefaultScript&quot;</span><span class="p">,</span> <span class="s2">&quot;DoNothing&quot;</span><span class="p">,</span> <span class="s2">&quot;Store&quot;</span><span class="p">]</span>
<span class="k">class</span> <span class="nc">ExtendedLoopingCall</span><span class="p">(</span><span class="n">LoopingCall</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Custom child of LoopingCall that can start at a delay different than</span>
<span class="sd"> `self.interval` and self.count=0. This allows it to support pausing</span>
<span class="sd"> by resuming at a later period.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">start_delay</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">callcount</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">def</span> <span class="nf">start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">interval</span><span class="p">,</span> <span class="n">now</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">start_delay</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">count_start</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Start running function every interval seconds.</span>
<span class="sd"> This overloads the LoopingCall default by offering the</span>
<span class="sd"> start_delay keyword and ability to repeat.</span>
<span class="sd"> Args:</span>
<span class="sd"> interval (int): Repeat interval in seconds.</span>
<span class="sd"> now (bool, optional): Whether to start immediately or after</span>
<span class="sd"> `start_delay` seconds.</span>
<span class="sd"> start_delay (int, optional): This only applies is `now=False`. It gives</span>
<span class="sd"> number of seconds to wait before starting. If `None`, use</span>
<span class="sd"> `interval` as this value instead. Internally, this is used as a</span>
<span class="sd"> way to start with a variable start time after a pause.</span>
<span class="sd"> count_start (int): Number of repeats to start at. The count</span>
<span class="sd"> goes up every time the system repeats. This is used to</span>
<span class="sd"> implement something repeating `N` number of times etc.</span>
<span class="sd"> Raises:</span>
<span class="sd"> AssertError: if trying to start a task which is already running.</span>
<span class="sd"> ValueError: If interval is set to an invalid value &lt; 0.</span>
<span class="sd"> Notes:</span>
<span class="sd"> As opposed to Twisted&#39;s inbuilt count mechanism, this</span>
<span class="sd"> system will count also if force_repeat() was called rather</span>
<span class="sd"> than just the number of `interval` seconds since the start.</span>
<span class="sd"> This allows us to force-step through a limited number of</span>
<span class="sd"> steps if we want.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">assert</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">running</span><span class="p">,</span> <span class="s2">&quot;Tried to start an already running ExtendedLoopingCall.&quot;</span>
<span class="k">if</span> <span class="n">interval</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;interval must be &gt;= 0&quot;</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">running</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">deferred</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_deferred</span> <span class="o">=</span> <span class="n">Deferred</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">starttime</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">clock</span><span class="o">.</span><span class="n">seconds</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">interval</span> <span class="o">=</span> <span class="n">interval</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_runAtStart</span> <span class="o">=</span> <span class="n">now</span>
<span class="bp">self</span><span class="o">.</span><span class="n">callcount</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">count_start</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">start_delay</span> <span class="o">=</span> <span class="n">start_delay</span> <span class="k">if</span> <span class="n">start_delay</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="nb">max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">start_delay</span><span class="p">)</span>
<span class="k">if</span> <span class="n">now</span><span class="p">:</span>
<span class="c1"># run immediately</span>
<span class="bp">self</span><span class="p">()</span>
<span class="k">elif</span> <span class="n">start_delay</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">start_delay</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">:</span>
<span class="c1"># start after some time: for this to work we need to</span>
<span class="c1"># trick _scheduleFrom by temporarily setting a different</span>
<span class="c1"># self.interval for it to check.</span>
<span class="n">real_interval</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">interval</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">interval</span><span class="p">,</span> <span class="n">start_delay</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_scheduleFrom</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">starttime</span><span class="p">)</span>
<span class="c1"># re-set the actual interval (this will be picked up</span>
<span class="c1"># next time it runs</span>
<span class="bp">self</span><span class="o">.</span><span class="n">interval</span> <span class="o">=</span> <span class="n">real_interval</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_scheduleFrom</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">starttime</span><span class="p">)</span>
<span class="k">return</span> <span class="n">deferred</span>
<span class="k">def</span> <span class="fm">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Tick one step. We update callcount (tracks number of calls) as</span>
<span class="sd"> well as null start_delay (needed in order to correctly</span>
<span class="sd"> estimate next_call_time at all times).</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">callcount</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">start_delay</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">start_delay</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">starttime</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">clock</span><span class="o">.</span><span class="n">seconds</span><span class="p">()</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_deferred</span><span class="p">:</span>
<span class="n">LoopingCall</span><span class="o">.</span><span class="fm">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">force_repeat</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Force-fire the callback</span>
<span class="sd"> Raises:</span>
<span class="sd"> AssertionError: When trying to force a task that is not</span>
<span class="sd"> running.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">assert</span> <span class="bp">self</span><span class="o">.</span><span class="n">running</span><span class="p">,</span> <span class="s2">&quot;Tried to fire an ExtendedLoopingCall that was not running.&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">call</span><span class="o">.</span><span class="n">cancel</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">call</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">starttime</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">clock</span><span class="o">.</span><span class="n">seconds</span><span class="p">()</span>
<span class="bp">self</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">next_call_time</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Get the next call time. This also takes the eventual effect</span>
<span class="sd"> of start_delay into account.</span>
<span class="sd"> Returns:</span>
<span class="sd"> int or None: The time in seconds until the next call. This</span>
<span class="sd"> takes `start_delay` into account. Returns `None` if</span>
<span class="sd"> the task is not running.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">running</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">interval</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">total_runtime</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">clock</span><span class="o">.</span><span class="n">seconds</span><span class="p">()</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">starttime</span>
<span class="n">interval</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">start_delay</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">interval</span>
<span class="k">return</span> <span class="nb">max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">interval</span> <span class="o">-</span> <span class="p">(</span><span class="n">total_runtime</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">interval</span><span class="p">))</span>
<span class="k">class</span> <span class="nc">ScriptBase</span><span class="p">(</span><span class="n">ScriptDB</span><span class="p">,</span> <span class="n">metaclass</span><span class="o">=</span><span class="n">TypeclassBase</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Base class for scripts. Don&#39;t inherit from this, inherit from the</span>
<span class="sd"> class `DefaultScript` below instead.</span>
<span class="sd"> This handles the timer-component of the Script.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">objects</span> <span class="o">=</span> <span class="n">ScriptManager</span><span class="p">()</span>
<span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="s2">&quot;&lt;</span><span class="si">{cls}</span><span class="s2"> </span><span class="si">{key}</span><span class="s2">&gt;&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">cls</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="p">)</span>
<span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">at_idmapper_flush</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> If we&#39;re flushing this object, make sure the LoopingCall is gone too.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">ret</span> <span class="o">=</span> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">at_idmapper_flush</span><span class="p">()</span>
<span class="k">if</span> <span class="n">ret</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_task</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_pause_task</span><span class="p">(</span><span class="n">auto_pause</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="c1"># TODO - restart anew ?</span>
<span class="k">return</span> <span class="n">ret</span>
<span class="k">def</span> <span class="nf">_start_task</span><span class="p">(</span>
<span class="bp">self</span><span class="p">,</span>
<span class="n">interval</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">start_delay</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">repeats</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">force_restart</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">auto_unpause</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="o">**</span><span class="n">kwargs</span><span class="p">,</span>
<span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Start/Unpause task runner, optionally with new values. If given, this will</span>
<span class="sd"> update the Script&#39;s fields.</span>
<span class="sd"> Keyword Args:</span>
<span class="sd"> interval (int): How often to tick the task, in seconds. If this is &lt;= 0,</span>
<span class="sd"> no task will start and properties will not be updated on the Script.</span>
<span class="sd"> start_delay (int): If the start should be delayed.</span>
<span class="sd"> repeats (int): How many repeats. 0 for infinite repeats.</span>
<span class="sd"> force_restart (bool): If set, always create a new task running even if an</span>
<span class="sd"> old one already was running. Otherwise this will only happen if</span>
<span class="sd"> new script properties were passed.</span>
<span class="sd"> auto_unpause (bool): This is an automatic unpaused (used e.g by Evennia after</span>
<span class="sd"> a reload) and should not un-pause manually paused Script timers.</span>
<span class="sd"> Note:</span>
<span class="sd"> If setting the `start-delay` of a *paused* Script, the Script will</span>
<span class="sd"> restart exactly after that new start-delay, ignoring the time it</span>
<span class="sd"> was paused at. If only changing the `interval`, the Script will</span>
<span class="sd"> come out of pause comparing the time it spent in the *old* interval</span>
<span class="sd"> with the *new* interval in order to determine when next to fire.</span>
<span class="sd"> Examples:</span>
<span class="sd"> - Script previously had an interval of 10s and was paused 5s into that interval.</span>
<span class="sd"> Script is now restarted with a 20s interval. It will next fire after 15s.</span>
<span class="sd"> - Same Script is restarted with a 3s interval. It will fire immediately.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">pk</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="c1"># script object already deleted from db - don&#39;t start a new timer</span>
<span class="k">raise</span> <span class="n">ScriptDB</span><span class="o">.</span><span class="n">DoesNotExist</span>
<span class="c1"># handle setting/updating fields</span>
<span class="n">update_fields</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">old_interval</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">db_interval</span>
<span class="k">if</span> <span class="n">interval</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db_interval</span> <span class="o">=</span> <span class="n">interval</span>
<span class="n">update_fields</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;db_interval&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">start_delay</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="c1"># note that for historical reasons, the start_delay is a boolean field, not an int; the</span>
<span class="c1"># actual value is only used with the task.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db_start_delay</span> <span class="o">=</span> <span class="nb">bool</span><span class="p">(</span><span class="n">start_delay</span><span class="p">)</span>
<span class="n">update_fields</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;db_start_delay&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">repeats</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db_repeats</span> <span class="o">=</span> <span class="n">repeats</span>
<span class="n">update_fields</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;db_repeats&quot;</span><span class="p">)</span>
<span class="c1"># validate interval</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">db_interval</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">db_interval</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_active</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db_is_active</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">update_fields</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;db_is_active&quot;</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># no point in starting a task with no interval.</span>
<span class="k">return</span>
<span class="n">restart</span> <span class="o">=</span> <span class="nb">bool</span><span class="p">(</span><span class="n">update_fields</span><span class="p">)</span> <span class="ow">or</span> <span class="n">force_restart</span>
<span class="bp">self</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="n">update_fields</span><span class="o">=</span><span class="n">update_fields</span><span class="p">)</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_task</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_task</span><span class="o">.</span><span class="n">running</span><span class="p">:</span>
<span class="k">if</span> <span class="n">restart</span><span class="p">:</span>
<span class="c1"># a change needed/forced; stop/remove old task</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_stop_task</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># task alreaady running and no changes needed</span>
<span class="k">return</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_task</span><span class="p">:</span>
<span class="c1"># we should have a fresh task after this point</span>
<span class="bp">self</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_task</span> <span class="o">=</span> <span class="n">ExtendedLoopingCall</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_step_task</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_unpause_task</span><span class="p">(</span>
<span class="n">interval</span><span class="o">=</span><span class="n">interval</span><span class="p">,</span>
<span class="n">start_delay</span><span class="o">=</span><span class="n">start_delay</span><span class="p">,</span>
<span class="n">auto_unpause</span><span class="o">=</span><span class="n">auto_unpause</span><span class="p">,</span>
<span class="n">old_interval</span><span class="o">=</span><span class="n">old_interval</span><span class="p">,</span>
<span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_task</span><span class="o">.</span><span class="n">running</span><span class="p">:</span>
<span class="c1"># if not unpausing started it, start script anew with the new values</span>
<span class="bp">self</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_task</span><span class="o">.</span><span class="n">start</span><span class="p">(</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db_interval</span><span class="p">,</span> <span class="n">now</span><span class="o">=</span><span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">db_start_delay</span><span class="p">,</span> <span class="n">start_delay</span><span class="o">=</span><span class="n">start_delay</span>
<span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">at_start</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">_pause_task</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">auto_pause</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Pause task where it is, saving the current status.</span>
<span class="sd"> Args:</span>
<span class="sd"> auto_pause (str):</span>
<span class="sd"> &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">db</span><span class="o">.</span><span class="n">_paused_time</span><span class="p">:</span>
<span class="c1"># only allow pause if not already paused</span>
<span class="n">task</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_task</span>
<span class="k">if</span> <span class="n">task</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">_paused_time</span> <span class="o">=</span> <span class="n">task</span><span class="o">.</span><span class="n">next_call_time</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">_paused_callcount</span> <span class="o">=</span> <span class="n">task</span><span class="o">.</span><span class="n">callcount</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">_manually_paused</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">auto_pause</span>
<span class="k">if</span> <span class="n">task</span><span class="o">.</span><span class="n">running</span><span class="p">:</span>
<span class="n">task</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_task</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">at_pause</span><span class="p">(</span><span class="n">auto_pause</span><span class="o">=</span><span class="n">auto_pause</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">_unpause_task</span><span class="p">(</span>
<span class="bp">self</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">start_delay</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">auto_unpause</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">old_interval</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span>
<span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Unpause task from paused status. This is used for auto-paused tasks, such</span>
<span class="sd"> as tasks paused on a server reload.</span>
<span class="sd"> Args:</span>
<span class="sd"> interval (int): How often to tick the task, in seconds.</span>
<span class="sd"> start_delay (int): If the start should be delayed.</span>
<span class="sd"> auto_unpause (bool): If set, this will only unpause scripts that were unpaused</span>
<span class="sd"> automatically (useful during a system reload/shutdown).</span>
<span class="sd"> old_interval (int): The old Script interval (or current one if nothing changed). Used</span>
<span class="sd"> to recalculate the unpause startup interval.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">paused_time</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">_paused_time</span>
<span class="k">if</span> <span class="n">paused_time</span><span class="p">:</span>
<span class="k">if</span> <span class="n">auto_unpause</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">_manually_paused</span><span class="p">:</span>
<span class="c1"># this was manually paused.</span>
<span class="k">return</span>
<span class="c1"># task was paused. This will use the new values as needed.</span>
<span class="n">callcount</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">_paused_callcount</span> <span class="ow">or</span> <span class="mi">0</span>
<span class="k">if</span> <span class="n">start_delay</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">interval</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="c1"># adjust start-delay based on how far we were into previous interval</span>
<span class="n">start_delay</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">interval</span> <span class="o">-</span> <span class="p">(</span><span class="n">old_interval</span> <span class="o">-</span> <span class="n">paused_time</span><span class="p">))</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">start_delay</span> <span class="o">=</span> <span class="n">paused_time</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_task</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_task</span> <span class="o">=</span> <span class="n">ExtendedLoopingCall</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_step_task</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_task</span><span class="o">.</span><span class="n">start</span><span class="p">(</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db_interval</span><span class="p">,</span> <span class="n">now</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">start_delay</span><span class="o">=</span><span class="n">start_delay</span><span class="p">,</span> <span class="n">count_start</span><span class="o">=</span><span class="n">callcount</span>
<span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">_paused_time</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">_paused_callcount</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">_manually_paused</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">at_start</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">_stop_task</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Stop task runner and delete the task.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">task_stopped</span> <span class="o">=</span> <span class="kc">False</span>
<span class="n">task</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_task</span>
<span class="k">if</span> <span class="n">task</span> <span class="ow">and</span> <span class="n">task</span><span class="o">.</span><span class="n">running</span><span class="p">:</span>
<span class="n">task</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>
<span class="n">task_stopped</span> <span class="o">=</span> <span class="kc">True</span>
<span class="bp">self</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_task</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db_is_active</span> <span class="o">=</span> <span class="kc">False</span>
<span class="c1"># make sure this is not confused as a paused script</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">_paused_time</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">_paused_callcount</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">_manually_paused</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="n">update_fields</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;db_is_active&quot;</span><span class="p">])</span>
<span class="k">if</span> <span class="n">task_stopped</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">at_stop</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">_step_errback</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">e</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Callback for runner errors</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">cname</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span>
<span class="n">estring</span> <span class="o">=</span> <span class="n">_</span><span class="p">(</span>
<span class="s2">&quot;Script </span><span class="si">{key}</span><span class="s2">(#</span><span class="si">{dbid}</span><span class="s2">) of type &#39;</span><span class="si">{name}</span><span class="s2">&#39;: at_repeat() error &#39;</span><span class="si">{err}</span><span class="s2">&#39;.&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
<span class="n">key</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="p">,</span> <span class="n">dbid</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">dbid</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">cname</span><span class="p">,</span> <span class="n">err</span><span class="o">=</span><span class="n">e</span><span class="o">.</span><span class="n">getErrorMessage</span><span class="p">()</span>
<span class="p">)</span>
<span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db_obj</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">estring</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
<span class="c1"># we must not crash inside the errback, even if db_obj is None.</span>
<span class="k">pass</span>
<span class="n">logger</span><span class="o">.</span><span class="n">log_err</span><span class="p">(</span><span class="n">estring</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">_step_callback</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Step task runner. No try..except needed due to defer wrap.</span>
<span class="sd"> &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">ndb</span><span class="o">.</span><span class="n">_task</span><span class="p">:</span>
<span class="c1"># if there is no task, we have no business using this method</span>
<span class="k">return</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_valid</span><span class="p">():</span>
<span class="bp">self</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>
<span class="k">return</span>
<span class="c1"># call hook</span>
<span class="k">try</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">at_repeat</span><span class="p">()</span>
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
<span class="n">logger</span><span class="o">.</span><span class="n">log_trace</span><span class="p">()</span>
<span class="k">raise</span>
<span class="c1"># check repeats</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_task</span><span class="p">:</span>
<span class="c1"># we need to check for the task in case stop() was called</span>
<span class="c1"># inside at_repeat() and it already went away.</span>
<span class="n">callcount</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_task</span><span class="o">.</span><span class="n">callcount</span>
<span class="n">maxcount</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">db_repeats</span>
<span class="k">if</span> <span class="n">maxcount</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">maxcount</span> <span class="o">&lt;=</span> <span class="n">callcount</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">_step_task</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Step task. This groups error handling.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">return</span> <span class="n">maybeDeferred</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_step_callback</span><span class="p">)</span><span class="o">.</span><span class="n">addErrback</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_step_errback</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
<span class="n">logger</span><span class="o">.</span><span class="n">log_trace</span><span class="p">()</span>
<span class="k">return</span> <span class="kc">None</span>
<span class="c1"># Access methods / hooks</span>
<span class="k">def</span> <span class="nf">at_first_save</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> This is called after very first time this object is saved.</span>
<span class="sd"> Generally, you don&#39;t need to overload this, but only the hooks</span>
<span class="sd"> called by this method.</span>
<span class="sd"> Args:</span>
<span class="sd"> **kwargs (dict): Arbitrary, optional arguments for users</span>
<span class="sd"> overriding the call (unused by default).</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">basetype_setup</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">at_script_creation</span><span class="p">()</span>
<span class="c1"># initialize Attribute/TagProperties</span>
<span class="bp">self</span><span class="o">.</span><span class="n">init_evennia_properties</span><span class="p">()</span>
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">&quot;_createdict&quot;</span><span class="p">):</span>
<span class="c1"># this will only be set if the utils.create_script</span>
<span class="c1"># function was used to create the object. We want</span>
<span class="c1"># the create call&#39;s kwargs to override the values</span>
<span class="c1"># set by hooks.</span>
<span class="n">cdict</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_createdict</span>
<span class="n">updates</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">cdict</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;key&quot;</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">db_key</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">&quot;key&quot;</span><span class="p">):</span>
<span class="c1"># take key from the object typeclass</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db_key</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">key</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># no key set anywhere, use class+dbid as key</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db_key</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="si">}</span><span class="s2">(#</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">dbid</span><span class="si">}</span><span class="s2">)&quot;</span>
<span class="n">updates</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;db_key&quot;</span><span class="p">)</span>
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">db_key</span> <span class="o">!=</span> <span class="n">cdict</span><span class="p">[</span><span class="s2">&quot;key&quot;</span><span class="p">]:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db_key</span> <span class="o">=</span> <span class="n">cdict</span><span class="p">[</span><span class="s2">&quot;key&quot;</span><span class="p">]</span>
<span class="n">updates</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;db_key&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">cdict</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;interval&quot;</span><span class="p">)</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">interval</span> <span class="o">!=</span> <span class="n">cdict</span><span class="p">[</span><span class="s2">&quot;interval&quot;</span><span class="p">]:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db_interval</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">cdict</span><span class="p">[</span><span class="s2">&quot;interval&quot;</span><span class="p">])</span>
<span class="n">updates</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;db_interval&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">cdict</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;start_delay&quot;</span><span class="p">)</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">start_delay</span> <span class="o">!=</span> <span class="n">cdict</span><span class="p">[</span><span class="s2">&quot;start_delay&quot;</span><span class="p">]:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db_start_delay</span> <span class="o">=</span> <span class="n">cdict</span><span class="p">[</span><span class="s2">&quot;start_delay&quot;</span><span class="p">]</span>
<span class="n">updates</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;db_start_delay&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">cdict</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;repeats&quot;</span><span class="p">)</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">repeats</span> <span class="o">!=</span> <span class="n">cdict</span><span class="p">[</span><span class="s2">&quot;repeats&quot;</span><span class="p">]:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db_repeats</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">cdict</span><span class="p">[</span><span class="s2">&quot;repeats&quot;</span><span class="p">])</span>
<span class="n">updates</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;db_repeats&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">cdict</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;persistent&quot;</span><span class="p">)</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">persistent</span> <span class="o">!=</span> <span class="n">cdict</span><span class="p">[</span><span class="s2">&quot;persistent&quot;</span><span class="p">]:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db_persistent</span> <span class="o">=</span> <span class="n">cdict</span><span class="p">[</span><span class="s2">&quot;persistent&quot;</span><span class="p">]</span>
<span class="n">updates</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;db_persistent&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">cdict</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;desc&quot;</span><span class="p">)</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">desc</span> <span class="o">!=</span> <span class="n">cdict</span><span class="p">[</span><span class="s2">&quot;desc&quot;</span><span class="p">]:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db_desc</span> <span class="o">=</span> <span class="n">cdict</span><span class="p">[</span><span class="s2">&quot;desc&quot;</span><span class="p">]</span>
<span class="n">updates</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;db_desc&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">updates</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="n">update_fields</span><span class="o">=</span><span class="n">updates</span><span class="p">)</span>
<span class="k">if</span> <span class="n">cdict</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;permissions&quot;</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">permissions</span><span class="o">.</span><span class="n">batch_add</span><span class="p">(</span><span class="o">*</span><span class="n">cdict</span><span class="p">[</span><span class="s2">&quot;permissions&quot;</span><span class="p">])</span>
<span class="k">if</span> <span class="n">cdict</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;locks&quot;</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">locks</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">cdict</span><span class="p">[</span><span class="s2">&quot;locks&quot;</span><span class="p">])</span>
<span class="k">if</span> <span class="n">cdict</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;tags&quot;</span><span class="p">):</span>
<span class="c1"># this should be a list of tags, tuples (key, category) or (key, category, data)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">batch_add</span><span class="p">(</span><span class="o">*</span><span class="n">cdict</span><span class="p">[</span><span class="s2">&quot;tags&quot;</span><span class="p">])</span>
<span class="k">if</span> <span class="n">cdict</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;attributes&quot;</span><span class="p">):</span>
<span class="c1"># this should be tuples (key, val, ...)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">attributes</span><span class="o">.</span><span class="n">batch_add</span><span class="p">(</span><span class="o">*</span><span class="n">cdict</span><span class="p">[</span><span class="s2">&quot;attributes&quot;</span><span class="p">])</span>
<span class="k">if</span> <span class="n">cdict</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;nattributes&quot;</span><span class="p">):</span>
<span class="c1"># this should be a dict of nattrname:value</span>
<span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">cdict</span><span class="p">[</span><span class="s2">&quot;nattributes&quot;</span><span class="p">]:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">nattributes</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
<span class="k">if</span> <span class="n">cdict</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;autostart&quot;</span><span class="p">):</span>
<span class="c1"># autostart the script</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_start_task</span><span class="p">(</span><span class="n">force_restart</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">delete</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Delete the Script. Normally stops any timer task. This fires at_script_delete before</span>
<span class="sd"> deletion.</span>
<span class="sd"> Returns:</span>
<span class="sd"> bool: If deletion was successful or not. Only time this can fail would be if</span>
<span class="sd"> the script was already previously deleted, or `at_script_delete` returns</span>
<span class="sd"> False.</span>
<span class="sd"> &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">pk</span> <span class="ow">or</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">at_script_delete</span><span class="p">():</span>
<span class="k">return</span> <span class="kc">False</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_stop_task</span><span class="p">()</span>
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">delete</span><span class="p">()</span>
<span class="k">return</span> <span class="kc">True</span>
<span class="k">def</span> <span class="nf">basetype_setup</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Changes fundamental aspects of the type. Usually changes are made in at_script creation</span>
<span class="sd"> instead.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">at_init</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Called when the Script is cached in the idmapper. This is usually more reliable</span>
<span class="sd"> than overriding `__init__` since the latter can be called at unexpected times.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">at_script_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Should be overridden in child.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">at_script_delete</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Called when script is deleted, before the script timer stops.</span>
<span class="sd"> Returns:</span>
<span class="sd"> bool: If False, deletion is aborted.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="kc">True</span>
<span class="k">def</span> <span class="nf">is_valid</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> If returning False, `at_repeat` will not be called and timer will stop</span>
<span class="sd"> updating.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="kc">True</span>
<span class="k">def</span> <span class="nf">at_repeat</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Called repeatedly every `interval` seconds, once `.start()` has</span>
<span class="sd"> been called on the Script at least once.</span>
<span class="sd"> Args:</span>
<span class="sd"> **kwargs (dict): Arbitrary, optional arguments for users</span>
<span class="sd"> overriding the call (unused by default).</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">at_start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">at_pause</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">at_stop</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">start_delay</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">repeats</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Start/Unpause timer component, optionally with new values. If given,</span>
<span class="sd"> this will update the Script&#39;s fields. This will start `at_repeat` being</span>
<span class="sd"> called every `interval` seconds.</span>
<span class="sd"> Keyword Args:</span>
<span class="sd"> interval (int): How often to fire `at_repeat` in seconds.</span>
<span class="sd"> start_delay (int): If the start of ticking should be delayed and by how much.</span>
<span class="sd"> repeats (int): How many repeats. 0 for infinite repeats.</span>
<span class="sd"> **kwargs: Optional (default unused) kwargs passed on into the `at_start` hook.</span>
<span class="sd"> Notes:</span>
<span class="sd"> If setting the `start-delay` of a *paused* Script, the Script will</span>
<span class="sd"> restart exactly after that new start-delay, ignoring the time it</span>
<span class="sd"> was paused at. If only changing the `interval`, the Script will</span>
<span class="sd"> come out of pause comparing the time it spent in the *old* interval</span>
<span class="sd"> with the *new* interval in order to determine when next to fire.</span>
<span class="sd"> Examples:</span>
<span class="sd"> - Script previously had an interval of 10s and was paused 5s into that interval.</span>
<span class="sd"> Script is now restarted with a 20s interval. It will next fire after 15s.</span>
<span class="sd"> - Same Script is restarted with a 3s interval. It will fire immediately.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_start_task</span><span class="p">(</span><span class="n">interval</span><span class="o">=</span><span class="n">interval</span><span class="p">,</span> <span class="n">start_delay</span><span class="o">=</span><span class="n">start_delay</span><span class="p">,</span> <span class="n">repeats</span><span class="o">=</span><span class="n">repeats</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
<span class="c1"># legacy alias</span>
<span class="n">update</span> <span class="o">=</span> <span class="n">start</span>
<span class="k">def</span> <span class="nf">stop</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Stop the Script&#39;s timer component. This will not delete the Sctipt,</span>
<span class="sd"> just stop the regular firing of `at_repeat`. Running `.start()` will</span>
<span class="sd"> start the timer anew, optionally with new settings..</span>
<span class="sd"> Args:</span>
<span class="sd"> **kwargs: Optional (default unused) kwargs passed on into the `at_stop` hook.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_stop_task</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">pause</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Manually the Script&#39;s timer component manually.</span>
<span class="sd"> Args:</span>
<span class="sd"> **kwargs: Optional (default unused) kwargs passed on into the `at_pause` hook.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_pause_task</span><span class="p">(</span><span class="n">manual_pause</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">unpause</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Manually unpause a Paused Script.</span>
<span class="sd"> Args:</span>
<span class="sd"> **kwargs: Optional (default unused) kwargs passed on into the `at_start` hook.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_unpause_task</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">time_until_next_repeat</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Get time until the script fires it `at_repeat` hook again.</span>
<span class="sd"> Returns:</span>
<span class="sd"> int or None: Time in seconds until the script runs again.</span>
<span class="sd"> If not a timed script, return `None`.</span>
<span class="sd"> Notes:</span>
<span class="sd"> This hook is not used in any way by the script&#39;s stepping</span>
<span class="sd"> system; it&#39;s only here for the user to be able to check in</span>
<span class="sd"> on their scripts and when they will next be run.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">task</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_task</span>
<span class="k">if</span> <span class="n">task</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="nb">round</span><span class="p">(</span><span class="n">task</span><span class="o">.</span><span class="n">next_call_time</span><span class="p">()))</span>
<span class="k">except</span> <span class="ne">TypeError</span><span class="p">:</span>
<span class="k">pass</span>
<span class="k">return</span> <span class="kc">None</span>
<span class="k">def</span> <span class="nf">remaining_repeats</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Get the number of returning repeats for limited Scripts.</span>
<span class="sd"> Returns:</span>
<span class="sd"> int or None: The number of repeats remaining until the Script</span>
<span class="sd"> stops. Returns `None` if it has unlimited repeats.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">task</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_task</span>
<span class="k">if</span> <span class="n">task</span><span class="p">:</span>
<span class="k">return</span> <span class="nb">max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">db_repeats</span> <span class="o">-</span> <span class="n">task</span><span class="o">.</span><span class="n">callcount</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">None</span>
<span class="k">def</span> <span class="nf">reset_callcount</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Reset the count of the number of calls done.</span>
<span class="sd"> Args:</span>
<span class="sd"> value (int, optional): The repeat value to reset to. Default</span>
<span class="sd"> is to set it all the way back to 0.</span>
<span class="sd"> Notes:</span>
<span class="sd"> This is only useful if repeats != 0.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">task</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_task</span>
<span class="k">if</span> <span class="n">task</span><span class="p">:</span>
<span class="n">task</span><span class="o">.</span><span class="n">callcount</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">value</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">force_repeat</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Fire a premature triggering of the script callback. This</span>
<span class="sd"> will reset the timer and count down repeats as if the script</span>
<span class="sd"> had fired normally.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">task</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_task</span>
<span class="k">if</span> <span class="n">task</span><span class="p">:</span>
<span class="n">task</span><span class="o">.</span><span class="n">force_repeat</span><span class="p">()</span>
<div class="viewcode-block" id="DefaultScript"><a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.scripts.scripts.DefaultScript">[docs]</a><span class="k">class</span> <span class="nc">DefaultScript</span><span class="p">(</span><span class="n">ScriptBase</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> This is the base TypeClass for all Scripts. Scripts describe</span>
<span class="sd"> all entities/systems without a physical existence in the game world</span>
<span class="sd"> that require database storage (like an economic system or</span>
<span class="sd"> combat tracker). They</span>
<span class="sd"> can also have a timer/ticker component.</span>
<span class="sd"> A script type is customized by redefining some or all of its hook</span>
<span class="sd"> methods and variables.</span>
<span class="sd"> * available properties (check docs for full listing, this could be</span>
<span class="sd"> outdated).</span>
<span class="sd"> key (string) - name of object</span>
<span class="sd"> name (string)- same as key</span>
<span class="sd"> aliases (list of strings) - aliases to the object. Will be saved</span>
<span class="sd"> to database as AliasDB entries but returned as strings.</span>
<span class="sd"> dbref (int, read-only) - unique #id-number. Also &quot;id&quot; can be used.</span>
<span class="sd"> date_created (string) - time stamp of object creation</span>
<span class="sd"> permissions (list of strings) - list of permission strings</span>
<span class="sd"> desc (string) - optional description of script, shown in listings</span>
<span class="sd"> obj (Object) - optional object that this script is connected to</span>
<span class="sd"> and acts on (set automatically by obj.scripts.add())</span>
<span class="sd"> interval (int) - how often script should run, in seconds. &lt;0 turns</span>
<span class="sd"> off ticker</span>
<span class="sd"> start_delay (bool) - if the script should start repeating right away or</span>
<span class="sd"> wait self.interval seconds</span>
<span class="sd"> repeats (int) - how many times the script should repeat before</span>
<span class="sd"> stopping. 0 means infinite repeats</span>
<span class="sd"> persistent (bool) - if script should survive a server shutdown or not</span>
<span class="sd"> is_active (bool) - if script is currently running</span>
<span class="sd"> * Handlers</span>
<span class="sd"> locks - lock-handler: use locks.add() to add new lock strings</span>
<span class="sd"> db - attribute-handler: store/retrieve database attributes on this</span>
<span class="sd"> self.db.myattr=val, val=self.db.myattr</span>
<span class="sd"> ndb - non-persistent attribute handler: same as db but does not</span>
<span class="sd"> create a database entry when storing data</span>
<span class="sd"> * Helper methods</span>
<span class="sd"> create(key, **kwargs)</span>
<span class="sd"> start() - start script (this usually happens automatically at creation</span>
<span class="sd"> and obj.script.add() etc)</span>
<span class="sd"> stop() - stop script, and delete it</span>
<span class="sd"> pause() - put the script on hold, until unpause() is called. If script</span>
<span class="sd"> is persistent, the pause state will survive a shutdown.</span>
<span class="sd"> unpause() - restart a previously paused script. The script will continue</span>
<span class="sd"> from the paused timer (but at_start() will be called).</span>
<span class="sd"> time_until_next_repeat() - if a timed script (interval&gt;0), returns time</span>
<span class="sd"> until next tick</span>
<span class="sd"> * Hook methods (should also include self as the first argument):</span>
<span class="sd"> at_script_creation() - called only once, when an object of this</span>
<span class="sd"> class is first created.</span>
<span class="sd"> is_valid() - is called to check if the script is valid to be running</span>
<span class="sd"> at the current time. If is_valid() returns False, the running</span>
<span class="sd"> script is stopped and removed from the game. You can use this</span>
<span class="sd"> to check state changes (i.e. an script tracking some combat</span>
<span class="sd"> stats at regular intervals is only valid to run while there is</span>
<span class="sd"> actual combat going on).</span>
<span class="sd"> at_start() - Called every time the script is started, which for persistent</span>
<span class="sd"> scripts is at least once every server start. Note that this is</span>
<span class="sd"> unaffected by self.delay_start, which only delays the first</span>
<span class="sd"> call to at_repeat().</span>
<span class="sd"> at_repeat() - Called every self.interval seconds. It will be called</span>
<span class="sd"> immediately upon launch unless self.delay_start is True, which</span>
<span class="sd"> will delay the first call of this method by self.interval</span>
<span class="sd"> seconds. If self.interval==0, this method will never</span>
<span class="sd"> be called.</span>
<span class="sd"> at_pause()</span>
<span class="sd"> at_stop() - Called as the script object is stopped and is about to be</span>
<span class="sd"> removed from the game, e.g. because is_valid() returned False.</span>
<span class="sd"> at_script_delete()</span>
<span class="sd"> at_server_reload() - Called when server reloads. Can be used to</span>
<span class="sd"> save temporary variables you want should survive a reload.</span>
<span class="sd"> at_server_shutdown() - called at a full server shutdown.</span>
<span class="sd"> at_server_start()</span>
<span class="sd"> &quot;&quot;&quot;</span>
<div class="viewcode-block" id="DefaultScript.create"><a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.scripts.scripts.DefaultScript.create">[docs]</a> <span class="nd">@classmethod</span>
<span class="k">def</span> <span class="nf">create</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Provides a passthrough interface to the utils.create_script() function.</span>
<span class="sd"> Args:</span>
<span class="sd"> key (str): Name of the new object.</span>
<span class="sd"> Returns:</span>
<span class="sd"> object (Object): A newly created object of the given typeclass.</span>
<span class="sd"> errors (list): A list of errors in string form, if any.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">obj</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">kwargs</span><span class="p">[</span><span class="s2">&quot;key&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">key</span>
<span class="c1"># If no typeclass supplied, use this class</span>
<span class="n">kwargs</span><span class="p">[</span><span class="s2">&quot;typeclass&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">&quot;typeclass&quot;</span><span class="p">,</span> <span class="bp">cls</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">obj</span> <span class="o">=</span> <span class="n">create</span><span class="o">.</span><span class="n">create_script</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
<span class="n">logger</span><span class="o">.</span><span class="n">log_trace</span><span class="p">()</span>
<span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;The script &#39;</span><span class="si">%s</span><span class="s2">&#39; encountered errors and could not be created.&quot;</span> <span class="o">%</span> <span class="n">key</span><span class="p">)</span>
<span class="k">return</span> <span class="n">obj</span><span class="p">,</span> <span class="n">errors</span></div>
<div class="viewcode-block" id="DefaultScript.at_script_creation"><a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.scripts.scripts.DefaultScript.at_script_creation">[docs]</a> <span class="k">def</span> <span class="nf">at_script_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Only called once, when script is first created.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">pass</span></div>
<div class="viewcode-block" id="DefaultScript.is_valid"><a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.scripts.scripts.DefaultScript.is_valid">[docs]</a> <span class="k">def</span> <span class="nf">is_valid</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Is called to check if the script&#39;s timer is valid to run at this time.</span>
<span class="sd"> Should return a boolean. If False, the timer will be stopped.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="kc">True</span></div>
<div class="viewcode-block" id="DefaultScript.at_start"><a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.scripts.scripts.DefaultScript.at_start">[docs]</a> <span class="k">def</span> <span class="nf">at_start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Called whenever the script timer is started, which for persistent</span>
<span class="sd"> timed scripts is at least once every server start. It will also be</span>
<span class="sd"> called when starting again after a pause (including after a</span>
<span class="sd"> server reload).</span>
<span class="sd"> Args:</span>
<span class="sd"> **kwargs (dict): Arbitrary, optional arguments for users</span>
<span class="sd"> overriding the call (unused by default).</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">pass</span></div>
<div class="viewcode-block" id="DefaultScript.at_repeat"><a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.scripts.scripts.DefaultScript.at_repeat">[docs]</a> <span class="k">def</span> <span class="nf">at_repeat</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Called repeatedly if this Script is set to repeat regularly.</span>
<span class="sd"> Args:</span>
<span class="sd"> **kwargs (dict): Arbitrary, optional arguments for users</span>
<span class="sd"> overriding the call (unused by default).</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">pass</span></div>
<div class="viewcode-block" id="DefaultScript.at_pause"><a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.scripts.scripts.DefaultScript.at_pause">[docs]</a> <span class="k">def</span> <span class="nf">at_pause</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">manual_pause</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Called when this script&#39;s timer pauses.</span>
<span class="sd"> Args:</span>
<span class="sd"> manual_pause (bool): If set, pausing was done by a direct call. The</span>
<span class="sd"> non-manual pause indicates the script was paused as part of</span>
<span class="sd"> the server reload.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">pass</span></div>
<div class="viewcode-block" id="DefaultScript.at_stop"><a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.scripts.scripts.DefaultScript.at_stop">[docs]</a> <span class="k">def</span> <span class="nf">at_stop</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Called whenever when it&#39;s time for this script&#39;s timer to stop (either</span>
<span class="sd"> because is_valid returned False, it ran out of iterations or it was manuallys</span>
<span class="sd"> stopped.</span>
<span class="sd"> Args:</span>
<span class="sd"> **kwargs (dict): Arbitrary, optional arguments for users</span>
<span class="sd"> overriding the call (unused by default).</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">pass</span></div>
<div class="viewcode-block" id="DefaultScript.at_script_delete"><a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.scripts.scripts.DefaultScript.at_script_delete">[docs]</a> <span class="k">def</span> <span class="nf">at_script_delete</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Called when the Script is deleted, before stopping the timer.</span>
<span class="sd"> Returns:</span>
<span class="sd"> bool: If False, the deletion is aborted.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="kc">True</span></div>
<div class="viewcode-block" id="DefaultScript.at_server_reload"><a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.scripts.scripts.DefaultScript.at_server_reload">[docs]</a> <span class="k">def</span> <span class="nf">at_server_reload</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> This hook is called whenever the server is shutting down for</span>
<span class="sd"> restart/reboot. If you want to, for example, save</span>
<span class="sd"> non-persistent properties across a restart, this is the place</span>
<span class="sd"> to do it.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">pass</span></div>
<div class="viewcode-block" id="DefaultScript.at_server_shutdown"><a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.scripts.scripts.DefaultScript.at_server_shutdown">[docs]</a> <span class="k">def</span> <span class="nf">at_server_shutdown</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> This hook is called whenever the server is shutting down fully</span>
<span class="sd"> (i.e. not for a restart).</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">pass</span></div>
<div class="viewcode-block" id="DefaultScript.at_server_start"><a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.scripts.scripts.DefaultScript.at_server_start">[docs]</a> <span class="k">def</span> <span class="nf">at_server_start</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> This hook is called after the server has started. It can be used to add</span>
<span class="sd"> post-startup setup for Scripts without a timer component (for which at_start</span>
<span class="sd"> could be used).</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">pass</span></div></div>
<span class="c1"># Some useful default Script types used by Evennia.</span>
<div class="viewcode-block" id="DoNothing"><a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.scripts.scripts.DoNothing">[docs]</a><span class="k">class</span> <span class="nc">DoNothing</span><span class="p">(</span><span class="n">DefaultScript</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> A script that does nothing. Used as default fallback.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<div class="viewcode-block" id="DoNothing.at_script_creation"><a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.scripts.scripts.DoNothing.at_script_creation">[docs]</a> <span class="k">def</span> <span class="nf">at_script_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Setup the script</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;sys_do_nothing&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">desc</span> <span class="o">=</span> <span class="s2">&quot;This is an empty placeholder script.&quot;</span></div></div>
<div class="viewcode-block" id="Store"><a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.scripts.scripts.Store">[docs]</a><span class="k">class</span> <span class="nc">Store</span><span class="p">(</span><span class="n">DefaultScript</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Simple storage script</span>
<span class="sd"> &quot;&quot;&quot;</span>
<div class="viewcode-block" id="Store.at_script_creation"><a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.scripts.scripts.Store.at_script_creation">[docs]</a> <span class="k">def</span> <span class="nf">at_script_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Setup the script</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;sys_storage&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">desc</span> <span class="o">=</span> <span class="s2">&quot;This is a generic storage container.&quot;</span></div></div>
</pre></div>
</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="nav-item nav-item-0"><a href="../../../index.html">Evennia latest</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="../../index.html" >Module code</a> &#187;</li>
<li class="nav-item nav-item-2"><a href="../../evennia.html" >evennia</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">evennia.scripts.scripts</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> 3.2.1.
</div>
</body>
</html>