Contrib: Added a new, alternative login system, using menus. Also edited the ways unlogged commands are started by the engine, by using a standardized system command name (it does not need to be "look" anymore).

This commit is contained in:
Griatch 2011-11-06 18:53:10 +01:00
parent 2b2d27ed39
commit 55f6f5b713
6 changed files with 81 additions and 15 deletions

View file

@ -149,15 +149,19 @@ class MenuTree(object):
'START' and 'END' respectively. 'START' and 'END' respectively.
""" """
def __init__(self, caller, nodes=None, startnode="START", endnode="END"): def __init__(self, caller, nodes=None, startnode="START", endnode="END", exec_end="look"):
""" """
We specify startnode/endnode so that the system knows where to We specify startnode/endnode so that the system knows where to
enter and where to exit the menu tree. If nodes is given, it enter and where to exit the menu tree. If nodes is given, it
shuld be a list of valid node objects to add to the tree. shuld be a list of valid node objects to add to the tree.
exec_end - if not None, will execute the given command string
directly after the menu system has been exited.
""" """
self.tree = {} self.tree = {}
self.startnode = startnode self.startnode = startnode
self.endnode = endnode self.endnode = endnode
self.exec_end = exec_end
self.caller = caller self.caller = caller
if nodes and utils.is_iter(nodes): if nodes and utils.is_iter(nodes):
for node in nodes: for node in nodes:
@ -186,7 +190,8 @@ class MenuTree(object):
# if we was given the END node key, we clean up immediately. # if we was given the END node key, we clean up immediately.
self.caller.cmdset.delete("menucmdset") self.caller.cmdset.delete("menucmdset")
del self.caller.db._menu_data del self.caller.db._menu_data
self.caller.execute_cmd("look") if self.exec_end != None:
self.caller.execute_cmd(self.exec_end)
return return
# not exiting, look for a valid code. # not exiting, look for a valid code.
node = self.tree.get(key, None) node = self.tree.get(key, None)

View file

@ -128,7 +128,7 @@ class Character(BaseCharacter):
# save location again to be sure # save location again to be sure
self.db.prelogout_location = self.location self.db.prelogout_location = self.location
self.location.msg_contents("%s has entered the game." % self.name) self.location.msg_contents("%s has entered the game." % self.name, exclude=[self])
self.location.at_object_receive(self, self.location) self.location.at_object_receive(self, self.location)
class Room(BaseRoom): class Room(BaseRoom):

View file

@ -50,11 +50,17 @@ COMMAND_PARSER = utils.mod_import(*settings.COMMAND_PARSER.rsplit('.', 1))
# allow for custom behaviour when the command handler hits # allow for custom behaviour when the command handler hits
# special situations -- it then calls a normal Command # special situations -- it then calls a normal Command
# that you can customize! # that you can customize!
# Import these variables and use them rather than trying
# to remember the actual string constants.
CMD_NOINPUT = "__noinput_command" CMD_NOINPUT = "__noinput_command"
CMD_NOMATCH = "__nomatch_command" CMD_NOMATCH = "__nomatch_command"
CMD_MULTIMATCH = "__multimatch_command" CMD_MULTIMATCH = "__multimatch_command"
CMD_CHANNEL = "__send_to_channel" CMD_CHANNEL = "__send_to_channel_command"
# this is the name of the command the engine calls when the player
# connects. It is expected to show the login screen.
CMD_LOGINSTART = "__unloggedin_look_command"
class NoCmdSets(Exception): class NoCmdSets(Exception):
"No cmdsets found. Critical error." "No cmdsets found. Critical error."

View file

@ -13,6 +13,7 @@ from src.comms.models import Channel
from src.utils import create, logger, utils, ansi from src.utils import create, logger, utils, ansi
from src.commands.default.muxcommand import MuxCommand from src.commands.default.muxcommand import MuxCommand
from src.commands.cmdhandler import CMD_LOGINSTART
CONNECTION_SCREEN_MODULE = settings.CONNECTION_SCREEN_MODULE CONNECTION_SCREEN_MODULE = settings.CONNECTION_SCREEN_MODULE
@ -221,10 +222,12 @@ class CmdQuit(MuxCommand):
class CmdUnconnectedLook(MuxCommand): class CmdUnconnectedLook(MuxCommand):
""" """
This is an unconnected version of the look command for simplicity. This is an unconnected version of the look command for simplicity.
All it does is re-show the connect screen.
This is called by the server and kicks everything in gear.
All it does is display the connect screen.
""" """
key = "look" key = CMD_LOGINSTART
aliases = "l" aliases = ["look", "l"]
locks = "cmd:all()" locks = "cmd:all()"
def func(self): def func(self):

View file

@ -59,10 +59,6 @@ class ServerSession(Session):
# start (persistent) scripts on this object # start (persistent) scripts on this object
ScriptDB.objects.validate(obj=character) ScriptDB.objects.validate(obj=character)
def at_cmdset_get(self):
"dummy hook all objects with cmdsets need to have"
pass
def session_login(self, player): def session_login(self, player):
""" """
Startup mechanisms that need to run at login. This is called Startup mechanisms that need to run at login. This is called
@ -96,11 +92,10 @@ class ServerSession(Session):
player.at_pre_login() player.at_pre_login()
character = player.character character = player.character
#print "at_init() - character"
character.at_init()
if character: if character:
# this player has a character. Check if it's the # this player has a character. Check if it's the
# first time *this character* logs in # first time *this character* logs in
character.at_init()
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
@ -216,6 +211,7 @@ class ServerSession(Session):
def __eq__(self, other): def __eq__(self, other):
return self.address == other.address return self.address == other.address
def __str__(self): def __str__(self):
""" """
String representation of the user session class. We use String representation of the user session class. We use
@ -249,3 +245,57 @@ class ServerSession(Session):
def msg(self, string='', data=None): def msg(self, string='', data=None):
"alias for at_data_out" "alias for at_data_out"
self.data_out(string, data=data) self.data_out(string, data=data)
# Dummy API hooks for use a non-loggedin operation
def at_cmdset_get(self):
"dummy hook all objects with cmdsets need to have"
pass
# Mock db/ndb properties for allowing easy storage on the session
# (note that no databse is involved at all here. session.db.attr =
# value just saves a normal property in memory, just like ndb).
#@property
def ndb_get(self):
"""
A non-persistent store (ndb: NonDataBase). Everything stored
to this is guaranteed to be cleared when a server is shutdown.
Syntax is same as for the _get_db_holder() method and
property, e.g. obj.ndb.attr = value etc.
"""
try:
return self._ndb_holder
except AttributeError:
class NdbHolder(object):
"Holder for storing non-persistent attributes."
def all(self):
return [val for val in self.__dict__.keys()
if not val.startswith['_']]
def __getattribute__(self, key):
# return None if no matching attribute was found.
try:
return object.__getattribute__(self, key)
except AttributeError:
return None
self._ndb_holder = NdbHolder()
return self._ndb_holder
#@ndb.setter
def ndb_set(self, value):
"Stop accidentally replacing the db object"
string = "Cannot assign directly to ndb object! "
string = "Use ndb.attr=value instead."
raise Exception(string)
#@ndb.deleter
def ndb_del(self):
"Stop accidental deletion."
raise Exception("Cannot delete the ndb object!")
ndb = property(ndb_get, ndb_set, ndb_del)
db = property(ndb_get, ndb_set, ndb_del)
# Mock access method for the session (there is no lock info
# at this stage, so we just present a uniform API)
def access(self, *args, **kwargs):
"Dummy method."
return True

View file

@ -19,6 +19,8 @@ from django.contrib.auth.models import User
from src.server.models import ServerConfig from src.server.models import ServerConfig
from src.utils import utils from src.utils import utils
from src.commands.cmdhandler import CMD_LOGINSTART
# i18n # i18n
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
@ -94,7 +96,7 @@ class ServerSessionHandler(SessionHandler):
Creates a new, unlogged-in game session. Creates a new, unlogged-in game session.
""" """
self.sessions[sessid] = session self.sessions[sessid] = session
session.execute_cmd('look') session.execute_cmd(CMD_LOGINSTART)
def portal_disconnect(self, sessid): def portal_disconnect(self, sessid):
""" """