<h1><spanclass="section-number">8. </span>Adding custom commands<aclass="headerlink"href="#adding-custom-commands"title="Permalink to this headline">¶</a></h1>
<p>In this lesson we’ll learn how to create our own Evennia <aclass="reference internal"href="../../../Components/Commands.html"><spanclass="doc std std-doc">Commands</span></a> If you are new to Python you’ll also learn some more basics about how to manipulate strings and get information out of Evennia.</p>
<p>A Command is something that handles the input from a user and causes a result to happen.
An example is <codeclass="docutils literal notranslate"><spanclass="pre">look</span></code>, which examines your current location and tells you what it looks like and
what is in it.</p>
<asideclass="sidebar">
<pclass="sidebar-title">Commands are not typeclassed</p>
<p>If you just came from the previous lesson, you might want to know that Commands and CommandSets are not <codeclass="docutils literal notranslate"><spanclass="pre">typeclassed</span></code>. That is, instances of them are not saved to the database. They are “just” normal Python classes.</p>
<p>In Evennia, a Command is a Python <em>class</em>. If you are unsure about what a class is, review the
<aclass="reference internal"href="Beginner-Tutorial-Python-classes-and-objects.html"><spanclass="doc std std-doc">previous lesson about it</span></a>! A Command inherits from <codeclass="docutils literal notranslate"><spanclass="pre">evennia.Command</span></code> or from one of the alternative command- classes, such as <codeclass="docutils literal notranslate"><spanclass="pre">MuxCommand</span></code> which is what most default commands use.</p>
<p>All Commands are grouped in another class called a <em>Command Set</em>. Think of a Command Set as a bag holding many different commands. One CmdSet could for example hold all commands for combat, another for building etc.</p>
<p>Command-Sets are then associated with objects, for example with your Character. Doing so makes the commands in that cmdset available to the object. By default, Evennia groups all character-commands into one big cmdset called the <codeclass="docutils literal notranslate"><spanclass="pre">CharacterCmdSet</span></code>. It sits on <codeclass="docutils literal notranslate"><spanclass="pre">DefaultCharacter</span></code> (and thus, through inheritance, on <codeclass="docutils literal notranslate"><spanclass="pre">typeclasses.characters.Character</span></code>).</p>
<sectionid="creating-a-custom-command">
<h2><spanclass="section-number">8.1. </span>Creating a custom command<aclass="headerlink"href="#creating-a-custom-command"title="Permalink to this headline">¶</a></h2>
<spanclass="c1"># (lots of commented-out stuff)</span>
<spanclass="c1"># ...</span>
</pre></div>
</div>
<p>Ignoring the docstrings (which you can read if you want), this is the only really active code in the module.</p>
<p>We can see that we import <codeclass="docutils literal notranslate"><spanclass="pre">Command</span></code> from <codeclass="docutils literal notranslate"><spanclass="pre">evennia</span></code> and use the <codeclass="docutils literal notranslate"><spanclass="pre">from</span><spanclass="pre">...</span><spanclass="pre">import</span><spanclass="pre">...</span><spanclass="pre">as</span><spanclass="pre">...</span></code> form to rename it to <codeclass="docutils literal notranslate"><spanclass="pre">BaseCommand</span></code>. This is so we can let our child class also be named <codeclass="docutils literal notranslate"><spanclass="pre">Command</span></code> to make it easier to reference. The class itself doesn’t do anything, it just has <codeclass="docutils literal notranslate"><spanclass="pre">pass</span></code>. So in the same way as <codeclass="docutils literal notranslate"><spanclass="pre">Object</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code> in the previous lessons, this class is identical to its parent.</p>
<blockquote>
<div><p>The commented out <codeclass="docutils literal notranslate"><spanclass="pre">default_cmds</span></code> gives us access to Evennia’s default commands for easy overriding. We’ll try that a little later.</p>
</div></blockquote>
<p>We could modify this module directly, but let’s work in a separate module just for the heck of it. Open a new file <codeclass="docutils literal notranslate"><spanclass="pre">mygame/commands/mycommands.py</span></code> and add the following code:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># in mygame/commands/mycommands.py</span>
<p>This is the simplest form of command you can imagine. It just gives itself a name, “echo”. This is what you will use to call this command later.</p>
<p>Next we need to put this in a CmdSet. It will be a one-command CmdSet for now! Change your file as such:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># in mygame/commands/mycommands.py</span>
<p>Our <codeclass="docutils literal notranslate"><spanclass="pre">MyCmdSet</span></code> class must have an <codeclass="docutils literal notranslate"><spanclass="pre">at_cmdset_creation</span></code> method, named exactly like this - this is what Evennia will be looking for when setting up the cmdset later, so if you didn’t set it up, it will use the parent’s version, which is empty. Inside we add the command class to the cmdset by <codeclass="docutils literal notranslate"><spanclass="pre">self.add()</span></code>. If you wanted to add more commands to this CmdSet you could just add more lines of <codeclass="docutils literal notranslate"><spanclass="pre">self.add</span></code> after this.</p>
<p>Finally, let’s add this command to ourselves so we can try it out. In-game you can experiment with <codeclass="docutils literal notranslate"><spanclass="pre">py</span></code> again:</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">me.cmdset</span></code> is the store of all cmdsets stored on us. By giving the path to our CmdSet class, it will be added.</p>
Command echo has no defined `func()` - showing on-command variables:
...
...
</pre></div>
</div>
<p><codeclass="docutils literal notranslate"><spanclass="pre">echo</span></code> works! You should be getting a long list of outputs. The reason for this is that your <codeclass="docutils literal notranslate"><spanclass="pre">echo</span></code> function is not really “doing” anything yet and the default function is then to show all useful resources available to you when you use your Command. Let’s look at some of those listed:</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>Command echo has no defined `func()` - showing on-command variables:
<p>These are all properties you can access with <codeclass="docutils literal notranslate"><spanclass="pre">.</span></code> on the Command instance, such as <codeclass="docutils literal notranslate"><spanclass="pre">.key</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">.args</span></code> and so on. Evennia makes these available to you and they will be different every time a command is run. The most important ones we will make use of now are:</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">caller</span></code> - this is ‘you’, the person calling the command.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">args</span></code> - this is all arguments to the command. Now it’s empty, but if you tried <codeclass="docutils literal notranslate"><spanclass="pre">echo</span><spanclass="pre">foo</span><spanclass="pre">bar</span></code> you’d find that this would be <codeclass="docutils literal notranslate"><spanclass="pre">"</span><spanclass="pre">foo</span><spanclass="pre">bar"</span></code>.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">obj</span></code> - this is object on which this Command (and CmdSet) “sits”. So you, in this case.</p></li>
</ul>
<p>The reason our command doesn’t do anything yet is because it’s missing a <codeclass="docutils literal notranslate"><spanclass="pre">func</span></code> method. This is what Evennia looks for to figure out what a Command actually does. Modify your <codeclass="docutils literal notranslate"><spanclass="pre">CmdEcho</span></code> class:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># in mygame/commands/mycommands.py</span>
<p>First we added a docstring. This is always a good thing to do in general, but for a Command class, it will also automatically become the in-game help entry!</p>
<asideclass="sidebar">
<pclass="sidebar-title">Use Command.msg </p>
<p>In a Command class, the <codeclass="docutils literal notranslate"><spanclass="pre">self.msg()</span></code> acts as a convenient shortcut for <codeclass="docutils literal notranslate"><spanclass="pre">self.caller.msg()</span></code>. Not only is it shorter, it also has some advantages because the command can include more metadata with the message. So using <codeclass="docutils literal notranslate"><spanclass="pre">self.msg()</span></code> is usually better. For this tutorial though, <codeclass="docutils literal notranslate"><spanclass="pre">self.caller.msg()</span></code> is more explicit in showing what is going on.</p>
</aside>
<p>Next we add the <codeclass="docutils literal notranslate"><spanclass="pre">func</span></code> method. It has one active line where it makes use of some of those variables the Command class offers to us. If you did the <aclass="reference internal"href="Beginner-Tutorial-Python-basic-introduction.html"><spanclass="doc std std-doc">basic Python tutorial</span></a>, you will recognize <codeclass="docutils literal notranslate"><spanclass="pre">.msg</span></code> - this will send a message to the object it is attached to us - in this case <codeclass="docutils literal notranslate"><spanclass="pre">self.caller</span></code>, that is, us. We grab <codeclass="docutils literal notranslate"><spanclass="pre">self.args</span></code> and includes that in the message.</p>
<p>Since we haven’t changed <codeclass="docutils literal notranslate"><spanclass="pre">MyCmdSet</span></code>, that will work as before. Reload and re-add this command to ourselves to try out the new version:</p>
<p>Note that there is an extra space before <codeclass="docutils literal notranslate"><spanclass="pre">Woo</span></code>. That is because self.args contains <em>everything</em> after the command name, including spaces. Let’s remove that extra space with a small tweak:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># in mygame/commands/mycommands.py</span>
<p>The only difference is that we called <codeclass="docutils literal notranslate"><spanclass="pre">.strip()</span></code> on <codeclass="docutils literal notranslate"><spanclass="pre">self.args</span></code>. This is a helper method available on all strings - it strips out all whitespace before and after the string. Now the Command-argument will no longer have any space in front of it.</p>
<p>Don’t forget to look at the help for the echo command:</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>> help echo
</pre></div>
</div>
<p>You will get the docstring you put in your Command-class!</p>
<sectionid="making-our-cmdset-persistent">
<h3><spanclass="section-number">8.1.1. </span>Making our cmdset persistent<aclass="headerlink"href="#making-our-cmdset-persistent"title="Permalink to this headline">¶</a></h3>
<p>It’s getting a little annoying to have to re-add our cmdset every time we reload, right? It’s simple enough to make <codeclass="docutils literal notranslate"><spanclass="pre">echo</span></code> a <em>persistent</em> change though:</p>
<p>Now you can <codeclass="docutils literal notranslate"><spanclass="pre">reload</span></code> as much as you want and your code changes will be available directly without needing to re-add the MyCmdSet again.</p>
<p>We will add this cmdset in another way, so remove it manually:</p>
<h3><spanclass="section-number">8.1.2. </span>Add the echo command to the default cmdset<aclass="headerlink"href="#add-the-echo-command-to-the-default-cmdset"title="Permalink to this headline">¶</a></h3>
<p>Above we added the <codeclass="docutils literal notranslate"><spanclass="pre">echo</span></code> command to ourselves. It will <em>only</em> be available to us and noone else in the game. But all commands in Evennia are part of command-sets, including the normal <codeclass="docutils literal notranslate"><spanclass="pre">look</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">py</span></code> commands we have been using all the while. You can easily extend the default command set with your <codeclass="docutils literal notranslate"><spanclass="pre">echo</span></code> command - this way <em>everyone</em> in the game will have access to it!</p>
<p>In <codeclass="docutils literal notranslate"><spanclass="pre">mygame/commands/</span></code> you’ll find an existing module named <codeclass="docutils literal notranslate"><spanclass="pre">default_cmdsets.py</span></code> Open it and you’ll find four empty cmdset-classes:</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">CharacterCmdSet</span></code> - this sits on all Characters (this is the one we usually want to modify)</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">AccountCmdSet</span></code> - this sits on all Accounts (shared between Characters, like <codeclass="docutils literal notranslate"><spanclass="pre">logout</span></code> etc)</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">UnloggedCmdSet</span></code> - commands available <em>before</em> you login, like the commands for creating your password and connecting to the game.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">SessionCmdSet</span></code> - commands unique to your Session (your particular client connection). This is unused by default.</p></li>
</ul>
<p>Tweak this file as follows:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># in mygame/commands/default_cmdsets.py </span>
<pclass="sidebar-title">super() and overriding defaults</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">super()</span></code> Python keyword means that the <em>parent</em> is called. In this case, the parent adds all default commands to this cmdset.</p>
<p>Coincidentally, this is also how you replace default commands in Evennia!jj To replace e.g. the command <codeclass="docutils literal notranslate"><spanclass="pre">get</span></code>, you just give your replacement command the <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code>‘get’ and add it here - since it’s added after <codeclass="docutils literal notranslate"><spanclass="pre">super()</span></code>, it will replace the default version of <codeclass="docutils literal notranslate"><spanclass="pre">get</span></code>.</p>
</aside>
<p>This works the same way as when you added <codeclass="docutils literal notranslate"><spanclass="pre">CmdEcho</span></code> to your <codeclass="docutils literal notranslate"><spanclass="pre">MyCmdSet</span></code>. The only difference cmdsets are automatically added to all Characters/Accounts etc so you don’t have to do so manually. We must also make sure to import the <codeclass="docutils literal notranslate"><spanclass="pre">CmdEcho</span></code> from your <codeclass="docutils literal notranslate"><spanclass="pre">mycommands</span></code> module in order for this module to know about it. The period ‘’<codeclass="docutils literal notranslate"><spanclass="pre">.</span></code>‘’ in <codeclass="docutils literal notranslate"><spanclass="pre">from</span><spanclass="pre">.</span><spanclass="pre">import</span><spanclass="pre">mycommands</span></code> means that we are telling Python that <codeclass="docutils literal notranslate"><spanclass="pre">mycommands.py</span></code> sits in the same directory as this current module. We want to import the entire module. Further down we access <codeclass="docutils literal notranslate"><spanclass="pre">mycommands.CmdEcho</span></code> to add it to the character cmdset.</p>
<p>Just <codeclass="docutils literal notranslate"><spanclass="pre">reload</span></code> the server and your <codeclass="docutils literal notranslate"><spanclass="pre">echo</span></code> command will be available again. There is no limit to how many cmdsets a given Command can be a part of.</p>
<p>To remove, you just comment out or delete the <codeclass="docutils literal notranslate"><spanclass="pre">self.add()</span></code> line. Keep it like this for now though - we’ll expand on it below.</p>
</section>
<sectionid="figuring-out-who-to-hit">
<h3><spanclass="section-number">8.1.3. </span>Figuring out who to hit<aclass="headerlink"href="#figuring-out-who-to-hit"title="Permalink to this headline">¶</a></h3>
<p>Let’s try something a little more exciting than just echo. Let’s make a <codeclass="docutils literal notranslate"><spanclass="pre">hit</span></code> command, for punching someone in the face! This is how we want it to work:</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>> hit <target>
You hit <target> with full force!
</pre></div>
</div>
<p>Not only that, we want the <codeclass="docutils literal notranslate"><spanclass="pre"><target></span></code> to see</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>You got hit by <hitter> with full force!
</pre></div>
</div>
<p>Here, <codeclass="docutils literal notranslate"><spanclass="pre"><hitter></span></code> would be the one using the <codeclass="docutils literal notranslate"><spanclass="pre">hit</span></code> command and <codeclass="docutils literal notranslate"><spanclass="pre"><target></span></code> is the one doing the punching; so if your name was <codeclass="docutils literal notranslate"><spanclass="pre">Anna</span></code>, and you hit someone named <codeclass="docutils literal notranslate"><spanclass="pre">Bob</span></code>, this would look like this:</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>> hit bob
You hit Bob with full force!
</pre></div>
</div>
<p>And Bob would see</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>You got hit by by Anna with full force!
</pre></div>
</div>
<p>Still in <codeclass="docutils literal notranslate"><spanclass="pre">mygame/commands/mycommands.py</span></code>, add a new class, between <codeclass="docutils literal notranslate"><spanclass="pre">CmdEcho</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">MyCmdSet</span></code>.</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># in mygame/commands/mycommands.py</span>
<spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"Who do you want to hit?"</span><spanclass="p">)</span>
<spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"You hit </span><spanclass="si">{</span><spanclass="n">target</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2"> with full force!"</span><spanclass="p">)</span>
<spanclass="n">target</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"You got hit by </span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2"> with full force!"</span><spanclass="p">)</span>
<spanclass="c1"># ...</span>
</pre></div>
</div>
<p>A lot of things to dissect here:</p>
<ulclass="simple">
<li><p><strong>Line 3</strong>: The normal <codeclass="docutils literal notranslate"><spanclass="pre">class</span></code> header. We inherit from <codeclass="docutils literal notranslate"><spanclass="pre">Command</span></code> which we imported at the top of this file.</p></li>
<li><p><strong>Lines 4-10</strong>: The docstring and help-entry for the command. You could expand on this as much as you wanted.</p></li>
<li><p><strong>Line 11</strong>: We want to write <codeclass="docutils literal notranslate"><spanclass="pre">hit</span></code> to use this command.</p></li>
<li><p><strong>Line 14</strong>: We strip the whitespace from the argument like before. Since we don’t want to have to do <codeclass="docutils literal notranslate"><spanclass="pre">self.args.strip()</span></code> over and over, we store the stripped version in a <em>local variable</em><codeclass="docutils literal notranslate"><spanclass="pre">args</span></code>. Note that we don’t modify <codeclass="docutils literal notranslate"><spanclass="pre">self.args</span></code> by doing this, <codeclass="docutils literal notranslate"><spanclass="pre">self.args</span></code> will still have the whitespace and is not the same as <codeclass="docutils literal notranslate"><spanclass="pre">args</span></code> in this example.</p></li>
<p>There can be any number of <codeclass="docutils literal notranslate"><spanclass="pre">elifs</span></code> to mark when different branches of the code should run. If <codeclass="docutils literal notranslate"><spanclass="pre">else</span></code> is provided, it will run if none of the other conditions were truthy.</p>
</aside>
<ulclass="simple">
<li><p><strong>Line 15</strong> has our first <em>conditional</em>, an <codeclass="docutils literal notranslate"><spanclass="pre">if</span></code> statement. This is written on the form <codeclass="docutils literal notranslate"><spanclass="pre">if</span><spanclass="pre"><condition>:</span></code> and only if that condition is ‘truthy’ will the indented code block under the <codeclass="docutils literal notranslate"><spanclass="pre">if</span></code> statement run. To learn what is truthy in Python it’s usually easier to learn what is “falsy”:</p>
<ul>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">False</span></code> - this is a reserved boolean word in Python. The opposite is <codeclass="docutils literal notranslate"><spanclass="pre">True</span></code>.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> - another reserved word. This represents nothing, a null-result or value.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">0</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">0.0</span></code></p></li>
<li><p>The empty strings <codeclass="docutils literal notranslate"><spanclass="pre">""</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">''</span></code>, or empty triple-strings like <codeclass="docutils literal notranslate"><spanclass="pre">""""""</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">''''''</span></code></p></li>
<li><p>Empty <em>iterables</em> we haven’t used yet, like empty lists <codeclass="docutils literal notranslate"><spanclass="pre">[]</span></code>, empty tuples <codeclass="docutils literal notranslate"><spanclass="pre">()</span></code> and empty dicts <codeclass="docutils literal notranslate"><spanclass="pre">{}</span></code>.</p></li>
<li><p>Everything else is “truthy”.</p></li>
</ul>
</li>
<li><p><strong>Line 16</strong>’s condition is <codeclass="docutils literal notranslate"><spanclass="pre">not</span><spanclass="pre">args</span></code>. The <codeclass="docutils literal notranslate"><spanclass="pre">not</span></code><em>inverses</em> the result, so if <codeclass="docutils literal notranslate"><spanclass="pre">args</span></code> is the empty string (falsy), the whole conditional becomes truthy. Let’s continue in the code:</p></li>
<li><p><strong>Lines 16-17</strong>: This code will only run if the <codeclass="docutils literal notranslate"><spanclass="pre">if</span></code> statement is truthy, in this case if <codeclass="docutils literal notranslate"><spanclass="pre">args</span></code> is the empty string.</p></li>
<li><p><strong>Line 17</strong>: <codeclass="docutils literal notranslate"><spanclass="pre">return</span></code> is a reserved Python word that exits <codeclass="docutils literal notranslate"><spanclass="pre">func</span></code> immediately.</p></li>
<li><p><strong>Line 18</strong>: We use <codeclass="docutils literal notranslate"><spanclass="pre">self.caller.search</span></code> to look for the target in the current location.</p></li>
<li><p><strong>Lines 19-20</strong>: A feature of <codeclass="docutils literal notranslate"><spanclass="pre">.search</span></code> is that it will already inform <codeclass="docutils literal notranslate"><spanclass="pre">self.caller</span></code> if it couldn’t find the target. In that case, <codeclass="docutils literal notranslate"><spanclass="pre">target</span></code> will be <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> and we should just directly <codeclass="docutils literal notranslate"><spanclass="pre">return</span></code>.</p></li>
<li><p><strong>Lines 21-22</strong>: At this point we have a suitable target and can send our punching strings to each.</p></li>
</ul>
<p>Finally we must also add this to a CmdSet. Let’s add it to <codeclass="docutils literal notranslate"><spanclass="pre">MyCmdSet</span></code>.</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># in mygame/commands/mycommands.py</span>
<p>With longer code snippets to try, it gets more and more likely you’ll
make an error and get a <codeclass="docutils literal notranslate"><spanclass="pre">traceback</span></code> when you reload. This will either appear
directly in-game or in your log (view it with <codeclass="docutils literal notranslate"><spanclass="pre">evennia</span><spanclass="pre">-l</span></code> in a terminal).
Don’t panic; tracebacks are your friends - they are to be read bottom-up and usually describe exactly where your problem is. Refer to <aclass="reference internal"href="Beginner-Tutorial-Python-basic-introduction.html"><spanclass="doc std std-doc">The Python introduction lesson</span></a> for more hints. If you get stuck, reach out to the Evennia community for help.</p>
</aside>
<p>Note that since we did <codeclass="docutils literal notranslate"><spanclass="pre">py</span><spanclass="pre">self.cmdset.remove("commands.mycommands.MyCmdSet")</span></code> earlier, this cmdset is no longer available on our Character. Instead we will add these commands directly to our default cmdset.</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># in mygame/commands/default_cmdsets.py </span>
<p>We changed from adding the individual <codeclass="docutils literal notranslate"><spanclass="pre">echo</span></code> command to adding the entire <codeclass="docutils literal notranslate"><spanclass="pre">MyCmdSet</span></code> in one go! This will add all commands in that cmdset to the <codeclass="docutils literal notranslate"><spanclass="pre">CharacterCmdSet</span></code> and is a practical way to add a lot of command in one go. Once you explore Evennia further, you’ll find that <aclass="reference internal"href="../../../Contribs/Contribs-Overview.html"><spanclass="doc std std-doc">Evennia contribs</span></a> all distribute their new commands in cmdsets, so you can easily add them to your game like this.</p>
<p>Next we reload to let Evennia know of these code changes and try it out:</p>