diff --git a/evennia/commands/default/building.py b/evennia/commands/default/building.py index 5b632c276..ed49223de 100644 --- a/evennia/commands/default/building.py +++ b/evennia/commands/default/building.py @@ -2003,7 +2003,7 @@ class CmdExamine(ObjManipCommand): obj = caller.location if not obj.access(caller, 'examine'): #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 # using callback for printing result whenever function returns. 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 we don't have special info access, just look # at the object instead. - caller.look(obj_name) + self.msg(caller.at_look(obj)) continue if obj_attrs: diff --git a/evennia/commands/default/general.py b/evennia/commands/default/general.py index 9b1916181..422648de2 100644 --- a/evennia/commands/default/general.py +++ b/evennia/commands/default/general.py @@ -58,7 +58,16 @@ class CmdLook(MuxCommand): """ 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): diff --git a/evennia/commands/default/player.py b/evennia/commands/default/player.py index ec6ad4df9..b61f1c98d 100644 --- a/evennia/commands/default/player.py +++ b/evennia/commands/default/player.py @@ -25,25 +25,52 @@ from evennia.server.sessionhandler import SESSIONS from evennia.commands.default.muxcommand import MuxPlayerCommand from evennia.utils import utils, create, search, prettytable -MAX_NR_CHARACTERS = settings.MAX_NR_CHARACTERS -MULTISESSION_MODE = settings.MULTISESSION_MODE +_MAX_NR_CHARACTERS = settings.MAX_NR_CHARACTERS +_MULTISESSION_MODE = settings.MULTISESSION_MODE # limit symbol import for API __all__ = ("CmdOOCLook", "CmdIC", "CmdOOC", "CmdPassword", "CmdQuit", "CmdCharCreate", "CmdOption", "CmdSessions", "CmdWho", "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 -PERMISSION_HIERARCHY_LOWER = [perm.lower() for perm in PERMISSION_HIERARCHY] +class MuxPlayerLookCommand(MuxPlayerCommand): + """ + 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, # 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 -class CmdOOCLook(MuxPlayerCommand): +# note that this is inheriting from MuxPlayerLookCommand, +# and has the .playable property. +class CmdOOCLook(MuxPlayerLookCommand): """ look while out-of-character @@ -65,7 +92,14 @@ class CmdOOCLook(MuxPlayerCommand): def func(self): "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): @@ -93,7 +127,7 @@ class CmdCharCreate(MuxPlayerCommand): key = self.lhs 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 \ (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)) -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 @@ -210,7 +246,14 @@ class CmdOOC(MuxPlayerCommand): try: player.unpuppet_object(sessid) 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: self.msg("{rCould not unpuppet from {c%s{n: %s" % (old_char, exc)) diff --git a/evennia/objects/objects.py b/evennia/objects/objects.py index 4df6dd144..ffd0fbe46 100644 --- a/evennia/objects/objects.py +++ b/evennia/objects/objects.py @@ -1289,34 +1289,27 @@ class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)): string += "\n{wYou see:{n " + ", ".join(users + things) 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: - arg_string (str, optional): The string of what is being looked at. - """ - if arg_string: - # 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 + target (Object): The target being looked at. This is + commonly an object or the current location. It will + be checked for the "view" type access. - if not hasattr(looking_at_obj, 'return_appearance'): - # this is likely due to us having a player instead - looking_at_obj = looking_at_obj.character - if not looking_at_obj.access(self, "view"): - self.msg("Could not find '%s'." % args) - return - # get object's appearance - self.msg(looking_at_obj.return_appearance(self)) - # the object's at_desc() method. - looking_at_obj.at_desc(looker=self) + Returns: + lookstring (str): A ready-processed look string + potentially ready to return to the looker. + + """ + if not target.access(self, "view"): + return "Could not find '%s'." % target + # the target's at_desc() method. + target.at_desc(looker=self) + return target.return_appearance(self) def at_desc(self, looker=None): """ @@ -1408,7 +1401,7 @@ class DefaultCharacter(DefaultObject): 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): """ @@ -1440,7 +1433,8 @@ class DefaultCharacter(DefaultObject): """ self.msg("\nYou become {c%s{n.\n" % self.name) - self.look() + self.msg(self.at_look(self.location)) + def message(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) diff --git a/evennia/players/players.py b/evennia/players/players.py index baf820a69..7c4a30266 100644 --- a/evennia/players/players.py +++ b/evennia/players/players.py @@ -21,7 +21,7 @@ from evennia.comms.models import ChannelDB from evennia.commands import cmdhandler from evennia.utils import logger from evennia.utils.utils import (lazy_property, to_str, - make_iter, to_unicode, + make_iter, to_unicode, is_iter, variable_from_module) from evennia.typeclasses.attributes import NickHandler from evennia.scripts.scripthandler import ScriptHandler @@ -700,7 +700,7 @@ class DefaultPlayer(with_metaclass(TypeclassBase, PlayerDB)): elif _MULTISESSION_MODE in (2, 3): # In this mode we by default end up at a character selection # screen. We execute look on the player. - self.look(sessid=sessid) + self.msg(self.at_look(sessid=sessid)) def at_failed_login(self, session): """ @@ -765,29 +765,28 @@ class DefaultPlayer(with_metaclass(TypeclassBase, PlayerDB)): """ pass - def look(self, arg_string=None, sessid=None): - if _MULTISESSION_MODE < 2: - # only one character allowed - string = "You are out-of-character (OOC).\nUse {w@ic{n to get back into the game." - 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 + def at_look(self, target=None, sessid=None): + """ + Called when this object executes a look. It allows to customize + just what this means. - if characters is not None: - if None in characters: - # clean up list if character object was deleted in between - characters = [character for character in characters if character] - self.db._playable_characters = characters + Args: + target (Object or list, optional): An object or a list + objects to inspect. + sessid (int, optional): Id of the session doing this look. + + 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() is_su = self.is_superuser @@ -826,7 +825,7 @@ class DefaultPlayer(with_metaclass(TypeclassBase, PlayerDB)): if csessid: # character is already puppeted 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 if sess and 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" string += "\n - %s [%s]" % (char.key, ", ".join(char.permissions.all())) string = ("-" * 68) + "\n" + string + "\n" + ("-" * 68) - self.msg(string) + return string class DefaultGuest(DefaultPlayer):