After getting questions about it I recently added the Slow Exit contribution
to the main repository as an example.
Delayed movement is something often seen in various text games, it simply means that the time to move from room to room is artificially extended.
Evennia's default model uses traditional MU* rooms. These are simple nodes with exits linking them together. Such Rooms have no internal size and no inherent spatial relationship to each other. Moving from any Room to any other is happening as fast as the system can process the movement.
Introducing a delay on exit traversal can have a surprisingly big effect on a game:
- It dramatically changes the "feel" of the game. It often makes the game feel less "twitch" and slows things down in a very real way. It lets Players consider movement as a "cost".
- It simulates movement speed. A "quick" (or maybe well-rested) character might perceive an actual difference in traversal. The traversal speed can vary depending on if the Character is "running" or "walking".
- It can emulate travel distance. An Exit leading to "the top of the mountain" may take longer to traverse than going "inside the tent".
- It makes movement a "cost" to take into consideration in the game. Moving back and forth over and over across a distance of multiple rooms becomes a much more daunting prospect with a time delay than if you could just zip along as quickly as you could press the button. This also has effects on map and quest design.
Introducing delayed movement in Evennia is simple. But to explain the idea, let's first briefly explain how Evennia implements Exits.
A brief sideline: About Exits
in Evennia is a persistent Object
sitting in a room. The Exit
class is just like any Object
except for two things - it stores a "destination
" property and it houses a CommandSet
on itself. This particular CommandSet
holds a single command with the same name as the Exit
are things I've covered in earlier blog posts
. Suffice to say is that any number of command sets can be merged together dynamically to at any moment represent the commands available to the Character at any given time or situation.
What happens when an Exit
bject is in the same room as a Character is that the Exit
's command set is dynamically merged with that of the Character. This means a new command - which always has the same name as the Exit
- becomes available. The result is that if the Exit
object is called "south", the Character can use the command "south". By default all the command does is to call a hook method on the Exit
object. This hook hooks simply moves the calling Character to the "destination
" stored by the Exit
The nice thing with this is that the whole system is implemented without any special cases or custom hard-wired code. It also means that the entire Exit system can be changed and modified without ever touching Evennia's core.
To delay the traversal, the principle is simple - after the Exit command has triggered, wait for a little while before continuing.
Technically we define a new class of Exit
, let's call it SlowExit
, inheriting from the default Exit
. We locate the spot where the Exit
normally sends traversing objects on their way (this is a method called move_to()
Since Evennia is based on Twisted, we use Twisted's intrinsic CallLater()
function to delay the move for as many seconds we desire (in the contrib I use a thin wrapper around CallLater
). The result is that the command is called, you get a little text saying that you have started moving ... and a few seconds later you actually move.
Once one understands how Exits work it's really quite straight forward - see the code on github
for more details (it's got plenty of comments).
In the contrib are also some example utility commands for setting one's movement speed and to abort movement if you change your mind before the timeout has passed.
This simple start can easily be expanded as befits each individual game. One can imagine introducing anything from stamina costs to make travel time be dynamically calculated based on terrain or other factors.
In many traditional multiplayer text engines for MUD/MUSH/MU*, the player connects to the game with an account name that also becomes their character's in-game name. When they log into the game they immediately "become" that character. If they want to play with another character, they need to create a new account.
A single-login system is easy to implement but many code bases try to expand with some sort of "account system" where a single login "account" will allow you to manage one or more game characters. Matthew “Chaos” Sheahan beautifully argues for the benefits of an account system in the April issue of Imaginary Realities
; you can read his article here
Evennia and account systems
First a brief show of how Evennia handles this. We use the following separation:
Session(s) <-> Player <-> Objects/Characters(s)
object represents individual client connections to Evennia. The Player
is our "account" object. It holds the password hash and your login name but has no in-game existence. Finally we have Objects
, the most common being a subclass of Object we call Character.
Objects exist in the game. They are "puppeted" by Sessions via the Player account.
From this separation an account system follows naturally. Evennia also offers fully flexible puppeting out of the box: Changing characters (or for staff to puppet an NPC) is simply a matter of "disconnecting" from one Character and connecting to another (presuming you have permission to do so).
The Multisession modes of Evennia
This is the main gist of this entry since we just added another of these (mode 3). Evennia now offers four different multisession modes
for the game designer to choose between. They affect how you gamers may control their characters and can be changed with just a server reload.
This is emulates the "traditional" mud codebase style. In mode 0 a Session controls one Character and one character only. Only one Session per account is allowed - that is, if a user try to connect to their Player account with a different client the old connection will be disconnected. In the default command set a new Character is created with the same name as the Player account and the two are automatically connected whenever they log in. To the user this makes Player and Character seem to be virtually the same thing.
In this mode, multiple Sessions are allowed per Player account. You still only have one Character per account but you can control that Character from any number of simultaneously connected clients. This is a requirement from MUSHes and some slower-moving games where there are communities of gamers who want to conveniently track the progress of the game continuously on multiple clients and computers.
In multisession mode 2, multiple Characters are allowed per Player account. No Characters are created by default in this mode, rather the default command set will drop you to a simplified OOC management screen where you can create new characters, list the ones you already have and puppet them. This mode offers true multiplaying, where you can connect via several clients simultaneously, each Session controlling a different Character.
This mode allows gamers not only to play multiple Characters on the same Player account (as in mode 2) but to also connect multiple Sessions to each Character.
This is a multi-character version of Mode 1, where players can control the same Character via Player logins from several different clients on different machines in any combination.
It's interesting that some of these modes may seem silly or superfluous to people used to a certain type of MU* yet are killer features for other communities. It goes to show how different the needs are for users of different game styles.
Latest Evennia come with a range of improvements, mainly related to its integration with the web.
New and improved ways to expand the website/webclient
Thanks to the work of contributor Kelketek, Evennia's Django-based web system (website and webclient) has been restructured to be much easier to expand. Previously you had to basically copy the entire web/ folder into your game and modify things in-place. This was not ideal since it made it inherently harder to update when things changed upstream. Now Evennia makes use of Django's collectstatic functionality to allow people to plugin and overload only the media files and templates that they need. Kelketek wrote a new and shiny web tutorial explaining just how things work.
Websocket-based webclient with OOB
Evennia's webclient was an ajax-based one using a long polling ("comet") paradigm to work. These days all modern browsers support websockets
though, a protocol that allows asynchronous server-client communication without the cludgery of long polling. So Evennia's new webclient will now use websockets if the browser supports it and fall back to the old comet client if it does not.
The new client also has full support for OOB (Out-of-band) communication. The client uses JSON for straight forward OOB messaging with the server. As part of this, I had an excuse to go back to clean up and make the OOB backbone of Evennia more complete. The server-side oob commands are borrowed from MSDP
but the server side is of course independent of communication protocol (so webclient and telnet extensions can call the same server-side callbacks). I've not yet finalized the documentation for how to use the OOB yet, that will come soon-ish.