A working version of the emote system with proper sdesc search functionality and emote/sdesc handlers.
This commit is contained in:
parent
a630e6d020
commit
8590238c08
1 changed files with 256 additions and 85 deletions
|
|
@ -60,6 +60,8 @@ import itertools
|
|||
from copy import copy
|
||||
from evennia import DefaultObject, DefaultCharacter
|
||||
from evennia import Command
|
||||
from evennia import ansi
|
||||
from evennia.utils.utils import lazy_property
|
||||
|
||||
#------------------------------------------------------------
|
||||
# Emote parser
|
||||
|
|
@ -140,6 +142,8 @@ class EmoteError(Exception):
|
|||
class SdescError(Exception):
|
||||
pass
|
||||
|
||||
class RecogError(Exception):
|
||||
pass
|
||||
|
||||
class LanguageError(Exception):
|
||||
pass
|
||||
|
|
@ -170,6 +174,8 @@ def ordered_permutation_regex(sentence):
|
|||
"""
|
||||
# escape {#nnn} markers from sentence, replace with nnn
|
||||
sentence = _RE_REF.sub("\1", sentence)
|
||||
# escape {##nnn} markers, replace with nnn
|
||||
sentence = _RE_REF_LANG.sub("\1", sentence)
|
||||
# escape self-ref marker from sentence
|
||||
sentence = _RE_SELF_REF.sub("", sentence)
|
||||
|
||||
|
|
@ -296,14 +302,12 @@ def parse_sdescs_and_recogs(sender, candidates, emote, map_obj=False):
|
|||
emote = _RE_REF.sub("\1", emote)
|
||||
|
||||
# build all candidate regex tuples
|
||||
candidate_regexes = [
|
||||
(recog_regex, obj, sdesc) for obj, (recog_regex, sdesc)
|
||||
in sender.db.recog_objmap.items() if obj in candidates] + \
|
||||
[obj.db.sdesc_regex_tuple for obj in candidates]
|
||||
# pre-compile the regexes while filtering empty tuples
|
||||
print candidate_regexes
|
||||
candidate_regexes = [(re.compile(tup[0], _RE_FLAGS), tup[1], tup[2])
|
||||
for tup in candidate_regexes if tup]
|
||||
candidate_regexes = [sender.recog.get_regex_tuple(obj)
|
||||
for obj in candidates if hasattr(obj, "recog")] + \
|
||||
[obj.sdesc.get_regex_tuple()
|
||||
for obj in candidates if hasattr(obj, "sdesc")]
|
||||
# filter out non-found data
|
||||
candidate_regexes = [tup for tup in candidate_regexes if tup]
|
||||
|
||||
# handle self-reference first
|
||||
objlist = []
|
||||
|
|
@ -416,8 +420,10 @@ def receive_emote(sender, receiver, emote, sdesc_mapping, language_mapping):
|
|||
# overload mapping with receiver's recogs (which is on the same form)
|
||||
print "receiver.db.recog_refmap:", receiver, receiver.db.recog_refmap
|
||||
print "mapping:", mapping
|
||||
if receiver.db.recog_refmap:
|
||||
mapping.update(receiver.db.recog_refmap)
|
||||
try:
|
||||
mapping.update(receiver.recog.ref2recog)
|
||||
except AttributeError:
|
||||
pass
|
||||
# handle the language mapping, which always produce different keys ##nn
|
||||
for key, (langname, saytext) in language_mapping.iteritems():
|
||||
# color say's white
|
||||
|
|
@ -461,7 +467,7 @@ def send_emote(sender, receivers, emote, no_anonymous=True):
|
|||
# no self-reference in the emote - add to the end
|
||||
key = "#%i" % sender.id
|
||||
emote = "%s [%s]" % (emote, "{%s}" % key)
|
||||
sdesc_mapping[key] = sender.db.sdesc or sender.key
|
||||
sdesc_mapping[key] = sender.sdesc.get() or sender.key
|
||||
|
||||
# broadcast emote
|
||||
for receiver in receivers:
|
||||
|
|
@ -479,6 +485,7 @@ class RPCommand(Command):
|
|||
"strip extra whitespace"
|
||||
self.args = self.args.strip()
|
||||
|
||||
|
||||
class CmdEmote(RPCommand): # replaces the main emote
|
||||
"""
|
||||
Emote an action, allowing dynamic replacement of
|
||||
|
|
@ -534,7 +541,7 @@ class CmdSdesc(RPCommand): # set/look at own sdesc
|
|||
caller.msg("Usage: sdesc <sdesc-text>")
|
||||
return
|
||||
else:
|
||||
sdesc = caller.set_sdesc(self.args)
|
||||
sdesc = caller.sdesc.add(self.args)
|
||||
caller.msg("Your sdesc was set to '%s'." % sdesc)
|
||||
|
||||
|
||||
|
|
@ -649,6 +656,205 @@ class CmdLanguage(Command): # list available languages
|
|||
self.caller.msg("Languages available: %s" % ", ".join(_LANGUAGE_LIST))
|
||||
|
||||
|
||||
# Handlers
|
||||
|
||||
class SdescHandler(object):
|
||||
"""
|
||||
This Handler wraps all operations with sdescs. We
|
||||
need to use this since we do a lot preparations on
|
||||
sdescs when updating them, in order for them to be
|
||||
efficient to search for and query.
|
||||
"""
|
||||
def __init__(self, obj):
|
||||
"""
|
||||
Initialize the handler
|
||||
|
||||
Args:
|
||||
obj (Object): The entity on which this handler is stored.
|
||||
|
||||
"""
|
||||
self.obj = obj
|
||||
self.sdesc = ""
|
||||
self.sdesc_regex = ""
|
||||
self._cache()
|
||||
|
||||
def _cache(self):
|
||||
"""
|
||||
Cache data from storage
|
||||
|
||||
"""
|
||||
self.sdesc = self.obj.attributes.get("sdesc", default="")
|
||||
sdesc_regex = self.obj.attributes.get("sdesc_regex", default="")
|
||||
self.sdesc_regex = re.compile(sdesc_regex, _RE_FLAGS)
|
||||
|
||||
def add(self, sdesc, max_length=60):
|
||||
"""
|
||||
Add a new sdesc to object, replacing the old one.
|
||||
|
||||
Args:
|
||||
sdesc (str): The sdesc to set. This may be stripped
|
||||
of control sequences before setting.
|
||||
max_length (int, optional): The max limit of the sdesc.
|
||||
|
||||
Returns:
|
||||
sdesc (str): The actually set sdesc.
|
||||
|
||||
Raises:
|
||||
SdescError: If the sdesc can not be set or is longer than
|
||||
`max_length`.
|
||||
|
||||
"""
|
||||
# strip emote components from sdesc
|
||||
sdesc = _RE_REF.sub("\1",
|
||||
_RE_REF_LANG.sub("\1",
|
||||
_RE_SELF_REF.sub("",
|
||||
_RE_LANGUAGE.sub("",
|
||||
_RE_OBJ_REF_START.sub("", sdesc)))))
|
||||
|
||||
# make an sdesc clean of ANSI codes
|
||||
cleaned_sdesc = ansi.strip_ansi(sdesc)
|
||||
if len(cleaned_sdesc) > max_length:
|
||||
raise SdescError("Too long sdesc")
|
||||
|
||||
# store to attributes
|
||||
sdesc_regex = ordered_permutation_regex(cleaned_sdesc)
|
||||
self.obj.attributes.add("sdesc", sdesc)
|
||||
self.obj.attributes.add("sdesc_regex", sdesc_regex)
|
||||
# local caching
|
||||
self.sdesc = sdesc
|
||||
self.sdesc_regex = re.compile(sdesc_regex, _RE_FLAGS)
|
||||
|
||||
return sdesc
|
||||
|
||||
def get(self):
|
||||
"""
|
||||
Simple getter.
|
||||
|
||||
"""
|
||||
return self.sdesc
|
||||
|
||||
def get_regex_tuple(self):
|
||||
"""
|
||||
Return data for sdesc/recog handling
|
||||
|
||||
Returns:
|
||||
tup (tuple): tuple (sdesc_regex, obj, sdesc)
|
||||
|
||||
"""
|
||||
return self.sdesc_regex, self.obj, self.sdesc
|
||||
|
||||
|
||||
class RecogHandler(object):
|
||||
"""
|
||||
This handler manages the recognition mapping
|
||||
of an Object.
|
||||
|
||||
"""
|
||||
def __init__(self, obj):
|
||||
"""
|
||||
Initialize the handler
|
||||
|
||||
Args:
|
||||
obj (Object): The entity on which this handler is stored.
|
||||
|
||||
"""
|
||||
self.obj = obj
|
||||
# mappings
|
||||
self.ref2recog = {}
|
||||
self.obj2regex = {}
|
||||
self.obj2recog = {}
|
||||
|
||||
def _cache(self):
|
||||
"""
|
||||
Load data to handler cache
|
||||
"""
|
||||
self.ref2recog = self.obj.attributes.get("recog_ref2recog", default={})
|
||||
obj2regex = self.obj.attributes.get("recog_obj2regex", default={})
|
||||
obj2recog = self.obj.attributes.get("recog_obj2recog", default={})
|
||||
self.obj2regex = dict((obj, re.compile(regex, _RE_FLAGS))
|
||||
for obj, regex in obj2regex.items() if obj)
|
||||
self.obj2recog = dict((obj, recog)
|
||||
for obj, recog in obj2recog.items() if obj)
|
||||
|
||||
def add(self, obj, recog, max_length=60):
|
||||
"""
|
||||
Assign a custom recog (nick) to the given object.
|
||||
|
||||
Args:
|
||||
obj (Object): The object ot associate with the recog
|
||||
string. This is usually determined from the sdesc in the
|
||||
room by a call to parse_sdescs_and_recogs, but can also be
|
||||
given.
|
||||
recog (str): The replacement string to use with this object.
|
||||
max_length (int, optional): The max length of the recog string.
|
||||
|
||||
Returns:
|
||||
recog (str): The (possibly cleaned up) recog string actually set.
|
||||
|
||||
Raises:
|
||||
SdescError: When recog could not be set or sdesc longer
|
||||
than `max_length`.
|
||||
|
||||
|
||||
"""
|
||||
# strip emote components from recog
|
||||
recog = _RE_REF.sub("\1",
|
||||
_RE_REF_LANG.sub("\1",
|
||||
_RE_SELF_REF.sub("",
|
||||
_RE_LANGUAGE.sub("",
|
||||
_RE_OBJ_REF_START.sub("", recog)))))
|
||||
|
||||
# make an recog clean of ANSI codes
|
||||
cleaned_recog = ansi.strip_ansi(recog)
|
||||
if len(cleaned_recog) > max_length:
|
||||
raise RecogError("Too long recog")
|
||||
|
||||
# mapping #dbref:obj
|
||||
key = "#%i" % obj.id
|
||||
self.db.ref2recog[key] = recog
|
||||
self.db.obj2recog[obj] = recog
|
||||
regex = ordered_permutation_regex(cleaned_recog)
|
||||
self.db.obj2regex[obj] = regex
|
||||
# local caching
|
||||
self.ref2recog[key] = recog
|
||||
self.obj2recog[obj] = recog
|
||||
self.obj2regex[obj] = re.compile(regex, _RE_FLAGS)
|
||||
return recog
|
||||
|
||||
def get(self, obj):
|
||||
"""
|
||||
Get recog replacement string, if one exists.
|
||||
|
||||
Args:
|
||||
obj (Object): The object, whose sdesc to replace
|
||||
Returns:
|
||||
recog (str): The replacement string to use.
|
||||
"""
|
||||
return self.obj2recog.get(obj)
|
||||
|
||||
def remove(self, obj):
|
||||
"""
|
||||
Clear recog for a given object.
|
||||
|
||||
Args:
|
||||
obj (Object): The object for which to remove recog.
|
||||
"""
|
||||
if obj in self.db.obj2recog:
|
||||
del self.db.obj2recog[obj]
|
||||
del self.db.obj2regex[obj]
|
||||
del self.db.ref2regex["#%i" % obj.id]
|
||||
self._cache()
|
||||
|
||||
def get_regex_tuple(self, obj):
|
||||
"""
|
||||
Returns:
|
||||
rec (tuple): Tuple (recog_regex, obj, recog)
|
||||
"""
|
||||
if obj in self.obj2recog:
|
||||
return self.obj2regex[obj], obj, self.obj2regex[obj]
|
||||
return None
|
||||
|
||||
|
||||
#------------------------------------------------------------
|
||||
# RP Object typeclass
|
||||
#------------------------------------------------------------
|
||||
|
|
@ -660,6 +866,15 @@ class RPObject(DefaultObject):
|
|||
name replacement and look extensions.
|
||||
"""
|
||||
|
||||
# Handlers
|
||||
@lazy_property
|
||||
def sdesc(self):
|
||||
return SdescHandler(self)
|
||||
|
||||
@lazy_property
|
||||
def recog(self):
|
||||
return RecogHandler(self)
|
||||
|
||||
def at_object_creation(self):
|
||||
"""
|
||||
Called at initial creation.
|
||||
|
|
@ -670,85 +885,41 @@ class RPObject(DefaultObject):
|
|||
self.db.pose = ""
|
||||
self.db.pose_default = "is here."
|
||||
|
||||
self.db.sdesc = None
|
||||
self.db.sdesc_regex_tuple = None
|
||||
self.set_sdesc("A normal person")
|
||||
self.db.recog_refmap = {}
|
||||
self.db.recog_objmap = {}
|
||||
self.db.sdesc = ""
|
||||
self.db.sdesc_regex = ""
|
||||
|
||||
def set_sdesc(self, sdesc):
|
||||
self.db.recog_ref2recog = {}
|
||||
self.db.recog_obj2regex = {}
|
||||
self.db.recog_obj2recog = {}
|
||||
|
||||
# initializing
|
||||
self.sdesc.add("A normal person")
|
||||
|
||||
def search(self, searchdata, **kwargs):
|
||||
"""
|
||||
Assign a new sdesc to this character. It's important
|
||||
to use this in order to set up all mappings.
|
||||
This version of search will pre-parse searchdata for eventual
|
||||
matches against recogs and sdescs of candidates in the same
|
||||
location.
|
||||
|
||||
Args:
|
||||
sdesc (str): The short description to set.
|
||||
searchdata (str): Search string.
|
||||
|
||||
Returns:
|
||||
sdesc (str): The (possibly cleaned up) sdesc actually set.
|
||||
Notes:
|
||||
Recog/sdesc matching is always turned off if the keyword
|
||||
`global_search` is set or `candidates` are given.
|
||||
|
||||
"""
|
||||
# strip emote components from sdesc
|
||||
sdesc = _RE_REF.sub("\1",
|
||||
_RE_REF_LANG.sub("\1",
|
||||
_RE_SELF_REF.sub("",
|
||||
_RE_LANGUAGE.sub("",
|
||||
_RE_OBJ_REF_START.sub("", sdesc)))))
|
||||
|
||||
self.db.sdesc = sdesc
|
||||
self.db.sdesc_regex_tuple = (ordered_permutation_regex(sdesc), self, sdesc)
|
||||
return sdesc
|
||||
|
||||
def set_recog(self, obj, recog):
|
||||
"""
|
||||
Assign a custom recog (nick) to the given sdesc. This
|
||||
requires that the sdesc exists in the same room as us.
|
||||
|
||||
Args:
|
||||
obj (Object): The object ot associate with the recog string. This
|
||||
is usually determined from the sdesc in the room by a call to
|
||||
parse_sdescs_and_recogs, but can also be given, say as part
|
||||
of changing an existing recog value.given, say as part
|
||||
recog (str): The replacement string to use for this sdesc.
|
||||
|
||||
Returns:
|
||||
recog (str): The (possibly cleaned up) recog string actually set.
|
||||
|
||||
"""
|
||||
# strip emote components from recog
|
||||
recog = _RE_REF.sub("\1",
|
||||
_RE_REF_LANG.sub("\1",
|
||||
_RE_SELF_REF.sub("",
|
||||
_RE_LANGUAGE.sub("",
|
||||
_RE_OBJ_REF_START.sub("", recog)))))
|
||||
|
||||
# mapping #dbref:obj
|
||||
self.db.recog_refmap["#%i" % obj.id] = recog
|
||||
# mapping obj:(regex, recog)
|
||||
self.db.recog_objmap[obj] = (ordered_permutation_regex(recog), recog)
|
||||
return recog
|
||||
|
||||
def get_recog(self, obj):
|
||||
"""
|
||||
Get recog replacement string, if one exists.
|
||||
|
||||
Args:
|
||||
obj (Object): The object, whose sdesc to replace
|
||||
Returns:
|
||||
recog (str): The replacement string to use.
|
||||
|
||||
"""
|
||||
return self.db.recog_objmap.get(obj, (None, None))[1]
|
||||
|
||||
# def search(self, searchdata, **kwargs):
|
||||
# """
|
||||
# This version of search will pre-parse searchdata
|
||||
# for eventual matches against sdescs in candidates.
|
||||
# """
|
||||
# if isinstance(searchdata, basestring):
|
||||
# pass
|
||||
# if not candidates:
|
||||
|
||||
if (isinstance(searchdata, basestring) and not
|
||||
(kwargs.get("global_search") or
|
||||
kwargs.get("candidates"))):
|
||||
try:
|
||||
_, mapping = parse_sdescs_and_recogs(self,
|
||||
self.location.contents, _PREFIX + searchdata, map_obj=True)
|
||||
return mapping.values()[0]
|
||||
except EmoteError:
|
||||
pass
|
||||
# fall back to original search method
|
||||
return super(RPObject, self).search(searchdata, **kwargs)
|
||||
|
||||
|
||||
def get_display_name(self, looker, **kwargs):
|
||||
|
|
@ -771,7 +942,7 @@ class RPObject(DefaultObject):
|
|||
"""
|
||||
idstr = " (#%s)" % self.id if self.access(looker, access_type='control') else ""
|
||||
try:
|
||||
recog = looker.get_recog(self)
|
||||
recog = looker.recog.get(self)
|
||||
except AttributeError:
|
||||
recog = None
|
||||
sdesc = recog or self.db.sdesc or self.key
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue