Make RPSystem CmdRecog list recogs if given no args. Resolve #2059.

This commit is contained in:
Griatch 2020-02-29 14:00:04 +01:00
parent 25a0de12d7
commit 0aa38eddab
3 changed files with 102 additions and 12 deletions

View file

@ -50,6 +50,8 @@ without arguments starts a full interactive Python console.
and `SERVER_LOG_MAX_SIZE` (and equivalent for PORTAL) to control log rotation. and `SERVER_LOG_MAX_SIZE` (and equivalent for PORTAL) to control log rotation.
- Addded `inside_rec` lockfunc - if room is locked, the normal `inside()` lockfunc will - Addded `inside_rec` lockfunc - if room is locked, the normal `inside()` lockfunc will
fail e.g. for your inventory objs (since their loc is you), whereas this will pass. fail e.g. for your inventory objs (since their loc is you), whereas this will pass.
- RPSystem contrib's CmdRecog will now list all recogs if no arg is given. Also multiple
bugfixes.
## Evennia 0.9 (2018-2019) ## Evennia 0.9 (2018-2019)

View file

@ -798,6 +798,16 @@ class RecogHandler(object):
# recog_mask log not passed, disable recog # recog_mask log not passed, disable recog
return obj.sdesc.get() if hasattr(obj, "sdesc") else obj.key return obj.sdesc.get() if hasattr(obj, "sdesc") else obj.key
def all(self):
"""
Get a mapping of the recogs stored in handler.
Returns:
recogs (dict): A mapping of {recog: obj} stored in handler.
"""
return {self.obj2recog[obj]: obj for obj in self.obj2recog.keys()}
def remove(self, obj): def remove(self, obj):
""" """
Clear recog for a given object. Clear recog for a given object.
@ -931,6 +941,9 @@ class CmdSdesc(RPCommand): # set/look at own sdesc
except SdescError as err: except SdescError as err:
caller.msg(err) caller.msg(err)
return return
except AttributeError:
caller.msg(f"Cannot set sdesc on {caller.key}.")
return
caller.msg("%s's sdesc was set to '%s'." % (caller.key, sdesc)) caller.msg("%s's sdesc was set to '%s'." % (caller.key, sdesc))
@ -1040,6 +1053,7 @@ class CmdRecog(RPCommand): # assign personal alias to object in room
Recognize another person in the same room. Recognize another person in the same room.
Usage: Usage:
recog
recog sdesc as alias recog sdesc as alias
forget alias forget alias
@ -1047,8 +1061,8 @@ class CmdRecog(RPCommand): # assign personal alias to object in room
recog tall man as Griatch recog tall man as Griatch
forget griatch forget griatch
This will assign a personal alias for a person, or This will assign a personal alias for a person, or forget said alias.
forget said alias. Using the command without arguments will list all current recogs.
""" """
@ -1057,6 +1071,7 @@ class CmdRecog(RPCommand): # assign personal alias to object in room
def parse(self): def parse(self):
"Parse for the sdesc as alias structure" "Parse for the sdesc as alias structure"
self.sdesc, self.alias = "", ""
if " as " in self.args: if " as " in self.args:
self.sdesc, self.alias = [part.strip() for part in self.args.split(" as ", 2)] self.sdesc, self.alias = [part.strip() for part in self.args.split(" as ", 2)]
elif self.args: elif self.args:
@ -1069,22 +1084,47 @@ class CmdRecog(RPCommand): # assign personal alias to object in room
def func(self): def func(self):
"Assign the recog" "Assign the recog"
caller = self.caller caller = self.caller
if not self.args:
caller.msg("Usage: recog <sdesc> as <alias> or forget <alias>")
return
sdesc = self.sdesc
alias = self.alias.rstrip(".?!") alias = self.alias.rstrip(".?!")
sdesc = self.sdesc
recog_mode = self.cmdstring != "forget" and alias and sdesc
forget_mode = self.cmdstring == "forget" and sdesc
list_mode = not self.args
if not (recog_mode or forget_mode or list_mode):
caller.msg("Usage: recog, recog <sdesc> as <alias> or forget <alias>")
return
if list_mode:
# list all previously set recogs
all_recogs = caller.recog.all()
if not all_recogs:
caller.msg(
"You recognize no-one. " "(Use 'recog <sdesc> as <alias>' to recognize people."
)
else:
# note that we don't skip those failing enable_recog lock here,
# because that would actually reveal more than we want.
lst = "\n".join(
" {} ({})".format(key, obj.sdesc.get() if hasattr(obj, "sdesc") else obj.key)
for key, obj in all_recogs.items()
)
caller.msg(
f"Currently recognized (use 'recog <sdesc> as <alias>' to add "
f"new and 'forget <alias>' to remove):\n{lst}"
)
return
prefixed_sdesc = sdesc if sdesc.startswith(_PREFIX) else _PREFIX + sdesc prefixed_sdesc = sdesc if sdesc.startswith(_PREFIX) else _PREFIX + sdesc
candidates = caller.location.contents candidates = caller.location.contents
matches = parse_sdescs_and_recogs(caller, candidates, prefixed_sdesc, search_mode=True) matches = parse_sdescs_and_recogs(caller, candidates, prefixed_sdesc, search_mode=True)
nmatches = len(matches) nmatches = len(matches)
# handle 0, 1 and >1 matches # handle 0 and >1 matches
if nmatches == 0: if nmatches == 0:
caller.msg(_EMOTE_NOMATCH_ERROR.format(ref=sdesc)) caller.msg(_EMOTE_NOMATCH_ERROR.format(ref=sdesc))
elif nmatches > 1: elif nmatches > 1:
reflist = [ reflist = [
"%s%s%s (%s%s)" "{}{}{} ({}{})".format(
% (
inum + 1, inum + 1,
_NUM_SEP, _NUM_SEP,
_RE_PREFIX.sub("", sdesc), _RE_PREFIX.sub("", sdesc),
@ -1094,17 +1134,20 @@ class CmdRecog(RPCommand): # assign personal alias to object in room
for inum, obj in enumerate(matches) for inum, obj in enumerate(matches)
] ]
caller.msg(_EMOTE_MULTIMATCH_ERROR.format(ref=sdesc, reflist="\n ".join(reflist))) caller.msg(_EMOTE_MULTIMATCH_ERROR.format(ref=sdesc, reflist="\n ".join(reflist)))
else: else:
# one single match
obj = matches[0] obj = matches[0]
if not obj.access(self.obj, "enable_recog", default=True): if not obj.access(self.obj, "enable_recog", default=True):
# don't apply recog if object doesn't allow it (e.g. by being masked). # don't apply recog if object doesn't allow it (e.g. by being masked).
caller.msg("Can't recognize someone who is masked.") caller.msg("It's impossible to recognize them.")
return return
if self.cmdstring == "forget": if forget_mode:
# remove existing recog # remove existing recog
caller.recog.remove(obj) caller.recog.remove(obj)
caller.msg("%s will now know only '%s'." % (caller.key, obj.recog.get(obj))) caller.msg("%s will now know them only as '%s'." % (caller.key, obj.recog.get(obj)))
else: else:
# set recog
sdesc = obj.sdesc.get() if hasattr(obj, "sdesc") else obj.key sdesc = obj.sdesc.get() if hasattr(obj, "sdesc") else obj.key
try: try:
alias = caller.recog.add(obj, alias) alias = caller.recog.add(obj, alias)

View file

@ -169,6 +169,8 @@ class TestRPSystem(EvenniaTest):
self.speaker.recog.remove(self.receiver1) self.speaker.recog.remove(self.receiver1)
self.assertEqual(self.speaker.recog.get(self.receiver1), sdesc1) self.assertEqual(self.speaker.recog.get(self.receiver1), sdesc1)
self.assertEqual(self.speaker.recog.all(), {"Mr Receiver2": self.receiver2})
def test_parse_language(self): def test_parse_language(self):
self.assertEqual( self.assertEqual(
rpsystem.parse_language(self.speaker, emote), rpsystem.parse_language(self.speaker, emote),
@ -233,6 +235,49 @@ class TestRPSystem(EvenniaTest):
self.assertEqual(self.speaker.search("colliding"), self.receiver2) self.assertEqual(self.speaker.search("colliding"), self.receiver2)
class TestRPSystemCommands(CommandTest):
def setUp(self):
super().setUp()
self.char1.swap_typeclass(rpsystem.ContribRPCharacter)
self.char2.swap_typeclass(rpsystem.ContribRPCharacter)
def test_commands(self):
self.call(
rpsystem.CmdSdesc(), "Foobar Character", "Char's sdesc was set to 'Foobar Character'."
)
self.call(
rpsystem.CmdSdesc(),
"BarFoo Character",
"Char2's sdesc was set to 'BarFoo Character'.",
caller=self.char2,
)
self.call(rpsystem.CmdSay(), "Hello!", 'Char says, "Hello!"')
self.call(rpsystem.CmdEmote(), "/me smiles to /barfoo.", "Char smiles to BarFoo Character")
self.call(
rpsystem.CmdPose(),
"stands by the bar",
"Pose will read 'Foobar Character stands by the bar.'.",
)
self.call(
rpsystem.CmdRecog(),
"barfoo as friend",
"Char will now remember BarFoo Character as friend.",
)
self.call(
rpsystem.CmdRecog(),
"",
"Currently recognized (use 'recog <sdesc> as <alias>' to add new "
"and 'forget <alias>' to remove):\n friend (BarFoo Character)",
)
self.call(
rpsystem.CmdRecog(),
"friend",
"Char will now know them only as 'BarFoo Character'",
cmdstring="forget",
)
# Testing of ExtendedRoom contrib # Testing of ExtendedRoom contrib
from django.conf import settings from django.conf import settings