mirror of
https://github.com/evennia/evennia.git
synced 2026-04-01 13:37:17 +02:00
323 lines
No EOL
18 KiB
HTML
323 lines
No EOL
18 KiB
HTML
|
||
<!DOCTYPE html>
|
||
|
||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<title>Evennia for Diku Users — 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="evennia-for-diku-users">
|
||
<h1>Evennia for Diku Users<a class="headerlink" href="#evennia-for-diku-users" title="Permalink to this headline">¶</a></h1>
|
||
<p>Evennia represents a learning curve for those who used to code on <a class="reference external" href="https://en.wikipedia.org/wiki/DikuMUD">Diku</a> type MUDs. While coding in Python is easy if you already know C, the main effort is to get rid of old C programming habits. Trying to code Python the way you code C will not only look ugly, it will lead to less optimal and harder to maintain code. Reading Evennia example code is a good way to get a feel for how different problems are approached in Python.</p>
|
||
<p>Overall, Python offers an extensive library of resources, safe memory management and excellent handling of errors. While Python code does not run as fast as raw C code does, the difference is not all that important for a text-based game. The main advantage of Python is an extremely fast development cycle with and easy ways to create game systems that would take many times more code and be much harder to make stable and maintainable in C.</p>
|
||
<div class="section" id="core-differences">
|
||
<h2>Core Differences<a class="headerlink" href="#core-differences" title="Permalink to this headline">¶</a></h2>
|
||
<ul class="simple">
|
||
<li><p>As mentioned, the main difference between Evennia and a Diku-derived codebase is that Evennia is written purely in Python. Since Python is an interpreted language there is no compile stage. It is modified and extended by the server loading Python modules at run-time. It also runs on all computer platforms Python runs on (which is basically everywhere).</p></li>
|
||
<li><p>Vanilla Diku type engines save their data in custom <em>flat file</em> type storage solutions. By contrast, Evennia stores all game data in one of several supported SQL databases. Whereas flat files have the advantage of being easier to implement, they (normally) lack many expected safety features and ways to effectively extract subsets of the stored data. For example, if the server loses power while writing to a flatfile it may become corrupt and the data lost. A proper database solution is not susceptible to this - at no point is the data in a state where it cannot be recovered. Databases are also highly optimized for querying large data sets efficiently.</p></li>
|
||
</ul>
|
||
</div>
|
||
<div class="section" id="some-familiar-things">
|
||
<h2>Some Familiar Things<a class="headerlink" href="#some-familiar-things" title="Permalink to this headline">¶</a></h2>
|
||
<p>Diku expresses the character object referenced normally by:</p>
|
||
<p><code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">char</span> <span class="pre">ch*</span></code> then all character-related fields can be accessed by <code class="docutils literal notranslate"><span class="pre">ch-></span></code>. In Evennia, one must pay attention to what object you are using, and when you are accessing another through back-handling, that you are accessing the right object. In Diku C, accessing character object is normally done by:</p>
|
||
<div class="highlight-c notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="cm">/* creating pointer of both character and room struct */</span>
|
||
|
||
<span class="kt">void</span><span class="p">(</span><span class="k">struct</span> <span class="kt">char</span> <span class="n">ch</span><span class="o">*</span><span class="p">,</span> <span class="k">struct</span> <span class="n">room</span> <span class="n">room</span><span class="o">*</span><span class="p">){</span>
|
||
<span class="kt">int</span> <span class="n">dam</span><span class="p">;</span>
|
||
<span class="k">if</span> <span class="p">(</span><span class="n">ROOM_FLAGGED</span><span class="p">(</span><span class="n">room</span><span class="p">,</span> <span class="n">ROOM_LAVA</span><span class="p">)){</span>
|
||
<span class="n">dam</span> <span class="o">=</span> <span class="mi">100</span>
|
||
<span class="n">ch</span><span class="o">-></span><span class="n">damage_taken</span> <span class="o">=</span> <span class="n">dam</span>
|
||
<span class="p">};</span>
|
||
<span class="p">};</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>As an example for creating Commands in Evennia via the <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">evennia</span> <span class="pre">import</span> <span class="pre">Command</span></code> the character object that calls the command is denoted by a class property as <code class="docutils literal notranslate"><span class="pre">self.caller</span></code>. In this example <code class="docutils literal notranslate"><span class="pre">self.caller</span></code> is essentially the ‘object’ that has called the Command, but most of the time it is an Account object. For a more familiar Diku feel, create a variable that becomes the account object as:</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</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1">#mygame/commands/command.py</span>
|
||
|
||
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">Command</span>
|
||
|
||
<span class="k">class</span> <span class="nc">CmdMyCmd</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> This is a Command Evennia Object</span>
|
||
<span class="sd"> """</span>
|
||
|
||
<span class="p">[</span><span class="o">...</span><span class="p">]</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="n">ch</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span>
|
||
<span class="c1"># then you can access the account object directly by using the familiar ch.</span>
|
||
<span class="n">ch</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"..."</span><span class="p">)</span>
|
||
<span class="n">account_name</span> <span class="o">=</span> <span class="n">ch</span><span class="o">.</span><span class="n">name</span>
|
||
<span class="n">race</span> <span class="o">=</span> <span class="n">ch</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">race</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>As mentioned above, care must be taken what specific object you are working with. If focused on a room object and you need to access the account object:</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</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1">#mygame/typeclasses/room.py</span>
|
||
|
||
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">DefaultRoom</span>
|
||
|
||
<span class="k">class</span> <span class="nc">MyRoom</span><span class="p">(</span><span class="n">DefaultRoom</span><span class="p">):</span>
|
||
<span class="p">[</span><span class="o">...</span><span class="p">]</span>
|
||
|
||
<span class="k">def</span> <span class="nf">is_account_object</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">object</span><span class="p">):</span>
|
||
<span class="c1"># a test to see if object is an account</span>
|
||
<span class="p">[</span><span class="o">...</span><span class="p">]</span>
|
||
|
||
<span class="k">def</span> <span class="nf">myMethod</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="c1">#self.caller would not make any sense, since self refers to the</span>
|
||
<span class="c1"># object of 'DefaultRoom', you must find the character obj first:</span>
|
||
<span class="k">for</span> <span class="n">ch</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_account_object</span><span class="p">(</span><span class="n">ch</span><span class="p">):</span>
|
||
<span class="c1"># now you can access the account object with ch:</span>
|
||
<span class="n">account_name</span> <span class="o">=</span> <span class="n">ch</span><span class="o">.</span><span class="n">name</span>
|
||
<span class="n">race</span> <span class="o">=</span> <span class="n">ch</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">race</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
</div>
|
||
<div class="section" id="emulating-evennia-to-look-and-feel-like-a-diku-rom">
|
||
<h2>Emulating Evennia to Look and Feel Like A Diku/ROM<a class="headerlink" href="#emulating-evennia-to-look-and-feel-like-a-diku-rom" title="Permalink to this headline">¶</a></h2>
|
||
<p>To emulate a Diku Mud on Evennia some work has to be done before hand. If there is anything that all coders and builders remember from Diku/Rom days is the presence of VNUMs. Essentially all data was saved in flat files and indexed by VNUMs for easy access. Evennia has the ability to emulate VNUMS to the extent of categorising rooms/mobs/objs/trigger/zones[…] into vnum ranges.</p>
|
||
<p>Evennia has objects that are called Scripts. As defined, they are the ‘out of game’ instances that exist within the mud, but never directly interacted with. Scripts can be used for timers, mob AI, and even a stand alone databases.</p>
|
||
<p>Because of their wonderful structure all mob, room, zone, triggers, etc.. data can be saved in independently created global scripts.</p>
|
||
<p>Here is a sample mob file from a Diku Derived flat file.</p>
|
||
<div class="highlight-text 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</pre></div></td><td class="code"><div class="highlight"><pre><span></span>#0
|
||
mob0~
|
||
mob0~
|
||
mob0
|
||
~
|
||
Mob0
|
||
~
|
||
10 0 0 0 0 0 0 0 0 E
|
||
1 20 9 0d0+10 1d2+0
|
||
10 100
|
||
8 8 0
|
||
E
|
||
#1
|
||
Puff dragon fractal~
|
||
Puff~
|
||
Puff the Fractal Dragon is here, contemplating a higher reality.
|
||
~
|
||
Is that some type of differential curve involving some strange, and unknown
|
||
calculus that she seems to be made out of?
|
||
~
|
||
516106 0 0 0 2128 0 0 0 1000 E
|
||
34 9 -10 6d6+340 5d5+5
|
||
340 115600
|
||
8 8 2
|
||
BareHandAttack: 12
|
||
E
|
||
T 95
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>Each line represents something that the MUD reads in and does something with it. This isn’t easy to read, but let’s see if we can emulate this as a dictionary to be stored on a database script created in Evennia.</p>
|
||
<p>First, let’s create a global script that does absolutely nothing and isn’t attached to anything. You can either create this directly in-game with the @py command or create it in another file to do some checks and balances if for whatever reason the script needs to be created again. Progmatically it can be done like so:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2
|
||
3
|
||
4
|
||
5</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">create_script</span>
|
||
|
||
<span class="n">mob_db</span> <span class="o">=</span> <span class="n">create_script</span><span class="p">(</span><span class="s2">"typeclasses.scripts.DefaultScript"</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">"mobdb"</span><span class="p">,</span>
|
||
<span class="n">persistent</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">obj</span><span class="o">=</span><span class="bp">None</span><span class="p">)</span>
|
||
<span class="n">mob_db</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">vnums</span> <span class="o">=</span> <span class="p">{}</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>Just by creating a simple script object and assigning it a ‘vnums’ attribute as a type dictionary. Next we have to create the mob layout..</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</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># vnum : mob_data</span>
|
||
|
||
<span class="n">mob_vnum_1</span> <span class="o">=</span> <span class="p">{</span>
|
||
<span class="s1">'key'</span> <span class="p">:</span> <span class="s1">'puff'</span><span class="p">,</span>
|
||
<span class="s1">'sdesc'</span> <span class="p">:</span> <span class="s1">'puff the fractal dragon'</span><span class="p">,</span>
|
||
<span class="s1">'ldesc'</span> <span class="p">:</span> <span class="s1">'Puff the Fractal Dragon is here, '</span> \
|
||
<span class="s1">'contemplating a higher reality.'</span><span class="p">,</span>
|
||
<span class="s1">'ddesc'</span> <span class="p">:</span> <span class="s1">' Is that some type of differential curve '</span> \
|
||
<span class="s1">'involving some strange, and unknown calculus '</span> \
|
||
<span class="s1">'that she seems to be made out of?'</span><span class="p">,</span>
|
||
<span class="p">[</span><span class="o">...</span><span class="p">]</span>
|
||
<span class="p">}</span>
|
||
|
||
<span class="c1"># Then saving it to the data, assuming you have the script obj stored in a variable.</span>
|
||
<span class="n">mob_db</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">vnums</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">mob_vnum_1</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>This is a very ‘caveman’ example, but it gets the idea across. You can use the keys in the <code class="docutils literal notranslate"><span class="pre">mob_db.vnums</span></code> to act as the mob vnum while the rest contains the data..</p>
|
||
<p>Much simpler to read and edit. If you plan on taking this route, you must keep in mind that by default evennia ‘looks’ at different properties when using the <code class="docutils literal notranslate"><span class="pre">look</span></code> command for instance. If you create an instance of this mob and make its <code class="docutils literal notranslate"><span class="pre">self.key</span> <span class="pre">=</span> <span class="pre">1</span></code>, by default evennia will say</p>
|
||
<p><code class="docutils literal notranslate"><span class="pre">Here</span> <span class="pre">is</span> <span class="pre">:</span> <span class="pre">1</span></code></p>
|
||
<p>You must restructure all default commands so that the mud looks at different properties defined on your mob.</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="#">Evennia for Diku Users</a><ul>
|
||
<li><a class="reference internal" href="#core-differences">Core Differences</a></li>
|
||
<li><a class="reference internal" href="#some-familiar-things">Some Familiar Things</a></li>
|
||
<li><a class="reference internal" href="#emulating-evennia-to-look-and-feel-like-a-diku-rom">Emulating Evennia to Look and Feel Like A Diku/ROM</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/Evennia-for-Diku-Users.md.txt"
|
||
rel="nofollow">Show Page Source</a></li>
|
||
</ul>
|
||
</div>
|
||
<h3>Versions</h3>
|
||
<ul>
|
||
<li><a href="Evennia-for-Diku-Users.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/Evennia-for-Diku-Users.md.txt"
|
||
rel="nofollow">Page source</a>
|
||
</div>
|
||
|
||
|
||
|
||
|
||
</body>
|
||
</html> |