Moved login and disconnect from session-level to sessionhandler level to make the process cleaner with hooks rather than direct calls.

This commit is contained in:
Griatch 2013-02-17 18:48:48 +01:00
parent 261363bae7
commit 25505d69a6
7 changed files with 109 additions and 70 deletions

View file

@ -118,14 +118,12 @@ class Command(object):
# used by the help system to group commands in lists.
help_category = "general"
# this normally does not need to be changed. It allows to turn off
# auto-help entry creation for individual commands.
# This allows to turn off auto-help entry creation for individual commands.
auto_help = True
# There is also the property 'obj'. This gets set by the system
# on the fly to tie this particular command to a certain in-game entity.
# self.obj should NOT be defined here since it will not be overwritten
# if it already exists.
# auto-set (by Evennia on command instantiation) are:
# obj - which object this command is defined on
# sessid - which session-id (if any) is responsible for triggering this command
#
def __init__(self):
"the lockhandler works the same as for objects."
@ -190,6 +188,29 @@ class Command(object):
"""
return self.lockhandler.check(srcobj, access_type, default=default)
def msg(self, msg="", data=None, from_obj=None, to_obj=None, all_sessions=False):
"""
This is a shortcut instad of calling msg() directly on an object - it will
determine
detect if caller is an Object or a Player and also appends self.sessid
automatically.
msg - text string of message to send
data - optional dictionary of data
from_obj - source of message. Defaults to self.caller.
to_obj - target object of message. Defaults to self.caller
all_sessions (bool) - default is to send only to the session connected to
the target object
"""
from_obj = from_obj or self.caller
to_obj = to_obj or from_obj
if hasattr(to_obj, "sessid"):
sessid = all_sessions and None or to_obj.sessid
else:
sessid = None
to_obj.msg(msg, from_obj=from_obj, data=data, sessid=sessid)
# Common Command hooks
def at_pre_cmd(self):

View file

@ -388,7 +388,11 @@ class CmdQuit(MuxCommand):
Usage:
@quit
Gracefully disconnect from the game.
Switch:
all - disconnect all connected sessions
Gracefully disconnect your current session from the
game. Use the /all switch to disconnect from all sessions.
"""
key = "@quit"
locks = "cmd:all()"
@ -400,10 +404,20 @@ class CmdQuit(MuxCommand):
else:
player = self.caller
player.msg("{RQuitting{n. Hope to see you soon again.", sessid=self.sessid)
player.disconnect_session_from_player(self.sessid)
#for session in self.caller.sessions:
# session.session_disconnect()
if 'all' in self.switches:
player.msg("{RQuitting{n all sessions. Hope to see you soon again.", sessid=self.sessid)
for session in player.get_all_sessions():
player.disconnect_session_from_player(session.sessid)
else:
nsess = len(player.get_all_sessions())
if nsess == 2:
player.msg("{RQuitting{n. One session is still connected.", sessid=self.sessid)
elif nsess > 2:
player.msg("{RQuitting{n. %i session are still connected." % (nsess-1), sessid=self.sessid)
else:
# we are quitting the last available session
player.msg("{RQuitting{n. Hope to see you soon again.", sessid=self.sessid)
player.disconnect_session_from_player(self.sessid)
class CmdWho(MuxCommand):
"""

View file

@ -97,7 +97,7 @@ class CmdUnconnectedConnect(MuxCommand):
# at_pre_login()
# player.at_post_login() - calls look if no character is set
# character.at_post_login() - this calls look command by default
session.session_login(player)
session.sessionhandler.login(session, player)
class CmdUnconnectedCreate(MuxCommand):
"""
@ -224,8 +224,8 @@ class CmdUnconnectedQuit(MuxCommand):
def func(self):
"Simply close the connection."
session = self.caller
session.msg("Good bye! Disconnecting ...")
session.session_disconnect()
#session.msg("Good bye! Disconnecting ...")
session.sessionhandler.disconnect(session, "Good bye! Disconnecting ...")
class CmdUnconnectedLook(MuxCommand):
"""

View file

@ -584,7 +584,6 @@ class ObjectDB(TypedObject):
if ostring in (_ME, _SELF, '*' + _ME, '*' + _SELF):
return self
if use_nicks:
nick = None
nicktype = "object"
@ -670,7 +669,7 @@ class ObjectDB(TypedObject):
break
return cmdhandler.cmdhandler(_GA(self, "typeclass"), raw_string, sessid=sessid)
def msg(self, message, from_obj=None, data=None):
def msg(self, msg=None, from_obj=None, data=None, sessid=0):
"""
Emits something to a session attached to the object.
@ -678,10 +677,14 @@ class ObjectDB(TypedObject):
from_obj (obj): object that is sending.
data (object): an optional data object that may or may not
be used by the protocol.
sessid (int): sessid to relay to, if any.
If set to 0 (default), use self.sessid automatically
If None, echo to all connected sessions
"""
if _GA(self, 'player'):
# note that we must call the player *typeclass'* msg(), otherwise one couldn't overload it.
_GA(_GA(self, 'player'), "typeclass").msg(message, from_obj=from_obj, data=data, sessid=_GA(self, "sessid"))
_GA(_GA(self, 'player'), "typeclass").msg(msg, from_obj=from_obj, data=data,
sessid=(sessid==0 and _GA(self, "sessid") or sessid or None))
def emit_to(self, message, from_obj=None, data=None):
"Deprecated. Alias for msg"

View file

@ -423,16 +423,23 @@ class PlayerDB(TypedObject):
# a non-character session; this goes to player directly
_GA(self, "execute_cmd")(ingoing_string, sessid=sessid)
def disconnect_session_from_player(self, sessid):
def get_session_from_sessid(self, sessid):
"""
Access method for disconnecting a given session from the player.
Get the session object from sessid. If session with sessid is not
connected to this player, return None.
"""
global _SESSIONS
if not _SESSIONS:
from src.server.sessionhandler import SESSIONS as _SESSIONS
_SESSIONS.disconnect(sessid=sessid)
return _SESSIONS.sessions_from_player(self, sessid=sessid)
def disconnect_session_from_player(self, sessid):
"""
Access method for disconnecting a given session from the player.
"""
session = self.get_session_from_sessid(sessid)
if session:
session.sessionhandler.disconnect(session)
def connect_session_to_character(self, sessid, character, force=False):
"""
@ -502,7 +509,6 @@ class PlayerDB(TypedObject):
"""
char = _GA(self, "get_character")(sessid=sessid, return_dbobj=True)
if not char:
print "No reconnecting character found"
return
self.connect_session_to_character(sessid, char, force=True)

View file

@ -59,23 +59,12 @@ class ServerSession(Session):
else:
self.player.reconnect_session_to_character(self.sessid)
def session_login(self, player):
def at_login(self, player):
"""
Startup mechanisms that need to run at login. This is called
by the login command (which need to have handled authentication
already before calling this method)
Hook called by sessionhandler when the session becomes authenticated.
player - the connected player
player - the player associated with the session
"""
# we have to check this first before uid has been assigned
# this session.
if not self.sessionhandler.sessions_from_player(player):
player.is_connected = True
# actually do the login by assigning session data
self.player = player
self.user = player.user
self.uid = self.user.id
@ -87,31 +76,9 @@ class ServerSession(Session):
self.user.last_login = datetime.now()
self.user.save()
# player init
player.at_init()
# Check if this is the first time the *player* logs in
if player.db.FIRST_LOGIN:
player.at_first_login()
del player.db.FIRST_LOGIN
player.at_pre_login()
self.log(_('Logged in: %(self)s') % {'self': self})
# start (persistent) scripts on this object
#ScriptDB.objects.validate(obj=self.player.character)
#add session to connected list
self.sessionhandler.login(self)
player.at_post_login()
def session_disconnect(self):
def at_disconnect(self):
"""
Clean up the session, removing it from the game and doing some
accounting. This method is used also for non-loggedin
accounts.
Hook called by sessionhandler when disconnecting this session.
"""
if self.logged_in:
sessid = self.sessid
@ -123,8 +90,9 @@ class ServerSession(Session):
uaccount.save()
self.logged_in = False
if not self.sessionhandler.sessions_from_player(player):
# no more sessions connected to this player
player.is_connected = False
self.sessionhandler.disconnect(self)
def get_player(self):
"""
@ -268,12 +236,12 @@ class ServerSession(Session):
# easy-access functions
def login(self, player):
"alias for at_login"
self.session_login(player)
def disconnect(self):
"alias for session_disconnect"
self.session_disconnect()
#def login(self, player):
# "alias for at_login"
# self.session_login(player)
#def disconnect(self):
# "alias for session_disconnect"
# self.session_disconnect()
def msg(self, string='', data=None):
"alias for at_data_out"
self.data_out(string, data=data)

View file

@ -199,6 +199,7 @@ class ServerSessionHandler(SessionHandler):
"""
session = self.sessions.get(session.sessid, None)
if session:
session.at_disconnect()
sessid = session.sessid
del self.sessions[sessid]
# inform portal that session should be closed.
@ -206,7 +207,7 @@ class ServerSessionHandler(SessionHandler):
operation=SDISCONN,
data=reason)
def login(self, session):
def login(self, session, player):
"""
Log in the previously unloggedin session and the player we by
now should know is connected to it. After this point we
@ -214,15 +215,41 @@ class ServerSessionHandler(SessionHandler):
"""
# prep the session with player/user info
# we have to check this first before uid has been assigned
# this session.
if not self.sessions_from_player(player):
player.is_connected = True
# sets up and assigns all properties on the session
session.at_login(player)
# player init
player.at_init()
# Check if this is the first time the *player* logs in
if player.db.FIRST_LOGIN:
player.at_first_login()
del player.db.FIRST_LOGIN
player.at_pre_login()
session.log(_('Logged in: %(self)s') % {'self': self})
# start (persistent) scripts on this object
#ScriptDB.objects.validate(obj=self.player.character)
if MULTISESSION_MODE == 0:
# disconnect all previous sessions.
self.disconnect_duplicate_sessions(session)
session.logged_in = True
# sync the portal to this session
# sync the portal to the session
sessdata = session.get_sync_data()
self.server.amp_protocol.call_remote_PortalAdmin(session.sessid,
operation=SLOGIN,
data=sessdata)
player.at_post_login()
def all_sessions_portal_sync(self):
"""