Continued work on multi-char-per-account. Added a new default login point. Still need to add sessid to commands.

This commit is contained in:
Griatch 2013-02-02 15:55:42 +01:00
parent b50266623e
commit 231af4a351
5 changed files with 120 additions and 50 deletions

View file

@ -649,7 +649,12 @@ class CmdAccess(MuxCommand):
string += "\nPlayer {c%s{n: %s" % (caller.player.key, pperms) string += "\nPlayer {c%s{n: %s" % (caller.player.key, pperms)
caller.msg(string) caller.msg(string)
#------------------------------------------------------------
# OOC commands # OOC commands
#------------------------------------------------------------
class CmdOOCLook(MuxCommandOOC, CmdLook): class CmdOOCLook(MuxCommandOOC, CmdLook):
""" """
@ -658,28 +663,67 @@ class CmdOOCLook(MuxCommandOOC, CmdLook):
Usage: Usage:
look look
This is an OOC version of the look command. Since a Look in the ooc state.
Player doesn't have an in-game existence, there is no
concept of location or "self". If we are controlling
a character, pass control over to normal look.
""" """
#This is an OOC version of the look command. Since a
#Player doesn't have an in-game existence, there is no
#concept of location or "self". If we are controlling
#a character, pass control over to normal look.
key = "look" key = "look"
aliases = ["l", "ls"] aliases = ["l", "ls"]
locks = "cmd:all()" locks = "cmd:all()"
help_category = "General" help_category = "General"
def look_target(self):
"Hook method for when an argument is given."
# caller is assumed to be a player object here.
caller = self.caller
looktarget = caller.get_character(key=self.args)
if looktarget:
caller.msg(looktarget.return_appearance())
else:
caller.msg("No such character.")
return
def no_look_target(self):
"Hook method for default look without a specified target"
# caller is always a player at this point.
player = self.caller
sessid = self.sessid
# get all our characters
characters = player.get_all_characters() # get all characters
string = "You are logged in as {g%s{n." % player.key
string += " Use {w@ic <character>{n to enter the game."
string += "\n\nAvailable character%s:" % (characters.count() > 1 and "s" or "")
for char in characters:
csessid = char.sessid
if csessid:
# character is already puppeted
if csessid == sessid:
# this should not happen.
string += "\n - {r%s{n (sessid not properly cleared! Contact an admin!)" % char.key
elif player.get_session(csessid):
string += "\n - {G%s{n (played by you in another session)"
else:
string += "\n - {R%s{n (played by someone else)" % char.key
else:
# character is "free to puppet"
string += "\n - %s" % char.key
player.msg(string)
def func(self): def func(self):
"implement the ooc look command" "implement the ooc look command"
if not self.character: if utils.inherits_from(self.caller, "src.objects.objects.Object"):
string = "You are out-of-character (OOC). " # An object of some type is calling. Use default look instead.
string += "Use {w@ic{n to get back to the game, {whelp{n for more info."
self.caller.msg(string)
else:
self.caller = self.character # we have to put this back for normal look to work.
super(CmdOOCLook, self).func() super(CmdOOCLook, self).func()
elif self.args:
self.look_target()
else:
self.no_look_target()
class CmdIC(MuxCommandOOC): class CmdIC(MuxCommandOOC):
""" """

View file

@ -274,14 +274,13 @@ class ObjectDB(TypedObject):
if not get_field_cache(self, "player"): if not get_field_cache(self, "player"):
del_field_cache(self, "sessid") del_field_cache(self, "sessid")
return get_field_cache(self, "sessid") return get_field_cache(self, "sessid")
#@sessid.setter
#@player.setter
def __sessid_set(self, player): def __sessid_set(self, player):
"Setter. Allows for self.player = value" "Setter. Allows for self.player = value"
if inherits_from(player, TypeClass): if inherits_from(player, TypeClass):
player = player.dbobj player = player.dbobj
set_field_cache(self, "player", player) set_field_cache(self, "player", player)
#@player.deleter #@sessid.deleter
def __player_del(self): def __player_del(self):
"Deleter. Allows for del self.player" "Deleter. Allows for del self.player"
del_field_cache(self, "player") del_field_cache(self, "player")

View file

@ -225,7 +225,7 @@ class PlayerDB(TypedObject):
#@property #@property
def character_get(self): def character_get(self):
"Getter. Allows for value = self.character" "Getter. Allows for value = self.character"
return get_field_cache(self, "obj) return get_field_cache(self, "obj")
#@character.setter #@character.setter
def character_set(self, character): def character_set(self, character):
"Setter. Allows for self.character = value" "Setter. Allows for self.character = value"
@ -378,7 +378,7 @@ class PlayerDB(TypedObject):
session = _GA(self, "get_session")(sessid) session = _GA(self, "get_session")(sessid)
if session: if session:
char = _GA(self, "get_character")(sessid) char = _GA(self, "get_character")(sessid)
if char and not char.at_msg_receive(outgoing_string, from_obj=from_obj, data=data)): if char and not char.at_msg_receive(outgoing_string, from_obj=from_obj, data=data):
# if hook returns false, cancel send # if hook returns false, cancel send
return return
session.msg(outgoing_string, data) session.msg(outgoing_string, data)
@ -411,7 +411,7 @@ class PlayerDB(TypedObject):
its session id. its session id.
""" """
def get_sessions(self, sessid=None): def get_session(self, sessid=None):
""" """
Return session with given sessid connected to this player. If sessid is Return session with given sessid connected to this player. If sessid is
not given, return all connected sessions. not given, return all connected sessions.
@ -420,24 +420,36 @@ class PlayerDB(TypedObject):
""" """
return SESSIONS.get_session_from_player(self, sessid=sessid) return SESSIONS.get_session_from_player(self, sessid=sessid)
def get_character(self, sessid): def get_character(self, sessid=None, key=None):
""" """
Get the character connected through this sessid, if any Get the character connected through this sessid, if any. May also
try to return a character based on key. If neither sessid nor key
is given, return all characters connected to this player
""" """
if not sessid: # sessid is always > 0 cache = get_prop_cache(self, "_characters") or {}
return None if sessid:
try: # try to return a character with a given sessid
char = get_prop_cache(self, "_characters").get(sessid) char = cache.get(sessid)
except AttributeError: if not char:
set_prop_cache(self, "_characters", {}) char = self.db_objs.filter(player=self, sessid=sessid) or None
char = None if char:
if not char: cache[sessid] = char[0]
char = self.db_objs.filter(player=self, sessid=sessid) set_prop_cache(self, "_characters", cache)
if char.count(): if key:
chars_cache = get_prop_cache(self, "_characters") return char.key.lower() == key.lower() and char or None
chars_cache[sessid] = char[0] return char
set_prop_cache(self, "_characters") elif key:
return char char = self.db_objs.filter(player=self, db_key__iexact=key)
return char and char[0] or None
else:
# no sessid given - return all available characters
return list(self.db_objs.filter(player=self, sessid=sessid))
def get_all_characters(self):
"""
Readability-wrapper for getting all characters
"""
return self.get_character(sessid=None)
def connect_character(self, character, sessid): def connect_character(self, character, sessid):
""" """
@ -446,25 +458,39 @@ class PlayerDB(TypedObject):
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.
""" """
# first disconnect any other character from this session
self.disconnect_character(sessid=sessid)
character = character.dbobj character = character.dbobj
character.player = self character.player = self
character.sessid = sessid character.sessid = sessid
self.db_objs.add(character) self.db_objs.add(character)
self.save() self.save()
# update cache
cache = get_prop_cache(self, "_characters") or {}
cache[sessid] = character
set_prop_cache(self, "_characters", cache)
def disconnect_character(self, character): def disconnect_character(self, sessid=None, char=None):
""" """
Disconnect a character from this player. Disconnect a character from this player, either based
on sessid or by giving the character object directly
""" """
character = character.dbobj key = char and char.key or None
if self.db_objs.filter(id=_GA(character,"id")): char = self.get_character(sessid=sessid, key=key)
self.db_objs.remove(character) if char:
character.player = None self.db_objs.remove(char)
character.sessid = None del char.player
del char.sessid
self.save() self.save()
# clear cache
cache = get_prop_cache(self, "_characters") or {}
if cache and sessid in cache:
del cache[sessid]
set_prop_cache(self, "_characters", cache)
def disconnect_all_characters(self): def disconnect_all_characters(self):
for char in self.db_objs.all(): for char in self.db_objs.all():
self.disconnect_character(char)
def swap_character(self, new_character, delete_old_character=False): def swap_character(self, new_character, delete_old_character=False):
""" """

View file

@ -32,7 +32,8 @@ SSYNC = chr(8) # server session sync
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
SERVERNAME = settings.SERVERNAME SERVERNAME = settings.SERVERNAME
ALLOW_MULTISESSION = settings.ALLOW_MULTISESSION #ALLOW_MULTISESSION = settings.ALLOW_MULTISESSION
MULTISESSION_MODE = settings.MULTISESSION_MODE
IDLE_TIMEOUT = settings.IDLE_TIMEOUT IDLE_TIMEOUT = settings.IDLE_TIMEOUT
#----------------------------------------------------------- #-----------------------------------------------------------
@ -163,8 +164,8 @@ class ServerSessionHandler(SessionHandler):
""" """
# prep the session with player/user info # prep the session with player/user info
if not ALLOW_MULTISESSION: if MULTISESSION_MODE == 0:
# disconnect previous sessions. # disconnect all previous sessions.
self.disconnect_duplicate_sessions(session) self.disconnect_duplicate_sessions(session)
session.logged_in = True session.logged_in = True
# sync the portal to this session # sync the portal to this session
@ -235,7 +236,7 @@ class ServerSessionHandler(SessionHandler):
uid = player.uid uid = player.uid
if sessid: if sessid:
return [session for session in self.sessions.values() if session.logged_in and session.sessid == sessid and session.uid == uid] return [session for session in self.sessions.values() if session.logged_in and session.sessid == sessid and session.uid == uid]
else else:
return [session for session in self.sessions.values() if session.logged_in and session.uid == uid] return [session for session in self.sessions.values() if session.logged_in and session.uid == uid]
def sessions_from_character(self, character): def sessions_from_character(self, character):

View file

@ -59,12 +59,12 @@ SSL_ENABLED = False
SSL_PORTS = [4001] SSL_PORTS = [4001]
# Interface addresses to listen to. If 0.0.0.0, listen to all. # Interface addresses to listen to. If 0.0.0.0, listen to all.
SSL_INTERFACES = ['0.0.0.0'] SSL_INTERFACES = ['0.0.0.0']
# If multisessions are allowed, a user can log into the game # Multisession modes allow a player (=account) to connect to the game simultaneously
# from several different computers/clients at the same time. # with multiple clients in various ways according to the set mode:
# All feedback from the game will be echoed to all sessions. # 0 - no multisession - when a new session is connected, the old one is disconnected
# If false, only one session is allowed, all other are logged off # 1 - multiple sessions, one player, one character, each session getting the same data
# when a new connects. # 2 - multiple sessions, one player, each session controlling different characters
ALLOW_MULTISESSION = False MULTISESSION_MODE = 0
# The path that contains this settings.py file (no trailing slash). # The path that contains this settings.py file (no trailing slash).
BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Path to the src directory containing the bulk of the codebase's code. # Path to the src directory containing the bulk of the codebase's code.