Updated ReST docs.
This commit is contained in:
parent
3aeec1298a
commit
64a30c655d
29 changed files with 1391 additions and 1186 deletions
|
|
@ -20,9 +20,9 @@ new additional commands of your own.
|
||||||
but in this example we assume you don't.
|
but in this example we assume you don't.
|
||||||
#. Edit ``game/settings.py``, adding the following line:
|
#. Edit ``game/settings.py``, adding the following line:
|
||||||
|
|
||||||
``CMDSET_DEFAULT="game.gamesrc.commands.cmdset.DefaultCmdSet"``
|
``CMDSET_CHARACTER="game.gamesrc.commands.cmdset.CharacterCmdSet"``
|
||||||
|
|
||||||
Evennia will now look for default commands in the ``DefaultCmdSet``
|
Evennia will now look for default commands in the ``CharacterCmdSet``
|
||||||
class of your newly copied module. You only need to do this once.
|
class of your newly copied module. You only need to do this once.
|
||||||
|
|
||||||
Creating a custom command
|
Creating a custom command
|
||||||
|
|
@ -45,6 +45,7 @@ Creating a custom command
|
||||||
|
|
||||||
# file game/gamesrc/commands/command.py
|
# file game/gamesrc/commands/command.py
|
||||||
#[...]
|
#[...]
|
||||||
|
from ev import default_cmds
|
||||||
class CmdEcho(default_cmds.MuxCommand):
|
class CmdEcho(default_cmds.MuxCommand):
|
||||||
"""
|
"""
|
||||||
Simple command example
|
Simple command example
|
||||||
|
|
@ -65,30 +66,30 @@ Creating a custom command
|
||||||
else:
|
else:
|
||||||
self.caller.msg("You gave the string: '%s'" % self.args)
|
self.caller.msg("You gave the string: '%s'" % self.args)
|
||||||
|
|
||||||
Adding the Command to a Cmdset
|
Adding the Command to a default Cmdset
|
||||||
------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
The command is not available to use until it is part of a Command Set.
|
The command is not available to use until it is part of a Command Set.
|
||||||
In this example we will go the easiest route and add it to the default
|
In this example we will go the easiest route and add it to the default
|
||||||
command set we already prepared.
|
Character command set we already prepared.
|
||||||
|
|
||||||
#. Edit your recently copied ``game/gamesrc/commands/cmdset.py``
|
#. Edit your recently copied ``game/gamesrc/commands/cmdset.py``
|
||||||
#. In this copied module you will find the ``DefaultCmdSet`` class
|
#. In this copied module you will find the ``DefaultCmdSet`` class
|
||||||
already imported and prepared for you. Import your new command module
|
already imported and prepared for you. Import your new command module
|
||||||
here with ``from game.gamesrc.commands.command import CmdEcho``.
|
here with ``from game.gamesrc.commands.command import CmdEcho``.
|
||||||
#. Add a line ``self.add(CmdEcho())`` to ``DefaultCmdSet``, in the
|
#. Add a line ``self.add(CmdEcho())`` to ``CharacterCmdSet``, in the
|
||||||
``at_cmdset_creation`` method (the template tells you where). This is
|
``at_cmdset_creation`` method (the template tells you where). This is
|
||||||
approximately how it should look at this point:
|
approximately how it should look at this point:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
# file gamesrc/commands/examples/cmdset.py
|
# file gamesrc/commands/cmdset.py
|
||||||
#[...]
|
#[...]
|
||||||
from game.gamesrc.commands.command import CmdEcho
|
from game.gamesrc.commands.command import CmdEcho
|
||||||
#[...]
|
#[...]
|
||||||
class DefaultCmdSet(default_cmds.DefaultCmdSet):
|
class CharacterCmdSet(default_cmds.CharacterCmdSet):
|
||||||
|
|
||||||
key = DefaultMUX
|
key = DefaultCharacter
|
||||||
|
|
||||||
def at_cmdset_creation(self):
|
def at_cmdset_creation(self):
|
||||||
|
|
||||||
|
|
@ -115,3 +116,73 @@ old one - it will overload the default one. Just remember that you must
|
||||||
|
|
||||||
See `Commands <Commands.html>`_ for many more details and possibilities
|
See `Commands <Commands.html>`_ for many more details and possibilities
|
||||||
when defining Commands and using Cmdsets in various ways.
|
when defining Commands and using Cmdsets in various ways.
|
||||||
|
|
||||||
|
Adding the command to specific object types
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
You do not *have* to expand the ``CharacterCmdSet``, it's just the
|
||||||
|
easiest example. The cmdset system is very generic. You can create your
|
||||||
|
own cmdsets and add them to objects as you please (just how to control
|
||||||
|
how they merge with the existing set is described in detail in the
|
||||||
|
[Commands#Command\_Sets Command Set documentation]).
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
# file gamesrc/commands/cmdset.py
|
||||||
|
#[...]
|
||||||
|
from game.gamesrc.commands.command import CmdEcho
|
||||||
|
#[...]
|
||||||
|
class MyCmdSet(default_cmds.CmdSet):
|
||||||
|
|
||||||
|
key = MyCmdSet
|
||||||
|
|
||||||
|
def at_cmdset_creation(self):
|
||||||
|
self.add(CmdEcho())
|
||||||
|
|
||||||
|
Now you just need to add this to an object. To test things (as
|
||||||
|
superuser) you can do
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
@py self.cmdset.add("cmdset.MyCmdSet")
|
||||||
|
|
||||||
|
This will add the cmdset (and the echo command) to yourself so you can
|
||||||
|
test it. This is not permanent though, if you do a ``@reload`` the
|
||||||
|
merger will be gone. You *can* add the ``permanent=True`` keyword to the
|
||||||
|
``cmdset.add`` call. This will however only make the new merged cmdset
|
||||||
|
permanent on that single object, not on other objects of that type,
|
||||||
|
which is usually what you want.
|
||||||
|
|
||||||
|
To make sure all new created objects get your new merged set, put the
|
||||||
|
``cmdset.add`` call in your custom `Typeclass <Typeclasses.html>`_'
|
||||||
|
``at_object_creation`` method:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
from ev import Object
|
||||||
|
class MyObject(Object):
|
||||||
|
|
||||||
|
def at_object_creation(self):
|
||||||
|
"called when the object is first created"
|
||||||
|
self.cmdset.add("cmdset.MyCmdSet")
|
||||||
|
|
||||||
|
|
||||||
|
All new objects of this typeclass will now start with this cmdset.
|
||||||
|
|
||||||
|
*Note:* An important caveat with this is that ``at_object_creation`` is
|
||||||
|
only called *once*, when the object is first created. This means that if
|
||||||
|
you already have existing objects in your databases using that
|
||||||
|
typeclass, they will not have been initiated the same way. There are
|
||||||
|
many ways to update them; since it's a one-time update you can usually
|
||||||
|
just simply loop through them. As superuser, try the following:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
@py [obj.cmdset.add("cmdset.MyCmdSet") for obj in
|
||||||
|
ev.managers.typeclass_search("game.gamesrc.objects.objects.mytypeclass.MyTypeClass"]
|
||||||
|
|
||||||
|
This goes through all objects in your database having the right
|
||||||
|
typeclass, adding the new cmdset to each. The good news is that you only
|
||||||
|
have to do this if you want to post-add cmdsets. If you just want to add
|
||||||
|
a new command, you can just add that command to the cmdset's
|
||||||
|
``at_cmdset_creation`` and @reload.
|
||||||
|
|
|
||||||
|
|
@ -66,16 +66,19 @@ that characters should not have the ability to pick up.
|
||||||
That's it. Below is a ``Heavy`` Typeclass that you could try. Note that
|
That's it. Below is a ``Heavy`` Typeclass that you could try. Note that
|
||||||
the `lock <Locks.html>`_ and `Attribute <Attribute.html>`_ here set in
|
the `lock <Locks.html>`_ and `Attribute <Attribute.html>`_ here set in
|
||||||
the typeclass could just as well have been set using commands in-game,
|
the typeclass could just as well have been set using commands in-game,
|
||||||
so this is a *very* simple example.
|
so this is a *very* simple example. We also add a custom
|
||||||
|
[Commands#Command\_Sets Command set] to it.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
# file game/gamesrc/objects/heavy.py
|
# file game/gamesrc/objects/heavy.py
|
||||||
from ev import Object
|
from ev import Object
|
||||||
|
# let's assume we defined our own cmdset earlier
|
||||||
|
from game.gamesrc.commands.mycmdsets import HeavySet
|
||||||
|
|
||||||
class Heavy(Object):
|
class Heavy(Object):
|
||||||
"Heavy object"
|
"Heavy object"
|
||||||
at_object_creation(self):
|
def at_object_creation(self):
|
||||||
"Called whenever a new object is created"
|
"Called whenever a new object is created"
|
||||||
# lock the object down by default
|
# lock the object down by default
|
||||||
self.locks.add("get:false()")
|
self.locks.add("get:false()")
|
||||||
|
|
@ -84,6 +87,8 @@ so this is a *very* simple example.
|
||||||
# this, you'd have to look at the code of the 'get' command to
|
# this, you'd have to look at the code of the 'get' command to
|
||||||
# find out).
|
# find out).
|
||||||
self.db.get_err_msg = "This is too heavy for you to pick up."
|
self.db.get_err_msg = "This is too heavy for you to pick up."
|
||||||
|
# expand the default cmdset with your own custom set (defined elsewhere)
|
||||||
|
self.cmdset.add(HeavySet)
|
||||||
|
|
||||||
Change Default Rooms, Exits, Character Typeclass
|
Change Default Rooms, Exits, Character Typeclass
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ Installation and Early Life
|
||||||
Customizing the server
|
Customizing the server
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
- `Changing the Settings <SettingsDefault.html>`_
|
||||||
- `Change Evennia's language <Internationalization.html>`_
|
- `Change Evennia's language <Internationalization.html>`_
|
||||||
- `Apache webserver configuration <ApacheConfig.html>`_ (optional)
|
- `Apache webserver configuration <ApacheConfig.html>`_ (optional)
|
||||||
- `Changing text encodings used by the server <TextEncodings.html>`_
|
- `Changing text encodings used by the server <TextEncodings.html>`_
|
||||||
|
|
@ -34,4 +35,5 @@ Working with Evennia
|
||||||
|
|
||||||
- `Setting up your work environment with version
|
- `Setting up your work environment with version
|
||||||
control <VersionControl.html>`_
|
control <VersionControl.html>`_
|
||||||
|
- `First steps coding with Evennia <FirstStepsCoding.html>`_
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,19 +62,84 @@ will for example delete an ``Attribute``:
|
||||||
|
|
||||||
del rose.db.has_thorns
|
del rose.db.has_thorns
|
||||||
|
|
||||||
Both ``db`` and ``ndb`` defaults to offering an ``all`` property on
|
Both ``db`` and ``ndb`` defaults to offering an ``all()`` method on
|
||||||
themselves. This returns all associated attributes or non-persistent
|
themselves. This returns all associated attributes or non-persistent
|
||||||
properties.
|
properties.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
list_of_all_rose_attributes = rose.db.all
|
list_of_all_rose_attributes = rose.db.all()
|
||||||
list_of_all_rose_ndb_attrs = rose.ndb.all
|
list_of_all_rose_ndb_attrs = rose.ndb.all()
|
||||||
|
|
||||||
If you use ``all`` as the name of an attribute, this will be used
|
If you use ``all`` as the name of an attribute, this will be used
|
||||||
instead. Later deleting your custom ``all`` will return the default
|
instead. Later deleting your custom ``all`` will return the default
|
||||||
behaviour.
|
behaviour.
|
||||||
|
|
||||||
|
Properties of Attributes
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
An Attribute object is stored in the database. It has the following
|
||||||
|
properties:
|
||||||
|
|
||||||
|
- ``key`` - the name of the Attribute. When doing e.g.
|
||||||
|
``obj.db.attrname = value``, this property is set to ``attrname``.
|
||||||
|
- ``value`` - this is the value of the Attribute. This value can be
|
||||||
|
anything which can be pickled - objects, lists, numbers or what have
|
||||||
|
you (see
|
||||||
|
[Attributes#What\_types\_of\_data\_can\_I\_save\_in\_an\_Attribute
|
||||||
|
this section] for more info). In the example
|
||||||
|
``obj.db.attrname = value``, the ``value`` is stored here.
|
||||||
|
- ``category`` - this is an optional property that is set to None for
|
||||||
|
most Attributes. Setting this allows to use Attributes for different
|
||||||
|
functionality. This is usually not needed unless you want to use
|
||||||
|
Attributes for very different functionality (`Nicks <Nicks.html>`_ is
|
||||||
|
an example of using Attributes in this way). To modify this property
|
||||||
|
you need to use the [Attributes#The\_Attribute\_Handler Attribute
|
||||||
|
Handler].
|
||||||
|
- ``strvalue`` - this is a separate value field that only accepts
|
||||||
|
strings. This severaly limits the data possible to store, but allows
|
||||||
|
for easier database lookups. This property is usually not used except
|
||||||
|
when re-using Attributes for some other purpose
|
||||||
|
(`Nicks <Nicks.html>`_ use it). It is only accessible via the
|
||||||
|
[Attributes#The\_Attribute\_Handler Attribute Handler].
|
||||||
|
|
||||||
|
Non-database attributes have no equivalence to category nor strvalue.
|
||||||
|
|
||||||
|
The Attribute Handler
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The Attribute handler is what is used under the hood to manage the
|
||||||
|
Attributes on an object. It is accessible as ``obj.attributes``. For
|
||||||
|
most operations, the ``db`` or ``ndb`` wrappers are enough. But
|
||||||
|
sometimes you won't know the attribute name beforehand or you need to
|
||||||
|
manipulate your Attributes in more detail. The Attribute handler has the
|
||||||
|
following methods (the argument lists are mostly shortened; you can see
|
||||||
|
the full call signatures in ``src.typeclasses.models``):
|
||||||
|
|
||||||
|
- ``attributes.has(...)`` - this checks if the object has an Attribute
|
||||||
|
with this key. This is equivalent to doing ``obj.db.key``.
|
||||||
|
- ``get(...)`` - this retrieves the given Attribute. Normally the
|
||||||
|
``value`` property of the Attribute is returned, but the method takes
|
||||||
|
keywords for returning the Attribute object itself. By supplying an
|
||||||
|
``accessing_object`` oto the call one can also make sure to check
|
||||||
|
permissions before modifying anything.
|
||||||
|
- ``add(...)`` - this adds a new Attribute to the object. An optional
|
||||||
|
`lockstring <Locks.html>`_ can be supplied here to restrict future
|
||||||
|
access and also the call itself may be checked against locks.
|
||||||
|
- ``remove(...)`` - Remove the given Attribute. This can optionally be
|
||||||
|
made to check for permission before performing the deletion.
|
||||||
|
- ``clear(...)`` - removes all Attributes from object.
|
||||||
|
- ``all(...)`` - returns all Attributes (of the given category)
|
||||||
|
attached to this object.
|
||||||
|
|
||||||
|
See [Attributes#Locking\_and\_checking\_Attributes this section] for
|
||||||
|
more about locking down Attribute access and editing.
|
||||||
|
|
||||||
|
There is an equivalent ``nattribute`` handler for managing non-database
|
||||||
|
Attributes. This has the same methods but is much simpler since it does
|
||||||
|
not concern itself with category nor strvalue. It also offers no concept
|
||||||
|
of access control.
|
||||||
|
|
||||||
Persistent vs non-persistent
|
Persistent vs non-persistent
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
|
|
@ -248,15 +313,15 @@ are specified `here <Locks.html>`_. The relevant lock types are
|
||||||
- *attrread* - limits who may read the value of the Attribute
|
- *attrread* - limits who may read the value of the Attribute
|
||||||
- *attredit* - limits who may set/change this Attribute
|
- *attredit* - limits who may set/change this Attribute
|
||||||
|
|
||||||
You cannot use e.g. ``obj.db.attrname`` handler to modify Attribute
|
You cannot use the ``db`` handler to modify Attribute object (such as
|
||||||
objects (such as setting a lock on them - you will only get the
|
setting a lock on them) - The ``db`` handler will return the Attribute's
|
||||||
Attribute *value* that way, not the actual Attribute *object*. You get
|
*value*, not the Attribute object itself. Instead you use
|
||||||
the latter with ``get_attribute_obj`` (see next section) which allows
|
``get_attribute_obj`` (see next section) which allows you to set the
|
||||||
you to set the lock something like this:
|
lock something like this:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
obj.get_attribute_obj.locks.add("attread:all();attredit:perm(Wizards)")
|
obj.attributes.get("myattr", return_obj=True).locks.add("attread:all();attredit:perm(Wizards)")
|
||||||
|
|
||||||
A lock is no good if nothing checks it -- and by default Evennia does
|
A lock is no good if nothing checks it -- and by default Evennia does
|
||||||
not check locks on Attributes. You have to add a check to your
|
not check locks on Attributes. You have to add a check to your
|
||||||
|
|
@ -266,60 +331,12 @@ commands/code wherever it fits (such as before setting an Attribute).
|
||||||
|
|
||||||
# in some command code where we want to limit
|
# in some command code where we want to limit
|
||||||
# setting of a given attribute name on an object
|
# setting of a given attribute name on an object
|
||||||
attr = obj.get_attribute_obj(attrname, default=None)
|
attr = obj.attributes.get(attrname, return_obj=True, accessing_obj=caller, default=None, default_access=False)
|
||||||
if not (attr and attr.locks.check(caller, 'attredit', default=True)):
|
if not attr:
|
||||||
caller.msg("You cannot edit that Attribute!")
|
caller.msg("You cannot edit that Attribute!")
|
||||||
return
|
return
|
||||||
# edit the Attribute here
|
# edit the Attribute here
|
||||||
|
|
||||||
Note that in this example this lock check will default to ``True`` if no
|
The same keywords are available to use with ``obj.attributes.set()`` and
|
||||||
lock was defined on the Attribute (which is the normal case). You can
|
``obj.attributes.remove()``, those will check for the *attredit* lock
|
||||||
set this to False if you know all your Attributes always check access in
|
type.
|
||||||
all situations. If you want some special control over what the default
|
|
||||||
Attribute access is (such as allowing everyone to view, but never
|
|
||||||
allowing anyone to edit unless explicitly allowing it with a lock), you
|
|
||||||
can use the ``secure_attr`` method on Typeclassed objects like this:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
obj.secure_attr(caller, attrname, value=None,
|
|
||||||
delete=False,
|
|
||||||
default_access_read=True,
|
|
||||||
default_access_edit=False,
|
|
||||||
default_access_create=True)
|
|
||||||
|
|
||||||
The secure\_attr will try to retrieve the attribute value of an existing
|
|
||||||
Attribute if the ``value`` keyword is not set and create/set/delete it
|
|
||||||
otherwise. The *default\_access* keywords specify what should be the
|
|
||||||
default policy for each operation if no appropriate lock string is set
|
|
||||||
on the Attribute.
|
|
||||||
|
|
||||||
Other ways to access Attributes
|
|
||||||
-------------------------------
|
|
||||||
|
|
||||||
Normally ``db`` is all you need. But there there are also several other
|
|
||||||
ways to access information about Attributes, some of which cannot be
|
|
||||||
replicated by ``db``. These are available on all Typeclassed objects:
|
|
||||||
|
|
||||||
- ``has_attribute(attrname)`` - checks if the object has an attribute
|
|
||||||
with the given name. This is equivalent to doing ``obj.db.attrname``.
|
|
||||||
- ``set_attribute(attrname, value)`` - equivalent to
|
|
||||||
``obj.db.attrname = value``.
|
|
||||||
- ``get_attribute(attrname)`` - returns the attribute value. Equivalent
|
|
||||||
to ``obj.db.attrname``.
|
|
||||||
- ``get_attribute_raise(attrname)`` - returns the attribute value, but
|
|
||||||
instead of returning ``None`` if no such attribute is found, this
|
|
||||||
method raises ``AttributeError``.
|
|
||||||
- ``get_attribute_obj(attrname)`` - returns the attribute *object*
|
|
||||||
itself rather than the value stored in it.
|
|
||||||
- ``del_attribute(attrname)`` - equivalent to ``del obj.db.attrname``.
|
|
||||||
Quietly fails if ``attrname`` is not found.
|
|
||||||
- ``del_attribute_raise(attrname)`` - deletes attribute, raising
|
|
||||||
``AttributeError`` if no matching Attribute is found.
|
|
||||||
- ``get_all_attributes`` - equivalent to ``obj.db.all``
|
|
||||||
- ``attr(attrname, value=None, delete=False)`` - this is a convenience
|
|
||||||
function for getting, setting and deleting Attributes. It's
|
|
||||||
recommended to use ``db`` instead.
|
|
||||||
- ``secure_attr(...)`` - lock-checking version of ``attr``. See example
|
|
||||||
in previous section.
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ To temporarily step down from your superuser position you can use the
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
@quell
|
> @quell
|
||||||
|
|
||||||
This will make you start using the permission of your current
|
This will make you start using the permission of your current
|
||||||
`Character <Objects.html>`_ instead of your superuser level. If you
|
`Character <Objects.html>`_ instead of your superuser level. If you
|
||||||
|
|
@ -64,19 +64,18 @@ rather short name, let's is give a few aliases.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
> @name box = very large box;box;very;bo;crate
|
> @name box = very large box;box;very;crate
|
||||||
|
|
||||||
We now actually renamed the box to *very large box* (and this is what we
|
We now actually renamed the box to *very large box* (and this is what we
|
||||||
will see when looking at the room), but we will also recognize it by any
|
will see when looking at it), but we will also recognize it by any of
|
||||||
of the other names we give - like *crate* or simply *box* as before. We
|
the other names we give - like *crate* or simply *box* as before. We
|
||||||
could have given these aliases directly after the name in the
|
could have given these aliases directly after the name in the
|
||||||
``@create`` command, this is true for all creation commands - you can
|
``@create`` command, this is true for all creation commands - you can
|
||||||
always tag on a list of ;-separated aliases to the name of your new
|
always tag on a list of ;-separated aliases to the name of your new
|
||||||
object. If you had wanted to not change the name itself, but to only add
|
object. If you had wanted to not change the name itself, but to only add
|
||||||
aliases, you could have used the ``@alias`` command.
|
aliases, you could have used the ``@alias`` command.
|
||||||
|
|
||||||
We are currently carrying the box, which you can see if you give the
|
We are currently carrying the box. Let's drop it.
|
||||||
command ``inventory`` (or ``i``). Let's drop it.
|
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
|
@ -118,8 +117,7 @@ box was dropped in the room, then try this:
|
||||||
Locks are a rather `big topic <Locks.html>`_, but for now that will do
|
Locks are a rather `big topic <Locks.html>`_, but for now that will do
|
||||||
what we want. This will lock the box so noone can lift it. The exception
|
what we want. This will lock the box so noone can lift it. The exception
|
||||||
is superusers, they override all locks and will pick it up anyway. Make
|
is superusers, they override all locks and will pick it up anyway. Make
|
||||||
sure you are using your builder account and not the superuser account
|
sure you are quelling your superuser powers and try to get the box now:
|
||||||
and try to get the box now:
|
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
|
@ -134,7 +132,7 @@ attributes using the ``@set`` command:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
> @set box/get_err_msg = The box is way too heavy for you to lift.
|
> @set box/get_err_msg = It's way too heavy for you to lift.
|
||||||
|
|
||||||
Try to get it now and you should see a nicer error message echoed back
|
Try to get it now and you should see a nicer error message echoed back
|
||||||
to you.
|
to you.
|
||||||
|
|
@ -178,7 +176,7 @@ Pushing your buttons
|
||||||
|
|
||||||
If we get back to the box we made, there is only so much fun you can do
|
If we get back to the box we made, there is only so much fun you can do
|
||||||
with it at this point. It's just a dumb generic object. If you renamed
|
with it at this point. It's just a dumb generic object. If you renamed
|
||||||
it ``carpet`` and changed its description noone would be the wiser.
|
it to ``stone`` and changed its description noone would be the wiser.
|
||||||
However, with the combined use of custom
|
However, with the combined use of custom
|
||||||
`Typeclasses <Typeclasses.html>`_, `Scripts <Scripts.html>`_ and
|
`Typeclasses <Typeclasses.html>`_, `Scripts <Scripts.html>`_ and
|
||||||
object-based `Commands <Commands.html>`_, you could expand it and other
|
object-based `Commands <Commands.html>`_, you could expand it and other
|
||||||
|
|
@ -201,7 +199,7 @@ Python except Evennia defaults to looking in ``game/gamesrc/objects/``
|
||||||
so you don't have to write the full path every time. There you go - one
|
so you don't have to write the full path every time. There you go - one
|
||||||
red button.
|
red button.
|
||||||
|
|
||||||
The RedButton is an example object intended to show off many of
|
The RedButton is an example object intended to show off a few of
|
||||||
Evennia's features. You will find that the `Scripts <Scripts.html>`_ and
|
Evennia's features. You will find that the `Scripts <Scripts.html>`_ and
|
||||||
`Commands <Commands.html>`_ controlling it are scattered in
|
`Commands <Commands.html>`_ controlling it are scattered in
|
||||||
``examples``-folders all across ``game/gamesrc/``.
|
``examples``-folders all across ``game/gamesrc/``.
|
||||||
|
|
@ -210,8 +208,8 @@ If you wait for a while (make sure you dropped it!) the button will
|
||||||
blink invitingly. Why don't you try to push it ...? Surely a big red
|
blink invitingly. Why don't you try to push it ...? Surely a big red
|
||||||
button is meant to be pushed. You know you want to.
|
button is meant to be pushed. You know you want to.
|
||||||
|
|
||||||
Creating a room called 'house'
|
Making yourself a house
|
||||||
------------------------------
|
-----------------------
|
||||||
|
|
||||||
The main command for shaping the game world is ``@dig``. For example, if
|
The main command for shaping the game world is ``@dig``. For example, if
|
||||||
you are standing in Limbo you can dig a route to your new house location
|
you are standing in Limbo you can dig a route to your new house location
|
||||||
|
|
@ -240,8 +238,7 @@ This will create a new room "cliff" with an exit "southwest" leading
|
||||||
there and a path "northeast" leading back from the cliff to your current
|
there and a path "northeast" leading back from the cliff to your current
|
||||||
location.
|
location.
|
||||||
|
|
||||||
You can create exits from anywhere at any time using the ``@open``
|
You can create new exits from where you are using the ``@open`` command:
|
||||||
command:
|
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
|
@ -251,9 +248,9 @@ This opens an exit ``north`` to the previously created room ``house``.
|
||||||
|
|
||||||
If you have many rooms named ``house`` you will get a list of matches
|
If you have many rooms named ``house`` you will get a list of matches
|
||||||
and have to select which one you want to link to. You can also give its
|
and have to select which one you want to link to. You can also give its
|
||||||
database ref number, which is unique to every object. This can be found
|
database (#dbref) number, which is unique to every object. This can be
|
||||||
with the ``examine`` command or by looking at the latest constructions
|
found with the ``examine`` command or by looking at the latest
|
||||||
with ``@objects``.
|
constructions with ``@objects``.
|
||||||
|
|
||||||
Follow the north exit to your 'house' or ``@teleport`` to it:
|
Follow the north exit to your 'house' or ``@teleport`` to it:
|
||||||
|
|
||||||
|
|
@ -276,37 +273,46 @@ To manually open an exit back to Limbo (if you didn't do so with the
|
||||||
|
|
||||||
(or give limbo's dbref which is #2)
|
(or give limbo's dbref which is #2)
|
||||||
|
|
||||||
Finding and manipulating existing objects
|
Reshuffling the world
|
||||||
-----------------------------------------
|
---------------------
|
||||||
|
|
||||||
To re-point an exit at another room or object, you can use
|
You can find things using the ``@find`` command. Assuming you are back
|
||||||
|
at ``Limbo``, let's teleport the *large box to our house*.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
> @link <room name> = <new_target name>
|
> @teleport box = house
|
||||||
|
very large box is leaving Limbo, heading for house.
|
||||||
|
Teleported very large box -> house.
|
||||||
|
|
||||||
To find something, use
|
We can still find the box by using @find:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
> @find <name>
|
> @find box
|
||||||
|
One Match(#1-#8):
|
||||||
|
very large box(#8) - src.objects.objects.Object
|
||||||
|
|
||||||
This will return a list of dbrefs that have a similar name.
|
Knowing the #dbref of the box (#8 in this example), you can grab the box
|
||||||
|
and get it back here without actually yourself going to ``house`` first:
|
||||||
To teleport something somewhere, one uses
|
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
> @teleport <object> = <destination>
|
> @teleport #8 = here
|
||||||
|
|
||||||
To destroy something existing, use
|
(You can usually use ``here`` to refer to your current location. To
|
||||||
|
refer to yourself you can use ``self`` or ``me``). The box should now be
|
||||||
|
back in Limbo with you.
|
||||||
|
|
||||||
|
We are getting tired of the box. Let's destroy it.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
> @destroy <object>
|
> @destroy box
|
||||||
|
|
||||||
You can destroy many objects in one go by giving a comma-separated list
|
You can destroy many objects in one go by giving a comma-separated list
|
||||||
of objects to the command.
|
of objects (or their #dbrefs, if they are not in the same location) to
|
||||||
|
the command.
|
||||||
|
|
||||||
Adding a help entry
|
Adding a help entry
|
||||||
-------------------
|
-------------------
|
||||||
|
|
@ -322,16 +328,27 @@ command.
|
||||||
Adding a World
|
Adding a World
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
Evennia comes with a tutorial world for you to build. To build this you
|
After this brief introduction to building you may be ready to see a more
|
||||||
need to log back in as *superuser*. Place yourself in Limbo and do:
|
fleshed-out example. Evennia comes with a tutorial world for you to
|
||||||
|
explore.
|
||||||
|
|
||||||
|
First you need to switch back to *superuser* by using the ``@unquell``
|
||||||
|
command. Next, place yourself in ``Limbo`` and run the following
|
||||||
|
command:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
@batchcommand contrib.tutorial_world.build
|
> @batchcommand contrib.tutorial_world.build
|
||||||
|
|
||||||
This will take a while, but you will see a lot of messages as the world
|
This will take a while (be patient and don't re-run the command). You
|
||||||
is built for you. You will end up with a new exit from Limbo named
|
will see all the commands used to build the world scroll by as the world
|
||||||
*tutorial*. See more info about the tutorial world
|
is built for you.
|
||||||
`here <TutorialWorldIntroduction.html>`_. Read
|
|
||||||
``contrib/tutorial_world/build.ev`` to see exactly how it's built, step
|
You will end up with a new exit from Limbo named *tutorial*. Apart from
|
||||||
by step.
|
being a little solo-adventure in its own right, the tutorial world is a
|
||||||
|
good source for learning Evennia building (and coding).
|
||||||
|
|
||||||
|
Read
|
||||||
|
`contrib/tutorial\_world/build.ev <https://code.google.com/p/evennia/source/browse/contrib/tutorial_world/build.ev>`_
|
||||||
|
to see exactly how it's built, step by step. See also more info about
|
||||||
|
the tutorial world `here <TutorialWorldIntroduction.html>`_.
|
||||||
|
|
|
||||||
|
|
@ -60,8 +60,8 @@ clean the idmapper cache, the safest way is therefore a soft-reload of
|
||||||
the server (via e.g. the ``@reload`` command).
|
the server (via e.g. the ``@reload`` command).
|
||||||
|
|
||||||
Most developers will not need to care with the idmapper cache - it just
|
Most developers will not need to care with the idmapper cache - it just
|
||||||
makes models work intuitively. It is visible mostly in that all database
|
makes models work intuitively. It is visible mostly in that many
|
||||||
models in Evennia inherits from
|
database models in Evennia inherit from
|
||||||
``src.utils.idmapper.models.SharedMemoryModel``.
|
``src.utils.idmapper.models.SharedMemoryModel``.
|
||||||
|
|
||||||
On-object variable cache
|
On-object variable cache
|
||||||
|
|
@ -95,24 +95,6 @@ latter will give an invalid-field error. If you use Evennia's own search
|
||||||
methods you don't need to worry about this, they look for the right
|
methods you don't need to worry about this, they look for the right
|
||||||
things behind the scenes for you.
|
things behind the scenes for you.
|
||||||
|
|
||||||
Mutable variable caches
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Some object properties may appear mutable - that is, they return lists.
|
|
||||||
One such example is the ``permissions`` property. This is however not
|
|
||||||
actually a list - it's just a handler that *returns* and *accepts*
|
|
||||||
lists. ``db_permissions`` is actually stored as a comma-separated
|
|
||||||
string. The uptake of this is that you cannot do list operations on the
|
|
||||||
handler. So ``obj.permissions.append('Immortals')`` will not work.
|
|
||||||
Rather, you will have to do such operations on what is returned. Like
|
|
||||||
this:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
perms = obj.permissions # this returns a list!
|
|
||||||
perms.append("Immortals")
|
|
||||||
obj.permissions = perms # overwrites with new list
|
|
||||||
|
|
||||||
Content cache
|
Content cache
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
@ -162,6 +144,8 @@ as fast as accessing any normal python property - this removes the
|
||||||
necessity for subsequent database look-ups in order to retrieve
|
necessity for subsequent database look-ups in order to retrieve
|
||||||
attributes. Both ``db`` and ``ndn`` work the same way in this regard.
|
attributes. Both ``db`` and ``ndn`` work the same way in this regard.
|
||||||
|
|
||||||
Apart from the lookup, each Attribute object itself caches the values
|
Due to the possibility of storing objects in Attributes, the system
|
||||||
stored in it. Again this means that (after the first time) accessing an
|
cannot cache the value of data stored in the Attribute (this would allow
|
||||||
attribute is equivalent to accessing any normal Python property.
|
for the system not detecting a stored Object being deleted elsewhere -
|
||||||
|
it would still be accessible from the Attribute). So having to re-access
|
||||||
|
such objects every load does incur a minor speed penalty.
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
*This tutorial requires that you first well understand how
|
||||||
|
`Commands <Commands.html>`_ work.*
|
||||||
|
|
||||||
Cooldowns
|
Cooldowns
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -7,7 +7,9 @@ system. Stock evennia implements a 'MUX-like' system of channels, but
|
||||||
there is nothing stopping you from changing things to better suit your
|
there is nothing stopping you from changing things to better suit your
|
||||||
taste.
|
taste.
|
||||||
|
|
||||||
Comms rely on two main database objects - ``Msg`` and ``Channel``.
|
Comms rely on two main database objects - ``Msg`` and ``Channel``. There
|
||||||
|
is also the ``TempMsg`` which mimics the API of a ``Msg`` but has no
|
||||||
|
connection to the database.
|
||||||
|
|
||||||
Msg
|
Msg
|
||||||
---
|
---
|
||||||
|
|
@ -67,10 +69,15 @@ next section).
|
||||||
Channels
|
Channels
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
Channels are `Typeclassed <Typeclass.html>`_ entities, which mean they
|
||||||
|
can be easily extended and their functionality modified. To change which
|
||||||
|
channel typeclass Evennia uses, change
|
||||||
|
settings.BASE\_CHANNEL\_TYPECLASS.
|
||||||
|
|
||||||
Channels act as generic distributors of messages. Think of them as
|
Channels act as generic distributors of messages. Think of them as
|
||||||
"switch boards" redistributing ``Msg`` objects. Internally they hold a
|
"switch boards" redistributing ``Msg`` objects. Internally they hold a
|
||||||
list of "listening" objects and any ``Msg`` sent to the channel will be
|
list of "listening" objects and any ``Msg`` (or ``TempMsg`` sent to the
|
||||||
distributed out to all channel listeners. Channels have
|
channel will be distributed out to all channel listeners. Channels have
|
||||||
`Locks <Locks.html>`_ to limit who may listen and/or send messages
|
`Locks <Locks.html>`_ to limit who may listen and/or send messages
|
||||||
through them.
|
through them.
|
||||||
|
|
||||||
|
|
@ -92,11 +99,12 @@ methods of channels:
|
||||||
|
|
||||||
channel.msg(msgobj, header=None, senders=None, persistent=True)
|
channel.msg(msgobj, header=None, senders=None, persistent=True)
|
||||||
|
|
||||||
The argument ``msgobj`` can be a previously constructed ``Msg`` or
|
The argument ``msgobj`` can be either a string, a previously constructed
|
||||||
``TempMsg`` - in that case all the following keywords are ignored. If
|
``Msg`` or a ``TempMsg`` - in the latter cases all the following
|
||||||
``msgobj`` is a string, the other keywords are used for creating a new
|
keywords are ignored. If ``msgobj`` is a string, the other keywords are
|
||||||
``Msg`` or ``TempMsg`` on the fly, depending on if ``persistent`` is set
|
used for creating a new ``Msg`` or ``TempMsg`` on the fly, depending on
|
||||||
or not.
|
if ``persistent`` is set or not. Default is to use ``TempMsg`` for
|
||||||
|
channel communication (i.e. not save everything to the database).
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
|
@ -108,18 +116,13 @@ or not.
|
||||||
# use the Msg object directly, no other keywords are needed
|
# use the Msg object directly, no other keywords are needed
|
||||||
mychan.msg(mymsg)
|
mychan.msg(mymsg)
|
||||||
|
|
||||||
# create a Msg automatically behind the scenes
|
# Send a non-persistent message to a channel
|
||||||
mychan.msg("Hello!", senders=[sender])
|
mychan.msg("Hello!", senders=[sender])
|
||||||
|
|
||||||
# send a non-persistent TempMsg (note that the senders
|
# send a message to list, save it to the database
|
||||||
# keyword can also be used without a list if there is
|
# (note how the senders keyword can also be used
|
||||||
# only one sender)
|
# without a list if there is only one sender)
|
||||||
mychan.msg("Hello!", senders=sender, persistent=False)
|
mychan.msg("Hello!", senders=sender, persistent=True)
|
||||||
|
|
||||||
# this is a shortcut that always sends a non-persistent TempMsg
|
|
||||||
# also if a full Msg was supplied to it (it also creates TempMsgs
|
|
||||||
# on the fly if given a string).
|
|
||||||
mychan.tempmsg(mymsg)
|
|
||||||
|
|
||||||
On a more advanced note, when a player enters something like
|
On a more advanced note, when a player enters something like
|
||||||
``ooc Hello!`` (where ``ooc`` is the name/alias of a channel), this is
|
``ooc Hello!`` (where ``ooc`` is the name/alias of a channel), this is
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,12 @@ do this once):
|
||||||
|
|
||||||
Once you have an online clone and a local copy of it:
|
Once you have an online clone and a local copy of it:
|
||||||
|
|
||||||
|
#. Make sure that you have edited Mercurial's config file (``hgrc``) and
|
||||||
|
under the header ``[ui]`` added the line
|
||||||
|
``username=Yourname <your email>``. This is important for proper
|
||||||
|
crediting and eventual conversions. See the first point of the
|
||||||
|
`Mercurial
|
||||||
|
Quickstart <http://mercurial.selenic.com/wiki/QuickStart>`_.
|
||||||
#. Code away on your computer, fixing bugs or whatnot (you can be
|
#. Code away on your computer, fixing bugs or whatnot (you can be
|
||||||
offline for this). Commit your code to your local clone as you work,
|
offline for this). Commit your code to your local clone as you work,
|
||||||
as often as you like. There are some suggestions for setting up a
|
as often as you like. There are some suggestions for setting up a
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -26,6 +26,7 @@ General Evennia development information
|
||||||
- `Setting up a Mercurial environment for
|
- `Setting up a Mercurial environment for
|
||||||
coding <VersionControl.html>`_
|
coding <VersionControl.html>`_
|
||||||
- `Planning your own Evennia game <GamePlanning.html>`_
|
- `Planning your own Evennia game <GamePlanning.html>`_
|
||||||
|
- `First steps coding Evennia <FirstStepsCoding.html>`_
|
||||||
|
|
||||||
Evennia Component Documentation
|
Evennia Component Documentation
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
@ -34,21 +35,25 @@ Evennia Component Documentation
|
||||||
|
|
||||||
- `Directory Overview <DirectoryOverview.html>`_
|
- `Directory Overview <DirectoryOverview.html>`_
|
||||||
- `Portal and Server <PortalAndServer.html>`_
|
- `Portal and Server <PortalAndServer.html>`_
|
||||||
|
- `Session <Session.html>`_
|
||||||
- `Commands <Commands.html>`_
|
- `Commands <Commands.html>`_
|
||||||
- `Typeclass system <Typeclasses.html>`_
|
- `Typeclass system <Typeclasses.html>`_
|
||||||
|
|
||||||
- `Objects <Objects.html>`_
|
- `Objects <Objects.html>`_
|
||||||
- `Scripts <Scripts.html>`_
|
- `Scripts <Scripts.html>`_
|
||||||
- `Players <Players.html>`_
|
- `Players <Players.html>`_
|
||||||
|
- [Communications#Channels Channels]
|
||||||
- `Attributes <Attributes.html>`_
|
- `Attributes <Attributes.html>`_
|
||||||
|
|
||||||
- `Locks and Permissions <Locks.html>`_
|
- `Locks and Permissions <Locks.html>`_
|
||||||
- `Communications <Communications.html>`_
|
- `Communications <Communications.html>`_
|
||||||
- `Help System <HelpSystem.html>`_
|
- `Help System <HelpSystem.html>`_
|
||||||
- `Nicks <Nicks.html>`_
|
- `Nicks <Nicks.html>`_
|
||||||
|
- `Tags <Tags.html>`_
|
||||||
- `Sessions and Protocols <SessionProtocols.html>`_
|
- `Sessions and Protocols <SessionProtocols.html>`_
|
||||||
- `Caches <Caches.html>`_
|
- `Caches <Caches.html>`_
|
||||||
- `Web features <WebFeatures.html>`_
|
- `Web features <WebFeatures.html>`_
|
||||||
|
- `Out-of-band communication <OOB.html>`_
|
||||||
- `Configuration and module plugins <ServerConf.html>`_
|
- `Configuration and module plugins <ServerConf.html>`_
|
||||||
|
|
||||||
Programming Evennia
|
Programming Evennia
|
||||||
|
|
@ -59,6 +64,7 @@ Programming Evennia
|
||||||
- `Useful coding utilities <CodingUtils.html>`_
|
- `Useful coding utilities <CodingUtils.html>`_
|
||||||
- `Running and writing unit tests for Evennia <UnitTesting.html>`_
|
- `Running and writing unit tests for Evennia <UnitTesting.html>`_
|
||||||
- `Running processes asynchronously <AsyncProcess.html>`_
|
- `Running processes asynchronously <AsyncProcess.html>`_
|
||||||
|
- `Expanding Evennia with new database models <NewModels.html>`_
|
||||||
|
|
||||||
Work in Progress - Developer brainstorms and whitepages
|
Work in Progress - Developer brainstorms and whitepages
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
|
@ -70,6 +76,5 @@ the road.*
|
||||||
- `Basic game system implementation <WorkshopDefaultGame.html>`_
|
- `Basic game system implementation <WorkshopDefaultGame.html>`_
|
||||||
(inactive)
|
(inactive)
|
||||||
- `Rtclient protocol <Workshop.html>`_ (deprecated)
|
- `Rtclient protocol <Workshop.html>`_ (deprecated)
|
||||||
- `Summary of changes <EvenniaDevel.html>`_ of latest version vs old
|
- `Change log <EvenniaDevel.html>`_ of big Evennia updates over time
|
||||||
Evennia (implemented in aug2010)
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -188,6 +188,7 @@ or features missing, file a bug report or send us a message.
|
||||||
players/
|
players/
|
||||||
scripts/
|
scripts/
|
||||||
server/
|
server/
|
||||||
|
portal/
|
||||||
typeclasses/
|
typeclasses/
|
||||||
utils/
|
utils/
|
||||||
web/
|
web/
|
||||||
|
|
@ -277,10 +278,10 @@ connection timeouts) are also defined here.
|
||||||
~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
This directory is the heart of Evennia. It holds the server process
|
This directory is the heart of Evennia. It holds the server process
|
||||||
itself (started from ``game/evennia.py``), the portal and all `sessions
|
itself (started from ``game/evennia.py``). Its subfolder ``portal/``
|
||||||
and protocols <SessionProtocols.html>`_ that allow users to connect to
|
holds the portal and all `sessions and
|
||||||
the game. It also knows how to store dynamic server info in the
|
protocols <SessionProtocols.html>`_ that allow users to connect to the
|
||||||
database.
|
game.
|
||||||
|
|
||||||
\`src/typeclasses/\`
|
\`src/typeclasses/\`
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -17,14 +17,15 @@ Quick start
|
||||||
For you who are extremely impatient, here's the gist of getting a
|
For you who are extremely impatient, here's the gist of getting a
|
||||||
vanilla Evennia install running.
|
vanilla Evennia install running.
|
||||||
|
|
||||||
#. *Get the pre-requisites (Python, Django, Twisted and Mercurial)*.
|
#. *Get the pre-requisites (Python, Django, Twisted, South and
|
||||||
|
Mercurial)*.
|
||||||
#. *Start a command terminal/dos prompt and change directory to where
|
#. *Start a command terminal/dos prompt and change directory to where
|
||||||
you want to have your 'evennia' folder appear*.
|
you want to have your 'evennia' folder appear*.
|
||||||
#. ``hg clone https://code.google.com/p/evennia/ evennia``
|
#. ``hg clone https://code.google.com/p/evennia/ evennia``
|
||||||
#. *Change directory to evennia/game*.
|
#. *Change directory to evennia/game*.
|
||||||
#. ``python manage.py``
|
#. ``python manage.py``
|
||||||
#. ``python manage.py syncdb``
|
#. ``python manage.py syncdb``
|
||||||
#. ``python manage.py migrate`` (only if using South)
|
#. ``python manage.py migrate``
|
||||||
#. ``python evennia.py -i start``
|
#. ``python evennia.py -i start``
|
||||||
|
|
||||||
Evennia should now be running and you can connect to it by pointing a
|
Evennia should now be running and you can connect to it by pointing a
|
||||||
|
|
@ -40,7 +41,7 @@ As far as operating systems go, any system with Python support should
|
||||||
work.
|
work.
|
||||||
|
|
||||||
- Linux/Unix
|
- Linux/Unix
|
||||||
- Windows (2000, XP, Vista, Win7)
|
- Windows (2000, XP, Vista, Win7, Win8)
|
||||||
- Mac OSX (>=10.5 recommended)
|
- Mac OSX (>=10.5 recommended)
|
||||||
|
|
||||||
If you run into problems, or have success running Evennia on another
|
If you run into problems, or have success running Evennia on another
|
||||||
|
|
@ -55,19 +56,19 @@ Evennia:
|
||||||
`ActivePython <http://www.activestate.com/activepython/downloads>`_
|
`ActivePython <http://www.activestate.com/activepython/downloads>`_
|
||||||
instead.
|
instead.
|
||||||
|
|
||||||
- **`Twisted <http://twistedmatrix.com>`_** (v10.0+)
|
- **`Twisted <http://twistedmatrix.com>`_** (v11.0+)
|
||||||
|
|
||||||
- `ZopeInterface <http://www.zope.org/Products/ZopeInterface>`_
|
- `ZopeInterface <http://www.zope.org/Products/ZopeInterface>`_
|
||||||
(v3.0+) - usually included in Twisted packages
|
(v3.0+) - usually included in Twisted packages
|
||||||
- Windows users might also need
|
- Windows users might also need
|
||||||
`pywin32 <http://sourceforge.net/projects/pywin32>`_.
|
`pywin32 <http://sourceforge.net/projects/pywin32>`_.
|
||||||
|
|
||||||
- **`Django <http://www.djangoproject.com>`_** (v1.4+)
|
- **`Django <http://www.djangoproject.com>`_** (v1.5+)
|
||||||
|
|
||||||
- `PIL <http://www.pythonware.com/products/pil>`_ (Python Image
|
- `PIL <http://www.pythonware.com/products/pil>`_ (Python Image
|
||||||
Library) - often distributed with Django.
|
Library) - often distributed with Django.
|
||||||
|
|
||||||
- **`South <http://south.aeracode.org/>`_** (v0.7+)
|
- **`South <http://south.aeracode.org/>`_** (v0.8+)
|
||||||
|
|
||||||
- South is used to track and apply changes to the database's
|
- South is used to track and apply changes to the database's
|
||||||
structure.
|
structure.
|
||||||
|
|
@ -145,22 +146,14 @@ Optional:
|
||||||
problems compiling the ``PIL`` library on Mac, it's however not
|
problems compiling the ``PIL`` library on Mac, it's however not
|
||||||
strictly required in order to use Django (it's used for images).
|
strictly required in order to use Django (it's used for images).
|
||||||
|
|
||||||
\_Note (June 2012): Some versions of MacOSX does not seem to have
|
**Windows** users should first and foremost recognize that the
|
||||||
a locale setting out of the box, and this causes a traceback
|
Evennia server is run from the command line, something which some
|
||||||
during database creation. This is a known upstream bug in Django
|
might not be familiar with (based on the questions we have
|
||||||
1.4, described
|
received). In the Windows launch menu, just start \_All Programs
|
||||||
`here <http://code.google.com/p/evennia/wiki/Quirks#Known_upstream_bugs>`_.
|
-> Accessories -> command prompt and you will get the Windows
|
||||||
In the bug comments is also described how to add the locale and
|
command line interface. There are plenty of online tutorials on
|
||||||
circumvent this bug for now. This affects also Unix/Linux systems,
|
using the Windows command line, one example is found
|
||||||
but those usually have the locale set out of the box.
|
`here <http://www.bleepingcomputer.com/tutorials/windows-command-prompt-introduction/>`_.
|
||||||
|
|
||||||
**Windows** users should first and foremost recognize that the Evennia
|
|
||||||
server is run from the command line, something which some might not be
|
|
||||||
familiar with (based on the questions we have received). In the Windows
|
|
||||||
launch menu, just start *All Programs -> Accessories -> command prompt*
|
|
||||||
and you will get the Windows command line interface. There are plenty of
|
|
||||||
online tutorials on using the Windows command line, one example is found
|
|
||||||
`here <http://www.bleepingcomputer.com/tutorials/windows-command-prompt-introduction/>`_.
|
|
||||||
|
|
||||||
Windows users may want to install
|
Windows users may want to install
|
||||||
`ActivePython <http://www.activestate.com/activepython/downloads>`_
|
`ActivePython <http://www.activestate.com/activepython/downloads>`_
|
||||||
|
|
@ -169,11 +162,12 @@ one won't let you download any packages without paying for a "Business"
|
||||||
license). If ActivePython is installed, you can use
|
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 - that platform defaults to missing many of
|
getting started on Windows - this platform defaults to lacking sane
|
||||||
the sane developer tools that Linux users take for granted.
|
developer tools and package management.
|
||||||
|
|
||||||
After installing ActivePython you may need to restart the terminal/DOS
|
After installing ActivePython you may need to restart the terminal/DOS
|
||||||
window to make the pypm command available on the command line:
|
window to make the pypm command available on the command line. Then
|
||||||
|
write:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
|
@ -260,24 +254,19 @@ with the standard tables and values:
|
||||||
|
|
||||||
python manage.py syncdb
|
python manage.py syncdb
|
||||||
|
|
||||||
You should be asked for a superuser username, email, and password. Make
|
You will see a lot of spammy install messages. If all goes well, you're
|
||||||
**sure** you create a superuser here when asked, this becomes your login
|
ready to continue to the next step. If not, look at the error messages
|
||||||
name for the superuser account ``#1`` in game. After this you will see a
|
and double-check your ``settings.py`` file.
|
||||||
lot of spammy install messages. If all goes well, you're ready to
|
|
||||||
continue to the next step. If not, look at the error messages and
|
|
||||||
double-check your ``settings.py`` file.
|
|
||||||
|
|
||||||
If you installed ``South`` for database schema migrations, you will then
|
Next you migrate the database to the current revision:
|
||||||
need to do this:
|
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
python manage.py migrate
|
python manage.py migrate
|
||||||
|
|
||||||
This will migrate the server to the latest version. If you don't use
|
This can take a while. When we make changes to the database schema in
|
||||||
``South``, migrations will not be used and your server will already be
|
the future (we announce this on the homepage) you just need to re-run
|
||||||
at the latest version (but your existing database might have to be
|
this command to have your existing database converted for you.
|
||||||
manually edited to match eventual future schema changes that we do).
|
|
||||||
|
|
||||||
Step 3: Starting and Stopping the Server
|
Step 3: Starting and Stopping the Server
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
@ -289,10 +278,18 @@ and execute ``evennia.py`` like this:
|
||||||
|
|
||||||
python evennia.py -i start
|
python evennia.py -i start
|
||||||
|
|
||||||
This starts the server and portal. The ``-i`` flag means that the server
|
(The ``-i`` flag means that the server starts in *interactive mode*, as
|
||||||
starts in *interactive mode*, as a foreground process. You will see
|
a foreground process. You will see debug/log messages directly in the
|
||||||
debug/log messages directly in the terminal window instead of logging
|
terminal window instead of logging them to a file.)
|
||||||
them to a file.
|
|
||||||
|
You should be asked to create a superuser. Make **sure** you create a
|
||||||
|
superuser here when asked, this becomes your login name for the
|
||||||
|
superuser (owner) account in game. It will ask for email address and
|
||||||
|
password. The email address does not have to be an existing one.
|
||||||
|
|
||||||
|
After entering the superuser information, the server and portal will
|
||||||
|
start for the first time. Evennia will quickly run some first-time
|
||||||
|
configurations, restart once and then be running.
|
||||||
|
|
||||||
To stop Evennia, do:
|
To stop Evennia, do:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,10 +55,15 @@ For testing, we choose the *Freenode* network, ``irc.freenode.net``. We
|
||||||
will connect to a test channel, let's call it *#myevennia-test* (an IRC
|
will connect to a test channel, let's call it *#myevennia-test* (an IRC
|
||||||
channel always begins with ``#``). It's best if you pick an obscure
|
channel always begins with ``#``). It's best if you pick an obscure
|
||||||
channel name that didn't exist previously - if it didn't exist it will
|
channel name that didn't exist previously - if it didn't exist it will
|
||||||
be created for you. *Don't* connect to ``#evennia``, that is Evennia's
|
be created for you. *Don't* connect to ``#evennia`` for testing and
|
||||||
official chat channel!
|
debugging, that is Evennia's official chat channel!
|
||||||
|
|
||||||
A *port* needed depends on the network. For Freenode this is ``6667``.
|
(By the way, you *are* welcome to connect your game to ``#evennia`` once
|
||||||
|
you have everything working - it can be a good way to get help and
|
||||||
|
ideas. But if you do, please do so with an in-game channel open only to
|
||||||
|
your game admins and developers).
|
||||||
|
|
||||||
|
The *port* needed depends on the network. For Freenode this is ``6667``.
|
||||||
|
|
||||||
What will happen is that your Evennia server will connect to this IRC
|
What will happen is that your Evennia server will connect to this IRC
|
||||||
channel as a normal user. This "user" (or "bot") needs a name, which you
|
channel as a normal user. This "user" (or "bot") needs a name, which you
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,10 @@ Third-party Evennia links
|
||||||
- `Latitude <https://github.com/dbenoy/latitude>`_ (MUCK under
|
- `Latitude <https://github.com/dbenoy/latitude>`_ (MUCK under
|
||||||
development, using Evennia)
|
development, using Evennia)
|
||||||
|
|
||||||
|
- `notimetoplay
|
||||||
|
post <http://notimetoplay.org/2013/08/29/evennia-a-mud-building-toolkit/>`_
|
||||||
|
about Evennia
|
||||||
|
|
||||||
General mud/game development ideas and discussions
|
General mud/game development ideas and discussions
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -77,7 +81,26 @@ General mud/game development ideas and discussions
|
||||||
discussion about rule systems and game balance that could be
|
discussion about rule systems and game balance that could be
|
||||||
applicable also for MUDs.
|
applicable also for MUDs.
|
||||||
|
|
||||||
x
|
Litterature
|
||||||
|
-----------
|
||||||
|
|
||||||
|
- Richard Bartle *Designing Virtual Worlds* (`amazon
|
||||||
|
page <http://www.amazon.com/Designing-Virtual-Worlds-Richard-Bartle/dp/0131018167>`_)
|
||||||
|
- Essential reading for the design of any persistent game world,
|
||||||
|
written by the co-creator of the original game *MUD*. Discusses
|
||||||
|
basically everything you need to think about and more.
|
||||||
|
- Richard Cantillon *An Essay on Economic Theory* (`free
|
||||||
|
pdf <http://mises.org/books/essay_on_economic_theory_cantillon.pdf>`_)
|
||||||
|
- A very good English translation of *Essai sur la Nature du Commerce
|
||||||
|
en Général*, one of the foundations of modern economic theory.
|
||||||
|
Written in 1730 but the translation is annotated and is very easy to
|
||||||
|
follow for a modern reader. Required reading if you think of
|
||||||
|
implementing a sane game economic system.
|
||||||
|
- David M. Beazley *Python Essential Reference (4th ed)* (`amazon
|
||||||
|
page <http://www.amazon.com/Python-Essential-Reference-David-Beazley/dp/0672329786/>`_)
|
||||||
|
- Our recommended book on Python; it not only efficiently summarizes
|
||||||
|
the language but is also an excellent reference to the standard
|
||||||
|
library for more experienced Python coders.
|
||||||
|
|
||||||
Frameworks
|
Frameworks
|
||||||
----------
|
----------
|
||||||
|
|
|
||||||
|
|
@ -221,6 +221,25 @@ Some useful default lockfuncs (see ``src/locks/lockfuncs.py`` for more):
|
||||||
``id/dbref`` but always looks for permissions and dbrefs of
|
``id/dbref`` but always looks for permissions and dbrefs of
|
||||||
*Players*, not on Characters.
|
*Players*, not on Characters.
|
||||||
|
|
||||||
|
Checking simple strings
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Sometimes you don't really need to look up a certain lock, you just want
|
||||||
|
to check a lockstring. A common use is inside Commands, in order to
|
||||||
|
check if a user has a certain permission. The lockhandler has a method
|
||||||
|
``check_lockstring(accessing_obj, lockstring, bypass_superuser=False)``
|
||||||
|
that allows this.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
# inside command definition
|
||||||
|
if not self.caller.locks.check_lockstring(self.caller, "dummy:perm(Wizards)"):
|
||||||
|
self.caller.msg("You must be Wizard or higher to do this!"
|
||||||
|
return
|
||||||
|
|
||||||
|
Note here that the ``access_type`` can be left to a dummy value since
|
||||||
|
this method does not actually do a Lock lookup.
|
||||||
|
|
||||||
Default locks
|
Default locks
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,8 +78,8 @@ Coding with nicks
|
||||||
|
|
||||||
Nicks are are stored as the ``Nick`` database model and are referred
|
Nicks are are stored as the ``Nick`` database model and are referred
|
||||||
from the normal Evennia `object <Objects.html>`_ through the ``nicks``
|
from the normal Evennia `object <Objects.html>`_ through the ``nicks``
|
||||||
property. `` nicks`` is a special handler that offers effective error
|
property - this is known as the NickHandler. The NickHandler offers
|
||||||
checking, searches and conversion.
|
effective error checking, searches and conversion.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
|
@ -87,16 +87,16 @@ checking, searches and conversion.
|
||||||
object.nicks.add("greetjack", "tell Jack = Hello pal!")
|
object.nicks.add("greetjack", "tell Jack = Hello pal!")
|
||||||
|
|
||||||
# An object nick:
|
# An object nick:
|
||||||
object.nicks.add("rose", "The red flower", nick_type="object")
|
obj.nicks.add("rose", "The red flower", nick_type="object")
|
||||||
|
|
||||||
# An player nick:
|
# An player nick:
|
||||||
object.nicks("tom", "Tommy Hill", nick_type="player")
|
obj.nicks.add("tom", "Tommy Hill", nick_type="player")
|
||||||
|
|
||||||
# My own custom nick type (handled by my own game code somehow):
|
# My own custom nick type (handled by my own game code somehow):
|
||||||
object.nicks.add("hood", "The hooded man", nick_type="my_identsystem")
|
obj.nicks.add("hood", "The hooded man", nick_type="my_identsystem")
|
||||||
|
|
||||||
# get back the translated nick:
|
# get back the translated nick:
|
||||||
full_name = object.nicks.get("rose", nick_type="object")
|
full_name = obj.nicks.get("rose", nick_type="object")
|
||||||
|
|
||||||
# delete a previous set nick
|
# delete a previous set nick
|
||||||
object.nicks.del("rose", nick_type="object")
|
object.nicks.del("rose", nick_type="object")
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,11 +1,11 @@
|
||||||
Players
|
Players
|
||||||
=======
|
=======
|
||||||
|
|
||||||
All gamers (real people) that opens a game *Session* on Evennia are
|
All *gamers* (real people) that opens a game `Session <Session.html>`_
|
||||||
doing so through an object called *Player*. The Player object has no
|
on Evennia are doing so through an object called *Player*. The Player
|
||||||
in-game representation, it represents the account the gamer has on the
|
object has no in-game representation, it represents the account the
|
||||||
game. In order to actually get on the game the Player must *puppet* an
|
gamer has on the game. In order to actually get on the game the Player
|
||||||
`Object <Objects.html>`_ (normally a Character).
|
must *puppet* an `Object <Objects.html>`_ (normally a Character).
|
||||||
|
|
||||||
Just how this works depends on the configuration option
|
Just how this works depends on the configuration option
|
||||||
``MULTISESSION_MODE``. There are three multisession modes, described in
|
``MULTISESSION_MODE``. There are three multisession modes, described in
|
||||||
|
|
@ -25,7 +25,7 @@ or some of the other protocols Evennia supports.
|
||||||
client is doing exactly the same thing as doing so in any other
|
client is doing exactly the same thing as doing so in any other
|
||||||
connected client. All sessions will see the same output and e.g.
|
connected client. All sessions will see the same output and e.g.
|
||||||
giving the @quit command will kill all sessions.
|
giving the @quit command will kill all sessions.
|
||||||
- In mode 2 (right) eeach Player can hold any number of sessions and
|
- In mode 2 (right) each Player can hold any number of sessions and
|
||||||
they are kept separate from one another. This allows a single player
|
they are kept separate from one another. This allows a single player
|
||||||
to puppet any number of Characters and Objects.
|
to puppet any number of Characters and Objects.
|
||||||
|
|
||||||
|
|
@ -39,19 +39,18 @@ characters as well as configuration options. Players are
|
||||||
`CmdSet <Commands.html>`_ defaulting to the set defined by
|
`CmdSet <Commands.html>`_ defaulting to the set defined by
|
||||||
``settings.CMDSET_PLAYER``.
|
``settings.CMDSET_PLAYER``.
|
||||||
|
|
||||||
If you are logged in into default Evennia under any multisession mode,
|
Logged into default Evennia, you can use the ``@ooc`` command to leave
|
||||||
you can use the ``@ooc`` command to leave your current
|
your current `Character <Objects.html>`_ and go into OOC mode. You are
|
||||||
`Character <Objects.html>`_ and go into OOC mode. You are quite limited
|
quite limited in this mode, basically it works like a simple chat
|
||||||
in this mode, basically it works like a simple chat program. It acts as
|
program. It acts as a staging area for switching between Characters (if
|
||||||
a staging area for switching between Characters (if your game supports
|
your game supports that) or as a safety mode if your Character gets
|
||||||
that) or as a safety mode if your Character gets deleted. . Use ``@ic``
|
deleted. Use ``@ic`` to attempt to puppet a Character.
|
||||||
attempt to puppet a Character.
|
|
||||||
|
|
||||||
Note that the Player object can and often do have a different set of
|
Note that the Player object can and often do have a different set of
|
||||||
[Locks#Permissions Permissions] from the Character they control.
|
[Locks#Permissions Permissions] from the Character they control.
|
||||||
Normally you should put your permissions on the Player level - only if
|
Normally you should put your permissions on the Player level - this will
|
||||||
your Player does not have a given permission will the permissions on the
|
overrule permissions set on the Character level (unless ``@quell``-ing
|
||||||
Character be checked.
|
is used).
|
||||||
|
|
||||||
How to create your own Player types
|
How to create your own Player types
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ Evennia Quirks
|
||||||
This is a list of various problems or stumbling blocks that people often
|
This is a list of various problems or stumbling blocks that people often
|
||||||
ask about or report when using (or trying to use) Evennia. These are
|
ask about or report when using (or trying to use) Evennia. These are
|
||||||
common stumbling blocks, non-intuitive behaviour and common newbie
|
common stumbling blocks, non-intuitive behaviour and common newbie
|
||||||
mistakes when working with Evennia. They are not bugs.
|
mistakes when working with Evennia. They are not Evennia bugs.
|
||||||
|
|
||||||
Actual Evennia bugs should be reported in
|
Actual Evennia bugs should be reported in
|
||||||
`Issues <https://code.google.com/p/evennia/issues/list>`_.
|
`Issues <https://code.google.com/p/evennia/issues/list>`_.
|
||||||
|
|
@ -48,9 +48,10 @@ Web admin to create new Player
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
If you use the default login system and is trying to use the Web admin
|
If you use the default login system and is trying to use the Web admin
|
||||||
to create a new Player account, you need to thread carefully. The
|
to create a new Player account, you need to consider which
|
||||||
default login system *requires* the Player object to already have a
|
MULTIPLAYER\_MODE you are in. If you are in MULTIPLAYER\_MODE 0 or 1,
|
||||||
connected Character object - there is no character creation screen by
|
the login system expects each Player to also have a Character object
|
||||||
|
named the same as the Player - there is no character creation screen by
|
||||||
default. If using the normal mud login screen, a Character with the same
|
default. If using the normal mud login screen, a Character with the same
|
||||||
name is automatically created and connected to your Player. From the web
|
name is automatically created and connected to your Player. From the web
|
||||||
interface you must do this manually.
|
interface you must do this manually.
|
||||||
|
|
@ -62,13 +63,6 @@ property on the Character and the "character" property on the Player to
|
||||||
point to each other. You must also set the lockstring of the Character
|
point to each other. You must also set the lockstring of the Character
|
||||||
to allow the Player to "puppet" this particular character.
|
to allow the Player to "puppet" this particular character.
|
||||||
|
|
||||||
The default login system is very simple and intended for you to easily
|
|
||||||
get into the game. The more advanced login system in ``contrib/`` along
|
|
||||||
with the example character-creation system does not require such an
|
|
||||||
initial coupling (i.e. you can create the coupling in-game). For your
|
|
||||||
initial experiments, it's easist to create your characters from the
|
|
||||||
normal MUD connection screen instead.
|
|
||||||
|
|
||||||
Mutable attributes and their connection to the database
|
Mutable attributes and their connection to the database
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -117,22 +111,4 @@ appreciate getting more input and help.
|
||||||
Known upstream bugs
|
Known upstream bugs
|
||||||
===================
|
===================
|
||||||
|
|
||||||
These are known bugs in in the libraries Evennia uses, i.e. things out
|
There are no known upstream bugs at this time.
|
||||||
of our control.
|
|
||||||
|
|
||||||
Error during manage.py syncdb
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
This error can be seen using Django 1.4 without a *locale* set. It
|
|
||||||
causes a traceback during the ``manage.py syncdb`` phase, just when
|
|
||||||
trying to create the superuser.
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
TypeError: decode() argument 1 must be string, not None
|
|
||||||
|
|
||||||
This opaque error means no locale could be found. Not properly handling
|
|
||||||
this is a bug in Django 1.4 reported
|
|
||||||
`here <https://code.djangoproject.com/ticket/16017>`_. You resolve it by
|
|
||||||
setting your locale (this is a good thing to have in any case). See the
|
|
||||||
comments to that bug report for how to do this.
|
|
||||||
|
|
|
||||||
|
|
@ -143,10 +143,10 @@ find longer descriptions of these in ``src/scripts/scripts.py``.
|
||||||
situations such as reloads. This is also useful for using scripts as
|
situations such as reloads. This is also useful for using scripts as
|
||||||
state managers. If the method returns ``False``, the script is
|
state managers. If the method returns ``False``, the script is
|
||||||
stopped and cleanly removed.
|
stopped and cleanly removed.
|
||||||
- ``at_start()`` - this is called when the script first starts. For
|
- ``at_start()`` - this is called when the script starts or is
|
||||||
persistent scripts this is at least once ever server startup. Note
|
unpaused. For persistent scripts this is at least once ever server
|
||||||
that this will *always* be called right away, also if ``start_delay``
|
startup. Note that this will *always* be called right away, also if
|
||||||
is ``True``.
|
``start_delay`` is ``True``.
|
||||||
- ``at_repeat()`` - this is called every ``interval`` seconds, or not
|
- ``at_repeat()`` - this is called every ``interval`` seconds, or not
|
||||||
at all. It is called right away at startup, unless ``start_delay`` is
|
at all. It is called right away at startup, unless ``start_delay`` is
|
||||||
``True``, in which case the system will wait ``interval`` seconds
|
``True``, in which case the system will wait ``interval`` seconds
|
||||||
|
|
@ -173,10 +173,10 @@ possible to also invoke manually)
|
||||||
resumed. This is called automatically when the server reloads. No
|
resumed. This is called automatically when the server reloads. No
|
||||||
hooks are called - as far as the script knows, it never stopped -
|
hooks are called - as far as the script knows, it never stopped -
|
||||||
this is a suspension of the script, not a change of state.
|
this is a suspension of the script, not a change of state.
|
||||||
- ``unpause()`` - resumes a previously paused script. Timers etc are
|
- ``unpause()`` - resumes a previously paused script. The at\_start()
|
||||||
restored to what they were before pause. The server unpauses all
|
hook will be called to allow it to reclaim its internal state. Timers
|
||||||
paused scripts after a server reload. No hooks are called - as far as
|
etc are restored to what they were before pause. The server unpauses
|
||||||
the script is concerned, it never stopped running.
|
all paused scripts after a server reload.
|
||||||
- ``time_until_next_repeat()`` - for timed scripts, this returns the
|
- ``time_until_next_repeat()`` - for timed scripts, this returns the
|
||||||
time in seconds until it next fires. Returns ``None`` if
|
time in seconds until it next fires. Returns ``None`` if
|
||||||
``interval==0``.
|
``interval==0``.
|
||||||
|
|
|
||||||
|
|
@ -43,11 +43,11 @@ code. The only way to change an Evennia setting is to edit
|
||||||
\`game/gamesrc/conf\` directory
|
\`game/gamesrc/conf\` directory
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
The ``game/gamesrc/conf/`` directory contains module templates for
|
The ``game/gamesrc/conf/examples/`` directory contains module templates
|
||||||
customizing Evennia. Common for all these is that you should *copy* the
|
for customizing Evennia. Common for all these is that you should *copy*
|
||||||
template up one level (to ``game/gamesrc/conf/``) and edit the copy, not
|
the template up one level (to ``game/gamesrc/conf/``) and edit the copy,
|
||||||
the original. You then need to change your settings file to point the
|
not the original. You then need to change your settings file to point
|
||||||
right variable at your new module. Each template header describes
|
the right variable at your new module. Each template header describes
|
||||||
exactly how to use it and which settings variable needs to be changed
|
exactly how to use it and which settings variable needs to be changed
|
||||||
for Evennia to be able to locate it.
|
for Evennia to be able to locate it.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,72 @@ MUSH parsers have jumped light years ahead of where they were even seven
|
||||||
or eight years ago, they can still stutter under the weight of the more
|
or eight years ago, they can still stutter under the weight of the more
|
||||||
complex systems if not designed properly.
|
complex systems if not designed properly.
|
||||||
|
|
||||||
|
To further illustrate the lack of readability for building larger
|
||||||
|
systems in softcode, here is another example, PennMush softcode this
|
||||||
|
time, for implementing an "+info" command (it allows you to store pages
|
||||||
|
of extra character info that is later confirmed by admins and can be
|
||||||
|
viewed by other players):
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
&INC`SET u(ifo)=@include u(ifo)/INC`TARGET;@include \
|
||||||
|
u(ifo)/INC`FILENAME;@assert strlen(%q<filename>)=@nspemit \
|
||||||
|
%#=announce(INFO)%BERROR: Info file name empty.;@switch/inline \
|
||||||
|
gt(strlen(setr(attr,u(u(ifo)/FUN`FINDFILE,%q<target>,%q<filename>))),0)=1,{@assert \
|
||||||
|
or(isadmin(%#),strmatch(%q<target>,%#))=@nspemit \
|
||||||
|
%#=announce(INFO)%BERROR: You may not change another's Info \
|
||||||
|
files.;@switch/inline \
|
||||||
|
or(getstat(%q<target>/%q<attr>`FLAGS,Hidden),getstat(%q<target>/%q<attr>`FLAGS,Approved))=1,{@assert \
|
||||||
|
isadmin(%#)=@nspemit %#=announce(INFO)%BERROR: That Info File may not \
|
||||||
|
be changed by you.}},0,{@break gt(strlen(%q<filename>),18)=@nspemit \
|
||||||
|
%#=ERROR: Info names are limited to 18 characters or less.;@break \
|
||||||
|
regmatchi(%q<filename>,\\|)=@nspemit %#=ERROR: Pipe symbols are not \
|
||||||
|
allowed in info names.;@break regmatchi(%q<filename>,\/)=@nspemit \
|
||||||
|
%#=ERROR: Slashes symbols are not allowed in info names.;@assert \
|
||||||
|
strlen(%1)=ERROR: Text field empty. To delete an +info file, use \
|
||||||
|
+info/delete.};&[strfirstof(%q<attr>,setr(attr,D`INFOFILE`[nextslot(%q<target>,D`INFOFILE)]))] \
|
||||||
|
%q<target>=%q<filename>;&%q<attr>`CONTENTS %q<target>=%1;th \
|
||||||
|
setstat(%q<target>/%q<attr>`FLAGS,SetBy,%#);th \
|
||||||
|
setstat(%q<target>/%q<attr>`FLAGS,SetOn,secs());@switch/inline \
|
||||||
|
strmatch(%#,%q<target>)=1,{@nspemit %#=announce(INFO)%BYou set your \
|
||||||
|
%q<filename> Info File},{@nspemit %#=announce(INFO)%BYou set \
|
||||||
|
[name(%q<target>)]'s %q<filename> Info File!;@nspemit \
|
||||||
|
%q<target>=announce(INFO)%B%n set your %q<filename> Info File!}
|
||||||
|
|
||||||
|
(Note that the softcode is actually all one line, it was split to be
|
||||||
|
viewable on this wiki). Below is the rough Evennia equivalent
|
||||||
|
functionality as an Evennia command method, written by the same softcode
|
||||||
|
author after a week of learning Evennia:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
def switch_set(self,target,files,rhs,isadmin):
|
||||||
|
if self.caller is not target and not isadmin:
|
||||||
|
self.caller.msg("ERROR: You may not set that person's files.")
|
||||||
|
return
|
||||||
|
if not self.rhs:
|
||||||
|
self.caller.msg("ERROR: No info file contents entered to set.")
|
||||||
|
return
|
||||||
|
for info in files:
|
||||||
|
if not re.match('^[\w-]+$', info.lower().strip()):
|
||||||
|
self.caller.msg("ERROR: File '" + info + \
|
||||||
|
"' could not be set: may only use alphanumeric characters, -, and spaces in info names.")
|
||||||
|
elif self.files.get(info.lower().strip(),{}).get("approved",None) is True:
|
||||||
|
self.caller.msg("ERROR: File '" + info.strip() + "' could not be set: file is approved.")
|
||||||
|
else:
|
||||||
|
self.files[info.lower().strip()] = {"contents":rhs, "setby":self.caller,
|
||||||
|
"seton":"timestamp", "displayname":info.strip()}
|
||||||
|
if target is self.caller:
|
||||||
|
self.caller.msg("Info File '" + info.strip() + "' set!")
|
||||||
|
else:
|
||||||
|
self.caller.msg("Info File '" + info.strip() + "' set!")
|
||||||
|
target.caller.msg(self.caller.key + " set your '" + info.strip() + "' info file!")
|
||||||
|
target.db.infofiles = dict(self.files)
|
||||||
|
return
|
||||||
|
|
||||||
|
The details of the implementation are unimportant, the difference in
|
||||||
|
readability is the main point here.
|
||||||
|
|
||||||
Changing Times
|
Changing Times
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@ Coding basics
|
||||||
More details about coding with Evennia is found in the `Developer
|
More details about coding with Evennia is found in the `Developer
|
||||||
Central <DeveloperCentral.html>`_.
|
Central <DeveloperCentral.html>`_.
|
||||||
|
|
||||||
|
- `First Steps Coding with Evennia <FirstStepsCoding.html>`_ - this is
|
||||||
|
partly duplicated in the following two tutorials using different
|
||||||
|
words.
|
||||||
- `Tutorial: Adding a new default
|
- `Tutorial: Adding a new default
|
||||||
command <AddingCommandTutorial.html>`_
|
command <AddingCommandTutorial.html>`_
|
||||||
- `Tutorial: Adding new Object typeclasses and
|
- `Tutorial: Adding new Object typeclasses and
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -27,23 +27,76 @@ unlimited power to extend the game leveraging the full power of a mature
|
||||||
high level programming language. You can find a more elaborate
|
high level programming language. You can find a more elaborate
|
||||||
discussion about our take on MUX SoftCode `here <SoftCode.html>`_.
|
discussion about our take on MUX SoftCode `here <SoftCode.html>`_.
|
||||||
|
|
||||||
|
Documentation policy
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
All the commands in the default command sets have their doc-strings
|
||||||
|
formatted on a similar form:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
"""
|
||||||
|
Short header
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
key[/switches, if any] <mandatory args> [<optional args or types>]
|
||||||
|
|
||||||
|
Switches:
|
||||||
|
switch1 - description
|
||||||
|
switch2 - description
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
usage example and output
|
||||||
|
|
||||||
|
Longer documentation detailing the command.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
The ``Switches`` and ``Examples`` headers can be skipped if not needed.
|
||||||
|
Here is the ``nick`` command as an example:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
"""
|
||||||
|
Define a personal alias/nick
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
nick[/switches] <nickname> = [<string>]
|
||||||
|
alias ''
|
||||||
|
|
||||||
|
Switches:
|
||||||
|
object - alias an object
|
||||||
|
player - alias a player
|
||||||
|
clearall - clear all your aliases
|
||||||
|
list - show all defined aliases (also "nicks" works)
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
nick hi = say Hello, I'm Sarah!
|
||||||
|
nick/object tom = the tall man
|
||||||
|
|
||||||
|
A 'nick' is a personal shortcut you create for your own use [...]
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
For commands that *require arguments*, the policy is for it to return a
|
||||||
|
``Usage`` string if the command is entered without any arguments. So for
|
||||||
|
such commands, the Command body should contain something to the effect
|
||||||
|
of
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
if not self.args:
|
||||||
|
self.caller.msg("Usage: nick[/switches] <nickname> = [<string>]")
|
||||||
|
return
|
||||||
|
|
||||||
WWMD - What Would MUX Do?
|
WWMD - What Would MUX Do?
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
Our policy for implementing the default commands is as follows - we tend
|
Our original policy for implementing the default commands was to look at
|
||||||
to look at MUX2's implementation before contriving one of our own. This
|
MUX2's implementation and base our command syntax on that. This means
|
||||||
comes with a caveat though - there are many cases where this is
|
that many default commands have roughly similar syntax and switches as
|
||||||
impossible without sacrificing the usability and utility of the
|
MUX commands. There are however many differences between the systems and
|
||||||
codebase. In those cases, differences in implementation as well as
|
readability and usability has taken priority (frankly, the MUX syntax is
|
||||||
command syntax is to be expected. Evennia is *not* MUX - we handle all
|
outright arcane in places). So the default command sets can be
|
||||||
underlying systems very differently and don't use
|
considered to implement a "MUX-like" dialect - whereas the overall feel
|
||||||
`SoftCode <SoftCode.html>`_. The WWMD policy is only applied to the
|
is familiar, the details may differ considerably.
|
||||||
default commands, not to any other programming paradigms in the
|
|
||||||
codebase.
|
|
||||||
|
|
||||||
If you are an Evennia codebase developer, consider activating
|
|
||||||
``IMPORT_MUX_HELP`` in your ``settings.py`` file. This will import a
|
|
||||||
copy of the MUX2 help database and might come in handy when it comes to
|
|
||||||
adding/implementing new default commands. If you must deviate from
|
|
||||||
MUX2's implementation of something, make sure to document it extensively
|
|
||||||
in the command's docstring.
|
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,36 @@ should be easy to retrieve.
|
||||||
|
|
||||||
Many MUD codebases hardcode zones as part of the engine and database.
|
Many MUD codebases hardcode zones as part of the engine and database.
|
||||||
Evennia does no such distinction due to the fact that rooms themselves
|
Evennia does no such distinction due to the fact that rooms themselves
|
||||||
are meant to be customized to any level anyway. Below is just *one*
|
are meant to be customized to any level anyway. Below are two
|
||||||
example of how one could add zone-like functionality to a game.
|
suggestions for how zones could be implemented.
|
||||||
|
|
||||||
|
Zones using Tags
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
*OBS: Placeholder - this section is NOT fully supported by the code at
|
||||||
|
the moment!*
|
||||||
|
|
||||||
|
All objects in Evennia can hold any number of `tags <Tag.html>`_. Tags
|
||||||
|
are short labels that you attach to objects. They make it very easy to
|
||||||
|
retrieve groups of objects. An object can have any number of different
|
||||||
|
tags. So let's attach the relevant tag to our forest:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
forestobj.tags.add("magicalforest", category="zone")
|
||||||
|
|
||||||
|
You could add this manually, or automatically during creation somehow
|
||||||
|
(you'd need to modify your @dig command for this, most likely).
|
||||||
|
|
||||||
|
Henceforth you can then easily retrieve only objects with a given tag:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
import ev
|
||||||
|
rooms = ev.managers.Tags.get_objs_with_tag("magicalforest", category="zone") # (error here)
|
||||||
|
|
||||||
|
Zones using Aliases
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
All objects have a *key* property, stored in the database. This is the
|
All objects have a *key* property, stored in the database. This is the
|
||||||
primary name of the object. But it can also have any number of *Aliases*
|
primary name of the object. But it can also have any number of *Aliases*
|
||||||
|
|
@ -41,8 +69,8 @@ alias "door". Aliases are actually separate database entities and are as
|
||||||
such very fast to search for in the database, about as fast as searching
|
such very fast to search for in the database, about as fast as searching
|
||||||
for the object's primary key in fact.
|
for the object's primary key in fact.
|
||||||
|
|
||||||
This makes Aliases prime candiates for implementing zones. All you need
|
This makes Aliases another candidate for implementing zones. All you
|
||||||
to do is to come up with a consistent aliasing scheme. Here's one
|
need to do is to come up with a consistent aliasing scheme. Here's one
|
||||||
suggestion:
|
suggestion:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
@ -130,12 +158,12 @@ zone in the typeclass rather than enforce the ``@dig`` command to do it:
|
||||||
class MagicalForestRoom(Room)
|
class MagicalForestRoom(Room)
|
||||||
def at_object_creation(self):
|
def at_object_creation(self):
|
||||||
...
|
...
|
||||||
self.aliases = "#magicforest|%s" % self.key
|
self.aliases.add("#magicforest|%s" % self.key)
|
||||||
...
|
...
|
||||||
class NormalForestRoom(Room)
|
class NormalForestRoom(Room)
|
||||||
def at_object_creation(self):
|
def at_object_creation(self):
|
||||||
...
|
...
|
||||||
self.aliases = "#normalforest|%s" % self.key
|
self.aliases.add("#normalforest|%s" % self.key)
|
||||||
...
|
...
|
||||||
|
|
||||||
Of course, an alternative way to implement zones themselves is to have
|
Of course, an alternative way to implement zones themselves is to have
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue