Updated ReST documentation.
This commit is contained in:
parent
36b15b4ad8
commit
a8139feb1a
37 changed files with 963 additions and 910 deletions
|
|
@ -37,9 +37,9 @@ mod\_wsgi Setup
|
||||||
Install mod\_wsgi
|
Install mod\_wsgi
|
||||||
~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
mod*wsgi is an excellent, secure, and high-performance way to serve
|
mod\ *wsgi is an excellent, secure, and high-performance way to serve
|
||||||
Python projects. Code reloading is a breeze, Python modules are executed
|
Python projects. Code reloading is a breeze, Python modules are executed
|
||||||
as a user of your choice (which is a great security win), and mod*wsgi
|
as a user of your choice (which is a great security win), and mod*\ wsgi
|
||||||
is easy to set up on most distributions.
|
is easy to set up on most distributions.
|
||||||
|
|
||||||
For the sake of brevity, this guide will refer you to mod\_wsgi's
|
For the sake of brevity, this guide will refer you to mod\_wsgi's
|
||||||
|
|
@ -50,10 +50,10 @@ Ubuntu, you may install the entire stack with the following command:
|
||||||
|
|
||||||
``sudo aptitude install libapache2-mod-wsgi``
|
``sudo aptitude install libapache2-mod-wsgi``
|
||||||
|
|
||||||
This should install apache2 (if it isn't already), mod*wsgi, and load
|
This should install apache2 (if it isn't already), mod\ *wsgi, and load
|
||||||
the module. On Fedora or CentOS, you'll do this with ``yum`` and a
|
the module. On Fedora or CentOS, you'll do this with ``yum`` and a
|
||||||
similar package name that you'll need to search for. On Windows, you'll
|
similar package name that you'll need to search for. On Windows, you'll
|
||||||
need to download and install apache2 and mod*wsgi binaries.
|
need to download and install apache2 and mod*\ wsgi binaries.
|
||||||
|
|
||||||
Copy and modify the VHOST
|
Copy and modify the VHOST
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
@ -88,12 +88,13 @@ site <http://evennia.com>`_.
|
||||||
A note on code reloading
|
A note on code reloading
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
If your mod*wsgi is set up to run on daemon mode (as will be the case by
|
If your mod\ *wsgi is set up to run on daemon mode (as will be the case
|
||||||
default on Debian and Ubuntu), you may tell mod*wsgi to reload by using
|
by default on Debian and Ubuntu), you may tell mod*\ wsgi to reload by
|
||||||
the ``touch`` command on ``evennia/game/web/utils/apache_wsgi.conf``.
|
using the ``touch`` command on
|
||||||
When mod\_wsgi sees that the file modification time has changed, it will
|
``evennia/game/web/utils/apache_wsgi.conf``. When mod\_wsgi sees that
|
||||||
force a code reload. Any modifications to the code will not be
|
the file modification time has changed, it will force a code reload. Any
|
||||||
propagated to the live instance of your site until reloaded.
|
modifications to the code will not be propagated to the live instance of
|
||||||
|
your site until reloaded.
|
||||||
|
|
||||||
If you are not running in daemon mode or want to force the issue, simply
|
If you are not running in daemon mode or want to force the issue, simply
|
||||||
restart or reload apache2 to apply your changes.
|
restart or reload apache2 to apply your changes.
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ use of the ``run_async()`` function in ``src/utils/utils.py``.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
from src.utils import utils print "before call ..." utils.run_async(long_running_function) print "after call ..."
|
from ev import utils print "before call ..." utils.run_async(long_running_function) print "after call ..."
|
||||||
|
|
||||||
Now, when running this you will find that the program will not wait
|
Now, when running this you will find that the program will not wait
|
||||||
around for ``long_running_function`` to finish. Infact you will see
|
around for ``long_running_function`` to finish. Infact you will see
|
||||||
|
|
@ -93,7 +93,7 @@ An example of making an asynchronous call from inside a
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
from src.utils import utils from game.gamesrc.commands.basecommand import Command class CmdAsync(Command): key = "asynccommand" def func(self): def long_running_function(): #[... lots of time-consuming code return final_value def at_return(r): self.caller.msg("The final value is %s" % r) def at_err(e): self.caller.msg("There was an error: %s" % e) # do the async call, setting all callbacks utils.run_async(long_running_function, at_return, at_err)
|
from ev import utils from game.gamesrc.commands.basecommand import Command class CmdAsync(Command): key = "asynccommand" def func(self): def long_running_function(): #[... lots of time-consuming code return final_value def at_return(r): self.caller.msg("The final value is %s" % r) def at_err(e): self.caller.msg("There was an error: %s" % e) # do the async call, setting all callbacks utils.run_async(long_running_function, at_return, at_err)
|
||||||
|
|
||||||
That's it - from here on we can forget about ``long_running_function``
|
That's it - from here on we can forget about ``long_running_function``
|
||||||
and go on with what else need to be done. *Whenever* it finishes, the
|
and go on with what else need to be done. *Whenever* it finishes, the
|
||||||
|
|
|
||||||
|
|
@ -24,25 +24,25 @@ Saving and Retrieving data
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
To save persistent data on a Typeclassed object you normally use the
|
To save persistent data on a Typeclassed object you normally use the
|
||||||
``db`` operator. Let's try to save some data to a *Rose* (an
|
``db`` (!DataBase) operator. Let's try to save some data to a *Rose* (an
|
||||||
`Object <Objects.html>`_):
|
`Object <Objects.html>`_):
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
# saving rose.db.has_thorns = True # getting it back is_ouch = rose.db.has_thorns
|
# saving rose.db.has_thorns = True # getting it back is_ouch = rose.db.has_thorns
|
||||||
|
|
||||||
This looks like any normal Python assignment, but that ``db`` makes sure
|
This looks like any normal Python assignment, but that ``db`` makes sure
|
||||||
that an *Attribute* is created behind the scenes and is stored in the
|
that an *Attribute* is created behind the scenes and is stored in the
|
||||||
database. Your rose will continue to have thorns throughout the life of
|
database. Your rose will continue to have thorns throughout the life of
|
||||||
the server now, until you deliberately remove them.
|
the server now, until you deliberately remove them.
|
||||||
|
|
||||||
To be sure to save **non-persistently**, i.e. to make sure NOT create a
|
To be sure to save **non-persistently**, i.e. to make sure NOT to create
|
||||||
database entry, you use ``ndb`` (!NonDataBase). It works in the same
|
a database entry, you use ``ndb`` (!NonDataBase). It works in the same
|
||||||
way:
|
way:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
# saving rose.ndb.has_thorns = True # getting it back is_ouch = rose.ndb.has_thorns
|
# saving rose.ndb.has_thorns = True # getting it back is_ouch = rose.ndb.has_thorns
|
||||||
|
|
||||||
Strictly speaking, ``ndb`` has nothing to do with ``Attributes``,
|
Strictly speaking, ``ndb`` has nothing to do with ``Attributes``,
|
||||||
despite how similar they look. No ``Attribute`` object is created behind
|
despite how similar they look. No ``Attribute`` object is created behind
|
||||||
|
|
@ -56,28 +56,52 @@ will for example delete an ``Attribute``:
|
||||||
|
|
||||||
del rose.db.has_thorns
|
del rose.db.has_thorns
|
||||||
|
|
||||||
Fast assignment
|
Both ``db`` and ``ndb`` defaults to offering an ``all`` property on
|
||||||
---------------
|
themselves. This returns all associated attributes or non-persistent
|
||||||
|
properties.
|
||||||
For quick testing you can most often skip the ``db`` operator and assign
|
|
||||||
Attributes like you would any normal Python property:
|
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
# saving rose.has_thorns = True# getting it back is_ouch = rose.has_thorns
|
list_of_all_rose_attributes = rose.db.all list_of_all_rose_ndb_attrs = rose.ndb.all
|
||||||
|
|
||||||
|
If you use ``all`` as the name of an attribute, this will be used
|
||||||
|
instead. Later deleting your custom ``all`` will return the default
|
||||||
|
behaviour.
|
||||||
|
|
||||||
|
Fast assignment
|
||||||
|
---------------
|
||||||
|
|
||||||
|
For quick testing you can in principle skip the ``db`` operator and
|
||||||
|
assign Attributes like you would any normal Python property:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
# saving rose.has_thorns = True # getting it back is_ouch = rose.has_thorns
|
||||||
|
|
||||||
This looks like any normal Python assignment, but calls ``db`` behind
|
This looks like any normal Python assignment, but calls ``db`` behind
|
||||||
the scenes for you.
|
the scenes for you.
|
||||||
|
|
||||||
Note however that this form stands the chance of overloading already
|
Note however that this form stands the chance of overloading already
|
||||||
existing properties on typeclasses and their database objects.
|
existing properties on typeclasses and their database objects. Unless
|
||||||
``rose.msg()`` is for example an already defined method for sending
|
you know what you are doing, this can cause lots of trouble.
|
||||||
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
|
rose.msg("hello") # this uses the in-built msg() method rose.msg = "Ouch!" # this OVERLOADS the msg() method with a string rose.msg("hello") # this now a gives traceback!
|
||||||
the safer bet. And it also makes it visually clear at all times when you
|
|
||||||
are saving to the database and not.
|
Overloading ``msg()`` with a string is a very bad idea since Evennia
|
||||||
|
uses this method all the time to send text to you. There are of course
|
||||||
|
situations when you *want* to overload default methods with your own
|
||||||
|
implementations - but then you'll hopefully do so intentionally and with
|
||||||
|
something that works.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
rose.db.msg = "Ouch" # this stands no risk of overloading msg() rose.msg("hello") # this works as it should
|
||||||
|
|
||||||
|
So using ``db``/``ndb`` will always do what you expect and is usually
|
||||||
|
the safer bet. It also makes it visually clear at all times when you are
|
||||||
|
saving to the database and not.
|
||||||
|
|
||||||
Another drawback of this shorter form is that it will handle a non-found
|
Another drawback of this shorter form is that it will handle a non-found
|
||||||
Attribute as it would any non-found property on the object. The ``db``
|
Attribute as it would any non-found property on the object. The ``db``
|
||||||
|
|
@ -97,32 +121,33 @@ is, you don't have to. Most of the time you really want to save as much
|
||||||
as you possibly can. Non-persistent data is potentially useful in a few
|
as you possibly can. Non-persistent data is potentially useful in a few
|
||||||
situations though.
|
situations though.
|
||||||
|
|
||||||
- You are worried about database performance. Maybe you are
|
- You are worried about database performance. Since Evennia caches
|
||||||
reading/storing data many times a second (for whatever reason) or you
|
Attributes very aggressively, this is not an issue unless you are
|
||||||
have many players doing things at the same time. Hitting the database
|
reading *and* writing to your Attribute very often (like many times
|
||||||
over and over might not be ideal in that case. Non-persistent data
|
per second). Reading from an already cached Attribute is as fast as
|
||||||
simply writes to memory, it doesn't hit the database at all. It
|
reading any Python property. But even then this is not likely
|
||||||
should be said that with the speed and quality of hardware these
|
something to worry about: Apart from Evennia's own caching, modern
|
||||||
days, this point is less likely to be of any big concern except for
|
database systems themselves also cache data very efficiently for
|
||||||
the most extreme of situations. Modern database systems cache data
|
speed. Our default database even runs completely in RAM if possible,
|
||||||
very efficiently for speed. Our default database even runs completely
|
alleviating much of the need to write to disk during heavy loads.
|
||||||
in RAM if possible, alleviating much of the need to write to disk
|
- A more valid reason for using non-persistent data is if you *want* to
|
||||||
during heavy loads.
|
loose your state when logging off. Maybe you are storing throw-away
|
||||||
- You *want* to loose your state when logging off. Maybe you are
|
data that are re-initialized at server startup. Maybe you are
|
||||||
testing a buggy `Script <Scripts.html>`_ that does potentially
|
implementing some caching of your own. Or maybe you are testing a
|
||||||
harmful stuff to your character object. With non-persistent storage
|
buggy `Script <Scripts.html>`_ that does potentially harmful stuff to
|
||||||
you can be sure that whatever the script messes up, it's nothing a
|
your character object. With non-persistent storage you can be sure
|
||||||
server reboot can't clear up.
|
that whatever is messed up, it's nothing a server reboot can't clear
|
||||||
|
up.
|
||||||
- You want to implement a fully or partly *non-persistent world*. Who
|
- You want to implement a fully or partly *non-persistent world*. Who
|
||||||
are we to argue with your grand vision!
|
are we to argue with your grand vision!
|
||||||
|
|
||||||
What types of data can I save?
|
What types of data can I save in an Attribute?
|
||||||
------------------------------
|
----------------------------------------------
|
||||||
|
|
||||||
If you store a single object (that is, not a iterable list of objects),
|
If you store a single object (that is, not an iterable list of objects),
|
||||||
you can practically store any Python object that can be
|
you can practically store any Python object that can be
|
||||||
`pickled <http://docs.python.org/library/pickle.html>`_. Evennia uses
|
`pickled <http://docs.python.org/library/pickle.html>`_. Evennia uses
|
||||||
the ``pickle`` module to serialize data into the database.
|
the ``pickle`` module to serialize Attribute data into the database.
|
||||||
|
|
||||||
There is one notable type of object that cannot be pickled - and that is
|
There is one notable type of object that cannot be pickled - and that is
|
||||||
a Django database object. These will instead be stored as a wrapper
|
a Django database object. These will instead be stored as a wrapper
|
||||||
|
|
@ -132,7 +157,7 @@ accessed. Since erroneously trying to save database objects in an
|
||||||
Attribute will lead to errors, Evennia will try to detect database
|
Attribute will lead to errors, Evennia will try to detect database
|
||||||
objects by analyzing the data being stored. This means that Evennia must
|
objects by analyzing the data being stored. This means that Evennia must
|
||||||
recursively traverse all iterables to make sure all database objects in
|
recursively traverse all iterables to make sure all database objects in
|
||||||
them are stored safely. So for efficiency, it can be a good idea is to
|
them are stored safely. So for efficiency, it can be a good idea to
|
||||||
avoid deeply nested lists with objects if you can.
|
avoid deeply nested lists with objects if you can.
|
||||||
|
|
||||||
To store several objects, you may only use python *lists*,
|
To store several objects, you may only use python *lists*,
|
||||||
|
|
@ -146,13 +171,14 @@ usually not a limitation you need to worry about.
|
||||||
custom, non-iterable classes and stored database objects in them. So to
|
custom, non-iterable classes and stored database objects in them. So to
|
||||||
make this clear - saving such an object is **not supported** and will
|
make this clear - saving such an object is **not supported** and will
|
||||||
probably make your game unstable. Store your database objects using
|
probably make your game unstable. Store your database objects using
|
||||||
lists, dictionaries or a combination of the two and you should be fine.*
|
lists, tuples, dictionaries or a combination of the three and you should
|
||||||
|
be fine.*
|
||||||
|
|
||||||
Examples of valid attribute data:
|
Examples of valid attribute data:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
# a single value obj.db.test1 = 23 obj.db.test1 = False # a database object (will be stored as dbref) obj.db.test2 = myobj # a list of objects obj.db.test3 = [obj1, 45, obj2, 67] # a dictionary obj.db.test4 = 'str':34, 'dex':56, 'agi':22, 'int':77 # a mixed dictionary/list obj.db.test5 = 'members': [obj1,obj2,obj3], 'enemies':[obj4,obj5] # a tuple with a list in it obj.db.test6 = (1,3,4,8, ["test", "test2"], 9) # a set will still be stored and returned as a list [1,2,3,4,5]! obj.db.test7 = set([1,2,3,4,5])
|
# a single value obj.db.test1 = 23 obj.db.test1 = False # a database object (will be stored as dbref) obj.db.test2 = myobj # a list of objects obj.db.test3 = [obj1, 45, obj2, 67] # a dictionary obj.db.test4 = 'str':34, 'dex':56, 'agi':22, 'int':77 # a mixed dictionary/list obj.db.test5 = 'members': [obj1,obj2,obj3], 'enemies':[obj4,obj5] # a tuple with a list in it obj.db.test6 = (1,3,4,8, ["test", "test2"], 9) # a set will still be stored and returned as a list [1,2,3,4,5]! obj.db.test7 = set([1,2,3,4,5]) # in-situ manipulation obj.db.test8 = [1,2,"test":1] obj.db.test8[0] = 4 obj.db.test8[2]["test"] = 5 # test8 is now [4,2,"test":5]
|
||||||
|
|
||||||
Example of non-supported save:
|
Example of non-supported save:
|
||||||
|
|
||||||
|
|
@ -164,21 +190,44 @@ Retrieving Mutable objects
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
A side effect of the way Evennia stores Attributes is that Python Lists
|
A side effect of the way Evennia stores Attributes is that Python Lists
|
||||||
and Dictionaries (only )are handled by custom objects called PackedLists
|
and Dictionaries (only) are handled by custom objects called PackedLists
|
||||||
and !PackedDicts. These have the special property that they save to the
|
and !PackedDicts. These behave just like normal lists and dicts except
|
||||||
database whenever new data gets assigned to them. This allows you to do
|
they have the special property that they save to the database whenever
|
||||||
things like self.db.mylist`4 <4.html>`_
|
new data gets assigned to them. This allows you to do things like
|
||||||
|
``self.db.mylist[4]`` = val without having to extract the mylist
|
||||||
val without having to extract the mylist Attribute into a temporary
|
Attribute into a temporary variable first.
|
||||||
variable first.
|
|
||||||
|
|
||||||
There is however an important thing to remember. If you retrieve this
|
There is however an important thing to remember. If you retrieve this
|
||||||
data into another variable, e.g. ``mylist2 = obj.db.mylist``, your new
|
data into another variable, e.g. ``mylist2 = obj.db.mylist``, your new
|
||||||
variable will *still* be a PackedList, and if you assign things to it,
|
variable (``mylist2``) will *still* be a !PackedList! This means it will
|
||||||
it will save to the database! To "disconnect" it from the database
|
continue to save itself to the database whenever it is updated! This is
|
||||||
system, you need to convert it to a normal list with mylist2
|
important to keep in mind so you are not confused by the results.
|
||||||
|
|
||||||
list(mylist2).
|
::
|
||||||
|
|
||||||
|
obj.db.mylist = [1,2,3,4] mylist = obj.db.mylist mylist[3] = 5 # this will also update database print mylist # this is now [1,2,3,5] print mylist.db.mylist # this is also [1,2,3,5]
|
||||||
|
|
||||||
|
To "disconnect" your extracted mutable variable from the database you
|
||||||
|
simply need to convert the PackedList or PackedDict to a normal Python
|
||||||
|
list or dictionary. This is done with the builtin ``list()`` and
|
||||||
|
``dict()`` functions. In the case of "nested" lists and dicts, you only
|
||||||
|
have to convert the "outermost" list/dict in order to cut the entire
|
||||||
|
structure's connection to the database.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
obj.db.mylist = [1,2,3,4] mylist = list(obj.db.mylist) # convert to normal list mylist[3] = 5 print mylist # this is now [1,2,3,5] print obj.db.mylist # this remains [1,2,3,4]
|
||||||
|
|
||||||
|
Remember, this is only valid for mutable iterables - lists and dicts and
|
||||||
|
combinations of the two.
|
||||||
|
`Immutable <http://en.wikipedia.org/wiki/Immutable>`_ objects (strings,
|
||||||
|
numbers, tuples etc) are already disconnected from the database from the
|
||||||
|
onset. So making the outermost iterable into a tuple is also a way to
|
||||||
|
stop any changes to the structure from updating the database.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
obj.db.mytup = (1,2,[3,4]) obj.db.mytup[0] = 5 # this fails since tuples are immutable obj.db.mytup[2][1] = 5 # this works but will NOT update database since outermost iterable is a tuple print obj.db.mytup[2][1] # this still returns 4, not 5 mytup1 = obj.db.mytup # mytup1 is already disconnected from database since outermost # iterable is a tuple, so we can edit the internal list as we want # without affecting the database.
|
||||||
|
|
||||||
Notes
|
Notes
|
||||||
-----
|
-----
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ The batch-command processor is a superuser-only function, invoked by
|
||||||
> @batchcode path.to.batchcodefile
|
> @batchcode path.to.batchcodefile
|
||||||
|
|
||||||
Where ``path.to.batchcodefile`` is the path to a *batch-code file* with
|
Where ``path.to.batchcodefile`` is the path to a *batch-code file* with
|
||||||
the "``.py``" file ending. This path is given like a python path
|
the "``.py``\ " file ending. This path is given like a python path
|
||||||
relative to a folder you define to hold your batch files, set by
|
relative to a folder you define to hold your batch files, set by
|
||||||
``BATCH_IMPORT_PATH`` in your settings. Default folder is
|
``BATCH_IMPORT_PATH`` in your settings. Default folder is
|
||||||
``game/gamesrc/world``. So if you want to run the example batch file in
|
``game/gamesrc/world``. So if you want to run the example batch file in
|
||||||
|
|
@ -61,10 +61,15 @@ Here are the rules of syntax of the batch-command ``*.py`` file.
|
||||||
``obj1, obj2, ...`` parts are optional object labels used by the
|
``obj1, obj2, ...`` parts are optional object labels used by the
|
||||||
processor's *debug* mode in order to auto-delete objects after a test
|
processor's *debug* mode in order to auto-delete objects after a test
|
||||||
run.
|
run.
|
||||||
- A new ``#HEADER`` or ``#CODE`` (or the end of the file) ends the
|
- ``#INSERT path.filename`` as the first on a line loads the contents
|
||||||
previous block. Text before the first block are ignored.
|
of another batch-code file into this one. Its ``#CODE`` blocks will
|
||||||
- A ``#`` that is not starting a ``#HEADER`` or ``#CODE`` block is
|
be executed as if they were defined in this file, but they will not
|
||||||
considered a comment.
|
share ``#HEADER``\ s with the current file, but only use its own, if
|
||||||
|
any.
|
||||||
|
- A new ``#HEADER``, ``#CODE`` or ``#INSERT`` (or the end of the file)
|
||||||
|
ends a previous block. Text before the first block are ignored.
|
||||||
|
- A ``#`` that is not starting a ``#HEADER``, ``#CODE`` or ``#INSERT``
|
||||||
|
instruction is considered a comment.
|
||||||
- Inside a block, normal Python syntax rules apply. For the sake of
|
- Inside a block, normal Python syntax rules apply. For the sake of
|
||||||
indentation, each block acts as a separate python module.
|
indentation, each block acts as a separate python module.
|
||||||
- The variable ``caller`` is always made available to the script,
|
- The variable ``caller`` is always made available to the script,
|
||||||
|
|
@ -77,7 +82,7 @@ Below is a version of the example file found in
|
||||||
|
|
||||||
#
|
#
|
||||||
# This is an example batch-code build file for Evennia.
|
# This is an example batch-code build file for Evennia.
|
||||||
##HEADER# This will be included in all other #CODE blocksfrom src.utils import create, search from game.gamesrc.objects.examples import red_button from game.gamesrc.objects import baseobjectslimbo = search.objects(caller, 'Limbo', global_search=True)[0]#CODE (create red button)red_button = create.create_object(red_button.RedButton, key="Red button", location=limbo, aliases=["button"])# caller points to the one running the script caller.msg("A red button was created.")#CODE (create table and chair) table, chairtable = create.create_object(baseobjects.Object, key="Blue Table", location=limbo) chair = create.create_object(baseobjects.Object, key="Blue Chair", location=limbo)string = "A %s and %s were created. If debug was active, they were deleted again." caller.msg(string % (table, chair))
|
##HEADER# This will be included in all other #CODE blocksfrom src.utils import create, search from game.gamesrc.objects.examples import red_button from game.gamesrc.objects import baseobjectslimbo = search.objects(caller, 'Limbo', global_search=True)[0]#CODE (create red button)red_button = create.create_object(red_button.RedButton, key="Red button", location=limbo, aliases=["button"])# caller points to the one running the script caller.msg("A red button was created.")# importing more code from another batch-code file #INSERT examples.batch_code_insert#CODE (create table and chair) table, chairtable = create.create_object(baseobjects.Object, key="Blue Table", location=limbo) chair = create.create_object(baseobjects.Object, key="Blue Chair", location=limbo)string = "A %s and %s were created. If debug was active, they were deleted again." caller.msg(string % (table, chair))
|
||||||
|
|
||||||
This uses Evennia's Python API to create three objects in sequence.
|
This uses Evennia's Python API to create three objects in sequence.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ The batch-command processor is a superuser-only function, invoked by
|
||||||
> @batchcommand path.to.batchcmdfile
|
> @batchcommand path.to.batchcmdfile
|
||||||
|
|
||||||
Where ``path.to.batchcmdfile`` is the path to a *batch-command file*
|
Where ``path.to.batchcmdfile`` is the path to a *batch-command file*
|
||||||
with the "``.ev``" file ending. This path is given like a python path
|
with the "``.ev``\ " file ending. This path is given like a python path
|
||||||
relative to a folder you define to hold your batch files, set with
|
relative to a folder you define to hold your batch files, set with
|
||||||
``BATCH_IMPORT_PATH`` in your settings. Default folder is
|
``BATCH_IMPORT_PATH`` in your settings. Default folder is
|
||||||
``game/gamesrc/world``. So if you want to run the example batch file in
|
``game/gamesrc/world``. So if you want to run the example batch file in
|
||||||
|
|
@ -52,6 +52,11 @@ really, really simple:
|
||||||
after one another in the file - separate them with a comment, or the
|
after one another in the file - separate them with a comment, or the
|
||||||
second of the two will be considered an argument to the first one.
|
second of the two will be considered an argument to the first one.
|
||||||
Besides, using plenty of comments is good practice anyway.
|
Besides, using plenty of comments is good practice anyway.
|
||||||
|
- A line that starts with the word ``#INSERT`` is a comment line but
|
||||||
|
also signifies a special instruction. The syntax is
|
||||||
|
``#INSERT <path.batchfile>`` and tries to import a given batch-cmd
|
||||||
|
file into this one. The inserted batch file (file ending ``.ev``)
|
||||||
|
will run normally from the point of the ``#INSERT`` instruction.
|
||||||
- Extra whitespace in a command definition is *ignored*.
|
- Extra whitespace in a command definition is *ignored*.
|
||||||
- A completely empty line translates in to a line break in texts. Two
|
- A completely empty line translates in to a line break in texts. Two
|
||||||
empty lines thus means a new paragraph (this is obviously only
|
empty lines thus means a new paragraph (this is obviously only
|
||||||
|
|
@ -59,13 +64,18 @@ really, really simple:
|
||||||
``@desc`` command).
|
``@desc`` command).
|
||||||
- The very last command in the file is not required to end with a
|
- The very last command in the file is not required to end with a
|
||||||
comment.
|
comment.
|
||||||
|
- You *cannot* nest another ``@batchcommand`` statement into your batch
|
||||||
|
file. If you want to link many batch-files together, use the
|
||||||
|
``#INSERT`` batch instruction instead. You also cannot launch the
|
||||||
|
``@batchcode`` command from your batch file, the two batch processors
|
||||||
|
are not compatible.
|
||||||
|
|
||||||
Below is a version of the example file found in
|
Below is a version of the example file found in
|
||||||
``game/gamesrc/commands/examples/batch_cmds.ev``.
|
``game/gamesrc/commands/examples/batch_cmds.ev``.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
# # This is an example batch build file for Evennia. ## This creates a red button @create button:examples.red_button.RedButton # (This comment ends input for @create) # Next command. Let's create something. @set button/desc = This is a large red button. Now and then it flashes in an evil, yet strangely tantalizing way. A big sign sits next to it. It says:----------- Press me! ----------- ... It really begs to be pressed! You know you want to! # (This ends the @set command). Note that single line breaks # and extra whitespace in the argument are ignored. Empty lines # translate into line breaks in the output. # Now let's place the button where it belongs (let's say limbo #2 is # the evil lair in our example) @teleport #2 # (This comments ends the @teleport command.) # Now we drop it so others can see it. # The very last command in the file needs not be ended with #. drop button
|
# # This is an example batch build file for Evennia. ## This creates a red button @create button:examples.red_button.RedButton # (This comment ends input for @create) # Next command. Let's create something. @set button/desc = This is a large red button. Now and then it flashes in an evil, yet strangely tantalizing way. A big sign sits next to it. It says:----------- Press me! ----------- ... It really begs to be pressed! You know you want to! # This inserts the commands from another batch-cmd file named # batch_insert_file.ev. #INSERT examples.batch_insert_file # (This ends the @set command). Note that single line breaks # and extra whitespace in the argument are ignored. Empty lines # translate into line breaks in the output. # Now let's place the button where it belongs (let's say limbo #2 is # the evil lair in our example) @teleport #2 # (This comments ends the @teleport command.) # Now we drop it so others can see it. # The very last command in the file needs not be ended with #. drop button
|
||||||
|
|
||||||
To test this, run ``@batchcommand`` on the file. A button will be
|
To test this, run ``@batchcommand`` on the file. A button will be
|
||||||
created, described and dropped in Limbo. All commands will be executed
|
created, described and dropped in Limbo. All commands will be executed
|
||||||
|
|
|
||||||
|
|
@ -37,17 +37,20 @@ as locks. This can be useful, but it also hides some functionality that
|
||||||
you might want to test. Let's create a more "normal" Builder player
|
you might want to test. Let's create a more "normal" Builder player
|
||||||
account instead.
|
account instead.
|
||||||
|
|
||||||
Log off and choose ``create`` from the login screen. Create a new
|
Get to Evennia's login screen (log off with ``@quit`` if you are already
|
||||||
account (don't log in). Let's say we call the new account "Anna". Next
|
connected) and choose ``create`` from the login screen. Create a new
|
||||||
log in as your superuser account and give the recently created player
|
account (don't log in yet). You can use any e-mail address, it doesn't
|
||||||
build rights:
|
have to be an existing one. Let's say we call the new account "Anna".
|
||||||
|
Next log in *on your superuser account* and give the recently created
|
||||||
|
player build rights:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
@perm Anna = Builders
|
@perm Anna = Builders
|
||||||
|
|
||||||
That should do it. Log out again (``@quit``) and finally log back in as
|
You could give the permission "Immortals" instead, if you want to assign
|
||||||
your builder account.
|
full admin privileges. Log out of your superuser account (``@quit``) and
|
||||||
|
finally log back in again as your new builder account.
|
||||||
|
|
||||||
Creating an object
|
Creating an object
|
||||||
------------------
|
------------------
|
||||||
|
|
@ -129,8 +132,8 @@ and try to get the box now:
|
||||||
Think the default error message looks dull? The ``get`` command looks
|
Think the default error message looks dull? The ``get`` command looks
|
||||||
for an `Attribute <Attributes.html>`_ named ``get_err_msg`` for
|
for an `Attribute <Attributes.html>`_ named ``get_err_msg`` for
|
||||||
returning a nicer error message (we just happen to know this, you would
|
returning a nicer error message (we just happen to know this, you would
|
||||||
currently need to peek into the code for the ``get`` command to find
|
need to peek into the code for the ``get`` command to find out). You set
|
||||||
out. You set attributes using the ``@set`` command:
|
attributes using the ``@set`` command:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
|
@ -185,11 +188,10 @@ object-based `Commands <Commands.html>`_, you could expand it and other
|
||||||
items to be as unique, complex and interactive as you want.
|
items to be as unique, complex and interactive as you want.
|
||||||
|
|
||||||
Let's take an example. So far we have only created objects that use the
|
Let's take an example. So far we have only created objects that use the
|
||||||
default object typeclass found in
|
default object typeclass named simply ``Object``. Let's create an object
|
||||||
``game/gamesrc/objects/baseobjects.py``. It is called simply *Object*.
|
that is a little more interesting. Under ``game/gamesrc/objects/`` there
|
||||||
Let's create an object that is a little more interesting. Under
|
is a directory ``examples`` with a module ``red_button.py``. It contains
|
||||||
``game/gamesrc/objects/`` there is a directory ``examples`` with a
|
the enigmatic RedButton typeclass.
|
||||||
module ``red_button.py``. It contains the enigmatic RedButton typeclass.
|
|
||||||
|
|
||||||
Let's make us one of *those*!
|
Let's make us one of *those*!
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@ unless your database is huge.
|
||||||
|
|
||||||
**Note:** If you for some reason need to use a third-party web server
|
**Note:** If you for some reason need to use a third-party web server
|
||||||
like Apache rather than Evennia's internal web server, SQLite is
|
like Apache rather than Evennia's internal web server, SQLite is
|
||||||
probably not be the best choice. This is due to the possibility of
|
probably not the best choice. This is due to the possibility of clashes
|
||||||
clashes with file-locking when using SQLite from more than one process.
|
with file-locking when using SQLite from more than one process.
|
||||||
|
|
||||||
Postgres
|
Postgres
|
||||||
--------
|
--------
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,7 @@ Defining a Command
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
All commands are implemented as normal Python classes inheriting from
|
All commands are implemented as normal Python classes inheriting from
|
||||||
the base class ``Command``
|
the base class ``Command`` (``ev.Command``). You will find that this
|
||||||
(``game.gamesrc.commands.basecommand.Command``). You will find that this
|
|
||||||
base class is very "bare". The default commands of Evennia actually
|
base class is very "bare". The default commands of Evennia actually
|
||||||
inherit from a child of ``Command`` called ``MuxCommand`` - this is the
|
inherit from a child of ``Command`` called ``MuxCommand`` - this is the
|
||||||
class that knows all the mux-like syntax like ``/switches``, splitting
|
class that knows all the mux-like syntax like ``/switches``, splitting
|
||||||
|
|
@ -48,7 +47,7 @@ class directly.
|
||||||
::
|
::
|
||||||
|
|
||||||
# basic Command definition
|
# basic Command definition
|
||||||
from game.gamesrc.commands.basecommand import Command
|
from ev import Command
|
||||||
class MyCmd(Command):
|
class MyCmd(Command):
|
||||||
"""
|
"""
|
||||||
This is the help-text for the command
|
This is the help-text for the command
|
||||||
|
|
@ -86,18 +85,18 @@ assigns it the following properties:
|
||||||
*Player* object (usually used only when a Player has no character
|
*Player* object (usually used only when a Player has no character
|
||||||
assigned to them, like when creating a new one).
|
assigned to them, like when creating a new one).
|
||||||
- ``cmdstring`` - the matched key for the command. This would be
|
- ``cmdstring`` - the matched key for the command. This would be
|
||||||
"``look``" in our example.
|
"``look``\ " in our example.
|
||||||
- ``args`` - this is the rest of the string, except the command name.
|
- ``args`` - this is the rest of the string, except the command name.
|
||||||
So if the string entered was ``look at sword``, ``args`` would simply
|
So if the string entered was ``look at sword``, ``args`` would simply
|
||||||
be "``at sword``".
|
be "``at sword``\ ".
|
||||||
- ``obj`` - the game `Object <Objects.html>`_ on which this command is
|
- ``obj`` - the game `Object <Objects.html>`_ on which this command is
|
||||||
defined. This need not be the caller, but since ``look`` is a common
|
defined. This need not be the caller, but since ``look`` is a common
|
||||||
(default) command, this is probably defined directly on *!BigGuy* -
|
(default) command, this is probably defined directly on *!BigGuy* -
|
||||||
so ``obj`` will point to !BigGuy. Otherwise ``obj`` could be any
|
so ``obj`` will point to !BigGuy. Otherwise ``obj`` could be any
|
||||||
interactive object with commands defined on it, like in the example
|
interactive object with commands defined on it, like in the example
|
||||||
of the "check time" command defined on a "Clock" object or a `red
|
of the "check time" command defined on a "Clock" object or a `red
|
||||||
button <https://code.google.com/p/evennia/source/browse/trunk/game/gamesrc/objects/examples/red%3Ci%3Ebutton.py.html>`_
|
button <https://code.google.com/p/evennia/source/browse/trunk/game/gamesrc/objects/examples/red<i>button.py.html>`_
|
||||||
that you can "``push``".
|
that you can "``push``\ ".
|
||||||
- ``cmdset`` - this is a reference to the merged CmdSet (see below)
|
- ``cmdset`` - this is a reference to the merged CmdSet (see below)
|
||||||
from which this command was matched. This variable is rarely used,
|
from which this command was matched. This variable is rarely used,
|
||||||
it's main use is for the `auto-help system <HelpSystem.html>`_
|
it's main use is for the `auto-help system <HelpSystem.html>`_
|
||||||
|
|
@ -113,9 +112,7 @@ Beyond the properties Evennia always assigns to the command at runtime
|
||||||
|
|
||||||
- ``key`` (string) - the identifier for the command, like ``look``.
|
- ``key`` (string) - the identifier for the command, like ``look``.
|
||||||
This should (ideally) be unique. it can be more than one word long in
|
This should (ideally) be unique. it can be more than one word long in
|
||||||
a string, like "press button". Maximum number of space-separated
|
a string, like "press button" or "pull lever left".
|
||||||
words that can be part of a command name is given by
|
|
||||||
``settings.CMD_MAXLEN``.
|
|
||||||
- ``aliases`` (optional list) - a list of alternate names for the
|
- ``aliases`` (optional list) - a list of alternate names for the
|
||||||
command (``["l", "glance", "see"]``). Same name rules as for ``key``
|
command (``["l", "glance", "see"]``). Same name rules as for ``key``
|
||||||
applies.
|
applies.
|
||||||
|
|
@ -131,10 +128,10 @@ Beyond the properties Evennia always assigns to the command at runtime
|
||||||
to it) will be stored by the system and can be accessed by the next
|
to it) will be stored by the system and can be accessed by the next
|
||||||
command called by retrieving ``self.caller.ndb.last_cmd``. The next
|
command called by retrieving ``self.caller.ndb.last_cmd``. The next
|
||||||
run command will either clear or replace the storage.
|
run command will either clear or replace the storage.
|
||||||
- 'arg*regex' (optional raw string): This should be given as a `raw
|
- 'arg\ *regex' (optional raw string): This should be given as a `raw
|
||||||
regular expression string <http://docs.python.org/library/re.html>`_.
|
regular expression string <http://docs.python.org/library/re.html>`_.
|
||||||
This will be compiled by the system at runtime. This allows you to
|
This will be compiled by the system at runtime. This allows you to
|
||||||
customize how the part*immediately following the command name (or
|
customize how the part*\ immediately following the command name (or
|
||||||
alias) must look in order for the parser to match for this command.
|
alias) must look in order for the parser to match for this command.
|
||||||
Normally the parser is highly efficient in picking out the command
|
Normally the parser is highly efficient in picking out the command
|
||||||
name, also as the beginning of a longer word (as long as the longer
|
name, also as the beginning of a longer word (as long as the longer
|
||||||
|
|
@ -147,7 +144,7 @@ Beyond the properties Evennia always assigns to the command at runtime
|
||||||
expected.
|
expected.
|
||||||
- autohelp (optional boolean). Defaults to ``True``. This allows for
|
- autohelp (optional boolean). Defaults to ``True``. This allows for
|
||||||
turning off the `auto-help
|
turning off the `auto-help
|
||||||
system <HelpSystem#Command%3Ci%3EAuto-help%3C/i%3Esystem.html>`_ on a
|
system <HelpSystem#Command<i>Auto-help</i>system.html>`_ on a
|
||||||
per-command basis. This could be useful if you either want to write
|
per-command basis. This could be useful if you either want to write
|
||||||
your help entries manually or hide the existence of a command from
|
your help entries manually or hide the existence of a command from
|
||||||
``help``'s generated list.
|
``help``'s generated list.
|
||||||
|
|
@ -173,11 +170,11 @@ by the `Help system <HelpSystem.html>`_ to create the help entry for
|
||||||
this command. You should decide on a way to format your help and stick
|
this command. You should decide on a way to format your help and stick
|
||||||
to that.
|
to that.
|
||||||
|
|
||||||
Below is how you define a simple alternative "``look at``" command:
|
Below is how you define a simple alternative "``look at``\ " command:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
from game.gamesrc.commands.basecommand import Commandclass CmdLookAt(Command): """ An alternative (and silly) look command Usage: look at <what> Where <what> may only be 'here' in this example. This initial string (the __doc__ string) is also used to auto-generate the help for this command ... """ key = "look at" # this is the command name to use aliases = ["la", "look a"] # aliases to the command name locks = "cmd:all()" help_category = "General" def parse(self): "Very trivial parser" self.what = self.args.strip() def func(self): "This actually does things" caller = self.caller if not self.what: caller.msg("Look at what?") elif self.what == 'here': # look at the current location description = caller.location.db.desc caller.msg(description) else: # we don't add any more functionality in this example caller.msg("Sorry, you can only look 'here'...")
|
from ev import Commandclass CmdLookAt(Command): """ An alternative (and silly) look command Usage: look at <what> Where <what> may only be 'here' in this example. This initial string (the __doc__ string) is also used to auto-generate the help for this command ... """ key = "look at" # this is the command name to use aliases = ["la", "look a"] # aliases to the command name locks = "cmd:all()" help_category = "General" def parse(self): "Very trivial parser" self.what = self.args.strip() def func(self): "This actually does things" caller = self.caller if not self.what: caller.msg("Look at what?") elif self.what == 'here': # look at the current location description = caller.location.db.desc caller.msg(description) else: # we don't add any more functionality in this example caller.msg("Sorry, you can only look 'here'...")
|
||||||
|
|
||||||
The power of having commands as classes and to separate ``parse()`` and
|
The power of having commands as classes and to separate ``parse()`` and
|
||||||
``func()`` lies in the ability to inherit functionality without having
|
``func()`` lies in the ability to inherit functionality without having
|
||||||
|
|
@ -201,7 +198,7 @@ number of different !CmdSets. CmdSets can be stored on game
|
||||||
|
|
||||||
When a user issues a command, it is matched against the contents of all
|
When a user issues a command, it is matched against the contents of all
|
||||||
cmdsets available at the time, `merged
|
cmdsets available at the time, `merged
|
||||||
together <Commands#Adding%3Ci%3Eand%3C/i%3Emerging%3Ci%3Ecommand%3C/i%3Esets.html>`_.
|
together <Commands#Adding<i>and</i>merging<i>command</i>sets.html>`_.
|
||||||
The currently valid command sets are collected from the following
|
The currently valid command sets are collected from the following
|
||||||
sources, in this order:
|
sources, in this order:
|
||||||
|
|
||||||
|
|
@ -217,24 +214,25 @@ The default ``CmdSet`` shipping with Evennia is automatically added to
|
||||||
all new characters and contains commands such as ``look``, ``drop``,
|
all new characters and contains commands such as ``look``, ``drop``,
|
||||||
``@dig`` etc. You can find it defined in
|
``@dig`` etc. You can find it defined in
|
||||||
``src/commands/default/cmdset_default.py``, but it is also referenced by
|
``src/commands/default/cmdset_default.py``, but it is also referenced by
|
||||||
``game/gamesrc/commands/basecmdset.py``. Players have an
|
importing ``ev.default_cmds`` and accessing its property
|
||||||
Out-of-character cmdset called ``cmdset_ooc`` that can also be found
|
``DefaultCmdset``. Players have an Out-of-character cmdset called
|
||||||
from the same place. There is finally an "unloggedin" cmdset that is
|
``cmdset_ooc`` that can also be found from the same place. There is
|
||||||
used before the Player has authenticated to the game. The path to these
|
finally an "unloggedin" cmdset that is used before the Player has
|
||||||
three standard command sets are defined in settings, as
|
authenticated to the game. The path to these three standard command sets
|
||||||
``CMDSET_UNLOGGEDIN``, ``CMDSET_DEFAULT`` and ``CMDSET_OOC``. You can
|
are defined in settings, as ``CMDSET_UNLOGGEDIN``, ``CMDSET_DEFAULT``
|
||||||
create any number of command sets besides those to fit your needs.
|
and ``CMDSET_OOC``. You can create any number of command sets besides
|
||||||
|
those to fit your needs.
|
||||||
|
|
||||||
A CmdSet is, as most things in Evennia, defined as a Python class
|
A CmdSet is, as most things in Evennia, defined as a Python class
|
||||||
inheriting from the correct parent (``src.commands.cmdset.CmdSet``). The
|
inheriting from the correct parent (``ev.CmdSet`` or
|
||||||
CmdSet class only needs to define one method, called
|
``src.commands.cmdset.CmdSet``). The CmdSet class only needs to define
|
||||||
``at_cmdset_creation()``. All other class parameters are optional, but
|
one method, called ``at_cmdset_creation()``. All other class parameters
|
||||||
are used for more advanced set manipulation and coding (see the `merge
|
are optional, but are used for more advanced set manipulation and coding
|
||||||
rules <Commands#Merge_rules.html>`_ section).
|
(see the `merge rules <Commands#Merge_rules.html>`_ section).
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
from src.commands.cmdset import CmdSet from game.gamesrc.commands import mycommandsclass MyCmdSet(CmdSet): def at_cmdset_creation(self): """ The only thing this method should need to do is to add commands to the set. """ self.add(mycommands.MyCommand1()) self.add(mycommands.MyCommand2()) self.add(mycommands.MyCommand3())
|
from ev import CmdSet from game.gamesrc.commands import mycommands class MyCmdSet(CmdSet): def at_cmdset_creation(self): """ The only thing this method should need to do is to add commands to the set. """ self.add(mycommands.MyCommand1()) self.add(mycommands.MyCommand2()) self.add(mycommands.MyCommand3())
|
||||||
|
|
||||||
The !CmdSet's ``add()`` method can also take another CmdSet as input. In
|
The !CmdSet's ``add()`` method can also take another CmdSet as input. In
|
||||||
this case all the commands from that CmdSet will be appended to this one
|
this case all the commands from that CmdSet will be appended to this one
|
||||||
|
|
@ -271,7 +269,7 @@ server, or you run
|
||||||
@py self.cmdset.delete('game.gamesrc.commands.mycmdset.MyCmdSet')
|
@py self.cmdset.delete('game.gamesrc.commands.mycmdset.MyCmdSet')
|
||||||
|
|
||||||
For more permanent addition, read the `step-by-step
|
For more permanent addition, read the `step-by-step
|
||||||
guide <Commands#Adding%3Ci%3Ea%3C/i%3Enew%3Ci%3Ecommand%3C/i%3E-%3Ci%3Ea%3C/i%3Estep%3Ci%3Eby%3C/i%3Estep_guide.html>`_
|
guide <Commands#Adding<i>a</i>new<i>command</i>-<i>a</i>step<i>by</i>step_guide.html>`_
|
||||||
below. Generally you can customize which command sets are added to your
|
below. Generally you can customize which command sets are added to your
|
||||||
objects by using ``self.cmdset.add()`` or ``self.cmdset.add_default()``.
|
objects by using ``self.cmdset.add()`` or ``self.cmdset.add_default()``.
|
||||||
|
|
||||||
|
|
@ -283,36 +281,36 @@ assume you have just downloaded Evennia and wants to try to add a new
|
||||||
command to use. This is the way to do it.
|
command to use. This is the way to do it.
|
||||||
|
|
||||||
#. In ``game/gamesrc/commands``, create a new module. Name it, say,
|
#. In ``game/gamesrc/commands``, create a new module. Name it, say,
|
||||||
``mycommand.py``.
|
``mycommand.py``. Copy from the templates in ``examples/`` if you
|
||||||
#. Import ``game.gamesrc.commands.basecommands.MuxCommand`` (this is a
|
like.
|
||||||
convenient shortcut so you don't have to import from src/ directly).
|
#. Import ``ev.default_cmds`` and access ``MuxCommand`` from that (this
|
||||||
The ``MuxCommand`` class handles command line parsing for you, giving
|
is a convenient shortcut so you don't have to import from src/
|
||||||
you stuff like /switches, the syntax using '=' etc). In other words,
|
directly). The ``MuxCommand`` class handles command line parsing for
|
||||||
you don't have to implement ``parse()`` on your own.
|
you, giving you stuff like /switches, the syntax using '=' etc). In
|
||||||
|
other words, you don't have to implement ``parse()`` on your own.
|
||||||
#. Create a new class in ``mycommand`` that inherits from
|
#. Create a new class in ``mycommand`` that inherits from
|
||||||
``MuxCommand``.
|
``MuxCommand``.
|
||||||
#. Set the class variable ``key`` to the name to call your command with,
|
#. Set the class variable ``key`` to the name to call your command with,
|
||||||
say ``mycommand``.
|
say ``mycommand``.
|
||||||
#. Set the ``locks`` property on the command to a suitable
|
#. Set the ``locks`` property on the command to a suitable
|
||||||
`lockstring <Locks#Defining%3Ci%3Elocks.html>`_. If you are unsure,
|
`lockstring <Locks#Defining<i>locks.html>`_. If you are unsure, use
|
||||||
use "cmd:all()".
|
"cmd:all()".
|
||||||
#. Define a class method ``func()`` that does stuff. See below.
|
#. Define a class method ``func()`` that does stuff. See below.
|
||||||
#. Give your class a useful *doc*\_ string, this acts as the help entry
|
#. Give your class a useful *doc*\ \_ string, this acts as the help
|
||||||
for the command.
|
entry for the command.
|
||||||
|
|
||||||
Your command definition is now ready. Here's an example of how it could
|
Your command definition is now ready. Here's an example of how it could
|
||||||
look:
|
look:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
from game.gamesrc.commands.basecommand import MuxCommandclass MyCommand(MuxCommand): """ Simple command example Usage: mycommand <text> This command simply echoes text back to the caller. (this string is also the help text for the command) """ key = "mycommand" locks = "cmd:all()" def func(self): "This actually does things" if not self.args: self.caller.msg("You didn't enter anything!") else: self.caller.msg("You gave the string: '%s'" % self.args)
|
from ev import default_cmdsclass MyCommand(default_cmds.MuxCommand): """ Simple command example Usage: mycommand <text> This command simply echoes text back to the caller. (this string is also the help text for the command) """ key = "mycommand" locks = "cmd:all()" def func(self): "This actually does things" if not self.args: self.caller.msg("You didn't enter anything!") else: self.caller.msg("You gave the string: '%s'" % self.args)
|
||||||
|
|
||||||
Next we want to make this command available to us. There are many ways
|
Next we want to make this command available to us. There are many ways
|
||||||
to do this, but all of them involves putting this command in a *Command
|
to do this, but all of them involves putting this command in a *Command
|
||||||
Set*. First, let's try the more involved way.
|
Set*. First, let's try the more involved way.
|
||||||
|
|
||||||
#. Create a class that inherits from
|
#. Create a class that inherits from ``ev.CmdSet``.
|
||||||
``game.gamesrc.commands.basecmdset.CmdSet``.
|
|
||||||
#. (Optionally) set a key to name your command set.
|
#. (Optionally) set a key to name your command set.
|
||||||
#. Add a method ``at_cmdset_creation()`` and use the ``self.add()``
|
#. Add a method ``at_cmdset_creation()`` and use the ``self.add()``
|
||||||
method to add your command to the command set.
|
method to add your command to the command set.
|
||||||
|
|
@ -321,7 +319,7 @@ This is what we have now:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
from game.gamesrc.commands.basecmdset import CmdSet
|
from ev import CmdSet
|
||||||
from game.gamesrc.commands import mycommandclass MyCmdSet(CmdSet): key = "MyCmdSet" def at_cmdset_creation(self): self.add(mycommand.MyCommand())
|
from game.gamesrc.commands import mycommandclass MyCmdSet(CmdSet): key = "MyCmdSet" def at_cmdset_creation(self): self.add(mycommand.MyCommand())
|
||||||
|
|
||||||
This new command set could of course contain any number of commands. We
|
This new command set could of course contain any number of commands. We
|
||||||
|
|
@ -379,14 +377,16 @@ will be loaded every server start along with all the other default
|
||||||
commands.
|
commands.
|
||||||
|
|
||||||
The default command set is found in
|
The default command set is found in
|
||||||
``src/commands/default/cmdset_default.py`` but there is already a
|
``src/commands/default/cmdset_default.py`` but the template in
|
||||||
shortcut to it in ``gamesrc/commands/basecmdset.py`` called
|
``gamesrc/commands/examples/`` already shows how to extend it. Copy that
|
||||||
``DefaultCmdSet``. Add your command to the end of the ``DefaultSet``
|
file to ``game/gamesrc/`` and edit ``settings.CMDSET_DEFAULT`` to point
|
||||||
class and you will in fact append it to the existing command set.
|
to this class instead. Next you add your new commands to the end of the
|
||||||
|
Default Cmdset in that file and you will in fact append it to the
|
||||||
|
existing command set.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
# file gamesrc/commands/basecmdset.py ... from game.gamesrc.commands import mycommandclass DefaultSet(BaseDefaultSet): key = DefaultMUX def at_cmdset_creation(self): # this first adds all default commands super(DefaultSet, self).at_cmdset_creation() # all commands added after this point will extend or # overwrite the default commands. self.add(mycommand.MyCommand())
|
# file gamesrc/commands/examples/cmdset.py ... from game.gamesrc.commands import mycommandclass DefaultSet(BaseDefaultSet): key = DefaultMUX def at_cmdset_creation(self): # this first adds all default commands super(DefaultSet, self).at_cmdset_creation() # all commands added after this point will extend or # overwrite the default commands. self.add(mycommand.MyCommand())
|
||||||
|
|
||||||
Again, you need to run the ``@reload`` command to make these changes
|
Again, you need to run the ``@reload`` command to make these changes
|
||||||
available.
|
available.
|
||||||
|
|
@ -401,7 +401,7 @@ make sure to set your new command's ``key`` variable to ``look`` as
|
||||||
well.
|
well.
|
||||||
|
|
||||||
If you want to expand/build on the original command, just copy&paste its
|
If you want to expand/build on the original command, just copy&paste its
|
||||||
command class from ``src/commands/default``(the ``look`` class is for
|
command class from ``src/commands/default``\ (the ``look`` class is for
|
||||||
example found in ``src/commands/default/general.py``) into
|
example found in ``src/commands/default/general.py``) into
|
||||||
``game/gamesrc/commands`` and edit it there.
|
``game/gamesrc/commands`` and edit it there.
|
||||||
|
|
||||||
|
|
@ -505,23 +505,24 @@ high-prio one as a template.
|
||||||
Besides ``priority`` and ``mergetype``, a command set also takes a few
|
Besides ``priority`` and ``mergetype``, a command set also takes a few
|
||||||
other variables to control how they merge:
|
other variables to control how they merge:
|
||||||
|
|
||||||
- *allow*duplicates*(bool) - determines what happens when two sets of
|
- *allow*\ duplicates\ *(bool) - determines what happens when two sets
|
||||||
equal priority merge. Default is that the new set in the merger (i.e.
|
of equal priority merge. Default is that the new set in the merger
|
||||||
**A** above) automatically takes precedence. But if*allow*duplicates*
|
(i.e. **A** above) automatically takes precedence. But
|
||||||
is true, the result will be a merger with more than one of each name
|
if*\ allow\ *duplicates* is true, the result will be a merger with
|
||||||
match. This will usually lead to the player receiving a
|
more than one of each name match. This will usually lead to the
|
||||||
multiple-match error higher up the road, but can be good for things
|
player receiving a multiple-match error higher up the road, but can
|
||||||
like cmdsets on non-player objects in a room, to allow the system to
|
be good for things like cmdsets on non-player objects in a room, to
|
||||||
warn that more than one 'ball' in the room has the same 'kick'
|
allow the system to warn that more than one 'ball' in the room has
|
||||||
command defined on it, so it may offer a chance to select which ball
|
the same 'kick' command defined on it, so it may offer a chance to
|
||||||
to kick ... Allowing duplicates only makes sense for *Union* and
|
select which ball to kick ... Allowing duplicates only makes sense
|
||||||
*Intersect*, the setting is ignored for the other mergetypes.
|
for *Union* and *Intersect*, the setting is ignored for the other
|
||||||
- *key*mergetype*(dict) - allows the cmdset to define a unique
|
mergetypes.
|
||||||
|
- *key*\ mergetype\ *(dict) - allows the cmdset to define a unique
|
||||||
mergetype for particular cmdsets, identified by their cmdset-key.
|
mergetype for particular cmdsets, identified by their cmdset-key.
|
||||||
Format is ``CmdSetkey:mergetype``. Priorities still apply. Example:
|
Format is ``CmdSetkey:mergetype``. Priorities still apply. Example:
|
||||||
``'Myevilcmdset','Replace'`` which would make sure for this set to
|
``'Myevilcmdset','Replace'`` which would make sure for this set to
|
||||||
always use 'Replace' on ``Myevilcmdset`` only, no matter
|
always use 'Replace' on ``Myevilcmdset`` only, no matter
|
||||||
what*mergetype\_ is set to.
|
what*\ mergetype\_ is set to.
|
||||||
|
|
||||||
More advanced cmdset example:
|
More advanced cmdset example:
|
||||||
|
|
||||||
|
|
@ -548,29 +549,30 @@ are defined at the top of ``src/commands/cmdhandler.py``). You can find
|
||||||
``src/commands/default/system_commands.py``. Since these are not (by
|
``src/commands/default/system_commands.py``. Since these are not (by
|
||||||
default) included in any ``CmdSet`` they are not actually used, they are
|
default) included in any ``CmdSet`` they are not actually used, they are
|
||||||
just there for show. When the special situation occurs, Evennia will
|
just there for show. When the special situation occurs, Evennia will
|
||||||
look through all valid ``CmdSet``s for your custom system command. Only
|
look through all valid ``CmdSet``\ s for your custom system command.
|
||||||
after that will it resort to its own, hard-coded implementation.
|
Only after that will it resort to its own, hard-coded implementation.
|
||||||
|
|
||||||
Here are the exceptional situations that triggers system commands:
|
Here are the exceptional situations that triggers system commands. You
|
||||||
|
can find the command keys they use as properties on ``ev.syscmdkeys``
|
||||||
|
|
||||||
- No input (``cmdhandler.CMD_NOINPUT``) - the player just pressed
|
- No input (``syscmdkeys.CMD_NOINPUT``) - the player just pressed
|
||||||
return without any input. Default is to do nothing, but it can be
|
return without any input. Default is to do nothing, but it can be
|
||||||
useful to do something here for certain implementations such as line
|
useful to do something here for certain implementations such as line
|
||||||
editors that interpret non-commands as text input (an empty line in
|
editors that interpret non-commands as text input (an empty line in
|
||||||
the editing buffer).
|
the editing buffer).
|
||||||
- Command not found (``cmdhandler.CMD_NOMATCH``) - No matching command
|
- Command not found (``syscmdkeys.CMD_NOMATCH``) - No matching command
|
||||||
was found. Default is to display the "Huh?" error message.
|
was found. Default is to display the "Huh?" error message.
|
||||||
- Several matching commands where found (``cmdhandler.CMD_MULTIMATCH``)
|
- Several matching commands where found (``syscmdkeys.CMD_MULTIMATCH``)
|
||||||
- Default is to show a list of matches.
|
- Default is to show a list of matches.
|
||||||
- User is not allowed to execute the command
|
- User is not allowed to execute the command
|
||||||
(``cmdhandler.CMD_NOPERM``) - Default is to display the "Huh?" error
|
(``syscmdkeys.CMD_NOPERM``) - Default is to display the "Huh?" error
|
||||||
message.
|
message.
|
||||||
- Channel (``cmdhandler.CMD_CHANNEL``) - This is a
|
- Channel (``syscmdkeys.CMD_CHANNEL``) - This is a
|
||||||
`Channel <Communications.html>`_ name of a channel you are
|
`Channel <Communications.html>`_ name of a channel you are
|
||||||
subscribing to - Default is to relay the command's argument to that
|
subscribing to - Default is to relay the command's argument to that
|
||||||
channel. Such commands are created by the Comm system on the fly
|
channel. Such commands are created by the Comm system on the fly
|
||||||
depending on your subscriptions.
|
depending on your subscriptions.
|
||||||
- New session connection ('cmdhandler.CMD\_LOGINSTART'). This command
|
- New session connection ('syscmdkeys.CMD\_LOGINSTART'). This command
|
||||||
name should be put in the ``settings.CMDSET_UNLOGGEDIN``. Whenever a
|
name should be put in the ``settings.CMDSET_UNLOGGEDIN``. Whenever a
|
||||||
new connection is established, this command is always called on the
|
new connection is established, this command is always called on the
|
||||||
server (default is to show the login screen).
|
server (default is to show the login screen).
|
||||||
|
|
@ -581,7 +583,7 @@ command must be added to a cmdset as well before it will work.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
from src.commands import cmdhandler from game.gamesrc.commands.basecommand import Commandclass MyNoInputCommand(Command): "Usage: Just press return, I dare you" key = cmdhandler.CMD_NOINPUT def func(self): self.caller.msg("Don't just press return like that, talk to me!")
|
from ev import syscmdkeys, Commandclass MyNoInputCommand(Command): "Usage: Just press return, I dare you" key = syscmdkeys.CMD_NOINPUT def func(self): self.caller.msg("Don't just press return like that, talk to me!")
|
||||||
|
|
||||||
Exits
|
Exits
|
||||||
-----
|
-----
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ send a non-persistent message, also if you send it a ``Msg`` object.
|
||||||
|
|
||||||
As a more advanced note, sending text to channels is a "special
|
As a more advanced note, sending text to channels is a "special
|
||||||
exception" as far as commands are concerned, and you may completely
|
exception" as far as commands are concerned, and you may completely
|
||||||
customize how this works by defining a *system*command\_ with your own
|
customize how this works by defining a *system*\ command\_ with your own
|
||||||
code. See `Commands <Commands.html>`_ for more details.
|
code. See `Commands <Commands.html>`_ for more details.
|
||||||
|
|
||||||
Properties defined on ``Channel``
|
Properties defined on ``Channel``
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ To help with Evennia development it's recommended to do so using a clone
|
||||||
repository as described above. But for small, well isolated fixes you
|
repository as described above. But for small, well isolated fixes you
|
||||||
are also welcome to submit your suggested Evennia fixes/addendums as
|
are also welcome to submit your suggested Evennia fixes/addendums as
|
||||||
*patches*. You can use normal
|
*patches*. You can use normal
|
||||||
`patches <https://secure.wikimedia.org/wikipedia/en/wiki/Patch_(computing).html>`_,
|
`patches <https://secure.wikimedia.org/wikipedia/en/wiki/Patch_%28computing%29.html>`_,
|
||||||
but it might be easier to use mercurial's own patch mechanism. Make sure
|
but it might be easier to use mercurial's own patch mechanism. Make sure
|
||||||
you have committed your latest fixes first, then
|
you have committed your latest fixes first, then
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -22,6 +22,7 @@ more links to Evennia resources from the `Links <Links.html>`_ page.
|
||||||
General Evennia development information
|
General Evennia development information
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
|
- `Introduction to coding with Evennia <CodingIntroduction.html>`_
|
||||||
- `Evennia Licensing FAQ <Licensing.html>`_
|
- `Evennia Licensing FAQ <Licensing.html>`_
|
||||||
- `Contributing to Evennia <Contributing.html>`_
|
- `Contributing to Evennia <Contributing.html>`_
|
||||||
- `Evennia Code Style
|
- `Evennia Code Style
|
||||||
|
|
@ -34,6 +35,8 @@ General Evennia development information
|
||||||
Evennia Component Documentation
|
Evennia Component Documentation
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
|
- `ev - the flat API <evAPI.html>`_
|
||||||
|
|
||||||
`Directory Overview <DirectoryOverview.html>`_
|
`Directory Overview <DirectoryOverview.html>`_
|
||||||
|
|
||||||
`Portal and Server <PortalAndServer.html>`_
|
`Portal and Server <PortalAndServer.html>`_
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ Evennia directory overview
|
||||||
::
|
::
|
||||||
|
|
||||||
evennia/
|
evennia/
|
||||||
|
ev.py
|
||||||
contrib/
|
contrib/
|
||||||
docs/
|
docs/
|
||||||
game/
|
game/
|
||||||
|
|
@ -25,6 +26,12 @@ directories. When you have run Evennia at least once you will find that
|
||||||
there will also be ``.pyc`` files appearing, these are pre-compiled
|
there will also be ``.pyc`` files appearing, these are pre-compiled
|
||||||
binary versions of the ``.py`` files to speed up execution.
|
binary versions of the ``.py`` files to speed up execution.
|
||||||
|
|
||||||
|
The file ``ev.py`` is important to remember. This is the home of
|
||||||
|
Evennia's flat API, essentially a set of shortcuts to various important
|
||||||
|
places in ``src/``. By importing ``ev`` from your code in ``game/`` you
|
||||||
|
have access to most important Evennia systems without *having* to know
|
||||||
|
where everything is located, as described in the following sections.
|
||||||
|
|
||||||
The ``docs/`` directory
|
The ``docs/`` directory
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
|
@ -94,29 +101,25 @@ Evennia.
|
||||||
^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
``gamesrc/commands/`` contains modules for defining
|
``gamesrc/commands/`` contains modules for defining
|
||||||
`Commands <Commands.html>`_. It contains a file ``basecommand.py`` which
|
`Commands <Commands.html>`_. In ``commands/examples`` you will find
|
||||||
defines the root object from which all your own command classes will
|
templates for starting to define your own commands and cmdsets. Copy
|
||||||
inherit.The file ``basecmdset.py`` is where you'll inherit your `Command
|
these out into the parent ``command`` folder and work from there.
|
||||||
Set <Commands.html>`_ classes from. ``commands/examples`` contains the
|
|
||||||
main interactive commands and cmdsets of the *Red Button*.
|
|
||||||
|
|
||||||
``gamesrc/scripts/``
|
``gamesrc/scripts/``
|
||||||
^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
``gamesrc/scripts/`` holds everything related to
|
``gamesrc/scripts/`` holds everything related to
|
||||||
`Scripts <Scripts.html>`_. It has a file ``basescript.py`` that hold the
|
`Scripts <Scripts.html>`_. ``scripts/examples`` holds templates you can
|
||||||
parent for all scripts and which you should inherit from.
|
make copies of and build from to define your own scripts.
|
||||||
``scripts/examples`` holds the *Red Button*'s scripts.
|
|
||||||
|
|
||||||
``gamesrc/objects/``
|
``gamesrc/objects/``
|
||||||
^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
``gamesrc/objects/`` should contain the definitions for all your
|
``gamesrc/objects/`` should contain the definitions for all your
|
||||||
`Objects <Objects.html>`_. ``baseobjects.py`` contains the parent
|
`Objects <Objects.html>`_. ``objects/examples`` contain templates for
|
||||||
classes for the normal *Object* as well as its three basic subclasses
|
*Object* as well as its three basic subclasses *Character*, *Room* and
|
||||||
*Character*, *Room* and *Exit*. Your own objects will inherit from the
|
*Exit*. Make copies of these templates to have somthing to start from
|
||||||
classes in this file. ``objects/examples`` define the example *Red
|
when defining your own in-game entities.
|
||||||
Button* object itself.
|
|
||||||
|
|
||||||
``gamesrc/world/``
|
``gamesrc/world/``
|
||||||
^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
@ -143,21 +146,23 @@ syntax.
|
||||||
^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
``gamesrc/conf/`` holds optional extension modules for the Evennia
|
``gamesrc/conf/`` holds optional extension modules for the Evennia
|
||||||
engine. Certain functionality in the server is meant to be extended, and
|
engine. It is empty by default, but in ``conf/examples/`` are templates
|
||||||
in order to allow you to do this without modifying the server itself, it
|
for the various config files that the server undertands. Each template
|
||||||
imports files from this directory. Modifying these are optional and you
|
file contains instructions for how you should use them; copy out the
|
||||||
can usually change a variable in ``game/settings.py`` to change exactly
|
ones you want into the ``conf/`` directory and edit them there.
|
||||||
which module Evennia actually uses. There are dummy example files in
|
|
||||||
here, read their headers for usage instructions.
|
|
||||||
|
|
||||||
The ``src/`` directory
|
The ``src/`` directory
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
``src/`` contains the main running code of the Evennia server. You will
|
``src/`` contains the main running code of the Evennia server. You can
|
||||||
often need to import modules from here to access the functionality of
|
import files directly from here, but normally you will probably find it
|
||||||
Evennia. You should generally not modify anything in this folder
|
easier to use the shortcuts in the top-level ``ev`` module.
|
||||||
directly since it might be changed when we release updates. If you find
|
|
||||||
bugs or features missing, file a bug report or send us a message.
|
You should never modify anything in this folder directly since it might
|
||||||
|
be changed when we release updates. If you want to use some code as a
|
||||||
|
base for your own work (such as new commands), copy the relevant code
|
||||||
|
out into your own modules in ``game/gamesrc`` instead. If you find bugs
|
||||||
|
or features missing, file a bug report or send us a message.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
|
@ -196,7 +201,7 @@ Evennia. It defines basic command function, parsing and command-set
|
||||||
handling.
|
handling.
|
||||||
|
|
||||||
``commands/default/`` holds a multitude of modules that together form
|
``commands/default/`` holds a multitude of modules that together form
|
||||||
Evennia's default ('`MUX-like <UsingMUXAsAStandard.html>`_') command
|
Evennia's default ('`MUX-like <UsingMUXAsAStandard.html>`_\ ') command
|
||||||
set. The files ``game/gamesrc/basecommand.py`` and
|
set. The files ``game/gamesrc/basecommand.py`` and
|
||||||
``game/gamesrc/basecmdset.py`` both link to their respective parents
|
``game/gamesrc/basecmdset.py`` both link to their respective parents
|
||||||
here. If you want to edit a default command, copy&paste the respective
|
here. If you want to edit a default command, copy&paste the respective
|
||||||
|
|
|
||||||
|
|
@ -52,9 +52,9 @@ function on the database model or if it in fact sat on the script parent
|
||||||
|
|
||||||
By contrast, a typeclass is a normal python class that inherits from the
|
By contrast, a typeclass is a normal python class that inherits from the
|
||||||
*!TypeClass* parent. There are no other required functions to define.
|
*!TypeClass* parent. There are no other required functions to define.
|
||||||
This class uses **getattribute** and **setattr** transparently behind
|
This class uses **\ getattribute\ ** and **\ setattr\ ** transparently
|
||||||
the scenes to store data onto the persistent django object. Also the
|
behind the scenes to store data onto the persistent django object. Also
|
||||||
django model is aware of the typeclass in the reverse direction. The
|
the django model is aware of the typeclass in the reverse direction. The
|
||||||
admin don't really have to worry about this connection, they can usually
|
admin don't really have to worry about this connection, they can usually
|
||||||
consider the two objects (typeclass and django model) to be one.
|
consider the two objects (typeclass and django model) to be one.
|
||||||
|
|
||||||
|
|
@ -74,14 +74,15 @@ Command functions + !StateCommands-> Command classes + CmdSets
|
||||||
--------------------------------------------------------------
|
--------------------------------------------------------------
|
||||||
|
|
||||||
In trunk, there was one default group of commands in a list
|
In trunk, there was one default group of commands in a list
|
||||||
GLOBAL*CMD*TABLE. Every player in game used this. There was a second
|
GLOBAL\ *CMD*\ TABLE. Every player in game used this. There was a second
|
||||||
dictionary GLOBAL*STATE*TABLE that held commands valid only for certain
|
dictionary GLOBAL\ *STATE*\ TABLE that held commands valid only for
|
||||||
*states* the player might end up in - like entering a dark room, a text
|
certain *states* the player might end up in - like entering a dark room,
|
||||||
editor, or whatever. The problem with this state system, was that it was
|
a text editor, or whatever. The problem with this state system, was that
|
||||||
limited in its use - every player could ever only be in one state at a
|
it was limited in its use - every player could ever only be in one state
|
||||||
time for example, never two at the same time. The way the system was set
|
at a time for example, never two at the same time. The way the system
|
||||||
up also explicitly made states something unique to players - an object
|
was set up also explicitly made states something unique to players - an
|
||||||
could not offer different commands dependent on its state, for example.
|
object could not offer different commands dependent on its state, for
|
||||||
|
example.
|
||||||
|
|
||||||
In devel, *every* command definition is grouped in what's called a
|
In devel, *every* command definition is grouped in what's called a
|
||||||
*!CmdSet* (this is, like most things in Devel, defined as a class). A
|
*!CmdSet* (this is, like most things in Devel, defined as a class). A
|
||||||
|
|
@ -319,7 +320,7 @@ where it might be unclear if you receive a session or a player object
|
||||||
(especially during login/logout), you can now use simply use ``msg()``
|
(especially during login/logout), you can now use simply use ``msg()``
|
||||||
without having to check (however, you *can* still use ``emit_to`` for
|
without having to check (however, you *can* still use ``emit_to`` for
|
||||||
legacy code, it's an alias to msg() now). Same is true with
|
legacy code, it's an alias to msg() now). Same is true with
|
||||||
emit*to*contents() -> msg*to*contents().
|
emit\ *to*\ contents() -> msg\ *to*\ contents().
|
||||||
|
|
||||||
``source_object`` in default commands are now consistently named
|
``source_object`` in default commands are now consistently named
|
||||||
*caller* instead.
|
*caller* instead.
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,16 @@ interactive fiction, and online chat. Players can read or view
|
||||||
descriptions of rooms, objects, other players, non-player characters,
|
descriptions of rooms, objects, other players, non-player characters,
|
||||||
and actions performed in the virtual world. Players typically interact
|
and actions performed in the virtual world. Players typically interact
|
||||||
with each other and the world by typing commands that resemble a natural
|
with each other and the world by typing commands that resemble a natural
|
||||||
language.*" - `Wikipedia <http://en.wikipedia.org/wiki/MUD>`_
|
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
|
If you are reading this, it's quite likely you are dreaming of creating
|
||||||
and running a text-based massively-multiplayer game
|
and running a text-based massively-multiplayer game
|
||||||
(`MUD/MUX/MU <http://en.wikipedia.org/wiki/Mu%3Cstrong%3E>`_ etc) of
|
(`MUD/MUX/MU <http://en.wikipedia.org/wiki/Mu<strong>>`_ etc) of your
|
||||||
your very own. You might just be starting to think about it, or you
|
very own. You might just be starting to think about it, or you might
|
||||||
might have lugged around that *perfect* game in your mind for years ...
|
have lugged around that *perfect* game in your mind for years ... you
|
||||||
you know *just* how good it would be, if you could only make it come to
|
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.
|
||||||
|
|
||||||
|
|
@ -132,24 +132,23 @@ instructions <GettingStarted.html>`_) and have gotten as far as to start
|
||||||
the server and connect to it with the client of your choice, here's what
|
the server and connect to it with the client of your choice, here's what
|
||||||
you need to know depending on your skills and needs.
|
you need to know depending on your skills and needs.
|
||||||
|
|
||||||
I don't know (or don't want to do) any programming - I just want to run
|
I don't know (or don't want to do) any programming - I just want to run a game!
|
||||||
a game!
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
Evennia comes with a default set of commands for the Python newbies and
|
Evennia comes with a default set of commands for the Python newbies and
|
||||||
for those who need to get a game running *now*. Stock Evennia is enough
|
for those who need to get a game running *now*. Stock Evennia is enough
|
||||||
for running a simple 'Talker'-type game - you can build and describe
|
for running a simple 'Talker'-type game - you can build and describe
|
||||||
rooms and basic objects, have chat channels, do emotes and other things
|
rooms and basic objects, have chat channels, do emotes and other things
|
||||||
suitable for a social or free-form MU``*``. Combat, mobs and other game
|
suitable for a social or free-form MU\ ``*``. Combat, mobs and other
|
||||||
elements are not included, so you'll have a very basic game indeed if
|
game elements are not included, so you'll have a very basic game indeed
|
||||||
you are not willing to do at least *some* coding.
|
if you are not willing to do at least *some* coding.
|
||||||
|
|
||||||
I know basic Python, or am willing to learn
|
I know basic Python, or am willing to learn
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
|
|
||||||
Evennia's source code is extensively documented and `viewable
|
Evennia's source code is extensively documented and `viewable
|
||||||
online <http://code.google.com/p/evennia/source/browse/trunk>`_. We also
|
online <http://code.google.com/p/evennia/source/browse/>`_. We also have
|
||||||
have a comprehensive `online
|
a comprehensive `online
|
||||||
manual <http://code.google.com/p/evennia/wiki/Index>`_ with lots of
|
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
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@ The ``@py`` command
|
||||||
|
|
||||||
The ``@py`` command supplied with the default command set of Evennia
|
The ``@py`` command supplied with the default command set of Evennia
|
||||||
allows you to execute Python commands directly from inside the game. An
|
allows you to execute Python commands directly from inside the game. An
|
||||||
alias to ``@py`` is simply "``!``". *Access to the ``@py`` command
|
alias to ``@py`` is simply "``!``\ ". *Access to the ``@py`` command
|
||||||
should be severely restricted only to game admins.* Being able to
|
should be severely restricted*. This is no joke - being able to execute
|
||||||
execute arbitrary Python code on the server is not something you should
|
arbitrary Python code on the server is not something you should entrust
|
||||||
entrust to just anybody.
|
to just anybody.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
|
@ -16,27 +16,24 @@ Available variables
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
A few local variables are made available when running ``@py``. These
|
A few local variables are made available when running ``@py``. These
|
||||||
offer entry into the running system and allows for quick exploration of
|
offer entry into the running system.
|
||||||
the standard objects.
|
|
||||||
|
|
||||||
- **self** / **me** - the calling object (i.e. you)
|
- **self** / **me** - the calling object (i.e. you)
|
||||||
- **here** - the current caller's location
|
- **here** - the current caller's location
|
||||||
- **obj** - a dummy `Object <Objects.html>`_ instance
|
- **obj** - a dummy `Object <Objects.html>`_ instance
|
||||||
- **script** - a dummy `Script <Scripts.html>`_ instance
|
- **ev** - Evennia's flat API - through this you can access all of
|
||||||
- **config** - a dummy ConfigValue instance
|
Evennia.
|
||||||
- **ObjectDB** - direct reference to the ObjectDB database class
|
|
||||||
- **ScriptDB** - direct reference to the ScriptDB database class
|
|
||||||
- **!ConfigValue** - direct reference to the ConfigValue database class
|
|
||||||
|
|
||||||
Returning output
|
Returning output
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
This is an example where we import and test one of Evennia's utilities
|
This is an example where we import and test one of Evennia's utilities
|
||||||
found in ``src/utils/utils.py``:
|
found in ``src/utils/utils.py``, but also accessible through
|
||||||
|
``ev.utils``:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
@py from src.utils import utils; utils.time_format(33333) <<< Done.
|
@py from ev import utils; utils.time_format(33333) <<< Done.
|
||||||
|
|
||||||
Note that we didn't get any return value, all we where told is that the
|
Note that we didn't get any return value, all we where told is that the
|
||||||
code finished executing without error. This is often the case in more
|
code finished executing without error. This is often the case in more
|
||||||
|
|
@ -46,7 +43,7 @@ system to echo it to us explicitly with ``self.msg()``.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
@py from src.utils import utils; self.msg(utils.time_format(33333)) 09:15 <<< Done.
|
@py from ev import utils; self.msg(utils.time_format(33333)) 09:15 <<< Done.
|
||||||
|
|
||||||
If you were to use Python's standard ``print``, you will see the result
|
If you were to use Python's standard ``print``, you will see the result
|
||||||
in your current ``stdout`` (your terminal by default), *if* you are
|
in your current ``stdout`` (your terminal by default), *if* you are
|
||||||
|
|
@ -68,31 +65,28 @@ Locating an object is best done using ``self.search()``:
|
||||||
``self.search()`` is by far the most used case, but you can also search
|
``self.search()`` is by far the most used case, but you can also search
|
||||||
other database tables for other Evennia entities like scripts or
|
other database tables for other Evennia entities like scripts or
|
||||||
configuration entities. To do this you can use the generic search
|
configuration entities. To do this you can use the generic search
|
||||||
entries found in ``src.utils.search``.
|
entries found in ``ev.search_*``.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
@py from src.utils import search; self.msg(search.scripts("sys_game_time")) <<< [<src.utils.gametime.GameTime object at 0x852be2c>]
|
@py ev.search_script("sys_game_time") <<< [<src.utils.gametime.GameTime object at 0x852be2c>]
|
||||||
|
|
||||||
You can also use the database model managers directly (accessible
|
(Note that since this becomes a simple statement, we don't have to wrap
|
||||||
through the ``objects`` properties of database models). This is a bit
|
it in ``self.msg()`` to get the output). You can also use the database
|
||||||
more flexible since it gives you access to the full range of database
|
model managers directly (accessible through the ``objects`` properties
|
||||||
search methods defined in each manager.
|
of database models or as ``ev.db_*``). This is a bit more flexible since
|
||||||
|
it gives you access to the full range of database search methods defined
|
||||||
|
in each manager.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
@py ScriptDB.objects.script_search("sys_game_time") <<< [<src.utils.gametime.GameTime object at 0x852be2c>]
|
@py ev.db_scripts.script_search("sys_game_time") <<< [<src.utils.gametime.GameTime object at 0x852be2c>]
|
||||||
|
|
||||||
(Note that since this second example becomes a simple statement, we
|
The managers are useful for all sorts of database studies.
|
||||||
don't have to wrap it in ``self.msg()`` to get the output). If you want
|
|
||||||
to see what is available, the managers are found in the ``manager.py``
|
|
||||||
files throughout the ``src`` directory (e.g.
|
|
||||||
``src/objects/manager.py``). Through the manager you can also view the
|
|
||||||
contents of the database using normal Django query operations:
|
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
@py ConfigValue.objects.all() <<< [<ConfigValue: default_home]>, <ConfigValue:site_name>, ...]
|
@py ev.db_configvalues.all() <<< [<ConfigValue: default_home]>, <ConfigValue:site_name>, ...]
|
||||||
|
|
||||||
In doing so however, keep in mind the difference between `Typeclasses
|
In doing so however, keep in mind the difference between `Typeclasses
|
||||||
and Database Objects <Typeclasses.html>`_: Using the search commands in
|
and Database Objects <Typeclasses.html>`_: Using the search commands in
|
||||||
|
|
@ -104,7 +98,7 @@ most situations.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
# this uses Evennia's manager method get_id(). # It returns a Character typeclass instance @py ObjectDB.objects.get_id(1).__class__ <<< Character# this uses the standard Django get() query. # It returns a django database model instance. @py ObjectDB.objects.get(id=1).__class__ <<< <class 'src.objects.models.ObjectDB'>
|
# this uses Evennia's manager method get_id(). # It returns a Character typeclass instance @py ev.db_objects.get_id(1).__class__ <<< Character# this uses the standard Django get() query. # It returns a django database model instance. @py ev.db_objects.get(id=1).__class__ <<< <class 'src.objects.models.ObjectDB'>
|
||||||
|
|
||||||
Running a Python Parser outside the game
|
Running a Python Parser outside the game
|
||||||
========================================
|
========================================
|
||||||
|
|
@ -122,12 +116,13 @@ Go to the ``game`` directory and get into a new terminal.
|
||||||
Your default Python intrepeter will start up, configured to be able to
|
Your default Python intrepeter will start up, configured to be able to
|
||||||
work with and import all modules of your Evennia installation. From here
|
work with and import all modules of your Evennia installation. From here
|
||||||
you can explore the database and test-run individual modules as desired.
|
you can explore the database and test-run individual modules as desired.
|
||||||
Not only does a fully featured Python interpreter like
|
Most of the time you can get by with just the ``ev`` module though. A
|
||||||
|
fully featured Python interpreter like
|
||||||
`iPython <http://ipython.scipy.org/moin/>`_ allow you to work over
|
`iPython <http://ipython.scipy.org/moin/>`_ allow you to work over
|
||||||
several lines, it also has lots of other editing features, usch as
|
several lines, but also has lots of other editing features, usch as
|
||||||
tab-completion and ``__doc__``-string reading.
|
tab-completion and ``__doc__``-string reading.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
$ python manage.py shellIPython 0.10 -- An enhanced Interactive Python ...In [1]: from src.objects.models import ObjectDB In [2]: ObjectDB.objects.all() Out[3]: [<ObjectDB: Harry>, <ObjectDB: Limbo>, ...]
|
$ python manage.py shellIPython 0.10 -- An enhanced Interactive Python ...In [1]: import ev In [2]: ev.db_objects.all() Out[3]: [<ObjectDB: Harry>, <ObjectDB: Limbo>, ...]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ Installing pre-requisites
|
||||||
**All platforms** can set up an *virtual Python environment* and install
|
**All platforms** can set up an *virtual Python environment* and install
|
||||||
Evennia to that. All you need pre-installed is Python. Setup is
|
Evennia to that. All you need pre-installed is Python. Setup is
|
||||||
described in detail
|
described in detail
|
||||||
`here <GettingStarted#Optional:%3Ci%3EA%3C/i%3Eseparate%3Ci%3Einstallation%3C/i%3Eenvironment%3Ci%3Ewith%3C/i%3Evirtualenv.html>`_.
|
`here <GettingStarted#Optional:<i>A</i>separate<i>installation</i>environment<i>with</i>virtualenv.html>`_.
|
||||||
Windows users will probably want to go the ActivePython way instead
|
Windows users will probably want to go the ActivePython way instead
|
||||||
though (see below), there are issues with installing certain extensions
|
though (see below), there are issues with installing certain extensions
|
||||||
in Windows.
|
in Windows.
|
||||||
|
|
@ -113,7 +113,7 @@ Debian-derived systems (such as Ubuntu) you can do something like this
|
||||||
Few distros actually keep the latest updated security updates (notably
|
Few distros actually keep the latest updated security updates (notably
|
||||||
django and twisted) in their repos though. So it might be worth to use
|
django and twisted) in their repos though. So it might be worth to use
|
||||||
Python's
|
Python's
|
||||||
`easyinstall <http://packages.python.org/distribute/easy%3Ci%3Einstall.html>`_
|
`easyinstall <http://packages.python.org/distribute/easy<i>install.html>`_
|
||||||
or the alternative
|
or the alternative
|
||||||
`pip <http://www.pip-installer.org/en/latest/index.html>`_ to get some
|
`pip <http://www.pip-installer.org/en/latest/index.html>`_ to get some
|
||||||
or all of these instead:
|
or all of these instead:
|
||||||
|
|
@ -126,6 +126,15 @@ or all of these instead:
|
||||||
|
|
||||||
pip install django twisted pil mercurial south
|
pip install django twisted pil mercurial south
|
||||||
|
|
||||||
|
If you already have Python and mercurial, and have downloaded Evennia,
|
||||||
|
the package comes with a ``requirements.txt`` file. This can be used
|
||||||
|
with ``pip`` to install the remaining dependencies (possibly useful for
|
||||||
|
automated build systems):
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
||||||
**Mac** users should be able to get most dependencies through
|
**Mac** users should be able to get most dependencies through
|
||||||
``easy_install`` or ``pip`` like Linux users do. There are however
|
``easy_install`` or ``pip`` like Linux users do. There are however
|
||||||
reports that you might need to get the
|
reports that you might need to get the
|
||||||
|
|
@ -136,9 +145,11 @@ installers or python setups. Some users have reported problems compiling
|
||||||
the ``PIL`` library on Mac, it's however not strictly required to use
|
the ``PIL`` library on Mac, it's however not strictly required to use
|
||||||
Django.
|
Django.
|
||||||
|
|
||||||
**Windows** users may choose to install
|
**Windows** users may want to install
|
||||||
`ActivePython <http://www.activestate.com/activepython/downloads>`_
|
`ActivePython <http://www.activestate.com/activepython/downloads>`_
|
||||||
instead of the usual Python. If ActivePython is installed, you can use
|
instead of the usual Python. Get the 32-bit version (it seems the 64-bit
|
||||||
|
one won't let you download any packages without paying for a "Business"
|
||||||
|
license). If ActivePython is installed, you can use
|
||||||
`pypm <http://docs.activestate.com/activepython/2.6/pypm.html>`_ in the
|
`pypm <http://docs.activestate.com/activepython/2.6/pypm.html>`_ in the
|
||||||
same manner as ``easy_install``/``pip`` above. This *greatly* simplifies
|
same manner as ``easy_install``/``pip`` above. This *greatly* simplifies
|
||||||
getting started on Windows since that platform is by default missing
|
getting started on Windows since that platform is by default missing
|
||||||
|
|
@ -156,7 +167,7 @@ Windows users not using ActivePython or virtual environments will have
|
||||||
to manually download and install the packages in turn (including their
|
to manually download and install the packages in turn (including their
|
||||||
own dependencies in the list above). Most have normal Windows
|
own dependencies in the list above). Most have normal Windows
|
||||||
installers, but in some cases you'll need to know how to use the Windows
|
installers, but in some cases you'll need to know how to use the Windows
|
||||||
command prompt to execute python install scripts (usually it's not
|
command prompt to execute python install scripts (it's usually not
|
||||||
harder than running ``python setup.py install`` from the downloaded
|
harder than running ``python setup.py install`` from the downloaded
|
||||||
package's folder).
|
package's folder).
|
||||||
|
|
||||||
|
|
@ -298,8 +309,10 @@ Optional: A separate installation environment with virtualenv
|
||||||
Apart from installing the packages and versions as above, you can also
|
Apart from installing the packages and versions as above, you can also
|
||||||
set up a very easy self-contained Evennia install using the
|
set up a very easy self-contained Evennia install using the
|
||||||
`virtualenv <http://pypi.python.org/pypi/virtualenv>`_ program. If you
|
`virtualenv <http://pypi.python.org/pypi/virtualenv>`_ program. If you
|
||||||
are unsure how to get it, just grab the ``virtualenv.py`` file from that
|
are unsure how to get it, just grab the
|
||||||
page and run it directly in the terminal with ``python virtualenv.py``.
|
`virtualenv.py <https://raw.github.com/pypa/virtualenv/master/virtualenv.py.html>`_
|
||||||
|
file from that page and run it directly in the terminal with
|
||||||
|
``python virtualenv.py``.
|
||||||
|
|
||||||
Virtualenv sets aside a folder on your harddrive as a stand-alone Python
|
Virtualenv sets aside a folder on your harddrive as a stand-alone Python
|
||||||
environment. It should work both on Linux/Unix and Windows. First,
|
environment. It should work both on Linux/Unix and Windows. First,
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ A help entry consists of four parts:
|
||||||
- The *text* - the help text itself, of any length.
|
- The *text* - the help text itself, of any length.
|
||||||
- locks - a `lock definition <Locks.html>`_. This can be used to limit
|
- locks - a `lock definition <Locks.html>`_. This can be used to limit
|
||||||
access to this help entry, maybe because it's staff-only or otherwise
|
access to this help entry, maybe because it's staff-only or otherwise
|
||||||
meant to be restricted. Help commands check for ``access_type``s
|
meant to be restricted. Help commands check for ``access_type``\ s
|
||||||
``view`` and ``edit``. An example of a lock string would be
|
``view`` and ``edit``. An example of a lock string would be
|
||||||
``view:perm(Builders)``.
|
``view:perm(Builders)``.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ documentation <Index.html>`_, here's what to do:
|
||||||
- If you think the documentation is not clear enough, fill in our quick
|
- If you think the documentation is not clear enough, fill in our quick
|
||||||
little "https://docs.google.com/spreadsheet/viewform?hl
|
little "https://docs.google.com/spreadsheet/viewform?hl
|
||||||
|
|
||||||
en*US&formkey*
|
en\ *US&formkey*
|
||||||
|
|
||||||
dGN0VlJXMWpCT3VHaHpscDEzY1RoZGc6MQ#gid
|
dGN0VlJXMWpCT3VHaHpscDEzY1RoZGc6MQ#gid
|
||||||
======================================
|
======================================
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ IRC
|
||||||
===
|
===
|
||||||
|
|
||||||
`IRC (Internet Relay
|
`IRC (Internet Relay
|
||||||
Chat) <http://en.wikipedia.org/wiki/Internet%3Ci%3ERelay%3C/i%3EChat>`_
|
Chat) <http://en.wikipedia.org/wiki/Internet<i>Relay</i>Chat>`_ is a
|
||||||
is a long standing chat protocol used by many open-source projects for
|
long standing chat protocol used by many open-source projects for
|
||||||
communicating in real time. By connecting one of Evennia's
|
communicating in real time. By connecting one of Evennia's
|
||||||
`Channels <Communications.html>`_ to an IRC channel you can communicate
|
`Channels <Communications.html>`_ to an IRC channel you can communicate
|
||||||
also with people not on an mud themselves. Note that you can use IRC
|
also with people not on an mud themselves. Note that you can use IRC
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,7 @@ directory. You can also read the full license file
|
||||||
You should read the full license text to know what it says exactly, but
|
You should read the full license text to know what it says exactly, but
|
||||||
here are some answers to common questions.
|
here are some answers to common questions.
|
||||||
|
|
||||||
Q: When creating a game using Evennia, what does the licence permit me
|
Q: When creating a game using Evennia, what does the licence permit me to do with it?
|
||||||
to do with it?
|
|
||||||
-------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------
|
||||||
|
|
||||||
**A:** It's your own game world to do with as you please! To summarize,
|
**A:** It's your own game world to do with as you please! To summarize,
|
||||||
|
|
@ -38,8 +37,7 @@ is referred to as "The Package, Standard version" in the license.
|
||||||
of course, if you plan to add new features to the server, the easiest
|
of course, if you plan to add new features to the server, the easiest
|
||||||
way to do so is to simply become an Evennia developer!
|
way to do so is to simply become an Evennia developer!
|
||||||
|
|
||||||
Q: Can I re-distribute the Evennia server package along with my custom
|
Q: Can I re-distribute the Evennia server package along with my custom game implementation?
|
||||||
game implementation?
|
|
||||||
-------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
**A:** Sure. This is covered in **§4** - just package the "Standard
|
**A:** Sure. This is covered in **§4** - just package the "Standard
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ General mud/game development ideas and discussions
|
||||||
aggregator following blogs of current MUD development around the
|
aggregator following blogs of current MUD development around the
|
||||||
'net.
|
'net.
|
||||||
- Mud Dev mailing list archive
|
- Mud Dev mailing list archive
|
||||||
(`mirror1 <http://nilgiri.net/MUD-Dev-archive/>`_),(`mirror2 <http://www.disinterest.org/resource/MUD-Dev/>`_)
|
(`mirror1 <http://nilgiri.net/MUD-Dev-archive/>`_),(\ `mirror2 <http://www.disinterest.org/resource/MUD-Dev/>`_)
|
||||||
- Influential mailing list active 1996-2004. Advanced game design
|
- Influential mailing list active 1996-2004. Advanced game design
|
||||||
discussions.
|
discussions.
|
||||||
- `Imaginary
|
- `Imaginary
|
||||||
|
|
|
||||||
|
|
@ -49,8 +49,9 @@ add, delete and check locks.
|
||||||
One can call ``locks.check()`` to perform a lock check, but to hide the
|
One can call ``locks.check()`` to perform a lock check, but to hide the
|
||||||
underlying implementation all objects also have a convenience function
|
underlying implementation all objects also have a convenience function
|
||||||
called ``access``. This should preferably be used. In the example below,
|
called ``access``. This should preferably be used. In the example below,
|
||||||
``accessing_obj`` is the object requesting the 'delete' access. This is
|
``accessing_obj`` is the object requesting the 'delete' access whereas
|
||||||
how it would (and do) look from inside the ``@delete`` command:
|
``obj`` is the object that might get deleted. This is how it would (and
|
||||||
|
do) look from inside the ``@delete`` command:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
|
@ -63,7 +64,7 @@ Defining a lock (i.e. an access restriction) in Evennia is done by
|
||||||
adding simple strings of lock definitions to the object's ``locks``
|
adding simple strings of lock definitions to the object's ``locks``
|
||||||
property using ``obj.locks.add()``.
|
property using ``obj.locks.add()``.
|
||||||
|
|
||||||
Here are some examples of lock strings:
|
Here are some examples of lock strings (not including the quotes):
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
|
@ -79,7 +80,7 @@ where ``[..]`` marks optional parts. AND, OR and NOT are not case
|
||||||
sensitive and excess spaces are ignored. ``func1, func2`` etc are
|
sensitive and excess spaces are ignored. ``func1, func2`` etc are
|
||||||
special *lock functions* available to the lock system.
|
special *lock functions* available to the lock system.
|
||||||
|
|
||||||
So, a lockstrings consists of the type of restriction (the
|
So, a lockstring consists of the type of restriction (the
|
||||||
``access_type``), a colon (``:``) and then a list of function calls that
|
``access_type``), a colon (``:``) and then a list of function calls that
|
||||||
determine what is needed to pass the lock. Each function returns either
|
determine what is needed to pass the lock. Each function returns either
|
||||||
``True`` or ``False``. AND/OR and NOT works like normal Python to
|
``True`` or ``False``. AND/OR and NOT works like normal Python to
|
||||||
|
|
@ -163,7 +164,8 @@ You are not allowed to use just any function in your lock definition;
|
||||||
you are infact only allowed to use those functions defined in one of the
|
you are infact only allowed to use those functions defined in one of the
|
||||||
modules given in ``settings.LOCK_FUNC_MODULES``. All functions in any of
|
modules given in ``settings.LOCK_FUNC_MODULES``. All functions in any of
|
||||||
those modules will automatically be considered a valid lock function.
|
those modules will automatically be considered a valid lock function.
|
||||||
The default ones are found in ``src/locks/lockfuncs.py``.
|
The default ones are found in ``src/locks/lockfuncs.py`` or via
|
||||||
|
``ev.lockfuncs``.
|
||||||
|
|
||||||
A lock function must always accept at least two arguments - the
|
A lock function must always accept at least two arguments - the
|
||||||
*accessing object* (this is the object wanting to get access) and the
|
*accessing object* (this is the object wanting to get access) and the
|
||||||
|
|
@ -195,7 +197,7 @@ Some useful default lockfuncs (see ``src/locks/lockfuncs.py`` for more):
|
||||||
- ``attr(attrname)`` - checks if a certain
|
- ``attr(attrname)`` - checks if a certain
|
||||||
`Attribute <Attributes.html>`_ exists on accessingobject.
|
`Attribute <Attributes.html>`_ exists on accessingobject.
|
||||||
- ``attr(attrname, value)`` - checks so an attribute exists on
|
- ``attr(attrname, value)`` - checks so an attribute exists on
|
||||||
accessing*object*and has the given value.
|
accessing\ *object*\ and has the given value.
|
||||||
- ``attr_gt(attrname, value)`` - checks so accessingobject has a value
|
- ``attr_gt(attrname, value)`` - checks so accessingobject has a value
|
||||||
larger (``>``) than the given value.
|
larger (``>``) than the given value.
|
||||||
- ``attr_ge, attr_lt, attr_le, attr_ne`` - corresponding for ``>=``,
|
- ``attr_ge, attr_lt, attr_le, attr_ne`` - corresponding for ``>=``,
|
||||||
|
|
@ -260,9 +262,9 @@ looked for is not in the hierarchy, an exact match is required.
|
||||||
Superusers
|
Superusers
|
||||||
----------
|
----------
|
||||||
|
|
||||||
There is normally only one *superuser* account and that is the the one
|
There is normally only one *superuser* account and that is the one first
|
||||||
first created when starting Evennia (User #1). This is sometimes known
|
created when starting Evennia (User #1). This is sometimes known as the
|
||||||
as the "Owner" or "God" user. A superuser has more than full access - it
|
"Owner" or "God" user. A superuser has more than full access - it
|
||||||
completely *bypasses* all locks so no checks are even run. This allows
|
completely *bypasses* all locks so no checks are even run. This allows
|
||||||
for the superuser to always have access to everything in an emergency.
|
for the superuser to always have access to everything in an emergency.
|
||||||
But it also hides any eventual errors you might have made in your lock
|
But it also hides any eventual errors you might have made in your lock
|
||||||
|
|
@ -349,7 +351,7 @@ this snippet:
|
||||||
|
|
||||||
So the ``get`` command looks for a lock with the type *get* (not so
|
So the ``get`` command looks for a lock with the type *get* (not so
|
||||||
surprising). It also looks for an `Attribute <Attributes.html>`_ on the
|
surprising). It also looks for an `Attribute <Attributes.html>`_ on the
|
||||||
checked object called *get*err*msg* in order to return a customized
|
checked object called *get*\ err\ *msg* in order to return a customized
|
||||||
error message. Sounds good! Let's start by setting that on the box:
|
error message. Sounds good! Let's start by setting that on the box:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
@ -361,7 +363,7 @@ only be passed if the accessing object has the attribute *strength* of
|
||||||
the right value. For this we would need to create a lock function that
|
the right value. For this we would need to create a lock function that
|
||||||
checks if attributes have a value greater than a given value. Luckily
|
checks if attributes have a value greater than a given value. Luckily
|
||||||
there is already such a one included in evennia (see
|
there is already such a one included in evennia (see
|
||||||
``src/permissions/lockfuncs.py``), called``attr_gt``.
|
``src/permissions/lockfuncs.py``), called ``attr_gt``.
|
||||||
|
|
||||||
So the lock string will look like this: ``get:attr_gt(strength, 50)``.
|
So the lock string will look like this: ``get:attr_gt(strength, 50)``.
|
||||||
We put this on the box now:
|
We put this on the box now:
|
||||||
|
|
@ -379,14 +381,14 @@ like this:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
from src.utils import create box = create.create_object(None, key="box", locks="get:attr_gt(strength, 50)")# or, if we don't set the locks right awaybox.locks.add("get:attr_gt(strength, 50)")# set the attributesbox.db.desc = "This is a very big and heavy box." box.db.get_err_msg = "You are not strong enough to lift this box."# one heavy box, ready to withstand all but the strongest...
|
from ev import create_objectbox = create_object(None, key="box") box.locks.add("get:attr_gt(strength, 50)")# or we can assign locks right away box = create_object(None, key="box", locks="get:attr_gt(strength, 50)")# set the attributes box.db.desc = "This is a very big and heavy box." box.db.get_err_msg = "You are not strong enough to lift this box."# one heavy box, ready to withstand all but the strongest...
|
||||||
|
|
||||||
On Django's permission system
|
On Django's permission system
|
||||||
=============================
|
=============================
|
||||||
|
|
||||||
Django also implements a comprehensive permission/security system out of
|
Django also implements a comprehensive permission/security system of its
|
||||||
the box. The reason we don't use that is because it is app-centric (app
|
own. The reason we don't use that is because it is app-centric (app in
|
||||||
in the Django sense). Its permission strings are of the form
|
the Django sense). Its permission strings are of the form
|
||||||
``appname.permstring`` and it automatically adds three of them for each
|
``appname.permstring`` and it automatically adds three of them for each
|
||||||
database model in the app - for the app src/object this would be for
|
database model in the app - for the app src/object this would be for
|
||||||
example 'object.create', 'object.admin' and 'object.edit'. This makes a
|
example 'object.create', 'object.admin' and 'object.edit'. This makes a
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ commands expecting an object reference, such as
|
||||||
|
|
||||||
look mycar2
|
look mycar2
|
||||||
|
|
||||||
becomes equivalent to "``look The red sports car``".
|
becomes equivalent to "``look The red sports car``\ ".
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,13 @@ An Evennia Object is, per definition, a Python class that includes
|
||||||
``src.objects.objects.Object`` among its parents (if you are aware of
|
``src.objects.objects.Object`` among its parents (if you are aware of
|
||||||
how typeclasses work, this is a typeclass linked to the ``ObjectDB``
|
how typeclasses work, this is a typeclass linked to the ``ObjectDB``
|
||||||
database model). In your code you can however conveniently refer to
|
database model). In your code you can however conveniently refer to
|
||||||
``game.gamesrc.objects.baseobjects.Object`` instead.
|
``ev.Object`` instead.
|
||||||
|
|
||||||
Here's how to define a new Object typeclass in code:
|
Here's how to define a new Object typeclass in code:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
from game.gamesrc.objects.baseobjects import Objectclass Rose(Object): """ This creates a simple rose object """ def at_object_creation(self): "this is called only once, when object is first created" # add a persistent attribute 'desc' to object. self.db.desc = "This is a pretty rose with thorns."
|
from ev import Objectclass Rose(Object): """ This creates a simple rose object """ def at_object_creation(self): "this is called only once, when object is first created" # add a persistent attribute 'desc' to object. self.db.desc = "This is a pretty rose with thorns."
|
||||||
|
|
||||||
Save your class to a module under ``game/gamesrc/objects``, say
|
Save your class to a module under ``game/gamesrc/objects``, say
|
||||||
``flowers.py``. Now you just need to point to the class *Rose* with the
|
``flowers.py``. Now you just need to point to the class *Rose* with the
|
||||||
|
|
@ -29,21 +29,21 @@ Save your class to a module under ``game/gamesrc/objects``, say
|
||||||
|
|
||||||
> @create/drop MyRose:flowers.Rose
|
> @create/drop MyRose:flowers.Rose
|
||||||
|
|
||||||
To create a new object in code, use the method
|
To create a new object in code, use the method ``ev.create_object`` (a
|
||||||
``src.utils.create.create_object()``:
|
shortcut to src.utils.create.create\_object()
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
from src.utils import create new_rose = create.create_object("game.gamesrc.objects.flowers.Rose", key="MyRose")
|
):from ev import create_object new_rose = create_object("game.gamesrc.objects.flowers.Rose", key="MyRose")
|
||||||
|
|
||||||
(You have to give the full path to the class in this case -
|
(You have to give the full path to the class in this case -
|
||||||
``create.create_object`` is a powerful function that should be used for
|
``create.create_object`` is a powerful function that should be used for
|
||||||
all coded creating, for example if you create your own command that
|
all coded creating, for example if you create your own command that
|
||||||
creates some objects as it runs. Check out the ``src.utils.create``
|
creates some objects as it runs. Check out the ``ev.create_*``
|
||||||
module for more info on which arguments you can give the function.)
|
functions.
|
||||||
|
|
||||||
This particular Rose class doesn't really do much, all it does it make
|
This particular Rose class doesn't really do much, all it does it make
|
||||||
sure the attribute ``desc``(which is what the ``look`` command looks
|
sure the attribute ``desc``\ (which is what the ``look`` command looks
|
||||||
for) is pre-set, which is pretty pointless since you will usually want
|
for) is pre-set, which is pretty pointless since you will usually want
|
||||||
to change this at build time (using the ``@describe`` command). The
|
to change this at build time (using the ``@describe`` command). The
|
||||||
``Object`` typeclass offers many more hooks that is available to use
|
``Object`` typeclass offers many more hooks that is available to use
|
||||||
|
|
@ -108,34 +108,34 @@ The last two properties are special:
|
||||||
`scripts <Scripts.html>`_ attached to the object (if any).
|
`scripts <Scripts.html>`_ attached to the object (if any).
|
||||||
|
|
||||||
The Object also has a host of useful utility functions. See the function
|
The Object also has a host of useful utility functions. See the function
|
||||||
headers in ``src/objects/models.py`` for arguments and more details.
|
headers in ``src/objects/objects.py`` for their arguments and more
|
||||||
|
details.
|
||||||
|
|
||||||
- ``msg`` - this function is used to send messages from the server to a
|
- ``msg()`` - this function is used to send messages from the server to
|
||||||
player connected to this object.
|
a player connected to this object.
|
||||||
- ``msg_contents`` - calls ``msg`` on all objects inside this object.
|
- ``msg_contents()`` - calls ``msg`` on all objects inside this object.
|
||||||
- ``search`` - this is a convenient shorthand to search for a specific
|
- ``search()`` - this is a convenient shorthand to search for a
|
||||||
object, at a given location or globally. It's mainly useful when
|
specific object, at a given location or globally. It's mainly useful
|
||||||
defining commands (in which case the object executing the command is
|
when defining commands (in which case the object executing the
|
||||||
named ``caller`` and one can do ``caller.search()`` to find objects
|
command is named ``caller`` and one can do ``caller.search()`` to
|
||||||
in the room to operate on).
|
find objects in the room to operate on).
|
||||||
- ``execute_cmd`` - Lets the object execute the given string as if it
|
- ``execute_cmd()`` - Lets the object execute the given string as if it
|
||||||
was given on the command line.
|
was given on the command line.
|
||||||
- ``move_to`` - perform a full move of this object to a new location.
|
- ``move_to`` - perform a full move of this object to a new location.
|
||||||
This is the main move method and will call all relevant hooks, do all
|
This is the main move method and will call all relevant hooks, do all
|
||||||
checks etc.
|
checks etc.
|
||||||
- ``clear_exits`` - will delete all `Exits <Objects#Exits.html>`_ to
|
- ``clear_exits()`` - will delete all `Exits <Objects#Exits.html>`_ to
|
||||||
*and* from this object.
|
*and* from this object.
|
||||||
- ``clear_contents`` - this will not delete anything, but rather move
|
- ``clear_contents()`` - this will not delete anything, but rather move
|
||||||
all contents (except Exits) to their designated ``Home`` locations.
|
all contents (except Exits) to their designated ``Home`` locations.
|
||||||
- ``delete`` - deletes this object, first calling ``clear_exits()`` and
|
- ``delete()`` - deletes this object, first calling ``clear_exits()``
|
||||||
``clear_contents()``.
|
and ``clear_contents()``.
|
||||||
|
|
||||||
The Object Typeclass defines many more *hook methods* beyond
|
The Object Typeclass defines many more *hook methods* beyond
|
||||||
``at_object_creation``. Evennia calls these hooks at various points.
|
``at_object_creation``. Evennia calls these hooks at various points.
|
||||||
When implementing your custom objects, you will inherit from the base
|
When implementing your custom objects, you will inherit from the base
|
||||||
parent and overload these hooks with your own custom code. See
|
parent and overload these hooks with your own custom code. See
|
||||||
``game.gamesrc.baseobjects`` for an updated list of all the available
|
``src.objects.objects`` for an updated list of all the available hooks.
|
||||||
hooks.
|
|
||||||
|
|
||||||
Subclasses of *Object*
|
Subclasses of *Object*
|
||||||
----------------------
|
----------------------
|
||||||
|
|
@ -146,8 +146,7 @@ because these particular object types are fundamental, something you
|
||||||
will always need and in some cases requires some extra attention in
|
will always need and in some cases requires some extra attention in
|
||||||
order to be recognized by the game engine (there is nothing stopping you
|
order to be recognized by the game engine (there is nothing stopping you
|
||||||
from redefining them though). In practice they are all pretty similar to
|
from redefining them though). In practice they are all pretty similar to
|
||||||
the base Object. You will import them all from
|
the base Object.
|
||||||
``game.gamesrc.objects.baseobjects``.
|
|
||||||
|
|
||||||
Characters
|
Characters
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
|
@ -158,10 +157,10 @@ object is created and the Player object is assigned to the ``player``
|
||||||
attribute. A ``Character`` object must have a `Default
|
attribute. A ``Character`` object must have a `Default
|
||||||
Commandset <Commands#Command_Sets.html>`_ set on itself at creation, or
|
Commandset <Commands#Command_Sets.html>`_ set on itself at creation, or
|
||||||
the player will not be able to issue any commands! If you just inherit
|
the player will not be able to issue any commands! If you just inherit
|
||||||
your own class from ``baseobjects.Character`` and make sure the parent
|
your own class from ``ev.Character`` and make sure the parent methods
|
||||||
methods are not stopped from running you should not have to worry about
|
are not stopped from running you should not have to worry about this.
|
||||||
this. You can change the default typeclass assigned to new Players in
|
You can change the default typeclass assigned to new Players in your
|
||||||
your settings with ``BASE_CHARACTER_TYPECLASS``.
|
settings with ``BASE_CHARACTER_TYPECLASS``.
|
||||||
|
|
||||||
Rooms
|
Rooms
|
||||||
~~~~~
|
~~~~~
|
||||||
|
|
@ -170,8 +169,8 @@ Rooms
|
||||||
really separating a room from any other object is that they have no
|
really separating a room from any other object is that they have no
|
||||||
``location`` of their own and that default commands like ``@dig``
|
``location`` of their own and that default commands like ``@dig``
|
||||||
creates objects of this class - so if you want to expand your rooms with
|
creates objects of this class - so if you want to expand your rooms with
|
||||||
more functionality, just inherit from ``baseobjects.Room``. Change the
|
more functionality, just inherit from ``ev.Room``. Change the default
|
||||||
default used by ``@dig`` with ``BASE_ROOM_TYPECLASS``.
|
used by ``@dig`` with ``BASE_ROOM_TYPECLASS``.
|
||||||
|
|
||||||
Exits
|
Exits
|
||||||
~~~~~
|
~~~~~
|
||||||
|
|
@ -191,10 +190,10 @@ its own to move around, just as you would expect.
|
||||||
The exit functionality is all defined on the Exit typeclass, so you
|
The exit functionality is all defined on the Exit typeclass, so you
|
||||||
could in principle completely change how exits work in your game (it's
|
could in principle completely change how exits work in your game (it's
|
||||||
not recommended though, unless you really know what you are doing).
|
not recommended though, unless you really know what you are doing).
|
||||||
Exits are `locked <Locks.html>`_ using an access*type called*traverse\_
|
Exits are `locked <Locks.html>`_ using an access\ *type
|
||||||
and also make use of a few hook methods for giving feedback if the
|
called*\ traverse\_ and also make use of a few hook methods for giving
|
||||||
traversal fails. See ``baseobjects.Exit`` for more info, that is also
|
feedback if the traversal fails. See ``ev.Exit`` for more info, that is
|
||||||
what you should inherit from to make custom exit types. Change the
|
also what you should inherit from to make custom exit types. Change the
|
||||||
default class used by e.g. ``@dig`` and ``@open`` by editing
|
default class used by e.g. ``@dig`` and ``@open`` by editing
|
||||||
``BASE_EXIT_TYPECLASS`` in your settings.
|
``BASE_EXIT_TYPECLASS`` in your settings.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,23 +33,21 @@ player's typeclass dynamically).
|
||||||
An Evennia Player is, per definition, a Python class that includes
|
An Evennia Player is, per definition, a Python class that includes
|
||||||
``src.players.player.Player`` among its parents (if you are aware of how
|
``src.players.player.Player`` among its parents (if you are aware of how
|
||||||
`Typeclasses <Typeclasses.html>`_ work, this is a typeclass linked to
|
`Typeclasses <Typeclasses.html>`_ work, this is a typeclass linked to
|
||||||
the ``PlayerDB`` database model). There is no equivalence to this in the
|
the ``PlayerDB`` database model). You can also inherit from
|
||||||
``game/gamesrc`` folder, you need to inherit from the base object
|
``ev.Player`` which is a shortcut.
|
||||||
directly.
|
|
||||||
|
|
||||||
Here's how to define a new Player typeclass in code:
|
Here's how to define a new Player typeclass in code:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
from src.players.player import Player class ConfigPlayer(Player): """ This creates a Player with some configuration options """ at_player_creation(self): "this is called only once, when player is first created" self.db.real_name = None # this is set later self.db.real_address = None # '' self.db.config_1 = True # default config self.db.config_2 = False # " self.db.config_3 = 1 # " # ... whatever else our game needs to know
|
from ev import Player class ConfigPlayer(Player): """ This creates a Player with some configuration options """ at_player_creation(self): "this is called only once, when player is first created" self.db.real_name = None # this is set later self.db.real_address = None # '' self.db.config_1 = True # default config self.db.config_2 = False # " self.db.config_3 = 1 # " # ... whatever else our game needs to know
|
||||||
|
|
||||||
There is no pre-made folder in ``game/gamesrc`` to store custom player
|
There is no pre-made folder in ``game/gamesrc`` to store custom player
|
||||||
typeclasses. Either make your own folder or store it in
|
typeclasses. Make your own folder or store it in ``gamesrc/objects``
|
||||||
``gamesrc/objects`` (remember that if you make your own folder you need
|
(remember that if you make your own folder you need to add an empty
|
||||||
to add an empty ``__init__.py`` file so that you can import the file
|
``__init__.py`` file so that you can import the file later). To change
|
||||||
later). To change which object becomes the Player object for new
|
which object becomes the Player object for new players, set the variable
|
||||||
players, set the variable ``BASE_PLAYER_TYPECLASS`` in your
|
``BASE_PLAYER_TYPECLASS`` in your ``settings.py`` file.
|
||||||
``settings.py`` file.
|
|
||||||
|
|
||||||
Properties on Players
|
Properties on Players
|
||||||
---------------------
|
---------------------
|
||||||
|
|
@ -81,8 +79,8 @@ Special handlers:
|
||||||
How it all hangs together
|
How it all hangs together
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
Looking at the above list, it's clear there are more to ``Player``s than
|
Looking at the above list, it's clear there are more to ``Player``\ s
|
||||||
what first meets the eye.
|
than what first meets the eye.
|
||||||
|
|
||||||
What happens when a person connects to Evennia and logs in is that they
|
What happens when a person connects to Evennia and logs in is that they
|
||||||
log in as a ``User`` object. This is a Django object that knows all
|
log in as a ``User`` object. This is a Django object that knows all
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ to have players connect to the Portal but keep the MUD running on the
|
||||||
Server. This way one can restart/reload the game (the Server part)
|
Server. This way one can restart/reload the game (the Server part)
|
||||||
without Players getting disconnected.
|
without Players getting disconnected.
|
||||||
|
|
||||||
https://2498159658166209538-a-1802744773732722657-s-sites.googlegroups.com/site/evenniaserver/file-cabinet/evennia*server*portal.png
|
https://2498159658166209538-a-1802744773732722657-s-sites.googlegroups.com/site/evenniaserver/file-cabinet/evennia\ *server*\ portal.png
|
||||||
|
|
||||||
The Server and Portal are glued together via an AMP (Asynchronous
|
The Server and Portal are glued together via an AMP (Asynchronous
|
||||||
Messaging Protocol) connection. This allows the two programs to
|
Messaging Protocol) connection. This allows the two programs to
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ inheriting from ``game.gamesrc.objects.baseobjecs.Character``.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
from game.gamesrc.objects.baseobjects import Characterclass ColourableCharacter(Character): at_object_creation(self): # set a colour config value self.db.config_colour = True
|
from ev import Characterclass ColourableCharacter(Character): at_object_creation(self): # set a colour config value self.db.config_colour = True
|
||||||
|
|
||||||
Above we set a simple config value as an `attribute <Attributes.html>`_.
|
Above we set a simple config value as an `attribute <Attributes.html>`_.
|
||||||
|
|
||||||
|
|
@ -50,11 +50,13 @@ everything works - you don't want to render your root user unusable!).
|
||||||
|
|
||||||
@typeclass/reset/force Bob = mycharacter.ColourableCharacter
|
@typeclass/reset/force Bob = mycharacter.ColourableCharacter
|
||||||
|
|
||||||
The ``/reset`` switch clears all attributes and properties back to the
|
``@typeclass`` changes Bob's typeclass and runs all its creation hooks
|
||||||
default for the new typeclass and forces the object to re-run all its
|
all over again. The ``/reset`` switch clears all attributes and
|
||||||
creation hooks (important in this case). ``/force`` might be needed if
|
properties back to the default for the new typeclass - this is useful in
|
||||||
you edit the typeclass and want to update the object despite the actual
|
this case to avoid ending up with an object having a "mixture" of
|
||||||
typeclass name not having changed.
|
properties from the old typeclass and the new one. ``/force`` might be
|
||||||
|
needed if you edit the typeclass and want to update the object despite
|
||||||
|
the actual typeclass name not having changed.
|
||||||
|
|
||||||
Overload the ``msg()`` method
|
Overload the ``msg()`` method
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
@ -74,7 +76,7 @@ original. Here's how it could look:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
from src.utils import ansimsg(self, message, from_obj=None, data=None): "our custom msg()" if not self.db.config_colour: message = ansi.parse_ansi(message, strip_ansi=True) self.dbobj.msg(message, from_obj, data)
|
from ev import ansimsg(self, message, from_obj=None, data=None): "our custom msg()" if not self.db.config_colour: message = ansi.parse_ansi(message, strip_ansi=True) self.dbobj.msg(message, from_obj, data)
|
||||||
|
|
||||||
Above we create a custom version of the ``msg()`` method that cleans all
|
Above we create a custom version of the ``msg()`` method that cleans all
|
||||||
ansi characters if the config value is not set to True. Once that's
|
ansi characters if the config value is not set to True. Once that's
|
||||||
|
|
@ -106,15 +108,27 @@ for configuration down the line).
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
from game.gamesrc.commands.basecommand import MuxCommandclass ConfigColourCmd(MuxCommand): """ Configures your colour Usage: @setcolour on|off This turns ansii-colours on/off. Default is on. """ key = "@setcolour" aliases = ["@setcolor"] def func(self): "Implements the command" if not self.args or not self.args in ("on", "off"): self.caller.msg("Usage: @setcolour on|off") return if self.args == "on": self.caller.db.config_colour = True else: self.caller.db.config_colour = False self.caller.msg("Colour was turned %s." % self.args)
|
from ev import default_cmds
|
||||||
|
class ConfigColourCmd(default_cmds.MuxCommand):
|
||||||
|
"""
|
||||||
|
Configures your colour Usage: @setcolour on|off This turns ansii-colours on/off. Default is on. """ key = "@setcolour" aliases = ["@setcolor"] def func(self): "Implements the command" if not self.args or not self.args in ("on", "off"): self.caller.msg("Usage: @setcolour on|off") return if self.args == "on": self.caller.db.config_colour = True else: self.caller.db.config_colour = False self.caller.msg("Colour was turned %s." % self.args)
|
||||||
|
|
||||||
Lastly, we make this command available to the user by adding it to the
|
Lastly, we make this command available to the user by adding it to the
|
||||||
default command set. Easiest is to add it to the end of
|
default command set. Easiest is to add it to copy the template file from
|
||||||
``DefaultCmdSet`` class in gamesrc/commands/basecmdset.py:
|
``gamesrc/commands/examples``, set ``settings.CMDSET_DEFAULT`` to point
|
||||||
|
to, and then add your module to the end of ``DefaultCmdSet`` in that new
|
||||||
|
module.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
from game.gamesrc.commands import configcmds class DefaultCmdSet(cmdset_default.DefaultCmdSet): key = "DefaultMUX" def at_cmdset_creation(self): super(DefaultCmdSet, self).at_cmdset_creation() self.add(configcmds.ConfigColourCmd())
|
from game.gamesrc.commands import configcmds
|
||||||
|
class DefaultCmdSet(cmdset_default.DefaultCmdSet):
|
||||||
|
|
||||||
|
key = "DefaultMUX"
|
||||||
|
|
||||||
|
def at_cmdset_creation(self):
|
||||||
|
super(DefaultCmdSet, self).at_cmdset_creation()
|
||||||
|
self.add(configcmds.ConfigColourCmd())
|
||||||
|
|
||||||
When adding a new command to a cmdset like this you need to run the
|
When adding a new command to a cmdset like this you need to run the
|
||||||
``@reload`` command (or reboot the server). From here on out, your users
|
``@reload`` command (or reboot the server). From here on out, your users
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,7 @@ intervals (a *ticker*). Scripts not defined directly 'on' objects are
|
||||||
called *Global* scripts.
|
called *Global* scripts.
|
||||||
|
|
||||||
Custom script modules are usually stored in ``game/gamesrc/scripts``. As
|
Custom script modules are usually stored in ``game/gamesrc/scripts``. As
|
||||||
a convenience you can inherit all scripts from
|
a convenience you can inherit sripts from ``ev.Script``.
|
||||||
``game.gamesrc.scripts.basescript.Script``.
|
|
||||||
|
|
||||||
You can try out scripts an add them to objects by use of the ``@script``
|
You can try out scripts an add them to objects by use of the ``@script``
|
||||||
command (not to the confused with ``@scripts`` which lists scripts). You
|
command (not to the confused with ``@scripts`` which lists scripts). You
|
||||||
|
|
@ -79,12 +78,12 @@ to name your script uniquely before adding it. This can be useful if you
|
||||||
add many scripts of the same type and later plan to use
|
add many scripts of the same type and later plan to use
|
||||||
``myobj.scripts.delete`` to remove individual scripts.
|
``myobj.scripts.delete`` to remove individual scripts.
|
||||||
|
|
||||||
You can create global scripts with ``src.utils.create.create_script()``.
|
You can create global scripts with
|
||||||
Just don't supply an object to store it on.
|
``ev.create_script (a shortcut to``\ src.utils.create.create\_script()
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
# adding a global script from src.utils.create import create_script create_script("game.gamesrc.scripts.globals.MyGlobalEconomy", key="economy", obj=None)
|
). Just don't supply an object to store it on. # adding a global script from ev import create_script create_script("game.gamesrc.scripts.globals.MyGlobalEconomy", key="economy", obj=None)
|
||||||
|
|
||||||
Assuming the Script ``game.gamesrc.scripts.globals.MyGlobalEconomy``
|
Assuming the Script ``game.gamesrc.scripts.globals.MyGlobalEconomy``
|
||||||
exists, this will create and start it as a global script.
|
exists, this will create and start it as a global script.
|
||||||
|
|
@ -119,7 +118,7 @@ There is one special property:
|
||||||
|
|
||||||
It's also imperative to know the hook functions. Normally, overriding
|
It's also imperative to know the hook functions. Normally, overriding
|
||||||
these are all the customization you'll need to do in Scripts. You can
|
these are all the customization you'll need to do in Scripts. You can
|
||||||
find longer descriptions of these in ``gamesrc/scripts/basescript.py``.
|
find longer descriptions of these in ``src/scripts/scripts.py``.
|
||||||
|
|
||||||
- ``at_script_creation()`` - this is usually where the script class
|
- ``at_script_creation()`` - this is usually where the script class
|
||||||
sets things like ``interval`` and ``repeats``; things that control
|
sets things like ``interval`` and ``repeats``; things that control
|
||||||
|
|
@ -153,7 +152,7 @@ possible to also invoke manually)
|
||||||
automatically whenever you add a new script to a handler.
|
automatically whenever you add a new script to a handler.
|
||||||
``at_start()`` will be called.
|
``at_start()`` will be called.
|
||||||
- ``stop()`` - this will stop the script and delete it. Removing a
|
- ``stop()`` - this will stop the script and delete it. Removing a
|
||||||
script from a handler will stop it auomatically. ``at_stop()`` will
|
script from a handler will stop it automatically. ``at_stop()`` will
|
||||||
be called.
|
be called.
|
||||||
- ``pause()`` - this pauses a running script, rendering it inactive,
|
- ``pause()`` - this pauses a running script, rendering it inactive,
|
||||||
but not deleting it. All properties are saved and timers can be
|
but not deleting it. All properties are saved and timers can be
|
||||||
|
|
@ -174,7 +173,7 @@ Example script
|
||||||
::
|
::
|
||||||
|
|
||||||
import random
|
import random
|
||||||
from game.gamesrc.scripts.basescript import Script
|
from ev import Script
|
||||||
class Weather(Script):
|
class Weather(Script):
|
||||||
"Displays weather info. Meant to be attached to a room."
|
"Displays weather info. Meant to be attached to a room."
|
||||||
def at_script_creation(self):
|
def at_script_creation(self):
|
||||||
|
|
@ -212,7 +211,7 @@ locate the room you want:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
from src.utils.create import create_script create_script('game.gamesrc.scripts.weather.Weather', obj=myroom)
|
from ev import create_script create_script('game.gamesrc.scripts.weather.Weather', obj=myroom)
|
||||||
|
|
||||||
Or, from in-game, use the ``@script`` command:
|
Or, from in-game, use the ``@script`` command:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ On MUX and Softcode: A brief overview
|
||||||
|
|
||||||
Evennia was originally created in order to provide a MUX/MUSH-style
|
Evennia was originally created in order to provide a MUX/MUSH-style
|
||||||
development environment without the kludgery of softcode. Although it
|
development environment without the kludgery of softcode. Although it
|
||||||
has since grown to be adaptable to any style of MU``*`` it still ships
|
has since grown to be adaptable to any style of MU\ ``*`` it still ships
|
||||||
with 'MUX-like' default commands.
|
with 'MUX-like' default commands.
|
||||||
|
|
||||||
This document will provide a quick overview of what softcode is, why it
|
This document will provide a quick overview of what softcode is, why it
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ Resetting
|
||||||
---------
|
---------
|
||||||
|
|
||||||
*Resetting* is the equivalent of a "cold reboot" of the server - it will
|
*Resetting* is the equivalent of a "cold reboot" of the server - it will
|
||||||
restart but will behave as it if was fully shut down. You initiate a
|
restart but will behave as if it was fully shut down. You initiate a
|
||||||
reset using the ``@reset`` command from inside the game. As with a
|
reset using the ``@reset`` command from inside the game. As with a
|
||||||
reload, no players will be disconnected during a shutdown. It will
|
reload, no players will be disconnected during a shutdown. It will
|
||||||
however purge all non-persistent scripts and will call
|
however purge all non-persistent scripts and will call
|
||||||
|
|
|
||||||
|
|
@ -24,16 +24,13 @@ storing data they hide underlying database models ...
|
||||||
... and that's basically all you *really* need to know about how
|
... and that's basically all you *really* need to know about how
|
||||||
typeclasses work behind the scenes.
|
typeclasses work behind the scenes.
|
||||||
|
|
||||||
To work with them you should however know that Objects, Scripts and
|
To *work* with them you should however know that Objects, Scripts and
|
||||||
Players all inherit a lot of helper methods from the typeclass system,
|
Players all inherit a lot of helper methods from the typeclass system,
|
||||||
properties you can *always* expect a typeclassed entity to have. In
|
properties you can *always* expect a typeclassed entity to have. In
|
||||||
addition to these, each of the three sub types also offer a host of help
|
addition to these, each of the three sub types also offer a host of
|
||||||
methods and properties you can use. The database handling is hidden, but
|
additional, subtype-specific helper methods and properties for your use.
|
||||||
it means that typeclasses do some special things with their in-built
|
|
||||||
class methods that you shouldn't edit.
|
|
||||||
|
|
||||||
Properties available to all typeclassed entities (Players, Objects,
|
Properties available to all typeclassed entities (Players, Objects, Scripts)
|
||||||
Scripts)
|
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
- ``key`` - the main identifier for the entity, say 'Rose', 'myscript'
|
- ``key`` - the main identifier for the entity, say 'Rose', 'myscript'
|
||||||
|
|
@ -65,7 +62,7 @@ more info.
|
||||||
Things to remember when using TypeClasses
|
Things to remember when using TypeClasses
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
|
||||||
Typeclasses mostly behave like normal Python classes - you can
|
Typeclasses *mostly* behave like normal Python classes - you can
|
||||||
add/overload custom methods and inherit your own classes from them -
|
add/overload custom methods and inherit your own classes from them -
|
||||||
most things you'd expect to be able to do with a Python class. There are
|
most things you'd expect to be able to do with a Python class. There are
|
||||||
a few things that you need to remember however:
|
a few things that you need to remember however:
|
||||||
|
|
@ -182,6 +179,7 @@ Below is a schematic of the database/typeclass structure.
|
||||||
.. figure:: http://d.imagehost.org/0784/typeclasses1.png
|
.. figure:: http://d.imagehost.org/0784/typeclasses1.png
|
||||||
:align: center
|
:align: center
|
||||||
:alt:
|
:alt:
|
||||||
|
|
||||||
Let's see how object creation looks like in an example.
|
Let's see how object creation looks like in an example.
|
||||||
|
|
||||||
#. We have defined a Typeclass called *Rose* in
|
#. We have defined a Typeclass called *Rose* in
|
||||||
|
|
@ -213,9 +211,8 @@ Let's see how object creation looks like in an example.
|
||||||
|
|
||||||
Storing properties on the typeclass-instance will in fact transparently
|
Storing properties on the typeclass-instance will in fact transparently
|
||||||
save to the database object. So ``RedRose.thorns = True`` is the same as
|
save to the database object. So ``RedRose.thorns = True`` is the same as
|
||||||
``RedRose.dbobj.thorns = True`` (note also that depending on your
|
``RedRose.dbobj.thorns = True`` (this will in fact be saved in the
|
||||||
``FULL_PERSISTENCE`` setting, this may or may not save ``thorns`` as an
|
database as an attribute "thorns").
|
||||||
`Attribute <Attributes.html>`_ behind the scenes).
|
|
||||||
|
|
||||||
Doing ``ouch = RedRose.thorns`` is however not really as symmetric. The
|
Doing ``ouch = RedRose.thorns`` is however not really as symmetric. The
|
||||||
system will in this case *first* check the Typeclass instance and only
|
system will in this case *first* check the Typeclass instance and only
|
||||||
|
|
@ -228,13 +225,14 @@ are intended to *overload* the default methods on the database object.
|
||||||
These are thus searched and run first, and you can then safely use
|
These are thus searched and run first, and you can then safely use
|
||||||
``self.dbobj`` from the typeclass to call the original function if you
|
``self.dbobj`` from the typeclass to call the original function if you
|
||||||
want. An example of Typeclass overloading is found
|
want. An example of Typeclass overloading is found
|
||||||
`here <CommandPrompt#Prompt%3Ci%3Eon%3C/i%3Ethe%3Ci%3Esame%3C/i%3Eline.html>`_.
|
`here <CommandPrompt#Prompt<i>on</i>the<i>same</i>line.html>`_.
|
||||||
|
|
||||||
Another example:
|
Another example:
|
||||||
|
|
||||||
.. figure:: http://b.imagehost.org/0023/typeclasses2.png
|
.. figure:: http://b.imagehost.org/0023/typeclasses2.png
|
||||||
:align: center
|
:align: center
|
||||||
:alt:
|
:alt:
|
||||||
|
|
||||||
Caveats of the typeclass system
|
Caveats of the typeclass system
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
|
|
@ -261,7 +259,7 @@ Even more important to know for Django affectionados: Evennia's custom
|
||||||
methods return *lists* where you with normal Django methods would expect
|
methods return *lists* where you with normal Django methods would expect
|
||||||
``Query`` objects (e.g. from the ``filter()`` method). As long as you
|
``Query`` objects (e.g. from the ``filter()`` method). As long as you
|
||||||
don't confuse what result type you are dealing with (for example you
|
don't confuse what result type you are dealing with (for example you
|
||||||
cannot 'link' ``list``s together the way you can ``Querysets``), you
|
cannot 'link' ``list``\ s together the way you can ``Querysets``), you
|
||||||
should be fine.
|
should be fine.
|
||||||
|
|
||||||
Read the ``manager.py`` files in each relevant folder under ``src/`` to
|
Read the ``manager.py`` files in each relevant folder under ``src/`` to
|
||||||
|
|
|
||||||
|
|
@ -45,12 +45,12 @@ Inside the ``tests.py`` module you create classes inheriting from
|
||||||
used to test a single aspect or component in various ways. Each test
|
used to test a single aspect or component in various ways. Each test
|
||||||
case contains one ore more *test methods* - these define the actual
|
case contains one ore more *test methods* - these define the actual
|
||||||
tests to run. You can name the test methods anything you want as long as
|
tests to run. You can name the test methods anything you want as long as
|
||||||
the name starts with "``test_``". Your ``TestCase`` class can also have
|
the name starts with "``test_``\ ". Your ``TestCase`` class can also
|
||||||
a method !SetUp(). This is run before each test, setting up whatever
|
have a method !SetUp(). This is run before each test, setting up
|
||||||
preparations the test methods need.
|
whatever preparations the test methods need.
|
||||||
|
|
||||||
To test the results, you use special methods of the ``TestCase`` class.
|
To test the results, you use special methods of the ``TestCase`` class.
|
||||||
Many of those start with "``assert``", such as ``assertEqual`` or
|
Many of those start with "``assert``\ ", such as ``assertEqual`` or
|
||||||
``assertTrue``.
|
``assertTrue``.
|
||||||
|
|
||||||
Example of a ``TestCase`` class (inside a file ``tests.py``):
|
Example of a ``TestCase`` class (inside a file ``tests.py``):
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ components you need to clear the data from all of them:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
python manage.py reset objects players scripts comms help web auth
|
python manage.py reset server objects players scripts comms help web auth
|
||||||
|
|
||||||
Django also offers an easy way to start the database's own management
|
Django also offers an easy way to start the database's own management
|
||||||
should we want more direct control:
|
should we want more direct control:
|
||||||
|
|
@ -93,7 +93,7 @@ using the database's command line. This often means adding/removing new
|
||||||
tables or fields as well as possibly convert existing data to match what
|
tables or fields as well as possibly convert existing data to match what
|
||||||
the new Evennia version expects. It should be quite obvious that this
|
the new Evennia version expects. It should be quite obvious that this
|
||||||
quickly becomes cumbersome and error-prone. If your database doesn't
|
quickly becomes cumbersome and error-prone. If your database doesn't
|
||||||
contain anything critical yet iẗ́'s probably easiest to simply reset it
|
contain anything critical yet iẗ́'s probably easiest to simply reset it
|
||||||
and start over rather than to bother converting.
|
and start over rather than to bother converting.
|
||||||
|
|
||||||
Enter `South <http://south.aeracode.org/>`_. South keeps track of
|
Enter `South <http://south.aeracode.org/>`_. South keeps track of
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ NO\_AUTOCHUNK
|
||||||
Contents are never sent to the client until the encoding mode changes
|
Contents are never sent to the client until the encoding mode changes
|
||||||
(for example, switching from HTML to UNENCODED will send the HTML
|
(for example, switching from HTML to UNENCODED will send the HTML
|
||||||
buffer) or the buffering mode changes (for example, one could set
|
buffer) or the buffering mode changes (for example, one could set
|
||||||
NO*AUTOCHUNK, send some text, and set NO*AUTOCHUNK again to force a
|
NO\ *AUTOCHUNK, send some text, and set NO*\ AUTOCHUNK again to force a
|
||||||
flush.
|
flush.
|
||||||
|
|
||||||
AUTOCHUNK
|
AUTOCHUNK
|
||||||
|
|
|
||||||
|
|
@ -50,249 +50,249 @@ SMAUG specifics
|
||||||
Code Availability By Lvl
|
Code Availability By Lvl
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| Lvl | Code Bit |
|
| Lvl | Code Bit |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 0 | spell*disenchant*weapon |
|
| 0 | spell\ *disenchant*\ weapon |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 1 | spell*cause*light |
|
| 1 | spell\ *cause*\ light |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 1 | dohide |
|
| 1 | dohide |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 1 | spellventriloquate |
|
| 1 | spellventriloquate |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 1 | docook |
|
| 1 | docook |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 1 | doclimb |
|
| 1 | doclimb |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 1 | spellnull |
|
| 1 | spellnull |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 1 | dopick |
|
| 1 | dopick |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 1 | dosteal |
|
| 1 | dosteal |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 1 | dobackstab |
|
| 1 | dobackstab |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 1 | spellsmaug |
|
| 1 | spellsmaug |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 1 | dokick |
|
| 1 | dokick |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 2 | dodig |
|
| 2 | dodig |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 2 | domount |
|
| 2 | domount |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 2 | spell*faerie*fire |
|
| 2 | spell\ *faerie*\ fire |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 2 | spell*create*food |
|
| 2 | spell\ *create*\ food |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 2 | spell*create*water |
|
| 2 | spell\ *create*\ water |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 2 | spellweaken |
|
| 2 | spellweaken |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 2 | spellblackhand |
|
| 2 | spellblackhand |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 3 | doscan |
|
| 3 | doscan |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 3 | dosearch |
|
| 3 | dosearch |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 3 | dofeed |
|
| 3 | dofeed |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 3 | spell*chill*touch |
|
| 3 | spell\ *chill*\ touch |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 4 | dorescue |
|
| 4 | dorescue |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 4 | spellcureblindness |
|
| 4 | spellcureblindness |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 4 | spellinvis |
|
| 4 | spellinvis |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 4 | doaid |
|
| 4 | doaid |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 4 | spellgalvanicwhip |
|
| 4 | spellgalvanicwhip |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 5 | spellblindness |
|
| 5 | spellblindness |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 5 | spell*cause*serious |
|
| 5 | spell\ *cause*\ serious |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 5 | spell*detect*poison |
|
| 5 | spell\ *detect*\ poison |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 5 | spell*burning*hands |
|
| 5 | spell\ *burning*\ hands |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 5 | spell*know*alignment |
|
| 5 | spell\ *know*\ alignment |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 6 | spell*locate*object |
|
| 6 | spell\ *locate*\ object |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 6 | dotrack |
|
| 6 | dotrack |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 6 | spellremoveinvis |
|
| 6 | spellremoveinvis |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 6 | spellpoison |
|
| 6 | spellpoison |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 7 | spellearthquake |
|
| 7 | spellearthquake |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 7 | spellshockinggrasp |
|
| 7 | spellshockinggrasp |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 8 | spellteleport |
|
| 8 | spellteleport |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 8 | dobashdoor |
|
| 8 | dobashdoor |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 8 | spellsummon |
|
| 8 | spellsummon |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 8 | spell*cure*poison |
|
| 8 | spell\ *cure*\ poison |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 8 | spelldisruption |
|
| 8 | spelldisruption |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 9 | spellbethsaideantouch |
|
| 9 | spellbethsaideantouch |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 9 | spellcausecritical |
|
| 9 | spellcausecritical |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 9 | spelllightningbolt |
|
| 9 | spelllightningbolt |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 10 | spellidentify |
|
| 10 | spellidentify |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 10 | spell*faerie*fog |
|
| 10 | spell\ *faerie*\ fog |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 10 | spell*control*weather |
|
| 10 | spell\ *control*\ weather |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 10 | spell*dispel*evil |
|
| 10 | spell\ *dispel*\ evil |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 10 | dodisarm |
|
| 10 | dodisarm |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 11 | spellcolourspray |
|
| 11 | spellcolourspray |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 11 | dobite |
|
| 11 | dobite |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 11 | spell*dispel*magic |
|
| 11 | spell\ *dispel*\ magic |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 11 | dobloodlet |
|
| 11 | dobloodlet |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 12 | spellsleep |
|
| 12 | spellsleep |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 12 | spellcurse |
|
| 12 | spellcurse |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 12 | spellcalllightning |
|
| 12 | spellcalllightning |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 12 | spellremovecurse |
|
| 12 | spellremovecurse |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 12 | spellenchantweapon |
|
| 12 | spellenchantweapon |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 12 | spellword*of*recall |
|
| 12 | spellword\ *of*\ recall |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 13 | spellharm |
|
| 13 | spellharm |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 13 | spellfireball |
|
| 13 | spellfireball |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 13 | spellexpurgation |
|
| 13 | spellexpurgation |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 13 | spellflamestrike |
|
| 13 | spellflamestrike |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 13 | spell*midas*touch |
|
| 13 | spell\ *midas*\ touch |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 13 | spell*energy*drain |
|
| 13 | spell\ *energy*\ drain |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 14 | spell*spectral*furor |
|
| 14 | spell\ *spectral*\ furor |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 14 | spell*charm*person |
|
| 14 | spell\ *charm*\ person |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 15 | spell*remove*trap |
|
| 15 | spell\ *remove*\ trap |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 16 | spellfarsight |
|
| 16 | spellfarsight |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 16 | dodetrap |
|
| 16 | dodetrap |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 17 | spelltransport |
|
| 17 | spelltransport |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 17 | spelldream |
|
| 17 | spelldream |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 18 | spell*sulfurous*spray |
|
| 18 | spell\ *sulfurous*\ spray |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 18 | spell*pass*door |
|
| 18 | spell\ *pass*\ door |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 19 | spell*sonic*resonance |
|
| 19 | spell\ *sonic*\ resonance |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 20 | dogouge |
|
| 20 | dogouge |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 20 | spellacidblast |
|
| 20 | spellacidblast |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 21 | spellportal |
|
| 21 | spellportal |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 23 | spell*black*fist |
|
| 23 | spell\ *black*\ fist |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 25 | dopunch |
|
| 25 | dopunch |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 25 | docircle |
|
| 25 | docircle |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 25 | dobrew |
|
| 25 | dobrew |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 27 | spellmagneticthrust |
|
| 27 | spellmagneticthrust |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 27 | dopoisonweapon |
|
| 27 | dopoisonweapon |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 28 | spellscorchingsurge |
|
| 28 | spellscorchingsurge |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 30 | doscribe |
|
| 30 | doscribe |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 30 | dobash |
|
| 30 | dobash |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 30 | spellastralwalk |
|
| 30 | spellastralwalk |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 31 | domistwalk |
|
| 31 | domistwalk |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 32 | spell*ethereal*fist |
|
| 32 | spell\ *ethereal*\ fist |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 32 | spellknock |
|
| 32 | spellknock |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 33 | spellrecharge |
|
| 33 | spellrecharge |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 34 | spell*caustic*fount |
|
| 34 | spell\ *caustic*\ fount |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 35 | spell*sacral*divinity |
|
| 35 | spell\ *sacral*\ divinity |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 35 | spell*plant*pass |
|
| 35 | spell\ *plant*\ pass |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 37 | spell*hand*ofchaos |
|
| 37 | spell\ *hand*\ ofchaos |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 37 | spellacetumprimus |
|
| 37 | spellacetumprimus |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 39 | spellsolarflight |
|
| 39 | spellsolarflight |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 41 | dobroach |
|
| 41 | dobroach |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 41 | spell*frost*breath |
|
| 41 | spell\ *frost*\ breath |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 42 | spell*helical*flow |
|
| 42 | spell\ *helical*\ flow |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 42 | spell*animate*dead |
|
| 42 | spell\ *animate*\ dead |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 42 | spell*lightning*breath |
|
| 42 | spell\ *lightning*\ breath |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 43 | spell*acid*breath |
|
| 43 | spell\ *acid*\ breath |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 44 | spell*fire*breath |
|
| 44 | spell\ *fire*\ breath |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 45 | spell*gas*breath |
|
| 45 | spell\ *gas*\ breath |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 46 | spell*spiral*blast |
|
| 46 | spell\ *spiral*\ blast |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 46 | spell*black*lightning |
|
| 46 | spell\ *black*\ lightning |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 48 | dostun |
|
| 48 | dostun |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 48 | spellquantumspike |
|
| 48 | spellquantumspike |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 50 | dohitall |
|
| 50 | dohitall |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 51 | spellpossess |
|
| 51 | spellpossess |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 51 | spellchangesex |
|
| 51 | spellchangesex |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 51 | spellgate |
|
| 51 | spellgate |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 51 | doslice |
|
| 51 | doslice |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 51 | spellpolymorph |
|
| 51 | spellpolymorph |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
| 51 | do\_berserk |
|
| 51 | do\_berserk |
|
||||||
+-------+---------------------------+
|
+-------+-------------------------------+
|
||||||
|
|
||||||
+ the affects they apply float, sneak, hide, detect invisibility, detect
|
+ the affects they apply float, sneak, hide, detect invisibility, detect
|
||||||
magic, detect evil, invisibility
|
magic, detect evil, invisibility
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
"""
|
"""
|
||||||
This package contains all default commands of Evennia, grouped after category.
|
This package contains all default commands of Evennia, grouped after category.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue