Largely rewrote and refactored the help system.
The help entry database structure has changed! You have to resync or purge your database or your will get problems! New features: * Help entry access now fully controlled by evennia permissions * Categories for each help entry * All entries are created dynamically, with a See also: footer calculated after the current state of the database. * Indexes and topic list calculated on the fly (alphabetically/after category) * Added auto-help help entries for all default commands. * Only shows commands _actually implemented_ - MUX help db moved into 'MUX' category which is not shown by default. * More powerful auto-help markup - supports categories and permissions (and inheritance). * Global on/off switch for auto-help, when entering production * Auto_help_override switch for selectively activating auto-help when developing new commands (like the old system). * Refactored State help system; no more risk of overwriting global help entries. * State help now defers to main help db when no match found; makes system more transparent. * State help entries also support categories/permissions (state categories are not used much though). Other updates: * Added more commands to the batch processor * Many bug-fixes. /Griatch
This commit is contained in:
parent
46e2cd3ecb
commit
8074617285
27 changed files with 1995 additions and 1072 deletions
|
|
@ -14,11 +14,10 @@ recognized.
|
||||||
Next enter the mud and give the command
|
Next enter the mud and give the command
|
||||||
> entermenu
|
> entermenu
|
||||||
|
|
||||||
Note that the help entries added to the state system with the auto_help flag are NOT
|
Note that the help entries related to this little menu are not part of the normal
|
||||||
part of the normal help database, they are stored with the state and only accessible
|
help database, they are stored with the state and only accessible
|
||||||
from inside it (unless you also set the 'global_help' flag in the add_command(), in
|
from inside it. If you want to describe the state itself in more detail you
|
||||||
which case it is also added to the global help system). If you want to describe the
|
should add a help entry about it to the main help index manually.
|
||||||
state itself in more detail you should add that to the main help index manually.
|
|
||||||
|
|
||||||
To further test the state system, try the command
|
To further test the state system, try the command
|
||||||
> enterstate
|
> enterstate
|
||||||
|
|
@ -58,10 +57,13 @@ def cmd_entermenu(command):
|
||||||
#show the menu.
|
#show the menu.
|
||||||
s = """
|
s = """
|
||||||
Welcome to the Demo menu!
|
Welcome to the Demo menu!
|
||||||
In this demo all you can do is select one of the two options so it changes colour.
|
In this small demo all you can do is select one of
|
||||||
This is just intended to show off the possibility of the state system. More
|
the two options so it changes colour.
|
||||||
interesting things should of course happen in a real menu. Use @exit to
|
This is just intended to show off the
|
||||||
leave the menu."""
|
possibilities of the state system. More
|
||||||
|
interesting things should of course happen
|
||||||
|
in a real menu.
|
||||||
|
Use @exit to leave the menu."""
|
||||||
source_object.emit_to(s)
|
source_object.emit_to(s)
|
||||||
source_object.execute_cmd('menu')
|
source_object.execute_cmd('menu')
|
||||||
|
|
||||||
|
|
@ -88,7 +90,7 @@ def menu_cmd_menu(command):
|
||||||
"""
|
"""
|
||||||
menu
|
menu
|
||||||
Clears the options and redraws the menu.
|
Clears the options and redraws the menu.
|
||||||
<<TOPIC:autohelp>>
|
[[autohelp]]
|
||||||
This is an extra topic to test the auto-help functionality. The state-help
|
This is an extra topic to test the auto-help functionality. The state-help
|
||||||
system supports nested ('related') topics just like the normal help index does.
|
system supports nested ('related') topics just like the normal help index does.
|
||||||
"""
|
"""
|
||||||
|
|
@ -122,14 +124,10 @@ GLOBAL_STATE_TABLE.add_state(STATENAME,exit_command=True)
|
||||||
|
|
||||||
#Add the menu commands to the state table by tying them to the 'menu' state. It is
|
#Add the menu commands to the state table by tying them to the 'menu' state. It is
|
||||||
#important that the name of the state matches what we set the player-object to in
|
#important that the name of the state matches what we set the player-object to in
|
||||||
#the 'entry' command. Since auto_help is on, we will have help entries for all commands
|
#the 'entry' command.
|
||||||
#while in the menu.
|
GLOBAL_STATE_TABLE.add_command(STATENAME, "option1", menu_cmd_option1)
|
||||||
GLOBAL_STATE_TABLE.add_command(STATENAME, "option1", menu_cmd_option1,auto_help=True)
|
GLOBAL_STATE_TABLE.add_command(STATENAME, "option2", menu_cmd_option2)
|
||||||
GLOBAL_STATE_TABLE.add_command(STATENAME, "option2", menu_cmd_option2,auto_help=True)
|
GLOBAL_STATE_TABLE.add_command(STATENAME, "menu", menu_cmd_menu)
|
||||||
GLOBAL_STATE_TABLE.add_command(STATENAME, "menu", menu_cmd_menu,auto_help=True)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#-----------------------testing the depth of the state system
|
#-----------------------testing the depth of the state system
|
||||||
# This is a test suite that shows off all the features of the state system.
|
# This is a test suite that shows off all the features of the state system.
|
||||||
|
|
@ -234,7 +232,7 @@ GLOBAL_STATE_TABLE.add_state(TSTATE6,exit_command=True,
|
||||||
allow_exits=True,allow_obj_cmds=True)
|
allow_exits=True,allow_obj_cmds=True)
|
||||||
|
|
||||||
#append the "test" function to all states
|
#append the "test" function to all states
|
||||||
GLOBAL_STATE_TABLE.add_command(TSTATE1,'test',cmd_instate_cmd,auto_help=True)
|
GLOBAL_STATE_TABLE.add_command(TSTATE1,'test',cmd_instate_cmd)
|
||||||
GLOBAL_STATE_TABLE.add_command(TSTATE2,'test',cmd_instate_cmd)
|
GLOBAL_STATE_TABLE.add_command(TSTATE2,'test',cmd_instate_cmd)
|
||||||
GLOBAL_STATE_TABLE.add_command(TSTATE3,'test',cmd_instate_cmd)
|
GLOBAL_STATE_TABLE.add_command(TSTATE3,'test',cmd_instate_cmd)
|
||||||
GLOBAL_STATE_TABLE.add_command(TSTATE4,'test',cmd_instate_cmd)
|
GLOBAL_STATE_TABLE.add_command(TSTATE4,'test',cmd_instate_cmd)
|
||||||
|
|
|
||||||
|
|
@ -291,7 +291,8 @@ def match_exits(command,test=False):
|
||||||
raise ExitCommandHandler
|
raise ExitCommandHandler
|
||||||
|
|
||||||
|
|
||||||
def command_table_lookup(command, command_table, eval_perms=True,test=False,neighbor=None):
|
def command_table_lookup(command, command_table, eval_perms=True,
|
||||||
|
test=False, neighbor=None):
|
||||||
"""
|
"""
|
||||||
Performs a command table lookup on the specified command table. Also
|
Performs a command table lookup on the specified command table. Also
|
||||||
evaluates the permissions tuple.
|
evaluates the permissions tuple.
|
||||||
|
|
@ -349,7 +350,7 @@ def match_neighbor_ctables(command,test=False):
|
||||||
#no matches
|
#no matches
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def handle(command):
|
def handle(command, ignore_state=False):
|
||||||
"""
|
"""
|
||||||
Use the spliced (list) uinput variable to retrieve the correct
|
Use the spliced (list) uinput variable to retrieve the correct
|
||||||
command, or return an invalid command error.
|
command, or return an invalid command error.
|
||||||
|
|
@ -357,6 +358,8 @@ def handle(command):
|
||||||
We're basically grabbing the player's command by tacking
|
We're basically grabbing the player's command by tacking
|
||||||
their input on to 'cmd_' and looking it up in the GenCommands
|
their input on to 'cmd_' and looking it up in the GenCommands
|
||||||
class.
|
class.
|
||||||
|
|
||||||
|
ignore_state : ignore eventual statetable lookups completely.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# TODO: Protect against non-standard characters.
|
# TODO: Protect against non-standard characters.
|
||||||
|
|
@ -379,11 +382,11 @@ def handle(command):
|
||||||
state = command.source_object.get_state()
|
state = command.source_object.get_state()
|
||||||
state_cmd_table = statetable.GLOBAL_STATE_TABLE.get_cmd_table(state)
|
state_cmd_table = statetable.GLOBAL_STATE_TABLE.get_cmd_table(state)
|
||||||
|
|
||||||
if state and state_cmd_table:
|
if state and state_cmd_table and not ignore_state:
|
||||||
# Caller is in a special state.
|
# Caller is in a special state.
|
||||||
|
|
||||||
state_allow_exits, state_allow_obj_cmds = \
|
state_allow_exits, state_allow_obj_cmds = \
|
||||||
statetable.GLOBAL_STATE_TABLE.get_state_flags(state)
|
statetable.GLOBAL_STATE_TABLE.get_exec_rights(state)
|
||||||
|
|
||||||
state_lookup = True
|
state_lookup = True
|
||||||
if match_channel(command):
|
if match_channel(command):
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ based on the value of settings.COMMAND_MODULES and
|
||||||
settings.CUSTOM_COMMAND_MODULES. Each module imports cmdtable.py and runs
|
settings.CUSTOM_COMMAND_MODULES. Each module imports cmdtable.py and runs
|
||||||
add_command on the command table each command belongs to.
|
add_command on the command table each command belongs to.
|
||||||
"""
|
"""
|
||||||
|
from django.conf import settings
|
||||||
from src.helpsys.management.commands.edit_helpfiles import add_help
|
from src.helpsys import helpsystem
|
||||||
|
|
||||||
class CommandTable(object):
|
class CommandTable(object):
|
||||||
"""
|
"""
|
||||||
|
|
@ -28,7 +28,8 @@ class CommandTable(object):
|
||||||
self.ctable = {}
|
self.ctable = {}
|
||||||
|
|
||||||
def add_command(self, command_string, function, priv_tuple=None,
|
def add_command(self, command_string, function, priv_tuple=None,
|
||||||
extra_vals=None, auto_help=False, staff_help=False):
|
extra_vals=None, help_category="", priv_help_tuple=None,
|
||||||
|
auto_help_override=None):
|
||||||
"""
|
"""
|
||||||
Adds a command to the command table.
|
Adds a command to the command table.
|
||||||
|
|
||||||
|
|
@ -37,28 +38,44 @@ class CommandTable(object):
|
||||||
priv_tuple: (tuple) String tuple of permissions required for command.
|
priv_tuple: (tuple) String tuple of permissions required for command.
|
||||||
extra_vals: (dict) Dictionary to add to the Command object.
|
extra_vals: (dict) Dictionary to add to the Command object.
|
||||||
|
|
||||||
Auto-help system:
|
Auto-help system: (this is only used if settings.HELP_AUTO_ENABLED is active)
|
||||||
auto_help (bool): If true, automatically creates/replaces a help topic with the
|
help_category (str): An overall help category where auto-help will place
|
||||||
same name as the command_string, using the functions's __doc__ property
|
the help entry. If not given, 'General' is assumed.
|
||||||
for help text.
|
priv_help_tuple (tuple) String tuple of permissions required to view this
|
||||||
staff_help (bool): Only relevant if auto_help is activated; If True, makes the
|
help entry. If nothing is given, priv_tuple is used.
|
||||||
help topic (and all eventual subtopics) only visible to staff.
|
auto_help_override (bool): Override the value in settings.AUTO_HELP_ENABLED with the
|
||||||
|
value given. Use None to not override.
|
||||||
|
This can be useful when developing a new routine and
|
||||||
|
has made manual changes to help entries of other
|
||||||
|
commands in the database (and so do not want to use global
|
||||||
|
auto-help). It is also used by e.g. the state system
|
||||||
|
to selectively deactive auto-help.
|
||||||
|
|
||||||
Note: the auto_help system also supports limited markup. If you divide your __doc__
|
Note: the auto_help system also supports limited markup. You can divide your __doc__
|
||||||
with markers of the form <<TOPIC:MyTopic>>, the system will automatically create
|
with markers of any combinations of the forms
|
||||||
separate help topics for each topic. Your initial text (if you define no TOPIC)
|
[[Title]]
|
||||||
will still default to the name of your command.
|
[[Title, category]]
|
||||||
You can also custon-set the staff_only flag for individual subtopics by
|
[[Title, (priv_tuple)]]
|
||||||
using the markup <<TOPIC:STAFF:MyTopic>> and <<TOPIC:NOSTAFF:MyTopic>>.
|
[[Title, category, (priv_tuple)]],
|
||||||
|
If such markers are found, the system will automatically create
|
||||||
|
separate help topics for each topic. Your main help entry will
|
||||||
|
default to the name of your command.
|
||||||
"""
|
"""
|
||||||
self.ctable[command_string] = (function, priv_tuple, extra_vals)
|
self.ctable[command_string] = (function, priv_tuple, extra_vals)
|
||||||
|
|
||||||
if auto_help:
|
if auto_help_override == None:
|
||||||
|
auto_help_override = settings.HELP_AUTO_ENABLED
|
||||||
|
|
||||||
|
if auto_help_override:
|
||||||
#add automatic help text from the command's doc string
|
#add automatic help text from the command's doc string
|
||||||
topicstr = command_string
|
topicstr = command_string
|
||||||
entrytext = function.__doc__
|
entrytext = function.__doc__
|
||||||
add_help(topicstr, entrytext, staff_only=staff_help,
|
if not help_category:
|
||||||
force_create=True, auto_help=True)
|
help_category = "General"
|
||||||
|
if not priv_help_tuple:
|
||||||
|
priv_help_tuple = priv_tuple
|
||||||
|
helpsystem.edithelp.add_help_auto(topicstr, help_category,
|
||||||
|
entrytext, priv_help_tuple)
|
||||||
|
|
||||||
def get_command_tuple(self, func_name):
|
def get_command_tuple(self, func_name):
|
||||||
"""
|
"""
|
||||||
|
|
@ -67,10 +84,6 @@ class CommandTable(object):
|
||||||
"""
|
"""
|
||||||
return self.ctable.get(func_name, False)
|
return self.ctable.get(func_name, False)
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
Command tables
|
|
||||||
"""
|
|
||||||
# Global command table, for authenticated users.
|
# Global command table, for authenticated users.
|
||||||
GLOBAL_CMD_TABLE = CommandTable()
|
GLOBAL_CMD_TABLE = CommandTable()
|
||||||
# Global unconnected command table, for unauthenticated users.
|
# Global unconnected command table, for unauthenticated users.
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ from src.statetable import GLOBAL_STATE_TABLE
|
||||||
|
|
||||||
#global defines for storage
|
#global defines for storage
|
||||||
|
|
||||||
STATENAME="_interactive_batch_processor"
|
STATENAME="interactive batch processor"
|
||||||
CMDSTACKS={} # user:cmdstack pairs (for interactive)
|
CMDSTACKS={} # user:cmdstack pairs (for interactive)
|
||||||
STACKPTRS={} # user:stackpointer pairs (for interactive)
|
STACKPTRS={} # user:stackpointer pairs (for interactive)
|
||||||
FILENAMES={} # user:filename pairs (for interactive/reload)
|
FILENAMES={} # user:filename pairs (for interactive/reload)
|
||||||
|
|
@ -161,6 +161,8 @@ def batch_process(source_object, commands):
|
||||||
|
|
||||||
def cmd_batchprocess(command):
|
def cmd_batchprocess(command):
|
||||||
"""
|
"""
|
||||||
|
@batchprocess - build from batch file
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
@batchprocess[/interactive] <filename with full path>
|
@batchprocess[/interactive] <filename with full path>
|
||||||
|
|
||||||
|
|
@ -198,16 +200,16 @@ def cmd_batchprocess(command):
|
||||||
CMDSTACKS[source_object] = commands
|
CMDSTACKS[source_object] = commands
|
||||||
STACKPTRS[source_object] = 0
|
STACKPTRS[source_object] = 0
|
||||||
FILENAMES[source_object] = filename
|
FILENAMES[source_object] = filename
|
||||||
source_object.emit_to("Interactive mode (h for help).")
|
source_object.emit_to("\nBatch processor - Interactive mode ...")
|
||||||
show_curr(source_object)
|
show_curr(source_object)
|
||||||
else:
|
else:
|
||||||
|
source_object.emit_to("Running Batch processor - Automatic mode ...")
|
||||||
source_object.clear_state()
|
source_object.clear_state()
|
||||||
batch_process(source_object, commands)
|
batch_process(source_object, commands)
|
||||||
source_object.emit_to("%s== Batchfile '%s' applied." % (cgreen,filename))
|
source_object.emit_to("%s== Batchfile '%s' applied." % (cgreen,filename))
|
||||||
|
|
||||||
GLOBAL_CMD_TABLE.add_command("@batchprocess", cmd_batchprocess,
|
GLOBAL_CMD_TABLE.add_command("@batchprocess", cmd_batchprocess,
|
||||||
auto_help=True, staff_help=True,
|
priv_tuple=("genperms.process_control",), help_category="Building")
|
||||||
priv_tuple=("genperms.process_control"))
|
|
||||||
|
|
||||||
#interactive state commands
|
#interactive state commands
|
||||||
|
|
||||||
|
|
@ -271,43 +273,71 @@ def reload_stack(source_object):
|
||||||
source_object.emit_to("Commands in file could not be reloaded. Was it moved?")
|
source_object.emit_to("Commands in file could not be reloaded. Was it moved?")
|
||||||
|
|
||||||
def move_in_stack(source_object, step=1):
|
def move_in_stack(source_object, step=1):
|
||||||
|
"store data in stack"
|
||||||
global CMDSTACKS, STACKPTRS
|
global CMDSTACKS, STACKPTRS
|
||||||
N = len(CMDSTACKS[source_object])
|
N = len(CMDSTACKS[source_object])
|
||||||
currpos = STACKPTRS[source_object]
|
currpos = STACKPTRS[source_object]
|
||||||
STACKPTRS[source_object] = max(0,min(N-1,currpos+step))
|
STACKPTRS[source_object] = max(0,min(N-1,currpos+step))
|
||||||
|
|
||||||
def exit_state(source_object):
|
def exit_state(source_object):
|
||||||
|
"Quit the state"
|
||||||
global CMDSTACKS,STACKPTRS,FILENAMES
|
global CMDSTACKS,STACKPTRS,FILENAMES
|
||||||
|
try:
|
||||||
del CMDSTACKS[source_object]
|
del CMDSTACKS[source_object]
|
||||||
del STACKPTRS[source_object]
|
del STACKPTRS[source_object]
|
||||||
del FILENAMES[source_object]
|
del FILENAMES[source_object]
|
||||||
|
except KeyError:
|
||||||
|
logger.log_errmsg("Batchprocessor quit error: all state vars could not be deleted.")
|
||||||
source_object.clear_state()
|
source_object.clear_state()
|
||||||
|
|
||||||
def cmd_state_l(command):
|
def cmd_state_ll(command):
|
||||||
"l-ook at current command definition"
|
"""
|
||||||
|
ll
|
||||||
|
|
||||||
|
Look at the full source for the current
|
||||||
|
command definition.
|
||||||
|
"""
|
||||||
show_curr(command.source_object,showall=True)
|
show_curr(command.source_object,showall=True)
|
||||||
|
|
||||||
def cmd_state_p(command):
|
def cmd_state_pp(command):
|
||||||
"p-rocess current command definition"
|
"""
|
||||||
|
pp
|
||||||
|
|
||||||
|
Process the currently shown command definition.
|
||||||
|
"""
|
||||||
process_commands(command.source_object)
|
process_commands(command.source_object)
|
||||||
command.source_object.emit_to(printfooter())
|
command.source_object.emit_to(printfooter())
|
||||||
|
|
||||||
def cmd_state_r(command):
|
def cmd_state_rr(command):
|
||||||
"r-eload file, keep current stack position"
|
"""
|
||||||
|
rr
|
||||||
|
|
||||||
|
Reload the batch file, keeping the current
|
||||||
|
position in it.
|
||||||
|
"""
|
||||||
reload_stack(command.source_object)
|
reload_stack(command.source_object)
|
||||||
command.source_object.emit_to("\nFile reloaded. Staying on same command.\n")
|
command.source_object.emit_to("\nFile reloaded. Staying on same command.\n")
|
||||||
show_curr(command.source_object)
|
show_curr(command.source_object)
|
||||||
|
|
||||||
def cmd_state_rr(command):
|
def cmd_state_rrr(command):
|
||||||
"r-eload file, start over"
|
"""
|
||||||
|
rrr
|
||||||
|
|
||||||
|
Reload the batch file, starting over
|
||||||
|
from the beginning.
|
||||||
|
"""
|
||||||
global STACKPTRS
|
global STACKPTRS
|
||||||
reload_stack(command.source_object)
|
reload_stack(command.source_object)
|
||||||
STACKPTRS[command.source_object] = 0
|
STACKPTRS[command.source_object] = 0
|
||||||
command.source_object.emit_to("\nFile reloaded. Restarting from top.\n")
|
command.source_object.emit_to("\nFile reloaded. Restarting from top.\n")
|
||||||
show_curr(command.source_object)
|
show_curr(command.source_object)
|
||||||
|
|
||||||
def cmd_state_n(command):
|
def cmd_state_nn(command):
|
||||||
"n-ext command (no exec)"
|
"""
|
||||||
|
nn
|
||||||
|
|
||||||
|
Go to next command. No commands are executed.
|
||||||
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
arg = command.command_argument
|
arg = command.command_argument
|
||||||
if arg and arg.isdigit():
|
if arg and arg.isdigit():
|
||||||
|
|
@ -317,8 +347,29 @@ def cmd_state_n(command):
|
||||||
move_in_stack(source_object, step)
|
move_in_stack(source_object, step)
|
||||||
show_curr(source_object)
|
show_curr(source_object)
|
||||||
|
|
||||||
def cmd_state_b(command):
|
def cmd_state_nl(command):
|
||||||
"b-ackwards to previous command (no exec)"
|
"""
|
||||||
|
nl
|
||||||
|
|
||||||
|
Go to next command, viewing its full source.
|
||||||
|
No commands are executed.
|
||||||
|
"""
|
||||||
|
source_object = command.source_object
|
||||||
|
arg = command.command_argument
|
||||||
|
if arg and arg.isdigit():
|
||||||
|
step = int(command.command_argument)
|
||||||
|
else:
|
||||||
|
step = 1
|
||||||
|
move_in_stack(source_object, step)
|
||||||
|
show_curr(source_object, showall=True)
|
||||||
|
|
||||||
|
def cmd_state_bb(command):
|
||||||
|
"""
|
||||||
|
bb
|
||||||
|
|
||||||
|
Backwards to previous command. No commands
|
||||||
|
are executed.
|
||||||
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
arg = command.command_argument
|
arg = command.command_argument
|
||||||
if arg and arg.isdigit():
|
if arg and arg.isdigit():
|
||||||
|
|
@ -328,8 +379,30 @@ def cmd_state_b(command):
|
||||||
move_in_stack(source_object, step)
|
move_in_stack(source_object, step)
|
||||||
show_curr(source_object)
|
show_curr(source_object)
|
||||||
|
|
||||||
def cmd_state_s(command):
|
def cmd_state_bl(command):
|
||||||
"s-tep to next command (exec)"
|
"""
|
||||||
|
bl
|
||||||
|
|
||||||
|
Backwards to previous command, viewing its full
|
||||||
|
source. No commands are executed.
|
||||||
|
"""
|
||||||
|
source_object = command.source_object
|
||||||
|
arg = command.command_argument
|
||||||
|
if arg and arg.isdigit():
|
||||||
|
step = -int(command.command_argument)
|
||||||
|
else:
|
||||||
|
step = -1
|
||||||
|
move_in_stack(source_object, step)
|
||||||
|
show_curr(source_object, showall=True)
|
||||||
|
|
||||||
|
def cmd_state_ss(command):
|
||||||
|
"""
|
||||||
|
ss [steps]
|
||||||
|
|
||||||
|
Process current command, then step to the next
|
||||||
|
one. If steps is given,
|
||||||
|
process this many commands.
|
||||||
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
arg = command.command_argument
|
arg = command.command_argument
|
||||||
if arg and arg.isdigit():
|
if arg and arg.isdigit():
|
||||||
|
|
@ -339,8 +412,30 @@ def cmd_state_s(command):
|
||||||
process_commands(source_object,step)
|
process_commands(source_object,step)
|
||||||
show_curr(source_object)
|
show_curr(source_object)
|
||||||
|
|
||||||
def cmd_state_c(command):
|
def cmd_state_sl(command):
|
||||||
"c-ontinue to process remaining"
|
"""
|
||||||
|
sl [steps]
|
||||||
|
|
||||||
|
Process current command, then step to the next
|
||||||
|
one, viewing its full source. If steps is given,
|
||||||
|
process this many commands.
|
||||||
|
"""
|
||||||
|
source_object = command.source_object
|
||||||
|
arg = command.command_argument
|
||||||
|
if arg and arg.isdigit():
|
||||||
|
step = int(command.command_argument)
|
||||||
|
else:
|
||||||
|
step = 1
|
||||||
|
process_commands(source_object,step)
|
||||||
|
show_curr(source_object, showall=True)
|
||||||
|
|
||||||
|
def cmd_state_cc(command):
|
||||||
|
"""
|
||||||
|
cc
|
||||||
|
|
||||||
|
Continue to process all remaining
|
||||||
|
commands.
|
||||||
|
"""
|
||||||
global CMDSTACKS,STACKPTRS
|
global CMDSTACKS,STACKPTRS
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
N = len(CMDSTACKS[source_object])
|
N = len(CMDSTACKS[source_object])
|
||||||
|
|
@ -350,8 +445,12 @@ def cmd_state_c(command):
|
||||||
exit_state(source_object)
|
exit_state(source_object)
|
||||||
source_object.emit_to("Finished processing batch file.")
|
source_object.emit_to("Finished processing batch file.")
|
||||||
|
|
||||||
def cmd_state_j(command):
|
def cmd_state_jj(command):
|
||||||
"j-ump to specific command index"
|
"""
|
||||||
|
j <command number>
|
||||||
|
|
||||||
|
Jump to specific command number
|
||||||
|
"""
|
||||||
global STACKPTRS
|
global STACKPTRS
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
arg = command.command_argument
|
arg = command.command_argument
|
||||||
|
|
@ -365,18 +464,44 @@ def cmd_state_j(command):
|
||||||
move_in_stack(source_object, step)
|
move_in_stack(source_object, step)
|
||||||
show_curr(source_object)
|
show_curr(source_object)
|
||||||
|
|
||||||
def cmd_state_q(command):
|
def cmd_state_jl(command):
|
||||||
"q-uit state."
|
"""
|
||||||
|
jl <command number>
|
||||||
|
|
||||||
|
Jump to specific command number and view its full source.
|
||||||
|
"""
|
||||||
|
global STACKPTRS
|
||||||
|
source_object = command.source_object
|
||||||
|
arg = command.command_argument
|
||||||
|
if arg and arg.isdigit():
|
||||||
|
no = int(command.command_argument)-1
|
||||||
|
else:
|
||||||
|
source_object.emit_to("You must give a number index.")
|
||||||
|
return
|
||||||
|
ptr = STACKPTRS[source_object]
|
||||||
|
step = no - ptr
|
||||||
|
move_in_stack(source_object, step)
|
||||||
|
show_curr(source_object, showall=True)
|
||||||
|
|
||||||
|
def cmd_state_qq(command):
|
||||||
|
"""
|
||||||
|
qq
|
||||||
|
|
||||||
|
Quit the batchprocessor.
|
||||||
|
"""
|
||||||
exit_state(command.source_object)
|
exit_state(command.source_object)
|
||||||
command.source_object.emit_to("Aborted interactive batch mode.")
|
command.source_object.emit_to("Aborted interactive batch mode.")
|
||||||
|
|
||||||
def cmd_state_h(command):
|
def cmd_state_hh(command):
|
||||||
"Help command"
|
"Help command"
|
||||||
s = """
|
s = """
|
||||||
Interactive batch processing commands:
|
Interactive batch processing commands:
|
||||||
nn [steps] - next command (no processing)
|
nn [steps] - next command (no processing)
|
||||||
|
nl [steps] - next & look
|
||||||
bb [steps] - back to previous command (no processing)
|
bb [steps] - back to previous command (no processing)
|
||||||
|
bl [steps] - back & look
|
||||||
jj <N> - jump to command no N (no processing)
|
jj <N> - jump to command no N (no processing)
|
||||||
|
jl <N> - jump & look
|
||||||
pp - process currently shown command (no step)
|
pp - process currently shown command (no step)
|
||||||
ss [steps] - process & step
|
ss [steps] - process & step
|
||||||
ll - look at full definition of current command
|
ll - look at full definition of current command
|
||||||
|
|
@ -384,8 +509,8 @@ def cmd_state_h(command):
|
||||||
rrr - reload batch file (start from first)
|
rrr - reload batch file (start from first)
|
||||||
hh - this help list
|
hh - this help list
|
||||||
|
|
||||||
cc - continue processing to end and quit.
|
cc - continue processing to end, then quit.
|
||||||
qq - quit (abort all remaining)
|
qq - quit (abort all remaining commands)
|
||||||
"""
|
"""
|
||||||
command.source_object.emit_to(s)
|
command.source_object.emit_to(s)
|
||||||
|
|
||||||
|
|
@ -394,14 +519,18 @@ def cmd_state_h(command):
|
||||||
GLOBAL_STATE_TABLE.add_state(STATENAME,global_cmds='all',
|
GLOBAL_STATE_TABLE.add_state(STATENAME,global_cmds='all',
|
||||||
allow_exits=True,allow_obj_cmds=True)
|
allow_exits=True,allow_obj_cmds=True)
|
||||||
#add state commands
|
#add state commands
|
||||||
GLOBAL_STATE_TABLE.add_command(STATENAME,"nn",cmd_state_n)
|
GLOBAL_STATE_TABLE.add_command(STATENAME,"nn",cmd_state_nn)
|
||||||
GLOBAL_STATE_TABLE.add_command(STATENAME,"bb",cmd_state_b)
|
GLOBAL_STATE_TABLE.add_command(STATENAME,"nl",cmd_state_nl)
|
||||||
GLOBAL_STATE_TABLE.add_command(STATENAME,"jj",cmd_state_j)
|
GLOBAL_STATE_TABLE.add_command(STATENAME,"bb",cmd_state_bb)
|
||||||
GLOBAL_STATE_TABLE.add_command(STATENAME,"pp",cmd_state_p)
|
GLOBAL_STATE_TABLE.add_command(STATENAME,"bl",cmd_state_bl)
|
||||||
GLOBAL_STATE_TABLE.add_command(STATENAME,"ss",cmd_state_s)
|
GLOBAL_STATE_TABLE.add_command(STATENAME,"jj",cmd_state_jj)
|
||||||
GLOBAL_STATE_TABLE.add_command(STATENAME,"cc",cmd_state_c)
|
GLOBAL_STATE_TABLE.add_command(STATENAME,"jl",cmd_state_jl)
|
||||||
GLOBAL_STATE_TABLE.add_command(STATENAME,"ll",cmd_state_l)
|
GLOBAL_STATE_TABLE.add_command(STATENAME,"pp",cmd_state_pp)
|
||||||
GLOBAL_STATE_TABLE.add_command(STATENAME,"rr",cmd_state_r)
|
GLOBAL_STATE_TABLE.add_command(STATENAME,"ss",cmd_state_ss)
|
||||||
GLOBAL_STATE_TABLE.add_command(STATENAME,"rrr",cmd_state_rr)
|
GLOBAL_STATE_TABLE.add_command(STATENAME,"sl",cmd_state_sl)
|
||||||
GLOBAL_STATE_TABLE.add_command(STATENAME,"hh",cmd_state_h)
|
GLOBAL_STATE_TABLE.add_command(STATENAME,"cc",cmd_state_cc)
|
||||||
GLOBAL_STATE_TABLE.add_command(STATENAME,"qq",cmd_state_q)
|
GLOBAL_STATE_TABLE.add_command(STATENAME,"ll",cmd_state_ll)
|
||||||
|
GLOBAL_STATE_TABLE.add_command(STATENAME,"rr",cmd_state_rr)
|
||||||
|
GLOBAL_STATE_TABLE.add_command(STATENAME,"rrr",cmd_state_rrr)
|
||||||
|
GLOBAL_STATE_TABLE.add_command(STATENAME,"hh",cmd_state_hh)
|
||||||
|
GLOBAL_STATE_TABLE.add_command(STATENAME,"qq",cmd_state_qq)
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,22 @@
|
||||||
"""
|
"""
|
||||||
Comsys command module.
|
Comsys command module.
|
||||||
"""
|
"""
|
||||||
import time
|
|
||||||
from django.conf import settings
|
|
||||||
from src import comsys
|
from src import comsys
|
||||||
from src.channels.models import CommChannelMembership, CommChannel
|
from src.channels.models import CommChannelMembership, CommChannel
|
||||||
from src import defines_global
|
from src import defines_global
|
||||||
from src import ansi
|
|
||||||
from src.util import functions_general
|
|
||||||
from src.objects.models import Object
|
from src.objects.models import Object
|
||||||
from src.cmdtable import GLOBAL_CMD_TABLE
|
from src.cmdtable import GLOBAL_CMD_TABLE
|
||||||
|
|
||||||
def cmd_addcom(command):
|
def cmd_addcom(command):
|
||||||
"""
|
"""
|
||||||
addcom
|
addcom - join a channel with alias
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
addcom [alias=] <channel>
|
addcom [alias=] <channel>
|
||||||
|
|
||||||
Joins a channel. Allows adding an alias for it to make it
|
Allows adding an alias for a channel to make is easier and
|
||||||
easier and faster to use. Subsequent calls of this command
|
faster to use. Subsequent calls of this command can
|
||||||
can be used to add multiple aliases.
|
be used to add multiple aliases.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
command_argument = command.command_argument
|
command_argument = command.command_argument
|
||||||
|
|
@ -81,11 +77,11 @@ def cmd_addcom(command):
|
||||||
except CommChannel.DoesNotExist:
|
except CommChannel.DoesNotExist:
|
||||||
# Failed to match iexact on channel's 'name' attribute.
|
# Failed to match iexact on channel's 'name' attribute.
|
||||||
source_object.emit_to("Could not find channel %s." % chan_name)
|
source_object.emit_to("Could not find channel %s." % chan_name)
|
||||||
GLOBAL_CMD_TABLE.add_command("addcom", cmd_addcom)
|
GLOBAL_CMD_TABLE.add_command("addcom", cmd_addcom, help_category="Comms")
|
||||||
|
|
||||||
def cmd_delcom(command):
|
def cmd_delcom(command):
|
||||||
"""
|
"""
|
||||||
delcom
|
delcom - remove a channel alias
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
delcom <alias>
|
delcom <alias>
|
||||||
|
|
@ -113,10 +109,15 @@ def cmd_delcom(command):
|
||||||
leave_msg = "%s has left the channel." % \
|
leave_msg = "%s has left the channel." % \
|
||||||
(source_object.get_name(show_dbref=False),)
|
(source_object.get_name(show_dbref=False),)
|
||||||
comsys.send_cmessage(chan_name, leave_msg)
|
comsys.send_cmessage(chan_name, leave_msg)
|
||||||
GLOBAL_CMD_TABLE.add_command("delcom", cmd_delcom),
|
GLOBAL_CMD_TABLE.add_command("delcom", cmd_delcom,help_category="Comms")
|
||||||
|
|
||||||
def cmd_comlist(command):
|
def cmd_comlist(command):
|
||||||
"""
|
"""
|
||||||
|
comlist - list channel memberships
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
comlist
|
||||||
|
|
||||||
Lists the channels a user is subscribed to.
|
Lists the channels a user is subscribed to.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
@ -137,10 +138,13 @@ def cmd_comlist(command):
|
||||||
chan.get_name(), chan_on)
|
chan.get_name(), chan_on)
|
||||||
s = s[:-1]
|
s = s[:-1]
|
||||||
source_object.emit_to(s)
|
source_object.emit_to(s)
|
||||||
GLOBAL_CMD_TABLE.add_command("comlist", cmd_comlist)
|
GLOBAL_CMD_TABLE.add_command("comlist", cmd_comlist,help_category="Comms")
|
||||||
|
|
||||||
def cmd_allcom(command):
|
def cmd_allcom(command):
|
||||||
"""
|
"""
|
||||||
|
allcom - operate on all channels
|
||||||
|
|
||||||
|
Usage:
|
||||||
allcom [on | off | who | clear]
|
allcom [on | off | who | clear]
|
||||||
|
|
||||||
Allows the user to universally turn off or on all channels they are on,
|
Allows the user to universally turn off or on all channels they are on,
|
||||||
|
|
@ -197,14 +201,18 @@ def cmd_allcom(command):
|
||||||
s = s[:-2] + "\n"
|
s = s[:-2] + "\n"
|
||||||
s = s[:-1]
|
s = s[:-1]
|
||||||
source_object.emit_to(s)
|
source_object.emit_to(s)
|
||||||
GLOBAL_CMD_TABLE.add_command("allcom", cmd_allcom)
|
GLOBAL_CMD_TABLE.add_command("allcom", cmd_allcom, help_category="Comms")
|
||||||
|
|
||||||
def cmd_clearcom(command):
|
def cmd_clearcom(command):
|
||||||
"""
|
"""
|
||||||
|
clearcom - removes all channels
|
||||||
|
|
||||||
|
Usage:
|
||||||
clearcom
|
clearcom
|
||||||
|
|
||||||
Effectively runs delcom on all channels the user is on. It will remove their aliases,
|
Effectively runs delcom on all channels the user is on. It will remove
|
||||||
remove them from the channel, and clear any titles they have set.
|
their aliases, remove them from the channel, and clear any titles they
|
||||||
|
have set.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
#get aall subscribed channel memberships
|
#get aall subscribed channel memberships
|
||||||
|
|
@ -227,7 +235,10 @@ def cmd_clist(command):
|
||||||
"""
|
"""
|
||||||
@clist
|
@clist
|
||||||
|
|
||||||
Lists all available channels on the game.
|
Usage:
|
||||||
|
@clist
|
||||||
|
|
||||||
|
Lists all available channels in the game.
|
||||||
"""
|
"""
|
||||||
session = command.session
|
session = command.session
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
@ -248,13 +259,17 @@ def cmd_clist(command):
|
||||||
s = s[:-1]
|
s = s[:-1]
|
||||||
#s += "** End of Channel List **"
|
#s += "** End of Channel List **"
|
||||||
source_object.emit_to(s)
|
source_object.emit_to(s)
|
||||||
GLOBAL_CMD_TABLE.add_command("@clist", cmd_clist),
|
GLOBAL_CMD_TABLE.add_command("@clist", cmd_clist, help_category="Comms")
|
||||||
|
|
||||||
|
|
||||||
def cmd_cdestroy(command):
|
def cmd_cdestroy(command):
|
||||||
"""
|
"""
|
||||||
@cdestroy
|
@cdestroy
|
||||||
|
|
||||||
Destroys a channel.
|
Usage:
|
||||||
|
@cdestroy <channel>
|
||||||
|
|
||||||
|
Destroys a channel that you control.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
cname = command.command_argument
|
cname = command.command_argument
|
||||||
|
|
@ -275,7 +290,7 @@ def cmd_cdestroy(command):
|
||||||
else:
|
else:
|
||||||
source_object.emit_to("Permission denied.")
|
source_object.emit_to("Permission denied.")
|
||||||
return
|
return
|
||||||
GLOBAL_CMD_TABLE.add_command("@cdestroy", cmd_cdestroy)
|
GLOBAL_CMD_TABLE.add_command("@cdestroy", cmd_cdestroy, help_category="Comms")
|
||||||
|
|
||||||
def cmd_cset(command):
|
def cmd_cset(command):
|
||||||
"""
|
"""
|
||||||
|
|
@ -297,9 +312,12 @@ def cmd_ccharge(command):
|
||||||
|
|
||||||
def cmd_cboot(command):
|
def cmd_cboot(command):
|
||||||
"""
|
"""
|
||||||
@cboot[/quiet] <channel>=<object>
|
@cboot
|
||||||
|
|
||||||
Kicks a player or object from the channel
|
Usage:
|
||||||
|
@cboot[/quiet] <channel> = <player or object>
|
||||||
|
|
||||||
|
Kicks a player or object from a channel you control.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
args = command.command_argument
|
args = command.command_argument
|
||||||
|
|
@ -352,11 +370,14 @@ def cmd_cboot(command):
|
||||||
for mship in membership:
|
for mship in membership:
|
||||||
comsys.plr_del_channel(bootobj, mship.user_alias)
|
comsys.plr_del_channel(bootobj, mship.user_alias)
|
||||||
|
|
||||||
GLOBAL_CMD_TABLE.add_command("@cboot", cmd_cboot)
|
GLOBAL_CMD_TABLE.add_command("@cboot", cmd_cboot, help_category="Comms")
|
||||||
|
|
||||||
|
|
||||||
def cmd_cemit(command):
|
def cmd_cemit(command):
|
||||||
"""
|
"""
|
||||||
|
@cemit - send a message to channel
|
||||||
|
|
||||||
|
Usage:
|
||||||
@cemit <channel>=<message>
|
@cemit <channel>=<message>
|
||||||
@cemit/noheader <channel>=<message>
|
@cemit/noheader <channel>=<message>
|
||||||
@cemit/sendername <channel>=<message>
|
@cemit/sendername <channel>=<message>
|
||||||
|
|
@ -425,12 +446,12 @@ def cmd_cemit(command):
|
||||||
#pipe to external channels (IRC, IMC) eventually mapped to this channel
|
#pipe to external channels (IRC, IMC) eventually mapped to this channel
|
||||||
comsys.send_cexternal(cname_parsed, cmessage, caller=source_object)
|
comsys.send_cexternal(cname_parsed, cmessage, caller=source_object)
|
||||||
|
|
||||||
GLOBAL_CMD_TABLE.add_command("@cemit", cmd_cemit,priv_tuple=("channels.emit_commchannel",))
|
GLOBAL_CMD_TABLE.add_command("@cemit", cmd_cemit,priv_tuple=("channels.emit_commchannel",),
|
||||||
|
help_category="Comms")
|
||||||
|
|
||||||
def cmd_cwho(command):
|
def cmd_cwho(command):
|
||||||
"""
|
"""
|
||||||
@cwho
|
@cwho
|
||||||
list
|
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
@cwho channel[/all]
|
@cwho channel[/all]
|
||||||
|
|
@ -468,15 +489,17 @@ def cmd_cwho(command):
|
||||||
else:
|
else:
|
||||||
source_object.emit_to("No channel with that name was found.")
|
source_object.emit_to("No channel with that name was found.")
|
||||||
return
|
return
|
||||||
GLOBAL_CMD_TABLE.add_command("@cwho", cmd_cwho),
|
GLOBAL_CMD_TABLE.add_command("@cwho", cmd_cwho, help_category="Comms")
|
||||||
|
|
||||||
def cmd_ccreate(command):
|
def cmd_ccreate(command):
|
||||||
"""
|
"""
|
||||||
@ccreate
|
@ccreate
|
||||||
|
|
||||||
Creates a new channel with the invoker being the default owner.
|
Usage:
|
||||||
|
@ccreate <new channel>
|
||||||
|
|
||||||
|
Creates a new channel owned by you.
|
||||||
"""
|
"""
|
||||||
# TODO: Implement cmd_ccreate
|
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
cname = command.command_argument
|
cname = command.command_argument
|
||||||
|
|
||||||
|
|
@ -496,10 +519,13 @@ def cmd_ccreate(command):
|
||||||
# Create and set the object up.
|
# Create and set the object up.
|
||||||
new_chan = comsys.create_channel(cname, source_object)
|
new_chan = comsys.create_channel(cname, source_object)
|
||||||
source_object.emit_to("Channel %s created." % (new_chan.get_name(),))
|
source_object.emit_to("Channel %s created." % (new_chan.get_name(),))
|
||||||
GLOBAL_CMD_TABLE.add_command("@ccreate", cmd_ccreate)
|
GLOBAL_CMD_TABLE.add_command("@ccreate", cmd_ccreate, help_category="Comms")
|
||||||
|
|
||||||
def cmd_cchown(command):
|
def cmd_cchown(command):
|
||||||
"""
|
"""
|
||||||
|
@cchown
|
||||||
|
|
||||||
|
Usage:
|
||||||
@cchown <channel> = <player>
|
@cchown <channel> = <player>
|
||||||
|
|
||||||
Changes the owner of a channel.
|
Changes the owner of a channel.
|
||||||
|
|
@ -535,4 +561,4 @@ def cmd_cchown(command):
|
||||||
channel.set_owner(new_owner)
|
channel.set_owner(new_owner)
|
||||||
source_object.emit_to("Owner of %s changed from %s to %s." % (cname, old_pname, pname))
|
source_object.emit_to("Owner of %s changed from %s to %s." % (cname, old_pname, pname))
|
||||||
new_owner.emit_to("%s transfered ownership of channel '%s' to you." % (old_pname, cname))
|
new_owner.emit_to("%s transfered ownership of channel '%s' to you." % (old_pname, cname))
|
||||||
GLOBAL_CMD_TABLE.add_command("@cchown", cmd_cchown)
|
GLOBAL_CMD_TABLE.add_command("@cchown", cmd_cchown, help_category="Comms")
|
||||||
|
|
|
||||||
|
|
@ -7,17 +7,19 @@ from django.contrib.auth.models import User
|
||||||
from src.config.models import ConfigValue
|
from src.config.models import ConfigValue
|
||||||
from src.helpsys.models import HelpEntry
|
from src.helpsys.models import HelpEntry
|
||||||
from src.ansi import ANSITable
|
from src.ansi import ANSITable
|
||||||
from src import defines_global
|
|
||||||
from src import session_mgr
|
from src import session_mgr
|
||||||
from src.util import functions_general
|
from src.util import functions_general
|
||||||
import src.helpsys.management.commands.edit_helpfiles as edit_help
|
from src.helpsys import helpsystem
|
||||||
from src.cmdtable import GLOBAL_CMD_TABLE
|
from src.cmdtable import GLOBAL_CMD_TABLE
|
||||||
|
|
||||||
def cmd_password(command):
|
def cmd_password(command):
|
||||||
"""
|
"""
|
||||||
Changes your own password.
|
@password - set your password
|
||||||
|
|
||||||
@password <Oldpass>=<Newpass>
|
Usage:
|
||||||
|
@paassword <old password> = <new password>
|
||||||
|
|
||||||
|
Changes your password. Make sure to pick a safe one.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
||||||
|
|
@ -54,18 +56,27 @@ def cmd_password(command):
|
||||||
uaccount.set_password(newpass)
|
uaccount.set_password(newpass)
|
||||||
uaccount.save()
|
uaccount.save()
|
||||||
source_object.emit_to("Password changed.")
|
source_object.emit_to("Password changed.")
|
||||||
GLOBAL_CMD_TABLE.add_command("@password", cmd_password)
|
GLOBAL_CMD_TABLE.add_command("@password", cmd_password, help_category="System")
|
||||||
|
|
||||||
def cmd_pemit(command):
|
def cmd_pemit(command):
|
||||||
"""
|
"""
|
||||||
|
@pemit
|
||||||
|
|
||||||
Emits something to a player.
|
Emits something to a player.
|
||||||
|
|
||||||
|
(Not yet implemented)
|
||||||
"""
|
"""
|
||||||
# TODO: Implement cmd_pemit
|
# TODO: Implement cmd_pemit
|
||||||
#GLOBAL_CMD_TABLE.add_command("@pemit", cmd_pemit)
|
#GLOBAL_CMD_TABLE.add_command("@pemit", cmd_pemit)
|
||||||
|
|
||||||
def cmd_emit(command):
|
def cmd_emit(command):
|
||||||
"""
|
"""
|
||||||
Emits something to your location.
|
@emit
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
@emit <message>
|
||||||
|
|
||||||
|
Emits a message to your immediate surroundings.
|
||||||
"""
|
"""
|
||||||
message = command.command_argument
|
message = command.command_argument
|
||||||
|
|
||||||
|
|
@ -74,10 +85,15 @@ def cmd_emit(command):
|
||||||
else:
|
else:
|
||||||
command.source_object.emit_to("Emit what?")
|
command.source_object.emit_to("Emit what?")
|
||||||
GLOBAL_CMD_TABLE.add_command("@emit", cmd_emit,
|
GLOBAL_CMD_TABLE.add_command("@emit", cmd_emit,
|
||||||
priv_tuple=("genperms.announce")),
|
priv_tuple=("genperms.announce",),help_category="Comms"),
|
||||||
|
|
||||||
def cmd_wall(command):
|
def cmd_wall(command):
|
||||||
"""
|
"""
|
||||||
|
@wall
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
@wall <message>
|
||||||
|
|
||||||
Announces a message to all connected players.
|
Announces a message to all connected players.
|
||||||
"""
|
"""
|
||||||
wallstring = command.command_argument
|
wallstring = command.command_argument
|
||||||
|
|
@ -90,18 +106,29 @@ def cmd_wall(command):
|
||||||
command.source_object.get_name(show_dbref=False), wallstring)
|
command.source_object.get_name(show_dbref=False), wallstring)
|
||||||
session_mgr.announce_all(message)
|
session_mgr.announce_all(message)
|
||||||
GLOBAL_CMD_TABLE.add_command("@wall", cmd_wall,
|
GLOBAL_CMD_TABLE.add_command("@wall", cmd_wall,
|
||||||
priv_tuple=("genperms.announce"))
|
priv_tuple=("genperms.announce",),help_category="Comms")
|
||||||
|
|
||||||
def cmd_idle(command):
|
def cmd_idle(command):
|
||||||
"""
|
"""
|
||||||
Returns nothing, this lets the player set an idle timer without spamming
|
idle
|
||||||
his screen.
|
|
||||||
|
Usage:
|
||||||
|
idle
|
||||||
|
|
||||||
|
Returns and does nothing. You can use this to send idle
|
||||||
|
messages to the game, in order to avoid getting timed out.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
GLOBAL_CMD_TABLE.add_command("idle", cmd_idle)
|
GLOBAL_CMD_TABLE.add_command("idle", cmd_idle, help_category="System")
|
||||||
|
|
||||||
def cmd_inventory(command):
|
def cmd_inventory(command):
|
||||||
"""
|
"""
|
||||||
|
inventory
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
inventory
|
||||||
|
inv
|
||||||
|
|
||||||
Shows a player's inventory.
|
Shows a player's inventory.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
@ -121,7 +148,13 @@ GLOBAL_CMD_TABLE.add_command("inventory", cmd_inventory)
|
||||||
|
|
||||||
def cmd_look(command):
|
def cmd_look(command):
|
||||||
"""
|
"""
|
||||||
Handle looking at objects.
|
look
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
look
|
||||||
|
look <obj>
|
||||||
|
|
||||||
|
Observers your location or objects in your vicinity.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
||||||
|
|
@ -144,7 +177,13 @@ GLOBAL_CMD_TABLE.add_command("look", cmd_look)
|
||||||
|
|
||||||
def cmd_get(command):
|
def cmd_get(command):
|
||||||
"""
|
"""
|
||||||
Get an object and put it in a player's inventory.
|
get
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
get <obj>
|
||||||
|
|
||||||
|
Picks up an object from your location and puts it in
|
||||||
|
your inventory.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
obj_is_staff = source_object.is_staff()
|
obj_is_staff = source_object.is_staff()
|
||||||
|
|
@ -193,11 +232,15 @@ GLOBAL_CMD_TABLE.add_command("get", cmd_get)
|
||||||
|
|
||||||
def cmd_drop(command):
|
def cmd_drop(command):
|
||||||
"""
|
"""
|
||||||
Drop an object from a player's inventory into their current location.
|
drop
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
drop <obj>
|
||||||
|
|
||||||
|
Has you drop an object from your inventory into the
|
||||||
|
location you are currently in.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
obj_is_staff = source_object.is_staff()
|
|
||||||
|
|
||||||
if not command.command_argument:
|
if not command.command_argument:
|
||||||
source_object.emit_to("Drop what?")
|
source_object.emit_to("Drop what?")
|
||||||
return
|
return
|
||||||
|
|
@ -219,153 +262,40 @@ def cmd_drop(command):
|
||||||
target_obj.get_name(show_dbref=False)),
|
target_obj.get_name(show_dbref=False)),
|
||||||
exclude=source_object)
|
exclude=source_object)
|
||||||
|
|
||||||
# SCRIPT: Call the object's script's a_drop() method.
|
# SCRIPT: Call the object script's a_drop() method.
|
||||||
target_obj.scriptlink.at_drop(source_object)
|
target_obj.scriptlink.at_drop(source_object)
|
||||||
GLOBAL_CMD_TABLE.add_command("drop", cmd_drop),
|
GLOBAL_CMD_TABLE.add_command("drop", cmd_drop),
|
||||||
|
|
||||||
def cmd_examine(command):
|
|
||||||
"""
|
|
||||||
Detailed object examine command
|
|
||||||
"""
|
|
||||||
source_object = command.source_object
|
|
||||||
attr_search = False
|
|
||||||
|
|
||||||
if not command.command_argument:
|
|
||||||
# If no arguments are provided, examine the invoker's location.
|
|
||||||
target_obj = source_object.get_location()
|
|
||||||
else:
|
|
||||||
# Look for a slash in the input, indicating an attribute search.
|
|
||||||
attr_split = command.command_argument.split("/", 1)
|
|
||||||
|
|
||||||
# If the splitting by the "/" character returns a list with more than 1
|
|
||||||
# entry, it's an attribute match.
|
|
||||||
if len(attr_split) > 1:
|
|
||||||
attr_search = True
|
|
||||||
# Strip the object search string from the input with the
|
|
||||||
# object/attribute pair.
|
|
||||||
obj_searchstr = attr_split[0]
|
|
||||||
attr_searchstr = attr_split[1].strip()
|
|
||||||
|
|
||||||
# Protect against stuff like: ex me/
|
|
||||||
if attr_searchstr == '':
|
|
||||||
source_object.emit_to('No attribute name provided.')
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
# No slash in argument, just examine an object.
|
|
||||||
obj_searchstr = command.command_argument
|
|
||||||
|
|
||||||
# Resolve the target object.
|
|
||||||
target_obj = source_object.search_for_object(obj_searchstr)
|
|
||||||
# Use search_for_object to handle duplicate/nonexistant results.
|
|
||||||
if not target_obj:
|
|
||||||
return
|
|
||||||
|
|
||||||
# If the user doesn't control the object, just look at it instead.
|
|
||||||
if not source_object.controls_other(target_obj, builder_override=True):
|
|
||||||
command.command_string = 'look'
|
|
||||||
cmd_look(command)
|
|
||||||
return
|
|
||||||
|
|
||||||
if attr_search:
|
|
||||||
"""
|
|
||||||
Player did something like: examine me/* or examine me/TE*. Return
|
|
||||||
each matching attribute with its value.
|
|
||||||
"""
|
|
||||||
attr_matches = target_obj.attribute_namesearch(attr_searchstr)
|
|
||||||
if attr_matches:
|
|
||||||
for attribute in attr_matches:
|
|
||||||
source_object.emit_to(attribute.get_attrline())
|
|
||||||
else:
|
|
||||||
source_object.emit_to("No matching attributes found.")
|
|
||||||
else:
|
|
||||||
"""
|
|
||||||
Player is examining an object. Return a full readout of attributes,
|
|
||||||
along with detailed information about said object.
|
|
||||||
"""
|
|
||||||
s = ""
|
|
||||||
newl = "\r\n"
|
|
||||||
# Format the examine header area with general flag/type info.
|
|
||||||
|
|
||||||
s += str(target_obj.get_name(fullname=True)) + newl
|
|
||||||
s += str("Type: %s Flags: %s" % (target_obj.get_type(),
|
|
||||||
target_obj.get_flags())) + newl
|
|
||||||
s += str("Owner: %s " % target_obj.get_owner()) + newl
|
|
||||||
s += str("Zone: %s" % target_obj.get_zone()) + newl
|
|
||||||
s += str("Parent: %s " % target_obj.get_script_parent()) + newl
|
|
||||||
|
|
||||||
locks = target_obj.get_attribute_value("LOCKS")
|
|
||||||
if locks and "%s" % locks:
|
|
||||||
s += str("Locks: %s" % locks) + newl
|
|
||||||
|
|
||||||
# Contents container lists for sorting by type.
|
|
||||||
con_players = []
|
|
||||||
con_things = []
|
|
||||||
con_exits = []
|
|
||||||
|
|
||||||
# Break each object out into their own list.
|
|
||||||
for obj in target_obj.get_contents():
|
|
||||||
if obj.is_player():
|
|
||||||
con_players.append(obj)
|
|
||||||
elif obj.is_exit():
|
|
||||||
con_exits.append(obj)
|
|
||||||
elif obj.is_thing():
|
|
||||||
con_things.append(obj)
|
|
||||||
|
|
||||||
# Render the object's home or destination (for exits).
|
|
||||||
if not target_obj.is_room():
|
|
||||||
if target_obj.is_exit():
|
|
||||||
# The Home attribute on an exit is really its destination.
|
|
||||||
s += str("Destination: %s" % target_obj.get_home()) + newl
|
|
||||||
else:
|
|
||||||
# For everything else, home is home.
|
|
||||||
s += str("Home: %s" % target_obj.get_home()) + newl
|
|
||||||
# This obviously isn't valid for rooms.
|
|
||||||
s += str("Location: %s" % target_obj.get_location()) + newl
|
|
||||||
|
|
||||||
# Render other attributes
|
|
||||||
for attribute in target_obj.get_all_attributes():
|
|
||||||
s += str(attribute.get_attrline()) + newl
|
|
||||||
|
|
||||||
# Render Contents display.
|
|
||||||
if con_players or con_things:
|
|
||||||
s += str("%sContents:%s" % (ANSITable.ansi["hilite"],
|
|
||||||
ANSITable.ansi["normal"]))
|
|
||||||
for player in con_players:
|
|
||||||
s += str(' %s' % newl + player.get_name(fullname=True))
|
|
||||||
for thing in con_things:
|
|
||||||
s += str(' %s' % newl + thing.get_name(fullname=True))
|
|
||||||
|
|
||||||
# Render Exists display.
|
|
||||||
if con_exits:
|
|
||||||
s += str("%sExits:%s" % (newl + ANSITable.ansi["hilite"],
|
|
||||||
ANSITable.ansi["normal"]))
|
|
||||||
for exit in con_exits:
|
|
||||||
s += str(' %s' % newl + exit.get_name(fullname=True))
|
|
||||||
|
|
||||||
# Send it all
|
|
||||||
source_object.emit_to(s)
|
|
||||||
|
|
||||||
GLOBAL_CMD_TABLE.add_command("examine", cmd_examine,priv_tuple=("objects.info",))
|
|
||||||
|
|
||||||
def cmd_quit(command):
|
def cmd_quit(command):
|
||||||
"""
|
"""
|
||||||
Gracefully disconnect the user as per his own request.
|
quit
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
quit
|
||||||
|
|
||||||
|
Gracefully disconnect from the game.
|
||||||
"""
|
"""
|
||||||
if command.session:
|
if command.session:
|
||||||
session = command.session
|
session = command.session
|
||||||
session.msg("Quitting. Hope to see you soon again.")
|
session.msg("Quitting. Hope to see you soon again.")
|
||||||
session.handle_close()
|
session.handle_close()
|
||||||
GLOBAL_CMD_TABLE.add_command("quit", cmd_quit)
|
GLOBAL_CMD_TABLE.add_command("quit", cmd_quit, help_category="System")
|
||||||
|
|
||||||
def cmd_who(command):
|
def cmd_who(command):
|
||||||
"""
|
"""
|
||||||
Generic WHO command.
|
who
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
who
|
||||||
|
|
||||||
|
Shows who is currently online.
|
||||||
"""
|
"""
|
||||||
session_list = session_mgr.get_session_list()
|
session_list = session_mgr.get_session_list()
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
||||||
# In the case of the DOING command, don't show session data regardless.
|
# In the case of the DOING command, don't show session data regardless.
|
||||||
if command.extra_vars and command.extra_vars.get("show_session_data", None) == False:
|
if command.extra_vars and \
|
||||||
|
command.extra_vars.get("show_session_data", None) == False:
|
||||||
show_session_data = False
|
show_session_data = False
|
||||||
else:
|
else:
|
||||||
show_session_data = source_object.has_perm("genperms.see_session_data")
|
show_session_data = source_object.has_perm("genperms.see_session_data")
|
||||||
|
|
@ -412,12 +342,17 @@ def cmd_who(command):
|
||||||
|
|
||||||
source_object.emit_to(retval)
|
source_object.emit_to(retval)
|
||||||
GLOBAL_CMD_TABLE.add_command("doing", cmd_who,
|
GLOBAL_CMD_TABLE.add_command("doing", cmd_who,
|
||||||
extra_vals={"show_session_data": False})
|
extra_vals={"show_session_data": False}, help_category="System")
|
||||||
GLOBAL_CMD_TABLE.add_command("who", cmd_who)
|
GLOBAL_CMD_TABLE.add_command("who", cmd_who,help_category="System")
|
||||||
|
|
||||||
def cmd_say(command):
|
def cmd_say(command):
|
||||||
"""
|
"""
|
||||||
Room-based speech command.
|
say
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
say <message>
|
||||||
|
|
||||||
|
Talk to those in your current location.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
||||||
|
|
@ -441,7 +376,18 @@ GLOBAL_CMD_TABLE.add_command("say", cmd_say)
|
||||||
|
|
||||||
def cmd_pose(command):
|
def cmd_pose(command):
|
||||||
"""
|
"""
|
||||||
Pose/emote command.
|
pose - strike a pose
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
pose <pose text>
|
||||||
|
|
||||||
|
Example:
|
||||||
|
pose is standing by the wall, smiling.
|
||||||
|
-> others will see:
|
||||||
|
Tom is standing by the wall, smiling.
|
||||||
|
|
||||||
|
Describe an action being taken. The pose text will
|
||||||
|
automatically begin with your name.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
||||||
|
|
@ -464,189 +410,134 @@ def cmd_pose(command):
|
||||||
GLOBAL_CMD_TABLE.add_command("pose", cmd_pose)
|
GLOBAL_CMD_TABLE.add_command("pose", cmd_pose)
|
||||||
|
|
||||||
def cmd_group(command):
|
def cmd_group(command):
|
||||||
"""@group
|
"""
|
||||||
|
@group - show your groups
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
@group
|
@group
|
||||||
|
|
||||||
This command shows you which user permission groups you are a member of, if any.
|
This command shows you which user permission groups
|
||||||
|
you are a member of, if any.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
user = User.objects.get(username=source_object.get_name(show_dbref=False, no_ansi=True))
|
user = User.objects.get(username=source_object.get_name(show_dbref=False, no_ansi=True))
|
||||||
s = ""
|
string = ""
|
||||||
if source_object.is_superuser():
|
if source_object.is_superuser():
|
||||||
s += "\n This is a SUPERUSER account! Group membership does not matter."
|
string += "\n This is a SUPERUSER account! Group membership does not matter."
|
||||||
if not user.is_active:
|
if not user.is_active:
|
||||||
s += "\n ACCOUNT NOT ACTIVE."
|
string += "\n ACCOUNT NOT ACTIVE."
|
||||||
for g in user.groups.all():
|
for group in user.groups.all():
|
||||||
s += "\n -- %s" % g
|
string += "\n -- %s" % group
|
||||||
for p in g.permissions.all():
|
for perm in group.permissions.all():
|
||||||
s += "\n --- %s" % p.name
|
string += "\n --- %s" % perm.name
|
||||||
if not s:
|
if not string:
|
||||||
s = "You are not a member of any groups." % source_object.get_name(show_dbref=False)
|
string = "You are not a member of any groups." % source_object.get_name(show_dbref=False)
|
||||||
else:
|
else:
|
||||||
s = "\nYour (%s's) group memberships: %s" % (source_object.get_name(show_dbref=False),s)
|
string = "\nYour (%s's) group memberships: %s" % (source_object.get_name(show_dbref=False), string)
|
||||||
source_object.emit_to(s)
|
source_object.emit_to(string)
|
||||||
GLOBAL_CMD_TABLE.add_command("@group", cmd_group,auto_help=True)
|
GLOBAL_CMD_TABLE.add_command("@group", cmd_group)
|
||||||
|
GLOBAL_CMD_TABLE.add_command("@groups", cmd_group, help_category="System")
|
||||||
|
|
||||||
def cmd_help(command):
|
def cmd_help(command):
|
||||||
"""
|
"""
|
||||||
Help command
|
help - view help database
|
||||||
Usage: help <topic>
|
|
||||||
|
Usage:
|
||||||
|
help <topic>
|
||||||
|
|
||||||
Examples: help index
|
Examples: help index
|
||||||
help topic
|
help topic
|
||||||
help 2
|
help 345
|
||||||
|
|
||||||
Shows the available help on <topic>. Use without <topic> to
|
Shows the available help on <topic>. Use without <topic> to get the help
|
||||||
get the help index. If more than one topic match your query, you will get a
|
index. If more than one topic match your query, you will get a
|
||||||
list of topics to choose between. You can also supply a help entry number
|
list of topics to choose between. You can also supply a help entry number
|
||||||
directly if you know it.
|
directly if you know it.
|
||||||
|
|
||||||
<<TOPIC:STAFF:help_staff>>
|
|
||||||
Help command extra functions for staff:
|
|
||||||
|
|
||||||
help index - the normal index
|
|
||||||
help index_staff - show only help files unique to staff
|
|
||||||
help index_player - show only help files visible to all players
|
|
||||||
|
|
||||||
The help command has a range of staff-only switches for manipulating the
|
|
||||||
help data base:
|
|
||||||
|
|
||||||
help/add <topic>:<text> - add/replace help topic with text (staff only)
|
|
||||||
help/append <topic>:<text> - add text to the end of a topic (staff only)
|
|
||||||
(use the /newline switch to add a new paragraph
|
|
||||||
to your help entry.)
|
|
||||||
help/delete <topic> - delete help topic (staff only)
|
|
||||||
|
|
||||||
Note: further switches are /force and /staff. /force is used together with /add to
|
|
||||||
always create a help entry, also when they partially match a previous entry. /staff
|
|
||||||
makes the help file visible to staff only. The /append switch can be used to change the
|
|
||||||
/staff setting of an existing help file if required.
|
|
||||||
|
|
||||||
The <text> entry supports markup to automatically divide the help text into
|
|
||||||
sub-entries. These are started by the markup < <TOPIC:MyTopic> > (with no spaces
|
|
||||||
between the << >>), which will create a new subsectioned entry 'MyTopic' for all
|
|
||||||
text to follow it. All subsections to be added this way are automatically
|
|
||||||
referred to in the footer of each help entry. Normally the subsections inherit the
|
|
||||||
staff_only flag from the main entry (so if this is a staff-only help, all subentries
|
|
||||||
will also be staff-only and vice versa). You can override this behaviour using the
|
|
||||||
alternate forms < <TOPIC:STAFF:MyTopic> > and < <TOPIC:ALL:MyTopic> >.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
topicstr = command.command_argument
|
topicstr = command.command_argument
|
||||||
switches = command.command_switches
|
|
||||||
|
|
||||||
if not command.command_argument:
|
if not command.command_argument:
|
||||||
#display topic index if just help command is given
|
#display topic index if just help command is given
|
||||||
if not switches:
|
topicstr = "index"
|
||||||
topicstr = "topic"
|
|
||||||
else:
|
|
||||||
#avoid applying things to "topic" by mistake
|
|
||||||
source_object.emit_to("You have to supply a topic.")
|
|
||||||
return
|
|
||||||
|
|
||||||
elif len(topicstr) < 2 and not topicstr.isdigit():
|
if len(topicstr) < 2 and not topicstr.isdigit():
|
||||||
#check valid query
|
#check valid query
|
||||||
source_object.emit_to("Your search query must be at least two letters long.")
|
source_object.emit_to("Your search query must be at least two letters long.")
|
||||||
return
|
return
|
||||||
|
|
||||||
# speciel help index names. These entries are dynamically
|
# speciel help index names. These entries are dynamically
|
||||||
# created upon request.
|
# created upon request.
|
||||||
if topicstr == 'index':
|
if topicstr in ['topic','topics']:
|
||||||
#the normal index, affected by permissions
|
# the full index, affected by permissions
|
||||||
edit_help.get_help_index(source_object)
|
text = helpsystem.viewhelp.index_full(source_object)
|
||||||
return
|
text = " \nHELP TOPICS (By Category):\n\r%s" % text
|
||||||
elif topicstr == 'index_staff':
|
source_object.emit_to(text)
|
||||||
#allows staff to view only staff-specific help
|
|
||||||
edit_help.get_help_index(source_object,filter='staff')
|
|
||||||
return
|
|
||||||
elif topicstr == 'index_player':
|
|
||||||
#allows staff to view only the help files a player sees
|
|
||||||
edit_help.get_help_index(source_object,filter='player')
|
|
||||||
return
|
return
|
||||||
|
|
||||||
#handle special switches
|
elif 'index' in topicstr:
|
||||||
|
# view the category index
|
||||||
force_create = 'for' in switches or 'force' in switches
|
text = helpsystem.viewhelp.index_categories()
|
||||||
staff_only = 'sta' in switches or 'staff' in switches
|
text = " \nHELP CATEGORIES (try 'help <category>' or 'help topics'):\n\r\n\r%s" % text
|
||||||
|
source_object.emit_to(text)
|
||||||
if 'add' in switches:
|
|
||||||
#try to add/replace help text for a command
|
|
||||||
if not source_object.has_perm("helpsys.add_help"):
|
|
||||||
source_object.emit_to(defines_global.NOPERMS_MSG)
|
|
||||||
return
|
|
||||||
spl = (topicstr.split(':',1))
|
|
||||||
if len(spl) != 2:
|
|
||||||
source_object.emit_to("Format is help/add <topic>:<helptext>")
|
|
||||||
return
|
|
||||||
topicstr = spl[0]
|
|
||||||
text = spl[1]
|
|
||||||
topics = edit_help.add_help(topicstr,text,staff_only,force_create,source_object)
|
|
||||||
if not topics:
|
|
||||||
source_object.emit_to("No topic(s) added due to errors. Check syntax and that you don't have duplicate subtopics with the same name defined.")
|
|
||||||
return
|
|
||||||
elif len(topics)>1:
|
|
||||||
source_object.emit_to("Added or replaced multiple help entries.")
|
|
||||||
else:
|
|
||||||
source_object.emit_to("Added or replaced help entry for %s." % topicstr )
|
|
||||||
|
|
||||||
elif 'append' in switches or 'app' in switches:
|
|
||||||
#append text to a help entry
|
|
||||||
if not source_object.has_perm("helpsys.add_help"):
|
|
||||||
source_object.emit_to(defines_global.NOPERMS_MSG)
|
|
||||||
return
|
|
||||||
spl = (topicstr.split(':',1))
|
|
||||||
if len(spl) != 2:
|
|
||||||
source_object.emit_to("""Format is help/append <topic>:<text to add>
|
|
||||||
Use the /newline switch to make a new paragraph.""")
|
|
||||||
return
|
|
||||||
topicstr = spl[0]
|
|
||||||
text = spl[1]
|
|
||||||
topics = HelpEntry.objects.find_topicmatch(source_object, topicstr)
|
|
||||||
if len(topics) == 1:
|
|
||||||
newtext = topics[0].get_entrytext_ingame()
|
|
||||||
if 'newl' in switches or 'newline' in switches:
|
|
||||||
newtext += "\n\r\n\r%s" % text
|
|
||||||
else:
|
|
||||||
newtext += "\n\r%s" % text
|
|
||||||
topics = edit_help.add_help(topicstr,newtext,staff_only,force_create,source_object)
|
|
||||||
if topics:
|
|
||||||
source_object.emit_to("Appended text to help entry for %s." % topicstr)
|
|
||||||
|
|
||||||
elif 'del' in switches or 'delete' in switches:
|
|
||||||
#delete a help entry
|
|
||||||
if not source_object.has_perm("helpsys.del_help"):
|
|
||||||
source_object.emit_to(defines_global.NOPERMS_MSG)
|
|
||||||
return
|
|
||||||
topics = edit_help.del_help(source_object,topicstr)
|
|
||||||
if type(topics) != type(list()):
|
|
||||||
source_object.emit_to("Help entry '%s' deleted." % topicstr)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
else:
|
# not a special help index entry. Do a search for the help entry.
|
||||||
#no switch; just try to get the help as normal
|
|
||||||
topics = HelpEntry.objects.find_topicmatch(source_object, topicstr)
|
topics = HelpEntry.objects.find_topicmatch(source_object, topicstr)
|
||||||
|
|
||||||
# display help entry or handle no/multiple matches
|
# display help entry or handle no/multiple matches
|
||||||
|
|
||||||
if len(topics) == 0:
|
string = ""
|
||||||
source_object.emit_to("No matching topics found, please refine your search.")
|
if not topics:
|
||||||
suggestions = HelpEntry.objects.find_topicsuggestions(source_object,
|
# no matches.
|
||||||
|
|
||||||
|
# try to see if it is matching the name of a category. If so,
|
||||||
|
# show the topics for this category.
|
||||||
|
text = helpsystem.viewhelp.index_category(source_object, topicstr)
|
||||||
|
if text:
|
||||||
|
# We have category matches, display the index and exit.
|
||||||
|
string = "\n%s%s%s\n\r\n\r%s" % ("---", " Help topics in category %s: " % \
|
||||||
|
topicstr.capitalize(), "-"* (30-len(topicstr)), text)
|
||||||
|
source_object.emit_to(string)
|
||||||
|
return
|
||||||
|
|
||||||
|
# at this point we just give a not-found error and give suggestions.
|
||||||
|
topics = HelpEntry.objects.find_topicsuggestions(source_object,
|
||||||
topicstr)
|
topicstr)
|
||||||
if len(suggestions) > 0:
|
if topics:
|
||||||
source_object.emit_to("Matching similarly named topics:")
|
if len(topics) > 3:
|
||||||
for result in suggestions:
|
topics = topics[:3]
|
||||||
source_object.emit_to(" %s" % (result,))
|
string += "\n\rMatching similarly named topics (use name or number to refine search):"
|
||||||
source_object.emit_to("You may type 'help <#>' to see any of these topics.")
|
for entry in topics:
|
||||||
elif len(topics) > 1:
|
string += "\n %i.%s" % (entry.id, entry.topicname)
|
||||||
source_object.emit_to("More than one match found:")
|
|
||||||
for result in topics:
|
|
||||||
source_object.emit_to(" %3d. %s" % (result.id, result.get_topicname()))
|
|
||||||
source_object.emit_to("You may type 'help <#>' to see any of these topics.")
|
|
||||||
else:
|
else:
|
||||||
|
string += "No matching topics found, please refine your search."
|
||||||
|
|
||||||
|
|
||||||
|
elif len(topics) > 1:
|
||||||
|
# multiple matches found
|
||||||
|
string += "More than one match found:"
|
||||||
|
for result in topics:
|
||||||
|
string += " %3d. %s" % (result.id, result.get_topicname())
|
||||||
|
|
||||||
|
else:
|
||||||
|
# a single match found
|
||||||
topic = topics[0]
|
topic = topics[0]
|
||||||
source_object.emit_to("\n\r "+ topic.get_entrytext_ingame())
|
header = "--- Help entry for '%s' (%s category) " % (topic.get_topicname(),
|
||||||
GLOBAL_CMD_TABLE.add_command("help", cmd_help, auto_help=True)
|
topic.get_category())
|
||||||
|
header = "%s%s" % (header, "-" * (80-len(header)))
|
||||||
|
string += "\n\r%s\n\r\n\r%s" % (header, topic.get_entrytext_ingame())
|
||||||
|
|
||||||
|
# add the 'See also:' footer
|
||||||
|
topics = HelpEntry.objects.find_topicsuggestions(source_object,
|
||||||
|
topicstr)
|
||||||
|
if topics:
|
||||||
|
if len(topics) > 5:
|
||||||
|
topics = topics[:5]
|
||||||
|
topics = [str(topic.topicname) for topic in topics ]
|
||||||
|
string += "\n\r\n\r" + " " * helpsystem.viewhelp.indent + \
|
||||||
|
"See also: " + ", ".join(topics)
|
||||||
|
|
||||||
|
source_object.emit_to(string)
|
||||||
|
GLOBAL_CMD_TABLE.add_command("help", cmd_help)
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,8 @@
|
||||||
"""
|
"""
|
||||||
IMC2 user and administrative commands.
|
IMC2 user and administrative commands.
|
||||||
"""
|
"""
|
||||||
from time import time
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from src.config.models import ConfigValue
|
|
||||||
from src.objects.models import Object
|
|
||||||
from src import defines_global
|
|
||||||
from src import ansi
|
|
||||||
from src import comsys
|
from src import comsys
|
||||||
from src.util import functions_general
|
|
||||||
from src.cmdtable import GLOBAL_CMD_TABLE
|
from src.cmdtable import GLOBAL_CMD_TABLE
|
||||||
from src.ansi import parse_ansi
|
from src.ansi import parse_ansi
|
||||||
from src.imc2.imc_ansi import IMCANSIParser
|
from src.imc2.imc_ansi import IMCANSIParser
|
||||||
|
|
@ -20,7 +14,12 @@ from src.channels.models import CommChannel
|
||||||
|
|
||||||
def cmd_imcwhois(command):
|
def cmd_imcwhois(command):
|
||||||
"""
|
"""
|
||||||
Shows a player's inventory.
|
imcwhois
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
imcwhois
|
||||||
|
|
||||||
|
IMC2 command. Shows a player's inventory.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
if not command.command_argument:
|
if not command.command_argument:
|
||||||
|
|
@ -30,10 +29,15 @@ def cmd_imcwhois(command):
|
||||||
source_object.emit_to("Sending IMC whois request. If you receive no response, no matches were found.")
|
source_object.emit_to("Sending IMC whois request. If you receive no response, no matches were found.")
|
||||||
packet = IMC2PacketWhois(source_object, command.command_argument)
|
packet = IMC2PacketWhois(source_object, command.command_argument)
|
||||||
imc2_conn.IMC2_PROTOCOL_INSTANCE.send_packet(packet)
|
imc2_conn.IMC2_PROTOCOL_INSTANCE.send_packet(packet)
|
||||||
GLOBAL_CMD_TABLE.add_command("imcwhois", cmd_imcwhois)
|
GLOBAL_CMD_TABLE.add_command("imcwhois", cmd_imcwhois, help_category="Comms")
|
||||||
|
|
||||||
def cmd_imcansi(command):
|
def cmd_imcansi(command):
|
||||||
"""
|
"""
|
||||||
|
imcansi
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
imcansi <string>
|
||||||
|
|
||||||
Test IMC ANSI conversion.
|
Test IMC ANSI conversion.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
@ -43,20 +47,30 @@ def cmd_imcansi(command):
|
||||||
else:
|
else:
|
||||||
retval = parse_ansi(command.command_argument, parser=IMCANSIParser())
|
retval = parse_ansi(command.command_argument, parser=IMCANSIParser())
|
||||||
source_object.emit_to(retval)
|
source_object.emit_to(retval)
|
||||||
GLOBAL_CMD_TABLE.add_command("imcansi", cmd_imcansi)
|
GLOBAL_CMD_TABLE.add_command("imcansi", cmd_imcansi, help_category="Comms")
|
||||||
|
|
||||||
def cmd_imcicerefresh(command):
|
def cmd_imcicerefresh(command):
|
||||||
"""
|
"""
|
||||||
Semds an ice-refresh packet.
|
imcicerefresh
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
imcicerefresh
|
||||||
|
|
||||||
|
IMC2: Semds an ice-refresh packet.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
packet = IMC2PacketIceRefresh()
|
packet = IMC2PacketIceRefresh()
|
||||||
imc2_conn.IMC2_PROTOCOL_INSTANCE.send_packet(packet)
|
imc2_conn.IMC2_PROTOCOL_INSTANCE.send_packet(packet)
|
||||||
source_object.emit_to("Sent")
|
source_object.emit_to("Sent")
|
||||||
GLOBAL_CMD_TABLE.add_command("imcicerefresh", cmd_imcicerefresh)
|
GLOBAL_CMD_TABLE.add_command("imcicerefresh", cmd_imcicerefresh, help_category="Comms")
|
||||||
|
|
||||||
def cmd_imcchanlist(command):
|
def cmd_imcchanlist(command):
|
||||||
"""
|
"""
|
||||||
|
imcchanlist
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
imcchanlist
|
||||||
|
|
||||||
Shows the list of cached channels from the IMC2 Channel list.
|
Shows the list of cached channels from the IMC2 Channel list.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
@ -73,10 +87,15 @@ def cmd_imcchanlist(command):
|
||||||
channel.policy)
|
channel.policy)
|
||||||
retval += '%s channels found.' % len(IMC2_CHANLIST.chan_list)
|
retval += '%s channels found.' % len(IMC2_CHANLIST.chan_list)
|
||||||
source_object.emit_to(retval)
|
source_object.emit_to(retval)
|
||||||
GLOBAL_CMD_TABLE.add_command("imcchanlist", cmd_imcchanlist)
|
GLOBAL_CMD_TABLE.add_command("imcchanlist", cmd_imcchanlist, help_category="Comms")
|
||||||
|
|
||||||
def cmd_imclist(command):
|
def cmd_imclist(command):
|
||||||
"""
|
"""
|
||||||
|
imclist
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
imclist
|
||||||
|
|
||||||
Shows the list of cached games from the IMC2 Mud list.
|
Shows the list of cached games from the IMC2 Mud list.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
@ -88,10 +107,15 @@ def cmd_imclist(command):
|
||||||
retval += '%s\n\r' % mudline[:78]
|
retval += '%s\n\r' % mudline[:78]
|
||||||
retval += '%s active MUDs found.' % len(IMC2_MUDLIST.mud_list)
|
retval += '%s active MUDs found.' % len(IMC2_MUDLIST.mud_list)
|
||||||
source_object.emit_to(retval)
|
source_object.emit_to(retval)
|
||||||
GLOBAL_CMD_TABLE.add_command("imclist", cmd_imclist)
|
GLOBAL_CMD_TABLE.add_command("imclist", cmd_imclist, help_category="Comms")
|
||||||
|
|
||||||
def cmd_imcstatus(command):
|
def cmd_imcstatus(command):
|
||||||
"""
|
"""
|
||||||
|
imcstatus
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
imcstatus
|
||||||
|
|
||||||
Shows some status information for your IMC2 connection.
|
Shows some status information for your IMC2 connection.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
@ -118,21 +142,24 @@ def cmd_imcstatus(command):
|
||||||
|
|
||||||
source_object.emit_to(retval)
|
source_object.emit_to(retval)
|
||||||
GLOBAL_CMD_TABLE.add_command("imcstatus", cmd_imcstatus,
|
GLOBAL_CMD_TABLE.add_command("imcstatus", cmd_imcstatus,
|
||||||
priv_tuple=('imc2.admin_imc_channels',))
|
priv_tuple=('imc2.admin_imc_channels',), help_category="Comms")
|
||||||
|
|
||||||
|
|
||||||
def cmd_IMC2chan(command):
|
def cmd_IMC2chan(command):
|
||||||
"""
|
"""
|
||||||
@imc2chan IMCServer:IMCchannel channel
|
@imc2chan
|
||||||
|
|
||||||
Links an IMC channel to an existing
|
Usage:
|
||||||
evennia channel. You can link as many existing
|
@imc2chan <IMCServer> : <IMCchannel> <channel>
|
||||||
|
|
||||||
|
Links an IMC channel to an existing evennia
|
||||||
|
channel. You can link as many existing
|
||||||
evennia channels as you like to the
|
evennia channels as you like to the
|
||||||
IMC channel this way. Running the command with an
|
IMC channel this way. Running the command with an
|
||||||
existing mapping will re-map the channels.
|
existing mapping will re-map the channels.
|
||||||
|
|
||||||
Use 'imcchanlist' to get a list of IMC channels and servers.
|
Use 'imcchanlist' to get a list of IMC channels and
|
||||||
Note that both are case sensitive.
|
servers. Note that both are case sensitive.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
if not settings.IMC2_ENABLED:
|
if not settings.IMC2_ENABLED:
|
||||||
|
|
@ -179,6 +206,6 @@ def cmd_IMC2chan(command):
|
||||||
outstring += "Mapping set: %s." % mapping
|
outstring += "Mapping set: %s." % mapping
|
||||||
source_object.emit_to(outstring)
|
source_object.emit_to(outstring)
|
||||||
|
|
||||||
GLOBAL_CMD_TABLE.add_command("@imc2chan",cmd_IMC2chan,auto_help=True,staff_help=True,
|
GLOBAL_CMD_TABLE.add_command("@imc2chan",cmd_IMC2chan,
|
||||||
priv_tuple=("imc2.admin_imc_channels",))
|
priv_tuple=("imc2.admin_imc_channels",), help_category="Comms")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,25 +17,41 @@ from src.cmdtable import GLOBAL_CMD_TABLE
|
||||||
|
|
||||||
def cmd_version(command):
|
def cmd_version(command):
|
||||||
"""
|
"""
|
||||||
Version info command.
|
@version - game version
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
@version
|
||||||
|
|
||||||
|
Display the game version info
|
||||||
"""
|
"""
|
||||||
retval = "-"*50 +"\n\r"
|
retval = "-"*50 +"\n\r"
|
||||||
retval += " Evennia %s\n\r" % (defines_global.EVENNIA_VERSION,)
|
retval += " Evennia %s\n\r" % (defines_global.EVENNIA_VERSION,)
|
||||||
retval += " Django %s\n\r" % (django.get_version())
|
retval += " Django %s\n\r" % (django.get_version())
|
||||||
retval += "-"*50
|
retval += "-"*50
|
||||||
command.source_object.emit_to(retval)
|
command.source_object.emit_to(retval)
|
||||||
GLOBAL_CMD_TABLE.add_command("version", cmd_version),
|
GLOBAL_CMD_TABLE.add_command("@version", cmd_version, help_category="Admin"),
|
||||||
|
|
||||||
def cmd_time(command):
|
def cmd_time(command):
|
||||||
"""
|
"""
|
||||||
|
@time
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
@time
|
||||||
|
|
||||||
Server local time.
|
Server local time.
|
||||||
"""
|
"""
|
||||||
command.source_object.emit_to('Current server time : %s' %
|
command.source_object.emit_to('Current server time : %s' %
|
||||||
(time.strftime('%a %b %d %H:%M:%S %Y (%Z)', time.localtime(),)))
|
(time.strftime('%a %b %d %H:%M:%S %Y (%Z)', time.localtime(),)))
|
||||||
GLOBAL_CMD_TABLE.add_command("time", cmd_time),
|
GLOBAL_CMD_TABLE.add_command("@time", cmd_time, priv_tuple=("genperms.game_info",),
|
||||||
|
help_category="Admin")
|
||||||
|
|
||||||
def cmd_uptime(command):
|
def cmd_uptime(command):
|
||||||
"""
|
"""
|
||||||
|
@uptime
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
@uptime
|
||||||
|
|
||||||
Server uptime and stats.
|
Server uptime and stats.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
@ -54,11 +70,18 @@ def cmd_uptime(command):
|
||||||
loadavg = os.getloadavg()
|
loadavg = os.getloadavg()
|
||||||
source_object.emit_to('Server load (1 min) : %.2f' %
|
source_object.emit_to('Server load (1 min) : %.2f' %
|
||||||
loadavg[0])
|
loadavg[0])
|
||||||
GLOBAL_CMD_TABLE.add_command("uptime", cmd_uptime),
|
GLOBAL_CMD_TABLE.add_command("@uptime", cmd_uptime, priv_tuple=("genperms.game_info",),
|
||||||
|
help_category="Admin")
|
||||||
|
|
||||||
def cmd_list(command):
|
def cmd_list(command):
|
||||||
"""
|
"""
|
||||||
Shows some game related information.
|
@list - list info
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
@list commands | flags | process
|
||||||
|
|
||||||
|
Shows game related information depending
|
||||||
|
on which argument is given.
|
||||||
"""
|
"""
|
||||||
server = command.session.server
|
server = command.session.server
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
@ -99,10 +122,15 @@ def cmd_list(command):
|
||||||
source_object.emit_to("Flags: "+" ".join(flags.SERVER_FLAGS))
|
source_object.emit_to("Flags: "+" ".join(flags.SERVER_FLAGS))
|
||||||
else:
|
else:
|
||||||
source_object.emit_to(msg_invalid)
|
source_object.emit_to(msg_invalid)
|
||||||
GLOBAL_CMD_TABLE.add_command("@list", cmd_list,priv_tuple=("genperms.game_info",)),
|
GLOBAL_CMD_TABLE.add_command("@list", cmd_list,priv_tuple=("genperms.game_info",), help_category="Admin")
|
||||||
|
|
||||||
def cmd_ps(command):
|
def cmd_ps(command):
|
||||||
"""
|
"""
|
||||||
|
@ps - list processes
|
||||||
|
|
||||||
|
Usage
|
||||||
|
@ps
|
||||||
|
|
||||||
Shows the process/event table.
|
Shows the process/event table.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
@ -115,13 +143,23 @@ def cmd_ps(command):
|
||||||
event.description))
|
event.description))
|
||||||
source_object.emit_to("Totals: %d interval events" % (len(scheduler.schedule),))
|
source_object.emit_to("Totals: %d interval events" % (len(scheduler.schedule),))
|
||||||
GLOBAL_CMD_TABLE.add_command("@ps", cmd_ps,
|
GLOBAL_CMD_TABLE.add_command("@ps", cmd_ps,
|
||||||
priv_tuple=("genperms.process_control")),
|
priv_tuple=("genperms.process_control",), help_category="Admin")
|
||||||
|
|
||||||
def cmd_stats(command):
|
def cmd_stats(command):
|
||||||
"""
|
"""
|
||||||
Shows stats about the database.
|
@stats - show object stats
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
@stats
|
||||||
|
|
||||||
|
Example:
|
||||||
|
@stats
|
||||||
|
->
|
||||||
4012 objects = 144 rooms, 212 exits, 613 things, 1878 players. (1165 garbage)
|
4012 objects = 144 rooms, 212 exits, 613 things, 1878 players. (1165 garbage)
|
||||||
|
|
||||||
|
Shows stats about the database.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
stats_dict = Object.objects.object_totals()
|
stats_dict = Object.objects.object_totals()
|
||||||
command.source_object.emit_to(
|
command.source_object.emit_to(
|
||||||
"%d objects = %d rooms, %d exits, %d things, %d players. (%d garbage)" %
|
"%d objects = %d rooms, %d exits, %d things, %d players. (%d garbage)" %
|
||||||
|
|
@ -131,4 +169,4 @@ def cmd_stats(command):
|
||||||
stats_dict["things"],
|
stats_dict["things"],
|
||||||
stats_dict["players"],
|
stats_dict["players"],
|
||||||
stats_dict["garbage"]))
|
stats_dict["garbage"]))
|
||||||
GLOBAL_CMD_TABLE.add_command("@stats", cmd_stats, priv_tuple=("genperms.game_info",)),
|
GLOBAL_CMD_TABLE.add_command("@stats", cmd_stats, priv_tuple=("genperms.game_info",), help_category="Admin"),
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,10 @@ from src.channels.models import CommChannel
|
||||||
|
|
||||||
def cmd_IRC2chan(command):
|
def cmd_IRC2chan(command):
|
||||||
"""
|
"""
|
||||||
@irc2chan IRCchannel channel
|
@irc2chan - link irc to ingame channel
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
@irc2chan <#IRCchannel> <local channel>
|
||||||
|
|
||||||
Links an IRC channel (including #) to an existing
|
Links an IRC channel (including #) to an existing
|
||||||
evennia channel. You can link as many existing
|
evennia channel. You can link as many existing
|
||||||
|
|
@ -55,12 +58,16 @@ def cmd_IRC2chan(command):
|
||||||
outstring += "Mapping set: %s." % mapping
|
outstring += "Mapping set: %s." % mapping
|
||||||
source_object.emit_to(outstring)
|
source_object.emit_to(outstring)
|
||||||
|
|
||||||
GLOBAL_CMD_TABLE.add_command("@irc2chan",cmd_IRC2chan,auto_help=True,staff_help=True,
|
GLOBAL_CMD_TABLE.add_command("@irc2chan",cmd_IRC2chan,
|
||||||
priv_tuple=("irc.admin_irc_channels",))
|
priv_tuple=("irc.admin_irc_channels",),
|
||||||
|
help_category="Comms")
|
||||||
|
|
||||||
def cmd_IRCjoin(command):
|
def cmd_IRCjoin(command):
|
||||||
"""
|
"""
|
||||||
@ircjoin IRCchannel
|
@ircjoin - join a new irc channel
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
@ircjoin <#IRCchannel>
|
||||||
|
|
||||||
Attempts to connect a bot to a new IRC channel (don't forget that
|
Attempts to connect a bot to a new IRC channel (don't forget that
|
||||||
IRC channels begin with a #).
|
IRC channels begin with a #).
|
||||||
|
|
@ -99,19 +106,25 @@ def cmd_IRCjoin(command):
|
||||||
# irc.setName("%s:%s" % ("IRC",channel))
|
# irc.setName("%s:%s" % ("IRC",channel))
|
||||||
# irc.setServiceParent(mud_service.service_collection)
|
# irc.setServiceParent(mud_service.service_collection)
|
||||||
|
|
||||||
GLOBAL_CMD_TABLE.add_command("@ircjoin",cmd_IRCjoin,auto_help=True,
|
GLOBAL_CMD_TABLE.add_command("@ircjoin",cmd_IRCjoin,
|
||||||
staff_help=True,
|
priv_tuple=("irc.admin_irc_channels",),
|
||||||
priv_tuple=("irc.admin_irc_channels",))
|
help_category="Comms")
|
||||||
|
|
||||||
def cmd_IRCchanlist(command):
|
def cmd_IRCchanlist(command):
|
||||||
"""
|
"""
|
||||||
ircchanlist
|
ircchanlist
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
ircchanlist
|
||||||
|
|
||||||
Lists all externally available IRC channels.
|
Lists all externally available IRC channels.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
s = "Available IRC channels:"
|
s = "Available IRC channels:"
|
||||||
for c in IRC_CHANNELS:
|
for c in IRC_CHANNELS:
|
||||||
s += "\n %s \t(nick '%s') on %s" % (c.factory.channel,c.factory.nickname,c.factory.network,)
|
s += "\n %s \t(nick '%s') on %s" % (c.factory.channel,
|
||||||
|
c.factory.nickname,
|
||||||
|
c.factory.network,)
|
||||||
source_object.emit_to(s)
|
source_object.emit_to(s)
|
||||||
GLOBAL_CMD_TABLE.add_command("ircchanlist", cmd_IRCchanlist, auto_help=True)
|
GLOBAL_CMD_TABLE.add_command("ircchanlist", cmd_IRCchanlist,
|
||||||
|
help_category="Comms")
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,21 @@ from src import locks
|
||||||
from src import ansi
|
from src import ansi
|
||||||
from src.cmdtable import GLOBAL_CMD_TABLE
|
from src.cmdtable import GLOBAL_CMD_TABLE
|
||||||
from src import defines_global
|
from src import defines_global
|
||||||
|
from src.ansi import ANSITable
|
||||||
|
|
||||||
def cmd_teleport(command):
|
def cmd_teleport(command):
|
||||||
"""
|
"""
|
||||||
Teleports an object somewhere.
|
teleport
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
teleport/switch [<object> = <location>]
|
||||||
|
|
||||||
|
Switches:
|
||||||
|
quiet - don't inform the source and target
|
||||||
|
locations about the move.
|
||||||
|
|
||||||
|
Teleports an object somewhere. If no object is
|
||||||
|
given we are teleporting ourselves.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
||||||
|
|
@ -66,10 +77,15 @@ def cmd_teleport(command):
|
||||||
|
|
||||||
source_object.move_to(target_obj, quiet=tel_quietly)
|
source_object.move_to(target_obj, quiet=tel_quietly)
|
||||||
GLOBAL_CMD_TABLE.add_command("@teleport", cmd_teleport,
|
GLOBAL_CMD_TABLE.add_command("@teleport", cmd_teleport,
|
||||||
priv_tuple=("objects.teleport",))
|
priv_tuple=("objects.teleport",), help_category="Building")
|
||||||
|
|
||||||
def cmd_alias(command):
|
def cmd_alias(command):
|
||||||
"""
|
"""
|
||||||
|
@alias
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
@alias <player> = <alias>
|
||||||
|
|
||||||
Assigns an alias to a player object for ease of paging, etc.
|
Assigns an alias to a player object for ease of paging, etc.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
@ -118,8 +134,17 @@ GLOBAL_CMD_TABLE.add_command("@alias", cmd_alias)
|
||||||
|
|
||||||
def cmd_wipe(command):
|
def cmd_wipe(command):
|
||||||
"""
|
"""
|
||||||
Wipes an object's attributes, or optionally only those matching a search
|
@wipe - clears attributes
|
||||||
string.
|
|
||||||
|
Usage:
|
||||||
|
@wipe <object> [/attribute-wildcard]
|
||||||
|
|
||||||
|
Example:
|
||||||
|
@wipe box
|
||||||
|
@wipe box/colour
|
||||||
|
|
||||||
|
Wipes all of an object's attributes, or optionally only those
|
||||||
|
matching the given attribute-wildcard search string.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
attr_search = False
|
attr_search = False
|
||||||
|
|
@ -166,11 +191,21 @@ def cmd_wipe(command):
|
||||||
target_obj.clear_attribute(attr.get_name())
|
target_obj.clear_attribute(attr.get_name())
|
||||||
source_object.emit_to("%s - %d attributes wiped." % (target_obj.get_name(),
|
source_object.emit_to("%s - %d attributes wiped." % (target_obj.get_name(),
|
||||||
len(attr_matches)))
|
len(attr_matches)))
|
||||||
GLOBAL_CMD_TABLE.add_command("@wipe", cmd_wipe,priv_tuple=("objects.wipe",))
|
GLOBAL_CMD_TABLE.add_command("@wipe", cmd_wipe,priv_tuple=("objects.wipe",),
|
||||||
|
help_category="Building")
|
||||||
|
|
||||||
def cmd_set(command):
|
def cmd_set(command):
|
||||||
"""
|
"""
|
||||||
Sets flags or attributes on objects.
|
@set - set attributes and flags
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
@set <obj> = <flag>
|
||||||
|
@set <obj> = <attr> : <value>
|
||||||
|
@set <obj> = !<flag>
|
||||||
|
@set <obj> = <attr> :
|
||||||
|
|
||||||
|
Sets flags or attributes on objects. The two last forms
|
||||||
|
above unsets the flag and clears the attribute, respectively.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
args = command.command_argument
|
args = command.command_argument
|
||||||
|
|
@ -251,16 +286,26 @@ def cmd_set(command):
|
||||||
s += '\nFlag %s=%s set.' % (target_name, flag.upper())
|
s += '\nFlag %s=%s set.' % (target_name, flag.upper())
|
||||||
target.set_flag(flag, True)
|
target.set_flag(flag, True)
|
||||||
source_object.emit_to(s[1:])
|
source_object.emit_to(s[1:])
|
||||||
GLOBAL_CMD_TABLE.add_command("@set", cmd_set, priv_tuple=("objects.modify_attributes",))
|
GLOBAL_CMD_TABLE.add_command("@set", cmd_set, priv_tuple=("objects.modify_attributes",),
|
||||||
|
help_category="Building")
|
||||||
|
|
||||||
def cmd_cpattr(command):
|
def cmd_cpattr(command):
|
||||||
"""
|
"""
|
||||||
copy an attribute to another object
|
@cpattr - copy attributes
|
||||||
|
|
||||||
|
Usage:
|
||||||
@cpattr <obj>/<attr> = <obj1>/<attr1> [,<obj2>/<attr2>,<obj3>/<attr3>,...]
|
@cpattr <obj>/<attr> = <obj1>/<attr1> [,<obj2>/<attr2>,<obj3>/<attr3>,...]
|
||||||
@cpattr <obj>/<attr> = <obj1> [,<obj2>,<obj3>,...]
|
@cpattr <obj>/<attr> = <obj1> [,<obj2>,<obj3>,...]
|
||||||
@cpattr <attr> = <obj1>/<attr1> [,<obj2>/<attr2>,<obj3>/<attr3>,...]
|
@cpattr <attr> = <obj1>/<attr1> [,<obj2>/<attr2>,<obj3>/<attr3>,...]
|
||||||
@cpattr <attr> = <obj1>[,<obj2>,<obj3>,...]
|
@cpattr <attr> = <obj1>[,<obj2>,<obj3>,...]
|
||||||
|
|
||||||
|
Example:
|
||||||
|
@cpattr coolness = Anna/chillout, Anna/nicety, Tom/nicety
|
||||||
|
->
|
||||||
|
copies the coolness attribute (defined on yourself), to attributes
|
||||||
|
on Anna and Tom.
|
||||||
|
|
||||||
|
Copy the attribute one object to one or more attributes on another object.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
args = command.command_argument
|
args = command.command_argument
|
||||||
|
|
@ -333,14 +378,17 @@ def cmd_cpattr(command):
|
||||||
to_objname, to_attr)
|
to_objname, to_attr)
|
||||||
source_object.emit_to(s)
|
source_object.emit_to(s)
|
||||||
GLOBAL_CMD_TABLE.add_command("@cpattr", cmd_cpattr,
|
GLOBAL_CMD_TABLE.add_command("@cpattr", cmd_cpattr,
|
||||||
priv_tuple=("objects.modify_attributes",))
|
priv_tuple=("objects.modify_attributes",), help_category="Building")
|
||||||
|
|
||||||
|
|
||||||
def cmd_mvattr(command):
|
def cmd_mvattr(command):
|
||||||
"""
|
"""
|
||||||
|
@mvattr - move attributes
|
||||||
|
|
||||||
|
Usage:
|
||||||
@mvattr <object>=<old>,<new>[,<copy1>[, <copy2 ...]]
|
@mvattr <object>=<old>,<new>[,<copy1>[, <copy2 ...]]
|
||||||
|
|
||||||
Move attributes around on an object
|
Move attributes around on the same object.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
arg = command.command_argument
|
arg = command.command_argument
|
||||||
|
|
@ -395,10 +443,16 @@ def cmd_mvattr(command):
|
||||||
source_object.emit_to(s)
|
source_object.emit_to(s)
|
||||||
|
|
||||||
GLOBAL_CMD_TABLE.add_command("@mvattr", cmd_mvattr,
|
GLOBAL_CMD_TABLE.add_command("@mvattr", cmd_mvattr,
|
||||||
priv_tuple=("objects.modify_attributes",))
|
priv_tuple=("objects.modify_attributes",),
|
||||||
|
help_category="Building")
|
||||||
|
|
||||||
def cmd_find(command):
|
def cmd_find(command):
|
||||||
"""
|
"""
|
||||||
|
find
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
find <searchname>
|
||||||
|
|
||||||
Searches for an object of a particular name.
|
Searches for an object of a particular name.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
@ -421,13 +475,14 @@ def cmd_find(command):
|
||||||
else:
|
else:
|
||||||
source_object.emit_to("No name matches found for: %s" % (searchstring,))
|
source_object.emit_to("No name matches found for: %s" % (searchstring,))
|
||||||
GLOBAL_CMD_TABLE.add_command("@find", cmd_find,
|
GLOBAL_CMD_TABLE.add_command("@find", cmd_find,
|
||||||
priv_tuple=("objects.info",))
|
priv_tuple=("objects.info",), help_category="Building")
|
||||||
|
|
||||||
def cmd_create(command):
|
def cmd_create(command):
|
||||||
"""
|
"""
|
||||||
@create
|
@create - create new objects
|
||||||
|
|
||||||
Usage: @create[/drop] objname [:parent]
|
Usage:
|
||||||
|
@create[/drop] objname [:parent]
|
||||||
|
|
||||||
switch:
|
switch:
|
||||||
drop - automatically drop the new object into your current location (this is not echoed)
|
drop - automatically drop the new object into your current location (this is not echoed)
|
||||||
|
|
@ -477,15 +532,20 @@ def cmd_create(command):
|
||||||
|
|
||||||
|
|
||||||
GLOBAL_CMD_TABLE.add_command("@create", cmd_create,
|
GLOBAL_CMD_TABLE.add_command("@create", cmd_create,
|
||||||
priv_tuple=("objects.create",),auto_help=True,staff_help=True)
|
priv_tuple=("objects.create",),
|
||||||
|
help_category="Building")
|
||||||
|
|
||||||
def cmd_copy(command):
|
def cmd_copy(command):
|
||||||
"""Usage:
|
"""
|
||||||
|
@copy - copy objects
|
||||||
|
|
||||||
|
Usage:
|
||||||
@copy[/reset] <original obj> [new_name] [, new_location]
|
@copy[/reset] <original obj> [new_name] [, new_location]
|
||||||
|
|
||||||
switch:
|
switch:
|
||||||
reset - make a 'clean' copy, without any changes that might have happened to the
|
reset - make a 'clean' copy off the object's script parent, thus
|
||||||
original since it was first created.
|
removing any changes that might have been made to the original
|
||||||
|
since it was first created.
|
||||||
|
|
||||||
Create an identical copy of an object.
|
Create an identical copy of an object.
|
||||||
"""
|
"""
|
||||||
|
|
@ -542,12 +602,13 @@ def cmd_copy(command):
|
||||||
reset_text = " (using default attrs/flags)"
|
reset_text = " (using default attrs/flags)"
|
||||||
source_object.emit_to("Copied object '%s'%s%s%s." % (objname,name_text,loc_text,reset_text))
|
source_object.emit_to("Copied object '%s'%s%s%s." % (objname,name_text,loc_text,reset_text))
|
||||||
GLOBAL_CMD_TABLE.add_command("@copy", cmd_copy,
|
GLOBAL_CMD_TABLE.add_command("@copy", cmd_copy,
|
||||||
priv_tuple=("objects.create",),auto_help=True,staff_help=True)
|
priv_tuple=("objects.create",), help_category="Building")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def cmd_nextfree(command):
|
def cmd_nextfree(command):
|
||||||
"""Usage:
|
"""
|
||||||
|
@nextfree
|
||||||
|
|
||||||
|
Usage:
|
||||||
@nextfree
|
@nextfree
|
||||||
|
|
||||||
Returns the next free object number.
|
Returns the next free object number.
|
||||||
|
|
@ -555,10 +616,12 @@ def cmd_nextfree(command):
|
||||||
nextfree = Object.objects.get_nextfree_dbnum()
|
nextfree = Object.objects.get_nextfree_dbnum()
|
||||||
command.source_object.emit_to("Next free object number: #%s" % nextfree)
|
command.source_object.emit_to("Next free object number: #%s" % nextfree)
|
||||||
GLOBAL_CMD_TABLE.add_command("@nextfree", cmd_nextfree,
|
GLOBAL_CMD_TABLE.add_command("@nextfree", cmd_nextfree,
|
||||||
priv_tuple=("objects.info",),auto_help=True,staff_help=True)
|
priv_tuple=("objects.info",), help_category="Building")
|
||||||
|
|
||||||
def cmd_open(command):
|
def cmd_open(command):
|
||||||
"""@open
|
"""
|
||||||
|
@open - create new exit
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
@open <new exit> [:parent] [= <destination> [,<return exit> [:parent]]]
|
@open <new exit> [:parent] [= <destination> [,<return exit> [:parent]]]
|
||||||
|
|
||||||
|
|
@ -670,15 +733,17 @@ def cmd_open(command):
|
||||||
source_object.emit_to("Created exit%s back from %s named %s." % \
|
source_object.emit_to("Created exit%s back from %s named %s." % \
|
||||||
(ptext, destination, new_object))
|
(ptext, destination, new_object))
|
||||||
GLOBAL_CMD_TABLE.add_command("@open", cmd_open,
|
GLOBAL_CMD_TABLE.add_command("@open", cmd_open,
|
||||||
priv_tuple=("objects.dig",),auto_help=True,staff_help=True)
|
priv_tuple=("objects.dig",), help_category="Building")
|
||||||
|
|
||||||
def cmd_chown(command):
|
def cmd_chown(command):
|
||||||
"""
|
"""
|
||||||
|
@chown - change ownerships
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
@chown <Object> = <NewOwner>
|
||||||
|
|
||||||
Changes the ownership of an object. The new owner specified must be a
|
Changes the ownership of an object. The new owner specified must be a
|
||||||
player object.
|
player object.
|
||||||
|
|
||||||
Forms:
|
|
||||||
@chown <Object>=<NewOwner>
|
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
||||||
|
|
@ -721,15 +786,19 @@ def cmd_chown(command):
|
||||||
# We haven't provided a target.
|
# We haven't provided a target.
|
||||||
source_object.emit_to("Who should be the new owner of the object?")
|
source_object.emit_to("Who should be the new owner of the object?")
|
||||||
return
|
return
|
||||||
GLOBAL_CMD_TABLE.add_command("@chown", cmd_chown, priv_tuple=("objects.modify_attributes","objects.admin_ownership"))
|
GLOBAL_CMD_TABLE.add_command("@chown", cmd_chown, priv_tuple=("objects.modify_attributes",
|
||||||
|
"objects.admin_ownership"),
|
||||||
|
help_category="Building" )
|
||||||
|
|
||||||
def cmd_chzone(command):
|
def cmd_chzone(command):
|
||||||
"""
|
"""
|
||||||
|
@chzone - set zones
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
@chzone <Object> = <NewZone>
|
||||||
|
|
||||||
Changes an object's zone. The specified zone may be of any object type, but
|
Changes an object's zone. The specified zone may be of any object type, but
|
||||||
will typically be a THING.
|
will typically be a THING.
|
||||||
|
|
||||||
Forms:
|
|
||||||
@chzone <Object>=<NewZone>
|
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
||||||
|
|
@ -773,10 +842,13 @@ def cmd_chzone(command):
|
||||||
# We haven't provided a target zone.
|
# We haven't provided a target zone.
|
||||||
source_object.emit_to("What should the object's zone be set to?")
|
source_object.emit_to("What should the object's zone be set to?")
|
||||||
return
|
return
|
||||||
GLOBAL_CMD_TABLE.add_command("@chzone", cmd_chzone, priv_tuple=("objects.dig",))
|
GLOBAL_CMD_TABLE.add_command("@chzone", cmd_chzone, priv_tuple=("objects.dig",),
|
||||||
|
help_category="Building" )
|
||||||
|
|
||||||
def cmd_link(command):
|
def cmd_link(command):
|
||||||
"""@link
|
"""
|
||||||
|
@link - connect objects
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
@link <object> = <target>
|
@link <object> = <target>
|
||||||
@link <object> =
|
@link <object> =
|
||||||
|
|
@ -864,13 +936,17 @@ def cmd_link(command):
|
||||||
else:
|
else:
|
||||||
source_object.emit_to("You set the home location of %s to %s%s." % (obj, destination, ohome_text))
|
source_object.emit_to("You set the home location of %s to %s%s." % (obj, destination, ohome_text))
|
||||||
GLOBAL_CMD_TABLE.add_command("@link", cmd_link,
|
GLOBAL_CMD_TABLE.add_command("@link", cmd_link,
|
||||||
priv_tuple=("objects.dig",), auto_help=True, staff_help=True)
|
priv_tuple=("objects.dig",), help_category="Building")
|
||||||
|
|
||||||
def cmd_unlink(command):
|
def cmd_unlink(command):
|
||||||
"""
|
"""
|
||||||
Unlinks an object.
|
@unlink - unconnect objects
|
||||||
|
|
||||||
|
Usage:
|
||||||
@unlink <Object>
|
@unlink <Object>
|
||||||
|
|
||||||
|
Unlinks an object, for example an exit, disconnecting
|
||||||
|
it from whatever it was connected to.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
||||||
|
|
@ -890,15 +966,19 @@ def cmd_unlink(command):
|
||||||
target_obj.set_home(None)
|
target_obj.set_home(None)
|
||||||
source_object.emit_to("You have unlinked %s." % target_obj.get_name())
|
source_object.emit_to("You have unlinked %s." % target_obj.get_name())
|
||||||
GLOBAL_CMD_TABLE.add_command("@unlink", cmd_unlink,
|
GLOBAL_CMD_TABLE.add_command("@unlink", cmd_unlink,
|
||||||
priv_tuple=("objects.dig",))
|
priv_tuple=("objects.dig",), help_category="Building")
|
||||||
|
|
||||||
def cmd_dig(command):
|
def cmd_dig(command):
|
||||||
"""@dig
|
"""
|
||||||
|
@dig - build and connect new rooms
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
@dig[/switches] roomname [:parent] [= exit_to_there [: parent][;alias]] [, exit_to_here [: parent][;alias]]
|
@dig[/switches] roomname [:parent] [= exit_to_there [: parent][;alias]] [, exit_to_here [: parent][;alias]]
|
||||||
switches:
|
|
||||||
|
Switches:
|
||||||
teleport - move yourself to the new room
|
teleport - move yourself to the new room
|
||||||
example:
|
|
||||||
|
Example:
|
||||||
@dig kitchen = north; n, south; s
|
@dig kitchen = north; n, south; s
|
||||||
|
|
||||||
This command is a convenient way to build rooms quickly; it creates the new room and you can optionally
|
This command is a convenient way to build rooms quickly; it creates the new room and you can optionally
|
||||||
|
|
@ -1018,13 +1098,16 @@ def cmd_dig(command):
|
||||||
source_object.move_to(new_room)
|
source_object.move_to(new_room)
|
||||||
|
|
||||||
GLOBAL_CMD_TABLE.add_command("@dig", cmd_dig,
|
GLOBAL_CMD_TABLE.add_command("@dig", cmd_dig,
|
||||||
priv_tuple=("objects.dig",), auto_help=True, staff_help=True)
|
priv_tuple=("objects.dig",), help_category="Building")
|
||||||
|
|
||||||
def cmd_name(command):
|
def cmd_name(command):
|
||||||
"""
|
"""
|
||||||
Handle naming an object.
|
@name - name objects
|
||||||
|
|
||||||
|
Usage:
|
||||||
@name <Object> = <Value>
|
@name <Object> = <Value>
|
||||||
|
|
||||||
|
Handle naming an object.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
||||||
|
|
@ -1060,10 +1143,16 @@ def cmd_name(command):
|
||||||
source_object.emit_to("You have renamed %s to %s." % (target_obj,
|
source_object.emit_to("You have renamed %s to %s." % (target_obj,
|
||||||
ansi_name))
|
ansi_name))
|
||||||
target_obj.set_name(new_name)
|
target_obj.set_name(new_name)
|
||||||
GLOBAL_CMD_TABLE.add_command("@name", cmd_name)
|
GLOBAL_CMD_TABLE.add_command("@name", cmd_name, priv_tuple=("objects.create",),
|
||||||
|
help_category="Building")
|
||||||
|
|
||||||
def cmd_description(command):
|
def cmd_description(command):
|
||||||
"""
|
"""
|
||||||
|
@desc
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
@desc [obj =] <descriptive text>
|
||||||
|
|
||||||
Set an object's description.
|
Set an object's description.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
@ -1099,13 +1188,12 @@ def cmd_description(command):
|
||||||
else:
|
else:
|
||||||
source_object.emit_to("%s - description set." % target_obj)
|
source_object.emit_to("%s - description set." % target_obj)
|
||||||
target_obj.set_attribute('desc', new_desc)
|
target_obj.set_attribute('desc', new_desc)
|
||||||
GLOBAL_CMD_TABLE.add_command("@describe", cmd_description)
|
GLOBAL_CMD_TABLE.add_command("@describe", cmd_description, priv_tuple=("objects.create",),
|
||||||
|
help_category="Building")
|
||||||
|
|
||||||
def cmd_recover(command):
|
def cmd_recover(command):
|
||||||
"""
|
"""
|
||||||
@recover
|
@recover - undo object deletion
|
||||||
|
|
||||||
Recovers @destroyed non-player objects.
|
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
@recover[/switches] [obj [,obj2, ...]]
|
@recover[/switches] [obj [,obj2, ...]]
|
||||||
|
|
@ -1114,6 +1202,8 @@ def cmd_recover(command):
|
||||||
ROOM - recover as ROOM type instead of THING
|
ROOM - recover as ROOM type instead of THING
|
||||||
EXIT - recover as EXIT type instead of THING
|
EXIT - recover as EXIT type instead of THING
|
||||||
|
|
||||||
|
Recovers @destroyed non-player objects.
|
||||||
|
|
||||||
If no argument is given, a list of all recoverable objects will be given.
|
If no argument is given, a list of all recoverable objects will be given.
|
||||||
|
|
||||||
Objects scheduled for destruction with the @destroy command are cleaned out
|
Objects scheduled for destruction with the @destroy command are cleaned out
|
||||||
|
|
@ -1165,13 +1255,11 @@ def cmd_recover(command):
|
||||||
|
|
||||||
|
|
||||||
GLOBAL_CMD_TABLE.add_command("@recover", cmd_recover,
|
GLOBAL_CMD_TABLE.add_command("@recover", cmd_recover,
|
||||||
priv_tuple=("objects.create",),auto_help=True,staff_help=True)
|
priv_tuple=("objects.create",), help_category="Building")
|
||||||
|
|
||||||
def cmd_destroy(command):
|
def cmd_destroy(command):
|
||||||
"""
|
"""
|
||||||
@destroy
|
@destroy - send objects to trashbin
|
||||||
|
|
||||||
Destroys one or many objects.
|
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
@destroy[/<switches>] obj [,obj2, obj3, ...]
|
@destroy[/<switches>] obj [,obj2, obj3, ...]
|
||||||
|
|
@ -1182,6 +1270,7 @@ def cmd_destroy(command):
|
||||||
switch overrides this safety.
|
switch overrides this safety.
|
||||||
instant|now - Destroy the object immediately, without delay.
|
instant|now - Destroy the object immediately, without delay.
|
||||||
|
|
||||||
|
Destroys one or many objects.
|
||||||
The objects are set to GOING and will be permanently destroyed next time the system
|
The objects are set to GOING and will be permanently destroyed next time the system
|
||||||
does cleanup. Until then non-player objects can still be saved by using the
|
does cleanup. Until then non-player objects can still be saved by using the
|
||||||
@recover command. The contents of a room will be moved out before it is destroyed,
|
@recover command. The contents of a room will be moved out before it is destroyed,
|
||||||
|
|
@ -1244,19 +1333,23 @@ def cmd_destroy(command):
|
||||||
source_object.emit_to("You schedule %s for destruction." % target_obj.get_name())
|
source_object.emit_to("You schedule %s for destruction." % target_obj.get_name())
|
||||||
|
|
||||||
GLOBAL_CMD_TABLE.add_command("@destroy", cmd_destroy,
|
GLOBAL_CMD_TABLE.add_command("@destroy", cmd_destroy,
|
||||||
priv_tuple=("objects.create",),auto_help=True,staff_help=True)
|
priv_tuple=("objects.create",), help_category="Building")
|
||||||
|
|
||||||
def cmd_lock(command):
|
def cmd_lock(command):
|
||||||
"""@lock
|
"""
|
||||||
|
@lock - limit use of objects
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
@lock[/switch] <obj> [:type] [= <key>[,key2,key3,...]]
|
@lock[/switch] <obj> [:type] [= <key>[,key2,key3,...]]
|
||||||
|
|
||||||
switches:
|
Switches:
|
||||||
add - add a lock (default) from object
|
add - add a lock (default) from object
|
||||||
del - remove a lock from object
|
del - remove a lock from object
|
||||||
list - view all locks on object (default)
|
list - view all locks on object (default)
|
||||||
type:
|
type:
|
||||||
DefaultLock - the default lock type (default)
|
DefaultLock - the default lock type (default)
|
||||||
|
UseLock - prevents usage of objects' commands
|
||||||
|
EnterLock - blocking objects from entering the object
|
||||||
|
|
||||||
Locks an object for everyone except those matching the keys.
|
Locks an object for everyone except those matching the keys.
|
||||||
The keys can be of the following types (and searched in this order):
|
The keys can be of the following types (and searched in this order):
|
||||||
|
|
@ -1433,4 +1526,137 @@ def cmd_lock(command):
|
||||||
source_object.emit_to("Added lock '%s' to %s with keys%s." % (ltype, obj.get_name(), kstring))
|
source_object.emit_to("Added lock '%s' to %s with keys%s." % (ltype, obj.get_name(), kstring))
|
||||||
|
|
||||||
obj.set_attribute("LOCKS",obj_locks)
|
obj.set_attribute("LOCKS",obj_locks)
|
||||||
GLOBAL_CMD_TABLE.add_command("@lock", cmd_lock, priv_tuple=("objects.create",),auto_help=True, staff_help=True)
|
GLOBAL_CMD_TABLE.add_command("@lock", cmd_lock, priv_tuple=("objects.create",), help_category="Building")
|
||||||
|
|
||||||
|
def cmd_examine(command):
|
||||||
|
"""
|
||||||
|
examine - detailed info on objects
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
examine [<object>]
|
||||||
|
|
||||||
|
The examine command shows detailed game info about an
|
||||||
|
object; which attributes/flags it has and what it
|
||||||
|
contains. If object is not specified, the current
|
||||||
|
location is examined.
|
||||||
|
"""
|
||||||
|
source_object = command.source_object
|
||||||
|
attr_search = False
|
||||||
|
|
||||||
|
if not command.command_argument:
|
||||||
|
# If no arguments are provided, examine the invoker's location.
|
||||||
|
target_obj = source_object.get_location()
|
||||||
|
else:
|
||||||
|
# Look for a slash in the input, indicating an attribute search.
|
||||||
|
attr_split = command.command_argument.split("/", 1)
|
||||||
|
|
||||||
|
# If the splitting by the "/" character returns a list with more than 1
|
||||||
|
# entry, it's an attribute match.
|
||||||
|
if len(attr_split) > 1:
|
||||||
|
attr_search = True
|
||||||
|
# Strip the object search string from the input with the
|
||||||
|
# object/attribute pair.
|
||||||
|
obj_searchstr = attr_split[0]
|
||||||
|
attr_searchstr = attr_split[1].strip()
|
||||||
|
|
||||||
|
# Protect against stuff like: ex me/
|
||||||
|
if attr_searchstr == '':
|
||||||
|
source_object.emit_to('No attribute name provided.')
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
# No slash in argument, just examine an object.
|
||||||
|
obj_searchstr = command.command_argument
|
||||||
|
|
||||||
|
# Resolve the target object.
|
||||||
|
target_obj = source_object.search_for_object(obj_searchstr)
|
||||||
|
# Use search_for_object to handle duplicate/nonexistant results.
|
||||||
|
if not target_obj:
|
||||||
|
return
|
||||||
|
|
||||||
|
# If the user doesn't control the object, just look at it instead.
|
||||||
|
if not source_object.controls_other(target_obj, builder_override=True):
|
||||||
|
command.command_string = 'look'
|
||||||
|
cmd_look(command)
|
||||||
|
return
|
||||||
|
|
||||||
|
if attr_search:
|
||||||
|
# Player did something like: examine me/* or examine me/TE*. Return
|
||||||
|
# each matching attribute with its value.
|
||||||
|
attr_matches = target_obj.attribute_namesearch(attr_searchstr)
|
||||||
|
if attr_matches:
|
||||||
|
for attribute in attr_matches:
|
||||||
|
source_object.emit_to(attribute.get_attrline())
|
||||||
|
else:
|
||||||
|
source_object.emit_to("No matching attributes found.")
|
||||||
|
else:
|
||||||
|
|
||||||
|
# Player is examining an object. Return a full readout of attributes,
|
||||||
|
# along with detailed information about said object.
|
||||||
|
|
||||||
|
string = ""
|
||||||
|
newl = "\r\n"
|
||||||
|
# Format the examine header area with general flag/type info.
|
||||||
|
|
||||||
|
string += str(target_obj.get_name(fullname=True)) + newl
|
||||||
|
string += str("Type: %s Flags: %s" % (target_obj.get_type(),
|
||||||
|
target_obj.get_flags())) + newl
|
||||||
|
string += str("Owner: %s " % target_obj.get_owner()) + newl
|
||||||
|
string += str("Zone: %s" % target_obj.get_zone()) + newl
|
||||||
|
string += str("Parent: %s " % target_obj.get_script_parent()) + newl
|
||||||
|
|
||||||
|
locks = target_obj.get_attribute_value("LOCKS")
|
||||||
|
if locks and "%s" % locks:
|
||||||
|
string += str("Locks: %s" % locks) + newl
|
||||||
|
|
||||||
|
# Contents container lists for sorting by type.
|
||||||
|
con_players = []
|
||||||
|
con_things = []
|
||||||
|
con_exits = []
|
||||||
|
|
||||||
|
# Break each object out into their own list.
|
||||||
|
for obj in target_obj.get_contents():
|
||||||
|
if obj.is_player():
|
||||||
|
con_players.append(obj)
|
||||||
|
elif obj.is_exit():
|
||||||
|
con_exits.append(obj)
|
||||||
|
elif obj.is_thing():
|
||||||
|
con_things.append(obj)
|
||||||
|
|
||||||
|
# Render the object's home or destination (for exits).
|
||||||
|
if not target_obj.is_room():
|
||||||
|
if target_obj.is_exit():
|
||||||
|
# The Home attribute on an exit is really its destination.
|
||||||
|
string += str("Destination: %s" % target_obj.get_home()) + newl
|
||||||
|
else:
|
||||||
|
# For everything else, home is home.
|
||||||
|
string += str("Home: %s" % target_obj.get_home()) + newl
|
||||||
|
# This obviously isn't valid for rooms.
|
||||||
|
string += str("Location: %s" % target_obj.get_location()) + newl
|
||||||
|
|
||||||
|
# Render other attributes
|
||||||
|
for attribute in target_obj.get_all_attributes():
|
||||||
|
string += str(attribute.get_attrline()) + newl
|
||||||
|
|
||||||
|
# Render Contents display.
|
||||||
|
if con_players or con_things:
|
||||||
|
string += str("%sContents:%s" % (ANSITable.ansi["hilite"],
|
||||||
|
ANSITable.ansi["normal"]))
|
||||||
|
for player in con_players:
|
||||||
|
string += str(' %s' % newl + player.get_name(fullname=True))
|
||||||
|
for thing in con_things:
|
||||||
|
string += str(' %s' % newl + thing.get_name(fullname=True))
|
||||||
|
|
||||||
|
# Render Exists display.
|
||||||
|
if con_exits:
|
||||||
|
string += str("%sExits:%s" % (newl + ANSITable.ansi["hilite"],
|
||||||
|
ANSITable.ansi["normal"]))
|
||||||
|
for exit in con_exits:
|
||||||
|
string += str(' %s' % newl + exit.get_name(fullname=True))
|
||||||
|
|
||||||
|
# Send it all
|
||||||
|
source_object.emit_to(string)
|
||||||
|
|
||||||
|
GLOBAL_CMD_TABLE.add_command("examine", cmd_examine, priv_tuple=("objects.info",))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
Paging command and support functions.
|
Paging command and support functions.
|
||||||
"""
|
"""
|
||||||
from src.objects.models import Object
|
from src.objects.models import Object
|
||||||
from src import defines_global
|
|
||||||
from src.cmdtable import GLOBAL_CMD_TABLE
|
from src.cmdtable import GLOBAL_CMD_TABLE
|
||||||
|
|
||||||
def get_last_paged_objects(source_object):
|
def get_last_paged_objects(source_object):
|
||||||
|
|
@ -31,7 +30,14 @@ def get_last_paged_objects(source_object):
|
||||||
|
|
||||||
def cmd_page(command):
|
def cmd_page(command):
|
||||||
"""
|
"""
|
||||||
Send a message to target user (if online).
|
page - send private message
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
page [<user> = <message>]
|
||||||
|
|
||||||
|
Send a message to target user (if online). If no
|
||||||
|
argument is given, you will instead see who was the last
|
||||||
|
person you paged to.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
# Get the last paged person(s)
|
# Get the last paged person(s)
|
||||||
|
|
@ -127,4 +133,4 @@ def cmd_page(command):
|
||||||
# Now set the LASTPAGED attribute
|
# Now set the LASTPAGED attribute
|
||||||
source_object.set_attribute("LASTPAGED", ','.join(
|
source_object.set_attribute("LASTPAGED", ','.join(
|
||||||
["#%d" % (x.id) for x in targets]))
|
["#%d" % (x.id) for x in targets]))
|
||||||
GLOBAL_CMD_TABLE.add_command("page", cmd_page, priv_tuple=('channels.page',))
|
GLOBAL_CMD_TABLE.add_command("page", cmd_page, priv_tuple=('channels.page',), help_category="Comms")
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,14 @@
|
||||||
Contains commands for managing script parents.
|
Contains commands for managing script parents.
|
||||||
"""
|
"""
|
||||||
from src import scripthandler
|
from src import scripthandler
|
||||||
|
from src import defines_global
|
||||||
from src.cmdtable import GLOBAL_CMD_TABLE
|
from src.cmdtable import GLOBAL_CMD_TABLE
|
||||||
|
|
||||||
def cmd_scriptcache(command):
|
def cmd_scriptcache(command):
|
||||||
"""Usage
|
"""
|
||||||
|
@scriptcache
|
||||||
|
|
||||||
|
Usage
|
||||||
@scriptcache
|
@scriptcache
|
||||||
|
|
||||||
Shows the contents of the script cache.
|
Shows the contents of the script cache.
|
||||||
|
|
@ -20,12 +24,21 @@ def cmd_scriptcache(command):
|
||||||
retval += "%d cached parents" % len(cache_dict)
|
retval += "%d cached parents" % len(cache_dict)
|
||||||
command.source_object.emit_to(retval)
|
command.source_object.emit_to(retval)
|
||||||
GLOBAL_CMD_TABLE.add_command("@scriptcache", cmd_scriptcache,
|
GLOBAL_CMD_TABLE.add_command("@scriptcache", cmd_scriptcache,
|
||||||
priv_tuple=("genperms.builder"),
|
priv_tuple=("genperms.builder",), help_category="Admin")
|
||||||
auto_help=True,staff_help=True)
|
|
||||||
|
|
||||||
def cmd_parent(command):
|
def cmd_parent(command):
|
||||||
"""
|
"""
|
||||||
Sets an object's script parent.
|
@parent - set script parent
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
@parent <object> = <parent>
|
||||||
|
|
||||||
|
Example:
|
||||||
|
@parent button = examples.red_button
|
||||||
|
|
||||||
|
Sets an object's script parent. The parent must be identified
|
||||||
|
by its location using dot-notation pointing to the script
|
||||||
|
parent module.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
||||||
|
|
@ -80,5 +93,5 @@ def cmd_parent(command):
|
||||||
(target_obj,current_parent))
|
(target_obj,current_parent))
|
||||||
|
|
||||||
GLOBAL_CMD_TABLE.add_command("@parent", cmd_parent,
|
GLOBAL_CMD_TABLE.add_command("@parent", cmd_parent,
|
||||||
priv_tuple=("genperms.builder"))
|
priv_tuple=("genperms.builder",), help_category="Building" )
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,21 +3,30 @@ This file contains commands that require special permissions to use. These
|
||||||
are generally @-prefixed commands, but there are exceptions.
|
are generally @-prefixed commands, but there are exceptions.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django.contrib.auth.models import Permission, Group, User
|
from django.contrib.auth.models import Permission, Group
|
||||||
from django.contrib.contenttypes.models import ContentType
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from src.objects.models import Object
|
from src.objects.models import Object
|
||||||
from src import defines_global
|
|
||||||
from src import ansi
|
|
||||||
from src import session_mgr
|
from src import session_mgr
|
||||||
from src import comsys
|
from src import comsys
|
||||||
from src.scripthandler import rebuild_cache
|
from src.scripthandler import rebuild_cache
|
||||||
from src.util import functions_general
|
|
||||||
from src.cmdtable import GLOBAL_CMD_TABLE
|
from src.cmdtable import GLOBAL_CMD_TABLE
|
||||||
|
from src.helpsys.models import HelpEntry
|
||||||
|
from src.helpsys import helpsystem
|
||||||
|
|
||||||
def cmd_reload(command):
|
def cmd_reload(command):
|
||||||
"""
|
"""
|
||||||
Reloads all modules.
|
@reload - reload game subsystems
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
@reload/switches
|
||||||
|
|
||||||
|
Switches:
|
||||||
|
aliases - alias definitions
|
||||||
|
commands - the command modules
|
||||||
|
scripts, parents - the script parent modules
|
||||||
|
all
|
||||||
|
|
||||||
|
Reloads all the identified subsystems.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
switches = command.command_switches
|
switches = command.command_switches
|
||||||
|
|
@ -44,12 +53,17 @@ def cmd_reload(command):
|
||||||
comsys.cemit_mudinfo("... all Command modules were reloaded.")
|
comsys.cemit_mudinfo("... all Command modules were reloaded.")
|
||||||
|
|
||||||
GLOBAL_CMD_TABLE.add_command("@reload", cmd_reload,
|
GLOBAL_CMD_TABLE.add_command("@reload", cmd_reload,
|
||||||
priv_tuple=("genperms.process_control",)),
|
priv_tuple=("genperms.process_control",), help_category="Admin")
|
||||||
GLOBAL_CMD_TABLE.add_command("@restart", cmd_reload,
|
GLOBAL_CMD_TABLE.add_command("@restart", cmd_reload,
|
||||||
priv_tuple=("genperms.process_control",)),
|
priv_tuple=("genperms.process_control",), help_category="Admin")
|
||||||
|
|
||||||
def cmd_boot(command):
|
def cmd_boot(command):
|
||||||
"""
|
"""
|
||||||
|
@boot
|
||||||
|
|
||||||
|
Usage
|
||||||
|
@boot <player obj>
|
||||||
|
|
||||||
Boot a player object from the server.
|
Boot a player object from the server.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
@ -119,10 +133,16 @@ def cmd_boot(command):
|
||||||
session_mgr.remove_session(boot)
|
session_mgr.remove_session(boot)
|
||||||
return
|
return
|
||||||
GLOBAL_CMD_TABLE.add_command("@boot", cmd_boot,
|
GLOBAL_CMD_TABLE.add_command("@boot", cmd_boot,
|
||||||
priv_tuple=("genperms.manage_players",))
|
priv_tuple=("genperms.manage_players",),
|
||||||
|
help_category="Admin")
|
||||||
|
|
||||||
def cmd_newpassword(command):
|
def cmd_newpassword(command):
|
||||||
"""
|
"""
|
||||||
|
@newpassword
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
@newpassword <user obj> = <new password>
|
||||||
|
|
||||||
Set a player's password.
|
Set a player's password.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
@ -157,10 +177,16 @@ def cmd_newpassword(command):
|
||||||
target_obj.emit_to("%s has changed your password." %
|
target_obj.emit_to("%s has changed your password." %
|
||||||
(source_object.get_name(show_dbref=False),))
|
(source_object.get_name(show_dbref=False),))
|
||||||
GLOBAL_CMD_TABLE.add_command("@newpassword", cmd_newpassword,
|
GLOBAL_CMD_TABLE.add_command("@newpassword", cmd_newpassword,
|
||||||
priv_tuple=("genperms.manage_players",))
|
priv_tuple=("genperms.manage_players",),
|
||||||
|
help_category="Admin")
|
||||||
|
|
||||||
def cmd_home(command):
|
def cmd_home(command):
|
||||||
"""
|
"""
|
||||||
|
home
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
home
|
||||||
|
|
||||||
Teleport the player to their home.
|
Teleport the player to their home.
|
||||||
"""
|
"""
|
||||||
pobject = command.source_object
|
pobject = command.source_object
|
||||||
|
|
@ -174,8 +200,18 @@ GLOBAL_CMD_TABLE.add_command("home", cmd_home,
|
||||||
|
|
||||||
def cmd_service(command):
|
def cmd_service(command):
|
||||||
"""
|
"""
|
||||||
Service management system. Allows for the listing, starting, and stopping
|
@service - manage services
|
||||||
of services.
|
|
||||||
|
Usage:
|
||||||
|
@service[/switch] <service>
|
||||||
|
|
||||||
|
Switches:
|
||||||
|
start - activates a service
|
||||||
|
stop - stops a service
|
||||||
|
list - shows all available services
|
||||||
|
|
||||||
|
Service management system. Allows for the listing,
|
||||||
|
starting, and stopping of services.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
switches = command.command_switches
|
switches = command.command_switches
|
||||||
|
|
@ -242,17 +278,25 @@ def cmd_service(command):
|
||||||
return
|
return
|
||||||
|
|
||||||
GLOBAL_CMD_TABLE.add_command("@service", cmd_service,
|
GLOBAL_CMD_TABLE.add_command("@service", cmd_service,
|
||||||
priv_tuple=("genperms.process_control",))
|
priv_tuple=("genperms.process_control",),
|
||||||
|
help_category="Admin")
|
||||||
|
|
||||||
def cmd_shutdown(command):
|
def cmd_shutdown(command):
|
||||||
"""
|
"""
|
||||||
Shut the server down gracefully.
|
@shutdown
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
@shutdown
|
||||||
|
|
||||||
|
Shut the game server down gracefully.
|
||||||
"""
|
"""
|
||||||
command.source_object.emit_to('Shutting down...')
|
command.source_object.emit_to('Shutting down...')
|
||||||
print 'Server shutdown by %s' % (command.source_object.get_name(show_dbref=False),)
|
print 'Server shutdown by %s' % (command.source_object.get_name(show_dbref=False),)
|
||||||
command.session.server.shutdown()
|
command.session.server.shutdown()
|
||||||
GLOBAL_CMD_TABLE.add_command("@shutdown", cmd_shutdown,
|
GLOBAL_CMD_TABLE.add_command("@shutdown", cmd_shutdown,
|
||||||
priv_tuple=("genperms.process_control",))
|
priv_tuple=("genperms.process_control",),
|
||||||
|
help_category="Admin")
|
||||||
|
|
||||||
|
|
||||||
# permission administration
|
# permission administration
|
||||||
|
|
||||||
|
|
@ -260,6 +304,7 @@ GLOBAL_CMD_TABLE.add_command("@shutdown", cmd_shutdown,
|
||||||
# mess with, but which are not very useful from inside the game. While these
|
# mess with, but which are not very useful from inside the game. While these
|
||||||
# permissions are ok to use, we only show the permissions that we have defined
|
# permissions are ok to use, we only show the permissions that we have defined
|
||||||
# in our settings file in order to give better control.
|
# in our settings file in order to give better control.
|
||||||
|
|
||||||
APPS_NOSHOW = ("news","admin","auth","config","contentypes",
|
APPS_NOSHOW = ("news","admin","auth","config","contentypes",
|
||||||
"flatpages","news","sessions","sites")
|
"flatpages","news","sessions","sites")
|
||||||
SETTINGS_PERM_NAMES = []
|
SETTINGS_PERM_NAMES = []
|
||||||
|
|
@ -268,7 +313,9 @@ for apps in settings.PERM_ALL_DEFAULTS + settings.PERM_ALL_CUSTOM:
|
||||||
SETTINGS_PERM_NAMES.append(permtuples[1])
|
SETTINGS_PERM_NAMES.append(permtuples[1])
|
||||||
|
|
||||||
def cmd_setperm(command):
|
def cmd_setperm(command):
|
||||||
"""@setperm
|
"""
|
||||||
|
@setperm - set permissions
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
@setperm[/switch] [<user>] = [<permission>]
|
@setperm[/switch] [<user>] = [<permission>]
|
||||||
|
|
||||||
|
|
@ -380,17 +427,21 @@ def cmd_setperm(command):
|
||||||
obj.emit_to("%s removed your permission '%s'." % (source_object.get_name(show_dbref=False,no_ansi=True),
|
obj.emit_to("%s removed your permission '%s'." % (source_object.get_name(show_dbref=False,no_ansi=True),
|
||||||
permission.name))
|
permission.name))
|
||||||
GLOBAL_CMD_TABLE.add_command("@setperm", cmd_setperm,
|
GLOBAL_CMD_TABLE.add_command("@setperm", cmd_setperm,
|
||||||
priv_tuple=("auth.change_permission","genperms.admin_perm"), auto_help=True, staff_help=True)
|
priv_tuple=("auth.change_permission",
|
||||||
|
"genperms.admin_perm"),
|
||||||
|
help_category="Admin")
|
||||||
|
|
||||||
def cmd_setgroup(command):
|
def cmd_setgroup(command):
|
||||||
"""@setgroup
|
"""
|
||||||
|
@setgroup - manage group memberships
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
@setgroup[/switch] [<user>] [= <group>]
|
@setgroup[/switch] [<user>] [= <group>]
|
||||||
|
|
||||||
switches
|
Switches:
|
||||||
add : add user to a group
|
add - add user to a group
|
||||||
del : remove user from a group
|
del - remove user from a group
|
||||||
list : list all groups a user is part of, or list all available groups if no user is given
|
list - list all groups a user is part of, or list all available groups if no user is given
|
||||||
|
|
||||||
Changes and views the group membership of a user.
|
Changes and views the group membership of a user.
|
||||||
"""
|
"""
|
||||||
|
|
@ -410,7 +461,8 @@ def cmd_setgroup(command):
|
||||||
for p in g.permissions.all():
|
for p in g.permissions.all():
|
||||||
app = p.content_type.app_label
|
app = p.content_type.app_label
|
||||||
if app not in APPS_NOSHOW:
|
if app not in APPS_NOSHOW:
|
||||||
s += "\n --- %s.%s%s\t%s" % (app, p.codename, (35 - len(app) - len(p.codename)) * " ", p.name)
|
s += "\n --- %s.%s%s\t%s" % (app, p.codename,
|
||||||
|
(35 - len(app) - len(p.codename)) * " ", p.name)
|
||||||
source_object.emit_to(s)
|
source_object.emit_to(s)
|
||||||
return
|
return
|
||||||
#we have command arguments.
|
#we have command arguments.
|
||||||
|
|
@ -484,5 +536,155 @@ def cmd_setgroup(command):
|
||||||
obj.emit_to("%s removed you from group '%s'." % (source_object.get_name(show_dbref=False,no_ansi=True),
|
obj.emit_to("%s removed you from group '%s'." % (source_object.get_name(show_dbref=False,no_ansi=True),
|
||||||
group.name))
|
group.name))
|
||||||
GLOBAL_CMD_TABLE.add_command("@setgroup", cmd_setgroup,
|
GLOBAL_CMD_TABLE.add_command("@setgroup", cmd_setgroup,
|
||||||
priv_tuple=("auth.change_group","genperms.admin_group"), auto_help=True, staff_help=True)
|
priv_tuple=("auth.change_group",
|
||||||
|
"genperms.admin_group"),
|
||||||
|
help_category="Admin")
|
||||||
|
|
||||||
|
def cmd_sethelp(command):
|
||||||
|
"""
|
||||||
|
@sethelp - edit the help database
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
@sethelp[/switches] <topic>[,category][(permissions)][:<text>]
|
||||||
|
|
||||||
|
Switches:
|
||||||
|
add - add or replace a new topic with text.
|
||||||
|
append - add text to the end of topic.
|
||||||
|
delete - remove help topic.
|
||||||
|
force - (used with add) create help topic also if the topic
|
||||||
|
already exists.
|
||||||
|
newl - (used with append) add a newline between the old
|
||||||
|
text and the appended text.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
@sethelp/add throw : This throws something at ...
|
||||||
|
@sethelp/add throw, General (genperms.throwing) : This throws ...
|
||||||
|
@sethelp/add throw : 1st help entry
|
||||||
|
|
||||||
|
[[@sethelp_markup]]
|
||||||
|
|
||||||
|
@sethelp Help markup
|
||||||
|
|
||||||
|
The <text> entry in @sethelp supports markup to automatically divide the help text into
|
||||||
|
several sub-entries. The beginning of each new entry is marked in the form
|
||||||
|
|
||||||
|
[ [Title, category, (privtuple)] ] (with no spaces between the square brackets)
|
||||||
|
|
||||||
|
In the markup header, Title is mandatory, the other parts are optional. A new
|
||||||
|
help entry named Title will be created for each occurence. It is recommended
|
||||||
|
that the help entries should begin similarly since the system will then identify
|
||||||
|
them and better handle a list of recommended topics.
|
||||||
|
"""
|
||||||
|
|
||||||
|
source_object = command.source_object
|
||||||
|
arg = command.command_argument
|
||||||
|
switches = command.command_switches
|
||||||
|
|
||||||
|
if not arg or not switches:
|
||||||
|
source_object.emit_to("Usage: @sethelp/[add|del|append] <topic>[,category][:<text>]")
|
||||||
|
return
|
||||||
|
|
||||||
|
topicstr = ""
|
||||||
|
category = ""
|
||||||
|
text = ""
|
||||||
|
permtuple = ()
|
||||||
|
|
||||||
|
# analyze the argument
|
||||||
|
arg = arg.split(':', 1)
|
||||||
|
if len(arg) < 2:
|
||||||
|
# no : detected; this means we are deleting something.
|
||||||
|
topicstr = arg[0].strip()
|
||||||
|
else:
|
||||||
|
text = arg[1].strip()
|
||||||
|
# we have 4 possibilities:
|
||||||
|
# topicstr
|
||||||
|
# topicstr, category
|
||||||
|
# topicstr (perm1,perm2,...)
|
||||||
|
# topicstr, category, (perm1,perm2,...)
|
||||||
|
arg = arg[0].split('(',1)
|
||||||
|
if len(arg) > 1:
|
||||||
|
# we have a perm tuple
|
||||||
|
arg, permtuple = arg
|
||||||
|
try:
|
||||||
|
permtuple = permtuple.strip()[:-1] # cut last ')'
|
||||||
|
except IndexError:
|
||||||
|
source_object.emit_to("Malformed permission tuple. %s" % permtuple)
|
||||||
|
return
|
||||||
|
permtuple = tuple(permtuple.split(','))
|
||||||
|
else:
|
||||||
|
# no perm tuple
|
||||||
|
arg = arg[0]
|
||||||
|
arg = arg.split(',', 1)
|
||||||
|
if len(arg) > 1:
|
||||||
|
# we have a category
|
||||||
|
category = arg[1].strip()
|
||||||
|
topicstr = arg[0].strip()
|
||||||
|
|
||||||
|
if 'add' in switches:
|
||||||
|
# add a new help entry.
|
||||||
|
if not topicstr or not text:
|
||||||
|
source_object.emit_to("Usage: @sethelp/add <topic>[,category]:<text>")
|
||||||
|
return
|
||||||
|
force_create = ('for' in switches) or ('force' in switches)
|
||||||
|
topics = helpsystem.edithelp.add_help_manual(source_object, topicstr,
|
||||||
|
category, text,
|
||||||
|
permissions=permtuple,
|
||||||
|
force=force_create)
|
||||||
|
if not topics:
|
||||||
|
return
|
||||||
|
if len(topics) == 1:
|
||||||
|
string = "The topic already exists. Use /force to overwrite it."
|
||||||
|
elif len(topics)>1:
|
||||||
|
string = "The following results are similar to '%s'."
|
||||||
|
string += " Make sure you are not misspelling, then "
|
||||||
|
string += "use the /force flag to create a new entry."
|
||||||
|
string += "\n ".join(topics)
|
||||||
|
source_object.emit_to(string)
|
||||||
|
|
||||||
|
elif 'append' in switches or 'app' in switches:
|
||||||
|
# add text to the end of a help topic
|
||||||
|
if not topicstr or not text:
|
||||||
|
source_object.emit_to("Usage: @sethelp/append <topic>:<text>")
|
||||||
|
return
|
||||||
|
# find the topic to append to
|
||||||
|
topics = HelpEntry.objects.find_topicmatch(source_object, topicstr)
|
||||||
|
if not topics:
|
||||||
|
source_object.emit_to("Help topic '%s' not found." % topicstr)
|
||||||
|
elif len(topics) > 1:
|
||||||
|
string = "Multiple matches to this topic. Refine your search."
|
||||||
|
string += "\n ".join(topics)
|
||||||
|
else:
|
||||||
|
# we have exactly one match. Extract all info from it,
|
||||||
|
# append the text and feed it back into the system.
|
||||||
|
newtext = topics[0].get_entrytext_ingame()
|
||||||
|
category = topics[0].category
|
||||||
|
perm_tuple = topics[0].canview
|
||||||
|
if perm_tuple:
|
||||||
|
perm_tuple = tuple(perm for perm in perm_tuple.split(','))
|
||||||
|
|
||||||
|
newl = "\n"
|
||||||
|
if 'newl' in switches or 'newline' in switches:
|
||||||
|
newl = "\n\n"
|
||||||
|
newtext += "%s%s" % (newl, text)
|
||||||
|
|
||||||
|
topics = helpsystem.edithelp.add_help_manual(source_object,
|
||||||
|
topicstr,
|
||||||
|
category,
|
||||||
|
newtext,
|
||||||
|
perm_tuple,
|
||||||
|
force=True)
|
||||||
|
|
||||||
|
elif 'del' in switches or 'delete' in switches:
|
||||||
|
#delete a help entry
|
||||||
|
topics = helpsystem.edithelp.del_help_manual(source_object, topicstr)
|
||||||
|
if not topics:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
string = "Multiple matches for '%s'. Please specify:" % topicstr
|
||||||
|
string += "\n ".join(topics)
|
||||||
|
|
||||||
|
GLOBAL_CMD_TABLE.add_command("@sethelp", cmd_sethelp,
|
||||||
|
priv_tuple=("helpsys.add_help",
|
||||||
|
"helpsys.del_help",
|
||||||
|
"helpsys.admin_heelp"),
|
||||||
|
help_category="Admin")
|
||||||
|
|
|
||||||
|
|
@ -146,6 +146,11 @@ def build_query(source_object, search_query, search_player, search_type,
|
||||||
|
|
||||||
def cmd_search(command):
|
def cmd_search(command):
|
||||||
"""
|
"""
|
||||||
|
search
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
search <name>
|
||||||
|
|
||||||
Searches for owned objects as per MUX2.
|
Searches for owned objects as per MUX2.
|
||||||
"""
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
|
|
@ -232,4 +237,5 @@ def cmd_search(command):
|
||||||
|
|
||||||
display_results(source_object, search_query)
|
display_results(source_object, search_query)
|
||||||
GLOBAL_CMD_TABLE.add_command("@search", cmd_search,
|
GLOBAL_CMD_TABLE.add_command("@search", cmd_search,
|
||||||
priv_tuple=("objects.info")),
|
priv_tuple=("objects.info",),
|
||||||
|
help_category="Building")
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ Commands that are available from the connect screen.
|
||||||
"""
|
"""
|
||||||
import traceback
|
import traceback
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from src.objects.models import Attribute, Object
|
from src.objects.models import Object
|
||||||
from src import defines_global
|
from src import defines_global
|
||||||
from src.util import functions_general
|
from src.util import functions_general
|
||||||
from src.cmdtable import GLOBAL_UNCON_CMD_TABLE
|
from src.cmdtable import GLOBAL_UNCON_CMD_TABLE
|
||||||
|
|
@ -47,7 +47,7 @@ def cmd_connect(command):
|
||||||
else:
|
else:
|
||||||
uname = user.username
|
uname = user.username
|
||||||
session.login(user)
|
session.login(user)
|
||||||
GLOBAL_UNCON_CMD_TABLE.add_command("connect", cmd_connect)
|
GLOBAL_UNCON_CMD_TABLE.add_command("connect", cmd_connect, auto_help_override=False)
|
||||||
|
|
||||||
def cmd_create(command):
|
def cmd_create(command):
|
||||||
"""
|
"""
|
||||||
|
|
@ -113,7 +113,7 @@ def cmd_create(command):
|
||||||
log_errmsg(traceback.format_exc())
|
log_errmsg(traceback.format_exc())
|
||||||
raise
|
raise
|
||||||
|
|
||||||
GLOBAL_UNCON_CMD_TABLE.add_command("create", cmd_create)
|
GLOBAL_UNCON_CMD_TABLE.add_command("create", cmd_create, auto_help_override=False)
|
||||||
|
|
||||||
def cmd_quit(command):
|
def cmd_quit(command):
|
||||||
"""
|
"""
|
||||||
|
|
@ -124,4 +124,4 @@ def cmd_quit(command):
|
||||||
session = command.session
|
session = command.session
|
||||||
session.msg("Good bye! Disconnecting ...")
|
session.msg("Good bye! Disconnecting ...")
|
||||||
session.handle_close()
|
session.handle_close()
|
||||||
GLOBAL_UNCON_CMD_TABLE.add_command("quit", cmd_quit)
|
GLOBAL_UNCON_CMD_TABLE.add_command("quit", cmd_quit, auto_help_override=False)
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,7 @@ PERM_CHANNELS = (
|
||||||
('page','May page other users.'),)
|
('page','May page other users.'),)
|
||||||
# help system access permissions
|
# help system access permissions
|
||||||
PERM_HELPSYS = (
|
PERM_HELPSYS = (
|
||||||
|
("admin_help","May admin the help system"),
|
||||||
("staff_help", "May see staff help topics."),
|
("staff_help", "May see staff help topics."),
|
||||||
("add_help", "May add or append to help entries"),
|
("add_help", "May add or append to help entries"),
|
||||||
("del_help", "May delete help entries"),)
|
("del_help", "May delete help entries"),)
|
||||||
|
|
@ -136,21 +137,24 @@ PERM_ALL_CUSTOM = ()
|
||||||
# A dict defining the groups, on the form {group_name:(perm1,perm2,...),...}
|
# A dict defining the groups, on the form {group_name:(perm1,perm2,...),...}
|
||||||
PERM_GROUPS = \
|
PERM_GROUPS = \
|
||||||
{"Immortals":('irc.admin_irc_channels', 'imc2.admin_imc_channels', 'channels.emit_commchannel',
|
{"Immortals":('irc.admin_irc_channels', 'imc2.admin_imc_channels', 'channels.emit_commchannel',
|
||||||
'channels.channel_admin','channels.page','helpsys.staff_help','helpsys.add_help',
|
'channels.channel_admin', 'channels.page', 'helpsys.admin_help',
|
||||||
|
'helpsys.staff_help', 'helpsys.add_help',
|
||||||
'helpsys.del_help', 'objects.teleport', 'objects.wipe', 'objects.modify_attributes',
|
'helpsys.del_help', 'objects.teleport', 'objects.wipe', 'objects.modify_attributes',
|
||||||
'objects.info','objects.create','objects.dig','objects.see_dbref','objects.admin_ownership',
|
'objects.info','objects.create','objects.dig','objects.see_dbref',
|
||||||
'genperms.announce','genperms.admin_perm','genperms.admin_group','genperms.process_control',
|
'objects.admin_ownership', 'genperms.announce', 'genperms.admin_perm',
|
||||||
'genperms.manage_players','genperms.game_info'),
|
'genperms.admin_group', 'genperms.process_control', 'genperms.manage_players',
|
||||||
"Wizards": ('irc.admin_irc_channels','imc2.admin_imc_channels','channels.emit_commchannel',
|
|
||||||
'channels.channel_admin','channels.page','helpsys.staff_help','helpsys.add_help',
|
|
||||||
'helpsys.del_help','objects.teleport','objects.wipe','objects.see_dbref',
|
|
||||||
'objects.modify_attributes',
|
|
||||||
'objects.info','objects.create','objects.dig','objects.admin_ownership','genperms.announce',
|
|
||||||
'genperms.game_info'),
|
'genperms.game_info'),
|
||||||
"Builders":('channels.emit_commchannel','channels.page','helpsys.staff_help','helpsys.add_help',
|
"Wizards": ('irc.admin_irc_channels', 'imc2.admin_imc_channels', 'channels.emit_commchannel',
|
||||||
|
'channels.channel_admin', 'channels.page', 'helpsys.admin_help',
|
||||||
|
'helpsys.staff_help', 'helpsys.add_help',
|
||||||
'helpsys.del_help', 'objects.teleport', 'objects.wipe', 'objects.see_dbref',
|
'helpsys.del_help', 'objects.teleport', 'objects.wipe', 'objects.see_dbref',
|
||||||
'objects.modify_attributes', 'objects.info', 'objects.create', 'objects.dig',
|
'objects.modify_attributes', 'objects.info', 'objects.create', 'objects.dig',
|
||||||
'genperms.game_info'),
|
'objects.admin_ownership', 'genperms.announce', 'genperms.game_info'),
|
||||||
|
"Builders":('channels.emit_commchannel', 'channels.page', 'helpsys.staff_help',
|
||||||
|
'helpsys.add_help', 'helpsys.del_help',
|
||||||
|
'objects.teleport', 'objects.wipe', 'objects.see_dbref',
|
||||||
|
'objects.modify_attributes', 'objects.info',
|
||||||
|
'objects.create', 'objects.dig', 'genperms.game_info'),
|
||||||
"Player Helpers":('channels.emit_commchannel', 'channels.page', 'helpsys.staff_help',
|
"Player Helpers":('channels.emit_commchannel', 'channels.page', 'helpsys.staff_help',
|
||||||
'helpsys.add_help', 'helpsys.del_help'),
|
'helpsys.add_help', 'helpsys.del_help'),
|
||||||
"Players":('channels.emit_commchannel', 'channels.page')
|
"Players":('channels.emit_commchannel', 'channels.page')
|
||||||
|
|
@ -158,8 +162,24 @@ PERM_GROUPS = \
|
||||||
# By defining a default player group, all players may start with some permissions pre-set.
|
# By defining a default player group, all players may start with some permissions pre-set.
|
||||||
PERM_DEFAULT_PLAYER_GROUP = "Players"
|
PERM_DEFAULT_PLAYER_GROUP = "Players"
|
||||||
|
|
||||||
|
## Help system
|
||||||
|
## Evennia allows automatic help-updating of commands by use of the auto-help system
|
||||||
|
## which use the command's docstrings for documentation, automatically updating it
|
||||||
|
## as commands are reloaded. Auto-help is a powerful way to keep your help database
|
||||||
|
## up-to-date, but it will also overwrite manual changes made
|
||||||
|
## to the help database using other means (@set_help, admin interface etc), so
|
||||||
|
## for a production environment you might want to turn auto-help off. You can
|
||||||
|
## later activate auto-help on a per-command basis (e.g. when developing a new command)
|
||||||
|
## using the auto_help_override argument to add_command().
|
||||||
|
|
||||||
|
# activate the auto-help system
|
||||||
|
HELP_AUTO_ENABLED = True
|
||||||
|
# Add a dynamically calculated 'See also' footer to help entries
|
||||||
|
HELP_SHOW_RELATED = True
|
||||||
|
|
||||||
|
## Channels
|
||||||
|
## Your names of various default comm channels for emitting debug- or informative messages.
|
||||||
|
|
||||||
# Your names of various default comm channels for emitting debug- or informative messages.
|
|
||||||
COMMCHAN_MUD_INFO = 'MUDInfo'
|
COMMCHAN_MUD_INFO = 'MUDInfo'
|
||||||
COMMCHAN_MUD_CONNECTIONS = 'MUDConnections'
|
COMMCHAN_MUD_CONNECTIONS = 'MUDConnections'
|
||||||
COMMCHAN_IMC2_INFO = 'MUDInfo'
|
COMMCHAN_IMC2_INFO = 'MUDInfo'
|
||||||
|
|
|
||||||
411
src/helpsys/helpsystem.py
Normal file
411
src/helpsys/helpsystem.py
Normal file
|
|
@ -0,0 +1,411 @@
|
||||||
|
"""
|
||||||
|
Support functions for the help system.
|
||||||
|
Allows adding help to the data base from inside the mud as
|
||||||
|
well as creating auto-docs of commands based on their doc strings.
|
||||||
|
The system supports help-markup for multiple help entries as well
|
||||||
|
as a dynamically updating help index.
|
||||||
|
"""
|
||||||
|
import textwrap
|
||||||
|
from django.conf import settings
|
||||||
|
from src.helpsys.models import HelpEntry
|
||||||
|
from src import logger
|
||||||
|
from src import defines_global
|
||||||
|
|
||||||
|
|
||||||
|
class EditHelp(object):
|
||||||
|
"""
|
||||||
|
This sets up an object able to perform normal editing
|
||||||
|
operations on the help database.
|
||||||
|
"""
|
||||||
|
def __init__(self, indent=4, width=70):
|
||||||
|
"""
|
||||||
|
We check if auto-help is active or not and
|
||||||
|
set some formatting options.
|
||||||
|
"""
|
||||||
|
self.indent = indent # indentation of help text
|
||||||
|
self.width = width # width of help text
|
||||||
|
|
||||||
|
def format_help_text(self, help_text):
|
||||||
|
"""
|
||||||
|
This formats the help entry text for proper left-side indentation.
|
||||||
|
|
||||||
|
The first line is adjusted to the proper indentation and the
|
||||||
|
subsequent lines are then adjusted proportionally to the first;
|
||||||
|
so indentation relative this first line remains intact.
|
||||||
|
"""
|
||||||
|
lines = help_text.expandtabs().splitlines()
|
||||||
|
|
||||||
|
# strip empty lines above and below the text
|
||||||
|
while True:
|
||||||
|
if lines and not lines[0].strip():
|
||||||
|
lines.pop(0)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
while True:
|
||||||
|
if lines and not lines[-1].strip():
|
||||||
|
lines.pop()
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
if not lines:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
# produce a list of the indentations of each line initially
|
||||||
|
indentlist = [len(line) - len(line.lstrip()) for line in lines]
|
||||||
|
|
||||||
|
# use the first line to set the shift
|
||||||
|
lineshift = indentlist[0] - self.indent
|
||||||
|
|
||||||
|
# shift everything to the left
|
||||||
|
indentlist = [max(self.indent, indent-lineshift) for indent in indentlist]
|
||||||
|
trimmed = []
|
||||||
|
for il, line in enumerate(lines):
|
||||||
|
indentstr = " " * indentlist[il]
|
||||||
|
trimmed.append("%s%s" % (indentstr, line.strip()))
|
||||||
|
return "\n".join(trimmed)
|
||||||
|
|
||||||
|
def parse_markup_header(self, subtopic_header):
|
||||||
|
"""
|
||||||
|
The possible markup headers for splitting the help into sections are:
|
||||||
|
[[TopicTitle]]
|
||||||
|
[[TopicTitle,category]]
|
||||||
|
[[TopicTitle(perm1,perm2)]]
|
||||||
|
[[TopicTitle,category(perm1,perm2)]]
|
||||||
|
"""
|
||||||
|
subtitle = ""
|
||||||
|
subcategory = ""
|
||||||
|
subpermissions = ()
|
||||||
|
#identifying the header parts. The header can max have three parts:
|
||||||
|
# topicname, category (perm1,perm2,...)
|
||||||
|
try:
|
||||||
|
# find the permission tuple
|
||||||
|
lindex = subtopic_header.index('(')
|
||||||
|
rindex = subtopic_header.index(')')
|
||||||
|
if lindex < rindex:
|
||||||
|
permtuple = subtopic_header[lindex+1:rindex]
|
||||||
|
subpermissions = tuple([p.strip()
|
||||||
|
for p in permtuple.split(',')])
|
||||||
|
subtopic_header = subtopic_header[:lindex]
|
||||||
|
except ValueError:
|
||||||
|
# no permission tuple found
|
||||||
|
pass
|
||||||
|
# see if we have a name, category pair.
|
||||||
|
try:
|
||||||
|
subtitle, subcategory = subtopic_header.split(',')
|
||||||
|
subtitle, subcategory = subtitle.strip(), subcategory.strip()
|
||||||
|
except ValueError:
|
||||||
|
subtitle = subtopic_header.strip()
|
||||||
|
# we are done, return a tuple with the results
|
||||||
|
return ( subtitle, subcategory, subpermissions )
|
||||||
|
|
||||||
|
def format_help_entry(self, helptopic, category, helptext, permissions=None):
|
||||||
|
"""
|
||||||
|
helptopic (string) - name of the full help entry
|
||||||
|
helptext (string) - the help entry (may contain sections)
|
||||||
|
permissions (tuple) - tuple with permission/group names
|
||||||
|
defined for the entire help entry.
|
||||||
|
(markup permissions override those)
|
||||||
|
Handles help markup in order to split help into subsections.
|
||||||
|
|
||||||
|
These markup markers will be assumed to start a new line, regardless
|
||||||
|
of where they are located in the help entry. If no permission string
|
||||||
|
tuple and/or category is given, the overall permission/category of
|
||||||
|
the entire help entry is used.
|
||||||
|
"""
|
||||||
|
# sanitize input
|
||||||
|
topics = []
|
||||||
|
if '[[' not in helptext:
|
||||||
|
formatted_text = self.format_help_text(helptext)
|
||||||
|
topics.append((helptopic, category,
|
||||||
|
formatted_text, permissions))
|
||||||
|
return topics
|
||||||
|
|
||||||
|
subtopics = helptext.split('[[')
|
||||||
|
|
||||||
|
if subtopics[0]:
|
||||||
|
# the very first entry (before any markup) is the normal
|
||||||
|
# help entry for the helptopic at hand.
|
||||||
|
formatted_text = self.format_help_text(subtopics[0])
|
||||||
|
topics.append((helptopic, category, formatted_text, permissions))
|
||||||
|
|
||||||
|
for subtopic in subtopics[1:]:
|
||||||
|
# handle all extra topics designated with markup
|
||||||
|
try:
|
||||||
|
subtopic_header, subtopic_text = subtopic.split(']]', 1)
|
||||||
|
except ValueError:
|
||||||
|
# if we have no ending, the entry is malformed and
|
||||||
|
# we ignore this entry (better than overwriting
|
||||||
|
# something in the database).
|
||||||
|
logger.log_errmsg("Malformed help markup in %s: '%s'\n (missing end ']]' )" % \
|
||||||
|
(helptopic, subtopic))
|
||||||
|
continue
|
||||||
|
# parse and format the help entry parts
|
||||||
|
subtopic_header = self.parse_markup_header(subtopic_header)
|
||||||
|
if not subtopic_header[0]:
|
||||||
|
# we require a topic title.
|
||||||
|
logger.log_errmsg("Malformed help markup in '%s': Missing title." % subtopic_header)
|
||||||
|
return
|
||||||
|
# parse the header and use defaults
|
||||||
|
subtopic_name = subtopic_header[0]
|
||||||
|
subtopic_category = subtopic_header[1]
|
||||||
|
subtopic_text = self.format_help_text(subtopic_text)
|
||||||
|
subtopic_permissions = subtopic_header[2]
|
||||||
|
if not subtopic_category:
|
||||||
|
# no category set; inherit from main topic
|
||||||
|
subtopic_category = category
|
||||||
|
if not subtopic_permissions:
|
||||||
|
# no permissions set; inherit from main topic
|
||||||
|
subtopic_permissions = permissions
|
||||||
|
|
||||||
|
# We have a finished topic, add it to the list as a topic tuple.
|
||||||
|
topics.append((subtopic_name, subtopic_category,
|
||||||
|
subtopic_text, subtopic_permissions))
|
||||||
|
return topics
|
||||||
|
|
||||||
|
def create_help(self, newtopic):
|
||||||
|
"""
|
||||||
|
Add a help entry to the database, replace an old one if it exists.
|
||||||
|
topic (tuple) - this is a formatted tuple of data as prepared
|
||||||
|
by format_help_entry, on the form (title, category, text, (perm_tuple))
|
||||||
|
"""
|
||||||
|
#sanity checks;
|
||||||
|
topicname = newtopic[0]
|
||||||
|
category = newtopic[1]
|
||||||
|
entrytext = newtopic[2]
|
||||||
|
permissions = newtopic[3]
|
||||||
|
|
||||||
|
if not (topicname or entrytext):
|
||||||
|
# don't create anything if there we
|
||||||
|
# are missing vital parts
|
||||||
|
return
|
||||||
|
if not category:
|
||||||
|
# this will force the default
|
||||||
|
category = "General"
|
||||||
|
if permissions:
|
||||||
|
# the permissions tuple might be mangled;
|
||||||
|
# make sure we build a string properly.
|
||||||
|
if type(permissions) != type(tuple()):
|
||||||
|
permissions = "%s" % permissions
|
||||||
|
else:
|
||||||
|
permissions = ", ".join(permissions)
|
||||||
|
else:
|
||||||
|
permissions = ""
|
||||||
|
|
||||||
|
# check if the help topic already exist.
|
||||||
|
oldtopic = HelpEntry.objects.filter(topicname__iexact=newtopic[0])
|
||||||
|
if oldtopic:
|
||||||
|
#replace an old help file
|
||||||
|
topic = oldtopic[0]
|
||||||
|
topic.category = category
|
||||||
|
topic.entrytext = entrytext
|
||||||
|
topic.canview = permissions
|
||||||
|
topic.save()
|
||||||
|
else:
|
||||||
|
#we have a new topic - create a new help object
|
||||||
|
new_entry = HelpEntry(topicname=topicname,
|
||||||
|
category=category,
|
||||||
|
entrytext=entrytext,
|
||||||
|
canview=permissions)
|
||||||
|
new_entry.save()
|
||||||
|
|
||||||
|
def add_help_auto(self, topicstr, category, entrytext, permissions=()):
|
||||||
|
"""
|
||||||
|
This is used by the auto_help system to add help one or more
|
||||||
|
help entries to the system.
|
||||||
|
"""
|
||||||
|
# sanity checks
|
||||||
|
if permissions and type(permissions) != type(tuple()):
|
||||||
|
string = "Auto-Help: malformed perm_tuple %s: %s -> %s (fixed)" % \
|
||||||
|
(topicstr,permissions, (permissions,))
|
||||||
|
logger.log_errmsg(string)
|
||||||
|
permissions = (permissions,)
|
||||||
|
|
||||||
|
# identify markup and do nice formatting as well as eventual
|
||||||
|
# related entries to the help entries.
|
||||||
|
logger.log_infomsg("auto-help in: %s %s %s %s" % (topicstr, category, entrytext, permissions))
|
||||||
|
topics = self.format_help_entry(topicstr, category,
|
||||||
|
entrytext, permissions)
|
||||||
|
logger.log_infomsg("auto-help: %s -> %s" % (topicstr,topics))
|
||||||
|
# create the help entries:
|
||||||
|
if topics:
|
||||||
|
for topic in topics:
|
||||||
|
self.create_help(topic)
|
||||||
|
|
||||||
|
def add_help_manual(self, pobject, topicstr, category,
|
||||||
|
entrytext, permissions=(), force=False):
|
||||||
|
"""
|
||||||
|
This is used when a player wants to add a help entry to the database
|
||||||
|
manually (most often from inside the game)
|
||||||
|
|
||||||
|
force - this is given by the player and forces an overwrite also if the
|
||||||
|
entry already exists or there are multiple similar matches to
|
||||||
|
the entry.
|
||||||
|
"""
|
||||||
|
# permission check:
|
||||||
|
if not (pobject.is_superuser() or pobject.has_perm("helpsys.add_help")):
|
||||||
|
pobject.emit_to(defines_global.NOPERMS_MSG)
|
||||||
|
return None
|
||||||
|
# do a more fuzzy search to warn in case in case we are misspelling.
|
||||||
|
topic = HelpEntry.objects.find_topicmatch(pobject, topicstr)
|
||||||
|
if topic and not force:
|
||||||
|
return topic
|
||||||
|
self.add_help_auto(topicstr, category, entrytext, permissions)
|
||||||
|
pobject.emit_to("Added/appended help topic '%s'." % topicstr)
|
||||||
|
|
||||||
|
def del_help_auto(self, topicstr):
|
||||||
|
"""
|
||||||
|
Delete a help entry from the data base. Automatic version.
|
||||||
|
"""
|
||||||
|
topic = HelpEntry.objects.filter(topicname__iexact=topicstr)
|
||||||
|
if topic:
|
||||||
|
topic[0].delete()
|
||||||
|
|
||||||
|
def del_help_manual(self, pobject, topicstr):
|
||||||
|
"""
|
||||||
|
Deletes an entry from the database. Interactive version.
|
||||||
|
Note that it makes no sense to delete auto-added help entries this way since
|
||||||
|
they will be re-added on the next @reload. This is mostly useful for cleaning
|
||||||
|
the database from doublet or orphaned entries, or when auto-help is turned off.
|
||||||
|
"""
|
||||||
|
# find topic with permission checks
|
||||||
|
if not (pobject.is_superuser() or pobject.has_perm("helpsys.del_help")):
|
||||||
|
pobject.emit_to(defines_global.NOPERMS_MSG)
|
||||||
|
return None
|
||||||
|
topic = HelpEntry.objects.find_topicmatch(pobject, topicstr)
|
||||||
|
if not topic or len(topic) > 1:
|
||||||
|
return topic
|
||||||
|
# we have an exact match. Delete topic.
|
||||||
|
topic[0].delete()
|
||||||
|
pobject.emit_to("Help entry '%s' deleted." % topicstr)
|
||||||
|
|
||||||
|
def homogenize_database(self, category):
|
||||||
|
"""
|
||||||
|
This sets the entire help database to one category.
|
||||||
|
It can be used to mark an initially loaded help database
|
||||||
|
in a particular category, for later filtering.
|
||||||
|
|
||||||
|
In evennia dev version, this is done with MUX help database.
|
||||||
|
"""
|
||||||
|
entries = HelpEntry.objects.all()
|
||||||
|
for entry in entries:
|
||||||
|
entry.category = category
|
||||||
|
entry.save()
|
||||||
|
logger.log_infomsg("Help database homogenized to category %s" % category)
|
||||||
|
|
||||||
|
def autoclean_database(self, topiclist):
|
||||||
|
"""
|
||||||
|
This syncs the entire help database against a reference topic
|
||||||
|
list, deleting non-used or duplicate help entries that can be
|
||||||
|
the result of auto-help misspellings etc.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
class ViewHelp(object):
|
||||||
|
"""
|
||||||
|
This class contains ways to view the
|
||||||
|
help database in a dynamical fashion.
|
||||||
|
"""
|
||||||
|
def __init__(self, indent=4, width=78, category_cols=4, entry_cols=6):
|
||||||
|
"""
|
||||||
|
indent (int) - number of spaces to indent tables with
|
||||||
|
width (int) - width of index tables
|
||||||
|
category_cols (int) - number of collumns per row for
|
||||||
|
category tables
|
||||||
|
entry_cols (int) - number of collumns per row for help entries
|
||||||
|
"""
|
||||||
|
self.width = width
|
||||||
|
self.indent = indent
|
||||||
|
self.category_cols = category_cols
|
||||||
|
self.entry_cols = entry_cols
|
||||||
|
self.show_related = settings.HELP_SHOW_RELATED
|
||||||
|
|
||||||
|
def make_table(self, items, cols):
|
||||||
|
"""
|
||||||
|
This takes a list of string items and displays them in collumn order,
|
||||||
|
(sorted horizontally-first), ie
|
||||||
|
A A A A
|
||||||
|
A B B B
|
||||||
|
B B C C
|
||||||
|
C C
|
||||||
|
cols is the number of collumns to format.
|
||||||
|
"""
|
||||||
|
items.sort()
|
||||||
|
if not items or not cols:
|
||||||
|
return []
|
||||||
|
length = len(items)
|
||||||
|
# split the list into sublists of length cols
|
||||||
|
rows = [items[i:i+cols] for i in xrange(0, length, cols)]
|
||||||
|
# build the table
|
||||||
|
string = ""
|
||||||
|
for row in rows:
|
||||||
|
string += self.indent * " " + ", ".join(row) + "\n"
|
||||||
|
return string
|
||||||
|
|
||||||
|
def index_full(self, pobject):
|
||||||
|
"""
|
||||||
|
This lists all available topics in the help index,
|
||||||
|
ordered after category.
|
||||||
|
|
||||||
|
The MUX category is not shown, it is for development
|
||||||
|
reference only.
|
||||||
|
"""
|
||||||
|
entries = HelpEntry.objects.all()
|
||||||
|
|
||||||
|
categories = [e.category for e in entries if e.category != 'MUX']
|
||||||
|
categories = list(set(categories)) # make list unique
|
||||||
|
categories.sort()
|
||||||
|
table = ""
|
||||||
|
for category in categories:
|
||||||
|
topics = [e.topicname.lower() for e in entries.filter(category__iexact=category)
|
||||||
|
if e.can_view(pobject)]
|
||||||
|
|
||||||
|
# pretty-printing the list
|
||||||
|
header = "--- Topics in category %s:" % category
|
||||||
|
nl = self.width - len(header)
|
||||||
|
if not topics:
|
||||||
|
text = self.indent*" " + "[There are no topics relevant to you in this category.]\n\r"
|
||||||
|
else:
|
||||||
|
text = self.make_table(topics, self.entry_cols)
|
||||||
|
table += "\r\n%s%s\n\r\n\r%s" % (header, "-"*nl, text)
|
||||||
|
return table
|
||||||
|
|
||||||
|
def index_categories(self):
|
||||||
|
"""
|
||||||
|
This lists all categories defined in the help index.
|
||||||
|
"""
|
||||||
|
entries = HelpEntry.objects.all()
|
||||||
|
categories = [e.category for e in entries]
|
||||||
|
categories = list(set(categories)) # make list unique
|
||||||
|
return self.make_table(categories, self.category_cols)
|
||||||
|
|
||||||
|
def index_category(self, pobject, category):
|
||||||
|
"""
|
||||||
|
List the help entries within a certain category
|
||||||
|
"""
|
||||||
|
entries = HelpEntry.objects.find_topics_with_category(pobject, category)
|
||||||
|
if not entries:
|
||||||
|
return []
|
||||||
|
# filter out those we can actually view
|
||||||
|
helptopics = [e.topicname.lower() for e in entries if e.can_view(pobject)]
|
||||||
|
if not helptopics:
|
||||||
|
# we don't have permission to view anything in this category
|
||||||
|
return " [There are no topics relevant to you in this category.]\n\r"
|
||||||
|
return self.make_table(helptopics, self.entry_cols)
|
||||||
|
|
||||||
|
def suggest_help(self, pobject, topic):
|
||||||
|
"""
|
||||||
|
This goes through the help database, searching for relatively
|
||||||
|
close matches to this topic. If those are found, they are
|
||||||
|
added as a nice footer to the end of the topic entry.
|
||||||
|
"""
|
||||||
|
if not self.show_related:
|
||||||
|
return None
|
||||||
|
topicname = topic.topicname
|
||||||
|
return HelpEntry.objects.find_topicsuggestions(pobject, topicname)
|
||||||
|
|
||||||
|
# Object instances
|
||||||
|
edithelp = EditHelp(indent=3,
|
||||||
|
width=80)
|
||||||
|
viewhelp = ViewHelp(indent=3,
|
||||||
|
width=80,
|
||||||
|
category_cols=4,
|
||||||
|
entry_cols=4)
|
||||||
|
|
@ -1,230 +0,0 @@
|
||||||
"""
|
|
||||||
Support commands for a more advanced help system.
|
|
||||||
Allows adding help to the data base from inside the mud as
|
|
||||||
well as creating auto-docs of commands based on their doc strings.
|
|
||||||
The system supports help-markup for multiple help entries as well
|
|
||||||
as a dynamically updating help index.
|
|
||||||
"""
|
|
||||||
from django.contrib.auth.models import User
|
|
||||||
from src.helpsys.models import HelpEntry
|
|
||||||
from src.ansi import ANSITable
|
|
||||||
|
|
||||||
#
|
|
||||||
# Helper functions
|
|
||||||
#
|
|
||||||
|
|
||||||
def _privileged_help_search(topicstr):
|
|
||||||
"""
|
|
||||||
searches the topic data base without needing to know who calls it. Needed
|
|
||||||
for autohelp functionality. Will show all help entries, also those set to staff
|
|
||||||
only.
|
|
||||||
"""
|
|
||||||
if topicstr.isdigit():
|
|
||||||
t_query = HelpEntry.objects.filter(id=topicstr)
|
|
||||||
else:
|
|
||||||
exact_match = HelpEntry.objects.filter(topicname__iexact=topicstr)
|
|
||||||
if exact_match:
|
|
||||||
t_query = exact_match
|
|
||||||
else:
|
|
||||||
t_query = HelpEntry.objects.filter(topicname__istartswith=topicstr)
|
|
||||||
return t_query
|
|
||||||
|
|
||||||
|
|
||||||
def _create_help(topicstr, entrytext, staff_only=False, force_create=False,
|
|
||||||
pobject=None, noauth=False):
|
|
||||||
"""
|
|
||||||
Add a help entry to the database, replace an old one if it exists.
|
|
||||||
|
|
||||||
Note - noauth=True will bypass permission checks, so do not use this from
|
|
||||||
inside mud, it is needed by the autohelp system only.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if noauth:
|
|
||||||
#do not check permissions (for autohelp)
|
|
||||||
topic = _privileged_help_search(topicstr)
|
|
||||||
elif pobject:
|
|
||||||
#checks access rights before searching (this should have been
|
|
||||||
#done already at the command level)
|
|
||||||
if not pobject.has_perm("helpsys.add_help"): return []
|
|
||||||
topic = HelpEntry.objects.find_topicmatch(pobject, topicstr)
|
|
||||||
else:
|
|
||||||
return []
|
|
||||||
|
|
||||||
if len(topic) == 1:
|
|
||||||
#replace an old help file
|
|
||||||
topic = topic[0]
|
|
||||||
topic.entrytext = entrytext
|
|
||||||
topic.staff_only = staff_only
|
|
||||||
topic.save()
|
|
||||||
return [topic]
|
|
||||||
elif len(topic) > 1 and not force_create:
|
|
||||||
#a partial match, return it for inspection.
|
|
||||||
return topic
|
|
||||||
else:
|
|
||||||
#we have a new topic - create a new help object
|
|
||||||
new_entry = HelpEntry(topicname=topicstr,
|
|
||||||
entrytext=entrytext,
|
|
||||||
staff_only=staff_only)
|
|
||||||
new_entry.save()
|
|
||||||
return [new_entry]
|
|
||||||
|
|
||||||
def handle_help_markup(topicstr, entrytext, staff_only, identifier="<<TOPIC:"):
|
|
||||||
"""
|
|
||||||
Handle help markup in order to split help into subsections.
|
|
||||||
Handles markup of the form <<TOPIC:STAFF:TopicTitle>> and
|
|
||||||
<<TOPIC:ALL:TopicTitle>> to override the staff_only flag on a per-subtopic
|
|
||||||
basis.
|
|
||||||
"""
|
|
||||||
topic_list = entrytext.split(identifier)
|
|
||||||
topic_dict = {}
|
|
||||||
staff_dict = {}
|
|
||||||
for txt in topic_list:
|
|
||||||
txt = txt.rstrip()
|
|
||||||
if txt.count('>>'):
|
|
||||||
topic, text = txt.split('>>',1)
|
|
||||||
text = text.rstrip()
|
|
||||||
topic = topic.lower()
|
|
||||||
|
|
||||||
if topic in topic_dict.keys():
|
|
||||||
#do not allow multiple topics of the same name
|
|
||||||
return {}, []
|
|
||||||
if 'all:' in topic:
|
|
||||||
topic = topic[4:]
|
|
||||||
staff_dict[topic] = False
|
|
||||||
elif 'staff:' in topic:
|
|
||||||
topic = topic[6:]
|
|
||||||
staff_dict[topic] = True
|
|
||||||
else:
|
|
||||||
staff_dict[topic] = staff_only
|
|
||||||
topic_dict[topic] = text
|
|
||||||
else:
|
|
||||||
#no markup, just add the entry as-is
|
|
||||||
topic = topicstr.lower()
|
|
||||||
topic_dict[topic] = txt
|
|
||||||
staff_dict[topic] = staff_only
|
|
||||||
return topic_dict, staff_dict
|
|
||||||
|
|
||||||
def format_footer(top, text, topic_dict, staff_dict):
|
|
||||||
"""
|
|
||||||
Formats the subtopic with a 'Related Topics:' footer. If mixed
|
|
||||||
staff-only flags are set, those help entries without the staff-only flag
|
|
||||||
will not see staff-only help files recommended in the footer. This allows
|
|
||||||
to separate out the staff-only help switches etc into a separate
|
|
||||||
help file so as not to confuse normal players.
|
|
||||||
"""
|
|
||||||
if text:
|
|
||||||
#only include non-staff related footers to non-staff commands
|
|
||||||
if staff_dict[top]:
|
|
||||||
other_topics = other_topics = filter(lambda o: o != top, topic_dict.keys())
|
|
||||||
else:
|
|
||||||
other_topics = other_topics = filter(lambda o: o != top and not staff_dict[o],
|
|
||||||
topic_dict.keys())
|
|
||||||
if other_topics:
|
|
||||||
footer = ANSITable.ansi['normal'] + "\n\r\n\r Related Topics: "
|
|
||||||
for t in other_topics:
|
|
||||||
footer += t + ', '
|
|
||||||
footer = footer[:-2] + '.'
|
|
||||||
return text + footer
|
|
||||||
else:
|
|
||||||
return text
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
#
|
|
||||||
# Access functions
|
|
||||||
#
|
|
||||||
|
|
||||||
def add_help(topicstr, entrytext, staff_only=False, force_create=False,
|
|
||||||
pobject=None, auto_help=False):
|
|
||||||
"""
|
|
||||||
Add a help topic to the database. This is also usable by autohelp, with auto=True.
|
|
||||||
|
|
||||||
Allows <<TOPIC:TopicTitle>> markup in the help text, to automatically spawn
|
|
||||||
subtopics. For creating mixed staff/ordinary subtopics, the <<TOPIC:STAFF:TopicTitle>> and
|
|
||||||
<<TOPIC:ALL:TopicTitle>> commands can override the overall staff_only setting for
|
|
||||||
that entry only.
|
|
||||||
"""
|
|
||||||
identifier = '<<TOPIC:'
|
|
||||||
if identifier in entrytext:
|
|
||||||
#There is markup in the entry, so we should split the doc into separate subtopics
|
|
||||||
topic_dict, staff_dict = handle_help_markup(topicstr, entrytext,
|
|
||||||
staff_only, identifier)
|
|
||||||
topics = []
|
|
||||||
for topic, text in topic_dict.items():
|
|
||||||
|
|
||||||
#format with nice footer
|
|
||||||
entry = format_footer(topic, text, topic_dict, staff_dict)
|
|
||||||
|
|
||||||
if entry:
|
|
||||||
#create the subtopic
|
|
||||||
newtopic = _create_help(topic, entry,staff_only=staff_dict[topic],
|
|
||||||
force_create=force_create,pobject=pobject,noauth=auto_help)
|
|
||||||
topics.extend(newtopic)
|
|
||||||
return topics
|
|
||||||
|
|
||||||
elif entrytext:
|
|
||||||
#if there were no topic sections, just create the help entry as normal
|
|
||||||
return _create_help(topicstr.lower(),entrytext,staff_only=staff_only,
|
|
||||||
force_create=force_create,pobject=pobject,noauth=auto_help)
|
|
||||||
|
|
||||||
def del_help(pobject,topicstr):
|
|
||||||
"""
|
|
||||||
Delete a help entry from the data base.
|
|
||||||
|
|
||||||
Note that it makes no sense to delete auto-added help entries this way since
|
|
||||||
they will just be re-added on the next @reload. Delete such entries by turning
|
|
||||||
off their auto-help functionality first.
|
|
||||||
"""
|
|
||||||
#find topic with permission checks
|
|
||||||
if not pobject.is_staff(): return []
|
|
||||||
topic = HelpEntry.objects.find_topicmatch(pobject, topicstr)
|
|
||||||
if topic:
|
|
||||||
if len(topic) == 1:
|
|
||||||
#delete topic
|
|
||||||
topic.delete()
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return topic
|
|
||||||
else:
|
|
||||||
return []
|
|
||||||
|
|
||||||
def get_help_index(pobject,filter=None):
|
|
||||||
"""
|
|
||||||
Dynamically builds a help index depending on who asks for it, so
|
|
||||||
normal players won't see staff-only help files, for example.
|
|
||||||
|
|
||||||
The filter parameter allows staff to limit their view of the help index
|
|
||||||
no filter (default) - view all help files, staff and non-staff
|
|
||||||
filter='staff' - view only staff-specific help files
|
|
||||||
filter='player' - view only those files visible to all
|
|
||||||
"""
|
|
||||||
|
|
||||||
if pobject.has_perm("helpsys.staff_help"):
|
|
||||||
if filter == 'staff':
|
|
||||||
helpentries = HelpEntry.objects.filter(staff_only=True).order_by('topicname')
|
|
||||||
elif filter == 'player':
|
|
||||||
helpentries = HelpEntry.objects.filter(staff_only=False).order_by('topicname')
|
|
||||||
else:
|
|
||||||
helpentries = HelpEntry.objects.all().order_by('topicname')
|
|
||||||
else:
|
|
||||||
helpentries = HelpEntry.objects.filter(staff_only=False).order_by('topicname')
|
|
||||||
|
|
||||||
if not helpentries:
|
|
||||||
pobject.emit_to("No help entries found.")
|
|
||||||
return
|
|
||||||
|
|
||||||
topics = [entry.topicname for entry in helpentries]
|
|
||||||
#format help entries into suitable alphabetized collumns.
|
|
||||||
percollumn = 8
|
|
||||||
s = ""
|
|
||||||
i = 0
|
|
||||||
while True:
|
|
||||||
i += 1
|
|
||||||
try:
|
|
||||||
top = topics.pop(0)
|
|
||||||
s+= " %s " % top
|
|
||||||
if i%percollumn == 0: s += '\n\r'
|
|
||||||
except IndexError:
|
|
||||||
break
|
|
||||||
s += " (%i entries)" % (i-1)
|
|
||||||
pobject.emit_to(s)
|
|
||||||
|
|
@ -4,35 +4,56 @@ Custom manager for HelpEntry objects.
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
class HelpEntryManager(models.Manager):
|
class HelpEntryManager(models.Manager):
|
||||||
def find_topicmatch(self, pobject, topicstr):
|
"""
|
||||||
|
This implements different ways to search for help entries.
|
||||||
|
"""
|
||||||
|
def find_topicmatch(self, pobject, topicstr, exact=False):
|
||||||
"""
|
"""
|
||||||
Searches for matching topics based on player's input.
|
Searches for matching topics based on player's input.
|
||||||
"""
|
"""
|
||||||
is_staff = pobject.is_staff()
|
|
||||||
|
|
||||||
if topicstr.isdigit():
|
if topicstr.isdigit():
|
||||||
t_query = self.filter(id=topicstr)
|
return self.filter(id=topicstr)
|
||||||
else:
|
t_query = self.filter(topicname__iexact=topicstr)
|
||||||
exact_match = self.filter(topicname__iexact=topicstr)
|
if not t_query and not exact:
|
||||||
if exact_match:
|
|
||||||
t_query = exact_match
|
|
||||||
else:
|
|
||||||
t_query = self.filter(topicname__istartswith=topicstr)
|
t_query = self.filter(topicname__istartswith=topicstr)
|
||||||
|
# check permissions
|
||||||
if not is_staff:
|
t_query = [topic for topic in t_query if topic.can_view(pobject)]
|
||||||
return t_query.exclude(staff_only=1)
|
|
||||||
|
|
||||||
return t_query
|
return t_query
|
||||||
|
|
||||||
def find_topicsuggestions(self, pobject, topicstr):
|
def find_topicsuggestions(self, pobject, topicstr):
|
||||||
"""
|
"""
|
||||||
Do a fuzzier "contains" match.
|
Do a fuzzy match, preferably within the category of the
|
||||||
|
current topic.
|
||||||
"""
|
"""
|
||||||
is_staff = pobject.is_staff()
|
basetopic = self.filter(topicname__iexact=topicstr)
|
||||||
t_query = self.filter(topicname__icontains=topicstr)
|
if not basetopic:
|
||||||
|
# this topic does not exist; just reply partial
|
||||||
|
# matches to the string
|
||||||
|
topics = self.filter(topicname__icontains=topicstr)
|
||||||
|
return [topic for topic in topics if topic.can_view(pobject)]
|
||||||
|
|
||||||
if not is_staff:
|
# we know that the topic exists, try to find similar ones within
|
||||||
return t_query.exclude(staff_only=1)
|
# its category.
|
||||||
|
basetopic = basetopic[0]
|
||||||
|
category = basetopic.category
|
||||||
|
topics = []
|
||||||
|
|
||||||
return t_query
|
#remove the @
|
||||||
|
crop = topicstr.lstrip('@')
|
||||||
|
|
||||||
|
# first we filter for matches with the full name
|
||||||
|
topics = self.filter(category__iexact=category).filter(topicname__icontains=crop)
|
||||||
|
if len(crop) > 4:
|
||||||
|
# next search with a cropped version of the command.
|
||||||
|
ttemp = self.filter(category__iexact=category).filter(topicname__icontains=crop[:4])
|
||||||
|
ttemp = [topic for topic in ttemp if topic not in topics]
|
||||||
|
topics = list(topics) + list(ttemp)
|
||||||
|
# we need to clean away the given help entry.
|
||||||
|
return [topic for topic in topics if topic.topicname.lower() != topicstr.lower()]
|
||||||
|
|
||||||
|
def find_topics_with_category(self, pobject, category):
|
||||||
|
"""
|
||||||
|
Search topics having a particular category
|
||||||
|
"""
|
||||||
|
t_query = self.filter(category__iexact=category)
|
||||||
|
return [topic for topic in t_query if topic.can_view(pobject)]
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,21 @@ class HelpEntry(models.Model):
|
||||||
A generic help entry.
|
A generic help entry.
|
||||||
"""
|
"""
|
||||||
topicname = models.CharField(max_length=255, unique=True)
|
topicname = models.CharField(max_length=255, unique=True)
|
||||||
entrytext = models.TextField(blank=True, null=True)
|
category = models.CharField(max_length=255, default="General")
|
||||||
|
canview = models.CharField(max_length=255, blank=True)
|
||||||
|
entrytext = models.TextField(blank=True)
|
||||||
|
|
||||||
|
#deprecated, only here to allow MUX helpfile load.
|
||||||
staff_only = models.BooleanField(default=False)
|
staff_only = models.BooleanField(default=False)
|
||||||
|
|
||||||
objects = HelpEntryManager()
|
objects = HelpEntryManager()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
"""
|
||||||
|
Permissions here defines access to modifying help
|
||||||
|
entries etc, not which entries can be viewed (that
|
||||||
|
is controlled by the canview field).
|
||||||
|
"""
|
||||||
verbose_name_plural = "Help entries"
|
verbose_name_plural = "Help entries"
|
||||||
ordering = ['topicname']
|
ordering = ['topicname']
|
||||||
permissions = settings.PERM_HELPSYS
|
permissions = settings.PERM_HELPSYS
|
||||||
|
|
@ -30,6 +39,23 @@ class HelpEntry(models.Model):
|
||||||
"""
|
"""
|
||||||
return self.topicname
|
return self.topicname
|
||||||
|
|
||||||
|
def get_category(self):
|
||||||
|
"""
|
||||||
|
Returns the category of this help entry.
|
||||||
|
"""
|
||||||
|
return self.category
|
||||||
|
|
||||||
|
def can_view(self, pobject):
|
||||||
|
"""
|
||||||
|
Check if the pobject has the necessary permission/group
|
||||||
|
to view this help entry.
|
||||||
|
"""
|
||||||
|
perm = self.canview.split(',')
|
||||||
|
if not perm or (len(perm) == 1 and not perm[0]) or \
|
||||||
|
pobject.has_perm("helpsys.admin_help"):
|
||||||
|
return True
|
||||||
|
return pobject.has_perm_list(perm)
|
||||||
|
|
||||||
def get_entrytext_ingame(self):
|
def get_entrytext_ingame(self):
|
||||||
"""
|
"""
|
||||||
Gets the entry text for in-game viewing.
|
Gets the entry text for in-game viewing.
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ from django.conf import settings
|
||||||
from src.objects.models import Object
|
from src.objects.models import Object
|
||||||
from src.config.models import ConfigValue, CommandAlias, ConnectScreen
|
from src.config.models import ConfigValue, CommandAlias, ConnectScreen
|
||||||
from src import comsys, defines_global, logger
|
from src import comsys, defines_global, logger
|
||||||
|
from src.helpsys import helpsystem
|
||||||
|
|
||||||
def get_god_user():
|
def get_god_user():
|
||||||
"""
|
"""
|
||||||
Returns the initially created 'god' User object.
|
Returns the initially created 'god' User object.
|
||||||
|
|
@ -131,6 +133,16 @@ def import_help_files():
|
||||||
"""
|
"""
|
||||||
management.call_command('loaddata', 'docs/help_files.json', verbosity=0)
|
management.call_command('loaddata', 'docs/help_files.json', verbosity=0)
|
||||||
|
|
||||||
|
def categorize_initial_helpdb():
|
||||||
|
"""
|
||||||
|
This makes sure that the initially loaded
|
||||||
|
database is separated into its own
|
||||||
|
help category.
|
||||||
|
"""
|
||||||
|
default_category = "MUX"
|
||||||
|
print " Moving initial imported help db to help category '%s'." % default_category
|
||||||
|
helpsystem.edithelp.homogenize_database(default_category)
|
||||||
|
|
||||||
def handle_setup():
|
def handle_setup():
|
||||||
"""
|
"""
|
||||||
Main logic for the module.
|
Main logic for the module.
|
||||||
|
|
@ -142,3 +154,4 @@ def handle_setup():
|
||||||
create_groups()
|
create_groups()
|
||||||
create_channels()
|
create_channels()
|
||||||
import_help_files()
|
import_help_files()
|
||||||
|
categorize_initial_helpdb()
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,13 @@ This is where all of the crucial, core object models reside.
|
||||||
import re
|
import re
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
try: import cPickle as pickle
|
try:
|
||||||
except ImportError: import pickle
|
import cPickle as pickle
|
||||||
|
except ImportError:
|
||||||
|
import pickle
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.contrib.auth.models import User, Group
|
from django.contrib.auth.models import User
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from src.objects.util import object as util_object
|
from src.objects.util import object as util_object
|
||||||
from src.objects.managers.object import ObjectManager
|
from src.objects.managers.object import ObjectManager
|
||||||
|
|
@ -24,8 +26,6 @@ from src import logger
|
||||||
import src.flags
|
import src.flags
|
||||||
from src.util import functions_general
|
from src.util import functions_general
|
||||||
|
|
||||||
from src.logger import log_infomsg
|
|
||||||
|
|
||||||
class Attribute(models.Model):
|
class Attribute(models.Model):
|
||||||
"""
|
"""
|
||||||
Attributes are things that are specific to different types of objects. For
|
Attributes are things that are specific to different types of objects. For
|
||||||
|
|
@ -46,9 +46,9 @@ class Attribute(models.Model):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s(%s)" % (self.attr_name, self.id)
|
return "%s(%s)" % (self.attr_name, self.id)
|
||||||
|
|
||||||
"""
|
#
|
||||||
BEGIN COMMON METHODS
|
# BEGIN COMMON METHODS
|
||||||
"""
|
#
|
||||||
def get_name(self):
|
def get_name(self):
|
||||||
"""
|
"""
|
||||||
Returns an attribute's name.
|
Returns an attribute's name.
|
||||||
|
|
@ -74,7 +74,8 @@ class Attribute(models.Model):
|
||||||
"""
|
"""
|
||||||
Returns True if the attribute is hidden.
|
Returns True if the attribute is hidden.
|
||||||
"""
|
"""
|
||||||
if self.attr_hidden or self.get_name().upper() in defines_global.HIDDEN_ATTRIBS:
|
if self.attr_hidden or self.get_name().upper() \
|
||||||
|
in defines_global.HIDDEN_ATTRIBS:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
@ -83,7 +84,8 @@ class Attribute(models.Model):
|
||||||
"""
|
"""
|
||||||
Returns True if the attribute is unsettable.
|
Returns True if the attribute is unsettable.
|
||||||
"""
|
"""
|
||||||
if self.get_name().upper() in defines_global.NOSET_ATTRIBS: return True
|
if self.get_name().upper() in defines_global.NOSET_ATTRIBS:
|
||||||
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
@ -103,21 +105,28 @@ class Object(models.Model):
|
||||||
ROOM, or other entities within the database. Pretty much anything in the
|
ROOM, or other entities within the database. Pretty much anything in the
|
||||||
game is an object. Objects may be one of several different types, and
|
game is an object. Objects may be one of several different types, and
|
||||||
may be parented to allow for differing behaviors.
|
may be parented to allow for differing behaviors.
|
||||||
|
|
||||||
We eventually want to find some way to implement object parents via loadable
|
|
||||||
modules or sub-classing.
|
|
||||||
"""
|
"""
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
ansi_name = models.CharField(max_length=255)
|
ansi_name = models.CharField(max_length=255)
|
||||||
owner = models.ForeignKey('self', related_name="obj_owner", blank=True, null=True)
|
owner = models.ForeignKey('self',
|
||||||
zone = models.ForeignKey('self', related_name="obj_zone", blank=True, null=True)
|
related_name="obj_owner",
|
||||||
script_parent = models.CharField(max_length=255, blank=True, null=True)
|
blank=True, null=True)
|
||||||
home = models.ForeignKey('self', related_name="obj_home", blank=True, null=True)
|
zone = models.ForeignKey('self',
|
||||||
|
related_name="obj_zone",
|
||||||
|
blank=True, null=True)
|
||||||
|
script_parent = models.CharField(max_length=255,
|
||||||
|
blank=True, null=True)
|
||||||
|
home = models.ForeignKey('self',
|
||||||
|
related_name="obj_home",
|
||||||
|
blank=True, null=True)
|
||||||
type = models.SmallIntegerField(choices=defines_global.OBJECT_TYPES)
|
type = models.SmallIntegerField(choices=defines_global.OBJECT_TYPES)
|
||||||
location = models.ForeignKey('self', related_name="obj_location", blank=True, null=True)
|
location = models.ForeignKey('self',
|
||||||
|
related_name="obj_location",
|
||||||
|
blank=True, null=True)
|
||||||
flags = models.TextField(blank=True, null=True)
|
flags = models.TextField(blank=True, null=True)
|
||||||
nosave_flags = models.TextField(blank=True, null=True)
|
nosave_flags = models.TextField(blank=True, null=True)
|
||||||
date_created = models.DateField(editable=False, auto_now_add=True)
|
date_created = models.DateField(editable=False,
|
||||||
|
auto_now_add=True)
|
||||||
|
|
||||||
# 'scriptlink' is a 'get' property for retrieving a reference to the correct
|
# 'scriptlink' is a 'get' property for retrieving a reference to the correct
|
||||||
# script object. Defined down by get_scriptlink()
|
# script object. Defined down by get_scriptlink()
|
||||||
|
|
@ -125,10 +134,15 @@ class Object(models.Model):
|
||||||
|
|
||||||
objects = ObjectManager()
|
objects = ObjectManager()
|
||||||
|
|
||||||
#state system can set a particular command table to be used (not persistent).
|
# state system can set a particular command
|
||||||
|
# table to be used (not persistent).
|
||||||
state = None
|
state = None
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
"""
|
||||||
|
Define permission types on the object class and
|
||||||
|
how it is ordered in the database.
|
||||||
|
"""
|
||||||
ordering = ['-date_created', 'id']
|
ordering = ['-date_created', 'id']
|
||||||
permissions = settings.PERM_OBJECTS
|
permissions = settings.PERM_OBJECTS
|
||||||
|
|
||||||
|
|
@ -147,12 +161,16 @@ class Object(models.Model):
|
||||||
"""
|
"""
|
||||||
return "#%s" % str(self.id)
|
return "#%s" % str(self.id)
|
||||||
|
|
||||||
"""
|
#
|
||||||
BEGIN COMMON METHODS
|
# BEGIN COMMON METHODS
|
||||||
"""
|
#
|
||||||
def search_for_object(self, ostring, emit_to_obj=None, search_contents=True,
|
def search_for_object(self, ostring,
|
||||||
search_location=True, dbref_only=False,
|
emit_to_obj=None,
|
||||||
limit_types=False, search_aliases=False,
|
search_contents=True,
|
||||||
|
search_location=True,
|
||||||
|
dbref_only=False,
|
||||||
|
limit_types=False,
|
||||||
|
search_aliases=False,
|
||||||
attribute_name=None):
|
attribute_name=None):
|
||||||
"""
|
"""
|
||||||
Perform a standard object search, handling multiple
|
Perform a standard object search, handling multiple
|
||||||
|
|
@ -187,13 +205,15 @@ class Object(models.Model):
|
||||||
attribute_name=attribute_name)
|
attribute_name=attribute_name)
|
||||||
|
|
||||||
if len(results) > 1:
|
if len(results) > 1:
|
||||||
s = "More than one match for '%s' (please narrow target):" % ostring
|
string = "More than one match for '%s' (please narrow target):" % ostring
|
||||||
for num, result in enumerate(results):
|
for num, result in enumerate(results):
|
||||||
invtext = ""
|
invtext = ""
|
||||||
if result.get_location() == self:
|
if result.get_location() == self:
|
||||||
invtext = " (carried)"
|
invtext = " (carried)"
|
||||||
s += "\n %i-%s%s" % (num+1, result.get_name(show_dbref=False),invtext)
|
string += "\n %i-%s%s" % (num+1,
|
||||||
emit_to_obj.emit_to(s)
|
result.get_name(show_dbref=False),
|
||||||
|
invtext)
|
||||||
|
emit_to_obj.emit_to(string)
|
||||||
return False
|
return False
|
||||||
elif len(results) == 0:
|
elif len(results) == 0:
|
||||||
emit_to_obj.emit_to("I don't see that here.")
|
emit_to_obj.emit_to("I don't see that here.")
|
||||||
|
|
@ -224,13 +244,18 @@ class Object(models.Model):
|
||||||
for session in sessions:
|
for session in sessions:
|
||||||
session.msg(parse_ansi(message))
|
session.msg(parse_ansi(message))
|
||||||
|
|
||||||
def execute_cmd(self, command_str, session=None):
|
def execute_cmd(self, command_str, session=None, ignore_state=False):
|
||||||
"""
|
"""
|
||||||
Do something as this object.
|
Do something as this object.
|
||||||
|
|
||||||
|
bypass_state - ignore the fact that a player is in a state
|
||||||
|
(means the normal command table will be used
|
||||||
|
no matter what)
|
||||||
"""
|
"""
|
||||||
# The Command object has all of the methods for parsing and preparing
|
# The Command object has all of the methods for parsing and preparing
|
||||||
# for searching and execution. Send it to the handler once populated.
|
# for searching and execution. Send it to the handler once populated.
|
||||||
cmdhandler.handle(cmdhandler.Command(self, command_str, session=session))
|
cmdhandler.handle(cmdhandler.Command(self, command_str, session=session),
|
||||||
|
ignore_state=ignore_state)
|
||||||
|
|
||||||
def emit_to_contents(self, message, exclude=None):
|
def emit_to_contents(self, message, exclude=None):
|
||||||
"""
|
"""
|
||||||
|
|
@ -384,7 +409,8 @@ class Object(models.Model):
|
||||||
|
|
||||||
# When builder_override is enabled, a builder permission means
|
# When builder_override is enabled, a builder permission means
|
||||||
# the object controls the other.
|
# the object controls the other.
|
||||||
if builder_override and not other_obj.is_player() and self.has_group('Builders'):
|
if builder_override and not other_obj.is_player() \
|
||||||
|
and self.has_group('Builders'):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# They've failed to meet any of the above conditions.
|
# They've failed to meet any of the above conditions.
|
||||||
|
|
@ -466,7 +492,8 @@ class Object(models.Model):
|
||||||
uobj.is_active = False
|
uobj.is_active = False
|
||||||
uobj.save()
|
uobj.save()
|
||||||
except:
|
except:
|
||||||
functions_general.log_errmsg('Destroying object %s but no matching player.' % (self,))
|
string = 'Destroying object %s but no matching player.' % (self,)
|
||||||
|
functions_general.log_errmsg(string)
|
||||||
|
|
||||||
# Set the object type to GOING
|
# Set the object type to GOING
|
||||||
self.type = defines_global.OTYPE_GOING
|
self.type = defines_global.OTYPE_GOING
|
||||||
|
|
@ -644,7 +671,8 @@ class Object(models.Model):
|
||||||
"""
|
"""
|
||||||
Returns a QuerySet of an object's attributes.
|
Returns a QuerySet of an object's attributes.
|
||||||
"""
|
"""
|
||||||
return [attr for attr in self.attribute_set.all() if not attr.is_hidden()]
|
return [attr for attr in self.attribute_set.all()
|
||||||
|
if not attr.is_hidden()]
|
||||||
|
|
||||||
|
|
||||||
def clear_all_attributes(self):
|
def clear_all_attributes(self):
|
||||||
|
|
@ -684,9 +712,11 @@ class Object(models.Model):
|
||||||
re.IGNORECASE)
|
re.IGNORECASE)
|
||||||
# If the regular expression search returns a match object, add to results.
|
# If the regular expression search returns a match object, add to results.
|
||||||
if exclude_noset:
|
if exclude_noset:
|
||||||
return [attr for attr in attrs if match_exp.search(attr.get_name()) and not attr.is_hidden() and not attr.is_noset()]
|
return [attr for attr in attrs if match_exp.search(attr.get_name())
|
||||||
|
and not attr.is_hidden() and not attr.is_noset()]
|
||||||
else:
|
else:
|
||||||
return [attr for attr in attrs if match_exp.search(attr.get_name()) and not attr.is_hidden()]
|
return [attr for attr in attrs if match_exp.search(attr.get_name())
|
||||||
|
and not attr.is_hidden()]
|
||||||
|
|
||||||
|
|
||||||
def has_flag(self, flag):
|
def has_flag(self, flag):
|
||||||
|
|
@ -751,6 +781,9 @@ class Object(models.Model):
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
def unset_flag(self, flag):
|
def unset_flag(self, flag):
|
||||||
|
"""
|
||||||
|
Clear the flag.
|
||||||
|
"""
|
||||||
self.set_flag(flag, value=False)
|
self.set_flag(flag, value=False)
|
||||||
|
|
||||||
def get_flags(self):
|
def get_flags(self):
|
||||||
|
|
@ -815,7 +848,8 @@ class Object(models.Model):
|
||||||
try:
|
try:
|
||||||
return self.location
|
return self.location
|
||||||
except:
|
except:
|
||||||
functions_general.log_errmsg("Object '%s(#%d)' has invalid location: #%s" % (self.name,self.id,self.location_id))
|
functions_general.log_errmsg("Object '%s(#%d)' has invalid location: #%s" % \
|
||||||
|
(self.name,self.id,self.location_id))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_scriptlink(self):
|
def get_scriptlink(self):
|
||||||
|
|
@ -857,7 +891,8 @@ class Object(models.Model):
|
||||||
script_parent: (string) String pythonic import path of the script parent
|
script_parent: (string) String pythonic import path of the script parent
|
||||||
assuming the python path is game/gamesrc/parents.
|
assuming the python path is game/gamesrc/parents.
|
||||||
"""
|
"""
|
||||||
if script_parent != None and scripthandler.scriptlink(self, str(script_parent).strip()):
|
if script_parent != None and scripthandler.scriptlink(self,
|
||||||
|
str(script_parent).strip()):
|
||||||
#assigning a custom parent
|
#assigning a custom parent
|
||||||
self.script_parent = str(script_parent).strip()
|
self.script_parent = str(script_parent).strip()
|
||||||
self.save()
|
self.save()
|
||||||
|
|
@ -1047,6 +1082,9 @@ class Object(models.Model):
|
||||||
#state access functions
|
#state access functions
|
||||||
|
|
||||||
def get_state(self):
|
def get_state(self):
|
||||||
|
"""
|
||||||
|
Returns the player's current state.
|
||||||
|
"""
|
||||||
return self.state
|
return self.state
|
||||||
|
|
||||||
def set_state(self, state_name=None):
|
def set_state(self, state_name=None):
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import time
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from src.config.models import ConfigValue
|
from src.config.models import ConfigValue
|
||||||
from src import logger
|
from src import logger
|
||||||
from src.util import functions_general
|
|
||||||
|
|
||||||
# Our list of connected sessions.
|
# Our list of connected sessions.
|
||||||
session_list = []
|
session_list = []
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,43 @@
|
||||||
"""
|
"""
|
||||||
The state system allows the player to enter states/modes where only a special set of commands
|
State table
|
||||||
are available. This can be used for all sorts of useful things:
|
|
||||||
- in-game menus (picking an option from a list, much more powerful than using 'rooms')
|
|
||||||
- inline text editors (entering text into a buffer)
|
|
||||||
- npc conversation (select replies)
|
|
||||||
- only allowing certain commands in special situations (e.g. special attack commands
|
|
||||||
when in 'combat' mode)
|
|
||||||
- adding special commands to the normal set (e.g. a 'howl' command when in 'werewolf' state)
|
|
||||||
- deactivating certain commands (e.g. removing the 'say' command in said 'werewolf' state ...)
|
|
||||||
|
|
||||||
Basically the GLOBAL_STATE_TABLE contains a dict with command tables keyed after the
|
The state system allows the player to enter states/modes where only a
|
||||||
name of the state. To use, a function must set the 'state' variable on a player object
|
special set of commands are available. This can be used for all sorts
|
||||||
using the obj.set_state() function. The GLOBAL_STATE_TABLE will then be searched by the
|
of useful things: - in-game menus (picking an option from a list, much
|
||||||
command handler and if the state is defined its command table is used instead
|
more powerful than using 'rooms') - inline text editors (entering text
|
||||||
|
into a buffer) - npc conversation (select replies) - only allowing
|
||||||
|
certain commands in special situations (e.g. special attack commands
|
||||||
|
when in 'combat' mode) - adding special commands to the normal set
|
||||||
|
(e.g. a 'howl' command when in 'werewolf' state) - deactivating
|
||||||
|
certain commands (e.g. removing the 'say' command in said 'werewolf'
|
||||||
|
state ...)
|
||||||
|
|
||||||
|
Basically the GLOBAL_STATE_TABLE contains a dict with command tables
|
||||||
|
keyed after the name of the state. To use, a function must set the
|
||||||
|
'state' variable on a player object using the obj.set_state()
|
||||||
|
function. The GLOBAL_STATE_TABLE will then be searched by the command
|
||||||
|
handler and if the state is defined its command table is used instead
|
||||||
of the normal global command table.
|
of the normal global command table.
|
||||||
|
|
||||||
The state system is pluggable, in the same way that commands are added to the global command
|
The state system is pluggable, in the same way that commands are added
|
||||||
table, commands are added to the GLOBAL_STATE_TABLE using add_command supplying in
|
to the global command table, commands are added to the
|
||||||
addition the name of the state. The main difference is that new states must first be created
|
GLOBAL_STATE_TABLE using add_command supplying in addition the name of
|
||||||
using the GLOBAL_STATE_TABLE.add_state() command. See examples in game/gamesrc.
|
the state. The main difference is that new states must first be
|
||||||
|
created using the GLOBAL_STATE_TABLE.add_state() command. See examples
|
||||||
|
in game/gamesrc.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from cmdtable import CommandTable, GLOBAL_CMD_TABLE
|
from cmdtable import CommandTable, GLOBAL_CMD_TABLE
|
||||||
from logger import log_errmsg
|
from logger import log_errmsg
|
||||||
import src.helpsys.management.commands.edit_helpfiles as edit_help
|
from src import defines_global
|
||||||
|
from src.helpsys import helpsystem
|
||||||
|
from src.helpsys.models import HelpEntry
|
||||||
|
|
||||||
class StateTable(object):
|
class StateTable(object):
|
||||||
|
"""
|
||||||
|
This implements a variant of the command table handling states.
|
||||||
|
"""
|
||||||
state_table = None
|
state_table = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
@ -35,9 +46,9 @@ class StateTable(object):
|
||||||
self.state_flags = {}
|
self.state_flags = {}
|
||||||
|
|
||||||
def add_state(self, state_name,
|
def add_state(self, state_name,
|
||||||
global_cmds=None, global_filter=[],
|
global_cmds=None, global_filter=None,
|
||||||
allow_exits=False, allow_obj_cmds=False,
|
allow_exits=False, allow_obj_cmds=False,
|
||||||
exit_command=False):
|
help_command=True, exit_command=False):
|
||||||
"""
|
"""
|
||||||
Creates a new game state. Each state has its own unique set of commands and
|
Creates a new game state. Each state has its own unique set of commands and
|
||||||
can change how the game works.
|
can change how the game works.
|
||||||
|
|
@ -76,50 +87,57 @@ class StateTable(object):
|
||||||
special conditions or clean-up operations before allowing a player
|
special conditions or clean-up operations before allowing a player
|
||||||
to exit (e.g. combat states and text editors), in which case this
|
to exit (e.g. combat states and text editors), in which case this
|
||||||
feature should be turned off and handled by custom exit commands.
|
feature should be turned off and handled by custom exit commands.
|
||||||
|
help_command
|
||||||
"""
|
"""
|
||||||
|
|
||||||
state_name = state_name.strip()
|
state_name = state_name.strip()
|
||||||
#create state
|
#create state
|
||||||
self.state_table[state_name] = CommandTable()
|
self.state_table[state_name] = CommandTable()
|
||||||
|
|
||||||
if global_cmds != None:
|
#store special state flags
|
||||||
|
self.state_flags[state_name] = {}
|
||||||
|
self.state_flags[state_name]['globals'] = global_cmds
|
||||||
|
self.state_flags[state_name]['exits'] = allow_exits
|
||||||
|
self.state_flags[state_name]['obj_cmds'] = allow_obj_cmds
|
||||||
|
|
||||||
if global_cmds == 'all':
|
if global_cmds == 'all':
|
||||||
f = lambda c: True
|
# we include all global commands
|
||||||
|
func = lambda c: True
|
||||||
elif global_cmds == 'include':
|
elif global_cmds == 'include':
|
||||||
f = lambda c: c in global_filter
|
# selective global inclusion
|
||||||
|
func = lambda c: c in global_filter
|
||||||
if not 'help' in global_filter:
|
if not 'help' in global_filter:
|
||||||
global_filter.append('help')
|
global_filter.append('help')
|
||||||
elif global_cmds == 'exclude':
|
elif global_cmds == 'exclude':
|
||||||
f = lambda c: c not in global_filter
|
# selective global exclusion
|
||||||
|
func = lambda c: c not in global_filter
|
||||||
else:
|
else:
|
||||||
log_errmsg("ERROR: in statetable, state %s: Unknown global_cmds flag '%s'." %
|
# no global commands
|
||||||
(state_name, global_cmds))
|
func = lambda c: False
|
||||||
return
|
|
||||||
for cmd in filter(f,GLOBAL_CMD_TABLE.ctable.keys()):
|
# add copies of the global command defs to the state's command table.
|
||||||
|
for cmd in filter(func, GLOBAL_CMD_TABLE.ctable.keys()):
|
||||||
self.state_table[state_name].ctable[cmd] = \
|
self.state_table[state_name].ctable[cmd] = \
|
||||||
GLOBAL_CMD_TABLE.get_command_tuple(cmd)
|
GLOBAL_CMD_TABLE.get_command_tuple(cmd)
|
||||||
if exit_command:
|
|
||||||
#if we import global commands, we use the normal help index; thus add
|
# create a stand-alone state-based help index
|
||||||
#help for @exit to the global index.
|
|
||||||
self.state_table[state_name].add_command("@exit",
|
|
||||||
cmd_state_exit,
|
|
||||||
auto_help=True)
|
|
||||||
else:
|
|
||||||
#when no global cmds are imported, we create a small custom
|
|
||||||
#state-based help index instead
|
|
||||||
self.help_index.add_state(state_name)
|
self.help_index.add_state(state_name)
|
||||||
|
|
||||||
|
# if the auto-help command is not wanted, just make a custom command
|
||||||
|
# overwriting this default 'help' command. Keeps 'info' as a way to have
|
||||||
|
# both a custom help command and state auto-help; replace this too
|
||||||
|
# to completely hide auto-help functionality in the state.
|
||||||
self.add_command(state_name, 'help', cmd_state_help)
|
self.add_command(state_name, 'help', cmd_state_help)
|
||||||
|
self.add_command(state_name, 'info', cmd_state_help)
|
||||||
|
|
||||||
if exit_command:
|
if exit_command:
|
||||||
#add the @exit command
|
#add the @exit command
|
||||||
self.state_table[state_name].add_command("@exit",
|
self.state_table[state_name].add_command("@exit",
|
||||||
cmd_state_exit)
|
cmd_state_exit)
|
||||||
self.help_index.add_state_help(state_name, "@exit",
|
self.help_index.add_state_help(state_name,
|
||||||
|
"@exit",
|
||||||
|
"General",
|
||||||
cmd_state_exit.__doc__)
|
cmd_state_exit.__doc__)
|
||||||
#store special state flags
|
|
||||||
self.state_flags[state_name] = {}
|
|
||||||
self.state_flags[state_name]['exits'] = allow_exits
|
|
||||||
self.state_flags[state_name]['obj_cmds'] = allow_obj_cmds
|
|
||||||
|
|
||||||
def del_state(self, state_name):
|
def del_state(self, state_name):
|
||||||
"""
|
"""
|
||||||
|
|
@ -147,12 +165,12 @@ class StateTable(object):
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
del self.state_table[state_name].ctable[command_string]
|
del self.state_table[state_name].ctable[command_string]
|
||||||
err = self.help_index.del_state_help(state_name,command_string)
|
self.help_index.del_state_help(state_name, command_string)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def add_command(self, state_name, command_string, function, priv_tuple=None,
|
def add_command(self, state_name, command_string, function, priv_tuple=None,
|
||||||
extra_vals=None, auto_help=False, staff_help=False):
|
extra_vals=None, help_category="", priv_help_tuple=None):
|
||||||
"""
|
"""
|
||||||
Transparently add commands to a specific state.
|
Transparently add commands to a specific state.
|
||||||
This command is similar to the normal
|
This command is similar to the normal
|
||||||
|
|
@ -163,12 +181,12 @@ class StateTable(object):
|
||||||
function: (reference) command function object
|
function: (reference) command function object
|
||||||
priv_tuple: (tuple) String tuple of permissions required for command.
|
priv_tuple: (tuple) String tuple of permissions required for command.
|
||||||
extra_vals: (dict) Dictionary to add to the Command object.
|
extra_vals: (dict) Dictionary to add to the Command object.
|
||||||
auto_help: (bool) Activate the auto_help system. By default this stores the
|
|
||||||
help inside the statetable only (not in the main help database), and so
|
Auto-help functionality: (only used if settings.HELP_AUTO_ENABLED=True)
|
||||||
the help entries are only available when the player is actually inside
|
help_category (str): An overall help category where auto-help will place
|
||||||
the state. Note that the auto_help system of state-commands do not
|
the help entry. If not given, 'General' is assumed.
|
||||||
support <<TOPIC:mytitle>> markup.
|
priv_help_tuple (tuple) String tuple of permissions required to view this
|
||||||
staff_help: (bool) Help entry is only available for staff players.
|
help entry. If nothing is given, priv_tuple is used.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if state_name not in self.state_table.keys():
|
if state_name not in self.state_table.keys():
|
||||||
|
|
@ -177,21 +195,30 @@ class StateTable(object):
|
||||||
return
|
return
|
||||||
|
|
||||||
state_name = state_name.strip()
|
state_name = state_name.strip()
|
||||||
#handle auto-help for the state commands
|
|
||||||
if auto_help:
|
# handle the creation of an auto-help entry in the
|
||||||
if self.help_index.has_state(state_name):
|
# stand-alone help index
|
||||||
#add the help text to state help index only, don't add
|
|
||||||
#it to the global help index
|
topicstr = command_string
|
||||||
self.help_index.add_state_help(state_name,command_string,
|
if not help_category:
|
||||||
|
help_category = state_name
|
||||||
|
help_category = help_category.capitalize()
|
||||||
|
|
||||||
|
self.help_index.add_state_help(state_name,
|
||||||
|
topicstr,
|
||||||
|
help_category,
|
||||||
function.__doc__,
|
function.__doc__,
|
||||||
staff_help=staff_help)
|
priv_help_tuple)
|
||||||
auto_help = False
|
|
||||||
|
|
||||||
# finally add the new command to the state's command table
|
# finally add the new command to the state's command table
|
||||||
|
|
||||||
self.state_table[state_name].add_command(command_string,
|
self.state_table[state_name].add_command(command_string,
|
||||||
function, priv_tuple,
|
function,
|
||||||
extra_vals,auto_help=auto_help,
|
priv_tuple,
|
||||||
staff_help=staff_help)
|
extra_vals,
|
||||||
|
help_category,
|
||||||
|
priv_help_tuple,
|
||||||
|
auto_help_override=False)
|
||||||
|
|
||||||
def get_cmd_table(self, state_name):
|
def get_cmd_table(self, state_name):
|
||||||
"""
|
"""
|
||||||
|
|
@ -202,150 +229,157 @@ class StateTable(object):
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_state_flags(self, state_name):
|
def get_exec_rights(self, state_name):
|
||||||
"""
|
"""
|
||||||
Return the state flags for a particular state.
|
Used by the cmdhandler. Accesses the relevant state flags
|
||||||
|
concerned with execution access for a particular state.
|
||||||
"""
|
"""
|
||||||
if self.state_flags.has_key(state_name):
|
if self.state_flags.has_key(state_name):
|
||||||
return self.state_flags[state_name]['exits'], \
|
return self.state_flags[state_name]['exits'], \
|
||||||
self.state_flags[state_name]['obj_cmds']
|
self.state_flags[state_name]['obj_cmds']
|
||||||
else:
|
else:
|
||||||
return False, False
|
return False, False, False
|
||||||
|
|
||||||
|
|
||||||
class StateHelpIndex(object):
|
class StateHelpIndex(object):
|
||||||
"""
|
"""
|
||||||
Handles the dynamic state help system.
|
Handles the dynamic state help system. This is
|
||||||
|
a non-db based help system intended for the special
|
||||||
|
commands associated with a state.
|
||||||
|
|
||||||
|
The system gives preference to help matches within
|
||||||
|
the state, but defers to the normal, global help
|
||||||
|
system when it fails to find a help entry match.
|
||||||
"""
|
"""
|
||||||
help_index = None
|
help_index = None
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.help_index = {}
|
self.help_index = {}
|
||||||
self.identifier = '<<TOPIC:'
|
|
||||||
|
|
||||||
def add_state(self, state_name):
|
def add_state(self, state_name):
|
||||||
"Create a new state"
|
"Create a new state"
|
||||||
self.help_index[state_name] = {}
|
self.help_index[state_name] = {}
|
||||||
|
|
||||||
def has_state(self, state_name):
|
def has_state(self, state_name):
|
||||||
|
"Checks if we have this state"
|
||||||
return self.help_index.has_key(state_name)
|
return self.help_index.has_key(state_name)
|
||||||
|
|
||||||
def add_state_help(self, state,command,text,staff_help=False):
|
def add_state_help(self, state, topicstr, help_category,
|
||||||
"""Store help for a command under a certain state.
|
help_text, priv_help_tuple=()):
|
||||||
Supports <<TOPIC:MyTopic>> and <<TOPIC:STAFF:MyTopic>> markup."""
|
"""
|
||||||
if self.help_index.has_key(state):
|
Store help for a command under a certain state.
|
||||||
|
Supports [[Title, category, (priv_tuple)]] markup
|
||||||
|
"""
|
||||||
|
|
||||||
text = text.rstrip()
|
if not self.help_index.has_key(state):
|
||||||
if self.identifier in text:
|
return
|
||||||
topic_dict, staff_dict = edit_help.handle_help_markup(command, text, staff_help,
|
# produce nicely formatted help entries, taking markup
|
||||||
identifier=self.identifier)
|
# into account.
|
||||||
for topic, text in topic_dict.items():
|
topics = helpsystem.edithelp.format_help_entry(topicstr,
|
||||||
entry = edit_help.format_footer(topic,text,topic_dict,staff_dict)
|
help_category,
|
||||||
if entry:
|
help_text,
|
||||||
self.help_index[state][topic] = (staff_help, entry)
|
priv_help_tuple)
|
||||||
else:
|
# store in state's dict-based database
|
||||||
self.help_index[state][command] = (staff_help, text)
|
for topic in topics:
|
||||||
|
self.help_index[state][topic[0]] = topic
|
||||||
def del_state_help(self, state, topic):
|
|
||||||
"""Manually delete a help topic from state help system. Note that this is
|
|
||||||
only going to last until the next @reload unless you also turn off auto_help
|
|
||||||
for the relevant topic."""
|
|
||||||
if self.help_index.has_key(state) and self.help_index[state].has_key(topic):
|
|
||||||
del self.help_index[state][topic]
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_state_help(self, caller, state, command):
|
def get_state_help(self, caller, state, command):
|
||||||
"get help for a particular command within a state"
|
"""
|
||||||
if self.help_index.has_key(state) and self.help_index[state].has_key(command):
|
Get help for a particular command within a state.
|
||||||
|
"""
|
||||||
|
if self.help_index.has_key(state) and \
|
||||||
|
self.help_index[state].has_key(command):
|
||||||
|
# this is a state help entry.
|
||||||
help_tuple = self.help_index[state][command]
|
help_tuple = self.help_index[state][command]
|
||||||
if caller.is_staff() or not help_tuple[0]:
|
# check permissions
|
||||||
return help_tuple[1]
|
if help_tuple and help_tuple[2]:
|
||||||
|
if help_tuple[3] and not caller.has_perm_list(help_tuple[3]):
|
||||||
return None
|
return None
|
||||||
|
return help_tuple[2]
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_state_index(self,caller, state):
|
|
||||||
|
def get_state_index(self, state):
|
||||||
"list all help topics for a state"
|
"list all help topics for a state"
|
||||||
if self.help_index.has_key(state):
|
if self.help_index.has_key(state):
|
||||||
if caller.is_staff():
|
tuples = self.help_index[state].items()
|
||||||
index = self.help_index[state].keys()
|
items = [tup[0] for tup in tuples]
|
||||||
else:
|
table = helpsystem.viewhelp.make_table(items, 6)
|
||||||
index = []
|
return table
|
||||||
for key, tup in self.help_index[state].items():
|
|
||||||
if not tup[0]:
|
|
||||||
index.append(key)
|
|
||||||
return sorted(index)
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
#default commands available for all special states
|
# default commands available for all special states. These
|
||||||
|
# are added to states during the state initialization if
|
||||||
|
# the proper flags are set.
|
||||||
|
|
||||||
def cmd_state_exit(command):
|
def cmd_state_exit(command):
|
||||||
"""@exit (when in a state)
|
"""
|
||||||
|
@exit - exit from a state
|
||||||
|
|
||||||
This command only works when inside certain special game 'states' (like a menu or
|
Usage:
|
||||||
editor or similar situations).
|
@exit
|
||||||
|
|
||||||
It aborts what you were doing and force-exits back to the normal mode of
|
This command only works when inside certain special game 'states'
|
||||||
gameplay. Some states might deactivate the @exit command for various reasons."""
|
(like a menu or editor or similar situations).
|
||||||
|
|
||||||
|
It aborts what you were doing and force-exits back to the normal
|
||||||
|
mode of gameplay. Some states might deactivate the @exit command
|
||||||
|
for various reasons.
|
||||||
|
"""
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
source_object.clear_state()
|
source_object.clear_state()
|
||||||
source_object.emit_to("... Exited.")
|
source_object.emit_to("... Exited.")
|
||||||
source_object.execute_cmd('look')
|
source_object.execute_cmd('look')
|
||||||
|
|
||||||
|
|
||||||
|
## In-state help system. This is NOT tied to the normal help
|
||||||
|
## system and is not stored in the database. It is intended as a quick
|
||||||
|
## reference for users when in the state; if you want a detailed description
|
||||||
|
## of the state itself, you should probably add it to the main help system
|
||||||
|
## so the user can read it at any time.
|
||||||
|
## If you don't want to use the auto-system, turn off auto_help
|
||||||
|
## for all commands in the state. You could then for example make a custom help command
|
||||||
|
## that displays just a short help summary page instead.
|
||||||
|
|
||||||
|
## Note that at this time we are not displaying categories in the state help system;
|
||||||
|
## (although they are stored). Instead the state itself is treated as a
|
||||||
|
## category in itself.
|
||||||
|
|
||||||
def cmd_state_help(command):
|
def cmd_state_help(command):
|
||||||
"""
|
"""
|
||||||
help <topic> (while in a special state)
|
help - view help database
|
||||||
|
|
||||||
In-state help system. This is NOT tied to the normal help
|
Usage:
|
||||||
system and is not stored in the database. It is intended as a quick
|
help <topic>
|
||||||
reference for users when in the state; if you want a detailed description
|
|
||||||
of the state itself, you should probably add it to the main help system
|
Shows the available help on <topic>. Use without a topic
|
||||||
so the user can read it at any time.
|
to get the index.
|
||||||
If you don't want to use the auto-system, turn off auto_help
|
|
||||||
for all commands in the state. You could then for example make a custom help command
|
|
||||||
that displays just a short help summary page instead.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
source_object = command.source_object
|
source_object = command.source_object
|
||||||
state = source_object.get_state()
|
|
||||||
args = command.command_argument
|
args = command.command_argument
|
||||||
switches = command.command_switches
|
switches = command.command_switches
|
||||||
|
|
||||||
help_index = GLOBAL_STATE_TABLE.help_index
|
help_index = GLOBAL_STATE_TABLE.help_index
|
||||||
|
state = source_object.get_state()
|
||||||
|
|
||||||
if not args:
|
if not args:
|
||||||
index = help_index.get_state_index(source_object, state)
|
# first show the normal help index
|
||||||
if not index:
|
source_object.execute_cmd("help", ignore_state=True)
|
||||||
source_object.emit_to("There is no help available here.")
|
|
||||||
return
|
|
||||||
s = "Help topics for %s:\n\r" % state
|
|
||||||
for i in index:
|
|
||||||
s += " %s\n\r" % i
|
|
||||||
s = s[:-2]
|
|
||||||
source_object.emit_to(s)
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
args = args.strip()
|
|
||||||
|
|
||||||
if 'del' in switches:
|
text = help_index.get_state_index(state)
|
||||||
if not source_object.is_staff():
|
if text:
|
||||||
source_object.emit_to("Only staff can delete help topics.")
|
# Try to list the state-specific help entries after the main list
|
||||||
return
|
string = "\n%s%s%s\n\r\n\r%s" % ("---", " Help topics for %s: " % \
|
||||||
if help_index.del_state_help(state,args):
|
state.capitalize(), "-"*(30-len(state)), text)
|
||||||
source_object.emit_to("Topic %s deleted." % args)
|
source_object.emit_to(string)
|
||||||
else:
|
|
||||||
source_object.emit_to("Topic %s not found." % args)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
help = help_index.get_state_help(source_object, state, args)
|
# try to first find a matching state help topic, then defer to global help
|
||||||
if help:
|
topicstr = args.strip()
|
||||||
source_object.emit_to("%s" % help)
|
helptext = help_index.get_state_help(source_object, state, topicstr)
|
||||||
|
if helptext:
|
||||||
|
source_object.emit_to("\n%s" % helptext)
|
||||||
else:
|
else:
|
||||||
source_object.emit_to("No help available on %s." % args)
|
source_object.execute_cmd("help %s" % topicstr, ignore_state=True)
|
||||||
|
|
||||||
#import this into modules
|
#import this instance into your modules
|
||||||
GLOBAL_STATE_TABLE = StateTable()
|
GLOBAL_STATE_TABLE = StateTable()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue