Reworked that look() methods on Players and Objects into at_look. They were also changed to accept pre-searched target objects rather than the command string. They also return a processed look string rather than sending it directly. The reason for this is that methods on the typeclass should not be handling command parsing - this should be the exclusive job of Command.parse in order to make command parsing completely contained withing one system. Likewise, it makes for more flexibility to not call self.msg() inside at_look but to let the outside caller do this explicitly - it might want to modify and append to the string before sending it off (something not used anywhere yet but which may be interesting). In order to correctly keep parsing entirely in the command body for the player, I made a custom parent for CmdOOCLook and CmdOOC, which does the parsing of the 'playable' characters already at the parse() step, storing the result in the .playable property on the (player-) command. This technique could probably be applied to other player commands looking up the _playable_characters Attribute, in order to centralize it.

This commit is contained in:
Griatch 2015-11-01 17:13:00 +01:00
parent c51ccd5bc7
commit c58f858339
5 changed files with 111 additions and 66 deletions

View file

@ -2003,7 +2003,7 @@ class CmdExamine(ObjManipCommand):
obj = caller.location obj = caller.location
if not obj.access(caller, 'examine'): if not obj.access(caller, 'examine'):
#If we don't have special info access, just look at the object instead. #If we don't have special info access, just look at the object instead.
caller.look(obj.name) self.msg(caller.at_look(obj))
return return
# using callback for printing result whenever function returns. # using callback for printing result whenever function returns.
get_and_merge_cmdsets(obj, self.session, self.player, obj, "object").addCallback(get_cmdset_callback) get_and_merge_cmdsets(obj, self.session, self.player, obj, "object").addCallback(get_cmdset_callback)
@ -2033,7 +2033,7 @@ class CmdExamine(ObjManipCommand):
if not obj.access(caller, 'examine'): if not obj.access(caller, 'examine'):
#If we don't have special info access, just look #If we don't have special info access, just look
# at the object instead. # at the object instead.
caller.look(obj_name) self.msg(caller.at_look(obj))
continue continue
if obj_attrs: if obj_attrs:

View file

@ -58,7 +58,16 @@ class CmdLook(MuxCommand):
""" """
Handle the looking. Handle the looking.
""" """
self.caller.look(self.args) if not self.args:
target = self.caller.location
if not target:
self.caller.msg("You have no location to look at!")
return
else:
target = self.caller.search(self.args)
if not target:
return
self.msg(self.caller.at_look(target))
class CmdNick(MuxCommand): class CmdNick(MuxCommand):

View file

@ -25,25 +25,52 @@ from evennia.server.sessionhandler import SESSIONS
from evennia.commands.default.muxcommand import MuxPlayerCommand from evennia.commands.default.muxcommand import MuxPlayerCommand
from evennia.utils import utils, create, search, prettytable from evennia.utils import utils, create, search, prettytable
MAX_NR_CHARACTERS = settings.MAX_NR_CHARACTERS _MAX_NR_CHARACTERS = settings.MAX_NR_CHARACTERS
MULTISESSION_MODE = settings.MULTISESSION_MODE _MULTISESSION_MODE = settings.MULTISESSION_MODE
# limit symbol import for API # limit symbol import for API
__all__ = ("CmdOOCLook", "CmdIC", "CmdOOC", "CmdPassword", "CmdQuit", __all__ = ("CmdOOCLook", "CmdIC", "CmdOOC", "CmdPassword", "CmdQuit",
"CmdCharCreate", "CmdOption", "CmdSessions", "CmdWho", "CmdCharCreate", "CmdOption", "CmdSessions", "CmdWho",
"CmdColorTest", "CmdQuell") "CmdColorTest", "CmdQuell")
# force max nr chars to 1 if mode is 0 or 1
BASE_PLAYER_TYPECLASS = settings.BASE_PLAYER_TYPECLASS
PERMISSION_HIERARCHY = settings.PERMISSION_HIERARCHY class MuxPlayerLookCommand(MuxPlayerCommand):
PERMISSION_HIERARCHY_LOWER = [perm.lower() for perm in PERMISSION_HIERARCHY] """
Custom parent (only) parsing for OOC looking, sets a "playable"
property on the command based on the parsing.
"""
def parse(self):
"Custom parsing"
super(MuxPlayerLookCommand, self).parse()
if _MULTISESSION_MODE < 2:
# only one character allowed - not used in this mode
self.playable = None
return
playable = self.player.db._playable_characters
if playable is not None:
# clean up list if character object was deleted in between
if None in playable:
playable = [character for character in playable if character]
self.player.db._playable_characters = playable
# store playable property
if self.args:
self.playable = dict((utils.to_str(char.key.lower()), char)
for char in playable).get(self.args.lower(), None)
else:
self.playable = playable
# Obs - these are all intended to be stored on the Player, and as such, # Obs - these are all intended to be stored on the Player, and as such,
# use self.player instead of self.caller, just to be sure. Also self.msg() # use self.player instead of self.caller, just to be sure. Also self.msg()
# is used to make sure returns go to the right session # is used to make sure returns go to the right session
class CmdOOCLook(MuxPlayerCommand): # note that this is inheriting from MuxPlayerLookCommand,
# and has the .playable property.
class CmdOOCLook(MuxPlayerLookCommand):
""" """
look while out-of-character look while out-of-character
@ -65,7 +92,14 @@ class CmdOOCLook(MuxPlayerCommand):
def func(self): def func(self):
"implement the ooc look command" "implement the ooc look command"
self.player.look(self.args, sessid=self.sessid)
if _MULTISESSION_MODE < 2:
# only one character allowed
self.msg("You are out-of-character (OOC).\nUse {w@ic{n to get back into the game.")
return
# call on-player look helper method
self.msg(self.player.at_look(target=self.playable, sessid=self.sessid))
class CmdCharCreate(MuxPlayerCommand): class CmdCharCreate(MuxPlayerCommand):
@ -93,7 +127,7 @@ class CmdCharCreate(MuxPlayerCommand):
key = self.lhs key = self.lhs
desc = self.rhs desc = self.rhs
charmax = MAX_NR_CHARACTERS if MULTISESSION_MODE > 1 else 1 charmax = _MAX_NR_CHARACTERS if _MULTISESSION_MODE > 1 else 1
if not player.is_superuser and \ if not player.is_superuser and \
(player.db._playable_characters and (player.db._playable_characters and
@ -175,7 +209,9 @@ class CmdIC(MuxPlayerCommand):
self.msg("{rYou cannot become {C%s{n: %s" % (new_character.name, exc)) self.msg("{rYou cannot become {C%s{n: %s" % (new_character.name, exc))
class CmdOOC(MuxPlayerCommand): # note that this is inheriting from MuxPlayerLookCommand,
# and as such has the .playable property.
class CmdOOC(MuxPlayerLookCommand):
""" """
stop puppeting and go ooc stop puppeting and go ooc
@ -210,7 +246,14 @@ class CmdOOC(MuxPlayerCommand):
try: try:
player.unpuppet_object(sessid) player.unpuppet_object(sessid)
self.msg("\n{GYou go OOC.{n\n") self.msg("\n{GYou go OOC.{n\n")
player.look(sessid=sessid)
if _MULTISESSION_MODE < 2:
# only one character allowed
self.msg("You are out-of-character (OOC).\nUse {w@ic{n to get back into the game.")
return
self.msg(player.at_look(target=self.playable, sessid=sessid))
except RuntimeError as exc: except RuntimeError as exc:
self.msg("{rCould not unpuppet from {c%s{n: %s" % (old_char, exc)) self.msg("{rCould not unpuppet from {c%s{n: %s" % (old_char, exc))

View file

@ -1289,34 +1289,27 @@ class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)):
string += "\n{wYou see:{n " + ", ".join(users + things) string += "\n{wYou see:{n " + ", ".join(users + things)
return string return string
def look(self, arg_string=None): def at_look(self, target):
""" """
This is called whenever this object looks at something. Called when this object performs a look. It allows to
customize just what this means. It will not itself
send any data.
Args: Args:
arg_string (str, optional): The string of what is being looked at. target (Object): The target being looked at. This is
""" commonly an object or the current location. It will
if arg_string: be checked for the "view" type access.
# Use search to handle duplicate/nonexistant results.
looking_at_obj = self.search(arg_string, use_nicks=True)
if not looking_at_obj:
return
else:
looking_at_obj = self.location
if not looking_at_obj:
self.msg("You have no location to look at!")
return
if not hasattr(looking_at_obj, 'return_appearance'): Returns:
# this is likely due to us having a player instead lookstring (str): A ready-processed look string
looking_at_obj = looking_at_obj.character potentially ready to return to the looker.
if not looking_at_obj.access(self, "view"):
self.msg("Could not find '%s'." % args) """
return if not target.access(self, "view"):
# get object's appearance return "Could not find '%s'." % target
self.msg(looking_at_obj.return_appearance(self)) # the target's at_desc() method.
# the object's at_desc() method. target.at_desc(looker=self)
looking_at_obj.at_desc(looker=self) return target.return_appearance(self)
def at_desc(self, looker=None): def at_desc(self, looker=None):
""" """
@ -1408,7 +1401,7 @@ class DefaultCharacter(DefaultObject):
We make sure to look around after a move. We make sure to look around after a move.
""" """
self.look() self.msg(self.at_look(self.location))
def at_pre_puppet(self, player, sessid=None): def at_pre_puppet(self, player, sessid=None):
""" """
@ -1440,7 +1433,8 @@ class DefaultCharacter(DefaultObject):
""" """
self.msg("\nYou become {c%s{n.\n" % self.name) self.msg("\nYou become {c%s{n.\n" % self.name)
self.look() self.msg(self.at_look(self.location))
def message(obj, from_obj): def message(obj, from_obj):
obj.msg("%s has entered the game." % self.get_display_name(obj), from_obj=from_obj) obj.msg("%s has entered the game." % self.get_display_name(obj), from_obj=from_obj)
self.location.for_contents(message, exclude=[self], from_obj=self) self.location.for_contents(message, exclude=[self], from_obj=self)

View file

@ -21,7 +21,7 @@ from evennia.comms.models import ChannelDB
from evennia.commands import cmdhandler from evennia.commands import cmdhandler
from evennia.utils import logger from evennia.utils import logger
from evennia.utils.utils import (lazy_property, to_str, from evennia.utils.utils import (lazy_property, to_str,
make_iter, to_unicode, make_iter, to_unicode, is_iter,
variable_from_module) variable_from_module)
from evennia.typeclasses.attributes import NickHandler from evennia.typeclasses.attributes import NickHandler
from evennia.scripts.scripthandler import ScriptHandler from evennia.scripts.scripthandler import ScriptHandler
@ -700,7 +700,7 @@ class DefaultPlayer(with_metaclass(TypeclassBase, PlayerDB)):
elif _MULTISESSION_MODE in (2, 3): elif _MULTISESSION_MODE in (2, 3):
# In this mode we by default end up at a character selection # In this mode we by default end up at a character selection
# screen. We execute look on the player. # screen. We execute look on the player.
self.look(sessid=sessid) self.msg(self.at_look(sessid=sessid))
def at_failed_login(self, session): def at_failed_login(self, session):
""" """
@ -765,29 +765,28 @@ class DefaultPlayer(with_metaclass(TypeclassBase, PlayerDB)):
""" """
pass pass
def look(self, arg_string=None, sessid=None): def at_look(self, target=None, sessid=None):
if _MULTISESSION_MODE < 2: """
# only one character allowed Called when this object executes a look. It allows to customize
string = "You are out-of-character (OOC).\nUse {w@ic{n to get back into the game." just what this means.
self.msg(string)
elif arg_string:
key = arg_string.lower()
chars = dict((to_str(char.key.lower()), char)
for char in self.db._playable_characters)
looktarget = chars.get(key)
if looktarget:
self.msg(looktarget.return_appearance(self))
else:
self.msg("No such character.")
else:
# get all our characters and sessions
characters = self.db._playable_characters
if characters is not None: Args:
if None in characters: target (Object or list, optional): An object or a list
# clean up list if character object was deleted in between objects to inspect.
characters = [character for character in characters if character] sessid (int, optional): Id of the session doing this look.
self.db._playable_characters = characters
Returns:
look_string (str): A prepared look string, ready to send
off to any recipient (usually to ourselves)
"""
if target and not is_iter(target):
# single target - just show it
return target.return_appearance()
else:
# list of targets - make list
characters = target
sessions = self.get_all_sessions() sessions = self.get_all_sessions()
is_su = self.is_superuser is_su = self.is_superuser
@ -826,7 +825,7 @@ class DefaultPlayer(with_metaclass(TypeclassBase, PlayerDB)):
if csessid: if csessid:
# character is already puppeted # character is already puppeted
sessi = self.get_session(csessid) sessi = self.get_session(csessid)
for sess in utils.make_iter(sessi): for sess in make_iter(sessi):
sid = sess in sessions and sessions.index(sess) + 1 sid = sess in sessions and sessions.index(sess) + 1
if sess and sid: if sess and sid:
string += "\n - {G%s{n [%s] (played by you in session %i)" % (char.key, ", ".join(char.permissions.all()), sid) string += "\n - {G%s{n [%s] (played by you in session %i)" % (char.key, ", ".join(char.permissions.all()), sid)
@ -836,7 +835,7 @@ class DefaultPlayer(with_metaclass(TypeclassBase, PlayerDB)):
# character is "free to puppet" # character is "free to puppet"
string += "\n - %s [%s]" % (char.key, ", ".join(char.permissions.all())) string += "\n - %s [%s]" % (char.key, ", ".join(char.permissions.all()))
string = ("-" * 68) + "\n" + string + "\n" + ("-" * 68) string = ("-" * 68) + "\n" + string + "\n" + ("-" * 68)
self.msg(string) return string
class DefaultGuest(DefaultPlayer): class DefaultGuest(DefaultPlayer):