evennia/docs/0.x/Adding-Command-Tutorial.html
2023-12-20 19:10:09 +01:00

279 lines
No EOL
21 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

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

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Adding Command Tutorial &#8212; Evennia 0.9.5 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>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</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 0.9.5</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Adding Command Tutorial</a></li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section class="tex2jax_ignore mathjax_ignore" id="adding-command-tutorial">
<h1>Adding Command Tutorial<a class="headerlink" href="#adding-command-tutorial" title="Permalink to this headline"></a></h1>
<p>This is a quick first-time tutorial expanding on the <a class="reference internal" href="Commands.html"><span class="doc std std-doc">Commands</span></a> documentation.</p>
<p>Lets assume you have just downloaded Evennia, installed it and created your game folder (lets call
it just <code class="docutils literal notranslate"><span class="pre">mygame</span></code> here). Now you want to try to add a new command. This is the fastest way to do it.</p>
<section id="step-1-creating-a-custom-command">
<h2>Step 1: Creating a custom command<a class="headerlink" href="#step-1-creating-a-custom-command" title="Permalink to this headline"></a></h2>
<ol class="simple">
<li><p>Open <code class="docutils literal notranslate"><span class="pre">mygame/commands/command.py</span></code> in a text editor. This is just one place commands could be
placed but you get it setup from the onset as an easy place to start. It also already contains some
example code.</p></li>
<li><p>Create a new class in <code class="docutils literal notranslate"><span class="pre">command.py</span></code> inheriting from <code class="docutils literal notranslate"><span class="pre">default_cmds.MuxCommand</span></code>. Lets call it
<code class="docutils literal notranslate"><span class="pre">CmdEcho</span></code> in this example.</p></li>
<li><p>Set the class variable <code class="docutils literal notranslate"><span class="pre">key</span></code> to a good command name, like <code class="docutils literal notranslate"><span class="pre">echo</span></code>.</p></li>
<li><p>Give your class a useful <em>docstring</em>. A docstring is the string at the very top of a class or
function/method. The docstring at the top of the command class is read by Evennia to become the help
entry for the Command (see
<a class="reference internal" href="Help-System.html#command-auto-help-system"><span class="std std-doc">Command Auto-help</span></a>).</p></li>
<li><p>Define a class method <code class="docutils literal notranslate"><span class="pre">func(self)</span></code> that echoes your input back to you.</p></li>
</ol>
<p>Below is an example how this all could look for the echo command:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># file mygame/commands/command.py</span>
<span class="c1">#[...]</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">default_cmds</span>
<span class="k">class</span> <span class="nc">CmdEcho</span><span class="p">(</span><span class="n">default_cmds</span><span class="o">.</span><span class="n">MuxCommand</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Simple command example</span>
<span class="sd"> </span>
<span class="sd"> Usage:</span>
<span class="sd"> echo [text]</span>
<span class="sd"> </span>
<span class="sd"> This command simply echoes text back to the caller.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;echo&quot;</span>
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="s2">&quot;This actually does things&quot;</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;You didn&#39;t enter anything!&quot;</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;You gave the string: &#39;</span><span class="si">%s</span><span class="s2">&#39;&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="step-2-adding-the-command-to-a-default-cmdset">
<h2>Step 2: Adding the Command to a default Cmdset<a class="headerlink" href="#step-2-adding-the-command-to-a-default-cmdset" title="Permalink to this headline"></a></h2>
<p>The command is not available to use until it is part of a <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">Command Set</span></a>. In this
example we will go the easiest route and add it to the default Character commandset that already
exists.</p>
<ol class="simple">
<li><p>Edit <code class="docutils literal notranslate"><span class="pre">mygame/commands/default_cmdsets.py</span></code></p></li>
<li><p>Import your new command with <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">commands.command</span> <span class="pre">import</span> <span class="pre">CmdEcho</span></code>.</p></li>
<li><p>Add a line <code class="docutils literal notranslate"><span class="pre">self.add(CmdEcho())</span></code> to <code class="docutils literal notranslate"><span class="pre">CharacterCmdSet</span></code>, in the <code class="docutils literal notranslate"><span class="pre">at_cmdset_creation</span></code> method (the
template tells you where).</p></li>
</ol>
<p>This is approximately how it should look at this point:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># file mygame/commands/default_cmdsets.py</span>
<span class="c1">#[...]</span>
<span class="kn">from</span> <span class="nn">commands.command</span> <span class="kn">import</span> <span class="n">CmdEcho</span>
<span class="c1">#[...]</span>
<span class="k">class</span> <span class="nc">CharacterCmdSet</span><span class="p">(</span><span class="n">default_cmds</span><span class="o">.</span><span class="n">CharacterCmdSet</span><span class="p">):</span>
<span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;DefaultCharacter&quot;</span>
<span class="k">def</span> <span class="nf">at_cmdset_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="c1"># this first adds all default commands</span>
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">at_cmdset_creation</span><span class="p">()</span>
<span class="c1"># all commands added after this point will extend or</span>
<span class="c1"># overwrite the default commands.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">CmdEcho</span><span class="p">())</span>
</pre></div>
</div>
<p>Next, run the <code class="docutils literal notranslate"><span class="pre">&#64;reload</span></code> command. You should now be able to use your new <code class="docutils literal notranslate"><span class="pre">echo</span></code> command from inside
the game. Use <code class="docutils literal notranslate"><span class="pre">help</span> <span class="pre">echo</span></code> to see the documentation for the command.</p>
<p>If you have trouble, make sure to check the log for error messages (probably due to syntax errors in
your command definition).</p>
<blockquote>
<div><p>Note: Typing <code class="docutils literal notranslate"><span class="pre">echotest</span></code> will also work. It will be handled as the command <code class="docutils literal notranslate"><span class="pre">echo</span></code> directly followed
by
its argument <code class="docutils literal notranslate"><span class="pre">test</span></code> (which will end up in <code class="docutils literal notranslate"><span class="pre">self.args).</span> <span class="pre">To</span> <span class="pre">change</span> <span class="pre">this</span> <span class="pre">behavior,</span> <span class="pre">you</span> <span class="pre">can</span> <span class="pre">add</span> <span class="pre">the</span> </code>arg_regex<code class="docutils literal notranslate"><span class="pre">property</span> <span class="pre">alongside</span></code>key<code class="docutils literal notranslate"><span class="pre">,</span> </code>help_category` etc. <a class="reference internal" href="Commands.html#on-arg-regex"><span class="std std-doc">See the arg_regex
documentation</span></a> for more info.</p>
</div></blockquote>
<p>If you want to overload existing default commands (such as <code class="docutils literal notranslate"><span class="pre">look</span></code> or <code class="docutils literal notranslate"><span class="pre">get</span></code>), just add your new
command with the same key as the old one - it will then replace it. Just remember that you must use
<code class="docutils literal notranslate"><span class="pre">&#64;reload</span></code> to see any changes.</p>
<p>See <a class="reference internal" href="Commands.html"><span class="doc std std-doc">Commands</span></a> for many more details and possibilities when defining Commands and using
Cmdsets in various ways.</p>
</section>
<section id="adding-the-command-to-specific-object-types">
<h2>Adding the command to specific object types<a class="headerlink" href="#adding-the-command-to-specific-object-types" title="Permalink to this headline"></a></h2>
<p>Adding your Command to the <code class="docutils literal notranslate"><span class="pre">CharacterCmdSet</span></code> is just one easy exapmple. The cmdset system is very
generic. You can create your own cmdsets (lets say in a module <code class="docutils literal notranslate"><span class="pre">mycmdsets.py</span></code>) and add them to
objects as you please (how to control their merging is described in detail in the <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">Command Set
documentation</span></a>).</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># file mygame/commands/mycmdsets.py</span>
<span class="c1">#[...]</span>
<span class="kn">from</span> <span class="nn">commands.command</span> <span class="kn">import</span> <span class="n">CmdEcho</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">CmdSet</span>
<span class="c1">#[...]</span>
<span class="k">class</span> <span class="nc">MyCmdSet</span><span class="p">(</span><span class="n">CmdSet</span><span class="p">):</span>
<span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;MyCmdSet&quot;</span>
<span class="k">def</span> <span class="nf">at_cmdset_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">CmdEcho</span><span class="p">())</span>
</pre></div>
</div>
<p>Now you just need to add this to an object. To test things (as superuser) you can do</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> @py self.cmdset.add(&quot;mycmdsets.MyCmdSet&quot;)
</pre></div>
</div>
<p>This will add this cmdset (along with its echo command) to yourself so you can test it. Note that
you cannot add a single Command to an object on its own, it must be part of a CommandSet in order to
do so.</p>
<p>The Command you added is not there permanently at this point. If you do a <code class="docutils literal notranslate"><span class="pre">&#64;reload</span></code> the merger will
be gone. You <em>could</em> add the <code class="docutils literal notranslate"><span class="pre">permanent=True</span></code> keyword to the <code class="docutils literal notranslate"><span class="pre">cmdset.add</span></code> call. This will however
only make the new merged cmdset permanent on that <em>single</em> object. Often you want <em>all</em> objects of
this particular class to have this cmdset.</p>
<p>To make sure all new created objects get your new merged set, put the <code class="docutils literal notranslate"><span class="pre">cmdset.add</span></code> call in your
custom <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclasses</span></a> <code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code> method:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># e.g. in mygame/typeclasses/objects.py</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">DefaultObject</span>
<span class="k">class</span> <span class="nc">MyObject</span><span class="p">(</span><span class="n">DefaultObject</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">at_object_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="s2">&quot;called when the object is first created&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">cmdset</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;mycmdset.MyCmdSet&quot;</span><span class="p">,</span> <span class="n">permanent</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</pre></div>
</div>
<p>All new objects of this typeclass will now start with this cmdset and it will survive a <code class="docutils literal notranslate"><span class="pre">&#64;reload</span></code>.</p>
<p><em>Note:</em> An important caveat with this is that <code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code> is only called <em>once</em>, when the
object is first created. This means that if you already have existing objects in your databases
using that typeclass, they will not have been initiated the same way. There are many ways to update
them; since its a one-time update you can usually just simply loop through them. As superuser, try
the following:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> @py from typeclasses.objects import MyObject; [o.cmdset.add(&quot;mycmdset.MyCmdSet&quot;) for o in
</pre></div>
</div>
<p>MyObject.objects.all()]</p>
<p>This goes through all objects in your database having the right typeclass, adding the new cmdset to
each. The good news is that you only have to do this if you want to post-add <em>cmdsets</em>. If you just
want to add a new <em>command</em>, you can simply add that command to the cmdsets <code class="docutils literal notranslate"><span class="pre">at_cmdset_creation</span></code>
and <code class="docutils literal notranslate"><span class="pre">&#64;reload</span></code> to make the Command immediately available.</p>
</section>
<section id="change-where-evennia-looks-for-command-sets">
<h2>Change where Evennia looks for command sets<a class="headerlink" href="#change-where-evennia-looks-for-command-sets" title="Permalink to this headline"></a></h2>
<p>Evennia uses settings variables to know where to look for its default command sets. These are
normally not changed unless you want to re-organize your game folder in some way. For example, the
default character cmdset defaults to being defined as</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>CMDSET_CHARACTER=&quot;commands.default_cmdset.CharacterCmdSet&quot;
</pre></div>
</div>
<p>See <code class="docutils literal notranslate"><span class="pre">evennia/settings_default.py</span></code> for the other settings.</p>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<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>
<p><h3><a href="index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Adding Command Tutorial</a><ul>
<li><a class="reference internal" href="#step-1-creating-a-custom-command">Step 1: Creating a custom command</a></li>
<li><a class="reference internal" href="#step-2-adding-the-command-to-a-default-cmdset">Step 2: Adding the Command to a default Cmdset</a></li>
<li><a class="reference internal" href="#adding-the-command-to-specific-object-types">Adding the command to specific object types</a></li>
<li><a class="reference internal" href="#change-where-evennia-looks-for-command-sets">Change where Evennia looks for command sets</a></li>
</ul>
</li>
</ul>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="_sources/Adding-Command-Tutorial.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div><h3>Links</h3>
<ul>
<li><a href="https://www.evennia.com">Home page</a> </li>
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
<li><a href="http://games.evennia.com">Game Index</a> </li>
<li><a href="http://webchat.freenode.net/?channels=evennia&uio=MT1mYWxzZSY5PXRydWUmMTE9MTk1JjEyPXRydWUbb">IRC</a> -
<a href="https://discord.gg/NecFePw">Discord</a> -
<a href="https://groups.google.com/forum/#%21forum/evennia">Forums</a>
</li>
<li><a href="http://evennia.blogspot.com/">Evennia Dev blog</a> </li>
</ul>
<h3>Versions</h3>
<ul>
<li><a href="../1.0-dev/index.html">1.0-dev (develop branch)</a></li>
<li><a href="Adding-Command-Tutorial.html">0.9.5 (v0.9.5 branch)</a></li>
</ul>
</div>
</div>
<div class="clearer"></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 0.9.5</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Adding Command Tutorial</a></li>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2020, The Evennia developer community.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
</div>
</body>
</html>