Lots of cleanup and bug fixes. Still some issues with reconnecting to the right location in multisession_mode 0.

This commit is contained in:
Griatch 2013-04-03 18:31:53 +02:00
parent e86c127903
commit 9eb1903f02
8 changed files with 73 additions and 83 deletions

View file

@ -903,9 +903,14 @@ class CmdCharCreate(MuxCommandOOC):
new_character = create.create_object(typeclass, key=key, location=default_home, new_character = create.create_object(typeclass, key=key, location=default_home,
home=default_home, permissions=permissions) home=default_home, permissions=permissions)
# only allow creator (and immortals) to puppet this char
new_character.locks.add("puppet:id(%i) or pid(%i) or perm(Immortals) or pperm(Immortals)" %
(new_character.id, player.id))
player.db._playable_characters.append(new_character) player.db._playable_characters.append(new_character)
if desc: if desc:
new_character.db.desc = desc new_character.db.desc = desc
else:
new_character.db.desc = "This is a Player."
self.msg("Created new character %s." % new_character.key) self.msg("Created new character %s." % new_character.key)
@ -942,7 +947,7 @@ class CmdIC(MuxCommandOOC):
new_character = None new_character = None
if not self.args: if not self.args:
new_character = caller.db.last_puppet new_character = caller.db._last_puppet
if not new_character: if not new_character:
self.msg("Usage: @ic <character>") self.msg("Usage: @ic <character>")
return return
@ -960,7 +965,10 @@ class CmdIC(MuxCommandOOC):
return return
if new_character.player: if new_character.player:
if new_character.sessid == sessid: if new_character.sessid == sessid:
self.msg("{RYou already act as {c%s{n from another session." % new_character.name) self.msg("{RYou already act as {c%s{n." % new_character.name)
return
elif new_character.player == caller:
self.msg("{RYou already act as {c%s{n in another session." % new_character.name)
return return
elif not caller.get_character(character=new_character): elif not caller.get_character(character=new_character):
self.msg("{c%s{r is already acted by another player.{n" % new_character.name) self.msg("{c%s{r is already acted by another player.{n" % new_character.name)
@ -1012,7 +1020,7 @@ class CmdOOC(MuxCommandOOC):
self.msg(string) self.msg(string)
return return
caller.db.last_puppet = old_char caller.db._last_puppet = old_char
# save location as if we were disconnecting from the game entirely. # save location as if we were disconnecting from the game entirely.
if old_char.location: if old_char.location:
old_char.location.msg_contents("%s has left the game." % old_char.key, exclude=[old_char]) old_char.location.msg_contents("%s has left the game." % old_char.key, exclude=[old_char])

View file

@ -92,12 +92,11 @@ class CmdUnconnectedConnect(MuxCommand):
return return
# actually do the login. This will call all other hooks: # actually do the login. This will call all other hooks:
# session.at_init() # session.at_login()
# if character: # player.at_init() # always called when object is loaded from disk
# at_first_login() # only once # player.at_pre_login()
# at_pre_login() # player.at_first_login() # only once
# player.at_post_login() - calls look if no character is set # player.at_post_login()
# character.at_post_login() - this calls look command by default
session.sessionhandler.login(session, player) session.sessionhandler.login(session, player)
class CmdUnconnectedCreate(MuxCommand): class CmdUnconnectedCreate(MuxCommand):
@ -199,7 +198,8 @@ class CmdUnconnectedCreate(MuxCommand):
# If no description is set, set a default description # If no description is set, set a default description
if not new_character.db.desc: if not new_character.db.desc:
new_character.db.desc = "This is a Player." new_character.db.desc = "This is a Player."
# set flag for triggering first-time login hook
new_character.db._first_login = True
# tell the caller everything went well. # tell the caller everything went well.
string = "A new account '%s' was created. Welcome!" string = "A new account '%s' was created. Welcome!"

View file

@ -794,6 +794,7 @@ class Character(Object):
""" """
This recovers the character again after having been "stoved away" at disconnect. This recovers the character again after having been "stoved away" at disconnect.
""" """
print "char:at_post_login", self
if self.db.prelogout_location: if self.db.prelogout_location:
# try to recover # try to recover
self.location = self.db.prelogout_location self.location = self.db.prelogout_location

View file

@ -36,7 +36,7 @@ from src.typeclasses.typeclass import TypeClass
from src.commands.cmdsethandler import CmdSetHandler from src.commands.cmdsethandler import CmdSetHandler
from src.commands import cmdhandler from src.commands import cmdhandler
from src.utils import logger, utils from src.utils import logger, utils
from src.utils.utils import inherits_from from src.utils.utils import inherits_from, make_iter
__all__ = ("PlayerAttribute", "PlayerNick", "PlayerDB") __all__ = ("PlayerAttribute", "PlayerNick", "PlayerDB")
@ -182,50 +182,17 @@ class PlayerDB(TypedObject):
#@property #@property
def objs_get(self): def objs_get(self):
"Getter. Allows for value = self.obj" "Getter. Allows for value = self.obj"
return self.db_objs.all() return list(self.db_objs.all())
#return get_field_cache(self, "objs").all() #@objs.setter
#@obj.setter
def objs_set(self, value): def objs_set(self, value):
"Setter. Allows for self.obj = value" "Setter. Allows for self.objs = value"
global _TYPECLASS raise Exception("Use access methods to add new characters instead.")
if not _TYPECLASS:
from src.typeclasses.typeclass import TypeClass as _TYPECLASS
if isinstance(value, _TYPECLASS):
value = value.dbobj
try:
self.db_objs.add(value)
self.save()
#set_field_cache(self, "obj", value)
except Exception:
logger.log_trace()
raise Exception("Cannot assign %s as a player object!" % value)
#@obj.deleter #@obj.deleter
def objs_del(self): def objs_del(self):
"Deleter. Allows for del self.obj" "Deleter. Allows for del self.obj"
self.db_objs.clear() raise Exception("Use access methods to delete new characters instead.")
self.save()
#del_field_cache(self, "obj")
objs = property(objs_get, objs_set, objs_del) objs = property(objs_get, objs_set, objs_del)
characters = property(objs_get, objs_set, objs_del)
# whereas the name 'obj' is consistent with the rest of the code,
# 'character' is a more intuitive property name, so we
# define this too, as an alias to player.obj.
#@property
def character_get(self):
"Getter. Allows for value = self.character"
return get_field_cache(self, "obj")
#@character.setter
def character_set(self, character):
"Setter. Allows for self.character = value"
if inherits_from(character, TypeClass):
character = character.dbobj
set_field_cache(self, "obj", character)
#@character.deleter
def character_del(self):
"Deleter. Allows for del self.character"
del_field_cache(self, "obj")
character = property(character_get, character_set, character_del)
# cmdset_storage property # cmdset_storage property
# This seems very sensitive to caching, so leaving it be for now /Griatch # This seems very sensitive to caching, so leaving it be for now /Griatch
@ -407,6 +374,22 @@ class PlayerDB(TypedObject):
# a non-character session; this goes to player directly # a non-character session; this goes to player directly
_GA(self, "execute_cmd")(ingoing_string, sessid=sessid) _GA(self, "execute_cmd")(ingoing_string, sessid=sessid)
def get_session(self, sessid):
"""
Return session with given sessid connected to this player.
"""
global _SESSIONS
if not _SESSIONS:
from src.server.sessionhandler import SESSIONS as _SESSIONS
return _SESSIONS.sessions_from_player(self, sessid=sessid)
def get_all_sessions(self):
"Return all sessions connected to this player"
global _SESSIONS
if not _SESSIONS:
from src.server.sessionhandler import SESSIONS as _SESSIONS
return _SESSIONS.sessions_from_player(self)
def get_session_from_sessid(self, sessid): def get_session_from_sessid(self, sessid):
""" """
Get the session object from sessid. If session with sessid is not Get the session object from sessid. If session with sessid is not
@ -421,8 +404,8 @@ class PlayerDB(TypedObject):
""" """
Access method for disconnecting a given session from the player. Access method for disconnecting a given session from the player.
""" """
session = self.get_session_from_sessid(sessid) sessions = self.get_session_from_sessid(sessid)
if session: for session in make_iter(sessions):
session.sessionhandler.disconnect(session) session.sessionhandler.disconnect(session)
def connect_session_to_character(self, sessid, character, force=False): def connect_session_to_character(self, sessid, character, force=False):
@ -454,10 +437,11 @@ class PlayerDB(TypedObject):
# start (persistent) scripts on this object # start (persistent) scripts on this object
#ScriptDB.objects.validate(obj=character) #ScriptDB.objects.validate(obj=character)
pass pass
if character.db.FIRST_LOGIN: if character.db._first_login:
character.at_first_login() character.at_first_login()
del character.db.FIRST_LOGIN del character.db._first_login
character.at_pre_login() character.at_pre_login()
print "player: calling at_post_login on char"
character.at_post_login() character.at_post_login()
return True return True
@ -494,23 +478,8 @@ class PlayerDB(TypedObject):
char = _GA(self, "get_character")(sessid=sessid, return_dbobj=True) char = _GA(self, "get_character")(sessid=sessid, return_dbobj=True)
if not char: if not char:
return return
self.connect_session_to_character(sessid, char, force=True) _GA(self, "connect_session_to_character")(sessid, char, force=True)
def get_session(self, sessid):
"""
Return session with given sessid connected to this player.
"""
global _SESSIONS
if not _SESSIONS:
from src.server.sessionhandler import SESSIONS as _SESSIONS
return _SESSIONS.sessions_from_player(self, sessid=sessid)
def get_all_sessions(self):
"Return all sessions connected to this player"
global _SESSIONS
if not _SESSIONS:
from src.server.sessionhandler import SESSIONS as _SESSIONS
return _SESSIONS.sessions_from_player(self)
def get_character(self, sessid=None, character=None, return_dbobj=False): def get_character(self, sessid=None, character=None, return_dbobj=False):
""" """
@ -550,14 +519,23 @@ class PlayerDB(TypedObject):
""" """
return _GA(self, "get_character")(sessid=None, character=None) return _GA(self, "get_character")(sessid=None, character=None)
def get_all_connected_characters(self):
"""
Return all characters with an active session connected
to them through this player
"""
chars = make_iter(_GA(self, "get_character")(sessid=None, character=None))
sessids = [sess.sessid for sess in _GA(self, "get_all_sessions")()]
return [char for char in chars if char.sessid in sessids]
def connect_character(self, character, sessid=None): def connect_character(self, character, sessid=None):
""" """
Use the Player to connect a Character to a session. Note that Use the Player to connect a Character to the Player. Note that
we don't do any access checks at this point. Note that if the we don't do any access checks at this point. If the
game was fully restarted (including the Portal), this must be game was fully restarted (including the Portal), this must be
used, since sessids will have changed as players reconnect. used, since sessids will have changed as players reconnect.
if sessid is given, also connect the sessid to the character. if sessid is given, also connect the sessid to the character directly.
""" """
# first disconnect any other character from this session # first disconnect any other character from this session
char = character.dbobj char = character.dbobj
@ -590,7 +568,6 @@ class PlayerDB(TypedObject):
set_prop_cache(self, "_characters", cache) set_prop_cache(self, "_characters", cache)
return char return char
def disconnect_all_characters(self): def disconnect_all_characters(self):
for char in self.db_objs.all(): for char in self.db_objs.all():
_GA(self, "disconnect_character")(char) _GA(self, "disconnect_character")(char)

View file

@ -18,6 +18,7 @@ from src.comms.models import Channel
from src.utils import logger from src.utils import logger
__all__ = ("Player",) __all__ = ("Player",)
_MULTISESSION_MODE = settings.MULTISESSION_MODE
_CMDSET_OOC = settings.CMDSET_OOC _CMDSET_OOC = settings.CMDSET_OOC
_CONNECT_CHANNEL = None _CONNECT_CHANNEL = None
@ -322,6 +323,8 @@ class Player(TypeClass):
at_post_login hook. at_post_login hook.
""" """
self._send_to_connect_channel("{G%s connected{n" % self.key) self._send_to_connect_channel("{G%s connected{n" % self.key)
if _MULTISESSION_MODE == 2 or not self.get_all_characters():
# Character.at_post_login also looks around. Only use # Character.at_post_login also looks around. Only use
# this as a backup when logging in without a character # this as a backup when logging in without a character
self.execute_cmd("look") self.execute_cmd("look")

View file

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

View file

@ -143,7 +143,7 @@ class ServerSession(Session):
return return
if self.logged_in: if self.logged_in:
# the inmsg handler will relay to the right place # the inmsg handler will relay to the right place
self.player.inmsg(command_string, self.sessid) self.player.inmsg(command_string, sessid=self.sessid)
else: else:
# we are not logged in. Use the session directly # we are not logged in. Use the session directly
# (it uses the settings.UNLOGGEDIN cmdset) # (it uses the settings.UNLOGGEDIN cmdset)

View file

@ -233,7 +233,7 @@ class ServerSessionHandler(SessionHandler):
player.at_pre_login() player.at_pre_login()
session.log(_('Logged in: %(self)s') % {'self': self}) session.log(_('Logged in: %(self)s') % {'self': player})
# start (persistent) scripts on this object # start (persistent) scripts on this object
#ScriptDB.objects.validate(obj=self.player.character) #ScriptDB.objects.validate(obj=self.player.character)
@ -275,12 +275,12 @@ class ServerSessionHandler(SessionHandler):
def disconnect_duplicate_sessions(self, curr_session, reason = _("Logged in from elsewhere. Disconnecting.") ): def disconnect_duplicate_sessions(self, curr_session, reason = _("Logged in from elsewhere. Disconnecting.") ):
""" """
Disconnects any existing sessions with the same game object. Disconnects any existing sessions with the same user.
""" """
curr_char = curr_session.get_character() uid = curr_session.uid
doublet_sessions = [sess for sess in self.sessions.values() doublet_sessions = [sess for sess in self.sessions.values()
if sess.logged_in if sess.logged_in
and sess.get_character() == curr_char and sess.uid == uid
and sess != curr_session] and sess != curr_session]
for session in doublet_sessions: for session in doublet_sessions:
self.disconnect(session, reason) self.disconnect(session, reason)