diff --git a/evennia/commands/cmdhandler.py b/evennia/commands/cmdhandler.py index 135235d8cd..0f13774780 100644 --- a/evennia/commands/cmdhandler.py +++ b/evennia/commands/cmdhandler.py @@ -100,7 +100,7 @@ def _msg_err(receiver, string): string (str): string with a {traceback} format marker inside it. """ - receiver.msg(string.format(traceback=format_exc())) + receiver.msg(string.format(traceback=format_exc(), _nomulti=True)) # custom Exceptions @@ -411,15 +411,18 @@ def cmdhandler(called_by, raw_string, _testing=False, callertype="session", sess elif callertype == "player": player = called_by if sessid: + session = player.get_session(sessid) obj = yield player.get_puppet(sessid) elif callertype == "object": obj = called_by else: raise RuntimeError("cmdhandler: callertype %s is not valid." % callertype) - # the caller will be the one to receive messages and excert its permissions. # we assign the caller with preference 'bottom up' caller = obj or player or session + # The error_to is the default recipient for errors. Tries to make sure a player + # does not get spammed for errors while preserving character mirroring. + error_to = obj or session or player try: # catch bugs in cmdhandler itself try: # catch special-type commands @@ -470,7 +473,7 @@ def cmdhandler(called_by, raw_string, _testing=False, callertype="session", sess # No commands match our entered command syscmd = yield cmdset.get(CMD_NOMATCH) if syscmd: - # use custom CMD_NOMATH command + # use custom CMD_NOMATCH command sysarg = raw_string else: # fallback to default error text @@ -516,19 +519,19 @@ def cmdhandler(called_by, raw_string, _testing=False, callertype="session", sess returnValue(ret) elif sysarg: # return system arg - caller.msg(exc.sysarg) + error_to.msg(exc.sysarg, _nomulti=True) except NoCmdSets: # Critical error. logger.log_errmsg("No cmdsets found: %s" % caller) - caller.msg(_ERROR_NOCMDSETS) + error_to.msg(_ERROR_NOCMDSETS, _nomulti=True) except Exception: # We should not end up here. If we do, it's a programming bug. logger.log_trace() - _msg_err(caller, _ERROR_UNTRAPPED) + _msg_err(error_to, _ERROR_UNTRAPPED) except Exception: # This catches exceptions in cmdhandler exceptions themselves logger.log_trace() - _msg_err(caller, _ERROR_CMDHANDLER) + _msg_err(error_to, _ERROR_CMDHANDLER) diff --git a/evennia/commands/default/syscommands.py b/evennia/commands/default/syscommands.py index c4c83406e3..29953f7d7a 100644 --- a/evennia/commands/default/syscommands.py +++ b/evennia/commands/default/syscommands.py @@ -61,7 +61,7 @@ class SystemNoMatch(MuxCommand): """ This is given the failed raw string as input. """ - self.caller.msg("Huh?") + self.msg("Huh?") # @@ -124,7 +124,7 @@ class SystemMultimatch(MuxCommand): all the clashing matches. """ string = self.format_multimatches(self.caller, self.matches) - self.caller.msg(string) + self.msg(string) # Command called when the command given at the command line diff --git a/evennia/objects/objects.py b/evennia/objects/objects.py index 5707e879a4..6270ac250a 100644 --- a/evennia/objects/objects.py +++ b/evennia/objects/objects.py @@ -533,18 +533,12 @@ class DefaultObject(ObjectDB): if self.player: # for there to be a session there must be a Player. if sessid: - # this could still be an iterable if sessid is. - sessions = self.player.get_session(sessid) - if sessions: - # this is a special instruction to ignore MULTISESSION_MODE - # and only relay to this given session. - for session in make_iter(sessions): - session.msg(text=text, **kwargs) - return - # Send to all sessions connected to this object - sessions = [self.player.get_session(sessid) for sessid in self.sessid.get()] + sessions = make_iter(self.player.get_session(sessid)) + else: + # Send to all sessions connected to this object + sessions = [self.player.get_session(sessid) for sessid in self.sessid.get()] if sessions: - sessions[0].msg(text=text, **kwargs) + sessions[0].msg(text=text, session=sessions, **kwargs) def msg_contents(self, message, exclude=None, from_obj=None, **kwargs): """ diff --git a/evennia/players/players.py b/evennia/players/players.py index 92dcc06aa0..bce1882144 100644 --- a/evennia/players/players.py +++ b/evennia/players/players.py @@ -231,7 +231,6 @@ class DefaultPlayer(PlayerDB): # re-cache locks to make sure superuser bypass is updated obj.locks.cache_lock_bypass(obj) - def unpuppet_object(self, sessid): """ Disengage control over an object diff --git a/evennia/server/serversession.py b/evennia/server/serversession.py index abf5b7b0cb..13c6565f8e 100644 --- a/evennia/server/serversession.py +++ b/evennia/server/serversession.py @@ -222,7 +222,9 @@ class ServerSession(Session): text = text if text else "" if INLINEFUNC_ENABLED and not "raw" in kwargs: text = parse_inlinefunc(text, strip="strip_inlinefunc" in kwargs, session=self) - self.sessionhandler.data_out(self, text=text, **kwargs) + session = kwargs.pop('session', None) + session = session or self + self.sessionhandler.data_out(session, text=text, **kwargs) # alias msg = data_out diff --git a/evennia/server/sessionhandler.py b/evennia/server/sessionhandler.py index fde52dbb6b..ad094c7794 100644 --- a/evennia/server/sessionhandler.py +++ b/evennia/server/sessionhandler.py @@ -16,7 +16,8 @@ import time from django.conf import settings from evennia.commands.cmdhandler import CMD_LOGINSTART from evennia.utils.utils import variable_from_module, is_iter, \ - to_str, to_unicode, strip_control_sequences + to_str, to_unicode, strip_control_sequences, make_iter + try: import cPickle as pickle except ImportError: @@ -454,10 +455,10 @@ class ServerSessionHandler(SessionHandler): Useful for connection handling messages. """ - text = text and to_str(to_unicode(text), encoding=session.encoding) + sessions = make_iter(session) + text = text and to_str(to_unicode(text), encoding=sessions[0].encoding) multi = not kwargs.pop("_nomulti", None) forced_nomulti = kwargs.pop("_forced_nomulti", None) - sessions = [session] # Mode 1 mirrors to all. if _MULTISESSION_MODE == 1: multi = True