mirror of
https://github.com/evennia/evennia.git
synced 2026-03-19 06:16:31 +01:00
756 lines
No EOL
51 KiB
HTML
756 lines
No EOL
51 KiB
HTML
|
||
<!DOCTYPE html>
|
||
|
||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<title>Customize channels — Evennia 1.0-dev documentation</title>
|
||
<link rel="stylesheet" href="_static/alabaster.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="index" title="Index" href="genindex.html" />
|
||
<link rel="search" title="Search" href="search.html" />
|
||
|
||
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
|
||
|
||
|
||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||
|
||
</head><body>
|
||
|
||
|
||
<div class="document">
|
||
<div class="documentwrapper">
|
||
<div class="bodywrapper">
|
||
|
||
|
||
<div class="body" role="main">
|
||
|
||
<div class="section" id="customize-channels">
|
||
<h1>Customize channels<a class="headerlink" href="#customize-channels" title="Permalink to this headline">¶</a></h1>
|
||
</div>
|
||
<div class="section" id="channel-commands-in-evennia">
|
||
<h1>Channel commands in Evennia<a class="headerlink" href="#channel-commands-in-evennia" title="Permalink to this headline">¶</a></h1>
|
||
<p>By default, Evennia’s default channel commands are inspired by MUX. They all
|
||
begin with “c” followed by the action to perform (like “ccreate” or “cdesc”).
|
||
If this default seems strange to you compared to other Evennia commands that
|
||
rely on switches, you might want to check this tutorial out.</p>
|
||
<p>This tutorial will also give you insight into the workings of the channel system.
|
||
So it may be useful even if you don’t plan to make the exact changes shown here.</p>
|
||
<div class="section" id="what-we-will-try-to-do">
|
||
<h2>What we will try to do<a class="headerlink" href="#what-we-will-try-to-do" title="Permalink to this headline">¶</a></h2>
|
||
<p>Our mission: change the default channel commands to have a different syntax.</p>
|
||
<p>This tutorial will do the following changes:</p>
|
||
<ul class="simple">
|
||
<li><p>Remove all the default commands to handle channels.</p></li>
|
||
<li><p>Add a <code class="docutils literal notranslate"><span class="pre">+</span></code> and <code class="docutils literal notranslate"><span class="pre">-</span></code> command to join and leave a channel. So, assuming there is
|
||
a <code class="docutils literal notranslate"><span class="pre">public</span></code> channel on your game (most often the case), you could type <code class="docutils literal notranslate"><span class="pre">+public</span></code>
|
||
to join it and <code class="docutils literal notranslate"><span class="pre">-public</span></code> to leave it.</p></li>
|
||
<li><p>Group the commands to manipulate channels under the channel name, after a
|
||
switch. For instance, instead of writing <code class="docutils literal notranslate"><span class="pre">cdesc</span> <span class="pre">public</span> <span class="pre">=</span> <span class="pre">My</span> <span class="pre">public</span> <span class="pre">channel</span></code>,
|
||
you would write <code class="docutils literal notranslate"><span class="pre">public/desc</span> <span class="pre">My</span> <span class="pre">public</span> <span class="pre">channel</span></code>.</p></li>
|
||
</ul>
|
||
<blockquote>
|
||
<div><p>I listed removing the default Evennia commands as a first step in the
|
||
process. Actually, we’ll move it at the very bottom of the list, since we
|
||
still want to use them, we might get it wrong and rely on Evennia commands
|
||
for a while longer.</p>
|
||
</div></blockquote>
|
||
</div>
|
||
<div class="section" id="a-command-to-join-another-to-leave">
|
||
<h2>A command to join, another to leave<a class="headerlink" href="#a-command-to-join-another-to-leave" title="Permalink to this headline">¶</a></h2>
|
||
<p>We’ll do the most simple task at first: create two commands, one to join a
|
||
channel, one to leave.</p>
|
||
<blockquote>
|
||
<div><p>Why not have them as switches? <code class="docutils literal notranslate"><span class="pre">public/join</span></code> and <code class="docutils literal notranslate"><span class="pre">public/leave</span></code> for instance?</p>
|
||
</div></blockquote>
|
||
<p>For security reasons, I will hide channels to which the caller is not
|
||
connected. It means that if the caller is not connected to the “public”
|
||
channel, he won’t be able to use the “public” command. This is somewhat
|
||
standard: if we create an administrator-only channel, we don’t want players to
|
||
try (or even know) the channel command. Again, you could design it a different
|
||
way should you want to.</p>
|
||
<p>First create a file named <code class="docutils literal notranslate"><span class="pre">comms.py</span></code> in your <code class="docutils literal notranslate"><span class="pre">commands</span></code> package. It’s
|
||
a rather logical place, since we’ll write different commands to handle
|
||
communication.</p>
|
||
<p>Okay, let’s add the first command to join a channel:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18
|
||
19
|
||
20
|
||
21
|
||
22
|
||
23
|
||
24
|
||
25
|
||
26
|
||
27
|
||
28
|
||
29
|
||
30
|
||
31
|
||
32
|
||
33
|
||
34
|
||
35
|
||
36
|
||
37
|
||
38
|
||
39
|
||
40
|
||
41</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in commands/comms.py</span>
|
||
<span class="kn">from</span> <span class="nn">evennia.utils.search</span> <span class="kn">import</span> <span class="n">search_channel</span>
|
||
<span class="kn">from</span> <span class="nn">commands.command</span> <span class="kn">import</span> <span class="n">Command</span>
|
||
|
||
<span class="k">class</span> <span class="nc">CmdConnect</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> Connect to a channel.</span>
|
||
<span class="sd"> """</span>
|
||
|
||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"+"</span>
|
||
<span class="n">help_category</span> <span class="o">=</span> <span class="s2">"Comms"</span>
|
||
<span class="n">locks</span> <span class="o">=</span> <span class="s2">"cmd:not pperm(channel_banned)"</span>
|
||
<span class="n">auto_help</span> <span class="o">=</span> <span class="bp">False</span>
|
||
|
||
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="sd">"""Implement the command"""</span>
|
||
<span class="n">caller</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span>
|
||
<span class="n">args</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">args</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"Which channel do you want to connect to?"</span><span class="p">)</span>
|
||
<span class="k">return</span>
|
||
|
||
<span class="n">channelname</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</span>
|
||
<span class="n">channel</span> <span class="o">=</span> <span class="n">search_channel</span><span class="p">(</span><span class="n">channelname</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">channel</span><span class="p">:</span>
|
||
<span class="k">return</span>
|
||
|
||
<span class="c1"># Check permissions</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">channel</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s1">'listen'</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"</span><span class="si">%s</span><span class="s2">: You are not allowed to listen to this channel."</span> <span class="o">%</span> <span class="n">channel</span><span class="o">.</span><span class="n">key</span><span class="p">)</span>
|
||
<span class="k">return</span>
|
||
|
||
<span class="c1"># If not connected to the channel, try to connect</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">channel</span><span class="o">.</span><span class="n">has_connection</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">channel</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"</span><span class="si">%s</span><span class="s2">: You are not allowed to join this channel."</span> <span class="o">%</span> <span class="n">channel</span><span class="o">.</span><span class="n">key</span><span class="p">)</span>
|
||
<span class="k">return</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"You now are connected to the </span><span class="si">%s</span><span class="s2"> channel. "</span> <span class="o">%</span> <span class="n">channel</span><span class="o">.</span><span class="n">key</span><span class="o">.</span><span class="n">lower</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">msg</span><span class="p">(</span><span class="s2">"You already are connected to the </span><span class="si">%s</span><span class="s2"> channel. "</span> <span class="o">%</span> <span class="n">channel</span><span class="o">.</span><span class="n">key</span><span class="o">.</span><span class="n">lower</span><span class="p">())</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>Okay, let’s review this code, but if you’re used to Evennia commands, it shouldn’t be too strange:</p>
|
||
<ol class="simple">
|
||
<li><p>We import <code class="docutils literal notranslate"><span class="pre">search_channel</span></code>. This is a little helper function that we will use to search for channels by name and aliases, found in <code class="docutils literal notranslate"><span class="pre">evennia.utils.search</span></code>. It’s just more convenient.</p></li>
|
||
<li><p>Our class <code class="docutils literal notranslate"><span class="pre">CmdConnect</span></code> contains the body of our command to join a channel.</p></li>
|
||
<li><p>Notice the key of this command is simply <code class="docutils literal notranslate"><span class="pre">"+"</span></code>. When you enter <code class="docutils literal notranslate"><span class="pre">+something</span></code> in the game, it will try to find a command key <code class="docutils literal notranslate"><span class="pre">+something</span></code>. Failing that, it will look at other potential matches. Evennia is smart enough to understand that when we type <code class="docutils literal notranslate"><span class="pre">+something</span></code>, <code class="docutils literal notranslate"><span class="pre">+</span></code> is the command key and <code class="docutils literal notranslate"><span class="pre">something</span></code> is the command argument. This will, of course, fail if you have a command beginning by <code class="docutils literal notranslate"><span class="pre">+</span></code> conflicting with the <code class="docutils literal notranslate"><span class="pre">CmdConnect</span></code> key.</p></li>
|
||
<li><p>We have altered some class attributes, like <code class="docutils literal notranslate"><span class="pre">auto_help</span></code>. If you want to know what they do and why they have changed here, you can check the <a class="reference internal" href="Commands.html"><span class="doc">documentation on commands</span></a>.</p></li>
|
||
<li><p>In the command body, we begin by extracting the channel name. Remember that this name should be in the command arguments (that is, in <code class="docutils literal notranslate"><span class="pre">self.args</span></code>). Following the same example, if a player enters <code class="docutils literal notranslate"><span class="pre">+something</span></code>, <code class="docutils literal notranslate"><span class="pre">self.args</span></code> should contain <code class="docutils literal notranslate"><span class="pre">"something"</span></code>. We use <code class="docutils literal notranslate"><span class="pre">search_channel</span></code> to see if this channel exists.</p></li>
|
||
<li><p>We then check the access level of the channel, to see if the caller can listen to it (not necessarily use it to speak, mind you, just listen to others speak, as these are two different locks on Evennia).</p></li>
|
||
<li><p>Finally, we connect the caller if he’s not already connected to the channel. We use the channel’s <code class="docutils literal notranslate"><span class="pre">connect</span></code> method to do this. Pretty straightforward eh?</p></li>
|
||
</ol>
|
||
<p>Now we’ll add a command to leave a channel. It’s almost the same, turned upside down:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18
|
||
19
|
||
20
|
||
21
|
||
22
|
||
23
|
||
24
|
||
25
|
||
26
|
||
27
|
||
28
|
||
29
|
||
30
|
||
31
|
||
32</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">CmdDisconnect</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> Disconnect from a channel.</span>
|
||
<span class="sd"> """</span>
|
||
|
||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"-"</span>
|
||
<span class="n">help_category</span> <span class="o">=</span> <span class="s2">"Comms"</span>
|
||
<span class="n">locks</span> <span class="o">=</span> <span class="s2">"cmd:not pperm(channel_banned)"</span>
|
||
<span class="n">auto_help</span> <span class="o">=</span> <span class="bp">False</span>
|
||
|
||
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="sd">"""Implement the command"""</span>
|
||
<span class="n">caller</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span>
|
||
<span class="n">args</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">args</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"Which channel do you want to disconnect from?"</span><span class="p">)</span>
|
||
<span class="k">return</span>
|
||
|
||
<span class="n">channelname</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</span>
|
||
<span class="n">channel</span> <span class="o">=</span> <span class="n">search_channel</span><span class="p">(</span><span class="n">channelname</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">channel</span><span class="p">:</span>
|
||
<span class="k">return</span>
|
||
|
||
<span class="c1"># If connected to the channel, try to disconnect</span>
|
||
<span class="k">if</span> <span class="n">channel</span><span class="o">.</span><span class="n">has_connection</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">channel</span><span class="o">.</span><span class="n">disconnect</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"</span><span class="si">%s</span><span class="s2">: You are not allowed to disconnect from this channel."</span> <span class="o">%</span> <span class="n">channel</span><span class="o">.</span><span class="n">key</span><span class="p">)</span>
|
||
<span class="k">return</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"You stop listening to the </span><span class="si">%s</span><span class="s2"> channel. "</span> <span class="o">%</span> <span class="n">channel</span><span class="o">.</span><span class="n">key</span><span class="o">.</span><span class="n">lower</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">msg</span><span class="p">(</span><span class="s2">"You are not connected to the </span><span class="si">%s</span><span class="s2"> channel. "</span> <span class="o">%</span> <span class="n">channel</span><span class="o">.</span><span class="n">key</span><span class="o">.</span><span class="n">lower</span><span class="p">())</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>So far, you shouldn’t have trouble following what this command does: it’s
|
||
pretty much the same as the <code class="docutils literal notranslate"><span class="pre">CmdConnect</span></code> class in logic, though it accomplishes
|
||
the opposite. If you are connected to the channel <code class="docutils literal notranslate"><span class="pre">public</span></code> you could
|
||
disconnect from it using <code class="docutils literal notranslate"><span class="pre">-public</span></code>. Remember, you can use channel aliases too
|
||
(<code class="docutils literal notranslate"><span class="pre">+pub</span></code> and <code class="docutils literal notranslate"><span class="pre">-pub</span></code> will also work, assuming you have the alias <code class="docutils literal notranslate"><span class="pre">pub</span></code> on the
|
||
<code class="docutils literal notranslate"><span class="pre">public</span></code> channel).</p>
|
||
<p>It’s time to test this code, and to do so, you will need to add these two
|
||
commands. Here is a good time to say it: by default, Evennia connects accounts
|
||
to channels. Some other games (usually with a higher multisession mode) will
|
||
want to connect characters instead of accounts, so that several characters in
|
||
the same account can be connected to various channels. You can definitely add
|
||
these commands either in the <code class="docutils literal notranslate"><span class="pre">AccountCmdSet</span></code> or <code class="docutils literal notranslate"><span class="pre">CharacterCmdSet</span></code>, the caller
|
||
will be different and the command will add or remove accounts of characters.
|
||
If you decide to install these commands on the <code class="docutils literal notranslate"><span class="pre">CharacterCmdSet</span></code>, you might
|
||
have to disconnect your superuser account (account #1) from the channel before
|
||
joining it with your characters, as Evennia tends to subscribe all accounts
|
||
automatically if you don’t tell it otherwise.</p>
|
||
<p>So here’s an example of how to add these commands into your <code class="docutils literal notranslate"><span class="pre">AccountCmdSet</span></code>.
|
||
Edit the file <code class="docutils literal notranslate"><span class="pre">commands/default_cmdsets.py</span></code> to change a few things:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18
|
||
19
|
||
20
|
||
21
|
||
22
|
||
23
|
||
24
|
||
25</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># In commands/default_cmdsets.py</span>
|
||
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">default_cmds</span>
|
||
<span class="kn">from</span> <span class="nn">commands.comms</span> <span class="kn">import</span> <span class="n">CmdConnect</span><span class="p">,</span> <span class="n">CmdDisconnect</span>
|
||
|
||
|
||
<span class="c1"># ... Skip to the AccountCmdSet class ...</span>
|
||
|
||
<span class="k">class</span> <span class="nc">AccountCmdSet</span><span class="p">(</span><span class="n">default_cmds</span><span class="o">.</span><span class="n">AccountCmdSet</span><span class="p">):</span>
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> This is the cmdset available to the Account at all times. It is</span>
|
||
<span class="sd"> combined with the `CharacterCmdSet` when the Account puppets a</span>
|
||
<span class="sd"> Character. It holds game-account-specific commands, channel</span>
|
||
<span class="sd"> commands, etc.</span>
|
||
<span class="sd"> """</span>
|
||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"DefaultAccount"</span>
|
||
|
||
<span class="k">def</span> <span class="nf">at_cmdset_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> Populates the cmdset</span>
|
||
<span class="sd"> """</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"># Channel commands</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">CmdConnect</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">CmdDisconnect</span><span class="p">())</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>Save, reload your game, and you should be able to use <code class="docutils literal notranslate"><span class="pre">+public</span></code> and <code class="docutils literal notranslate"><span class="pre">-public</span></code>
|
||
now!</p>
|
||
</div>
|
||
<div class="section" id="a-generic-channel-command-with-switches">
|
||
<h2>A generic channel command with switches<a class="headerlink" href="#a-generic-channel-command-with-switches" title="Permalink to this headline">¶</a></h2>
|
||
<p>It’s time to dive a little deeper into channel processing. What happens in
|
||
Evennia when a player enters <code class="docutils literal notranslate"><span class="pre">public</span> <span class="pre">Hello</span> <span class="pre">everybody!</span></code>?</p>
|
||
<p>Like exits, channels are a particular command that Evennia automatically
|
||
creates and attaches to individual channels. So when you enter <code class="docutils literal notranslate"><span class="pre">public</span> <span class="pre">message</span></code> in your game, Evennia calls the <code class="docutils literal notranslate"><span class="pre">public</span></code> command.</p>
|
||
<blockquote>
|
||
<div><p>But I didn’t add any public command…</p>
|
||
</div></blockquote>
|
||
<p>Evennia will just create these commands automatically based on the existing
|
||
channels. The base command is the command we’ll need to edit.</p>
|
||
<blockquote>
|
||
<div><p>Why edit it? It works just fine to talk.</p>
|
||
</div></blockquote>
|
||
<p>Unfortunately, if we want to add switches to our channel names, we’ll have to
|
||
edit this command. It’s not too hard, however, we’ll just start writing a
|
||
standard command with minor twitches.</p>
|
||
<div class="section" id="some-additional-imports">
|
||
<h3>Some additional imports<a class="headerlink" href="#some-additional-imports" title="Permalink to this headline">¶</a></h3>
|
||
<p>You’ll need to add a line of import in your <code class="docutils literal notranslate"><span class="pre">commands/comms.py</span></code> file. We’ll
|
||
see why this import is important when diving in the command itself:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.comms.models</span> <span class="kn">import</span> <span class="n">ChannelDB</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
</div>
|
||
<div class="section" id="the-class-layout">
|
||
<h3>The class layout<a class="headerlink" href="#the-class-layout" title="Permalink to this headline">¶</a></h3>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18
|
||
19
|
||
20
|
||
21
|
||
22
|
||
23
|
||
24
|
||
25
|
||
26
|
||
27
|
||
28
|
||
29
|
||
30
|
||
31
|
||
32
|
||
33
|
||
34
|
||
35
|
||
36
|
||
37</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># In commands/comms.py</span>
|
||
<span class="k">class</span> <span class="nc">ChannelCommand</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> {channelkey} channel</span>
|
||
|
||
<span class="sd"> {channeldesc}</span>
|
||
|
||
<span class="sd"> Usage:</span>
|
||
<span class="sd"> {lower_channelkey} <message></span>
|
||
<span class="sd"> {lower_channelkey}/history [start]</span>
|
||
<span class="sd"> {lower_channelkey}/me <message></span>
|
||
<span class="sd"> {lower_channelkey}/who</span>
|
||
|
||
<span class="sd"> Switch:</span>
|
||
<span class="sd"> history: View 20 previous messages, either from the end or</span>
|
||
<span class="sd"> from <start> number of messages from the end.</span>
|
||
<span class="sd"> me: Perform an emote on this channel.</span>
|
||
<span class="sd"> who: View who is connected to this channel.</span>
|
||
|
||
<span class="sd"> Example:</span>
|
||
<span class="sd"> {lower_channelkey} Hello World!</span>
|
||
<span class="sd"> {lower_channelkey}/history</span>
|
||
<span class="sd"> {lower_channelkey}/history 30</span>
|
||
<span class="sd"> {lower_channelkey}/me grins.</span>
|
||
<span class="sd"> {lower_channelkey}/who</span>
|
||
<span class="sd"> """</span>
|
||
<span class="c1"># note that channeldesc and lower_channelkey will be filled</span>
|
||
<span class="c1"># automatically by ChannelHandler</span>
|
||
|
||
<span class="c1"># this flag is what identifies this cmd as a channel cmd</span>
|
||
<span class="c1"># and branches off to the system send-to-channel command</span>
|
||
<span class="c1"># (which is customizable by admin)</span>
|
||
<span class="n">is_channel</span> <span class="o">=</span> <span class="bp">True</span>
|
||
<span class="n">key</span> <span class="o">=</span> <span class="s2">"general"</span>
|
||
<span class="n">help_category</span> <span class="o">=</span> <span class="s2">"Channel Names"</span>
|
||
<span class="n">obj</span> <span class="o">=</span> <span class="bp">None</span>
|
||
<span class="n">arg_regex</span> <span class="o">=</span> <span class="s2">""</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>There are some differences here compared to most common commands.</p>
|
||
<ul class="simple">
|
||
<li><p>There is something disconcerting in the class docstring. Some information is
|
||
between curly braces. This is a format-style which is only used for channel
|
||
commands. <code class="docutils literal notranslate"><span class="pre">{channelkey}</span></code> will be replaced by the actual channel key (like
|
||
public). <code class="docutils literal notranslate"><span class="pre">{channeldesc}</span></code> will be replaced by the channel description (like
|
||
“public channel”). And <code class="docutils literal notranslate"><span class="pre">{lower_channelkey}</span></code>.</p></li>
|
||
<li><p>We have set <code class="docutils literal notranslate"><span class="pre">is_channel</span></code> to <code class="docutils literal notranslate"><span class="pre">True</span></code> in the command class variables. You
|
||
shouldn’t worry too much about that: it just tells Evennia this is a special
|
||
command just for channels.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">key</span></code> is a bit misleading because it will be replaced eventually. So we
|
||
could set it to virtually anything.</p></li>
|
||
<li><p>The <code class="docutils literal notranslate"><span class="pre">obj</span></code> class variable is another one we won’t detail right now.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">arg_regex</span></code> is important: the default <code class="docutils literal notranslate"><span class="pre">arg_regex</span></code> in the channel command will
|
||
forbid to use switches (a slash just after the channel name is not allowed).
|
||
That’s why we enforce it here, we allow any syntax.</p></li>
|
||
</ul>
|
||
<blockquote>
|
||
<div><p>What will become of this command?</p>
|
||
</div></blockquote>
|
||
<p>Well, when we’ll be through with it, and once we’ll add it as the default
|
||
command to handle channels, Evennia will create one per existing channel. For
|
||
instance, the public channel will receive one command of this class, with <code class="docutils literal notranslate"><span class="pre">key</span></code>
|
||
set to <code class="docutils literal notranslate"><span class="pre">public</span></code> and <code class="docutils literal notranslate"><span class="pre">aliases</span></code> set to the channel aliases (like <code class="docutils literal notranslate"><span class="pre">['pub']</span></code>).</p>
|
||
<blockquote>
|
||
<div><p>Can I see it work?</p>
|
||
</div></blockquote>
|
||
<p>Not just yet, there’s still a lot of code needed.</p>
|
||
<p>Okay we have the command structure but it’s rather empty.</p>
|
||
</div>
|
||
<div class="section" id="the-parse-method">
|
||
<h3>The parse method<a class="headerlink" href="#the-parse-method" title="Permalink to this headline">¶</a></h3>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">parse</span></code> method is called before <code class="docutils literal notranslate"><span class="pre">func</span></code> in every command. Its job is to
|
||
parse arguments and in our case, we will analyze switches here.</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># ...</span>
|
||
<span class="k">def</span> <span class="nf">parse</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> Simple parser</span>
|
||
<span class="sd"> """</span>
|
||
<span class="c1"># channel-handler sends channame:msg here.</span>
|
||
<span class="n">channelname</span><span class="p">,</span> <span class="n">msg</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">":"</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">switch</span> <span class="o">=</span> <span class="bp">None</span>
|
||
<span class="k">if</span> <span class="n">msg</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"/"</span><span class="p">):</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="n">switch</span><span class="p">,</span> <span class="n">msg</span> <span class="o">=</span> <span class="n">msg</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">" "</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
||
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
||
<span class="n">switch</span> <span class="o">=</span> <span class="n">msg</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span>
|
||
<span class="n">msg</span> <span class="o">=</span> <span class="s2">""</span>
|
||
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">switch</span> <span class="o">=</span> <span class="n">switch</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
|
||
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">args</span> <span class="o">=</span> <span class="p">(</span><span class="n">channelname</span><span class="o">.</span><span class="n">strip</span><span class="p">(),</span> <span class="n">msg</span><span class="o">.</span><span class="n">strip</span><span class="p">())</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>Reading the comments we see that the channel handler will send the command in a
|
||
strange way: a string with the channel name, a colon and the actual message
|
||
entered by the player. So if the player enters “public hello”, the command
|
||
<code class="docutils literal notranslate"><span class="pre">args</span></code> will contain <code class="docutils literal notranslate"><span class="pre">"public:hello"</span></code>. You can look at the way the channel name
|
||
and message are parsed, this can be used in a lot of different commands.</p>
|
||
<p>Next we check if there’s any switch, that is, if the message starts with a
|
||
slash. This would be the case if a player entered <code class="docutils literal notranslate"><span class="pre">public/me</span> <span class="pre">jumps</span> <span class="pre">up</span> <span class="pre">and</span> <span class="pre">down</span></code>, for instance. If there is a switch, we save it in <code class="docutils literal notranslate"><span class="pre">self.switch</span></code>. We
|
||
alter <code class="docutils literal notranslate"><span class="pre">self.args</span></code> at the end to contain a tuple with two values: the channel
|
||
name, and the message (if a switch was used, notice that the switch will be
|
||
stored in <code class="docutils literal notranslate"><span class="pre">self.switch</span></code>, not in the second element of <code class="docutils literal notranslate"><span class="pre">self.args</span></code>).</p>
|
||
</div>
|
||
<div class="section" id="the-command-func">
|
||
<h3>The command func<a class="headerlink" href="#the-command-func" title="Permalink to this headline">¶</a></h3>
|
||
<p>Finally, let’s see the <code class="docutils literal notranslate"><span class="pre">func</span></code> method in the command class. It will have to
|
||
handle switches and also the raw message to send if no switch was used.</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18
|
||
19
|
||
20
|
||
21
|
||
22
|
||
23
|
||
24
|
||
25
|
||
26
|
||
27
|
||
28
|
||
29
|
||
30
|
||
31
|
||
32
|
||
33
|
||
34
|
||
35
|
||
36
|
||
37
|
||
38
|
||
39
|
||
40
|
||
41
|
||
42
|
||
43</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># ...</span>
|
||
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> Create a new message and send it to channel, using</span>
|
||
<span class="sd"> the already formatted input.</span>
|
||
<span class="sd"> """</span>
|
||
<span class="n">channelkey</span><span class="p">,</span> <span class="n">msg</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</span>
|
||
<span class="n">caller</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span>
|
||
<span class="n">channel</span> <span class="o">=</span> <span class="n">ChannelDB</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get_channel</span><span class="p">(</span><span class="n">channelkey</span><span class="p">)</span>
|
||
|
||
<span class="c1"># Check that the channel exists</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">channel</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s2">"Channel '</span><span class="si">%s</span><span class="s2">' not found."</span><span class="p">)</span> <span class="o">%</span> <span class="n">channelkey</span><span class="p">)</span>
|
||
<span class="k">return</span>
|
||
|
||
<span class="c1"># Check that the caller is connected</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">channel</span><span class="o">.</span><span class="n">has_connection</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
||
<span class="n">string</span> <span class="o">=</span> <span class="s2">"You are not connected to channel '</span><span class="si">%s</span><span class="s2">'."</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">string</span> <span class="o">%</span> <span class="n">channelkey</span><span class="p">)</span>
|
||
<span class="k">return</span>
|
||
|
||
<span class="c1"># Check that the caller has send access</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">channel</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s1">'send'</span><span class="p">):</span>
|
||
<span class="n">string</span> <span class="o">=</span> <span class="s2">"You are not permitted to send to channel '</span><span class="si">%s</span><span class="s2">'."</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">string</span> <span class="o">%</span> <span class="n">channelkey</span><span class="p">)</span>
|
||
<span class="k">return</span>
|
||
|
||
<span class="c1"># Handle the various switches</span>
|
||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">switch</span> <span class="o">==</span> <span class="s2">"me"</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">msg</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"What do you want to do on this channel?"</span><span class="p">)</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="n">msg</span> <span class="o">=</span> <span class="s2">"{} {}"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">caller</span><span class="o">.</span><span class="n">key</span><span class="p">,</span> <span class="n">msg</span><span class="p">)</span>
|
||
<span class="n">channel</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="n">online</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
|
||
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">switch</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"{}: Invalid switch {}."</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">channel</span><span class="o">.</span><span class="n">key</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">switch</span><span class="p">))</span>
|
||
<span class="k">elif</span> <span class="ow">not</span> <span class="n">msg</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"Say what?"</span><span class="p">)</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="n">caller</span> <span class="ow">in</span> <span class="n">channel</span><span class="o">.</span><span class="n">mutelist</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"You currently have </span><span class="si">%s</span><span class="s2"> muted."</span> <span class="o">%</span> <span class="n">channel</span><span class="p">)</span>
|
||
<span class="k">return</span>
|
||
<span class="n">channel</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="n">senders</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="p">,</span> <span class="n">online</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<ul class="simple">
|
||
<li><p>First of all, we try to get the channel object from the channel name we have
|
||
in the <code class="docutils literal notranslate"><span class="pre">self.args</span></code> tuple. We use <code class="docutils literal notranslate"><span class="pre">ChannelDB.objects.get_channel</span></code> this time
|
||
because we know the channel name isn’t an alias (that was part of the deal,
|
||
<code class="docutils literal notranslate"><span class="pre">channelname</span></code> in the <code class="docutils literal notranslate"><span class="pre">parse</span></code> method contains a command key).</p></li>
|
||
<li><p>We check that the channel does exist.</p></li>
|
||
<li><p>We then check that the caller is connected to the channel. Remember, if the
|
||
caller isn’t connected, we shouldn’t allow him to use this command (that
|
||
includes the switches on channels).</p></li>
|
||
<li><p>We then check that the caller has access to the channel’s <code class="docutils literal notranslate"><span class="pre">send</span></code> lock. This
|
||
time, we make sure the caller can send messages to the channel, no matter what
|
||
operation he’s trying to perform.</p></li>
|
||
<li><p>Finally we handle switches. We try only one switch: <code class="docutils literal notranslate"><span class="pre">me</span></code>. This switch would
|
||
be used if a player entered <code class="docutils literal notranslate"><span class="pre">public/me</span> <span class="pre">jumps</span> <span class="pre">up</span> <span class="pre">and</span> <span class="pre">down</span></code> (to do a channel
|
||
emote).</p></li>
|
||
<li><p>We handle the case where the switch is unknown and where there’s no switch
|
||
(the player simply wants to talk on this channel).</p></li>
|
||
</ul>
|
||
<p>The good news: The code is not too complicated by itself. The bad news is that
|
||
this is just an abridged version of the code. If you want to handle all the
|
||
switches mentioned in the command help, you will have more code to write. This
|
||
is left as an exercise.</p>
|
||
</div>
|
||
<div class="section" id="end-of-class">
|
||
<h3>End of class<a class="headerlink" href="#end-of-class" title="Permalink to this headline">¶</a></h3>
|
||
<p>It’s almost done, but we need to add a method in this command class that isn’t
|
||
often used. I won’t detail it’s usage too much, just know that Evennia will use
|
||
it and will get angry if you don’t add it. So at the end of your class, just
|
||
add:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># ...</span>
|
||
<span class="k">def</span> <span class="nf">get_extra_info</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">caller</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> Let users know that this command is for communicating on a channel.</span>
|
||
|
||
<span class="sd"> Args:</span>
|
||
<span class="sd"> caller (TypedObject): A Character or Account who has entered an ambiguous command.</span>
|
||
|
||
<span class="sd"> Returns:</span>
|
||
<span class="sd"> A string with identifying information to disambiguate the object, conventionally with a preceding space.</span>
|
||
<span class="sd"> """</span>
|
||
<span class="k">return</span> <span class="s2">" (channel)"</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
</div>
|
||
<div class="section" id="adding-this-channel-command">
|
||
<h3>Adding this channel command<a class="headerlink" href="#adding-this-channel-command" title="Permalink to this headline">¶</a></h3>
|
||
<p>Contrary to most Evennia commands, we won’t add our <code class="docutils literal notranslate"><span class="pre">ChannelCommand</span></code> to a
|
||
<code class="docutils literal notranslate"><span class="pre">CmdSet</span></code>. Instead we need to tell Evennia that it should use the command we
|
||
just created instead of its default channel-command.</p>
|
||
<p>In your <code class="docutils literal notranslate"><span class="pre">server/conf/settings.py</span></code> file, add a new setting:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># Channel options</span>
|
||
<span class="n">CHANNEL_COMMAND_CLASS</span> <span class="o">=</span> <span class="s2">"commands.comms.ChannelCommand"</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>Then you can reload your game. Try to type <code class="docutils literal notranslate"><span class="pre">public</span> <span class="pre">hello</span></code> and <code class="docutils literal notranslate"><span class="pre">public/me</span> <span class="pre">jumps</span> <span class="pre">up</span> <span class="pre">and</span> <span class="pre">down</span></code>. Don’t forget to enter <code class="docutils literal notranslate"><span class="pre">help</span> <span class="pre">public</span></code> to see if your command has
|
||
truly been added.</p>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="conclusion-and-full-code">
|
||
<h2>Conclusion and full code<a class="headerlink" href="#conclusion-and-full-code" title="Permalink to this headline">¶</a></h2>
|
||
<p>That was some adventure! And there’s still things to do! But hopefully, this
|
||
tutorial will have helped you in designing your own channel system. Here are a
|
||
few things to do:</p>
|
||
<ul class="simple">
|
||
<li><p>Add more switches to handle various actions, like changing the description of
|
||
a channel for instance, or listing the connected participants.</p></li>
|
||
<li><p>Remove the default Evennia commands to handle channels.</p></li>
|
||
<li><p>Alter the behavior of the channel system so it better aligns with what you
|
||
want to do.</p></li>
|
||
</ul>
|
||
<p>As a special bonus, you can find a full, working example of a communication
|
||
system similar to the one I’ve shown you: this is a working example, it
|
||
integrates all switches and does ever some extra checking, but it’s also very
|
||
close from the code I’ve provided here. Notice, however, that this resource is
|
||
external to Evennia and not maintained by anyone but the original author of
|
||
this article.</p>
|
||
<p><a class="reference external" href="https://github.com/vincent-lg/avenew/blob/master/commands/comms.py">Read the full example on Github</a></p>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||
<div class="sphinxsidebarwrapper">
|
||
<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="#">Customize channels</a></li>
|
||
<li><a class="reference internal" href="#channel-commands-in-evennia">Channel commands in Evennia</a><ul>
|
||
<li><a class="reference internal" href="#what-we-will-try-to-do">What we will try to do</a></li>
|
||
<li><a class="reference internal" href="#a-command-to-join-another-to-leave">A command to join, another to leave</a></li>
|
||
<li><a class="reference internal" href="#a-generic-channel-command-with-switches">A generic channel command with switches</a><ul>
|
||
<li><a class="reference internal" href="#some-additional-imports">Some additional imports</a></li>
|
||
<li><a class="reference internal" href="#the-class-layout">The class layout</a></li>
|
||
<li><a class="reference internal" href="#the-parse-method">The parse method</a></li>
|
||
<li><a class="reference internal" href="#the-command-func">The command func</a></li>
|
||
<li><a class="reference internal" href="#end-of-class">End of class</a></li>
|
||
<li><a class="reference internal" href="#adding-this-channel-command">Adding this channel command</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#conclusion-and-full-code">Conclusion and full code</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<div class="relations">
|
||
<h3>Related Topics</h3>
|
||
<ul>
|
||
<li><a href="index.html">Documentation overview</a><ul>
|
||
</ul></li>
|
||
</ul>
|
||
</div>
|
||
<div role="note" aria-label="source link">
|
||
<!--h3>This Page</h3-->
|
||
<ul class="this-page-menu">
|
||
<li><a href="_sources/Customize-channels.md.txt"
|
||
rel="nofollow">Show Page Source</a></li>
|
||
</ul>
|
||
</div>
|
||
<h3>Versions</h3>
|
||
<ul>
|
||
<li><a href="Customize-channels.html">1.0-dev (develop branch)</a></li>
|
||
<li><a href="../../versions/0.9.1/index.html">0.9.1 (master branch)</a></li>
|
||
</ul>
|
||
|
||
</div>
|
||
</div>
|
||
<div class="clearer"></div>
|
||
</div>
|
||
<div class="footer">
|
||
©2020, The Evennia developer community.
|
||
|
||
|
|
||
Powered by <a href="http://sphinx-doc.org/">Sphinx 2.4.4</a>
|
||
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
||
|
||
|
|
||
<a href="_sources/Customize-channels.md.txt"
|
||
rel="nofollow">Page source</a>
|
||
</div>
|
||
|
||
|
||
|
||
|
||
</body>
|
||
</html> |