More whitespace cleanup.

This commit is contained in:
Griatch 2012-03-30 23:57:04 +02:00
parent c0322c9eae
commit 45c5be8468
43 changed files with 1116 additions and 1131 deletions

View file

@ -2,7 +2,7 @@
"""
EVENNIA SERVER STARTUP SCRIPT
This is the start point for running Evennia.
This is the start point for running Evennia.
Sets the appropriate environmental variables and launches the server
and portal through the runner. Run without arguments to get a
@ -47,12 +47,12 @@ if not os.path.exists('settings.py'):
When you are set up, run evennia.py again to start the server."""
sys.exit()
# signal processing
# signal processing
SIG = signal.SIGINT
HELPENTRY = \
"""
(version %s)
(version %s)
This program launches Evennia with various options. You can access all
this functionality directly from the command line; for example option
@ -83,7 +83,7 @@ directly see tracebacks on standard output, so starting with options
server (option 5) to make it available to users.
Reload and stop is not well supported in Windows. If you have issues, log
into the game to stop or restart the server instead.
into the game to stop or restart the server instead.
"""
MENU = \
@ -160,7 +160,7 @@ except DatabaseError:
Your database does not seem to be set up correctly.
Please run:
python manage.py syncdb
(make sure to create an admin user when prompted). If you use
@ -231,7 +231,7 @@ if os.name == 'nt':
# Functions
def get_pid(pidfile):
"""
Get the PID (Process ID) by trying to access
@ -319,7 +319,7 @@ def run_menu():
if inp == 5:
if os.name == 'nt':
print "This operation is not supported under Windows. Log into the game to restart/reload the server."
return
return
kill(SERVER_PIDFILE, SIG, "Server reloaded.", errmsg % "Server")
elif inp == 6:
if os.name == 'nt':
@ -353,8 +353,8 @@ def handle_args(options, mode, service):
errmsg = "The %s does not seem to be running."
if mode == 'start':
# launch the error checker. Best to catch the errors already here.
# launch the error checker. Best to catch the errors already here.
error_check_python_modules()
# starting one or many services
@ -376,13 +376,13 @@ def handle_args(options, mode, service):
# restarting services
if os.name == 'nt':
print "Restarting from command line is not supported under Windows. Log into the game to restart."
return
return
if service == 'server':
kill(SERVER_PIDFILE, SIG, "Server reloaded.", errmsg % 'Server')
elif service == 'portal':
print """
Note: Portal usually don't need to be reloaded unless you are debugging in interactive mode.
If Portal was running in default Daemon mode, it cannot be restarted. In that case you have
If Portal was running in default Daemon mode, it cannot be restarted. In that case you have
to restart it manually with 'evennia.py start portal'
"""
kill(PORTAL_PIDFILE, SIG, "Portal reloaded (or stopped, if it was in daemon mode).", errmsg % 'Portal', PORTAL_RESTART)
@ -408,7 +408,7 @@ def error_check_python_modules():
with exceptions in the engine (since they are formatting errors in
the python source files themselves). Best they fail already here
before we get any further.
"""
"""
def imp(path, split=True):
mod, fromlist = path, "None"
if split:
@ -473,12 +473,12 @@ def main():
# handle command-line arguments
cmdstr = handle_args(options, mode, service)
if cmdstr:
# call the runner.
# call the runner.
cmdstr.append('start')
Popen(cmdstr)
if __name__ == '__main__':
# start Evennia
# start Evennia
from src.utils.utils import check_evennia_dependencies
if check_evennia_dependencies():
main()

View file

@ -1,10 +1,10 @@
"""
Example command set template module.
Example command set template module.
To create new commands to populate the cmdset, see
examples/command.py.
To extend the default command set:
To extend the default command set:
- copy this file up one level to gamesrc/commands and name it
something fitting.
- change settings.CMDSET_DEFAULT to point to the new module's
@ -36,12 +36,12 @@ class ExampleCmdSet(CmdSet):
"""
Implements an empty, example cmdset.
"""
key = "ExampleSet"
def at_cmdset_creation(self):
"""
This is the only method defined in a cmdset, called during
This is the only method defined in a cmdset, called during
its creation. It should populate the set with command instances.
Here we just add the empty base Command object. It prints some info.
@ -51,7 +51,7 @@ class ExampleCmdSet(CmdSet):
class DefaultCmdSet(default_cmds.DefaultCmdSet):
"""
This is an example of how to overload the default command
This is an example of how to overload the default command
set defined in src/commands/default/cmdset_default.py.
Here we copy everything by calling the parent, but you can
@ -60,7 +60,7 @@ class DefaultCmdSet(default_cmds.DefaultCmdSet):
to this class.
"""
key = "DefaultMUX"
def at_cmdset_creation(self):
"""
Populates the cmdset
@ -72,8 +72,8 @@ class DefaultCmdSet(default_cmds.DefaultCmdSet):
# any commands you add below will overload the default ones.
#
#self.add(menusystem.CmdMenuTest())
#self.add(lineeditor.CmdEditor())
#self.add(misc_commands.CmdQuell())
#self.add(lineeditor.CmdEditor())
#self.add(misc_commands.CmdQuell())
class UnloggedinCmdSet(default_cmds.UnloggedinCmdSet):
"""
@ -87,25 +87,25 @@ class UnloggedinCmdSet(default_cmds.UnloggedinCmdSet):
point to this class.
"""
key = "Unloggedin"
def at_cmdset_creation(self):
"""
Populates the cmdset
"""
# calling setup in src.commands.default.cmdset_unloggedin
super(UnloggedinCmdSet, self).at_cmdset_creation()
#
# any commands you add below will overload the default ones.
#
class OOCCmdSet(default_cmds.OOCCmdSet):
"""
This is set is available to the player when they have no
This is set is available to the player when they have no
character connected to them (i.e. they are out-of-character, ooc).
"""
key = "OOC"
def at_cmdset_creation(self):
"""
Populates the cmdset
@ -114,9 +114,4 @@ class OOCCmdSet(default_cmds.OOCCmdSet):
super(OOCCmdSet, self).at_cmdset_creation()
#
# any commands you add below will overload the default ones.
#
#

View file

@ -1,13 +1,13 @@
"""
This defines the cmdset for the red_button. Here we have defined
the commands and the cmdset in the same module, but if you
have many different commands to merge it is often better
have many different commands to merge it is often better
to define the cmdset separately, picking and choosing from
among the available commands as to what should be included in the
among the available commands as to what should be included in the
cmdset - this way you can often re-use the commands too.
"""
import random
import random
from ev import Command, CmdSet
# Some simple commands for the red button
@ -19,14 +19,14 @@ from ev import Command, CmdSet
class CmdNudge(Command):
"""
Try to nudge the button's lid
Usage:
Usage:
nudge lid
This command will have you try to
push the lid of the button away.
This command will have you try to
push the lid of the button away.
"""
key = "nudge lid" # two-word command name!
aliases = ["nudge"]
locks = "cmd:all()"
@ -43,10 +43,10 @@ class CmdNudge(Command):
else:
self.caller.msg("You manage to get a nail under the lid.")
self.caller.execute_cmd("open lid")
class CmdPush(Command):
"""
Push the red button
Push the red button
Usage:
push button
@ -55,7 +55,7 @@ class CmdPush(Command):
key = "push button"
aliases = ["push", "press button", "press"]
locks = "cmd:all()"
def func(self):
"""
Note that we choose to implement this with checking for
@ -64,7 +64,7 @@ class CmdPush(Command):
An alternative would be to make two versions of this command
and tuck them into the cmdset linked to the Open and Closed
lid-state respectively.
lid-state respectively.
"""
@ -72,15 +72,15 @@ class CmdPush(Command):
string = "You reach out to press the big red button ..."
string += "\n\nA BOOM! A bright light blinds you!"
string += "\nThe world goes dark ..."
self.caller.msg(string)
self.caller.location.msg_contents("%s presses the button. BOOM! %s is blinded by a flash!" %
self.caller.msg(string)
self.caller.location.msg_contents("%s presses the button. BOOM! %s is blinded by a flash!" %
(self.caller.name, self.caller.name), exclude=self.caller)
# the button's method will handle all setup of scripts etc.
self.obj.press_button(self.caller)
self.obj.press_button(self.caller)
else:
string = "You cannot push the button - there is a glass lid covering it."
self.caller.msg(string)
class CmdSmashGlass(Command):
@ -92,15 +92,15 @@ class CmdSmashGlass(Command):
Try to smash the glass of the button.
"""
key = "smash glass"
aliases = ["smash lid", "break lid", "smash"]
locks = "cmd:all()"
def func(self):
"""
The lid won't open, but there is a small chance
of causing the lamp to break.
of causing the lamp to break.
"""
rand = random.random()
@ -109,11 +109,11 @@ class CmdSmashGlass(Command):
string += " with all your might. The lid won't budge"
string += " but you cause quite the tremor through the button's mount."
string += "\nIt looks like the button's lamp stopped working for the time being."
self.obj.lamp_works = False
self.obj.lamp_works = False
elif rand < 0.6:
string = "You hit the lid hard. It doesn't move an inch."
else:
string = "You place a well-aimed fist against the glass of the lid."
string = "You place a well-aimed fist against the glass of the lid."
string += " Unfortunately all you get is a pain in your hand. Maybe"
string += " you should just try to open the lid instead?"
self.caller.msg(string)
@ -125,7 +125,7 @@ class CmdOpenLid(Command):
open lid
Usage:
open lid
open lid
"""
@ -135,21 +135,21 @@ class CmdOpenLid(Command):
def func(self):
"simply call the right function."
if self.obj.db.lid_locked:
self.caller.msg("This lid seems locked in place for the moment.")
return
return
string = "\nA ticking sound is heard, like a winding mechanism. Seems "
string += "the lid will soon close again."
self.caller.msg(string)
self.caller.location.msg_contents("%s opens the lid of the button." %
self.caller.location.msg_contents("%s opens the lid of the button." %
(self.caller.name), exclude=self.caller)
# add the relevant cmdsets to button
# add the relevant cmdsets to button
self.obj.cmdset.add(LidClosedCmdSet)
# call object method
self.obj.open_lid()
class CmdCloseLid(Command):
"""
close the lid
@ -163,7 +163,7 @@ class CmdCloseLid(Command):
key = "close lid"
aliases = ["close"]
locks = "cmd:all()"
def func(self):
"Close the lid"
@ -171,9 +171,9 @@ class CmdCloseLid(Command):
# this will clean out scripts dependent on lid being open.
self.caller.msg("You close the button's lid. It clicks back into place.")
self.caller.location.msg_contents("%s closes the button's lid." %
self.caller.location.msg_contents("%s closes the button's lid." %
(self.caller.name), exclude=self.caller)
class CmdBlindLook(Command):
"""
Looking around in darkness
@ -185,14 +185,14 @@ class CmdBlindLook(Command):
"""
key = "look"
key = "look"
aliases = ["l", "get", "examine", "ex", "feel", "listen"]
locks = "cmd:all()"
def func(self):
"This replaces all the senses when blinded."
# we decide what to reply based on which command was
# we decide what to reply based on which command was
# actually tried
if self.cmdstring == "get":
@ -208,7 +208,7 @@ class CmdBlindLook(Command):
string = "You are temporarily blinded by the flash. "
string += "Until it wears off, all you can do is feel around blindly."
self.caller.msg(string)
self.caller.location.msg_contents("%s stumbles around, blinded." %
self.caller.location.msg_contents("%s stumbles around, blinded." %
(self.caller.name), exclude=self.caller)
class CmdBlindHelp(Command):
@ -220,7 +220,7 @@ class CmdBlindHelp(Command):
"""
key = "help"
aliases = "h"
aliases = "h"
locks = "cmd:all()"
def func(self):
@ -242,13 +242,13 @@ class DefaultCmdSet(CmdSet):
The default cmdset always sits
on the button object and whereas other
command sets may be added/merge onto it
and hide it, removing them will always
and hide it, removing them will always
bring it back. It's added to the object
using obj.cmdset.add_default().
"""
key = "RedButtonDefault"
mergetype = "Union" # this is default, we don't really need to put it here.
mergetype = "Union" # this is default, we don't really need to put it here.
def at_cmdset_creation(self):
"Init the cmdset"
self.add(CmdPush())
@ -260,13 +260,13 @@ class LidClosedCmdSet(CmdSet):
It contains the commands that launches the other
command sets, making the red button a self-contained
item (i.e. you don't have to manually add any
scripts etc to it when creating it).
scripts etc to it when creating it).
"""
key = "LidClosedCmdSet"
# default Union is used *except* if we are adding to a
# cmdset named LidOpenCmdSet - this one we replace
# default Union is used *except* if we are adding to a
# cmdset named LidOpenCmdSet - this one we replace
# completely.
key_mergetype = {"LidOpenCmdSet": "Replace"}
key_mergetype = {"LidOpenCmdSet": "Replace"}
def at_cmdset_creation(self):
"Populates the cmdset when it is instantiated."
@ -276,14 +276,14 @@ class LidClosedCmdSet(CmdSet):
class LidOpenCmdSet(CmdSet):
"""
This is the opposite of the Closed cmdset.
This is the opposite of the Closed cmdset.
"""
key = "LidOpenCmdSet"
# default Union is used *except* if we are adding to a
# cmdset named LidClosedCmdSet - this one we replace
# default Union is used *except* if we are adding to a
# cmdset named LidClosedCmdSet - this one we replace
# completely.
key_mergetype = {"LidClosedCmdSet": "Replace"}
def at_cmdset_creation(self):
"setup the cmdset (just one command)"
self.add(CmdCloseLid())
@ -295,13 +295,13 @@ class BlindCmdSet(CmdSet):
"""
key = "BlindCmdSet"
# we want it to completely replace all normal commands
# until the timed script removes it again.
mergetype = "Replace"
# until the timed script removes it again.
mergetype = "Replace"
# we want to stop the player from walking around
# in this blinded state, so we hide all exits too.
# (channel commands will still work).
no_exits = True # keep player in the same room
no_objs = True # don't allow object commands
no_objs = True # don't allow object commands
def at_cmdset_creation(self):
"Setup the blind cmdset"

View file

@ -1,5 +1,5 @@
"""
Example command module template
Example command module template
Copy this module up one level to gamesrc/commands/ and name it as
befits your use. You can then use it as a template to define your new
@ -15,30 +15,30 @@ from ev import utils
class Command(BaseCommand):
"""
Inherit from this if you want to create your own
command styles. Note that Evennia's default commands
command styles. Note that Evennia's default commands
use MuxCommand instead (next in this module)
Note that the class's __doc__ string (this text) is
used by Evennia to create the automatic help entry for
the command, so make sure to document consistently here.
the command, so make sure to document consistently here.
"""
# these need to be specified
# these need to be specified
key = "MyCommand"
aliases = ["mycmd", "myc"]
aliases = ["mycmd", "myc"]
locks = "cmd:all()"
help_category = "General"
# auto_help = False # uncomment to deactive auto-help for this command.
# arg_regex = r"\s.*?|$" # optional regex detailing how the part after
# arg_regex = r"\s.*?|$" # optional regex detailing how the part after
# the cmdname must look to match this command.
# (we don't implement hook method access() here, you don't need to
# modify that unless you want to change how the lock system works
# (in that case see src.commands.command.Command))
def at_pre_cmd(self):
"""
This hook is called before self.parse() on all commands
@ -51,15 +51,15 @@ class Command(BaseCommand):
has been identified. It creates a new set of member variables
that can be later accessed from self.func() (see below)
The following variables are available to us:
# class variables:
The following variables are available to us:
# class variables:
self.key - the name of this command ('mycommand')
self.aliases - the aliases of this cmd ('mycmd','myc')
self.locks - lock string for this command ("cmd:all()")
self.help_category - overall category of command ("General")
# added at run-time by cmdhandler:
# added at run-time by cmdhandler:
self.caller - the object calling this command
self.cmdstring - the actual command name used to call this
@ -67,10 +67,10 @@ class Command(BaseCommand):
for example)
self.args - the raw input; everything following self.cmdstring.
self.cmdset - the cmdset from which this command was picked. Not
often used (useful for commands like 'help' or to
often used (useful for commands like 'help' or to
list all available commands etc)
self.obj - the object on which this command was defined. It is often
the same as self.caller.
the same as self.caller.
"""
pass
@ -78,13 +78,13 @@ class Command(BaseCommand):
"""
This is the hook function that actually does all the work. It is called
by the cmdhandler right after self.parser() finishes, and so has access
to all the variables defined therein.
to all the variables defined therein.
"""
self.caller.msg("Command called!")
def at_post_cmd(self):
"""
This hook is called after self.func().
This hook is called after self.func().
"""
pass
@ -101,32 +101,32 @@ class MuxCommand(default_cmd.MuxCommand):
name[ with several words][/switch[/switch..]] arg1[,arg2,...] [[=|,] arg[,..]]
The 'name[ with several words]' part is already dealt with by the
cmdhandler at this point, and stored in self.cmdname. The rest is stored
in self.args.
cmdhandler at this point, and stored in self.cmdname. The rest is stored
in self.args.
The MuxCommand parser breaks self.args into its constituents and stores them in the
following variables:
The MuxCommand parser breaks self.args into its constituents and stores them in the
following variables:
self.switches = optional list of /switches (without the /)
self.raw = This is the raw argument input, including switches
self.args = This is re-defined to be everything *except* the switches
self.lhs = Everything to the left of = (lhs:'left-hand side'). If
self.lhs = Everything to the left of = (lhs:'left-hand side'). If
no = is found, this is identical to self.args.
self.rhs: Everything to the right of = (rhs:'right-hand side').
self.rhs: Everything to the right of = (rhs:'right-hand side').
If no '=' is found, this is None.
self.lhslist - self.lhs split into a list by comma
self.rhslist - list of self.rhs split into a list by comma
self.arglist = list of space-separated args (including '=' if it exists)
All args and list members are stripped of excess whitespace around the
strings, but case is preserved.
All args and list members are stripped of excess whitespace around the
strings, but case is preserved.
"""
def func(self):
"""
This is the hook function that actually does all the work. It is called
by the cmdhandler right after self.parser() finishes, and so has access
to all the variables defined therein.
"""
# this can be removed in your child class, it's just
to all the variables defined therein.
"""
# this can be removed in your child class, it's just
# printing the ingoing variables as a demo.
super(MuxCommand, self).func()

View file

@ -2,7 +2,7 @@
At_initial_setup module template
Copy this module up one level to /gamesrc/conf, name it what you like
and then use it as a template to modify.
and then use it as a template to modify.
Then edit settings.AT_INITIAL_SETUP_HOOK_MODULE to point to your new
module.
@ -21,4 +21,4 @@ does what you expect it to.
"""
def at_initial_setup():
pass
pass

View file

@ -3,7 +3,7 @@
At_server_startstop module template
Copy this module one level up, to gamesrc/conf/, name it what you
will and use it as a template for your modifications.
will and use it as a template for your modifications.
Then edit settings.AT_SERVER_STARTSTOP_MODULE to point to your new
module.
@ -15,10 +15,10 @@ already been executed. The main purpose of this is module is to have a
safe place to initialize eventual custom modules that your game needs
to start up or load.
The module should define at least these global functions:
The module should define at least these global functions:
at_server_start()
at_server_stop()
at_server_start()
at_server_stop()
"""

View file

@ -1,8 +1,8 @@
"""
Connect screen module template
Connect screen module template
Copy this module one level up, to gamesrc/conf/, name it what
you want and modify it to your liking.
you want and modify it to your liking.
Then you set settings.CONNECTION_SCREEN_MODULE to point to your
new module.
@ -10,7 +10,7 @@ new module.
This module holds textual connection screen definitions. All global
string variables (only) in this module are read by Evennia and
assumed to define a Connection screen.
assumed to define a Connection screen.
The names of the string variables doesn't matter (except they
shouldn't start with _), but each should hold a string defining a
@ -25,13 +25,13 @@ new module.
"""
from src.utils import utils
from src.utils import utils
from src.commands.connection_screen import DEFAULT_SCREEN
#
# CUSTOM_SCREEN = \
# """{b=============================================================={n
# Welcome to {gEvennia{n, version %s!
# Welcome to {gEvennia{n, version %s!
#
# If you have an existing account, connect to it by typing:
# {wconnect <email> <password>{n
@ -45,5 +45,5 @@ from src.commands.connection_screen import DEFAULT_SCREEN
# MENU_SCREEN = \
# """{b=============================================================={n
# Welcome to {gEvennnia{n, version %s!
# Welcome to {gEvennnia{n, version %s!
# {b=============================================================={n""" % utils.get_evennia_version()

View file

@ -3,9 +3,9 @@
Lockfuncs module template
Copy this module one level up, to gamesrc/conf/, name it what
you will and edit it to your liking.
you will and edit it to your liking.
Then add the new module's path to the end of the tuple
Then add the new module's path to the end of the tuple
defined in settings.LOCK_FUNC_MODULES.
All functions defined globally in this module are assumed to be
@ -18,15 +18,15 @@ arguments should be handled (excess ones calling magic (*args,
**kwargs) to avoid errors). The lock function should handle all
eventual tracebacks by logging the error and returning False.
See many more examples of lock functions in src.locks.lockfuncs.
See many more examples of lock functions in src.locks.lockfuncs.
"""
def myfalse(accessing_obj, accessed_obj, *args, **kwargs):
"""
called in lockstring with myfalse().
called in lockstring with myfalse().
A simple logger that always returns false. Prints to stdout
for simplicity, should use utils.logger for real operation.
"""
print "%s tried to access %s. Access denied." % (accessing_obj, accessed_obj)
return False
return False

View file

@ -1,22 +1,22 @@
"""
MSSP module template
MSSP module template
Copy this module one level up, to gamesrc/conf/, name it
what you want and edit it to your satisfaction.
what you want and edit it to your satisfaction.
Then change settings.MSSP_META_MODULE to point to your new module.
MSSP (Mud Server Status Protocol) meta information
MSSP (Mud Server Status Protocol) meta information
MUD website listings (that you have registered with) can use this
information to keep up-to-date with your game stats as you change
them. Also number of currently active players and uptime will
automatically be reported. You don't have to fill in everything
(and most are not used by all crawlers); leave the default
if so needed. You need to @reload the game before updated
information is made available to crawlers (reloading does not
affect uptime).
if so needed. You need to @reload the game before updated
information is made available to crawlers (reloading does not
affect uptime).
"""
MSSPTable = {
@ -29,16 +29,16 @@ MSSPTable = {
"CRAWL DELAY": "-1", # limit how often crawler updates the listing. -1 for no limit
"HOSTNAME": "", # current or new hostname
"HOSTNAME": "", # current or new hostname
"PORT": ["4000"], # most important port should be last in list
"CODEBASE": "Evennia",
"CONTACT": "", # email for contacting the mud
"CREATED": "", # year MUD was created
"ICON": "", # url to icon 32x32 or larger; <32kb.
"ICON": "", # url to icon 32x32 or larger; <32kb.
"IP": "", # current or new IP address
"LANGUAGE": "", # name of language used, e.g. English
"LOCATION": "", # full English name of server country
"MINIMUM AGE": "0", # set to 0 if not applicable
"MINIMUM AGE": "0", # set to 0 if not applicable
"WEBSITE": "www.evennia.com",
# Categorisation
@ -50,14 +50,14 @@ MSSPTable = {
# Roleplaying, Simulation, Social or Strategy
"STATUS": "Open Beta", # Alpha, Closed Beta, Open Beta, Live
"GAMESYSTEM": "Custom", # D&D, d20 System, World of Darkness, etc. Use Custom if homebrew
"INTERMUD": "IMC2", # evennia supports IMC2.
"SUBGENRE": "None", # LASG, Medieval Fantasy, World War II, Frankenstein,
"INTERMUD": "IMC2", # evennia supports IMC2.
"SUBGENRE": "None", # LASG, Medieval Fantasy, World War II, Frankenstein,
# Cyberpunk, Dragonlance, etc. Or None if not available.
# World
"AREAS": "0",
"HELPFILES": "0",
"AREAS": "0",
"HELPFILES": "0",
"MOBILES": "0",
"OBJECTS": "0",
"ROOMS": "0", # use 0 if room-less
@ -121,7 +121,7 @@ MSSPTable = {
# Protocols (only change if you added/removed something manually)
"ATCP": "0",
"MSDP": "0",
"MSDP": "0",
"MCCP": "1",
"SSL": "1",
"UTF-8": "1",

View file

@ -3,14 +3,14 @@
** OBS This module is not yet used by Evennia **
Example module holding functions for out-of-band protocols to
import and map to given commands from the client. This module
is selected by settings.OOB_FUNC_MODULE.
import and map to given commands from the client. This module
is selected by settings.OOB_FUNC_MODULE.
All functions defined global in this module will be available
for the oob system to call. They will be called with a session/character
as first argument (depending on if the session is logged in or not),
as first argument (depending on if the session is logged in or not),
following by any number of extra arguments. The return value will
be packed and returned to the oob protocol and can be on any form.
be packed and returned to the oob protocol and can be on any form.
"""
def testoob(character, *args, **kwargs):

View file

@ -3,16 +3,16 @@
Template for Characters
Copy this module up one level and name it as you like, then
use it as a template to create your own Character class.
use it as a template to create your own Character class.
To make new logins default to creating characters
To make new logins default to creating characters
of your new type, change settings.BASE_CHARACTER_TYPECLASS to point to
your new class, e.g.
settings.BASE_CHARACTER_TYPECLASS = "game.gamesrc.objects.mychar.MyChar"
Note that objects already created in the database will not notice
this change, you have to convert them manually e.g. with the
this change, you have to convert them manually e.g. with the
@typeclass command.
"""
@ -20,22 +20,21 @@ from ev import Character
class ExampleCharacter(Character):
"""
The Character is like any normal Object (see example/object.py for
a list of properties and methods), except it actually implements
some of its hook methods to do some work:
at_basetype_setup - always assigns the default_cmdset to this object type
(important!)sets locks so character cannot be picked up
The Character is like any normal Object (see example/object.py for
a list of properties and methods), except it actually implements
some of its hook methods to do some work:
at_basetype_setup - always assigns the default_cmdset to this object type
(important!)sets locks so character cannot be picked up
and its commands only be called by itself, not anyone else.
(to change things, use at_object_creation() instead)
at_after_move - launches the "look" command
at_disconnect - stores the current location, so the "unconnected" character
object does not need to stay on grid but can be given a
None-location while offline.
object does not need to stay on grid but can be given a
None-location while offline.
at_post_login - retrieves the character's old location and puts it back
on the grid with a "charname has connected" message echoed
to the room
"""
pass
pass

View file

@ -12,7 +12,7 @@ your new class, e.g.
settings.BASE_EXIT_TYPECLASS = "game.gamesrc.objects.myexit.MyExit"
Note that objects already created in the database will not notice
this change, you have to convert them manually e.g. with the
this change, you have to convert them manually e.g. with the
@typeclass command.
"""
@ -21,8 +21,8 @@ from ev import Exit
class ExampleExit(Exit):
"""
Exits are connectors between rooms. Exits are normal Objects except
they defines the 'destination' property. It also does work in the
following methods:
they defines the 'destination' property. It also does work in the
following methods:
basetype_setup() - sets default exit locks (to change, use at_object_creation instead)
at_cmdset_get() - this auto-creates and caches a command and a command set on itself
@ -33,11 +33,11 @@ class ExampleExit(Exit):
go there") if exit traversal fails and an
attribute err_traverse is not defined.
Relevant hooks to overload (compared to other types of Objects):
Relevant hooks to overload (compared to other types of Objects):
at_before_traverse(traveller) - called just before traversing
at_after_traverse(traveller, source_loc) - called just after traversing
at_failed_traverse(traveller) - called if traversal failed for some reason. Will
not be called if the attribute 'err_traverse' is
not be called if the attribute 'err_traverse' is
defined, in which case that will simply be echoed.
"""
pass

View file

@ -3,7 +3,7 @@
Template for Objects
Copy this module up one level and name it as you like, then
use it as a template to create your own Objects.
use it as a template to create your own Objects.
To make the default commands default to creating objects of your new
type (and also change the "fallback" object used when typeclass
@ -13,7 +13,7 @@ your new class, e.g.
settings.BASE_OBJECT_TYPECLASS = "game.gamesrc.objects.myobj.MyObj"
Note that objects already created in the database will not notice
this change, you have to convert them manually e.g. with the
this change, you have to convert them manually e.g. with the
@typeclass command.
"""
@ -34,19 +34,19 @@ class ExampleObject(Object):
methods, such as __init__ and especially never __getattribute__ and
__setattr__ since these are used heavily by the typeclass system
of Evennia and messing with them might well break things for you.
* Base properties defined/available on all Objects
key (string) - name of object
* Base properties defined/available on all Objects
key (string) - name of object
name (string)- same as key
aliases (list of strings) - aliases to the object. Will be saved to database as AliasDB entries but returned as strings.
dbref (int, read-only) - unique #id-number. Also "id" can be used.
dbobj (Object, read-only) - link to database model. dbobj.typeclass points back to this class
typeclass (Object, read-only) - this links back to this class as an identified only. Use self.swap_typeclass() to switch.
date_created (string) - time stamp of object creation
permissions (list of strings) - list of permission strings
permissions (list of strings) - list of permission strings
player (Player) - controlling player (will also return offline player)
location (Object) - current location. Is None if this is a room
home (Object) - safety start-location
@ -54,19 +54,19 @@ class ExampleObject(Object):
has_player (bool, read-only)- will only return *connected* players
contents (list of Objects, read-only) - returns all objects inside this object (including exits)
exits (list of Objects, read-only) - returns all exits from this object, if any
destination (Object) - only set if this object is an exit.
destination (Object) - only set if this object is an exit.
is_superuser (bool, read-only) - True/False if this user is a superuser
* Handlers available
* Handlers available
locks - lock-handler: use locks.add() to add new lock strings
db - attribute-handler: store/retrieve database attributes on this self.db.myattr=val, val=self.db.myattr
ndb - non-persistent attribute handler: same as db but does not create a database entry when storing data
ndb - non-persistent attribute handler: same as db but does not create a database entry when storing data
scripts - script-handler. Add new scripts to object with scripts.add()
cmdset - cmdset-handler. Use cmdset.add() to add new cmdsets to object
nicks - nick-handler. New nicks with nicks.add().
* Helper methods (see src.objects.objects.py for full headers)
* Helper methods (see src.objects.objects.py for full headers)
search(ostring, global_search=False, attribute_name=None, use_nicks=False, location=None, ignore_errors=False, player=False)
execute_cmd(raw_string)
@ -79,21 +79,21 @@ class ExampleObject(Object):
swap_typeclass(new_typeclass, clean_attributes=False, no_default=True)
access(accessing_obj, access_type='read', default=False)
check_permstring(permstring)
* Hooks (these are class methods, so their arguments should also start with self):
* Hooks (these are class methods, so their arguments should also start with self):
basetype_setup() - only called once, used for behind-the-scenes setup. Normally not modified.
basetype_posthook_setup() - customization in basetype, after the object has been created; Normally not modified.
at_object_creation() - only called once, when object is first created. Object customizations go here.
at_object_creation() - only called once, when object is first created. Object customizations go here.
at_object_delete() - called just before deleting an object. If returning False, deletion is aborted. Note that all objects
inside a deleted object are automatically moved to their <home>, they don't need to be removed here.
inside a deleted object are automatically moved to their <home>, they don't need to be removed here.
at_init() - called whenever typeclass is cached from memory, at least once every server restart/reload
at_cmdset_get() - this is called just before the command handler requests a cmdset from this object
at_first_login() - (player-controlled objects only) called once, the very first time user logs in.
at_init() - called whenever typeclass is cached from memory, at least once every server restart/reload
at_cmdset_get() - this is called just before the command handler requests a cmdset from this object
at_first_login() - (player-controlled objects only) called once, the very first time user logs in.
at_pre_login() - (player-controlled objects only) called every time the user connects, after they have identified, before other setup
at_post_login() - (player-controlled objects only) called at the end of login, just before setting the player loose in the world.
at_post_login() - (player-controlled objects only) called at the end of login, just before setting the player loose in the world.
at_disconnect() - (player-controlled objects only) called just before the user disconnects (or goes linkless)
at_server_reload() - called before server is reloaded
at_server_shutdown() - called just before server is fully shut down
@ -106,15 +106,15 @@ class ExampleObject(Object):
at_object_receive(obj, source_location) - called when this object receives another object
at_before_traverse(traversing_object) - (exit-objects only) called just before an object traverses this object
at_after_traverse(traversing_object, source_location) - (exit-objects only) called just after a traversal has happened.
at_after_traverse(traversing_object, source_location) - (exit-objects only) called just after a traversal has happened.
at_failed_traverse(traversing_object) - (exit-objects only) called if traversal fails and property err_traverse is not defined.
at_msg_receive(self, msg, from_obj=None, data=None) - called when a message (via self.msg()) is sent to this obj.
at_msg_receive(self, msg, from_obj=None, data=None) - called when a message (via self.msg()) is sent to this obj.
If returns false, aborts send.
at_msg_send(self, msg, to_obj=None, data=None) - called when this objects sends a message to someone via self.msg().
at_msg_send(self, msg, to_obj=None, data=None) - called when this objects sends a message to someone via self.msg().
return_appearance(looker) - describes this object. Used by "look" command by default
at_desc(looker=None) - called by 'look' whenever the appearance is requested.
at_desc(looker=None) - called by 'look' whenever the appearance is requested.
at_get(getter) - called after object has been picked up. Does not stop pickup.
at_drop(dropper) - called when this object has been dropped.
at_say(speaker, message) - by default, called if an object inside this object speaks

View file

@ -3,16 +3,16 @@
Template module for Players
Copy this module up one level and name it as you like, then
use it as a template to create your own Player class.
use it as a template to create your own Player class.
To make the default account login default to using a Player
To make the default account login default to using a Player
of your new type, change settings.BASE_PLAYER_TYPECLASS to point to
your new class, e.g.
settings.BASE_PLAYER_TYPECLASS = "game.gamesrc.objects.myplayer.MyPlayer"
Note that objects already created in the database will not notice
this change, you have to convert them manually e.g. with the
this change, you have to convert them manually e.g. with the
@typeclass command.
"""
@ -20,19 +20,19 @@ from ev import Player
class ExamplePlayer(Player):
"""
This class describes the actual OOC player (i.e. the user connecting
This class describes the actual OOC player (i.e. the user connecting
to the MUD). It does NOT have visual appearance in the game world (that
is handled by the character which is connected to this). Comm channels
are attended/joined using this object.
It can be useful e.g. for storing configuration options for your game, but
are attended/joined using this object.
It can be useful e.g. for storing configuration options for your game, but
should generally not hold any character-related info (that's best handled
on the character level).
Can be set using BASE_PLAYER_TYPECLASS.
* available properties
* available properties
key (string) - name of player
name (string)- wrapper for user.username
@ -41,18 +41,18 @@ class ExamplePlayer(Player):
dbobj (Player, read-only) - link to database model. dbobj.typeclass points back to this class
typeclass (Player, read-only) - this links back to this class as an identified only. Use self.swap_typeclass() to switch.
date_created (string) - time stamp of object creation
permissions (list of strings) - list of permission strings
permissions (list of strings) - list of permission strings
user (User, read-only) - django User authorization object
obj (Object) - game object controlled by player. 'character' can also be used.
sessions (list of Sessions) - sessions connected to this player
is_superuser (bool, read-only) - if the connected user is a superuser
* Handlers
* Handlers
locks - lock-handler: use locks.add() to add new lock strings
db - attribute-handler: store/retrieve database attributes on this self.db.myattr=val, val=self.db.myattr
ndb - non-persistent attribute handler: same as db but does not create a database entry when storing data
ndb - non-persistent attribute handler: same as db but does not create a database entry when storing data
scripts - script-handler. Add new scripts to object with scripts.add()
cmdset - cmdset-handler. Use cmdset.add() to add new cmdsets to object
nicks - nick-handler. New nicks with nicks.add().
@ -71,12 +71,12 @@ class ExamplePlayer(Player):
* Hook methods (when re-implementation, remember methods need to have self as first arg)
basetype_setup()
at_player_creation()
at_player_creation()
- note that the following hooks are also found on Objects and are
usually handled on the character level:
at_init()
at_init()
at_cmdset_get()
at_first_login()
at_post_login()

View file

@ -4,13 +4,13 @@ This is a more advanced example object. It combines functions from
script.examples as well as commands.examples to make an interactive
button typeclass.
Create this button with
Create this button with
@create/drop examples.red_button.RedButton
@create/drop examples.red_button.RedButton
Note that if you must drop the button before you can see its messages!
Note that if you must drop the button before you can see its messages!
"""
import random
import random
from ev import Object
from game.gamesrc.scripts.examples import red_button_scripts as scriptexamples
from game.gamesrc.commands.examples import cmdset_red_button as cmdsetexamples
@ -18,7 +18,7 @@ from game.gamesrc.commands.examples import cmdset_red_button as cmdsetexamples
#
# Definition of the object itself
#
class RedButton(Object):
"""
This class describes an evil red button. It will use the script
@ -36,30 +36,30 @@ class RedButton(Object):
"""
This function is called when object is created. Use this
instead of e.g. __init__.
"""
"""
# store desc (default, you can change this at creation time)
desc = "This is a large red button, inviting yet evil-looking. "
desc += "A closed glass lid protects it."
self.db.desc = desc
desc += "A closed glass lid protects it."
self.db.desc = desc
# We have to define all the variables the scripts
# are checking/using *before* adding the scripts or
# they might be deactivated before even starting!
self.db.lid_open = False
self.db.lamp_works = True
# We have to define all the variables the scripts
# are checking/using *before* adding the scripts or
# they might be deactivated before even starting!
self.db.lid_open = False
self.db.lamp_works = True
self.db.lid_locked = False
self.cmdset.add_default(cmdsetexamples.DefaultCmdSet, permanent=True)
# since the cmdsets relevant to the button are added 'on the fly',
# we need to setup custom scripts to do this for us (also, these scripts
# check so they are valid (i.e. the lid is actually still closed)).
# The AddClosedCmdSet script makes sure to add the Closed-cmdset.
# check so they are valid (i.e. the lid is actually still closed)).
# The AddClosedCmdSet script makes sure to add the Closed-cmdset.
self.scripts.add(scriptexamples.ClosedLidState)
# the script EventBlinkButton makes the button blink regularly.
self.scripts.add(scriptexamples.BlinkButtonEvent)
# state-changing methods
# state-changing methods
def open_lid(self):
"""
@ -68,12 +68,12 @@ class RedButton(Object):
"""
if self.db.lid_open:
return
return
desc = self.db.desc_lid_open
if not desc:
desc = "This is a large red button, inviting yet evil-looking. "
desc += "Its glass cover is open and the button exposed."
self.db.desc = desc
self.db.desc = desc
self.db.lid_open = True
# with the lid open, we validate scripts; this will clean out
@ -93,13 +93,13 @@ class RedButton(Object):
"""
if not self.db.lid_open:
return
return
desc = self.db.desc_lid_closed
if not desc:
desc = "This is a large red button, inviting yet evil-looking. "
desc += "Its glass cover is closed, protecting it."
self.db.desc = desc
self.db.lid_open = False
desc += "Its glass cover is closed, protecting it."
self.db.desc = desc
self.db.lid_open = False
# clean out scripts depending on lid to be open
self.scripts.validate()
@ -109,17 +109,17 @@ class RedButton(Object):
def break_lamp(self, feedback=True):
"""
Breaks the lamp in the button, stopping it from blinking.
"""
self.db.lamp_works = False
self.db.lamp_works = False
desc = self.db.desc_lamp_broken
if not desc:
if not desc:
self.db.desc += "\nThe big red button has stopped blinking for the time being."
else:
self.db.desc = desc
if feedback and self.location:
self.location.msg_contents("The lamp flickers, the button going dark.")
self.location.msg_contents("The lamp flickers, the button going dark.")
self.scripts.validate()
def press_button(self, pobject):
@ -129,7 +129,7 @@ class RedButton(Object):
"""
# deactivate the button so it won't flash/close lid etc.
self.scripts.add(scriptexamples.DeactivateButtonEvent)
# blind the person pressing the button. Note that this
# blind the person pressing the button. Note that this
# script is set on the *character* pressing the button!
pobject.scripts.add(scriptexamples.BlindedState)
@ -140,19 +140,18 @@ class RedButton(Object):
The script system will regularly call this
function to make the button blink. Now and then
it won't blink at all though, to add some randomness
to how often the message is echoed.
to how often the message is echoed.
"""
loc = self.location
if loc:
loc = self.location
if loc:
rand = random.random()
if rand < 0.2:
if rand < 0.2:
string = "The red button flashes briefly."
elif rand < 0.4:
string = "The red button blinks invitingly."
elif rand < 0.6:
string = "The red button flashes. You know you wanna push it!"
string = "The red button flashes. You know you wanna push it!"
else:
# no blink
return
return
loc.msg_contents(string)

View file

@ -3,7 +3,7 @@
Template module for Rooms
Copy this module up one level and name it as you like, then
use it as a template to create your own Objects.
use it as a template to create your own Objects.
To make the default commands (such as @dig) default to creating rooms
of your new type, change settings.BASE_ROOM_TYPECLASS to point to
@ -12,7 +12,7 @@ your new class, e.g.
settings.BASE_ROOM_TYPECLASS = "game.gamesrc.objects.myroom.MyRoom"
Note that objects already created in the database will not notice
this change, you have to convert them manually e.g. with the
this change, you have to convert them manually e.g. with the
@typeclass command.
"""
@ -22,11 +22,11 @@ from ev import Room
class ExampleRoom(Room):
"""
Rooms are like any Object, except their location is None
(which is default). They also use basetype_setup() to
(which is default). They also use basetype_setup() to
add locks so they cannot be puppeted or picked up.
(to change that, use at_object_creation instead)
See examples/object.py for a list of
properties and methods available on all Objects.
properties and methods available on all Objects.
"""
pass

View file

@ -1,9 +1,9 @@
"""
Example script for testing. This adds a simple timer that
has your character make observations and noices at irregular
intervals.
intervals.
To test, use
To test, use
@script me = examples.bodyfunctions.BodyFunctions
The script will only send messages to the object it
@ -11,7 +11,7 @@ is stored on, so make sure to put it on yourself
or you won't see any messages!
"""
import random
import random
from ev import Script
class BodyFunctions(Script):
@ -19,26 +19,26 @@ class BodyFunctions(Script):
This class defines the script itself
"""
def at_script_creation(self):
def at_script_creation(self):
self.key = "bodyfunction"
self.desc = "Adds various timed events to a character."
self.interval = 20 # seconds
#self.repeats = 5 # repeat only a certain number of times
self.start_delay = True # wait self.interval until first call
#self.persistent = True
def at_repeat(self):
"""
This gets called every self.interval seconds. We make
a random check here so as to only return 33% of the time.
This gets called every self.interval seconds. We make
a random check here so as to only return 33% of the time.
"""
if random.random() < 0.66:
# no message this time
return
return
rand = random.random()
# return a random message
if rand < 0.1:
if rand < 0.1:
string = "You tap your foot, looking around."
elif rand < 0.2:
string = "You have an itch. Hard to reach too."
@ -58,6 +58,6 @@ class BodyFunctions(Script):
string = "You get a great idea. Of course you won't tell anyone."
else:
string = "You suddenly realize how much you love Evennia!"
# echo the message to the object
self.obj.msg(string)

View file

@ -1,7 +1,7 @@
"""
Example of scripts.
These are scripts intended for a particular object - the
These are scripts intended for a particular object - the
red_button object type in gamesrc/types/examples. A few variations
on uses of scripts are included.
@ -11,45 +11,45 @@ from game.gamesrc.commands.examples import cmdset_red_button as cmdsetexamples
#
# Scripts as state-managers
#
#
# Scripts have many uses, one of which is to statically
# make changes when a particular state of an object changes.
# There is no "timer" involved in this case (although there could be),
# whenever the script determines it is "invalid", it simply shuts down
# along with all the things it controls.
#
# along with all the things it controls.
#
# To show as many features as possible of the script and cmdset systems,
# we will use three scripts controlling one state each of the red_button,
# each with its own set of commands, handled by cmdsets - one for when
# each with its own set of commands, handled by cmdsets - one for when
# the button has its lid open, and one for when it is closed and a
# last one for when the player pushed the button and gets blinded by
# a bright light. The last one also has a timer component that allows it
# to remove itself after a while (and the player recovers their eyesight).
# to remove itself after a while (and the player recovers their eyesight).
class ClosedLidState(Script):
"""
This manages the cmdset for the "closed" button state. What this
This manages the cmdset for the "closed" button state. What this
means is that while this script is valid, we add the RedButtonClosed
cmdset to it (with commands like open, nudge lid etc)
"""
def at_script_creation(self):
"Called when script first created."
self.desc = "Script that manages the closed-state cmdsets for red button."
self.persistent = True
self.persistent = True
def at_start(self):
"""
This is called once every server restart, so we want to add the
(memory-resident) cmdset to the object here. is_valid is automatically
checked so we don't need to worry about adding the script to an
open lid.
open lid.
"""
#All we do is add the cmdset for the closed state.
self.obj.cmdset.add(cmdsetexamples.LidClosedCmdSet)
def is_valid(self):
"""
The script is only valid while the lid is closed.
The script is only valid while the lid is closed.
self.obj is the red_button on which this script is defined.
"""
return not self.obj.db.lid_open
@ -57,7 +57,7 @@ class ClosedLidState(Script):
def at_stop(self):
"""
When the script stops we must make sure to clean up after us.
"""
self.obj.cmdset.delete(cmdsetexamples.LidClosedCmdSet)
@ -68,23 +68,23 @@ class OpenLidState(Script):
the RedButtonOpen
"""
def at_script_creation(self):
"Called when script first created."
"Called when script first created."
self.desc = "Script that manages the opened-state cmdsets for red button."
self.persistent = True
self.persistent = True
def at_start(self):
"""
This is called once every server restart, so we want to add the
(memory-resident) cmdset to the object here. is_valid is
automatically checked, so we don't need to worry about
(memory-resident) cmdset to the object here. is_valid is
automatically checked, so we don't need to worry about
adding the cmdset to a closed lid-button.
"""
#print "In Open at_start (should add cmdset)"
self.obj.cmdset.add(cmdsetexamples.LidOpenCmdSet)
def is_valid(self):
"""
The script is only valid while the lid is open.
The script is only valid while the lid is open.
self.obj is the red_button on which this script is defined.
"""
return self.obj.db.lid_open
@ -99,12 +99,12 @@ class OpenLidState(Script):
class BlindedState(Script):
"""
This is a timed state.
This is a timed state.
This adds a (very limited) cmdset TO THE PLAYER, during a certain time,
after which the script will close and all functions are
after which the script will close and all functions are
restored. It's up to the function starting the script to actually
set it on the right player object.
set it on the right player object.
"""
def at_script_creation(self):
"""
@ -114,13 +114,13 @@ class BlindedState(Script):
self.desc = "Temporarily blinds the player for a little while."
self.interval = 20 # seconds
self.start_delay = True # we don't want it to stop until after 20s.
self.repeats = 1 # this will go away after interval seconds.
self.repeats = 1 # this will go away after interval seconds.
self.persistent = False # we will ditch this if server goes down
def at_start(self):
"""
We want to add the cmdset to the linked object.
Note that the RedButtonBlind cmdset is defined to completly
replace the other cmdsets on the stack while it is active
(this means that while blinded, only operations in this cmdset
@ -133,39 +133,39 @@ class BlindedState(Script):
def at_stop(self):
"""
It's important that we clear out that blinded cmdset
when we are done!
when we are done!
"""
self.obj.msg("You blink feverishly as your eyesight slowly returns.")
self.obj.location.msg_contents("%s seems to be recovering their eyesight."
% self.obj.name,
self.obj.location.msg_contents("%s seems to be recovering their eyesight."
% self.obj.name,
exclude=self.obj)
self.obj.cmdset.delete() # this will clear the latest added cmdset,
self.obj.cmdset.delete() # this will clear the latest added cmdset,
# (which is the blinded one).
#
# Timer/Event-like Scripts
#
# Scripts can also work like timers, or "events". Below we
# Scripts can also work like timers, or "events". Below we
# define three such timed events that makes the button a little
# more "alive" - one that makes the button blink menacingly, another
# that makes the lid covering the button slide back after a while.
# more "alive" - one that makes the button blink menacingly, another
# that makes the lid covering the button slide back after a while.
#
class CloseLidEvent(Script):
"""
This event closes the glass lid over the button
some time after it was opened. It's a one-off
script that should be started/created when the
lid is opened.
script that should be started/created when the
lid is opened.
"""
def at_script_creation(self):
"""
Called when script object is first created. Sets things up.
We want to have a lid on the button that the user can pull
aside in order to make the button 'pressable'. But after a set
aside in order to make the button 'pressable'. But after a set
time that lid should auto-close again, making the button safe
from pressing (and deleting this command).
from pressing (and deleting this command).
"""
self.key = "lid_closer"
self.desc = "Closes lid on a red buttons"
@ -177,61 +177,61 @@ class CloseLidEvent(Script):
def is_valid(self):
"""
This script can only operate if the lid is open; if it
This script can only operate if the lid is open; if it
is already closed, the script is clearly invalid.
Note that we are here relying on an self.obj being
defined (and being a RedButton object) - this we should be able to
expect since this type of script is always tied to one individual
defined (and being a RedButton object) - this we should be able to
expect since this type of script is always tied to one individual
red button object and not having it would be an error.
"""
return self.obj.db.lid_open
def at_repeat(self):
"""
Called after self.interval seconds. It closes the lid. Before this method is
called, self.is_valid() is automatically checked, so there is no need to
Called after self.interval seconds. It closes the lid. Before this method is
called, self.is_valid() is automatically checked, so there is no need to
check this manually.
"""
self.obj.close_lid()
class BlinkButtonEvent(Script):
"""
This timed script lets the button flash at regular intervals.
"""
This timed script lets the button flash at regular intervals.
"""
def at_script_creation(self):
"""
Sets things up. We want the button's lamp to blink at
Sets things up. We want the button's lamp to blink at
regular intervals, unless it's broken (can happen
if you try to smash the glass, say).
if you try to smash the glass, say).
"""
self.key = "blink_button"
self.desc = "Blinks red buttons"
self.interval = 35 #seconds
self.start_delay = False #blink right away
self.persistent = True #keep blinking also after server reboot
def is_valid(self):
"""
Button will keep blinking unless it is broken.
"""
#print "self.obj.db.lamp_works:", self.obj.db.lamp_works
return self.obj.db.lamp_works
def at_repeat(self):
"""
Called every self.interval seconds. Makes the lamp in
Called every self.interval seconds. Makes the lamp in
the button blink.
"""
self.obj.blink()
class DeactivateButtonEvent(Script):
"""
This deactivates the button for a short while (it won't blink, won't
This deactivates the button for a short while (it won't blink, won't
close its lid etc). It is meant to be called when the button is pushed
and run as long as the blinded effect lasts. We cannot put these methods
in the AddBlindedCmdSet script since that script is defined on the *player*
whereas this one must be defined on the *button*.
whereas this one must be defined on the *button*.
"""
def at_script_creation(self):
"""
@ -241,9 +241,9 @@ class DeactivateButtonEvent(Script):
self.desc = "Deactivate red button temporarily"
self.interval = 21 #seconds
self.start_delay = True # wait with the first repeat for self.interval seconds.
self.persistent = True
self.persistent = True
self.repeats = 1 # only do this once
def at_start(self):
"""
Deactivate the button. Observe that this method is always
@ -252,9 +252,9 @@ class DeactivateButtonEvent(Script):
"""
# closing the lid will also add the ClosedState script
self.obj.close_lid()
# lock the lid so other players can't access it until the
# lock the lid so other players can't access it until the
# first one's effect has worn off.
self.obj.db.lid_locked = True
self.obj.db.lid_locked = True
# breaking the lamp also sets a correct desc
self.obj.break_lamp(feedback=False)
@ -263,11 +263,11 @@ class DeactivateButtonEvent(Script):
When this is called, reset the functionality of the button.
"""
# restore button's desc.
self.obj.db.lamp_works = True
desc = "This is a large red button, inviting yet evil-looking. "
desc += "Its glass cover is closed, protecting it."
self.db.desc = desc
desc += "Its glass cover is closed, protecting it."
self.db.desc = desc
# re-activate the blink button event.
self.obj.scripts.add(BlinkButtonEvent)
# unlock the lid

View file

@ -1,6 +1,6 @@
"""
Template module for Scripts
Template module for Scripts
Copy this module up one level to gamesrc/scripts and name it
appropriately, then use that as a template to create your own script.
@ -13,10 +13,10 @@ Scripts are objects that handle everything in the game having
a time-component (i.e. that may change with time, with or without
a player being involved in the change). Scripts can work like "events",
in that they are triggered at regular intervals to do a certain script,
but an Script set on an object can also be responsible for silently
but an Script set on an object can also be responsible for silently
checking if its state changes, so as to update it. Evennia use several
in-built scripts to keep track of things like time, to clean out
dropped connections etc.
dropped connections etc.
"""
@ -26,32 +26,32 @@ class ExampleScript(BaseScript):
"""
A script type is customized by redefining some or all of its hook methods and variables.
* available properties
* available properties
key (string) - name of object
key (string) - name of object
name (string)- same as key
aliases (list of strings) - aliases to the object. Will be saved to database as AliasDB entries but returned as strings.
dbref (int, read-only) - unique #id-number. Also "id" can be used.
dbobj (Object, read-only) - link to database model. dbobj.typeclass points back to this class
typeclass (Object, read-only) - this links back to this class as an identified only. Use self.swap_typeclass() to switch.
date_created (string) - time stamp of object creation
permissions (list of strings) - list of permission strings
permissions (list of strings) - list of permission strings
desc (string) - optional description of script, shown in listings
obj (Object) - optional object that this script is connected to and acts on (set automatically by obj.scripts.add())
obj (Object) - optional object that this script is connected to and acts on (set automatically by obj.scripts.add())
interval (int) - how often script should run, in seconds. <0 turns off ticker
start_delay (bool) - if the script should start repeating right away or wait self.interval seconds
repeats (int) - how many times the script should repeat before stopping. 0 means infinite repeats
persistent (bool) - if script should survive a server shutdown or not
is_active (bool) - if script is currently running
is_active (bool) - if script is currently running
* Handlers
locks - lock-handler: use locks.add() to add new lock strings
db - attribute-handler: store/retrieve database attributes on this self.db.myattr=val, val=self.db.myattr
ndb - non-persistent attribute handler: same as db but does not create a database entry when storing data
ndb - non-persistent attribute handler: same as db but does not create a database entry when storing data
* Helper methods
* Helper methods
start() - start script (this usually happens automatically at creation and obj.script.add() etc)
stop() - stop script, and delete it
@ -66,22 +66,22 @@ class ExampleScript(BaseScript):
is_valid() - is called to check if the script is valid to be running
at the current time. If is_valid() returns False, the running
script is stopped and removed from the game. You can use this
to check state changes (i.e. an script tracking some combat
stats at regular intervals is only valid to run while there is
actual combat going on).
to check state changes (i.e. an script tracking some combat
stats at regular intervals is only valid to run while there is
actual combat going on).
at_start() - Called every time the script is started, which for persistent
scripts is at least once every server start. Note that this is
unaffected by self.delay_start, which only delays the first call
to at_repeat().
to at_repeat().
at_repeat() - Called every self.interval seconds. It will be called immediately
upon launch unless self.delay_start is True, which will delay
the first call of this method by self.interval seconds. If
self.interval==0, this method will never be called.
the first call of this method by self.interval seconds. If
self.interval==0, this method will never be called.
at_stop() - Called as the script object is stopped and is about to be removed from
the game, e.g. because is_valid() returned False.
at_server_reload() - Called when server reloads. Can be used to save temporary
at_server_reload() - Called when server reloads. Can be used to save temporary
variables you want should survive a reload.
at_server_shutdown() - called at a full server shutdown.
at_server_shutdown() - called at a full server shutdown.
"""
pass
pass

View file

@ -1,5 +1,5 @@
#
# This is an example batch build file for Evennia.
# This is an example batch build file for Evennia.
#
# It allows batch processing of normal Evennia commands.
# Test it by loading it with the @batchprocess command
@ -10,9 +10,9 @@
# marks the end of a previous command definition (important!).
#
# All supplied commands are given as normal, on their own line
# and accepts arguments in any format up until the first next
# and accepts arguments in any format up until the first next
# comment line begins. Extra whitespace is removed; an empty
# line in a command definition translates into a newline.
# line in a command definition translates into a newline.
#
# This creates a red button
@ -20,32 +20,32 @@
@create button:examples.red_button.RedButton
# This comment ends input for @create
# Next command:
# Next command:
@set button/desc =
This is a large red button. Now and then
it flashes in an evil, yet strangely tantalizing way.
@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!
Press me!
-----------
... It really begs to be pressed, doesn't it? You
know you want to!
# This ends the @set command. Note that line breaks and extra spaces
# in the argument are not considered. A completely empty line
... It really begs to be pressed, doesn't it? You
know you want to!
# This ends the @set command. Note that line breaks and extra spaces
# in the argument are not considered. A completely empty line
# translates to a \n newline in the command; two empty lines will thus
# create a new paragraph. (note that few commands support it though, you
# mainly want to use it for descriptions)
# Now let's place the button where it belongs (let's say limbo #2 is
# Now let's place the button where it belongs (let's say limbo #2 is
# the evil lair in our example)
@teleport #2

View file

@ -1,6 +1,6 @@
#
# Batchcode script
#
#
#
# The Batch-code processor accepts full python modules (e.g. "batch.py") that
# looks identical to normal Python files with a few exceptions that allows them
@ -8,29 +8,29 @@
# of the file and allows for features like stepping from block to block
# (without executing those coming before), as well as automatic deletion
# of created objects etc. You can however also run a batch-code python file
# directly using Python (and can also be de).
# directly using Python (and can also be de).
# Code blocks are separated by python comments starting with special code words.
# Code blocks are separated by python comments starting with special code words.
# #HEADER - this denotes commands global to the entire file, such as
# import statements and global variables. They will
# automatically be made available for each block. Observe
# that changes to these variables made in one block is not
# preserved between blocks!)
# #CODE (infotext) [objname, objname, ...] - This designates a code block that will be executed like a
# #CODE (infotext) [objname, objname, ...] - This designates a code block that will be executed like a
# stand-alone piece of code together with any #HEADER
# defined.
# infotext is a describing text about what goes in in this block. It will be
# defined.
# infotext is a describing text about what goes in in this block. It will be
# shown by the batchprocessing command.
# <objname>s mark the (variable-)names of objects created in the code,
# and which may be auto-deleted by the processor if desired (such as when
# debugging the script). E.g., if the code contains the command
# <objname>s mark the (variable-)names of objects created in the code,
# and which may be auto-deleted by the processor if desired (such as when
# debugging the script). E.g., if the code contains the command
# myobj = create.create_object(...), you could put 'myobj' in the #CODE header
# regardless of what the created object is actually called in-game.
# #INSERT filename - this includes another code batch file. The named file will be loaded and
# regardless of what the created object is actually called in-game.
# #INSERT filename - this includes another code batch file. The named file will be loaded and
# run at this point. Note that code from the inserted file will NOT share #HEADERs
# with the importing file, but will only use the headers in the importing file.
# make sure to not create a cyclic import here!
# make sure to not create a cyclic import here!
# The following variable is automatically made available for the script:
@ -38,9 +38,9 @@
#
#HEADER
#HEADER
# everything in this block will be appended to the beginning of
# everything in this block will be appended to the beginning of
# all other #CODE blocks when they are executed.
from ev import create, search
@ -53,13 +53,13 @@ limbo = search.objects('Limbo', global_search=True)[0]
#CODE (create red button)
# This is the first code block. Within each block, python
# code works as normal. Note how we make use if imports and
# code works as normal. Note how we make use if imports and
# 'limbo' defined in the #HEADER block. This block's header
# offers no information about red_button variable, so it
# won't be able to be deleted in debug mode.
# offers no information about red_button variable, so it
# won't be able to be deleted in debug mode.
# create a red button in limbo
red_button = create.create_object(red_button.RedButton, key="Red button",
red_button = create.create_object(red_button.RedButton, key="Red button",
location=limbo, aliases=["button"])
# we take a look at what we created
@ -74,10 +74,10 @@ caller.msg("A %s was created." % red_button.key)
# times).
# the python variables we assign to must match the ones given in the
# header for the system to be able to delete them afterwards during a
# debugging run.
# header for the system to be able to delete them afterwards during a
# debugging run.
table = create.create_object(baseobjects.Object, key="Table", location=limbo)
chair = create.create_object(baseobjects.Object, key="Chair", location=limbo)
string = "A %s and %s were created. If debug was active, they were deleted again."
string = "A %s and %s were created. If debug was active, they were deleted again."
caller.msg(string % (table, chair))

View file

@ -2,7 +2,7 @@
"""
Set up the evennia system. A first startup consists of giving
the command './manage syncdb' to setup the system and create
the database.
the database.
"""
import sys
@ -21,10 +21,10 @@ except IOError:
VERSION = "Unknown version"
#------------------------------------------------------------
# Check so session file exists in the current dir- if not, create it.
# Check so session file exists in the current dir- if not, create it.
#------------------------------------------------------------
_CREATED_SETTINGS = False
_CREATED_SETTINGS = False
if not os.path.exists('settings.py'):
# If settings.py doesn't already exist, create it and populate it with some
# basic stuff.
@ -33,7 +33,7 @@ if not os.path.exists('settings.py'):
_CREATED_SETTINGS = True
string = \
"""#
"""#
# Evennia MU* server configuration file
#
# You may customize your setup by copy&pasting the variables you want
@ -44,14 +44,14 @@ if not os.path.exists('settings.py'):
# (also, the master config file may change with server updates).
#
from src.settings_default import *
from src.settings_default import *
###################################################
# Evennia base server config
# Evennia base server config
###################################################
###################################################
# Evennia Database config
# Evennia Database config
###################################################
###################################################
@ -59,15 +59,15 @@ from src.settings_default import *
###################################################
###################################################
# Default command sets
# Default command sets
###################################################
###################################################
# Typeclasses
# Typeclasses
###################################################
###################################################
# Batch processors
# Batch processors
###################################################
###################################################
@ -100,8 +100,8 @@ from src.settings_default import *
# obs - this string cannot be under i18n since settings didn't exist yet.
print """
Welcome to Evennia (version %(version)s)!
We created a fresh settings.py file for you.""" % {'version': VERSION}
Welcome to Evennia (version %(version)s)!
We created a fresh settings.py file for you.""" % {'version': VERSION}
#------------------------------------------------------------
@ -118,18 +118,18 @@ except Exception:
# note - if this fails, ugettext will also fail, so we cannot translate this string.
string += """\n
Error: Couldn't import the file 'settings.py' in the directory
containing %(file)r. There are usually two reasons for this:
1) You moved your settings.py elsewhere. In that case move it back or
create a link to it from this folder.
Error: Couldn't import the file 'settings.py' in the directory
containing %(file)r. There are usually two reasons for this:
1) You moved your settings.py elsewhere. In that case move it back or
create a link to it from this folder.
2) The settings module is where it's supposed to be, but contains errors.
Review the traceback above to resolve the problem, then try again.
3) If you get errors on finding DJANGO_SETTINGS_MODULE you might have
Review the traceback above to resolve the problem, then try again.
3) If you get errors on finding DJANGO_SETTINGS_MODULE you might have
set up django wrong in some way. If you run a virtual machine, it might be worth
to restart it to see if this resolves the issue. Evennia should not require you
to define any environment variables manually.
""" % {'file': __file__}
print string
to restart it to see if this resolves the issue. Evennia should not require you
to define any environment variables manually.
""" % {'file': __file__}
print string
sys.exit(1)
os.environ['DJANGO_SETTINGS_MODULE'] = 'game.settings'
@ -139,8 +139,8 @@ os.environ['DJANGO_SETTINGS_MODULE'] = 'game.settings'
#------------------------------------------------------------
if __name__ == "__main__":
# checks if the settings file was created this run
if _CREATED_SETTINGS:
# checks if the settings file was created this run
if _CREATED_SETTINGS:
print _("""
Edit your new settings.py file as needed, then run
'python manage syncdb' and follow the prompts to
@ -149,7 +149,7 @@ if __name__ == "__main__":
sys.exit()
# run the standard django manager, if dependencies match
from src.utils.utils import check_evennia_dependencies
from src.utils.utils import check_evennia_dependencies
if check_evennia_dependencies():
from django.core.management import execute_manager
from django.core.management import execute_manager
execute_manager(settings)

View file

@ -14,7 +14,7 @@ upon returning, or not. A process returning != 0 will always stop, no
matter the value of this file.
"""
import os
import os
import sys
from optparse import OptionParser
from subprocess import Popen, call
@ -22,7 +22,7 @@ import Queue, thread, subprocess
#
# System Configuration
#
#
SERVER_PIDFILE = "server.pid"
@ -39,7 +39,7 @@ if not os.path.exists('settings.py'):
print "No settings.py file found. Run evennia.py to create it."
sys.exit()
# Get the settings
from django.conf import settings
@ -58,26 +58,26 @@ if 'PYTHONPATH' in os.environ:
else:
os.environ['PYTHONPATH'] = currpath
TWISTED_BINARY = 'twistd'
TWISTED_BINARY = 'twistd'
if os.name == 'nt':
TWISTED_BINARY = 'twistd.bat'
err = False
err = False
try:
import win32api # Test for for win32api
except ImportError:
err = True
err = True
if not os.path.exists(TWISTED_BINARY):
err = True
err = True
if err:
print "Twisted binary for Windows is not ready to use. Please run evennia.py."
sys.exit()
# Functions
# Functions
def set_restart_mode(restart_file, flag=True):
"""
This sets a flag file for the restart mode.
"""
This sets a flag file for the restart mode.
"""
f = open(restart_file, 'w')
f.write(str(flag))
f.close()
@ -89,24 +89,24 @@ def get_restart_mode(restart_file):
if os.path.exists(restart_file):
flag = open(restart_file, 'r').read()
return flag == "True"
return False
return False
def get_pid(pidfile):
"""
Get the PID (Process ID) by trying to access
an PID file.
an PID file.
"""
pid = None
pid = None
if os.path.exists(pidfile):
f = open(pidfile, 'r')
pid = f.read()
return pid
return pid
def cycle_logfile(logfile):
"""
Move the old log files to <filename>.old
"""
"""
logfile_old = logfile + '.old'
if os.path.exists(logfile):
# Cycle the old logfiles to *.old
@ -122,70 +122,70 @@ def cycle_logfile(logfile):
if os.path.exists(logfile_old):
# E.g. Windows don't support rename-replace
os.remove(logfile_old)
os.rename(logfile, logfile_old)
os.rename(logfile, logfile_old)
# Start program management
# Start program management
SERVER = None
PORTAL = None
PORTAL = None
def start_services(server_argv, portal_argv):
"""
This calls a threaded loop that launces the Portal and Server
and then restarts them when they finish.
and then restarts them when they finish.
"""
global SERVER, PORTAL
global SERVER, PORTAL
processes = Queue.Queue()
def server_waiter(queue):
try:
def server_waiter(queue):
try:
rc = Popen(server_argv).wait()
except Exception, e:
print "Server process error: %(e)s" % {'e': e}
queue.put(("server_stopped", rc)) # this signals the controller that the program finished
def portal_waiter(queue):
try:
def portal_waiter(queue):
try:
rc = Popen(portal_argv).wait()
except Exception, e:
print "Portal process error: %(e)s" % {'e': e}
queue.put(("portal_stopped", rc)) # this signals the controller that the program finished
if server_argv:
# start server as a reloadable thread
# start server as a reloadable thread
SERVER = thread.start_new_thread(server_waiter, (processes, ))
if portal_argv:
if portal_argv:
if get_restart_mode(PORTAL_RESTART):
# start portal as interactive, reloadable thread
# start portal as interactive, reloadable thread
PORTAL = thread.start_new_thread(portal_waiter, (processes, ))
else:
# normal operation: start portal as a daemon; we don't care to monitor it for restart
PORTAL = Popen(portal_argv)
if not SERVER:
# if portal is daemon and no server is running, we have no reason to continue to the loop.
return
return
# Reload loop
# Reload loop
while True:
# this blocks until something is actually returned.
message, rc = processes.get()
message, rc = processes.get()
# restart only if process stopped cleanly
if message == "server_stopped" and int(rc) == 0 and get_restart_mode(SERVER_RESTART):
print "Evennia Server stopped. Restarting ..."
print "Evennia Server stopped. Restarting ..."
SERVER = thread.start_new_thread(server_waiter, (processes, ))
continue
continue
# normally the portal is not reloaded since it's run as a daemon.
if message == "portal_stopped" and int(rc) == 0 and get_restart_mode(PORTAL_RESTART):
print "Evennia Portal stopped in interactive mode. Restarting ..."
PORTAL = thread.start_new_thread(portal_waiter, (processes, ))
continue
break
PORTAL = thread.start_new_thread(portal_waiter, (processes, ))
continue
break
# Setup signal handling
@ -193,19 +193,19 @@ def main():
"""
This handles the command line input of the runner (it's most often called by evennia.py)
"""
parser = OptionParser(usage="%prog [options] start",
description="This runner should normally *not* be called directly - it is called automatically from the evennia.py main program. It manages the Evennia game server and portal processes an hosts a threaded loop to restart the Server whenever it is stopped (this constitues Evennia's reload mechanism).")
parser.add_option('-s', '--noserver', action='store_true',
parser.add_option('-s', '--noserver', action='store_true',
dest='noserver', default=False,
help='Do not start Server process')
parser.add_option('-p', '--noportal', action='store_true',
parser.add_option('-p', '--noportal', action='store_true',
dest='noportal', default=False,
help='Do not start Portal process')
parser.add_option('-i', '--iserver', action='store_true',
parser.add_option('-i', '--iserver', action='store_true',
dest='iserver', default=False,
help='output server log to stdout instead of logfile')
parser.add_option('-d', '--iportal', action='store_true',
parser.add_option('-d', '--iportal', action='store_true',
dest='iportal', default=False,
help='output portal log to stdout. Does not make portal a daemon.')
parser.add_option('-S', '--profile-server', action='store_true',
@ -222,17 +222,17 @@ def main():
parser.print_help()
sys.exit()
# set up default project calls
server_argv = [TWISTED_BINARY,
# set up default project calls
server_argv = [TWISTED_BINARY,
'--nodaemon',
'--logfile=%s' % SERVER_LOGFILE,
'--pidfile=%s' % SERVER_PIDFILE,
'--pidfile=%s' % SERVER_PIDFILE,
'--python=%s' % SERVER_PY_FILE]
portal_argv = [TWISTED_BINARY,
'--logfile=%s' % PORTAL_LOGFILE,
'--pidfile=%s' % PORTAL_PIDFILE,
'--python=%s' % PORTAL_PY_FILE]
'--pidfile=%s' % PORTAL_PIDFILE,
'--python=%s' % PORTAL_PY_FILE]
# Profiling settings (read file from python shell e.g with
# p = pstats.Stats('server.prof')
sprof_argv = ['--savestats',
@ -242,14 +242,14 @@ def main():
'--profiler=cprofile',
'--profile=portal.prof']
# Server
# Server
pid = get_pid(SERVER_PIDFILE)
if pid and not options.noserver:
print "\nEvennia Server is already running as process %(pid)s. Not restarted." % {'pid': pid}
options.noserver = True
if options.noserver:
server_argv = None
server_argv = None
else:
set_restart_mode(SERVER_RESTART, True)
if options.iserver:
@ -264,19 +264,19 @@ def main():
cycle_logfile(SERVER_LOGFILE)
# Portal
# Portal
pid = get_pid(PORTAL_PIDFILE)
if pid and not options.noportal:
print "\nEvennia Portal is already running as process %(pid)s. Not restarted." % {'pid': pid}
options.noportal = True
print "\nEvennia Portal is already running as process %(pid)s. Not restarted." % {'pid': pid}
options.noportal = True
if options.noportal:
portal_argv = None
portal_argv = None
else:
if options.iportal:
# make portal interactive
portal_argv[1] = '--nodaemon'
PORTAL_INTERACTIVE = True
PORTAL_INTERACTIVE = True
set_restart_mode(PORTAL_RESTART, True)
print "\nStarting Evennia Portal in non-Daemon mode (output to stdout)."
else:
@ -297,7 +297,7 @@ def main():
# Start processes
start_services(server_argv, portal_argv)
if __name__ == '__main__':
from src.utils.utils import check_evennia_dependencies
if check_evennia_dependencies():