Added the apropos command for broader help searching (uses icontains).

The suggestions: footer used in help gave too narrow results, now using apropos-style search instead.
Bug fix of state-help command to make it accept switches.
Added several new example commands and cleaned up old ones to be more user-friendly.
Added protection in @delevent to make it harder to delete system events.
Some small bug fixes and other cleanup.
This commit is contained in:
Griatch 2009-12-20 12:39:08 +00:00
parent c7cbc4854e
commit 81bec61d7d
12 changed files with 295 additions and 138 deletions

View file

@ -30,10 +30,10 @@ def cmd_example(command):
example - example command example - example command
Usage: Usage:
example[/switches] <text> @testcommand[/switches] <text>
switches: switches:
use any string (can be any string, e.g. /test1 or /tom/sarah/peter)
This is the help text for the 'example' command, a command to This is the help text for the 'example' command, a command to
show how the pluggable command system works. show how the pluggable command system works.
@ -70,17 +70,34 @@ def cmd_example(command):
# A list of switches provided (if any) # A list of switches provided (if any)
retval += " Switches: %s\n\r" % command.command_switches retval += " Switches: %s\n\r" % command.command_switches
# A string with any arguments provided with the command # A string with any arguments provided with the command
retval += " Arguments: %s\n\r" % command.command_argument retval += " Arguments: %s\n\r" % command.command_argument
# The function that was looked up via cmdtable.py # The function that was looked up via cmdtable.py
retval += " Function: %s\n\r" % command.command_function retval += " Function: %s\n\r" % command.command_function
# Extra variables passed with cmdtable.py's add_command(). # Extra variables passed with cmdtable.py's add_command().
retval += " Extra vars: %s\n\r" % command.extra_vars retval += " Extra vars: %s\n\r" % command.extra_vars
# Some more info for more advanced commands.
if not command.command_switches and \
command.command_argument:
retval += "\n Obs: When no switches, also multi-word\n"
retval += " command names are possible. Max allowed\n"
retval += " length is set in game/settings.py.\n"
retval += " So if there exist a matching command in the\n"
retval += " command table, Evennia would also allow\n"
retval += " the following as valid commands (and the\n"
retval += " argument list would shrink accordingly):\n"
multi = ""
for arg in command.command_argument.split():
multi += " %s" % arg
retval += " %s%s\n" % (command.command_string, multi)
# send string to player
command.source_object.emit_to(retval) command.source_object.emit_to(retval)
# Add the command to the common global command table. Note that # Add the command to the common global command table. Note that
# this will auto-create help entries 'example' and # this will auto-create help entries 'example' and
# "example_auto_help" for us. # "example_auto_help" for us.
GLOBAL_CMD_TABLE.add_command("example", cmd_example) GLOBAL_CMD_TABLE.add_command("@testcommand", cmd_example)
# #
# another simple example # another simple example

View file

@ -0,0 +1,135 @@
"""
This module contains various commands for testing some
of Evennia's subsystems. They were used for initial testing
but are also instructive for playing around with to learn
how different systems work. See also state_example.py.
To make these commands available in-game, add this module
to the CUSTOM_COMMAND_MODULES tuple in game/settings.py
as 'game.gamesrc.commands.examples.misc_tests'.
None of these commands are auto-added to the help database
(they have no docstrings) in order to help make it clean.
"""
from src.cmdtable import GLOBAL_CMD_TABLE
#------------------------------------------------------------
# Tests of the event system
#------------------------------------------------------------
def cmd_testevent(command):
#
# This test allows testing the event system
#
# Usage:
# @testevent [pid]
#
# Without argument, this command creates
# a dummy event in the process table.
# Use @ps to see it. Give the equivalent
# pid to remove it again (careful though,
# this command can also remove useful
# events if you give the wrong pid).
#
from src import events
from src import scheduler
source_object = command.source_object
if not source_object.is_superuser():
# To avoid accidental access to process table
source_object.emit_to("This command is superuser only.")
return
if not command.command_argument:
# No argument given; create a new test event.
event = events.IntervalEvent()
event.description = "Test event created with @testevent."
event.repeats = 3
event.interval = 5
pid = scheduler.add_event(event)
string = "Event with pid %s added. " % pid
string += "It repeats %i times and waits " % event.repeats
string += "for %i seconds between each repeat." % event.interval
string += "After all repeats, it will delete itself."
string += "\nUse @ps to see it and give this "
string += "command with the pid as argument to delete it."
source_object.emit_to(string)
else:
# An argument given; assume this is a pid.
try:
pid = int(command.command_argument)
except:
source_object.emit_to("Not a valid argument. You must give a number.")
return
if pid < 3:
string = "This low pid might belong to a system process, \n"
string += "so as a safety measure you cannot delete it using \n"
string += "this test command. Use @delevent instead."
source_object.emit_to(string)
return
pid = command.command_argument
scheduler.del_event(pid)
string = "Event with pid %s removed (if it existed)." % pid
string += " Confirm this worked using @ps."
source_object.emit_to(string)
GLOBAL_CMD_TABLE.add_command("@testevent", cmd_testevent,
auto_help_override=False)
#------------------------------------------------------------
# Test of Cache system
#------------------------------------------------------------
def cmd_testcache(command):
#
# Tests the cache system by writing to it
# back and forth several times.
#
# Usage:
# @testcache [get]
#
# Use without 'get' to store test data in
# caches and with 'get' to read them back
# and make sure they all saved as they
# should. You might also want to
# try shut down the server between
# calls to make sure the persistent
# cache does survive the shutdown.
from src.cache import cache
from src import gametime
source_object = command.source_object
switches = command.command_switches
s1 = "Value: Cache: OK"
s2 = "Value: PCache 1 (set using property assignment): OK"
s3 = "Value: PCache 2 (set using function call): OK"
if switches and "get" in switches:
# Reading from cache
source_object.emit_to("Reading from cache ...")
cache.load_pcache()
cache_vol = source_object.cache.testcache
source_object.emit_to("< volatile cache:\n %s" % cache_vol)
cache_perm = source_object.pcache.testcache_perm
source_object.emit_to("< persistent cache 1/2:\n %s" % cache_perm)
cache_perm2 = cache.get_pcache("permtest2")
source_object.emit_to("< persistent cache 2/2:\n %s" % cache_perm2)
else:
# Saving to cache
source_object.emit_to("Save to cache ...")
source_object.cache.testcache = s1
# using two different ways to set pcache
source_object.pcache.testcache_perm = s2
cache.set_pcache("permtest2", s3)
source_object.emit_to("> volatile cache:\n %s" % s1)
source_object.emit_to("> persistent cache 1/2:\n %s" % s2)
source_object.emit_to("> persistent cache 2/2:\n %s" % s3)
cache.save_pcache()
string = "Caches saved. Use /get as a switch to read them back."
source_object.emit_to(string)
source_object.emit_to("Running Gametime: %i" % gametime.time())
GLOBAL_CMD_TABLE.add_command("@testcache", cmd_testcache,
auto_help_override=False)

View file

@ -15,7 +15,7 @@ files are recognized.
Next enter the mud and give the command Next enter the mud and give the command
> entermenu > @testmenu
Note that the help entries related to this little menu are not part of Note that the help entries related to this little menu are not part of
the normal help database, they are stored with the state and only the normal help database, they are stored with the state and only
@ -25,10 +25,12 @@ in action.
To further test the state system, try the command To further test the state system, try the command
> enterstate > @teststate
This takes arguments between 1-6 to set up various states with varying This takes arguments between 1-6 to set up various states with varying
access to different global commands. access to different global commands.
See also misc_tests.py for other tests.
""" """
# This is the normal command table, accessible by default # This is the normal command table, accessible by default
@ -54,7 +56,7 @@ STATENAME = 'menu'
def cmd_entermenu(command): def cmd_entermenu(command):
""" """
entermenu - enter the example menu entermenu - enter the example menu
Usage: Usage:
entermenu entermenu
@ -144,7 +146,8 @@ def print_menu(source_obj, choice=None):
source_obj.emit_to(string) source_obj.emit_to(string)
# Add the 'entry' command to the normal command table # Add the 'entry' command to the normal command table
GLOBAL_CMD_TABLE.add_command("entermenu", cmd_entermenu) GLOBAL_CMD_TABLE.add_command("@testmenu", cmd_entermenu,
auto_help_override=False)
# create the state. We make sure the player can exit it at # create the state. We make sure the player can exit it at
# any time by @exit. # any time by @exit.
@ -182,11 +185,11 @@ TSTATE6 = 'noglobal_allow_exits_obj_cmds'
# #
def cmd_test_state(command): def cmd_test_state(command):
""" """
enterstate - testing the state system @teststate - testing the state system
Usage: enterstate [1 - 6] Usage: @teststate [1 - 6]
Give arguments 1..6 to enter different game states. Use @exit to Give arguments 1-6 to enter different game states. Use @exit to
get out of the state at any time. get out of the state at any time.
1: A very limited state; only contains the 'test' state command. 1: A very limited state; only contains the 'test' state command.
@ -202,13 +205,13 @@ def cmd_test_state(command):
both traverse exits and use object-based cmds. both traverse exits and use object-based cmds.
Ideas for in-game use: Ideas for in-game use:
1: Try out the 'entermenu' command for an example of this state. 1: Try out the '@testmenu' command for an example of this state.
2: Could be used in order to stop someone from moving despite exits 2: Could be used in order to stop someone from moving despite exits
being open (tied up? In combat?) being open (tied up? In combat?)
3: someone incapacitated or blinded might get only limited commands 3: someone incapacitated or blinded might get only limited commands
available available
4: in e.g. a combat state, things like crafting should not be 4: in e.g. a combat state, things like crafting should not be
possible possible.
5: Pretty much default operation, just removing some global commands. 5: Pretty much default operation, just removing some global commands.
Maybe limiting the use of magical weapons in a room or similar. Maybe limiting the use of magical weapons in a room or similar.
6: A state of panic - You can move, but not take in your surroundings. 6: A state of panic - You can move, but not take in your surroundings.
@ -219,7 +222,7 @@ def cmd_test_state(command):
args = command.command_argument args = command.command_argument
# check for missing arguments # check for missing arguments
if not args: if not args:
source_object.emit_to("Usage: enterstate [1 - 6]") source_object.emit_to("Usage: @teststate [1 - 6]")
return return
# build up a return string # build up a return string
string = "\n Entering state ... \nThis state includes the" string = "\n Entering state ... \nThis state includes the"
@ -325,6 +328,6 @@ GLOBAL_STATE_TABLE.add_command(TSTATE5, 'test', cmd_instate_cmd)
GLOBAL_STATE_TABLE.add_command(TSTATE6, 'test', cmd_instate_cmd) GLOBAL_STATE_TABLE.add_command(TSTATE6, 'test', cmd_instate_cmd)
#create the entry function for testing all states #create the entry function for testing all states
GLOBAL_CMD_TABLE.add_command('enterstate', cmd_test_state) GLOBAL_CMD_TABLE.add_command('@teststate', cmd_test_state)

View file

@ -91,7 +91,6 @@ class Command(object):
# create a list with at least two entries. # create a list with at least two entries.
raw = "%s " % self.raw_input raw = "%s " % self.raw_input
cmd_words = raw.split(' ') cmd_words = raw.split(' ')
try: try:
if '/' in cmd_words[0]: if '/' in cmd_words[0]:
# if we have switches we directly go for the first command form. # if we have switches we directly go for the first command form.
@ -489,8 +488,7 @@ def handle(command, ignore_state=False):
command_table_lookup(command, state_cmd_table) command_table_lookup(command, state_cmd_table)
else: else:
# Not in a state. Normal operation. # Not in a state. Normal operation.
state = None #make sure, in case the object had a malformed statename. state = None # make sure, in case the object had a malformed statename.
# Check if the user is using a channel command. # Check if the user is using a channel command.
match_channel(command) match_channel(command)
# See if the user is trying to traverse an exit. # See if the user is trying to traverse an exit.

View file

@ -43,14 +43,13 @@ class CommandTable(object):
the help entry. If not given, 'General' is assumed. the help entry. If not given, 'General' is assumed.
priv_help_tuple (tuple) String tuple of permissions required to view this priv_help_tuple (tuple) String tuple of permissions required to view this
help entry. If nothing is given, priv_tuple is used. help entry. If nothing is given, priv_tuple is used.
auto_help_override (bool): Override the value in settings.AUTO_HELP_ENABLED with the auto_help_override (bool/None): Override the value in settings.AUTO_HELP_ENABLED with the
value given. Use None to not override. value given. Use None to not override.
This can be useful when developing a new routine and This can be useful when developing a new routine and
has made manual changes to help entries of other has made manual changes to help entries of other
commands in the database (and so do not want to use global commands in the database (and so do not want to use global
auto-help). It is also used by e.g. the state system auto-help).
to selectively deactive auto-help.
Note: the auto_help system also supports limited markup. You can divide your __doc__ Note: the auto_help system also supports limited markup. You can divide your __doc__
with markers of any combinations of the forms with markers of any combinations of the forms
[[Title]] [[Title]]

View file

@ -59,7 +59,7 @@ from src.statetable import GLOBAL_STATE_TABLE
STATENAME="_interactive batch processor" STATENAME="_interactive batch processor"
cwhite = r"%cn%ch%cw" cwhite = r"%cn%ch%cw"
cred = r"%cn%ch%cw" cred = r"%cn%ch%cr"
cgreen = r"%cn%ci%cg" cgreen = r"%cn%ci%cg"
cyellow = r"%cn%ch%cy" cyellow = r"%cn%ch%cy"
cnorm = r"%cn" cnorm = r"%cn"
@ -172,7 +172,6 @@ def cmd_batchprocess(command):
Interactive mode allows the user more control over the Interactive mode allows the user more control over the
processing of the file. processing of the file.
""" """
#global CMDSTACKS,STACKPTRS,FILENAMES
source_object = command.source_object source_object = command.source_object
@ -183,7 +182,7 @@ def cmd_batchprocess(command):
args = command.command_argument args = command.command_argument
if not args: if not args:
source_object.emit_to("Usage: @batchprocess[/interactive] <filename with full path>") source_object.emit_to("Usage: @batchprocess[/interactive] <path/to/file>")
return return
filename = args.strip() filename = args.strip()
@ -196,23 +195,19 @@ def cmd_batchprocess(command):
return return
switches = command.command_switches switches = command.command_switches
if switches and switches[0] in ['inter','interactive']: if switches and switches[0] in ['inter','interactive']:
# allow more control over how batch file is executed # Allow more control over how batch file is executed
if source_object.has_flag("ADMIN_NOSTATE"):
source_object.unset_flag("ADMIN_NOSTATE")
string = cred + "\nOBS: Flag ADMIN_NOSTATE unset in order to "
string += "run Interactive mode. Don't forget to re-set "
string += "it (if you need it) after you're done."
source_object.emit_to(string)
if not source_object.set_state(STATENAME): # Set interactive state directly
# if we failed it is likely because we have source_object.cache.state = STATENAME
# ADMIN_NOSTATE set.
source_object.unset_flag("ADMIN_NOSTATE") # Store work data in cache
if not source_object.set_state(STATENAME):
source_object.emit_to("Error in entering the interactive state.")
source_object.set_flag("ADMIN_NOSTATE")
return
else:
string = "OBS: Flag ADMIN_NOSTATE unset in order to "
string += "run Interactive mode. Don't forget to re-set "
string += "it (if you need it) after you're done."
source_object.emit_to(string)
# store work data in cache
source_object.cache.batch_cmdstack = commands source_object.cache.batch_cmdstack = commands
source_object.cache.batch_stackptr = 0 source_object.cache.batch_stackptr = 0
source_object.cache.batch_filename = filename source_object.cache.batch_filename = filename
@ -234,13 +229,8 @@ def cmd_batchprocess(command):
GLOBAL_CMD_TABLE.add_command("@batchprocess", cmd_batchprocess, GLOBAL_CMD_TABLE.add_command("@batchprocess", cmd_batchprocess,
priv_tuple=("genperms.process_control",), help_category="Building") priv_tuple=("genperms.process_control",), help_category="Building")
#interactive state commands
def printfooter(): # The Interactive batch processor state
"prints a nice footer"
#s = "%s\n== nn/bb/jj == pp/ss == ll == rr/rrr == cc/qq == (hh for help) ==" % cgreen
s = ""
return s
def show_curr(source_object,showall=False): def show_curr(source_object,showall=False):
"Show the current command." "Show the current command."
@ -264,7 +254,6 @@ def show_curr(source_object,showall=False):
cnorm) cnorm)
if showall: if showall:
s += "\n%s" % command s += "\n%s" % command
s += printfooter()
source_object.emit_to(s) source_object.emit_to(s)
def process_commands(source_object, steps=0): def process_commands(source_object, steps=0):
@ -309,7 +298,7 @@ def exit_state(source_object):
# since clear_state() is protected against exiting the interactive mode # since clear_state() is protected against exiting the interactive mode
# (to avoid accidental drop-outs by rooms clearing a player's state), # (to avoid accidental drop-outs by rooms clearing a player's state),
# we have to clear the state directly here. # we have to clear the state directly here.
source_object.state = None source_object.cache.state = None
def cmd_state_ll(command): def cmd_state_ll(command):
""" """
@ -327,7 +316,6 @@ def cmd_state_pp(command):
Process the currently shown command definition. Process the currently shown command definition.
""" """
process_commands(command.source_object) process_commands(command.source_object)
command.source_object.emit_to(printfooter())
def cmd_state_rr(command): def cmd_state_rr(command):
""" """

View file

@ -18,7 +18,7 @@ def cmd_password(command):
@password - set your password @password - set your password
Usage: Usage:
@paassword <old password> = <new password> @password <old password> = <new password>
Changes your password. Make sure to pick a safe one. Changes your password. Make sure to pick a safe one.
""" """
@ -666,12 +666,17 @@ def cmd_help(command):
help - view help database help - view help database
Usage: Usage:
help <topic> help[/switches] <topic>
Switch:
apropos - show a list of all topics loosely matching the search criterion
(you can also use the commands 'apropos' or 'suggest' for this).
Examples: help index Examples: help index
help topic help topic
help 345 help 345
help/apropos del
Shows the available help on <topic>. Use without <topic> to get the help Shows the available help on <topic>. Use without <topic> to 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
@ -680,6 +685,7 @@ def cmd_help(command):
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
@ -689,7 +695,7 @@ def cmd_help(command):
#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 in ['topic','topics']: if topicstr in ['topic','topics']:
@ -706,6 +712,21 @@ def cmd_help(command):
source_object.emit_to(text) source_object.emit_to(text)
return return
if switches and 'apropos' in switches:
# run a loose apropos match
topics = HelpEntry.objects.find_apropos(source_object, topicstr)
if topics:
if len(topics) > 50:
string = "Topics containing string '%s' (first 50):\n" % topicstr
topics = topics[:49]
else:
string = "Topics containing string '%s':\n" % topicstr
string += ", ".join(topic.get_topicname() for topic in topics)
else:
string = "No matches found for %s." % topicstr
source_object.emit_to(string)
return
# not a special help index entry. Do a search for the help entry. # not a special help index entry. Do a search for the help entry.
topics = HelpEntry.objects.find_topicmatch(source_object, topicstr) topics = HelpEntry.objects.find_topicmatch(source_object, topicstr)
@ -765,51 +786,22 @@ def cmd_help(command):
source_object.emit_to(string) source_object.emit_to(string)
GLOBAL_CMD_TABLE.add_command("help", cmd_help) GLOBAL_CMD_TABLE.add_command("help", cmd_help)
def cmd_apropos(command):
"""
apropos - show rough help matches
## def cmd_testevent(command): Usage:
## from src import events apropos <text>
## from src import scheduler or
## source_object = command.source_object suggest <text>
## if not command.command_argument: This presents a list of topics very loosely matching your
## #event = events.IntervalEvent() search text. Use this command when you are searching for
## event = events.IntervalEvent() help on a certain concept but don't know any exact
## event.repeats = 3 command names. You can also use the normal help command
## event.interval = 5 with the /apropos switch to get the same functionality.
## pid = scheduler.add_event(event) """
## source_object.emit_to("event with pid %s added." % pid) arg = command.command_argument
## else: command.source_object.execute_cmd("help/apropos %s" % arg)
## pid = command.command_argument GLOBAL_CMD_TABLE.add_command("apropos", cmd_apropos)
## scheduler.del_event(pid) GLOBAL_CMD_TABLE.add_command("suggest", cmd_apropos)
## source_object.emit_to("event with pid %s removed (if it existed)." % pid)
## GLOBAL_CMD_TABLE.add_command("testevent", cmd_testevent)
## def cmd_testcache(command):
## from src.cache import cache
## from src import scheduler
## from src import events
## from src import gametime
## source_object = command.source_object
## switches = command.command_switches
## s1 = "Temp_cache_val_OK"
## s2 = "Perm_cache_val_OK"
## s3 = "Perm_cache_val2_OK"
## if switches and "get" in switches:
## cache.load_pcache()
## cache_vol = source_object.cache.testcache
## source_object.emit_to("< volatile cache: %s" % cache_vol)
## cache_perm = source_object.pcache.testcache_perm
## source_object.emit_to("< cache_perm1: %s" % cache_perm)
## cache_perm2 = cache.get_pcache("permtest2")
## source_object.emit_to("< cache_perm2: %s" % cache_perm2)
## else:
## source_object.cache.testcache = s1
## source_object.pcache.testcache_perm = s2
## cache.set_pcache("permtest2", s3)
## source_object.emit_to("> volatile cache: %s" % s1)
## source_object.emit_to("> cache_perm1: %s" % s2)
## source_object.emit_to("> cache_perm2: %s" % s3)
## cache.save_pcache()
## source_object.emit_to("Caches saved.")
## source_object.emit_to("Time: %i" % gametime.time())
## GLOBAL_CMD_TABLE.add_command("testcache", cmd_testcache)

View file

@ -18,6 +18,7 @@ from src import cache
from src import scheduler from src import scheduler
def cmd_reload(command): def cmd_reload(command):
""" """
@reload - reload game subsystems @reload - reload game subsystems
@ -771,13 +772,18 @@ def cmd_delevent(command):
@delevent - remove events manually @delevent - remove events manually
Usage: Usage:
@delevent <pid> @delevent[/switch] <pid>
Switch:
force - by default, certain default low-pid system events are protected
from accidental deletion. This switch overrides this
protection.
Removes an event with the given pid (process ID) from the event scheduler. Removes an event with the given pid (process ID) from the event scheduler.
To see all active events and their pids, use the @ps command. To see all active events and their pids, use the @ps command.
""" """
source_object = command.source_object source_object = command.source_object
switches = command.command_switches
if not command.command_argument: if not command.command_argument:
source_object.emit_to("Usage: @delevent <pid>") source_object.emit_to("Usage: @delevent <pid>")
return return
@ -786,6 +792,19 @@ def cmd_delevent(command):
except ValueError: except ValueError:
source_object.emit_to("You must supply a valid pid number.") source_object.emit_to("You must supply a valid pid number.")
return return
if pid < 3 and "force" not in switches:
# low-pid protection
string = "Warning:\n"
string += " Pid %i is a low-pid system event. It is usually not\n" % pid
string +=" something you want to delete since crucial\n"
string += " engine functions depend on it. If you were not\n"
string += " mistaken and know what you are doing, give this\n"
string += " command again with the /force switch to override\n"
string += " this protection."
source_object.emit_to(string)
return
event = scheduler.get_event(pid) event = scheduler.get_event(pid)
if event: if event:
desc = event.description desc = event.description

View file

@ -19,37 +19,24 @@ class HelpEntryManager(models.Manager):
# check permissions # check permissions
t_query = [topic for topic in t_query if topic.can_view(pobject)] t_query = [topic for topic in t_query if topic.can_view(pobject)]
return t_query return t_query
def find_apropos(self, pobject, topicstr):
"""
Do a very loose search, returning all help entries containing
the search criterion in their titles.
"""
topics = self.filter(topicname__icontains=topicstr)
return [topic for topic in topics if topic.can_view(pobject)]
def find_topicsuggestions(self, pobject, topicstr): def find_topicsuggestions(self, pobject, topicstr):
""" """
Do a fuzzy match, preferably within the category of the Do a fuzzy match, preferably within the category of the
current topic. current topic.
""" """
basetopic = self.filter(topicname__iexact=topicstr) topics = self.find_apropos(pobject, 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)]
# we know that the topic exists, try to find similar ones within
# its category.
basetopic = basetopic[0]
category = basetopic.category
topics = []
#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. # we need to clean away the given help entry.
return [topic for topic in topics if topic.topicname.lower() != topicstr.lower()] return [topic for topic in topics
if topic.topicname.lower() != topicstr.lower()]
def find_topics_with_category(self, pobject, category): def find_topics_with_category(self, pobject, category):
""" """
@ -57,3 +44,4 @@ class HelpEntryManager(models.Manager):
""" """
t_query = self.filter(category__iexact=category) t_query = self.filter(category__iexact=category)
return [topic for topic in t_query if topic.can_view(pobject)] return [topic for topic in t_query if topic.can_view(pobject)]

View file

@ -441,6 +441,12 @@ class ObjectManager(models.Manager):
new_object.owner = None new_object.owner = None
new_object.zone = None new_object.zone = None
else: else:
if owner == None:
# if owner is None for a non-player object we are probably
# creating an object from a script. In this case we set
# the owner to be the superuser.
owner = self.get_object_from_dbref("#1")
new_object.owner = owner new_object.owner = owner
if new_object.get_owner().get_zone(): if new_object.get_owner().get_zone():
new_object.zone = new_object.get_owner().get_zone() new_object.zone = new_object.get_owner().get_zone()

View file

@ -62,7 +62,7 @@ class Attribute(models.Model):
""" """
attr_value = self.attr_value attr_value = self.attr_value
if self.attr_ispickled: if self.attr_ispickled:
attr_value = pickle.loads(str(attr_value)) attr_value = pickle.loads(str(attr_value))
return attr_value return attr_value
def set_value(self, new_value): def set_value(self, new_value):
@ -82,7 +82,7 @@ class Attribute(models.Model):
self.attr_value = new_value self.attr_value = new_value
self.attr_ispickled = ispickled self.attr_ispickled = ispickled
self.save() self.save()
def get_object(self): def get_object(self):
""" """
Returns the object that the attribute resides on. Returns the object that the attribute resides on.
@ -315,7 +315,7 @@ class Object(models.Model):
no matter what) 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, cmdhandler.handle(cmdhandler.Command(self, command_str,
session=session), session=session),
ignore_state=ignore_state) ignore_state=ignore_state)
@ -1267,14 +1267,15 @@ class Object(models.Model):
# we never enter other states if we are already in # we never enter other states if we are already in
# the interactive batch processor. # the interactive batch processor.
nostate = nostate or self.get_state() == "_interactive batch processor" nostate = nostate or \
self.get_state() == "_interactive batch processor"
if nostate: if nostate:
return False return False
# switch the state
self.cache.state = state_name self.cache.state = state_name
return True return True
def clear_state(self): def clear_state(self):
""" """
Set to no state (return to normal operation) Set to no state (return to normal operation)
@ -1284,7 +1285,7 @@ class Object(models.Model):
(batch processor clears the state directly instead) (batch processor clears the state directly instead)
""" """
if not self.state == "_interactive batch processor": if not self.state == "_interactive batch processor":
self.state = None self.cache.state = None
def purge_object(self): def purge_object(self):
"Completely clears all aspects of the object." "Completely clears all aspects of the object."

View file

@ -354,10 +354,21 @@ def cmd_state_help(command):
help - view help database help - view help database
Usage: Usage:
help <topic> help[/switches] <topic>
Switch:
apropos - show a list of all matches containing the search criterion
(you can also use the command 'apropos' for this).
Shows the available help on <topic>. Use without a topic Examples: help index
to get the index. help topic
help 345
help/apropos del
Shows the available help on <topic>. Use without <topic> to get the help
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
directly if you know it.
""" """
source_object = command.source_object source_object = command.source_object
@ -385,7 +396,7 @@ def cmd_state_help(command):
if helptext: if helptext:
source_object.emit_to("\n%s" % helptext) source_object.emit_to("\n%s" % helptext)
else: else:
source_object.execute_cmd("help %s" % topicstr, ignore_state=True) source_object.execute_cmd("%s" % command.raw_input, ignore_state=True)
#import this instance into your modules #import this instance into your modules
GLOBAL_STATE_TABLE = StateTable() GLOBAL_STATE_TABLE = StateTable()