Evennia in pictures¶
This article tries to give a high-level overview of the Evennia server and some of its moving parts. It should hopefully give a better understanding of how everything hangs together.
The two main Evennia pieces¶
What you see in this figure is the part of Evennia that you download from us. It will not start a game on its own. We’ll soon create the missing ‘jigsaw puzzle piece’. But first, let’s see what we have.
First, you’ll notice that Evennia has two main components - the Portal and Server. These are separate processes.
The Portal tracks all connections to the outside world and understands Telnet protocols, websockets, SSH and so on. It knows nothing about the database or the game state. Data sent between the Portal and the Server is protocol-agnostic, meaning the Server sends/receives the same data regardless of how the user is connected. Hiding behind the Portal also means that the Server can be completely rebooted without anyone getting disconnected.
The Server is the main “mud driver” and handles everything related to the game world and its database. It’s asynchronous and uses Twisted.
In the same process of the Server is also the Evennia Web Server . This serves the game’s website.
Initializing the game folder¶
After installing evennia you will have the
evennia command available. Using this you create a game directory (let’s call it
mygame). This is the darker grey piece in this figure. It was missing previously. This is where you will create your dream game!
During initialization, Evennia will create Python module templates in
mygame/ and link up all configurations to make mygame a fully functioning, if empty, game, ready to start extending.
As part of the intialization, you’ll create the database and then start the server. From this point on, your new game is up and running and you can connect to your new game with telnet on localhost:4000 or by pointing your browser to http://localhost:4001.
Now, our new mygame world needs Characters, locations, items and more!
Evennia is fully persistent and abstracts its database in Python using Django. The database tables are few and generic, each represented by a single Python class. As seen in this figure, the example
ObjectDB Python class represents one database table. The properties on the class are the columns (fields) of the table. Each row is an instance of the class (one entity in the game).
Among the example columns shown is the key (name) of the
ObjectDB entity as well as a Foreign key-relationship for its current “location”.
From the figure we can see that Trigger is in the Dungeon, carrying his trusty crossbow Old Betsy!
db_typeclass_path is an important field. This is a python-style path and tells Evennia which subclass of
ObjectDB is actually representing this entity. This is the core of Evennia’s Typeclass system, which allows you to work with database entities using normal Python.
From database to Python¶
Here we see the (somewhat simplified) Python class inheritance tree that you as an Evennia developer will see, along with the three instanced entities.
Objects represent stuff you will actually see in-game and its child classes implement all the handlers, helper code and the hook methods that Evennia makes use of. In your
mygame/ folder you just import these and overload the things you want to modify. In this way, the
Crossbow is modified to do the stuff only crossbows can do and
CastleRoom adds whatever it is that is special about rooms in the castle.
When creating a new entity in-game, a new row will automatically be created in the database table and then
Trigger will appear in-game! If we, in code, search the database for Trigger, we will get an instance of the Character class back - a Python object we can work with normally.
Looking at this you may think that you will be making a lot of classes for every different object in the game. Your exact layout is up to you but Evennia also offers other ways to customize each individual object. Read on.
The Attribute is another class directly tied to the database behind the scenes. Each
Attribute basically has a key, a value and a ForeignKey relation to another
Attribute serializes Python constructs into the database, meaning you can store basically any valid Python, like the dictionary of skills in this image. The “strength” and “skills” Attributes will henceforth be reachable directly from the Trigger object. This (and a few other resources) allow you to create individualized entities while only needing to create classes for those that really behave fundamentally different.
Controlling the action¶
Trigger is most likely played by a human. This human connects to the game via one or more Sessions, one for each client they connect with.
Their account on
mygame is represented by a Account entity. The
AccountDB holds the password and other account info but has no existence in the game world. Through the
Sessions can control (“puppet”) one or more
Object entities in-game.
In this figure, a user is connected to the game with three
Sessions simultaneously. They are logged in to their player
Account named Richard. Through these
Sessions they are simultaneously puppeting the in-game entities Trigger and Sir Hiss. Evennia can be configured to allow or disallow a range of different Connection Styles like this.
For users to be able to control their game entities and actually play the game, they need to be able to send Commands.
Command can be made to represent anything a user can input actively to the game, such as the
emote and so on.
Command handles both argument parsing and execution. Since each Command is described with a normal Python class, it means that you can implement parsing once and then just have the rest of your commands inherit the effect. In the above figure, the
DIKUCommand parent class implements parsing of all the syntax common for all DIKU-style commands so
CmdLook and others won’t have to.
All Evennia Commands are are always joined together in
CommandSets. These are containers that can hold many
Command instances. A given
Command class can contribute instances to any number of
CommandSets. These sets are always associated with game entities.
In this figure, Trigger has received a
CommandSet with a bunch of useful commands that he (and by extension his controlling
Account/Player) can now use.
CommandSet is only available to himself. In this figure we put a
CommandSet with three commands on the Dungeon room. The room itself has no use for commands but we configure this set to affect those inside it instead. Note that we let these be different versions of these commands (hence the different color)! We’ll explain why below.
Merging Command Sets¶
CommandSets can be dynamically (and temporarily) merged together in a similar fashion as Set Theory, except the merge priority can be customized. In this figure we see a Union-type merger where the Commands from Dungeon of the same name temporarily override the commands from Trigger. While in the Dungeon, Trigger will be using this version of those commands. When Trigger leaves, his own
CommandSet will be restored unharmed.
Why would we want to do this? Consider for example that the dungeon is in darkness. We can then let the Dungeon’s version of the
look command show only the contents of the room if Trigger is carrying a light source. You might also not be able to easily get things in the room without light - you might even be fumbling randomly in your inventory!
Any number of Command Sets can be merged on the fly. This allows you to implement multiple overlapping states (like combat in a darkened room while intoxicated) without needing huge if statements for every possible combination. The merger is non-destructive, so you can remove cmdsets to get back previous states as needed.
Now go and explore!¶
This is by no means a full list of Evennia features. But it should give you a bunch of interesting concepts to read more about.