Further fixes to the system, still some issues remaining.

This commit is contained in:
Griatch 2013-04-06 21:36:52 +02:00
parent 9eb1903f02
commit 20a57d4167
7 changed files with 119 additions and 69 deletions

View file

@ -978,7 +978,7 @@ class CmdIC(MuxCommandOOC):
return
if caller.connect_character(new_character, sessid=sessid):
self.msg("\n{gYou become {c%s{n.\n" % new_character.name)
caller.db.last_puppet = old_character
caller.db._last_puppet = old_character
if not new_character.location:
# this might be due to being hidden away at logout; check
loc = new_character.db.prelogout_location

View file

@ -106,11 +106,11 @@ class Object(TypeClass):
inside a deleted object are automatically moved to their <home>, they don't need to be removed here.
at_init() - called whenever typeclass is cached from memory, at least once every server restart/reload
at_cmdset_get() - this is called just before the command handler requests a cmdset from this object
at_first_login() - (player-controlled objects only) called once, the very first time user logs in.
at_pre_login() - (player-controlled objects only) called every time the user connects, after they have identified, before other setup
at_post_login() - (player-controlled objects only) called at the end of login, just before setting the player loose in the world.
at_disconnect() - (player-controlled objects only) called just before the user disconnects (or goes linkless)
at_cmdset_get() - this is called just before the command handler requests a cmdset from this objecth
at_pre_puppet(player)- (player-controlled objects only) called just before puppeting
at_post_puppet() - (player-controlled objects only) called just after completing connection player<->object
at_pre_unpuppet() - (player-controlled objects only) called just before un-puppeting
at_post_unpuppet(player) - (player-controlled objects only) called just after disconnecting player<->object link
at_server_reload() - called before server is reloaded
at_server_shutdown() - called just before server is fully shut down
@ -458,33 +458,66 @@ class Object(TypeClass):
"""
pass
def at_first_login(self):
def at_pre_puppet(self, player):
"""
Only called once, the very first
time the user logs in.
"""
pass
def at_pre_login(self):
"""
Called every time the user logs in,
before they are actually logged in.
"""
pass
def at_post_login(self):
"""
Called at the end of the login
process, just before letting
them loose.
Called just before a Player connects to this object
to puppet it.
player - connecting player object
"""
pass
def at_disconnect(self):
def at_post_puppet(self):
"""
Called just before user
is disconnected.
Called just after puppeting has been completed and
all Player<->Object links have been established.
"""
pass
def at_pre_unpuppet(self):
"""
Called just before beginning to un-connect a puppeting
from this Player.
"""
pass
def at_post_unpuppet(self, player):
"""
Called just after the Player successfully disconnected
from this object, severing all connections.
player - the player object that just disconnected from
this object.
"""
pass
#def at_first_login(self):
# """
# Only called once, the very first
# time the user logs in.
# """
# pass
#def at_pre_login(self):
# """
# Called every time the user logs in,
# before they are actually logged in.
# """
# pass
#def at_post_login(self):
# """
# Called at the end of the login
# process, just before letting
# them loose.
# """
# pass
#def at_disconnect(self):
# """
# Called just before user
# is disconnected.
# """
# pass
def at_server_reload(self):
"""
This hook is called whenever the server is shutting down for restart/reboot.
@ -780,21 +813,12 @@ class Character(Object):
"Default is to look around after a move."
self.execute_cmd('look')
def at_disconnect(self):
def at_pre_puppet(self, player):
"""
We stove away the character when logging off, otherwise the character object will
remain in the room also after the player logged off ("headless", so to say).
This recovers the character again after having been "stoved away" at the unpuppet
"""
if self.location: # have to check, in case of multiple connections closing
self.location.msg_contents("%s has left the game." % self.name, exclude=[self])
self.db.prelogout_location = self.location
self.location = None
print "object at_pre_puppet", self, player
def at_post_login(self):
"""
This recovers the character again after having been "stoved away" at disconnect.
"""
print "char:at_post_login", self
if self.db.prelogout_location:
# try to recover
self.location = self.db.prelogout_location
@ -806,8 +830,24 @@ class Character(Object):
self.location.msg_contents("%s has entered the game." % self.name, exclude=[self])
self.location.at_object_receive(self, self.location)
def at_post_puppet(self):
"Once puppeting is complete, make sure to view the location."
# call look
print "object at_post_puppet", self
self.execute_cmd("look")
def at_post_unpuppet(self, player):
"""
We stove away the character when the player goes ooc/logs off, otherwise the character object will
remain in the room also after the player logged off ("headless", so to say).
"""
print "at_post_unpuppet", player
if self.location: # have to check, in case of multiple connections closing
self.location.msg_contents("%s has left the game." % self.name, exclude=[self])
self.db.prelogout_location = self.location
self.location = None
#
# Base Room object
#

View file

@ -31,6 +31,7 @@ from django.utils.encoding import smart_str
from src.server.caches import get_field_cache, set_field_cache, del_field_cache
from src.server.caches import get_prop_cache, set_prop_cache, del_prop_cache
from src.players import manager
from src.scripts.models import ScriptDB
from src.typeclasses.models import Attribute, TypedObject, TypeNick, TypeNickHandler
from src.typeclasses.typeclass import TypeClass
from src.commands.cmdsethandler import CmdSetHandler
@ -364,8 +365,6 @@ class PlayerDB(TypedObject):
data - dictionary of optional data
sessid - session sending this data
"""
if _MULTISESSION_MODE < 2:
sessid = None
character = _GA(self, "get_character")(sessid=sessid)
if character:
# execute command on character
@ -406,15 +405,18 @@ class PlayerDB(TypedObject):
"""
sessions = self.get_session_from_sessid(sessid)
for session in make_iter(sessions):
# this will also trigger disconnection of character(s)
session.sessionhandler.disconnect(session)
def connect_session_to_character(self, sessid, character, force=False):
def connect_session_to_character(self, sessid, character, force=False, call_hooks=True):
"""
Connect the given session to a character through this player.
Note that this assumes the character has previously been
linked to the player using self.connect_character().
force - drop existing connection to other character
call_hooks - call puppet/unpuppet hooks. This is not wanted e.g. if
server is reloading
Returns True if connection was successful, False otherwise
"""
@ -425,24 +427,21 @@ class PlayerDB(TypedObject):
_GA(self, "disconnect_session_from_character")(sessid)
else:
return
# pre-puppet hook
if call_hooks:
# if e.g. server reloads we don't want to call any hooks anew
_GA(character.typeclass, "at_pre_puppet")(self.typeclass)
# do the connection
character.sessid = sessid
# update cache
cache = get_prop_cache(self, "_characters") or {}
cache[sessid] = character
set_prop_cache(self, "_characters", cache)
# call hooks
character.at_init()
if character:
# start (persistent) scripts on this object
#ScriptDB.objects.validate(obj=character)
pass
if character.db._first_login:
character.at_first_login()
del character.db._first_login
character.at_pre_login()
print "player: calling at_post_login on char"
character.at_post_login()
# start/validate (persistent) scripts on this object
ScriptDB.objects.validate(obj=character)
# post-puppet hook
if call_hooks:
_GA(character.typeclass, "at_post_puppet")()
return True
def disconnect_session_from_character(self, sessid):
@ -451,21 +450,26 @@ class PlayerDB(TypedObject):
connection to the Player)
returns the newly disconnected character, if it existed
"""
print "player disconnect_session_from_character", sessid
if not sessid:
return
char = _GA(self, "get_character")(sessid=sessid, return_dbobj=True)
print char
if char:
# call hook before disconnecting
_GA(char.typeclass, "at_disconnect")()
_GA(char.typeclass, "at_pre_unpuppet")()
del char.sessid
# update cache
cache = get_prop_cache(self, "_characters") or {}
if sessid in cache:
del cache[sessid]
set_prop_cache(self, "_characters", cache)
# call post-unpuppet hook
_GA(char.typeclass, "at_post_unpuppet")(self.typeclass)
print "... leaving player disconnect_session_from_character", sessid
return char
def reconnect_session_to_character(self, sessid):
def server_reconnect_session_to_character(self, sessid):
"""
Auto-re-connect a session to a character. This is called by the sessionhandler
during a server reload. It goes through the characters stored in this player's
@ -478,19 +482,20 @@ class PlayerDB(TypedObject):
char = _GA(self, "get_character")(sessid=sessid, return_dbobj=True)
if not char:
return
_GA(self, "connect_session_to_character")(sessid, char, force=True)
_GA(self, "connect_session_to_character")(sessid, char, force=True, call_hooks=False)
def get_character(self, sessid=None, character=None, return_dbobj=False):
"""
Get the character connected to this player and sessid
Get the character connected to this player and sessid. This is the main
method for retrieving the character from the player's end.
sessid - return character connected to this sessid,
character - return character if connected to this player, else None.
Combining both keywords will check the entire connection - if the
given session is currently connected to the given char. If no
keywords are given, returns all connected characters.
keywords are given, returns all connected characters as a list.
"""
cache = get_prop_cache(self, "_characters") or {}
if sessid:

View file

@ -296,9 +296,10 @@ class Player(TypeClass):
def at_pre_login(self):
"""
Called every time the user logs in,
before they are actually logged in.
Called every time the user logs in, just before the actual
login-state is set.
"""
print "player at_pre_login", self
pass
def _send_to_connect_channel(self, message):
@ -322,6 +323,7 @@ class Player(TypeClass):
them loose. This is called before an eventual Character's
at_post_login hook.
"""
print "player at_post_login", self
self._send_to_connect_channel("{G%s connected{n" % self.key)
if _MULTISESSION_MODE == 2 or not self.get_all_characters():
@ -331,10 +333,11 @@ class Player(TypeClass):
def at_disconnect(self, reason=None):
"""
Called just before user
is disconnected.
Called just before user is disconnected.
"""
self._send_to_connect_channel("{R%s disconnected{n" % self.key)
print "player at_disconnect", self
reason = reason and "(%s)" % reason or ""
self._send_to_connect_channel("{R%s disconnected %s{n" % (self.key, reason))
def at_message_receive(self, message, from_obj=None):
"""

View file

@ -61,7 +61,7 @@ def create_objects():
god_character.save()
god_character.set_attribute("_superuser_character", True)
gor_character.set_attribute("_first_login", True)
god_character.set_attribute("_first_login", True)
# Limbo is the default "nowhere" starting room

View file

@ -272,7 +272,7 @@ class Evennia(object):
yield [(o.typeclass, o.at_server_shutdown()) for o in ObjectDB.get_all_cached_instances()]
else: # shutdown
yield [_SA(p, "is_connected", False) for p in PlayerDB.get_all_cached_instances()]
yield [(o.typeclass, o.at_disconnect(), o.at_server_shutdown()) for o in ObjectDB.get_all_cached_instances()]
yield [(o.typeclass, o.at_server_shutdown()) for o in ObjectDB.get_all_cached_instances()]
yield [(p.typeclass, p.at_server_shutdown()) for p in PlayerDB.get_all_cached_instances()]
yield [(s.typeclass, s.at_server_shutdown()) for s in ScriptDB.get_all_cached_instances()]

View file

@ -17,6 +17,7 @@ from src.commands import cmdhandler, cmdsethandler
from src.server.session import Session
IDLE_COMMAND = settings.IDLE_COMMAND
_GA = object.__getattribute__
# load optional out-of-band function module
OOB_FUNC_MODULE = settings.OOB_FUNC_MODULE
@ -57,7 +58,7 @@ class ServerSession(Session):
self.cmdset.update(init_mode=True)
return
else:
self.player.reconnect_session_to_character(self.sessid)
self.player.server_reconnect_session_to_character(self.sessid)
def at_login(self, player):
"""
@ -83,17 +84,18 @@ class ServerSession(Session):
if self.logged_in:
sessid = self.sessid
player = self.player
if player.get_character(sessid):
player.disconnect_session_from_character(sessid)
uaccount = player.user
print "session at_disconnect", self
_GA(player.dbobj, "disconnect_session_from_character")(sessid)
uaccount = _GA(player.dbobj, "user")
uaccount.last_login = datetime.now()
uaccount.save()
# calling player hook
_GA(player.typeclass, "at_disconnect")()
self.logged_in = False
if not self.sessionhandler.sessions_from_player(player):
# no more sessions connected to this player
player.is_connected = False
def get_player(self):
"""
Get the player associated with this session