diff --git a/evennia/__init__.py b/evennia/__init__.py index d1aac45bb..fc68e75c9 100644 --- a/evennia/__init__.py +++ b/evennia/__init__.py @@ -106,6 +106,9 @@ MONITOR_HANDLER = None GLOBAL_SCRIPTS = None OPTION_CLASSES = None +# variables +PORTAL_MODE = False + def _create_version(): """ @@ -160,6 +163,8 @@ def _init(portal_mode=False): global EvMenu, EvTable, EvForm, EvMore, EvEditor global ANSIString, FuncParser global AttributeProperty, TagProperty, TagCategoryProperty + global PORTAL_MODE + PORTAL_MODE = portal_mode # Parent typeclasses # utilities @@ -187,8 +192,9 @@ def _init(portal_mode=False): from .utils import ansi, gametime, logger from .utils.ansi import ANSIString - # containers - from .utils.containers import GLOBAL_SCRIPTS, OPTION_CLASSES + if not PORTAL_MODE: + # containers + from .utils.containers import GLOBAL_SCRIPTS, OPTION_CLASSES # create functions from .utils.create import ( @@ -218,7 +224,7 @@ def _init(portal_mode=False): ) from .utils.utils import class_from_module - if portal_mode: + if PORTAL_MODE: # Set up the PortalSessionHandler from evennia.server.portal import portalsessionhandler @@ -227,6 +233,7 @@ def _init(portal_mode=False): else: # Create the ServerSesssionHandler from evennia.server import sessionhandler + sess_handler_class = class_from_module(settings.SERVER_SESSION_HANDLER_CLASS) sessionhandler.SESSIONS = sess_handler_class() sessionhandler.SESSION_HANDLER = sessionhandler.SESSIONS @@ -375,11 +382,6 @@ def _init(portal_mode=False): del SystemCmds del _EvContainer - # delayed starts - important so as to not back-access evennia before it has - # finished initializing - if not portal_mode: - GLOBAL_SCRIPTS.start() - def set_trace(term_size=(140, 80), debugger="auto"): """ diff --git a/evennia/server/server.py b/evennia/server/server.py index c5bd6da95..1491550cf 100644 --- a/evennia/server/server.py +++ b/evennia/server/server.py @@ -453,6 +453,10 @@ class Evennia: # always call this regardless of start type self.at_server_start() + # Moved here from evennia._init() to ensure it only runs after + # setup is complete and only in server mode. + evennia.GLOBAL_SCRIPTS.start() + @defer.inlineCallbacks def shutdown(self, mode="reload", _reactor_stopping=False): """ diff --git a/evennia/utils/containers.py b/evennia/utils/containers.py index 23e41db45..70b7b43f7 100644 --- a/evennia/utils/containers.py +++ b/evennia/utils/containers.py @@ -114,26 +114,13 @@ class GlobalScriptContainer(Container): initialized before Scripts are actually initialized. """ - self.typeclass_storage = None + self.typeclass_storage = dict() self.loaded_data = { key: {} if data is None else data for key, data in settings.GLOBAL_SCRIPTS.items() } - - def _get_scripts(self, key=None, default=None): - global SCRIPTDB - if not SCRIPTDB: - from evennia.scripts.models import ScriptDB as SCRIPTDB - if key: - try: - return SCRIPTDB.objects.get(db_key__exact=key, db_obj__isnull=True) - except SCRIPTDB.DoesNotExist: - return default - else: - return SCRIPTDB.objects.filter(db_obj__isnull=True) + self.loaded = False def _load_script(self, key): - self.load_data() - typeclass = self.typeclass_storage[key] script = typeclass.objects.filter( db_key=key, db_account__isnull=True, db_obj__isnull=True @@ -168,7 +155,7 @@ class GlobalScriptContainer(Container): return None # store a hash representation of the setup - script.attributes.add("_global_script_settings", compare_hash, category="settings_hash") + script.attributes.add("global_script_settings", compare_hash, category="settings_hash") return script @@ -182,14 +169,18 @@ class GlobalScriptContainer(Container): """ # populate self.typeclass_storage - self.load_data() + if not self.loaded: + self.load_data() # make sure settings-defined scripts are loaded + scripts_to_run = [] for key in self.loaded_data: - self._load_script(key) + script = self._load_script(key) + if script: + scripts_to_run.append(script) # start all global scripts try: - for script in self._get_scripts(): + for script in scripts_to_run: script.start() except (OperationalError, ProgrammingError): # this can happen if db is not loaded yet (such as when building docs) @@ -201,13 +192,15 @@ class GlobalScriptContainer(Container): initialized. """ - if self.typeclass_storage is None: - self.typeclass_storage = {} + if self.loaded: + return + if not self.typeclass_storage: for key, data in list(self.loaded_data.items()): typeclass = data.get("typeclass", settings.BASE_SCRIPT_TYPECLASS) self.typeclass_storage[key] = class_from_module( typeclass, fallback=settings.BASE_SCRIPT_TYPECLASS ) + self.loaded = True def get(self, key, default=None): """ @@ -223,20 +216,23 @@ class GlobalScriptContainer(Container): Returns: any (any): The data loaded on this container. """ - res = self._get_scripts(key) - if not res: - if key in self.loaded_data: - if key not in self.typeclass_storage: - # this means we are trying to load in a loop - raise RuntimeError( - f"Trying to access `GLOBAL_SCRIPTS.{key}` before scripts have finished " - "initializing. This can happen if accessing GLOBAL_SCRIPTS from the same " - "module the script is defined in." - ) - # recreate if we have the info - return self._load_script(key) or default - return default - return res + if not self.loaded: + self.load_data() + out_value = default + if key in self.loaded_data: + if key not in self.typeclass_storage: + # this means we are trying to load in a loop + raise RuntimeError( + f"Trying to access `GLOBAL_SCRIPTS.{key}` before scripts have finished " + "initializing. This can happen if accessing GLOBAL_SCRIPTS from the same " + "module the script is defined in." + ) + # recreate if we have the info + script_found = self._load_script(key) + if script_found: + out_value = script_found + + return out_value def all(self): """ @@ -247,11 +243,9 @@ class GlobalScriptContainer(Container): scripts (list): All global script objects stored on the container. """ - self.typeclass_storage = None - self.load_data() - for key in self.loaded_data: - self._load_script(key) - return self._get_scripts(None) + if not self.loaded: + self.load_data() + return self.scripts.values() # Create all singletons