Changed cmdhandler to include Session-level cmdset.

This commit is contained in:
Griatch 2013-09-08 00:14:06 +02:00
parent 07b1e40299
commit 1e96b13920
11 changed files with 205 additions and 80 deletions

View file

@ -48,6 +48,8 @@ from django.utils.translation import ugettext as _
__all__ = ("cmdhandler",) __all__ = ("cmdhandler",)
_GA = object.__getattribute__
# This decides which command parser is to be used. # This decides which command parser is to be used.
# You have to restart the server for changes to take effect. # You have to restart the server for changes to take effect.
_COMMAND_PARSER = utils.variable_from_module(*settings.COMMAND_PARSER.rsplit('.', 1)) _COMMAND_PARSER = utils.variable_from_module(*settings.COMMAND_PARSER.rsplit('.', 1))
@ -83,65 +85,112 @@ class ExecSystemCommand(Exception):
# Helper function # Helper function
@inlineCallbacks @inlineCallbacks
def get_and_merge_cmdsets(caller): def get_and_merge_cmdsets(caller, session, player, obj, callertype, sessid=None):
""" """
Gather all relevant cmdsets and merge them. Note Gather all relevant cmdsets and merge them.
that this is only relevant for logged-in callers.
callertype is one of "session", "player" or "object" dependin
on which level the cmdhandler is invoked. Session includes the
cmdsets available to Session, Player and its eventual puppeted Object.
Player-level include cmdsets on Player and Object, while calling
the handler on an Object only includes cmdsets on itself.
The cdmsets are merged in order generality, so that the Object's
cmdset is merged last (and will thus take precedence over
same-named and same-prio commands on Player and Session).
Note that this function returns a deferred! Note that this function returns a deferred!
""" """
# The calling object's cmdset local_obj_cmdsets = [None]
try:
yield caller.at_cmdset_get()
except Exception:
logger.log_trace()
try:
caller_cmdset = caller.cmdset.current
except AttributeError:
caller_cmdset = None
# Create cmdset for all player's available channels @inlineCallbacks
channel_cmdset = None def _get_channel_cmdsets(player, player_cmdset):
if not caller_cmdset.no_channels: "Channel-cmdsets"
channel_cmdset = yield CHANNELHANDLER.get_cmdset(caller) # Create cmdset for all player's available channels
channel_cmdset = None
if not player_cmdset.no_channels:
channel_cmdset = yield CHANNELHANDLER.get_cmdset(player)
returnValue(channel_cmdset)
# Gather cmdsets from location, objects in location or carried @inlineCallbacks
local_objects_cmdsets = [None] def _get_local_obj_cmdsets(obj, obj_cmdset):
try: "Object-level cmdsets"
location = caller.location # Gather cmdsets from location, objects in location or carried
except Exception: local_obj_cmdsets = [None]
location = None try:
if location and not caller_cmdset.no_objs: location = obj.location
# Gather all cmdsets stored on objects in the room and except Exception:
# also in the caller's inventory and the location itself location = None
local_objlist = yield location.contents_get(exclude=caller.dbobj) + caller.contents + [location] if location and not obj_cmdset.no_objs:
for obj in local_objlist: # Gather all cmdsets stored on objects in the room and
try: # also in the caller's inventory and the location itself
# call hook in case we need to do dynamic changing to cmdset local_objlist = yield location.contents_get(exclude=obj.dbobj) + obj.contents + [location]
yield obj.at_cmdset_get() for lobj in local_objlist:
except Exception: try:
logger.log_trace() # call hook in case we need to do dynamic changing to cmdset
# the call-type lock is checked here, it makes sure a player is not seeing e.g. the commands _GA(lobj, "at_cmdset_get")()
# on a fellow player (which is why the no_superuser_bypass must be True) except Exception:
local_objects_cmdsets = yield [obj.cmdset.current for obj in local_objlist logger.log_trace()
if (obj.cmdset.current and obj.locks.check(caller, 'call', no_superuser_bypass=True))] # the call-type lock is checked here, it makes sure a player is not seeing e.g. the commands
for cset in local_objects_cmdsets: # on a fellow player (which is why the no_superuser_bypass must be True)
#This is necessary for object sets, or we won't be able to separate local_obj_cmdsets = yield [lobj.cmdset.current for lobj in local_objlist
#the command sets from each other in a busy room. if (lobj.cmdset.current and lobj.locks.check(caller, 'call', no_superuser_bypass=True))]
cset.old_duplicates = cset.duplicates for cset in local_obj_cmdsets:
cset.duplicates = True #This is necessary for object sets, or we won't be able to separate
#the command sets from each other in a busy room.
cset.old_duplicates = cset.duplicates
cset.duplicates = True
returnValue(local_obj_cmdsets)
# Player object's commandsets @inlineCallbacks
try: def _get_cmdset(obj):
player_cmdset = caller.player.cmdset.current "Get cmdset, triggering all hooks"
except AttributeError: try:
player_cmdset = None yield obj.at_cmdset_get()
except Exception:
logger.log_trace()
try:
returnValue(obj.cmdset.current)
except AttributeError:
returnValue(None)
if callertype == "session":
# we are calling the command from the session level
report_to = session
session_cmdset = yield _get_cmdset(session)
cmdsets = [session_cmdset]
if player: # this automatically implies logged-in
player_cmdset = yield _get_cmdset(player)
channel_cmdset = yield _get_channel_cmdsets(player, player_cmdset)
cmdsets.extend([player_cmdset, channel_cmdset])
if obj:
obj_cmdset = yield _get_cmdset(obj)
local_obj_cmdsets = yield _get_local_obj_cmdsets(obj, obj_cmdset)
cmdsets.extend([obj_cmdset] + local_obj_cmdsets)
elif callertype == "player":
# we are calling the command from the player level
report_to = player
player_cmdset = yield _get_cmdset(player)
channel_cmdset = yield _get_channel_cmdsets(player, player_cmdset)
cmdsets = [player_cmdset, channel_cmdset]
if obj:
obj_cmdset = yield _get_cmdset(obj)
local_obj_cmdsets = yield _get_local_obj_cmdsets(obj, obj_cmdset)
cmdsets.extend([obj_cmdset] + local_obj_cmdsets)
elif callertype == "object":
# we are calling the command from the object level
report_to = obj
obj_cmdset = yield _get_cmdset(obj)
local_obj_cmdsets = yield _get_local_obj_cmdsets(obj, obj_cmdset)
cmdsets = [obj_cmdset] + local_obj_cmdsets
else:
raise Exception("get_and_merge_cmdsets: callertype %s is not valid." % callertype)
#cmdsets = yield [caller_cmdset] + [player_cmdset] + [channel_cmdset] + local_obj_cmdsets
cmdsets = yield [caller_cmdset] + [player_cmdset] + [channel_cmdset] + local_objects_cmdsets
# weed out all non-found sets # weed out all non-found sets
cmdsets = yield [cmdset for cmdset in cmdsets if cmdset and cmdset.key!="Empty"] cmdsets = yield [cmdset for cmdset in cmdsets if cmdset and cmdset.key!="Empty"]
# report cmdset errors to user (these should already have been logged) # report cmdset errors to user (these should already have been logged)
yield [caller.msg(cmdset.errmessage) for cmdset in cmdsets if cmdset.key == "_CMDSET_ERROR"] yield [report_to.msg(cmdset.errmessage) for cmdset in cmdsets if cmdset.key == "_CMDSET_ERROR"]
if cmdsets: if cmdsets:
# we group and merge all same-prio cmdsets separately (this avoids order-dependent # we group and merge all same-prio cmdsets separately (this avoids order-dependent
@ -167,7 +216,7 @@ def get_and_merge_cmdsets(caller):
else: else:
cmdset = None cmdset = None
for cset in (cset for cset in local_objects_cmdsets if cset): for cset in (cset for cset in local_obj_cmdsets if cset):
cset.duplicates = cset.old_duplicates cset.duplicates = cset.old_duplicates
returnValue(cmdset) returnValue(cmdset)
@ -175,21 +224,49 @@ def get_and_merge_cmdsets(caller):
# Main command-handler function # Main command-handler function
@inlineCallbacks @inlineCallbacks
def cmdhandler(caller, raw_string, testing=False, sessid=None): def cmdhandler(called_on, raw_string, testing=False, callertype="session", sessid=None):
""" """
This is the main function to handle any string sent to the engine. This is the main function to handle any string sent to the engine.
caller - calling object called_on - object on which this was called from. This is either a Session, a Player or an Object.
raw_string - the command string given on the command line raw_string - the command string given on the command line
testing - if we should actually execute the command or not. testing - if we should actually execute the command or not.
if True, the command instance will be returned instead. if True, the command instance will be returned instead.
sessid - the session id calling this handler, if any callertype - this is one of "session", "player" or "object", in decending
order. So when the Session is the caller, it will merge its
own cmdset into cmdsets from both Player and eventual puppeted Object (and
cmdsets in its room etc). A Player will only include its
own cmdset and the Objects and so on. Merge order is the
same order, so that Object cmdsets are merged in last, giving
them precendence for same-name and same-prio commands.
sessid - Relevant if callertype is "player" - the session id will help retrieve the
correct cmdsets from puppeted objects.
Note that this function returns a deferred! Note that this function returns a deferred!
""" """
session, player, obj = None, None, None
if callertype == "session":
session = called_on
player = session.player
if player:
obj = yield _GA(player.dbobj, "get_puppet")(session.sessid)
elif callertype == "player":
player = called_on
if sessid:
obj = yield _GA(player.dbobj, "get_puppet")(sessid)
elif callertype == "object":
obj = called_on
else:
raise RuntimeError("cmdhandler: callertype %s is not valid." % callertype)
# the caller will be the one to receive messages and excert its permissions.
# we assign the caller with preference 'bottom up'
caller = obj or player or session
try: # catch bugs in cmdhandler itself try: # catch bugs in cmdhandler itself
try: # catch special-type commands try: # catch special-type commands
cmdset = yield get_and_merge_cmdsets(caller) cmdset = yield get_and_merge_cmdsets(caller, session, player, obj, callertype, sessid)
if not cmdset: if not cmdset:
# this is bad and shouldn't happen. # this is bad and shouldn't happen.
raise NoCmdSets raise NoCmdSets
@ -212,13 +289,15 @@ def cmdhandler(caller, raw_string, testing=False, sessid=None):
syscmd = yield cmdset.get(CMD_MULTIMATCH) syscmd = yield cmdset.get(CMD_MULTIMATCH)
sysarg = _("There were multiple matches.") sysarg = _("There were multiple matches.")
if syscmd: if syscmd:
# use custom CMD_MULTIMATCH
syscmd.matches = matches syscmd.matches = matches
else: else:
# fall back to default error handling
sysarg = yield at_multimatch_cmd(caller, matches) sysarg = yield at_multimatch_cmd(caller, matches)
raise ExecSystemCommand(syscmd, sysarg) raise ExecSystemCommand(syscmd, sysarg)
if len(matches) == 1: if len(matches) == 1:
# We have a unique command match. # We have a unique command match. But it may still be invalid.
match = matches[0] match = matches[0]
cmdname, args, cmd = match[0], match[1], match[2] cmdname, args, cmd = match[0], match[1], match[2]
@ -232,8 +311,10 @@ def cmdhandler(caller, raw_string, testing=False, sessid=None):
# No commands match our entered command # No commands match our entered command
syscmd = yield cmdset.get(CMD_NOMATCH) syscmd = yield cmdset.get(CMD_NOMATCH)
if syscmd: if syscmd:
# use custom CMD_NOMATH command
sysarg = raw_string sysarg = raw_string
else: else:
# fallback to default error text
sysarg = _("Command '%s' is not available.") % raw_string sysarg = _("Command '%s' is not available.") % raw_string
suggestions = string_suggestions(raw_string, cmdset.get_all_cmd_keys_and_aliases(caller), cutoff=0.7, maxnum=3) suggestions = string_suggestions(raw_string, cmdset.get_all_cmd_keys_and_aliases(caller), cutoff=0.7, maxnum=3)
if suggestions: if suggestions:
@ -243,7 +324,7 @@ def cmdhandler(caller, raw_string, testing=False, sessid=None):
raise ExecSystemCommand(syscmd, sysarg) raise ExecSystemCommand(syscmd, sysarg)
# Check if this is a Channel match. # Check if this is a Channel-cmd match.
if hasattr(cmd, 'is_channel') and cmd.is_channel: if hasattr(cmd, 'is_channel') and cmd.is_channel:
# even if a user-defined syscmd is not defined, the # even if a user-defined syscmd is not defined, the
# found cmd is already a system command in its own right. # found cmd is already a system command in its own right.
@ -251,7 +332,7 @@ def cmdhandler(caller, raw_string, testing=False, sessid=None):
if syscmd: if syscmd:
# replace system command with custom version # replace system command with custom version
cmd = syscmd cmd = syscmd
cmd.sessid = sessid cmd.sessid = caller.sessid if callertype=="session" else None
sysarg = "%s:%s" % (cmdname, args) sysarg = "%s:%s" % (cmdname, args)
raise ExecSystemCommand(cmd, sysarg) raise ExecSystemCommand(cmd, sysarg)
@ -262,11 +343,14 @@ def cmdhandler(caller, raw_string, testing=False, sessid=None):
cmd.cmdstring = cmdname cmd.cmdstring = cmdname
cmd.args = args cmd.args = args
cmd.cmdset = cmdset cmd.cmdset = cmdset
cmd.sessid = sessid cmd.session = session
cmd.player = player
#cmd.obj # set via command handler
cmd.sessid = session.sessid if session else sessid
cmd.raw_string = unformatted_raw_string cmd.raw_string = unformatted_raw_string
if hasattr(cmd, 'obj') and hasattr(cmd.obj, 'scripts'): if hasattr(cmd, 'obj') and hasattr(cmd.obj, 'scripts'):
# cmd.obj is automatically made available. # cmd.obj is automatically made available by the cmdhandler.
# we make sure to validate its scripts. # we make sure to validate its scripts.
yield cmd.obj.scripts.validate() yield cmd.obj.scripts.validate()
@ -312,7 +396,7 @@ def cmdhandler(caller, raw_string, testing=False, sessid=None):
syscmd.cmdstring = syscmd.key syscmd.cmdstring = syscmd.key
syscmd.args = sysarg syscmd.args = sysarg
syscmd.cmdset = cmdset syscmd.cmdset = cmdset
syscmd.sessid = sessid syscmd.sessid = caller.sessid if callertype=="session" else None
syscmd.raw_string = unformatted_raw_string syscmd.raw_string = unformatted_raw_string
if hasattr(syscmd, 'obj') and hasattr(syscmd.obj, 'scripts'): if hasattr(syscmd, 'obj') and hasattr(syscmd.obj, 'scripts'):

View file

@ -262,7 +262,7 @@ def at_multimatch_cmd(caller, matches):
id1 = "" id1 = ""
id2 = "" id2 = ""
if not (is_channel or is_exit) and (hasattr(cmd, 'obj') and cmd.obj != caller): if not (is_channel or is_exit) and (hasattr(cmd, 'obj') and cmd.obj != caller) and hasattr(cmd.obj, "key"):
# the command is defined on some other object # the command is defined on some other object
id1 = "%s-%s" % (num + 1, cmdname) id1 = "%s-%s" % (num + 1, cmdname)
id2 = " (%s)" % (cmd.obj.key) id2 = " (%s)" % (cmd.obj.key)

View file

@ -1673,7 +1673,7 @@ class CmdExamine(ObjManipCommand):
caller.execute_cmd('look %s' % obj.name) caller.execute_cmd('look %s' % obj.name)
return return
# using callback for printing result whenever function returns. # using callback for printing result whenever function returns.
get_and_merge_cmdsets(obj).addCallback(get_cmdset_callback) get_and_merge_cmdsets(obj, self.session, self.player, obj, "session").addCallback(get_cmdset_callback)
else: else:
self.msg("You need to supply a target to examine.") self.msg("You need to supply a target to examine.")
return return
@ -1708,7 +1708,7 @@ class CmdExamine(ObjManipCommand):
caller.msg(self.format_attributes(obj, attrname, crop=False)) caller.msg(self.format_attributes(obj, attrname, crop=False))
else: else:
# using callback to print results whenever function returns. # using callback to print results whenever function returns.
get_and_merge_cmdsets(obj).addCallback(get_cmdset_callback) get_and_merge_cmdsets(obj, self.session, self.player, obj, "session").addCallback(get_cmdset_callback)
class CmdFind(MuxCommand): class CmdFind(MuxCommand):

View file

@ -29,7 +29,7 @@ class PlayerCmdSet(CmdSet):
self.add(player.CmdIC()) self.add(player.CmdIC())
self.add(player.CmdOOC()) self.add(player.CmdOOC())
self.add(player.CmdCharCreate()) self.add(player.CmdCharCreate())
self.add(player.CmdSessions()) #self.add(player.CmdSessions())
self.add(player.CmdWho()) self.add(player.CmdWho())
self.add(player.CmdEncoding()) self.add(player.CmdEncoding())
self.add(player.CmdQuit()) self.add(player.CmdQuit())

View file

@ -0,0 +1,16 @@
"""
This module stores session-level commands.
"""
from src.commands.cmdset import CmdSet
from src.commands.default import player
class SessionCmdSet(CmdSet):
"""
Sets up the unlogged cmdset.
"""
key = "DefaultSession"
priority = 0
def at_cmdset_creation(self):
"Populate the cmdset"
self.add(player.CmdSessions())

View file

@ -656,7 +656,7 @@ class ObjectDB(TypedObject):
if nick.db_key in raw_list: if nick.db_key in raw_list:
raw_string = raw_string.replace(nick.db_key, nick.db_strvalue, 1) raw_string = raw_string.replace(nick.db_key, nick.db_strvalue, 1)
break break
return cmdhandler.cmdhandler(_GA(self, "typeclass"), raw_string, sessid=sessid) return cmdhandler.cmdhandler(_GA(self, "typeclass"), raw_string, callertype="object", sessid=sessid)
def msg(self, msg=None, from_obj=None, data=None, sessid=0): def msg(self, msg=None, from_obj=None, data=None, sessid=0):
""" """

View file

@ -494,7 +494,7 @@ class PlayerDB(TypedObject, AbstractUser):
# should not matter (since the return goes to all of them we can just # should not matter (since the return goes to all of them we can just
# use the first one as the source) # use the first one as the source)
sessid = self.get_all_sessions()[0].sessid sessid = self.get_all_sessions()[0].sessid
return cmdhandler.cmdhandler(self.typeclass, raw_string, sessid=sessid) return cmdhandler.cmdhandler(self.typeclass, raw_string, callertype="player", sessid=sessid)
def search(self, ostring, return_character=False, **kwargs): def search(self, ostring, return_character=False, **kwargs):
""" """

View file

@ -13,6 +13,7 @@ from django.conf import settings
from src.scripts.models import ScriptDB from src.scripts.models import ScriptDB
from src.comms.models import Channel from src.comms.models import Channel
from src.utils import logger, utils from src.utils import logger, utils
from src.utils.utils import make_iter
from src.commands import cmdhandler, cmdsethandler from src.commands import cmdhandler, cmdsethandler
from src.server.session import Session from src.server.session import Session
@ -46,6 +47,15 @@ class ServerSession(Session):
def __init__(self): def __init__(self):
"Initiate to avoid AttributeErrors down the line" "Initiate to avoid AttributeErrors down the line"
self.puppet = None self.puppet = None
self.player = None
self.cmdset_storage_string = ""
self.cmdset = cmdsethandler.CmdSetHandler(self)
def __cmdset_storage_get(self):
return [path.strip() for path in self.cmdset_storage_string.split(',')]
def __cmdset_storage_set(self, value):
self.cmdset_storage_string = ",".join(str(val).strip() for val in make_iter(value))
cmdset_storage = property(__cmdset_storage_get, __cmdset_storage_set)
def at_sync(self): def at_sync(self):
""" """
@ -62,10 +72,11 @@ class ServerSession(Session):
if not self.logged_in: if not self.logged_in:
# assign the unloggedin-command set. # assign the unloggedin-command set.
self.cmdset = cmdsethandler.CmdSetHandler(self) self.cmdset_storage = settings.CMDSET_UNLOGGEDIN
self.cmdset_storage = [settings.CMDSET_UNLOGGEDIN]
self.cmdset.update(init_mode=True) self.cmdset.update(init_mode=True)
elif self.puid:
if self.puid:
# reconnect puppet (puid is only set if we are coming back from a server reload) # reconnect puppet (puid is only set if we are coming back from a server reload)
obj = _ObjectDB.objects.get(id=self.puid) obj = _ObjectDB.objects.get(id=self.puid)
self.player.puppet_object(self.sessid, obj, normal_mode=False) self.player.puppet_object(self.sessid, obj, normal_mode=False)
@ -83,11 +94,16 @@ class ServerSession(Session):
self.conn_time = time.time() self.conn_time = time.time()
self.puid = None self.puid = None
self.puppet = None self.puppet = None
self.cmdset_storage = settings.CMDSET_SESSION
# Update account's last login time. # Update account's last login time.
self.player.last_login = datetime.now() self.player.last_login = datetime.now()
self.player.save() self.player.save()
# add the session-level cmdset
self.cmdset = cmdsethandler.CmdSetHandler(self)
self.cmdset.update(init_mode=True)
def at_disconnect(self): def at_disconnect(self):
""" """
Hook called by sessionhandler when disconnecting this session. Hook called by sessionhandler when disconnecting this session.
@ -156,13 +172,14 @@ class ServerSession(Session):
if str(command_string).strip() == IDLE_COMMAND: if str(command_string).strip() == IDLE_COMMAND:
self.update_session_counters(idle=True) self.update_session_counters(idle=True)
return return
if self.logged_in: cmdhandler.cmdhandler(self, command_string, callertype="session", sessid=self.sessid)
# the inmsg handler will relay to the right place #if self.logged_in:
self.player.inmsg(command_string, self) # # the inmsg handler will relay to the right place
else: # self.player.inmsg(command_string, self)
# we are not logged in. Execute cmd with the the session directly #else:
# (it uses the settings.UNLOGGEDIN cmdset) # # we are not logged in. Execute cmd with the the session directly
cmdhandler.cmdhandler(self, command_string, sessid=self.sessid) # # (it uses the settings.UNLOGGEDIN cmdset)
# cmdhandler.cmdhandler(self, command_string, sessid=self.sessid)
self.update_session_counters() self.update_session_counters()
execute_cmd = data_in # alias execute_cmd = data_in # alias

View file

@ -36,7 +36,7 @@ class Session(object):
_attrs_to_sync = ('protocol_key', 'address', 'suid', 'sessid', 'uid', 'uname', _attrs_to_sync = ('protocol_key', 'address', 'suid', 'sessid', 'uid', 'uname',
'logged_in', 'puid', 'encoding', 'logged_in', 'puid', 'encoding',
'conn_time', 'cmd_last', 'cmd_last_visible', 'cmd_total', 'conn_time', 'cmd_last', 'cmd_last_visible', 'cmd_total',
'protocol_flags', 'server_data') 'protocol_flags', 'server_data', "cmdset_storage_string")
def init_session(self, protocol_key, address, sessionhandler): def init_session(self, protocol_key, address, sessionhandler):
""" """

View file

@ -15,6 +15,7 @@ There are two similar but separate stores of sessions:
import time import time
from django.conf import settings from django.conf import settings
from src.commands.cmdhandler import CMD_LOGINSTART from src.commands.cmdhandler import CMD_LOGINSTART
from src.utils.utils import variable_from_module
# delayed imports # delayed imports
_PlayerDB = None _PlayerDB = None
@ -43,7 +44,9 @@ def delayed_import():
"Helper method for delayed import of all needed entities" "Helper method for delayed import of all needed entities"
global _ServerSession, _PlayerDB, _ServerConfig, _ScriptDB global _ServerSession, _PlayerDB, _ServerConfig, _ScriptDB
if not _ServerSession: if not _ServerSession:
from src.server.serversession import ServerSession as _ServerSession # we allow optional arbitrary serversession class for overloading
modulename, classname = settings.SERVER_SESSION_CLASS.rsplit(".", 1)
_ServerSession = variable_from_module(modulename, classname)
if not _PlayerDB: if not _PlayerDB:
from src.players.models import PlayerDB as _PlayerDB from src.players.models import PlayerDB as _PlayerDB
if not _ServerConfig: if not _ServerConfig:

View file

@ -216,17 +216,22 @@ LOCK_FUNC_MODULES = ("src.locks.lockfuncs",)
# to point to these copies instead - these you can then change as you please # to point to these copies instead - these you can then change as you please
# (or copy/paste from the default modules in src/ if you prefer). # (or copy/paste from the default modules in src/ if you prefer).
# Command set used before player has logged in # Command set used on session before player has logged in
CMDSET_UNLOGGEDIN = "src.commands.default.cmdset_unloggedin.UnloggedinCmdSet" CMDSET_UNLOGGEDIN = "src.commands.default.cmdset_unloggedin.UnloggedinCmdSet"
# Command set used on the logged-in session
CMDSET_SESSION = "src.commands.default.cmdset_session.SessionCmdSet"
# Default set for logged in player with characters (fallback) # Default set for logged in player with characters (fallback)
CMDSET_CHARACTER = "src.commands.default.cmdset_character.CharacterCmdSet" CMDSET_CHARACTER = "src.commands.default.cmdset_character.CharacterCmdSet"
# Command set for players without a character (ooc) # Command set for players without a character (ooc)
CMDSET_PLAYER = "src.commands.default.cmdset_player.PlayerCmdSet" CMDSET_PLAYER = "src.commands.default.cmdset_player.PlayerCmdSet"
###################################################################### ######################################################################
# Typeclasses # Typeclasses and other paths
###################################################################### ######################################################################
# Server-side session class used.
SERVER_SESSION_CLASS = "src.server.serversession.ServerSession"
# Base paths for typeclassed object classes. These paths must be # Base paths for typeclassed object classes. These paths must be
# defined relative evennia's root directory. They will be searched in # defined relative evennia's root directory. They will be searched in
# order to find relative typeclass paths. # order to find relative typeclass paths.