Ran black on branc

This commit is contained in:
Griatch 2019-12-16 20:31:42 +01:00
parent 6effb6f456
commit 4ea6209123
230 changed files with 7108 additions and 2395 deletions

View file

@ -39,25 +39,25 @@ SERVERNAME = "testing_mygame"
# Testing database types # Testing database types
DATABASES = { DATABASES = {
'default': { "default": {
'ENGINE': 'django.db.backends.mysql', "ENGINE": "django.db.backends.mysql",
'NAME': 'evennia', "NAME": "evennia",
'USER': 'evennia', "USER": "evennia",
'PASSWORD': 'password', "PASSWORD": "password",
'HOST': 'localhost', "HOST": "localhost",
'PORT': '', # use default port "PORT": "", # use default port
'OPTIONS': { "OPTIONS": {
'charset': 'utf8mb4', "charset": "utf8mb4",
'init_command': 'set collation_connection=utf8mb4_unicode_ci' "init_command": "set collation_connection=utf8mb4_unicode_ci",
}, },
'TEST': { "TEST": {
'NAME': 'default', "NAME": "default",
'OPTIONS': { "OPTIONS": {
'charset': 'utf8mb4', "charset": "utf8mb4",
# 'init_command': 'set collation_connection=utf8mb4_unicode_ci' # 'init_command': 'set collation_connection=utf8mb4_unicode_ci'
'init_command': "SET NAMES 'utf8mb4'" "init_command": "SET NAMES 'utf8mb4'",
} },
} },
} }
} }

View file

@ -39,16 +39,14 @@ SERVERNAME = "testing_mygame"
# Testing database types # Testing database types
DATABASES = { DATABASES = {
'default': { "default": {
'ENGINE': 'django.db.backends.postgresql_psycopg2', "ENGINE": "django.db.backends.postgresql_psycopg2",
'NAME': 'evennia', "NAME": "evennia",
'USER': 'evennia', "USER": "evennia",
'PASSWORD': 'password', "PASSWORD": "password",
'HOST': 'localhost', "HOST": "localhost",
'PORT': '', # use default "PORT": "", # use default
'TEST': { "TEST": {"NAME": "default"},
'NAME': 'default'
}
} }
} }

View file

@ -23,7 +23,7 @@ USE_COLOR = True
FAKE_MODE = False FAKE_MODE = False
# if these words are longer than output word, retain given case # if these words are longer than output word, retain given case
CASE_WORD_EXCEPTIONS = ('an', ) CASE_WORD_EXCEPTIONS = ("an",)
_HELP_TEXT = """This program interactively renames words in all files of your project. It's _HELP_TEXT = """This program interactively renames words in all files of your project. It's
currently renaming {sources} to {targets}. currently renaming {sources} to {targets}.
@ -80,6 +80,7 @@ def _case_sensitive_replace(string, old, new):
`old` has been replaced with `new`, retaining case. `old` has been replaced with `new`, retaining case.
""" """
def repl(match): def repl(match):
current = match.group() current = match.group()
# treat multi-word sentences word-by-word # treat multi-word sentences word-by-word
@ -99,15 +100,21 @@ def _case_sensitive_replace(string, old, new):
all_upper = False all_upper = False
# special cases - keep remaing case) # special cases - keep remaing case)
if new_word.lower() in CASE_WORD_EXCEPTIONS: if new_word.lower() in CASE_WORD_EXCEPTIONS:
result.append(new_word[ind + 1:]) result.append(new_word[ind + 1 :])
# append any remaining characters from new # append any remaining characters from new
elif all_upper: elif all_upper:
result.append(new_word[ind + 1:].upper()) result.append(new_word[ind + 1 :].upper())
else: else:
result.append(new_word[ind + 1:].lower()) result.append(new_word[ind + 1 :].lower())
out.append("".join(result)) out.append("".join(result))
# if we have more new words than old ones, just add them verbatim # if we have more new words than old ones, just add them verbatim
out.extend([new_word for ind, new_word in enumerate(new_words) if ind >= len(old_words)]) out.extend(
[
new_word
for ind, new_word in enumerate(new_words)
if ind >= len(old_words)
]
)
return " ".join(out) return " ".join(out)
regex = re.compile(re.escape(old), re.I) regex = re.compile(re.escape(old), re.I)
@ -147,7 +154,9 @@ def rename_in_tree(path, in_list, out_list, excl_list, fileend_list, is_interact
print("%s skipped (excluded)." % full_path) print("%s skipped (excluded)." % full_path)
continue continue
if not fileend_list or any(file.endswith(ending) for ending in fileend_list): if not fileend_list or any(
file.endswith(ending) for ending in fileend_list
):
rename_in_file(full_path, in_list, out_list, is_interactive) rename_in_file(full_path, in_list, out_list, is_interactive)
# rename file - always ask # rename file - always ask
@ -155,8 +164,10 @@ def rename_in_tree(path, in_list, out_list, excl_list, fileend_list, is_interact
for src, dst in repl_mapping: for src, dst in repl_mapping:
new_file = _case_sensitive_replace(new_file, src, dst) new_file = _case_sensitive_replace(new_file, src, dst)
if new_file != file: if new_file != file:
inp = input(_green("Rename %s\n -> %s\n Y/[N]? > " % (file, new_file))) inp = input(
if inp.upper() == 'Y': _green("Rename %s\n -> %s\n Y/[N]? > " % (file, new_file))
)
if inp.upper() == "Y":
new_full_path = os.path.join(root, new_file) new_full_path = os.path.join(root, new_file)
try: try:
os.rename(full_path, new_full_path) os.rename(full_path, new_full_path)
@ -171,8 +182,10 @@ def rename_in_tree(path, in_list, out_list, excl_list, fileend_list, is_interact
for src, dst in repl_mapping: for src, dst in repl_mapping:
new_root = _case_sensitive_replace(new_root, src, dst) new_root = _case_sensitive_replace(new_root, src, dst)
if new_root != root: if new_root != root:
inp = input(_green("Dir Rename %s\n -> %s\n Y/[N]? > " % (root, new_root))) inp = input(
if inp.upper() == 'Y': _green("Dir Rename %s\n -> %s\n Y/[N]? > " % (root, new_root))
)
if inp.upper() == "Y":
try: try:
os.rename(root, new_root) os.rename(root, new_root)
except OSError as err: except OSError as err:
@ -201,7 +214,7 @@ def rename_in_file(path, in_list, out_list, is_interactive):
print("%s is a directory. You should use the --recursive option." % path) print("%s is a directory. You should use the --recursive option." % path)
sys.exit() sys.exit()
with open(path, 'r') as fil: with open(path, "r") as fil:
org_text = fil.read() org_text = fil.read()
repl_mapping = list(zip(in_list, out_list)) repl_mapping = list(zip(in_list, out_list))
@ -215,7 +228,7 @@ def rename_in_file(path, in_list, out_list, is_interactive):
if FAKE_MODE: if FAKE_MODE:
print(" ... Saved changes to %s. (faked)" % path) print(" ... Saved changes to %s. (faked)" % path)
else: else:
with open(path, 'w') as fil: with open(path, "w") as fil:
fil.write(new_text) fil.write(new_text)
print(" ... Saved changes to %s." % path) print(" ... Saved changes to %s." % path)
else: else:
@ -239,18 +252,24 @@ def rename_in_file(path, in_list, out_list, is_interactive):
while True: while True:
for iline, renamed_line in sorted(list(renamed.items()), key=lambda tup: tup[0]): for iline, renamed_line in sorted(
list(renamed.items()), key=lambda tup: tup[0]
):
print("%3i orig: %s" % (iline + 1, org_lines[iline])) print("%3i orig: %s" % (iline + 1, org_lines[iline]))
print(" new : %s" % (_yellow(renamed_line))) print(" new : %s" % (_yellow(renamed_line)))
print(_green("%s (%i lines changed)" % (path, len(renamed)))) print(_green("%s (%i lines changed)" % (path, len(renamed))))
ret = input(_green("Choose: " ret = input(
_green(
"Choose: "
"[q]uit, " "[q]uit, "
"[h]elp, " "[h]elp, "
"[s]kip file, " "[s]kip file, "
"[i]gnore lines, " "[i]gnore lines, "
"[c]lear ignores, " "[c]lear ignores, "
"[a]ccept/save file: ".lower())) "[a]ccept/save file: ".lower()
)
)
if ret == "s": if ret == "s":
# skip file entirely # skip file entirely
@ -267,7 +286,7 @@ def rename_in_file(path, in_list, out_list, is_interactive):
if FAKE_MODE: if FAKE_MODE:
print(" ... Saved file %s (faked)" % path) print(" ... Saved file %s (faked)" % path)
return return
with open(path, 'w') as fil: with open(path, "w") as fil:
fil.writelines("\n".join(org_lines)) fil.writelines("\n".join(org_lines))
print(" ... Saved file %s" % path) print(" ... Saved file %s" % path)
return return
@ -278,7 +297,11 @@ def rename_in_file(path, in_list, out_list, is_interactive):
input(_HELP_TEXT.format(sources=in_list, targets=out_list)) input(_HELP_TEXT.format(sources=in_list, targets=out_list))
elif ret.startswith("i"): elif ret.startswith("i"):
# ignore one or more lines # ignore one or more lines
ignores = [int(ind) - 1 for ind in ret[1:].split(',') if ind.strip().isdigit()] ignores = [
int(ind) - 1
for ind in ret[1:].split(",")
if ind.strip().isdigit()
]
if not ignores: if not ignores:
input("Ignore example: i 2,7,34,133\n (return to continue)") input("Ignore example: i 2,7,34,133\n (return to continue)")
continue continue
@ -291,36 +314,57 @@ if __name__ == "__main__":
import argparse import argparse
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description="Rename text in a source tree, or a single file") description="Rename text in a source tree, or a single file"
)
parser.add_argument('-i', '--input', action='append', parser.add_argument(
help="Source word to rename (quote around multiple words)") "-i",
parser.add_argument('-o', '--output', action='append', "--input",
help="Word to rename a matching src-word to") action="append",
parser.add_argument('-x', '--exc', action='append', help="Source word to rename (quote around multiple words)",
help="File path patterns to exclude") )
parser.add_argument('-a', '--auto', action='store_true', parser.add_argument(
help="Automatic mode, don't ask to rename") "-o", "--output", action="append", help="Word to rename a matching src-word to"
parser.add_argument('-r', '--recursive', action='store_true', )
help="Recurse subdirs") parser.add_argument(
parser.add_argument('-f', '--fileending', action='append', "-x", "--exc", action="append", help="File path patterns to exclude"
help="Change which file endings to allow (default .py and .html)") )
parser.add_argument('--nocolor', action='store_true', parser.add_argument(
help="Turn off in-program color") "-a", "--auto", action="store_true", help="Automatic mode, don't ask to rename"
parser.add_argument('--fake', action='store_true', )
help="Simulate run but don't actually save") parser.add_argument(
parser.add_argument('path', "-r", "--recursive", action="store_true", help="Recurse subdirs"
help="File or directory in which to rename text") )
parser.add_argument(
"-f",
"--fileending",
action="append",
help="Change which file endings to allow (default .py and .html)",
)
parser.add_argument(
"--nocolor", action="store_true", help="Turn off in-program color"
)
parser.add_argument(
"--fake", action="store_true", help="Simulate run but don't actually save"
)
parser.add_argument("path", help="File or directory in which to rename text")
args = parser.parse_args() args = parser.parse_args()
in_list, out_list, exc_list, fileend_list = args.input, args.output, args.exc, args.fileending in_list, out_list, exc_list, fileend_list = (
args.input,
args.output,
args.exc,
args.fileending,
)
if not (in_list and out_list): if not (in_list and out_list):
print('At least one source- and destination word must be given.') print("At least one source- and destination word must be given.")
sys.exit() sys.exit()
if len(in_list) != len(out_list): if len(in_list) != len(out_list):
print('Number of sources must be identical to the number of destination arguments.') print(
"Number of sources must be identical to the number of destination arguments."
)
sys.exit() sys.exit()
exc_list = exc_list or [] exc_list = exc_list or []
@ -332,6 +376,8 @@ if __name__ == "__main__":
FAKE_MODE = args.fake FAKE_MODE = args.fake
if is_recursive: if is_recursive:
rename_in_tree(args.path, in_list, out_list, exc_list, fileend_list, is_interactive) rename_in_tree(
args.path, in_list, out_list, exc_list, fileend_list, is_interactive
)
else: else:
rename_in_file(args.path, in_list, out_list, is_interactive) rename_in_file(args.path, in_list, out_list, is_interactive)

View file

@ -14,4 +14,5 @@ sys.path.insert(0, os.path.abspath(os.getcwd()))
sys.path.insert(0, os.path.join(sys.prefix, "Lib", "site-packages")) sys.path.insert(0, os.path.join(sys.prefix, "Lib", "site-packages"))
from evennia.server.evennia_launcher import main from evennia.server.evennia_launcher import main
main() main()

View file

@ -142,7 +142,9 @@ def _create_version():
print(err) print(err)
try: try:
rev = ( rev = (
check_output("git rev-parse --short HEAD", shell=True, cwd=root, stderr=STDOUT) check_output(
"git rev-parse --short HEAD", shell=True, cwd=root, stderr=STDOUT
)
.strip() .strip()
.decode() .decode()
) )
@ -261,7 +263,9 @@ def _init():
def _help(self): def _help(self):
"Returns list of contents" "Returns list of contents"
names = [name for name in self.__class__.__dict__ if not name.startswith("_")] names = [
name for name in self.__class__.__dict__ if not name.startswith("_")
]
names += [name for name in self.__dict__ if not name.startswith("_")] names += [name for name in self.__dict__ if not name.startswith("_")]
print(self.__doc__ + "-" * 60 + "\n" + ", ".join(names)) print(self.__doc__ + "-" * 60 + "\n" + ", ".join(names))

View file

@ -26,7 +26,13 @@ from evennia.commands import cmdhandler
from evennia.server.models import ServerConfig from evennia.server.models import ServerConfig
from evennia.server.throttle import Throttle from evennia.server.throttle import Throttle
from evennia.utils import class_from_module, create, logger from evennia.utils import class_from_module, create, logger
from evennia.utils.utils import lazy_property, to_str, make_iter, is_iter, variable_from_module from evennia.utils.utils import (
lazy_property,
to_str,
make_iter,
is_iter,
variable_from_module,
)
from evennia.server.signals import ( from evennia.server.signals import (
SIGNAL_ACCOUNT_POST_CREATE, SIGNAL_ACCOUNT_POST_CREATE,
SIGNAL_OBJECT_POST_PUPPET, SIGNAL_OBJECT_POST_PUPPET,
@ -289,7 +295,9 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase):
self.msg(txt1, session=session) self.msg(txt1, session=session)
self.msg(txt2, session=obj.sessions.all()) self.msg(txt2, session=obj.sessions.all())
else: else:
txt1 = f"Taking over |c{obj.name}|n from another of your sessions." txt1 = (
f"Taking over |c{obj.name}|n from another of your sessions."
)
txt2 = f"|c{obj.name}|n|R is now acted from another of your sessions.|n" txt2 = f"|c{obj.name}|n|R is now acted from another of your sessions.|n"
self.msg(txt1, session=session) self.msg(txt1, session=session)
self.msg(txt2, session=obj.sessions.all()) self.msg(txt2, session=obj.sessions.all())
@ -344,7 +352,9 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase):
if not obj.sessions.count(): if not obj.sessions.count():
del obj.account del obj.account
obj.at_post_unpuppet(self, session=session) obj.at_post_unpuppet(self, session=session)
SIGNAL_OBJECT_POST_UNPUPPET.send(sender=obj, session=session, account=self) SIGNAL_OBJECT_POST_UNPUPPET.send(
sender=obj, session=session, account=self
)
# Just to be sure we're always clear. # Just to be sure we're always clear.
session.puppet = None session.puppet = None
session.puid = None session.puid = None
@ -380,7 +390,9 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase):
by this Account. by this Account.
""" """
return list(set(session.puppet for session in self.sessions.all() if session.puppet)) return list(
set(session.puppet for session in self.sessions.all() if session.puppet)
)
def __get_single_puppet(self): def __get_single_puppet(self):
""" """
@ -723,7 +735,11 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase):
try: try:
try: try:
account = create.create_account( account = create.create_account(
username, email, password, permissions=permissions, typeclass=typeclass username,
email,
password,
permissions=permissions,
typeclass=typeclass,
) )
logger.log_sec(f"Account Created: {account} (IP: {ip}).") logger.log_sec(f"Account Created: {account} (IP: {ip}).")
@ -744,9 +760,13 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase):
account.db.creator_ip = ip account.db.creator_ip = ip
# join the new account to the public channel # join the new account to the public channel
pchannel = ChannelDB.objects.get_channel(settings.DEFAULT_CHANNELS[0]["key"]) pchannel = ChannelDB.objects.get_channel(
settings.DEFAULT_CHANNELS[0]["key"]
)
if not pchannel or not pchannel.connect(account): if not pchannel or not pchannel.connect(account):
string = f"New account '{account.key}' could not connect to public channel!" string = (
f"New account '{account.key}' could not connect to public channel!"
)
errors.append(string) errors.append(string)
logger.log_err(string) logger.log_err(string)
@ -781,7 +801,9 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase):
# We are in the middle between logged in and -not, so we have # We are in the middle between logged in and -not, so we have
# to handle tracebacks ourselves at this point. If we don't, # to handle tracebacks ourselves at this point. If we don't,
# we won't see any errors at all. # we won't see any errors at all.
errors.append("An error occurred. Please e-mail an admin if the problem persists.") errors.append(
"An error occurred. Please e-mail an admin if the problem persists."
)
logger.log_trace() logger.log_trace()
# Update the throttle to indicate a new account was created from this IP # Update the throttle to indicate a new account was created from this IP
@ -808,7 +830,9 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase):
except RuntimeError: except RuntimeError:
# no puppet to disconnect from # no puppet to disconnect from
pass pass
session.sessionhandler.disconnect(session, reason=_("Account being deleted.")) session.sessionhandler.disconnect(
session, reason=_("Account being deleted.")
)
self.scripts.stop() self.scripts.stop()
self.attributes.clear() self.attributes.clear()
self.nicks.clear() self.nicks.clear()
@ -968,7 +992,12 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase):
return matches return matches
def access( def access(
self, accessing_obj, access_type="read", default=False, no_superuser_bypass=False, **kwargs self,
accessing_obj,
access_type="read",
default=False,
no_superuser_bypass=False,
**kwargs,
): ):
""" """
Determines if another object has permission to access this Determines if another object has permission to access this
@ -1048,7 +1077,9 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase):
""" """
# set an (empty) attribute holding the characters this account has # set an (empty) attribute holding the characters this account has
lockstring = "attrread:perm(Admins);attredit:perm(Admins);" "attrcreate:perm(Admins);" lockstring = (
"attrread:perm(Admins);attredit:perm(Admins);" "attrcreate:perm(Admins);"
)
self.attributes.add("_playable_characters", [], lockstring=lockstring) self.attributes.add("_playable_characters", [], lockstring=lockstring)
self.attributes.add("_saved_protocol_flags", {}, lockstring=lockstring) self.attributes.add("_saved_protocol_flags", {}, lockstring=lockstring)
@ -1203,13 +1234,19 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase):
global _MUDINFO_CHANNEL global _MUDINFO_CHANNEL
if not _MUDINFO_CHANNEL: if not _MUDINFO_CHANNEL:
try: try:
_MUDINFO_CHANNEL = ChannelDB.objects.filter(db_key=settings.CHANNEL_MUDINFO["key"])[ _MUDINFO_CHANNEL = ChannelDB.objects.filter(
0 db_key=settings.CHANNEL_MUDINFO["key"]
] )[0]
except Exception: except Exception:
logger.log_trace() logger.log_trace()
now = timezone.now() now = timezone.now()
now = "%02i-%02i-%02i(%02i:%02i)" % (now.year, now.month, now.day, now.hour, now.minute) now = "%02i-%02i-%02i(%02i:%02i)" % (
now.year,
now.month,
now.day,
now.hour,
now.minute,
)
if _MUDINFO_CHANNEL: if _MUDINFO_CHANNEL:
_MUDINFO_CHANNEL.tempmsg(f"[{_MUDINFO_CHANNEL.key}, {now}]: {message}") _MUDINFO_CHANNEL.tempmsg(f"[{_MUDINFO_CHANNEL.key}, {now}]: {message}")
else: else:
@ -1261,9 +1298,12 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase):
# screen. We execute look on the account. # screen. We execute look on the account.
# we make sure to clean up the _playable_characters list in case # we make sure to clean up the _playable_characters list in case
# any was deleted in the interim. # any was deleted in the interim.
self.db._playable_characters = [char for char in self.db._playable_characters if char] self.db._playable_characters = [
char for char in self.db._playable_characters if char
]
self.msg( self.msg(
self.at_look(target=self.db._playable_characters, session=session), session=session self.at_look(target=self.db._playable_characters, session=session),
session=session,
) )
def at_failed_login(self, session, **kwargs): def at_failed_login(self, session, **kwargs):
@ -1421,7 +1461,9 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase):
csessid = sess.sessid csessid = sess.sessid
addr = "%s (%s)" % ( addr = "%s (%s)" % (
sess.protocol_key, sess.protocol_key,
isinstance(sess.address, tuple) and str(sess.address[0]) or str(sess.address), isinstance(sess.address, tuple)
and str(sess.address[0])
or str(sess.address),
) )
result.append( result.append(
"\n %s %s" "\n %s %s"
@ -1444,14 +1486,18 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase):
"\n\n You don't have any characters yet. See |whelp @charcreate|n for creating one." "\n\n You don't have any characters yet. See |whelp @charcreate|n for creating one."
) )
else: else:
result.append("\n |w@charcreate <name> [=description]|n - create new character") result.append(
"\n |w@charcreate <name> [=description]|n - create new character"
)
result.append( result.append(
"\n |w@chardelete <name>|n - delete a character (cannot be undone!)" "\n |w@chardelete <name>|n - delete a character (cannot be undone!)"
) )
if characters: if characters:
string_s_ending = len(characters) > 1 and "s" or "" string_s_ending = len(characters) > 1 and "s" or ""
result.append("\n |w@ic <character>|n - enter the game (|w@ooc|n to get back here)") result.append(
"\n |w@ic <character>|n - enter the game (|w@ooc|n to get back here)"
)
if is_su: if is_su:
result.append( result.append(
f"\n\nAvailable character{string_s_ending} ({len(characters)}/unlimited):" f"\n\nAvailable character{string_s_ending} ({len(characters)}/unlimited):"
@ -1461,7 +1507,9 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase):
"\n\nAvailable character%s%s:" "\n\nAvailable character%s%s:"
% ( % (
string_s_ending, string_s_ending,
charmax > 1 and " (%i/%i)" % (len(characters), charmax) or "", charmax > 1
and " (%i/%i)" % (len(characters), charmax)
or "",
) )
) )
@ -1481,7 +1529,9 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase):
) )
else: else:
# character is "free to puppet" # character is "free to puppet"
result.append(f"\n - {char.key} [{', '.join(char.permissions.all())}]") result.append(
f"\n - {char.key} [{', '.join(char.permissions.all())}]"
)
look_string = ("-" * 68) + "\n" + "".join(result) + "\n" + ("-" * 68) look_string = ("-" * 68) + "\n" + "".join(result) + "\n" + ("-" * 68)
return look_string return look_string
@ -1559,7 +1609,9 @@ class DefaultGuest(DefaultAccount):
# We are in the middle between logged in and -not, so we have # We are in the middle between logged in and -not, so we have
# to handle tracebacks ourselves at this point. If we don't, # to handle tracebacks ourselves at this point. If we don't,
# we won't see any errors at all. # we won't see any errors at all.
errors.append("An error occurred. Please e-mail an admin if the problem persists.") errors.append(
"An error occurred. Please e-mail an admin if the problem persists."
)
logger.log_trace() logger.log_trace()
return None, errors return None, errors

View file

@ -32,7 +32,8 @@ class AccountDBChangeForm(UserChangeForm):
"invalid": "This value may contain only letters, spaces, numbers " "invalid": "This value may contain only letters, spaces, numbers "
"and @/./+/-/_ characters." "and @/./+/-/_ characters."
}, },
help_text="30 characters or fewer. Letters, spaces, digits and " "@/./+/-/_ only.", help_text="30 characters or fewer. Letters, spaces, digits and "
"@/./+/-/_ only.",
) )
def clean_username(self): def clean_username(self):
@ -66,7 +67,8 @@ class AccountDBCreationForm(UserCreationForm):
"invalid": "This value may contain only letters, spaces, numbers " "invalid": "This value may contain only letters, spaces, numbers "
"and @/./+/-/_ characters." "and @/./+/-/_ characters."
}, },
help_text="30 characters or fewer. Letters, spaces, digits and " "@/./+/-/_ only.", help_text="30 characters or fewer. Letters, spaces, digits and "
"@/./+/-/_ only.",
) )
def clean_username(self): def clean_username(self):
@ -228,7 +230,13 @@ class AccountDBAdmin(BaseUserAdmin):
( (
"Website Permissions", "Website Permissions",
{ {
"fields": ("is_active", "is_staff", "is_superuser", "user_permissions", "groups"), "fields": (
"is_active",
"is_staff",
"is_superuser",
"user_permissions",
"groups",
),
"description": "<i>These are permissions/permission groups for " "description": "<i>These are permissions/permission groups for "
"accessing the admin site. They are unrelated to " "accessing the admin site. They are unrelated to "
"in-game access rights.</i>", "in-game access rights.</i>",
@ -238,7 +246,8 @@ class AccountDBAdmin(BaseUserAdmin):
"Game Options", "Game Options",
{ {
"fields": ("db_typeclass_path", "db_cmdset_storage", "db_lock_storage"), "fields": ("db_typeclass_path", "db_cmdset_storage", "db_lock_storage"),
"description": "<i>These are attributes that are more relevant " "to gameplay.</i>", "description": "<i>These are attributes that are more relevant "
"to gameplay.</i>",
}, },
), ),
) )
@ -281,7 +290,9 @@ class AccountDBAdmin(BaseUserAdmin):
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.urls import reverse from django.urls import reverse
return HttpResponseRedirect(reverse("admin:accounts_accountdb_change", args=[obj.id])) return HttpResponseRedirect(
reverse("admin:accounts_accountdb_change", args=[obj.id])
)
admin.site.register(AccountDB, AccountDBAdmin) admin.site.register(AccountDB, AccountDBAdmin)

View file

@ -124,7 +124,9 @@ class Bot(DefaultAccount):
Evennia -> outgoing protocol Evennia -> outgoing protocol
""" """
super().msg(text=text, from_obj=from_obj, session=session, options=options, **kwargs) super().msg(
text=text, from_obj=from_obj, session=session, options=options, **kwargs
)
def execute_cmd(self, raw_string, session=None): def execute_cmd(self, raw_string, session=None):
""" """
@ -325,8 +327,12 @@ class IRCBot(Bot):
if kwargs["type"] == "nicklist": if kwargs["type"] == "nicklist":
# the return of a nicklist request # the return of a nicklist request
if hasattr(self, "_nicklist_callers") and self._nicklist_callers: if hasattr(self, "_nicklist_callers") and self._nicklist_callers:
chstr = f"{self.db.irc_channel} ({self.db.irc_network}:{self.db.irc_port})" chstr = (
nicklist = ", ".join(sorted(kwargs["nicklist"], key=lambda n: n.lower())) f"{self.db.irc_channel} ({self.db.irc_network}:{self.db.irc_port})"
)
nicklist = ", ".join(
sorted(kwargs["nicklist"], key=lambda n: n.lower())
)
for obj in self._nicklist_callers: for obj in self._nicklist_callers:
obj.msg(f"Nicks at {chstr}:\n {nicklist}") obj.msg(f"Nicks at {chstr}:\n {nicklist}")
self._nicklist_callers = [] self._nicklist_callers = []
@ -335,7 +341,9 @@ class IRCBot(Bot):
elif kwargs["type"] == "ping": elif kwargs["type"] == "ping":
# the return of a ping # the return of a ping
if hasattr(self, "_ping_callers") and self._ping_callers: if hasattr(self, "_ping_callers") and self._ping_callers:
chstr = f"{self.db.irc_channel} ({self.db.irc_network}:{self.db.irc_port})" chstr = (
f"{self.db.irc_channel} ({self.db.irc_network}:{self.db.irc_port})"
)
for obj in self._ping_callers: for obj in self._ping_callers:
obj.msg(f"IRC ping return from {chstr} took {kwargs['timing']}s.") obj.msg(f"IRC ping return from {chstr} took {kwargs['timing']}s.")
self._ping_callers = [] self._ping_callers = []
@ -434,8 +442,14 @@ class RSSBot(Bot):
self.db.rss_rate = rss_rate self.db.rss_rate = rss_rate
# instruct the server and portal to create a new session with # instruct the server and portal to create a new session with
# the stored configuration # the stored configuration
configdict = {"uid": self.dbid, "url": self.db.rss_url, "rate": self.db.rss_rate} configdict = {
_SESSIONS.start_bot_session("evennia.server.portal.rss.RSSBotFactory", configdict) "uid": self.dbid,
"url": self.db.rss_url,
"rate": self.db.rss_rate,
}
_SESSIONS.start_bot_session(
"evennia.server.portal.rss.RSSBotFactory", configdict
)
def execute_cmd(self, txt=None, session=None, **kwargs): def execute_cmd(self, txt=None, session=None, **kwargs):
""" """

View file

@ -92,7 +92,9 @@ class AccountDBManager(TypedObjectManager, UserManager):
end_date = timezone.now() end_date = timezone.now()
tdelta = datetime.timedelta(days) tdelta = datetime.timedelta(days)
start_date = end_date - tdelta start_date = end_date - tdelta
return self.filter(last_login__range=(start_date, end_date)).order_by("-last_login") return self.filter(last_login__range=(start_date, end_date)).order_by(
"-last_login"
)
def get_account_from_email(self, uemail): def get_account_from_email(self, uemail):
""" """
@ -177,7 +179,11 @@ class AccountDBManager(TypedObjectManager, UserManager):
# try alias match # try alias match
matches = self.filter( matches = self.filter(
db_tags__db_tagtype__iexact="alias", db_tags__db_tagtype__iexact="alias",
**{"db_tags__db_key__iexact" if exact else "db_tags__db_key__icontains": ostring}, **{
"db_tags__db_key__iexact"
if exact
else "db_tags__db_key__icontains": ostring
},
) )
return matches return matches

View file

@ -17,7 +17,10 @@ class Migration(migrations.Migration):
( (
"id", "id",
models.AutoField( models.AutoField(
verbose_name="ID", serialize=False, auto_created=True, primary_key=True verbose_name="ID",
serialize=False,
auto_created=True,
primary_key=True,
), ),
), ),
("password", models.CharField(max_length=128, verbose_name="password")), ("password", models.CharField(max_length=128, verbose_name="password")),
@ -51,15 +54,21 @@ class Migration(migrations.Migration):
), ),
( (
"first_name", "first_name",
models.CharField(max_length=30, verbose_name="first name", blank=True), models.CharField(
max_length=30, verbose_name="first name", blank=True
),
), ),
( (
"last_name", "last_name",
models.CharField(max_length=30, verbose_name="last name", blank=True), models.CharField(
max_length=30, verbose_name="last name", blank=True
),
), ),
( (
"email", "email",
models.EmailField(max_length=75, verbose_name="email address", blank=True), models.EmailField(
max_length=75, verbose_name="email address", blank=True
),
), ),
( (
"is_staff", "is_staff",
@ -83,7 +92,10 @@ class Migration(migrations.Migration):
default=django.utils.timezone.now, verbose_name="date joined" default=django.utils.timezone.now, verbose_name="date joined"
), ),
), ),
("db_key", models.CharField(max_length=255, verbose_name="key", db_index=True)), (
"db_key",
models.CharField(max_length=255, verbose_name="key", db_index=True),
),
( (
"db_typeclass_path", "db_typeclass_path",
models.CharField( models.CharField(
@ -95,7 +107,9 @@ class Migration(migrations.Migration):
), ),
( (
"db_date_created", "db_date_created",
models.DateTimeField(auto_now_add=True, verbose_name="creation date"), models.DateTimeField(
auto_now_add=True, verbose_name="creation date"
),
), ),
( (
"db_lock_storage", "db_lock_storage",

View file

@ -6,7 +6,9 @@ from django.db import models, migrations
def convert_defaults(apps, schema_editor): def convert_defaults(apps, schema_editor):
AccountDB = apps.get_model("accounts", "AccountDB") AccountDB = apps.get_model("accounts", "AccountDB")
for account in AccountDB.objects.filter(db_typeclass_path="src.accounts.account.Account"): for account in AccountDB.objects.filter(
db_typeclass_path="src.accounts.account.Account"
):
account.db_typeclass_path = "typeclasses.accounts.Account" account.db_typeclass_path = "typeclasses.accounts.Account"
account.save() account.save()

View file

@ -10,7 +10,10 @@ class Migration(migrations.Migration):
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name="DefaultAccount", fields=[], options={"proxy": True}, bases=("accounts.accountdb",) name="DefaultAccount",
fields=[],
options={"proxy": True},
bases=("accounts.accountdb",),
), ),
migrations.CreateModel( migrations.CreateModel(
name="DefaultGuest", name="DefaultGuest",
@ -18,5 +21,7 @@ class Migration(migrations.Migration):
options={"proxy": True}, options={"proxy": True},
bases=("accounts.defaultaccount",), bases=("accounts.defaultaccount",),
), ),
migrations.AlterModelOptions(name="accountdb", options={"verbose_name": "Account"}), migrations.AlterModelOptions(
name="accountdb", options={"verbose_name": "Account"}
),
] ]

View file

@ -14,12 +14,15 @@ class Migration(migrations.Migration):
migrations.DeleteModel(name="DefaultGuest"), migrations.DeleteModel(name="DefaultGuest"),
migrations.DeleteModel(name="DefaultAccount"), migrations.DeleteModel(name="DefaultAccount"),
migrations.AlterModelManagers( migrations.AlterModelManagers(
name="accountdb", managers=[("objects", evennia.accounts.manager.AccountDBManager())] name="accountdb",
managers=[("objects", evennia.accounts.manager.AccountDBManager())],
), ),
migrations.AlterField( migrations.AlterField(
model_name="accountdb", model_name="accountdb",
name="email", name="email",
field=models.EmailField(max_length=254, verbose_name="email address", blank=True), field=models.EmailField(
max_length=254, verbose_name="email address", blank=True
),
), ),
migrations.AlterField( migrations.AlterField(
model_name="accountdb", model_name="accountdb",
@ -36,7 +39,9 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name="accountdb", model_name="accountdb",
name="last_login", name="last_login",
field=models.DateTimeField(null=True, verbose_name="last login", blank=True), field=models.DateTimeField(
null=True, verbose_name="last login", blank=True
),
), ),
migrations.AlterField( migrations.AlterField(
model_name="accountdb", model_name="accountdb",

View file

@ -12,7 +12,8 @@ class Migration(migrations.Migration):
operations = [ operations = [
migrations.AlterModelManagers( migrations.AlterModelManagers(
name="accountdb", managers=[("objects", evennia.accounts.manager.AccountDBManager())] name="accountdb",
managers=[("objects", evennia.accounts.manager.AccountDBManager())],
), ),
migrations.AlterField( migrations.AlterField(
model_name="accountdb", model_name="accountdb",
@ -41,7 +42,9 @@ class Migration(migrations.Migration):
model_name="accountdb", model_name="accountdb",
name="db_is_bot", name="db_is_bot",
field=models.BooleanField( field=models.BooleanField(
default=False, help_text="Used to identify irc/rss bots", verbose_name="is_bot" default=False,
help_text="Used to identify irc/rss bots",
verbose_name="is_bot",
), ),
), ),
migrations.AlterField( migrations.AlterField(

View file

@ -5,19 +5,25 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [("accounts", "0008_auto_20190128_1820")]
('accounts', '0008_auto_20190128_1820'),
]
operations = [ operations = [
migrations.AlterField( migrations.AlterField(
model_name='accountdb', model_name="accountdb",
name='db_typeclass_path', name="db_typeclass_path",
field=models.CharField(db_index=True, help_text="this defines what 'type' of entity this is. This variable holds a Python path to a module with a valid Evennia Typeclass.", max_length=255, null=True, verbose_name='typeclass'), field=models.CharField(
db_index=True,
help_text="this defines what 'type' of entity this is. This variable holds a Python path to a module with a valid Evennia Typeclass.",
max_length=255,
null=True,
verbose_name="typeclass",
),
), ),
migrations.AlterField( migrations.AlterField(
model_name='accountdb', model_name="accountdb",
name='last_name', name="last_name",
field=models.CharField(blank=True, max_length=150, verbose_name='last name'), field=models.CharField(
blank=True, max_length=150, verbose_name="last name"
),
), ),
] ]

View file

@ -129,7 +129,11 @@ class AccountDB(TypedObject, AbstractUser):
Setter. Allows for self.name = value. Stores as a comma-separated Setter. Allows for self.name = value. Stores as a comma-separated
string. string.
""" """
_SA(self, "db_cmdset_storage", ",".join(str(val).strip() for val in make_iter(value))) _SA(
self,
"db_cmdset_storage",
",".join(str(val).strip() for val in make_iter(value)),
)
_GA(self, "save")() _GA(self, "save")()
# @cmdset_storage.deleter # @cmdset_storage.deleter
@ -138,7 +142,9 @@ class AccountDB(TypedObject, AbstractUser):
_SA(self, "db_cmdset_storage", None) _SA(self, "db_cmdset_storage", None)
_GA(self, "save")() _GA(self, "save")()
cmdset_storage = property(__cmdset_storage_get, __cmdset_storage_set, __cmdset_storage_del) cmdset_storage = property(
__cmdset_storage_get, __cmdset_storage_set, __cmdset_storage_del
)
# #
# property/field access # property/field access

View file

@ -54,7 +54,9 @@ class TestAccountSessionHandler(TestCase):
evennia.server.sessionhandler.SESSIONS[s3.uid] = s3 evennia.server.sessionhandler.SESSIONS[s3.uid] = s3
self.assertEqual([s.uid for s in self.handler.get()], [s1.uid]) self.assertEqual([s.uid for s in self.handler.get()], [s1.uid])
self.assertEqual([s.uid for s in [self.handler.get(self.account.uid)]], [s1.uid]) self.assertEqual(
[s.uid for s in [self.handler.get(self.account.uid)]], [s1.uid]
)
self.assertEqual([s.uid for s in self.handler.get(self.account.uid + 1)], []) self.assertEqual([s.uid for s in self.handler.get(self.account.uid + 1)], [])
def test_all(self): def test_all(self):
@ -86,7 +88,8 @@ class TestDefaultGuest(EvenniaTest):
# Create a second guest account # Create a second guest account
account, errors = DefaultGuest.authenticate(ip=self.ip) account, errors = DefaultGuest.authenticate(ip=self.ip)
self.assertFalse( self.assertFalse(
account, "Two guest accounts were created with a single entry on the guest list!" account,
"Two guest accounts were created with a single entry on the guest list!",
) )
@patch("evennia.accounts.accounts.ChannelDB.objects.get_channel") @patch("evennia.accounts.accounts.ChannelDB.objects.get_channel")
@ -147,13 +150,17 @@ class TestDefaultAccountAuth(EvenniaTest):
# Try creating a duplicate account # Try creating a duplicate account
account2, errors = DefaultAccount.create(username="Ziggy", password="starman11") account2, errors = DefaultAccount.create(username="Ziggy", password="starman11")
self.assertFalse(account2, "Duplicate account name should not have been allowed.") self.assertFalse(
account2, "Duplicate account name should not have been allowed."
)
account.delete() account.delete()
def test_throttle(self): def test_throttle(self):
"Confirm throttle activates on too many failures." "Confirm throttle activates on too many failures."
for x in range(20): for x in range(20):
obj, errors = DefaultAccount.authenticate(self.account.name, "xyzzy", ip="12.24.36.48") obj, errors = DefaultAccount.authenticate(
self.account.name, "xyzzy", ip="12.24.36.48"
)
self.assertFalse( self.assertFalse(
obj, obj,
"Authentication was provided a bogus password; this should NOT have returned an account!", "Authentication was provided a bogus password; this should NOT have returned an account!",
@ -176,7 +183,9 @@ class TestDefaultAccountAuth(EvenniaTest):
# Should not allow duplicate username # Should not allow duplicate username
result, error = DefaultAccount.validate_username(self.account.name) result, error = DefaultAccount.validate_username(self.account.name)
self.assertFalse(result, "Duplicate username should not have passed validation.") self.assertFalse(
result, "Duplicate username should not have passed validation."
)
# Should not allow username too short # Should not allow username too short
result, error = DefaultAccount.validate_username("xx") result, error = DefaultAccount.validate_username("xx")
@ -292,7 +301,9 @@ class TestDefaultAccount(TestCase):
account.puppet_object(self.s1, obj) account.puppet_object(self.s1, obj)
self.assertTrue( self.assertTrue(
self.s1.data_out.call_args[1]["text"].startswith("You don't have permission to puppet") self.s1.data_out.call_args[1]["text"].startswith(
"You don't have permission to puppet"
)
) )
self.assertIsNone(obj.at_post_puppet.call_args) self.assertIsNone(obj.at_post_puppet.call_args)
@ -323,7 +334,9 @@ class TestDefaultAccount(TestCase):
account.puppet_object(self.s1, obj) account.puppet_object(self.s1, obj)
# works because django.conf.settings.MULTISESSION_MODE is not in (1, 3) # works because django.conf.settings.MULTISESSION_MODE is not in (1, 3)
self.assertTrue( self.assertTrue(
self.s1.data_out.call_args[1]["text"].endswith("from another of your sessions.|n") self.s1.data_out.call_args[1]["text"].endswith(
"from another of your sessions.|n"
)
) )
self.assertTrue(obj.at_post_puppet.call_args[1] == {}) self.assertTrue(obj.at_post_puppet.call_args[1] == {})
@ -365,12 +378,15 @@ class TestAccountPuppetDeletion(EvenniaTest):
def test_puppet_deletion(self): def test_puppet_deletion(self):
# Check for existing chars # Check for existing chars
self.assertFalse( self.assertFalse(
self.account.db._playable_characters, "Account should not have any chars by default." self.account.db._playable_characters,
"Account should not have any chars by default.",
) )
# Add char1 to account's playable characters # Add char1 to account's playable characters
self.account.db._playable_characters.append(self.char1) self.account.db._playable_characters.append(self.char1)
self.assertTrue(self.account.db._playable_characters, "Char was not added to account.") self.assertTrue(
self.account.db._playable_characters, "Char was not added to account."
)
# See what happens when we delete char1. # See what happens when we delete char1.
self.char1.delete() self.char1.delete()
@ -398,7 +414,9 @@ class TestDefaultAccountEv(EvenniaTest):
self.account.msg = MagicMock() self.account.msg = MagicMock()
with patch("evennia.accounts.accounts._MULTISESSION_MODE", 2): with patch("evennia.accounts.accounts._MULTISESSION_MODE", 2):
self.account.puppet_object(self.session, self.char1) self.account.puppet_object(self.session, self.char1)
self.account.msg.assert_called_with("You are already puppeting this object.") self.account.msg.assert_called_with(
"You are already puppeting this object."
)
@patch("evennia.accounts.accounts.time.time", return_value=10000) @patch("evennia.accounts.accounts.time.time", return_value=10000)
def test_idle_time(self, mock_time): def test_idle_time(self, mock_time):
@ -432,8 +450,15 @@ class TestDefaultAccountEv(EvenniaTest):
"test@test.com", "test@test.com",
"testpassword123", "testpassword123",
locks="test:all()", locks="test:all()",
tags=[("tag1", "category1"), ("tag2", "category2", "data1"), ("tag3", None)], tags=[
attributes=[("key1", "value1", "category1", "edit:false()", True), ("key2", "value2")], ("tag1", "category1"),
("tag2", "category2", "data1"),
("tag3", None),
],
attributes=[
("key1", "value1", "category1", "edit:false()", True),
("key2", "value2"),
],
) )
acct.save() acct.save()
self.assertTrue(acct.pk) self.assertTrue(acct.pk)

View file

@ -82,7 +82,9 @@ CMD_CHANNEL = "__send_to_channel_command"
CMD_LOGINSTART = "__unloggedin_look_command" CMD_LOGINSTART = "__unloggedin_look_command"
# Function for handling multiple command matches. # Function for handling multiple command matches.
_SEARCH_AT_RESULT = utils.variable_from_module(*settings.SEARCH_AT_RESULT.rsplit(".", 1)) _SEARCH_AT_RESULT = utils.variable_from_module(
*settings.SEARCH_AT_RESULT.rsplit(".", 1)
)
# Output strings. The first is the IN_GAME_ERRORS return, the second # Output strings. The first is the IN_GAME_ERRORS return, the second
# is the normal "production message to echo to the account. # is the normal "production message to echo to the account.
@ -132,7 +134,8 @@ likely file a bug report with the Evennia project.
) )
_ERROR_RECURSION_LIMIT = ( _ERROR_RECURSION_LIMIT = (
"Command recursion limit ({recursion_limit}) " "reached for '{raw_cmdname}' ({cmdclass})." "Command recursion limit ({recursion_limit}) "
"reached for '{raw_cmdname}' ({cmdclass})."
) )
@ -161,7 +164,9 @@ def _msg_err(receiver, stringtuple):
if _IN_GAME_ERRORS: if _IN_GAME_ERRORS:
receiver.msg( receiver.msg(
string.format( string.format(
traceback=tracestring, errmsg=stringtuple[0].strip(), timestamp=timestamp traceback=tracestring,
errmsg=stringtuple[0].strip(),
timestamp=timestamp,
).strip() ).strip()
) )
else: else:
@ -213,7 +218,9 @@ def _progressive_cmd_run(cmd, generator, response=None):
elif isinstance(value, str): elif isinstance(value, str):
_GET_INPUT(cmd.caller, value, _process_input, cmd=cmd, generator=generator) _GET_INPUT(cmd.caller, value, _process_input, cmd=cmd, generator=generator)
else: else:
raise ValueError("unknown type for a yielded value in command: {}".format(type(value))) raise ValueError(
"unknown type for a yielded value in command: {}".format(type(value))
)
def _process_input(caller, prompt, result, cmd, generator): def _process_input(caller, prompt, result, cmd, generator):
@ -324,7 +331,9 @@ def get_and_merge_cmdsets(caller, session, account, obj, callertype, raw_string)
# Gather all cmdsets stored on objects in the room and # Gather all cmdsets stored on objects in the room and
# also in the caller's inventory and the location itself # also in the caller's inventory and the location itself
local_objlist = yield ( local_objlist = yield (
location.contents_get(exclude=obj) + obj.contents_get() + [location] location.contents_get(exclude=obj)
+ obj.contents_get()
+ [location]
) )
local_objlist = [o for o in local_objlist if not o._is_deleted] local_objlist = [o for o in local_objlist if not o._is_deleted]
for lobj in local_objlist: for lobj in local_objlist:
@ -354,7 +363,9 @@ def get_and_merge_cmdsets(caller, session, account, obj, callertype, raw_string)
# only keep the setting if duplicates were set to False/True # only keep the setting if duplicates were set to False/True
# explicitly. # explicitly.
cset.old_duplicates = cset.duplicates cset.old_duplicates = cset.duplicates
cset.duplicates = True if cset.duplicates is None else cset.duplicates cset.duplicates = (
True if cset.duplicates is None else cset.duplicates
)
returnValue(local_obj_cmdsets) returnValue(local_obj_cmdsets)
except Exception: except Exception:
_msg_err(caller, _ERROR_CMDSETS) _msg_err(caller, _ERROR_CMDSETS)
@ -394,7 +405,9 @@ def get_and_merge_cmdsets(caller, session, account, obj, callertype, raw_string)
if current.no_exits: if current.no_exits:
# filter out all exits # filter out all exits
local_obj_cmdsets = [ local_obj_cmdsets = [
cmdset for cmdset in local_obj_cmdsets if cmdset.key != "ExitCmdSet" cmdset
for cmdset in local_obj_cmdsets
if cmdset.key != "ExitCmdSet"
] ]
cmdsets += local_obj_cmdsets cmdsets += local_obj_cmdsets
if not current.no_channels: if not current.no_channels:
@ -418,7 +431,9 @@ def get_and_merge_cmdsets(caller, session, account, obj, callertype, raw_string)
if current.no_exits: if current.no_exits:
# filter out all exits # filter out all exits
local_obj_cmdsets = [ local_obj_cmdsets = [
cmdset for cmdset in local_obj_cmdsets if cmdset.key != "ExitCmdSet" cmdset
for cmdset in local_obj_cmdsets
if cmdset.key != "ExitCmdSet"
] ]
cmdsets += local_obj_cmdsets cmdsets += local_obj_cmdsets
if not current.no_channels: if not current.no_channels:
@ -436,20 +451,28 @@ def get_and_merge_cmdsets(caller, session, account, obj, callertype, raw_string)
if current.no_exits: if current.no_exits:
# filter out all exits # filter out all exits
local_obj_cmdsets = [ local_obj_cmdsets = [
cmdset for cmdset in local_obj_cmdsets if cmdset.key != "ExitCmdSet" cmdset
for cmdset in local_obj_cmdsets
if cmdset.key != "ExitCmdSet"
] ]
cmdsets += yield local_obj_cmdsets cmdsets += yield local_obj_cmdsets
if not current.no_channels: if not current.no_channels:
# also objs may have channels # also objs may have channels
cmdsets += yield _get_channel_cmdset(obj) cmdsets += yield _get_channel_cmdset(obj)
else: else:
raise Exception("get_and_merge_cmdsets: callertype %s is not valid." % callertype) raise Exception(
"get_and_merge_cmdsets: callertype %s is not valid." % callertype
)
# weed out all non-found sets # weed out all non-found sets
cmdsets = yield [cmdset for cmdset in cmdsets if cmdset and cmdset.key != "_EMPTY_CMDSET"] cmdsets = yield [
cmdset for cmdset in cmdsets if cmdset and cmdset.key != "_EMPTY_CMDSET"
]
# report cmdset errors to user (these should already have been logged) # report cmdset errors to user (these should already have been logged)
yield [ yield [
report_to.msg(cmdset.errmessage) for cmdset in cmdsets if cmdset.key == "_CMDSET_ERROR" report_to.msg(cmdset.errmessage)
for cmdset in cmdsets
if cmdset.key == "_CMDSET_ERROR"
] ]
if cmdsets: if cmdsets:
@ -472,7 +495,9 @@ def get_and_merge_cmdsets(caller, session, account, obj, callertype, raw_string)
tempmergers[prio] = cmdset tempmergers[prio] = cmdset
# sort cmdsets after reverse priority (highest prio are merged in last) # sort cmdsets after reverse priority (highest prio are merged in last)
cmdsets = yield sorted(list(tempmergers.values()), key=lambda x: x.priority) cmdsets = yield sorted(
list(tempmergers.values()), key=lambda x: x.priority
)
# Merge all command sets into one, beginning with the lowest-prio one # Merge all command sets into one, beginning with the lowest-prio one
cmdset = cmdsets[0] cmdset = cmdsets[0]
@ -733,7 +758,12 @@ def cmdhandler(
if len(matches) == 1: if len(matches) == 1:
# We have a unique command match. But it may still be invalid. # We have a unique command match. But it may still be invalid.
match = matches[0] match = matches[0]
cmdname, args, cmd, raw_cmdname = match[0], match[1], match[2], match[5] cmdname, args, cmd, raw_cmdname = (
match[0],
match[1],
match[2],
match[5],
)
if not matches: if not matches:
# No commands match our entered command # No commands match our entered command
@ -771,7 +801,9 @@ def cmdhandler(
raise ExecSystemCommand(cmd, sysarg) raise ExecSystemCommand(cmd, sysarg)
# A normal command. # A normal command.
ret = yield _run_command(cmd, cmdname, args, raw_cmdname, cmdset, session, account) ret = yield _run_command(
cmd, cmdname, args, raw_cmdname, cmdset, session, account
)
returnValue(ret) returnValue(ret)
except ErrorReported as exc: except ErrorReported as exc:
@ -787,7 +819,13 @@ def cmdhandler(
if syscmd: if syscmd:
ret = yield _run_command( ret = yield _run_command(
syscmd, syscmd.key, sysarg, unformatted_raw_string, cmdset, session, account syscmd,
syscmd.key,
sysarg,
unformatted_raw_string,
cmdset,
session,
account,
) )
returnValue(ret) returnValue(ret)
elif sysarg: elif sysarg:

View file

@ -71,13 +71,18 @@ def build_matches(raw_string, cmdset, include_prefixes=False):
for cmdname in [cmd.key] + cmd.aliases for cmdname in [cmd.key] + cmd.aliases
if cmdname if cmdname
and l_raw_string.startswith(cmdname.lower()) and l_raw_string.startswith(cmdname.lower())
and (not cmd.arg_regex or cmd.arg_regex.match(l_raw_string[len(cmdname) :])) and (
not cmd.arg_regex
or cmd.arg_regex.match(l_raw_string[len(cmdname) :])
)
] ]
) )
else: else:
# strip prefixes set in settings # strip prefixes set in settings
raw_string = ( raw_string = (
raw_string.lstrip(_CMD_IGNORE_PREFIXES) if len(raw_string) > 1 else raw_string raw_string.lstrip(_CMD_IGNORE_PREFIXES)
if len(raw_string) > 1
else raw_string
) )
l_raw_string = raw_string.lower() l_raw_string = raw_string.lower()
for cmd in cmdset: for cmd in cmdset:
@ -90,9 +95,14 @@ def build_matches(raw_string, cmdset, include_prefixes=False):
if ( if (
cmdname cmdname
and l_raw_string.startswith(cmdname.lower()) and l_raw_string.startswith(cmdname.lower())
and (not cmd.arg_regex or cmd.arg_regex.match(l_raw_string[len(cmdname) :])) and (
not cmd.arg_regex
or cmd.arg_regex.match(l_raw_string[len(cmdname) :])
)
): ):
matches.append(create_match(cmdname, raw_string, cmd, raw_cmdname)) matches.append(
create_match(cmdname, raw_string, cmd, raw_cmdname)
)
except Exception: except Exception:
log_trace("cmdhandler error. raw_input:%s" % raw_string) log_trace("cmdhandler error. raw_input:%s" % raw_string)
return matches return matches
@ -125,7 +135,10 @@ def try_num_prefixes(raw_string):
# the user might be trying to identify the command # the user might be trying to identify the command
# with a #num-command style syntax. We expect the regex to # with a #num-command style syntax. We expect the regex to
# contain the groups "number" and "name". # contain the groups "number" and "name".
mindex, new_raw_string = num_ref_match.group("number"), num_ref_match.group("name") mindex, new_raw_string = (
num_ref_match.group("number"),
num_ref_match.group("name"),
)
return mindex, new_raw_string return mindex, new_raw_string
else: else:
return None, None return None, None
@ -180,7 +193,9 @@ def cmdparser(raw_string, cmdset, caller, match_index=None):
if _CMD_IGNORE_PREFIXES: if _CMD_IGNORE_PREFIXES:
# still no match. Try to strip prefixes # still no match. Try to strip prefixes
raw_string = ( raw_string = (
raw_string.lstrip(_CMD_IGNORE_PREFIXES) if len(raw_string) > 1 else raw_string raw_string.lstrip(_CMD_IGNORE_PREFIXES)
if len(raw_string) > 1
else raw_string
) )
matches = build_matches(raw_string, cmdset, include_prefixes=False) matches = build_matches(raw_string, cmdset, include_prefixes=False)

View file

@ -334,7 +334,9 @@ class CmdSet(object, metaclass=_CmdSetMeta):
commands (str): Representation of commands in Cmdset. commands (str): Representation of commands in Cmdset.
""" """
return ", ".join([str(cmd) for cmd in sorted(self.commands, key=lambda o: o.key)]) return ", ".join(
[str(cmd) for cmd in sorted(self.commands, key=lambda o: o.key)]
)
def __iter__(self): def __iter__(self):
""" """
@ -403,10 +405,16 @@ class CmdSet(object, metaclass=_CmdSetMeta):
# set changes the setting (i.e. has a non-None value). We don't pass through # set changes the setting (i.e. has a non-None value). We don't pass through
# the duplicates setting; that is per-merge # the duplicates setting; that is per-merge
cmdset_c.no_channels = ( cmdset_c.no_channels = (
self.no_channels if cmdset_a.no_channels is None else cmdset_a.no_channels self.no_channels
if cmdset_a.no_channels is None
else cmdset_a.no_channels
)
cmdset_c.no_exits = (
self.no_exits if cmdset_a.no_exits is None else cmdset_a.no_exits
)
cmdset_c.no_objs = (
self.no_objs if cmdset_a.no_objs is None else cmdset_a.no_objs
) )
cmdset_c.no_exits = self.no_exits if cmdset_a.no_exits is None else cmdset_a.no_exits
cmdset_c.no_objs = self.no_objs if cmdset_a.no_objs is None else cmdset_a.no_objs
else: else:
# B higher priority than A # B higher priority than A
@ -432,8 +440,12 @@ class CmdSet(object, metaclass=_CmdSetMeta):
cmdset_c.no_channels = ( cmdset_c.no_channels = (
cmdset_a.no_channels if self.no_channels is None else self.no_channels cmdset_a.no_channels if self.no_channels is None else self.no_channels
) )
cmdset_c.no_exits = cmdset_a.no_exits if self.no_exits is None else self.no_exits cmdset_c.no_exits = (
cmdset_c.no_objs = cmdset_a.no_objs if self.no_objs is None else self.no_objs cmdset_a.no_exits if self.no_exits is None else self.no_exits
)
cmdset_c.no_objs = (
cmdset_a.no_objs if self.no_objs is None else self.no_objs
)
# we store actual_mergetype since key_mergetypes # we store actual_mergetype since key_mergetypes
# might be different from the main mergetype. # might be different from the main mergetype.
@ -617,7 +629,11 @@ class CmdSet(object, metaclass=_CmdSetMeta):
""" """
names = [] names = []
if caller: if caller:
[names.extend(cmd._keyaliases) for cmd in self.commands if cmd.access(caller)] [
names.extend(cmd._keyaliases)
for cmd in self.commands
if cmd.access(caller)
]
else: else:
[names.extend(cmd._keyaliases) for cmd in self.commands] [names.extend(cmd._keyaliases) for cmd in self.commands]
return names return names

View file

@ -114,7 +114,9 @@ Replacing with fallback '{fallback_path}'.
""" """
) )
_ERROR_CMDSET_NO_FALLBACK = _("""Fallback path '{fallback_path}' failed to generate a cmdset.""") _ERROR_CMDSET_NO_FALLBACK = _(
"""Fallback path '{fallback_path}' failed to generate a cmdset."""
)
class _ErrorCmdSet(CmdSet): class _ErrorCmdSet(CmdSet):
@ -160,7 +162,9 @@ def import_cmdset(path, cmdsetobj, emit_to_obj=None, no_logging=False):
""" """
python_paths = [path] + [ python_paths = [path] + [
"%s.%s" % (prefix, path) for prefix in _CMDSET_PATHS if not path.startswith(prefix) "%s.%s" % (prefix, path)
for prefix in _CMDSET_PATHS
if not path.startswith(prefix)
] ]
errstring = "" errstring = ""
for python_path in python_paths: for python_path in python_paths:
@ -168,7 +172,9 @@ def import_cmdset(path, cmdsetobj, emit_to_obj=None, no_logging=False):
if "." in path: if "." in path:
modpath, classname = python_path.rsplit(".", 1) modpath, classname = python_path.rsplit(".", 1)
else: else:
raise ImportError("The path '%s' is not on the form modulepath.ClassName" % path) raise ImportError(
"The path '%s' is not on the form modulepath.ClassName" % path
)
try: try:
# first try to get from cache # first try to get from cache
@ -207,7 +213,9 @@ def import_cmdset(path, cmdsetobj, emit_to_obj=None, no_logging=False):
errstring += _ERROR_CMDSET_IMPORT errstring += _ERROR_CMDSET_IMPORT
if _IN_GAME_ERRORS: if _IN_GAME_ERRORS:
errstring = errstring.format( errstring = errstring.format(
path=python_path, traceback=format_exc(), timestamp=logger.timeformat() path=python_path,
traceback=format_exc(),
timestamp=logger.timeformat(),
) )
else: else:
errstring = errstring.format( errstring = errstring.format(
@ -226,7 +234,9 @@ def import_cmdset(path, cmdsetobj, emit_to_obj=None, no_logging=False):
errstring += _ERROR_CMDSET_SYNTAXERROR errstring += _ERROR_CMDSET_SYNTAXERROR
if _IN_GAME_ERRORS: if _IN_GAME_ERRORS:
errstring = errstring.format( errstring = errstring.format(
path=python_path, traceback=format_exc(), timestamp=logger.timeformat() path=python_path,
traceback=format_exc(),
timestamp=logger.timeformat(),
) )
else: else:
errstring = errstring.format( errstring = errstring.format(
@ -238,7 +248,9 @@ def import_cmdset(path, cmdsetobj, emit_to_obj=None, no_logging=False):
errstring += _ERROR_CMDSET_EXCEPTION errstring += _ERROR_CMDSET_EXCEPTION
if _IN_GAME_ERRORS: if _IN_GAME_ERRORS:
errstring = errstring.format( errstring = errstring.format(
path=python_path, traceback=format_exc(), timestamp=logger.timeformat() path=python_path,
traceback=format_exc(),
timestamp=logger.timeformat(),
) )
else: else:
errstring = errstring.format( errstring = errstring.format(
@ -347,13 +359,17 @@ class CmdSetHandler(object):
permstring = "non-perm" permstring = "non-perm"
if self.current.permanent: if self.current.permanent:
permstring = "perm" permstring = "perm"
tmpstring = _(" <{key} ({mergetype}, prio {prio}, {permstring})>:\n {keylist}") tmpstring = _(
" <{key} ({mergetype}, prio {prio}, {permstring})>:\n {keylist}"
)
string += tmpstring.format( string += tmpstring.format(
key=self.current.key, key=self.current.key,
mergetype=mergetype, mergetype=mergetype,
prio=self.current.priority, prio=self.current.priority,
permstring=permstring, permstring=permstring,
keylist=", ".join(cmd.key for cmd in sorted(self.current, key=lambda o: o.key)), keylist=", ".join(
cmd.key for cmd in sorted(self.current, key=lambda o: o.key)
),
) )
return string.strip() return string.strip()
@ -491,7 +507,9 @@ class CmdSetHandler(object):
permanent (bool, optional): The new Cmdset should survive a server reboot. permanent (bool, optional): The new Cmdset should survive a server reboot.
""" """
self.add(cmdset, emit_to_obj=emit_to_obj, permanent=permanent, default_cmdset=True) self.add(
cmdset, emit_to_obj=emit_to_obj, permanent=permanent, default_cmdset=True
)
def remove(self, cmdset=None, default_cmdset=False): def remove(self, cmdset=None, default_cmdset=False):
""" """
@ -535,7 +553,9 @@ class CmdSetHandler(object):
else: else:
# try it as a callable # try it as a callable
if callable(cmdset) and hasattr(cmdset, "path"): if callable(cmdset) and hasattr(cmdset, "path"):
delcmdsets = [cset for cset in self.cmdset_stack[1:] if cset.path == cmdset.path] delcmdsets = [
cset for cset in self.cmdset_stack[1:] if cset.path == cmdset.path
]
else: else:
# try it as a path or key # try it as a path or key
delcmdsets = [ delcmdsets = [
@ -627,12 +647,15 @@ class CmdSetHandler(object):
if must_be_default: if must_be_default:
return self.cmdset_stack and (self.cmdset_stack[0].path == cmdset.path) return self.cmdset_stack and (self.cmdset_stack[0].path == cmdset.path)
else: else:
return any([cset for cset in self.cmdset_stack if cset.path == cmdset.path]) return any(
[cset for cset in self.cmdset_stack if cset.path == cmdset.path]
)
else: else:
# try it as a path or key # try it as a path or key
if must_be_default: if must_be_default:
return self.cmdset_stack and ( return self.cmdset_stack and (
self.cmdset_stack[0].key == cmdset or self.cmdset_stack[0].path == cmdset self.cmdset_stack[0].key == cmdset
or self.cmdset_stack[0].path == cmdset
) )
else: else:
return any( return any(

View file

@ -37,10 +37,14 @@ def _init_command(cls, **kwargs):
cls.key = cls.key.lower() cls.key = cls.key.lower()
if cls.aliases and not is_iter(cls.aliases): if cls.aliases and not is_iter(cls.aliases):
try: try:
cls.aliases = [str(alias).strip().lower() for alias in cls.aliases.split(",")] cls.aliases = [
str(alias).strip().lower() for alias in cls.aliases.split(",")
]
except Exception: except Exception:
cls.aliases = [] cls.aliases = []
cls.aliases = list(set(alias for alias in cls.aliases if alias and alias != cls.key)) cls.aliases = list(
set(alias for alias in cls.aliases if alias and alias != cls.key)
)
# optimization - a set is much faster to match against than a list # optimization - a set is much faster to match against than a list
cls._matchset = set([cls.key] + cls.aliases) cls._matchset = set([cls.key] + cls.aliases)
@ -410,7 +414,8 @@ class Command(object, metaclass=CommandMeta):
""" """
variables = "\n".join( variables = "\n".join(
" |w{}|n ({}): {}".format(key, type(val), val) for key, val in self.__dict__.items() " |w{}|n ({}): {}".format(key, type(val), val)
for key, val in self.__dict__.items()
) )
string = f""" string = f"""
Command {self} has no defined `func()` - showing on-command variables: Command {self} has no defined `func()` - showing on-command variables:
@ -426,7 +431,10 @@ Command {self} has no defined `func()` - showing on-command variables:
string += "\nname of cmd (self.key): |w%s|n\n" % self.key string += "\nname of cmd (self.key): |w%s|n\n" % self.key
string += "cmd aliases (self.aliases): |w%s|n\n" % self.aliases string += "cmd aliases (self.aliases): |w%s|n\n" % self.aliases
string += "cmd locks (self.locks): |w%s|n\n" % self.locks string += "cmd locks (self.locks): |w%s|n\n" % self.locks
string += "help category (self.help_category): |w%s|n\n" % self.help_category.capitalize() string += (
"help category (self.help_category): |w%s|n\n"
% self.help_category.capitalize()
)
string += "object calling (self.caller): |w%s|n\n" % self.caller string += "object calling (self.caller): |w%s|n\n" % self.caller
string += "object storing cmdset (self.obj): |w%s|n\n" % self.obj string += "object storing cmdset (self.obj): |w%s|n\n" % self.obj
string += "command string given (self.cmdstring): |w%s|n\n" % self.cmdstring string += "command string given (self.cmdstring): |w%s|n\n" % self.cmdstring
@ -577,15 +585,21 @@ Command {self} has no defined `func()` - showing on-command variables:
if header_text: if header_text:
if color_header: if color_header:
header_text = ANSIString(header_text).clean() header_text = ANSIString(header_text).clean()
header_text = ANSIString("|n|%s%s|n" % (colors["headertext"], header_text)) header_text = ANSIString(
"|n|%s%s|n" % (colors["headertext"], header_text)
)
if mode == "header": if mode == "header":
begin_center = ANSIString( begin_center = ANSIString(
"|n|%s<|%s* |n" % (colors["border"], colors["headerstar"]) "|n|%s<|%s* |n" % (colors["border"], colors["headerstar"])
) )
end_center = ANSIString("|n |%s*|%s>|n" % (colors["headerstar"], colors["border"])) end_center = ANSIString(
"|n |%s*|%s>|n" % (colors["headerstar"], colors["border"])
)
center_string = ANSIString(begin_center + header_text + end_center) center_string = ANSIString(begin_center + header_text + end_center)
else: else:
center_string = ANSIString("|n |%s%s |n" % (colors["headertext"], header_text)) center_string = ANSIString(
"|n |%s%s |n" % (colors["headertext"], header_text)
)
else: else:
center_string = "" center_string = ""
@ -599,14 +613,22 @@ Command {self} has no defined `func()` - showing on-command variables:
right_width = math.floor(remain_fill / 2) right_width = math.floor(remain_fill / 2)
left_width = math.ceil(remain_fill / 2) left_width = math.ceil(remain_fill / 2)
right_fill = ANSIString("|n|%s%s|n" % (colors["border"], fill_character * int(right_width))) right_fill = ANSIString(
left_fill = ANSIString("|n|%s%s|n" % (colors["border"], fill_character * int(left_width))) "|n|%s%s|n" % (colors["border"], fill_character * int(right_width))
)
left_fill = ANSIString(
"|n|%s%s|n" % (colors["border"], fill_character * int(left_width))
)
if edge_character: if edge_character:
edge_fill = ANSIString("|n|%s%s|n" % (colors["border"], edge_character)) edge_fill = ANSIString("|n|%s%s|n" % (colors["border"], edge_character))
main_string = ANSIString(center_string) main_string = ANSIString(center_string)
final_send = ( final_send = (
ANSIString(edge_fill) + left_fill + main_string + right_fill + ANSIString(edge_fill) ANSIString(edge_fill)
+ left_fill
+ main_string
+ right_fill
+ ANSIString(edge_fill)
) )
else: else:
final_send = left_fill + ANSIString(center_string) + right_fill final_send = left_fill + ANSIString(center_string) + right_fill

View file

@ -72,9 +72,9 @@ class MuxAccountLookCommand(COMMAND_DEFAULT_CLASS):
self.account.db._playable_characters = playable self.account.db._playable_characters = playable
# store playable property # store playable property
if self.args: if self.args:
self.playable = dict((utils.to_str(char.key.lower()), char) for char in playable).get( self.playable = dict(
self.args.lower(), None (utils.to_str(char.key.lower()), char) for char in playable
) ).get(self.args.lower(), None)
else: else:
self.playable = playable self.playable = playable
@ -113,7 +113,9 @@ class CmdOOCLook(MuxAccountLookCommand):
if _MULTISESSION_MODE < 2: if _MULTISESSION_MODE < 2:
# only one character allowed # only one character allowed
self.msg("You are out-of-character (OOC).\nUse |wic|n to get back into the game.") self.msg(
"You are out-of-character (OOC).\nUse |wic|n to get back into the game."
)
return return
# call on-account look helper method # call on-account look helper method
@ -152,7 +154,8 @@ class CmdCharCreate(COMMAND_DEFAULT_CLASS):
charmax = _MAX_NR_CHARACTERS charmax = _MAX_NR_CHARACTERS
if not account.is_superuser and ( if not account.is_superuser and (
account.db._playable_characters and len(account.db._playable_characters) >= charmax account.db._playable_characters
and len(account.db._playable_characters) >= charmax
): ):
self.msg("You may only create a maximum of %i characters." % charmax) self.msg("You may only create a maximum of %i characters." % charmax)
return return
@ -172,7 +175,11 @@ class CmdCharCreate(COMMAND_DEFAULT_CLASS):
default_home = ObjectDB.objects.get_id(settings.DEFAULT_HOME) default_home = ObjectDB.objects.get_id(settings.DEFAULT_HOME)
permissions = settings.PERMISSION_ACCOUNT_DEFAULT permissions = settings.PERMISSION_ACCOUNT_DEFAULT
new_character = create.create_object( new_character = create.create_object(
typeclass, key=key, location=start_location, home=default_home, permissions=permissions typeclass,
key=key,
location=start_location,
home=default_home,
permissions=permissions,
) )
# only allow creator (and developers) to puppet this char # only allow creator (and developers) to puppet this char
new_character.locks.add( new_character.locks.add(
@ -259,9 +266,7 @@ class CmdCharDelete(COMMAND_DEFAULT_CLASS):
self.msg("You do not have permission to delete this character.") self.msg("You do not have permission to delete this character.")
return return
prompt = ( prompt = "|rThis will permanently destroy '%s'. This cannot be undone.|n Continue yes/[no]?"
"|rThis will permanently destroy '%s'. This cannot be undone.|n Continue yes/[no]?"
)
get_input(account, prompt % match.key, _callback) get_input(account, prompt % match.key, _callback)
@ -308,7 +313,9 @@ class CmdIC(COMMAND_DEFAULT_CLASS):
if not new_character: if not new_character:
# search for a matching character # search for a matching character
new_character = [ new_character = [
char for char in search.object_search(self.args) if char.access(account, "puppet") char
for char in search.object_search(self.args)
if char.access(account, "puppet")
] ]
if not new_character: if not new_character:
self.msg("That is not a valid character choice.") self.msg("That is not a valid character choice.")
@ -379,7 +386,9 @@ class CmdOOC(MuxAccountLookCommand):
if _MULTISESSION_MODE < 2: if _MULTISESSION_MODE < 2:
# only one character allowed # only one character allowed
self.msg("You are out-of-character (OOC).\nUse |wic|n to get back into the game.") self.msg(
"You are out-of-character (OOC).\nUse |wic|n to get back into the game."
)
return return
self.msg(account.at_look(target=self.playable, session=session)) self.msg(account.at_look(target=self.playable, session=session))
@ -457,9 +466,9 @@ class CmdWho(COMMAND_DEFAULT_CLASS):
if self.cmdstring == "doing": if self.cmdstring == "doing":
show_session_data = False show_session_data = False
else: else:
show_session_data = account.check_permstring("Developer") or account.check_permstring( show_session_data = account.check_permstring(
"Admins" "Developer"
) ) or account.check_permstring("Admins")
naccounts = SESSIONS.account_count() naccounts = SESSIONS.account_count()
if show_session_data: if show_session_data:
@ -486,11 +495,15 @@ class CmdWho(COMMAND_DEFAULT_CLASS):
utils.crop(account.get_display_name(account), width=25), utils.crop(account.get_display_name(account), width=25),
utils.time_format(delta_conn, 0), utils.time_format(delta_conn, 0),
utils.time_format(delta_cmd, 1), utils.time_format(delta_cmd, 1),
utils.crop(puppet.get_display_name(account) if puppet else "None", width=25), utils.crop(
puppet.get_display_name(account) if puppet else "None", width=25
),
utils.crop(location, width=25), utils.crop(location, width=25),
session.cmd_total, session.cmd_total,
session.protocol_key, session.protocol_key,
isinstance(session.address, tuple) and session.address[0] or session.address, isinstance(session.address, tuple)
and session.address[0]
or session.address,
) )
else: else:
# unprivileged # unprivileged
@ -562,7 +575,9 @@ class CmdOption(COMMAND_DEFAULT_CLASS):
self.msg("|gCleared all saved options.") self.msg("|gCleared all saved options.")
options = dict(flags) # make a copy of the flag dict options = dict(flags) # make a copy of the flag dict
saved_options = dict(self.caller.attributes.get("_saved_protocol_flags", default={})) saved_options = dict(
self.caller.attributes.get("_saved_protocol_flags", default={})
)
if "SCREENWIDTH" in options: if "SCREENWIDTH" in options:
if len(options["SCREENWIDTH"]) == 1: if len(options["SCREENWIDTH"]) == 1:
@ -589,11 +604,15 @@ class CmdOption(COMMAND_DEFAULT_CLASS):
if saved_options: if saved_options:
saved = " |YYes|n" if key in saved_options else "" saved = " |YYes|n" if key in saved_options else ""
changed = ( changed = (
"|y*|n" if key in saved_options and flags[key] != saved_options[key] else "" "|y*|n"
if key in saved_options and flags[key] != saved_options[key]
else ""
) )
row.append("%s%s" % (saved, changed)) row.append("%s%s" % (saved, changed))
table.add_row(*row) table.add_row(*row)
self.msg("|wClient settings (%s):|n\n%s|n" % (self.session.protocol_key, table)) self.msg(
"|wClient settings (%s):|n\n%s|n" % (self.session.protocol_key, table)
)
return return
@ -623,7 +642,9 @@ class CmdOption(COMMAND_DEFAULT_CLASS):
old_val = flags.get(new_name, False) old_val = flags.get(new_name, False)
new_val = validator(new_val) new_val = validator(new_val)
if old_val == new_val: if old_val == new_val:
self.msg("Option |w%s|n was kept as '|w%s|n'." % (new_name, old_val)) self.msg(
"Option |w%s|n was kept as '|w%s|n'." % (new_name, old_val)
)
else: else:
flags[new_name] = new_val flags[new_name] = new_val
self.msg( self.msg(
@ -667,7 +688,9 @@ class CmdOption(COMMAND_DEFAULT_CLASS):
# a valid setting # a valid setting
if "save" in self.switches: if "save" in self.switches:
# save this option only # save this option only
saved_options = self.account.attributes.get("_saved_protocol_flags", default={}) saved_options = self.account.attributes.get(
"_saved_protocol_flags", default={}
)
saved_options.update(optiondict) saved_options.update(optiondict)
self.account.attributes.add("_saved_protocol_flags", saved_options) self.account.attributes.add("_saved_protocol_flags", saved_options)
for key in optiondict: for key in optiondict:
@ -675,7 +698,9 @@ class CmdOption(COMMAND_DEFAULT_CLASS):
if "clear" in self.switches: if "clear" in self.switches:
# clear this save # clear this save
for key in optiondict: for key in optiondict:
self.account.attributes.get("_saved_protocol_flags", {}).pop(key, None) self.account.attributes.get("_saved_protocol_flags", {}).pop(
key, None
)
self.msg("|gCleared saved %s." % key) self.msg("|gCleared saved %s." % key)
self.session.update_flags(**optiondict) self.session.update_flags(**optiondict)
@ -752,7 +777,8 @@ class CmdQuit(COMMAND_DEFAULT_CLASS):
if "all" in self.switches: if "all" in self.switches:
account.msg( account.msg(
"|RQuitting|n all sessions. Hope to see you soon again.", session=self.session "|RQuitting|n all sessions. Hope to see you soon again.",
session=self.session,
) )
reason = "quit/all" reason = "quit/all"
for session in account.sessions.all(): for session in account.sessions.all():
@ -761,7 +787,10 @@ class CmdQuit(COMMAND_DEFAULT_CLASS):
nsess = len(account.sessions.all()) nsess = len(account.sessions.all())
reason = "quit" reason = "quit"
if nsess == 2: if nsess == 2:
account.msg("|RQuitting|n. One session is still connected.", session=self.session) account.msg(
"|RQuitting|n. One session is still connected.",
session=self.session,
)
elif nsess > 2: elif nsess > 2:
account.msg( account.msg(
"|RQuitting|n. %i sessions are still connected." % (nsess - 1), "|RQuitting|n. %i sessions are still connected." % (nsess - 1),
@ -769,7 +798,9 @@ class CmdQuit(COMMAND_DEFAULT_CLASS):
) )
else: else:
# we are quitting the last available session # we are quitting the last available session
account.msg("|RQuitting|n. Hope to see you again, soon.", session=self.session) account.msg(
"|RQuitting|n. Hope to see you again, soon.", session=self.session
)
account.disconnect_session_from_account(self.session, reason) account.disconnect_session_from_account(self.session, reason)
@ -841,11 +872,13 @@ class CmdColorTest(COMMAND_DEFAULT_CLASS):
for code, _ in ap.ansi_map[self.slice_dark_fg] for code, _ in ap.ansi_map[self.slice_dark_fg]
] ]
dark_bg = [ dark_bg = [
"%s%s|n" % (code.replace("\\", ""), code.replace("|", "||").replace("\\", "")) "%s%s|n"
% (code.replace("\\", ""), code.replace("|", "||").replace("\\", ""))
for code, _ in ap.ansi_map[self.slice_dark_bg] for code, _ in ap.ansi_map[self.slice_dark_bg]
] ]
bright_bg = [ bright_bg = [
"%s%s|n" % (code.replace("\\", ""), code.replace("|", "||").replace("\\", "")) "%s%s|n"
% (code.replace("\\", ""), code.replace("|", "||").replace("\\", ""))
for code, _ in ap.ansi_xterm256_bright_bg_map[self.slice_bright_bg] for code, _ in ap.ansi_xterm256_bright_bg_map[self.slice_bright_bg]
] ]
dark_fg.extend(["" for _ in range(len(bright_fg) - len(dark_fg))]) dark_fg.extend(["" for _ in range(len(bright_fg) - len(dark_fg))])
@ -867,11 +900,21 @@ class CmdColorTest(COMMAND_DEFAULT_CLASS):
for ig in range(6): for ig in range(6):
for ib in range(6): for ib in range(6):
# foreground table # foreground table
table[ir].append("|%i%i%i%s|n" % (ir, ig, ib, "||%i%i%i" % (ir, ig, ib))) table[ir].append(
"|%i%i%i%s|n" % (ir, ig, ib, "||%i%i%i" % (ir, ig, ib))
)
# background table # background table
table[6 + ir].append( table[6 + ir].append(
"|%i%i%i|[%i%i%i%s|n" "|%i%i%i|[%i%i%i%s|n"
% (5 - ir, 5 - ig, 5 - ib, ir, ig, ib, "||[%i%i%i" % (ir, ig, ib)) % (
5 - ir,
5 - ig,
5 - ib,
ir,
ig,
ib,
"||[%i%i%i" % (ir, ig, ib),
)
) )
table = self.table_format(table) table = self.table_format(table)
string = "Xterm256 colors (if not all hues show, your client might not report that it can handle xterm256):" string = "Xterm256 colors (if not all hues show, your client might not report that it can handle xterm256):"
@ -882,7 +925,9 @@ class CmdColorTest(COMMAND_DEFAULT_CLASS):
letter = chr(97 + (ibatch * 6 + igray)) letter = chr(97 + (ibatch * 6 + igray))
inverse = chr(122 - (ibatch * 6 + igray)) inverse = chr(122 - (ibatch * 6 + igray))
table[0 + igray].append("|=%s%s |n" % (letter, "||=%s" % letter)) table[0 + igray].append("|=%s%s |n" % (letter, "||=%s" % letter))
table[6 + igray].append("|=%s|[=%s%s |n" % (inverse, letter, "||[=%s" % letter)) table[6 + igray].append(
"|=%s|[=%s%s |n" % (inverse, letter, "||[=%s" % letter)
)
for igray in range(6): for igray in range(6):
# the last row (y, z) has empty columns # the last row (y, z) has empty columns
if igray < 2: if igray < 2:
@ -968,7 +1013,10 @@ class CmdQuell(COMMAND_DEFAULT_CLASS):
cpermstr += "\nUse unquell to return to normal permission usage." cpermstr += "\nUse unquell to return to normal permission usage."
self.msg(cpermstr) self.msg(cpermstr)
else: else:
self.msg("Quelling Account permissions%s. Use unquell to get them back." % permstr) self.msg(
"Quelling Account permissions%s. Use unquell to get them back."
% permstr
)
self._recache_locks(account) self._recache_locks(account)
@ -999,7 +1047,10 @@ class CmdStyle(COMMAND_DEFAULT_CLASS):
for op_key in self.account.options.options_dict.keys(): for op_key in self.account.options.options_dict.keys():
op_found = self.account.options.get(op_key, return_obj=True) op_found = self.account.options.get(op_key, return_obj=True)
table.add_row( table.add_row(
op_key, op_found.description, op_found.__class__.__name__, op_found.display() op_key,
op_found.description,
op_found.__class__.__name__,
op_found.display(),
) )
self.msg(str(table)) self.msg(str(table))

View file

@ -89,7 +89,9 @@ class CmdBoot(COMMAND_DEFAULT_CLASS):
boot_list.append(match) boot_list.append(match)
if not boot_list: if not boot_list:
caller.msg("No matching sessions found. The Account does not seem to be online.") caller.msg(
"No matching sessions found. The Account does not seem to be online."
)
return return
# Carry out the booting of the sessions in the boot list. # Carry out the booting of the sessions in the boot list.
@ -190,7 +192,8 @@ class CmdBan(COMMAND_DEFAULT_CLASS):
banlist = [] banlist = []
if not self.args or ( if not self.args or (
self.switches and not any(switch in ("ip", "name") for switch in self.switches) self.switches
and not any(switch in ("ip", "name") for switch in self.switches)
): ):
self.caller.msg(list_bans(self, banlist)) self.caller.msg(list_bans(self, banlist))
return return
@ -399,9 +402,12 @@ class CmdNewPassword(COMMAND_DEFAULT_CLASS):
account.save() account.save()
self.msg("%s - new password set to '%s'." % (account.name, newpass)) self.msg("%s - new password set to '%s'." % (account.name, newpass))
if account.character != caller: if account.character != caller:
account.msg("%s has changed your password to '%s'." % (caller.name, newpass)) account.msg(
"%s has changed your password to '%s'." % (caller.name, newpass)
)
logger.log_sec( logger.log_sec(
"Password Changed: %s (Caller: %s, IP: %s)." % (account, caller, self.session.address) "Password Changed: %s (Caller: %s, IP: %s)."
% (account, caller, self.session.address)
) )
@ -486,14 +492,17 @@ class CmdPerm(COMMAND_DEFAULT_CLASS):
obj.permissions.remove(perm) obj.permissions.remove(perm)
if obj.permissions.get(perm): if obj.permissions.get(perm):
caller_result.append( caller_result.append(
"\nPermissions %s could not be removed from %s." % (perm, obj.name) "\nPermissions %s could not be removed from %s."
% (perm, obj.name)
) )
else: else:
caller_result.append( caller_result.append(
"\nPermission %s removed from %s (if they existed)." % (perm, obj.name) "\nPermission %s removed from %s (if they existed)."
% (perm, obj.name)
) )
target_result.append( target_result.append(
"\n%s revokes the permission(s) %s from you." % (caller.name, perm) "\n%s revokes the permission(s) %s from you."
% (caller.name, perm)
) )
logger.log_sec( logger.log_sec(
"Permissions Deleted: %s, %s (Caller: %s, IP: %s)." "Permissions Deleted: %s, %s (Caller: %s, IP: %s)."
@ -523,7 +532,8 @@ class CmdPerm(COMMAND_DEFAULT_CLASS):
obj.permissions.add(perm) obj.permissions.add(perm)
plystring = "the Account" if accountmode else "the Object/Character" plystring = "the Account" if accountmode else "the Object/Character"
caller_result.append( caller_result.append(
"\nPermission '%s' given to %s (%s)." % (perm, obj.name, plystring) "\nPermission '%s' given to %s (%s)."
% (perm, obj.name, plystring)
) )
target_result.append( target_result.append(
"\n%s gives you (%s, %s) the permission '%s'." "\n%s gives you (%s, %s) the permission '%s'."
@ -583,13 +593,17 @@ class CmdForce(COMMAND_DEFAULT_CLASS):
def func(self): def func(self):
"""Implements the force command""" """Implements the force command"""
if not self.lhs or not self.rhs: if not self.lhs or not self.rhs:
self.caller.msg("You must provide a target and a command string to execute.") self.caller.msg(
"You must provide a target and a command string to execute."
)
return return
targ = self.caller.search(self.lhs) targ = self.caller.search(self.lhs)
if not targ: if not targ:
return return
if not targ.access(self.caller, self.perm_used): if not targ.access(self.caller, self.perm_used):
self.caller.msg("You don't have permission to force them to execute commands.") self.caller.msg(
"You don't have permission to force them to execute commands."
)
return return
targ.execute_cmd(self.rhs) targ.execute_cmd(self.rhs)
self.caller.msg("You have forced %s to: %s" % (targ, self.rhs)) self.caller.msg("You have forced %s to: %s" % (targ, self.rhs))

View file

@ -269,7 +269,9 @@ class CmdBatchCommands(_COMMAND_DEFAULT_CLASS):
"%s'%s' could not load. You have to supply python paths " "%s'%s' could not load. You have to supply python paths "
"from one of the defined batch-file directories\n (%s)." "from one of the defined batch-file directories\n (%s)."
) )
caller.msg(string % (err, python_path, ", ".join(settings.BASE_BATCHPROCESS_PATHS))) caller.msg(
string % (err, python_path, ", ".join(settings.BASE_BATCHPROCESS_PATHS))
)
return return
if not commands: if not commands:
caller.msg("File %s seems empty of valid commands." % python_path) caller.msg("File %s seems empty of valid commands." % python_path)
@ -292,7 +294,9 @@ class CmdBatchCommands(_COMMAND_DEFAULT_CLASS):
# Set interactive state directly # Set interactive state directly
caller.cmdset.add(BatchInteractiveCmdSet) caller.cmdset.add(BatchInteractiveCmdSet)
caller.msg("\nBatch-command processor - Interactive mode for %s ..." % python_path) caller.msg(
"\nBatch-command processor - Interactive mode for %s ..." % python_path
)
show_curr(caller) show_curr(caller)
else: else:
caller.msg( caller.msg(
@ -391,7 +395,9 @@ class CmdBatchCode(_COMMAND_DEFAULT_CLASS):
"%s'%s' could not load. You have to supply python paths " "%s'%s' could not load. You have to supply python paths "
"from one of the defined batch-file directories\n (%s)." "from one of the defined batch-file directories\n (%s)."
) )
caller.msg(string % (err, python_path, ", ".join(settings.BASE_BATCHPROCESS_PATHS))) caller.msg(
string % (err, python_path, ", ".join(settings.BASE_BATCHPROCESS_PATHS))
)
return return
if not codes: if not codes:
caller.msg("File %s seems empty of functional code." % python_path) caller.msg("File %s seems empty of functional code." % python_path)
@ -415,10 +421,14 @@ class CmdBatchCode(_COMMAND_DEFAULT_CLASS):
# Set interactive state directly # Set interactive state directly
caller.cmdset.add(BatchInteractiveCmdSet) caller.cmdset.add(BatchInteractiveCmdSet)
caller.msg("\nBatch-code processor - Interactive mode for %s ..." % python_path) caller.msg(
"\nBatch-code processor - Interactive mode for %s ..." % python_path
)
show_curr(caller) show_curr(caller)
else: else:
caller.msg("Running Batch-code processor - Automatic mode for %s ..." % python_path) caller.msg(
"Running Batch-code processor - Automatic mode for %s ..." % python_path
)
procpool = False procpool = False
if "PythonProcPool" in utils.server_services(): if "PythonProcPool" in utils.server_services():
@ -479,7 +489,9 @@ class CmdStateAbort(_COMMAND_DEFAULT_CLASS):
def func(self): def func(self):
"""Exit back to default.""" """Exit back to default."""
purge_processor(self.caller) purge_processor(self.caller)
self.caller.msg("Exited processor and reset out active cmdset back to the default one.") self.caller.msg(
"Exited processor and reset out active cmdset back to the default one."
)
class CmdStateLL(_COMMAND_DEFAULT_CLASS): class CmdStateLL(_COMMAND_DEFAULT_CLASS):

View file

@ -108,12 +108,20 @@ class ObjManipCommand(COMMAND_DEFAULT_CLASS):
objdef, option = [part.strip() for part in objdef.rsplit(":", 1)] objdef, option = [part.strip() for part in objdef.rsplit(":", 1)]
if ";" in objdef: if ";" in objdef:
objdef, aliases = [part.strip() for part in objdef.split(";", 1)] objdef, aliases = [part.strip() for part in objdef.split(";", 1)]
aliases = [alias.strip() for alias in aliases.split(";") if alias.strip()] aliases = [
alias.strip() for alias in aliases.split(";") if alias.strip()
]
if "/" in objdef: if "/" in objdef:
objdef, attrs = [part.strip() for part in objdef.split("/", 1)] objdef, attrs = [part.strip() for part in objdef.split("/", 1)]
attrs = [part.strip().lower() for part in attrs.split("/") if part.strip()] attrs = [
part.strip().lower()
for part in attrs.split("/")
if part.strip()
]
# store data # store data
obj_defs[iside].append({"name": objdef, "option": option, "aliases": aliases}) obj_defs[iside].append(
{"name": objdef, "option": option, "aliases": aliases}
)
obj_attrs[iside].append({"name": objdef, "attrs": attrs}) obj_attrs[iside].append({"name": objdef, "attrs": attrs})
# store for future access # store for future access
@ -177,7 +185,12 @@ class CmdSetObjAlias(COMMAND_DEFAULT_CLASS):
obj.get_display_name(caller), obj.get_display_name(caller),
", ".join( ", ".join(
"'%s'%s" "'%s'%s"
% (alias, "" if category is None else "[category:'%s']" % category) % (
alias,
""
if category is None
else "[category:'%s']" % category,
)
for (alias, category) in aliases for (alias, category) in aliases
), ),
) )
@ -218,7 +231,9 @@ class CmdSetObjAlias(COMMAND_DEFAULT_CLASS):
# merge the old and new aliases (if any) # merge the old and new aliases (if any)
old_aliases = obj.aliases.get(category=category, return_list=True) old_aliases = obj.aliases.get(category=category, return_list=True)
new_aliases = [alias.strip().lower() for alias in rhs.split(",") if alias.strip()] new_aliases = [
alias.strip().lower() for alias in rhs.split(",") if alias.strip()
]
# make the aliases only appear once # make the aliases only appear once
old_aliases.extend(new_aliases) old_aliases.extend(new_aliases)
@ -324,7 +339,10 @@ class CmdCopy(ObjManipCommand):
to_obj_aliases, to_obj_aliases,
) )
else: else:
string = "There was an error copying %s to '%s'." % (from_obj_name, to_obj_name) string = "There was an error copying %s to '%s'." % (
from_obj_name,
to_obj_name,
)
# we are done, echo to user # we are done, echo to user
caller.msg(string) caller.msg(string)
@ -547,7 +565,9 @@ class CmdCreate(ObjManipCommand):
# lockstring of newly created objects, for easy overloading. # lockstring of newly created objects, for easy overloading.
# Will be formatted with the {id} of the creating object. # Will be formatted with the {id} of the creating object.
new_obj_lockstring = "control:id({id}) or perm(Admin);delete:id({id}) or perm(Admin)" new_obj_lockstring = (
"control:id({id}) or perm(Admin);delete:id({id}) or perm(Admin)"
)
def func(self): def func(self):
""" """
@ -640,7 +660,9 @@ class CmdDesc(COMMAND_DEFAULT_CLASS):
def edit_handler(self): def edit_handler(self):
if self.rhs: if self.rhs:
self.msg("|rYou may specify a value, or use the edit switch, " "but not both.|n") self.msg(
"|rYou may specify a value, or use the edit switch, " "but not both.|n"
)
return return
if self.args: if self.args:
obj = self.caller.search(self.args) obj = self.caller.search(self.args)
@ -650,7 +672,9 @@ class CmdDesc(COMMAND_DEFAULT_CLASS):
return return
if not (obj.access(self.caller, "control") or obj.access(self.caller, "edit")): if not (obj.access(self.caller, "control") or obj.access(self.caller, "edit")):
self.caller.msg("You don't have permission to edit the description of %s." % obj.key) self.caller.msg(
"You don't have permission to edit the description of %s." % obj.key
)
self.caller.db.evmenu_target = obj self.caller.db.evmenu_target = obj
# launch the editor # launch the editor
@ -691,7 +715,9 @@ class CmdDesc(COMMAND_DEFAULT_CLASS):
obj.db.desc = desc obj.db.desc = desc
caller.msg("The description was set on %s." % obj.get_display_name(caller)) caller.msg("The description was set on %s." % obj.get_display_name(caller))
else: else:
caller.msg("You don't have permission to edit the description of %s." % obj.key) caller.msg(
"You don't have permission to edit the description of %s." % obj.key
)
class CmdDestroy(COMMAND_DEFAULT_CLASS): class CmdDestroy(COMMAND_DEFAULT_CLASS):
@ -772,9 +798,13 @@ class CmdDestroy(COMMAND_DEFAULT_CLASS):
else: else:
string += "\n%s was destroyed." % objname string += "\n%s was destroyed." % objname
if had_exits: if had_exits:
string += " Exits to and from %s were destroyed as well." % objname string += (
" Exits to and from %s were destroyed as well." % objname
)
if had_objs: if had_objs:
string += " Objects inside %s were moved to their homes." % objname string += (
" Objects inside %s were moved to their homes." % objname
)
return string return string
objs = [] objs = []
@ -784,7 +814,9 @@ class CmdDestroy(COMMAND_DEFAULT_CLASS):
if "-" in objname: if "-" in objname:
# might be a range of dbrefs # might be a range of dbrefs
dmin, dmax = [utils.dbref(part, reqhash=False) for part in objname.split("-", 1)] dmin, dmax = [
utils.dbref(part, reqhash=False) for part in objname.split("-", 1)
]
if dmin and dmax: if dmin and dmax:
for dbref in range(int(dmin), int(dmax + 1)): for dbref in range(int(dmin), int(dmax + 1)):
obj = caller.search("#" + str(dbref)) obj = caller.search("#" + str(dbref))
@ -877,7 +909,10 @@ class CmdDig(ObjManipCommand):
caller = self.caller caller = self.caller
if not self.lhs: if not self.lhs:
string = "Usage: dig[/teleport] <roomname>[;alias;alias...]" "[:parent] [= <exit_there>" string = (
"Usage: dig[/teleport] <roomname>[;alias;alias...]"
"[:parent] [= <exit_there>"
)
string += "[;alias;alias..][:parent]] " string += "[;alias;alias..][:parent]] "
string += "[, <exit_back_here>[;alias;alias..][:parent]]" string += "[, <exit_back_here>[;alias;alias..][:parent]]"
caller.msg(string) caller.msg(string)
@ -957,7 +992,9 @@ class CmdDig(ObjManipCommand):
if not back_exit["name"]: if not back_exit["name"]:
exit_back_string = "\nNo back exit created." exit_back_string = "\nNo back exit created."
elif not location: elif not location:
exit_back_string = "\nYou cannot create an exit back to a None-location." exit_back_string = (
"\nYou cannot create an exit back to a None-location."
)
else: else:
typeclass = back_exit["option"] typeclass = back_exit["option"]
if not typeclass: if not typeclass:
@ -1051,8 +1088,9 @@ class CmdTunnel(COMMAND_DEFAULT_CLASS):
exitshort = self.lhs.split(":")[0] exitshort = self.lhs.split(":")[0]
if exitshort not in self.directions: if exitshort not in self.directions:
string = "tunnel can only understand the following directions: %s." % ",".join( string = (
sorted(self.directions.keys()) "tunnel can only understand the following directions: %s."
% ",".join(sorted(self.directions.keys()))
) )
string += "\n(use dig for more freedom)" string += "\n(use dig for more freedom)"
self.caller.msg(string) self.caller.msg(string)
@ -1083,7 +1121,13 @@ class CmdTunnel(COMMAND_DEFAULT_CLASS):
backstring = ", %s;%s" % (backname, backshort) backstring = ", %s;%s" % (backname, backshort)
# build the string we will use to call dig # build the string we will use to call dig
digstring = "dig%s %s = %s;%s%s" % (telswitch, roomname, exitname, exitshort, backstring) digstring = "dig%s %s = %s;%s%s" % (
telswitch,
roomname,
exitname,
exitshort,
backstring,
)
self.execute_cmd(digstring) self.execute_cmd(digstring)
@ -1124,8 +1168,12 @@ class CmdLink(COMMAND_DEFAULT_CLASS):
# try to search locally first # try to search locally first
results = caller.search(object_name, quiet=True) results = caller.search(object_name, quiet=True)
if len(results) > 1: # local results was a multimatch. Inform them to be more specific if (
_AT_SEARCH_RESULT = variable_from_module(*settings.SEARCH_AT_RESULT.rsplit(".", 1)) len(results) > 1
): # local results was a multimatch. Inform them to be more specific
_AT_SEARCH_RESULT = variable_from_module(
*settings.SEARCH_AT_RESULT.rsplit(".", 1)
)
return _AT_SEARCH_RESULT(results, caller, query=object_name) return _AT_SEARCH_RESULT(results, caller, query=object_name)
elif len(results) == 1: # A unique local match elif len(results) == 1: # A unique local match
obj = results[0] obj = results[0]
@ -1150,9 +1198,9 @@ class CmdLink(COMMAND_DEFAULT_CLASS):
string = note % (obj.name, obj.dbref) string = note % (obj.name, obj.dbref)
if "twoway" in self.switches: if "twoway" in self.switches:
if not (target.location and obj.location): if not (target.location and obj.location):
string = "To create a two-way link, %s and %s must both have a location" % ( string = (
obj, "To create a two-way link, %s and %s must both have a location"
target, % (obj, target)
) )
string += " (i.e. they cannot be rooms, but should be exits)." string += " (i.e. they cannot be rooms, but should be exits)."
self.caller.msg(string) self.caller.msg(string)
@ -1179,7 +1227,10 @@ class CmdLink(COMMAND_DEFAULT_CLASS):
if dest: if dest:
string = "%s is an exit to %s." % (obj.name, dest.name) string = "%s is an exit to %s." % (obj.name, dest.name)
else: else:
string = "%s is not an exit. Its home location is %s." % (obj.name, obj.home) string = "%s is not an exit. Its home location is %s." % (
obj.name,
obj.home,
)
else: else:
# We gave the command link 'obj = ' which means we want to # We gave the command link 'obj = ' which means we want to
@ -1282,7 +1333,11 @@ class CmdSetHome(CmdLink):
new_home.dbref, new_home.dbref,
) )
else: else:
string = "Home location of %s was set to %s(%s)." % (obj, new_home, new_home.dbref) string = "Home location of %s was set to %s(%s)." % (
obj,
new_home,
new_home.dbref,
)
self.caller.msg(string) self.caller.msg(string)
@ -1355,8 +1410,12 @@ class CmdName(ObjManipCommand):
if not newname: if not newname:
caller.msg("No name defined!") caller.msg("No name defined!")
return return
if not (obj.access(caller, "control") or obj.access(caller, "edit")): if not (
caller.msg("You don't have right to edit this account %s." % obj) obj.access(caller, "control") or obj.access(caller, "edit")
):
caller.msg(
"You don't have right to edit this account %s." % obj
)
return return
obj.username = newname obj.username = newname
obj.save() obj.save()
@ -1411,7 +1470,9 @@ class CmdOpen(ObjManipCommand):
help_category = "Building" help_category = "Building"
# a custom member method to chug out exits and do checks # a custom member method to chug out exits and do checks
def create_exit(self, exit_name, location, destination, exit_aliases=None, typeclass=None): def create_exit(
self, exit_name, location, destination, exit_aliases=None, typeclass=None
):
""" """
Helper function to avoid code duplication. Helper function to avoid code duplication.
At this point we know destination is a valid location At this point we know destination is a valid location
@ -1432,9 +1493,7 @@ class CmdOpen(ObjManipCommand):
if not exit_obj.destination: if not exit_obj.destination:
# we are trying to link a non-exit # we are trying to link a non-exit
string = "'%s' already exists and is not an exit!\nIf you want to convert it " string = "'%s' already exists and is not an exit!\nIf you want to convert it "
string += ( string += "to an exit, you must assign an object to the 'destination' property first."
"to an exit, you must assign an object to the 'destination' property first."
)
caller.msg(string % exit_name) caller.msg(string % exit_name)
return None return None
# we are re-linking an old exit. # we are re-linking an old exit.
@ -1446,9 +1505,9 @@ class CmdOpen(ObjManipCommand):
exit_obj.destination = destination exit_obj.destination = destination
if exit_aliases: if exit_aliases:
[exit_obj.aliases.add(alias) for alias in exit_aliases] [exit_obj.aliases.add(alias) for alias in exit_aliases]
string += " Rerouted its old destination '%s' to '%s' and changed aliases." % ( string += (
old_destination.name, " Rerouted its old destination '%s' to '%s' and changed aliases."
destination.name, % (old_destination.name, destination.name)
) )
else: else:
string += " It already points to the correct place." string += " It already points to the correct place."
@ -1458,7 +1517,11 @@ class CmdOpen(ObjManipCommand):
if not typeclass: if not typeclass:
typeclass = settings.BASE_EXIT_TYPECLASS typeclass = settings.BASE_EXIT_TYPECLASS
exit_obj = create.create_object( exit_obj = create.create_object(
typeclass, key=exit_name, location=location, aliases=exit_aliases, report_to=caller typeclass,
key=exit_name,
location=location,
aliases=exit_aliases,
report_to=caller,
) )
if exit_obj: if exit_obj:
# storing a destination is what makes it an exit! # storing a destination is what makes it an exit!
@ -1513,7 +1576,9 @@ class CmdOpen(ObjManipCommand):
return return
# Create exit # Create exit
ok = self.create_exit(exit_name, location, destination, exit_aliases, exit_typeclass) ok = self.create_exit(
exit_name, location, destination, exit_aliases, exit_typeclass
)
if not ok: if not ok:
# an error; the exit was not created, so we quit. # an error; the exit was not created, so we quit.
return return
@ -1523,7 +1588,11 @@ class CmdOpen(ObjManipCommand):
back_exit_aliases = self.lhs_objs[1]["aliases"] back_exit_aliases = self.lhs_objs[1]["aliases"]
back_exit_typeclass = self.lhs_objs[1]["option"] back_exit_typeclass = self.lhs_objs[1]["option"]
self.create_exit( self.create_exit(
back_exit_name, destination, location, back_exit_aliases, back_exit_typeclass back_exit_name,
destination,
location,
back_exit_aliases,
back_exit_typeclass,
) )
@ -1718,11 +1787,18 @@ class CmdSetAttribute(ObjManipCommand):
del deep[del_key] del deep[del_key]
except (IndexError, KeyError, TypeError): except (IndexError, KeyError, TypeError):
continue continue
return "\nDeleted attribute '%s' (= nested) from %s." % (attr, obj.name) return "\nDeleted attribute '%s' (= nested) from %s." % (
attr,
obj.name,
)
else: else:
exists = obj.attributes.has(key) exists = obj.attributes.has(key)
obj.attributes.remove(attr) obj.attributes.remove(attr)
return "\nDeleted attribute '%s' (= %s) from %s." % (attr, exists, obj.name) return "\nDeleted attribute '%s' (= %s) from %s." % (
attr,
exists,
obj.name,
)
error = "\n%s has no attribute '%s'." % (obj.name, attr) error = "\n%s has no attribute '%s'." % (obj.name, attr)
if nested: if nested:
error += " (Nested lookups attempted)" error += " (Nested lookups attempted)"
@ -1816,7 +1892,9 @@ class CmdSetAttribute(ObjManipCommand):
""" """
from evennia.utils.utils import variable_from_module from evennia.utils.utils import variable_from_module
_AT_SEARCH_RESULT = variable_from_module(*settings.SEARCH_AT_RESULT.rsplit(".", 1)) _AT_SEARCH_RESULT = variable_from_module(
*settings.SEARCH_AT_RESULT.rsplit(".", 1)
)
caller = self.caller caller = self.caller
if objname.startswith("*") or "account" in self.switches: if objname.startswith("*") or "account" in self.switches:
found_obj = caller.search_account(objname.lstrip("*")) found_obj = caller.search_account(objname.lstrip("*"))
@ -1835,7 +1913,9 @@ class CmdSetAttribute(ObjManipCommand):
else: else:
global_search = False global_search = False
typeclass = None typeclass = None
found_obj = caller.search(objname, global_search=global_search, typeclass=typeclass) found_obj = caller.search(
objname, global_search=global_search, typeclass=typeclass
)
return found_obj return found_obj
def func(self): def func(self):
@ -1861,12 +1941,16 @@ class CmdSetAttribute(ObjManipCommand):
result = [] result = []
if "edit" in self.switches: if "edit" in self.switches:
# edit in the line editor # edit in the line editor
if not (obj.access(self.caller, "control") or obj.access(self.caller, "edit")): if not (
obj.access(self.caller, "control") or obj.access(self.caller, "edit")
):
caller.msg("You don't have permission to edit %s." % obj.key) caller.msg("You don't have permission to edit %s." % obj.key)
return return
if len(attrs) > 1: if len(attrs) > 1:
caller.msg("The Line editor can only be applied " "to one attribute at a time.") caller.msg(
"The Line editor can only be applied " "to one attribute at a time."
)
return return
self.edit_handler(obj, attrs[0]) self.edit_handler(obj, attrs[0])
return return
@ -1884,7 +1968,10 @@ class CmdSetAttribute(ObjManipCommand):
return return
else: else:
# deleting the attribute(s) # deleting the attribute(s)
if not (obj.access(self.caller, "control") or obj.access(self.caller, "edit")): if not (
obj.access(self.caller, "control")
or obj.access(self.caller, "edit")
):
caller.msg("You don't have permission to edit %s." % obj.key) caller.msg("You don't have permission to edit %s." % obj.key)
return return
for attr in attrs: for attr in attrs:
@ -1893,7 +1980,9 @@ class CmdSetAttribute(ObjManipCommand):
result.append(self.rm_attr(obj, attr)) result.append(self.rm_attr(obj, attr))
else: else:
# setting attribute(s). Make sure to convert to real Python type before saving. # setting attribute(s). Make sure to convert to real Python type before saving.
if not (obj.access(self.caller, "control") or obj.access(self.caller, "edit")): if not (
obj.access(self.caller, "control") or obj.access(self.caller, "edit")
):
caller.msg("You don't have permission to edit %s." % obj.key) caller.msg("You don't have permission to edit %s." % obj.key)
return return
for attr in attrs: for attr in attrs:
@ -1964,15 +2053,17 @@ class CmdTypeclass(COMMAND_DEFAULT_CLASS):
if "list" in self.switches: if "list" in self.switches:
tclasses = get_all_typeclasses() tclasses = get_all_typeclasses()
contribs = [key for key in sorted(tclasses) if key.startswith("evennia.contrib")] or [ contribs = [
"<None loaded>" key for key in sorted(tclasses) if key.startswith("evennia.contrib")
] ] or ["<None loaded>"]
core = [ core = [
key for key in sorted(tclasses) if key.startswith("evennia") and key not in contribs key
for key in sorted(tclasses)
if key.startswith("evennia") and key not in contribs
] or ["<None loaded>"]
game = [
key for key in sorted(tclasses) if not key.startswith("evennia")
] or ["<None loaded>"] ] or ["<None loaded>"]
game = [key for key in sorted(tclasses) if not key.startswith("evennia")] or [
"<None loaded>"
]
string = ( string = (
"|wCore typeclasses|n\n" "|wCore typeclasses|n\n"
" {core}\n" " {core}\n"
@ -1981,7 +2072,9 @@ class CmdTypeclass(COMMAND_DEFAULT_CLASS):
"|wGame-dir typeclasses|n\n" "|wGame-dir typeclasses|n\n"
" {game}" " {game}"
).format( ).format(
core="\n ".join(core), contrib="\n ".join(contribs), game="\n ".join(game) core="\n ".join(core),
contrib="\n ".join(contribs),
game="\n ".join(game),
) )
EvMore(caller, string, exit_on_lastpage=True) EvMore(caller, string, exit_on_lastpage=True)
return return
@ -1997,7 +2090,9 @@ class CmdTypeclass(COMMAND_DEFAULT_CLASS):
# no object found to examine, see if it's a typeclass-path instead # no object found to examine, see if it's a typeclass-path instead
tclasses = get_all_typeclasses() tclasses = get_all_typeclasses()
matches = [ matches = [
(key, tclass) for key, tclass in tclasses.items() if key.endswith(oquery) (key, tclass)
for key, tclass in tclasses.items()
if key.endswith(oquery)
] ]
nmatches = len(matches) nmatches = len(matches)
if nmatches > 1: if nmatches > 1:
@ -2007,11 +2102,15 @@ class CmdTypeclass(COMMAND_DEFAULT_CLASS):
) )
) )
elif not matches: elif not matches:
caller.msg("No object or typeclass path found to match '{}'".format(oquery)) caller.msg(
"No object or typeclass path found to match '{}'".format(oquery)
)
else: else:
# one match found # one match found
caller.msg( caller.msg(
"Docstring for typeclass '{}':\n{}".format(oquery, matches[0][1].__doc__) "Docstring for typeclass '{}':\n{}".format(
oquery, matches[0][1].__doc__
)
) )
else: else:
# do the search again to get the error handling in case of multi-match # do the search again to get the error handling in case of multi-match
@ -2071,11 +2170,17 @@ class CmdTypeclass(COMMAND_DEFAULT_CLASS):
# we let this raise exception if needed # we let this raise exception if needed
obj.swap_typeclass( obj.swap_typeclass(
new_typeclass, clean_attributes=reset, clean_cmdsets=reset, run_start_hooks=hooks new_typeclass,
clean_attributes=reset,
clean_cmdsets=reset,
run_start_hooks=hooks,
) )
if is_same: if is_same:
string = "%s updated its existing typeclass (%s).\n" % (obj.name, obj.path) string = "%s updated its existing typeclass (%s).\n" % (
obj.name,
obj.path,
)
else: else:
string = "%s changed typeclass from %s to %s.\n" % ( string = "%s changed typeclass from %s to %s.\n" % (
obj.name, obj.name,
@ -2189,7 +2294,8 @@ class CmdLock(ObjManipCommand):
caller = self.caller caller = self.caller
if not self.args: if not self.args:
string = ( string = (
"Usage: lock <object>[ = <lockstring>] or lock[/switch] " "<object>/<access_type>" "Usage: lock <object>[ = <lockstring>] or lock[/switch] "
"<object>/<access_type>"
) )
caller.msg(string) caller.msg(string)
return return
@ -2335,7 +2441,10 @@ class CmdExamine(ObjManipCommand):
except Exception: except Exception:
ndb_attr = None ndb_attr = None
else: else:
db_attr = [(attr.key, attr.value, attr.category) for attr in obj.db_attributes.all()] db_attr = [
(attr.key, attr.value, attr.category)
for attr in obj.db_attributes.all()
]
try: try:
ndb_attr = obj.nattributes.all(return_tuples=True) ndb_attr = obj.nattributes.all(return_tuples=True)
except Exception: except Exception:
@ -2359,7 +2468,9 @@ class CmdExamine(ObjManipCommand):
""" """
string = "\n|wName/key|n: |c%s|n (%s)" % (obj.name, obj.dbref) string = "\n|wName/key|n: |c%s|n (%s)" % (obj.name, obj.dbref)
if hasattr(obj, "aliases") and obj.aliases.all(): if hasattr(obj, "aliases") and obj.aliases.all():
string += "\n|wAliases|n: %s" % (", ".join(utils.make_iter(str(obj.aliases)))) string += "\n|wAliases|n: %s" % (
", ".join(utils.make_iter(str(obj.aliases)))
)
if hasattr(obj, "sessions") and obj.sessions.all(): if hasattr(obj, "sessions") and obj.sessions.all():
string += "\n|wSession id(s)|n: %s" % ( string += "\n|wSession id(s)|n: %s" % (
", ".join("#%i" % sess.sessid for sess in obj.sessions.all()) ", ".join("#%i" % sess.sessid for sess in obj.sessions.all())
@ -2401,14 +2512,20 @@ class CmdExamine(ObjManipCommand):
locks = str(obj.locks) locks = str(obj.locks)
if locks: if locks:
locks_string = utils.fill("; ".join([lock for lock in locks.split(";")]), indent=6) locks_string = utils.fill(
"; ".join([lock for lock in locks.split(";")]), indent=6
)
else: else:
locks_string = " Default" locks_string = " Default"
string += "\n|wLocks|n:%s" % locks_string string += "\n|wLocks|n:%s" % locks_string
if not (len(obj.cmdset.all()) == 1 and obj.cmdset.current.key == "_EMPTY_CMDSET"): if not (
len(obj.cmdset.all()) == 1 and obj.cmdset.current.key == "_EMPTY_CMDSET"
):
# all() returns a 'stack', so make a copy to sort. # all() returns a 'stack', so make a copy to sort.
stored_cmdsets = sorted(obj.cmdset.all(), key=lambda x: x.priority, reverse=True) stored_cmdsets = sorted(
obj.cmdset.all(), key=lambda x: x.priority, reverse=True
)
string += "\n|wStored Cmdset(s)|n:\n %s" % ( string += "\n|wStored Cmdset(s)|n:\n %s" % (
"\n ".join( "\n ".join(
"%s [%s] (%s, prio %s)" "%s [%s] (%s, prio %s)"
@ -2423,7 +2540,9 @@ class CmdExamine(ObjManipCommand):
# we always at least try to add account- and session sets since these are ignored # we always at least try to add account- and session sets since these are ignored
# if we merge on the object level. # if we merge on the object level.
if hasattr(obj, "account") and obj.account: if hasattr(obj, "account") and obj.account:
all_cmdsets.extend([(cmdset.key, cmdset) for cmdset in obj.account.cmdset.all()]) all_cmdsets.extend(
[(cmdset.key, cmdset) for cmdset in obj.account.cmdset.all()]
)
if obj.sessions.count(): if obj.sessions.count():
# if there are more sessions than one on objects it's because of multisession mode 3. # if there are more sessions than one on objects it's because of multisession mode 3.
# we only show the first session's cmdset here (it is -in principle- possible that # we only show the first session's cmdset here (it is -in principle- possible that
@ -2441,7 +2560,9 @@ class CmdExamine(ObjManipCommand):
all_cmdsets.extend( all_cmdsets.extend(
[ [
(cmdset.key, cmdset) (cmdset.key, cmdset)
for cmdset in obj.get_session(obj.sessions.get()).cmdset.all() for cmdset in obj.get_session(
obj.sessions.get()
).cmdset.all()
] ]
) )
except (TypeError, AttributeError): except (TypeError, AttributeError):
@ -2458,15 +2579,21 @@ class CmdExamine(ObjManipCommand):
) )
# list the commands available to this object # list the commands available to this object
avail_cmdset = sorted([cmd.key for cmd in avail_cmdset if cmd.access(obj, "cmd")]) avail_cmdset = sorted(
[cmd.key for cmd in avail_cmdset if cmd.access(obj, "cmd")]
cmdsetstr = utils.fill(", ".join(avail_cmdset), indent=2)
string += "\n|wCommands available to %s (result of Merged CmdSets)|n:\n %s" % (
obj.key,
cmdsetstr,
) )
if hasattr(obj, "scripts") and hasattr(obj.scripts, "all") and obj.scripts.all(): cmdsetstr = utils.fill(", ".join(avail_cmdset), indent=2)
string += (
"\n|wCommands available to %s (result of Merged CmdSets)|n:\n %s"
% (obj.key, cmdsetstr)
)
if (
hasattr(obj, "scripts")
and hasattr(obj.scripts, "all")
and obj.scripts.all()
):
string += "\n|wScripts|n:\n %s" % obj.scripts string += "\n|wScripts|n:\n %s" % obj.scripts
# add the attributes # add the attributes
string += self.format_attributes(obj) string += self.format_attributes(obj)
@ -2645,7 +2772,9 @@ class CmdFind(COMMAND_DEFAULT_CLASS):
caller.msg("Usage: find <string> [= low [-high]]") caller.msg("Usage: find <string> [= low [-high]]")
return return
if "locate" in self.cmdstring: # Use option /loc as a default for locate command alias if (
"locate" in self.cmdstring
): # Use option /loc as a default for locate command alias
switches.append("loc") switches.append("loc")
searchstring = self.lhs searchstring = self.lhs
@ -2693,10 +2822,16 @@ class CmdFind(COMMAND_DEFAULT_CLASS):
if not result: if not result:
string += "\n |RNo match found.|n" string += "\n |RNo match found.|n"
elif not low <= int(result[0].id) <= high: elif not low <= int(result[0].id) <= high:
string += "\n |RNo match found for '%s' in #dbref interval.|n" % searchstring string += (
"\n |RNo match found for '%s' in #dbref interval.|n"
% searchstring
)
else: else:
result = result[0] result = result[0]
string += "\n|g %s - %s|n" % (result.get_display_name(caller), result.path) string += "\n|g %s - %s|n" % (
result.get_display_name(caller),
result.path,
)
if "loc" in self.switches and not is_account and result.location: if "loc" in self.switches and not is_account and result.location:
string += " (|wlocation|n: |g{}|n)".format( string += " (|wlocation|n: |g{}|n)".format(
result.location.get_display_name(caller) result.location.get_display_name(caller)
@ -2713,7 +2848,9 @@ class CmdFind(COMMAND_DEFAULT_CLASS):
id__lte=high, id__lte=high,
) )
elif "startswith" in switches: elif "startswith" in switches:
keyquery = Q(db_key__istartswith=searchstring, id__gte=low, id__lte=high) keyquery = Q(
db_key__istartswith=searchstring, id__gte=low, id__lte=high
)
aliasquery = Q( aliasquery = Q(
db_tags__db_key__istartswith=searchstring, db_tags__db_key__istartswith=searchstring,
db_tags__db_tagtype__iexact="alias", db_tags__db_tagtype__iexact="alias",
@ -2736,19 +2873,33 @@ class CmdFind(COMMAND_DEFAULT_CLASS):
# convert result to typeclasses. # convert result to typeclasses.
results = [result for result in results] results = [result for result in results]
if "room" in switches: if "room" in switches:
results = [obj for obj in results if inherits_from(obj, ROOM_TYPECLASS)] results = [
obj for obj in results if inherits_from(obj, ROOM_TYPECLASS)
]
if "exit" in switches: if "exit" in switches:
results = [obj for obj in results if inherits_from(obj, EXIT_TYPECLASS)] results = [
obj for obj in results if inherits_from(obj, EXIT_TYPECLASS)
]
if "char" in switches: if "char" in switches:
results = [obj for obj in results if inherits_from(obj, CHAR_TYPECLASS)] results = [
obj for obj in results if inherits_from(obj, CHAR_TYPECLASS)
]
nresults = len(results) nresults = len(results)
# still results after type filtering? # still results after type filtering?
if nresults: if nresults:
if nresults > 1: if nresults > 1:
string = "|w%i Matches|n(#%i-#%i%s):" % (nresults, low, high, restrictions) string = "|w%i Matches|n(#%i-#%i%s):" % (
nresults,
low,
high,
restrictions,
)
for res in results: for res in results:
string += "\n |g%s - %s|n" % (res.get_display_name(caller), res.path) string += "\n |g%s - %s|n" % (
res.get_display_name(caller),
res.path,
)
else: else:
string = "|wOne Match|n(#%i-#%i%s):" % (low, high, restrictions) string = "|wOne Match|n(#%i-#%i%s):" % (low, high, restrictions)
string += "\n |g%s - %s|n" % ( string += "\n |g%s - %s|n" % (
@ -2834,7 +2985,8 @@ class CmdTeleport(COMMAND_DEFAULT_CLASS):
caller.msg("Teleported %s -> None-location." % obj_to_teleport) caller.msg("Teleported %s -> None-location." % obj_to_teleport)
if obj_to_teleport.location and not tel_quietly: if obj_to_teleport.location and not tel_quietly:
obj_to_teleport.location.msg_contents( obj_to_teleport.location.msg_contents(
"%s teleported %s into nothingness." % (caller, obj_to_teleport), exclude=caller "%s teleported %s into nothingness." % (caller, obj_to_teleport),
exclude=caller,
) )
obj_to_teleport.location = None obj_to_teleport.location = None
return return
@ -2877,7 +3029,10 @@ class CmdTeleport(COMMAND_DEFAULT_CLASS):
# try the teleport # try the teleport
if obj_to_teleport.move_to( if obj_to_teleport.move_to(
destination, quiet=tel_quietly, emit_to_obj=caller, use_destination=use_destination destination,
quiet=tel_quietly,
emit_to_obj=caller,
use_destination=use_destination,
): ):
if obj_to_teleport == caller: if obj_to_teleport == caller:
caller.msg("Teleported to %s." % destination) caller.msg("Teleported to %s." % destination)
@ -2922,7 +3077,9 @@ class CmdScript(COMMAND_DEFAULT_CLASS):
return return
if not self.lhs: if not self.lhs:
caller.msg("To create a global script you need |wscripts/add <typeclass>|n.") caller.msg(
"To create a global script you need |wscripts/add <typeclass>|n."
)
return return
obj = caller.search(self.lhs) obj = caller.search(self.lhs)
@ -2934,7 +3091,9 @@ class CmdScript(COMMAND_DEFAULT_CLASS):
# no rhs means we want to operate on all scripts # no rhs means we want to operate on all scripts
scripts = obj.scripts.all() scripts = obj.scripts.all()
if not scripts: if not scripts:
result.append("No scripts defined on %s." % obj.get_display_name(caller)) result.append(
"No scripts defined on %s." % obj.get_display_name(caller)
)
elif not self.switches: elif not self.switches:
# view all scripts # view all scripts
from evennia.commands.default.system import format_script_list from evennia.commands.default.system import format_script_list
@ -2942,12 +3101,17 @@ class CmdScript(COMMAND_DEFAULT_CLASS):
result.append(format_script_list(scripts)) result.append(format_script_list(scripts))
elif "start" in self.switches: elif "start" in self.switches:
num = sum([obj.scripts.start(script.key) for script in scripts]) num = sum([obj.scripts.start(script.key) for script in scripts])
result.append("%s scripts started on %s." % (num, obj.get_display_name(caller))) result.append(
"%s scripts started on %s." % (num, obj.get_display_name(caller))
)
elif "stop" in self.switches: elif "stop" in self.switches:
for script in scripts: for script in scripts:
result.append( result.append(
"Stopping script %s on %s." "Stopping script %s on %s."
% (script.get_display_name(caller), obj.get_display_name(caller)) % (
script.get_display_name(caller),
obj.get_display_name(caller),
)
) )
script.stop() script.stop()
obj.scripts.validate() obj.scripts.validate()
@ -2975,7 +3139,10 @@ class CmdScript(COMMAND_DEFAULT_CLASS):
for path in paths: for path in paths:
ok = obj.scripts.stop(path) ok = obj.scripts.stop(path)
if not ok: if not ok:
result.append("\nScript %s could not be stopped. Does it exist?" % path) result.append(
"\nScript %s could not be stopped. Does it exist?"
% path
)
else: else:
result = ["Script stopped and removed from object."] result = ["Script stopped and removed from object."]
break break
@ -2984,7 +3151,9 @@ class CmdScript(COMMAND_DEFAULT_CLASS):
for path in paths: for path in paths:
ok = obj.scripts.start(path) ok = obj.scripts.start(path)
if not ok: if not ok:
result.append("\nScript %s could not be (re)started." % path) result.append(
"\nScript %s could not be (re)started." % path
)
else: else:
result = ["Script started successfully."] result = ["Script started successfully."]
break break
@ -3088,7 +3257,10 @@ class CmdTag(COMMAND_DEFAULT_CLASS):
] ]
if old_tags: if old_tags:
obj.tags.clear() obj.tags.clear()
string = "Cleared all tags from %s: %s" % (obj, ", ".join(sorted(old_tags))) string = "Cleared all tags from %s: %s" % (
obj,
", ".join(sorted(old_tags)),
)
else: else:
string = "No Tags to clear on %s." % obj string = "No Tags to clear on %s." % obj
self.caller.msg(string) self.caller.msg(string)
@ -3119,12 +3291,18 @@ class CmdTag(COMMAND_DEFAULT_CLASS):
tagtuples = obj.tags.all(return_key_and_category=True) tagtuples = obj.tags.all(return_key_and_category=True)
ntags = len(tagtuples) ntags = len(tagtuples)
tags = [tup[0] for tup in tagtuples] tags = [tup[0] for tup in tagtuples]
categories = [" (category: %s)" % tup[1] if tup[1] else "" for tup in tagtuples] categories = [
" (category: %s)" % tup[1] if tup[1] else "" for tup in tagtuples
]
if ntags: if ntags:
string = "Tag%s on %s: %s" % ( string = "Tag%s on %s: %s" % (
"s" if ntags > 1 else "", "s" if ntags > 1 else "",
obj, obj,
", ".join(sorted("'%s'%s" % (tags[i], categories[i]) for i in range(ntags))), ", ".join(
sorted(
"'%s'%s" % (tags[i], categories[i]) for i in range(ntags)
)
),
) )
else: else:
string = "No tags attached to %s." % obj string = "No tags attached to %s." % obj
@ -3239,9 +3417,12 @@ class CmdSpawn(COMMAND_DEFAULT_CLASS):
return None return None
if expect == dict: if expect == dict:
# an actual prototype. We need to make sure it's safe. Don't allow exec # an actual prototype. We need to make sure it's safe. Don't allow exec
if "exec" in prototype and not self.caller.check_permstring("Developer"): if "exec" in prototype and not self.caller.check_permstring(
"Developer"
):
self.caller.msg( self.caller.msg(
"Spawn aborted: You are not allowed to " "use the 'exec' prototype key." "Spawn aborted: You are not allowed to "
"use the 'exec' prototype key."
) )
return None return None
try: try:
@ -3277,7 +3458,10 @@ class CmdSpawn(COMMAND_DEFAULT_CLASS):
if len(prototype) > 1: if len(prototype) > 1:
caller.msg( caller.msg(
"More than one match for {}:\n{}".format( "More than one match for {}:\n{}".format(
key, "\n".join(proto.get("prototype_key", "") for proto in prototype) key,
"\n".join(
proto.get("prototype_key", "") for proto in prototype
),
) )
) )
return return
@ -3298,7 +3482,9 @@ class CmdSpawn(COMMAND_DEFAULT_CLASS):
else: else:
key, tags = self.args.strip(), None key, tags = self.args.strip(), None
if ";" in self.args: if ";" in self.args:
key, tags = (part.strip().lower() for part in self.args.split(";", 1)) key, tags = (
part.strip().lower() for part in self.args.split(";", 1)
)
tags = [tag.strip() for tag in tags.split(",")] if tags else None tags = [tag.strip() for tag in tags.split(",")] if tags else None
EvMore( EvMore(
caller, caller,
@ -3351,14 +3537,18 @@ class CmdSpawn(COMMAND_DEFAULT_CLASS):
prototype_key = prototype.get("prototype_key") prototype_key = prototype.get("prototype_key")
if not prototype_key: if not prototype_key:
caller.msg("\n|yTo save a prototype it must have the 'prototype_key' set.") caller.msg(
"\n|yTo save a prototype it must have the 'prototype_key' set."
)
return return
# check for existing prototype, # check for existing prototype,
old_matchstring = _search_show_prototype(prototype_key) old_matchstring = _search_show_prototype(prototype_key)
if old_matchstring: if old_matchstring:
string += "\n|yExisting saved prototype found:|n\n{}".format(old_matchstring) string += "\n|yExisting saved prototype found:|n\n{}".format(
old_matchstring
)
question = "\n|yDo you want to replace the existing prototype?|n [Y]/N" question = "\n|yDo you want to replace the existing prototype?|n [Y]/N"
answer = yield (string + question) answer = yield (string + question)
@ -3396,7 +3586,9 @@ class CmdSpawn(COMMAND_DEFAULT_CLASS):
"Use spawn/update <key> to apply later as needed.|n" "Use spawn/update <key> to apply later as needed.|n"
) )
return return
n_updated = spawner.batch_update_objects_with_prototype(existing_objects, key) n_updated = spawner.batch_update_objects_with_prototype(
existing_objects, key
)
caller.msg("{} objects were updated.".format(n_updated)) caller.msg("{} objects were updated.".format(n_updated))
return return
@ -3424,7 +3616,9 @@ class CmdSpawn(COMMAND_DEFAULT_CLASS):
caller.msg("|rError deleting:|R {}|n".format(err)) caller.msg("|rError deleting:|R {}|n".format(err))
caller.msg( caller.msg(
"Deletion {}.".format( "Deletion {}.".format(
"successful" if success else "failed (does the prototype exist?)" "successful"
if success
else "failed (does the prototype exist?)"
) )
) )
return return
@ -3448,7 +3642,9 @@ class CmdSpawn(COMMAND_DEFAULT_CLASS):
if answer.lower() in ["n", "no"]: if answer.lower() in ["n", "no"]:
caller.msg("|rUpdate cancelled.") caller.msg("|rUpdate cancelled.")
return return
n_updated = spawner.batch_update_objects_with_prototype(existing_objects, key) n_updated = spawner.batch_update_objects_with_prototype(
existing_objects, key
)
caller.msg("{} objects were updated.".format(n_updated)) caller.msg("{} objects were updated.".format(n_updated))
# A direct creation of an object from a given prototype # A direct creation of an object from a given prototype
@ -3474,14 +3670,19 @@ class CmdSpawn(COMMAND_DEFAULT_CLASS):
"Found {} prototypes matching '{}':\n {}".format( "Found {} prototypes matching '{}':\n {}".format(
nprots, nprots,
prototype, prototype,
", ".join(proto.get("prototype_key", "") for proto in prototypes), ", ".join(
proto.get("prototype_key", "") for proto in prototypes
),
) )
) )
return return
# we have a prototype, check access # we have a prototype, check access
prototype = prototypes[0] prototype = prototypes[0]
if not caller.locks.check_lockstring( if not caller.locks.check_lockstring(
caller, prototype.get("prototype_locks", ""), access_type="spawn", default=True caller,
prototype.get("prototype_locks", ""),
access_type="spawn",
default=True,
): ):
caller.msg("You don't have access to use this prototype.") caller.msg("You don't have access to use this prototype.")
return return

View file

@ -188,14 +188,18 @@ class CmdDelCom(COMMAND_DEFAULT_CLASS):
if delnicks: if delnicks:
for nick in [ for nick in [
nick nick
for nick in make_iter(caller.nicks.get(category="channel", return_obj=True)) for nick in make_iter(
caller.nicks.get(category="channel", return_obj=True)
)
if nick and nick.pk and nick.value[3].lower() == chkey if nick and nick.pk and nick.value[3].lower() == chkey
]: ]:
nick.delete() nick.delete()
disconnect = channel.disconnect(account) disconnect = channel.disconnect(account)
if disconnect: if disconnect:
wipednicks = " Eventual aliases were removed." if delnicks else "" wipednicks = " Eventual aliases were removed." if delnicks else ""
self.msg("You stop listening to channel '%s'.%s" % (channel.key, wipednicks)) self.msg(
"You stop listening to channel '%s'.%s" % (channel.key, wipednicks)
)
return return
else: else:
# we are removing a channel nick # we are removing a channel nick
@ -206,7 +210,10 @@ class CmdDelCom(COMMAND_DEFAULT_CLASS):
else: else:
if caller.nicks.get(ostring, category="channel"): if caller.nicks.get(ostring, category="channel"):
caller.nicks.remove(ostring, category="channel") caller.nicks.remove(ostring, category="channel")
self.msg("Your alias '%s' for channel %s was cleared." % (ostring, channel.key)) self.msg(
"Your alias '%s' for channel %s was cleared."
% (ostring, channel.key)
)
else: else:
self.msg("You had no such alias defined for this channel.") self.msg("You had no such alias defined for this channel.")
@ -340,7 +347,9 @@ class CmdChannels(COMMAND_DEFAULT_CLASS):
"%s%s" "%s%s"
% ( % (
chan.key, chan.key,
chan.aliases.all() and "(%s)" % ",".join(chan.aliases.all()) or "", chan.aliases.all()
and "(%s)" % ",".join(chan.aliases.all())
or "",
), ),
"%s" "%s"
% ",".join( % ",".join(
@ -381,7 +390,9 @@ class CmdChannels(COMMAND_DEFAULT_CLASS):
"%s%s" "%s%s"
% ( % (
chan.key, chan.key,
chan.aliases.all() and "(%s)" % ",".join(chan.aliases.all()) or "", chan.aliases.all()
and "(%s)" % ",".join(chan.aliases.all())
or "",
), ),
"%s" "%s"
% ",".join( % ",".join(
@ -433,7 +444,9 @@ class CmdCdestroy(COMMAND_DEFAULT_CLASS):
self.msg("You are not allowed to do that.") self.msg("You are not allowed to do that.")
return return
channel_key = channel.key channel_key = channel.key
message = "%s is being destroyed. Make sure to change your aliases." % channel_key message = (
"%s is being destroyed. Make sure to change your aliases." % channel_key
)
msgobj = create.create_message(caller, message, channel) msgobj = create.create_message(caller, message, channel)
channel.msg(msgobj) channel.msg(msgobj)
channel.delete() channel.delete()
@ -494,7 +507,10 @@ class CmdCBoot(COMMAND_DEFAULT_CLASS):
self.msg(string) self.msg(string)
return return
if not channel.subscriptions.has(account): if not channel.subscriptions.has(account):
string = "Account %s is not connected to channel %s." % (account.key, channel.key) string = "Account %s is not connected to channel %s." % (
account.key,
channel.key,
)
self.msg(string) self.msg(string)
return return
if "quiet" not in self.switches: if "quiet" not in self.switches:
@ -645,7 +661,9 @@ class CmdChannelCreate(COMMAND_DEFAULT_CLASS):
return return
# Create and set the channel up # Create and set the channel up
lockstring = "send:all();listen:all();control:id(%s)" % caller.id lockstring = "send:all();listen:all();control:id(%s)" % caller.id
new_chan = create.create_channel(channame.strip(), aliases, description, locks=lockstring) new_chan = create.create_channel(
channame.strip(), aliases, description, locks=lockstring
)
new_chan.connect(caller) new_chan.connect(caller)
CHANNELHANDLER.update() CHANNELHANDLER.update()
self.msg("Created channel %s and connected to it." % new_chan.key) self.msg("Created channel %s and connected to it." % new_chan.key)
@ -777,7 +795,9 @@ class CmdPage(COMMAND_DEFAULT_CLASS):
caller = self.caller caller = self.caller
# get the messages we've sent (not to channels) # get the messages we've sent (not to channels)
pages_we_sent = Msg.objects.get_messages_by_sender(caller, exclude_channel_messages=True) pages_we_sent = Msg.objects.get_messages_by_sender(
caller, exclude_channel_messages=True
)
# get last messages we've got # get last messages we've got
pages_we_got = Msg.objects.get_messages_by_receiver(caller) pages_we_got = Msg.objects.get_messages_by_receiver(caller)
@ -895,7 +915,10 @@ def _list_bots(cmd):
""" """
ircbots = [ ircbots = [
bot for bot in AccountDB.objects.filter(db_is_bot=True, username__startswith="ircbot-") bot
for bot in AccountDB.objects.filter(
db_is_bot=True, username__startswith="ircbot-"
)
] ]
if ircbots: if ircbots:
table = cmd.styled_table( table = cmd.styled_table(
@ -964,7 +987,9 @@ class CmdIRC2Chan(COMMAND_DEFAULT_CLASS):
"""Setup the irc-channel mapping""" """Setup the irc-channel mapping"""
if not settings.IRC_ENABLED: if not settings.IRC_ENABLED:
string = """IRC is not enabled. You need to activate it in game/settings.py.""" string = (
"""IRC is not enabled. You need to activate it in game/settings.py."""
)
self.msg(string) self.msg(string)
return return
@ -973,7 +998,11 @@ class CmdIRC2Chan(COMMAND_DEFAULT_CLASS):
self.msg(_list_bots(self)) self.msg(_list_bots(self))
return return
if "disconnect" in self.switches or "remove" in self.switches or "delete" in self.switches: if (
"disconnect" in self.switches
or "remove" in self.switches
or "delete" in self.switches
):
botname = "ircbot-%s" % self.lhs botname = "ircbot-%s" % self.lhs
matches = AccountDB.objects.filter(db_is_bot=True, username=botname) matches = AccountDB.objects.filter(db_is_bot=True, username=botname)
dbref = utils.dbref(self.lhs) dbref = utils.dbref(self.lhs)
@ -1103,7 +1132,9 @@ class CmdIRCStatus(COMMAND_DEFAULT_CLASS):
elif option in ("users", "nicklist", "who"): elif option in ("users", "nicklist", "who"):
# retrieve user list. The bot must handles the echo since it's # retrieve user list. The bot must handles the echo since it's
# an asynchronous call. # an asynchronous call.
self.caller.msg("Requesting nicklist from %s (%s:%s)." % (channel, network, port)) self.caller.msg(
"Requesting nicklist from %s (%s:%s)." % (channel, network, port)
)
ircbot.get_nicklist(self.caller) ircbot.get_nicklist(self.caller)
elif self.caller.locks.check_lockstring( elif self.caller.locks.check_lockstring(
self.caller, "dummy:perm(ircstatus) or perm(Developer)" self.caller, "dummy:perm(ircstatus) or perm(Developer)"
@ -1151,7 +1182,9 @@ class CmdRSS2Chan(COMMAND_DEFAULT_CLASS):
# checking we have all we need # checking we have all we need
if not settings.RSS_ENABLED: if not settings.RSS_ENABLED:
string = """RSS is not enabled. You need to activate it in game/settings.py.""" string = (
"""RSS is not enabled. You need to activate it in game/settings.py."""
)
self.msg(string) self.msg(string)
return return
try: try:
@ -1170,7 +1203,9 @@ class CmdRSS2Chan(COMMAND_DEFAULT_CLASS):
# show all connections # show all connections
rssbots = [ rssbots = [
bot bot
for bot in AccountDB.objects.filter(db_is_bot=True, username__startswith="rssbot-") for bot in AccountDB.objects.filter(
db_is_bot=True, username__startswith="rssbot-"
)
] ]
if rssbots: if rssbots:
table = self.styled_table( table = self.styled_table(
@ -1183,19 +1218,28 @@ class CmdRSS2Chan(COMMAND_DEFAULT_CLASS):
) )
for rssbot in rssbots: for rssbot in rssbots:
table.add_row( table.add_row(
rssbot.id, rssbot.db.rss_rate, rssbot.db.ev_channel, rssbot.db.rss_url rssbot.id,
rssbot.db.rss_rate,
rssbot.db.ev_channel,
rssbot.db.rss_url,
) )
self.msg(table) self.msg(table)
else: else:
self.msg("No rss bots found.") self.msg("No rss bots found.")
return return
if "disconnect" in self.switches or "remove" in self.switches or "delete" in self.switches: if (
"disconnect" in self.switches
or "remove" in self.switches
or "delete" in self.switches
):
botname = "rssbot-%s" % self.lhs botname = "rssbot-%s" % self.lhs
matches = AccountDB.objects.filter(db_is_bot=True, db_key=botname) matches = AccountDB.objects.filter(db_is_bot=True, db_key=botname)
if not matches: if not matches:
# try dbref match # try dbref match
matches = AccountDB.objects.filter(db_is_bot=True, id=self.args.lstrip("#")) matches = AccountDB.objects.filter(
db_is_bot=True, id=self.args.lstrip("#")
)
if matches: if matches:
matches[0].delete() matches[0].delete()
self.msg("RSS connection destroyed.") self.msg("RSS connection destroyed.")
@ -1277,24 +1321,34 @@ class CmdGrapevine2Chan(COMMAND_DEFAULT_CLASS):
maxwidth=_DEFAULT_WIDTH, maxwidth=_DEFAULT_WIDTH,
) )
for gwbot in gwbots: for gwbot in gwbots:
table.add_row(gwbot.id, gwbot.db.ev_channel, gwbot.db.grapevine_channel) table.add_row(
gwbot.id, gwbot.db.ev_channel, gwbot.db.grapevine_channel
)
self.msg(table) self.msg(table)
else: else:
self.msg("No grapevine bots found.") self.msg("No grapevine bots found.")
return return
if "disconnect" in self.switches or "remove" in self.switches or "delete" in self.switches: if (
"disconnect" in self.switches
or "remove" in self.switches
or "delete" in self.switches
):
botname = "grapevinebot-%s" % self.lhs botname = "grapevinebot-%s" % self.lhs
matches = AccountDB.objects.filter(db_is_bot=True, db_key=botname) matches = AccountDB.objects.filter(db_is_bot=True, db_key=botname)
if not matches: if not matches:
# try dbref match # try dbref match
matches = AccountDB.objects.filter(db_is_bot=True, id=self.args.lstrip("#")) matches = AccountDB.objects.filter(
db_is_bot=True, id=self.args.lstrip("#")
)
if matches: if matches:
matches[0].delete() matches[0].delete()
self.msg("Grapevine connection destroyed.") self.msg("Grapevine connection destroyed.")
else: else:
self.msg("Grapevine connection/bot could not be removed, does it exist?") self.msg(
"Grapevine connection/bot could not be removed, does it exist?"
)
return return
if not self.args or not self.rhs: if not self.args or not self.rhs:
@ -1317,7 +1371,9 @@ class CmdGrapevine2Chan(COMMAND_DEFAULT_CLASS):
self.msg("Reusing bot '%s' (%s)" % (botname, bot.dbref)) self.msg("Reusing bot '%s' (%s)" % (botname, bot.dbref))
else: else:
# create a new bot # create a new bot
bot = create.create_account(botname, None, None, typeclass=bots.GrapevineBot) bot = create.create_account(
botname, None, None, typeclass=bots.GrapevineBot
)
bot.start(ev_channel=channel, grapevine_channel=grapevine_channel) bot.start(ev_channel=channel, grapevine_channel=grapevine_channel)
self.msg(f"Grapevine connection created {channel} <-> {grapevine_channel}.") self.msg(f"Grapevine connection created {channel} <-> {grapevine_channel}.")

View file

@ -157,14 +157,24 @@ class CmdNick(COMMAND_DEFAULT_CLASS):
caller = self.caller caller = self.caller
switches = self.switches switches = self.switches
nicktypes = [switch for switch in switches if switch in ("object", "account", "inputline")] nicktypes = [
switch
for switch in switches
if switch in ("object", "account", "inputline")
]
specified_nicktype = bool(nicktypes) specified_nicktype = bool(nicktypes)
nicktypes = nicktypes if specified_nicktype else ["inputline"] nicktypes = nicktypes if specified_nicktype else ["inputline"]
nicklist = ( nicklist = (
utils.make_iter(caller.nicks.get(category="inputline", return_obj=True) or []) utils.make_iter(
+ utils.make_iter(caller.nicks.get(category="object", return_obj=True) or []) caller.nicks.get(category="inputline", return_obj=True) or []
+ utils.make_iter(caller.nicks.get(category="account", return_obj=True) or []) )
+ utils.make_iter(
caller.nicks.get(category="object", return_obj=True) or []
)
+ utils.make_iter(
caller.nicks.get(category="account", return_obj=True) or []
)
) )
if "list" in switches or self.cmdstring in ("nicks",): if "list" in switches or self.cmdstring in ("nicks",):
@ -176,7 +186,10 @@ class CmdNick(COMMAND_DEFAULT_CLASS):
for inum, nickobj in enumerate(nicklist): for inum, nickobj in enumerate(nicklist):
_, _, nickvalue, replacement = nickobj.value _, _, nickvalue, replacement = nickobj.value
table.add_row( table.add_row(
str(inum + 1), nickobj.db_category, _cy(nickvalue), _cy(replacement) str(inum + 1),
nickobj.db_category,
_cy(nickvalue),
_cy(replacement),
) )
string = "|wDefined Nicks:|n\n%s" % table string = "|wDefined Nicks:|n\n%s" % table
caller.msg(string) caller.msg(string)
@ -207,7 +220,9 @@ class CmdNick(COMMAND_DEFAULT_CLASS):
if not specified_nicktype: if not specified_nicktype:
nicktypes = ("object", "account", "inputline") nicktypes = ("object", "account", "inputline")
for nicktype in nicktypes: for nicktype in nicktypes:
oldnicks.append(caller.nicks.get(arg, category=nicktype, return_obj=True)) oldnicks.append(
caller.nicks.get(arg, category=nicktype, return_obj=True)
)
oldnicks = [oldnick for oldnick in oldnicks if oldnick] oldnicks = [oldnick for oldnick in oldnicks if oldnick]
if oldnicks: if oldnicks:
@ -241,7 +256,9 @@ class CmdNick(COMMAND_DEFAULT_CLASS):
_, _, nick, repl = nick.value _, _, nick, repl = nick.value
if nick.startswith(self.lhs): if nick.startswith(self.lhs):
strings.append( strings.append(
"{}-nick: '{}' -> '{}'".format(nicktype.capitalize(), nick, repl) "{}-nick: '{}' -> '{}'".format(
nicktype.capitalize(), nick, repl
)
) )
if strings: if strings:
caller.msg("\n".join(strings)) caller.msg("\n".join(strings))
@ -259,12 +276,16 @@ class CmdNick(COMMAND_DEFAULT_CLASS):
obj = account obj = account
else: else:
obj = caller obj = caller
nicks = utils.make_iter(obj.nicks.get(category=nicktype, return_obj=True)) nicks = utils.make_iter(
obj.nicks.get(category=nicktype, return_obj=True)
)
for nick in nicks: for nick in nicks:
_, _, nick, repl = nick.value _, _, nick, repl = nick.value
if nick.startswith(self.lhs): if nick.startswith(self.lhs):
strings.append( strings.append(
"{}-nick: '{}' -> '{}'".format(nicktype.capitalize(), nick, repl) "{}-nick: '{}' -> '{}'".format(
nicktype.capitalize(), nick, repl
)
) )
if strings: if strings:
caller.msg("\n".join(strings)) caller.msg("\n".join(strings))
@ -282,12 +303,16 @@ class CmdNick(COMMAND_DEFAULT_CLASS):
obj = account obj = account
else: else:
obj = caller obj = caller
nicks = utils.make_iter(obj.nicks.get(category=nicktype, return_obj=True)) nicks = utils.make_iter(
obj.nicks.get(category=nicktype, return_obj=True)
)
for nick in nicks: for nick in nicks:
_, _, nick, repl = nick.value _, _, nick, repl = nick.value
if nick.startswith(self.lhs): if nick.startswith(self.lhs):
strings.append( strings.append(
"{}-nick: '{}' -> '{}'".format(nicktype.capitalize(), nick, repl) "{}-nick: '{}' -> '{}'".format(
nicktype.capitalize(), nick, repl
)
) )
if strings: if strings:
caller.msg("\n".join(strings)) caller.msg("\n".join(strings))
@ -316,7 +341,9 @@ class CmdNick(COMMAND_DEFAULT_CLASS):
old_nickstring = None old_nickstring = None
old_replstring = None old_replstring = None
oldnick = caller.nicks.get(key=nickstring, category=nicktype, return_obj=True) oldnick = caller.nicks.get(
key=nickstring, category=nicktype, return_obj=True
)
if oldnick: if oldnick:
_, _, old_nickstring, old_replstring = oldnick.value _, _, old_nickstring, old_replstring = oldnick.value
if replstring: if replstring:
@ -428,7 +455,9 @@ class CmdGet(COMMAND_DEFAULT_CLASS):
obj.move_to(caller, quiet=True) obj.move_to(caller, quiet=True)
caller.msg("You pick up %s." % obj.name) caller.msg("You pick up %s." % obj.name)
caller.location.msg_contents("%s picks up %s." % (caller.name, obj.name), exclude=caller) caller.location.msg_contents(
"%s picks up %s." % (caller.name, obj.name), exclude=caller
)
# calling at_get hook method # calling at_get hook method
obj.at_get(caller) obj.at_get(caller)
@ -473,7 +502,9 @@ class CmdDrop(COMMAND_DEFAULT_CLASS):
obj.move_to(caller.location, quiet=True) obj.move_to(caller.location, quiet=True)
caller.msg("You drop %s." % (obj.name,)) caller.msg("You drop %s." % (obj.name,))
caller.location.msg_contents("%s drops %s." % (caller.name, obj.name), exclude=caller) caller.location.msg_contents(
"%s drops %s." % (caller.name, obj.name), exclude=caller
)
# Call the object script's at_drop() method. # Call the object script's at_drop() method.
obj.at_drop(caller) obj.at_drop(caller)
@ -675,7 +706,9 @@ class CmdPose(COMMAND_DEFAULT_CLASS):
self.caller.msg(msg) self.caller.msg(msg)
else: else:
msg = "%s%s" % (self.caller.name, self.args) msg = "%s%s" % (self.caller.name, self.args)
self.caller.location.msg_contents(text=(msg, {"type": "pose"}), from_obj=self.caller) self.caller.location.msg_contents(
text=(msg, {"type": "pose"}), from_obj=self.caller
)
class CmdAccess(COMMAND_DEFAULT_CLASS): class CmdAccess(COMMAND_DEFAULT_CLASS):
@ -699,7 +732,9 @@ class CmdAccess(COMMAND_DEFAULT_CLASS):
caller = self.caller caller = self.caller
hierarchy_full = settings.PERMISSION_HIERARCHY hierarchy_full = settings.PERMISSION_HIERARCHY
string = "\n|wPermission Hierarchy|n (climbing):\n %s" % ", ".join(hierarchy_full) string = "\n|wPermission Hierarchy|n (climbing):\n %s" % ", ".join(
hierarchy_full
)
if self.caller.account.is_superuser: if self.caller.account.is_superuser:
cperms = "<Superuser>" cperms = "<Superuser>"

View file

@ -67,7 +67,10 @@ class CmdHelp(Command):
if type(self).help_more: if type(self).help_more:
usemore = True usemore = True
if self.session and self.session.protocol_key in ("websocket", "ajax/comet"): if self.session and self.session.protocol_key in (
"websocket",
"ajax/comet",
):
try: try:
options = self.account.db._saved_webclient_options options = self.account.db._saved_webclient_options
if options and options["helppopup"]: if options and options["helppopup"]:
@ -101,7 +104,9 @@ class CmdHelp(Command):
if title: if title:
string += "|CHelp for |w%s|n" % title string += "|CHelp for |w%s|n" % title
if aliases: if aliases:
string += " |C(aliases: %s|C)|n" % ("|C,|n ".join("|w%s|n" % ali for ali in aliases)) string += " |C(aliases: %s|C)|n" % (
"|C,|n ".join("|w%s|n" % ali for ali in aliases)
)
if help_text: if help_text:
string += "\n%s" % dedent(help_text.rstrip()) string += "\n%s" % dedent(help_text.rstrip())
if suggested: if suggested:
@ -124,14 +129,18 @@ class CmdHelp(Command):
string += "\n" + _SEP + "\n |CCommand help entries|n\n" + _SEP string += "\n" + _SEP + "\n |CCommand help entries|n\n" + _SEP
for category in sorted(hdict_cmds.keys()): for category in sorted(hdict_cmds.keys()):
string += "\n |w%s|n:\n" % (str(category).title()) string += "\n |w%s|n:\n" % (str(category).title())
string += "|G" + fill("|C, |G".join(sorted(hdict_cmds[category]))) + "|n" string += (
"|G" + fill("|C, |G".join(sorted(hdict_cmds[category]))) + "|n"
)
if hdict_db and any(hdict_db.values()): if hdict_db and any(hdict_db.values()):
string += "\n\n" + _SEP + "\n\r |COther help entries|n\n" + _SEP string += "\n\n" + _SEP + "\n\r |COther help entries|n\n" + _SEP
for category in sorted(hdict_db.keys()): for category in sorted(hdict_db.keys()):
string += "\n\r |w%s|n:\n" % (str(category).title()) string += "\n\r |w%s|n:\n" % (str(category).title())
string += ( string += (
"|G" "|G"
+ fill(", ".join(sorted([str(topic) for topic in hdict_db[category]]))) + fill(
", ".join(sorted([str(topic) for topic in hdict_db[category]]))
)
+ "|n" + "|n"
) )
return string return string
@ -204,7 +213,9 @@ class CmdHelp(Command):
# retrieve all available commands and database topics # retrieve all available commands and database topics
all_cmds = [cmd for cmd in cmdset if self.check_show_help(cmd, caller)] all_cmds = [cmd for cmd in cmdset if self.check_show_help(cmd, caller)]
all_topics = [ all_topics = [
topic for topic in HelpEntry.objects.all() if topic.access(caller, "view", default=True) topic
for topic in HelpEntry.objects.all()
if topic.access(caller, "view", default=True)
] ]
all_categories = list( all_categories = list(
set( set(
@ -242,13 +253,18 @@ class CmdHelp(Command):
suggestions = [ suggestions = [
sugg sugg
for sugg in string_suggestions( for sugg in string_suggestions(
query, set(vocabulary), cutoff=suggestion_cutoff, maxnum=suggestion_maxnum query,
set(vocabulary),
cutoff=suggestion_cutoff,
maxnum=suggestion_maxnum,
) )
if sugg != query if sugg != query
] ]
if not suggestions: if not suggestions:
suggestions = [ suggestions = [
sugg for sugg in vocabulary if sugg != query and sugg.startswith(query) sugg
for sugg in vocabulary
if sugg != query and sugg.startswith(query)
] ]
# try an exact command auto-help match # try an exact command auto-help match
@ -291,8 +307,18 @@ class CmdHelp(Command):
if query in all_categories: if query in all_categories:
self.msg_help( self.msg_help(
self.format_help_list( self.format_help_list(
{query: [cmd.key for cmd in all_cmds if cmd.help_category == query]}, {
{query: [topic.key for topic in all_topics if topic.help_category == query]}, query: [
cmd.key for cmd in all_cmds if cmd.help_category == query
]
},
{
query: [
topic.key
for topic in all_topics
if topic.help_category == query
]
},
) )
) )
return return
@ -376,14 +402,19 @@ class CmdSetHelp(COMMAND_DEFAULT_CLASS):
self.msg("You have to define a topic!") self.msg("You have to define a topic!")
return return
topicstrlist = topicstr.split(";") topicstrlist = topicstr.split(";")
topicstr, aliases = topicstrlist[0], topicstrlist[1:] if len(topicstr) > 1 else [] topicstr, aliases = (
topicstrlist[0],
topicstrlist[1:] if len(topicstr) > 1 else [],
)
aliastxt = ("(aliases: %s)" % ", ".join(aliases)) if aliases else "" aliastxt = ("(aliases: %s)" % ", ".join(aliases)) if aliases else ""
old_entry = None old_entry = None
# check if we have an old entry with the same name # check if we have an old entry with the same name
try: try:
for querystr in topicstrlist: for querystr in topicstrlist:
old_entry = HelpEntry.objects.find_topicmatch(querystr) # also search by alias old_entry = HelpEntry.objects.find_topicmatch(
querystr
) # also search by alias
if old_entry: if old_entry:
old_entry = list(old_entry)[0] old_entry = list(old_entry)[0]
break break
@ -405,7 +436,11 @@ class CmdSetHelp(COMMAND_DEFAULT_CLASS):
helpentry = old_entry helpentry = old_entry
else: else:
helpentry = create.create_help_entry( helpentry = create.create_help_entry(
topicstr, self.rhs, category=category, locks=lockstring, aliases=aliases topicstr,
self.rhs,
category=category,
locks=lockstring,
aliases=aliases,
) )
self.caller.db._editing_help = helpentry self.caller.db._editing_help = helpentry
@ -422,7 +457,9 @@ class CmdSetHelp(COMMAND_DEFAULT_CLASS):
if "append" in switches or "merge" in switches or "extend" in switches: if "append" in switches or "merge" in switches or "extend" in switches:
# merge/append operations # merge/append operations
if not old_entry: if not old_entry:
self.msg("Could not find topic '%s'. You must give an exact name." % topicstr) self.msg(
"Could not find topic '%s'. You must give an exact name." % topicstr
)
return return
if not self.rhs: if not self.rhs:
self.msg("You must supply text to append/merge.") self.msg("You must supply text to append/merge.")
@ -469,7 +506,9 @@ class CmdSetHelp(COMMAND_DEFAULT_CLASS):
topicstr, self.rhs, category=category, locks=lockstring, aliases=aliases topicstr, self.rhs, category=category, locks=lockstring, aliases=aliases
) )
if new_entry: if new_entry:
self.msg("Topic '%s'%s was successfully created." % (topicstr, aliastxt)) self.msg(
"Topic '%s'%s was successfully created." % (topicstr, aliastxt)
)
if "edit" in switches: if "edit" in switches:
# open the line editor to edit the helptext # open the line editor to edit the helptext
self.caller.db._editing_help = new_entry self.caller.db._editing_help = new_entry
@ -484,5 +523,6 @@ class CmdSetHelp(COMMAND_DEFAULT_CLASS):
return return
else: else:
self.msg( self.msg(
"Error when creating topic '%s'%s! Contact an admin." % (topicstr, aliastxt) "Error when creating topic '%s'%s! Contact an admin."
% (topicstr, aliastxt)
) )

View file

@ -129,10 +129,14 @@ class MuxCommand(Command):
if switches and self.switch_options: if switches and self.switch_options:
valid_switches, unused_switches, extra_switches = [], [], [] valid_switches, unused_switches, extra_switches = [], [], []
for element in switches: for element in switches:
option_check = [opt for opt in self.switch_options if opt == element] option_check = [
opt for opt in self.switch_options if opt == element
]
if not option_check: if not option_check:
option_check = [ option_check = [
opt for opt in self.switch_options if opt.startswith(element) opt
for opt in self.switch_options
if opt.startswith(element)
] ]
match_count = len(option_check) match_count = len(option_check)
if match_count > 1: if match_count > 1:
@ -140,9 +144,13 @@ class MuxCommand(Command):
option_check option_check
) # Either the option provided is ambiguous, ) # Either the option provided is ambiguous,
elif match_count == 1: elif match_count == 1:
valid_switches.extend(option_check) # or it is a valid option abbreviation, valid_switches.extend(
option_check
) # or it is a valid option abbreviation,
elif match_count == 0: elif match_count == 0:
unused_switches.append(element) # or an extraneous option to be ignored. unused_switches.append(
element
) # or an extraneous option to be ignored.
if extra_switches: # User provided switches if extra_switches: # User provided switches
self.msg( self.msg(
"|g%s|n: |wAmbiguous switch supplied: Did you mean /|C%s|w?" "|g%s|n: |wAmbiguous switch supplied: Did you mean /|C%s|w?"
@ -154,13 +162,17 @@ class MuxCommand(Command):
'|g%s|n: |wExtra switch%s "/|C%s|w" ignored.' '|g%s|n: |wExtra switch%s "/|C%s|w" ignored.'
% (self.cmdstring, plural, "|n, /|C".join(unused_switches)) % (self.cmdstring, plural, "|n, /|C".join(unused_switches))
) )
switches = valid_switches # Only include valid_switches in command function call switches = (
valid_switches
) # Only include valid_switches in command function call
arglist = [arg.strip() for arg in args.split()] arglist = [arg.strip() for arg in args.split()]
# check for arg1, arg2, ... = argA, argB, ... constructs # check for arg1, arg2, ... = argA, argB, ... constructs
lhs, rhs = args.strip(), None lhs, rhs = args.strip(), None
if lhs: if lhs:
if delimiters and hasattr(delimiters, "__iter__"): # If delimiter is iterable, if delimiters and hasattr(
delimiters, "__iter__"
): # If delimiter is iterable,
best_split = delimiters[0] # (default to first delimiter) best_split = delimiters[0] # (default to first delimiter)
for this_split in delimiters: # try each delimiter for this_split in delimiters: # try each delimiter
if this_split in lhs: # to find first successful split if this_split in lhs: # to find first successful split
@ -192,11 +204,15 @@ class MuxCommand(Command):
# a special property "character" for the puppeted object, if any. This # a special property "character" for the puppeted object, if any. This
# is convenient for commands defined on the Account only. # is convenient for commands defined on the Account only.
if self.account_caller: if self.account_caller:
if utils.inherits_from(self.caller, "evennia.objects.objects.DefaultObject"): if utils.inherits_from(
self.caller, "evennia.objects.objects.DefaultObject"
):
# caller is an Object/Character # caller is an Object/Character
self.character = self.caller self.character = self.caller
self.caller = self.caller.account self.caller = self.caller.account
elif utils.inherits_from(self.caller, "evennia.accounts.accounts.DefaultAccount"): elif utils.inherits_from(
self.caller, "evennia.accounts.accounts.DefaultAccount"
):
# caller was already an Account # caller was already an Account
self.character = self.caller.get_puppet(self.session) self.character = self.caller.get_puppet(self.session)
else: else:
@ -209,7 +225,8 @@ class MuxCommand(Command):
to all the variables defined therein. to all the variables defined therein.
""" """
variables = "\n".join( variables = "\n".join(
" |w{}|n ({}): {}".format(key, type(val), val) for key, val in self.__dict__.items() " |w{}|n ({}): {}".format(key, type(val), val)
for key, val in self.__dict__.items()
) )
string = f""" string = f"""
Command {self} has no defined `func()` - showing on-command variables: No child func() defined for {self} - available variables: Command {self} has no defined `func()` - showing on-command variables: No child func() defined for {self} - available variables:
@ -236,7 +253,9 @@ Command {self} has no defined `func()` - showing on-command variables: No child
string += "cmd args (self.args): |w%s|n\n" % self.args string += "cmd args (self.args): |w%s|n\n" % self.args
string += "cmd switches (self.switches): |w%s|n\n" % self.switches string += "cmd switches (self.switches): |w%s|n\n" % self.switches
string += "cmd options (self.switch_options): |w%s|n\n" % self.switch_options string += "cmd options (self.switch_options): |w%s|n\n" % self.switch_options
string += "cmd parse left/right using (self.rhs_split): |w%s|n\n" % self.rhs_split string += (
"cmd parse left/right using (self.rhs_split): |w%s|n\n" % self.rhs_split
)
string += "space-separated arg list (self.arglist): |w%s|n\n" % self.arglist string += "space-separated arg list (self.arglist): |w%s|n\n" % self.arglist
string += "lhs, left-hand side of '=' (self.lhs): |w%s|n\n" % self.lhs string += "lhs, left-hand side of '=' (self.lhs): |w%s|n\n" % self.lhs
string += "lhs, comma separated (self.lhslist): |w%s|n\n" % self.lhslist string += "lhs, comma separated (self.lhslist): |w%s|n\n" % self.lhslist
@ -261,4 +280,6 @@ class MuxAccountCommand(MuxCommand):
character is actually attached to this Account and Session. character is actually attached to this Account and Session.
""" """
account_caller = True # Using MuxAccountCommand explicitly defaults the caller to an account account_caller = (
True
) # Using MuxAccountCommand explicitly defaults the caller to an account

View file

@ -103,7 +103,9 @@ class SystemMultimatch(COMMAND_DEFAULT_CLASS):
# evennia.commands.cmdparse.create_match for more details. # evennia.commands.cmdparse.create_match for more details.
matches = self.matches matches = self.matches
# at_search_result will itself msg the multimatch options to the caller. # at_search_result will itself msg the multimatch options to the caller.
at_search_result([match[2] for match in matches], self.caller, query=matches[0][0]) at_search_result(
[match[2] for match in matches], self.caller, query=matches[0][0]
)
# Command called when the command given at the command line # Command called when the command given at the command line

View file

@ -150,7 +150,12 @@ def _py_code(caller, buf):
string = "Executing code%s ..." % (" (measure timing)" if measure_time else "") string = "Executing code%s ..." % (" (measure timing)" if measure_time else "")
caller.msg(string) caller.msg(string)
_run_code_snippet( _run_code_snippet(
caller, buf, mode="exec", measure_time=measure_time, client_raw=client_raw, show_input=False caller,
buf,
mode="exec",
measure_time=measure_time,
client_raw=client_raw,
show_input=False,
) )
return True return True
@ -235,7 +240,9 @@ def _run_code_snippet(
for session in sessions: for session in sessions:
try: try:
caller.msg(ret, session=session, options={"raw": True, "client_raw": client_raw}) caller.msg(
ret, session=session, options={"raw": True, "client_raw": client_raw}
)
except TypeError: except TypeError:
caller.msg(ret, options={"raw": True, "client_raw": client_raw}) caller.msg(ret, options={"raw": True, "client_raw": client_raw})
@ -477,7 +484,9 @@ class CmdScripts(COMMAND_DEFAULT_CLASS):
if new_script: if new_script:
caller.msg("Global script %s was started successfully." % args) caller.msg("Global script %s was started successfully." % args)
else: else:
caller.msg("Global script %s could not start correctly. See logs." % args) caller.msg(
"Global script %s could not start correctly. See logs." % args
)
return return
# test first if this is a script match # test first if this is a script match
@ -498,7 +507,10 @@ class CmdScripts(COMMAND_DEFAULT_CLASS):
return return
if not scripts: if not scripts:
string = "No scripts found with a key '%s', or on an object named '%s'." % (args, args) string = "No scripts found with a key '%s', or on an object named '%s'." % (
args,
args,
)
caller.msg(string) caller.msg(string)
return return
@ -585,7 +597,9 @@ class CmdObjects(COMMAND_DEFAULT_CLASS):
nexits, nexits,
"%.2f" % ((float(nexits) / nobjs) * 100), "%.2f" % ((float(nexits) / nobjs) * 100),
) )
totaltable.add_row("Other", "", nother, "%.2f" % ((float(nother) / nobjs) * 100)) totaltable.add_row(
"Other", "", nother, "%.2f" % ((float(nother) / nobjs) * 100)
)
# typeclass table # typeclass table
typetable = self.styled_table( typetable = self.styled_table(
@ -597,9 +611,16 @@ class CmdObjects(COMMAND_DEFAULT_CLASS):
typetable.add_row(path, count, "%.2f" % ((float(count) / nobjs) * 100)) typetable.add_row(path, count, "%.2f" % ((float(count) / nobjs) * 100))
# last N table # last N table
objs = ObjectDB.objects.all().order_by("db_date_created")[max(0, nobjs - nlim) :] objs = ObjectDB.objects.all().order_by("db_date_created")[
max(0, nobjs - nlim) :
]
latesttable = self.styled_table( latesttable = self.styled_table(
"|wcreated|n", "|wdbref|n", "|wname|n", "|wtypeclass|n", align="l", border="table" "|wcreated|n",
"|wdbref|n",
"|wname|n",
"|wtypeclass|n",
align="l",
border="table",
) )
latesttable.align = "l" latesttable.align = "l"
for obj in objs: for obj in objs:
@ -607,7 +628,10 @@ class CmdObjects(COMMAND_DEFAULT_CLASS):
utils.datetime_format(obj.date_created), obj.dbref, obj.key, obj.path utils.datetime_format(obj.date_created), obj.dbref, obj.key, obj.path
) )
string = "\n|wObject subtype totals (out of %i Objects):|n\n%s" % (nobjs, totaltable) string = "\n|wObject subtype totals (out of %i Objects):|n\n%s" % (
nobjs,
totaltable,
)
string += "\n|wObject typeclass distribution:|n\n%s" % typetable string += "\n|wObject typeclass distribution:|n\n%s" % typetable
string += "\n|wLast %s Objects created:|n\n%s" % (min(nobjs, nlim), latesttable) string += "\n|wLast %s Objects created:|n\n%s" % (min(nobjs, nlim), latesttable)
caller.msg(string) caller.msg(string)
@ -660,7 +684,9 @@ class CmdAccounts(COMMAND_DEFAULT_CLASS):
return return
if len(accounts) > 1: if len(accounts) > 1:
string = "There were multiple matches:\n" string = "There were multiple matches:\n"
string += "\n".join(" %s %s" % (account.id, account.key) for account in accounts) string += "\n".join(
" %s %s" % (account.id, account.key) for account in accounts
)
self.msg(string) self.msg(string)
return return
account = accounts.first() account = accounts.first()
@ -709,9 +735,16 @@ class CmdAccounts(COMMAND_DEFAULT_CLASS):
for path, count in dbtotals.items(): for path, count in dbtotals.items():
typetable.add_row(path, count, "%.2f" % ((float(count) / naccounts) * 100)) typetable.add_row(path, count, "%.2f" % ((float(count) / naccounts) * 100))
# last N table # last N table
plyrs = AccountDB.objects.all().order_by("db_date_created")[max(0, naccounts - nlim) :] plyrs = AccountDB.objects.all().order_by("db_date_created")[
max(0, naccounts - nlim) :
]
latesttable = self.styled_table( latesttable = self.styled_table(
"|wcreated|n", "|wdbref|n", "|wname|n", "|wtypeclass|n", border="cells", align="l" "|wcreated|n",
"|wdbref|n",
"|wname|n",
"|wtypeclass|n",
border="cells",
align="l",
) )
for ply in plyrs: for ply in plyrs:
latesttable.add_row( latesttable.add_row(
@ -719,7 +752,10 @@ class CmdAccounts(COMMAND_DEFAULT_CLASS):
) )
string = "\n|wAccount typeclass distribution:|n\n%s" % typetable string = "\n|wAccount typeclass distribution:|n\n%s" % typetable
string += "\n|wLast %s Accounts created:|n\n%s" % (min(naccounts, nlim), latesttable) string += "\n|wLast %s Accounts created:|n\n%s" % (
min(naccounts, nlim),
latesttable,
)
caller.msg(string) caller.msg(string)
@ -769,7 +805,9 @@ class CmdService(COMMAND_DEFAULT_CLASS):
"|wService|n (use services/start|stop|delete)", "|wstatus", align="l" "|wService|n (use services/start|stop|delete)", "|wstatus", align="l"
) )
for service in service_collection.services: for service in service_collection.services:
table.add_row(service.name, service.running and "|gRunning" or "|rNot Running") table.add_row(
service.name, service.running and "|gRunning" or "|rNot Running"
)
caller.msg(str(table)) caller.msg(str(table))
return return
@ -779,7 +817,9 @@ class CmdService(COMMAND_DEFAULT_CLASS):
service = service_collection.getServiceNamed(self.args) service = service_collection.getServiceNamed(self.args)
except Exception: except Exception:
string = "Invalid service name. This command is case-sensitive. " string = "Invalid service name. This command is case-sensitive. "
string += "See service/list for valid service name (enter the full name exactly)." string += (
"See service/list for valid service name (enter the full name exactly)."
)
caller.msg(string) caller.msg(string)
return return
@ -793,7 +833,9 @@ class CmdService(COMMAND_DEFAULT_CLASS):
return return
if service.name[:7] == "Evennia": if service.name[:7] == "Evennia":
if delmode: if delmode:
caller.msg("You cannot remove a core Evennia service (named 'Evennia***').") caller.msg(
"You cannot remove a core Evennia service (named 'Evennia***')."
)
return return
string = "You seem to be shutting down a core Evennia service (named 'Evennia***'). Note that" string = "You seem to be shutting down a core Evennia service (named 'Evennia***'). Note that"
string += "stopping some TCP port services will *not* disconnect users *already*" string += "stopping some TCP port services will *not* disconnect users *already*"
@ -885,7 +927,9 @@ class CmdTime(COMMAND_DEFAULT_CLASS):
table1.add_row("Current uptime", utils.time_format(gametime.uptime(), 3)) table1.add_row("Current uptime", utils.time_format(gametime.uptime(), 3))
table1.add_row("Portal uptime", utils.time_format(gametime.portal_uptime(), 3)) table1.add_row("Portal uptime", utils.time_format(gametime.portal_uptime(), 3))
table1.add_row("Total runtime", utils.time_format(gametime.runtime(), 2)) table1.add_row("Total runtime", utils.time_format(gametime.runtime(), 2))
table1.add_row("First start", datetime.datetime.fromtimestamp(gametime.server_epoch())) table1.add_row(
"First start", datetime.datetime.fromtimestamp(gametime.server_epoch())
)
table1.add_row("Current time", datetime.datetime.now()) table1.add_row("Current time", datetime.datetime.now())
table1.reformat_column(0, width=30) table1.reformat_column(0, width=30)
table2 = self.styled_table( table2 = self.styled_table(
@ -895,11 +939,14 @@ class CmdTime(COMMAND_DEFAULT_CLASS):
width=77, width=77,
border_top=0, border_top=0,
) )
epochtxt = "Epoch (%s)" % ("from settings" if settings.TIME_GAME_EPOCH else "server start") epochtxt = "Epoch (%s)" % (
"from settings" if settings.TIME_GAME_EPOCH else "server start"
)
table2.add_row(epochtxt, datetime.datetime.fromtimestamp(gametime.game_epoch())) table2.add_row(epochtxt, datetime.datetime.fromtimestamp(gametime.game_epoch()))
table2.add_row("Total time passed:", utils.time_format(gametime.gametime(), 2)) table2.add_row("Total time passed:", utils.time_format(gametime.gametime(), 2))
table2.add_row( table2.add_row(
"Current time ", datetime.datetime.fromtimestamp(gametime.gametime(absolute=True)) "Current time ",
datetime.datetime.fromtimestamp(gametime.gametime(absolute=True)),
) )
table2.reformat_column(0, width=30) table2.reformat_column(0, width=30)
self.caller.msg(str(table1) + "\n" + str(table2)) self.caller.msg(str(table1) + "\n" + str(table2))
@ -996,7 +1043,9 @@ class CmdServerLoad(COMMAND_DEFAULT_CLASS):
# Display table # Display table
loadtable = self.styled_table("property", "statistic", align="l") loadtable = self.styled_table("property", "statistic", align="l")
loadtable.add_row("Total CPU load", "%g %%" % loadavg) loadtable.add_row("Total CPU load", "%g %%" % loadavg)
loadtable.add_row("Total computer memory usage", "%g MB (%g%%)" % (rmem, pmem)) loadtable.add_row(
"Total computer memory usage", "%g MB (%g%%)" % (rmem, pmem)
)
loadtable.add_row("Process ID", "%g" % pid), loadtable.add_row("Process ID", "%g" % pid),
else: else:
loadtable = ( loadtable = (
@ -1013,10 +1062,12 @@ class CmdServerLoad(COMMAND_DEFAULT_CLASS):
loadavg = os.getloadavg()[0] loadavg = os.getloadavg()[0]
rmem = ( rmem = (
float(os.popen("ps -p %d -o %s | tail -1" % (pid, "rss")).read()) / 1000.0 float(os.popen("ps -p %d -o %s | tail -1" % (pid, "rss")).read())
/ 1000.0
) # resident memory ) # resident memory
vmem = ( vmem = (
float(os.popen("ps -p %d -o %s | tail -1" % (pid, "vsz")).read()) / 1000.0 float(os.popen("ps -p %d -o %s | tail -1" % (pid, "vsz")).read())
/ 1000.0
) # virtual memory ) # virtual memory
pmem = float( pmem = float(
os.popen("ps -p %d -o %s | tail -1" % (pid, "%mem")).read() os.popen("ps -p %d -o %s | tail -1" % (pid, "%mem")).read()
@ -1048,9 +1099,12 @@ class CmdServerLoad(COMMAND_DEFAULT_CLASS):
% (rusage.ru_majflt, rusage.ru_minflt, rusage.ru_nswap), % (rusage.ru_majflt, rusage.ru_minflt, rusage.ru_nswap),
) )
loadtable.add_row( loadtable.add_row(
"Disk I/O", "%g reads, %g writes" % (rusage.ru_inblock, rusage.ru_oublock) "Disk I/O",
"%g reads, %g writes" % (rusage.ru_inblock, rusage.ru_oublock),
)
loadtable.add_row(
"Network I/O", "%g in, %g out" % (rusage.ru_msgrcv, rusage.ru_msgsnd)
) )
loadtable.add_row("Network I/O", "%g in, %g out" % (rusage.ru_msgrcv, rusage.ru_msgsnd))
loadtable.add_row( loadtable.add_row(
"Context switching", "Context switching",
"%g vol, %g forced, %g signals" "%g vol, %g forced, %g signals"
@ -1070,7 +1124,9 @@ class CmdServerLoad(COMMAND_DEFAULT_CLASS):
) )
memtable = self.styled_table("entity name", "number", "idmapper %", align="l") memtable = self.styled_table("entity name", "number", "idmapper %", align="l")
for tup in sorted_cache: for tup in sorted_cache:
memtable.add_row(tup[0], "%i" % tup[1], "%.2f" % (float(tup[1]) / total_num * 100)) memtable.add_row(
tup[0], "%i" % tup[1], "%.2f" % (float(tup[1]) / total_num * 100)
)
string += "\n|w Entity idmapper cache:|n %i items\n%s" % (total_num, memtable) string += "\n|w Entity idmapper cache:|n %i items\n%s" % (total_num, memtable)
@ -1102,14 +1158,18 @@ class CmdTickers(COMMAND_DEFAULT_CLASS):
if not all_subs: if not all_subs:
self.caller.msg("No tickers are currently active.") self.caller.msg("No tickers are currently active.")
return return
table = self.styled_table("interval (s)", "object", "path/methodname", "idstring", "db") table = self.styled_table(
"interval (s)", "object", "path/methodname", "idstring", "db"
)
for sub in all_subs: for sub in all_subs:
table.add_row( table.add_row(
sub[3], sub[3],
"%s%s" "%s%s"
% ( % (
sub[0] or "[None]", sub[0] or "[None]",
sub[0] and " (#%s)" % (sub[0].id if hasattr(sub[0], "id") else "") or "", sub[0]
and " (#%s)" % (sub[0].id if hasattr(sub[0], "id") else "")
or "",
), ),
sub[1] if sub[1] else sub[2], sub[1] if sub[1] else sub[2],
sub[4] or "[Unset]", sub[4] or "[Unset]",

View file

@ -99,7 +99,9 @@ class CommandTest(EvenniaTest):
cmdobj.cmdset = cmdset cmdobj.cmdset = cmdset
cmdobj.session = SESSIONS.session_from_sessid(1) cmdobj.session = SESSIONS.session_from_sessid(1)
cmdobj.account = self.account cmdobj.account = self.account
cmdobj.raw_string = raw_string if raw_string is not None else cmdobj.key + " " + args cmdobj.raw_string = (
raw_string if raw_string is not None else cmdobj.key + " " + args
)
cmdobj.obj = obj or (caller if caller else self.char1) cmdobj.obj = obj or (caller if caller else self.char1)
# test # test
old_msg = receiver.msg old_msg = receiver.msg
@ -140,14 +142,18 @@ class CommandTest(EvenniaTest):
for name, args, kwargs in receiver.msg.mock_calls for name, args, kwargs in receiver.msg.mock_calls
] ]
# Get the first element of a tuple if msg received a tuple instead of a string # Get the first element of a tuple if msg received a tuple instead of a string
stored_msg = [str(smsg[0]) if isinstance(smsg, tuple) else str(smsg) for smsg in stored_msg] stored_msg = [
str(smsg[0]) if isinstance(smsg, tuple) else str(smsg)
for smsg in stored_msg
]
if msg is not None: if msg is not None:
msg = str(msg) # to be safe, e.g. `py` command may return ints msg = str(msg) # to be safe, e.g. `py` command may return ints
# set our separator for returned messages based on parsing ansi or not # set our separator for returned messages based on parsing ansi or not
msg_sep = "|" if noansi else "||" msg_sep = "|" if noansi else "||"
# Have to strip ansi for each returned message for the regex to handle it correctly # Have to strip ansi for each returned message for the regex to handle it correctly
returned_msg = msg_sep.join( returned_msg = msg_sep.join(
_RE.sub("", ansi.parse_ansi(mess, strip_ansi=noansi)) for mess in stored_msg _RE.sub("", ansi.parse_ansi(mess, strip_ansi=noansi))
for mess in stored_msg
).strip() ).strip()
if msg == "" and returned_msg or not returned_msg.startswith(msg.strip()): if msg == "" and returned_msg or not returned_msg.startswith(msg.strip()):
sep1 = "\n" + "=" * 30 + "Wanted message" + "=" * 34 + "\n" sep1 = "\n" + "=" * 30 + "Wanted message" + "=" * 34 + "\n"
@ -202,8 +208,12 @@ class TestGeneral(CommandTest):
self.assertEqual( self.assertEqual(
"testaliasedstring2", self.char1.nicks.get("testalias", category="account") "testaliasedstring2", self.char1.nicks.get("testalias", category="account")
) )
self.assertEqual(None, self.char1.account.nicks.get("testalias", category="account")) self.assertEqual(
self.assertEqual("testaliasedstring3", self.char1.nicks.get("testalias", category="object")) None, self.char1.account.nicks.get("testalias", category="account")
)
self.assertEqual(
"testaliasedstring3", self.char1.nicks.get("testalias", category="object")
)
def test_get_and_drop(self): def test_get_and_drop(self):
self.call(general.CmdGet(), "Obj", "You pick up Obj.") self.call(general.CmdGet(), "Obj", "You pick up Obj.")
@ -230,9 +240,13 @@ class TestGeneral(CommandTest):
"Switches matched: ['test', 'testswitch', 'testswitch2']", "Switches matched: ['test', 'testswitch', 'testswitch2']",
) )
self.call(CmdTest(), "/test", "Switches matched: ['test']") self.call(CmdTest(), "/test", "Switches matched: ['test']")
self.call(CmdTest(), "/test/testswitch", "Switches matched: ['test', 'testswitch']")
self.call( self.call(
CmdTest(), "/testswitch/testswitch2", "Switches matched: ['testswitch', 'testswitch2']" CmdTest(), "/test/testswitch", "Switches matched: ['test', 'testswitch']"
)
self.call(
CmdTest(),
"/testswitch/testswitch2",
"Switches matched: ['testswitch', 'testswitch2']",
) )
self.call(CmdTest(), "/testswitch", "Switches matched: ['testswitch']") self.call(CmdTest(), "/testswitch", "Switches matched: ['testswitch']")
self.call(CmdTest(), "/testswitch2", "Switches matched: ['testswitch2']") self.call(CmdTest(), "/testswitch2", "Switches matched: ['testswitch2']")
@ -274,7 +288,9 @@ class TestHelp(CommandTest):
"testhelp, General = This is a test", "testhelp, General = This is a test",
"Topic 'testhelp' was successfully created.", "Topic 'testhelp' was successfully created.",
) )
self.call(help.CmdHelp(), "testhelp", "Help for testhelp", cmdset=CharacterCmdSet()) self.call(
help.CmdHelp(), "testhelp", "Help for testhelp", cmdset=CharacterCmdSet()
)
class TestSystem(CommandTest): class TestSystem(CommandTest):
@ -332,7 +348,10 @@ class TestAccount(CommandTest):
def test_ooc_look(self): def test_ooc_look(self):
if settings.MULTISESSION_MODE < 2: if settings.MULTISESSION_MODE < 2:
self.call( self.call(
account.CmdOOCLook(), "", "You are out-of-character (OOC).", caller=self.account account.CmdOOCLook(),
"",
"You are out-of-character (OOC).",
caller=self.account,
) )
if settings.MULTISESSION_MODE == 2: if settings.MULTISESSION_MODE == 2:
self.call( self.call(
@ -348,7 +367,11 @@ class TestAccount(CommandTest):
def test_ic(self): def test_ic(self):
self.account.unpuppet_object(self.session) self.account.unpuppet_object(self.session)
self.call( self.call(
account.CmdIC(), "Char", "You become Char.", caller=self.account, receiver=self.char1 account.CmdIC(),
"Char",
"You become Char.",
caller=self.account,
receiver=self.char1,
) )
def test_password(self): def test_password(self):
@ -367,11 +390,16 @@ class TestAccount(CommandTest):
def test_quit(self): def test_quit(self):
self.call( self.call(
account.CmdQuit(), "", "Quitting. Hope to see you again, soon.", caller=self.account account.CmdQuit(),
"",
"Quitting. Hope to see you again, soon.",
caller=self.account,
) )
def test_sessions(self): def test_sessions(self):
self.call(account.CmdSessions(), "", "Your current session(s):", caller=self.account) self.call(
account.CmdSessions(), "", "Your current session(s):", caller=self.account
)
def test_color_test(self): def test_color_test(self):
self.call(account.CmdColorTest(), "ansi", "ANSI colors:", caller=self.account) self.call(account.CmdColorTest(), "ansi", "ANSI colors:", caller=self.account)
@ -456,7 +484,11 @@ class TestBuilding(CommandTest):
self.call(building.CmdExamine(), "*TestAccount", "Name/key: TestAccount") self.call(building.CmdExamine(), "*TestAccount", "Name/key: TestAccount")
self.char1.db.test = "testval" self.char1.db.test = "testval"
self.call(building.CmdExamine(), "self/test", "Persistent attributes:\n test = testval") self.call(
building.CmdExamine(),
"self/test",
"Persistent attributes:\n test = testval",
)
self.call(building.CmdExamine(), "NotFound", "Could not find 'NotFound'.") self.call(building.CmdExamine(), "NotFound", "Could not find 'NotFound'.")
self.call(building.CmdExamine(), "out", "Name/key: out") self.call(building.CmdExamine(), "out", "Name/key: out")
@ -476,7 +508,11 @@ class TestBuilding(CommandTest):
self.call(building.CmdSetObjAlias(), "", "Usage: ") self.call(building.CmdSetObjAlias(), "", "Usage: ")
self.call(building.CmdSetObjAlias(), "NotFound =", "Could not find 'NotFound'.") self.call(building.CmdSetObjAlias(), "NotFound =", "Could not find 'NotFound'.")
self.call(building.CmdSetObjAlias(), "Obj", "Aliases for Obj(#{}): 'testobj1b'".format(oid)) self.call(
building.CmdSetObjAlias(),
"Obj",
"Aliases for Obj(#{}): 'testobj1b'".format(oid),
)
self.call(building.CmdSetObjAlias(), "Obj2 =", "Cleared aliases from Obj2") self.call(building.CmdSetObjAlias(), "Obj2 =", "Cleared aliases from Obj2")
self.call(building.CmdSetObjAlias(), "Obj2 =", "No aliases to clear.") self.call(building.CmdSetObjAlias(), "Obj2 =", "No aliases to clear.")
@ -487,7 +523,11 @@ class TestBuilding(CommandTest):
"Copied Obj to 'TestObj3' (aliases: ['TestObj3b']", "Copied Obj to 'TestObj3' (aliases: ['TestObj3b']",
) )
self.call(building.CmdCopy(), "", "Usage: ") self.call(building.CmdCopy(), "", "Usage: ")
self.call(building.CmdCopy(), "Obj", "Identical copy of Obj, named 'Obj_copy' was created.") self.call(
building.CmdCopy(),
"Obj",
"Identical copy of Obj, named 'Obj_copy' was created.",
)
self.call(building.CmdCopy(), "NotFound = Foo", "Could not find 'NotFound'.") self.call(building.CmdCopy(), "NotFound = Foo", "Could not find 'NotFound'.")
def test_attribute_commands(self): def test_attribute_commands(self):
@ -502,8 +542,14 @@ class TestBuilding(CommandTest):
'Obj2/test2="value2"', 'Obj2/test2="value2"',
"Created attribute Obj2/test2 = 'value2'", "Created attribute Obj2/test2 = 'value2'",
) )
self.call(building.CmdSetAttribute(), "Obj2/test2", "Attribute Obj2/test2 = value2") self.call(
self.call(building.CmdSetAttribute(), "Obj2/NotFound", "Obj2 has no attribute 'notfound'.") building.CmdSetAttribute(), "Obj2/test2", "Attribute Obj2/test2 = value2"
)
self.call(
building.CmdSetAttribute(),
"Obj2/NotFound",
"Obj2 has no attribute 'notfound'.",
)
with mock.patch("evennia.commands.default.building.EvEditor") as mock_ed: with mock.patch("evennia.commands.default.building.EvEditor") as mock_ed:
self.call(building.CmdSetAttribute(), "/edit Obj2/test3") self.call(building.CmdSetAttribute(), "/edit Obj2/test3")
@ -527,35 +573,59 @@ class TestBuilding(CommandTest):
"(value: 'value2')", "(value: 'value2')",
) )
self.call(building.CmdMvAttr(), "", "Usage: ") self.call(building.CmdMvAttr(), "", "Usage: ")
self.call(building.CmdMvAttr(), "Obj2/test2 = Obj/test3", "Moved Obj2.test2 -> Obj.test3") self.call(
building.CmdMvAttr(),
"Obj2/test2 = Obj/test3",
"Moved Obj2.test2 -> Obj.test3",
)
self.call(building.CmdCpAttr(), "", "Usage: ") self.call(building.CmdCpAttr(), "", "Usage: ")
self.call(building.CmdCpAttr(), "Obj/test1 = Obj2/test3", "Copied Obj.test1 -> Obj2.test3") self.call(
building.CmdCpAttr(),
"Obj/test1 = Obj2/test3",
"Copied Obj.test1 -> Obj2.test3",
)
self.call(building.CmdWipe(), "", "Usage: ") self.call(building.CmdWipe(), "", "Usage: ")
self.call(building.CmdWipe(), "Obj2/test2/test3", "Wiped attributes test2,test3 on Obj2.") self.call(
building.CmdWipe(),
"Obj2/test2/test3",
"Wiped attributes test2,test3 on Obj2.",
)
self.call(building.CmdWipe(), "Obj2", "Wiped all attributes on Obj2.") self.call(building.CmdWipe(), "Obj2", "Wiped all attributes on Obj2.")
def test_nested_attribute_commands(self): def test_nested_attribute_commands(self):
# list - adding white space proves real parsing # list - adding white space proves real parsing
self.call( self.call(
building.CmdSetAttribute(), "Obj/test1=[1,2]", "Created attribute Obj/test1 = [1, 2]" building.CmdSetAttribute(),
"Obj/test1=[1,2]",
"Created attribute Obj/test1 = [1, 2]",
)
self.call(
building.CmdSetAttribute(), "Obj/test1", "Attribute Obj/test1 = [1, 2]"
)
self.call(
building.CmdSetAttribute(), "Obj/test1[0]", "Attribute Obj/test1[0] = 1"
)
self.call(
building.CmdSetAttribute(), "Obj/test1[1]", "Attribute Obj/test1[1] = 2"
) )
self.call(building.CmdSetAttribute(), "Obj/test1", "Attribute Obj/test1 = [1, 2]")
self.call(building.CmdSetAttribute(), "Obj/test1[0]", "Attribute Obj/test1[0] = 1")
self.call(building.CmdSetAttribute(), "Obj/test1[1]", "Attribute Obj/test1[1] = 2")
self.call( self.call(
building.CmdSetAttribute(), building.CmdSetAttribute(),
"Obj/test1[0] = 99", "Obj/test1[0] = 99",
"Modified attribute Obj/test1 = [99, 2]", "Modified attribute Obj/test1 = [99, 2]",
) )
self.call(building.CmdSetAttribute(), "Obj/test1[0]", "Attribute Obj/test1[0] = 99") self.call(
building.CmdSetAttribute(), "Obj/test1[0]", "Attribute Obj/test1[0] = 99"
)
# list delete # list delete
self.call( self.call(
building.CmdSetAttribute(), building.CmdSetAttribute(),
"Obj/test1[0] =", "Obj/test1[0] =",
"Deleted attribute 'test1[0]' (= nested) from Obj.", "Deleted attribute 'test1[0]' (= nested) from Obj.",
) )
self.call(building.CmdSetAttribute(), "Obj/test1[0]", "Attribute Obj/test1[0] = 2") self.call(
building.CmdSetAttribute(), "Obj/test1[0]", "Attribute Obj/test1[0] = 2"
)
self.call( self.call(
building.CmdSetAttribute(), building.CmdSetAttribute(),
"Obj/test1[1]", "Obj/test1[1]",
@ -586,17 +656,35 @@ class TestBuilding(CommandTest):
"Created attribute Obj/test2 = {'one': 1, 'two': 2}", "Created attribute Obj/test2 = {'one': 1, 'two': 2}",
) )
self.call( self.call(
building.CmdSetAttribute(), "Obj/test2", "Attribute Obj/test2 = {'one': 1, 'two': 2}" building.CmdSetAttribute(),
"Obj/test2",
"Attribute Obj/test2 = {'one': 1, 'two': 2}",
)
self.call(
building.CmdSetAttribute(),
"Obj/test2['one']",
"Attribute Obj/test2['one'] = 1",
)
self.call(
building.CmdSetAttribute(),
"Obj/test2['one]",
"Attribute Obj/test2['one] = 1",
) )
self.call(building.CmdSetAttribute(), "Obj/test2['one']", "Attribute Obj/test2['one'] = 1")
self.call(building.CmdSetAttribute(), "Obj/test2['one]", "Attribute Obj/test2['one] = 1")
self.call( self.call(
building.CmdSetAttribute(), building.CmdSetAttribute(),
"Obj/test2['one']=99", "Obj/test2['one']=99",
"Modified attribute Obj/test2 = {'one': 99, 'two': 2}", "Modified attribute Obj/test2 = {'one': 99, 'two': 2}",
) )
self.call(building.CmdSetAttribute(), "Obj/test2['one']", "Attribute Obj/test2['one'] = 99") self.call(
self.call(building.CmdSetAttribute(), "Obj/test2['two']", "Attribute Obj/test2['two'] = 2") building.CmdSetAttribute(),
"Obj/test2['one']",
"Attribute Obj/test2['one'] = 99",
)
self.call(
building.CmdSetAttribute(),
"Obj/test2['two']",
"Attribute Obj/test2['two'] = 2",
)
self.call( self.call(
building.CmdSetAttribute(), building.CmdSetAttribute(),
"Obj/test2[+'three']", "Obj/test2[+'three']",
@ -629,7 +717,9 @@ class TestBuilding(CommandTest):
"Obj has no attribute 'test2['two']'. (Nested lookups attempted)", "Obj has no attribute 'test2['two']'. (Nested lookups attempted)",
) )
self.call( self.call(
building.CmdSetAttribute(), "Obj/test2", "Attribute Obj/test2 = {'one': 99, 'three': 3}" building.CmdSetAttribute(),
"Obj/test2",
"Attribute Obj/test2 = {'one': 99, 'three': 3}",
) )
self.call( self.call(
building.CmdSetAttribute(), building.CmdSetAttribute(),
@ -654,7 +744,9 @@ class TestBuilding(CommandTest):
# tuple # tuple
self.call( self.call(
building.CmdSetAttribute(), "Obj/tup = (1,2)", "Created attribute Obj/tup = (1, 2)" building.CmdSetAttribute(),
"Obj/tup = (1,2)",
"Created attribute Obj/tup = (1, 2)",
) )
self.call( self.call(
building.CmdSetAttribute(), building.CmdSetAttribute(),
@ -685,15 +777,23 @@ class TestBuilding(CommandTest):
"Created attribute Obj/test3 = [{'one': 1}]", "Created attribute Obj/test3 = [{'one': 1}]",
) )
self.call( self.call(
building.CmdSetAttribute(), "Obj/test3[0]['one']", "Attribute Obj/test3[0]['one'] = 1" building.CmdSetAttribute(),
"Obj/test3[0]['one']",
"Attribute Obj/test3[0]['one'] = 1",
)
self.call(
building.CmdSetAttribute(),
"Obj/test3[0]",
"Attribute Obj/test3[0] = {'one': 1}",
) )
self.call(building.CmdSetAttribute(), "Obj/test3[0]", "Attribute Obj/test3[0] = {'one': 1}")
self.call( self.call(
building.CmdSetAttribute(), building.CmdSetAttribute(),
"Obj/test3[0]['one'] =", "Obj/test3[0]['one'] =",
"Deleted attribute 'test3[0]['one']' (= nested) from Obj.", "Deleted attribute 'test3[0]['one']' (= nested) from Obj.",
) )
self.call(building.CmdSetAttribute(), "Obj/test3[0]", "Attribute Obj/test3[0] = {}") self.call(
building.CmdSetAttribute(), "Obj/test3[0]", "Attribute Obj/test3[0] = {}"
)
self.call(building.CmdSetAttribute(), "Obj/test3", "Attribute Obj/test3 = [{}]") self.call(building.CmdSetAttribute(), "Obj/test3", "Attribute Obj/test3 = [{}]")
# Naughty keys # Naughty keys
@ -702,23 +802,35 @@ class TestBuilding(CommandTest):
"Obj/test4[0]='foo'", "Obj/test4[0]='foo'",
"Created attribute Obj/test4[0] = 'foo'", "Created attribute Obj/test4[0] = 'foo'",
) )
self.call(building.CmdSetAttribute(), "Obj/test4[0]", "Attribute Obj/test4[0] = foo") self.call(
building.CmdSetAttribute(), "Obj/test4[0]", "Attribute Obj/test4[0] = foo"
)
self.call( self.call(
building.CmdSetAttribute(), building.CmdSetAttribute(),
"Obj/test4=[{'one': 1}]", "Obj/test4=[{'one': 1}]",
"Created attribute Obj/test4 = [{'one': 1}]", "Created attribute Obj/test4 = [{'one': 1}]",
) )
self.call( self.call(
building.CmdSetAttribute(), "Obj/test4[0]['one']", "Attribute Obj/test4[0]['one'] = 1" building.CmdSetAttribute(),
"Obj/test4[0]['one']",
"Attribute Obj/test4[0]['one'] = 1",
) )
# Prefer nested items # Prefer nested items
self.call(building.CmdSetAttribute(), "Obj/test4[0]", "Attribute Obj/test4[0] = {'one': 1}")
self.call( self.call(
building.CmdSetAttribute(), "Obj/test4[0]['one']", "Attribute Obj/test4[0]['one'] = 1" building.CmdSetAttribute(),
"Obj/test4[0]",
"Attribute Obj/test4[0] = {'one': 1}",
)
self.call(
building.CmdSetAttribute(),
"Obj/test4[0]['one']",
"Attribute Obj/test4[0]['one'] = 1",
) )
# Restored access # Restored access
self.call(building.CmdWipe(), "Obj/test4", "Wiped attributes test4 on Obj.") self.call(building.CmdWipe(), "Obj/test4", "Wiped attributes test4 on Obj.")
self.call(building.CmdSetAttribute(), "Obj/test4[0]", "Attribute Obj/test4[0] = foo") self.call(
building.CmdSetAttribute(), "Obj/test4[0]", "Attribute Obj/test4[0] = foo"
)
self.call( self.call(
building.CmdSetAttribute(), building.CmdSetAttribute(),
"Obj/test4[0]['one']", "Obj/test4[0]['one']",
@ -736,7 +848,11 @@ class TestBuilding(CommandTest):
# duplicate keys don't cause issues # duplicate keys don't cause issues
"test5[0][0]": [("test5", [0, 0]), ("test5[0]", [0]), ("test5[0][0]", [])], "test5[0][0]": [("test5", [0, 0]), ("test5[0]", [0]), ("test5[0][0]", [])],
# String ints preserved # String ints preserved
'test6["0"][0]': [("test6", ["0", 0]), ('test6["0"]', [0]), ('test6["0"][0]', [])], 'test6["0"][0]': [
("test6", ["0", 0]),
('test6["0"]', [0]),
('test6["0"][0]', []),
],
# Unmatched [] # Unmatched []
"test7[dict": [("test7[dict", [])], "test7[dict": [("test7[dict", [])],
} }
@ -776,16 +892,24 @@ class TestBuilding(CommandTest):
"*TestAccount=TestAccountRenamed", "*TestAccount=TestAccountRenamed",
"Account's name changed to 'TestAccountRenamed'.", "Account's name changed to 'TestAccountRenamed'.",
) )
self.call(building.CmdName(), "*NotFound=TestAccountRenamed", "Could not find '*NotFound'")
self.call( self.call(
building.CmdName(), "Obj3=Obj4;foo;bar", "Object's name changed to 'Obj4' (foo, bar)." building.CmdName(),
"*NotFound=TestAccountRenamed",
"Could not find '*NotFound'",
)
self.call(
building.CmdName(),
"Obj3=Obj4;foo;bar",
"Object's name changed to 'Obj4' (foo, bar).",
) )
self.call(building.CmdName(), "Obj4=", "No names or aliases defined!") self.call(building.CmdName(), "Obj4=", "No names or aliases defined!")
def test_desc(self): def test_desc(self):
oid = self.obj2.id oid = self.obj2.id
self.call( self.call(
building.CmdDesc(), "Obj2=TestDesc", "The description was set on Obj2(#{}).".format(oid) building.CmdDesc(),
"Obj2=TestDesc",
"The description was set on Obj2(#{}).".format(oid),
) )
self.call(building.CmdDesc(), "", "Usage: ") self.call(building.CmdDesc(), "", "Usage: ")
@ -807,7 +931,11 @@ class TestBuilding(CommandTest):
oid = self.obj2.id oid = self.obj2.id
o2d = self.obj2.db.desc o2d = self.obj2.db.desc
r1d = self.room1.db.desc r1d = self.room1.db.desc
self.call(building.CmdDesc(), "Obj2=", "The description was set on Obj2(#{}).".format(oid)) self.call(
building.CmdDesc(),
"Obj2=",
"The description was set on Obj2(#{}).".format(oid),
)
assert self.obj2.db.desc == "" and self.obj2.db.desc != o2d assert self.obj2.db.desc == "" and self.obj2.db.desc != o2d
assert self.room1.db.desc == r1d assert self.room1.db.desc == r1d
@ -816,7 +944,11 @@ class TestBuilding(CommandTest):
rid = self.room1.id rid = self.room1.id
o2d = self.obj2.db.desc o2d = self.obj2.db.desc
r1d = self.room1.db.desc r1d = self.room1.db.desc
self.call(building.CmdDesc(), "Obj2", "The description was set on Room(#{}).".format(rid)) self.call(
building.CmdDesc(),
"Obj2",
"The description was set on Room(#{}).".format(rid),
)
assert self.obj2.db.desc == o2d assert self.obj2.db.desc == o2d
assert self.room1.db.desc == "Obj2" and self.room1.db.desc != r1d assert self.room1.db.desc == "Obj2" and self.room1.db.desc != r1d
@ -858,14 +990,22 @@ class TestBuilding(CommandTest):
) )
def test_dig(self): def test_dig(self):
self.call(building.CmdDig(), "TestRoom1=testroom;tr,back;b", "Created room TestRoom1") self.call(
building.CmdDig(), "TestRoom1=testroom;tr,back;b", "Created room TestRoom1"
)
self.call(building.CmdDig(), "", "Usage: ") self.call(building.CmdDig(), "", "Usage: ")
def test_tunnel(self): def test_tunnel(self):
self.call(building.CmdTunnel(), "n = TestRoom2;test2", "Created room TestRoom2") self.call(building.CmdTunnel(), "n = TestRoom2;test2", "Created room TestRoom2")
self.call(building.CmdTunnel(), "", "Usage: ") self.call(building.CmdTunnel(), "", "Usage: ")
self.call(building.CmdTunnel(), "foo = TestRoom2;test2", "tunnel can only understand the") self.call(
self.call(building.CmdTunnel(), "/tel e = TestRoom3;test3", "Created room TestRoom3") building.CmdTunnel(),
"foo = TestRoom2;test2",
"tunnel can only understand the",
)
self.call(
building.CmdTunnel(), "/tel e = TestRoom3;test3", "Created room TestRoom3"
)
DefaultRoom.objects.get_family(db_key="TestRoom3") DefaultRoom.objects.get_family(db_key="TestRoom3")
exits = DefaultExit.objects.filter_family(db_key__in=("east", "west")) exits = DefaultExit.objects.filter_family(db_key__in=("east", "west"))
self.assertEqual(len(exits), 2) self.assertEqual(len(exits), 2)
@ -879,20 +1019,32 @@ class TestBuilding(CommandTest):
def test_exit_commands(self): def test_exit_commands(self):
self.call( self.call(
building.CmdOpen(), "TestExit1=Room2", "Created new Exit 'TestExit1' from Room to Room2" building.CmdOpen(),
"TestExit1=Room2",
"Created new Exit 'TestExit1' from Room to Room2",
)
self.call(
building.CmdLink(),
"TestExit1=Room",
"Link created TestExit1 -> Room (one way).",
) )
self.call(building.CmdLink(), "TestExit1=Room", "Link created TestExit1 -> Room (one way).")
self.call(building.CmdUnLink(), "", "Usage: ") self.call(building.CmdUnLink(), "", "Usage: ")
self.call(building.CmdLink(), "NotFound", "Could not find 'NotFound'.") self.call(building.CmdLink(), "NotFound", "Could not find 'NotFound'.")
self.call(building.CmdLink(), "TestExit", "TestExit1 is an exit to Room.") self.call(building.CmdLink(), "TestExit", "TestExit1 is an exit to Room.")
self.call(building.CmdLink(), "Obj", "Obj is not an exit. Its home location is Room.")
self.call( self.call(
building.CmdUnLink(), "TestExit1", "Former exit TestExit1 no longer links anywhere." building.CmdLink(), "Obj", "Obj is not an exit. Its home location is Room."
)
self.call(
building.CmdUnLink(),
"TestExit1",
"Former exit TestExit1 no longer links anywhere.",
) )
self.char1.location = self.room2 self.char1.location = self.room2
self.call( self.call(
building.CmdOpen(), "TestExit2=Room", "Created new Exit 'TestExit2' from Room2 to Room." building.CmdOpen(),
"TestExit2=Room",
"Created new Exit 'TestExit2' from Room2 to Room.",
) )
self.call( self.call(
building.CmdOpen(), building.CmdOpen(),
@ -902,7 +1054,9 @@ class TestBuilding(CommandTest):
# ensure it matches locally first # ensure it matches locally first
self.call( self.call(
building.CmdLink(), "TestExit=Room2", "Link created TestExit2 -> Room2 (one way)." building.CmdLink(),
"TestExit=Room2",
"Link created TestExit2 -> Room2 (one way).",
) )
self.call( self.call(
building.CmdLink(), building.CmdLink(),
@ -923,21 +1077,29 @@ class TestBuilding(CommandTest):
# ensure can still match globally when not a local name # ensure can still match globally when not a local name
self.call(building.CmdLink(), "TestExit1=Room2", "Note: TestExit1") self.call(building.CmdLink(), "TestExit1=Room2", "Note: TestExit1")
self.call( self.call(
building.CmdLink(), "TestExit1=", "Former exit TestExit1 no longer links anywhere." building.CmdLink(),
"TestExit1=",
"Former exit TestExit1 no longer links anywhere.",
) )
def test_set_home(self): def test_set_home(self):
self.call( self.call(
building.CmdSetHome(), "Obj = Room2", "Home location of Obj was changed from Room" building.CmdSetHome(),
"Obj = Room2",
"Home location of Obj was changed from Room",
) )
self.call(building.CmdSetHome(), "", "Usage: ") self.call(building.CmdSetHome(), "", "Usage: ")
self.call(building.CmdSetHome(), "self", "Char's current home is Room") self.call(building.CmdSetHome(), "self", "Char's current home is Room")
self.call(building.CmdSetHome(), "Obj", "Obj's current home is Room2") self.call(building.CmdSetHome(), "Obj", "Obj's current home is Room2")
self.obj1.home = None self.obj1.home = None
self.call(building.CmdSetHome(), "Obj = Room2", "Home location of Obj was set to Room") self.call(
building.CmdSetHome(), "Obj = Room2", "Home location of Obj was set to Room"
)
def test_list_cmdsets(self): def test_list_cmdsets(self):
self.call(building.CmdListCmdSets(), "", "<DefaultCharacter (Union, prio 0, perm)>:") self.call(
building.CmdListCmdSets(), "", "<DefaultCharacter (Union, prio 0, perm)>:"
)
self.call(building.CmdListCmdSets(), "NotFound", "Could not find 'NotFound'") self.call(building.CmdListCmdSets(), "NotFound", "Could not find 'NotFound'")
def test_typeclass(self): def test_typeclass(self):
@ -971,7 +1133,9 @@ class TestBuilding(CommandTest):
"/force Obj = evennia.objects.objects.DefaultExit", "/force Obj = evennia.objects.objects.DefaultExit",
"Obj updated its existing typeclass ", "Obj updated its existing typeclass ",
) )
self.call(building.CmdTypeclass(), "Obj = evennia.objects.objects.DefaultObject") self.call(
building.CmdTypeclass(), "Obj = evennia.objects.objects.DefaultObject"
)
self.call( self.call(
building.CmdTypeclass(), building.CmdTypeclass(),
"/show Obj", "/show Obj",
@ -993,13 +1157,19 @@ class TestBuilding(CommandTest):
def test_lock(self): def test_lock(self):
self.call(building.CmdLock(), "", "Usage: ") self.call(building.CmdLock(), "", "Usage: ")
self.call(building.CmdLock(), "Obj = test:all()", "Added lock 'test:all()' to Obj.") self.call(
building.CmdLock(), "Obj = test:all()", "Added lock 'test:all()' to Obj."
)
self.call( self.call(
building.CmdLock(), building.CmdLock(),
"*TestAccount = test:all()", "*TestAccount = test:all()",
"Added lock 'test:all()' to TestAccount", "Added lock 'test:all()' to TestAccount",
) )
self.call(building.CmdLock(), "Obj/notfound", "Obj has no lock of access type 'notfound'.") self.call(
building.CmdLock(),
"Obj/notfound",
"Obj has no lock of access type 'notfound'.",
)
self.call(building.CmdLock(), "Obj/test", "test:all()") self.call(building.CmdLock(), "Obj/test", "test:all()")
self.call( self.call(
building.CmdLock(), building.CmdLock(),
@ -1020,7 +1190,9 @@ class TestBuilding(CommandTest):
self.call(building.CmdFind(), "", "Usage: ") self.call(building.CmdFind(), "", "Usage: ")
self.call(building.CmdFind(), "oom2", "One Match") self.call(building.CmdFind(), "oom2", "One Match")
self.call(building.CmdFind(), "oom2 = 1-{}".format(rmax), "One Match") self.call(building.CmdFind(), "oom2 = 1-{}".format(rmax), "One Match")
self.call(building.CmdFind(), "oom2 = 1 {}".format(rmax), "One Match") # space works too self.call(
building.CmdFind(), "oom2 = 1 {}".format(rmax), "One Match"
) # space works too
self.call(building.CmdFind(), "Char2", "One Match", cmdstring="locate") self.call(building.CmdFind(), "Char2", "One Match", cmdstring="locate")
self.call( self.call(
building.CmdFind(), building.CmdFind(),
@ -1046,7 +1218,9 @@ class TestBuilding(CommandTest):
def test_script(self): def test_script(self):
self.call(building.CmdScript(), "Obj = ", "No scripts defined on Obj") self.call(building.CmdScript(), "Obj = ", "No scripts defined on Obj")
self.call( self.call(
building.CmdScript(), "Obj = scripts.Script", "Script scripts.Script successfully added" building.CmdScript(),
"Obj = scripts.Script",
"Script scripts.Script successfully added",
) )
self.call(building.CmdScript(), "", "Usage: ") self.call(building.CmdScript(), "", "Usage: ")
self.call( self.call(
@ -1062,7 +1236,9 @@ class TestBuilding(CommandTest):
self.call(building.CmdScript(), "/stop Obj", "Stopping script") self.call(building.CmdScript(), "/stop Obj", "Stopping script")
self.call( self.call(
building.CmdScript(), "Obj = scripts.Script", "Script scripts.Script successfully added" building.CmdScript(),
"Obj = scripts.Script",
"Script scripts.Script successfully added",
) )
self.call( self.call(
building.CmdScript(), building.CmdScript(),
@ -1093,12 +1269,18 @@ class TestBuilding(CommandTest):
oid, rid, rid2 oid, rid, rid2
), ),
) )
self.call(building.CmdTeleport(), "NotFound = Room", "Could not find 'NotFound'.")
self.call( self.call(
building.CmdTeleport(), "Obj = Obj", "You can't teleport an object inside of itself!" building.CmdTeleport(), "NotFound = Room", "Could not find 'NotFound'."
)
self.call(
building.CmdTeleport(),
"Obj = Obj",
"You can't teleport an object inside of itself!",
) )
self.call(building.CmdTeleport(), "/tonone Obj2", "Teleported Obj2 -> None-location.") self.call(
building.CmdTeleport(), "/tonone Obj2", "Teleported Obj2 -> None-location."
)
self.call(building.CmdTeleport(), "/quiet Room2", "Room2(#{})".format(rid2)) self.call(building.CmdTeleport(), "/quiet Room2", "Room2(#{})".format(rid2))
self.call( self.call(
building.CmdTeleport(), building.CmdTeleport(),
@ -1127,19 +1309,30 @@ class TestBuilding(CommandTest):
self.call( self.call(
building.CmdTag(), building.CmdTag(),
"Obj", "Obj",
"Tags on Obj: 'testtag', 'testtag2', " "'testtag2' (category: category1), 'testtag3'", "Tags on Obj: 'testtag', 'testtag2', "
"'testtag2' (category: category1), 'testtag3'",
) )
self.call(building.CmdTag(), "/search NotFound", "No objects found with tag 'NotFound'.") self.call(
self.call(building.CmdTag(), "/search testtag", "Found 1 object with tag 'testtag':") building.CmdTag(),
self.call(building.CmdTag(), "/search testtag2", "Found 1 object with tag 'testtag2':") "/search NotFound",
"No objects found with tag 'NotFound'.",
)
self.call(
building.CmdTag(), "/search testtag", "Found 1 object with tag 'testtag':"
)
self.call(
building.CmdTag(), "/search testtag2", "Found 1 object with tag 'testtag2':"
)
self.call( self.call(
building.CmdTag(), building.CmdTag(),
"/search testtag2:category1", "/search testtag2:category1",
"Found 1 object with tag 'testtag2' (category: 'category1'):", "Found 1 object with tag 'testtag2' (category: 'category1'):",
) )
self.call(building.CmdTag(), "/del Obj = testtag3", "Removed tag 'testtag3' from Obj.") self.call(
building.CmdTag(), "/del Obj = testtag3", "Removed tag 'testtag3' from Obj."
)
self.call( self.call(
building.CmdTag(), building.CmdTag(),
"/del Obj", "/del Obj",
@ -1175,7 +1368,8 @@ class TestBuilding(CommandTest):
self.call( self.call(
building.CmdSpawn(), building.CmdSpawn(),
"/save {'key':'Test Char', " "'typeclass':'evennia.objects.objects.DefaultCharacter'}", "/save {'key':'Test Char', "
"'typeclass':'evennia.objects.objects.DefaultCharacter'}",
"To save a prototype it must have the 'prototype_key' set.", "To save a prototype it must have the 'prototype_key' set.",
) )
@ -1285,7 +1479,9 @@ class TestBuilding(CommandTest):
# spawn/edit with invalid prototype # spawn/edit with invalid prototype
msg = self.call( msg = self.call(
building.CmdSpawn(), "/edit NO_EXISTS", "No prototype 'NO_EXISTS' was found." building.CmdSpawn(),
"/edit NO_EXISTS",
"No prototype 'NO_EXISTS' was found.",
) )
# spawn/examine (missing prototype) # spawn/examine (missing prototype)
@ -1300,7 +1496,11 @@ class TestBuilding(CommandTest):
# spawn/examine with invalid prototype # spawn/examine with invalid prototype
# shows error # shows error
self.call(building.CmdSpawn(), "/examine NO_EXISTS", "No prototype 'NO_EXISTS' was found.") self.call(
building.CmdSpawn(),
"/examine NO_EXISTS",
"No prototype 'NO_EXISTS' was found.",
)
class TestComms(CommandTest): class TestComms(CommandTest):

View file

@ -202,11 +202,11 @@ class CmdUnconnectedCreate(COMMAND_DEFAULT_CLASS):
# tell the caller everything went well. # tell the caller everything went well.
string = "A new account '%s' was created. Welcome!" string = "A new account '%s' was created. Welcome!"
if " " in username: if " " in username:
string += ( string += "\n\nYou can now log in with the command 'connect \"%s\" <your password>'."
"\n\nYou can now log in with the command 'connect \"%s\" <your password>'."
)
else: else:
string += "\n\nYou can now log with the command 'connect %s <your password>'." string += (
"\n\nYou can now log with the command 'connect %s <your password>'."
)
session.msg(string % (username, username)) session.msg(string % (username, username))
else: else:
session.msg("|R%s|n" % "\n".join(errors)) session.msg("|R%s|n" % "\n".join(errors))
@ -258,9 +258,13 @@ class CmdUnconnectedLook(COMMAND_DEFAULT_CLASS):
if "connection_screen" in callables: if "connection_screen" in callables:
connection_screen = callables["connection_screen"]() connection_screen = callables["connection_screen"]()
else: else:
connection_screen = utils.random_string_from_module(CONNECTION_SCREEN_MODULE) connection_screen = utils.random_string_from_module(
CONNECTION_SCREEN_MODULE
)
if not connection_screen: if not connection_screen:
connection_screen = "No connection screen found. Please contact an admin." connection_screen = (
"No connection screen found. Please contact an admin."
)
self.caller.msg(connection_screen) self.caller.msg(connection_screen)
@ -357,7 +361,8 @@ class CmdUnconnectedEncoding(COMMAND_DEFAULT_CLASS):
string = "" string = ""
if pencoding: if pencoding:
string += ( string += (
"Default encoding: |g%s|n (change with |wencoding <encoding>|n)" % pencoding "Default encoding: |g%s|n (change with |wencoding <encoding>|n)"
% pencoding
) )
encodings = settings.ENCODINGS encodings = settings.ENCODINGS
if encodings: if encodings:
@ -380,9 +385,9 @@ class CmdUnconnectedEncoding(COMMAND_DEFAULT_CLASS):
) )
else: else:
self.session.protocol_flags["ENCODING"] = encoding self.session.protocol_flags["ENCODING"] = encoding
string = "Your custom text encoding was changed from '|w%s|n' to '|w%s|n'." % ( string = (
old_encoding, "Your custom text encoding was changed from '|w%s|n' to '|w%s|n'."
encoding, % (old_encoding, encoding)
) )
sync = True sync = True
if sync: if sync:
@ -436,7 +441,9 @@ class CmdUnconnectedInfo(COMMAND_DEFAULT_CLASS):
) )
def _create_account(session, accountname, password, permissions, typeclass=None, email=None): def _create_account(
session, accountname, password, permissions, typeclass=None, email=None
):
""" """
Helper function, creates an account of the specified typeclass. Helper function, creates an account of the specified typeclass.
""" """
@ -461,7 +468,9 @@ def _create_account(session, accountname, password, permissions, typeclass=None,
# join the new account to the public channel # join the new account to the public channel
pchannel = ChannelDB.objects.get_channel(settings.DEFAULT_CHANNELS[0]["key"]) pchannel = ChannelDB.objects.get_channel(settings.DEFAULT_CHANNELS[0]["key"])
if not pchannel or not pchannel.connect(new_account): if not pchannel or not pchannel.connect(new_account):
string = "New account '%s' could not connect to public channel!" % new_account.key string = (
"New account '%s' could not connect to public channel!" % new_account.key
)
logger.log_err(string) logger.log_err(string)
return new_account return new_account

View file

@ -99,68 +99,116 @@ class TestCmdSetMergers(TestCase):
a, c = self.cmdset_a, self.cmdset_c a, c = self.cmdset_a, self.cmdset_c
cmdset_f = a + c # same-prio cmdset_f = a + c # same-prio
self.assertEqual(len(cmdset_f.commands), 4) self.assertEqual(len(cmdset_f.commands), 4)
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 2) self.assertEqual(
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 2) sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 2
)
self.assertEqual(
sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 2
)
cmdset_f = c + a # same-prio, inverse order cmdset_f = c + a # same-prio, inverse order
self.assertEqual(len(cmdset_f.commands), 4) self.assertEqual(len(cmdset_f.commands), 4)
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 4) self.assertEqual(
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 0) sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 4
)
self.assertEqual(
sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 0
)
a.priority = 1 a.priority = 1
cmdset_f = a + c # high prio A cmdset_f = a + c # high prio A
self.assertEqual(len(cmdset_f.commands), 4) self.assertEqual(len(cmdset_f.commands), 4)
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 4) self.assertEqual(
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 0) sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 4
)
self.assertEqual(
sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 0
)
def test_intersect(self): def test_intersect(self):
a, c = self.cmdset_a, self.cmdset_c a, c = self.cmdset_a, self.cmdset_c
a.mergetype = "Intersect" a.mergetype = "Intersect"
cmdset_f = a + c # same-prio - c's Union kicks in cmdset_f = a + c # same-prio - c's Union kicks in
self.assertEqual(len(cmdset_f.commands), 4) self.assertEqual(len(cmdset_f.commands), 4)
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 2) self.assertEqual(
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 2) sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 2
)
self.assertEqual(
sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 2
)
cmdset_f = c + a # same-prio - a's Intersect kicks in cmdset_f = c + a # same-prio - a's Intersect kicks in
self.assertEqual(len(cmdset_f.commands), 2) self.assertEqual(len(cmdset_f.commands), 2)
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 2) self.assertEqual(
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 0) sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 2
)
self.assertEqual(
sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 0
)
a.priority = 1 a.priority = 1
cmdset_f = a + c # high prio A, intersect kicks in cmdset_f = a + c # high prio A, intersect kicks in
self.assertEqual(len(cmdset_f.commands), 2) self.assertEqual(len(cmdset_f.commands), 2)
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 2) self.assertEqual(
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 0) sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 2
)
self.assertEqual(
sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 0
)
def test_replace(self): def test_replace(self):
a, c = self.cmdset_a, self.cmdset_c a, c = self.cmdset_a, self.cmdset_c
c.mergetype = "Replace" c.mergetype = "Replace"
cmdset_f = a + c # same-prio. C's Replace kicks in cmdset_f = a + c # same-prio. C's Replace kicks in
self.assertEqual(len(cmdset_f.commands), 2) self.assertEqual(len(cmdset_f.commands), 2)
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 0) self.assertEqual(
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 2) sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 0
)
self.assertEqual(
sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 2
)
cmdset_f = c + a # same-prio. A's Union kicks in cmdset_f = c + a # same-prio. A's Union kicks in
self.assertEqual(len(cmdset_f.commands), 4) self.assertEqual(len(cmdset_f.commands), 4)
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 4) self.assertEqual(
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 0) sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 4
)
self.assertEqual(
sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 0
)
c.priority = 1 c.priority = 1
cmdset_f = c + a # c higher prio. C's Replace kicks in cmdset_f = c + a # c higher prio. C's Replace kicks in
self.assertEqual(len(cmdset_f.commands), 2) self.assertEqual(len(cmdset_f.commands), 2)
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 0) self.assertEqual(
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 2) sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 0
)
self.assertEqual(
sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 2
)
def test_remove(self): def test_remove(self):
a, c = self.cmdset_a, self.cmdset_c a, c = self.cmdset_a, self.cmdset_c
c.mergetype = "Remove" c.mergetype = "Remove"
cmdset_f = a + c # same-prio. C's Remove kicks in cmdset_f = a + c # same-prio. C's Remove kicks in
self.assertEqual(len(cmdset_f.commands), 2) self.assertEqual(len(cmdset_f.commands), 2)
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 2) self.assertEqual(
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 0) sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 2
)
self.assertEqual(
sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 0
)
cmdset_f = c + a # same-prio. A's Union kicks in cmdset_f = c + a # same-prio. A's Union kicks in
self.assertEqual(len(cmdset_f.commands), 4) self.assertEqual(len(cmdset_f.commands), 4)
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 4) self.assertEqual(
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 0) sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 4
)
self.assertEqual(
sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 0
)
c.priority = 1 c.priority = 1
cmdset_f = c + a # c higher prio. C's Remove kicks in cmdset_f = c + a # c higher prio. C's Remove kicks in
self.assertEqual(len(cmdset_f.commands), 2) self.assertEqual(len(cmdset_f.commands), 2)
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 2) self.assertEqual(
self.assertEqual(sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 0) sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "A"), 2
)
self.assertEqual(
sum(1 for cmd in cmdset_f.commands if cmd.from_cmdset == "C"), 0
)
def test_order(self): def test_order(self):
"Merge in reverse- and forward orders, same priorities" "Merge in reverse- and forward orders, same priorities"
@ -169,12 +217,18 @@ class TestCmdSetMergers(TestCase):
self.assertEqual(cmdset_f.priority, 0) self.assertEqual(cmdset_f.priority, 0)
self.assertEqual(cmdset_f.mergetype, "Union") self.assertEqual(cmdset_f.mergetype, "Union")
self.assertEqual(len(cmdset_f.commands), 4) self.assertEqual(len(cmdset_f.commands), 4)
self.assertTrue(all(True for cmd in cmdset_f.commands if cmd.from_cmdset == "A")) self.assertTrue(
all(True for cmd in cmdset_f.commands if cmd.from_cmdset == "A")
)
cmdset_f = a + b + c + d # merge in order of priority cmdset_f = a + b + c + d # merge in order of priority
self.assertEqual(cmdset_f.priority, 0) self.assertEqual(cmdset_f.priority, 0)
self.assertEqual(cmdset_f.mergetype, "Union") self.assertEqual(cmdset_f.mergetype, "Union")
self.assertEqual(len(cmdset_f.commands), 4) # duplicates setting from A transfers self.assertEqual(
self.assertTrue(all(True for cmd in cmdset_f.commands if cmd.from_cmdset == "D")) len(cmdset_f.commands), 4
) # duplicates setting from A transfers
self.assertTrue(
all(True for cmd in cmdset_f.commands if cmd.from_cmdset == "D")
)
def test_priority_order(self): def test_priority_order(self):
"Merge in reverse- and forward order with well-defined prioritities" "Merge in reverse- and forward order with well-defined prioritities"
@ -187,12 +241,16 @@ class TestCmdSetMergers(TestCase):
self.assertEqual(cmdset_f.priority, 2) self.assertEqual(cmdset_f.priority, 2)
self.assertEqual(cmdset_f.mergetype, "Union") self.assertEqual(cmdset_f.mergetype, "Union")
self.assertEqual(len(cmdset_f.commands), 4) self.assertEqual(len(cmdset_f.commands), 4)
self.assertTrue(all(True for cmd in cmdset_f.commands if cmd.from_cmdset == "A")) self.assertTrue(
all(True for cmd in cmdset_f.commands if cmd.from_cmdset == "A")
)
cmdset_f = a + b + c + d # merge in order of priority cmdset_f = a + b + c + d # merge in order of priority
self.assertEqual(cmdset_f.priority, 2) self.assertEqual(cmdset_f.priority, 2)
self.assertEqual(cmdset_f.mergetype, "Union") self.assertEqual(cmdset_f.mergetype, "Union")
self.assertEqual(len(cmdset_f.commands), 4) self.assertEqual(len(cmdset_f.commands), 4)
self.assertTrue(all(True for cmd in cmdset_f.commands if cmd.from_cmdset == "A")) self.assertTrue(
all(True for cmd in cmdset_f.commands if cmd.from_cmdset == "A")
)
def test_option_transfer(self): def test_option_transfer(self):
"Test transfer of cmdset options" "Test transfer of cmdset options"
@ -225,7 +283,9 @@ class TestCmdSetMergers(TestCase):
self.assertTrue(cmdset_f.no_channels) self.assertTrue(cmdset_f.no_channels)
self.assertTrue(cmdset_f.duplicates) self.assertTrue(cmdset_f.duplicates)
self.assertEqual(len(cmdset_f.commands), 4) self.assertEqual(len(cmdset_f.commands), 4)
cmdset_f = a + b + c + d # forward, A top priority. This never happens in practice. cmdset_f = (
a + b + c + d
) # forward, A top priority. This never happens in practice.
self.assertTrue(cmdset_f.no_exits) self.assertTrue(cmdset_f.no_exits)
self.assertTrue(cmdset_f.no_objs) self.assertTrue(cmdset_f.no_objs)
self.assertTrue(cmdset_f.no_channels) self.assertTrue(cmdset_f.no_channels)
@ -331,7 +391,9 @@ class TestGetAndMergeCmdSets(TwistedTestCase, EvenniaTest):
def test_from_object(self): def test_from_object(self):
self.set_cmdsets(self.obj1, self.cmdset_a) self.set_cmdsets(self.obj1, self.cmdset_a)
deferred = cmdhandler.get_and_merge_cmdsets(self.obj1, None, None, self.obj1, "object", "") deferred = cmdhandler.get_and_merge_cmdsets(
self.obj1, None, None, self.obj1, "object", ""
)
# get_and_merge_cmdsets converts to lower-case internally. # get_and_merge_cmdsets converts to lower-case internally.
def _callback(cmdset): def _callback(cmdset):
@ -348,7 +410,9 @@ class TestGetAndMergeCmdSets(TwistedTestCase, EvenniaTest):
a.no_channels = True a.no_channels = True
self.set_cmdsets(self.obj1, a, b, c, d) self.set_cmdsets(self.obj1, a, b, c, d)
deferred = cmdhandler.get_and_merge_cmdsets(self.obj1, None, None, self.obj1, "object", "") deferred = cmdhandler.get_and_merge_cmdsets(
self.obj1, None, None, self.obj1, "object", ""
)
def _callback(cmdset): def _callback(cmdset):
self.assertTrue(cmdset.no_exits) self.assertTrue(cmdset.no_exits)
@ -363,7 +427,9 @@ class TestGetAndMergeCmdSets(TwistedTestCase, EvenniaTest):
from evennia.commands.default.cmdset_account import AccountCmdSet from evennia.commands.default.cmdset_account import AccountCmdSet
from evennia.comms.channelhandler import CHANNEL_HANDLER from evennia.comms.channelhandler import CHANNEL_HANDLER
testchannel = evennia.create_channel("channeltest", locks="listen:all();send:all()") testchannel = evennia.create_channel(
"channeltest", locks="listen:all();send:all()"
)
CHANNEL_HANDLER.add(testchannel) CHANNEL_HANDLER.add(testchannel)
CHANNEL_HANDLER.update() CHANNEL_HANDLER.update()
self.assertTrue(testchannel.connect(self.account)) self.assertTrue(testchannel.connect(self.account))
@ -377,9 +443,14 @@ class TestGetAndMergeCmdSets(TwistedTestCase, EvenniaTest):
def _callback(cmdset): def _callback(cmdset):
pcmdset = AccountCmdSet() pcmdset = AccountCmdSet()
pcmdset.at_cmdset_creation() pcmdset.at_cmdset_creation()
pcmds = [cmd.key for cmd in pcmdset.commands] + ["a", "b", "c", "d"] + ["out"] pcmds = (
[cmd.key for cmd in pcmdset.commands] + ["a", "b", "c", "d"] + ["out"]
)
self.assertTrue( self.assertTrue(
all(cmd.key or hasattr(cmd, "is_channel") in pcmds for cmd in cmdset.commands) all(
cmd.key or hasattr(cmd, "is_channel") in pcmds
for cmd in cmdset.commands
)
) )
self.assertTrue(any(hasattr(cmd, "is_channel") for cmd in cmdset.commands)) self.assertTrue(any(hasattr(cmd, "is_channel") for cmd in cmdset.commands))
@ -393,7 +464,9 @@ class TestGetAndMergeCmdSets(TwistedTestCase, EvenniaTest):
b.duplicates = True b.duplicates = True
d.duplicates = True d.duplicates = True
self.set_cmdsets(self.obj1, a, b, c, d) self.set_cmdsets(self.obj1, a, b, c, d)
deferred = cmdhandler.get_and_merge_cmdsets(self.obj1, None, None, self.obj1, "object", "") deferred = cmdhandler.get_and_merge_cmdsets(
self.obj1, None, None, self.obj1, "object", ""
)
def _callback(cmdset): def _callback(cmdset):
self.assertEqual(len(cmdset.commands), 9) self.assertEqual(len(cmdset.commands), 9)
@ -466,7 +539,9 @@ class TestCmdParser(TestCase):
# test prefix exclusion on the cmd class # test prefix exclusion on the cmd class
bcmd = [cmd for cmd in a_cmdset.commands if cmd.key == "&the third command"][0] bcmd = [cmd for cmd in a_cmdset.commands if cmd.key == "&the third command"][0]
self.assertEqual( self.assertEqual(
cmdparser.build_matches("the third command", a_cmdset, include_prefixes=False), cmdparser.build_matches(
"the third command", a_cmdset, include_prefixes=False
),
[("the third command", "", bcmd, 17, 1.0, "&the third command")], [("the third command", "", bcmd, 17, 1.0, "&the third command")],
) )
@ -477,7 +552,8 @@ class TestCmdParser(TestCase):
self.assertEqual(cmdparser.try_num_prefixes("567-look me"), ("567", "look me")) self.assertEqual(cmdparser.try_num_prefixes("567-look me"), ("567", "look me"))
@override_settings( @override_settings(
SEARCH_MULTIMATCH_REGEX=r"(?P<number>[0-9]+)-(?P<name>.*)", CMD_IGNORE_PREFIXES="@&/+" SEARCH_MULTIMATCH_REGEX=r"(?P<number>[0-9]+)-(?P<name>.*)",
CMD_IGNORE_PREFIXES="@&/+",
) )
def test_cmdparser(self): def test_cmdparser(self):
a_cmdset = _CmdSetTest() a_cmdset = _CmdSetTest()

View file

@ -117,7 +117,9 @@ class ChannelAdmin(admin.ModelAdmin):
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.urls import reverse from django.urls import reverse
return HttpResponseRedirect(reverse("admin:comms_channeldb_change", args=[obj.id])) return HttpResponseRedirect(
reverse("admin:comms_channeldb_change", args=[obj.id])
)
admin.site.register(ChannelDB, ChannelAdmin) admin.site.register(ChannelDB, ChannelAdmin)

View file

@ -129,11 +129,16 @@ class ChannelCommand(command.Command):
return return
if self.history_start is not None: if self.history_start is not None:
# Try to view history # Try to view history
log_file = channel.attributes.get("log_file", default="channel_%s.log" % channel.key) log_file = channel.attributes.get(
"log_file", default="channel_%s.log" % channel.key
)
def send_msg(lines): def send_msg(lines):
return self.msg( return self.msg(
"".join(line.split("[-]", 1)[1] if "[-]" in line else line for line in lines) "".join(
line.split("[-]", 1)[1] if "[-]" in line else line
for line in lines
)
) )
tail_log_file(log_file, self.history_start, 20, callback=send_msg) tail_log_file(log_file, self.history_start, 20, callback=send_msg)

View file

@ -301,7 +301,13 @@ class DefaultChannel(ChannelDB, metaclass=TypeclassBase):
CHANNELHANDLER.update() CHANNELHANDLER.update()
def message_transform( def message_transform(
self, msgobj, emit=False, prefix=True, sender_strings=None, external=False, **kwargs self,
msgobj,
emit=False,
prefix=True,
sender_strings=None,
external=False,
**kwargs,
): ):
""" """
Generates the formatted string sent to listeners on a channel. Generates the formatted string sent to listeners on a channel.
@ -355,7 +361,9 @@ class DefaultChannel(ChannelDB, metaclass=TypeclassBase):
# note our addition of the from_channel keyword here. This could be checked # note our addition of the from_channel keyword here. This could be checked
# by a custom account.msg() to treat channel-receives differently. # by a custom account.msg() to treat channel-receives differently.
entity.msg( entity.msg(
msgobj.message, from_obj=msgobj.senders, options={"from_channel": self.id} msgobj.message,
from_obj=msgobj.senders,
options={"from_channel": self.id},
) )
except AttributeError as e: except AttributeError as e:
logger.log_trace("%s\nCannot send msg to '%s'." % (e, entity)) logger.log_trace("%s\nCannot send msg to '%s'." % (e, entity))
@ -363,7 +371,8 @@ class DefaultChannel(ChannelDB, metaclass=TypeclassBase):
if msgobj.keep_log: if msgobj.keep_log:
# log to file # log to file
logger.log_file( logger.log_file(
msgobj.message, self.attributes.get("log_file") or "channel_%s.log" % self.key msgobj.message,
self.attributes.get("log_file") or "channel_%s.log" % self.key,
) )
def msg( def msg(
@ -417,7 +426,9 @@ class DefaultChannel(ChannelDB, metaclass=TypeclassBase):
senders = make_iter(senders) if senders else [] senders = make_iter(senders) if senders else []
if isinstance(msgobj, str): if isinstance(msgobj, str):
# given msgobj is a string - convert to msgobject (always TempMsg) # given msgobj is a string - convert to msgobject (always TempMsg)
msgobj = TempMsg(senders=senders, header=header, message=msgobj, channels=[self]) msgobj = TempMsg(
senders=senders, header=header, message=msgobj, channels=[self]
)
# we store the logging setting for use in distribute_message() # we store the logging setting for use in distribute_message()
msgobj.keep_log = keep_log if keep_log is not None else self.db.keep_log msgobj.keep_log = keep_log if keep_log is not None else self.db.keep_log
@ -678,7 +689,8 @@ class DefaultChannel(ChannelDB, metaclass=TypeclassBase):
""" """
content_type = ContentType.objects.get_for_model(self.__class__) content_type = ContentType.objects.get_for_model(self.__class__)
return reverse( return reverse(
"admin:%s_%s_change" % (content_type.app_label, content_type.model), args=(self.id,) "admin:%s_%s_change" % (content_type.app_label, content_type.model),
args=(self.id,),
) )
@classmethod @classmethod

View file

@ -205,24 +205,30 @@ class MsgManager(TypedObjectManager):
# explicitly exclude channel recipients # explicitly exclude channel recipients
if typ == "account": if typ == "account":
return list( return list(
self.filter(db_sender_accounts=obj, db_receivers_channels__isnull=True).exclude( self.filter(
db_hide_from_accounts=obj db_sender_accounts=obj, db_receivers_channels__isnull=True
) ).exclude(db_hide_from_accounts=obj)
) )
elif typ == "object": elif typ == "object":
return list( return list(
self.filter(db_sender_objects=obj, db_receivers_channels__isnull=True).exclude( self.filter(
db_hide_from_objects=obj db_sender_objects=obj, db_receivers_channels__isnull=True
) ).exclude(db_hide_from_objects=obj)
) )
else: else:
raise CommError raise CommError
else: else:
# get everything, channel or not # get everything, channel or not
if typ == "account": if typ == "account":
return list(self.filter(db_sender_accounts=obj).exclude(db_hide_from_accounts=obj)) return list(
self.filter(db_sender_accounts=obj).exclude(
db_hide_from_accounts=obj
)
)
elif typ == "object": elif typ == "object":
return list(self.filter(db_sender_objects=obj).exclude(db_hide_from_objects=obj)) return list(
self.filter(db_sender_objects=obj).exclude(db_hide_from_objects=obj)
)
else: else:
raise CommError raise CommError
@ -242,11 +248,21 @@ class MsgManager(TypedObjectManager):
""" """
obj, typ = identify_object(recipient) obj, typ = identify_object(recipient)
if typ == "account": if typ == "account":
return list(self.filter(db_receivers_accounts=obj).exclude(db_hide_from_accounts=obj)) return list(
self.filter(db_receivers_accounts=obj).exclude(
db_hide_from_accounts=obj
)
)
elif typ == "object": elif typ == "object":
return list(self.filter(db_receivers_objects=obj).exclude(db_hide_from_objects=obj)) return list(
self.filter(db_receivers_objects=obj).exclude(db_hide_from_objects=obj)
)
elif typ == "channel": elif typ == "channel":
return list(self.filter(db_receivers_channels=obj).exclude(db_hide_from_channels=obj)) return list(
self.filter(db_receivers_channels=obj).exclude(
db_hide_from_channels=obj
)
)
else: else:
raise CommError raise CommError
@ -261,7 +277,9 @@ class MsgManager(TypedObjectManager):
messages (list): Persistent Msg objects saved for this channel. messages (list): Persistent Msg objects saved for this channel.
""" """
return self.filter(db_receivers_channels=channel).exclude(db_hide_from_channels=channel) return self.filter(db_receivers_channels=channel).exclude(
db_hide_from_channels=channel
)
def search_message(self, sender=None, receiver=None, freetext=None, dbref=None): def search_message(self, sender=None, receiver=None, freetext=None, dbref=None):
""" """
@ -297,9 +315,13 @@ class MsgManager(TypedObjectManager):
# filter by sender # filter by sender
sender, styp = identify_object(sender) sender, styp = identify_object(sender)
if styp == "account": if styp == "account":
sender_restrict = Q(db_sender_accounts=sender) & ~Q(db_hide_from_accounts=sender) sender_restrict = Q(db_sender_accounts=sender) & ~Q(
db_hide_from_accounts=sender
)
elif styp == "object": elif styp == "object":
sender_restrict = Q(db_sender_objects=sender) & ~Q(db_hide_from_objects=sender) sender_restrict = Q(db_sender_objects=sender) & ~Q(
db_hide_from_objects=sender
)
else: else:
sender_restrict = Q() sender_restrict = Q()
# filter by receiver # filter by receiver
@ -309,7 +331,9 @@ class MsgManager(TypedObjectManager):
db_hide_from_accounts=receiver db_hide_from_accounts=receiver
) )
elif rtyp == "object": elif rtyp == "object":
receiver_restrict = Q(db_receivers_objects=receiver) & ~Q(db_hide_from_objects=receiver) receiver_restrict = Q(db_receivers_objects=receiver) & ~Q(
db_hide_from_objects=receiver
)
elif rtyp == "channel": elif rtyp == "channel":
receiver_restrict = Q(db_receivers_channels=receiver) & ~Q( receiver_restrict = Q(db_receivers_channels=receiver) & ~Q(
db_hide_from_channels=receiver db_hide_from_channels=receiver
@ -318,11 +342,15 @@ class MsgManager(TypedObjectManager):
receiver_restrict = Q() receiver_restrict = Q()
# filter by full text # filter by full text
if freetext: if freetext:
fulltext_restrict = Q(db_header__icontains=freetext) | Q(db_message__icontains=freetext) fulltext_restrict = Q(db_header__icontains=freetext) | Q(
db_message__icontains=freetext
)
else: else:
fulltext_restrict = Q() fulltext_restrict = Q()
# execute the query # execute the query
return list(self.filter(sender_restrict & receiver_restrict & fulltext_restrict)) return list(
self.filter(sender_restrict & receiver_restrict & fulltext_restrict)
)
# back-compatibility alias # back-compatibility alias
message_search = search_message message_search = search_message
@ -419,12 +447,17 @@ class ChannelDBManager(TypedObjectManager):
if exact: if exact:
channels = self.filter( channels = self.filter(
Q(db_key__iexact=ostring) Q(db_key__iexact=ostring)
| Q(db_tags__db_tagtype__iexact="alias", db_tags__db_key__iexact=ostring) | Q(
db_tags__db_tagtype__iexact="alias", db_tags__db_key__iexact=ostring
)
).distinct() ).distinct()
else: else:
channels = self.filter( channels = self.filter(
Q(db_key__icontains=ostring) Q(db_key__icontains=ostring)
| Q(db_tags__db_tagtype__iexact="alias", db_tags__db_key__icontains=ostring) | Q(
db_tags__db_tagtype__iexact="alias",
db_tags__db_key__icontains=ostring,
)
).distinct() ).distinct()
return channels return channels

View file

@ -15,10 +15,16 @@ class Migration(migrations.Migration):
( (
"id", "id",
models.AutoField( models.AutoField(
verbose_name="ID", serialize=False, auto_created=True, primary_key=True verbose_name="ID",
serialize=False,
auto_created=True,
primary_key=True,
), ),
), ),
("db_key", models.CharField(max_length=255, verbose_name="key", db_index=True)), (
"db_key",
models.CharField(max_length=255, verbose_name="key", db_index=True),
),
( (
"db_typeclass_path", "db_typeclass_path",
models.CharField( models.CharField(
@ -30,7 +36,9 @@ class Migration(migrations.Migration):
), ),
( (
"db_date_created", "db_date_created",
models.DateTimeField(auto_now_add=True, verbose_name="creation date"), models.DateTimeField(
auto_now_add=True, verbose_name="creation date"
),
), ),
( (
"db_lock_storage", "db_lock_storage",
@ -50,7 +58,10 @@ class Migration(migrations.Migration):
( (
"id", "id",
models.AutoField( models.AutoField(
verbose_name="ID", serialize=False, auto_created=True, primary_key=True verbose_name="ID",
serialize=False,
auto_created=True,
primary_key=True,
), ),
), ),
( (
@ -63,7 +74,10 @@ class Migration(migrations.Migration):
db_index=True, db_index=True,
), ),
), ),
("db_header", models.TextField(null=True, verbose_name="header", blank=True)), (
"db_header",
models.TextField(null=True, verbose_name="header", blank=True),
),
("db_message", models.TextField(verbose_name="messsage")), ("db_message", models.TextField(verbose_name="messsage")),
( (
"db_date_sent", "db_date_sent",
@ -74,13 +88,17 @@ class Migration(migrations.Migration):
( (
"db_lock_storage", "db_lock_storage",
models.TextField( models.TextField(
help_text="access locks on this message.", verbose_name="locks", blank=True help_text="access locks on this message.",
verbose_name="locks",
blank=True,
), ),
), ),
( (
"db_hide_from_channels", "db_hide_from_channels",
models.ManyToManyField( models.ManyToManyField(
related_name="hide_from_channels_set", null=True, to="comms.ChannelDB" related_name="hide_from_channels_set",
null=True,
to="comms.ChannelDB",
), ),
), ),
], ],

View file

@ -19,7 +19,9 @@ class Migration(migrations.Migration):
model_name="msg", model_name="msg",
name="db_hide_from_accounts", name="db_hide_from_accounts",
field=models.ManyToManyField( field=models.ManyToManyField(
related_name="hide_from_accounts_set", null=True, to=settings.AUTH_USER_MODEL related_name="hide_from_accounts_set",
null=True,
to=settings.AUTH_USER_MODEL,
), ),
preserve_default=True, preserve_default=True,
), ),

View file

@ -6,7 +6,9 @@ from django.db import models, migrations
def convert_defaults(apps, schema_editor): def convert_defaults(apps, schema_editor):
ChannelDB = apps.get_model("comms", "ChannelDB") ChannelDB = apps.get_model("comms", "ChannelDB")
for channel in ChannelDB.objects.filter(db_typeclass_path="src.comms.comms.Channel"): for channel in ChannelDB.objects.filter(
db_typeclass_path="src.comms.comms.Channel"
):
channel.db_typeclass_path = "typeclasses.channels.Channel" channel.db_typeclass_path = "typeclasses.channels.Channel"
channel.save() channel.save()

View file

@ -6,7 +6,10 @@ from django.db import models, migrations
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("objects", "0004_auto_20150118_1622"), ("comms", "0005_auto_20150223_1517")] dependencies = [
("objects", "0004_auto_20150118_1622"),
("comms", "0005_auto_20150223_1517"),
]
operations = [ operations = [
migrations.AddField( migrations.AddField(

View file

@ -15,14 +15,20 @@ class Migration(migrations.Migration):
model_name="msg", model_name="msg",
name="db_hide_from_channels", name="db_hide_from_channels",
field=models.ManyToManyField( field=models.ManyToManyField(
blank=True, null=True, related_name="hide_from_channels_set", to="comms.ChannelDB" blank=True,
null=True,
related_name="hide_from_channels_set",
to="comms.ChannelDB",
), ),
), ),
migrations.AlterField( migrations.AlterField(
model_name="msg", model_name="msg",
name="db_hide_from_objects", name="db_hide_from_objects",
field=models.ManyToManyField( field=models.ManyToManyField(
blank=True, null=True, related_name="hide_from_objects_set", to="objects.ObjectDB" blank=True,
null=True,
related_name="hide_from_objects_set",
to="objects.ObjectDB",
), ),
), ),
migrations.AlterField( migrations.AlterField(

View file

@ -7,7 +7,10 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("scripts", "0007_auto_20150403_2339"), ("comms", "0010_auto_20161206_1912")] dependencies = [
("scripts", "0007_auto_20150403_2339"),
("comms", "0010_auto_20161206_1912"),
]
operations = [ operations = [
migrations.AddField( migrations.AddField(

View file

@ -67,7 +67,9 @@ class Migration(migrations.Migration):
model_name="msg", model_name="msg",
name="db_hide_from_accounts", name="db_hide_from_accounts",
field=models.ManyToManyField( field=models.ManyToManyField(
blank=True, related_name="hide_from_accounts_set", to=settings.AUTH_USER_MODEL blank=True,
related_name="hide_from_accounts_set",
to=settings.AUTH_USER_MODEL,
), ),
), ),
migrations.AlterField( migrations.AlterField(

View file

@ -7,6 +7,9 @@ from django.db import migrations
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("comms", "0011_auto_20170606_1731"), ("comms", "0011_auto_20170217_2039")] dependencies = [
("comms", "0011_auto_20170606_1731"),
("comms", "0011_auto_20170217_2039"),
]
operations = [] operations = []

View file

@ -116,7 +116,9 @@ class Migration(migrations.Migration):
model_name="msg", model_name="msg",
name="db_hide_from_accounts", name="db_hide_from_accounts",
field=models.ManyToManyField( field=models.ManyToManyField(
blank=True, related_name="hide_from_accounts_set", to="accounts.AccountDB" blank=True,
related_name="hide_from_accounts_set",
to="accounts.AccountDB",
), ),
), ),
migrations.AddField( migrations.AddField(

View file

@ -12,6 +12,8 @@ class Migration(migrations.Migration):
operations = [ operations = [
migrations.RemoveField(model_name="channeldb", name="db_subscriptions"), migrations.RemoveField(model_name="channeldb", name="db_subscriptions"),
migrations.AlterField( migrations.AlterField(
model_name="msg", name="db_message", field=models.TextField(verbose_name="message") model_name="msg",
name="db_message",
field=models.TextField(verbose_name="message"),
), ),
] ]

View file

@ -80,7 +80,9 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name="msg", model_name="msg",
name="db_date_created", name="db_date_created",
field=models.DateTimeField(auto_now_add=True, db_index=True, verbose_name="date sent"), field=models.DateTimeField(
auto_now_add=True, db_index=True, verbose_name="date sent"
),
), ),
migrations.AlterField( migrations.AlterField(
model_name="msg", model_name="msg",
@ -91,11 +93,15 @@ class Migration(migrations.Migration):
model_name="msg", model_name="msg",
name="db_lock_storage", name="db_lock_storage",
field=models.TextField( field=models.TextField(
blank=True, help_text="access locks on this message.", verbose_name="locks" blank=True,
help_text="access locks on this message.",
verbose_name="locks",
), ),
), ),
migrations.AlterField( migrations.AlterField(
model_name="msg", name="db_message", field=models.TextField(verbose_name="message") model_name="msg",
name="db_message",
field=models.TextField(verbose_name="message"),
), ),
migrations.AlterField( migrations.AlterField(
model_name="msg", model_name="msg",

View file

@ -5,14 +5,18 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [("comms", "0017_auto_20190128_1820")]
('comms', '0017_auto_20190128_1820'),
]
operations = [ operations = [
migrations.AlterField( migrations.AlterField(
model_name='channeldb', model_name="channeldb",
name='db_typeclass_path', name="db_typeclass_path",
field=models.CharField(db_index=True, help_text="this defines what 'type' of entity this is. This variable holds a Python path to a module with a valid Evennia Typeclass.", max_length=255, null=True, verbose_name='typeclass'), field=models.CharField(
db_index=True,
help_text="this defines what 'type' of entity this is. This variable holds a Python path to a module with a valid Evennia Typeclass.",
max_length=255,
null=True,
verbose_name="typeclass",
), ),
)
] ]

View file

@ -134,7 +134,10 @@ class Msg(SharedMemoryModel):
help_text="script_receivers", help_text="script_receivers",
) )
db_receivers_channels = models.ManyToManyField( db_receivers_channels = models.ManyToManyField(
"ChannelDB", related_name="channel_set", blank=True, help_text="channel recievers" "ChannelDB",
related_name="channel_set",
blank=True,
help_text="channel recievers",
) )
# header could be used for meta-info about the message if your system needs # header could be used for meta-info about the message if your system needs
@ -400,10 +403,11 @@ class Msg(SharedMemoryModel):
def __str__(self): def __str__(self):
"This handles what is shown when e.g. printing the message" "This handles what is shown when e.g. printing the message"
senders = ",".join(getattr(obj, 'key', str(obj)) for obj in self.senders) senders = ",".join(getattr(obj, "key", str(obj)) for obj in self.senders)
receivers = ",".join( receivers = ",".join(
["[%s]" % getattr(obj, 'key', str(obj)) for obj in self.channels] + [getattr(obj, 'key', str(obj)) for obj in self.receivers] ["[%s]" % getattr(obj, "key", str(obj)) for obj in self.channels]
+ [getattr(obj, "key", str(obj)) for obj in self.receivers]
) )
return "%s->%s: %s" % (senders, receivers, crop(self.message, width=40)) return "%s->%s: %s" % (senders, receivers, crop(self.message, width=40))
@ -483,7 +487,8 @@ class TempMsg(object):
""" """
senders = ",".join(obj.key for obj in self.senders) senders = ",".join(obj.key for obj in self.senders)
receivers = ",".join( receivers = ",".join(
["[%s]" % obj.key for obj in self.channels] + [obj.key for obj in self.receivers] ["[%s]" % obj.key for obj in self.channels]
+ [obj.key for obj in self.receivers]
) )
return "%s->%s: %s" % (senders, receivers, crop(self.message, width=40)) return "%s->%s: %s" % (senders, receivers, crop(self.message, width=40))

View file

@ -13,6 +13,6 @@ class ObjectCreationTest(EvenniaTest):
self.assertEqual(description, obj.db.desc) self.assertEqual(description, obj.db.desc)
def test_message_create(self): def test_message_create(self):
msg = create_message('peewee herman', 'heh-heh!', header='mail time!') msg = create_message("peewee herman", "heh-heh!", header="mail time!")
self.assertTrue(msg) self.assertTrue(msg)
self.assertEqual(str(msg), 'peewee herman->: heh-heh!') self.assertEqual(str(msg), "peewee herman->: heh-heh!")

View file

@ -414,9 +414,13 @@ class CmdTradeBase(Command):
self.args, self.emote = [part.strip() for part in self.args.rsplit(":", 1)] self.args, self.emote = [part.strip() for part in self.args.rsplit(":", 1)]
self.str_caller = 'You say, "' + self.emote + '"\n [%s]' self.str_caller = 'You say, "' + self.emote + '"\n [%s]'
if self.caller.has_account: if self.caller.has_account:
self.str_other = '|c%s|n says, "' % self.caller.key + self.emote + '"\n [%s]' self.str_other = (
'|c%s|n says, "' % self.caller.key + self.emote + '"\n [%s]'
)
else: else:
self.str_other = '%s says, "' % self.caller.key + self.emote + '"\n [%s]' self.str_other = (
'%s says, "' % self.caller.key + self.emote + '"\n [%s]'
)
# trade help # trade help
@ -566,7 +570,9 @@ class CmdAccept(CmdTradeBase):
) )
self.msg_other( self.msg_other(
caller, caller,
self.str_other % "%s |Gaccepts|n the offer. You must now also accept." % caller.key, self.str_other
% "%s |Gaccepts|n the offer. You must now also accept."
% caller.key,
) )
@ -602,7 +608,10 @@ class CmdDecline(CmdTradeBase):
return return
if self.tradehandler.decline(self.caller): if self.tradehandler.decline(self.caller):
# changed a previous accept # changed a previous accept
caller.msg(self.str_caller % "You change your mind, |Rdeclining|n the current offer.") caller.msg(
self.str_caller
% "You change your mind, |Rdeclining|n the current offer."
)
self.msg_other( self.msg_other(
caller, caller,
self.str_other self.str_other
@ -612,7 +621,9 @@ class CmdDecline(CmdTradeBase):
else: else:
# no acceptance to change # no acceptance to change
caller.msg(self.str_caller % "You |Rdecline|n the current offer.") caller.msg(self.str_caller % "You |Rdecline|n the current offer.")
self.msg_other(caller, self.str_other % "%s declines the current offer." % caller.key) self.msg_other(
caller, self.str_other % "%s declines the current offer." % caller.key
)
# evaluate # evaluate
@ -746,7 +757,8 @@ class CmdFinish(CmdTradeBase):
self.tradehandler.finish(force=True) self.tradehandler.finish(force=True)
caller.msg(self.str_caller % "You |raborted|n trade. No deal was made.") caller.msg(self.str_caller % "You |raborted|n trade. No deal was made.")
self.msg_other( self.msg_other(
caller, self.str_other % "%s |raborted|n trade. No deal was made." % caller.key caller,
self.str_other % "%s |raborted|n trade. No deal was made." % caller.key,
) )
@ -802,8 +814,13 @@ class CmdTrade(Command):
"""Initiate trade""" """Initiate trade"""
if not self.args: if not self.args:
if self.caller.ndb.tradehandler and self.caller.ndb.tradeevent.trade_started: if (
self.caller.msg("You are already in a trade. Use 'end trade' to abort it.") self.caller.ndb.tradehandler
and self.caller.ndb.tradeevent.trade_started
):
self.caller.msg(
"You are already in a trade. Use 'end trade' to abort it."
)
else: else:
self.caller.msg("Usage: trade <other party> [accept|decline] [:emote]") self.caller.msg("Usage: trade <other party> [accept|decline] [:emote]")
return return
@ -852,7 +869,9 @@ class CmdTrade(Command):
if self.caller.ndb.tradehandler: if self.caller.ndb.tradehandler:
# trying to start trade without stopping a previous one # trying to start trade without stopping a previous one
if self.caller.ndb.tradehandler.trade_started: if self.caller.ndb.tradehandler.trade_started:
string = "You are already in trade with %s. You need to end trade first." string = (
"You are already in trade with %s. You need to end trade first."
)
else: else:
string = "You are already trying to initiate trade with %s. You need to decline that trade first." string = "You are already trying to initiate trade with %s. You need to decline that trade first."
self.caller.msg(string % part_b.key) self.caller.msg(string % part_b.key)
@ -865,7 +884,9 @@ class CmdTrade(Command):
# initiate a new trade # initiate a new trade
TradeHandler(part_a, part_b) TradeHandler(part_a, part_b)
part_a.msg(selfemote + str_init_a % (part_b.key, TRADE_TIMEOUT)) part_a.msg(selfemote + str_init_a % (part_b.key, TRADE_TIMEOUT))
part_b.msg(theiremote + str_init_b % (part_a.key, part_a.key, TRADE_TIMEOUT)) part_b.msg(
theiremote + str_init_b % (part_a.key, part_a.key, TRADE_TIMEOUT)
)
part_a.scripts.add(TradeTimeout) part_a.scripts.add(TradeTimeout)
return return
elif accept: elif accept:
@ -873,7 +894,8 @@ class CmdTrade(Command):
if part_a.ndb.tradehandler: if part_a.ndb.tradehandler:
# already in a trade # already in a trade
part_a.msg( part_a.msg(
"You are already in trade with %s. You need to end that first." % part_b.key "You are already in trade with %s. You need to end that first."
% part_b.key
) )
return return
if part_b.ndb.tradehandler.join(part_a): if part_b.ndb.tradehandler.join(part_a):
@ -888,7 +910,9 @@ class CmdTrade(Command):
# stopping an invite # stopping an invite
part_a.ndb.tradehandler.finish(force=True) part_a.ndb.tradehandler.finish(force=True)
part_b.msg(theiremote + "%s aborted trade attempt with you." % part_a) part_b.msg(theiremote + "%s aborted trade attempt with you." % part_a)
part_a.msg(selfemote + "You aborted the trade attempt with %s." % part_b) part_a.msg(
selfemote + "You aborted the trade attempt with %s." % part_b
)
elif part_b.ndb.tradehandler and part_b.ndb.tradehandler.unjoin(part_a): elif part_b.ndb.tradehandler and part_b.ndb.tradehandler.unjoin(part_a):
part_b.msg(theiremote + str_noinit_a % part_a.key) part_b.msg(theiremote + str_noinit_a % part_a.key)
part_a.msg(selfemote + str_noinit_b % part_b.key) part_a.msg(selfemote + str_noinit_b % part_b.key)

View file

@ -162,7 +162,9 @@ def _menu_savefunc(caller, buf):
def _menu_quitfunc(caller): def _menu_quitfunc(caller):
caller.cmdset.add( caller.cmdset.add(
BuildingMenuCmdSet, BuildingMenuCmdSet,
permanent=caller.ndb._building_menu and caller.ndb._building_menu.persistent or False, permanent=caller.ndb._building_menu
and caller.ndb._building_menu.persistent
or False,
) )
if caller.ndb._building_menu: if caller.ndb._building_menu:
caller.ndb._building_menu.move(back=True) caller.ndb._building_menu.move(back=True)
@ -209,7 +211,9 @@ def _call_or_get(value, menu=None, choice=None, string=None, obj=None, caller=No
spec = getargspec(value) spec = getargspec(value)
args = spec.args args = spec.args
if spec.keywords: if spec.keywords:
kwargs.update(dict(menu=menu, choice=choice, string=string, obj=obj, caller=caller)) kwargs.update(
dict(menu=menu, choice=choice, string=string, obj=obj, caller=caller)
)
else: else:
if "menu" in args: if "menu" in args:
kwargs["menu"] = menu kwargs["menu"] = menu
@ -343,7 +347,9 @@ class CmdNoInput(Command):
self.menu.display() self.menu.display()
else: else:
log_err("When CMDNOINPUT was called, the building menu couldn't be found") log_err("When CMDNOINPUT was called, the building menu couldn't be found")
self.caller.msg("|rThe building menu couldn't be found, remove the CmdSet.|n") self.caller.msg(
"|rThe building menu couldn't be found, remove the CmdSet.|n"
)
self.caller.cmdset.delete(BuildingMenuCmdSet) self.caller.cmdset.delete(BuildingMenuCmdSet)
@ -363,7 +369,9 @@ class CmdNoMatch(Command):
raw_string = self.args.rstrip() raw_string = self.args.rstrip()
if self.menu is None: if self.menu is None:
log_err("When CMDNOMATCH was called, the building menu couldn't be found") log_err("When CMDNOMATCH was called, the building menu couldn't be found")
self.caller.msg("|rThe building menu couldn't be found, remove the CmdSet.|n") self.caller.msg(
"|rThe building menu couldn't be found, remove the CmdSet.|n"
)
self.caller.cmdset.delete(BuildingMenuCmdSet) self.caller.cmdset.delete(BuildingMenuCmdSet)
return return
@ -485,7 +493,12 @@ class Choice(object):
text = "" text = ""
if self.text: if self.text:
text = _call_or_get( text = _call_or_get(
self.text, menu=self.menu, choice=self, string="", caller=self.caller, obj=self.obj self.text,
menu=self.menu,
choice=self,
string="",
caller=self.caller,
obj=self.obj,
) )
text = dedent(text.strip("\n")) text = dedent(text.strip("\n"))
text = text.format(obj=self.obj, caller=self.caller) text = text.format(obj=self.obj, caller=self.caller)
@ -849,7 +862,9 @@ class BuildingMenu(object):
Current value: |c{{{obj_attr}}}|n Current value: |c{{{obj_attr}}}|n
""".format( """.format(
attr=attr, obj_attr="obj." + attr, back="|n or |y".join(self.keys_go_back) attr=attr,
obj_attr="obj." + attr,
back="|n or |y".join(self.keys_go_back),
) )
choice = Choice( choice = Choice(
@ -908,10 +923,18 @@ class BuildingMenu(object):
""" """
on_enter = on_enter or menu_edit on_enter = on_enter or menu_edit
return self.add_choice( return self.add_choice(
title, key=key, aliases=aliases, attr=attr, glance=glance, on_enter=on_enter, text="" title,
key=key,
aliases=aliases,
attr=attr,
glance=glance,
on_enter=on_enter,
text="",
) )
def add_choice_quit(self, title="quit the menu", key="q", aliases=None, on_enter=None): def add_choice_quit(
self, title="quit the menu", key="q", aliases=None, on_enter=None
):
""" """
Add a simple choice just to quit the building menu. Add a simple choice just to quit the building menu.
@ -975,7 +998,9 @@ class BuildingMenu(object):
menu_class = class_from_module(parent_class) menu_class = class_from_module(parent_class)
except Exception: except Exception:
log_trace( log_trace(
"BuildingMenu: attempting to load class {} failed".format(repr(parent_class)) "BuildingMenu: attempting to load class {} failed".format(
repr(parent_class)
)
) )
return return
@ -986,7 +1011,9 @@ class BuildingMenu(object):
) )
except Exception: except Exception:
log_trace( log_trace(
"An error occurred while creating building menu {}".format(repr(parent_class)) "An error occurred while creating building menu {}".format(
repr(parent_class)
)
) )
return return
else: else:
@ -1014,7 +1041,9 @@ class BuildingMenu(object):
""" """
parent_keys = parent_keys or [] parent_keys = parent_keys or []
parents = list(self.parents) parents = list(self.parents)
parents.append((type(self).__module__ + "." + type(self).__name__, self.obj, parent_keys)) parents.append(
(type(self).__module__ + "." + type(self).__name__, self.obj, parent_keys)
)
if self.caller.cmdset.has(BuildingMenuCmdSet): if self.caller.cmdset.has(BuildingMenuCmdSet):
self.caller.cmdset.remove(BuildingMenuCmdSet) self.caller.cmdset.remove(BuildingMenuCmdSet)
@ -1023,7 +1052,9 @@ class BuildingMenu(object):
menu_class = class_from_module(submenu_class) menu_class = class_from_module(submenu_class)
except Exception: except Exception:
log_trace( log_trace(
"BuildingMenu: attempting to load class {} failed".format(repr(submenu_class)) "BuildingMenu: attempting to load class {} failed".format(
repr(submenu_class)
)
) )
return return
@ -1032,7 +1063,9 @@ class BuildingMenu(object):
building_menu = menu_class(self.caller, submenu_obj, parents=parents) building_menu = menu_class(self.caller, submenu_obj, parents=parents)
except Exception: except Exception:
log_trace( log_trace(
"An error occurred while creating building menu {}".format(repr(submenu_class)) "An error occurred while creating building menu {}".format(
repr(submenu_class)
)
) )
return return
else: else:
@ -1068,7 +1101,9 @@ class BuildingMenu(object):
if not back: # Move forward if not back: # Move forward
if not key: if not key:
raise ValueError("you are asking to move forward, you should specify a key.") raise ValueError(
"you are asking to move forward, you should specify a key."
)
self.keys.append(key) self.keys.append(key)
else: # Move backward else: # Move backward
@ -1099,9 +1134,9 @@ class BuildingMenu(object):
# Display methods. Override for customization # Display methods. Override for customization
def display_title(self): def display_title(self):
"""Return the menu title to be displayed.""" """Return the menu title to be displayed."""
return _call_or_get(self.title, menu=self, obj=self.obj, caller=self.caller).format( return _call_or_get(
obj=self.obj self.title, menu=self, obj=self.obj, caller=self.caller
) ).format(obj=self.obj)
def display_choice(self, choice): def display_choice(self, choice):
"""Display the specified choice. """Display the specified choice.
@ -1117,13 +1152,24 @@ class BuildingMenu(object):
pos = clear_title.find(choice.key.lower()) pos = clear_title.find(choice.key.lower())
ret = " " ret = " "
if pos >= 0: if pos >= 0:
ret += title[:pos] + "[|y" + choice.key.title() + "|n]" + title[pos + len(choice.key) :] ret += (
title[:pos]
+ "[|y"
+ choice.key.title()
+ "|n]"
+ title[pos + len(choice.key) :]
)
else: else:
ret += "[|y" + choice.key.title() + "|n] " + title ret += "[|y" + choice.key.title() + "|n] " + title
if choice.glance: if choice.glance:
glance = _call_or_get( glance = _call_or_get(
choice.glance, menu=self, choice=choice, caller=self.caller, string="", obj=self.obj choice.glance,
menu=self,
choice=choice,
caller=self.caller,
string="",
obj=self.obj,
) )
glance = glance.format(obj=self.obj, caller=self.caller) glance = glance.format(obj=self.obj, caller=self.caller)
@ -1161,7 +1207,9 @@ class BuildingMenu(object):
if not class_name: if not class_name:
log_err( log_err(
"BuildingMenu: on caller {}, a persistent attribute holds building menu " "BuildingMenu: on caller {}, a persistent attribute holds building menu "
"data, but no class could be found to restore the menu".format(caller) "data, but no class could be found to restore the menu".format(
caller
)
) )
return return
@ -1169,7 +1217,9 @@ class BuildingMenu(object):
menu_class = class_from_module(class_name) menu_class = class_from_module(class_name)
except Exception: except Exception:
log_trace( log_trace(
"BuildingMenu: attempting to load class {} failed".format(repr(class_name)) "BuildingMenu: attempting to load class {} failed".format(
repr(class_name)
)
) )
return return
@ -1181,11 +1231,18 @@ class BuildingMenu(object):
persistent = menu.get("persistent", False) persistent = menu.get("persistent", False)
try: try:
building_menu = menu_class( building_menu = menu_class(
caller, obj, title=title, keys=keys, parents=parents, persistent=persistent caller,
obj,
title=title,
keys=keys,
parents=parents,
persistent=persistent,
) )
except Exception: except Exception:
log_trace( log_trace(
"An error occurred while creating building menu {}".format(repr(class_name)) "An error occurred while creating building menu {}".format(
repr(class_name)
)
) )
return return
@ -1256,7 +1313,9 @@ class GenericBuildingCmd(Command):
def func(self): def func(self):
if not self.args.strip(): if not self.args.strip():
self.msg("You should provide an argument to this function: the object to edit.") self.msg(
"You should provide an argument to this function: the object to edit."
)
return return
obj = self.caller.search(self.args.strip(), global_search=True) obj = self.caller.search(self.args.strip(), global_search=True)

View file

@ -79,7 +79,9 @@ class CmdOOCLook(default_cmds.CmdLook):
if self.args: if self.args:
# Maybe the caller wants to look at a character # Maybe the caller wants to look at a character
if not avail_chars: if not avail_chars:
self.caller.msg("You have no characters to look at. Why not create one?") self.caller.msg(
"You have no characters to look at. Why not create one?"
)
return return
objs = managers.objects.get_objs_with_key_and_typeclass( objs = managers.objects.get_objs_with_key_and_typeclass(
self.args.strip(), CHARACTER_TYPECLASS self.args.strip(), CHARACTER_TYPECLASS
@ -99,8 +101,12 @@ class CmdOOCLook(default_cmds.CmdLook):
charnames = [charobj.key for charobj in charobjs if charobj] charnames = [charobj.key for charobj in charobjs if charobj]
if charnames: if charnames:
charlist = "The following Character(s) are available:\n\n" charlist = "The following Character(s) are available:\n\n"
charlist += "\n\r".join(["|w %s|n" % charname for charname in charnames]) charlist += "\n\r".join(
charlist += "\n\n Use |w@ic <character name>|n to switch to that Character." ["|w %s|n" % charname for charname in charnames]
)
charlist += (
"\n\n Use |w@ic <character name>|n to switch to that Character."
)
else: else:
charlist = "You have no Characters." charlist = "You have no Characters."
string = """ You, %s, are an |wOOC ghost|n without form. The world is hidden string = """ You, %s, are an |wOOC ghost|n without form. The world is hidden
@ -155,7 +161,9 @@ class CmdOOCCharacterCreate(Command):
self.caller.msg("Usage: create <character name>") self.caller.msg("Usage: create <character name>")
return return
charname = self.args.strip() charname = self.args.strip()
old_char = managers.objects.get_objs_with_key_and_typeclass(charname, CHARACTER_TYPECLASS) old_char = managers.objects.get_objs_with_key_and_typeclass(
charname, CHARACTER_TYPECLASS
)
if old_char: if old_char:
self.caller.msg("Character |c%s|n already exists." % charname) self.caller.msg("Character |c%s|n already exists." % charname)
return return

View file

@ -254,7 +254,8 @@ class Clothing(DefaultObject):
for garment in get_worn_clothes(wearer): for garment in get_worn_clothes(wearer):
if ( if (
garment.db.clothing_type garment.db.clothing_type
and garment.db.clothing_type in CLOTHING_TYPE_AUTOCOVER[self.db.clothing_type] and garment.db.clothing_type
in CLOTHING_TYPE_AUTOCOVER[self.db.clothing_type]
): ):
to_cover.append(garment) to_cover.append(garment)
garment.db.covered_by = self garment.db.covered_by = self
@ -394,13 +395,18 @@ class CmdWear(MuxCommand):
return return
# Enforce overall clothing limit. # Enforce overall clothing limit.
if CLOTHING_OVERALL_LIMIT and len(get_worn_clothes(self.caller)) >= CLOTHING_OVERALL_LIMIT: if (
CLOTHING_OVERALL_LIMIT
and len(get_worn_clothes(self.caller)) >= CLOTHING_OVERALL_LIMIT
):
self.caller.msg("You can't wear any more clothes.") self.caller.msg("You can't wear any more clothes.")
return return
# Apply individual clothing type limits. # Apply individual clothing type limits.
if clothing.db.clothing_type and not clothing.db.worn: if clothing.db.clothing_type and not clothing.db.worn:
type_count = single_type_count(get_worn_clothes(self.caller), clothing.db.clothing_type) type_count = single_type_count(
get_worn_clothes(self.caller), clothing.db.clothing_type
)
if clothing.db.clothing_type in list(CLOTHING_TYPE_LIMIT.keys()): if clothing.db.clothing_type in list(CLOTHING_TYPE_LIMIT.keys()):
if type_count >= CLOTHING_TYPE_LIMIT[clothing.db.clothing_type]: if type_count >= CLOTHING_TYPE_LIMIT[clothing.db.clothing_type]:
self.caller.msg( self.caller.msg(
@ -414,7 +420,9 @@ class CmdWear(MuxCommand):
return return
if len(self.arglist) > 1: # If wearstyle arguments given if len(self.arglist) > 1: # If wearstyle arguments given
wearstyle_list = self.arglist # Split arguments into a list of words wearstyle_list = self.arglist # Split arguments into a list of words
del wearstyle_list[0] # Leave first argument (the clothing item) out of the wearstyle del wearstyle_list[
0
] # Leave first argument (the clothing item) out of the wearstyle
wearstring = " ".join( wearstring = " ".join(
str(e) for e in wearstyle_list str(e) for e in wearstyle_list
) # Join list of args back into one string ) # Join list of args back into one string
@ -457,7 +465,9 @@ class CmdRemove(MuxCommand):
self.caller.msg("You're not wearing that!") self.caller.msg("You're not wearing that!")
return return
if clothing.db.covered_by: if clothing.db.covered_by:
self.caller.msg("You have to take off %s first." % clothing.db.covered_by.name) self.caller.msg(
"You have to take off %s first." % clothing.db.covered_by.name
)
return return
clothing.remove(self.caller) clothing.remove(self.caller)
@ -489,13 +499,17 @@ class CmdCover(MuxCommand):
if self.arglist[1].lower() == "with" and len(self.arglist) > 2: if self.arglist[1].lower() == "with" and len(self.arglist) > 2:
del self.arglist[1] del self.arglist[1]
to_cover = self.caller.search(self.arglist[0], candidates=self.caller.contents) to_cover = self.caller.search(self.arglist[0], candidates=self.caller.contents)
cover_with = self.caller.search(self.arglist[1], candidates=self.caller.contents) cover_with = self.caller.search(
self.arglist[1], candidates=self.caller.contents
)
if not to_cover or not cover_with: if not to_cover or not cover_with:
return return
if not to_cover.is_typeclass("evennia.contrib.clothing.Clothing", exact=False): if not to_cover.is_typeclass("evennia.contrib.clothing.Clothing", exact=False):
self.caller.msg("%s isn't clothes!" % to_cover.name) self.caller.msg("%s isn't clothes!" % to_cover.name)
return return
if not cover_with.is_typeclass("evennia.contrib.clothing.Clothing", exact=False): if not cover_with.is_typeclass(
"evennia.contrib.clothing.Clothing", exact=False
):
self.caller.msg("%s isn't clothes!" % cover_with.name) self.caller.msg("%s isn't clothes!" % cover_with.name)
return return
if cover_with.db.clothing_type: if cover_with.db.clothing_type:
@ -513,7 +527,8 @@ class CmdCover(MuxCommand):
return return
if to_cover.db.covered_by: if to_cover.db.covered_by:
self.caller.msg( self.caller.msg(
"%s is already covered by %s." % (cover_with.name, to_cover.db.covered_by.name) "%s is already covered by %s."
% (cover_with.name, to_cover.db.covered_by.name)
) )
return return
if not cover_with.db.worn: if not cover_with.db.worn:
@ -562,9 +577,13 @@ class CmdUncover(MuxCommand):
return return
covered_by = to_uncover.db.covered_by covered_by = to_uncover.db.covered_by
if covered_by.db.covered_by: if covered_by.db.covered_by:
self.caller.msg("%s is under too many layers to uncover." % (to_uncover.name)) self.caller.msg(
"%s is under too many layers to uncover." % (to_uncover.name)
)
return return
self.caller.location.msg_contents("%s uncovers %s." % (self.caller, to_uncover.name)) self.caller.location.msg_contents(
"%s uncovers %s." % (self.caller, to_uncover.name)
)
to_uncover.db.covered_by = None to_uncover.db.covered_by = None
@ -605,7 +624,9 @@ class CmdDrop(MuxCommand):
# This part is new! # This part is new!
# You can't drop clothing items that are covered. # You can't drop clothing items that are covered.
if obj.db.covered_by: if obj.db.covered_by:
caller.msg("You can't drop that because it's covered by %s." % obj.db.covered_by) caller.msg(
"You can't drop that because it's covered by %s." % obj.db.covered_by
)
return return
# Remove clothes if they're dropped. # Remove clothes if they're dropped.
if obj.db.worn: if obj.db.worn:
@ -613,7 +634,9 @@ class CmdDrop(MuxCommand):
obj.move_to(caller.location, quiet=True) obj.move_to(caller.location, quiet=True)
caller.msg("You drop %s." % (obj.name,)) caller.msg("You drop %s." % (obj.name,))
caller.location.msg_contents("%s drops %s." % (caller.name, obj.name), exclude=caller) caller.location.msg_contents(
"%s drops %s." % (caller.name, obj.name), exclude=caller
)
# Call the object script's at_drop() method. # Call the object script's at_drop() method.
obj.at_drop(caller) obj.at_drop(caller)
@ -658,7 +681,8 @@ class CmdGive(MuxCommand):
# This is new! Can't give away something that's worn. # This is new! Can't give away something that's worn.
if to_give.db.covered_by: if to_give.db.covered_by:
caller.msg( caller.msg(
"You can't give that away because it's covered by %s." % to_give.db.covered_by "You can't give that away because it's covered by %s."
% to_give.db.covered_by
) )
return return
# Remove clothes if they're given. # Remove clothes if they're given.

View file

@ -115,7 +115,10 @@ CURLY_COLOR_ANSI_EXTRA_MAP = [
(r"{-", _ANSI_TAB), # tab (r"{-", _ANSI_TAB), # tab
(r"{_", _ANSI_SPACE), # space (r"{_", _ANSI_SPACE), # space
(r"{*", _ANSI_INVERSE), # invert (r"{*", _ANSI_INVERSE), # invert
(r"{^", _ANSI_BLINK), # blinking text (very annoying and not supported by all clients) (
r"{^",
_ANSI_BLINK,
), # blinking text (very annoying and not supported by all clients)
(r"{u", _ANSI_UNDERLINE), # underline (r"{u", _ANSI_UNDERLINE), # underline
(r"{r", _ANSI_HILITE + _ANSI_RED), (r"{r", _ANSI_HILITE + _ANSI_RED),
(r"{g", _ANSI_HILITE + _ANSI_GREEN), (r"{g", _ANSI_HILITE + _ANSI_GREEN),
@ -156,7 +159,9 @@ CURLY_COLOR_ANSI_EXTRA_MAP = [
] ]
CURLY_COLOR_XTERM256_EXTRA_FG = [r"\{([0-5])([0-5])([0-5])"] # |123 - foreground colour CURLY_COLOR_XTERM256_EXTRA_FG = [r"\{([0-5])([0-5])([0-5])"] # |123 - foreground colour
CURLY_COLOR_XTERM256_EXTRA_BG = [r"\{\[([0-5])([0-5])([0-5])"] # |[123 - background colour CURLY_COLOR_XTERM256_EXTRA_BG = [
r"\{\[([0-5])([0-5])([0-5])"
] # |[123 - background colour
CURLY_COLOR_XTERM256_EXTRA_GFG = [r"\{=([a-z])"] # |=a - greyscale foreground CURLY_COLOR_XTERM256_EXTRA_GFG = [r"\{=([a-z])"] # |=a - greyscale foreground
CURLY_COLOR_XTERM256_EXTRA_GBG = [r"\{\[=([a-z])"] # |[=a - greyscale background CURLY_COLOR_XTERM256_EXTRA_GBG = [r"\{\[=([a-z])"] # |[=a - greyscale background
@ -215,7 +220,9 @@ MUX_COLOR_ANSI_EXTRA_MAP = [
] ]
MUX_COLOR_XTERM256_EXTRA_FG = [r"%c([0-5])([0-5])([0-5])"] # %c123 - foreground colour MUX_COLOR_XTERM256_EXTRA_FG = [r"%c([0-5])([0-5])([0-5])"] # %c123 - foreground colour
MUX_COLOR_XTERM256_EXTRA_BG = [r"%c\[([0-5])([0-5])([0-5])"] # %c[123 - background colour MUX_COLOR_XTERM256_EXTRA_BG = [
r"%c\[([0-5])([0-5])([0-5])"
] # %c[123 - background colour
MUX_COLOR_XTERM256_EXTRA_GFG = [r"%c=([a-z])"] # %c=a - greyscale foreground MUX_COLOR_XTERM256_EXTRA_GFG = [r"%c=([a-z])"] # %c=a - greyscale foreground
MUX_COLOR_XTERM256_EXTRA_GBG = [r"%c\[=([a-z])"] # %c[=a - greyscale background MUX_COLOR_XTERM256_EXTRA_GBG = [r"%c\[=([a-z])"] # %c[=a - greyscale background

View file

@ -117,7 +117,9 @@ def gametime_to_realtime(format=False, **kwargs):
name = name[:-1] name = name[:-1]
if name not in UNITS: if name not in UNITS:
raise ValueError("the unit {} isn't defined as a valid " "game time unit".format(name)) raise ValueError(
"the unit {} isn't defined as a valid " "game time unit".format(name)
)
rtime += value * UNITS[name] rtime += value * UNITS[name]
rtime /= TIMEFACTOR rtime /= TIMEFACTOR
if format: if format:
@ -125,7 +127,9 @@ def gametime_to_realtime(format=False, **kwargs):
return rtime return rtime
def realtime_to_gametime(secs=0, mins=0, hrs=0, days=0, weeks=0, months=0, yrs=0, format=False): def realtime_to_gametime(
secs=0, mins=0, hrs=0, days=0, weeks=0, months=0, yrs=0, format=False
):
""" """
This method calculates how much in-game time a real-world time This method calculates how much in-game time a real-world time
interval would correspond to. This is usually a lot less interval would correspond to. This is usually a lot less

View file

@ -177,7 +177,9 @@ class CmdDice(default_cmds.MuxCommand):
ndicelimit = 10000 # Maximum number of dice ndicelimit = 10000 # Maximum number of dice
nsidelimit = 10000 # Maximum number of sides nsidelimit = 10000 # Maximum number of sides
if int(parts[0]) > ndicelimit or int(parts[2]) > nsidelimit: if int(parts[0]) > ndicelimit or int(parts[2]) > nsidelimit:
self.caller.msg("The maximum roll allowed is %sd%s." % (ndicelimit, nsidelimit)) self.caller.msg(
"The maximum roll allowed is %sd%s." % (ndicelimit, nsidelimit)
)
return return
ndice, nsides = parts[0], parts[2] ndice, nsides = parts[0], parts[2]
@ -201,7 +203,11 @@ class CmdDice(default_cmds.MuxCommand):
# do the roll # do the roll
try: try:
result, outcome, diff, rolls = roll_dice( result, outcome, diff, rolls = roll_dice(
ndice, nsides, modifier=modifier, conditional=conditional, return_tuple=True ndice,
nsides,
modifier=modifier,
conditional=conditional,
return_tuple=True,
) )
except ValueError: except ValueError:
self.caller.msg( self.caller.msg(
@ -211,7 +217,9 @@ class CmdDice(default_cmds.MuxCommand):
return return
# format output # format output
if len(rolls) > 1: if len(rolls) > 1:
rolls = ", ".join(str(roll) for roll in rolls[:-1]) + " and " + str(rolls[-1]) rolls = (
", ".join(str(roll) for roll in rolls[:-1]) + " and " + str(rolls[-1])
)
else: else:
rolls = rolls[0] rolls = rolls[0]
if outcome is None: if outcome is None:

View file

@ -56,7 +56,9 @@ MULTISESSION_MODE = settings.MULTISESSION_MODE
CONNECTION_SCREEN_MODULE = settings.CONNECTION_SCREEN_MODULE CONNECTION_SCREEN_MODULE = settings.CONNECTION_SCREEN_MODULE
CONNECTION_SCREEN = "" CONNECTION_SCREEN = ""
try: try:
CONNECTION_SCREEN = ansi.parse_ansi(utils.random_string_from_module(CONNECTION_SCREEN_MODULE)) CONNECTION_SCREEN = ansi.parse_ansi(
utils.random_string_from_module(CONNECTION_SCREEN_MODULE)
)
except Exception: except Exception:
# malformed connection screen or no screen given # malformed connection screen or no screen given
pass pass
@ -176,18 +178,24 @@ class CmdUnconnectedCreate(MuxCommand):
try: try:
accountname, email, password = self.accountinfo accountname, email, password = self.accountinfo
except ValueError: except ValueError:
string = '\n\r Usage (without <>): create "<accountname>" <email> <password>' string = (
'\n\r Usage (without <>): create "<accountname>" <email> <password>'
)
session.msg(string) session.msg(string)
return return
if not email or not password: if not email or not password:
session.msg("\n\r You have to supply an e-mail address followed by a password.") session.msg(
"\n\r You have to supply an e-mail address followed by a password."
)
return return
if not utils.validate_email_address(email): if not utils.validate_email_address(email):
# check so the email at least looks ok. # check so the email at least looks ok.
session.msg("'%s' is not a valid e-mail address." % email) session.msg("'%s' is not a valid e-mail address." % email)
return return
# sanity checks # sanity checks
if not re.findall(r"^[\w. @+\-']+$", accountname) or not (0 < len(accountname) <= 30): if not re.findall(r"^[\w. @+\-']+$", accountname) or not (
0 < len(accountname) <= 30
):
# this echoes the restrictions made by django's auth # this echoes the restrictions made by django's auth
# module (except not allowing spaces, for convenience of # module (except not allowing spaces, for convenience of
# logging in). # logging in).
@ -198,7 +206,9 @@ class CmdUnconnectedCreate(MuxCommand):
accountname = re.sub(r"\s+", " ", accountname).strip() accountname = re.sub(r"\s+", " ", accountname).strip()
if AccountDB.objects.filter(username__iexact=accountname): if AccountDB.objects.filter(username__iexact=accountname):
# account already exists (we also ignore capitalization here) # account already exists (we also ignore capitalization here)
session.msg("Sorry, there is already an account with the name '%s'." % accountname) session.msg(
"Sorry, there is already an account with the name '%s'." % accountname
)
return return
if AccountDB.objects.get_account_from_email(email): if AccountDB.objects.get_account_from_email(email):
# email already set on an account # email already set on an account
@ -251,9 +261,7 @@ class CmdUnconnectedCreate(MuxCommand):
# tell the caller everything went well. # tell the caller everything went well.
string = "A new account '%s' was created. Welcome!" string = "A new account '%s' was created. Welcome!"
if " " in accountname: if " " in accountname:
string += ( string += "\n\nYou can now log in with the command 'connect \"%s\" <your password>'."
"\n\nYou can now log in with the command 'connect \"%s\" <your password>'."
)
else: else:
string += "\n\nYou can now log with the command 'connect %s <your password>'." string += "\n\nYou can now log with the command 'connect %s <your password>'."
session.msg(string % (accountname, email)) session.msg(string % (accountname, email))
@ -262,7 +270,9 @@ class CmdUnconnectedCreate(MuxCommand):
# We are in the middle between logged in and -not, so we have # We are in the middle between logged in and -not, so we have
# to handle tracebacks ourselves at this point. If we don't, # to handle tracebacks ourselves at this point. If we don't,
# we won't see any errors at all. # we won't see any errors at all.
session.msg("An error occurred. Please e-mail an admin if the problem persists.") session.msg(
"An error occurred. Please e-mail an admin if the problem persists."
)
logger.log_trace() logger.log_trace()
raise raise

View file

@ -234,7 +234,9 @@ class CmdGiveUp(CmdEvscapeRoom):
self.room.log(f"QUIT: {self.caller.key} used the quit command") self.room.log(f"QUIT: {self.caller.key} used the quit command")
# manually call move hooks # manually call move hooks
self.room.msg_room(self.caller, f"|r{self.caller.key} gave up and was whisked away!|n") self.room.msg_room(
self.caller, f"|r{self.caller.key} gave up and was whisked away!|n"
)
self.room.at_object_leave(self.caller, self.caller.home) self.room.at_object_leave(self.caller, self.caller.home)
self.caller.move_to(self.caller.home, quiet=True, move_hooks=False) self.caller.move_to(self.caller.home, quiet=True, move_hooks=False)
@ -313,7 +315,9 @@ class CmdWho(CmdEvscapeRoom, default_cmds.CmdWho):
for obj in self.room.get_all_characters() for obj in self.room.get_all_characters()
if obj != caller if obj != caller
] ]
chars = "\n".join([f"{caller.key} - {caller.db.desc.strip()} (you)"] + chars) chars = "\n".join(
[f"{caller.key} - {caller.db.desc.strip()} (you)"] + chars
)
txt = f"|cPlayers in this room (room-name '{self.room.name}')|n:\n {chars}" txt = f"|cPlayers in this room (room-name '{self.room.name}')|n:\n {chars}"
caller.msg(txt) caller.msg(txt)
@ -389,7 +393,9 @@ class CmdEmote(Command):
emote = self.args.strip() emote = self.args.strip()
if not emote: if not emote:
self.caller.msg('Usage: emote /me points to /door, saying "look over there!"') self.caller.msg(
'Usage: emote /me points to /door, saying "look over there!"'
)
return return
speech_clr = "|c" speech_clr = "|c"
@ -429,7 +435,9 @@ class CmdEmote(Command):
if target == self.caller: if target == self.caller:
txt = [f"{self_clr}{self.caller.get_display_name(target)}|n "] + txt txt = [f"{self_clr}{self.caller.get_display_name(target)}|n "] + txt
else: else:
txt = [f"{player_clr}{self.caller.get_display_name(target)}|n "] + txt txt = [
f"{player_clr}{self.caller.get_display_name(target)}|n "
] + txt
txt = "".join(txt).strip() + ("." if add_period else "") txt = "".join(txt).strip() + ("." if add_period else "")
if not logged and hasattr(self.caller.location, "log"): if not logged and hasattr(self.caller.location, "log"):
self.caller.location.log(f"emote: {txt}") self.caller.location.log(f"emote: {txt}")
@ -531,7 +539,10 @@ class CmdRerouter(default_cmds.MuxCommand):
from evennia.commands import cmdhandler from evennia.commands import cmdhandler
cmdhandler.cmdhandler( cmdhandler.cmdhandler(
self.session, self.raw_string, cmdobj=CmdFocusInteraction(), cmdobj_key=self.cmdname self.session,
self.raw_string,
cmdobj=CmdFocusInteraction(),
cmdobj_key=self.cmdname,
) )
@ -603,7 +614,9 @@ class CmdStand(CmdEvscapeRoom):
obj, position = pos obj, position = pos
self.caller.attributes.remove("position", category=self.room.tagcategory) self.caller.attributes.remove("position", category=self.room.tagcategory)
del obj.db.positions[self.caller] del obj.db.positions[self.caller]
self.room.msg_room(self.caller, "~You ~are back standing on the floor again.") self.room.msg_room(
self.caller, "~You ~are back standing on the floor again."
)
else: else:
self.caller.msg("You are already standing.") self.caller.msg("You are already standing.")
@ -679,7 +692,9 @@ class CmdCreateObj(CmdEvscapeRoom):
else: else:
name = args.strip() name = args.strip()
obj = create_evscaperoom_object(typeclass=typeclass, key=name, location=self.room) obj = create_evscaperoom_object(
typeclass=typeclass, key=name, location=self.room
)
caller.msg(f"Created new object {name} ({obj.typeclass_path}).") caller.msg(f"Created new object {name} ({obj.typeclass_path}).")

View file

@ -151,7 +151,9 @@ def node_set_desc(caller, raw_string, **kwargs):
current_desc = kwargs.get("desc", caller.db.desc) current_desc = kwargs.get("desc", caller.db.desc)
text = ( text = (
"Your current description is\n\n " f' "{current_desc}"' "\n\nEnter your new description!" "Your current description is\n\n "
f' "{current_desc}"'
"\n\nEnter your new description!"
) )
def _temp_description(caller, raw_string, **kwargs): def _temp_description(caller, raw_string, **kwargs):
@ -169,7 +171,10 @@ def node_set_desc(caller, raw_string, **kwargs):
options = ( options = (
{"key": "_default", "goto": _temp_description}, {"key": "_default", "goto": _temp_description},
{"key": ("|g[a]ccept", "a"), "goto": (_set_description, {"desc": current_desc})}, {
"key": ("|g[a]ccept", "a"),
"goto": (_set_description, {"desc": current_desc}),
},
{"key": ("|r[c]ancel", "c"), "goto": "node_start"}, {"key": ("|r[c]ancel", "c"), "goto": "node_start"},
) )
return text, options return text, options
@ -180,7 +185,10 @@ def node_create_room(caller, raw_string, **kwargs):
text = _CREATE_ROOM_TEXT text = _CREATE_ROOM_TEXT
options = ( options = (
{"key": ("|g[c]reate new room and start game|n", "c"), "goto": _create_new_room}, {
"key": ("|g[c]reate new room and start game|n", "c"),
"goto": _create_new_room,
},
{"key": ("|r[a]bort and go back|n", "a"), "goto": "node_start"}, {"key": ("|r[a]bort and go back|n", "a"), "goto": "node_start"},
) )
@ -221,7 +229,10 @@ def node_quit(caller, raw_string, **kwargs):
from evennia import default_cmds from evennia import default_cmds
cmdhandler.cmdhandler( cmdhandler.cmdhandler(
caller.ndb._menutree._session, "", cmdobj=default_cmds.CmdQuit(), cmdobj_key="@quit" caller.ndb._menutree._session,
"",
cmdobj=default_cmds.CmdQuit(),
cmdobj_key="@quit",
) )
return text, None # empty options exit the menu return text, None # empty options exit the menu
@ -248,7 +259,9 @@ class EvscaperoomMenu(EvMenu):
main_options.append(key) main_options.append(key)
main_options = " | ".join(main_options) main_options = " | ".join(main_options)
room_choices = super().options_formatter(room_choices) room_choices = super().options_formatter(room_choices)
return "{}{}{}".format(main_options, "\n\n" if room_choices else "", room_choices) return "{}{}{}".format(
main_options, "\n\n" if room_choices else "", room_choices
)
# access function # access function
@ -265,7 +278,9 @@ def run_evscaperoom_menu(caller):
"node_join_room": node_join_room, "node_join_room": node_join_room,
} }
EvscaperoomMenu(caller, menutree, startnode="node_start", cmd_on_exit=None, auto_quit=True) EvscaperoomMenu(
caller, menutree, startnode="node_start", cmd_on_exit=None, auto_quit=True
)
# ------------------------------------------------------------ # ------------------------------------------------------------
@ -285,7 +300,9 @@ def _toggle_screen_reader(caller, raw_string, **kwargs):
session = kwargs["session"] session = kwargs["session"]
# flip old setting # flip old setting
session.protocol_flags["SCREENREADER"] = not session.protocol_flags.get("SCREENREADER", False) session.protocol_flags["SCREENREADER"] = not session.protocol_flags.get(
"SCREENREADER", False
)
# sync setting with portal # sync setting with portal
session.sessionhandler.session_portal_sync(session) session.sessionhandler.session_portal_sync(session)
return None, kwargs # rerun node return None, kwargs # rerun node

View file

@ -64,7 +64,12 @@ class EvscaperoomObject(DefaultObject):
# this mapping allows for prettier descriptions of our current # this mapping allows for prettier descriptions of our current
# position # position
position_prep_map = {"sit": "sitting", "kneel": "kneeling", "lie": "lying", "climb": "standing"} position_prep_map = {
"sit": "sitting",
"kneel": "kneeling",
"lie": "lying",
"climb": "standing",
}
def at_object_creation(self): def at_object_creation(self):
""" """
@ -161,7 +166,9 @@ class EvscaperoomObject(DefaultObject):
you = caller.key if caller else "they" you = caller.key if caller else "they"
first_person, third_person = parse_for_perspectives(string, you=you) first_person, third_person = parse_for_perspectives(string, you=you)
for char in self.room.get_all_characters(): for char in self.room.get_all_characters():
options = char.attributes.get("options", category=self.room.tagcategory, default={}) options = char.attributes.get(
"options", category=self.room.tagcategory, default={}
)
style = options.get("things_style", 2) style = options.get("things_style", 2)
if char == caller: if char == caller:
if not skip_caller: if not skip_caller:
@ -178,7 +185,9 @@ class EvscaperoomObject(DefaultObject):
""" """
# we must clean away markers # we must clean away markers
first_person, _ = parse_for_perspectives(string) first_person, _ = parse_for_perspectives(string)
options = caller.attributes.get("options", category=self.room.tagcategory, default={}) options = caller.attributes.get(
"options", category=self.room.tagcategory, default={}
)
style = options.get("things_style", 2) style = options.get("things_style", 2)
txt = parse_for_things(first_person, things_style=style) txt = parse_for_things(first_person, things_style=style)
caller.msg((txt, {"type": client_type})) caller.msg((txt, {"type": client_type}))
@ -276,7 +285,9 @@ class EvscaperoomObject(DefaultObject):
""" """
args = re.sub( args = re.sub(
r"|".join(r"^{}\s".format(prep) for prep in self.action_prepositions), "", args r"|".join(r"^{}\s".format(prep) for prep in self.action_prepositions),
"",
args,
) )
return args return args
@ -307,7 +318,8 @@ class EvscaperoomObject(DefaultObject):
helpstr = f"It looks like {self.key} may be " "suitable to {callsigns}." helpstr = f"It looks like {self.key} may be " "suitable to {callsigns}."
else: else:
helpstr = ( helpstr = (
f"At first glance, it looks like {self.key} might be " "suitable to {callsigns}." f"At first glance, it looks like {self.key} might be "
"suitable to {callsigns}."
) )
return command_signatures, helpstr return command_signatures, helpstr
@ -330,10 +342,14 @@ class EvscaperoomObject(DefaultObject):
# custom-created signatures. We don't sort these # custom-created signatures. We don't sort these
command_signatures, helpstr = self.get_cmd_signatures() command_signatures, helpstr = self.get_cmd_signatures()
callsigns = list_to_string(["*" + sig for sig in command_signatures], endsep="or") callsigns = list_to_string(
["*" + sig for sig in command_signatures], endsep="or"
)
# parse for *thing markers (use these as items) # parse for *thing markers (use these as items)
options = caller.attributes.get("options", category=self.room.tagcategory, default={}) options = caller.attributes.get(
"options", category=self.room.tagcategory, default={}
)
style = options.get("things_style", 2) style = options.get("things_style", 2)
helpstr = helpstr.format(callsigns=callsigns) helpstr = helpstr.format(callsigns=callsigns)
@ -521,7 +537,11 @@ class IndexReadable(Readable):
""" """
# keys should be lower-key # keys should be lower-key
index = {"page1": "This is page1", "page2": "This is page2", "page two": "page2"} # alias index = {
"page1": "This is page1",
"page2": "This is page2",
"page two": "page2",
} # alias
def at_focus_read(self, caller, **kwargs): def at_focus_read(self, caller, **kwargs):
@ -800,7 +820,8 @@ class Combinable(BaseApplicable):
new_obj = create_evscaperoom_object(**create_dict) new_obj = create_evscaperoom_object(**create_dict)
if new_obj and self.destroy_components: if new_obj and self.destroy_components:
self.msg_char( self.msg_char(
caller, f"You combine *{self.key} with {other_obj.key} to make {new_obj.key}!" caller,
f"You combine *{self.key} with {other_obj.key} to make {new_obj.key}!",
) )
other_obj.delete() other_obj.delete()
self.delete() self.delete()
@ -1020,7 +1041,8 @@ class BasePositionable(EvscaperoomObject):
def at_again_position(self, caller, position): def at_again_position(self, caller, position):
self.msg_char( self.msg_char(
caller, f"But you are already {self.position_prep_map[position]} on *{self.key}?" caller,
f"But you are already {self.position_prep_map[position]} on *{self.key}?",
) )
def at_position(self, caller, position): def at_position(self, caller, position):

View file

@ -102,7 +102,9 @@ class EvscapeRoom(EvscaperoomObject, DefaultRoom):
if achievement not in achievements: if achievement not in achievements:
self.log(f"achievement: {caller} earned '{achievement}' - {subtext}") self.log(f"achievement: {caller} earned '{achievement}' - {subtext}")
achievements[achievement] = subtext achievements[achievement] = subtext
caller.attributes.add("achievements", achievements, category=self.tagcategory) caller.attributes.add(
"achievements", achievements, category=self.tagcategory
)
def get_all_characters(self): def get_all_characters(self):
""" """
@ -224,7 +226,8 @@ class EvscapeRoom(EvscaperoomObject, DefaultRoom):
def return_appearance(self, looker, **kwargs): def return_appearance(self, looker, **kwargs):
obj, pos = self.get_position(looker) obj, pos = self.get_position(looker)
pos = ( pos = (
f"\n|x[{self.position_prep_map[pos]} on " f"{obj.get_display_name(looker)}]|n" f"\n|x[{self.position_prep_map[pos]} on "
f"{obj.get_display_name(looker)}]|n"
if obj if obj
else "" else ""
) )
@ -232,7 +235,9 @@ class EvscapeRoom(EvscaperoomObject, DefaultRoom):
admin_only = "" admin_only = ""
if self.check_perm(looker, "Admin"): if self.check_perm(looker, "Admin"):
# only for admins # only for admins
objs = DefaultObject.objects.filter_family(db_location=self).exclude(id=looker.id) objs = DefaultObject.objects.filter_family(db_location=self).exclude(
id=looker.id
)
admin_only = "\n|xAdmin only: " + list_to_string( admin_only = "\n|xAdmin only: " + list_to_string(
[obj.get_display_name(looker) for obj in objs] [obj.get_display_name(looker) for obj in objs]
) )

View file

@ -58,7 +58,9 @@ class StateHandler(object):
except Exception as err: except Exception as err:
logger.log_trace() logger.log_trace()
self.room.msg_room(None, f"|rBUG: Could not load state {statename}: {err}!") self.room.msg_room(None, f"|rBUG: Could not load state {statename}: {err}!")
self.room.msg_room(None, f"|rBUG: Falling back to {self.current_state_name}") self.room.msg_room(
None, f"|rBUG: Falling back to {self.current_state_name}"
)
return return
state = mod.State(self, self.room) state = mod.State(self, self.room)
@ -202,7 +204,9 @@ class BaseState(object):
if cinematic: if cinematic:
message = msg_cinematic(message, borders=borders) message = msg_cinematic(message, borders=borders)
if target: if target:
options = target.attributes.get("options", category=self.room.tagcategory, default={}) options = target.attributes.get(
"options", category=self.room.tagcategory, default={}
)
style = options.get("things_style", 2) style = options.get("things_style", 2)
# we assume this is a char # we assume this is a char
target.msg(parse_for_things(message, things_style=style)) target.msg(parse_for_things(message, things_style=style))

View file

@ -117,7 +117,9 @@ class HelpButton(objects.EvscaperoomObject):
self.msg_char(caller, "There are no more hints to be had.") self.msg_char(caller, "There are no more hints to be had.")
else: else:
self.msg_room( self.msg_room(
caller, f"{caller.key} pushes *button and gets the " f'hint:\n "{hint.strip()}"|n' caller,
f"{caller.key} pushes *button and gets the "
f'hint:\n "{hint.strip()}"|n',
) )

View file

@ -18,7 +18,9 @@ from . import utils
class TestEvscaperoomCommands(CommandTest): class TestEvscaperoomCommands(CommandTest):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.room1 = utils.create_evscaperoom_object("evscaperoom.room.EvscapeRoom", key="Testroom") self.room1 = utils.create_evscaperoom_object(
"evscaperoom.room.EvscapeRoom", key="Testroom"
)
self.char1.location = self.room1 self.char1.location = self.room1
self.obj1.location = self.room1 self.obj1.location = self.room1
@ -151,19 +153,24 @@ class TestEvscaperoomCommands(CommandTest):
cmd.room = self.room1 cmd.room = self.room1
cmd.focus = self.obj1 cmd.focus = self.obj1
self.assertEqual( self.assertEqual(
self.char1.attributes.get("focus", category=self.room1.tagcategory), self.obj1 self.char1.attributes.get("focus", category=self.room1.tagcategory),
self.obj1,
) )
def test_focus(self): def test_focus(self):
# don't focus on a non-room object # don't focus on a non-room object
self.call(commands.CmdFocus(), "obj") self.call(commands.CmdFocus(), "obj")
self.assertEqual(self.char1.attributes.get("focus", category=self.room1.tagcategory), None) self.assertEqual(
self.char1.attributes.get("focus", category=self.room1.tagcategory), None
)
# should focus correctly # should focus correctly
myobj = utils.create_evscaperoom_object( myobj = utils.create_evscaperoom_object(
objects.EvscaperoomObject, "mytestobj", location=self.room1 objects.EvscaperoomObject, "mytestobj", location=self.room1
) )
self.call(commands.CmdFocus(), "mytestobj") self.call(commands.CmdFocus(), "mytestobj")
self.assertEqual(self.char1.attributes.get("focus", category=self.room1.tagcategory), myobj) self.assertEqual(
self.char1.attributes.get("focus", category=self.room1.tagcategory), myobj
)
def test_look(self): def test_look(self):
self.call(commands.CmdLook(), "at obj", "Obj") self.call(commands.CmdLook(), "at obj", "Obj")
@ -173,13 +180,19 @@ class TestEvscaperoomCommands(CommandTest):
def test_speech(self): def test_speech(self):
self.call(commands.CmdSpeak(), "", "What do you want to say?", cmdstring="") self.call(commands.CmdSpeak(), "", "What do you want to say?", cmdstring="")
self.call(commands.CmdSpeak(), "Hello!", "You say: Hello!", cmdstring="") self.call(commands.CmdSpeak(), "Hello!", "You say: Hello!", cmdstring="")
self.call(commands.CmdSpeak(), "", "What do you want to whisper?", cmdstring="whisper") self.call(
commands.CmdSpeak(), "", "What do you want to whisper?", cmdstring="whisper"
)
self.call(commands.CmdSpeak(), "Hi.", "You whisper: Hi.", cmdstring="whisper") self.call(commands.CmdSpeak(), "Hi.", "You whisper: Hi.", cmdstring="whisper")
self.call(commands.CmdSpeak(), "Hi.", "You whisper: Hi.", cmdstring="whisper") self.call(commands.CmdSpeak(), "Hi.", "You whisper: Hi.", cmdstring="whisper")
self.call(commands.CmdSpeak(), "HELLO!", "You shout: HELLO!", cmdstring="shout") self.call(commands.CmdSpeak(), "HELLO!", "You shout: HELLO!", cmdstring="shout")
self.call(commands.CmdSpeak(), "Hello to obj", "You say: Hello", cmdstring="say") self.call(
self.call(commands.CmdSpeak(), "Hello to obj", "You shout: Hello", cmdstring="shout") commands.CmdSpeak(), "Hello to obj", "You say: Hello", cmdstring="say"
)
self.call(
commands.CmdSpeak(), "Hello to obj", "You shout: Hello", cmdstring="shout"
)
def test_emote(self): def test_emote(self):
self.call( self.call(
@ -194,7 +207,9 @@ class TestEvscaperoomCommands(CommandTest):
class TestUtils(EvenniaTest): class TestUtils(EvenniaTest):
def test_overwrite(self): def test_overwrite(self):
room = utils.create_evscaperoom_object("evscaperoom.room.EvscapeRoom", key="Testroom") room = utils.create_evscaperoom_object(
"evscaperoom.room.EvscapeRoom", key="Testroom"
)
obj1 = utils.create_evscaperoom_object( obj1 = utils.create_evscaperoom_object(
objects.EvscaperoomObject, key="testobj", location=room objects.EvscaperoomObject, key="testobj", location=room
) )
@ -212,11 +227,15 @@ class TestUtils(EvenniaTest):
def test_parse_for_perspectives(self): def test_parse_for_perspectives(self):
second, third = utils.parse_for_perspectives("~You ~look at the nice book", "TestGuy") second, third = utils.parse_for_perspectives(
"~You ~look at the nice book", "TestGuy"
)
self.assertTrue(second, "You look at the nice book") self.assertTrue(second, "You look at the nice book")
self.assertTrue(third, "TestGuy looks at the nice book") self.assertTrue(third, "TestGuy looks at the nice book")
# irregular # irregular
second, third = utils.parse_for_perspectives("With a smile, ~you ~were gone", "TestGuy") second, third = utils.parse_for_perspectives(
"With a smile, ~you ~were gone", "TestGuy"
)
self.assertTrue(second, "With a smile, you were gone") self.assertTrue(second, "With a smile, you were gone")
self.assertTrue(third, "With a smile, TestGuy was gone") self.assertTrue(third, "With a smile, TestGuy was gone")
@ -224,8 +243,12 @@ class TestUtils(EvenniaTest):
string = "Looking at *book and *key." string = "Looking at *book and *key."
self.assertEqual(utils.parse_for_things(string, 0), "Looking at book and key.") self.assertEqual(utils.parse_for_things(string, 0), "Looking at book and key.")
self.assertEqual(utils.parse_for_things(string, 1), "Looking at |ybook|n and |ykey|n.") self.assertEqual(
self.assertEqual(utils.parse_for_things(string, 2), "Looking at |y[book]|n and |y[key]|n.") utils.parse_for_things(string, 1), "Looking at |ybook|n and |ykey|n."
)
self.assertEqual(
utils.parse_for_things(string, 2), "Looking at |y[book]|n and |y[key]|n."
)
class TestEvScapeRoom(EvenniaTest): class TestEvScapeRoom(EvenniaTest):
@ -248,10 +271,14 @@ class TestEvScapeRoom(EvenniaTest):
self.assertEqual(list(room.get_all_characters()), [self.char1]) self.assertEqual(list(room.get_all_characters()), [self.char1])
room.tag_character(self.char1, "opened_door") room.tag_character(self.char1, "opened_door")
self.assertEqual(self.char1.tags.get("opened_door", category=self.roomtag), "opened_door") self.assertEqual(
self.char1.tags.get("opened_door", category=self.roomtag), "opened_door"
)
room.tag_all_characters("tagged_all") room.tag_all_characters("tagged_all")
self.assertEqual(self.char1.tags.get("tagged_all", category=self.roomtag), "tagged_all") self.assertEqual(
self.char1.tags.get("tagged_all", category=self.roomtag), "tagged_all"
)
room.character_cleanup(self.char1) room.character_cleanup(self.char1)
self.assertEqual(self.char1.tags.get(category=self.roomtag), None) self.assertEqual(self.char1.tags.get(category=self.roomtag), None)

View file

@ -94,7 +94,9 @@ from evennia import utils
from evennia import CmdSet from evennia import CmdSet
# error return function, needed by Extended Look command # error return function, needed by Extended Look command
_AT_SEARCH_RESULT = utils.variable_from_module(*settings.SEARCH_AT_RESULT.rsplit(".", 1)) _AT_SEARCH_RESULT = utils.variable_from_module(
*settings.SEARCH_AT_RESULT.rsplit(".", 1)
)
# regexes for in-desc replacements # regexes for in-desc replacements
RE_MORNING = re.compile(r"<morning>(.*?)</morning>", re.IGNORECASE) RE_MORNING = re.compile(r"<morning>(.*?)</morning>", re.IGNORECASE)
@ -444,7 +446,12 @@ class CmdExtendedRoomDesc(default_cmds.CmdDesc):
string += " |wgeneral:|n %s" % location.db.general_desc string += " |wgeneral:|n %s" % location.db.general_desc
caller.msg(string) caller.msg(string)
return return
if self.switches and self.switches[0] in ("spring", "summer", "autumn", "winter"): if self.switches and self.switches[0] in (
"spring",
"summer",
"autumn",
"winter",
):
# a seasonal switch was given # a seasonal switch was given
if self.rhs: if self.rhs:
caller.msg("Seasonal descs only work with rooms, not objects.") caller.msg("Seasonal descs only work with rooms, not objects.")
@ -519,9 +526,13 @@ class CmdExtendedRoomDetail(default_cmds.MuxCommand):
if not self.args: if not self.args:
details = location.db.details details = location.db.details
if not details: if not details:
self.msg("|rThe room {} doesn't have any detail set.|n".format(location)) self.msg(
"|rThe room {} doesn't have any detail set.|n".format(location)
)
else: else:
details = sorted(["|y{}|n: {}".format(key, desc) for key, desc in details.items()]) details = sorted(
["|y{}|n: {}".format(key, desc) for key, desc in details.items()]
)
self.msg("Details on Room:\n" + "\n".join(details)) self.msg("Details on Room:\n" + "\n".join(details))
return return

View file

@ -278,7 +278,11 @@ def menunode_fieldfill(caller, raw_string, **kwargs):
# Display current form data # Display current form data
text = ( text = (
display_formdata( display_formdata(
formtemplate, formdata, pretext=pretext, posttext=posttext, borderstyle=borderstyle formtemplate,
formdata,
pretext=pretext,
posttext=posttext,
borderstyle=borderstyle,
), ),
formhelptext, formhelptext,
) )
@ -292,7 +296,10 @@ def menunode_fieldfill(caller, raw_string, **kwargs):
for field in formtemplate: for field in formtemplate:
if "required" in field.keys(): if "required" in field.keys():
# If field is required but current form data for field is blank # If field is required but current form data for field is blank
if field["required"] is True and formdata[field["fieldname"]] is None: if (
field["required"] is True
and formdata[field["fieldname"]] is None
):
# Add to blank and required fields # Add to blank and required fields
blank_and_required.append(field["fieldname"]) blank_and_required.append(field["fieldname"])
if len(blank_and_required) > 0: if len(blank_and_required) > 0:
@ -428,22 +435,30 @@ def menunode_fieldfill(caller, raw_string, **kwargs):
# Test for max/min # Test for max/min
if max_value is not None: if max_value is not None:
if newvalue > max_value: if newvalue > max_value:
caller.msg("Field '%s' has a maximum value of %i." % (matched_field, max_value)) caller.msg(
"Field '%s' has a maximum value of %i."
% (matched_field, max_value)
)
text = (None, formhelptext) text = (None, formhelptext)
return text, options return text, options
if min_value is not None: if min_value is not None:
if newvalue < min_value: if newvalue < min_value:
caller.msg( caller.msg(
"Field '%s' reqiures a minimum value of %i." % (matched_field, min_value) "Field '%s' reqiures a minimum value of %i."
% (matched_field, min_value)
) )
text = (None, formhelptext) text = (None, formhelptext)
return text, options return text, options
# Field type bool verification # Field type bool verification
if fieldtype == "bool": if fieldtype == "bool":
if newvalue.lower() != truestr.lower() and newvalue.lower() != falsestr.lower(): if (
newvalue.lower() != truestr.lower()
and newvalue.lower() != falsestr.lower()
):
caller.msg( caller.msg(
"Please enter '%s' or '%s' for field '%s'." % (truestr, falsestr, matched_field) "Please enter '%s' or '%s' for field '%s'."
% (truestr, falsestr, matched_field)
) )
text = (None, formhelptext) text = (None, formhelptext)
return text, options return text, options
@ -509,7 +524,9 @@ def form_template_to_dict(formtemplate):
return formdata return formdata
def display_formdata(formtemplate, formdata, pretext="", posttext="", borderstyle="cells"): def display_formdata(
formtemplate, formdata, pretext="", posttext="", borderstyle="cells"
):
""" """
Displays a form's current data as a table. Used in the form menu. Displays a form's current data as a table. Used in the form menu.
@ -660,9 +677,7 @@ class CmdTestMenu(Command):
""" """
This performs the actual command. This performs the actual command.
""" """
pretext = ( pretext = "|cSend a delayed message to another player ---------------------------------------|n"
"|cSend a delayed message to another player ---------------------------------------|n"
)
posttext = ( posttext = (
"|c--------------------------------------------------------------------------------|n|/" "|c--------------------------------------------------------------------------------|n|/"
"Syntax: type |c<field> = <new value>|n to change the values of the form. Given|/" "Syntax: type |c<field> = <new value>|n to change the values of the form. Given|/"

View file

@ -101,7 +101,12 @@ class CallbackHandler(object):
if handler: if handler:
return self.format_callback( return self.format_callback(
handler.add_callback( handler.add_callback(
self.obj, callback_name, code, author=author, valid=valid, parameters=parameters self.obj,
callback_name,
code,
author=author,
valid=valid,
parameters=parameters,
) )
) )

View file

@ -136,7 +136,9 @@ class CmdCallback(COMMAND_DEFAULT_CLASS):
self.is_validator = validator self.is_validator = validator
self.autovalid = autovalid self.autovalid = autovalid
if self.handler is None: if self.handler is None:
caller.msg("The event handler is not running, can't " "access the event system.") caller.msg(
"The event handler is not running, can't " "access the event system."
)
return return
# Before the equal sign, there is an object name or nothing # Before the equal sign, there is an object name or nothing
@ -164,7 +166,9 @@ class CmdCallback(COMMAND_DEFAULT_CLASS):
elif switch in ["tasks", "task"]: elif switch in ["tasks", "task"]:
self.list_tasks() self.list_tasks()
else: else:
caller.msg("Mutually exclusive or invalid switches were " "used, cannot proceed.") caller.msg(
"Mutually exclusive or invalid switches were " "used, cannot proceed."
)
def list_callbacks(self): def list_callbacks(self):
"""Display the list of callbacks connected to the object.""" """Display the list of callbacks connected to the object."""
@ -178,7 +182,9 @@ class CmdCallback(COMMAND_DEFAULT_CLASS):
# Check that the callback name can be found in this object # Check that the callback name can be found in this object
created = callbacks.get(callback_name) created = callbacks.get(callback_name)
if created is None: if created is None:
self.msg("No callback {} has been set on {}.".format(callback_name, obj)) self.msg(
"No callback {} has been set on {}.".format(callback_name, obj)
)
return return
if parameters: if parameters:
@ -202,11 +208,15 @@ class CmdCallback(COMMAND_DEFAULT_CLASS):
updated_by = updated_by.key if updated_by else "|gUnknown|n" updated_by = updated_by.key if updated_by else "|gUnknown|n"
created_on = callback.get("created_on") created_on = callback.get("created_on")
created_on = ( created_on = (
created_on.strftime("%Y-%m-%d %H:%M:%S") if created_on else "|gUnknown|n" created_on.strftime("%Y-%m-%d %H:%M:%S")
if created_on
else "|gUnknown|n"
) )
updated_on = callback.get("updated_on") updated_on = callback.get("updated_on")
updated_on = ( updated_on = (
updated_on.strftime("%Y-%m-%d %H:%M:%S") if updated_on else "|gUnknown|n" updated_on.strftime("%Y-%m-%d %H:%M:%S")
if updated_on
else "|gUnknown|n"
) )
msg = "Callback {} {} of {}:".format(callback_name, parameters, obj) msg = "Callback {} {} of {}:".format(callback_name, parameters, obj)
msg += "\nCreated by {} on {}.".format(author, created_on) msg += "\nCreated by {} on {}.".format(author, created_on)
@ -254,13 +264,17 @@ class CmdCallback(COMMAND_DEFAULT_CLASS):
self.msg(str(table)) self.msg(str(table))
else: else:
names = list(set(list(types.keys()) + list(callbacks.keys()))) names = list(set(list(types.keys()) + list(callbacks.keys())))
table = EvTable("Callback name", "Number", "Description", valign="t", width=78) table = EvTable(
"Callback name", "Number", "Description", valign="t", width=78
)
table.reformat_column(0, width=20) table.reformat_column(0, width=20)
table.reformat_column(1, width=10, align="r") table.reformat_column(1, width=10, align="r")
table.reformat_column(2, width=48) table.reformat_column(2, width=48)
for name in sorted(names): for name in sorted(names):
number = len(callbacks.get(name, [])) number = len(callbacks.get(name, []))
lines = sum(len(e["code"].splitlines()) for e in callbacks.get(name, [])) lines = sum(
len(e["code"].splitlines()) for e in callbacks.get(name, [])
)
no = "{} ({})".format(number, lines) no = "{} ({})".format(number, lines)
description = types.get(name, (None, "Chained event."))[1] description = types.get(name, (None, "Chained event."))[1]
description = description.strip("\n").splitlines()[0] description = description.strip("\n").splitlines()[0]
@ -321,7 +335,9 @@ class CmdCallback(COMMAND_DEFAULT_CLASS):
# Check that the callback exists # Check that the callback exists
if callback_name not in callbacks: if callback_name not in callbacks:
self.msg("The callback name {} can't be found in {}.".format(callback_name, obj)) self.msg(
"The callback name {} can't be found in {}.".format(callback_name, obj)
)
return return
# If there's only one callback, just edit it # If there's only one callback, just edit it
@ -393,7 +409,9 @@ class CmdCallback(COMMAND_DEFAULT_CLASS):
# Check that the callback exists # Check that the callback exists
if callback_name not in callbacks: if callback_name not in callbacks:
self.msg("The callback name {} can't be found in {}.".format(callback_name, obj)) self.msg(
"The callback name {} can't be found in {}.".format(callback_name, obj)
)
return return
# If there's only one callback, just delete it # If there's only one callback, just delete it
@ -432,7 +450,11 @@ class CmdCallback(COMMAND_DEFAULT_CLASS):
# Delete the callback # Delete the callback
self.handler.del_callback(obj, callback_name, number) self.handler.del_callback(obj, callback_name, number)
self.msg("The callback {}[{}] of {} was deleted.".format(callback_name, number + 1, obj)) self.msg(
"The callback {}[{}] of {} was deleted.".format(
callback_name, number + 1, obj
)
)
def accept_callback(self): def accept_callback(self):
"""Accept a callback.""" """Accept a callback."""
@ -442,7 +464,9 @@ class CmdCallback(COMMAND_DEFAULT_CLASS):
# If no object, display the list of callbacks to be checked # If no object, display the list of callbacks to be checked
if obj is None: if obj is None:
table = EvTable("ID", "Type", "Object", "Name", "Updated by", "On", width=78) table = EvTable(
"ID", "Type", "Object", "Name", "Updated by", "On", width=78
)
table.reformat_column(0, align="r") table.reformat_column(0, align="r")
now = datetime.now() now = datetime.now()
for obj, name, number in self.handler.db.to_valid: for obj, name, number in self.handler.db.to_valid:
@ -484,7 +508,9 @@ class CmdCallback(COMMAND_DEFAULT_CLASS):
# Check that the callback exists # Check that the callback exists
if callback_name not in callbacks: if callback_name not in callbacks:
self.msg("The callback name {} can't be found in {}.".format(callback_name, obj)) self.msg(
"The callback name {} can't be found in {}.".format(callback_name, obj)
)
return return
if not parameters: if not parameters:
@ -499,7 +525,9 @@ class CmdCallback(COMMAND_DEFAULT_CLASS):
callback = callbacks[callback_name][number] callback = callbacks[callback_name][number]
except (ValueError, AssertionError, IndexError): except (ValueError, AssertionError, IndexError):
self.msg( self.msg(
"The callback {} {} cannot be found in {}.".format(callback_name, parameters, obj) "The callback {} {} cannot be found in {}.".format(
callback_name, parameters, obj
)
) )
return return
@ -509,7 +537,9 @@ class CmdCallback(COMMAND_DEFAULT_CLASS):
else: else:
self.handler.accept_callback(obj, callback_name, number) self.handler.accept_callback(obj, callback_name, number)
self.msg( self.msg(
"The callback {} {} of {} has been accepted.".format(callback_name, parameters, obj) "The callback {} {} of {} has been accepted.".format(
callback_name, parameters, obj
)
) )
def list_tasks(self): def list_tasks(self):
@ -557,10 +587,17 @@ def _ev_save(caller, buf):
return False return False
if (callback["obj"], callback["name"], callback["number"]) in handler.db.locked: if (callback["obj"], callback["name"], callback["number"]) in handler.db.locked:
handler.db.locked.remove((callback["obj"], callback["name"], callback["number"])) handler.db.locked.remove(
(callback["obj"], callback["name"], callback["number"])
)
handler.edit_callback( handler.edit_callback(
callback["obj"], callback["name"], callback["number"], buf, caller, valid=autovalid callback["obj"],
callback["name"],
callback["number"],
buf,
caller,
valid=autovalid,
) )
return True return True
@ -577,7 +614,9 @@ def _ev_quit(caller):
return False return False
if (callback["obj"], callback["name"], callback["number"]) in handler.db.locked: if (callback["obj"], callback["name"], callback["number"]) in handler.db.locked:
handler.db.locked.remove((callback["obj"], callback["name"], callback["number"])) handler.db.locked.remove(
(callback["obj"], callback["name"], callback["number"])
)
del caller.db._callback del caller.db._callback
caller.msg("Exited the code editor.") caller.msg("Exited the code editor.")

View file

@ -64,13 +64,17 @@ class EventHandler(DefaultScript):
""" """
self.ndb.events = {} self.ndb.events = {}
for typeclass, name, variables, help_text, custom_call, custom_add in EVENTS: for typeclass, name, variables, help_text, custom_call, custom_add in EVENTS:
self.add_event(typeclass, name, variables, help_text, custom_call, custom_add) self.add_event(
typeclass, name, variables, help_text, custom_call, custom_add
)
# Generate locals # Generate locals
self.ndb.current_locals = {} self.ndb.current_locals = {}
self.ndb.fresh_locals = {} self.ndb.fresh_locals = {}
addresses = ["evennia.contrib.ingame_python.eventfuncs"] addresses = ["evennia.contrib.ingame_python.eventfuncs"]
addresses.extend(getattr(settings, "EVENTFUNCS_LOCATIONS", ["world.eventfuncs"])) addresses.extend(
getattr(settings, "EVENTFUNCS_LOCATIONS", ["world.eventfuncs"])
)
for address in addresses: for address in addresses:
if pypath_to_realpath(address): if pypath_to_realpath(address):
self.ndb.fresh_locals.update(all_from_module(address)) self.ndb.fresh_locals.update(all_from_module(address))
@ -204,7 +208,9 @@ class EventHandler(DefaultScript):
return callbacks return callbacks
def add_callback(self, obj, callback_name, code, author=None, valid=False, parameters=""): def add_callback(
self, obj, callback_name, code, author=None, valid=False, parameters=""
):
""" """
Add the specified callback. Add the specified callback.
@ -246,7 +252,9 @@ class EventHandler(DefaultScript):
self.db.to_valid.append((obj, callback_name, len(callbacks) - 1)) self.db.to_valid.append((obj, callback_name, len(callbacks) - 1))
# Call the custom_add if needed # Call the custom_add if needed
custom_add = self.get_events(obj).get(callback_name, [None, None, None, None])[3] custom_add = self.get_events(obj).get(callback_name, [None, None, None, None])[
3
]
if custom_add: if custom_add:
custom_add(obj, callback_name, len(callbacks) - 1, parameters) custom_add(obj, callback_name, len(callbacks) - 1, parameters)
@ -292,7 +300,12 @@ class EventHandler(DefaultScript):
# Edit the callback # Edit the callback
callbacks[number].update( callbacks[number].update(
{"updated_on": datetime.now(), "updated_by": author, "valid": valid, "code": code} {
"updated_on": datetime.now(),
"updated_by": author,
"valid": valid,
"code": code,
}
) )
# If not valid, set it in 'to_valid' # If not valid, set it in 'to_valid'
@ -335,7 +348,9 @@ class EventHandler(DefaultScript):
return return
else: else:
logger.log_info( logger.log_info(
"Deleting callback {} {} of {}:\n{}".format(callback_name, number, obj, code) "Deleting callback {} {} of {}:\n{}".format(
callback_name, number, obj, code
)
) )
del callbacks[number] del callbacks[number]
@ -416,7 +431,8 @@ class EventHandler(DefaultScript):
allowed = ("number", "parameters", "locals") allowed = ("number", "parameters", "locals")
if any(k for k in kwargs if k not in allowed): if any(k for k in kwargs if k not in allowed):
raise TypeError( raise TypeError(
"Unknown keyword arguments were specified " "to call callbacks: {}".format(kwargs) "Unknown keyword arguments were specified "
"to call callbacks: {}".format(kwargs)
) )
event = self.get_events(obj).get(callback_name) event = self.get_events(obj).get(callback_name)
@ -436,7 +452,9 @@ class EventHandler(DefaultScript):
except IndexError: except IndexError:
logger.log_trace( logger.log_trace(
"callback {} of {} ({}): need variable " "callback {} of {} ({}): need variable "
"{} in position {}".format(callback_name, obj, type(obj), variable, i) "{} in position {}".format(
callback_name, obj, type(obj), variable, i
)
) )
return False return False
else: else:
@ -489,7 +507,9 @@ class EventHandler(DefaultScript):
oid = obj.id oid = obj.id
logger.log_err( logger.log_err(
"An error occurred during the callback {} of " "An error occurred during the callback {} of "
"{} (#{}), number {}\n{}".format(callback_name, obj, oid, number + 1, "\n".join(trace)) "{} (#{}), number {}\n{}".format(
callback_name, obj, oid, number + 1, "\n".join(trace)
)
) )
# Create the error message # Create the error message
@ -522,9 +542,12 @@ class EventHandler(DefaultScript):
if updater and updater.sessions.all(): if updater and updater.sessions.all():
updater.msg(err_msg) updater.msg(err_msg)
else: else:
err_msg = "Error in {} of {} (#{})[{}], line {}:" " {}\n {}".format( err_msg = (
"Error in {} of {} (#{})[{}], line {}:"
" {}\n {}".format(
callback_name, obj, oid, number + 1, lineno, line, exc callback_name, obj, oid, number + 1, lineno, line, exc
) )
)
self.ndb.channel.msg(err_msg) self.ndb.channel.msg(err_msg)
def add_event(self, typeclass, name, variables, help_text, custom_call, custom_add): def add_event(self, typeclass, name, variables, help_text, custom_call, custom_add):
@ -661,7 +684,9 @@ def complete_task(task_id):
return return
if task_id not in script.db.tasks: if task_id not in script.db.tasks:
logger.log_err("The task #{} was scheduled, but it cannot be " "found".format(task_id)) logger.log_err(
"The task #{} was scheduled, but it cannot be " "found".format(task_id)
)
return return
delta, obj, callback_name, locals = script.db.tasks.pop(task_id) delta, obj, callback_name, locals = script.db.tasks.pop(task_id)

View file

@ -31,15 +31,21 @@ class TestEventHandler(EvenniaTest):
def setUp(self): def setUp(self):
"""Create the event handler.""" """Create the event handler."""
super().setUp() super().setUp()
self.handler = create_script("evennia.contrib.ingame_python.scripts.EventHandler") self.handler = create_script(
"evennia.contrib.ingame_python.scripts.EventHandler"
)
# Copy old events if necessary # Copy old events if necessary
if OLD_EVENTS: if OLD_EVENTS:
self.handler.ndb.events = dict(OLD_EVENTS) self.handler.ndb.events = dict(OLD_EVENTS)
# Alter typeclasses # Alter typeclasses
self.char1.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventCharacter") self.char1.swap_typeclass(
self.char2.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventCharacter") "evennia.contrib.ingame_python.typeclasses.EventCharacter"
)
self.char2.swap_typeclass(
"evennia.contrib.ingame_python.typeclasses.EventCharacter"
)
self.room1.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventRoom") self.room1.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventRoom")
self.room2.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventRoom") self.room2.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventRoom")
self.exit.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventExit") self.exit.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventExit")
@ -64,7 +70,11 @@ class TestEventHandler(EvenniaTest):
"""Add a callback while needing validation.""" """Add a callback while needing validation."""
author = self.char1 author = self.char1
self.handler.add_callback( self.handler.add_callback(
self.room1, "dummy", "character.db.strength = 40", author=author, valid=False self.room1,
"dummy",
"character.db.strength = 40",
author=author,
valid=False,
) )
callback = self.handler.get_callbacks(self.room1).get("dummy") callback = self.handler.get_callbacks(self.room1).get("dummy")
callback = callback[0] callback = callback[0]
@ -90,7 +100,12 @@ class TestEventHandler(EvenniaTest):
# Edit it right away # Edit it right away
self.handler.edit_callback( self.handler.edit_callback(
self.room1, "dummy", 0, "character.db.strength = 65", author=self.char2, valid=True self.room1,
"dummy",
0,
"character.db.strength = 65",
author=self.char2,
valid=True,
) )
# Check that the callback was written # Check that the callback was written
@ -116,7 +131,12 @@ class TestEventHandler(EvenniaTest):
# Edit it right away # Edit it right away
self.handler.edit_callback( self.handler.edit_callback(
self.room1, "dummy", 0, "character.db.strength = 80", author=self.char2, valid=False self.room1,
"dummy",
0,
"character.db.strength = 80",
author=self.char2,
valid=False,
) )
# Run this dummy callback (shouldn't do anything) # Run this dummy callback (shouldn't do anything)
@ -129,13 +149,25 @@ class TestEventHandler(EvenniaTest):
"""Try to delete a callback.""" """Try to delete a callback."""
# Add 3 callbacks # Add 3 callbacks
self.handler.add_callback( self.handler.add_callback(
self.room1, "dummy", "character.db.strength = 5", author=self.char1, valid=True self.room1,
"dummy",
"character.db.strength = 5",
author=self.char1,
valid=True,
) )
self.handler.add_callback( self.handler.add_callback(
self.room1, "dummy", "character.db.strength = 8", author=self.char2, valid=False self.room1,
"dummy",
"character.db.strength = 8",
author=self.char2,
valid=False,
) )
self.handler.add_callback( self.handler.add_callback(
self.room1, "dummy", "character.db.strength = 9", author=self.char1, valid=True self.room1,
"dummy",
"character.db.strength = 9",
author=self.char1,
valid=True,
) )
# Note that the second callback isn't valid # Note that the second callback isn't valid
@ -171,10 +203,18 @@ class TestEventHandler(EvenniaTest):
"""Accept an callback.""" """Accept an callback."""
# Add 2 callbacks # Add 2 callbacks
self.handler.add_callback( self.handler.add_callback(
self.room1, "dummy", "character.db.strength = 5", author=self.char1, valid=True self.room1,
"dummy",
"character.db.strength = 5",
author=self.char1,
valid=True,
) )
self.handler.add_callback( self.handler.add_callback(
self.room1, "dummy", "character.db.strength = 8", author=self.char2, valid=False self.room1,
"dummy",
"character.db.strength = 8",
author=self.char2,
valid=False,
) )
# Note that the second callback isn't valid # Note that the second callback isn't valid
@ -209,12 +249,18 @@ class TestEventHandler(EvenniaTest):
"\n" "\n"
) )
) )
self.handler.add_callback(self.room1, "dummy", code, author=self.char1, valid=True) self.handler.add_callback(
self.room1, "dummy", code, author=self.char1, valid=True
)
# Call the dummy callback # Call the dummy callback
self.assertTrue(self.handler.call(self.room1, "dummy", locals={"character": self.char1})) self.assertTrue(
self.handler.call(self.room1, "dummy", locals={"character": self.char1})
)
self.assertEqual(self.char1.db.health, 50) self.assertEqual(self.char1.db.health, 50)
self.assertTrue(self.handler.call(self.room1, "dummy", locals={"character": self.char2})) self.assertTrue(
self.handler.call(self.room1, "dummy", locals={"character": self.char2})
)
self.assertEqual(self.char2.db.health, 0) self.assertEqual(self.char2.db.health, 0)
def test_handler(self): def test_handler(self):
@ -222,7 +268,9 @@ class TestEventHandler(EvenniaTest):
self.assertIsNotNone(self.char1.callbacks) self.assertIsNotNone(self.char1.callbacks)
# Add an callback # Add an callback
callback = self.room1.callbacks.add("dummy", "pass", author=self.char1, valid=True) callback = self.room1.callbacks.add(
"dummy", "pass", author=self.char1, valid=True
)
self.assertEqual(callback.obj, self.room1) self.assertEqual(callback.obj, self.room1)
self.assertEqual(callback.name, "dummy") self.assertEqual(callback.name, "dummy")
self.assertEqual(callback.code, "pass") self.assertEqual(callback.code, "pass")
@ -238,7 +286,9 @@ class TestEventHandler(EvenniaTest):
self.assertNotIn([callback], list(self.room1.callbacks.all().values())) self.assertNotIn([callback], list(self.room1.callbacks.all().values()))
# Try to call this callback # Try to call this callback
self.assertTrue(self.room1.callbacks.call("dummy", locals={"character": self.char2})) self.assertTrue(
self.room1.callbacks.call("dummy", locals={"character": self.char2})
)
self.assertTrue(self.char2.db.say) self.assertTrue(self.char2.db.say)
# Delete the callback # Delete the callback
@ -253,15 +303,21 @@ class TestCmdCallback(CommandTest):
def setUp(self): def setUp(self):
"""Create the callback handler.""" """Create the callback handler."""
super().setUp() super().setUp()
self.handler = create_script("evennia.contrib.ingame_python.scripts.EventHandler") self.handler = create_script(
"evennia.contrib.ingame_python.scripts.EventHandler"
)
# Copy old events if necessary # Copy old events if necessary
if OLD_EVENTS: if OLD_EVENTS:
self.handler.ndb.events = dict(OLD_EVENTS) self.handler.ndb.events = dict(OLD_EVENTS)
# Alter typeclasses # Alter typeclasses
self.char1.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventCharacter") self.char1.swap_typeclass(
self.char2.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventCharacter") "evennia.contrib.ingame_python.typeclasses.EventCharacter"
)
self.char2.swap_typeclass(
"evennia.contrib.ingame_python.typeclasses.EventCharacter"
)
self.room1.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventRoom") self.room1.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventRoom")
self.room2.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventRoom") self.room2.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventRoom")
self.exit.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventExit") self.exit.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventExit")
@ -291,7 +347,9 @@ class TestCmdCallback(CommandTest):
self.assertIn(cols[2].strip(), ("0 (0)", "")) self.assertIn(cols[2].strip(), ("0 (0)", ""))
# Add some callback # Add some callback
self.handler.add_callback(self.exit, "traverse", "pass", author=self.char1, valid=True) self.handler.add_callback(
self.exit, "traverse", "pass", author=self.char1, valid=True
)
# Try to obtain more details on a specific callback on exit # Try to obtain more details on a specific callback on exit
table = self.call(CmdCallback(), "out = traverse") table = self.call(CmdCallback(), "out = traverse")
@ -370,16 +428,22 @@ class TestCmdCallback(CommandTest):
def test_del(self): def test_del(self):
"""Add and remove an callback.""" """Add and remove an callback."""
self.handler.add_callback(self.exit, "traverse", "pass", author=self.char1, valid=True) self.handler.add_callback(
self.exit, "traverse", "pass", author=self.char1, valid=True
)
# Try to delete the callback # Try to delete the callback
# char2 shouldn't be allowed to do so (that's not HIS callback) # char2 shouldn't be allowed to do so (that's not HIS callback)
self.call(CmdCallback(), "/del out = traverse 1", caller=self.char2) self.call(CmdCallback(), "/del out = traverse 1", caller=self.char2)
self.assertTrue(len(self.handler.get_callbacks(self.exit).get("traverse", [])) == 1) self.assertTrue(
len(self.handler.get_callbacks(self.exit).get("traverse", [])) == 1
)
# Now, char1 should be allowed to delete it # Now, char1 should be allowed to delete it
self.call(CmdCallback(), "/del out = traverse 1") self.call(CmdCallback(), "/del out = traverse 1")
self.assertTrue(len(self.handler.get_callbacks(self.exit).get("traverse", [])) == 0) self.assertTrue(
len(self.handler.get_callbacks(self.exit).get("traverse", [])) == 0
)
def test_lock(self): def test_lock(self):
"""Test the lock of multiple editing.""" """Test the lock of multiple editing."""
@ -432,15 +496,21 @@ class TestDefaultCallbacks(CommandTest):
def setUp(self): def setUp(self):
"""Create the callback handler.""" """Create the callback handler."""
super().setUp() super().setUp()
self.handler = create_script("evennia.contrib.ingame_python.scripts.EventHandler") self.handler = create_script(
"evennia.contrib.ingame_python.scripts.EventHandler"
)
# Copy old events if necessary # Copy old events if necessary
if OLD_EVENTS: if OLD_EVENTS:
self.handler.ndb.events = dict(OLD_EVENTS) self.handler.ndb.events = dict(OLD_EVENTS)
# Alter typeclasses # Alter typeclasses
self.char1.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventCharacter") self.char1.swap_typeclass(
self.char2.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventCharacter") "evennia.contrib.ingame_python.typeclasses.EventCharacter"
)
self.char2.swap_typeclass(
"evennia.contrib.ingame_python.typeclasses.EventCharacter"
)
self.room1.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventRoom") self.room1.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventRoom")
self.room2.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventRoom") self.room2.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventRoom")
self.exit.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventExit") self.exit.swap_typeclass("evennia.contrib.ingame_python.typeclasses.EventExit")
@ -471,20 +541,28 @@ class TestDefaultCallbacks(CommandTest):
self.exit.destination = self.room2 self.exit.destination = self.room2
# Try the can_traverse callback # Try the can_traverse callback
self.handler.add_callback(self.exit, "can_traverse", code, author=self.char1, valid=True) self.handler.add_callback(
self.exit, "can_traverse", code, author=self.char1, valid=True
)
# Have char1 move through the exit # Have char1 move through the exit
self.call(ExitCommand(), "", "You can leave.", obj=self.exit) self.call(ExitCommand(), "", "You can leave.", obj=self.exit)
self.assertIs(self.char1.location, self.room2) self.assertIs(self.char1.location, self.room2)
# Have char2 move through this exit # Have char2 move through this exit
self.call(ExitCommand(), "", "You cannot leave.", obj=self.exit, caller=self.char2) self.call(
ExitCommand(), "", "You cannot leave.", obj=self.exit, caller=self.char2
)
self.assertIs(self.char2.location, self.room1) self.assertIs(self.char2.location, self.room1)
# Try the traverse callback # Try the traverse callback
self.handler.del_callback(self.exit, "can_traverse", 0) self.handler.del_callback(self.exit, "can_traverse", 0)
self.handler.add_callback( self.handler.add_callback(
self.exit, "traverse", "character.msg('Fine!')", author=self.char1, valid=True self.exit,
"traverse",
"character.msg('Fine!')",
author=self.char1,
valid=True,
) )
# Have char2 move through the exit # Have char2 move through the exit
@ -498,7 +576,9 @@ class TestDefaultCallbacks(CommandTest):
# Test msg_arrive and msg_leave # Test msg_arrive and msg_leave
code = 'message = "{character} goes out."' code = 'message = "{character} goes out."'
self.handler.add_callback(self.exit, "msg_leave", code, author=self.char1, valid=True) self.handler.add_callback(
self.exit, "msg_leave", code, author=self.char1, valid=True
)
# Have char1 move through the exit # Have char1 move through the exit
old_msg = self.char2.msg old_msg = self.char2.msg
@ -506,11 +586,15 @@ class TestDefaultCallbacks(CommandTest):
self.char2.msg = Mock() self.char2.msg = Mock()
self.call(ExitCommand(), "", obj=self.exit) self.call(ExitCommand(), "", obj=self.exit)
stored_msg = [ stored_msg = [
args[0] if args and args[0] else kwargs.get("text", utils.to_str(kwargs)) args[0]
if args and args[0]
else kwargs.get("text", utils.to_str(kwargs))
for name, args, kwargs in self.char2.msg.mock_calls for name, args, kwargs in self.char2.msg.mock_calls
] ]
# Get the first element of a tuple if msg received a tuple instead of a string # Get the first element of a tuple if msg received a tuple instead of a string
stored_msg = [smsg[0] if isinstance(smsg, tuple) else smsg for smsg in stored_msg] stored_msg = [
smsg[0] if isinstance(smsg, tuple) else smsg for smsg in stored_msg
]
returned_msg = ansi.parse_ansi("\n".join(stored_msg), strip_ansi=True) returned_msg = ansi.parse_ansi("\n".join(stored_msg), strip_ansi=True)
self.assertEqual(returned_msg, "char1 goes out.") self.assertEqual(returned_msg, "char1 goes out.")
finally: finally:
@ -524,7 +608,9 @@ class TestDefaultCallbacks(CommandTest):
destination=self.room1, destination=self.room1,
) )
code = 'message = "{character} goes in."' code = 'message = "{character} goes in."'
self.handler.add_callback(self.exit, "msg_arrive", code, author=self.char1, valid=True) self.handler.add_callback(
self.exit, "msg_arrive", code, author=self.char1, valid=True
)
# Have char1 move through the exit # Have char1 move through the exit
old_msg = self.char2.msg old_msg = self.char2.msg
@ -532,11 +618,15 @@ class TestDefaultCallbacks(CommandTest):
self.char2.msg = Mock() self.char2.msg = Mock()
self.call(ExitCommand(), "", obj=back) self.call(ExitCommand(), "", obj=back)
stored_msg = [ stored_msg = [
args[0] if args and args[0] else kwargs.get("text", utils.to_str(kwargs)) args[0]
if args and args[0]
else kwargs.get("text", utils.to_str(kwargs))
for name, args, kwargs in self.char2.msg.mock_calls for name, args, kwargs in self.char2.msg.mock_calls
] ]
# Get the first element of a tuple if msg received a tuple instead of a string # Get the first element of a tuple if msg received a tuple instead of a string
stored_msg = [smsg[0] if isinstance(smsg, tuple) else smsg for smsg in stored_msg] stored_msg = [
smsg[0] if isinstance(smsg, tuple) else smsg for smsg in stored_msg
]
returned_msg = ansi.parse_ansi("\n".join(stored_msg), strip_ansi=True) returned_msg = ansi.parse_ansi("\n".join(stored_msg), strip_ansi=True)
self.assertEqual(returned_msg, "char1 goes in.") self.assertEqual(returned_msg, "char1 goes in.")
finally: finally:

View file

@ -11,7 +11,11 @@ from evennia import DefaultCharacter, DefaultExit, DefaultObject, DefaultRoom
from evennia import ScriptDB from evennia import ScriptDB
from evennia.utils.utils import delay, inherits_from, lazy_property from evennia.utils.utils import delay, inherits_from, lazy_property
from evennia.contrib.ingame_python.callbackhandler import CallbackHandler from evennia.contrib.ingame_python.callbackhandler import CallbackHandler
from evennia.contrib.ingame_python.utils import register_events, time_event, phrase_event from evennia.contrib.ingame_python.utils import (
register_events,
time_event,
phrase_event,
)
# Character help # Character help
CHARACTER_CAN_DELETE = """ CHARACTER_CAN_DELETE = """
@ -170,7 +174,11 @@ class EventCharacter(DefaultCharacter):
"can_delete": (["character"], CHARACTER_CAN_DELETE), "can_delete": (["character"], CHARACTER_CAN_DELETE),
"can_move": (["character", "origin", "destination"], CHARACTER_CAN_MOVE), "can_move": (["character", "origin", "destination"], CHARACTER_CAN_MOVE),
"can_part": (["character", "departing"], CHARACTER_CAN_PART), "can_part": (["character", "departing"], CHARACTER_CAN_PART),
"can_say": (["speaker", "character", "message"], CHARACTER_CAN_SAY, phrase_event), "can_say": (
["speaker", "character", "message"],
CHARACTER_CAN_SAY,
phrase_event,
),
"delete": (["character"], CHARACTER_DELETE), "delete": (["character"], CHARACTER_DELETE),
"greet": (["character", "newcomer"], CHARACTER_GREET), "greet": (["character", "newcomer"], CHARACTER_GREET),
"move": (["character", "origin", "destination"], CHARACTER_MOVE), "move": (["character", "origin", "destination"], CHARACTER_MOVE),
@ -213,7 +221,9 @@ class EventCharacter(DefaultCharacter):
# Get the exit from location to destination # Get the exit from location to destination
location = self.location location = self.location
exits = [ exits = [
o for o in location.contents if o.location is location and o.destination is destination o
for o in location.contents
if o.location is location and o.destination is destination
] ]
mapping = mapping or {} mapping = mapping or {}
mapping.update({"character": self}) mapping.update({"character": self})
@ -255,7 +265,9 @@ class EventCharacter(DefaultCharacter):
if not source_location and self.location.has_account: if not source_location and self.location.has_account:
# This was created from nowhere and added to an account's # This was created from nowhere and added to an account's
# inventory; it's probably the result of a create command. # inventory; it's probably the result of a create command.
string = "You now have %s in your possession." % self.get_display_name(self.location) string = "You now have %s in your possession." % self.get_display_name(
self.location
)
self.location.msg(string) self.location.msg(string)
return return
@ -351,7 +363,9 @@ class EventCharacter(DefaultCharacter):
# Call the 'greet' event of characters in the location # Call the 'greet' event of characters in the location
for present in [ for present in [
o for o in destination.contents if isinstance(o, DefaultCharacter) and o is not self o
for o in destination.contents
if isinstance(o, DefaultCharacter) and o is not self
]: ]:
present.callbacks.call("greet", present, self) present.callbacks.call("greet", present, self)
@ -436,11 +450,14 @@ class EventCharacter(DefaultCharacter):
location = getattr(self, "location", None) location = getattr(self, "location", None)
location = ( location = (
location location
if location and inherits_from(location, "evennia.objects.objects.DefaultRoom") if location
and inherits_from(location, "evennia.objects.objects.DefaultRoom")
else None else None
) )
if location and not kwargs.get("whisper", False): if location and not kwargs.get("whisper", False):
allow = location.callbacks.call("can_say", self, location, message, parameters=message) allow = location.callbacks.call(
"can_say", self, location, message, parameters=message
)
message = location.callbacks.get_variable("message") message = location.callbacks.get_variable("message")
if not allow or not message: if not allow or not message:
return return
@ -452,7 +469,9 @@ class EventCharacter(DefaultCharacter):
): ):
continue continue
allow = obj.callbacks.call("can_say", self, obj, message, parameters=message) allow = obj.callbacks.call(
"can_say", self, obj, message, parameters=message
)
message = obj.callbacks.get_variable("message") message = obj.callbacks.get_variable("message")
if not allow or not message: if not allow or not message:
return return
@ -505,7 +524,8 @@ class EventCharacter(DefaultCharacter):
location = getattr(self, "location", None) location = getattr(self, "location", None)
location = ( location = (
location location
if location and inherits_from(location, "evennia.objects.objects.DefaultRoom") if location
and inherits_from(location, "evennia.objects.objects.DefaultRoom")
else None else None
) )
@ -520,7 +540,9 @@ class EventCharacter(DefaultCharacter):
and inherits_from(obj, "evennia.objects.objects.DefaultCharacter") and inherits_from(obj, "evennia.objects.objects.DefaultCharacter")
] ]
for present in presents: for present in presents:
present.callbacks.call("say", self, present, message, parameters=message) present.callbacks.call(
"say", self, present, message, parameters=message
)
# Exit help # Exit help
@ -657,7 +679,9 @@ class EventExit(DefaultExit):
""" """
is_character = inherits_from(traversing_object, DefaultCharacter) is_character = inherits_from(traversing_object, DefaultCharacter)
if is_character: if is_character:
allow = self.callbacks.call("can_traverse", traversing_object, self, self.location) allow = self.callbacks.call(
"can_traverse", traversing_object, self, self.location
)
if not allow: if not allow:
return return

View file

@ -79,9 +79,13 @@ def register_events(path_or_typeclass):
variables = help_text = custom_call = custom_add = None variables = help_text = custom_call = custom_add = None
if isinstance(storage, list): if isinstance(storage, list):
storage.append((typeclass_name, name, variables, help_text, custom_call, custom_add)) storage.append(
(typeclass_name, name, variables, help_text, custom_call, custom_add)
)
else: else:
storage.add_event(typeclass_name, name, variables, help_text, custom_call, custom_add) storage.add_event(
typeclass_name, name, variables, help_text, custom_call, custom_add
)
return typeclass return typeclass
@ -139,7 +143,8 @@ def get_next_wait(format):
if not piece.isdigit(): if not piece.isdigit():
logger.log_trace( logger.log_trace(
"The time specified '{}' in {} isn't " "a valid number".format(piece, format) "The time specified '{}' in {} isn't "
"a valid number".format(piece, format)
) )
return return
@ -176,7 +181,9 @@ def time_event(obj, event_name, number, parameters):
""" """
seconds, usual, key = get_next_wait(parameters) seconds, usual, key = get_next_wait(parameters)
script = create_script( script = create_script(
"evennia.contrib.ingame_python.scripts.TimeEventScript", interval=seconds, obj=obj "evennia.contrib.ingame_python.scripts.TimeEventScript",
interval=seconds,
obj=obj,
) )
script.key = key script.key = key
script.desc = "event on {}".format(key) script.desc = "event on {}".format(key)

View file

@ -126,9 +126,13 @@ class CmdMail(default_cmds.MuxAccountCommand):
""" """
if self.caller_is_account: if self.caller_is_account:
return Msg.objects.get_by_tag(category="mail").filter(db_receivers_accounts=self.caller) return Msg.objects.get_by_tag(category="mail").filter(
db_receivers_accounts=self.caller
)
else: else:
return Msg.objects.get_by_tag(category="mail").filter(db_receivers_objects=self.caller) return Msg.objects.get_by_tag(category="mail").filter(
db_receivers_objects=self.caller
)
def send_mail(self, recipients, subject, message, caller): def send_mail(self, recipients, subject, message, caller):
""" """
@ -177,7 +181,9 @@ class CmdMail(default_cmds.MuxAccountCommand):
mind = max(0, min(mind_max, int(self.lhs) - 1)) mind = max(0, min(mind_max, int(self.lhs) - 1))
if all_mail[mind]: if all_mail[mind]:
mail = all_mail[mind] mail = all_mail[mind]
question = "Delete message {} ({}) [Y]/N?".format(mind + 1, mail.header) question = "Delete message {} ({}) [Y]/N?".format(
mind + 1, mail.header
)
ret = yield (question) ret = yield (question)
# handle not ret, it will be None during unit testing # handle not ret, it will be None during unit testing
if not ret or ret.strip().upper() not in ("N", "No"): if not ret or ret.strip().upper() not in ("N", "No"):
@ -195,7 +201,8 @@ class CmdMail(default_cmds.MuxAccountCommand):
try: try:
if not self.rhs: if not self.rhs:
self.caller.msg( self.caller.msg(
"Cannot forward a message without a target list. " "Please try again." "Cannot forward a message without a target list. "
"Please try again."
) )
return return
elif not self.lhs: elif not self.lhs:
@ -229,7 +236,8 @@ class CmdMail(default_cmds.MuxAccountCommand):
self.send_mail( self.send_mail(
self.search_targets(self.lhslist), self.search_targets(self.lhslist),
"FWD: " + old_message.header, "FWD: " + old_message.header,
"\n---- Original Message ----\n" + old_message.message, "\n---- Original Message ----\n"
+ old_message.message,
self.caller, self.caller,
) )
self.caller.msg("Message forwarded.") self.caller.msg("Message forwarded.")
@ -240,7 +248,9 @@ class CmdMail(default_cmds.MuxAccountCommand):
except IndexError: except IndexError:
self.caller.msg("Message does not exixt.") self.caller.msg("Message does not exixt.")
except ValueError: except ValueError:
self.caller.msg("Usage: @mail/forward <account list>=<#>[/<Message>]") self.caller.msg(
"Usage: @mail/forward <account list>=<#>[/<Message>]"
)
elif "reply" in self.switches or "rep" in self.switches: elif "reply" in self.switches or "rep" in self.switches:
try: try:
if not self.rhs: if not self.rhs:
@ -258,7 +268,9 @@ class CmdMail(default_cmds.MuxAccountCommand):
self.send_mail( self.send_mail(
old_message.senders, old_message.senders,
"RE: " + old_message.header, "RE: " + old_message.header,
self.rhs + "\n---- Original Message ----\n" + old_message.message, self.rhs
+ "\n---- Original Message ----\n"
+ old_message.message,
self.caller, self.caller,
) )
old_message.tags.remove("new", category="mail") old_message.tags.remove("new", category="mail")
@ -277,7 +289,9 @@ class CmdMail(default_cmds.MuxAccountCommand):
subject, body = self.rhs.split("/", 1) subject, body = self.rhs.split("/", 1)
else: else:
body = self.rhs body = self.rhs
self.send_mail(self.search_targets(self.lhslist), subject, body, self.caller) self.send_mail(
self.search_targets(self.lhslist), subject, body, self.caller
)
else: else:
all_mail = self.get_all_mail() all_mail = self.get_all_mail()
mind_max = max(0, all_mail.count() - 1) mind_max = max(0, all_mail.count() - 1)
@ -292,13 +306,16 @@ class CmdMail(default_cmds.MuxAccountCommand):
if message: if message:
messageForm.append(_HEAD_CHAR * _WIDTH) messageForm.append(_HEAD_CHAR * _WIDTH)
messageForm.append( messageForm.append(
"|wFrom:|n %s" % (message.senders[0].get_display_name(self.caller)) "|wFrom:|n %s"
% (message.senders[0].get_display_name(self.caller))
) )
# note that we cannot use %-d format here since Windows does not support it # note that we cannot use %-d format here since Windows does not support it
day = message.db_date_created.day day = message.db_date_created.day
messageForm.append( messageForm.append(
"|wSent:|n %s" "|wSent:|n %s"
% message.db_date_created.strftime(f"%b {day}, %Y - %H:%M:%S") % message.db_date_created.strftime(
f"%b {day}, %Y - %H:%M:%S"
)
) )
messageForm.append("|wSubject:|n %s" % message.header) messageForm.append("|wSubject:|n %s" % message.header)
messageForm.append(_SUB_HEAD_CHAR * _WIDTH) messageForm.append(_SUB_HEAD_CHAR * _WIDTH)

View file

@ -237,11 +237,19 @@ def example2_build_verticle_exit(x, y, **kwargs):
# create exits in the rooms # create exits in the rooms
create_object( create_object(
exits.Exit, key="south", aliases=["s"], location=north_room, destination=south_room exits.Exit,
key="south",
aliases=["s"],
location=north_room,
destination=south_room,
) )
create_object( create_object(
exits.Exit, key="north", aliases=["n"], location=south_room, destination=north_room exits.Exit,
key="north",
aliases=["n"],
location=south_room,
destination=north_room,
) )
kwargs["caller"].msg("Connected: " + north_room.key + " & " + south_room.key) kwargs["caller"].msg("Connected: " + north_room.key + " & " + south_room.key)
@ -256,9 +264,13 @@ def example2_build_horizontal_exit(x, y, **kwargs):
west_room = kwargs["room_dict"][(x - 1, y)] west_room = kwargs["room_dict"][(x - 1, y)]
east_room = kwargs["room_dict"][(x + 1, y)] east_room = kwargs["room_dict"][(x + 1, y)]
create_object(exits.Exit, key="east", aliases=["e"], location=west_room, destination=east_room) create_object(
exits.Exit, key="east", aliases=["e"], location=west_room, destination=east_room
)
create_object(exits.Exit, key="west", aliases=["w"], location=east_room, destination=west_room) create_object(
exits.Exit, key="west", aliases=["w"], location=east_room, destination=west_room
)
kwargs["caller"].msg("Connected: " + west_room.key + " & " + east_room.key) kwargs["caller"].msg("Connected: " + west_room.key + " & " + east_room.key)
@ -328,7 +340,11 @@ def build_map(caller, game_map, legend, iterations=1, build_exits=True):
# obs - we must use == for strings # obs - we must use == for strings
if game_map[y][x] == key: if game_map[y][x] == key:
room = legend[key]( room = legend[key](
x, y, iteration=iteration, room_dict=room_dict, caller=caller x,
y,
iteration=iteration,
room_dict=room_dict,
caller=caller,
) )
if iteration == 0: if iteration == 0:
room_dict[(x, y)] = room room_dict[(x, y)] = room
@ -432,7 +448,10 @@ class CmdMapBuilder(COMMAND_DEFAULT_CLASS):
# Check if arguments passed. # Check if arguments passed.
if not self.args or (len(args) != 2): if not self.args or (len(args) != 2):
caller.msg("Usage: @mapbuilder <path.to.module.VARNAME> " "<path.to.module.MAP_LEGEND>") caller.msg(
"Usage: @mapbuilder <path.to.module.VARNAME> "
"<path.to.module.MAP_LEGEND>"
)
return return
# Set up base variables. # Set up base variables.

View file

@ -24,7 +24,11 @@ from django.conf import settings
from evennia import Command, CmdSet from evennia import Command, CmdSet
from evennia import syscmdkeys from evennia import syscmdkeys
from evennia.utils.evmenu import EvMenu from evennia.utils.evmenu import EvMenu
from evennia.utils.utils import random_string_from_module, class_from_module, callables_from_module from evennia.utils.utils import (
random_string_from_module,
class_from_module,
callables_from_module,
)
_CONNECTION_SCREEN_MODULE = settings.CONNECTION_SCREEN_MODULE _CONNECTION_SCREEN_MODULE = settings.CONNECTION_SCREEN_MODULE
_GUEST_ENABLED = settings.GUEST_ENABLED _GUEST_ENABLED = settings.GUEST_ENABLED
@ -32,7 +36,8 @@ _ACCOUNT = class_from_module(settings.BASE_ACCOUNT_TYPECLASS)
_GUEST = class_from_module(settings.BASE_GUEST_TYPECLASS) _GUEST = class_from_module(settings.BASE_GUEST_TYPECLASS)
_ACCOUNT_HELP = ( _ACCOUNT_HELP = (
"Enter the name you used to log into the game before, " "or a new account-name if you are new." "Enter the name you used to log into the game before, "
"or a new account-name if you are new."
) )
_PASSWORD_HELP = ( _PASSWORD_HELP = (
"Password should be a minimum of 8 characters (preferably longer) and " "Password should be a minimum of 8 characters (preferably longer) and "
@ -106,7 +111,10 @@ def node_enter_username(caller, raw_text, **kwargs):
options = ( options = (
{"key": "", "goto": "node_enter_username"}, {"key": "", "goto": "node_enter_username"},
{"key": ("quit", "q"), "goto": "node_quit_or_login"}, {"key": ("quit", "q"), "goto": "node_quit_or_login"},
{"key": ("help", "h"), "goto": (_show_help, {"help_entry": _ACCOUNT_HELP, **kwargs})}, {
"key": ("help", "h"),
"goto": (_show_help, {"help_entry": _ACCOUNT_HELP, **kwargs}),
},
{"key": "_default", "goto": _check_input}, {"key": "_default", "goto": _check_input},
) )
return text, options return text, options
@ -150,7 +158,9 @@ def node_enter_password(caller, raw_string, **kwargs):
if account: if account:
if new_user: if new_user:
session.msg("|gA new account |c{}|g was created. Welcome!|n".format(username)) session.msg(
"|gA new account |c{}|g was created. Welcome!|n".format(username)
)
# pass login info to login node # pass login info to login node
return "node_quit_or_login", {"login": True, "account": account} return "node_quit_or_login", {"login": True, "account": account}
else: else:
@ -170,15 +180,21 @@ def node_enter_password(caller, raw_string, **kwargs):
# Attempting to fix password # Attempting to fix password
text = "Enter a new password:" text = "Enter a new password:"
else: else:
text = "Creating a new account |c{}|n. " "Enter a password (empty to abort):".format( text = (
username "Creating a new account |c{}|n. "
"Enter a password (empty to abort):".format(username)
) )
else: else:
text = "Enter the password for account |c{}|n (empty to abort):".format(username) text = "Enter the password for account |c{}|n (empty to abort):".format(
username
)
options = ( options = (
{"key": "", "goto": _restart_login}, {"key": "", "goto": _restart_login},
{"key": ("quit", "q"), "goto": "node_quit_or_login"}, {"key": ("quit", "q"), "goto": "node_quit_or_login"},
{"key": ("help", "h"), "goto": (_show_help, {"help_entry": _PASSWORD_HELP, **kwargs})}, {
"key": ("help", "h"),
"goto": (_show_help, {"help_entry": _PASSWORD_HELP, **kwargs}),
},
{"key": "_default", "goto": (_check_input, kwargs)}, {"key": "_default", "goto": (_check_input, kwargs)},
) )
return text, options return text, options

View file

@ -71,7 +71,11 @@ def _update_store(caller, key=None, desc=None, delete=False, swapkey=None):
elif swapkey: elif swapkey:
# swap positions # swap positions
loswapkey = swapkey.lower() loswapkey = swapkey.lower()
swapmatch = [ind for ind, tup in enumerate(caller.db.multidesc) if tup[0] == loswapkey] swapmatch = [
ind
for ind, tup in enumerate(caller.db.multidesc)
if tup[0] == loswapkey
]
if swapmatch: if swapmatch:
iswap = swapmatch[0] iswap = swapmatch[0]
if idesc == iswap: if idesc == iswap:
@ -171,7 +175,8 @@ class CmdMultiDesc(default_cmds.MuxCommand):
do_crop = "full" not in switches do_crop = "full" not in switches
if do_crop: if do_crop:
outtext = [ outtext = [
"|w%s:|n %s" % (key, crop(desc)) for key, desc in caller.db.multidesc "|w%s:|n %s" % (key, crop(desc))
for key, desc in caller.db.multidesc
] ]
else: else:
outtext = [ outtext = [
@ -240,7 +245,9 @@ class CmdMultiDesc(default_cmds.MuxCommand):
new_desc.append(key) new_desc.append(key)
new_desc = "".join(new_desc) new_desc = "".join(new_desc)
caller.db.desc = new_desc caller.db.desc = new_desc
caller.msg("%s\n\n|wThe above was set as the current description.|n" % new_desc) caller.msg(
"%s\n\n|wThe above was set as the current description.|n" % new_desc
)
elif self.rhs or "add" in switches: elif self.rhs or "add" in switches:
# add text directly to a new entry or an existing one. # add text directly to a new entry or an existing one.

View file

@ -86,7 +86,9 @@ _PUZZLES_TAG_RECIPE = "puzzle_recipe"
# puzzle part and puzzle result # puzzle part and puzzle result
_PUZZLES_TAG_MEMBER = "puzzle_member" _PUZZLES_TAG_MEMBER = "puzzle_member"
_PUZZLE_DEFAULT_FAIL_USE_MESSAGE = "You try to utilize %s but nothing happens ... something amiss?" _PUZZLE_DEFAULT_FAIL_USE_MESSAGE = (
"You try to utilize %s but nothing happens ... something amiss?"
)
_PUZZLE_DEFAULT_SUCCESS_USE_MESSAGE = "You are a Genius!!!" _PUZZLE_DEFAULT_SUCCESS_USE_MESSAGE = "You are a Genius!!!"
_PUZZLE_DEFAULT_SUCCESS_USE_LOCATION_MESSAGE = "|c{caller}|n performs some kind of tribal dance and |y{result_names}|n seems to appear from thin air" _PUZZLE_DEFAULT_SUCCESS_USE_LOCATION_MESSAGE = "|c{caller}|n performs some kind of tribal dance and |y{result_names}|n seems to appear from thin air"
@ -140,7 +142,9 @@ def _colorize_message(msg):
return msg return msg
_PUZZLE_DEFAULT_SUCCESS_USE_MESSAGE = _colorize_message(_PUZZLE_DEFAULT_SUCCESS_USE_MESSAGE) _PUZZLE_DEFAULT_SUCCESS_USE_MESSAGE = _colorize_message(
_PUZZLE_DEFAULT_SUCCESS_USE_MESSAGE
)
# ------------------------------------------ # ------------------------------------------
@ -157,7 +161,9 @@ class PuzzleRecipe(DefaultScript):
self.db.mask = tuple() self.db.mask = tuple()
self.tags.add(_PUZZLES_TAG_RECIPE, category=_PUZZLES_TAG_CATEGORY) self.tags.add(_PUZZLES_TAG_RECIPE, category=_PUZZLES_TAG_CATEGORY)
self.db.use_success_message = _PUZZLE_DEFAULT_SUCCESS_USE_MESSAGE self.db.use_success_message = _PUZZLE_DEFAULT_SUCCESS_USE_MESSAGE
self.db.use_success_location_message = _PUZZLE_DEFAULT_SUCCESS_USE_LOCATION_MESSAGE self.db.use_success_location_message = (
_PUZZLE_DEFAULT_SUCCESS_USE_LOCATION_MESSAGE
)
class CmdCreatePuzzleRecipe(MuxCommand): class CmdCreatePuzzleRecipe(MuxCommand):
@ -301,7 +307,9 @@ class CmdCreatePuzzleRecipe(MuxCommand):
caller.msg( caller.msg(
"You may now dispose of all parts and results. \n" "You may now dispose of all parts and results. \n"
"Use @puzzleedit #{dbref} to customize this puzzle further. \n" "Use @puzzleedit #{dbref} to customize this puzzle further. \n"
"Use @armpuzzle #{dbref} to arm a new puzzle instance.".format(dbref=puzzle.dbref) "Use @armpuzzle #{dbref} to arm a new puzzle instance.".format(
dbref=puzzle.dbref
)
) )
@ -364,7 +372,9 @@ class CmdEditPuzzle(MuxCommand):
puzzle_name_id = "%s(%s)" % (puzzle.name, puzzle.dbref) puzzle_name_id = "%s(%s)" % (puzzle.name, puzzle.dbref)
if "delete" in self.switches: if "delete" in self.switches:
if not (puzzle.access(caller, "control") or puzzle.access(caller, "delete")): if not (
puzzle.access(caller, "control") or puzzle.access(caller, "delete")
):
caller.msg("You don't have permission to delete %s." % puzzle_name_id) caller.msg("You don't have permission to delete %s." % puzzle_name_id)
return return
@ -646,7 +656,9 @@ class CmdUsePuzzleParts(MuxCommand):
# Create lookup dict of puzzles by dbref # Create lookup dict of puzzles by dbref
puzzles_dict = dict((puzzle.dbref, puzzle) for puzzle in puzzles) puzzles_dict = dict((puzzle.dbref, puzzle) for puzzle in puzzles)
# Check if parts can be combined to solve a puzzle # Check if parts can be combined to solve a puzzle
matched_puzzles = _matching_puzzles(puzzles, puzzlename_tags_dict, puzzle_ingredients) matched_puzzles = _matching_puzzles(
puzzles, puzzlename_tags_dict, puzzle_ingredients
)
if len(matched_puzzles) == 0: if len(matched_puzzles) == 0:
# TODO: we could use part.fail_message instead, if there was one # TODO: we could use part.fail_message instead, if there was one
@ -655,7 +667,9 @@ class CmdUsePuzzleParts(MuxCommand):
caller.msg(_PUZZLE_DEFAULT_FAIL_USE_MESSAGE % (many)) caller.msg(_PUZZLE_DEFAULT_FAIL_USE_MESSAGE % (many))
return return
puzzletuples = sorted(matched_puzzles.items(), key=lambda t: len(t[1]), reverse=True) puzzletuples = sorted(
matched_puzzles.items(), key=lambda t: len(t[1]), reverse=True
)
logger.log_info("MATCHED PUZZLES %r" % (puzzletuples)) logger.log_info("MATCHED PUZZLES %r" % (puzzletuples))
@ -663,7 +677,9 @@ class CmdUsePuzzleParts(MuxCommand):
puzzledbref, matched_dbrefparts = puzzletuples[0] puzzledbref, matched_dbrefparts = puzzletuples[0]
nparts = len(matched_dbrefparts) nparts = len(matched_dbrefparts)
puzzle = puzzles_dict[puzzledbref] puzzle = puzzles_dict[puzzledbref]
largest_puzzles = list(itertools.takewhile(lambda t: len(t[1]) == nparts, puzzletuples)) largest_puzzles = list(
itertools.takewhile(lambda t: len(t[1]) == nparts, puzzletuples)
)
# if there are more than one, choose one at random. # if there are more than one, choose one at random.
# we could show the names of all those that can be resolved # we could show the names of all those that can be resolved
@ -694,7 +710,9 @@ class CmdUsePuzzleParts(MuxCommand):
result_names = ", ".join(result_names) result_names = ", ".join(result_names)
caller.msg(puzzle.db.use_success_message) caller.msg(puzzle.db.use_success_message)
caller.location.msg_contents( caller.location.msg_contents(
puzzle.db.use_success_location_message.format(caller=caller, result_names=result_names), puzzle.db.use_success_location_message.format(
caller=caller, result_names=result_names
),
exclude=(caller,), exclude=(caller,),
) )
@ -714,17 +732,25 @@ class CmdListPuzzleRecipes(MuxCommand):
def func(self): def func(self):
caller = self.caller caller = self.caller
recipes = search.search_script_tag(_PUZZLES_TAG_RECIPE, category=_PUZZLES_TAG_CATEGORY) recipes = search.search_script_tag(
_PUZZLES_TAG_RECIPE, category=_PUZZLES_TAG_CATEGORY
)
div = "-" * 60 div = "-" * 60
text = [div] text = [div]
msgf_recipe = "Puzzle |y'%s' %s(%s)|n" msgf_recipe = "Puzzle |y'%s' %s(%s)|n"
msgf_item = "%2s|c%15s|n: |w%s|n" msgf_item = "%2s|c%15s|n: |w%s|n"
for recipe in recipes: for recipe in recipes:
text.append(msgf_recipe % (recipe.db.puzzle_name, recipe.name, recipe.dbref))
text.append("Success Caller message:\n" + recipe.db.use_success_message + "\n")
text.append( text.append(
"Success Location message:\n" + recipe.db.use_success_location_message + "\n" msgf_recipe % (recipe.db.puzzle_name, recipe.name, recipe.dbref)
)
text.append(
"Success Caller message:\n" + recipe.db.use_success_message + "\n"
)
text.append(
"Success Location message:\n"
+ recipe.db.use_success_location_message
+ "\n"
) )
text.append("Mask:\n" + str(recipe.db.mask) + "\n") text.append("Mask:\n" + str(recipe.db.mask) + "\n")
text.append("Parts") text.append("Parts")
@ -761,10 +787,13 @@ class CmdListArmedPuzzles(MuxCommand):
def func(self): def func(self):
caller = self.caller caller = self.caller
armed_puzzles = search.search_tag(_PUZZLES_TAG_MEMBER, category=_PUZZLES_TAG_CATEGORY) armed_puzzles = search.search_tag(
_PUZZLES_TAG_MEMBER, category=_PUZZLES_TAG_CATEGORY
)
armed_puzzles = dict( armed_puzzles = dict(
(k, list(g)) for k, g in itertools.groupby(armed_puzzles, lambda ap: ap.db.puzzle_name) (k, list(g))
for k, g in itertools.groupby(armed_puzzles, lambda ap: ap.db.puzzle_name)
) )
div = "-" * 60 div = "-" * 60
@ -775,7 +804,8 @@ class CmdListArmedPuzzles(MuxCommand):
text.append(msgf_pznm % (pzname)) text.append(msgf_pznm % (pzname))
for item in items: for item in items:
text.append( text.append(
msgf_item % (item.name, item.dbref, item.location.name, item.location.dbref) msgf_item
% (item.name, item.dbref, item.location.name, item.location.dbref)
) )
else: else:
text.append(div) text.append(div)

View file

@ -168,7 +168,9 @@ class RandomStringGenerator(object):
try: try:
script = ScriptDB.objects.get(db_key="generator_script") script = ScriptDB.objects.get(db_key="generator_script")
except ScriptDB.DoesNotExist: except ScriptDB.DoesNotExist:
script = create_script("contrib.random_string_generator.RandomStringGeneratorScript") script = create_script(
"contrib.random_string_generator.RandomStringGeneratorScript"
)
type(self).script = script type(self).script = script
return script return script
@ -200,7 +202,9 @@ class RandomStringGenerator(object):
# Either the beginning or end, we ignore it # Either the beginning or end, we ignore it
continue continue
elif name == "min_repeat": elif name == "min_repeat":
raise RejectedRegex("you have to provide a maximum number of this character class") raise RejectedRegex(
"you have to provide a maximum number of this character class"
)
elif name == "max_repeat": elif name == "max_repeat":
desc["min"] = element[1][0] desc["min"] = element[1][0]
desc["max"] = element[1][1] desc["max"] = element[1][1]

View file

@ -112,7 +112,9 @@ _VOWELS = "eaoiuy"
# these must be able to be constructed from phonemes (so for example, # these must be able to be constructed from phonemes (so for example,
# if you have v here, there must exist at least one single-character # if you have v here, there must exist at least one single-character
# vowel phoneme defined above) # vowel phoneme defined above)
_GRAMMAR = "v cv vc cvv vcc vcv cvcc vccv cvccv cvcvcc cvccvcv vccvccvc cvcvccvv cvcvcvcvv" _GRAMMAR = (
"v cv vc cvv vcc vcv cvcc vccv cvccv cvcvcc cvccvcv vccvccvc cvcvccvv cvcvcvcvv"
)
_RE_FLAGS = re.MULTILINE + re.IGNORECASE + re.DOTALL + re.UNICODE _RE_FLAGS = re.MULTILINE + re.IGNORECASE + re.DOTALL + re.UNICODE
_RE_GRAMMAR = re.compile(r"vv|cc|v|c", _RE_FLAGS) _RE_GRAMMAR = re.compile(r"vv|cc|v|c", _RE_FLAGS)
@ -246,7 +248,9 @@ class LanguageHandler(DefaultScript):
grammar2phonemes = defaultdict(list) grammar2phonemes = defaultdict(list)
for phoneme in phonemes.split(): for phoneme in phonemes.split():
if re.search("\W", phoneme): if re.search("\W", phoneme):
raise LanguageError("The phoneme '%s' contains an invalid character" % phoneme) raise LanguageError(
"The phoneme '%s' contains an invalid character" % phoneme
)
gram = "".join(["v" if char in vowels else "c" for char in phoneme]) gram = "".join(["v" if char in vowels else "c" for char in phoneme])
grammar2phonemes[gram].append(phoneme) grammar2phonemes[gram].append(phoneme)
@ -272,7 +276,9 @@ class LanguageHandler(DefaultScript):
word = word.strip() word = word.strip()
lword = len(word) lword = len(word)
new_word = "" new_word = ""
wlen = max(0, lword + sum(randint(-1, 1) for i in range(word_length_variance))) wlen = max(
0, lword + sum(randint(-1, 1) for i in range(word_length_variance))
)
if wlen not in grammar: if wlen not in grammar:
# always create a translation, use random length # always create a translation, use random length
structure = choice(grammar[choice(list(grammar))]) structure = choice(grammar[choice(list(grammar))])
@ -286,7 +292,10 @@ class LanguageHandler(DefaultScript):
if manual_translations: if manual_translations:
# update with manual translations # update with manual translations
translation.update( translation.update(
dict((key.lower(), value.lower()) for key, value in manual_translations.items()) dict(
(key.lower(), value.lower())
for key, value in manual_translations.items()
)
) )
# store data # store data
@ -338,7 +347,10 @@ class LanguageHandler(DefaultScript):
wlen = max( wlen = max(
0, 0,
lword lword
+ sum(randint(-1, 1) for i in range(self.language["word_length_variance"])), + sum(
randint(-1, 1)
for i in range(self.language["word_length_variance"])
),
) )
grammar = self.language["grammar"] grammar = self.language["grammar"]
if wlen not in grammar: if wlen not in grammar:
@ -368,7 +380,9 @@ class LanguageHandler(DefaultScript):
if word.istitle(): if word.istitle():
title_word = "" title_word = ""
if not start_sentence and not self.language.get("noun_translate", False): if not start_sentence and not self.language.get(
"noun_translate", False
):
# don't translate what we identify as proper nouns (names) # don't translate what we identify as proper nouns (names)
title_word = word title_word = word
elif new_word: elif new_word:
@ -511,7 +525,9 @@ _RE_WHISPER_OBSCURE = [
re.compile(r"[ae]", _RE_FLAGS), # This -s - Test! #1 add uy re.compile(r"[ae]", _RE_FLAGS), # This -s - Test! #1 add uy
re.compile(r"[aeuy]", _RE_FLAGS), # This -s - Test! #2 add oue re.compile(r"[aeuy]", _RE_FLAGS), # This -s - Test! #2 add oue
re.compile(r"[aeiouy]", _RE_FLAGS), # Th-s -s - T-st! #3 add all consonants re.compile(r"[aeiouy]", _RE_FLAGS), # Th-s -s - T-st! #3 add all consonants
re.compile(r"[aeiouybdhjlmnpqrv]", _RE_FLAGS), # T--s -s - T-st! #4 add hard consonants re.compile(
r"[aeiouybdhjlmnpqrv]", _RE_FLAGS
), # T--s -s - T-st! #4 add hard consonants
re.compile(r"[a-eg-rt-z]", _RE_FLAGS), # T--s -s - T-s-! #5 add all capitals re.compile(r"[a-eg-rt-z]", _RE_FLAGS), # T--s -s - T-s-! #5 add all capitals
re.compile(r"[A-EG-RT-Za-eg-rt-z]", _RE_FLAGS), # ---s -s - --s-! #6 add f re.compile(r"[A-EG-RT-Za-eg-rt-z]", _RE_FLAGS), # ---s -s - --s-! #6 add f
re.compile(r"[A-EG-RT-Za-rt-z]", _RE_FLAGS), # ---s -s - --s-! #7 add s re.compile(r"[A-EG-RT-Za-rt-z]", _RE_FLAGS), # ---s -s - --s-! #7 add s

View file

@ -137,7 +137,9 @@ _RE_PREFIX = re.compile(r"^%s" % _PREFIX, re.UNICODE)
# separate multimatches from one another and word is the first word in the # separate multimatches from one another and word is the first word in the
# marker. So entering "/tall man" will return groups ("", "tall") # marker. So entering "/tall man" will return groups ("", "tall")
# and "/2-tall man" will return groups ("2", "tall"). # and "/2-tall man" will return groups ("2", "tall").
_RE_OBJ_REF_START = re.compile(r"%s(?:([0-9]+)%s)*(\w+)" % (_PREFIX, _NUM_SEP), _RE_FLAGS) _RE_OBJ_REF_START = re.compile(
r"%s(?:([0-9]+)%s)*(\w+)" % (_PREFIX, _NUM_SEP), _RE_FLAGS
)
_RE_LEFT_BRACKETS = re.compile(r"\{+", _RE_FLAGS) _RE_LEFT_BRACKETS = re.compile(r"\{+", _RE_FLAGS)
_RE_RIGHT_BRACKETS = re.compile(r"\}+", _RE_FLAGS) _RE_RIGHT_BRACKETS = re.compile(r"\}+", _RE_FLAGS)
@ -232,7 +234,8 @@ def ordered_permutation_regex(sentence):
if comb: if comb:
solution.append( solution.append(
_PREFIX _PREFIX
+ r"[0-9]*%s*%s(?=\W|$)+" % (_NUM_SEP, re_escape(" ".join(comb)).rstrip("\\")) + r"[0-9]*%s*%s(?=\W|$)+"
% (_NUM_SEP, re_escape(" ".join(comb)).rstrip("\\"))
) )
# combine into a match regex, first matching the longest down to the shortest components # combine into a match regex, first matching the longest down to the shortest components
@ -258,7 +261,10 @@ def regex_tuple_from_key_alias(obj):
""" """
return ( return (
re.compile(ordered_permutation_regex(" ".join([obj.key] + obj.aliases.all())), _RE_FLAGS), re.compile(
ordered_permutation_regex(" ".join([obj.key] + obj.aliases.all())),
_RE_FLAGS,
),
obj, obj,
obj.key, obj.key,
) )
@ -360,7 +366,11 @@ def parse_sdescs_and_recogs(sender, candidates, string, search_mode=False):
""" """
# Load all candidate regex tuples [(regex, obj, sdesc/recog),...] # Load all candidate regex tuples [(regex, obj, sdesc/recog),...]
candidate_regexes = ( candidate_regexes = (
([(_RE_SELF_REF, sender, sender.sdesc.get())] if hasattr(sender, "sdesc") else []) (
[(_RE_SELF_REF, sender, sender.sdesc.get())]
if hasattr(sender, "sdesc")
else []
)
+ ( + (
[sender.recog.get_regex_tuple(obj) for obj in candidates] [sender.recog.get_regex_tuple(obj) for obj in candidates]
if hasattr(sender, "recog") if hasattr(sender, "recog")
@ -395,19 +405,28 @@ def parse_sdescs_and_recogs(sender, candidates, string, search_mode=False):
# start index forward for all candidates. # start index forward for all candidates.
# first see if there is a number given (e.g. 1-tall) # first see if there is a number given (e.g. 1-tall)
num_identifier, _ = marker_match.groups("") # return "" if no match, rather than None num_identifier, _ = marker_match.groups(
""
) # return "" if no match, rather than None
istart0 = marker_match.start() istart0 = marker_match.start()
istart = istart0 istart = istart0
# loop over all candidate regexes and match against the string following the match # loop over all candidate regexes and match against the string following the match
matches = ((reg.match(string[istart:]), obj, text) for reg, obj, text in candidate_regexes) matches = (
(reg.match(string[istart:]), obj, text)
for reg, obj, text in candidate_regexes
)
# score matches by how long part of the string was matched # score matches by how long part of the string was matched
matches = [(match.end() if match else -1, obj, text) for match, obj, text in matches] matches = [
(match.end() if match else -1, obj, text) for match, obj, text in matches
]
maxscore = max(score for score, obj, text in matches) maxscore = max(score for score, obj, text in matches)
# we have a valid maxscore, extract all matches with this value # we have a valid maxscore, extract all matches with this value
bestmatches = [(obj, text) for score, obj, text in matches if maxscore == score != -1] bestmatches = [
(obj, text) for score, obj, text in matches if maxscore == score != -1
]
nmatches = len(bestmatches) nmatches = len(bestmatches)
if not nmatches: if not nmatches:
@ -426,7 +445,11 @@ def parse_sdescs_and_recogs(sender, candidates, string, search_mode=False):
else: else:
# multi-match. # multi-match.
# was a numerical identifier given to help us separate the multi-match? # was a numerical identifier given to help us separate the multi-match?
inum = min(max(0, int(num_identifier) - 1), nmatches - 1) if num_identifier else None inum = (
min(max(0, int(num_identifier) - 1), nmatches - 1)
if num_identifier
else None
)
if inum is not None: if inum is not None:
# A valid inum is given. Use this to separate data. # A valid inum is given. Use this to separate data.
obj = bestmatches[inum][0] obj = bestmatches[inum][0]
@ -548,7 +571,8 @@ def send_emote(sender, receivers, emote, anonymous_add="first"):
try: try:
recog_get = receiver.recog.get recog_get = receiver.recog.get
receiver_sdesc_mapping = dict( receiver_sdesc_mapping = dict(
(ref, process_recog(recog_get(obj), obj)) for ref, obj in obj_mapping.items() (ref, process_recog(recog_get(obj), obj))
for ref, obj in obj_mapping.items()
) )
except AttributeError: except AttributeError:
receiver_sdesc_mapping = dict( receiver_sdesc_mapping = dict(
@ -632,7 +656,9 @@ class SdescHandler(object):
r"\1", r"\1",
_RE_REF_LANG.sub( _RE_REF_LANG.sub(
r"\1", r"\1",
_RE_SELF_REF.sub(r"", _RE_LANGUAGE.sub(r"", _RE_OBJ_REF_START.sub(r"", sdesc))), _RE_SELF_REF.sub(
r"", _RE_LANGUAGE.sub(r"", _RE_OBJ_REF_START.sub(r"", sdesc))
),
), ),
) )
@ -714,7 +740,9 @@ class RecogHandler(object):
obj2regex = self.obj.attributes.get("_recog_obj2regex", default={}) obj2regex = self.obj.attributes.get("_recog_obj2regex", default={})
obj2recog = self.obj.attributes.get("_recog_obj2recog", default={}) obj2recog = self.obj.attributes.get("_recog_obj2recog", default={})
self.obj2regex = dict( self.obj2regex = dict(
(obj, re.compile(regex, _RE_FLAGS)) for obj, regex in obj2regex.items() if obj (obj, re.compile(regex, _RE_FLAGS))
for obj, regex in obj2regex.items()
if obj
) )
self.obj2recog = dict((obj, recog) for obj, recog in obj2recog.items() if obj) self.obj2recog = dict((obj, recog) for obj, recog in obj2recog.items() if obj)
@ -746,7 +774,9 @@ class RecogHandler(object):
r"\1", r"\1",
_RE_REF_LANG.sub( _RE_REF_LANG.sub(
r"\1", r"\1",
_RE_SELF_REF.sub(r"", _RE_LANGUAGE.sub(r"", _RE_OBJ_REF_START.sub(r"", recog))), _RE_SELF_REF.sub(
r"", _RE_LANGUAGE.sub(r"", _RE_OBJ_REF_START.sub(r"", recog))
),
), ),
) )
@ -793,7 +823,9 @@ class RecogHandler(object):
# check an eventual recog_masked lock on the object # check an eventual recog_masked lock on the object
# to avoid revealing masked characters. If lock # to avoid revealing masked characters. If lock
# does not exist, pass automatically. # does not exist, pass automatically.
return self.obj2recog.get(obj, obj.sdesc.get() if hasattr(obj, "sdesc") else obj.key) return self.obj2recog.get(
obj, obj.sdesc.get() if hasattr(obj, "sdesc") else obj.key
)
else: else:
# recog_mask log not passed, disable recog # recog_mask log not passed, disable recog
return obj.sdesc.get() if hasattr(obj, "sdesc") else obj.key return obj.sdesc.get() if hasattr(obj, "sdesc") else obj.key
@ -1020,7 +1052,9 @@ class CmdPose(RPCommand): # set current pose and default pose
return return
else: else:
# set the pose. We do one-time ref->sdesc mapping here. # set the pose. We do one-time ref->sdesc mapping here.
parsed, mapping = parse_sdescs_and_recogs(caller, caller.location.contents, pose) parsed, mapping = parse_sdescs_and_recogs(
caller, caller.location.contents, pose
)
mapping = dict( mapping = dict(
(ref, obj.sdesc.get() if hasattr(obj, "sdesc") else obj.key) (ref, obj.sdesc.get() if hasattr(obj, "sdesc") else obj.key)
for ref, obj in mapping.items() for ref, obj in mapping.items()
@ -1059,11 +1093,15 @@ class CmdRecog(RPCommand): # assign personal alias to object in room
def parse(self): def parse(self):
"Parse for the sdesc as alias structure" "Parse for the sdesc as alias structure"
if " as " in self.args: if " as " in self.args:
self.sdesc, self.alias = [part.strip() for part in self.args.split(" as ", 2)] self.sdesc, self.alias = [
part.strip() for part in self.args.split(" as ", 2)
]
elif self.args: elif self.args:
# try to split by space instead # try to split by space instead
try: try:
self.sdesc, self.alias = [part.strip() for part in self.args.split(None, 1)] self.sdesc, self.alias = [
part.strip() for part in self.args.split(None, 1)
]
except ValueError: except ValueError:
self.sdesc, self.alias = self.args.strip(), "" self.sdesc, self.alias = self.args.strip(), ""
@ -1077,7 +1115,9 @@ class CmdRecog(RPCommand): # assign personal alias to object in room
alias = self.alias.rstrip(".?!") alias = self.alias.rstrip(".?!")
prefixed_sdesc = sdesc if sdesc.startswith(_PREFIX) else _PREFIX + sdesc prefixed_sdesc = sdesc if sdesc.startswith(_PREFIX) else _PREFIX + sdesc
candidates = caller.location.contents candidates = caller.location.contents
matches = parse_sdescs_and_recogs(caller, candidates, prefixed_sdesc, search_mode=True) matches = parse_sdescs_and_recogs(
caller, candidates, prefixed_sdesc, search_mode=True
)
nmatches = len(matches) nmatches = len(matches)
# handle 0, 1 and >1 matches # handle 0, 1 and >1 matches
if nmatches == 0: if nmatches == 0:
@ -1094,7 +1134,11 @@ class CmdRecog(RPCommand): # assign personal alias to object in room
) )
for inum, obj in enumerate(matches) for inum, obj in enumerate(matches)
] ]
caller.msg(_EMOTE_MULTIMATCH_ERROR.format(ref=sdesc, reflist="\n ".join(reflist))) caller.msg(
_EMOTE_MULTIMATCH_ERROR.format(
ref=sdesc, reflist="\n ".join(reflist)
)
)
else: else:
obj = matches[0] obj = matches[0]
if not obj.access(self.obj, "enable_recog", default=True): if not obj.access(self.obj, "enable_recog", default=True):
@ -1104,7 +1148,9 @@ class CmdRecog(RPCommand): # assign personal alias to object in room
if self.cmdstring == "forget": if self.cmdstring == "forget":
# remove existing recog # remove existing recog
caller.recog.remove(obj) caller.recog.remove(obj)
caller.msg("%s will now know only '%s'." % (caller.key, obj.recog.get(obj))) caller.msg(
"%s will now know only '%s'." % (caller.key, obj.recog.get(obj))
)
else: else:
sdesc = obj.sdesc.get() if hasattr(obj, "sdesc") else obj.key sdesc = obj.sdesc.get() if hasattr(obj, "sdesc") else obj.key
try: try:
@ -1112,7 +1158,10 @@ class CmdRecog(RPCommand): # assign personal alias to object in room
except RecogError as err: except RecogError as err:
caller.msg(err) caller.msg(err)
return return
caller.msg("%s will now remember |w%s|n as |w%s|n." % (caller.key, sdesc, alias)) caller.msg(
"%s will now remember |w%s|n as |w%s|n."
% (caller.key, sdesc, alias)
)
class CmdMask(RPCommand): class CmdMask(RPCommand):
@ -1349,7 +1398,9 @@ class ContribRPObject(DefaultObject):
# in eventual error reporting later (not their keys). Doing # in eventual error reporting later (not their keys). Doing
# it like this e.g. allows for use of the typeclass kwarg # it like this e.g. allows for use of the typeclass kwarg
# limiter. # limiter.
results.extend([obj for obj in search_obj(candidate.key) if obj not in results]) results.extend(
[obj for obj in search_obj(candidate.key) if obj not in results]
)
if not results and is_builder: if not results and is_builder:
# builders get a chance to search only by key+alias # builders get a chance to search only by key+alias
@ -1414,7 +1465,9 @@ class ContribRPObject(DefaultObject):
if not looker: if not looker:
return "" return ""
# get and identify all objects # get and identify all objects
visible = (con for con in self.contents if con != looker and con.access(looker, "view")) visible = (
con for con in self.contents if con != looker and con.access(looker, "view")
)
exits, users, things = [], [], [] exits, users, things = [], [], []
for con in visible: for con in visible:
key = con.get_display_name(looker, pose=True) key = con.get_display_name(looker, pose=True)

View file

@ -26,7 +26,9 @@ AUDIT_MASKS = [
{"connect": r"^[@\s]*[connect]{5,8}\s+(?P<secret>[\w]+)"}, {"connect": r"^[@\s]*[connect]{5,8}\s+(?P<secret>[\w]+)"},
{"create": r"^[^@]?[create]{5,6}\s+(\w+|\".+?\")\s+(?P<secret>[\w]+)"}, {"create": r"^[^@]?[create]{5,6}\s+(\w+|\".+?\")\s+(?P<secret>[\w]+)"},
{"create": r"^[^@]?[create]{5,6}\s+(?P<secret>[\w]+)"}, {"create": r"^[^@]?[create]{5,6}\s+(?P<secret>[\w]+)"},
{"userpassword": r"^[@\s]*[userpassword]{11,14}\s+(\w+|\".+?\")\s+=*\s*(?P<secret>[\w]+)"}, {
"userpassword": r"^[@\s]*[userpassword]{11,14}\s+(\w+|\".+?\")\s+=*\s*(?P<secret>[\w]+)"
},
{"userpassword": r"^.*new password set to '(?P<secret>[^']+)'\."}, {"userpassword": r"^.*new password set to '(?P<secret>[^']+)'\."},
{"userpassword": r"^.* has changed your password to '(?P<secret>[^']+)'\."}, {"userpassword": r"^.* has changed your password to '(?P<secret>[^']+)'\."},
{"password": r"^[@\s]*[password]{6,9}\s+(?P<secret>.*)"}, {"password": r"^[@\s]*[password]{6,9}\s+(?P<secret>.*)"},
@ -36,7 +38,8 @@ AUDIT_MASKS = [
if AUDIT_CALLBACK: if AUDIT_CALLBACK:
try: try:
AUDIT_CALLBACK = getattr( AUDIT_CALLBACK = getattr(
mod_import(".".join(AUDIT_CALLBACK.split(".")[:-1])), AUDIT_CALLBACK.split(".")[-1] mod_import(".".join(AUDIT_CALLBACK.split(".")[:-1])),
AUDIT_CALLBACK.split(".")[-1],
) )
logger.log_sec("Auditing module online.") logger.log_sec("Auditing module online.")
logger.log_sec( logger.log_sec(
@ -182,7 +185,9 @@ class AuditedServerSession(ServerSession):
# Check to see if the command is embedded within server output # Check to see if the command is embedded within server output
_msg = msg _msg = msg
is_embedded = False is_embedded = False
match = re.match(".*Command.*'(.+)'.*is not available.*", msg, flags=re.IGNORECASE) match = re.match(
".*Command.*'(.+)'.*is not available.*", msg, flags=re.IGNORECASE
)
if match: if match:
msg = match.group(1).replace("\\", "") msg = match.group(1).replace("\\", "")
submsg = msg submsg = msg
@ -203,7 +208,10 @@ class AuditedServerSession(ServerSession):
if is_embedded: if is_embedded:
msg = re.sub( msg = re.sub(
submsg, "%s <Masked: %s>" % (masked, command), _msg, flags=re.IGNORECASE submsg,
"%s <Masked: %s>" % (masked, command),
_msg,
flags=re.IGNORECASE,
) )
else: else:
msg = masked msg = masked

View file

@ -15,7 +15,9 @@ settings.AUDIT_OUT = True
settings.AUDIT_ALLOW_SPARSE = True settings.AUDIT_ALLOW_SPARSE = True
# Configure settings to use custom session - TODO: This is bad practice, changing global settings # Configure settings to use custom session - TODO: This is bad practice, changing global settings
settings.SERVER_SESSION_CLASS = "evennia.contrib.security.auditing.server.AuditedServerSession" settings.SERVER_SESSION_CLASS = (
"evennia.contrib.security.auditing.server.AuditedServerSession"
)
class AuditingTest(EvenniaTest): class AuditingTest(EvenniaTest):
@ -55,13 +57,28 @@ class AuditingTest(EvenniaTest):
("connect johnny password123", "connect johnny ***********"), ("connect johnny password123", "connect johnny ***********"),
("concnct johnny password123", "concnct johnny ***********"), ("concnct johnny password123", "concnct johnny ***********"),
("concnct johnnypassword123", "concnct *****************"), ("concnct johnnypassword123", "concnct *****************"),
('connect "johnny five" "password 123"', 'connect "johnny five" **************'), (
'connect "johnny five" "password 123"',
'connect "johnny five" **************',
),
('connect johnny "password 123"', "connect johnny **************"), ('connect johnny "password 123"', "connect johnny **************"),
("create johnny password123", "create johnny ***********"), ("create johnny password123", "create johnny ***********"),
("@password password1234 = password2345", "@password ***************************"), (
("@password password1234 password2345", "@password *************************"), "@password password1234 = password2345",
("@passwd password1234 = password2345", "@passwd ***************************"), "@password ***************************",
("@userpassword johnny = password234", "@userpassword johnny = ***********"), ),
(
"@password password1234 password2345",
"@password *************************",
),
(
"@passwd password1234 = password2345",
"@passwd ***************************",
),
(
"@userpassword johnny = password234",
"@userpassword johnny = ***********",
),
("craete johnnypassword123", "craete *****************"), ("craete johnnypassword123", "craete *****************"),
( (
"Command 'conncect teddy teddy' is not available. Maybe you meant \"@encode\"?", "Command 'conncect teddy teddy' is not available. Maybe you meant \"@encode\"?",
@ -74,7 +91,9 @@ class AuditingTest(EvenniaTest):
) )
for index, (unsafe, safe) in enumerate(unsafe_cmds): for index, (unsafe, safe) in enumerate(unsafe_cmds):
self.assertEqual(re.sub(" <Masked: .+>", "", self.session.mask(unsafe)).strip(), safe) self.assertEqual(
re.sub(" <Masked: .+>", "", self.session.mask(unsafe)).strip(), safe
)
# Make sure scrubbing is not being abused to evade monitoring # Make sure scrubbing is not being abused to evade monitoring
secrets = [ secrets = [
@ -93,7 +112,9 @@ class AuditingTest(EvenniaTest):
""" """
log = self.session.audit(src="client", text=[["hello"]]) log = self.session.audit(src="client", text=[["hello"]])
obj = { obj = {
k: v for k, v in log.items() if k in ("direction", "protocol", "application", "text") k: v
for k, v in log.items()
if k in ("direction", "protocol", "application", "text")
} }
self.assertEqual( self.assertEqual(
obj, obj,
@ -107,7 +128,10 @@ class AuditingTest(EvenniaTest):
# Make sure OOB data is being recorded # Make sure OOB data is being recorded
log = self.session.audit( log = self.session.audit(
src="client", text="connect johnny password123", prompt="hp=20|st=10|ma=15", pane=2 src="client",
text="connect johnny password123",
prompt="hp=20|st=10|ma=15",
pane=2,
) )
self.assertEqual(log["text"], "connect johnny ***********") self.assertEqual(log["text"], "connect johnny ***********")
self.assertEqual(log["data"]["prompt"], "hp=20|st=10|ma=15") self.assertEqual(log["data"]["prompt"], "hp=20|st=10|ma=15")

View file

@ -97,13 +97,19 @@ class CmdOpen(default_cmds.CmdOpen):
__doc__ = default_cmds.CmdOpen.__doc__ __doc__ = default_cmds.CmdOpen.__doc__
# overloading parts of the default CmdOpen command to support doors. # overloading parts of the default CmdOpen command to support doors.
def create_exit(self, exit_name, location, destination, exit_aliases=None, typeclass=None): def create_exit(
self, exit_name, location, destination, exit_aliases=None, typeclass=None
):
""" """
Simple wrapper for the default CmdOpen.create_exit Simple wrapper for the default CmdOpen.create_exit
""" """
# create a new exit as normal # create a new exit as normal
new_exit = super().create_exit( new_exit = super().create_exit(
exit_name, location, destination, exit_aliases=exit_aliases, typeclass=typeclass exit_name,
location,
destination,
exit_aliases=exit_aliases,
typeclass=typeclass,
) )
if hasattr(self, "return_exit_already_created"): if hasattr(self, "return_exit_already_created"):
# we don't create a return exit if it was already created (because # we don't create a return exit if it was already created (because
@ -118,7 +124,11 @@ class CmdOpen(default_cmds.CmdOpen):
) )
self.return_exit_already_created = True self.return_exit_already_created = True
back_exit = self.create_exit( back_exit = self.create_exit(
exit_name, destination, location, exit_aliases=exit_aliases, typeclass=typeclass exit_name,
destination,
location,
exit_aliases=exit_aliases,
typeclass=typeclass,
) )
new_exit.db.return_exit = back_exit new_exit.db.return_exit = back_exit
back_exit.db.return_exit = new_exit back_exit.db.return_exit = new_exit

View file

@ -81,7 +81,12 @@ class SlowExit(DefaultExit):
# set speed - command # set speed - command
# #
SPEED_DESCS = {"stroll": "strolling", "walk": "walking", "run": "running", "sprint": "sprinting"} SPEED_DESCS = {
"stroll": "strolling",
"walk": "walking",
"run": "running",
"sprint": "sprinting",
}
class CmdSetSpeed(Command): class CmdSetSpeed(Command):

View file

@ -30,7 +30,10 @@ def menu_start_node(caller):
text = "'Hello there, how can I help you?'" text = "'Hello there, how can I help you?'"
options = ( options = (
{"desc": "Hey, do you know what this 'Evennia' thing is all about?", "goto": "info1"}, {
"desc": "Hey, do you know what this 'Evennia' thing is all about?",
"goto": "info1",
},
{"desc": "What's your name, little NPC?", "goto": "info2"}, {"desc": "What's your name, little NPC?", "goto": "info2"},
) )
@ -41,7 +44,10 @@ def info1(caller):
text = "'Oh, Evennia is where you are right now! Don't you feel the power?'" text = "'Oh, Evennia is where you are right now! Don't you feel the power?'"
options = ( options = (
{"desc": "Sure, *I* do, not sure how you do though. You are just an NPC.", "goto": "info3"}, {
"desc": "Sure, *I* do, not sure how you do though. You are just an NPC.",
"goto": "info3",
},
{"desc": "Sure I do. What's yer name, NPC?", "goto": "info2"}, {"desc": "Sure I do. What's yer name, NPC?", "goto": "info2"},
{"desc": "Ok, bye for now then.", "goto": "END"}, {"desc": "Ok, bye for now then.", "goto": "END"},
) )

File diff suppressed because it is too large Load diff

View file

@ -422,7 +422,10 @@ def optlist_to_menuoptions(treestr, optlist, index, mark_category, go_back):
gobackitem = { gobackitem = {
"key": ["<< Go Back", "go back", "back"], "key": ["<< Go Back", "go back", "back"],
"desc": "Return to the previous menu.", "desc": "Return to the previous menu.",
"goto": ["menunode_treeselect", {"newindex": go_up_one_category(treestr, index)}], "goto": [
"menunode_treeselect",
{"newindex": go_up_one_category(treestr, index)},
],
} }
menuoptions.append(gobackitem) menuoptions.append(gobackitem)
return menuoptions return menuoptions
@ -461,7 +464,9 @@ def menunode_treeselect(caller, raw_string, **kwargs):
# Otherwise, convert optlist to a list of menu options. # Otherwise, convert optlist to a list of menu options.
else: else:
options = optlist_to_menuoptions(treestr, optlist, index, mark_category, go_back) options = optlist_to_menuoptions(
treestr, optlist, index, mark_category, go_back
)
if index == None: if index == None:
# Use start_text for the menu text on the top level # Use start_text for the menu text on the top level
text = start_text text = start_text
@ -525,7 +530,10 @@ class CmdNameColor(Command):
def func(self): def func(self):
# This is all you have to do to initialize a menu! # This is all you have to do to initialize a menu!
init_tree_selection( init_tree_selection(
NAMECOLOR_MENU, self.caller, change_name_color, start_text="Name color options:" NAMECOLOR_MENU,
self.caller,
change_name_color,
start_text="Name color options:",
) )
@ -573,5 +581,7 @@ def change_name_color(caller, treestr, index, selection):
caller.msg("Name color removed.") caller.msg("Name color removed.")
elif selection in colordict: elif selection in colordict:
newcolor = colordict[selection] # Retrieve color code based on menu selection newcolor = colordict[selection] # Retrieve color code based on menu selection
caller.key = newcolor + caller.db.uncolored_name + "|n" # Add color code to caller's name caller.key = (
newcolor + caller.db.uncolored_name + "|n"
) # Add color code to caller's name
caller.msg(newcolor + ("Name color changed to %s!" % selection) + "|n") caller.msg(newcolor + ("Name color changed to %s!" % selection) + "|n")

View file

@ -291,7 +291,9 @@ def spend_action(character, actions, action_name=None):
character.db.combat_actionsleft -= actions # Use up actions. character.db.combat_actionsleft -= actions # Use up actions.
if character.db.combat_actionsleft < 0: if character.db.combat_actionsleft < 0:
character.db.combat_actionsleft = 0 # Can't have fewer than 0 actions character.db.combat_actionsleft = 0 # Can't have fewer than 0 actions
character.db.combat_turnhandler.turn_end_check(character) # Signal potential end of turn. character.db.combat_turnhandler.turn_end_check(
character
) # Signal potential end of turn.
""" """
@ -394,7 +396,9 @@ class TBBasicTurnHandler(DefaultScript):
self.db.fighters = ordered_by_roll self.db.fighters = ordered_by_roll
# Announce the turn order. # Announce the turn order.
self.obj.msg_contents("Turn order is: %s " % ", ".join(obj.key for obj in self.db.fighters)) self.obj.msg_contents(
"Turn order is: %s " % ", ".join(obj.key for obj in self.db.fighters)
)
# Start first fighter's turn. # Start first fighter's turn.
self.start_turn(self.db.fighters[0]) self.start_turn(self.db.fighters[0])
@ -409,7 +413,9 @@ class TBBasicTurnHandler(DefaultScript):
""" """
for fighter in self.db.fighters: for fighter in self.db.fighters:
combat_cleanup(fighter) # Clean up the combat attributes for every fighter. combat_cleanup(fighter) # Clean up the combat attributes for every fighter.
self.obj.db.combat_turnhandler = None # Remove reference to turn handler in location self.obj.db.combat_turnhandler = (
None
) # Remove reference to turn handler in location
def at_repeat(self): def at_repeat(self):
""" """
@ -427,7 +433,9 @@ class TBBasicTurnHandler(DefaultScript):
currentchar, "all", action_name="disengage" currentchar, "all", action_name="disengage"
) # Spend all remaining actions. ) # Spend all remaining actions.
return return
elif self.db.timer <= 10 and not self.db.timeout_warning_given: # 10 seconds left elif (
self.db.timer <= 10 and not self.db.timeout_warning_given
): # 10 seconds left
# Warn the current character if they're about to time out. # Warn the current character if they're about to time out.
currentchar.msg("WARNING: About to time out!") currentchar.msg("WARNING: About to time out!")
self.db.timeout_warning_given = True self.db.timeout_warning_given = True
@ -439,7 +447,9 @@ class TBBasicTurnHandler(DefaultScript):
Args: Args:
character (obj): Character to initialize for combat. character (obj): Character to initialize for combat.
""" """
combat_cleanup(character) # Clean up leftover combat attributes beforehand, just in case. combat_cleanup(
character
) # Clean up leftover combat attributes beforehand, just in case.
character.db.combat_actionsleft = ( character.db.combat_actionsleft = (
0 0
) # Actions remaining - start of turn adds to this, turn ends when it reaches 0 ) # Actions remaining - start of turn adds to this, turn ends when it reaches 0
@ -488,13 +498,17 @@ class TBBasicTurnHandler(DefaultScript):
defeated_characters = 0 defeated_characters = 0
for fighter in self.db.fighters: for fighter in self.db.fighters:
if fighter.db.HP == 0: if fighter.db.HP == 0:
defeated_characters += 1 # Add 1 for every fighter with 0 HP left (defeated) defeated_characters += (
1
) # Add 1 for every fighter with 0 HP left (defeated)
if defeated_characters == ( if defeated_characters == (
len(self.db.fighters) - 1 len(self.db.fighters) - 1
): # If only one character isn't defeated ): # If only one character isn't defeated
for fighter in self.db.fighters: for fighter in self.db.fighters:
if fighter.db.HP != 0: if fighter.db.HP != 0:
LastStanding = fighter # Pick the one fighter left with HP remaining LastStanding = (
fighter
) # Pick the one fighter left with HP remaining
self.obj.msg_contents("Only %s remains! Combat is over!" % LastStanding) self.obj.msg_contents("Only %s remains! Combat is over!" % LastStanding)
self.stop() # Stop this script and end combat. self.stop() # Stop this script and end combat.
return return
@ -503,11 +517,15 @@ class TBBasicTurnHandler(DefaultScript):
currentchar = self.db.fighters[self.db.turn] currentchar = self.db.fighters[self.db.turn]
self.db.turn += 1 # Go to the next in the turn order. self.db.turn += 1 # Go to the next in the turn order.
if self.db.turn > len(self.db.fighters) - 1: if self.db.turn > len(self.db.fighters) - 1:
self.db.turn = 0 # Go back to the first in the turn order once you reach the end. self.db.turn = (
0
) # Go back to the first in the turn order once you reach the end.
newchar = self.db.fighters[self.db.turn] # Note the new character newchar = self.db.fighters[self.db.turn] # Note the new character
self.db.timer = TURN_TIMEOUT + self.time_until_next_repeat() # Reset the timer. self.db.timer = TURN_TIMEOUT + self.time_until_next_repeat() # Reset the timer.
self.db.timeout_warning_given = False # Reset the timeout warning. self.db.timeout_warning_given = False # Reset the timeout warning.
self.obj.msg_contents("%s's turn ends - %s's turn begins!" % (currentchar, newchar)) self.obj.msg_contents(
"%s's turn ends - %s's turn begins!" % (currentchar, newchar)
)
self.start_turn(newchar) # Start the new character's turn. self.start_turn(newchar) # Start the new character's turn.
def turn_end_check(self, character): def turn_end_check(self, character):
@ -571,7 +589,9 @@ class CmdFight(Command):
if is_in_combat(self.caller): # Already in a fight if is_in_combat(self.caller): # Already in a fight
self.caller.msg("You're already in a fight!") self.caller.msg("You're already in a fight!")
return return
for thing in here.contents: # Test everything in the room to add it to the fight. for (
thing
) in here.contents: # Test everything in the room to add it to the fight.
if thing.db.HP: # If the object has HP... if thing.db.HP: # If the object has HP...
fighters.append(thing) # ...then add it to the fight. fighters.append(thing) # ...then add it to the fight.
if len(fighters) <= 1: # If you're the only able fighter in the room if len(fighters) <= 1: # If you're the only able fighter in the room
@ -666,7 +686,9 @@ class CmdPass(Command):
self.caller.location.msg_contents( self.caller.location.msg_contents(
"%s takes no further action, passing the turn." % self.caller "%s takes no further action, passing the turn." % self.caller
) )
spend_action(self.caller, "all", action_name="pass") # Spend all remaining actions. spend_action(
self.caller, "all", action_name="pass"
) # Spend all remaining actions.
class CmdDisengage(Command): class CmdDisengage(Command):
@ -697,8 +719,12 @@ class CmdDisengage(Command):
self.caller.msg("You can only do that on your turn.") self.caller.msg("You can only do that on your turn.")
return return
self.caller.location.msg_contents("%s disengages, ready to stop fighting." % self.caller) self.caller.location.msg_contents(
spend_action(self.caller, "all", action_name="disengage") # Spend all remaining actions. "%s disengages, ready to stop fighting." % self.caller
)
spend_action(
self.caller, "all", action_name="disengage"
) # Spend all remaining actions.
""" """
The action_name kwarg sets the character's last action to "disengage", which is checked by The action_name kwarg sets the character's last action to "disengage", which is checked by
the turn handler script to see if all fighters have disengaged. the turn handler script to see if all fighters have disengaged.
@ -750,7 +776,9 @@ class CmdCombatHelp(CmdHelp):
# tips on combat when used in a fight with no arguments. # tips on combat when used in a fight with no arguments.
def func(self): def func(self):
if is_in_combat(self.caller) and not self.args: # In combat and entered 'help' alone if (
is_in_combat(self.caller) and not self.args
): # In combat and entered 'help' alone
self.caller.msg( self.caller.msg(
"Available combat commands:|/" "Available combat commands:|/"
+ "|wAttack:|n Attack a target, attempting to deal damage.|/" + "|wAttack:|n Attack a target, attempting to deal damage.|/"

View file

@ -55,7 +55,13 @@ in your game and using it as-is.
""" """
from random import randint from random import randint
from evennia import DefaultCharacter, Command, default_cmds, DefaultScript, DefaultObject from evennia import (
DefaultCharacter,
Command,
default_cmds,
DefaultScript,
DefaultObject,
)
from evennia.commands.default.help import CmdHelp from evennia.commands.default.help import CmdHelp
""" """
@ -270,7 +276,8 @@ def resolve_attack(attacker, defender, attack_value=None, defense_value=None):
) )
else: else:
attacker.location.msg_contents( attacker.location.msg_contents(
"%s's %s bounces harmlessly off %s!" % (attacker, attackers_weapon, defender) "%s's %s bounces harmlessly off %s!"
% (attacker, attackers_weapon, defender)
) )
apply_damage(defender, damage_value) apply_damage(defender, damage_value)
# If defender HP is reduced to 0 or less, call at_defeat. # If defender HP is reduced to 0 or less, call at_defeat.
@ -342,7 +349,9 @@ def spend_action(character, actions, action_name=None):
character.db.combat_actionsleft -= actions # Use up actions. character.db.combat_actionsleft -= actions # Use up actions.
if character.db.combat_actionsleft < 0: if character.db.combat_actionsleft < 0:
character.db.combat_actionsleft = 0 # Can't have fewer than 0 actions character.db.combat_actionsleft = 0 # Can't have fewer than 0 actions
character.db.combat_turnhandler.turn_end_check(character) # Signal potential end of turn. character.db.combat_turnhandler.turn_end_check(
character
) # Signal potential end of turn.
""" """
@ -391,7 +400,9 @@ class TBEquipTurnHandler(DefaultScript):
self.db.fighters = ordered_by_roll self.db.fighters = ordered_by_roll
# Announce the turn order. # Announce the turn order.
self.obj.msg_contents("Turn order is: %s " % ", ".join(obj.key for obj in self.db.fighters)) self.obj.msg_contents(
"Turn order is: %s " % ", ".join(obj.key for obj in self.db.fighters)
)
# Start first fighter's turn. # Start first fighter's turn.
self.start_turn(self.db.fighters[0]) self.start_turn(self.db.fighters[0])
@ -406,7 +417,9 @@ class TBEquipTurnHandler(DefaultScript):
""" """
for fighter in self.db.fighters: for fighter in self.db.fighters:
combat_cleanup(fighter) # Clean up the combat attributes for every fighter. combat_cleanup(fighter) # Clean up the combat attributes for every fighter.
self.obj.db.combat_turnhandler = None # Remove reference to turn handler in location self.obj.db.combat_turnhandler = (
None
) # Remove reference to turn handler in location
def at_repeat(self): def at_repeat(self):
""" """
@ -424,7 +437,9 @@ class TBEquipTurnHandler(DefaultScript):
currentchar, "all", action_name="disengage" currentchar, "all", action_name="disengage"
) # Spend all remaining actions. ) # Spend all remaining actions.
return return
elif self.db.timer <= 10 and not self.db.timeout_warning_given: # 10 seconds left elif (
self.db.timer <= 10 and not self.db.timeout_warning_given
): # 10 seconds left
# Warn the current character if they're about to time out. # Warn the current character if they're about to time out.
currentchar.msg("WARNING: About to time out!") currentchar.msg("WARNING: About to time out!")
self.db.timeout_warning_given = True self.db.timeout_warning_given = True
@ -436,7 +451,9 @@ class TBEquipTurnHandler(DefaultScript):
Args: Args:
character (obj): Character to initialize for combat. character (obj): Character to initialize for combat.
""" """
combat_cleanup(character) # Clean up leftover combat attributes beforehand, just in case. combat_cleanup(
character
) # Clean up leftover combat attributes beforehand, just in case.
character.db.combat_actionsleft = ( character.db.combat_actionsleft = (
0 0
) # Actions remaining - start of turn adds to this, turn ends when it reaches 0 ) # Actions remaining - start of turn adds to this, turn ends when it reaches 0
@ -485,13 +502,17 @@ class TBEquipTurnHandler(DefaultScript):
defeated_characters = 0 defeated_characters = 0
for fighter in self.db.fighters: for fighter in self.db.fighters:
if fighter.db.HP == 0: if fighter.db.HP == 0:
defeated_characters += 1 # Add 1 for every fighter with 0 HP left (defeated) defeated_characters += (
1
) # Add 1 for every fighter with 0 HP left (defeated)
if defeated_characters == ( if defeated_characters == (
len(self.db.fighters) - 1 len(self.db.fighters) - 1
): # If only one character isn't defeated ): # If only one character isn't defeated
for fighter in self.db.fighters: for fighter in self.db.fighters:
if fighter.db.HP != 0: if fighter.db.HP != 0:
LastStanding = fighter # Pick the one fighter left with HP remaining LastStanding = (
fighter
) # Pick the one fighter left with HP remaining
self.obj.msg_contents("Only %s remains! Combat is over!" % LastStanding) self.obj.msg_contents("Only %s remains! Combat is over!" % LastStanding)
self.stop() # Stop this script and end combat. self.stop() # Stop this script and end combat.
return return
@ -500,11 +521,15 @@ class TBEquipTurnHandler(DefaultScript):
currentchar = self.db.fighters[self.db.turn] currentchar = self.db.fighters[self.db.turn]
self.db.turn += 1 # Go to the next in the turn order. self.db.turn += 1 # Go to the next in the turn order.
if self.db.turn > len(self.db.fighters) - 1: if self.db.turn > len(self.db.fighters) - 1:
self.db.turn = 0 # Go back to the first in the turn order once you reach the end. self.db.turn = (
0
) # Go back to the first in the turn order once you reach the end.
newchar = self.db.fighters[self.db.turn] # Note the new character newchar = self.db.fighters[self.db.turn] # Note the new character
self.db.timer = TURN_TIMEOUT + self.time_until_next_repeat() # Reset the timer. self.db.timer = TURN_TIMEOUT + self.time_until_next_repeat() # Reset the timer.
self.db.timeout_warning_given = False # Reset the timeout warning. self.db.timeout_warning_given = False # Reset the timeout warning.
self.obj.msg_contents("%s's turn ends - %s's turn begins!" % (currentchar, newchar)) self.obj.msg_contents(
"%s's turn ends - %s's turn begins!" % (currentchar, newchar)
)
self.start_turn(newchar) # Start the new character's turn. self.start_turn(newchar) # Start the new character's turn.
def turn_end_check(self, character): def turn_end_check(self, character):
@ -710,7 +735,9 @@ class CmdFight(Command):
if is_in_combat(self.caller): # Already in a fight if is_in_combat(self.caller): # Already in a fight
self.caller.msg("You're already in a fight!") self.caller.msg("You're already in a fight!")
return return
for thing in here.contents: # Test everything in the room to add it to the fight. for (
thing
) in here.contents: # Test everything in the room to add it to the fight.
if thing.db.HP: # If the object has HP... if thing.db.HP: # If the object has HP...
fighters.append(thing) # ...then add it to the fight. fighters.append(thing) # ...then add it to the fight.
if len(fighters) <= 1: # If you're the only able fighter in the room if len(fighters) <= 1: # If you're the only able fighter in the room
@ -805,7 +832,9 @@ class CmdPass(Command):
self.caller.location.msg_contents( self.caller.location.msg_contents(
"%s takes no further action, passing the turn." % self.caller "%s takes no further action, passing the turn." % self.caller
) )
spend_action(self.caller, "all", action_name="pass") # Spend all remaining actions. spend_action(
self.caller, "all", action_name="pass"
) # Spend all remaining actions.
class CmdDisengage(Command): class CmdDisengage(Command):
@ -836,8 +865,12 @@ class CmdDisengage(Command):
self.caller.msg("You can only do that on your turn.") self.caller.msg("You can only do that on your turn.")
return return
self.caller.location.msg_contents("%s disengages, ready to stop fighting." % self.caller) self.caller.location.msg_contents(
spend_action(self.caller, "all", action_name="disengage") # Spend all remaining actions. "%s disengages, ready to stop fighting." % self.caller
)
spend_action(
self.caller, "all", action_name="disengage"
) # Spend all remaining actions.
""" """
The action_name kwarg sets the character's last action to "disengage", which is checked by The action_name kwarg sets the character's last action to "disengage", which is checked by
the turn handler script to see if all fighters have disengaged. the turn handler script to see if all fighters have disengaged.
@ -889,7 +922,9 @@ class CmdCombatHelp(CmdHelp):
# tips on combat when used in a fight with no arguments. # tips on combat when used in a fight with no arguments.
def func(self): def func(self):
if is_in_combat(self.caller) and not self.args: # In combat and entered 'help' alone if (
is_in_combat(self.caller) and not self.args
): # In combat and entered 'help' alone
self.caller.msg( self.caller.msg(
"Available combat commands:|/" "Available combat commands:|/"
+ "|wAttack:|n Attack a target, attempting to deal damage.|/" + "|wAttack:|n Attack a target, attempting to deal damage.|/"
@ -980,7 +1015,9 @@ class CmdUnwield(Command):
else: else:
old_weapon = self.caller.db.wielded_weapon old_weapon = self.caller.db.wielded_weapon
self.caller.db.wielded_weapon = None self.caller.db.wielded_weapon = None
self.caller.location.msg_contents("%s lowers %s." % (self.caller, old_weapon)) self.caller.location.msg_contents(
"%s lowers %s." % (self.caller, old_weapon)
)
class CmdDon(Command): class CmdDon(Command):
@ -1056,7 +1093,9 @@ class CmdDoff(Command):
else: else:
old_armor = self.caller.db.worn_armor old_armor = self.caller.db.worn_armor
self.caller.db.worn_armor = None self.caller.db.worn_armor = None
self.caller.location.msg_contents("%s removes %s." % (self.caller, old_armor)) self.caller.location.msg_contents(
"%s removes %s." % (self.caller, old_armor)
)
class BattleCmdSet(default_cmds.CharacterCmdSet): class BattleCmdSet(default_cmds.CharacterCmdSet):

View file

@ -360,7 +360,9 @@ def spend_action(character, actions, action_name=None):
character.db.combat_actionsleft -= actions # Use up actions. character.db.combat_actionsleft -= actions # Use up actions.
if character.db.combat_actionsleft < 0: if character.db.combat_actionsleft < 0:
character.db.combat_actionsleft = 0 # Can't have fewer than 0 actions character.db.combat_actionsleft = 0 # Can't have fewer than 0 actions
character.db.combat_turnhandler.turn_end_check(character) # Signal potential end of turn. character.db.combat_turnhandler.turn_end_check(
character
) # Signal potential end of turn.
def spend_item_use(item, user): def spend_item_use(item, user):
@ -381,7 +383,9 @@ def spend_item_use(item, user):
if item.db.item_uses > 0: # Has uses remaining if item.db.item_uses > 0: # Has uses remaining
# Inform the player # Inform the player
user.msg("%s has %i uses remaining." % (item.key.capitalize(), item.db.item_uses)) user.msg(
"%s has %i uses remaining." % (item.key.capitalize(), item.db.item_uses)
)
else: # All uses spent else: # All uses spent
@ -390,13 +394,19 @@ def spend_item_use(item, user):
user.msg("%s has no uses remaining." % item.key.capitalize()) user.msg("%s has no uses remaining." % item.key.capitalize())
else: # If item is consumable else: # If item is consumable
if item.db.item_consumable == True: # If the value is 'True', just destroy the item if (
item.db.item_consumable == True
): # If the value is 'True', just destroy the item
user.msg("%s has been consumed." % item.key.capitalize()) user.msg("%s has been consumed." % item.key.capitalize())
item.delete() # Delete the spent item item.delete() # Delete the spent item
else: # If a string, use value of item_consumable to spawn an object in its place else: # If a string, use value of item_consumable to spawn an object in its place
residue = spawn({"prototype": item.db.item_consumable})[0] # Spawn the residue residue = spawn({"prototype": item.db.item_consumable})[
residue.location = item.location # Move the residue to the same place as the item 0
] # Spawn the residue
residue.location = (
item.location
) # Move the residue to the same place as the item
user.msg("After using %s, you are left with %s." % (item, residue)) user.msg("After using %s, you are left with %s." % (item, residue))
item.delete() # Delete the spent item item.delete() # Delete the spent item
@ -491,7 +501,9 @@ def add_condition(character, turnchar, condition, duration):
# The first value is the remaining turns - the second value is whose turn to count down on. # The first value is the remaining turns - the second value is whose turn to count down on.
character.db.conditions.update({condition: [duration, turnchar]}) character.db.conditions.update({condition: [duration, turnchar]})
# Tell everyone! # Tell everyone!
character.location.msg_contents("%s gains the '%s' condition." % (character, condition)) character.location.msg_contents(
"%s gains the '%s' condition." % (character, condition)
)
""" """
@ -577,13 +589,17 @@ class TBItemsCharacter(DefaultCharacter):
if self.db.hp + to_heal > self.db.max_hp: if self.db.hp + to_heal > self.db.max_hp:
to_heal = self.db.max_hp - self.db.hp # Cap healing to max HP to_heal = self.db.max_hp - self.db.hp # Cap healing to max HP
self.db.hp += to_heal self.db.hp += to_heal
self.location.msg_contents("%s regains %i HP from Regeneration." % (self, to_heal)) self.location.msg_contents(
"%s regains %i HP from Regeneration." % (self, to_heal)
)
# Poisoned: does 4 to 8 damage at the start of character's turn # Poisoned: does 4 to 8 damage at the start of character's turn
if "Poisoned" in self.db.conditions: if "Poisoned" in self.db.conditions:
to_hurt = randint(POISON_RATE[0], POISON_RATE[1]) # Deal damage to_hurt = randint(POISON_RATE[0], POISON_RATE[1]) # Deal damage
apply_damage(self, to_hurt) apply_damage(self, to_hurt)
self.location.msg_contents("%s takes %i damage from being Poisoned." % (self, to_hurt)) self.location.msg_contents(
"%s takes %i damage from being Poisoned." % (self, to_hurt)
)
if self.db.hp <= 0: if self.db.hp <= 0:
# Call at_defeat if poison defeats the character # Call at_defeat if poison defeats the character
at_defeat(self) at_defeat(self)
@ -596,7 +612,9 @@ class TBItemsCharacter(DefaultCharacter):
# Paralyzed: Have no actions in combat. # Paralyzed: Have no actions in combat.
if is_in_combat(self) and "Paralyzed" in self.db.conditions: if is_in_combat(self) and "Paralyzed" in self.db.conditions:
self.db.combat_actionsleft = 0 self.db.combat_actionsleft = 0
self.location.msg_contents("%s is Paralyzed, and can't act this turn!" % self) self.location.msg_contents(
"%s is Paralyzed, and can't act this turn!" % self
)
self.db.combat_turnhandler.turn_end_check(self) self.db.combat_turnhandler.turn_end_check(self)
def at_update(self): def at_update(self):
@ -671,7 +689,9 @@ class TBItemsTurnHandler(DefaultScript):
self.db.fighters = ordered_by_roll self.db.fighters = ordered_by_roll
# Announce the turn order. # Announce the turn order.
self.obj.msg_contents("Turn order is: %s " % ", ".join(obj.key for obj in self.db.fighters)) self.obj.msg_contents(
"Turn order is: %s " % ", ".join(obj.key for obj in self.db.fighters)
)
# Start first fighter's turn. # Start first fighter's turn.
self.start_turn(self.db.fighters[0]) self.start_turn(self.db.fighters[0])
@ -686,7 +706,9 @@ class TBItemsTurnHandler(DefaultScript):
""" """
for fighter in self.db.fighters: for fighter in self.db.fighters:
combat_cleanup(fighter) # Clean up the combat attributes for every fighter. combat_cleanup(fighter) # Clean up the combat attributes for every fighter.
self.obj.db.combat_turnhandler = None # Remove reference to turn handler in location self.obj.db.combat_turnhandler = (
None
) # Remove reference to turn handler in location
def at_repeat(self): def at_repeat(self):
""" """
@ -704,7 +726,9 @@ class TBItemsTurnHandler(DefaultScript):
currentchar, "all", action_name="disengage" currentchar, "all", action_name="disengage"
) # Spend all remaining actions. ) # Spend all remaining actions.
return return
elif self.db.timer <= 10 and not self.db.timeout_warning_given: # 10 seconds left elif (
self.db.timer <= 10 and not self.db.timeout_warning_given
): # 10 seconds left
# Warn the current character if they're about to time out. # Warn the current character if they're about to time out.
currentchar.msg("WARNING: About to time out!") currentchar.msg("WARNING: About to time out!")
self.db.timeout_warning_given = True self.db.timeout_warning_given = True
@ -716,7 +740,9 @@ class TBItemsTurnHandler(DefaultScript):
Args: Args:
character (obj): Character to initialize for combat. character (obj): Character to initialize for combat.
""" """
combat_cleanup(character) # Clean up leftover combat attributes beforehand, just in case. combat_cleanup(
character
) # Clean up leftover combat attributes beforehand, just in case.
character.db.combat_actionsleft = ( character.db.combat_actionsleft = (
0 0
) # Actions remaining - start of turn adds to this, turn ends when it reaches 0 ) # Actions remaining - start of turn adds to this, turn ends when it reaches 0
@ -765,13 +791,17 @@ class TBItemsTurnHandler(DefaultScript):
defeated_characters = 0 defeated_characters = 0
for fighter in self.db.fighters: for fighter in self.db.fighters:
if fighter.db.HP == 0: if fighter.db.HP == 0:
defeated_characters += 1 # Add 1 for every fighter with 0 HP left (defeated) defeated_characters += (
1
) # Add 1 for every fighter with 0 HP left (defeated)
if defeated_characters == ( if defeated_characters == (
len(self.db.fighters) - 1 len(self.db.fighters) - 1
): # If only one character isn't defeated ): # If only one character isn't defeated
for fighter in self.db.fighters: for fighter in self.db.fighters:
if fighter.db.HP != 0: if fighter.db.HP != 0:
LastStanding = fighter # Pick the one fighter left with HP remaining LastStanding = (
fighter
) # Pick the one fighter left with HP remaining
self.obj.msg_contents("Only %s remains! Combat is over!" % LastStanding) self.obj.msg_contents("Only %s remains! Combat is over!" % LastStanding)
self.stop() # Stop this script and end combat. self.stop() # Stop this script and end combat.
return return
@ -780,13 +810,17 @@ class TBItemsTurnHandler(DefaultScript):
currentchar = self.db.fighters[self.db.turn] currentchar = self.db.fighters[self.db.turn]
self.db.turn += 1 # Go to the next in the turn order. self.db.turn += 1 # Go to the next in the turn order.
if self.db.turn > len(self.db.fighters) - 1: if self.db.turn > len(self.db.fighters) - 1:
self.db.turn = 0 # Go back to the first in the turn order once you reach the end. self.db.turn = (
0
) # Go back to the first in the turn order once you reach the end.
newchar = self.db.fighters[self.db.turn] # Note the new character newchar = self.db.fighters[self.db.turn] # Note the new character
self.db.timer = TURN_TIMEOUT + self.time_until_next_repeat() # Reset the timer. self.db.timer = TURN_TIMEOUT + self.time_until_next_repeat() # Reset the timer.
self.db.timeout_warning_given = False # Reset the timeout warning. self.db.timeout_warning_given = False # Reset the timeout warning.
self.obj.msg_contents("%s's turn ends - %s's turn begins!" % (currentchar, newchar)) self.obj.msg_contents(
"%s's turn ends - %s's turn begins!" % (currentchar, newchar)
)
self.start_turn(newchar) # Start the new character's turn. self.start_turn(newchar) # Start the new character's turn.
# Count down condition timers. # Count down condition timers.
@ -854,7 +888,9 @@ class CmdFight(Command):
if is_in_combat(self.caller): # Already in a fight if is_in_combat(self.caller): # Already in a fight
self.caller.msg("You're already in a fight!") self.caller.msg("You're already in a fight!")
return return
for thing in here.contents: # Test everything in the room to add it to the fight. for (
thing
) in here.contents: # Test everything in the room to add it to the fight.
if thing.db.HP: # If the object has HP... if thing.db.HP: # If the object has HP...
fighters.append(thing) # ...then add it to the fight. fighters.append(thing) # ...then add it to the fight.
if len(fighters) <= 1: # If you're the only able fighter in the room if len(fighters) <= 1: # If you're the only able fighter in the room
@ -953,7 +989,9 @@ class CmdPass(Command):
self.caller.location.msg_contents( self.caller.location.msg_contents(
"%s takes no further action, passing the turn." % self.caller "%s takes no further action, passing the turn." % self.caller
) )
spend_action(self.caller, "all", action_name="pass") # Spend all remaining actions. spend_action(
self.caller, "all", action_name="pass"
) # Spend all remaining actions.
class CmdDisengage(Command): class CmdDisengage(Command):
@ -984,8 +1022,12 @@ class CmdDisengage(Command):
self.caller.msg("You can only do that on your turn.") self.caller.msg("You can only do that on your turn.")
return return
self.caller.location.msg_contents("%s disengages, ready to stop fighting." % self.caller) self.caller.location.msg_contents(
spend_action(self.caller, "all", action_name="disengage") # Spend all remaining actions. "%s disengages, ready to stop fighting." % self.caller
)
spend_action(
self.caller, "all", action_name="disengage"
) # Spend all remaining actions.
""" """
The action_name kwarg sets the character's last action to "disengage", which is checked by The action_name kwarg sets the character's last action to "disengage", which is checked by
the turn handler script to see if all fighters have disengaged. the turn handler script to see if all fighters have disengaged.
@ -1037,7 +1079,9 @@ class CmdCombatHelp(CmdHelp):
# tips on combat when used in a fight with no arguments. # tips on combat when used in a fight with no arguments.
def func(self): def func(self):
if is_in_combat(self.caller) and not self.args: # In combat and entered 'help' alone if (
is_in_combat(self.caller) and not self.args
): # In combat and entered 'help' alone
self.caller.msg( self.caller.msg(
"Available combat commands:|/" "Available combat commands:|/"
+ "|wAttack:|n Attack a target, attempting to deal damage.|/" + "|wAttack:|n Attack a target, attempting to deal damage.|/"
@ -1175,7 +1219,9 @@ def itemfunc_heal(item, user, target, **kwargs):
to_heal = target.db.max_hp - target.db.hp # Cap healing to max HP to_heal = target.db.max_hp - target.db.hp # Cap healing to max HP
target.db.hp += to_heal target.db.hp += to_heal
user.location.msg_contents("%s uses %s! %s regains %i HP!" % (user, item, target, to_heal)) user.location.msg_contents(
"%s uses %s! %s regains %i HP!" % (user, item, target, to_heal)
)
def itemfunc_add_condition(item, user, target, **kwargs): def itemfunc_add_condition(item, user, target, **kwargs):
@ -1235,7 +1281,10 @@ def itemfunc_cure_condition(item, user, target, **kwargs):
for key in target.db.conditions: for key in target.db.conditions:
if key in to_cure: if key in to_cure:
# If condition specified in to_cure, remove it. # If condition specified in to_cure, remove it.
item_msg += "%s no longer has the '%s' condition. " % (str(target), str(key)) item_msg += "%s no longer has the '%s' condition. " % (
str(target),
str(key),
)
del target.db.conditions[key] del target.db.conditions[key]
user.location.msg_contents(item_msg) user.location.msg_contents(item_msg)
@ -1261,7 +1310,9 @@ def itemfunc_attack(item, user, target, **kwargs):
return False # Returning false aborts the item use return False # Returning false aborts the item use
if not target: if not target:
user.msg("You have to specify a target to use %s! (use <item> = <target>)" % item) user.msg(
"You have to specify a target to use %s! (use <item> = <target>)" % item
)
return False return False
if target == user: if target == user:
@ -1445,7 +1496,9 @@ AMULET_OF_MIGHT = {
"desc": "The one who holds this amulet can call upon its power to gain great strength.", "desc": "The one who holds this amulet can call upon its power to gain great strength.",
"item_func": "add_condition", "item_func": "add_condition",
"item_selfonly": True, "item_selfonly": True,
"item_kwargs": {"conditions": [("Damage Up", 3), ("Accuracy Up", 3), ("Defense Up", 3)]}, "item_kwargs": {
"conditions": [("Damage Up", 3), ("Accuracy Up", 3), ("Defense Up", 3)]
},
} }
AMULET_OF_WEAKNESS = { AMULET_OF_WEAKNESS = {
@ -1453,5 +1506,7 @@ AMULET_OF_WEAKNESS = {
"desc": "The one who holds this amulet can call upon its power to gain great weakness. It's not a terribly useful artifact.", "desc": "The one who holds this amulet can call upon its power to gain great weakness. It's not a terribly useful artifact.",
"item_func": "add_condition", "item_func": "add_condition",
"item_selfonly": True, "item_selfonly": True,
"item_kwargs": {"conditions": [("Damage Down", 3), ("Accuracy Down", 3), ("Defense Down", 3)]}, "item_kwargs": {
"conditions": [("Damage Down", 3), ("Accuracy Down", 3), ("Defense Down", 3)]
},
} }

View file

@ -61,7 +61,13 @@ in your game and using it as-is.
""" """
from random import randint from random import randint
from evennia import DefaultCharacter, Command, default_cmds, DefaultScript, create_object from evennia import (
DefaultCharacter,
Command,
default_cmds,
DefaultScript,
create_object,
)
from evennia.commands.default.muxcommand import MuxCommand from evennia.commands.default.muxcommand import MuxCommand
from evennia.commands.default.help import CmdHelp from evennia.commands.default.help import CmdHelp
@ -312,7 +318,9 @@ def spend_action(character, actions, action_name=None):
character.db.combat_actionsleft -= actions # Use up actions. character.db.combat_actionsleft -= actions # Use up actions.
if character.db.combat_actionsleft < 0: if character.db.combat_actionsleft < 0:
character.db.combat_actionsleft = 0 # Can't have fewer than 0 actions character.db.combat_actionsleft = 0 # Can't have fewer than 0 actions
character.db.combat_turnhandler.turn_end_check(character) # Signal potential end of turn. character.db.combat_turnhandler.turn_end_check(
character
) # Signal potential end of turn.
""" """
@ -417,7 +425,9 @@ class TBMagicTurnHandler(DefaultScript):
self.db.fighters = ordered_by_roll self.db.fighters = ordered_by_roll
# Announce the turn order. # Announce the turn order.
self.obj.msg_contents("Turn order is: %s " % ", ".join(obj.key for obj in self.db.fighters)) self.obj.msg_contents(
"Turn order is: %s " % ", ".join(obj.key for obj in self.db.fighters)
)
# Start first fighter's turn. # Start first fighter's turn.
self.start_turn(self.db.fighters[0]) self.start_turn(self.db.fighters[0])
@ -432,7 +442,9 @@ class TBMagicTurnHandler(DefaultScript):
""" """
for fighter in self.db.fighters: for fighter in self.db.fighters:
combat_cleanup(fighter) # Clean up the combat attributes for every fighter. combat_cleanup(fighter) # Clean up the combat attributes for every fighter.
self.obj.db.combat_turnhandler = None # Remove reference to turn handler in location self.obj.db.combat_turnhandler = (
None
) # Remove reference to turn handler in location
def at_repeat(self): def at_repeat(self):
""" """
@ -450,7 +462,9 @@ class TBMagicTurnHandler(DefaultScript):
currentchar, "all", action_name="disengage" currentchar, "all", action_name="disengage"
) # Spend all remaining actions. ) # Spend all remaining actions.
return return
elif self.db.timer <= 10 and not self.db.timeout_warning_given: # 10 seconds left elif (
self.db.timer <= 10 and not self.db.timeout_warning_given
): # 10 seconds left
# Warn the current character if they're about to time out. # Warn the current character if they're about to time out.
currentchar.msg("WARNING: About to time out!") currentchar.msg("WARNING: About to time out!")
self.db.timeout_warning_given = True self.db.timeout_warning_given = True
@ -462,7 +476,9 @@ class TBMagicTurnHandler(DefaultScript):
Args: Args:
character (obj): Character to initialize for combat. character (obj): Character to initialize for combat.
""" """
combat_cleanup(character) # Clean up leftover combat attributes beforehand, just in case. combat_cleanup(
character
) # Clean up leftover combat attributes beforehand, just in case.
character.db.combat_actionsleft = ( character.db.combat_actionsleft = (
0 0
) # Actions remaining - start of turn adds to this, turn ends when it reaches 0 ) # Actions remaining - start of turn adds to this, turn ends when it reaches 0
@ -511,13 +527,17 @@ class TBMagicTurnHandler(DefaultScript):
defeated_characters = 0 defeated_characters = 0
for fighter in self.db.fighters: for fighter in self.db.fighters:
if fighter.db.HP == 0: if fighter.db.HP == 0:
defeated_characters += 1 # Add 1 for every fighter with 0 HP left (defeated) defeated_characters += (
1
) # Add 1 for every fighter with 0 HP left (defeated)
if defeated_characters == ( if defeated_characters == (
len(self.db.fighters) - 1 len(self.db.fighters) - 1
): # If only one character isn't defeated ): # If only one character isn't defeated
for fighter in self.db.fighters: for fighter in self.db.fighters:
if fighter.db.HP != 0: if fighter.db.HP != 0:
LastStanding = fighter # Pick the one fighter left with HP remaining LastStanding = (
fighter
) # Pick the one fighter left with HP remaining
self.obj.msg_contents("Only %s remains! Combat is over!" % LastStanding) self.obj.msg_contents("Only %s remains! Combat is over!" % LastStanding)
self.stop() # Stop this script and end combat. self.stop() # Stop this script and end combat.
return return
@ -526,11 +546,15 @@ class TBMagicTurnHandler(DefaultScript):
currentchar = self.db.fighters[self.db.turn] currentchar = self.db.fighters[self.db.turn]
self.db.turn += 1 # Go to the next in the turn order. self.db.turn += 1 # Go to the next in the turn order.
if self.db.turn > len(self.db.fighters) - 1: if self.db.turn > len(self.db.fighters) - 1:
self.db.turn = 0 # Go back to the first in the turn order once you reach the end. self.db.turn = (
0
) # Go back to the first in the turn order once you reach the end.
newchar = self.db.fighters[self.db.turn] # Note the new character newchar = self.db.fighters[self.db.turn] # Note the new character
self.db.timer = TURN_TIMEOUT + self.time_until_next_repeat() # Reset the timer. self.db.timer = TURN_TIMEOUT + self.time_until_next_repeat() # Reset the timer.
self.db.timeout_warning_given = False # Reset the timeout warning. self.db.timeout_warning_given = False # Reset the timeout warning.
self.obj.msg_contents("%s's turn ends - %s's turn begins!" % (currentchar, newchar)) self.obj.msg_contents(
"%s's turn ends - %s's turn begins!" % (currentchar, newchar)
)
self.start_turn(newchar) # Start the new character's turn. self.start_turn(newchar) # Start the new character's turn.
def turn_end_check(self, character): def turn_end_check(self, character):
@ -594,7 +618,9 @@ class CmdFight(Command):
if is_in_combat(self.caller): # Already in a fight if is_in_combat(self.caller): # Already in a fight
self.caller.msg("You're already in a fight!") self.caller.msg("You're already in a fight!")
return return
for thing in here.contents: # Test everything in the room to add it to the fight. for (
thing
) in here.contents: # Test everything in the room to add it to the fight.
if thing.db.HP: # If the object has HP... if thing.db.HP: # If the object has HP...
fighters.append(thing) # ...then add it to the fight. fighters.append(thing) # ...then add it to the fight.
if len(fighters) <= 1: # If you're the only able fighter in the room if len(fighters) <= 1: # If you're the only able fighter in the room
@ -689,7 +715,9 @@ class CmdPass(Command):
self.caller.location.msg_contents( self.caller.location.msg_contents(
"%s takes no further action, passing the turn." % self.caller "%s takes no further action, passing the turn." % self.caller
) )
spend_action(self.caller, "all", action_name="pass") # Spend all remaining actions. spend_action(
self.caller, "all", action_name="pass"
) # Spend all remaining actions.
class CmdDisengage(Command): class CmdDisengage(Command):
@ -720,8 +748,12 @@ class CmdDisengage(Command):
self.caller.msg("You can only do that on your turn.") self.caller.msg("You can only do that on your turn.")
return return
self.caller.location.msg_contents("%s disengages, ready to stop fighting." % self.caller) self.caller.location.msg_contents(
spend_action(self.caller, "all", action_name="disengage") # Spend all remaining actions. "%s disengages, ready to stop fighting." % self.caller
)
spend_action(
self.caller, "all", action_name="disengage"
) # Spend all remaining actions.
""" """
The action_name kwarg sets the character's last action to "disengage", which is checked by The action_name kwarg sets the character's last action to "disengage", which is checked by
the turn handler script to see if all fighters have disengaged. the turn handler script to see if all fighters have disengaged.
@ -786,11 +818,17 @@ class CmdLearnSpell(Command):
if len(spell_to_learn) == 1: # If one match, extract the string if len(spell_to_learn) == 1: # If one match, extract the string
spell_to_learn = spell_to_learn[0] spell_to_learn = spell_to_learn[0]
if spell_to_learn not in self.caller.db.spells_known: # If the spell isn't known... if (
caller.db.spells_known.append(spell_to_learn) # ...then add the spell to the character spell_to_learn not in self.caller.db.spells_known
): # If the spell isn't known...
caller.db.spells_known.append(
spell_to_learn
) # ...then add the spell to the character
caller.msg("You learn the spell '%s'!" % spell_to_learn) caller.msg("You learn the spell '%s'!" % spell_to_learn)
return return
if spell_to_learn in self.caller.db.spells_known: # Already has the spell specified if (
spell_to_learn in self.caller.db.spells_known
): # Already has the spell specified
caller.msg("You already know the spell '%s'!" % spell_to_learn) caller.msg("You already know the spell '%s'!" % spell_to_learn)
""" """
You will almost definitely want to replace this with your own system You will almost definitely want to replace this with your own system
@ -908,7 +946,9 @@ class CmdCast(MuxCommand):
# If not in combat and the spell isn't a non-combat spell, error ms and return. # If not in combat and the spell isn't a non-combat spell, error ms and return.
if spelldata["noncombat_spell"] == False and is_in_combat(caller) == False: if spelldata["noncombat_spell"] == False and is_in_combat(caller) == False:
caller.msg("You can't use the spell '%s' outside of combat." % spell_to_cast) caller.msg(
"You can't use the spell '%s' outside of combat." % spell_to_cast
)
return return
# If spell takes no targets and one is given, give error message and return # If spell takes no targets and one is given, give error message and return
@ -1014,7 +1054,9 @@ class CmdRest(Command):
self.caller.db.hp = self.caller.db.max_hp # Set current HP to maximum self.caller.db.hp = self.caller.db.max_hp # Set current HP to maximum
self.caller.db.mp = self.caller.db.max_mp # Set current MP to maximum self.caller.db.mp = self.caller.db.max_mp # Set current MP to maximum
self.caller.location.msg_contents("%s rests to recover HP and MP." % self.caller) self.caller.location.msg_contents(
"%s rests to recover HP and MP." % self.caller
)
# You'll probably want to replace this with your own system for recovering HP and MP. # You'll probably want to replace this with your own system for recovering HP and MP.
@ -1066,7 +1108,9 @@ class CmdCombatHelp(CmdHelp):
# tips on combat when used in a fight with no arguments. # tips on combat when used in a fight with no arguments.
def func(self): def func(self):
if is_in_combat(self.caller) and not self.args: # In combat and entered 'help' alone if (
is_in_combat(self.caller) and not self.args
): # In combat and entered 'help' alone
self.caller.msg( self.caller.msg(
"Available combat commands:|/" "Available combat commands:|/"
+ "|wAttack:|n Attack a target, attempting to deal damage.|/" + "|wAttack:|n Attack a target, attempting to deal damage.|/"

View file

@ -101,7 +101,13 @@ in your game and using it as-is.
""" """
from random import randint from random import randint
from evennia import DefaultCharacter, DefaultObject, Command, default_cmds, DefaultScript from evennia import (
DefaultCharacter,
DefaultObject,
Command,
default_cmds,
DefaultScript,
)
from evennia.commands.default.help import CmdHelp from evennia.commands.default.help import CmdHelp
""" """
@ -259,7 +265,9 @@ def at_defeat(defeated):
defeated.location.msg_contents("%s has been defeated!" % defeated) defeated.location.msg_contents("%s has been defeated!" % defeated)
def resolve_attack(attacker, defender, attack_type, attack_value=None, defense_value=None): def resolve_attack(
attacker, defender, attack_type, attack_value=None, defense_value=None
):
""" """
Resolves an attack and outputs the result. Resolves an attack and outputs the result.
@ -482,7 +490,9 @@ def spend_action(character, actions, action_name=None):
character.db.combat_actionsleft -= actions # Use up actions. character.db.combat_actionsleft -= actions # Use up actions.
if character.db.combat_actionsleft < 0: if character.db.combat_actionsleft < 0:
character.db.combat_actionsleft = 0 # Can't have fewer than 0 actions character.db.combat_actionsleft = 0 # Can't have fewer than 0 actions
character.db.combat_turnhandler.turn_end_check(character) # Signal potential end of turn. character.db.combat_turnhandler.turn_end_check(
character
) # Signal potential end of turn.
def combat_status_message(fighter): def combat_status_message(fighter):
@ -515,7 +525,9 @@ def combat_status_message(fighter):
range_obj.append(thing) range_obj.append(thing)
if engaged_obj: if engaged_obj:
status_msg += "|/Engaged targets: %s" % ", ".join(obj.key for obj in engaged_obj) status_msg += "|/Engaged targets: %s" % ", ".join(
obj.key for obj in engaged_obj
)
if reach_obj: if reach_obj:
status_msg += "|/Reach targets: %s" % ", ".join(obj.key for obj in reach_obj) status_msg += "|/Reach targets: %s" % ", ".join(obj.key for obj in reach_obj)
if range_obj: if range_obj:
@ -574,7 +586,9 @@ class TBRangeTurnHandler(DefaultScript):
self.db.fighters = ordered_by_roll self.db.fighters = ordered_by_roll
# Announce the turn order. # Announce the turn order.
self.obj.msg_contents("Turn order is: %s " % ", ".join(obj.key for obj in self.db.fighters)) self.obj.msg_contents(
"Turn order is: %s " % ", ".join(obj.key for obj in self.db.fighters)
)
# Start first fighter's turn. # Start first fighter's turn.
self.start_turn(self.db.fighters[0]) self.start_turn(self.db.fighters[0])
@ -588,8 +602,12 @@ class TBRangeTurnHandler(DefaultScript):
Called at script termination. Called at script termination.
""" """
for thing in self.obj.contents: for thing in self.obj.contents:
combat_cleanup(thing) # Clean up the combat attributes for every object in the room. combat_cleanup(
self.obj.db.combat_turnhandler = None # Remove reference to turn handler in location thing
) # Clean up the combat attributes for every object in the room.
self.obj.db.combat_turnhandler = (
None
) # Remove reference to turn handler in location
def at_repeat(self): def at_repeat(self):
""" """
@ -607,7 +625,9 @@ class TBRangeTurnHandler(DefaultScript):
currentchar, "all", action_name="disengage" currentchar, "all", action_name="disengage"
) # Spend all remaining actions. ) # Spend all remaining actions.
return return
elif self.db.timer <= 10 and not self.db.timeout_warning_given: # 10 seconds left elif (
self.db.timer <= 10 and not self.db.timeout_warning_given
): # 10 seconds left
# Warn the current character if they're about to time out. # Warn the current character if they're about to time out.
currentchar.msg("WARNING: About to time out!") currentchar.msg("WARNING: About to time out!")
self.db.timeout_warning_given = True self.db.timeout_warning_given = True
@ -672,7 +692,9 @@ class TBRangeTurnHandler(DefaultScript):
Args: Args:
character (obj): Character to initialize for combat. character (obj): Character to initialize for combat.
""" """
combat_cleanup(character) # Clean up leftover combat attributes beforehand, just in case. combat_cleanup(
character
) # Clean up leftover combat attributes beforehand, just in case.
character.db.combat_actionsleft = ( character.db.combat_actionsleft = (
0 0
) # Actions remaining - start of turn adds to this, turn ends when it reaches 0 ) # Actions remaining - start of turn adds to this, turn ends when it reaches 0
@ -720,13 +742,17 @@ class TBRangeTurnHandler(DefaultScript):
defeated_characters = 0 defeated_characters = 0
for fighter in self.db.fighters: for fighter in self.db.fighters:
if fighter.db.HP == 0: if fighter.db.HP == 0:
defeated_characters += 1 # Add 1 for every fighter with 0 HP left (defeated) defeated_characters += (
1
) # Add 1 for every fighter with 0 HP left (defeated)
if defeated_characters == ( if defeated_characters == (
len(self.db.fighters) - 1 len(self.db.fighters) - 1
): # If only one character isn't defeated ): # If only one character isn't defeated
for fighter in self.db.fighters: for fighter in self.db.fighters:
if fighter.db.HP != 0: if fighter.db.HP != 0:
LastStanding = fighter # Pick the one fighter left with HP remaining LastStanding = (
fighter
) # Pick the one fighter left with HP remaining
self.obj.msg_contents("Only %s remains! Combat is over!" % LastStanding) self.obj.msg_contents("Only %s remains! Combat is over!" % LastStanding)
self.stop() # Stop this script and end combat. self.stop() # Stop this script and end combat.
return return
@ -735,11 +761,15 @@ class TBRangeTurnHandler(DefaultScript):
currentchar = self.db.fighters[self.db.turn] currentchar = self.db.fighters[self.db.turn]
self.db.turn += 1 # Go to the next in the turn order. self.db.turn += 1 # Go to the next in the turn order.
if self.db.turn > len(self.db.fighters) - 1: if self.db.turn > len(self.db.fighters) - 1:
self.db.turn = 0 # Go back to the first in the turn order once you reach the end. self.db.turn = (
0
) # Go back to the first in the turn order once you reach the end.
newchar = self.db.fighters[self.db.turn] # Note the new character newchar = self.db.fighters[self.db.turn] # Note the new character
self.db.timer = TURN_TIMEOUT + self.time_until_next_repeat() # Reset the timer. self.db.timer = TURN_TIMEOUT + self.time_until_next_repeat() # Reset the timer.
self.db.timeout_warning_given = False # Reset the timeout warning. self.db.timeout_warning_given = False # Reset the timeout warning.
self.obj.msg_contents("%s's turn ends - %s's turn begins!" % (currentchar, newchar)) self.obj.msg_contents(
"%s's turn ends - %s's turn begins!" % (currentchar, newchar)
)
self.start_turn(newchar) # Start the new character's turn. self.start_turn(newchar) # Start the new character's turn.
def turn_end_check(self, character): def turn_end_check(self, character):
@ -876,7 +906,9 @@ class TBRangeObject(DefaultObject):
if dropper.location.db.combat_turnhandler: if dropper.location.db.combat_turnhandler:
# Object joins the range field # Object joins the range field
self.db.combat_range = {} self.db.combat_range = {}
dropper.location.db.combat_turnhandler.join_rangefield(self, anchor_obj=dropper) dropper.location.db.combat_turnhandler.join_rangefield(
self, anchor_obj=dropper
)
def at_before_get(self, getter): def at_before_get(self, getter):
""" """
@ -958,7 +990,8 @@ class TBRangeObject(DefaultObject):
return False return False
if get_range(giver, getter) > 0: # Too far away from target if get_range(giver, getter) > 0: # Too far away from target
giver.msg( giver.msg(
"You aren't close enough to give things to %s! (see: help approach)" % getter "You aren't close enough to give things to %s! (see: help approach)"
% getter
) )
return False return False
return True return True
@ -1019,7 +1052,9 @@ class CmdFight(Command):
if is_in_combat(self.caller): # Already in a fight if is_in_combat(self.caller): # Already in a fight
self.caller.msg("You're already in a fight!") self.caller.msg("You're already in a fight!")
return return
for thing in here.contents: # Test everything in the room to add it to the fight. for (
thing
) in here.contents: # Test everything in the room to add it to the fight.
if thing.db.HP: # If the object has HP... if thing.db.HP: # If the object has HP...
fighters.append(thing) # ...then add it to the fight. fighters.append(thing) # ...then add it to the fight.
if len(fighters) <= 1: # If you're the only able fighter in the room if len(fighters) <= 1: # If you're the only able fighter in the room
@ -1144,7 +1179,11 @@ class CmdShoot(Command):
in_melee = [] in_melee = []
for target in attacker.db.combat_range: for target in attacker.db.combat_range:
# Object is engaged and has HP # Object is engaged and has HP
if get_range(attacker, defender) == 0 and target.db.hp and target != self.caller: if (
get_range(attacker, defender) == 0
and target.db.hp
and target != self.caller
):
in_melee.append(target) # Add to list of targets in melee in_melee.append(target) # Add to list of targets in melee
if len(in_melee) > 0: if len(in_melee) > 0:
@ -1294,7 +1333,9 @@ class CmdPass(Command):
self.caller.location.msg_contents( self.caller.location.msg_contents(
"%s takes no further action, passing the turn." % self.caller "%s takes no further action, passing the turn." % self.caller
) )
spend_action(self.caller, "all", action_name="pass") # Spend all remaining actions. spend_action(
self.caller, "all", action_name="pass"
) # Spend all remaining actions.
class CmdDisengage(Command): class CmdDisengage(Command):
@ -1325,8 +1366,12 @@ class CmdDisengage(Command):
self.caller.msg("You can only do that on your turn.") self.caller.msg("You can only do that on your turn.")
return return
self.caller.location.msg_contents("%s disengages, ready to stop fighting." % self.caller) self.caller.location.msg_contents(
spend_action(self.caller, "all", action_name="disengage") # Spend all remaining actions. "%s disengages, ready to stop fighting." % self.caller
)
spend_action(
self.caller, "all", action_name="disengage"
) # Spend all remaining actions.
""" """
The action_name kwarg sets the character's last action to "disengage", which is checked by The action_name kwarg sets the character's last action to "disengage", which is checked by
the turn handler script to see if all fighters have disengaged. the turn handler script to see if all fighters have disengaged.
@ -1397,7 +1442,9 @@ class CmdCombatHelp(CmdHelp):
# tips on combat when used in a fight with no arguments. # tips on combat when used in a fight with no arguments.
def func(self): def func(self):
if is_in_combat(self.caller) and not self.args: # In combat and entered 'help' alone if (
is_in_combat(self.caller) and not self.args
): # In combat and entered 'help' alone
self.caller.msg( self.caller.msg(
"Available combat commands:|/" "Available combat commands:|/"
+ "|wAttack:|n Attack an engaged target, attempting to deal damage.|/" + "|wAttack:|n Attack an engaged target, attempting to deal damage.|/"

View file

@ -44,9 +44,7 @@ class BodyFunctions(DefaultScript):
elif rand < 0.2: elif rand < 0.2:
string = "You have an itch. Hard to reach too." string = "You have an itch. Hard to reach too."
elif rand < 0.3: elif rand < 0.3:
string = ( string = "You think you hear someone behind you. ... but when you look there's noone there."
"You think you hear someone behind you. ... but when you look there's noone there."
)
elif rand < 0.4: elif rand < 0.4:
string = "You inspect your fingernails. Nothing to report." string = "You inspect your fingernails. Nothing to report."
elif rand < 0.5: elif rand < 0.5:

View file

@ -113,7 +113,9 @@ class CmdSmashGlass(Command):
string = "You smash your hand against the glass" string = "You smash your hand against the glass"
string += " with all your might. The lid won't budge" string += " with all your might. The lid won't budge"
string += " but you cause quite the tremor through the button's mount." string += " but you cause quite the tremor through the button's mount."
string += "\nIt looks like the button's lamp stopped working for the time being." string += (
"\nIt looks like the button's lamp stopped working for the time being."
)
self.obj.lamp_works = False self.obj.lamp_works = False
elif rand < 0.6: elif rand < 0.6:
string = "You hit the lid hard. It doesn't move an inch." string = "You hit the lid hard. It doesn't move an inch."
@ -123,7 +125,8 @@ class CmdSmashGlass(Command):
string += " you should just try to open the lid instead?" string += " you should just try to open the lid instead?"
self.caller.msg(string) self.caller.msg(string)
self.caller.location.msg_contents( self.caller.location.msg_contents(
"%s tries to smash the glass of the button." % (self.caller.name), exclude=self.caller "%s tries to smash the glass of the button." % (self.caller.name),
exclude=self.caller,
) )

View file

@ -121,7 +121,9 @@ class RedButton(DefaultObject):
self.db.lamp_works = False self.db.lamp_works = False
desc = self.db.desc_lamp_broken desc = self.db.desc_lamp_broken
if not desc: if not desc:
self.db.desc += "\nThe big red button has stopped blinking for the time being." self.db.desc += (
"\nThe big red button has stopped blinking for the time being."
)
else: else:
self.db.desc = desc self.db.desc = desc

View file

@ -142,7 +142,8 @@ class BlindedState(DefaultScript):
""" """
self.obj.msg("You blink feverishly as your eyesight slowly returns.") self.obj.msg("You blink feverishly as your eyesight slowly returns.")
self.obj.location.msg_contents( self.obj.location.msg_contents(
"%s seems to be recovering their eyesight." % self.obj.name, exclude=self.obj "%s seems to be recovering their eyesight." % self.obj.name,
exclude=self.obj,
) )
self.obj.cmdset.delete() # this will clear the latest added cmdset, self.obj.cmdset.delete() # this will clear the latest added cmdset,
# (which is the blinded one). # (which is the blinded one).

Some files were not shown because too many files have changed in this diff Show more