diff --git a/src/commands/cmdhandler.py b/src/commands/cmdhandler.py index b39b106cf6..adf2e9a960 100644 --- a/src/commands/cmdhandler.py +++ b/src/commands/cmdhandler.py @@ -347,7 +347,9 @@ def cmdhandler(called_on, raw_string, testing=False, callertype="session", sessi cmd.session = session cmd.player = player cmd.raw_string = unformatted_raw_string - #cmd.obj # set via command handler + #cmd.obj # set via on-object cmdset handler for each command, + # since this may be different for every command when + # merging multuple cmdsets if hasattr(cmd, 'obj') and hasattr(cmd.obj, 'scripts'): # cmd.obj is automatically made available by the cmdhandler. diff --git a/src/commands/default/system.py b/src/commands/default/system.py index 0a7b043679..7f617f1316 100644 --- a/src/commands/default/system.py +++ b/src/commands/default/system.py @@ -215,7 +215,6 @@ def format_script_list(scripts): for script in scripts: nextrep = script.time_until_next_repeat() print type(script), - print script.key table.add_row([script.id, script.obj.key if (hasattr(script, 'obj') and script.obj) else "", script.key, diff --git a/src/objects/models.py b/src/objects/models.py index c6d0d7620b..63ee25707e 100644 --- a/src/objects/models.py +++ b/src/objects/models.py @@ -37,6 +37,7 @@ from django.utils.translation import ugettext as _ _ScriptDB = None _AT_SEARCH_RESULT = variable_from_module(*settings.SEARCH_AT_RESULT.rsplit('.', 1)) +_SESSIONS = None _GA = object.__getattribute__ _SA = object.__setattr__ @@ -670,21 +671,30 @@ class ObjectDB(TypedObject): If set to 0 (default), use either from_obj.sessid (if set) or self.sessid automatically If None, echo to all connected sessions """ + global _SESSIONS + if not _SESSIONS: + from src.server.sessionhandler import SESSIONS as _SESSIONS + + text = utils.to_str(text, force_string=True) if text else "" + if "data" in kwargs: + # deprecation warning from src.utils import logger logger.log_depmsg("ObjectDB.msg(): 'data'-dict keyword is deprecated. Use **kwargs instead.") data = kwargs.pop("data") if isinstance(data, dict): kwargs.update(data) - if _GA(self, 'player'): - # note that we must call the player *typeclass'* msg(), otherwise one couldn't overload it. - if not sessid: - if from_obj and hasattr(from_obj, "sessid"): - sessid = from_obj.sessid - elif hasattr(self, "sessid"): - sessid = self.sessid - _GA(_GA(self, 'player'), "typeclass").msg(text=text, from_obj=from_obj, sessid=sessid, **kwargs) + if from_obj: + # call hook + try: + _GA(from_obj, "at_msg_send")(text=text, to_obj=self, **kwargs) + except Exception: + pass + + session = _SESSIONS.session_from_sessid(sessid if sessid else _GA(self, "sessid")) + if session: + session.msg(text=text, **kwargs) def msg_contents(self, message, exclude=None, from_obj=None, **kwargs): """ diff --git a/src/objects/objects.py b/src/objects/objects.py index e090be4c59..b58a673c57 100644 --- a/src/objects/objects.py +++ b/src/objects/objects.py @@ -682,7 +682,7 @@ class Object(TypeClass): Note that this method is executed on the object passed along with the msg() function (i.e. using - obj.msg(msg, caller) will then launch caller.at_msg()) + obj.msg(msg, from_obj=caller) will then launch caller.at_msg()) and if no object was passed, it will never be called. """ pass diff --git a/src/players/models.py b/src/players/models.py index 52ef760879..f1fc818be9 100644 --- a/src/players/models.py +++ b/src/players/models.py @@ -254,7 +254,8 @@ class PlayerDB(TypedObject, AbstractUser): This is the main route for sending data back to the user from the server. outgoing_string (string) - text data to send - from_obj (Object/Player) - source object of message to send + from_obj (Object/Player) - source object of message to send. Its at_msg_send + hook will be called. sessid - the session id of the session to send to. If not given, return to all sessions connected to this player. This is usually only relevant when using msg() directly from a player-command (from @@ -263,20 +264,20 @@ class PlayerDB(TypedObject, AbstractUser): kwargs (dict) - All other keywords are parsed as extra data. """ if "data" in kwargs: + # deprecation warning from src.utils import logger logger.log_depmsg("PlayerDB:msg() 'data'-dict keyword is deprecated. Use **kwargs instead.") data = kwargs.pop("data") if isinstance(data, dict): kwargs.update(data) + text = utils.to_str(text, force_string=True) if text else "" if from_obj: # call hook try: _GA(from_obj, "at_msg_send")(text=text, to_obj=self, **kwargs) except Exception: pass - outgoing_string = utils.to_str(text, force_string=True) - session = _MULTISESSION_MODE == 2 and sessid and _GA(self, "get_session")(sessid) or None if session: obj = session.puppet @@ -289,33 +290,6 @@ class PlayerDB(TypedObject, AbstractUser): for sess in _GA(self, 'get_all_sessions')(): sess.msg(text=text, **kwargs) - def inmsg(self, ingoing_string, session): - """ - User -> Evennia - This is the reverse of msg - used by sessions to relay - messages/data back into the game. It is not called - from inside game code but only by the serversessions directly. - - ingoing_string - text string (i.e. command string) - data - dictionary of optional data - session - session sending this data (no need to look it up again) - """ - if _MULTISESSION_MODE == 1: - # many sessions - one puppet - sessions = [session for session in self.get_all_sessions() if session.puppet] - session = sessions and sessions[0] or session - - puppet = session.puppet - if puppet: - # execute command on the puppeted object (this will include - # cmdsets both on object and on player) - _GA(puppet, "execute_cmd")(ingoing_string, sessid=session.sessid) - else: - # a non-character session; this executes on player directly - # (this will only include cmdsets on player) - _GA(self, "execute_cmd")(ingoing_string, sessid=session.sessid) - - # session-related methods def get_session(self, sessid): diff --git a/src/server/serversession.py b/src/server/serversession.py index 1952778582..5df372c0c9 100644 --- a/src/server/serversession.py +++ b/src/server/serversession.py @@ -164,7 +164,7 @@ class ServerSession(Session): def data_in(self, text=None, **kwargs): """ - Send Player->Evennia. This will in effect + Send User->Evennia. This will in effect execute a command string on the server. Eventual extra data moves through oob_data_in """ @@ -185,14 +185,13 @@ class ServerSession(Session): def data_out(self, text=None, **kwargs): """ - Send Evennia -> Player + Send Evennia -> User """ self.sessionhandler.data_out(self, text=text, **kwargs) def __eq__(self, other): return self.address == other.address - def __str__(self): """ String representation of the user session class. We use diff --git a/src/utils/idmapper/base.py b/src/utils/idmapper/base.py index b29c399036..1eab91482f 100755 --- a/src/utils/idmapper/base.py +++ b/src/utils/idmapper/base.py @@ -93,7 +93,6 @@ class SharedMemoryModelBase(ModelBase): elif hasattr(value, "typeclass"): return _GA(value, "typeclass") return value - def _set_nonedit(cls, fname, value): "Wrapper for blocking editing of field" raise FieldError("Field %s cannot be edited." % fname) @@ -117,10 +116,9 @@ class SharedMemoryModelBase(ModelBase): #print "_set wrapper:", fname, value, type(value), cls._get_pk_val(cls._meta) _SA(cls, fname, value) # only use explicit update_fields in save if we actually have a - # primary key assigned already (won't be when first creating object) + # primary key assigned already (won't be set when first creating object) update_fields = [fname] if _GA(cls, "_get_pk_val")(_GA(cls, "_meta")) is not None else None _GA(cls, "save")(update_fields=update_fields) - def _del_nonedit(cls, fname): "wrapper for not allowing deletion" raise FieldError("Field %s cannot be edited." % fname) @@ -130,11 +128,11 @@ class SharedMemoryModelBase(ModelBase): update_fields = [fname] if _GA(cls, "_get_pk_val")(_GA(cls, "_meta")) is not None else None _GA(cls, "save")(update_fields=update_fields) - # create class wrappers + # create class field wrappers fget = lambda cls: _get(cls, fieldname) fset = lambda cls, val: _set(cls, fieldname, val) if editable else _set_nonedit(cls, fieldname, val) fdel = lambda cls: _del(cls, fieldname) if editable else _del_nonedit(cls,fieldname) - type(cls).__setattr__(cls, wrappername, property(fget, fset, fdel)) + type(cls).__setattr__(cls, wrappername, property(fget, fset, fdel))#, doc)) # exclude some models that should not auto-create wrapper fields if cls.__name__ in ("ServerConfig", "TypeNick"): @@ -142,13 +140,12 @@ class SharedMemoryModelBase(ModelBase): # dynamically create the wrapper properties for all fields not already handled for field in cls._meta.fields: fieldname = field.name - if not fieldname.startswith("db_"): - continue - wrappername = "dbid" if fieldname == "id" else fieldname.replace("db_", "") - if not hasattr(cls, wrappername): - # makes sure not to overload manually created wrappers on the model - #print "wrapping %s -> %s" % (fieldname, wrappername) - create_wrapper(cls, fieldname, wrappername, editable=field.editable) + if fieldname.startswith("db_"): + wrappername = "dbid" if fieldname == "id" else fieldname.replace("db_", "") + if not hasattr(cls, wrappername): + # makes sure not to overload manually created wrappers on the model + #print "wrapping %s -> %s" % (fieldname, wrappername) + create_wrapper(cls, fieldname, wrappername, editable=field.editable) class SharedMemoryModel(Model): # CL: setting abstract correctly to allow subclasses to inherit the default