diff --git a/src/commands/cmdhandler.py b/src/commands/cmdhandler.py index 546863c3c6..dc45408836 100644 --- a/src/commands/cmdhandler.py +++ b/src/commands/cmdhandler.py @@ -142,7 +142,8 @@ def get_and_merge_cmdsets(caller): # report cmdset errors to user (these should already have been logged) yield [caller.msg(cmdset.message) for cmdset in cmdsets if cmdset.key == "_CMDSET_ERROR"] # sort cmdsets after reverse priority (highest prio are merged in last) - cmdsets = yield sorted(cmdsets, key=lambda x: x.priority) + yield cmdsets.sort(key=lambda x: x.priority) + #cmdsets = yield sorted(cmdsets, key=lambda x: x.priority) if cmdsets: # Merge all command sets into one, beginning with the lowest-prio one diff --git a/src/commands/cmdset.py b/src/commands/cmdset.py index ee45a404e9..c434796950 100644 --- a/src/commands/cmdset.py +++ b/src/commands/cmdset.py @@ -144,10 +144,12 @@ class CmdSet(object): if key: self.key = key self.commands = [] + self.system_commands = [] self.actual_mergetype = self.mergetype self.cmdsetobj = cmdsetobj # initialize system self.at_cmdset_creation() + self._contains_cache = {} # Priority-sensitive merge operations for cmdsets @@ -223,7 +225,13 @@ class CmdSet(object): Returns True if this cmdset contains the given command (as defined by command name and aliases). This allows for things like 'if cmd in cmdset' """ - return othercmd in self.commands + # optimization test + try: + return self._contains_cache[othercmd] + except KeyError: + ret = othercmd in self.commands + self._contains_cache[othercmd] = ret + return ret def __add__(self, cmdset_b): """ @@ -327,18 +335,29 @@ class CmdSet(object): cmds = [self._instantiate(c) for c in cmd] else: cmds = [self._instantiate(cmd)] + commands = self.commands + system_commands = self.system_commands for cmd in cmds: # add all commands if not hasattr(cmd, 'obj'): cmd.obj = self.cmdsetobj try: - ic = self.commands.index(cmd) - self.commands[ic] = cmd # replace + ic = commands.index(cmd) + commands[ic] = cmd # replace except ValueError: - self.commands.append(cmd) + commands.append(cmd) # extra run to make sure to avoid doublets - self.commands = list(set(self.commands)) + self.commands = list(set(commands)) #print "In cmdset.add(cmd):", self.key, cmd + # add system_command to separate list as well, + # for quick look-up + if cmd.key.startswith("__"): + try: + ic = system_commands.index(cmd) + system_commands[ic] = cmd # replace + except ValueError: + system_commands.append(cmd) + def remove(self, cmd): """ @@ -369,7 +388,8 @@ class CmdSet(object): commands starting with double underscore __. These are excempt from merge operations. """ - return [cmd for cmd in self.commands if cmd.key.startswith('__')] + return self.system_commands + #return [cmd for cmd in self.commands if cmd.key.startswith('__')] def make_unique(self, caller): """ diff --git a/src/commands/command.py b/src/commands/command.py index 15d82e97d6..2a5a29376b 100644 --- a/src/commands/command.py +++ b/src/commands/command.py @@ -29,8 +29,8 @@ class CommandMeta(type): mcs.aliases = [str(alias).strip().lower() for alias in mcs.aliases] # optimization - a set is much faster to match against than a list mcs._matchset = set([mcs.key] + mcs.aliases) - # optimization for retrieving aliases and key as one list - mcs._keyaliases = [mcs.key] + mcs.aliases + # optimization for looping over keys+aliases + mcs._keyaliases = tuple(mcs._matchset) # by default we don't save the command between runs if not hasattr(mcs, "save_for_next"): diff --git a/src/objects/models.py b/src/objects/models.py index ab21753f71..7ec0e282a2 100644 --- a/src/objects/models.py +++ b/src/objects/models.py @@ -44,7 +44,6 @@ _ME = _("me") _SELF = _("self") _HERE = _("here") - def clean_content_cache(obj): "Clean obj's content cache" _SA(obj, "_contents_cache", None) @@ -428,8 +427,8 @@ class ObjectDB(TypedObject): Retrieve sessions connected to this object. """ # if the player is not connected, this will simply be an empty list. - if self.player: - return self.player.sessions + if _GA(self, "player"): + return _GA(_GA(self, "player"), "sessions") return [] sessions = property(__sessions_get) @@ -439,14 +438,15 @@ class ObjectDB(TypedObject): Convenience function for checking if an active player is currently connected to this object """ - return any(self.sessions) + return any(_GA(self, "sessions")) has_player = property(__has_player_get) is_player = property(__has_player_get) #@property def __is_superuser_get(self): "Check if user has a player, and if so, if it is a superuser." - return any(self.sessions) and self.player.is_superuser + #return any(self.sessions) and self.player.is_superuser + return any(_GA(self, "sessions")) and _GA(_GA(self, "player"), "is_superuser") is_superuser = property(__is_superuser_get) # contents diff --git a/src/objects/objects.py b/src/objects/objects.py index 57903c2e0e..fa8e0b631f 100644 --- a/src/objects/objects.py +++ b/src/objects/objects.py @@ -637,31 +637,26 @@ class Object(TypeClass): """ if not pobject: return - string = "{c%s{n" % self.name - desc = self.attr("desc") + # get and identify all objects + visible = (con for con in self.contents if con != pobject and con.access(pobject, "view")) + exits, users, things = [], [], [] + for con in visible: + key = con.key + if con.destination: + exits.append(key) + elif con.has_player: + users.append("{c%s{n" % key) + else: + things.append(key) + # get description, build string + string = "{c%s{n" % self.key + desc = self.db.desc if desc: string += "\n %s" % desc - exits = [] - users = [] - things = [] - for content in [con for con in self.contents if con.access(pobject, 'view')]: - if content == pobject: - continue - name = content.name - if content.destination: - exits.append(name) - elif content.has_player: - users.append(name) - else: - things.append(name) if exits: string += "\n{wExits:{n " + ", ".join(exits) if users or things: - string += "\n{wYou see: {n" - if users: - string += "{c" + ", ".join(users) + "{n " - if things: - string += ", ".join(things) + string += "\n{wYou see:{n " + ", ".join(users + things) return string def at_desc(self, looker=None): diff --git a/src/players/models.py b/src/players/models.py index 4021b5a6f1..2c31729e4f 100644 --- a/src/players/models.py +++ b/src/players/models.py @@ -180,9 +180,9 @@ class PlayerDB(TypedObject): "Parent must be initiated first" TypedObject.__init__(self, *args, **kwargs) # handlers - self.cmdset = CmdSetHandler(self) - self.cmdset.update(init_mode=True) - self.nicks = PlayerNickHandler(self) + _SA(self, "cmdset", CmdSetHandler(self)) + _GA(self, "cmdset").update(init_mode=True) + _SA(self, "nicks", PlayerNickHandler(self)) # Wrapper properties to easily set database fields. These are # @property decorators that allows to access these fields using @@ -240,21 +240,21 @@ class PlayerDB(TypedObject): #@property def cmdset_storage_get(self): "Getter. Allows for value = self.name. Returns a list of cmdset_storage." - if self.db_cmdset_storage: - return [path.strip() for path in self.db_cmdset_storage.split(',')] + if _GA(self, "db_cmdset_storage"): + return [path.strip() for path in _GA(self, "db_cmdset_storage").split(',')] return [] #@cmdset_storage.setter def cmdset_storage_set(self, value): "Setter. Allows for self.name = value. Stores as a comma-separated string." if utils.is_iter(value): value = ",".join([str(val).strip() for val in value]) - self.db_cmdset_storage = value - self.save() + _SA(self, "db_cmdset_storage", value) + _GA(self, "save")() #@cmdset_storage.deleter def cmdset_storage_del(self): "Deleter. Allows for del self.name" - self.db_cmdset_storage = "" - self.save() + _SA(self, "db_cmdset_storage", "") + _GA(self, "save")() cmdset_storage = property(cmdset_storage_get, cmdset_storage_set, cmdset_storage_del) #@property @@ -281,10 +281,10 @@ class PlayerDB(TypedObject): # def __str__(self): - return smart_str("%s(player %s)" % (self.name, self.dbid)) + return smart_str("%s(player %s)" % (_GA(self, "name"), _GA(self, "dbid"))) def __unicode__(self): - return u"%s(player#%s)" % (self.name, self.dbid) + return u"%s(player#%s)" % (_GA(self, "name"), _GA(self, "dbid")) # this is required to properly handle attributes and typeclass loading _typeclass_paths = settings.PLAYER_TYPECLASS_PATHS @@ -297,15 +297,15 @@ class PlayerDB(TypedObject): #@property def name_get(self): "Getter. Allows for value = self.name" - if not self._name_cache: - self._name_cache = self.user.username - return self._name_cache + if not _GA(self, "_name_cache"): + _SA(self, "_name_cache", _GA(self,"user").username) + return _GA(self, "_name_cache") #@name.setter def name_set(self, value): "Setter. Allows for player.name = newname" - self.user.username = value - self.user.save() # this might be stopped by Django? - self._name_cache = value + _GA(self, "user").username = value + _GA(self, "user").save() + _SA(self, "_name_cache", value) #@name.deleter def name_del(self): "Deleter. Allows for del self.name" @@ -317,9 +317,9 @@ class PlayerDB(TypedObject): #@property def uid_get(self): "Getter. Retrieves the user id" - if not self._uid_cache: - self._uid_cache = self.user.id - return self._uid_cache + if not _GA(self, "_uid_cache"): + _SA(self, "_uid_cache", _GA(self, "user").id) + return _GA(self, "_uid_cache") def uid_set(self, value): raise Exception("User id cannot be set!") def uid_del(self): @@ -345,9 +345,9 @@ class PlayerDB(TypedObject): _is_superuser_cache = None def is_superuser_get(self): "Superusers have all permissions." - if self._is_superuser_cache == None: - self._is_superuser_cache = self.user.is_superuser - return self._is_superuser_cache + if _GA(self, "_is_superuser_cache") == None: + _SA(self, "_is_superuser_cache", _GA(self, "user").is_superuser) + return _GA(self, "_is_superuser_cache") is_superuser = property(is_superuser_get) # @@ -379,7 +379,7 @@ class PlayerDB(TypedObject): """ Swaps character, if possible """ - return self.__class__.objects.swap_character(self, new_character, delete_old_character=delete_old_character) + return _GA(self, "__class__").objects.swap_character(self, new_character, delete_old_character=delete_old_character) def delete(self, *args, **kwargs): "Make sure to delete user also when deleting player - the two may never exist separately." diff --git a/src/utils/dummyrunner/dummyrunner.py b/src/utils/dummyrunner/dummyrunner.py index da82e177a0..16ab6550d7 100644 --- a/src/utils/dummyrunner/dummyrunner.py +++ b/src/utils/dummyrunner/dummyrunner.py @@ -101,7 +101,7 @@ DEFAULT_NCLIENTS = 1 # time between each 'tick', in seconds, if not set on command # line. All launched clients will be called upon to possibly do an # action with this frequency. -DEFAULT_TIMESTEP = 5 +DEFAULT_TIMESTEP = 2 # Port to use, if not specified on command line DEFAULT_PORT = settings.TELNET_PORTS[0] # chance of an action happening, per timestep. This helps to