update character_creator contrib

This commit is contained in:
Cal 2023-12-22 12:23:06 -07:00
parent 7a7416b084
commit 4628d86056
2 changed files with 111 additions and 111 deletions

View file

@ -23,10 +23,11 @@ from django.conf import settings
from evennia import DefaultAccount
from evennia.commands.default.muxcommand import MuxAccountCommand
from evennia.objects.models import ObjectDB
from evennia.utils import create, search
from evennia.utils.evmenu import EvMenu
from evennia.utils.utils import is_iter
_MAX_NR_CHARACTERS = settings.MAX_NR_CHARACTERS
_CHARACTER_TYPECLASS = settings.BASE_CHARACTER_TYPECLASS
try:
_CHARGEN_MENU = settings.CHARGEN_MENU
except AttributeError:
@ -60,37 +61,20 @@ class ContribCmdCharCreate(MuxAccountCommand):
# we're continuing chargen for a WIP character
new_character = in_progress[0]
else:
# we're making a new character
charmax = settings.MAX_NR_CHARACTERS
if not account.is_superuser and (
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}.")
return
# create the new character object, with default settings
# start_location = ObjectDB.objects.get_id(settings.START_LOCATION)
default_home = ObjectDB.objects.get_id(settings.DEFAULT_HOME)
permissions = settings.PERMISSION_ACCOUNT_DEFAULT
# generate a randomized key so the player can choose a character name later
key = "".join(choices(string.ascii_letters + string.digits, k=10))
new_character = create.create_object(
_CHARACTER_TYPECLASS,
key=key,
location=None,
home=default_home,
permissions=permissions,
)
# only allow creator (and developers) to puppet this char
new_character.locks.add(
f"puppet:pid({account.id}) or perm(Developer) or"
f" pperm(Developer);delete:id({account.id}) or perm(Admin)"
new_character, errors = account.create_character(
key=key, location=None, ip=session.address
)
if errors:
self.msg(errors)
if not new_character:
return
# initalize the new character to the beginning of the chargen menu
new_character.db.chargen_step = "menunode_welcome"
account.characters.add(new_character)
# make sure the character first logs in at the settings-defined start location
new_character.db.prelogout_location = ObjectDB.objects.get_id(settings.START_LOCATION)
# set the menu node to start at to the character's last saved step
startnode = new_character.db.chargen_step
@ -111,17 +95,17 @@ class ContribCmdCharCreate(MuxAccountCommand):
class ContribChargenAccount(DefaultAccount):
"""
A modified Account class that makes minor changes to the OOC look
output, to incorporate in-progress characters.
output to incorporate in-progress characters.
"""
def at_look(self, target=None, session=None, **kwargs):
"""
Called by the OOC look command. It displays a list of playable
characters and should be mostly identical to the core method.
Called when this object executes a look. It allows to customize
just what this means.
Args:
target (Object or list, optional): An object or a list
objects to inspect.
objects to inspect. This is normally a list of characters.
session (Session, optional): The session doing this look.
**kwargs (dict): Arbitrary, optional arguments for users
overriding the call (unused by default).
@ -129,73 +113,85 @@ class ContribChargenAccount(DefaultAccount):
Returns:
look_string (str): A prepared look string, ready to send
off to any recipient (usually to ourselves)
"""
# list of targets - make list to disconnect from db
if target and not is_iter(target):
# single target - just show it
if hasattr(target, "return_appearance"):
return target.return_appearance(self)
else:
return f"{target} has no in-game appearance."
# multiple targets - this is a list of characters
characters = list(tar for tar in target if tar) if target else []
ncars = len(characters)
sessions = self.sessions.all()
is_su = self.is_superuser
# text shown when looking in the ooc area
result = [f"Account |g{self.key}|n (you are Out-of-Character)"]
nsess = len(sessions)
if nsess == 1:
result.append("\n\n|wConnected session:|n")
elif nsess > 1:
result.append(f"\n\n|wConnected sessions ({nsess}):|n")
if not nsess:
# no sessions, nothing to report
return ""
# header text
txt_header = f"Account |g{self.name}|n (you are Out-of-Character)"
# sessions
sess_strings = []
for isess, sess in enumerate(sessions):
csessid = sess.sessid
addr = "{protocol} ({address})".format(
protocol=sess.protocol_key,
address=isinstance(sess.address, tuple)
and str(sess.address[0])
or str(sess.address),
ip_addr = sess.address[0] if isinstance(sess.address, tuple) else sess.address
addr = f"{sess.protocol_key} ({ip_addr})"
sess_str = (
f"|w* {isess + 1}|n"
if session and session.sessid == sess.sessid
else f" {isess + 1}"
)
if session.sessid == csessid:
result.append(f"\n |w* {isess+1}|n {addr}")
else:
result.append(f"\n {isess+1} {addr}")
result.append("\n\n |whelp|n - more commands")
result.append("\n |wpublic <Text>|n - talk on public channel")
sess_strings.append(f"{sess_str} {addr}")
charmax = settings.MAX_NR_CHARACTERS
txt_sessions = "|wConnected session(s):|n\n" + "\n".join(sess_strings)
if is_su or len(characters) < charmax:
result.append("\n |wcharcreate|n - create a new character")
if characters:
result.append("\n |wchardelete <name>|n - delete a character (cannot be undone!)")
plural = "" if len(characters) == 1 else "s"
result.append("\n |wic <character>|n - enter the game (|wooc|n to return here)")
if is_su:
result.append(f"\n\nAvailable character{plural} ({len(characters)}/unlimited):")
if not characters:
txt_characters = "You don't have a character yet. Use |wcharcreate|n."
else:
result.append(f"\n\nAvailable character{plural} ({len(characters)}/{charmax}):")
max_chars = (
"unlimited"
if self.is_superuser or _MAX_NR_CHARACTERS is None
else _MAX_NR_CHARACTERS
)
for char in characters:
if char.db.chargen_step:
# currently in-progress character; don't display placeholder names
result.append("\n - |Yin progress|n (|wcharcreate|n to continue)")
continue
csessions = char.sessions.all()
if csessions:
for sess in csessions:
# character is already puppeted
sid = sess in sessions and sessions.index(sess) + 1
if sess and sid:
result.append(
f"\n - |G{char.key}|n [{', '.join(char.permissions.all())}] (played by"
f" you in session {sid})"
)
else:
result.append(
f"\n - |R{char.key}|n [{', '.join(char.permissions.all())}] (played by"
" someone else)"
)
else:
# character is available
result.append(f"\n - {char.key} [{', '.join(char.permissions.all())}]")
look_string = ("-" * 68) + "\n" + "".join(result) + "\n" + ("-" * 68)
return look_string
char_strings = []
for char in characters:
csessions = char.sessions.all()
if csessions:
for sess in csessions:
# character is already puppeted
sid = sess in sessions and sessions.index(sess) + 1
if sess and sid:
char_strings.append(
f" - |G{char.name}|n [{', '.join(char.permissions.all())}] "
f"(played by you in session {sid})"
)
else:
char_strings.append(
f" - |R{char.name}|n [{', '.join(char.permissions.all())}] "
"(played by someone else)"
)
elif char.db.chargen_step:
# currently in-progress character; don't display placeholder names
char_strings.append("\n - |Yin progress|n (|wcharcreate|n to continue)")
continue
else:
# character is "free to puppet"
char_strings.append(f" - {char.name} [{', '.join(char.permissions.all())}]")
txt_characters = (
f"Available character(s) ({ncars}/{max_chars}, |wic <name>|n to play):|n\n"
+ "\n".join(char_strings)
)
return self.ooc_appearance_template.format(
header=txt_header,
sessions=txt_sessions,
characters=txt_characters,
footer="",
)

View file

@ -1,10 +1,4 @@
from unittest.mock import patch
from django.conf import settings
from django.test import override_settings
from evennia import DefaultCharacter
from evennia.commands.default import account
from evennia.utils import inherits_from
from evennia.utils.test_resources import BaseEvenniaCommandTest
@ -15,31 +9,41 @@ class TestCharacterCreator(BaseEvenniaCommandTest):
def setUp(self):
super().setUp()
self.account.swap_typeclass(character_creator.ContribChargenAccount)
def test_ooc_look(self):
self.account.characters.add(self.char1)
self.account.unpuppet_all()
def test_account_look(self):
self.account.characters.add(self.char1)
self.char1.db.chargen_step = "start"
with patch("evennia.commands.default.account._AUTO_PUPPET_ON_LOGIN", new=False):
# check that correct output is returning
output = self.call(
account.CmdOOCLook(),
# check that correct output is returning
output = self.account.at_look(target=self.account.characters.all(), session=self.session)
# check that char1 is recognized as in progress
self.assertIn("in progress", output)
def test_char_create(self):
with self.settings(START_LOCATION=f"#{self.room1.id}"):
self.call(
character_creator.ContribCmdCharCreate(),
"",
"Account TestAccount (you are Out-of-Character)",
caller=self.account,
)
# check that char1 is recognized as in progress
self.assertIn("in progress", output)
# verify menu was initialized
menu = self.session.ndb._menutree
self.assertNotEqual(menu, None)
# verify character was created
new_char = self.session.new_char
self.assertTrue(inherits_from(new_char, DefaultCharacter))
# verify character's "start location" was set
self.assertEqual(self.session.new_char.db.prelogout_location, self.room1)
@override_settings(CHARGEN_MENU="evennia.contrib.rpg.character_creator.example_menu")
def test_char_create(self):
# exit the menu, verify it resumes
menu.parse_input("q")
del self.session.new_char
self.assertEqual(self.session.ndb._menutree, None)
self.call(
character_creator.ContribCmdCharCreate(),
"",
caller=self.account,
)
menu = self.session.ndb._menutree
self.assertNotEqual(menu, None)
self.assertTrue(inherits_from(self.session.new_char, DefaultCharacter))
# should be the same new char
self.assertEqual(new_char, self.session.new_char)