evennia/docs/1.0-dev/Components/Sessions.html
Evennia docbuilder action 41ca2163d3 Updated HTML docs.
2022-11-26 14:42:25 +00:00

342 lines
No EOL
27 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

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

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Sessions &#8212; Evennia 1.0-dev documentation</title>
<link rel="stylesheet" href="../_static/nature.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Accounts" href="Accounts.html" />
<link rel="prev" title="Typeclasses" href="Typeclasses.html" />
</head><body>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="Accounts.html" title="Accounts"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="Typeclasses.html" title="Typeclasses"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="Components-Overview.html" accesskey="U">Core Components</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Sessions</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/evennia_logo.png" alt="Logo"/>
</a></p>
<div id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" />
<input type="submit" value="Go" />
</form>
</div>
</div>
<script>$('#searchbox').show(0);</script>
<h3><a href="../index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Sessions</a><ul>
<li><a class="reference internal" href="#properties-on-sessions">Properties on Sessions</a></li>
<li><a class="reference internal" href="#multisession-mode">Multisession mode</a></li>
<li><a class="reference internal" href="#returning-data-to-the-session">Returning data to the session</a></li>
<li><a class="reference internal" href="#customizing-the-session-object">Customizing the Session object</a></li>
<li><a class="reference internal" href="#portal-and-server-sessions">Portal and Server Sessions</a></li>
<li><a class="reference internal" href="#sessionhandlers">Sessionhandlers</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="Typeclasses.html"
title="previous chapter">Typeclasses</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="Accounts.html"
title="next chapter">Accounts</a></p>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="../_sources/Components/Sessions.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div><h3>Links</h3>
<ul>
<li><a href="https://www.evennia.com">Home page</a> </li>
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
<li><a href="http://games.evennia.com">Game Index</a> </li>
<li>
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
<a href="https://evennia.blogspot.com/">Blog</a>
</li>
</ul>
<h3>Versions</h3>
<ul>
<li><a href="Sessions.html">1.0-dev (develop branch)</a></li>
<ul>
<li><a href="../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
</ul>
</div>
</div>
<div class="bodywrapper">
<div class="body" role="main">
<section class="tex2jax_ignore mathjax_ignore" id="sessions">
<h1>Sessions<a class="headerlink" href="#sessions" title="Permalink to this headline"></a></h1>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>┌──────┐ │ ┌───────┐ ┌───────┐ ┌──────┐
│Client├─┼──►│Session├───►│Account├──►│Object│
└──────┘ │ └───────┘ └───────┘ └──────┘
^
</pre></div>
</div>
<p>An Evennia <em>Session</em> represents one single established connection to the server. Depending on the
Evennia session, it is possible for a person to connect multiple times, for example using different
clients in multiple windows. Each such connection is represented by a session object.</p>
<p>A session object has its own <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">cmdset</span></a>, usually the “unloggedin” cmdset. This is what is used to show the login screen and to handle commands to create a new account (or <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Account</span></a> in evennia lingo) read initial help and to log into the game with an existing account. A session object can either be “logged in” or not. Logged in means that the user has authenticated. When this happens the session is associated with an Account object (which is what holds account-centric stuff). The account can then in turn puppet any number of objects/characters.</p>
<p>A Session is not <em>persistent</em> - it is not a <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclass</span></a> and has no connection to the database. The Session will go away when a user disconnects and you will lose any custom data on it if the server reloads. The <code class="docutils literal notranslate"><span class="pre">.db</span></code> handler on Sessions is there to present a uniform API (so you can assume <code class="docutils literal notranslate"><span class="pre">.db</span></code> exists even if you dont know if you receive an Object or a Session), but this is just an alias to <code class="docutils literal notranslate"><span class="pre">.ndb</span></code>. So dont store any data on Sessions that you cant afford to lose in a reload.</p>
<section id="properties-on-sessions">
<h2>Properties on Sessions<a class="headerlink" href="#properties-on-sessions" title="Permalink to this headline"></a></h2>
<p>Here are some important properties available on (Server-)Sessions</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">sessid</span></code> - The unique session-id. This is an integer starting from 1.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">address</span></code> - The connected clients address. Different protocols give different information here.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">logged_in</span></code> - <code class="docutils literal notranslate"><span class="pre">True</span></code> if the user authenticated to this session.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">account</span></code> - The <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Account</span></a> this Session is attached to. If not logged in yet, this is
<code class="docutils literal notranslate"><span class="pre">None</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">puppet</span></code> - The <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Character/Object</span></a> currently puppeted by this Account/Session combo. If
not logged in or in OOC mode, this is <code class="docutils literal notranslate"><span class="pre">None</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">ndb</span></code> - The <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Non-persistent Attribute</span></a> handler.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">db</span></code> - As noted above, Sessions dont have regular Attributes. This is an alias to <code class="docutils literal notranslate"><span class="pre">ndb</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">cmdset</span></code> - The Sessions <a class="reference internal" href="Command-Sets.html"><span class="doc std std-doc">CmdSetHandler</span></a></p></li>
</ul>
<p>Session statistics are mainly used internally by Evennia.</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">conn_time</span></code> - How long this Session has been connected</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">cmd_last</span></code> - Last active time stamp. This will be reset by sending <code class="docutils literal notranslate"><span class="pre">idle</span></code> keepalives.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">cmd_last_visible</span></code> - last active time stamp. This ignores <code class="docutils literal notranslate"><span class="pre">idle</span></code> keepalives and representes the
last time this session was truly visibly active.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">cmd_total</span></code> - Total number of Commands passed through this Session.</p></li>
</ul>
</section>
<section id="multisession-mode">
<h2>Multisession mode<a class="headerlink" href="#multisession-mode" title="Permalink to this headline"></a></h2>
<p>The number of sessions possible to connect to a given account at the same time and how it works is given by the <code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE</span></code> setting:</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE=0</span></code>: One session per account. When connecting with a new session the old one is disconnected. This is the default mode and emulates many classic mud code bases.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>┌──────┐ │ ┌───────┐ ┌───────┐ ┌─────────┐
│Client├─┼──►│Session├───►│Account├──►│Character│
└──────┘ │ └───────┘ └───────┘ └─────────┘
</pre></div>
</div>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE=1</span></code>: Many sessions per account, input/output from/to each session is treated the same. For the player this means they can connect to the game from multiple clients and see the same output in all of them. The result of a command given in one client (that is, through one Session) will be returned to <em>all</em> connected Sessions/clients with no distinction.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
┌──────┐ │ ┌───────┐
│Client├─┼──►│Session├──┐
└──────┘ │ └───────┘ └──►┌───────┐ ┌─────────┐
│ │Account├──►│Character│
┌──────┐ │ ┌───────┐ ┌──►└───────┘ └─────────┘
│Client├─┼──►│Session├──┘
└──────┘ │ └───────┘
</pre></div>
</div>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE=2</span></code>: Many sessions per account, one character per session. In this mode, puppeting an Object/Character will link the puppet back only to the particular Session doing the puppeting. That is, input from that Session will make use of the CmdSet of that Object/Character and outgoing messages (such as the result of a <code class="docutils literal notranslate"><span class="pre">look</span></code>) will be passed back only to that puppeting Session. If another Session tries to puppet the same Character, the old Session will automatically un-puppet it. From the players perspective, this will mean that they can open separate game clients and play a different Character in each using one game account.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> │ ┌───────┐
┌──────┐ │ ┌───────┐ │Account│ ┌─────────┐
│Client├─┼──►│Session├──┐ │ │ ┌►│Character│
└──────┘ │ └───────┘ └──┼───────┼──┘ └─────────┘
│ │ │
┌──────┐ │ ┌───────┐ ┌──┼───────┼──┐ ┌─────────┐
│Client├─┼──►│Session├──┘ │ │ └►│Character│
└──────┘ │ └───────┘ │ │ └─────────┘
│ └───────┘
</pre></div>
</div>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE=3</span></code>: Many sessions per account <em>and</em> character. This is the full multi-puppeting mode, where multiple sessions may not only connect to the player account but multiple sessions may also puppet a single character at the same time. From the users perspective it means one can open multiple client windows, some for controlling different Characters and some that share a Characters input/output like in mode 1. This mode otherwise works the same as mode 2.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> │ ┌───────┐
┌──────┐ │ ┌───────┐ │Account│ ┌─────────┐
│Client├─┼──►│Session├──┐ │ │ ┌►│Character│
└──────┘ │ └───────┘ └──┼───────┼──┘ └─────────┘
│ │ │
┌──────┐ │ ┌───────┐ ┌──┼───────┼──┐
│Client├─┼──►│Session├──┘ │ │ └►┌─────────┐
└──────┘ │ └───────┘ │ │ │Character│
│ │ │ ┌►└─────────┘
┌──────┐ │ ┌───────┐ ┌──┼───────┼──┘ ▼
│Client├─┼──►│Session├──┘ │ │
└──────┘ │ └───────┘ └───────┘
</pre></div>
</div>
</li>
</ul>
<blockquote>
<div><p>Note that even if multiple Sessions puppet one Character, there is only ever one instance of that Character.</p>
</div></blockquote>
</section>
<section id="returning-data-to-the-session">
<h2>Returning data to the session<a class="headerlink" href="#returning-data-to-the-session" title="Permalink to this headline"></a></h2>
<p>When you use <code class="docutils literal notranslate"><span class="pre">msg()</span></code> to return data to a user, the object on which you call the <code class="docutils literal notranslate"><span class="pre">msg()</span></code> matters. The
<code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE</span></code> also matters, especially if greater than 1.</p>
<p>For example, if you use <code class="docutils literal notranslate"><span class="pre">account.msg(&quot;hello&quot;)</span></code> there is no way for evennia to know which session it
should send the greeting to. In this case it will send it to all sessions. If you want a specific
session you need to supply its session to the <code class="docutils literal notranslate"><span class="pre">msg</span></code> call (<code class="docutils literal notranslate"><span class="pre">account.msg(&quot;hello&quot;,</span> <span class="pre">session=mysession)</span></code>).</p>
<p>On the other hand, if you call the <code class="docutils literal notranslate"><span class="pre">msg()</span></code> message on a puppeted object, like
<code class="docutils literal notranslate"><span class="pre">character.msg(&quot;hello&quot;)</span></code>, the character already knows the session that controls it - it will
cleverly auto-add this for you (you can specify a different session if you specifically want to send
stuff to another session).</p>
<p>Finally, there is a wrapper for <code class="docutils literal notranslate"><span class="pre">msg()</span></code> on all command classes: <code class="docutils literal notranslate"><span class="pre">command.msg()</span></code>. This will
transparently detect which session was triggering the command (if any) and redirects to that session
(this is most often what you want). If you are having trouble redirecting to a given session,
<code class="docutils literal notranslate"><span class="pre">command.msg()</span></code> is often the safest bet.</p>
<p>You can get the <code class="docutils literal notranslate"><span class="pre">session</span></code> in two main ways:</p>
<ul class="simple">
<li><p><a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a> and <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a> (including Characters) have a <code class="docutils literal notranslate"><span class="pre">sessions</span></code> property.
This is a <em>handler</em> that tracks all Sessions attached to or puppeting them. Use e.g.
<code class="docutils literal notranslate"><span class="pre">accounts.sessions.get()</span></code> to get a list of Sessions attached to that entity.</p></li>
<li><p>A Command instance has a <code class="docutils literal notranslate"><span class="pre">session</span></code> property that always points back to the Session that triggered
it (its always a single one). It will be <code class="docutils literal notranslate"><span class="pre">None</span></code> if no session is involved, like when a mob or
script triggers the Command.</p></li>
</ul>
</section>
<section id="customizing-the-session-object">
<h2>Customizing the Session object<a class="headerlink" href="#customizing-the-session-object" title="Permalink to this headline"></a></h2>
<p>When would one want to customize the Session object? Consider for example a character creation
system: You might decide to keep this on the out-of-character level. This would mean that you create
the character at the end of some sort of menu choice. The actual char-create cmdset would then
normally be put on the account. This works fine as long as you are <code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE</span></code> below 2.
For higher modes, replacing the Account cmdset will affect <em>all</em> your connected sessions, also those
not involved in character creation. In this case you want to instead put the char-create cmdset on
the Session level - then all other sessions will keep working normally despite you creating a new
character in one of them.</p>
<p>By default, the session object gets the <code class="docutils literal notranslate"><span class="pre">commands.default_cmdsets.UnloggedinCmdSet</span></code> when the user
first connects. Once the session is authenticated it has <em>no</em> default sets. To add a “logged-in”
cmdset to the Session, give the path to the cmdset class with <code class="docutils literal notranslate"><span class="pre">settings.CMDSET_SESSION</span></code>. This set
will then henceforth always be present as soon as the account logs in.</p>
<p>To customize further you can completely override the Session with your own subclass. To replace the
default Session class, change <code class="docutils literal notranslate"><span class="pre">settings.SERVER_SESSION_CLASS</span></code> to point to your custom class. This is
a dangerous practice and errors can easily make your game unplayable. Make sure to take heed of the
<a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/server/session.py">original</a> and make your
changes carefully.</p>
</section>
<section id="portal-and-server-sessions">
<h2>Portal and Server Sessions<a class="headerlink" href="#portal-and-server-sessions" title="Permalink to this headline"></a></h2>
<p><em>Note: This is considered an advanced topic. You dont need to know this on a first read-through.</em></p>
<p>Evennia is split into two parts, the <a class="reference internal" href="Portal-And-Server.html"><span class="doc std std-doc">Portal and the Server</span></a>. Each side tracks
its own Sessions, syncing them to each other.</p>
<p>The “Session” we normally refer to is actually the <code class="docutils literal notranslate"><span class="pre">ServerSession</span></code>. Its counter-part on the Portal
side is the <code class="docutils literal notranslate"><span class="pre">PortalSession</span></code>. Whereas the server sessions deal with game states, the portal session
deals with details of the connection-protocol itself. The two are also acting as backups of critical
data such as when the server reboots.</p>
<p>New Account connections are listened for and handled by the Portal using the [protocols](Portal-And-
Server) it understands (such as telnet, ssh, webclient etc). When a new connection is established, a
<code class="docutils literal notranslate"><span class="pre">PortalSession</span></code> is created on the Portal side. This session object looks different depending on
which protocol is used to connect, but all still have a minimum set of attributes that are generic
to all
sessions.</p>
<p>These common properties are piped from the Portal, through the AMP connection, to the Server, which
is now informed a new connection has been established. On the Server side, a <code class="docutils literal notranslate"><span class="pre">ServerSession</span></code> object
is created to represent this. There is only one type of <code class="docutils literal notranslate"><span class="pre">ServerSession</span></code>; It looks the same
regardless of how the Account connects.</p>
<p>From now on, there is a one-to-one match between the <code class="docutils literal notranslate"><span class="pre">ServerSession</span></code> on one side of the AMP
connection and the <code class="docutils literal notranslate"><span class="pre">PortalSession</span></code> on the other. Data arriving to the Portal Session is sent on to
its mirror Server session and vice versa.</p>
<p>During certain situations, the portal- and server-side sessions are
“synced” with each other:</p>
<ul class="simple">
<li><p>The Player closes their client, killing the Portal Session. The Portal syncs with the Server to
make sure the corresponding Server Session is also deleted.</p></li>
<li><p>The Player quits from inside the game, killing the Server Session. The Server then syncs with the
Portal to make sure to close the Portal connection cleanly.</p></li>
<li><p>The Server is rebooted/reset/shutdown - The Server Sessions are copied over (“saved”) to the
Portal side. When the Server comes back up, this data is returned by the Portal so the two are again
in sync. This way an Accounts login status and other connection-critical things can survive a
server reboot (assuming the Portal is not stopped at the same time, obviously).</p></li>
</ul>
</section>
<section id="sessionhandlers">
<h2>Sessionhandlers<a class="headerlink" href="#sessionhandlers" title="Permalink to this headline"></a></h2>
<p>Both the Portal and Server each have a <em>sessionhandler</em> to manage the connections. These handlers
are global entities contain all methods for relaying data across the AMP bridge. All types of
Sessions hold a reference to their respective Sessionhandler (the property is called
<code class="docutils literal notranslate"><span class="pre">sessionhandler</span></code>) so they can relay data. See <a class="reference internal" href="../Concepts/Protocols.html"><span class="doc std std-doc">protocols</span></a> for more info
on building new protocols.</p>
<p>To get all Sessions in the game (i.e. all currently connected clients), you access the server-side
Session handler, which you get by</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.server.sessionhandler</span> <span class="kn">import</span> <span class="n">SESSION_HANDLER</span>
</pre></div>
</div>
<blockquote>
<div><p>Note: The <code class="docutils literal notranslate"><span class="pre">SESSION_HANDLER</span></code> singleton has an older alias <code class="docutils literal notranslate"><span class="pre">SESSIONS</span></code> that is commonly seen in
various places as well.</p>
</div></blockquote>
<p>See the
<a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/server/sessionhandler.py">sessionhandler.py</a>
module for details on the capabilities of the <code class="docutils literal notranslate"><span class="pre">ServerSessionHandler</span></code>.</p>
</section>
</section>
</div>
</div>
</div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="Accounts.html" title="Accounts"
>next</a> |</li>
<li class="right" >
<a href="Typeclasses.html" title="Typeclasses"
>previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="Components-Overview.html" >Core Components</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Sessions</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2022, The Evennia developer community.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
</div>
</body>
</html>