Refactor ChannelHandler. Fix issues with new cmdset merge procedures.

This commit is contained in:
Griatch 2016-10-12 23:31:39 +02:00
parent 196f1ad270
commit a61a33e87d
4 changed files with 49 additions and 54 deletions

View file

@ -36,6 +36,7 @@ command line. The processing of a command works as follows:
from collections import defaultdict from collections import defaultdict
from weakref import WeakValueDictionary from weakref import WeakValueDictionary
from traceback import format_exc from traceback import format_exc
from itertools import chain
from copy import copy from copy import copy
from twisted.internet.defer import inlineCallbacks, returnValue from twisted.internet.defer import inlineCallbacks, returnValue
from django.conf import settings from django.conf import settings
@ -223,7 +224,7 @@ def get_and_merge_cmdsets(caller, session, player, obj, callertype):
location = obj.location location = obj.location
except Exception: except Exception:
location = None location = None
if location:# and not obj_cmdset.no_objs: #TODO if location:
# Gather all cmdsets stored on objects in the room and # Gather all cmdsets stored on objects in the room and
# also in the caller's inventory and the location itself # also in the caller's inventory and the location itself
local_objlist = yield (location.contents_get(exclude=obj) + local_objlist = yield (location.contents_get(exclude=obj) +
@ -239,9 +240,10 @@ def get_and_merge_cmdsets(caller, session, player, obj, callertype):
# is not seeing e.g. the commands on a fellow player (which is why # is not seeing e.g. the commands on a fellow player (which is why
# the no_superuser_bypass must be True) # the no_superuser_bypass must be True)
local_obj_cmdsets = \ local_obj_cmdsets = \
yield [lobj.cmdset.current for lobj in local_objlist yield list(chain.from_iterable(
if (lobj.cmdset.current and lobj.cmdset.cmdset_stack for lobj in local_objlist
lobj.access(caller, access_type='call', no_superuser_bypass=True))] if (lobj.cmdset.current and
lobj.access(caller, access_type='call', no_superuser_bypass=True))))
for cset in local_obj_cmdsets: for cset in local_obj_cmdsets:
#This is necessary for object sets, or we won't be able to #This is necessary for object sets, or we won't be able to
# separate the command sets from each other in a busy room. We # separate the command sets from each other in a busy room. We
@ -267,8 +269,7 @@ def get_and_merge_cmdsets(caller, session, player, obj, callertype):
_msg_err(caller, _ERROR_CMDSETS) _msg_err(caller, _ERROR_CMDSETS)
raise ErrorReported raise ErrorReported
try: try:
# we don't return the 'duplicates' option since this happens per-merge returnValue((obj.cmdset.current, list(obj.cmdset.cmdset_stack)))
returnValue((obj.cmdset.current, obj.cmdset.cmdset_stack))
except AttributeError: except AttributeError:
returnValue(((None, None, None), [])) returnValue(((None, None, None), []))
@ -299,12 +300,13 @@ def get_and_merge_cmdsets(caller, session, player, obj, callertype):
if not current.no_channels: if not current.no_channels:
# also objs may have channels # also objs may have channels
channel_cmdsets = yield _get_channel_cmdset(obj) channel_cmdsets = yield _get_channel_cmdset(obj)
print "obj channel cmdsets:", len(channel_cmdsets), [cmdset.key for cmdset in channel_cmdsets] print "obj channel cmdsets:", len(channel_cmdsets), [cmdset.key if cmdset else cmdset for cmdset in channel_cmdsets]
cmdsets += channel_cmdsets cmdsets += channel_cmdsets
if not current.no_channels: if not current.no_channels:
channel_cmdsets = yield _get_channel_cmdset(obj) channel_cmdsets = yield _get_channel_cmdset(player)
print "player channel cmdsets:", len(channel_cmdsets), [cmdset.key for cmdset in channel_cmdsets] print "player channel cmdsets:", len(channel_cmdsets), [cmdset.key for cmdset in channel_cmdsets]
cmdsets += channel_cmdsets print channel_cmdsets[0].commands
cmdsets += channel_cmdsets
elif callertype == "player": elif callertype == "player":
# we are calling the command from the player level # we are calling the command from the player level

View file

@ -145,7 +145,7 @@ class ChannelHandler(object):
Initializes the channel handler's internal state. Initializes the channel handler's internal state.
""" """
self.cached_channel_cmds = [] self.cached_channel_cmds = {}
self.cached_cmdsets = {} self.cached_cmdsets = {}
def __str__(self): def __str__(self):
@ -160,7 +160,8 @@ class ChannelHandler(object):
Reset the cache storage. Reset the cache storage.
""" """
self.cached_channel_cmds = [] self.cached_channel_cmds = {}
self.cached_cmdsets = {}
def add(self, channel): def add(self, channel):
""" """
@ -195,7 +196,7 @@ class ChannelHandler(object):
cmd.__doc__ = cmd.__doc__.format(channelkey=key, cmd.__doc__ = cmd.__doc__.format(channelkey=key,
lower_channelkey=key.strip().lower(), lower_channelkey=key.strip().lower(),
channeldesc=channel.attributes.get("desc", default="").strip()) channeldesc=channel.attributes.get("desc", default="").strip())
self.cached_channel_cmds.append(cmd) self.cached_channel_cmds[channel] = cmd
self.cached_cmdsets = {} self.cached_cmdsets = {}
add_channel = add # legacy alias add_channel = add # legacy alias
@ -208,10 +209,10 @@ class ChannelHandler(object):
global _CHANNELDB global _CHANNELDB
if not _CHANNELDB: if not _CHANNELDB:
from evennia.comms.models import ChannelDB as _CHANNELDB from evennia.comms.models import ChannelDB as _CHANNELDB
self.cached_channel_cmds = [] self.cached_channel_cmds = {}
self.cached_cmdsets = {} self.cached_cmdsets = {}
for channel in _CHANNELDB.objects.get_all_channels(): for channel in _CHANNELDB.objects.get_all_channels():
self.add_channel(channel) self.add(channel)
def get_cmdset(self, source_object): def get_cmdset(self, source_object):
""" """
@ -221,7 +222,7 @@ class ChannelHandler(object):
Args: Args:
source_object (Object): An object subscribing to one source_object (Object): An object subscribing to one
or more channels. or more channels.
hannelhandler import CHANNEL_HANDLER
Returns: Returns:
cmdsets (list): The Channel-Cmdsets `source_object` has cmdsets (list): The Channel-Cmdsets `source_object` has
access to. access to.
@ -230,14 +231,18 @@ hannelhandler import CHANNEL_HANDLER
if source_object in self.cached_cmdsets: if source_object in self.cached_cmdsets:
return self.cached_cmdsets[source_object] return self.cached_cmdsets[source_object]
else: else:
# create a new cmdset holding all channels # create a new cmdset holding all viable channels
chan_cmdset = cmdset.CmdSet() chan_cmdset = None
chan_cmdset.key = 'ChannelCmdSet' chan_cmds = [channelcmd for channel, channelcmd in self.cached_channel_cmds.iteritems()
chan_cmdset.priority = 101 if channel.subscriptions.has(source_object)
chan_cmdset.duplicates = True and channelcmd.access(source_object, 'send')]
for cmd in [cmd for cmd in self.cached_channel_cmds if chan_cmds:
if cmd.access(source_object, 'send')]: chan_cmdset = cmdset.CmdSet()
chan_cmdset.add(cmd) chan_cmdset.key = 'ChannelCmdSet'
chan_cmdset.priority = 101
chan_cmdset.duplicates = True
for cmd in chan_cmds:
chan_cmdset.add(cmd)
self.cached_cmdsets[source_object] = chan_cmdset self.cached_cmdsets[source_object] = chan_cmdset
return chan_cmdset return chan_cmdset

View file

@ -109,7 +109,7 @@ class Msg(SharedMemoryModel):
db_hide_from_objects = models.ManyToManyField("objects.ObjectDB", related_name='hide_from_objects_set', null=True, blank=True) db_hide_from_objects = models.ManyToManyField("objects.ObjectDB", related_name='hide_from_objects_set', null=True, blank=True)
db_hide_from_channels = models.ManyToManyField("ChannelDB", related_name='hide_from_channels_set', null=True, blank=True) db_hide_from_channels = models.ManyToManyField("ChannelDB", related_name='hide_from_channels_set', null=True, blank=True)
db_tags = models.ManyToManyField(Tag, null=True, blank=True, db_tags = models.ManyToManyField(Tag, null=True, blank=True,
help_text='tags on this message. Tags are simple string markers to identify, group and alias messages.') help_text='tags on this message. Tags are simple string markers to identify, group and alias messages.')
# Database manager # Database manager
@ -331,7 +331,7 @@ class Msg(SharedMemoryModel):
""" """
return self.locks.check(accessing_obj, return self.locks.check(accessing_obj,
access_type=access_type, default=default) access_type=access_type, default=default)
#------------------------------------------------------------ #------------------------------------------------------------
# #
# TempMsg # TempMsg
@ -448,6 +448,11 @@ class SubscriptionHandler(object):
""" """
self.obj = obj self.obj = obj
self._cache = None
def _recache(self):
self._cache = {player : True for player in self.obj.db_subscriptions.all()}
self._cache.update({obj : True for obj in self.obj.db_object_subscriptions.all()})
def has(self, entity): def has(self, entity):
""" """
@ -463,12 +468,9 @@ class SubscriptionHandler(object):
subscriber. subscriber.
""" """
clsname = entity.__dbclass__.__name__ if self._cache is None:
if clsname == "PlayerDB": self._recache()
return entity in self.obj.db_subscriptions.all() return entity in self._cache
elif clsname == "ObjectDB":
return entity in self.obj.db_object_subscriptions.all()
def add(self, entity): def add(self, entity):
""" """
@ -492,10 +494,11 @@ class SubscriptionHandler(object):
self.obj.db_object_subscriptions.add(subscriber) self.obj.db_object_subscriptions.add(subscriber)
elif clsname == "PlayerDB": elif clsname == "PlayerDB":
self.obj.db_subscriptions.add(subscriber) self.obj.db_subscriptions.add(subscriber)
self._recache()
def remove(self, entity): def remove(self, entity):
""" """
Remove a subecriber from the channel. Remove a subscriber from the channel.
Args: Args:
entity (Player, Object or list): The entity or entity (Player, Object or list): The entity or
@ -510,6 +513,7 @@ class SubscriptionHandler(object):
self.obj.db_subscriptions.remove(entity) self.obj.db_subscriptions.remove(entity)
elif clsname == "ObjectDB": elif clsname == "ObjectDB":
self.obj.db_object_subscriptions.remove(entity) self.obj.db_object_subscriptions.remove(entity)
self._recache()
def all(self): def all(self):
""" """
@ -520,8 +524,9 @@ class SubscriptionHandler(object):
may be a mix of Players and Objects! may be a mix of Players and Objects!
""" """
return list(self.obj.db_subscriptions.all()) + \ if self._cache is None:
list(self.obj.db_object_subscriptions.all()) self._recache()
return self._cache
def clear(self): def clear(self):
""" """
@ -530,6 +535,7 @@ class SubscriptionHandler(object):
""" """
self.obj.db_subscriptions.clear() self.obj.db_subscriptions.clear()
self.obj.db_object_subscriptions.clear() self.obj.db_object_subscriptions.clear()
self._cache = None
class ChannelDB(TypedObject): class ChannelDB(TypedObject):

View file

@ -875,24 +875,6 @@ class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)):
self.at_access(result, accessing_obj, access_type, **kwargs) self.at_access(result, accessing_obj, access_type, **kwargs)
return result return result
def __eq__(self, other):
"""
Checks for equality against an id string or another object or
user.
Args:
other (Object): object to compare to.
"""
try:
return self.dbid == other.dbid
except AttributeError:
# compare players instead
try:
return self.player.uid == other.player.uid
except AttributeError:
return False
# #
# Hook methods # Hook methods
# #