diff --git a/evennia/commands/cmdsethandler.py b/evennia/commands/cmdsethandler.py index 3f01dbcac2..b52c70d3a8 100644 --- a/evennia/commands/cmdsethandler.py +++ b/evennia/commands/cmdsethandler.py @@ -80,6 +80,8 @@ __all__ = ("import_cmdset", "CmdSetHandler") _CACHED_CMDSETS = {} _CMDSET_PATHS = utils.make_iter(settings.CMDSET_PATHS) _IN_GAME_ERRORS = settings.IN_GAME_ERRORS +_CMDSET_FALLBACKS = settings.CMDSET_FALLBACKS + # Output strings @@ -102,6 +104,16 @@ _ERROR_CMDSET_EXCEPTION = _( Compile/Run error when loading cmdset '{path}'.", (Traceback was logged {timestamp})""") +_ERROR_CMDSET_FALLBACK = _( +""" +Error encountered for cmdset at path '{path}'. +Replacing with fallback '{fallback_path}'. +""") + +_ERROR_CMDSET_NO_FALLBACK = _( +"""Fallback path '{fallback_path}' failed to generate a cmdset.""" +) + class _ErrorCmdSet(CmdSet): """ @@ -351,6 +363,22 @@ class CmdSetHandler(object): elif path: cmdset = self._import_cmdset(path) if cmdset: + if cmdset.key == '_CMDSET_ERROR': + # If a cmdset fails to load, check if we have a fallback path to use + fallback_path = _CMDSET_FALLBACKS.get(path, None) + if fallback_path: + err = _ERROR_CMDSET_FALLBACK.format(path=path, fallback_path=fallback_path) + logger.log_err(err) + if _IN_GAME_ERRORS: + self.obj.msg(err) + cmdset = self._import_cmdset(fallback_path) + # If no cmdset is returned from the fallback, we can't go further + if not cmdset: + err = _ERROR_CMDSET_NO_FALLBACK.format(fallback_path=fallback_path) + logger.log_err(err) + if _IN_GAME_ERRORS: + self.obj.msg(err) + continue cmdset.permanent = cmdset.key != '_CMDSET_ERROR' self.cmdset_stack.append(cmdset) diff --git a/evennia/contrib/ingame_python/scripts.py b/evennia/contrib/ingame_python/scripts.py index 11a1b9e24a..cf538a7846 100644 --- a/evennia/contrib/ingame_python/scripts.py +++ b/evennia/contrib/ingame_python/scripts.py @@ -10,7 +10,7 @@ import traceback from django.conf import settings from evennia import DefaultObject, DefaultScript, ChannelDB, ScriptDB -from evennia import logger +from evennia import logger, ObjectDB from evennia.utils.ansi import raw from evennia.utils.create import create_channel from evennia.utils.dbserialize import dbserialize @@ -101,21 +101,29 @@ class EventHandler(DefaultScript): Return a dictionary of events on this object. Args: - obj (Object): the connected object. + obj (Object or typeclass): the connected object or a general typeclass. Returns: A dictionary of the object's events. - Note: + Notes: Events would define what the object can have as callbacks. Note, however, that chained callbacks will not appear in events and are handled separately. + You can also request the events of a typeclass, not a + connected object. This is useful to get the global list + of events for a typeclass that has no object yet. + """ events = {} all_events = self.ndb.events classes = Queue() - classes.put(type(obj)) + if isinstance(obj, type): + classes.put(obj) + else: + classes.put(type(obj)) + invalid = [] while not classes.empty(): typeclass = classes.get() diff --git a/evennia/settings_default.py b/evennia/settings_default.py index 283930eb0f..4ff4bdf6f7 100644 --- a/evennia/settings_default.py +++ b/evennia/settings_default.py @@ -348,6 +348,12 @@ CMDSET_CHARACTER = "commands.default_cmdsets.CharacterCmdSet" CMDSET_PLAYER = "commands.default_cmdsets.PlayerCmdSet" # Location to search for cmdsets if full path not given CMDSET_PATHS = ["commands", "evennia", "contribs"] +# Fallbacks for cmdset paths that fail to load. Note that if you change the path for your default cmdsets, +# you will also need to copy CMDSET_FALLBACKS after your change in your settings file for it to detect the change. +CMDSET_FALLBACKS = {CMDSET_CHARACTER: 'evennia.commands.default.cmdset_character.CharacterCmdSet', + CMDSET_PLAYER: 'evennia.commands.default.cmdset_player.PlayerCmdSet', + CMDSET_SESSION: 'evennia.commands.default.cmdset_session.SessionCmdSet', + CMDSET_UNLOGGEDIN: 'evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet'} # Parent class for all default commands. Changing this class will # modify all default commands, so do so carefully. COMMAND_DEFAULT_CLASS = "evennia.commands.default.muxcommand.MuxCommand"