diff --git a/evennia/contrib/puzzles.py b/evennia/contrib/puzzles.py index 1ca661cd5d..5eef1f77e2 100644 --- a/evennia/contrib/puzzles.py +++ b/evennia/contrib/puzzles.py @@ -289,7 +289,7 @@ class CmdCreatePuzzleRecipe(MuxCommand): proto_parts = [proto_def(obj) for obj in parts] proto_results = [proto_def(obj) for obj in results] - puzzle = create_script(PuzzleRecipe, key=puzzle_name) + puzzle = create_script(PuzzleRecipe, key=puzzle_name, persistent=True) puzzle.save_recipe(puzzle_name, proto_parts, proto_results) puzzle.locks.add("control:id(%s) or perm(Builder)" % caller.dbref[1:]) @@ -488,7 +488,7 @@ class CmdArmPuzzle(MuxCommand): Notes: Create puzzles with `@puzzle`; get list of - defined puzzles using `@lspuzlerecipies`. + defined puzzles using `@lspuzzlerecipes`. """ diff --git a/evennia/objects/manager.py b/evennia/objects/manager.py index 1217d0a91d..3e609991ff 100644 --- a/evennia/objects/manager.py +++ b/evennia/objects/manager.py @@ -159,7 +159,7 @@ class ObjectDBManager(TypedObjectManager): typeclasses (list, optional): Python pats to restrict matches with. Returns: - matches (list): Objects fullfilling both the `attribute_name` and + matches (query): Objects fullfilling both the `attribute_name` and `attribute_value` criterions. Notes: @@ -273,7 +273,7 @@ class ObjectDBManager(TypedObjectManager): to exclude from the match. Returns: - contents (list): Matching contents, without excludeobj, if given. + contents (query): Matching contents, without excludeobj, if given. """ exclude_restriction = ( Q(pk__in=[_GA(obj, "id") for obj in make_iter(excludeobj)]) if excludeobj else Q() @@ -291,7 +291,7 @@ class ObjectDBManager(TypedObjectManager): typeclasses (list): Only match objects with typeclasses having thess path strings. Returns: - matches (list): A list of matches of length 0, 1 or more. + matches (query): A list of matches of length 0, 1 or more. """ if not isinstance(ostring, str): if hasattr(ostring, "key"): diff --git a/evennia/objects/objects.py b/evennia/objects/objects.py index 8ee0d5bfa4..5e56197df9 100644 --- a/evennia/objects/objects.py +++ b/evennia/objects/objects.py @@ -503,7 +503,7 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase): ) if quiet: - return results + return list(results) return _AT_SEARCH_RESULT( results, self, diff --git a/evennia/server/server.py b/evennia/server/server.py index 5e65b7429b..0dc7e1cc57 100644 --- a/evennia/server/server.py +++ b/evennia/server/server.py @@ -105,6 +105,7 @@ _IDMAPPER_CACHE_MAXSIZE = settings.IDMAPPER_CACHE_MAXSIZE _GAMETIME_MODULE = None _IDLE_TIMEOUT = settings.IDLE_TIMEOUT +_LAST_SERVER_TIME_SNAPSHOT = 0 def _server_maintenance(): @@ -113,6 +114,8 @@ def _server_maintenance(): the server needs to do. It is called every minute. """ global EVENNIA, _MAINTENANCE_COUNT, _FLUSH_CACHE, _GAMETIME_MODULE + global _LAST_SERVER_TIME_SNAPSHOT + if not _FLUSH_CACHE: from evennia.utils.idmapper.models import conditional_flush as _FLUSH_CACHE if not _GAMETIME_MODULE: @@ -125,8 +128,13 @@ def _server_maintenance(): # first call after a reload _GAMETIME_MODULE.SERVER_START_TIME = now _GAMETIME_MODULE.SERVER_RUNTIME = ServerConfig.objects.conf("runtime", default=0.0) + _LAST_SERVER_TIME_SNAPSHOT = now else: - _GAMETIME_MODULE.SERVER_RUNTIME += 60.0 + # adjust the runtime not with 60s but with the actual elapsed time + # in case this may varies slightly from 60s. + _GAMETIME_MODULE.SERVER_RUNTIME += (now - _LAST_SERVER_TIME_SNAPSHOT) + _LAST_SERVER_TIME_SNAPSHOT = now + # update game time and save it across reloads _GAMETIME_MODULE.SERVER_RUNTIME_LAST_UPDATED = now ServerConfig.objects.conf("runtime", _GAMETIME_MODULE.SERVER_RUNTIME) diff --git a/evennia/server/tests/test_server.py b/evennia/server/tests/test_server.py index 076a03a879..33a9341cae 100644 --- a/evennia/server/tests/test_server.py +++ b/evennia/server/tests/test_server.py @@ -66,6 +66,7 @@ class TestServer(TestCase): connection=DEFAULT, _IDMAPPER_CACHE_MAXSIZE=1000, _MAINTENANCE_COUNT=3600 - 1, + _LAST_SERVER_TIME_SNAPSHOT=0, ServerConfig=DEFAULT, ) as mocks: mocks["connection"].close = MagicMock() @@ -84,6 +85,7 @@ class TestServer(TestCase): connection=DEFAULT, _IDMAPPER_CACHE_MAXSIZE=1000, _MAINTENANCE_COUNT=3700 - 1, + _LAST_SERVER_TIME_SNAPSHOT=0, ServerConfig=DEFAULT, ) as mocks: mocks["connection"].close = MagicMock() @@ -101,6 +103,7 @@ class TestServer(TestCase): connection=DEFAULT, _IDMAPPER_CACHE_MAXSIZE=1000, _MAINTENANCE_COUNT=(3600 * 7) - 1, + _LAST_SERVER_TIME_SNAPSHOT=0, ServerConfig=DEFAULT, ) as mocks: mocks["connection"].close = MagicMock() @@ -117,6 +120,7 @@ class TestServer(TestCase): connection=DEFAULT, _IDMAPPER_CACHE_MAXSIZE=1000, _MAINTENANCE_COUNT=(3600 * 7) - 1, + _LAST_SERVER_TIME_SNAPSHOT=0, SESSIONS=DEFAULT, _IDLE_TIMEOUT=10, time=DEFAULT, diff --git a/evennia/utils/test_resources.py b/evennia/utils/test_resources.py index d5ca8e1f32..606927e524 100644 --- a/evennia/utils/test_resources.py +++ b/evennia/utils/test_resources.py @@ -157,3 +157,15 @@ class EvenniaTest(TestCase): self.account.delete() self.account2.delete() super().tearDown() + +class LocalEvenniaTest(EvenniaTest): + """ + This test class is intended for inheriting in mygame tests. + It helps ensure your tests are run with your own objects. + """ + account_typeclass = settings.BASE_ACCOUNT_TYPECLASS + object_typeclass = settings.BASE_OBJECT_TYPECLASS + character_typeclass = settings.BASE_CHARACTER_TYPECLASS + exit_typeclass = settings.BASE_EXIT_TYPECLASS + room_typeclass = settings.BASE_ROOM_TYPECLASS + script_typeclass = settings.BASE_SCRIPT_TYPECLASS