Updated reST documentation.
This commit is contained in:
parent
329a13bf8a
commit
4b29114a83
6 changed files with 169 additions and 19 deletions
|
|
@ -616,6 +616,29 @@ command must be added to a cmdset as well before it will work.
|
||||||
def func(self):
|
def func(self):
|
||||||
self.caller.msg("Don't just press return like that, talk to me!")
|
self.caller.msg("Don't just press return like that, talk to me!")
|
||||||
|
|
||||||
|
Exits
|
||||||
|
-----
|
||||||
|
|
||||||
|
*Note: This is an advanced topic.*
|
||||||
|
|
||||||
|
The functionality of `Exit <Objects.html>`_ objects in Evennia is not
|
||||||
|
hard-coded in the engine. Instead Exits are normal typeclassed objects
|
||||||
|
that auto-creates a ``CmdSet`` on themselves when they are loaded. This
|
||||||
|
cmdset has a single command with the same name (and aliases) as the Exit
|
||||||
|
object itself. So what happens when a Player enters the name of the Exit
|
||||||
|
on the command line is simply that the command handler, in the process
|
||||||
|
of searching all available commands, also picks up the command from the
|
||||||
|
Exit object(s) in the same room. Having found the matching command, it
|
||||||
|
executes it. The command then makes sure to do all checks and eventually
|
||||||
|
move the Player across the exit as appropriate. This allows exits to be
|
||||||
|
extremely flexible - the functionality can be customized just like one
|
||||||
|
would edit any other command.
|
||||||
|
|
||||||
|
Admittedly, you will usually be fine just using the appropriate
|
||||||
|
``traverse_*`` hooks. But if you are interested in really changing how
|
||||||
|
things work under the hood, check out ``src.objects.objects`` for how
|
||||||
|
the default ``Exit`` typeclass is set up.
|
||||||
|
|
||||||
How commands actually work
|
How commands actually work
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
|
|
@ -684,3 +707,14 @@ Call ``func()`` on the command instance. This is the functional body of
|
||||||
the command, actually doing useful things.
|
the command, actually doing useful things.
|
||||||
|
|
||||||
Call ``at_post_command()`` on the command instance.
|
Call ``at_post_command()`` on the command instance.
|
||||||
|
|
||||||
|
Assorted notes
|
||||||
|
--------------
|
||||||
|
|
||||||
|
The return value of ``Command.func()`` *is* safely passed on should one
|
||||||
|
have some very specific use case in mind. So one could in principle do
|
||||||
|
``value = obj.execute_cmd(cmdname)``. Evennia does not use this
|
||||||
|
functionality at all by default (all default commands simply returns
|
||||||
|
``None``) and it's probably not relevant to any but the most
|
||||||
|
advanced/exotic designs (one might use it to create a "nested" command
|
||||||
|
structure for example).
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ and running a text-based massively-multiplayer game
|
||||||
your very own. You might just be starting to think about it, or you
|
your very own. You might just be starting to think about it, or you
|
||||||
might have lugged around that *perfect* game in your mind for years ...
|
might have lugged around that *perfect* game in your mind for years ...
|
||||||
you know *just* how good it would be, if you could only make it come to
|
you know *just* how good it would be, if you could only make it come to
|
||||||
reality. We know how you feel. That is, after all why Evennia came to
|
reality. We know how you feel. That is, after all, why Evennia came to
|
||||||
be.
|
be.
|
||||||
|
|
||||||
Evennia is in principle a MUD-building system: a bare-bones Python
|
Evennia is in principle a MUD-building system: a bare-bones Python
|
||||||
|
|
@ -33,11 +33,11 @@ will in that case all be optional.
|
||||||
|
|
||||||
What we *do* however, is to provide a solid foundation for all the
|
What we *do* however, is to provide a solid foundation for all the
|
||||||
boring database, networking, and behind-the-scenes administration stuff
|
boring database, networking, and behind-the-scenes administration stuff
|
||||||
that all online games need whether they like it or not. Evennia is by
|
that all online games need whether they like it or not. Evennia is
|
||||||
default *fully persistent*, that means things you drop on the ground
|
*fully persistent*, that means things you drop on the ground somewhere
|
||||||
somewhere will still be there a dozen server reboots later. Through
|
will still be there a dozen server reboots later. Through Django we
|
||||||
Django, we support a large variety of different database systems (the
|
support a large variety of different database systems (a database is
|
||||||
default of which is created for you automatically).
|
created for you automatically if you use the defaults).
|
||||||
|
|
||||||
Using the full power of Python throughout the server offers some
|
Using the full power of Python throughout the server offers some
|
||||||
distinct advantages. All your coding, from object definitions and custom
|
distinct advantages. All your coding, from object definitions and custom
|
||||||
|
|
@ -104,11 +104,11 @@ manual <http://code.google.com/p/evennia/wiki/Index>`_ with lots of
|
||||||
examples. But while Python is a relatively easy programming language, it
|
examples. But while Python is a relatively easy programming language, it
|
||||||
still represents a learning curve if you are new to programming. You
|
still represents a learning curve if you are new to programming. You
|
||||||
should probably sit down with a Python beginner's
|
should probably sit down with a Python beginner's
|
||||||
`tutorial <http://docs.python.org/tutorial/tutorial>`_ (there are plenty
|
`tutorial <http://docs.python.org/tutorial/>`_ (there are plenty of them
|
||||||
of them on the web if you look around) so you at least know know what
|
on the web if you look around) so you at least know what you are seeing.
|
||||||
you are seeing. To efficiently code your dream game in Evennia you don't
|
To efficiently code your dream game in Evennia you don't need to be a
|
||||||
need to be a Python guru, but you do need to be able to read example
|
Python guru, but you do need to be able to read example code containing
|
||||||
code containing at least these basic Python features:
|
at least these basic Python features:
|
||||||
|
|
||||||
- Importing python modules
|
- Importing python modules
|
||||||
- Using variables, `conditional
|
- Using variables, `conditional
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,7 @@ Evennia:
|
||||||
|
|
||||||
**Python** (http://www.python.org)
|
**Python** (http://www.python.org)
|
||||||
|
|
||||||
- Version 2.5+ strongly recommended, although 2.3 or 2.4 **may** work.
|
- Version 2.5+. Obs- Python3.x is not supported yet.
|
||||||
Obs- Python3.x is not supported yet.
|
|
||||||
- The default database system SQLite3 only comes as part of Python2.5
|
- The default database system SQLite3 only comes as part of Python2.5
|
||||||
and later.
|
and later.
|
||||||
- Windows users are recommended to use ActivePython
|
- Windows users are recommended to use ActivePython
|
||||||
|
|
@ -97,8 +96,8 @@ Installing pre-requisites
|
||||||
|
|
||||||
**Linux** package managers should usually handle all this for you.
|
**Linux** package managers should usually handle all this for you.
|
||||||
Python itself is definitely available through all distributions. On
|
Python itself is definitely available through all distributions. On
|
||||||
Debian-derived systems you can do something like this (as root) to get
|
Debian-derived systems (such as Ubuntu) you can do something like this
|
||||||
all you need:
|
(as root) to get all you need:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
|
@ -164,6 +163,7 @@ In the future, you just do
|
||||||
::
|
::
|
||||||
|
|
||||||
hg pull
|
hg pull
|
||||||
|
hg update
|
||||||
|
|
||||||
from your ``evennia/`` directory to obtain the latest updates.
|
from your ``evennia/`` directory to obtain the latest updates.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,12 +60,12 @@ form.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
django-admin.py compilemessages
|
django-admin compilemessages
|
||||||
|
|
||||||
This will go through all languages and create/update compiled files
|
This will go through all languages and create/update compiled files
|
||||||
(``*.mo``) for them. This needs to be done whenever a ``*.po`` file is
|
(``*.mo``) for them. This needs to be done whenever a ``*.po`` file is
|
||||||
updated.
|
updated.
|
||||||
|
|
||||||
When you are done, send the ``*.po`` and \*.mo file to the Evennia
|
When you are done, send the ``*.po`` and ``*.mo`` file to the Evennia
|
||||||
developer list (or push it into your own repository clone) so we can
|
developer list (or push it into your own repository clone) so we can
|
||||||
integrate your translation into Evennia!
|
integrate your translation into Evennia!
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,121 @@ be named exactly like this):
|
||||||
parsed. From inside Evennia, ``data_out`` is often called with the
|
parsed. From inside Evennia, ``data_out`` is often called with the
|
||||||
alias ``msg`` instead.
|
alias ``msg`` instead.
|
||||||
|
|
||||||
|
Out-of-band communication
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Out-of-band communication (OOB) is data being sent to and fro the
|
||||||
|
player's client and the server on the protocol level, often due to the
|
||||||
|
request of the player's client software rather than any sort of active
|
||||||
|
input by the player. There are two main types:
|
||||||
|
|
||||||
|
- Data requested by the client which the server responds to
|
||||||
|
immediately. This could for example be data that should go into a
|
||||||
|
window that the client just opened up.
|
||||||
|
- Data the server sends to the client to keep ut up-to-date. A common
|
||||||
|
example of this is something like a graphical health bar - *whenever*
|
||||||
|
the character's health status changes the server sends this data to
|
||||||
|
the client so it can update the bar graphic. This sending could also
|
||||||
|
be done on a timer, for example updating a weather map regularly.
|
||||||
|
|
||||||
|
To communicate to the client, there are a range of protocols available
|
||||||
|
for MUDs, supported by different clients, such as MSDP and GMCP. They
|
||||||
|
basically implements custom telnet negotiation sequences and goes into a
|
||||||
|
custom Evennia Portal protocol so Evennia can understand it.
|
||||||
|
|
||||||
|
It then needs to translate each protocol-specific function into an
|
||||||
|
Evennia function name - specifically a name of a module-level function
|
||||||
|
you define in the module given by ``settings.OOB_FUNC_MODULE``. These
|
||||||
|
function will get the session/character as first argument but is
|
||||||
|
otherwise completely free of form. The portal packs all function names
|
||||||
|
and eventual arguments they need in a dictionary and sends them off to
|
||||||
|
the Server by use of the ``sessionhandler.oob_data_in()`` method. On the
|
||||||
|
Server side, the dictionary is parsed, and the correct functions in
|
||||||
|
``settings.OOB_FUNC_MODULE`` are called with the given arguments. The
|
||||||
|
results from this function are again packed in a dictionary (keyed by
|
||||||
|
function name) and sent back to the portal. It will appear in the Portal
|
||||||
|
session's ``oob_data_out(data)`` method.
|
||||||
|
|
||||||
|
So to summarize: To implement a Portal protocol with OOB communication
|
||||||
|
support, you need to first let your normal ``getData`` method somehow
|
||||||
|
parse out the special protocol format format coming in from the client
|
||||||
|
(MSDP, GMCP etc). It needs to translate what the client wants into
|
||||||
|
function names matching that in the ``OOB_FUNC_MODULE`` - these
|
||||||
|
functions need to be created to match too of course. The function name
|
||||||
|
and arguments are packed in a dictionary and sent off to the server via
|
||||||
|
``sessionhandler.oob_data_in()``. Finally, the portal session must
|
||||||
|
implement ``oob_data_out(data)`` to handle the data coming back from
|
||||||
|
Server. It will be a dictionary of return values keyed by the function
|
||||||
|
names.
|
||||||
|
|
||||||
|
Example of out-of-band calling sequence
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Let's say we want our client to be able to request the character's
|
||||||
|
current health. In our Portal protocol we somehow parse the incoming
|
||||||
|
data stream and figure out what the request for health looks like. We
|
||||||
|
map this to the Evennia ``get_health`` function.
|
||||||
|
|
||||||
|
We point ``settings.OOB_FUNC_MODULE`` to someplace in ``game/`` and
|
||||||
|
create a module there with the following function:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
# the caller is always added as first argument
|
||||||
|
# we also assume health is stored as a simple
|
||||||
|
# attribute on the character here.
|
||||||
|
def get_health(character):
|
||||||
|
return character.db.health
|
||||||
|
|
||||||
|
Done, this function will do just what we want. Let's finish up the first
|
||||||
|
part of the portal protocol:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
# this method could be named differently depending on the
|
||||||
|
# protocol you are using (this is telnet)
|
||||||
|
def lineReceived(self, string):
|
||||||
|
# (does stuff to analyze the incoming string) outdict =
|
||||||
|
if GET_HEALTH:
|
||||||
|
# call get_health(char)
|
||||||
|
outdict["get_health"] = ([], )
|
||||||
|
elif GET_MANA:
|
||||||
|
# call get_mana(char)
|
||||||
|
outdict["get_mana"] = ([], )
|
||||||
|
elif GET_CONFIG:
|
||||||
|
# call get_config(char, 2, hidden=True)
|
||||||
|
outdict["get_config"] = ([2], 'hidden':True) [...] self.sessionhandler.oob_data_out(outdict)
|
||||||
|
|
||||||
|
The server will properly accept this and call get\_health and get the
|
||||||
|
right value for the health. We need to define an ``oob_data_out(data)``
|
||||||
|
in our portal protocol to catch the return value:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
def oob_data_out(self, data):
|
||||||
|
# the indata is a dicationary funcname:retval outstring = ""
|
||||||
|
for funcname, retval in data.items():
|
||||||
|
if funcname == 'get_health':
|
||||||
|
# convert to the right format for sending back to client, store
|
||||||
|
# in outstring ...
|
||||||
|
[...]
|
||||||
|
|
||||||
|
Above, once the dict is parsed and the return values properly put in a
|
||||||
|
format the client will understand, send the whole thing off using the
|
||||||
|
protocol's relevant send method.
|
||||||
|
|
||||||
|
Implementing auto-sending
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
To have the Server update the client regularly, simply create a global
|
||||||
|
`Script <Scripts.html>`_ that upon each repeat creates the request
|
||||||
|
dictionary (basically faking a request from the portal) and sends it
|
||||||
|
directly to
|
||||||
|
``src.server.sessionhandler.oob_data_in(session.sessid, datadict)``.
|
||||||
|
Repeat for all sessions. All specified OOB functions are called as
|
||||||
|
normal and data will be sent back to be handled by the portal just as if
|
||||||
|
the portal initiated the request.
|
||||||
|
|
||||||
Assorted notes
|
Assorted notes
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ root directory and type:
|
||||||
::
|
::
|
||||||
|
|
||||||
hg pull
|
hg pull
|
||||||
|
hg update
|
||||||
|
|
||||||
Assuming you've got the command line client. If you're using a graphical
|
Assuming you've got the command line client. If you're using a graphical
|
||||||
client, you will probably want to navigate to the ``evennia`` directory
|
client, you will probably want to navigate to the ``evennia`` directory
|
||||||
|
|
@ -112,8 +113,8 @@ used (you have to give the ``mange.py migrate`` command as well as
|
||||||
|
|
||||||
Once you have a database ready and using South, you work as normal.
|
Once you have a database ready and using South, you work as normal.
|
||||||
Whenever a new Evennia update tells you that the database schema has
|
Whenever a new Evennia update tells you that the database schema has
|
||||||
changed (check ``hg log`` or the online list), you go to ``game/`` and
|
changed (check ``hg log`` after you pulled the latest stuff, or read the
|
||||||
run this command:
|
online list), you go to ``game/`` and run this command:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue