diff --git a/docs/source/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Chargen.md b/docs/source/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Chargen.md index 98ff3d0e8..a7fc661e3 100644 --- a/docs/source/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Chargen.md +++ b/docs/source/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Chargen.md @@ -622,7 +622,7 @@ node_apply_character(caller, raw_string, **kwargs): tmp_character = kwargs["tmp_character"] new_character = tmp_character.apply(caller) - caller.account.db._playable_characters = [new_character] + caller.account.add_character(new_character) text = "Character created!" diff --git a/docs/source/Howtos/Turn-based-Combat-System.md b/docs/source/Howtos/Turn-based-Combat-System.md index 3c90489fc..b9168a8e9 100644 --- a/docs/source/Howtos/Turn-based-Combat-System.md +++ b/docs/source/Howtos/Turn-based-Combat-System.md @@ -311,12 +311,12 @@ Our rock-paper-scissor setup works like this: - `defend` does nothing but has a chance to beat `hit`. - `flee/disengage` must succeed two times in a row (i.e. not beaten by a `hit` once during the turn). If so the character leaves combat. - ```python # mygame/world/rules.py import random + # messages def resolve_combat(combat_handler, actiondict): @@ -326,7 +326,7 @@ def resolve_combat(combat_handler, actiondict): for each character: {char.id:[(action1, char, target), (action2, char, target)], ...} """ - flee = {} # track number of flee commands per character + flee = {} # track number of flee commands per character for isub in range(2): # loop over sub-turns messages = [] @@ -403,6 +403,7 @@ This is the last component we need, a command to initiate combat. This will tie from evennia import create_script + class CmdAttack(Command): """ initiates combat @@ -419,7 +420,7 @@ class CmdAttack(Command): def func(self): "Handle command" if not self.args: - self.caller.msg("Usage: attack ") + self.caller.msg("Usage: attack ") return target = self.caller.search(self.args) if not target: diff --git a/docs/source/Howtos/Web-Character-Generation.md b/docs/source/Howtos/Web-Character-Generation.md index caf30443d..e7ef7c823 100644 --- a/docs/source/Howtos/Web-Character-Generation.md +++ b/docs/source/Howtos/Web-Character-Generation.md @@ -206,7 +206,7 @@ def creating(request): # create the character char = create.create_object(typeclass=typeclass, key=name, home=home, permissions=perms) - user.db._playable_characters.append(char) + user.add_character(char) # add the right locks for the character so the account can # puppet it char.locks.add(" or ".join([ @@ -290,7 +290,7 @@ def creating(request): # create the character char = create.create_object(typeclass=typeclass, key=name, home=home, permissions=perms) - user.db._playable_characters.append(char) + user.add_character(char) # add the right locks for the character so the account can # puppet it char.locks.add(" or ".join([ diff --git a/docs/source/Howtos/Web-Help-System-Tutorial.md b/docs/source/Howtos/Web-Help-System-Tutorial.md index 1864dc22b..6afbede9c 100644 --- a/docs/source/Howtos/Web-Help-System-Tutorial.md +++ b/docs/source/Howtos/Web-Help-System-Tutorial.md @@ -198,8 +198,8 @@ def index(request): def index(request): """The 'index' view.""" user = request.user - if not user.is_anonymous() and user.db._playable_characters: - character = user.db._playable_characters[0] + if not user.is_anonymous() and user.characters: + character = user.characters[0] ``` In this second case, it will select the first character of the account. diff --git a/evennia/accounts/accounts.py b/evennia/accounts/accounts.py index eb7e8b5d7..3f11882b0 100644 --- a/evennia/accounts/accounts.py +++ b/evennia/accounts/accounts.py @@ -120,6 +120,80 @@ class AccountSessionHandler(object): return len(self.get()) +class CharactersHandler: + """ + A simple Handler that lives on DefaultAccount as .characters via @lazy_property used to + wrap access to .db._playable_characters. + """ + + def __init__(self, owner: "DefaultAccount"): + """ + Create the CharactersHandler. + + Args: + owner: The Account that owns this handler. + """ + self.owner = owner + self._ensure_playable_characters() + self._clean() + + def _ensure_playable_characters(self): + if self.owner.db._playable_characters is None: + self.owner.db._playable_characters = [] + + def _clean(self): + # Remove all instances of None from the list. + self.owner.db._playable_characters = [x for x in self.owner.db._playable_characters if x] + + def add(self, character: "DefaultCharacter"): + """ + Add a character to this account's list of playable characters. + + Args: + character (DefaultCharacter): The character to add. + """ + self._clean() + if character not in self.owner.db._playable_characters: + self.owner.db._playable_characters.append(character) + self.owner.at_post_add_character(character) + + def remove(self, character: "DefaultCharacter"): + """ + Remove a character from this account's list of playable characters. + + Args: + character (DefaultCharacter): The character to remove. + """ + self._clean() + if character in self.owner.db._playable_characters: + self.owner.db._playable_characters.remove(character) + self.owner.at_post_remove_character(character) + + def all(self) -> list["DefaultCharacter"]: + """ + Get all playable characters. + + Returns: + list[DefaultCharacter]: All playable characters. + """ + self._clean() + return list(self.owner.db._playable_characters) + + def count(self) -> int: + """ + Get the number of playable characters. + + Returns: + int: The number of playable characters. + """ + return len(self.all()) + + __len__ = count + + def __iter__(self): + return iter(self.all()) + + class DefaultAccount(AccountDB, metaclass=TypeclassBase): """ This is the base Typeclass for all Accounts. Accounts represent @@ -219,22 +293,31 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase): load_kwargs={"category": "option"}, ) - # Do not make this a lazy property; the web UI will not refresh it! - @property + @lazy_property def characters(self): - # Get playable characters list - objs = self.db._playable_characters or [] + return CharactersHandler(self) - # Rebuild the list if legacy code left null values after deletion - try: - if None in objs: - objs = [x for x in self.db._playable_characters if x] - self.db._playable_characters = objs - except Exception as e: - logger.log_trace(e) - logger.log_err(e) + def at_post_add_character(self, character: "DefaultCharacter"): + """ + Called after a character is added to this account's list of playable characters. - return objs + Use it to easily implement custom logic when a character is added to an account. + + Args: + character (DefaultCharacter): The character that was added. + """ + pass + + def at_post_remove_character(self, character: "DefaultAccount"): + """ + Called after a character is removed from this account's list of playable characters. + + Use it to easily implement custom logic when a character is removed from an account. + + Args: + character (DefaultCharacter): The character that was removed. + """ + pass def uses_screenreader(self, session=None): """ @@ -743,8 +826,7 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase): ) if character: # Update playable character list - if character not in self.characters: - self.db._playable_characters.append(character) + self.characters.add(character) # We need to set this to have @ic auto-connect to this character self.db._last_puppet = character @@ -1483,11 +1565,8 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase): else: # In this mode we don't auto-connect but by default end up at a character selection # screen. We execute look on the account. - # we make sure to clean up the _playable_characters list in case - # any was deleted in the interim. - self.db._playable_characters = [char for char in self.db._playable_characters if char] self.msg( - self.at_look(target=self.db._playable_characters, session=session), session=session + self.at_look(target=self.characters, session=session), session=session ) def at_failed_login(self, session, **kwargs): @@ -1825,11 +1904,8 @@ class DefaultGuest(DefaultAccount): be on the safe side. """ super().at_server_shutdown() - characters = self.db._playable_characters - if characters: - for character in characters: - if character: - character.delete() + for character in self.characters: + character.delete() def at_post_disconnect(self, **kwargs): """ @@ -1841,8 +1917,6 @@ class DefaultGuest(DefaultAccount): """ super().at_post_disconnect() - characters = self.db._playable_characters - for character in characters: - if character: - character.delete() + for character in self.characters: + character.delete() self.delete() diff --git a/evennia/accounts/tests.py b/evennia/accounts/tests.py index 384f9f882..18b4025d9 100644 --- a/evennia/accounts/tests.py +++ b/evennia/accounts/tests.py @@ -105,14 +105,14 @@ class TestDefaultGuest(BaseEvenniaTest): def test_at_server_shutdown(self): account, errors = DefaultGuest.create(ip=self.ip) self.char1.delete = MagicMock() - account.db._playable_characters = [self.char1] + account.characters.add(self.char1) account.at_server_shutdown() self.char1.delete.assert_called() def test_at_post_disconnect(self): account, errors = DefaultGuest.create(ip=self.ip) self.char1.delete = MagicMock() - account.db._playable_characters = [self.char1] + account.characters.add(self.char1) account.at_post_disconnect() self.char1.delete.assert_called() @@ -358,19 +358,19 @@ class TestAccountPuppetDeletion(BaseEvenniaTest): def test_puppet_deletion(self): # Check for existing chars self.assertFalse( - self.account.db._playable_characters, "Account should not have any chars by default." + self.account.characters, "Account should not have any chars by default." ) # Add char1 to account's playable characters - self.account.db._playable_characters.append(self.char1) - self.assertTrue(self.account.db._playable_characters, "Char was not added to account.") + self.account.characters.add(self.char1) + self.assertTrue(self.account.characters, "Char was not added to account.") # See what happens when we delete char1. self.char1.delete() # Playable char list should be empty. self.assertFalse( - self.account.db._playable_characters, - f"Playable character list is not empty! {self.account.db._playable_characters}", + self.account.characters, + f"Playable character list is not empty! {self.account.characters}", ) @@ -383,10 +383,20 @@ class TestDefaultAccountEv(BaseEvenniaTest): def test_characters_property(self): "test existence of None in _playable_characters Attr" self.account.db._playable_characters = [self.char1, None] - chars = self.account.characters - self.assertEqual(chars, [self.char1]) + self.assertEqual(self.account.characters.all(), [self.char1]) self.assertEqual(self.account.db._playable_characters, [self.char1]) + def test_add_character_to_playable_list(self): + self.assertEqual(self.account.characters.all(), []) + self.account.characters.add(self.char1) + self.assertEqual(self.account.characters.all(), [self.char1]) + + def test_remove_character_from_playable_list(self): + self.account.characters.add(self.char1) + self.assertEqual(self.account.characters.all(), [self.char1]) + self.account.characters.remove(self.char1) + self.assertEqual(self.account.characters.all(), []) + def test_puppet_success(self): self.account.msg = MagicMock() with patch("evennia.accounts.accounts._MULTISESSION_MODE", 2): diff --git a/evennia/commands/default/account.py b/evennia/commands/default/account.py index eb0b07495..5e38dea46 100644 --- a/evennia/commands/default/account.py +++ b/evennia/commands/default/account.py @@ -60,12 +60,7 @@ class MuxAccountLookCommand(COMMAND_DEFAULT_CLASS): super().parse() - playable = self.account.db._playable_characters - if playable is not None: - # clean up list if character object was deleted in between - if None in playable: - playable = [character for character in playable if character] - self.account.db._playable_characters = playable + playable = self.account.characters # store playable property if self.args: self.playable = dict((utils.to_str(char.key.lower()), char) for char in playable).get( @@ -155,8 +150,8 @@ class CmdCharCreate(COMMAND_DEFAULT_CLASS): if ( not account.is_superuser and not account.check_permstring("Developer") - and account.db._playable_characters - and len(account.db._playable_characters) >= _MAX_NR_CHARACTERS + and account.characters + and len(account.characters) >= _MAX_NR_CHARACTERS ): plural = "" if _MAX_NR_CHARACTERS == 1 else "s" self.msg(f"You may only have a maximum of {_MAX_NR_CHARACTERS} character{plural}.") @@ -184,7 +179,7 @@ class CmdCharCreate(COMMAND_DEFAULT_CLASS): "puppet:id(%i) or pid(%i) or perm(Developer) or pperm(Developer);delete:id(%i) or" " perm(Admin)" % (new_character.id, account.id, account.id) ) - account.db._playable_characters.append(new_character) + account.characters.add(new_character) if desc: new_character.db.desc = desc elif not new_character.db.desc: @@ -223,7 +218,7 @@ class CmdCharDelete(COMMAND_DEFAULT_CLASS): # use the playable_characters list to search match = [ char - for char in utils.make_iter(account.db._playable_characters) + for char in utils.make_iter(account.characters) if char.key.lower() == self.args.lower() ] if not match: @@ -243,9 +238,7 @@ class CmdCharDelete(COMMAND_DEFAULT_CLASS): # only take action delobj = caller.ndb._char_to_delete key = delobj.key - caller.db._playable_characters = [ - pc for pc in caller.db._playable_characters if pc != delobj - ] + caller.characters.remove(delobj) delobj.delete() self.msg(f"Character '{key}' was permanently deleted.") logger.log_sec( @@ -314,13 +307,13 @@ class CmdIC(COMMAND_DEFAULT_CLASS): else: # argument given - if account.db._playable_characters: + if (playables := account.characters): # look at the playable_characters list first character_candidates.extend( utils.make_iter( account.search( self.args, - candidates=account.db._playable_characters, + candidates=playables, search_object=True, quiet=True, ) diff --git a/evennia/commands/default/tests.py b/evennia/commands/default/tests.py index c499e6ada..774bd8333 100644 --- a/evennia/commands/default/tests.py +++ b/evennia/commands/default/tests.py @@ -589,7 +589,7 @@ class TestAccount(BaseEvenniaCommandTest): ] ) def test_ooc_look(self, multisession_mode, auto_puppet, max_nr_chars, expected_result): - self.account.db._playable_characters = [self.char1] + self.account.characters.add(self.char1) self.account.unpuppet_all() with self.settings(MULTISESSION=multisession_mode): @@ -609,14 +609,14 @@ class TestAccount(BaseEvenniaCommandTest): self.call(account.CmdOOC(), "", "You go OOC.", caller=self.account) def test_ic(self): - self.account.db._playable_characters = [self.char1] + self.account.characters.add(self.char1) self.account.unpuppet_object(self.session) self.call( account.CmdIC(), "Char", "You become Char.", caller=self.account, receiver=self.char1 ) def test_ic__other_object(self): - self.account.db._playable_characters = [self.obj1] + self.account.characters.add(self.obj1) self.account.unpuppet_object(self.session) self.call( account.CmdIC(), "Obj", "You become Obj.", caller=self.account, receiver=self.obj1 @@ -670,7 +670,7 @@ class TestAccount(BaseEvenniaCommandTest): # whether permissions are being checked # Add char to account playable characters - self.account.db._playable_characters.append(self.char1) + self.account.characters.add(self.char1) # Try deleting as Developer self.call( diff --git a/evennia/contrib/rpg/character_creator/character_creator.py b/evennia/contrib/rpg/character_creator/character_creator.py index 354769823..8ebc49435 100644 --- a/evennia/contrib/rpg/character_creator/character_creator.py +++ b/evennia/contrib/rpg/character_creator/character_creator.py @@ -54,7 +54,7 @@ class ContribCmdCharCreate(MuxAccountCommand): session = self.session # only one character should be in progress at a time, so we check for WIPs first - in_progress = [chara for chara in account.db._playable_characters if chara.db.chargen_step] + in_progress = [chara for chara in account.characters if chara.db.chargen_step] if len(in_progress): # we're continuing chargen for a WIP character @@ -64,7 +64,7 @@ class ContribCmdCharCreate(MuxAccountCommand): charmax = settings.MAX_NR_CHARACTERS if not account.is_superuser and ( - account.db._playable_characters and len(account.db._playable_characters) >= charmax + account.characters and len(account.characters) >= charmax ): plural = "" if charmax == 1 else "s" self.msg(f"You may only create a maximum of {charmax} character{plural}.") @@ -90,7 +90,7 @@ class ContribCmdCharCreate(MuxAccountCommand): ) # initalize the new character to the beginning of the chargen menu new_character.db.chargen_step = "menunode_welcome" - account.db._playable_characters.append(new_character) + account.characters.add(new_character) # set the menu node to start at to the character's last saved step startnode = new_character.db.chargen_step diff --git a/evennia/contrib/rpg/character_creator/tests.py b/evennia/contrib/rpg/character_creator/tests.py index 4ff180a3d..5cdaaa0ec 100644 --- a/evennia/contrib/rpg/character_creator/tests.py +++ b/evennia/contrib/rpg/character_creator/tests.py @@ -17,7 +17,7 @@ class TestCharacterCreator(BaseEvenniaCommandTest): self.account.swap_typeclass(character_creator.ContribChargenAccount) def test_ooc_look(self): - self.account.db._playable_characters = [self.char1] + self.account.characters.add(self.char1) self.account.unpuppet_all() self.char1.db.chargen_step = "start" diff --git a/evennia/contrib/tutorials/evadventure/chargen.py b/evennia/contrib/tutorials/evadventure/chargen.py index 26f3df646..ab440d2f4 100644 --- a/evennia/contrib/tutorials/evadventure/chargen.py +++ b/evennia/contrib/tutorials/evadventure/chargen.py @@ -316,7 +316,7 @@ def node_apply_character(caller, raw_string, **kwargs): """ tmp_character = kwargs["tmp_character"] new_character = tmp_character.apply(caller) - caller.db._playable_characters.append(new_character) + caller.characters.add(new_character) text = "Character created!" diff --git a/evennia/objects/objects.py b/evennia/objects/objects.py index ffd9e2165..f8f98b552 100644 --- a/evennia/objects/objects.py +++ b/evennia/objects/objects.py @@ -1149,10 +1149,7 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase): # sever the connection (important!) if self.account: # Remove the object from playable characters list - if self in self.account.db._playable_characters: - self.account.db._playable_characters = [ - x for x in self.account.db._playable_characters if x != self - ] + self.account.characters.remove(self) for session in self.sessions.all(): self.account.unpuppet_object(session) @@ -2562,8 +2559,7 @@ class DefaultCharacter(DefaultObject): obj.db.creator_ip = ip if account: obj.db.creator_id = account.id - if obj not in account.characters: - account.db._playable_characters.append(obj) + account.characters.add(obj) # Add locks if not locks and account: diff --git a/evennia/server/initial_setup.py b/evennia/server/initial_setup.py index ffec79ab1..cfd79fea0 100644 --- a/evennia/server/initial_setup.py +++ b/evennia/server/initial_setup.py @@ -98,16 +98,15 @@ def create_objects(): # Create the in-game god-character for account #1 and set # it to exist in Limbo. - character_typeclass = settings.BASE_CHARACTER_TYPECLASS try: superuser_character = ObjectDB.objects.get(id=1) except ObjectDB.DoesNotExist: - superuser_character = create.create_object( - character_typeclass, key=superuser.username, nohome=True + superuser_character, errors = superuser.create_character( + key=superuser.username, nohome=True, description=_("This is User #1.") ) + if errors: + raise Exception(str(errors)) - superuser_character.db_typeclass_path = character_typeclass - superuser_character.db.desc = _("This is User #1.") superuser_character.locks.add( "examine:perm(Developer);edit:false();delete:false();boot:false();msg:all();puppet:false()" ) @@ -118,11 +117,6 @@ def create_objects(): superuser.attributes.add("_first_login", True) superuser.attributes.add("_last_puppet", superuser_character) - try: - superuser.db._playable_characters.append(superuser_character) - except AttributeError: - superuser.db_playable_characters = [superuser_character] - room_typeclass = settings.BASE_ROOM_TYPECLASS try: limbo_obj = ObjectDB.objects.get(id=2) diff --git a/evennia/server/server.py b/evennia/server/server.py index 8407ff118..c5bd6da95 100644 --- a/evennia/server/server.py +++ b/evennia/server/server.py @@ -647,9 +647,8 @@ class Evennia: for guest in AccountDB.objects.all().filter( db_typeclass_path=settings.BASE_GUEST_TYPECLASS ): - for character in guest.db._playable_characters: - if character: - character.delete() + for character in guest.characters: + character.delete() guest.delete() for mod in SERVER_STARTSTOP_MODULES: if hasattr(mod, "at_server_cold_start"): diff --git a/evennia/server/serversession.py b/evennia/server/serversession.py index 9eeb186a2..1ea0778f9 100644 --- a/evennia/server/serversession.py +++ b/evennia/server/serversession.py @@ -444,3 +444,4 @@ class ServerSession(_BASE_SESSION_CLASS): return self.account.get_display_name(*args, **kwargs) else: return f"{self.protocol_key}({self.address})" + diff --git a/evennia/utils/ansi.py b/evennia/utils/ansi.py index cfa719247..c68dc1846 100644 --- a/evennia/utils/ansi.py +++ b/evennia/utils/ansi.py @@ -72,7 +72,6 @@ from evennia.utils.utils import to_str MXP_ENABLED = settings.MXP_ENABLED - # ANSI definitions ANSI_BEEP = "\07" diff --git a/evennia/utils/utils.py b/evennia/utils/utils.py index 4a2d6ead4..f5338ba24 100644 --- a/evennia/utils/utils.py +++ b/evennia/utils/utils.py @@ -2941,3 +2941,4 @@ def str2int(number): # invalid number-word, raise ValueError raise ValueError(f"String {original_input} cannot be converted to int.") return sum(sums) + diff --git a/evennia/web/admin/objects.py b/evennia/web/admin/objects.py index 1545add8e..48e5fe99e 100644 --- a/evennia/web/admin/objects.py +++ b/evennia/web/admin/objects.py @@ -310,7 +310,7 @@ class ObjectAdmin(admin.ModelAdmin): This will: - Set account.db._last_puppet to this object - - Add object to account.db._playable_characters + - Add object to account.characters - Change object locks to allow puppeting by account """ @@ -319,10 +319,7 @@ class ObjectAdmin(admin.ModelAdmin): if account: account.db._last_puppet = obj - if not account.db._playable_characters: - account.db._playable_characters = [] - if obj not in account.db._playable_characters: - account.db._playable_characters.append(obj) + account.characters.add(obj) if not obj.access(account, "puppet"): lock = obj.locks.get("puppet") lock += f" or pid({account.id})" @@ -331,7 +328,7 @@ class ObjectAdmin(admin.ModelAdmin): request, "Did the following (where possible): " f"Set Account.db._last_puppet = {obj}, " - f"Added {obj} to Account.db._playable_characters list, " + f"Added {obj} to Account.characters list, " f"Added 'puppet:pid({account.id})' lock to {obj}.", ) else: diff --git a/evennia/web/website/tests.py b/evennia/web/website/tests.py index fc1073a58..230d4442f 100644 --- a/evennia/web/website/tests.py +++ b/evennia/web/website/tests.py @@ -35,8 +35,8 @@ class EvenniaWebTest(BaseEvenniaTest): super().setUp() # Add chars to account rosters - self.account.db._playable_characters = [self.char1] - self.account2.db._playable_characters = [self.char2] + self.account.characters.add(self.char1) + self.account2.characters.add(self.char2) for account in (self.account, self.account2): # Demote accounts to Player permissions @@ -44,15 +44,15 @@ class EvenniaWebTest(BaseEvenniaTest): account.permissions.remove("Developer") # Grant permissions to chars - for char in account.db._playable_characters: + for char in account.characters: char.locks.add("edit:id(%s) or perm(Admin)" % account.pk) char.locks.add("delete:id(%s) or perm(Admin)" % account.pk) char.locks.add("view:all()") def test_valid_chars(self): "Make sure account has playable characters" - self.assertTrue(self.char1 in self.account.db._playable_characters) - self.assertTrue(self.char2 in self.account2.db._playable_characters) + self.assertTrue(self.char1 in self.account.characters) + self.assertTrue(self.char2 in self.account2.characters) def get_kwargs(self): return {} @@ -220,7 +220,7 @@ class CharacterCreateView(EvenniaWebTest): @override_settings(MAX_NR_CHARACTERS=1) def test_valid_access_multisession_0(self): "Account1 with no characters should be able to create a new one" - self.account.db._playable_characters = [] + self.account.characters.remove(self.char1) # Login account self.login() @@ -233,9 +233,9 @@ class CharacterCreateView(EvenniaWebTest): # Make sure the character was actually created self.assertTrue( - len(self.account.db._playable_characters) == 1, + len(self.account.characters) == 1, "Account only has the following characters attributed to it: %s" - % self.account.db._playable_characters, + % self.account.characters, ) @override_settings(MAX_NR_CHARACTERS=5) @@ -252,9 +252,9 @@ class CharacterCreateView(EvenniaWebTest): # Make sure the character was actually created self.assertTrue( - len(self.account.db._playable_characters) > 1, + len(self.account.characters) > 1, "Account only has the following characters attributed to it: %s" - % self.account.db._playable_characters, + % self.account.characters, ) @@ -352,7 +352,7 @@ class CharacterDeleteView(EvenniaWebTest): # Make sure it deleted self.assertFalse( - self.char1 in self.account.db._playable_characters, + self.char1 in self.account.characters, "Char1 is still in Account playable characters list.", ) diff --git a/evennia/web/website/views/help.py b/evennia/web/website/views/help.py index 677328d57..98ef5cbcb 100644 --- a/evennia/web/website/views/help.py +++ b/evennia/web/website/views/help.py @@ -102,7 +102,7 @@ def collect_topics(account): cmd_help_topics = [] if not str(account) == "AnonymousUser": # create list of account and account's puppets - puppets = account.db._playable_characters + [account] + puppets = account.characters.all() + [account] # add the account's and puppets' commands to cmd_help_topics list for puppet in puppets: for cmdset in puppet.cmdset.get(): diff --git a/pyproject.toml b/pyproject.toml index 9c74ce2cf..2120d3ced 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,7 +83,7 @@ dependencies = [ "anything ==0.2.1", "black >= 22.6", "isort >= 5.10", - "parameterized ==0.8.1", + "parameterized ==0.8.1" ] [project.optional-dependencies]