New list_node decorator for evmenu. Tested with olc menu
This commit is contained in:
parent
3c5d00ac3d
commit
34b8c0dbce
4 changed files with 152 additions and 66 deletions
|
|
@ -15,7 +15,8 @@ from evennia.utils.eveditor import EvEditor
|
||||||
from evennia.utils.evmore import EvMore
|
from evennia.utils.evmore import EvMore
|
||||||
from evennia.utils.spawner import (spawn, search_prototype, list_prototypes,
|
from evennia.utils.spawner import (spawn, search_prototype, list_prototypes,
|
||||||
save_db_prototype, build_metaproto, validate_prototype,
|
save_db_prototype, build_metaproto, validate_prototype,
|
||||||
delete_db_prototype, PermissionError, start_olc)
|
delete_db_prototype, PermissionError, start_olc,
|
||||||
|
metaproto_to_str)
|
||||||
from evennia.utils.ansi import raw
|
from evennia.utils.ansi import raw
|
||||||
|
|
||||||
COMMAND_DEFAULT_CLASS = class_from_module(settings.COMMAND_DEFAULT_CLASS)
|
COMMAND_DEFAULT_CLASS = class_from_module(settings.COMMAND_DEFAULT_CLASS)
|
||||||
|
|
@ -2886,21 +2887,10 @@ class CmdSpawn(COMMAND_DEFAULT_CLASS):
|
||||||
|
|
||||||
def _search_show_prototype(query, metaprots=None):
|
def _search_show_prototype(query, metaprots=None):
|
||||||
# prototype detail
|
# prototype detail
|
||||||
strings = []
|
|
||||||
if not metaprots:
|
if not metaprots:
|
||||||
metaprots = search_prototype(key=query, return_meta=True)
|
metaprots = search_prototype(key=query, return_meta=True)
|
||||||
if metaprots:
|
if metaprots:
|
||||||
for metaprot in metaprots:
|
return "\n".join(metaproto_to_str(metaprot) for metaprot in metaprots)
|
||||||
header = (
|
|
||||||
"|cprototype key:|n {}, |ctags:|n {}, |clocks:|n {} \n"
|
|
||||||
"|cdesc:|n {} \n|cprototype:|n ".format(
|
|
||||||
metaprot.key, ", ".join(metaprot.tags),
|
|
||||||
metaprot.locks, metaprot.desc))
|
|
||||||
prototype = ("{{\n {} \n}}".format("\n ".join("{!r}: {!r},".format(key, value)
|
|
||||||
for key, value in
|
|
||||||
sorted(metaprot.prototype.items())).rstrip(",")))
|
|
||||||
strings.append(header + prototype)
|
|
||||||
return "\n".join(strings)
|
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -979,18 +979,20 @@ class EvMenu(object):
|
||||||
#
|
#
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
def list_node(option_list, examine_processor, goto_processor, pagesize=10):
|
def list_node(option_generator, examine_processor, goto_processor, pagesize=10):
|
||||||
"""
|
"""
|
||||||
Decorator for making an EvMenu node into a multi-page list node. Will add new options,
|
Decorator for making an EvMenu node into a multi-page list node. Will add new options,
|
||||||
prepending those options added in the node.
|
prepending those options added in the node.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
option_list (list): List of strings indicating the options.
|
option_generator (callable or list): A list of strings indicating the options, or a callable
|
||||||
examine_processor (callable): Will be called with the caller and the chosen option when
|
that is called without any arguments to produce such a list.
|
||||||
examining said option. Should return a text string to display in the node.
|
examine_processor (callable, optional): Will be called with the caller and the chosen option
|
||||||
goto_processor (callable): Will be called with caller and
|
when examining said option. Should return a text string to display in the node.
|
||||||
the chosen option from the optionlist. Should return the target node to goto after the
|
goto_processor (callable, optional): Will be called as goto_processor(caller, menuchoice)
|
||||||
selection.
|
where menuchoice is the chosen option as a string. Should return the target node to
|
||||||
|
goto after this selection.
|
||||||
|
|
||||||
pagesize (int): How many options to show per page.
|
pagesize (int): How many options to show per page.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
@ -1009,6 +1011,7 @@ def list_node(option_list, examine_processor, goto_processor, pagesize=10):
|
||||||
|
|
||||||
available_choices = kwargs.get("available_choices", [])
|
available_choices = kwargs.get("available_choices", [])
|
||||||
processor = kwargs.get("selection_processor")
|
processor = kwargs.get("selection_processor")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
match_ind = int(re.search(r"[0-9]+$", raw_string).group()) - 1
|
match_ind = int(re.search(r"[0-9]+$", raw_string).group()) - 1
|
||||||
selection = available_choices[match_ind]
|
selection = available_choices[match_ind]
|
||||||
|
|
@ -1022,12 +1025,14 @@ def list_node(option_list, examine_processor, goto_processor, pagesize=10):
|
||||||
logger.log_trace()
|
logger.log_trace()
|
||||||
return selection
|
return selection
|
||||||
|
|
||||||
nall_options = len(option_list)
|
|
||||||
pages = [option_list[ind:ind + pagesize] for ind in range(0, nall_options, pagesize)]
|
|
||||||
npages = len(pages)
|
|
||||||
|
|
||||||
def _list_node(caller, raw_string, **kwargs):
|
def _list_node(caller, raw_string, **kwargs):
|
||||||
|
|
||||||
|
option_list = option_generator() if callable(option_generator) else option_generator
|
||||||
|
|
||||||
|
nall_options = len(option_list)
|
||||||
|
pages = [option_list[ind:ind + pagesize] for ind in range(0, nall_options, pagesize)]
|
||||||
|
npages = len(pages)
|
||||||
|
|
||||||
page_index = max(0, min(npages - 1, kwargs.get("optionpage_index", 0)))
|
page_index = max(0, min(npages - 1, kwargs.get("optionpage_index", 0)))
|
||||||
page = pages[page_index]
|
page = pages[page_index]
|
||||||
|
|
||||||
|
|
@ -1042,19 +1047,21 @@ def list_node(option_list, examine_processor, goto_processor, pagesize=10):
|
||||||
# if the goto callable returns None, the same node is rerun, and
|
# if the goto callable returns None, the same node is rerun, and
|
||||||
# kwargs not used by the callable are passed on to the node. This
|
# kwargs not used by the callable are passed on to the node. This
|
||||||
# allows us to call ourselves over and over, using different kwargs.
|
# allows us to call ourselves over and over, using different kwargs.
|
||||||
if page_index > 0:
|
|
||||||
options.append({"key": ("|wb|Wack|n", "b"),
|
|
||||||
"goto": (lambda caller: None,
|
|
||||||
{"optionpage_index": page_index - 1})})
|
|
||||||
if page_index < npages - 1:
|
|
||||||
options.append({"key": ("|wn|Wext|n", "n"),
|
|
||||||
"goto": (lambda caller: None,
|
|
||||||
{"optionpage_index": page_index + 1})})
|
|
||||||
|
|
||||||
options.append({"key": ("|Wcurrent|n", "c"),
|
options.append({"key": ("|Wcurrent|n", "c"),
|
||||||
"desc": "|W({}/{})|n".format(page_index + 1, npages),
|
"desc": "|W({}/{})|n".format(page_index + 1, npages),
|
||||||
"goto": (lambda caller: None,
|
"goto": (lambda caller: None,
|
||||||
{"optionpage_index": page_index})})
|
{"optionpage_index": page_index})})
|
||||||
|
if page_index > 0:
|
||||||
|
options.append({"key": ("|wp|Wrevious page|n", "p"),
|
||||||
|
"goto": (lambda caller: None,
|
||||||
|
{"optionpage_index": page_index - 1})})
|
||||||
|
if page_index < npages - 1:
|
||||||
|
options.append({"key": ("|wn|Wext page|n", "n"),
|
||||||
|
"goto": (lambda caller: None,
|
||||||
|
{"optionpage_index": page_index + 1})})
|
||||||
|
|
||||||
|
|
||||||
|
# this catches arbitrary input, notably to examine entries ('look 4' or 'l4' etc)
|
||||||
options.append({"key": "_default",
|
options.append({"key": "_default",
|
||||||
"goto": (lambda caller: None,
|
"goto": (lambda caller: None,
|
||||||
{"show_detail": True, "optionpage_index": page_index})})
|
{"show_detail": True, "optionpage_index": page_index})})
|
||||||
|
|
@ -1071,6 +1078,7 @@ def list_node(option_list, examine_processor, goto_processor, pagesize=10):
|
||||||
# add data from the decorated node
|
# add data from the decorated node
|
||||||
|
|
||||||
text = ''
|
text = ''
|
||||||
|
extra_options = []
|
||||||
try:
|
try:
|
||||||
text, extra_options = func(caller, raw_string)
|
text, extra_options = func(caller, raw_string)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
|
|
@ -1080,14 +1088,16 @@ def list_node(option_list, examine_processor, goto_processor, pagesize=10):
|
||||||
raise
|
raise
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.log_trace()
|
logger.log_trace()
|
||||||
|
print("extra_options:", extra_options)
|
||||||
else:
|
else:
|
||||||
if isinstance(extra_options, {}):
|
if isinstance(extra_options, {}):
|
||||||
extra_options = [extra_options]
|
extra_options = [extra_options]
|
||||||
else:
|
else:
|
||||||
extra_options = make_iter(extra_options)
|
extra_options = make_iter(extra_options)
|
||||||
options.append(extra_options)
|
|
||||||
|
|
||||||
|
options.extend(extra_options)
|
||||||
text = text + "\n\n" + text_detail if text_detail else text
|
text = text + "\n\n" + text_detail if text_detail else text
|
||||||
|
text += "\n\n(Make a choice or enter 'look <num>' to examine an option closer)"
|
||||||
|
|
||||||
return text, options
|
return text, options
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -333,7 +333,7 @@ def search_module_prototype(key=None, tags=None):
|
||||||
|
|
||||||
def search_prototype(key=None, tags=None, return_meta=True):
|
def search_prototype(key=None, tags=None, return_meta=True):
|
||||||
"""
|
"""
|
||||||
Find prototypes based on key and/or tags.
|
Find prototypes based on key and/or tags, or all prototypes.
|
||||||
|
|
||||||
Kwargs:
|
Kwargs:
|
||||||
key (str): An exact or partial key to query for.
|
key (str): An exact or partial key to query for.
|
||||||
|
|
@ -344,7 +344,8 @@ def search_prototype(key=None, tags=None, return_meta=True):
|
||||||
return MetaProto namedtuples including prototype meta info
|
return MetaProto namedtuples including prototype meta info
|
||||||
|
|
||||||
Return:
|
Return:
|
||||||
matches (list): All found prototype dicts or MetaProtos
|
matches (list): All found prototype dicts or MetaProtos. If no keys
|
||||||
|
or tags are given, all available prototypes/MetaProtos will be returned.
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
The available prototypes is a combination of those supplied in
|
The available prototypes is a combination of those supplied in
|
||||||
|
|
@ -438,6 +439,25 @@ def list_prototypes(caller, key=None, tags=None, show_non_use=False, show_non_ed
|
||||||
table.reformat_column(3, width=20)
|
table.reformat_column(3, width=20)
|
||||||
return table
|
return table
|
||||||
|
|
||||||
|
|
||||||
|
def metaproto_to_str(metaproto):
|
||||||
|
"""
|
||||||
|
Format a metaproto to a nice string representation.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
metaproto (NamedTuple): Represents the prototype.
|
||||||
|
"""
|
||||||
|
header = (
|
||||||
|
"|cprototype key:|n {}, |ctags:|n {}, |clocks:|n {} \n"
|
||||||
|
"|cdesc:|n {} \n|cprototype:|n ".format(
|
||||||
|
metaproto.key, ", ".join(metaproto.tags),
|
||||||
|
metaproto.locks, metaproto.desc))
|
||||||
|
prototype = ("{{\n {} \n}}".format("\n ".join("{!r}: {!r},".format(key, value)
|
||||||
|
for key, value in
|
||||||
|
sorted(metaproto.prototype.items())).rstrip(",")))
|
||||||
|
return header + prototype
|
||||||
|
|
||||||
|
|
||||||
# Spawner mechanism
|
# Spawner mechanism
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -660,7 +680,13 @@ def spawn(*prototypes, **kwargs):
|
||||||
return _batch_create_object(*objsparams)
|
return _batch_create_object(*objsparams)
|
||||||
|
|
||||||
|
|
||||||
# prototype design menu nodes
|
# ------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# OLC Prototype design menu
|
||||||
|
#
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
# Helper functions
|
||||||
|
|
||||||
def _get_menu_metaprot(caller):
|
def _get_menu_metaprot(caller):
|
||||||
if hasattr(caller.ndb._menutree, "olc_metaprot"):
|
if hasattr(caller.ndb._menutree, "olc_metaprot"):
|
||||||
|
|
@ -683,7 +709,7 @@ def _set_menu_metaprot(caller, field, value):
|
||||||
caller.ndb._menutree.olc_metaprot = build_metaproto(**kwargs)
|
caller.ndb._menutree.olc_metaprot = build_metaproto(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def _format_property(key, required=False, metaprot=None, prototype=None):
|
def _format_property(key, required=False, metaprot=None, prototype=None, cropper=None):
|
||||||
key = key.lower()
|
key = key.lower()
|
||||||
if metaprot is not None:
|
if metaprot is not None:
|
||||||
prop = getattr(metaprot, key) or ''
|
prop = getattr(metaprot, key) or ''
|
||||||
|
|
@ -700,7 +726,7 @@ def _format_property(key, required=False, metaprot=None, prototype=None):
|
||||||
out = ", ".join(str(pr) for pr in prop)
|
out = ", ".join(str(pr) for pr in prop)
|
||||||
if not out and required:
|
if not out and required:
|
||||||
out = "|rrequired"
|
out = "|rrequired"
|
||||||
return " ({}|n)".format(crop(out, _MENU_CROP_WIDTH))
|
return " ({}|n)".format(cropper(out) if cropper else crop(out, _MENU_CROP_WIDTH))
|
||||||
|
|
||||||
|
|
||||||
def _set_property(caller, raw_string, **kwargs):
|
def _set_property(caller, raw_string, **kwargs):
|
||||||
|
|
@ -744,26 +770,43 @@ def _set_property(caller, raw_string, **kwargs):
|
||||||
metaprot = _get_menu_metaprot(caller)
|
metaprot = _get_menu_metaprot(caller)
|
||||||
prototype = metaprot.prototype
|
prototype = metaprot.prototype
|
||||||
prototype[propname_low] = value
|
prototype[propname_low] = value
|
||||||
|
|
||||||
|
# typeclass and prototype can't co-exist
|
||||||
|
if propname_low == "typeclass":
|
||||||
|
prototype.pop("prototype", None)
|
||||||
|
if propname_low == "prototype":
|
||||||
|
prototype.pop("typeclass", None)
|
||||||
|
|
||||||
_set_menu_metaprot(caller, "prototype", prototype)
|
_set_menu_metaprot(caller, "prototype", prototype)
|
||||||
|
|
||||||
|
|
||||||
caller.msg("Set {prop} to {value}.".format(
|
caller.msg("Set {prop} to {value}.".format(
|
||||||
prop=prop.replace("_", "-").capitalize(), value=str(value)))
|
prop=prop.replace("_", "-").capitalize(), value=str(value)))
|
||||||
|
|
||||||
return next_node
|
return next_node
|
||||||
|
|
||||||
|
|
||||||
def _wizard_options(prev_node, next_node):
|
def _wizard_options(prev_node, next_node, color="|W"):
|
||||||
options = [{"desc": "forward ({})".format(next_node.replace("_", "-")),
|
options = [{"key": ("|wf|Worward", "f"),
|
||||||
|
"desc": "{color}({node})|n".format(
|
||||||
|
color=color, node=next_node.replace("_", "-")),
|
||||||
"goto": "node_{}".format(next_node)},
|
"goto": "node_{}".format(next_node)},
|
||||||
{"desc": "back ({})".format(prev_node.replace("_", "-")),
|
{"key": ("|wb|Wack", "b"),
|
||||||
|
"desc": "{color}({node})|n".format(
|
||||||
|
color=color, node=prev_node.replace("_", "-")),
|
||||||
"goto": "node_{}".format(prev_node)}]
|
"goto": "node_{}".format(prev_node)}]
|
||||||
if "index" not in (prev_node, next_node):
|
if "index" not in (prev_node, next_node):
|
||||||
options.append({"desc": "index",
|
options.append({"key": ("|wi|Wndex", "i"),
|
||||||
"goto": "node_index"})
|
"goto": "node_index"})
|
||||||
return options
|
return options
|
||||||
|
|
||||||
|
|
||||||
# menu nodes
|
def _path_cropper(pythonpath):
|
||||||
|
"Crop path to only the last component"
|
||||||
|
return pythonpath.split('.')[-1]
|
||||||
|
|
||||||
|
|
||||||
|
# Menu nodes
|
||||||
|
|
||||||
def node_index(caller):
|
def node_index(caller):
|
||||||
metaprot = _get_menu_metaprot(caller)
|
metaprot = _get_menu_metaprot(caller)
|
||||||
|
|
@ -784,15 +827,20 @@ def node_index(caller):
|
||||||
"goto": "node_meta_key"})
|
"goto": "node_meta_key"})
|
||||||
for key in ('Prototype', 'Typeclass', 'Key', 'Aliases', 'Attrs', 'Tags', 'Locks',
|
for key in ('Prototype', 'Typeclass', 'Key', 'Aliases', 'Attrs', 'Tags', 'Locks',
|
||||||
'Permissions', 'Location', 'Home', 'Destination'):
|
'Permissions', 'Location', 'Home', 'Destination'):
|
||||||
req = False
|
required = False
|
||||||
|
cropper = None
|
||||||
if key in ("Prototype", "Typeclass"):
|
if key in ("Prototype", "Typeclass"):
|
||||||
req = "prototype" not in prototype and "typeclass" not in prototype
|
required = "prototype" not in prototype and "typeclass" not in prototype
|
||||||
|
if key == 'Typeclass':
|
||||||
|
cropper = _path_cropper
|
||||||
options.append(
|
options.append(
|
||||||
{"desc": "|w{}|n{}".format(key, _format_property(key, req, None, prototype)),
|
{"desc": "|w{}|n{}".format(
|
||||||
|
key, _format_property(key, required, None, prototype, cropper=cropper)),
|
||||||
"goto": "node_{}".format(key.lower())})
|
"goto": "node_{}".format(key.lower())})
|
||||||
|
required = False
|
||||||
for key in ('Desc', 'Tags', 'Locks'):
|
for key in ('Desc', 'Tags', 'Locks'):
|
||||||
options.append(
|
options.append(
|
||||||
{"desc": "|WMeta-{}|n|n{}".format(key, _format_property(key, req, metaprot, None)),
|
{"desc": "|WMeta-{}|n|n{}".format(key, _format_property(key, required, metaprot, None)),
|
||||||
"goto": "node_meta_{}".format(key.lower())})
|
"goto": "node_meta_{}".format(key.lower())})
|
||||||
|
|
||||||
return text, options
|
return text, options
|
||||||
|
|
@ -837,6 +885,24 @@ def node_meta_key(caller):
|
||||||
return text, options
|
return text, options
|
||||||
|
|
||||||
|
|
||||||
|
def _all_prototypes():
|
||||||
|
return [mproto.key for mproto in search_prototype()]
|
||||||
|
|
||||||
|
|
||||||
|
def _prototype_examine(caller, prototype_name):
|
||||||
|
metaprot = search_prototype(key=prototype_name)
|
||||||
|
if metaprot:
|
||||||
|
return metaproto_to_str(metaprot[0])
|
||||||
|
return "Prototype not registered."
|
||||||
|
|
||||||
|
|
||||||
|
def _prototype_select(caller, prototype):
|
||||||
|
ret = _set_property(caller, prototype, prop="prototype", processor=str, next_node="node_key")
|
||||||
|
caller.msg("Selected prototype |y{}|n. Removed any set typeclass parent.".format(prototype))
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
@list_node(_all_prototypes, _prototype_examine, _prototype_select)
|
||||||
def node_prototype(caller):
|
def node_prototype(caller):
|
||||||
metaprot = _get_menu_metaprot(caller)
|
metaprot = _get_menu_metaprot(caller)
|
||||||
prot = metaprot.prototype
|
prot = metaprot.prototype
|
||||||
|
|
@ -848,25 +914,43 @@ def node_prototype(caller):
|
||||||
else:
|
else:
|
||||||
text.append("Parent prototype is not set")
|
text.append("Parent prototype is not set")
|
||||||
text = "\n\n".join(text)
|
text = "\n\n".join(text)
|
||||||
options = _wizard_options("meta_key", "typeclass")
|
options = _wizard_options("meta_key", "typeclass", color="|W")
|
||||||
options.append({"key": "_default",
|
|
||||||
"goto": (_set_property,
|
|
||||||
dict(prop="prototype",
|
|
||||||
processor=lambda s: s.strip(),
|
|
||||||
next_node="node_typeclass"))})
|
|
||||||
return text, options
|
return text, options
|
||||||
|
|
||||||
|
|
||||||
def _typeclass_examine(caller, typeclass):
|
def _all_typeclasses():
|
||||||
return "This is typeclass |y{}|n.".format(typeclass)
|
return list(sorted(get_all_typeclasses().keys()))
|
||||||
|
# return list(sorted(get_all_typeclasses(parent="evennia.objects.objects.DefaultObject").keys()))
|
||||||
|
|
||||||
|
|
||||||
|
def _typeclass_examine(caller, typeclass_path):
|
||||||
|
if typeclass_path is None:
|
||||||
|
# this means we are exiting the listing
|
||||||
|
return "node_key"
|
||||||
|
|
||||||
|
typeclass = get_all_typeclasses().get(typeclass_path)
|
||||||
|
if typeclass:
|
||||||
|
docstr = []
|
||||||
|
for line in typeclass.__doc__.split("\n"):
|
||||||
|
if line.strip():
|
||||||
|
docstr.append(line)
|
||||||
|
elif docstr:
|
||||||
|
break
|
||||||
|
docstr = '\n'.join(docstr) if docstr else "<empty>"
|
||||||
|
txt = "Typeclass |y{typeclass_path}|n; First paragraph of docstring:\n\n{docstring}".format(
|
||||||
|
typeclass_path=typeclass_path, docstring=docstr)
|
||||||
|
else:
|
||||||
|
txt = "This is typeclass |y{}|n.".format(typeclass)
|
||||||
|
return txt
|
||||||
|
|
||||||
|
|
||||||
def _typeclass_select(caller, typeclass):
|
def _typeclass_select(caller, typeclass):
|
||||||
caller.msg("Selected typeclass |y{}|n.".format(typeclass))
|
ret = _set_property(caller, typeclass, prop='typeclass', processor=str, next_node="node_key")
|
||||||
return None
|
caller.msg("Selected typeclass |y{}|n. Removed any set prototype parent.".format(typeclass))
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
@list_node(list(sorted(get_all_typeclasses().keys())), _typeclass_examine, _typeclass_select)
|
@list_node(_all_typeclasses, _typeclass_examine, _typeclass_select)
|
||||||
def node_typeclass(caller):
|
def node_typeclass(caller):
|
||||||
metaprot = _get_menu_metaprot(caller)
|
metaprot = _get_menu_metaprot(caller)
|
||||||
prot = metaprot.prototype
|
prot = metaprot.prototype
|
||||||
|
|
@ -879,12 +963,7 @@ def node_typeclass(caller):
|
||||||
text.append("Using default typeclass {typeclass}.".format(
|
text.append("Using default typeclass {typeclass}.".format(
|
||||||
typeclass=settings.BASE_OBJECT_TYPECLASS))
|
typeclass=settings.BASE_OBJECT_TYPECLASS))
|
||||||
text = "\n\n".join(text)
|
text = "\n\n".join(text)
|
||||||
options = _wizard_options("prototype", "key")
|
options = _wizard_options("prototype", "key", color="|W")
|
||||||
options.append({"key": "_default",
|
|
||||||
"goto": (_set_property,
|
|
||||||
dict(prop="typeclass",
|
|
||||||
processor=lambda s: s.strip(),
|
|
||||||
next_node="node_key"))})
|
|
||||||
return text, options
|
return text, options
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1882,10 +1882,14 @@ def get_game_dir_path():
|
||||||
raise RuntimeError("server/conf/settings.py not found: Must start from inside game dir.")
|
raise RuntimeError("server/conf/settings.py not found: Must start from inside game dir.")
|
||||||
|
|
||||||
|
|
||||||
def get_all_typeclasses():
|
def get_all_typeclasses(parent=None):
|
||||||
"""
|
"""
|
||||||
List available typeclasses from all available modules.
|
List available typeclasses from all available modules.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
parent (str, optional): If given, only return typeclasses inheriting (at any distance)
|
||||||
|
from this parent.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
typeclasses (dict): On the form {"typeclass.path": typeclass, ...}
|
typeclasses (dict): On the form {"typeclass.path": typeclass, ...}
|
||||||
|
|
||||||
|
|
@ -1898,4 +1902,7 @@ def get_all_typeclasses():
|
||||||
from evennia.typeclasses.models import TypedObject
|
from evennia.typeclasses.models import TypedObject
|
||||||
typeclasses = {"{}.{}".format(model.__module__, model.__name__): model
|
typeclasses = {"{}.{}".format(model.__module__, model.__name__): model
|
||||||
for model in apps.get_models() if TypedObject in getmro(model)}
|
for model in apps.get_models() if TypedObject in getmro(model)}
|
||||||
|
if parent:
|
||||||
|
typeclasses = {name: typeclass for name, typeclass in typeclasses.items()
|
||||||
|
if inherits_from(typeclass, parent)}
|
||||||
return typeclasses
|
return typeclasses
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue