mirror of
https://github.com/evennia/evennia.git
synced 2026-03-16 21:06:30 +01:00
Patched wiki2html to give correct source code snippet output.
This commit is contained in:
parent
22b23be095
commit
eae89eabc0
31 changed files with 1028 additions and 175 deletions
|
|
@ -113,5 +113,8 @@ are trouble.
|
|||
|
||||
::
|
||||
|
||||
<Directory "/home/<yourname>/evennia/game/web"> Options +ExecCGI Allow from all </Directory>
|
||||
<Directory "/home/<yourname>/evennia/game/web">
|
||||
Options +ExecCGI
|
||||
Allow from all
|
||||
</Directory>
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@ Consider this piece of code:
|
|||
|
||||
::
|
||||
|
||||
print "before call ..." long_running_function() print "after call ..."
|
||||
print "before call ..."
|
||||
long_running_function()
|
||||
print "after call ..."
|
||||
|
||||
When run, this will print ``"before call ..."``, after which the
|
||||
``long_running_function`` gets to work for however long time. Only once
|
||||
|
|
@ -43,7 +45,10 @@ use of the ``run_async()`` function in ``src/utils/utils.py``.
|
|||
|
||||
::
|
||||
|
||||
from src.utils import utils print "before call ..." utils.run_async(long_running_function) print "after call ..."
|
||||
from src.utils import utils
|
||||
print "before call ..."
|
||||
utils.run_async(long_running_function)
|
||||
print "after call ..."
|
||||
|
||||
Now, when running this you will find that the program will not wait
|
||||
around for ``long_running_function`` to finish. Infact you will see
|
||||
|
|
@ -74,7 +79,8 @@ called automatically.
|
|||
|
||||
::
|
||||
|
||||
def at_return(r): print r
|
||||
def at_return(r):
|
||||
print r
|
||||
|
||||
- ``at_err(e)`` (the *errback*) is called if the asynchronous function
|
||||
fails and raises an exception. This exception is passed to the
|
||||
|
|
@ -93,7 +99,19 @@ An example of making an asynchronous call from inside a
|
|||
|
||||
::
|
||||
|
||||
from src.utils import utils from game.gamesrc.commands.basecommand import Command class CmdAsync(Command): key = "asynccommand" def func(self): def long_running_function(): #[... lots of time-consuming code return final_value def at_return(r): self.caller.msg("The final value is %s" % r) def at_err(e): self.caller.msg("There was an error: %s" % e) # do the async call, setting all callbacks utils.run_async(long_running_function, at_return, at_err)
|
||||
from src.utils import utils
|
||||
from game.gamesrc.commands.basecommand import Command
|
||||
|
||||
class CmdAsync(Command): key = "asynccommand" def func(self):
|
||||
|
||||
def long_running_function():
|
||||
#[... lots of time-consuming code
|
||||
return final_value
|
||||
|
||||
def at_return(r):
|
||||
self.caller.msg("The final value is %s" % r) def at_err(e):
|
||||
self.caller.msg("There was an error: %s" % e) # do the async call, setting all callbacks
|
||||
utils.run_async(long_running_function, at_return, at_err)
|
||||
|
||||
That's it - from here on we can forget about ``long_running_function``
|
||||
and go on with what else need to be done. *Whenever* it finishes, the
|
||||
|
|
|
|||
|
|
@ -29,7 +29,9 @@ assign data to it. Let's try to save some data to a *Rose* (an
|
|||
|
||||
::
|
||||
|
||||
# saving rose.has_thorns = True# getting it back is_ouch = rose.has_thorns
|
||||
# saving
|
||||
rose.has_thorns = True# getting it back
|
||||
is_ouch = rose.has_thorns
|
||||
|
||||
Whether this data is saved *persistently* to the database or not (i.e.
|
||||
if it survives a server reboot) depends on the setting of the variable
|
||||
|
|
@ -41,7 +43,9 @@ of ``FULL_PERSISTENCE``, use the ``db`` (!DataBase) interface.
|
|||
|
||||
::
|
||||
|
||||
# saving rose.db.has_thorns = True # getting it back is_ouch = rose.db.has_thorns
|
||||
# saving
|
||||
rose.db.has_thorns = True # getting it back
|
||||
is_ouch = rose.db.has_thorns
|
||||
|
||||
This creates a new ``Attribute`` object and links it uniquely to
|
||||
``rose``. Using ``db`` ``will`` always save data to the database.
|
||||
|
|
@ -51,7 +55,9 @@ It works in the same way:
|
|||
|
||||
::
|
||||
|
||||
# saving rose.ndb.has_thorns = True # getting it back is_ouch = rose.ndb.has_thorns
|
||||
# saving
|
||||
rose.ndb.has_thorns = True # getting it back
|
||||
is_ouch = rose.ndb.has_thorns
|
||||
|
||||
(Using ``ndb`` like this will **NEVER** use the database.)
|
||||
|
||||
|
|
@ -156,7 +162,18 @@ Examples of valid attribute data:
|
|||
|
||||
::
|
||||
|
||||
# a single value obj.db.test1 = 23 obj.db.test1 = False # a database object (will be stored as dbref) obj.db.test2 = myobj # a list of objects obj.db.test3 = [obj1, 45, obj2, 67] # a dictionary obj.db.test4 = 'str':34, 'dex':56, 'agi':22, 'int':77 # a mixed dictionary/list obj.db.test5 = 'members': [obj1,obj2,obj3], 'enemies':[obj4,obj5]# a tuple will stored and returned as a list [1,2,3,4,5]! obj.db.test6 = (1,2,3,4,5)
|
||||
# a single value
|
||||
obj.db.test1 = 23
|
||||
obj.db.test1 = False
|
||||
# a database object (will be stored as dbref)
|
||||
obj.db.test2 = myobj
|
||||
# a list of objects
|
||||
obj.db.test3 = [obj1, 45, obj2, 67]
|
||||
# a dictionary
|
||||
obj.db.test4 = 'str':34, 'dex':56, 'agi':22, 'int':77
|
||||
# a mixed dictionary/list
|
||||
obj.db.test5 = 'members': [obj1,obj2,obj3], 'enemies':[obj4,obj5]# a tuple will stored and returned as a list [1,2,3,4,5]!
|
||||
obj.db.test6 = (1,2,3,4,5)
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
|
|
|||
|
|
@ -75,7 +75,13 @@ Below is a version of the example file found in
|
|||
|
||||
#
|
||||
# This is an example batch-code build file for Evennia.
|
||||
##HEADER# This will be included in all other #CODE blocksfrom src.utils import create, search from game.gamesrc.objects.examples import red_button from game.gamesrc.objects import baseobjectslimbo = search.objects(caller, 'Limbo', global_search=True)[0]#CODE (create red button)red_button = create.create_object(red_button.RedButton, key="Red button", location=limbo, aliases=["button"])# caller points to the one running the script caller.msg("A red button was created.")#CODE (create table and chair) table, chairtable = create.create_object(baseobjects.Object, key="Blue Table", location=limbo) chair = create.create_object(baseobjects.Object, key="Blue Chair", location=limbo)string = "A %s and %s were created. If debug was active, they were deleted again." caller.msg(string % (table, chair))
|
||||
##HEADER# This will be included in all other #CODE blocksfrom src.utils import create, search
|
||||
from game.gamesrc.objects.examples import red_button
|
||||
from game.gamesrc.objects import baseobjectslimbo = search.objects(caller, 'Limbo', global_search=True)[0]#CODE (create red button)red_button = create.create_object(red_button.RedButton, key="Red button",
|
||||
location=limbo, aliases=["button"])# caller points to the one running the script
|
||||
caller.msg("A red button was created.")#CODE (create table and chair) table, chairtable = create.create_object(baseobjects.Object, key="Blue Table", location=limbo)
|
||||
chair = create.create_object(baseobjects.Object, key="Blue Chair", location=limbo)string = "A %s and %s were created. If debug was active, they were deleted again."
|
||||
caller.msg(string % (table, chair))
|
||||
|
||||
This uses Evennia's Python API to create three objects in sequence.
|
||||
|
||||
|
|
@ -137,7 +143,11 @@ batch-processor version of ``look``).
|
|||
|
||||
::
|
||||
|
||||
from src.utils import create, search from game.gamesrc.objects.examples import red_button from game.gamesrc.objects import baseobjectslimbo = search.objects(caller, 'Limbo', global_search=True)[0]red_button = create.create_object(red_button.RedButton, key="Red button", location=limbo, aliases=["button"])# caller points to the one running the script caller.msg("A red button was created.")
|
||||
from src.utils import create, search
|
||||
from game.gamesrc.objects.examples import red_button
|
||||
from game.gamesrc.objects import baseobjectslimbo = search.objects(caller, 'Limbo', global_search=True)[0]red_button = create.create_object(red_button.RedButton, key="Red button",
|
||||
location=limbo, aliases=["button"])# caller points to the one running the script
|
||||
caller.msg("A red button was created.")
|
||||
|
||||
Compare with the example code given earlier. Notice how the content of
|
||||
``#HEADER`` has been pasted at the top of the ``#CODE`` block. Use
|
||||
|
|
|
|||
|
|
@ -60,7 +60,21 @@ Below is a version of the example file found in
|
|||
|
||||
::
|
||||
|
||||
# # This is an example batch build file for Evennia. ## This creates a red button button@create button:examples.red_button.RedButton# (This comment ends input for @create) # Next command. Let's create something. @set button/desc = This is a large red button. Now and then it flashes in an evil, yet strangely tantalizing way. A big sign sits next to it. It says:----------- Press me! ----------- ... It really begs to be pressed! You know you want to! # (This ends the @set command). Note that single line breaks # and extra whitespace in the argument are ignored. Empty lines # translate into line breaks in the output. # Now let's place the button where it belongs (let's say limbo #2 is # the evil lair in our example)@teleport #2# (This comments ends the @teleport command.) # Now we drop it so others can see it. # The very last command in the file needs not be ended with #.drop button
|
||||
#
|
||||
# This is an example batch build file for Evennia.
|
||||
## This creates a red button button@create button:examples.red_button.RedButton# (This comment ends input for @create)
|
||||
# Next command. Let's create something. @set button/desc =
|
||||
This is a large red button. Now and then
|
||||
it flashes in an evil, yet strangely tantalizing way. A big sign sits next to it. It says:----------- Press me! ----------- ... It really begs to be pressed! You
|
||||
know you want to!
|
||||
|
||||
# (This ends the @set command). Note that single line breaks
|
||||
# and extra whitespace in the argument are ignored. Empty lines
|
||||
# translate into line breaks in the output.
|
||||
# Now let's place the button where it belongs (let's say limbo #2 is
|
||||
# the evil lair in our example)@teleport #2# (This comments ends the @teleport command.)
|
||||
# Now we drop it so others can see it.
|
||||
# The very last command in the file needs not be ended with #.drop button
|
||||
|
||||
To test this, run ``@batchcommand`` on the file. A button will be
|
||||
created, described and dropped in Limbo. All commands will be executed
|
||||
|
|
|
|||
|
|
@ -101,7 +101,8 @@ you log in as another user than #1 and try to get the box now:
|
|||
|
||||
::
|
||||
|
||||
> get box You can't get that.
|
||||
> get box
|
||||
You can't get that.
|
||||
|
||||
Think the default error message looks dull? The ``get`` command looks
|
||||
for an `Attribute <Attributes.html>`_ named ``get_err_msg`` for
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@ mark colour:
|
|||
|
||||
::
|
||||
|
||||
This is a %crRed text%cn This is normal text again. %cRThis text has red background%cn this is normal text.
|
||||
This is a %crRed text%cn This is normal text again.
|
||||
%cRThis text has red background%cn this is normal text.
|
||||
|
||||
``%c#`` - markup works like a switch that is on until you actively turn
|
||||
it off with ``%cn`` (this returns the text to your default setting).
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ of the look command, followed by the prompt. As an example:
|
|||
|
||||
::
|
||||
|
||||
> look You see nothing special. HP:10, SP:20, MP: 5
|
||||
> look
|
||||
You see nothing special.
|
||||
HP:10, SP:20, MP: 5
|
||||
|
||||
MUD clients can be set to detect prompts like this and display them in
|
||||
various client-specific ways.
|
||||
|
|
@ -31,7 +33,12 @@ administration for example).
|
|||
|
||||
::
|
||||
|
||||
class MyCommand(Command): [...] def at_post_cmd(self): # we assume health/stamina/magic are just stored # as simple attributes on the character. hp = self.caller.db.hp sp = self.caller.db.sp mp = self.caller.db.mp self.caller.msg("HP: %i, SP: %i, MP: %i" % (hp, sp, mp))
|
||||
class MyCommand(Command): [...] def at_post_cmd(self):
|
||||
|
||||
# we assume health/stamina/magic are just stored
|
||||
# as simple attributes on the character. hp = self.caller.db.hp
|
||||
sp = self.caller.db.sp
|
||||
mp = self.caller.db.mp self.caller.msg("HP: %i, SP: %i, MP: %i" % (hp, sp, mp))
|
||||
|
||||
Prompt on the same line
|
||||
-----------------------
|
||||
|
|
@ -41,7 +48,8 @@ return of every command, on the same line:
|
|||
|
||||
::
|
||||
|
||||
> look HP: 10, SP:20, MP:5 -- You see nothing special.
|
||||
> look
|
||||
HP: 10, SP:20, MP:5 -- You see nothing special.
|
||||
|
||||
Now, there is an ``at_pre_cmd()`` hook analogous to the hook from last
|
||||
section except called just *before* parsing of the command. But putting
|
||||
|
|
@ -50,7 +58,9 @@ before* the function return:
|
|||
|
||||
::
|
||||
|
||||
> look HP:10, SP:20, MP: 5 You see nothing special.
|
||||
> look
|
||||
HP:10, SP:20, MP: 5
|
||||
You see nothing special.
|
||||
|
||||
... which might be cool too, but not what we wanted. To have the prompt
|
||||
appear on the same line as the return this, we need to change how
|
||||
|
|
@ -63,7 +73,8 @@ player. This is defined in ``src/objects/models.py``, on the
|
|||
|
||||
::
|
||||
|
||||
def msg(self, outgoing_message, from_obj=None, data=None): ...
|
||||
def msg(self, outgoing_message, from_obj=None, data=None):
|
||||
...
|
||||
|
||||
The only argument we are interested in here is the ``outgoing_message``,
|
||||
which contains the text that is about to be passed on to the player. We
|
||||
|
|
@ -74,7 +85,13 @@ custom Character typeclass add this:
|
|||
|
||||
::
|
||||
|
||||
def msg(self, outgoing_message, from_obj=None, data=None): # prepend the prompt in front of the message hp = self.db.hp sp = self.db.sp mp = self.db.mp prompt = "%i, %i, %i -- " % (hp, sp, mp) outgoing_message = prompt + outgoing_message # pass this on to the original msg() method on the database object self.dbobj.msg(outgoing_message, from_obj=from_obj, data=data)
|
||||
def msg(self, outgoing_message, from_obj=None, data=None):
|
||||
|
||||
# prepend the prompt in front of the message hp = self.db.hp
|
||||
sp = self.db.sp
|
||||
mp = self.db.mp
|
||||
prompt = "%i, %i, %i -- " % (hp, sp, mp)
|
||||
outgoing_message = prompt + outgoing_message # pass this on to the original msg() method on the database object self.dbobj.msg(outgoing_message, from_obj=from_obj, data=data)
|
||||
|
||||
Note that this solution will *always* give you the prompt, also if you
|
||||
use admin commands, which could get annoying. You might want to have
|
||||
|
|
|
|||
|
|
@ -124,17 +124,42 @@ to take one example.
|
|||
pre-parsed input to actually do whatever the command is supposed to do.
|
||||
This is the main body of the command.
|
||||
|
||||
Finally, you should always make an informative ```__doc__``
|
||||
Finally, you should always make an informative `doc
|
||||
string <http://www.python.org/dev/peps/pep-0257/#what-is-a-docstring>`_
|
||||
at the top of your class. This string is dynamically read 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.
|
||||
(``__doc__``) at the top of your class. This string is dynamically read
|
||||
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:
|
||||
|
||||
::
|
||||
|
||||
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 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'...")
|
||||
|
||||
The power of having commands as classes and to separate ``parse()`` and
|
||||
``func()`` lies in the ability to inherit functionality without having
|
||||
|
|
@ -191,7 +216,17 @@ 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 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())
|
||||
|
||||
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
|
||||
|
|
@ -199,7 +234,10 @@ as if you added them line by line:
|
|||
|
||||
::
|
||||
|
||||
at_cmdset_creation(): ... self.add(AdditionalCmdSet) # adds all command from this set ...
|
||||
at_cmdset_creation():
|
||||
...
|
||||
self.add(AdditionalCmdSet) # adds all command from this set
|
||||
...
|
||||
|
||||
If you added your command to an existing cmdset (like to the default
|
||||
cmdset), that set is already loaded into memory. You need to make the
|
||||
|
|
@ -261,7 +299,19 @@ 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 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)
|
||||
|
||||
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
|
||||
|
|
@ -278,7 +328,10 @@ This is what we have now:
|
|||
::
|
||||
|
||||
from game.gamesrc.commands.basecmdset import CmdSet
|
||||
from game.gamesrc.commands import mycommandclass MyCmdSet(CmdSet): key = "MyCmdSet" def at_cmdset_creation(self): self.add(mycommand.MyCommand())
|
||||
from game.gamesrc.commands import mycommandclass MyCmdSet(CmdSet):
|
||||
|
||||
key = "MyCmdSet" def at_cmdset_creation(self):
|
||||
self.add(mycommand.MyCommand())
|
||||
|
||||
This new command set could of course contain any number of commands. We
|
||||
will now temporarily *merge* this command set to your current set. This
|
||||
|
|
@ -342,7 +395,15 @@ class 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/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())
|
||||
|
||||
Again, you need to run the ``@reload`` command to make these changes
|
||||
available.
|
||||
|
|
@ -431,7 +492,8 @@ Same-key commands are merged by priority.
|
|||
|
||||
::
|
||||
|
||||
# Union A1,A2 + B1,B2,B3,B4 = A1,A2,B3,B4
|
||||
# Union
|
||||
A1,A2 + B1,B2,B3,B4 = A1,A2,B3,B4
|
||||
|
||||
**Intersect** - Only commands found in *both* cmdsets (i.e. which have
|
||||
the same keys) end up in the merged cmdset, with the higher-priority
|
||||
|
|
@ -439,7 +501,8 @@ cmdset replacing the lower one's commands.
|
|||
|
||||
::
|
||||
|
||||
# Intersect A1,A3,A5 + B1,B2,B4,B5 = A1,A5
|
||||
# Intersect
|
||||
A1,A3,A5 + B1,B2,B4,B5 = A1,A5
|
||||
|
||||
**Replace** - The commands of the higher-prio cmdset completely replaces
|
||||
the lower-priority cmdset's commands, regardless of if same-key commands
|
||||
|
|
@ -447,7 +510,8 @@ exist or not.
|
|||
|
||||
::
|
||||
|
||||
# Replace A1,A3 + B1,B2,B4,B5 = A1,A3
|
||||
# Replace
|
||||
A1,A3 + B1,B2,B4,B5 = A1,A3
|
||||
|
||||
**Remove** - The high-priority command sets removes same-key commands
|
||||
from the lower-priority cmdset. They are not replaced with anything, so
|
||||
|
|
@ -456,7 +520,8 @@ high-prio one as a template.
|
|||
|
||||
::
|
||||
|
||||
# Remove A1,A3 + B1,B2,B3,B4,B5 = B2,B4,B5
|
||||
# Remove
|
||||
A1,A3 + B1,B2,B3,B4,B5 = B2,B4,B5
|
||||
|
||||
Besides ``priority`` and ``mergetype``, a command set also takes a few
|
||||
other variables to control how they merge:
|
||||
|
|
@ -483,7 +548,17 @@ More advanced cmdset example:
|
|||
|
||||
::
|
||||
|
||||
class MyCmdSet(CmdSet): key = "MyCmdSet" priority = 4 mergetype = "Replace" key_mergetype = 'MyOtherCmdSet':'Union' 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())
|
||||
class MyCmdSet(CmdSet): key = "MyCmdSet"
|
||||
priority = 4
|
||||
mergetype = "Replace"
|
||||
key_mergetype = 'MyOtherCmdSet':'Union' 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())
|
||||
|
||||
System commands
|
||||
---------------
|
||||
|
|
@ -534,7 +609,12 @@ 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 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!")
|
||||
|
||||
How commands actually work
|
||||
--------------------------
|
||||
|
|
|
|||
|
|
@ -80,7 +80,12 @@ send a non-persistent message, also if you send it a ``Msg`` object.
|
|||
|
||||
::
|
||||
|
||||
# assume we have a 'sender' object and a channel named 'mychan'# send and store in database from src.utils import create mymsg = create.create_message(sender, "Hello!", channels=[mychan]) mychan.msg(mymsg)# send a one-time message mychan.msg("Hello!")# send a one-time message created from a Msg object mychan.tempmsg(mymsg)
|
||||
# assume we have a 'sender' object and a channel named 'mychan'# send and store in database
|
||||
from src.utils import create
|
||||
mymsg = create.create_message(sender, "Hello!", channels=[mychan])
|
||||
mychan.msg(mymsg)# send a one-time message
|
||||
mychan.msg("Hello!")# send a one-time message created from a Msg object
|
||||
mychan.tempmsg(mymsg)
|
||||
|
||||
As a more advanced note, sending text to channels is a "special
|
||||
exception" as far as commands are concerned, and you may completely
|
||||
|
|
|
|||
|
|
@ -8,7 +8,11 @@ tells you how to connect.
|
|||
::
|
||||
|
||||
==============================================================
|
||||
Welcome to Evennia, version SVN-Alpha! If you have an existing account, connect to it by typing: connect <email> <password> If you need to create an account, type (without the <>'s): create "<username>" <email> <password> Enter help for more info. look will re-show this screen. ==============================================================
|
||||
Welcome to Evennia, version SVN-Alpha! If you have an existing account, connect to it by typing:
|
||||
connect <email> <password>
|
||||
If you need to create an account, type (without the <>'s):
|
||||
create "<username>" <email> <password> Enter help for more info. look will re-show this screen.
|
||||
==============================================================
|
||||
|
||||
Effective, but not very exciting. You will most likely want to change
|
||||
this to be more unique for your game.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -61,7 +61,24 @@ the server.
|
|||
|
||||
game/
|
||||
evennia.py
|
||||
manage.py gamesrc/ commands/ basecommand.py basecmdset.py examples/ cmdset_red_button.py scripts/ basescript.py examples/ red_button_sripts.py objects/ baseobjects.py examples/ red_button.py world/ examples/ batch_cmds.ev batch_code.py
|
||||
manage.py gamesrc/
|
||||
commands/
|
||||
basecommand.py
|
||||
basecmdset.py
|
||||
examples/
|
||||
cmdset_red_button.py
|
||||
scripts/
|
||||
basescript.py
|
||||
examples/
|
||||
red_button_sripts.py
|
||||
objects/
|
||||
baseobjects.py
|
||||
examples/
|
||||
red_button.py
|
||||
world/
|
||||
examples/
|
||||
batch_cmds.ev
|
||||
batch_code.py
|
||||
|
||||
``game/gamesrc/``
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
|
@ -137,7 +154,17 @@ bugs or features missing, file a bug report or send us a message.
|
|||
::
|
||||
|
||||
src/
|
||||
settings_defaults.py commands/ comms/ help/ objects/ locks/ players/ scripts/ server/ typeclasses/ utils/ web/
|
||||
settings_defaults.py commands/
|
||||
comms/
|
||||
help/
|
||||
objects/
|
||||
locks/
|
||||
players/
|
||||
scripts/
|
||||
server/
|
||||
typeclasses/
|
||||
utils/
|
||||
web/
|
||||
|
||||
Most of the folders in ``src/`` are technically "Django apps",
|
||||
identified by containing a file ``models.py`` and usually
|
||||
|
|
|
|||
|
|
@ -116,7 +116,9 @@ Example of new command definition:
|
|||
|
||||
::
|
||||
|
||||
class CmdTest(Command): def func(self): self.caller.msg("This is the test!")
|
||||
class CmdTest(Command):
|
||||
def func(self):
|
||||
self.caller.msg("This is the test!")
|
||||
|
||||
Events + States -> Scripts
|
||||
--------------------------
|
||||
|
|
@ -262,14 +264,16 @@ just do:
|
|||
|
||||
::
|
||||
|
||||
obj.db.attr = value value = obj.db.attr
|
||||
obj.db.attr = value
|
||||
value = obj.db.attr
|
||||
|
||||
And for storing something non-persistently (stored only until the server
|
||||
reboots) you can just do
|
||||
|
||||
::
|
||||
|
||||
obj.attr = value value = obj.attr
|
||||
obj.attr = value
|
||||
value = obj.attr
|
||||
|
||||
The last example may sound trivial, but it's actually impossible to do
|
||||
in trunk since django objects are not guaranteed to remain the same
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ entrust to just anybody.
|
|||
|
||||
::
|
||||
|
||||
@py 1+2 <<< 3
|
||||
@py 1+2
|
||||
<<< 3
|
||||
|
||||
Available variables
|
||||
-------------------
|
||||
|
|
@ -36,7 +37,8 @@ found in ``src/utils/utils.py``:
|
|||
|
||||
::
|
||||
|
||||
@py from src.utils import utils; utils.time_format(33333) <<< Done.
|
||||
@py from src.utils import utils; utils.time_format(33333)
|
||||
<<< Done.
|
||||
|
||||
Note that we didn't get any return value, all we where told is that the
|
||||
code finished executing without error. This is often the case in more
|
||||
|
|
@ -46,7 +48,9 @@ system to echo it to us explicitly with ``self.msg()``.
|
|||
|
||||
::
|
||||
|
||||
@py from src.utils import utils; self.msg(utils.time_format(33333)) 09:15 <<< Done.
|
||||
@py from src.utils import utils; self.msg(utils.time_format(33333))
|
||||
09:15
|
||||
<<< Done.
|
||||
|
||||
If you were to use Python's standard ``print``, you will see the result
|
||||
in your current ``stdout`` (your terminal by default), *if* you are
|
||||
|
|
@ -63,7 +67,10 @@ Locating an object is best done using ``self.search()``:
|
|||
|
||||
::
|
||||
|
||||
@py self.search("red_ball") <<< Ball @py self.search("red_ball").db.color = "red" <<< Done. @py self.search("red_ball").db.color <<< red
|
||||
@py self.search("red_ball")
|
||||
<<< Ball @py self.search("red_ball").db.color = "red"
|
||||
<<< Done. @py self.search("red_ball").db.color
|
||||
<<< red
|
||||
|
||||
``self.search()`` is by far the most used case, but you can also search
|
||||
other database tables for other Evennia entities like scripts or
|
||||
|
|
@ -72,7 +79,8 @@ entries found in ``src.utils.search``.
|
|||
|
||||
::
|
||||
|
||||
@py from src.utils import search; self.msg(search.scripts("sys_game_time")) <<< [<src.utils.gametime.GameTime object at 0x852be2c>]
|
||||
@py from src.utils import search; self.msg(search.scripts("sys_game_time"))
|
||||
<<< [<src.utils.gametime.GameTime object at 0x852be2c>]
|
||||
|
||||
You can also use the database model managers directly (accessible
|
||||
through the ``objects`` properties of database models). This is a bit
|
||||
|
|
@ -81,7 +89,8 @@ search methods defined in each manager.
|
|||
|
||||
::
|
||||
|
||||
@py ScriptDB.objects.script_search("sys_game_time") <<< [<src.utils.gametime.GameTime object at 0x852be2c>]
|
||||
@py ScriptDB.objects.script_search("sys_game_time")
|
||||
<<< [<src.utils.gametime.GameTime object at 0x852be2c>]
|
||||
|
||||
(Note that since this second example becomes a simple statement, we
|
||||
don't have to wrap it in ``self.msg()`` to get the output). If you want
|
||||
|
|
@ -92,7 +101,8 @@ contents of the database using normal Django query operations:
|
|||
|
||||
::
|
||||
|
||||
@py ConfigValue.objects.all() <<< [<ConfigValue: default_home]>, <ConfigValue:site_name>, ...]
|
||||
@py ConfigValue.objects.all()
|
||||
<<< [<ConfigValue: default_home]>, <ConfigValue:site_name>, ...]
|
||||
|
||||
In doing so however, keep in mind the difference between `Typeclasses
|
||||
and Database Objects <Typeclasses.html>`_: Using the search commands in
|
||||
|
|
@ -104,7 +114,13 @@ most situations.
|
|||
|
||||
::
|
||||
|
||||
# this uses Evennia's manager method get_id(). # It returns a Character typeclass instance @py ObjectDB.objects.get_id(1).__class__ <<< Character# this uses the standard Django get() query. # It returns a django database model instance. @py ObjectDB.objects.get(id=1).__class__ <<< <class 'src.objects.models.ObjectDB'>
|
||||
# this uses Evennia's manager method get_id().
|
||||
# It returns a Character typeclass instance
|
||||
@py ObjectDB.objects.get_id(1).__class__
|
||||
<<< Character# this uses the standard Django get() query.
|
||||
# It returns a django database model instance.
|
||||
@py ObjectDB.objects.get(id=1).__class__
|
||||
<<< <class 'src.objects.models.ObjectDB'>
|
||||
|
||||
Running a Python Parser outside the game
|
||||
========================================
|
||||
|
|
@ -129,5 +145,8 @@ tab-completion and ``__doc__``-string reading.
|
|||
|
||||
::
|
||||
|
||||
$ python manage.py shellIPython 0.10 -- An enhanced Interactive Python ...In [1]: from src.objects.models import ObjectDB In [2]: ObjectDB.objects.all() Out[3]: [<ObjectDB: Harry>, <ObjectDB: Limbo>, ...]
|
||||
$ python manage.py shellIPython 0.10 -- An enhanced Interactive Python
|
||||
...In [1]: from src.objects.models import ObjectDB
|
||||
In [2]: ObjectDB.objects.all()
|
||||
Out[3]: [<ObjectDB: Harry>, <ObjectDB: Limbo>, ...]
|
||||
|
||||
|
|
|
|||
|
|
@ -288,14 +288,18 @@ isolated new folder *mudenv*:
|
|||
|
||||
::
|
||||
|
||||
python virtualenv mudenv --no-site-packages cd mudenv
|
||||
python virtualenv mudenv --no-site-packages
|
||||
cd mudenv
|
||||
|
||||
Now we should be in our new directory *mudenv*. Next we activate the
|
||||
virtual environment in here.
|
||||
|
||||
::
|
||||
|
||||
# for Linux: source bin/activate # for Windows: <path_to_this_place>\bin\activate.bat
|
||||
# for Linux:
|
||||
source bin/activate
|
||||
# for Windows:
|
||||
<path_to_this_place>\bin\activate.bat
|
||||
|
||||
In here you can play around and install python packages of any version
|
||||
without affecting your normal system installation at all. Next we get
|
||||
|
|
|
|||
|
|
@ -48,7 +48,16 @@ Example (from a module with command definitions):
|
|||
|
||||
::
|
||||
|
||||
class CmdMyCmd(Command): """ mycmd - my very own command Usage: mycmd[/switches] <args> Switches: test - test the command run - do something else This is my own command that does things to you when you supply it with arguments. """ ... help_category = "Building" ...
|
||||
class CmdMyCmd(Command):
|
||||
"""
|
||||
mycmd - my very own command Usage:
|
||||
mycmd[/switches] <args> Switches:
|
||||
test - test the command
|
||||
run - do something else This is my own command that does things to you when you
|
||||
supply it with arguments. """
|
||||
...
|
||||
help_category = "Building"
|
||||
...
|
||||
|
||||
So the text at the very top of the command class definition is the
|
||||
class' ``__doc__``-string and what will be shown to users looking for
|
||||
|
|
@ -87,7 +96,10 @@ You can create new help entries in code by using
|
|||
|
||||
::
|
||||
|
||||
from src.utils import create entry = create.create_help_entry("emote", "Emoting is important because ...", category="Roleplaying", locks="view:all()"):
|
||||
from src.utils import create
|
||||
entry = create.create_help_entry("emote",
|
||||
"Emoting is important because ...",
|
||||
category="Roleplaying", locks="view:all()"):
|
||||
|
||||
From inside the game those with the right permissions can use the
|
||||
``@sethelp`` command to add and modify help entries.
|
||||
|
|
|
|||
|
|
@ -85,7 +85,8 @@ Write something in the Evennia channel *irc*.
|
|||
|
||||
::
|
||||
|
||||
irc Hello, World! [irc] Anna: Hello, World!
|
||||
irc Hello, World!
|
||||
[irc] Anna: Hello, World!
|
||||
|
||||
If you are viewing your IRC channel with a separate IRC client you
|
||||
should see your text appearing there, spoken by the bot:
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ your ``game/settings.py`` file:
|
|||
|
||||
::
|
||||
|
||||
USE_I18N = True LANGUAGE_CODE = 'en'
|
||||
USE_I18N = True
|
||||
LANGUAGE_CODE = 'en'
|
||||
|
||||
Here ``'en'`` should be changed to the abbreviation for one of the
|
||||
supported languages found in ``locale/``. Restart the server to activate
|
||||
|
|
|
|||
|
|
@ -54,7 +54,9 @@ how it would (and do) look from inside the ``@delete`` command:
|
|||
|
||||
::
|
||||
|
||||
if not obj.access(accessing_obj, 'delete'): accessing_obj.msg("Sorry, you may not delete that.") return
|
||||
if not obj.access(accessing_obj, 'delete'):
|
||||
accessing_obj.msg("Sorry, you may not delete that.")
|
||||
return
|
||||
|
||||
Defining locks
|
||||
--------------
|
||||
|
|
@ -77,7 +79,9 @@ some much nicer examples:
|
|||
|
||||
::
|
||||
|
||||
delete:id(34) # only allow obj #34 to delete edit:all() # let everyone edit get: not attr(very_weak) or perm(Wizard) # only those who are not "very_weak" or are Wizards may pick this up
|
||||
delete:id(34) # only allow obj #34 to delete
|
||||
edit:all() # let everyone edit
|
||||
get: not attr(very_weak) or perm(Wizard) # only those who are not "very_weak" or are Wizards may pick this up
|
||||
|
||||
So, a lockstring consists of the type of restriction (the
|
||||
``access_type``), a colon (``:``) and then a list of function calls that
|
||||
|
|
@ -174,7 +178,11 @@ appear as extra arguments.
|
|||
|
||||
::
|
||||
|
||||
# A simple example lock function. Called with e.g. id(34)def id(accessing_obj, accessed_obj, *args, **kwargs): if args: wanted_id = args[0] return accessing_obj.id == wanted_id return False
|
||||
# A simple example lock function. Called with e.g. id(34)def id(accessing_obj, accessed_obj, *args, **kwargs):
|
||||
if args:
|
||||
wanted_id = args[0]
|
||||
return accessing_obj.id == wanted_id
|
||||
return False
|
||||
|
||||
(Using the ``*`` and ``**`` syntax causes Python to magically put all
|
||||
extra arguments into a list ``args``and all keyword arguments into a
|
||||
|
|
@ -197,14 +205,9 @@ Some useful default lockfuncs (see lockfuncs.py for a full list):
|
|||
- ``attr(attrname, value)`` - checks so an attribute exists on
|
||||
accessing*object*and has the given value.
|
||||
- ``attr_gt(attrname, value)`` - checks so accessingobject has a value
|
||||
larger (>) than the given value.
|
||||
- ``attr_ge, attr_lt, attr_le, attr_ne`` - corresponding for >
|
||||
|
||||
, <, <
|
||||
======
|
||||
|
||||
and !=.
|
||||
|
||||
larger (``>``) than the given value.
|
||||
- ``attr_ge, attr_lt, attr_le, attr_ne`` - corresponding for ``>=``,
|
||||
``<``, ``<=`` and ``!=``.
|
||||
- ``holds(objid)`` - checks so the accessing objects contains an object
|
||||
of given name or dbref.
|
||||
- ``pperm(perm)``, ``pid(num)/pdbref(num)`` - same as ``perm``,
|
||||
|
|
@ -247,7 +250,11 @@ default permission hierarchy is as follows:
|
|||
|
||||
::
|
||||
|
||||
Immortals Wizards Builders PlayerHelpers Players # this is what all new Players start with by default
|
||||
Immortals
|
||||
Wizards
|
||||
Builders
|
||||
PlayerHelpers
|
||||
Players # this is what all new Players start with by default
|
||||
|
||||
The main use of this is that if you use the lock function ``perm()``
|
||||
mentioned above, a lock check for a particular permission in the
|
||||
|
|
@ -260,7 +267,8 @@ looked for is not in the hierarchy, an exact match is required.
|
|||
|
||||
::
|
||||
|
||||
obj1.permissions = ["Builders", "cool_guy"] obj2.locks.add("enter:perm_above(Players) and perm(cool_guy)")obj2.access(obj1, "enter") # this returns True!
|
||||
obj1.permissions = ["Builders", "cool_guy"]
|
||||
obj2.locks.add("enter:perm_above(Players) and perm(cool_guy)")obj2.access(obj1, "enter") # this returns True!
|
||||
|
||||
Superusers
|
||||
----------
|
||||
|
|
@ -330,7 +338,8 @@ other is an `Object <Objects.html>`_ called ``box``.
|
|||
|
||||
::
|
||||
|
||||
> @create/drop box > @desc box = "This is a very big and heavy box."
|
||||
> @create/drop box
|
||||
> @desc box = "This is a very big and heavy box."
|
||||
|
||||
We want to limit which objects can pick up this heavy box. Let's say
|
||||
that to do that we require the would-be lifter to to have an attribute
|
||||
|
|
@ -349,7 +358,12 @@ this snippet:
|
|||
|
||||
::
|
||||
|
||||
if not obj.access(caller, 'get'): if obj.db.get_err_msg: caller.msg(obj.db.get_err_msg) else: caller.msg("You can't get that.") return
|
||||
if not obj.access(caller, 'get'):
|
||||
if obj.db.get_err_msg:
|
||||
caller.msg(obj.db.get_err_msg)
|
||||
else:
|
||||
caller.msg("You can't get that.")
|
||||
return
|
||||
|
||||
So the ``get`` command looks for a lock with the type *get* (not so
|
||||
surprising). It also looks for an `Attribute <Attributes.html>`_ on the
|
||||
|
|
@ -367,7 +381,7 @@ checks if attributes have a value greater than a given value. Luckily
|
|||
there is already such a one included in evennia (see
|
||||
``src/permissions/lockfuncs.py``), called``attr_gt``.
|
||||
|
||||
So the lock string will look like this: "``get:attr_gt(strength, 50)``".
|
||||
So the lock string will look like this: ``get:attr_gt(strength, 50)``.
|
||||
We put this on the box now:
|
||||
|
||||
::
|
||||
|
|
@ -383,7 +397,9 @@ like this:
|
|||
|
||||
::
|
||||
|
||||
from src.utils import create box = create.create_object(None, key="box", locks="get:attr_gt(strength, 50)")# or, if we don't set the locks right awaybox.locks.add("get:attr_gt(strength, 50)")# set the attributesbox.db.desc = "This is a very big and heavy box." box.db.get_err_msg = "You are not strong enough to lift this box."# one heavy box, ready to withstand all but the strongest...
|
||||
from src.utils import create
|
||||
box = create.create_object(None, key="box", locks="get:attr_gt(strength, 50)")# or, if we don't set the locks right awaybox.locks.add("get:attr_gt(strength, 50)")# set the attributesbox.db.desc = "This is a very big and heavy box."
|
||||
box.db.get_err_msg = "You are not strong enough to lift this box."# one heavy box, ready to withstand all but the strongest...
|
||||
|
||||
On Django's permission system
|
||||
=============================
|
||||
|
|
|
|||
|
|
@ -83,7 +83,13 @@ checking, searches and conversion.
|
|||
|
||||
::
|
||||
|
||||
# A command/channel nick: object.nicks.add("greetjack", "tell Jack = Hello pal!")# An object nick: object.nicks.add("rose", "The red flower", nick_type="object")# An player nick: object.nicks("tom", "Tommy Hill", nick_type="player")# My own custom nick type (handled by my own game code somehow): object.nicks.add("hood", "The hooded man", nick_type="my_identsystem")# get back the translated nick: full_name = object.nicks.get("rose", nick_type="object")# delete a previous set nick object.nicks.del("rose", nick_type="object")
|
||||
# A command/channel nick:
|
||||
object.nicks.add("greetjack", "tell Jack = Hello pal!")# An object nick:
|
||||
object.nicks.add("rose", "The red flower", nick_type="object")# An player nick:
|
||||
object.nicks("tom", "Tommy Hill", nick_type="player")# My own custom nick type (handled by my own game code somehow):
|
||||
object.nicks.add("hood", "The hooded man", nick_type="my_identsystem")# get back the translated nick:
|
||||
full_name = object.nicks.get("rose", nick_type="object")# delete a previous set nick
|
||||
object.nicks.del("rose", nick_type="object")
|
||||
|
||||
In a command definition you can reach the nick handler through
|
||||
``self.caller.nicks``. See the ``nick`` command in
|
||||
|
|
|
|||
|
|
@ -19,7 +19,14 @@ Here's how to define a new Object typeclass in code:
|
|||
|
||||
::
|
||||
|
||||
from game.gamesrc.objects.baseobjects import Objectclass Rose(Object): """ This creates a simple rose object """ at_object_creation(self): "this is called only once, when object is first created" # add a persistent attribute 'desc' to object. self.db.desc = "This is a pretty rose with thorns."
|
||||
from game.gamesrc.objects.baseobjects import Objectclass Rose(Object):
|
||||
"""
|
||||
This creates a simple rose object
|
||||
"""
|
||||
at_object_creation(self):
|
||||
"this is called only once, when object is first created"
|
||||
# add a persistent attribute 'desc' to object.
|
||||
self.db.desc = "This is a pretty rose with thorns."
|
||||
|
||||
Save your class to a module under ``game/gamesrc/objects``, say
|
||||
``flowers.py``. Now you just need to point to the class *Rose* with the
|
||||
|
|
@ -34,7 +41,8 @@ To create a new object in code, use the method
|
|||
|
||||
::
|
||||
|
||||
from src.utils import create new_rose = create.create_object("game.gamesrc.objects.flowers.Rose", key="MyRose")
|
||||
from src.utils import create
|
||||
new_rose = create.create_object("game.gamesrc.objects.flowers.Rose", key="MyRose")
|
||||
|
||||
(You have to give the full path to the class in this case.
|
||||
``create.create_object`` is a powerful function that should be used for
|
||||
|
|
|
|||
|
|
@ -41,7 +41,15 @@ Here's how to define a new Player typeclass in code:
|
|||
|
||||
::
|
||||
|
||||
from src.players.player import Playerclass ConfigPlayer(Player): """ This creates a Player with some configuration options """ at_player_creation(self): "this is called only once, when player is first created" self.db.real_name = None # this is set later self.db.real_address = None # '' self.db.config_1 = True # default config self.db.config_2 = False # " self.db.config_3 = 1 # " # ... whatever our game needs to know
|
||||
from src.players.player import Playerclass ConfigPlayer(Player):
|
||||
"""
|
||||
This creates a Player with some configuration options
|
||||
"""
|
||||
at_player_creation(self):
|
||||
"this is called only once, when player is first created" self.db.real_name = None # this is set later
|
||||
self.db.real_address = None # '' self.db.config_1 = True # default config
|
||||
self.db.config_2 = False # "
|
||||
self.db.config_3 = 1 # " # ... whatever our game needs to know
|
||||
|
||||
There is no pre-made folder in ``game/gamesrc`` to store custom player
|
||||
typeclasses. Either make your own folder or store it in
|
||||
|
|
|
|||
|
|
@ -34,7 +34,10 @@ inheriting from ``game.gamesrc.objects.baseobjecs.Character``.
|
|||
|
||||
::
|
||||
|
||||
from game.gamesrc.objects.baseobjects import Characterclass ColourableCharacter(Character): at_object_creation(self): # set a colour config value self.db.config_colour = True
|
||||
from game.gamesrc.objects.baseobjects import Characterclass ColourableCharacter(Character):
|
||||
at_object_creation(self):
|
||||
# set a colour config value
|
||||
self.db.config_colour = True
|
||||
|
||||
Above we set a simple config value as an `attribute <Attributes.html>`_.
|
||||
|
||||
|
|
@ -74,7 +77,11 @@ original. Here's how it could look:
|
|||
|
||||
::
|
||||
|
||||
from src.utils import ansimsg(self, message, from_obj=None, data=None): "our custom msg()" if not self.db.config_colour: message = ansi.parse_ansi(message, strip_ansi=True) self.dbobj.msg(message, from_obj, data)
|
||||
from src.utils import ansimsg(self, message, from_obj=None, data=None):
|
||||
"our custom msg()"
|
||||
if not self.db.config_colour:
|
||||
message = ansi.parse_ansi(message, strip_ansi=True)
|
||||
self.dbobj.msg(message, from_obj, data)
|
||||
|
||||
Above we create a custom version of the ``msg()`` method that cleans all
|
||||
ansi characters if the config value is not set to True. Once that's
|
||||
|
|
@ -100,7 +107,22 @@ for configuration down the line).
|
|||
|
||||
::
|
||||
|
||||
from game.gamesrc.commands.basecommand import MuxCommandclass ConfigColourCmd(MuxCommand): """ Configures your colour Usage: @setcolour on|off This turns ansii-colours on/off. Default is on. """ key = "@setcolour" aliases = ["@setcolor"] def func(self): "Implements the command" if not self.args or not self.args in ("on", "off"): self.caller.msg("Usage: @setcolour on|off") return if self.args == "on": self.caller.db.config_colour = True else: self.caller.db.config_colour = False self.caller.msg("Colour was turned %s." % self.args)
|
||||
from game.gamesrc.commands.basecommand import MuxCommandclass ConfigColourCmd(MuxCommand):
|
||||
"""
|
||||
Configures your colour Usage:
|
||||
@setcolour on|off This turns ansii-colours on/off.
|
||||
Default is on.
|
||||
""" key = "@setcolour"
|
||||
aliases = ["@setcolor"] def func(self):
|
||||
"Implements the command"
|
||||
if not self.args or not self.args in ("on", "off"):
|
||||
self.caller.msg("Usage: @setcolour on|off")
|
||||
return
|
||||
if self.args == "on":
|
||||
self.caller.db.config_colour = True
|
||||
else:
|
||||
self.caller.db.config_colour = False
|
||||
self.caller.msg("Colour was turned %s." % self.args)
|
||||
|
||||
Lastly, we make this command available to the user by adding it to the
|
||||
default command set. Easiest is to add it to the end of
|
||||
|
|
@ -108,7 +130,14 @@ default command set. Easiest is to add it to the end of
|
|||
|
||||
::
|
||||
|
||||
from game.gamesrc.commands import configcmds class DefaultCmdSet(cmdset_default.DefaultCmdSet): key = "DefaultMUX" def at_cmdset_creation(self): super(DefaultCmdSet, self).at_cmdset_creation() self.add(configcmds.ConfigColourCmd())
|
||||
from game.gamesrc.commands import configcmds
|
||||
class DefaultCmdSet(cmdset_default.DefaultCmdSet):
|
||||
|
||||
key = "DefaultMUX"
|
||||
|
||||
def at_cmdset_creation(self):
|
||||
super(DefaultCmdSet, self).at_cmdset_creation()
|
||||
self.add(configcmds.ConfigColourCmd())
|
||||
|
||||
When adding a new command to a cmdset like this you need to run the
|
||||
``@reload`` command (or reboot the server). From here on out, your users
|
||||
|
|
|
|||
|
|
@ -132,7 +132,24 @@ find longer descriptions of these in ``gamesrc/scripts/basescript.py``.
|
|||
::
|
||||
|
||||
import random
|
||||
from game.gamesrc.scripts.basescript import Scriptclass Weather(Script): "Displays weather info. Meant to be attached to a room." def at_script_creation(self): "Called once, during initial creation" self.key = "weather_script" self.desc = "Gives random weather messages." self.interval = 60 * 5 # every 5 minutes self.persistent = True self.at_repeat(self): "called every self.interval seconds." rand = random.random() if rand < 0.5: weather = "A faint breeze is felt." elif rand < 0.7: weather = "Clouds sweep across the sky." else: weather = "There is a light drizzle of rain." # send this message to everyone inside the object this # script is attached to (likely a room) self.obj.msg_contents(weather)
|
||||
from game.gamesrc.scripts.basescript import Scriptclass Weather(Script):
|
||||
"Displays weather info. Meant to be attached to a room." def at_script_creation(self):
|
||||
"Called once, during initial creation"
|
||||
self.key = "weather_script"
|
||||
self.desc = "Gives random weather messages."
|
||||
self.interval = 60 * 5 # every 5 minutes
|
||||
self.persistent = True self.at_repeat(self):
|
||||
"called every self.interval seconds."
|
||||
rand = random.random()
|
||||
if rand < 0.5:
|
||||
weather = "A faint breeze is felt."
|
||||
elif rand < 0.7:
|
||||
weather = "Clouds sweep across the sky."
|
||||
else:
|
||||
weather = "There is a light drizzle of rain."
|
||||
# send this message to everyone inside the object this
|
||||
# script is attached to (likely a room)
|
||||
self.obj.msg_contents(weather)
|
||||
|
||||
This is a simple weather script that we can put on an object. Every 5
|
||||
minutes it will tell everyone inside that object how the weather is.
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@ retrieved when emitting:
|
|||
|
||||
::
|
||||
|
||||
&HELLO_VALUE.D me=Hello World &HELLO_WORLD.C me=$hello:@pemit %#=[v(HELLO_VALUE.D)]
|
||||
&HELLO_VALUE.D me=Hello World
|
||||
&HELLO_WORLD.C me=$hello:@pemit %#=[v(HELLO_VALUE.D)]
|
||||
|
||||
The v() function returns the HELLO\_VALUE.D attribute on the object that
|
||||
the command resides (``me``, which is yourself in this case). This
|
||||
|
|
|
|||
|
|
@ -43,7 +43,8 @@ You can also start the two components one at a time.
|
|||
|
||||
::
|
||||
|
||||
python evennia.py start server python evennia.py start portal
|
||||
python evennia.py start server
|
||||
python evennia.py start portal
|
||||
|
||||
Adding -i to either of these explicit commands will start that component
|
||||
in interactive mode so it logs to the terminal rather than to log file.
|
||||
|
|
@ -84,7 +85,8 @@ A reset is equivalent to
|
|||
|
||||
::
|
||||
|
||||
python evennia.py stop server python evennia.py start server
|
||||
python evennia.py stop server
|
||||
python evennia.py start server
|
||||
|
||||
Shutting down
|
||||
-------------
|
||||
|
|
|
|||
|
|
@ -238,7 +238,8 @@ query). You can easily convert between them with ``dbobj.typeclass`` and
|
|||
|
||||
::
|
||||
|
||||
obj = ObjectDB.objects.get_id(1) # custom evennia manager method. This returns the typeclass. obj = ObjectDB.objects.get(1) # standard Django. Returns a Django model object.
|
||||
obj = ObjectDB.objects.get_id(1) # custom evennia manager method. This returns the typeclass.
|
||||
obj = ObjectDB.objects.get(1) # standard Django. Returns a Django model object.
|
||||
|
||||
Even more important to know for Django affectionados: Evennia's custom
|
||||
methods return *lists* where you with normal Django methods would expect
|
||||
|
|
|
|||
|
|
@ -57,7 +57,25 @@ Example of a ``TestCase`` class (inside a file ``tests.py``):
|
|||
|
||||
::
|
||||
|
||||
# testing a simple funciontry: # this is an optimized version only available in later Django versions from django.utils.unittest import TestCase except ImportError: # if the first fail, we use the old version from django.test import TestCase# the function we want to test from mypath import myfuncTestObj(unittest.TestCase): "This tests a function myfunc." def test_return_value(self): "test method. Makes sure return value is as expected." expected_return = "This is me being nice." actual_return = myfunc() # test self.assertEqual(expected_return, actual_return) def test_alternative_call(self): "test method. Calls with a keyword argument." expected_return = "This is me being baaaad." actual_return = myfunc(bad=True) # test self.assertEqual(expected_return, actual_return)
|
||||
# testing a simple funciontry:
|
||||
# this is an optimized version only available in later Django versions
|
||||
from django.utils.unittest import TestCase
|
||||
except ImportError:
|
||||
# if the first fail, we use the old version
|
||||
from django.test import TestCase# the function we want to test
|
||||
from mypath import myfuncTestObj(unittest.TestCase):
|
||||
"This tests a function myfunc." def test_return_value(self):
|
||||
"test method. Makes sure return value is as expected."
|
||||
expected_return = "This is me being nice."
|
||||
actual_return = myfunc()
|
||||
# test
|
||||
self.assertEqual(expected_return, actual_return)
|
||||
def test_alternative_call(self):
|
||||
"test method. Calls with a keyword argument."
|
||||
expected_return = "This is me being baaaad."
|
||||
actual_return = myfunc(bad=True)
|
||||
# test
|
||||
self.assertEqual(expected_return, actual_return)
|
||||
|
||||
The above example is very simplistic, but you should get the idea. Look
|
||||
at ``src/objects/tests.py`` for more realistic examples of tests. You
|
||||
|
|
|
|||
14
docs/sphinx/wiki2rest/wiki2html.patch
Normal file
14
docs/sphinx/wiki2rest/wiki2html.patch
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
Index: wiki2html/lib/wiki_syntax.rb
|
||||
===================================================================
|
||||
--- wiki2html/lib/wiki_syntax.rb (revision 1961)
|
||||
+++ wiki2html/lib/wiki_syntax.rb (working copy)
|
||||
@@ -227,7 +227,8 @@
|
||||
block
|
||||
else
|
||||
# remove newlines within normal (non-code) blocks of text
|
||||
- "<p>" + block.gsub(/\n/, ' ') + "</p>"
|
||||
+ #"<p>" + block.gsub(/\n/, ' ') + "</p>"
|
||||
+ "<p>" + block + "</p>"
|
||||
end
|
||||
end.join
|
||||
end
|
||||
|
|
@ -11,6 +11,11 @@
|
|||
#
|
||||
# This is a ruby program! Sorry, it was the best match I could find to do this.
|
||||
# So if you don't have ruby, you need that too.
|
||||
#
|
||||
# You also need to patch a bug in above program to make code snippets work. From the wiki2rest folder,
|
||||
# apply the patch like this:
|
||||
#
|
||||
# patch -p0 -i wiki2html.patch
|
||||
#
|
||||
# 2) Install pandoc:
|
||||
#
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue