Migrate. Made Exits work differently, by use of commands directly instead of an exithandler assigning commands on-the-fly. This solution is a lot cleaner and also solves an issue where @reload would kill typeclasses in situations where an exit was painting to an object whose typeclass was reloaded (same issue occured if the exit typeclass itself was reloaded). As part of these fixes I cleaned up the merging of cmdsets to now merge in strict priority order, as one would expect them to do. Many small bug-fixes and cleanups all over. Resolves issue 164. Resolves issue 163.
This commit is contained in:
parent
4bcd5239b5
commit
b8a13a2389
17 changed files with 323 additions and 298 deletions
|
|
@ -53,7 +53,6 @@ from traceback import format_exc
|
|||
from django.conf import settings
|
||||
from src.comms.channelhandler import CHANNELHANDLER
|
||||
from src.commands.cmdsethandler import import_cmdset
|
||||
from src.objects.exithandler import EXITHANDLER
|
||||
from src.utils import logger, utils
|
||||
|
||||
#This switches the command parser to a user-defined one.
|
||||
|
|
@ -70,7 +69,6 @@ CMD_NOMATCH = "__nomatch_command"
|
|||
CMD_MULTIMATCH = "__multimatch_command"
|
||||
CMD_NOPERM = "__noperm_command"
|
||||
CMD_CHANNEL = "__send_to_channel"
|
||||
CMD_EXIT = "__move_to_exit"
|
||||
|
||||
class NoCmdSets(Exception):
|
||||
"No cmdsets found. Critical error."
|
||||
|
|
@ -92,63 +90,45 @@ def get_and_merge_cmdsets(caller):
|
|||
caller_cmdset = caller.cmdset.current
|
||||
except AttributeError:
|
||||
caller_cmdset = None
|
||||
|
||||
# All surrounding cmdsets
|
||||
|
||||
# Create cmdset for all player's available channels
|
||||
channel_cmdset = None
|
||||
exit_cmdset = None
|
||||
local_objects_cmdsets = [None]
|
||||
|
||||
# Player object's commandsets
|
||||
try:
|
||||
player_cmdset = caller.player.cmdset.current
|
||||
except AttributeError:
|
||||
player_cmdset = None
|
||||
|
||||
if not caller_cmdset.no_channels:
|
||||
# Make cmdsets out of all valid channels
|
||||
channel_cmdset = CHANNELHANDLER.get_cmdset(caller)
|
||||
if not caller_cmdset.no_exits:
|
||||
# Make cmdsets out of all valid exits in the room
|
||||
exit_cmdset = EXITHANDLER.get_cmdset(caller)
|
||||
|
||||
# Gather cmdsets from location, objects in location or carried
|
||||
local_objects_cmdsets = [None]
|
||||
location = None
|
||||
if hasattr(caller, "location"):
|
||||
location = caller.location
|
||||
if location and not caller_cmdset.no_objs:
|
||||
# Gather all cmdsets stored on objects in the room and
|
||||
# also in the caller's inventory and the location itself
|
||||
local_objlist = location.contents + caller.contents + [location]
|
||||
local_objects_cmdsets = [obj.cmdset.current
|
||||
for obj in local_objlist
|
||||
local_objlist = location.contents_get(exclude=caller.dbobj) + caller.contents + [location]
|
||||
local_objects_cmdsets = [obj.cmdset.current for obj in local_objlist
|
||||
if obj.locks.check(caller, 'call', no_superuser_bypass=True)]
|
||||
# Merge all command sets into one
|
||||
# (the order matters, the higher-prio cmdsets are merged last)
|
||||
cmdset = caller_cmdset
|
||||
for obj_cmdset in [obj_cmdset for obj_cmdset in local_objects_cmdsets if obj_cmdset]:
|
||||
# Here only, object cmdsets are merged with duplicates=True
|
||||
# (or we would never be able to differentiate between same-prio objects)
|
||||
try:
|
||||
old_duplicate_flag = obj_cmdset.duplicates
|
||||
obj_cmdset.duplicates = True
|
||||
cmdset = obj_cmdset + cmdset
|
||||
obj_cmdset.duplicates = old_duplicate_flag
|
||||
except TypeError:
|
||||
pass
|
||||
# Exits and channels automatically has duplicates=True.
|
||||
try:
|
||||
cmdset = exit_cmdset + cmdset
|
||||
except TypeError:
|
||||
pass
|
||||
try:
|
||||
cmdset = channel_cmdset + cmdset
|
||||
except TypeError:
|
||||
pass
|
||||
# finally merge on the player cmdset. This should have a low priority
|
||||
try:
|
||||
cmdset = player_cmdset + cmdset
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
return cmdset
|
||||
# Player object's commandsets
|
||||
try:
|
||||
player_cmdset = caller.player.cmdset.current
|
||||
except AttributeError:
|
||||
player_cmdset = None
|
||||
|
||||
cmdsets = [caller_cmdset] + [player_cmdset] + [channel_cmdset] + local_objects_cmdsets
|
||||
# weed out all non-found sets
|
||||
cmdsets = [cmdset for cmdset in cmdsets if cmdset]
|
||||
# sort cmdsets after reverse priority (highest prio are merged in last)
|
||||
cmdsets = sorted(cmdsets, key=lambda x: x.priority)
|
||||
if cmdsets:
|
||||
# Merge all command sets into one, beginning with the lowest-prio one
|
||||
cmdset = cmdsets.pop(0)
|
||||
for merging_cmdset in cmdsets:
|
||||
#print "<%s(%s,%s)> onto <%s(%s,%s)>" % (merging_cmdset.key, merging_cmdset.priority, merging_cmdset.mergetype,
|
||||
# cmdset.key, cmdset.priority, cmdset.mergetype)
|
||||
cmdset = merging_cmdset + cmdset
|
||||
else:
|
||||
cmdset = None
|
||||
return cmdset
|
||||
|
||||
def match_command(cmd_candidates, cmdset, logged_caller=None):
|
||||
"""
|
||||
|
|
@ -365,17 +345,6 @@ def cmdhandler(caller, raw_string, unloggedin=False, testing=False):
|
|||
cmd_candidate.args)
|
||||
raise ExecSystemCommand(cmd, sysarg)
|
||||
|
||||
# Check if this is an Exit match.
|
||||
if hasattr(cmd, 'is_exit') and cmd.is_exit:
|
||||
# even if a user-defined syscmd is not defined, the
|
||||
# found cmd is already a system command in its own right.
|
||||
syscmd = cmdset.get(CMD_EXIT)
|
||||
if syscmd:
|
||||
# replace system command with custom version
|
||||
cmd = syscmd
|
||||
sysarg = raw_string
|
||||
raise ExecSystemCommand(cmd, sysarg)
|
||||
|
||||
# A normal command.
|
||||
|
||||
# Assign useful variables to the instance
|
||||
|
|
|
|||
|
|
@ -237,7 +237,6 @@ class CmdSet(object):
|
|||
cmds = [instantiate(cmd)]
|
||||
else:
|
||||
cmds = instantiate(cmd)
|
||||
|
||||
for cmd in cmds:
|
||||
# add all commands
|
||||
if not hasattr(cmd, 'obj'):
|
||||
|
|
@ -247,8 +246,9 @@ class CmdSet(object):
|
|||
self.commands[ic] = cmd # replace
|
||||
except ValueError:
|
||||
self.commands.append(cmd)
|
||||
# extra run to make sure to avoid doublets
|
||||
# extra run to make sure to avoid doublets
|
||||
self.commands = list(set(self.commands))
|
||||
#print "In cmdset.add(cmd):", self.key, cmd
|
||||
|
||||
def remove(self, cmd):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -136,6 +136,8 @@ class CmdSetObjAlias(MuxCommand):
|
|||
aliases = list(set(old_aliases))
|
||||
# save back to object.
|
||||
obj.aliases = aliases
|
||||
# we treat this as a re-caching (relevant for exits to re-build their exit commands with the correct aliases)
|
||||
obj.at_cache()
|
||||
caller.msg("Aliases for '%s' are now set to %s." % (obj.key, ", ".join(obj.aliases)))
|
||||
|
||||
class CmdCopy(ObjManipCommand):
|
||||
|
|
@ -175,7 +177,7 @@ class CmdCopy(ObjManipCommand):
|
|||
return
|
||||
to_obj_name = "%s_copy" % from_obj_name
|
||||
to_obj_aliases = ["%s_copy" % alias for alias in from_obj.aliases]
|
||||
copiedobj = ObjectDB.objects.copy_object(from_obj, new_name=to_obj_name,
|
||||
copiedobj = ObjectDB.objects.copy_object(from_obj, new_key=to_obj_name,
|
||||
new_aliases=to_obj_aliases)
|
||||
if copiedobj:
|
||||
string = "Identical copy of %s, named '%s' was created." % (from_obj_name, to_obj_name)
|
||||
|
|
@ -633,6 +635,8 @@ class CmdDig(ObjManipCommand):
|
|||
typeclass = "%s.%s" % (settings.BASE_TYPECLASS_PATH,
|
||||
typeclass)
|
||||
|
||||
# create room
|
||||
|
||||
lockstring = "control:id(%s) or perm(Immortal); delete:id(%s) or perm(Wizard); edit:id(%s) or perm(Wizard)"
|
||||
lockstring = lockstring % (caller.dbref, caller.dbref, caller.dbref)
|
||||
|
||||
|
|
@ -644,6 +648,9 @@ class CmdDig(ObjManipCommand):
|
|||
alias_string = " (%s)" % ", ".join(new_room.aliases)
|
||||
room_string = "Created room %s(%s)%s of type %s." % (new_room, new_room.dbref, alias_string, typeclass)
|
||||
|
||||
|
||||
# create exit to room
|
||||
|
||||
exit_to_string = ""
|
||||
exit_back_string = ""
|
||||
|
||||
|
|
@ -667,17 +674,17 @@ class CmdDig(ObjManipCommand):
|
|||
typeclass.startswith('game.')):
|
||||
typeclass = "%s.%s" % (settings.BASE_TYPECLASS_PATH,
|
||||
typeclass)
|
||||
new_to_exit = create.create_object(typeclass, to_exit["name"],
|
||||
location,
|
||||
aliases=to_exit["aliases"])
|
||||
new_to_exit.destination = new_room
|
||||
new_to_exit.locks.add(lockstring)
|
||||
new_to_exit = create.create_object(typeclass, to_exit["name"], location,
|
||||
aliases=to_exit["aliases"],
|
||||
locks=lockstring, destination=new_room)
|
||||
alias_string = ""
|
||||
if new_to_exit.aliases:
|
||||
alias_string = " (%s)" % ", ".join(new_to_exit.aliases)
|
||||
exit_to_string = "\nCreated Exit from %s to %s: %s(%s)%s."
|
||||
exit_to_string = exit_to_string % (location.name, new_room.name, new_to_exit,
|
||||
new_to_exit.dbref, alias_string)
|
||||
|
||||
# Create exit back from new room
|
||||
|
||||
if len(self.rhs_objs) > 1:
|
||||
# Building the exit back to the current room
|
||||
|
|
@ -700,10 +707,8 @@ class CmdDig(ObjManipCommand):
|
|||
typeclass = "%s.%s" % (settings.BASE_TYPECLASS_PATH,
|
||||
typeclass)
|
||||
new_back_exit = create.create_object(typeclass, back_exit["name"],
|
||||
new_room,
|
||||
aliases=back_exit["aliases"])
|
||||
new_back_exit.destination = location
|
||||
new_back_exit.locks.add(lockstring)
|
||||
new_room, aliases=back_exit["aliases"],
|
||||
locks=lockstring, destination=location)
|
||||
alias_string = ""
|
||||
if new_back_exit.aliases:
|
||||
alias_string = " (%s)" % ", ".join(new_back_exit.aliases)
|
||||
|
|
@ -1534,7 +1539,7 @@ class CmdExamine(ObjManipCommand):
|
|||
perms = ["<Superuser>"]
|
||||
elif not perms:
|
||||
perms = ["<None>"]
|
||||
string += headers["perms"] % (", ".join(perms))
|
||||
string += headers["playerperms"] % (", ".join(perms))
|
||||
string += headers["typeclass"] % (obj.typeclass, obj.typeclass_path)
|
||||
|
||||
if hasattr(obj, "location"):
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ class UnloggedinCmdSet(CmdSet):
|
|||
Sets up the unlogged cmdset.
|
||||
"""
|
||||
key = "Unloggedin"
|
||||
priority = 0
|
||||
|
||||
def at_cmdset_creation(self):
|
||||
"Populate the cmdset"
|
||||
|
|
|
|||
|
|
@ -613,13 +613,15 @@ class CmdOOCLook(CmdLook):
|
|||
help_cateogory = "General"
|
||||
|
||||
def func(self):
|
||||
"implement the command"
|
||||
"implement the ooc look command"
|
||||
|
||||
self.character = None
|
||||
self.character = None
|
||||
if utils.inherits_from(self.caller, "src.objects.objects.Object"):
|
||||
# An object of some type is calling. Convert to player.
|
||||
print self.caller, self.caller.__class__
|
||||
self.character = self.caller
|
||||
self.caller = self.caller.player
|
||||
if hasattr(self.caller, "player"):
|
||||
self.caller = self.caller.player
|
||||
|
||||
if not self.character:
|
||||
string = "You are out-of-character (OOC). "
|
||||
|
|
@ -627,7 +629,7 @@ class CmdOOCLook(CmdLook):
|
|||
self.caller.msg(string)
|
||||
else:
|
||||
self.caller = self.character # we have to put this back for normal look to work.
|
||||
super(CmdLook, self).func()
|
||||
super(CmdOOCLook, self).func()
|
||||
|
||||
class CmdIC(MuxCommand):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ class MuxCommand(Command):
|
|||
string += "-" * 50
|
||||
string += "\nname of cmd (self.key): {w%s{n\n" % self.key
|
||||
string += "cmd aliases (self.aliases): {w%s{n\n" % self.aliases
|
||||
string += "cmd perms (self.permissions): {w%s{n\n" % self.permissions
|
||||
string += "cmd locks (self.locks): {w%s{n\n" % self.locks
|
||||
string += "help category (self.help_category): {w%s{n\n" % self.help_category
|
||||
string += "object calling (self.caller): {w%s{n\n" % self.caller
|
||||
string += "object storing cmdset (self.obj): {w%s{n\n" % self.obj
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ from src.commands.cmdhandler import CMD_NOMATCH
|
|||
from src.commands.cmdhandler import CMD_MULTIMATCH
|
||||
from src.commands.cmdhandler import CMD_NOPERM
|
||||
from src.commands.cmdhandler import CMD_CHANNEL
|
||||
from src.commands.cmdhandler import CMD_EXIT
|
||||
|
||||
from src.commands.default.muxcommand import MuxCommand
|
||||
|
||||
|
|
@ -188,37 +187,3 @@ class SystemSendToChannel(MuxCommand):
|
|||
msg = "[%s] %s: %s" % (channel.key, caller.name, msg)
|
||||
msgobj = create.create_message(caller, msg, channels=[channel])
|
||||
channel.msg(msgobj)
|
||||
|
||||
#
|
||||
# Command called when the system recognizes the command given
|
||||
# as matching an exit from the room. E.g. if there is an exit called 'door'
|
||||
# and the user gives the command
|
||||
# > door
|
||||
# the exit 'door' should be traversed to its destination.
|
||||
|
||||
class SystemUseExit(MuxCommand):
|
||||
"""
|
||||
Handles what happens when user gives a valid exit
|
||||
as a command. It receives the raw string as input.
|
||||
"""
|
||||
key = CMD_EXIT
|
||||
locks = "cmd:all()"
|
||||
|
||||
def func(self):
|
||||
"""
|
||||
Handle traversing an exit
|
||||
"""
|
||||
caller = self.caller
|
||||
if not self.args:
|
||||
return
|
||||
exit_name = self.args
|
||||
exi = caller.search(exit_name)
|
||||
if not exi:
|
||||
return
|
||||
destination = exi.destination
|
||||
if not destination:
|
||||
return
|
||||
if exit.access(caller, 'traverse'):
|
||||
caller.move_to(destination)
|
||||
else:
|
||||
caller.msg("You cannot enter")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue