Updated reST docs.

This commit is contained in:
Griatch 2011-12-20 18:54:27 +01:00
parent dfec9eeb7d
commit e2b67b0ac4
10 changed files with 212 additions and 104 deletions

View file

@ -75,29 +75,15 @@ Attributes like you would any normal Python property:
This looks like any normal Python assignment, but calls ``db`` behind
the scenes for you.
Assigning attributes this way is intuitive and makes for slightly less
to write. There is a drawback to using this short-form though: Database
objects and typeclasses *already* have a number of Python methods and
properties defined on themselves. If you use one of those already-used
names with this short form you will not be setting a new Attribute but
will infact be editing an existing engine property.
For example, the property ``self.location`` on yourself is tied directly
to the ``db_location`` database field and will not accept anything but
an ``ObjectDB`` object or it will raise a traceback. ``self.delete`` is
a method handling the deletion of objects, and so on. The reason these
are available is of course that you may *want* to overload these
functions with your own implementations - this is one of the main powers
of Evennia. But if you blindly do e.g. ``self.msg = "Hello"`` you will
happily be overloading the core ``msg()`` method and be in a world of
pain.
Using ``db`` will always work like you expect. ``self.db.msg = 'Hello'``
will create a new Attribute ``msg`` without affecting the core method
named ``msg()`` at all. So in principle, whereas you can use the
short-form for simple testing, it's best to use ``db`` when you want
Attributes and skip it only when you explicitly want to edit/overload
something in the base classes.
Note however that this form stands the chance of overloading already
existing properties on typeclasses and their database objects.
``rose.msg()`` is for example an already defined method for sending
messages. Doing ``rose.msg = "Ouch"`` will overload the method with a
string and will create all sorts of trouble down the road (the engine
uses ``msg()`` a lot to send text to you). Using
``rose.db.msg = "Ouch"`` will always do what you expect and is usually
the safer bet. And it also makes it visually clear at all times when you
are saving to the database and not.
Persistent vs non-persistent
----------------------------
@ -117,8 +103,10 @@ situations though.
simply writes to memory, it doesn't hit the database at all. It
should be said that with the speed and quality of hardware these
days, this point is less likely to be of any big concern except for
the most extreme of situations. The default database even runs in RAM
if possible, alleviating the need to write to disk.
the most extreme of situations. Modern database systems cache data
very efficiently for speed. Our default database even runs completely
in RAM if possible, alleviating much of the need to write to disk
during heavy loads.
- You *want* to loose your state when logging off. Maybe you are
testing a buggy `Script <Scripts.html>`_ that does potentially
harmful stuff to your character object. With non-persistent storage
@ -205,29 +193,31 @@ example, you can do
::
# saving data
obj.db.mydict = "key":"test0"
obj.db.mydict["key"] = "test1"
obj.db.mylist[34] = "test2"
obj.db.mylist = [0,1,2,3]
obj.db.mylist[3] = "test2"
obj.db.mylist.append("test3")
# retrieving data
obj.db.mydict["key"] # returns "test1"
obj.db.mylist[34] # returns "test2
obj.db.mylist[3] # returns "test2
obj.db.mylist[-1] # returns "test3"
and it will work fine, thanks to a lot of magic happening behind the
scenes. What will *not* work however is editing *nested*
lists/dictionaries in-place. This is due to the way Python referencing
works. Consider the following:
scenes. What will *not* work however is *assigning nested
lists/dictionaries in-place*. This is due to the way Python referencing
works, no way around it alas. Consider the following:
::
obj.db.mydict = 1:2:3
This is a perfectly valid nested dictionary and Evennia will store it
just fine.
just fine. Retrieving this data will also work normally:
::
obj.db.mydict[1][2] # correctly returns 3
val = obj.db.mydict[1][2] # correctly returns 3
However:
@ -237,9 +227,10 @@ However:
will not work - trying to edit the nested structure will fail silently
and nothing will have changed. No, this is not consistent with normal
Python operation, it's where the database magic fails. All is not lost
however. In order to change a nested structure, you simply need to use a
temporary variable:
Python operation, it's where the database magic fails. Sorry, but there
does not seem to be a way around this (if you know one, let us know!)
All is not lost however. In order to change a nested structure, you
simply need to use a temporary variable:
::
@ -250,7 +241,7 @@ temporary variable:
# save back to database
obj.db.mydict = mydict
# test
obj.db.mydict[1][2] # now correctly returns "test"
val = obj.db.mydict[1][2] # now correctly returns "test"
mydict was updated and recreated in the database.

View file

@ -621,7 +621,7 @@ non-commands as text input.
- New session connection ('cmdhandler.CMD\_LOGINSTART'). This command
name should be put in the ``settings.CMDSET_UNLOGGEDIN``. Whenever a
new connection is established, this command is always called on the
the server (default is to show the login screen).
server (default is to show the login screen).
Below is an example of redefining what happens when the player don't
give any input (e.g. just presses return). Of course the new system

View file

@ -33,15 +33,9 @@ Properties defined on ``Msg``
to.
- ``channels`` - a list of target Channels to send to.
- ``message`` - the actual text being sent
- ``date_sent`` - when message was sent.
- ``date_sent`` - when message was sent (auto-created).
- ``locks`` - a `lock definition <Locks.html>`_.
The following is currently unimplemented in Evennia (stay tuned):
- hide*from*sender - bool if message should be hidden from sender
- hide*from*receivers - list of receiver objects to hide message from
- hide*from*channels - list of channels objects to hide message from
You create new messages in code using
``src.utils.create.create_message.``
@ -64,7 +58,9 @@ There are three default channels created in stock Evennia - ``MUDinfo``,
``MUDconnections`` and ``Public``. Two first ones are server-related
messages meant for Admins, the last one is open to everyone to chat on
(all new players are automatically joined to it when logging in, useful
for asking questions).
for asking questions). The default channels created are defined by
``settings.CHANNEL_PUBLIC``, ``settings.CHANNEL_MUDINFO`` and
``settings.CHANNEL_CONNECTINFO``.
You create new channels with ``src.utils.create.create_channel()``.

View file

@ -70,6 +70,12 @@ Programming Evennia
- `Adding a Command prompt <CommandPrompt.html>`_
- `Running processes asynchronously <AsyncProcess.html>`_
Game implementation hints
-------------------------
- `Creating a Zoning system <Zones.html>`_
- `Implementing cooldowns for commands <CommandCooldown.html>`_
Work in Progress - Developer brainstorms and whitepages
-------------------------------------------------------

View file

@ -24,7 +24,10 @@ up-to-date documentation is the online wiki however.
Read ``sphinx/README`` for instructions on building the ReST
documentation, based on a current snapshot of the wiki. This can be
browsed offline or made into a PDF for printing etc.
browsed offline or made into a PDF for printing etc. Since these files
are automatically converted directly from the wiki files, there may be
formatting problems here and there, especially if trying to convert to
printable format.
You can create the Evennia *autodocs* by following the instructions in
``doxygen/README``. This will make use of the source code itself to
@ -66,22 +69,14 @@ the server.
evennia.py
manage.py gamesrc/
commands/
basecommand.py
basecmdset.py
examples/
cmdset_red_button.py
scripts/
basescript.py
examples/
red_button_sripts.py
objects/
baseobjects.py
examples/
red_button.py
world/
examples/
batch_cmds.ev
batch_code.py
conf/
``game/gamesrc/``
~~~~~~~~~~~~~~~~~
@ -126,18 +121,17 @@ Button* object itself.
``gamesrc/world/``
^^^^^^^^^^^^^^^^^^
``gamesrc/world/``, finally, contains all the rest that make up your
world. This is where you would put your own custom economic system,
combat mechanic, emote-parser or what have you; organized in whatever
way you like. Just remember that if you create new folders under
``world``, they must contain an empty file ``__init__.py``, or Python
will not know how to import modules from them. The ``world`` folder is
also where Evennia's `batch processors <BatchProcessors.html>`_ by
default look for their input files. These allow you to build your world
offline using your favourite text editor rather than have to do it
online over a command line. The `Batch-Command
processor <BatchCommandProcessor.html>`_ expects files ending with
``.ev``, whereas the more advanced `Batch-Code
``gamesrc/world/``, contains all the rest that make up your world. This
is where you would put your own custom economic system, combat mechanic,
emote-parser or what have you; organized in whatever way you like. Just
remember that if you create new folders under ``world``, they must
contain an empty file ``__init__.py``, or Python will not know how to
import modules from them. The ``world`` folder is also where Evennia's
`batch processors <BatchProcessors.html>`_ by default look for their
input files. These allow you to build your world offline using your
favourite text editor rather than have to do it online over a command
line. The `Batch-Command processor <BatchCommandProcessor.html>`_
expects files ending with ``.ev``, whereas the more advanced `Batch-Code
processor <BatchCodeProcessor.html>`_ takes ``.py`` with some special
formatting.
@ -145,6 +139,17 @@ formatting.
creates a *Red Button* object in *Limbo* using their respective special
syntax.
``gamesrc/conf/``
^^^^^^^^^^^^^^^^^
``gamesrc/world/`` holds optional extension modules for the Evennia
engine. Certain functionality in the server is meant to be extended, and
in order to allow you to do this without modifying the server itself, it
imports files from this directory. Modifying these are optionally and
you can usually change a variable in ``game/settings.py`` to change
which module Evennia is looking for. There are dummy example files in
here, read their headers for usage instructions.
The ``src/`` directory
----------------------

View file

@ -8,8 +8,7 @@ and actions performed in the virtual world. Players typically interact
with each other and the world by typing commands that resemble a natural
language.*" - `Wikipedia <http://en.wikipedia.org/wiki/MUD>`_
Evennia introduction
====================
Evennia introduction=
If you are reading this, it's quite likely you are dreaming of creating
and running a text-based massively-multiplayer game
@ -54,15 +53,8 @@ commands, or to have the command syntax mimic other systems, like Diku,
LP, MOO and so on. Or why not create a new and better command system of
your own design.
There is already a default django website as well as an ajax web client
shipping with Evennia. You can also edit the database from the browser
using the admin interface. Apart from telnet, SSH, SSL and web
connections, you can connect e.g. IRC and IMC2 channels to evennia's
in-game channels so that your players can chat with people "outside" the
game.
Can I test it somewhere?
------------------------
~~~~~~~~~~~~~~~~~~~~~~~~
There are Evennia-based muds under development but they are still not
publicly available. If you do try to install Evennia (it's not hard), it
@ -74,6 +66,63 @@ tutorial takes only one single in-game command to install as explained
If you didn't see it before, here is also a
`screenshot <Screenshot.html>`_ of Evennia running.
Brief summary of features
=========================
Technical
~~~~~~~~~
- Game development is done by the server importing your normal Python
modules. Specific server features are implemented by overloading
hooks that the engine calls appropriately.
- All game entities are simply Python classes that handles database
negotiations behind the scenes without you needing to worry.
- Command sets are stored on individual objects (including characters)
to offer unique functionality and object-specific commands. Sets can
be updated and modified on the fly to expand/limit player input
options during play.
- Scripts are used to offer asynchronous/timed execution abilities.
Scripts can also be persistent. There are easy mechanisms to thread
particularly long-running processes.
- In-game communication channels are modular and can be modified to any
functionality, including mailing systems and full logging of all
messages.
- Server can be fully rebooted/reloaded without users disconnecting.
- A session (player) can freely connect/disconnect from game-objects,
offering an easy way to implement multi-character systems and
puppeting.
- All source code is extensively documented.
- Unit-testing suite, including tests of default commands and plugins
Default content
~~~~~~~~~~~~~~~
- Basic classes for Objects, Characers, Rooms and Exits
- Basic login system, using the Player's login name as their in-game
Character's name for simplicity
- "MUX-like" command set with administration, building, puppeting,
channels and social commands
- In-game Tutorial
- Contributions folder with working, but optional, code such as
alternative login, menus, character generation and more
Standards/Protocols supported
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Telnet with mud-specific extensions (MCCP, MSSP, TTYPE)
- SSH
- SSL
- TCP/Comet, JavaScript browser webclient included
- HTTP - Website served by in-built webserver and connected to same
database as game.
- IRC/IMC2 - external IRC and/or IMC2 channels can be connected to
in-game chat channels
- ANSI, xterm256 colours
- Several different databases supported (SQLite3, MySQL, ...)
For more extensive feature information, see
`here <http://code.google.com/p/evennia/wiki/DeveloperCentral>`_.
What you need to know to work with Evennia
==========================================

View file

@ -32,6 +32,33 @@ Third-party Evennia links
- `Evennia on
PyPi <http://pypi.python.org/pypi/Evennia%20MUD%20Server/Alpha>`_
General mud/game development ideas and discussions
--------------------------------------------------
- `MudLab <http://mudlab.org/>`_ mud design discussion forum
- `MudConnector <http://www.mudconnect.com/>`_ mud listing and forums
- `MudBytes <http://www.mudbytes.net/>`_ mud listing and forums
- `Top Mud bytes <http://www.topmudsites.com/>`_ mud listing and forums
- `MudStandards wiki <http://www.mudstandards.org/MudStandards_Wiki>`_
is an attempt at gathering protocol standards for MUD servers.
- `Planet Mud-Dev <http://planet-muddev.disinterest.org/>`_ is a blog
aggregator following blogs of current MUD development around the
'net.
- Mud Dev mailing list archive
(`mirror1 <http://nilgiri.net/MUD-Dev-archive/>`_),(`mirror2 <http://www.disinterest.org/resource/MUD-Dev/>`_)
- Influential mailing list active 1996-2004. Advanced game design
discussions.
- `Imaginary
Realities <http://disinterest.org/resource/imaginary-realities/>`_ is
an e-magazine on game/MUD design which were active 1998-2001.
Interesting articles.
- `Lost Garden <http://www.lostgarden.com/>`_ is a game development
blog with long and interesting articles (not MUD-specific)
- `What Games Are <http://whatgamesare.com/>`_ is a blog about general
game design (not MUD-specific)
Frameworks
----------

View file

@ -63,19 +63,9 @@ Defining locks
Defining a lock (i.e. an access restriction) in Evennia is done by
adding simple strings of lock definitions to the object's ``locks``
property using ``obj.locks.add()``. Such a *lockstring* formally looks
like this:
property using ``obj.locks.add()``.
::
access_type:[NOT] func1([arg1,..])[[AND|OR][ NOT] func2([arg1,...])[...]]
where ``[..]`` marks optional parts. AND, OR and NOT are not case
sensitive and excess spaces are ignored. ``func1, func2`` etc are
special *lock functions* available to the lock system.
This form of writing may look complicated, so let's immediately give
some much nicer examples:
Here are some examples of lock strings:
::
@ -83,7 +73,17 @@ some much nicer examples:
edit:all() # let everyone edit
get: not attr(very_weak) or perm(Wizard) # only those who are not "very_weak" or are Wizards may pick this up
So, a lockstring consists of the type of restriction (the
Formally, a lockstring has the following syntax:
::
access_type:[not] func1([arg1,..])[[and|or][ not] func2([arg1,...])[...]]
where ``[..]`` marks optional parts. AND, OR and NOT are not case
sensitive and excess spaces are ignored. ``func1, func2`` etc are
special *lock functions* available to the lock system.
So, a lockstrings consists of the type of restriction (the
``access_type``), a colon (``:``) and then a list of function calls that
determine what is needed to pass the lock. Each function returns either
``True`` or ``False``. AND/OR and NOT works like normal Python to

View file

@ -26,7 +26,7 @@ leaving the remaining poor characters in darkness once again.
By combining state-changes with timers one can make a room look
different during nighttime than it does during the day. Weather and
seasons might come and go. But one can also achieve more complex things
such as state-AI systems that make mobs move around and possibly persue
such as state-AI systems that make mobs move around and possibly pursue
characters between rooms.
... In short, Scripts make the game world *tick*. Scripts are
@ -130,6 +130,30 @@ find longer descriptions of these in ``gamesrc/scripts/basescript.py``.
- ``at_stop()`` - this is called when the script stops for whatever
reason. It's a good place to do custom cleanup.
Running methods (usually called automatically by the engine, but
possible to also invoke manually)
- ``start()`` - this will start the script. This is called
automatically whenever you add a new script to a handler.
``at_start()`` will be called.
- ``stop()`` - this will stop the script and delete it. Removing a
script from a handler will stop it auomatically. ``at_stop()`` will
be called.
- ``pause()`` - this pauses a running script, rendering it inactive,
but not deleting it. Timers are saved and can be resumed. This is
called automatically when the server reloads. No hooks are called -
this is a suspension of the script, not a change of state.
- ``unpause()`` - resumes a previously paused script. Timers etc are
restored to what they were before pause. The server unpauses all
paused scripts after a server reload. No hooks are called - as far as
the script is concerned, it never stopped running.
- ``time_until_next_repeat()`` - for timed scripts, this returns the
time in seconds until it next fires. Returns None if not a timed
script.
Example script
--------------
::
import random
@ -173,10 +197,18 @@ Or, from in-game, use the ``@script`` command:
@script here = weather.Weather
Further notes
-------------
Global scripts
--------------
Should you *really* need to create a script unrelated to a particular
Object (this is called a *Global* script), you can create it with
``src.utils.create.create_script()`` and refrain from supplying an
object to store it on. See that module for more info.
You can create scripts that are not attached to a given object -
*Global* scripts. You can create such a script with
``src.utils.create.create_script()`` by refrainnig from supplying an
object to store it on.
::
from src.utils.create import create_script
create_script(globals.MyGlobalEconomy, key="economy", obj=None)
Assuming ``game.gamesrc.scripts.global.MyGlobalEconomy`` can be found,
this will create and start it as a global script.

View file

@ -21,12 +21,14 @@ basically means that they are (almost) normal Python classes that hide
underlying database models ...
... and that's basically all you *really* need to know about how
typeclasses work behind the scenes. To work with them you should know
that all the listed game entities inherit a common interface from the
typeclass system, properties you can *always* expect a typeclassed
entity to have *beyond* the more specialized properties unique to each
sub-type. Typeclasses also do some special things with their in-built
class methods that you shouldn't edit.
typeclasses work behind the scenes.
To work with them you should however know that all the listed game
entities inherit a common interface from the typeclass system,
properties you can *always* expect a typeclassed entity to have *beyond*
the more specialized properties unique to each sub-type. Typeclasses
also do some special things with their in-built class methods that you
shouldn't edit.
Properties available to all typeclassed entities (Players, Objects,
Scripts)
@ -97,7 +99,7 @@ a few things that you need to remember however:
or you *will* crash the server! You have been warned.
How typeclasses actually work
-----------------------------
=============================
\_You don't need to read this section to use typeclassed entities, but
it might be useful if you want to do advanced things or are interested