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.session = session
cmd.player = player cmd.player = player
cmd.raw_string = unformatted_raw_string 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'): if hasattr(cmd, 'obj') and hasattr(cmd.obj, 'scripts'):
# cmd.obj is automatically made available by the cmdhandler. # cmd.obj is automatically made available by the cmdhandler.

View file

@ -215,7 +215,6 @@ def format_script_list(scripts):
for script in scripts: for script in scripts:
nextrep = script.time_until_next_repeat() nextrep = script.time_until_next_repeat()
print type(script), print type(script),
print script.key
table.add_row([script.id, table.add_row([script.id,
script.obj.key if (hasattr(script, 'obj') and script.obj) else "<Global>", script.obj.key if (hasattr(script, 'obj') and script.obj) else "<Global>",
script.key, script.key,

View file

@ -37,6 +37,7 @@ from django.utils.translation import ugettext as _
_ScriptDB = None _ScriptDB = None
_AT_SEARCH_RESULT = variable_from_module(*settings.SEARCH_AT_RESULT.rsplit('.', 1)) _AT_SEARCH_RESULT = variable_from_module(*settings.SEARCH_AT_RESULT.rsplit('.', 1))
_SESSIONS = None
_GA = object.__getattribute__ _GA = object.__getattribute__
_SA = object.__setattr__ _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 set to 0 (default), use either from_obj.sessid (if set) or self.sessid automatically
If None, echo to all connected sessions 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: if "data" in kwargs:
# deprecation warning
from src.utils import logger from src.utils import logger
logger.log_depmsg("ObjectDB.msg(): 'data'-dict keyword is deprecated. Use **kwargs instead.") logger.log_depmsg("ObjectDB.msg(): 'data'-dict keyword is deprecated. Use **kwargs instead.")
data = kwargs.pop("data") data = kwargs.pop("data")
if isinstance(data, dict): if isinstance(data, dict):
kwargs.update(data) kwargs.update(data)
if _GA(self, 'player'): if from_obj:
# note that we must call the player *typeclass'* msg(), otherwise one couldn't overload it. # call hook
if not sessid: try:
if from_obj and hasattr(from_obj, "sessid"): _GA(from_obj, "at_msg_send")(text=text, to_obj=self, **kwargs)
sessid = from_obj.sessid except Exception:
elif hasattr(self, "sessid"): pass
sessid = self.sessid
_GA(_GA(self, 'player'), "typeclass").msg(text=text, from_obj=from_obj, sessid=sessid, **kwargs) 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): 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 Note that this method is executed on the object
passed along with the msg() function (i.e. using 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. and if no object was passed, it will never be called.
""" """
pass 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. This is the main route for sending data back to the user from the server.
outgoing_string (string) - text data to send 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 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 all sessions connected to this player. This is usually only
relevant when using msg() directly from a player-command (from 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. kwargs (dict) - All other keywords are parsed as extra data.
""" """
if "data" in kwargs: if "data" in kwargs:
# deprecation warning
from src.utils import logger from src.utils import logger
logger.log_depmsg("PlayerDB:msg() 'data'-dict keyword is deprecated. Use **kwargs instead.") logger.log_depmsg("PlayerDB:msg() 'data'-dict keyword is deprecated. Use **kwargs instead.")
data = kwargs.pop("data") data = kwargs.pop("data")
if isinstance(data, dict): if isinstance(data, dict):
kwargs.update(data) kwargs.update(data)
text = utils.to_str(text, force_string=True) if text else ""
if from_obj: if from_obj:
# call hook # call hook
try: try:
_GA(from_obj, "at_msg_send")(text=text, to_obj=self, **kwargs) _GA(from_obj, "at_msg_send")(text=text, to_obj=self, **kwargs)
except Exception: except Exception:
pass pass
outgoing_string = utils.to_str(text, force_string=True)
session = _MULTISESSION_MODE == 2 and sessid and _GA(self, "get_session")(sessid) or None session = _MULTISESSION_MODE == 2 and sessid and _GA(self, "get_session")(sessid) or None
if session: if session:
obj = session.puppet obj = session.puppet
@ -289,33 +290,6 @@ class PlayerDB(TypedObject, AbstractUser):
for sess in _GA(self, 'get_all_sessions')(): for sess in _GA(self, 'get_all_sessions')():
sess.msg(text=text, **kwargs) 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 # session-related methods
def get_session(self, sessid): def get_session(self, sessid):

View file

@ -164,7 +164,7 @@ class ServerSession(Session):
def data_in(self, text=None, **kwargs): 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. execute a command string on the server.
Eventual extra data moves through oob_data_in Eventual extra data moves through oob_data_in
""" """
@ -185,14 +185,13 @@ class ServerSession(Session):
def data_out(self, text=None, **kwargs): def data_out(self, text=None, **kwargs):
""" """
Send Evennia -> Player Send Evennia -> User
""" """
self.sessionhandler.data_out(self, text=text, **kwargs) self.sessionhandler.data_out(self, text=text, **kwargs)
def __eq__(self, other): def __eq__(self, other):
return self.address == other.address return self.address == other.address
def __str__(self): def __str__(self):
""" """
String representation of the user session class. We use String representation of the user session class. We use

View file

@ -93,7 +93,6 @@ class SharedMemoryModelBase(ModelBase):
elif hasattr(value, "typeclass"): elif hasattr(value, "typeclass"):
return _GA(value, "typeclass") return _GA(value, "typeclass")
return value return value
def _set_nonedit(cls, fname, value): def _set_nonedit(cls, fname, value):
"Wrapper for blocking editing of field" "Wrapper for blocking editing of field"
raise FieldError("Field %s cannot be edited." % fname) 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) #print "_set wrapper:", fname, value, type(value), cls._get_pk_val(cls._meta)
_SA(cls, fname, value) _SA(cls, fname, value)
# only use explicit update_fields in save if we actually have a # 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 update_fields = [fname] if _GA(cls, "_get_pk_val")(_GA(cls, "_meta")) is not None else None
_GA(cls, "save")(update_fields=update_fields) _GA(cls, "save")(update_fields=update_fields)
def _del_nonedit(cls, fname): def _del_nonedit(cls, fname):
"wrapper for not allowing deletion" "wrapper for not allowing deletion"
raise FieldError("Field %s cannot be edited." % fname) 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 update_fields = [fname] if _GA(cls, "_get_pk_val")(_GA(cls, "_meta")) is not None else None
_GA(cls, "save")(update_fields=update_fields) _GA(cls, "save")(update_fields=update_fields)
# create class wrappers # create class field wrappers
fget = lambda cls: _get(cls, fieldname) fget = lambda cls: _get(cls, fieldname)
fset = lambda cls, val: _set(cls, fieldname, val) if editable else _set_nonedit(cls, fieldname, val) 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) 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 # exclude some models that should not auto-create wrapper fields
if cls.__name__ in ("ServerConfig", "TypeNick"): if cls.__name__ in ("ServerConfig", "TypeNick"):
@ -142,13 +140,12 @@ class SharedMemoryModelBase(ModelBase):
# dynamically create the wrapper properties for all fields not already handled # dynamically create the wrapper properties for all fields not already handled
for field in cls._meta.fields: for field in cls._meta.fields:
fieldname = field.name fieldname = field.name
if not fieldname.startswith("db_"): if fieldname.startswith("db_"):
continue wrappername = "dbid" if fieldname == "id" else fieldname.replace("db_", "")
wrappername = "dbid" if fieldname == "id" else fieldname.replace("db_", "") if not hasattr(cls, wrappername):
if not hasattr(cls, wrappername): # makes sure not to overload manually created wrappers on the model
# makes sure not to overload manually created wrappers on the model #print "wrapping %s -> %s" % (fieldname, wrappername)
#print "wrapping %s -> %s" % (fieldname, wrappername) create_wrapper(cls, fieldname, wrappername, editable=field.editable)
create_wrapper(cls, fieldname, wrappername, editable=field.editable)
class SharedMemoryModel(Model): class SharedMemoryModel(Model):
# CL: setting abstract correctly to allow subclasses to inherit the default # CL: setting abstract correctly to allow subclasses to inherit the default