From 4b29114a836b9d59bae1a18fb3fbd481a345e73b Mon Sep 17 00:00:00 2001 From: Griatch Date: Wed, 9 Nov 2011 00:14:41 +0100 Subject: [PATCH] Updated reST documentation. --- docs/sphinx/source/wiki/Commands.rst | 34 ++++++ .../source/wiki/EvenniaIntroduction.rst | 22 ++-- docs/sphinx/source/wiki/GettingStarted.rst | 8 +- .../source/wiki/Internationalization.rst | 4 +- docs/sphinx/source/wiki/SessionProtocols.rst | 115 ++++++++++++++++++ docs/sphinx/source/wiki/UpdatingYourGame.rst | 5 +- 6 files changed, 169 insertions(+), 19 deletions(-) diff --git a/docs/sphinx/source/wiki/Commands.rst b/docs/sphinx/source/wiki/Commands.rst index e1a9b54518..9e9b8c8fa2 100644 --- a/docs/sphinx/source/wiki/Commands.rst +++ b/docs/sphinx/source/wiki/Commands.rst @@ -616,6 +616,29 @@ command must be added to a cmdset as well before it will work. def func(self): 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 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 -------------------------- @@ -684,3 +707,14 @@ Call ``func()`` on the command instance. This is the functional body of the command, actually doing useful things. 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). diff --git a/docs/sphinx/source/wiki/EvenniaIntroduction.rst b/docs/sphinx/source/wiki/EvenniaIntroduction.rst index 6b799b0502..5b70931941 100644 --- a/docs/sphinx/source/wiki/EvenniaIntroduction.rst +++ b/docs/sphinx/source/wiki/EvenniaIntroduction.rst @@ -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 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 -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. 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 boring database, networking, and behind-the-scenes administration stuff -that all online games need whether they like it or not. Evennia is by -default *fully persistent*, that means things you drop on the ground -somewhere will still be there a dozen server reboots later. Through -Django, we support a large variety of different database systems (the -default of which is created for you automatically). +that all online games need whether they like it or not. Evennia is +*fully persistent*, that means things you drop on the ground somewhere +will still be there a dozen server reboots later. Through Django we +support a large variety of different database systems (a database is +created for you automatically if you use the defaults). Using the full power of Python throughout the server offers some distinct advantages. All your coding, from object definitions and custom @@ -104,11 +104,11 @@ manual `_ with lots of examples. But while Python is a relatively easy programming language, it still represents a learning curve if you are new to programming. You should probably sit down with a Python beginner's -`tutorial `_ (there are plenty -of them on the web if you look around) so you at least know know what -you are seeing. To efficiently code your dream game in Evennia you don't -need to be a Python guru, but you do need to be able to read example -code containing at least these basic Python features: +`tutorial `_ (there are plenty of them +on the web if you look around) so you at least know what you are seeing. +To efficiently code your dream game in Evennia you don't need to be a +Python guru, but you do need to be able to read example code containing +at least these basic Python features: - Importing python modules - Using variables, `conditional diff --git a/docs/sphinx/source/wiki/GettingStarted.rst b/docs/sphinx/source/wiki/GettingStarted.rst index 87e6e06aeb..9c4fb02ed4 100644 --- a/docs/sphinx/source/wiki/GettingStarted.rst +++ b/docs/sphinx/source/wiki/GettingStarted.rst @@ -44,8 +44,7 @@ Evennia: **Python** (http://www.python.org) -- Version 2.5+ strongly recommended, although 2.3 or 2.4 **may** work. - Obs- Python3.x is not supported yet. +- Version 2.5+. Obs- Python3.x is not supported yet. - The default database system SQLite3 only comes as part of Python2.5 and later. - Windows users are recommended to use ActivePython @@ -97,8 +96,8 @@ Installing pre-requisites **Linux** package managers should usually handle all this for you. Python itself is definitely available through all distributions. On -Debian-derived systems you can do something like this (as root) to get -all you need: +Debian-derived systems (such as Ubuntu) you can do something like this +(as root) to get all you need: :: @@ -164,6 +163,7 @@ In the future, you just do :: hg pull + hg update from your ``evennia/`` directory to obtain the latest updates. diff --git a/docs/sphinx/source/wiki/Internationalization.rst b/docs/sphinx/source/wiki/Internationalization.rst index 8042498e00..a285354173 100644 --- a/docs/sphinx/source/wiki/Internationalization.rst +++ b/docs/sphinx/source/wiki/Internationalization.rst @@ -60,12 +60,12 @@ form. :: - django-admin.py compilemessages + django-admin compilemessages This will go through all languages and create/update compiled files (``*.mo``) for them. This needs to be done whenever a ``*.po`` file is 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 integrate your translation into Evennia! diff --git a/docs/sphinx/source/wiki/SessionProtocols.rst b/docs/sphinx/source/wiki/SessionProtocols.rst index 0dac7ed152..268a89cb2a 100644 --- a/docs/sphinx/source/wiki/SessionProtocols.rst +++ b/docs/sphinx/source/wiki/SessionProtocols.rst @@ -99,6 +99,121 @@ be named exactly like this): parsed. From inside Evennia, ``data_out`` is often called with the 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 `_ 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 -------------- diff --git a/docs/sphinx/source/wiki/UpdatingYourGame.rst b/docs/sphinx/source/wiki/UpdatingYourGame.rst index 76d5d34d72..0f26289952 100644 --- a/docs/sphinx/source/wiki/UpdatingYourGame.rst +++ b/docs/sphinx/source/wiki/UpdatingYourGame.rst @@ -17,6 +17,7 @@ root directory and type: :: hg pull + hg update 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 @@ -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. 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 -run this command: +changed (check ``hg log`` after you pulled the latest stuff, or read the +online list), you go to ``game/`` and run this command: ::