update character_creator contrib
This commit is contained in:
parent
7a7416b084
commit
4628d86056
2 changed files with 111 additions and 111 deletions
|
|
@ -23,10 +23,11 @@ from django.conf import settings
|
||||||
from evennia import DefaultAccount
|
from evennia import DefaultAccount
|
||||||
from evennia.commands.default.muxcommand import MuxAccountCommand
|
from evennia.commands.default.muxcommand import MuxAccountCommand
|
||||||
from evennia.objects.models import ObjectDB
|
from evennia.objects.models import ObjectDB
|
||||||
from evennia.utils import create, search
|
|
||||||
from evennia.utils.evmenu import EvMenu
|
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:
|
try:
|
||||||
_CHARGEN_MENU = settings.CHARGEN_MENU
|
_CHARGEN_MENU = settings.CHARGEN_MENU
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
|
|
@ -60,37 +61,20 @@ class ContribCmdCharCreate(MuxAccountCommand):
|
||||||
# we're continuing chargen for a WIP character
|
# we're continuing chargen for a WIP character
|
||||||
new_character = in_progress[0]
|
new_character = in_progress[0]
|
||||||
else:
|
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
|
# generate a randomized key so the player can choose a character name later
|
||||||
key = "".join(choices(string.ascii_letters + string.digits, k=10))
|
key = "".join(choices(string.ascii_letters + string.digits, k=10))
|
||||||
new_character = create.create_object(
|
new_character, errors = account.create_character(
|
||||||
_CHARACTER_TYPECLASS,
|
key=key, location=None, ip=session.address
|
||||||
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)"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if errors:
|
||||||
|
self.msg(errors)
|
||||||
|
if not new_character:
|
||||||
|
return
|
||||||
# initalize the new character to the beginning of the chargen menu
|
# initalize the new character to the beginning of the chargen menu
|
||||||
new_character.db.chargen_step = "menunode_welcome"
|
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
|
# set the menu node to start at to the character's last saved step
|
||||||
startnode = new_character.db.chargen_step
|
startnode = new_character.db.chargen_step
|
||||||
|
|
@ -111,17 +95,17 @@ class ContribCmdCharCreate(MuxAccountCommand):
|
||||||
class ContribChargenAccount(DefaultAccount):
|
class ContribChargenAccount(DefaultAccount):
|
||||||
"""
|
"""
|
||||||
A modified Account class that makes minor changes to the OOC look
|
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):
|
def at_look(self, target=None, session=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
Called by the OOC look command. It displays a list of playable
|
Called when this object executes a look. It allows to customize
|
||||||
characters and should be mostly identical to the core method.
|
just what this means.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
target (Object or list, optional): An object or a list
|
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.
|
session (Session, optional): The session doing this look.
|
||||||
**kwargs (dict): Arbitrary, optional arguments for users
|
**kwargs (dict): Arbitrary, optional arguments for users
|
||||||
overriding the call (unused by default).
|
overriding the call (unused by default).
|
||||||
|
|
@ -129,73 +113,85 @@ class ContribChargenAccount(DefaultAccount):
|
||||||
Returns:
|
Returns:
|
||||||
look_string (str): A prepared look string, ready to send
|
look_string (str): A prepared look string, ready to send
|
||||||
off to any recipient (usually to ourselves)
|
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 []
|
characters = list(tar for tar in target if tar) if target else []
|
||||||
|
ncars = len(characters)
|
||||||
sessions = self.sessions.all()
|
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)
|
nsess = len(sessions)
|
||||||
if nsess == 1:
|
|
||||||
result.append("\n\n|wConnected session:|n")
|
if not nsess:
|
||||||
elif nsess > 1:
|
# no sessions, nothing to report
|
||||||
result.append(f"\n\n|wConnected sessions ({nsess}):|n")
|
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):
|
for isess, sess in enumerate(sessions):
|
||||||
csessid = sess.sessid
|
ip_addr = sess.address[0] if isinstance(sess.address, tuple) else sess.address
|
||||||
addr = "{protocol} ({address})".format(
|
addr = f"{sess.protocol_key} ({ip_addr})"
|
||||||
protocol=sess.protocol_key,
|
sess_str = (
|
||||||
address=isinstance(sess.address, tuple)
|
f"|w* {isess + 1}|n"
|
||||||
and str(sess.address[0])
|
if session and session.sessid == sess.sessid
|
||||||
or str(sess.address),
|
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")
|
sess_strings.append(f"{sess_str} {addr}")
|
||||||
result.append("\n |wpublic <Text>|n - talk on public channel")
|
|
||||||
|
|
||||||
charmax = settings.MAX_NR_CHARACTERS
|
txt_sessions = "|wConnected session(s):|n\n" + "\n".join(sess_strings)
|
||||||
|
|
||||||
if is_su or len(characters) < charmax:
|
if not characters:
|
||||||
result.append("\n |wcharcreate|n - create a new character")
|
txt_characters = "You don't have a character yet. Use |wcharcreate|n."
|
||||||
|
|
||||||
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):")
|
|
||||||
else:
|
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:
|
char_strings = []
|
||||||
if char.db.chargen_step:
|
for char in characters:
|
||||||
# currently in-progress character; don't display placeholder names
|
csessions = char.sessions.all()
|
||||||
result.append("\n - |Yin progress|n (|wcharcreate|n to continue)")
|
if csessions:
|
||||||
continue
|
for sess in csessions:
|
||||||
csessions = char.sessions.all()
|
# character is already puppeted
|
||||||
if csessions:
|
sid = sess in sessions and sessions.index(sess) + 1
|
||||||
for sess in csessions:
|
if sess and sid:
|
||||||
# character is already puppeted
|
char_strings.append(
|
||||||
sid = sess in sessions and sessions.index(sess) + 1
|
f" - |G{char.name}|n [{', '.join(char.permissions.all())}] "
|
||||||
if sess and sid:
|
f"(played by you in session {sid})"
|
||||||
result.append(
|
)
|
||||||
f"\n - |G{char.key}|n [{', '.join(char.permissions.all())}] (played by"
|
else:
|
||||||
f" you in session {sid})"
|
char_strings.append(
|
||||||
)
|
f" - |R{char.name}|n [{', '.join(char.permissions.all())}] "
|
||||||
else:
|
"(played by someone else)"
|
||||||
result.append(
|
)
|
||||||
f"\n - |R{char.key}|n [{', '.join(char.permissions.all())}] (played by"
|
elif char.db.chargen_step:
|
||||||
" someone else)"
|
# currently in-progress character; don't display placeholder names
|
||||||
)
|
char_strings.append("\n - |Yin progress|n (|wcharcreate|n to continue)")
|
||||||
else:
|
continue
|
||||||
# character is available
|
else:
|
||||||
result.append(f"\n - {char.key} [{', '.join(char.permissions.all())}]")
|
# character is "free to puppet"
|
||||||
look_string = ("-" * 68) + "\n" + "".join(result) + "\n" + ("-" * 68)
|
char_strings.append(f" - {char.name} [{', '.join(char.permissions.all())}]")
|
||||||
return look_string
|
|
||||||
|
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="",
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -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 import DefaultCharacter
|
||||||
from evennia.commands.default import account
|
|
||||||
from evennia.utils import inherits_from
|
from evennia.utils import inherits_from
|
||||||
from evennia.utils.test_resources import BaseEvenniaCommandTest
|
from evennia.utils.test_resources import BaseEvenniaCommandTest
|
||||||
|
|
||||||
|
|
@ -15,31 +9,41 @@ class TestCharacterCreator(BaseEvenniaCommandTest):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.account.swap_typeclass(character_creator.ContribChargenAccount)
|
self.account.swap_typeclass(character_creator.ContribChargenAccount)
|
||||||
|
|
||||||
def test_ooc_look(self):
|
|
||||||
self.account.characters.add(self.char1)
|
|
||||||
self.account.unpuppet_all()
|
self.account.unpuppet_all()
|
||||||
|
|
||||||
|
def test_account_look(self):
|
||||||
|
self.account.characters.add(self.char1)
|
||||||
self.char1.db.chargen_step = "start"
|
self.char1.db.chargen_step = "start"
|
||||||
|
|
||||||
with patch("evennia.commands.default.account._AUTO_PUPPET_ON_LOGIN", new=False):
|
# check that correct output is returning
|
||||||
# check that correct output is returning
|
output = self.account.at_look(target=self.account.characters.all(), session=self.session)
|
||||||
output = self.call(
|
# check that char1 is recognized as in progress
|
||||||
account.CmdOOCLook(),
|
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,
|
caller=self.account,
|
||||||
)
|
)
|
||||||
# check that char1 is recognized as in progress
|
# verify menu was initialized
|
||||||
self.assertIn("in progress", output)
|
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")
|
# exit the menu, verify it resumes
|
||||||
def test_char_create(self):
|
menu.parse_input("q")
|
||||||
|
del self.session.new_char
|
||||||
|
self.assertEqual(self.session.ndb._menutree, None)
|
||||||
self.call(
|
self.call(
|
||||||
character_creator.ContribCmdCharCreate(),
|
character_creator.ContribCmdCharCreate(),
|
||||||
"",
|
"",
|
||||||
caller=self.account,
|
caller=self.account,
|
||||||
)
|
)
|
||||||
menu = self.session.ndb._menutree
|
# should be the same new char
|
||||||
self.assertNotEqual(menu, None)
|
self.assertEqual(new_char, self.session.new_char)
|
||||||
self.assertTrue(inherits_from(self.session.new_char, DefaultCharacter))
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue