Changed object.msg() to relay directly to connected session rather than via the player.msg() method.

This commit is contained in:
Griatch 2013-09-22 11:39:24 +02:00
parent dd27b4b77d
commit 4659ddbfc3
7 changed files with 37 additions and 56 deletions

View file

@ -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.

View file

@ -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 "<Global>",
script.key,

View file

@ -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):
"""

View file

@ -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

View file

@ -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):

View file

@ -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

View file

@ -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