<h1>Web Client<aclass="headerlink"href="#web-client"title="Permalink to this headline">¶</a></h1>
<p>Evennia comes with a MUD client accessible from a normal web browser. During development you can try
it at <codeclass="docutils literal notranslate"><spanclass="pre">http://localhost:4001/webclient</span></code>. The client consists of several parts, all under
<p><codeclass="docutils literal notranslate"><spanclass="pre">templates/webclient/webclient.html</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">templates/webclient/base.html</span></code> are the very simplistic
django html templates describing the webclient layout.</p>
<p><codeclass="docutils literal notranslate"><spanclass="pre">static/webclient/js/evennia.js</span></code> is the main evennia javascript library. This handles all
communication between Evennia and the client over websockets and via AJAX/COMET if the browser can’t
handle websockets. It will make the Evennia object available to the javascript namespace, which
offers methods for sending and receiving data to/from the server transparently. This is intended to
be used also if swapping out the gui front end.</p>
<p><codeclass="docutils literal notranslate"><spanclass="pre">static/webclient/js/webclient_gui.js</span></code> is the default plugin manager. It adds the <codeclass="docutils literal notranslate"><spanclass="pre">plugins</span></code> and
<codeclass="docutils literal notranslate"><spanclass="pre">plugin_manager</span></code> objects to the javascript namespace, coordinates the GUI operations between the
various plugins, and uses the Evennia object library for all in/out.</p>
<p><codeclass="docutils literal notranslate"><spanclass="pre">static/webclient/js/plugins</span></code> provides a default set of plugins that implement a “telnet-like”
interface, and a couple of example plugins to show how you could implement new plugin features.</p>
<p><codeclass="docutils literal notranslate"><spanclass="pre">static/webclient/css/webclient.css</span></code> is the CSS file for the client; it also defines things like how
to display ANSI/Xterm256 colors etc.</p>
<p>The server-side webclient protocols are found in <codeclass="docutils literal notranslate"><spanclass="pre">evennia/server/portal/webclient.py</span></code> and
<codeclass="docutils literal notranslate"><spanclass="pre">webclient_ajax.py</span></code> for the two types of connections. You can’t (and should not need to) modify
these.</p>
<sectionid="customizing-the-web-client">
<h2>Customizing the web client<aclass="headerlink"href="#customizing-the-web-client"title="Permalink to this headline">¶</a></h2>
<p>Like was the case for the website, you override the webclient from your game directory. You need to
add/modify a file in the matching directory locations within your project’s <codeclass="docutils literal notranslate"><spanclass="pre">mygame/web/</span></code> directories.
These directories are NOT directly used by the web server when the game is running, the
server copies everything web related in the Evennia folder over to <codeclass="docutils literal notranslate"><spanclass="pre">mygame/server/.static/</span></code> and then
copies in all of your <codeclass="docutils literal notranslate"><spanclass="pre">mygame/web/</span></code> files. This can cause some cases were you edit a file, but it doesn’t
seem to make any difference in the servers behavior. <strong>Before doing anything else, try shutting
down the game and running <codeclass="docutils literal notranslate"><spanclass="pre">evennia</span><spanclass="pre">collectstatic</span></code> from the command line then start it back up, clear
your browser cache, and see if your edit shows up.</strong></p>
<p>Example: To change the list of in-use plugins, you need to override base.html by copying
<codeclass="docutils literal notranslate"><spanclass="pre">evennia/web/templates/webclient/base.html</span></code> to
<codeclass="docutils literal notranslate"><spanclass="pre">mygame/web/templates/webclient/base.html</span></code> and editing it to add your new plugin.</p>
<h2>Evennia Web Client API (from evennia.js)<aclass="headerlink"href="#evennia-web-client-api-from-evennia-js"title="Permalink to this headline">¶</a></h2>
<h2>Plugin Manager API (from webclient_gui.js)<aclass="headerlink"href="#plugin-manager-api-from-webclient-gui-js"title="Permalink to this headline">¶</a></h2>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">options</span></code> Object, Stores key/value ‘state’ that can be used by plugins to coordinate behavior.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">plugins</span></code> Object, key/value list of the all the loaded plugins.</p></li>
<h2>Plugin callbacks API<aclass="headerlink"href="#plugin-callbacks-api"title="Permalink to this headline">¶</a></h2>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">init()</span></code>– The only required callback</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">boolean</span><spanclass="pre">onKeydown(event)</span></code> This plugin listens for Keydown events</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">onBeforeUnload()</span></code> This plugin does something special just before the webclient page/tab is
closed.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">onLoggedIn(args,</span><spanclass="pre">kwargs)</span></code> This plugin does something when the webclient first logs in.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">onGotOptions(args,</span><spanclass="pre">kwargs)</span></code> This plugin does something with options sent from the server.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">boolean</span><spanclass="pre">onText(args,</span><spanclass="pre">kwargs)</span></code> This plugin does something with messages sent from the server.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">boolean</span><spanclass="pre">onPrompt(args,</span><spanclass="pre">kwargs)</span></code> This plugin does something when the server sends a prompt.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">boolean</span><spanclass="pre">onUnknownCmd(cmdname,</span><spanclass="pre">args,</span><spanclass="pre">kwargs)</span></code> This plugin does something with “unknown commands”.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">onConnectionClose(args,</span><spanclass="pre">kwargs)</span></code> This plugin does something when the webclient disconnects from
the server.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">newstring</span><spanclass="pre">onSend(string)</span></code> This plugin examines/alters text that other plugins generate. <strong>Use
with caution</strong></p></li>
</ul>
<p>The order of the plugins defined in <codeclass="docutils literal notranslate"><spanclass="pre">base.html</span></code> is important. All the callbacks for each plugin
will be executed in that order. Functions marked “boolean” above must return true/false. Returning
true will short-circuit the execution, so no other plugins lower in the base.html list will have
their callback for this event called. This enables things like the up/down arrow keys for the
history.js plugin to always occur before the default_in.js plugin adds that key to the current input
buffer.</p>
<sectionid="example-default-plugins-plugins-js">
<h3>Example/Default Plugins (<codeclass="docutils literal notranslate"><spanclass="pre">plugins/*.js</span></code>)<aclass="headerlink"href="#example-default-plugins-plugins-js"title="Permalink to this headline">¶</a></h3>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">clienthelp.js</span></code> Defines onOptionsUI from the options2 plugin. This is a mostly empty plugin to
add some “How To” information for your game.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">default_in.js</span></code> Defines onKeydown. <codeclass="docutils literal notranslate"><spanclass="pre"><enter></span></code> key or mouse clicking the arrow will send the currently typed text.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">default_out.js</span></code> Defines onText, onPrompt, and onUnknownCmd. Generates HTML output for the user.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">default_unload.js</span></code> Defines onBeforeUnload. Prompts the user to confirm that they meant to
leave/close the game.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">font.js</span></code> Defines onOptionsUI. The plugin adds the ability to select your font and font size.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">goldenlayout_default_config.js</span></code> Not actually a plugin, defines a global variable that
goldenlayout uses to determine its window layout, known tag routing, etc.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">goldenlayout.js</span></code> Defines onKeydown, onText and custom functions. A very powerful “tabbed” window manager for drag-n-drop windows, text routing and more.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">history.js</span></code> Defines onKeydown and onSend. Creates a history of past sent commands, and uses arrow keys to peruse.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">hotbuttons.js</span></code> Defines onGotOptions. A Disabled-by-default plugin that defines a button bar with
user-assignable commands.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">html.js</span></code> A basic plugin to allow the client to handle “raw html” messages from the server, this
allows the server to send native HTML messages like >div style=‘s’<styled text>/div<</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">iframe.js</span></code> Defines onOptionsUI. A goldenlayout-only plugin to create a restricted browsing sub-
window for a side-by-side web/text interface, mostly an example of how to build new HTML
“components” for goldenlayout.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">message_routing.js</span></code> Defines onOptionsUI, onText, onKeydown. This goldenlayout-only plugin
implements regex matching to allow users to “tag” arbitrary text that matches, so that it gets
routed to proper windows. Similar to “Spawn” functions for other clients.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">multimedia.js</span></code> An basic plugin to allow the client to handle “image” “audio” and “video” messages from the server and display them as inline HTML.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">notifications.js</span></code> Defines onText. Generates browser notification events for each new message
while the tab is hidden.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">oob.js</span></code> Defines onSend. Allows the user to test/send Out Of Band json messages to the server.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">options.js</span></code> Defines most callbacks. Provides a popup-based UI to coordinate options settings with the server.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">options2.js</span></code> Defines most callbacks. Provides a goldenlayout-based version of the options/settings tab. Integrates with other plugins via the custom onOptionsUI callback.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">popups.js</span></code> Provides default popups/Dialog UI for other plugins to use.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">text2html.js</span></code> Provides a new message handler type: <codeclass="docutils literal notranslate"><spanclass="pre">text2html</span></code>, similar to the multimedia and html plugins. This plugin provides a way to offload rendering the regular pipe-styled ASCII messages to the client. This allows the server to do less work, while also allowing the client a place to customize this conversion process. To use this plugin you will need to override the current commands in Evennia, changing any place where a raw text output message is generated and turn it into a <codeclass="docutils literal notranslate"><spanclass="pre">text2html</span></code> message. For example: <codeclass="docutils literal notranslate"><spanclass="pre">target.msg("my</span><spanclass="pre">text")</span></code> becomes: <codeclass="docutils literal notranslate"><spanclass="pre">target.msg(text2html=("my</span><spanclass="pre">text"))</span></code> (even better, use a webclient pane routing tag: <codeclass="docutils literal notranslate"><spanclass="pre">target.msg(text2html=("my</span><spanclass="pre">text",</span><spanclass="pre">{"type":</span><spanclass="pre">"sometag"}))</span></code>) <codeclass="docutils literal notranslate"><spanclass="pre">text2html</span></code> messages should format and behave identically to the server-side generated text2html() output.</p></li>
<h3>A side note on html messages vs text2html messages<aclass="headerlink"href="#a-side-note-on-html-messages-vs-text2html-messages"title="Permalink to this headline">¶</a></h3>
<p>So…lets say you have a desire to make your webclient output more like standard webpages…
For telnet clients, you could collect a bunch of text lines together, with ASCII formatted borders, etc. Then send the results to be rendered client-side via the text2html plugin.</p>
<p>But for webclients, you could format a message directly with the html plugin to render the whole thing as an HTML table, like so:</p>
<divclass="highlight-default notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># Server Side Python Code:</span>
<spanclass="n">tooltip</span><spanclass="p">:</span><spanclass="s1">'Input - The last input in the layout is always the default.'</span><spanclass="p">,</span>
<spanclass="n">tooltip</span><spanclass="p">:</span><spanclass="s1">'Input - The last input in the layout is always the default.'</span><spanclass="p">,</span>
<p>Remember, plugins are load-order dependent, so make sure the new <codeclass="docutils literal notranslate"><spanclass="pre"><script></span></code> tag comes before the <codeclass="docutils literal notranslate"><spanclass="pre">goldenlayout.js</span></code>.</p>
<p>Next, create a new plugin file <codeclass="docutils literal notranslate"><spanclass="pre">mygame/web/static/webclient/js/plugins/myplugin.js</span></code> and
<p>You can then add “mycomponent” to an item’s <codeclass="docutils literal notranslate"><spanclass="pre">componentName</span></code> in your <codeclass="docutils literal notranslate"><spanclass="pre">goldenlayout_default_config.js</span></code>.</p>
<p>Make sure to stop your server, evennia collectstatic, and restart your server. Then make sure to clear your browser cache before loading the webclient page.</p>