diff --git a/src/commands/default/player.py b/src/commands/default/player.py index 009ea4b98f..51c8f1c479 100644 --- a/src/commands/default/player.py +++ b/src/commands/default/player.py @@ -370,7 +370,7 @@ class CmdWho(MuxPlayerCommand): session.protocol_key, isinstance(session.address, tuple) and session.address[0] or session.address]) else: - table = prettytable.PrettyTable(["{wPlayer name", "{wOn for", "{Idle"]) + table = prettytable.PrettyTable(["{wPlayer name", "{wOn for", "{wIdle"]) for session in session_list: if not session.logged_in: continue delta_cmd = time.time() - session.cmd_last_visible diff --git a/src/commands/default/system.py b/src/commands/default/system.py index fe4b56bfeb..da57382afe 100644 --- a/src/commands/default/system.py +++ b/src/commands/default/system.py @@ -404,7 +404,7 @@ class CmdPlayers(MuxCommand): """ key = "@players" aliases = ["@listplayers"] - locks = "cmd:perm(listplayers) or perm(Admins)" + locks = "cmd:perm(listplayers) or perm(Wizards)" def func(self): "List the players" diff --git a/src/objects/models.py b/src/objects/models.py index 7fcb0d7684..d536ce7165 100644 --- a/src/objects/models.py +++ b/src/objects/models.py @@ -658,7 +658,7 @@ class ObjectDB(TypedObject): break return cmdhandler.cmdhandler(_GA(self, "typeclass"), raw_string, callertype="object", sessid=sessid) - def msg(self, msg=None, from_obj=None, data=None, sessid=0): + def msg(self, text=None, **kwargs):#from_obj=None, data=None, sessid=0): """ Emits something to a session attached to the object. @@ -672,13 +672,13 @@ class ObjectDB(TypedObject): """ if _GA(self, 'player'): # note that we must call the player *typeclass'* msg(), otherwise one couldn't overload it. - if sessid == 0: + if kwargs.get("sessid",0) == 0: sessid = None - if from_obj and hasattr(from_obj, "sessid"): - sessid = from_obj.sessid + if "from_obj" in kwargs and hasattr(kwargs["from_obj"], "sessid"): + kwargs["sessid"] = from_obj.sessid elif hasattr(self, "sessid"): - sessid = self.sessid - _GA(_GA(self, 'player'), "typeclass").msg(msg, from_obj=from_obj, data=data, sessid=sessid) + kwargs["sessid"] = self.sessid + _GA(_GA(self, 'player'), "typeclass").msg(text=text, **kwargs)#from_obj=from_obj, data=data, sessid=sessid) def emit_to(self, message, from_obj=None, data=None): "Deprecated. Alias for msg" diff --git a/src/objects/objects.py b/src/objects/objects.py index a6b74c664c..2eea10dc86 100644 --- a/src/objects/objects.py +++ b/src/objects/objects.py @@ -222,7 +222,7 @@ class Object(TypeClass): """ return self.dbobj.execute_cmd(raw_string, sessid=sessid) - def msg(self, message, from_obj=None, data=None, sessid=0): + def msg(self, text=None, **kwargs):#message, from_obj=None, data=None, sessid=0): """ Emits something to any sessions attached to the object. @@ -233,7 +233,7 @@ class Object(TypeClass): sessid: optional session target. If sessid=0, the session will default to self.sessid or from_obj.sessid. """ - self.dbobj.msg(message, from_obj=from_obj, data=data, sessid=0) + self.dbobj.msg(text=text, **kwargs)#message, from_obj=from_obj, data=data, sessid=0) def msg_contents(self, message, exclude=None, from_obj=None, data=None): """ @@ -653,7 +653,7 @@ class Object(TypeClass): """ pass - def at_msg_receive(self, msg, from_obj=None, data=None): + def at_msg_receive(self, text=None, **kwargs):#from_obj=None, data=None): """ This hook is called whenever someone sends a message to this object. @@ -674,7 +674,7 @@ class Object(TypeClass): """ return True - def at_msg_send(self, msg, to_obj=None, data=None): + def at_msg_send(self, text=None, **kwargs):#msg, to_obj=None, data=None): """ This is a hook that is called when /this/ object sends a message to another object with obj.msg() diff --git a/src/players/models.py b/src/players/models.py index 79eecd043b..2e38cc4d0b 100644 --- a/src/players/models.py +++ b/src/players/models.py @@ -248,7 +248,7 @@ class PlayerDB(TypedObject, AbstractUser): # PlayerDB class access methods # - def msg(self, outgoing_string, from_obj=None, data=None, sessid=None): + def msg(self, text=None, **kwargs):#outgoing_string, from_obj=None, data=None, sessid=None): """ Evennia -> User This is the main route for sending data back to the user from the server. @@ -262,25 +262,27 @@ class PlayerDB(TypedObject, AbstractUser): a command on a Character, the character automatically stores and handles the sessid). """ + from_obj = kwargs.pop("from_obj", None) + sessid = kwargs.pop("sessid", 0) if from_obj: # call hook try: - _GA(from_obj, "at_msg_send")(outgoing_string, to_obj=self, data=data) + _GA(from_obj, "at_msg_send")(text=text, to_obj=self, data=data) except Exception: pass - outgoing_string = utils.to_str(outgoing_string, force_string=True) + 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 - if obj and not obj.at_msg_receive(outgoing_string, from_obj=from_obj, data=data): + if obj and not obj.at_msg_receive(text, **kwargs): # if hook returns false, cancel send return - session.msg(outgoing_string, data) + session.msg(text=text, **kwargs) else: # if no session was specified, send to them all for sess in _GA(self, 'get_all_sessions')(): - sess.msg(outgoing_string, data) + sess.msg(text=text, **kwargs) def inmsg(self, ingoing_string, session): """ diff --git a/src/players/player.py b/src/players/player.py index 89db5db450..6f1c4c8b58 100644 --- a/src/players/player.py +++ b/src/players/player.py @@ -96,7 +96,7 @@ class Player(TypeClass): ## methods inherited from database model - def msg(self, outgoing_string, from_obj=None, data=None, sessid=None): + def msg(self, text=None, **kwargs):#outgoing_string, from_obj=None, data=None, sessid=None): """ Evennia -> User This is the main route for sending data back to the user from the server. @@ -110,7 +110,7 @@ class Player(TypeClass): a command on a Character, the character automatically stores and handles the sessid). """ - self.dbobj.msg(outgoing_string, from_obj=from_obj, data=data, sessid=sessid) + self.dbobj.msg(text=text, **kwargs)#outgoing_string, from_obj=from_obj, data=data, sessid=sessid) def swap_character(self, new_character, delete_old_character=False): """ diff --git a/src/server/oobhandler.py b/src/server/oobhandler.py index ca91e8632f..e6467fa64f 100644 --- a/src/server/oobhandler.py +++ b/src/server/oobhandler.py @@ -126,6 +126,14 @@ class OOBHandler(object): self.tracked = defaultdict(dict) self.oobstrings = "" + def parse_commanddict(self, dic): + """ + The command dict is on the form + {functionname:((args), {kwargs}), ...} + It is stored in text form as a pickle. + """ + + def _make_hash(self, callback_key, hashkey): """ diff --git a/src/server/serversession.py b/src/server/serversession.py index 2626eb008e..ff0dbbbcd5 100644 --- a/src/server/serversession.py +++ b/src/server/serversession.py @@ -183,11 +183,11 @@ class ServerSession(Session): self.update_session_counters() execute_cmd = data_in # alias - def data_out(self, msg, data=None): + def data_out(self, text=None, **kwargs): """ Send Evennia -> Player """ - self.sessionhandler.data_out(self, msg, data) + self.sessionhandler.data_out(self, text=text, **kwargs) def oob_data_in(self, data): """ @@ -276,9 +276,9 @@ class ServerSession(Session): #def disconnect(self): # "alias for session_disconnect" # self.session_disconnect() - def msg(self, string='', data=None): + def msg(self, text='', **kwargs): "alias for at_data_out" - self.data_out(string, data=data) + self.data_out(text=text, **kwargs) # Dummy API hooks for use during non-loggedin operation diff --git a/src/server/sessionhandler.py b/src/server/sessionhandler.py index eaa76c7d9a..7dc40cb832 100644 --- a/src/server/sessionhandler.py +++ b/src/server/sessionhandler.py @@ -15,7 +15,14 @@ There are two similar but separate stores of sessions: import time from django.conf import settings from src.commands.cmdhandler import CMD_LOGINSTART -from src.utils.utils import variable_from_module +from src.utils.utils import variable_from_module, to_str +try: + import cPickle as pickle +except ImportError: + import pickle + +dumps = lambda data: to_str(pickle.dumps(data, pickle.HIGHEST_PROTOCOL)) +loads = lambda data: pickle.loads(to_str(data)) # delayed imports _PlayerDB = None @@ -350,20 +357,21 @@ class ServerSessionHandler(SessionHandler): for sess in self.sessions.values(): self.data_out(sess, message) - def data_out(self, session, string="", data=""): + def data_out(self, session, text="", **kwargs): """ Sending data Server -> Portal """ self.server.amp_protocol.call_remote_MsgServer2Portal(sessid=session.sessid, - msg=string, - data=data) - def data_in(self, sessid, string="", data=""): + msg=text, + data=kwargs) + def data_in(self, sessid, text="", data=""): """ Data Portal -> Server """ session = self.sessions.get(sessid, None) if session: - session.data_in(string) + kwargs = data if data else {} + session.data_in(text, **kwargs) # ignore 'data' argument for now; this is otherwise the place # to put custom effects on the server due to data input, e.g. diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index 6e624e54c4..4c939e5f40 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -82,7 +82,6 @@ class Attribute(SharedMemoryModel): attributes, rather than making different classes for each object type and storing them directly. The added benefit is that we can add/remove attributes on the fly as we like. - The Attribute class defines the following properties: key - primary identifier lock_storage - perm strings diff --git a/src/utils/dbserialize.py b/src/utils/dbserialize.py index 44c1d36a1d..cb0b81f4a6 100644 --- a/src/utils/dbserialize.py +++ b/src/utils/dbserialize.py @@ -251,9 +251,10 @@ def from_pickle(data, db_obj=None): to a form that may contain database objects again. Note that if a database object was removed (or changed in-place) in the database, None will be returned. - db_obj - this is the model instance (normally an Attribute) that Saver*-type - iterables will save to when they update. It must have a 'value' - property that saves assigned data to the database. + db_obj - this is the model instance (normally an Attribute) that _Saver*-type + iterables (_SaverList etc) will save to when they update. It must have a 'value' + property that saves assigned data to the database. Skip if not serializing onto + a given object. If db_obj is given, this function will convert lists, dicts and sets to their _SaverList, _SaverDict and _SaverSet counterparts. @@ -338,3 +339,10 @@ def do_pickle(data): def do_unpickle(data): "Retrieve pickle from pickled string" return loads(to_str(data)) + +def dbserialize(data): + "Serialize to pickled form in one step" + return do_pickle(to_pickle(data)) +def dbunserialize(data, db_obj=None): + "Un-serialize in one step. See from_pickle for help db_obj." + return do_unpickle(from_pickle(data, db_obj=db_obj))