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,
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)
if desc:
new_character.db.desc = desc
else:
new_character.db.desc = "This is a Player."
self.msg("Created new character %s." % new_character.key)
@ -942,7 +947,7 @@ class CmdIC(MuxCommandOOC):
new_character = None
if not self.args:
new_character = caller.db.last_puppet
new_character = caller.db._last_puppet
if not new_character:
self.msg("Usage: @ic <character>")
return
@ -960,7 +965,10 @@ class CmdIC(MuxCommandOOC):
return
if new_character.player:
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
elif not caller.get_character(character=new_character):
self.msg("{c%s{r is already acted by another player.{n" % new_character.name)
@ -972,7 +980,7 @@ class CmdIC(MuxCommandOOC):
self.msg("\n{gYou become {c%s{n.\n" % new_character.name)
caller.db.last_puppet = old_character
if not new_character.location:
# this might be due to being hidden away at logout; check
# this might be due to being hidden away at logout; check
loc = new_character.db.prelogout_location
if not loc: # still no location; use home
loc = new_character.home
@ -1012,7 +1020,7 @@ class CmdOOC(MuxCommandOOC):
self.msg(string)
return
caller.db.last_puppet = old_char
caller.db._last_puppet = old_char
# save location as if we were disconnecting from the game entirely.
if old_char.location:
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
# actually do the login. This will call all other hooks:
# session.at_init()
# if character:
# at_first_login() # only once
# 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.at_login()
# player.at_init() # always called when object is loaded from disk
# player.at_pre_login()
# player.at_first_login() # only once
# player.at_post_login()
session.sessionhandler.login(session, player)
class CmdUnconnectedCreate(MuxCommand):
@ -199,7 +198,8 @@ class CmdUnconnectedCreate(MuxCommand):
# If no description is set, set a default description
if not new_character.db.desc:
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.
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.
"""
print "char:at_post_login", self
if self.db.prelogout_location:
# try to recover
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 import cmdhandler
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")
@ -182,50 +182,17 @@ class PlayerDB(TypedObject):
#@property
def objs_get(self):
"Getter. Allows for value = self.obj"
return self.db_objs.all()
#return get_field_cache(self, "objs").all()
#@obj.setter
return list(self.db_objs.all())
#@objs.setter
def objs_set(self, value):
"Setter. Allows for self.obj = value"
global _TYPECLASS
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)
"Setter. Allows for self.objs = value"
raise Exception("Use access methods to add new characters instead.")
#@obj.deleter
def objs_del(self):
"Deleter. Allows for del self.obj"
self.db_objs.clear()
self.save()
#del_field_cache(self, "obj")
raise Exception("Use access methods to delete new characters instead.")
objs = 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)
characters = property(objs_get, objs_set, objs_del)
# cmdset_storage property
# 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
_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):
"""
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.
"""
session = self.get_session_from_sessid(sessid)
if session:
sessions = self.get_session_from_sessid(sessid)
for session in make_iter(sessions):
session.sessionhandler.disconnect(session)
def connect_session_to_character(self, sessid, character, force=False):
@ -454,10 +437,11 @@ class PlayerDB(TypedObject):
# start (persistent) scripts on this object
#ScriptDB.objects.validate(obj=character)
pass
if character.db.FIRST_LOGIN:
if character.db._first_login:
character.at_first_login()
del character.db.FIRST_LOGIN
del character.db._first_login
character.at_pre_login()
print "player: calling at_post_login on char"
character.at_post_login()
return True
@ -494,23 +478,8 @@ class PlayerDB(TypedObject):
char = _GA(self, "get_character")(sessid=sessid, return_dbobj=True)
if not char:
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):
"""
@ -550,14 +519,23 @@ class PlayerDB(TypedObject):
"""
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):
"""
Use the Player to connect a Character to a session. Note that
we don't do any access checks at this point. Note that if the
Use the Player to connect a Character to the Player. Note that
we don't do any access checks at this point. If the
game was fully restarted (including the Portal), this must be
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
char = character.dbobj
@ -590,7 +568,6 @@ class PlayerDB(TypedObject):
set_prop_cache(self, "_characters", cache)
return char
def disconnect_all_characters(self):
for char in self.db_objs.all():
_GA(self, "disconnect_character")(char)

View file

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

View file

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

View file

@ -143,7 +143,7 @@ class ServerSession(Session):
return
if self.logged_in:
# 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:
# we are not logged in. Use the session directly
# (it uses the settings.UNLOGGEDIN cmdset)

View file

@ -233,7 +233,7 @@ class ServerSessionHandler(SessionHandler):
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
#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.") ):
"""
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()
if sess.logged_in
and sess.get_character() == curr_char
and sess.uid == uid
and sess != curr_session]
for session in doublet_sessions:
self.disconnect(session, reason)