Updated ReST documentation.

This commit is contained in:
Griatch 2012-05-01 17:37:37 +02:00
parent 36b15b4ad8
commit a8139feb1a
37 changed files with 963 additions and 910 deletions

View file

@ -37,8 +37,7 @@ Defining a Command
------------------
All commands are implemented as normal Python classes inheriting from
the base class ``Command``
(``game.gamesrc.commands.basecommand.Command``). You will find that this
the base class ``Command`` (``ev.Command``). You will find that this
base class is very "bare". The default commands of Evennia actually
inherit from a child of ``Command`` called ``MuxCommand`` - this is the
class that knows all the mux-like syntax like ``/switches``, splitting
@ -48,7 +47,7 @@ class directly.
::
# basic Command definition
from game.gamesrc.commands.basecommand import Command
from ev import Command
class MyCmd(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
assigned to them, like when creating a new one).
- ``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.
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
defined. This need not be the caller, but since ``look`` is a common
(default) command, this is probably defined directly on *!BigGuy* -
so ``obj`` will point to !BigGuy. Otherwise ``obj`` could be any
interactive object with commands defined on it, like in the example
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>`_
that you can "``push``".
button <https://code.google.com/p/evennia/source/browse/trunk/game/gamesrc/objects/examples/red<i>button.py.html>`_
that you can "``push``\ ".
- ``cmdset`` - this is a reference to the merged CmdSet (see below)
from which this command was matched. This variable is rarely used,
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``.
This should (ideally) be unique. it can be more than one word long in
a string, like "press button". Maximum number of space-separated
words that can be part of a command name is given by
``settings.CMD_MAXLEN``.
a string, like "press button" or "pull lever left".
- ``aliases`` (optional list) - a list of alternate names for the
command (``["l", "glance", "see"]``). Same name rules as for ``key``
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
command called by retrieving ``self.caller.ndb.last_cmd``. The next
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>`_.
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.
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
@ -147,7 +144,7 @@ Beyond the properties Evennia always assigns to the command at runtime
expected.
- autohelp (optional boolean). Defaults to ``True``. This allows for
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
your help entries manually or hide the existence of a command from
``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
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
``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
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
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``,
``@dig`` etc. You can find it defined in
``src/commands/default/cmdset_default.py``, but it is also referenced by
``game/gamesrc/commands/basecmdset.py``. Players have an
Out-of-character cmdset called ``cmdset_ooc`` that can also be found
from the same place. There is finally an "unloggedin" cmdset that is
used before the Player has authenticated to the game. The path to these
three standard command sets are defined in settings, as
``CMDSET_UNLOGGEDIN``, ``CMDSET_DEFAULT`` and ``CMDSET_OOC``. You can
create any number of command sets besides those to fit your needs.
importing ``ev.default_cmds`` and accessing its property
``DefaultCmdset``. Players have an Out-of-character cmdset called
``cmdset_ooc`` that can also be found from the same place. There is
finally an "unloggedin" cmdset that is used before the Player has
authenticated to the game. The path to these three standard command sets
are defined in settings, as ``CMDSET_UNLOGGEDIN``, ``CMDSET_DEFAULT``
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
inheriting from the correct parent (``src.commands.cmdset.CmdSet``). The
CmdSet class only needs to define one method, called
``at_cmdset_creation()``. All other class parameters are optional, but
are used for more advanced set manipulation and coding (see the `merge
rules <Commands#Merge_rules.html>`_ section).
inheriting from the correct parent (``ev.CmdSet`` or
``src.commands.cmdset.CmdSet``). The CmdSet class only needs to define
one method, called ``at_cmdset_creation()``. All other class parameters
are optional, but are used for more advanced set manipulation and coding
(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
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')
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
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.
#. In ``game/gamesrc/commands``, create a new module. Name it, say,
``mycommand.py``.
#. Import ``game.gamesrc.commands.basecommands.MuxCommand`` (this is a
convenient shortcut so you don't have to import from src/ directly).
The ``MuxCommand`` class handles command line parsing for you, giving
you stuff like /switches, the syntax using '=' etc). In other words,
you don't have to implement ``parse()`` on your own.
``mycommand.py``. Copy from the templates in ``examples/`` if you
like.
#. Import ``ev.default_cmds`` and access ``MuxCommand`` from that (this
is a convenient shortcut so you don't have to import from src/
directly). The ``MuxCommand`` class handles command line parsing for
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
``MuxCommand``.
#. Set the class variable ``key`` to the name to call your command with,
say ``mycommand``.
#. Set the ``locks`` property on the command to a suitable
`lockstring <Locks#Defining%3Ci%3Elocks.html>`_. If you are unsure,
use "cmd:all()".
`lockstring <Locks#Defining<i>locks.html>`_. If you are unsure, use
"cmd:all()".
#. Define a class method ``func()`` that does stuff. See below.
#. Give your class a useful *doc*\_ string, this acts as the help entry
for the command.
#. Give your class a useful *doc*\ \_ string, this acts as the help
entry for the command.
Your command definition is now ready. Here's an example of how it could
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
to do this, but all of them involves putting this command in a *Command
Set*. First, let's try the more involved way.
#. Create a class that inherits from
``game.gamesrc.commands.basecmdset.CmdSet``.
#. Create a class that inherits from ``ev.CmdSet``.
#. (Optionally) set a key to name your command set.
#. Add a method ``at_cmdset_creation()`` and use the ``self.add()``
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())
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.
The default command set is found in
``src/commands/default/cmdset_default.py`` but there is already a
shortcut to it in ``gamesrc/commands/basecmdset.py`` called
``DefaultCmdSet``. Add your command to the end of the ``DefaultSet``
class and you will in fact append it to the existing command set.
``src/commands/default/cmdset_default.py`` but the template in
``gamesrc/commands/examples/`` already shows how to extend it. Copy that
file to ``game/gamesrc/`` and edit ``settings.CMDSET_DEFAULT`` to point
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
available.
@ -401,7 +401,7 @@ make sure to set your new command's ``key`` variable to ``look`` as
well.
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
``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
other variables to control how they merge:
- *allow*duplicates*(bool) - determines what happens when two sets of
equal priority merge. Default is that the new set in the merger (i.e.
**A** above) automatically takes precedence. But if*allow*duplicates*
is true, the result will be a merger with more than one of each name
match. This will usually lead to the player receiving a
multiple-match error higher up the road, but can be good for things
like cmdsets on non-player objects in a room, to allow the system to
warn that more than one 'ball' in the room has the same 'kick'
command defined on it, so it may offer a chance to select which ball
to kick ... Allowing duplicates only makes sense for *Union* and
*Intersect*, the setting is ignored for the other mergetypes.
- *key*mergetype*(dict) - allows the cmdset to define a unique
- *allow*\ duplicates\ *(bool) - determines what happens when two sets
of equal priority merge. Default is that the new set in the merger
(i.e. **A** above) automatically takes precedence. But
if*\ allow\ *duplicates* is true, the result will be a merger with
more than one of each name match. This will usually lead to the
player receiving a multiple-match error higher up the road, but can
be good for things like cmdsets on non-player objects in a room, to
allow the system to warn that more than one 'ball' in the room has
the same 'kick' command defined on it, so it may offer a chance to
select which ball to kick ... Allowing duplicates only makes sense
for *Union* and *Intersect*, the setting is ignored for the other
mergetypes.
- *key*\ mergetype\ *(dict) - allows the cmdset to define a unique
mergetype for particular cmdsets, identified by their cmdset-key.
Format is ``CmdSetkey:mergetype``. Priorities still apply. Example:
``'Myevilcmdset','Replace'`` which would make sure for this set to
always use 'Replace' on ``Myevilcmdset`` only, no matter
what*mergetype\_ is set to.
what*\ mergetype\_ is set to.
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
default) included in any ``CmdSet`` they are not actually used, they are
just there for show. When the special situation occurs, Evennia will
look through all valid ``CmdSet``s for your custom system command. Only
after that will it resort to its own, hard-coded implementation.
look through all valid ``CmdSet``\ s for your custom system command.
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
useful to do something here for certain implementations such as line
editors that interpret non-commands as text input (an empty line in
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.
- Several matching commands where found (``cmdhandler.CMD_MULTIMATCH``)
- Several matching commands where found (``syscmdkeys.CMD_MULTIMATCH``)
- Default is to show a list of matches.
- 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.
- Channel (``cmdhandler.CMD_CHANNEL``) - This is a
- Channel (``syscmdkeys.CMD_CHANNEL``) - This is a
`Channel <Communications.html>`_ name of a channel you are
subscribing to - Default is to relay the command's argument to that
channel. Such commands are created by the Comm system on the fly
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
new connection is established, this command is always called on the
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
-----