Refactor spawn, update remaining in olc
This commit is contained in:
parent
16640fa923
commit
6126391406
3 changed files with 135 additions and 65 deletions
|
|
@ -1874,10 +1874,25 @@ def node_update_objects(caller, **kwargs):
|
||||||
diff, obj_prototype = spawner.prototype_diff_from_object(prototype, obj)
|
diff, obj_prototype = spawner.prototype_diff_from_object(prototype, obj)
|
||||||
|
|
||||||
text = ["Suggested changes to {} objects. ".format(len(update_objects)),
|
text = ["Suggested changes to {} objects. ".format(len(update_objects)),
|
||||||
"Showing random example obj to change: {name} (#{dbref}))\n".format(obj.key, obj.dbref)]
|
"Showing random example obj to change: {name} ({dbref}))\n".format(
|
||||||
options = []
|
name=obj.key, dbref=obj.dbref)]
|
||||||
|
|
||||||
|
helptext = """
|
||||||
|
Be careful with this operation! The upgrade mechanism will try to automatically estimate
|
||||||
|
what changes need to be applied. But the estimate is |wonly based on the analysis of one
|
||||||
|
randomly selected object|n among all objects spawned by this prototype. If that object
|
||||||
|
happens to be unusual in some way the estimate will be off and may lead to unexpected
|
||||||
|
results for other objects. Always test your objects carefully after an upgrade and
|
||||||
|
consider being conservative (switch to KEEP) or even do the update manually if you are
|
||||||
|
unsure that the results will be acceptable. """
|
||||||
|
|
||||||
|
options = _wizard_options("update_objects", back_node[5:], None)
|
||||||
io = 0
|
io = 0
|
||||||
for (key, inst) in sorted(((key, val) for key, val in diff.items()), key=lambda tup: tup[0]):
|
for (key, inst) in sorted(((key, val) for key, val in diff.items()), key=lambda tup: tup[0]):
|
||||||
|
|
||||||
|
if key in protlib._PROTOTYPE_META_NAMES:
|
||||||
|
continue
|
||||||
|
|
||||||
line = "{iopt} |w{key}|n: {old}{sep}{new} {change}"
|
line = "{iopt} |w{key}|n: {old}{sep}{new} {change}"
|
||||||
old_val = utils.crop(str(obj_prototype[key]), width=20)
|
old_val = utils.crop(str(obj_prototype[key]), width=20)
|
||||||
|
|
||||||
|
|
@ -1907,18 +1922,11 @@ def node_update_objects(caller, **kwargs):
|
||||||
{"key": "|wb|rack ({})".format(back_node[5:], 'b'),
|
{"key": "|wb|rack ({})".format(back_node[5:], 'b'),
|
||||||
"goto": back_node}])
|
"goto": back_node}])
|
||||||
|
|
||||||
helptext = """
|
text = "\n".join(text)
|
||||||
Be careful with this operation! The upgrade mechanism will try to automatically estimate
|
|
||||||
what changes need to be applied. But the estimate is |wonly based on the analysis of one
|
|
||||||
randomly selected object|n among all objects spawned by this prototype. If that object
|
|
||||||
happens to be unusual in some way the estimate will be off and may lead to unexpected
|
|
||||||
results for other objects. Always test your objects carefully after an upgrade and
|
|
||||||
consider being conservative (switch to KEEP) or even do the update manually if you are
|
|
||||||
unsure that the results will be acceptable. """
|
|
||||||
|
|
||||||
text = (text, helptext)
|
text = (text, helptext)
|
||||||
|
|
||||||
return text, options
|
return text, options
|
||||||
|
|
||||||
|
|
||||||
# prototype save node
|
# prototype save node
|
||||||
|
|
@ -1928,7 +1936,8 @@ def node_prototype_save(caller, **kwargs):
|
||||||
"""Save prototype to disk """
|
"""Save prototype to disk """
|
||||||
# these are only set if we selected 'yes' to save on a previous pass
|
# these are only set if we selected 'yes' to save on a previous pass
|
||||||
prototype = kwargs.get("prototype", None)
|
prototype = kwargs.get("prototype", None)
|
||||||
accept_save = kwargs.get("accept_save", False)
|
# set to True/False if answered, None if first pass
|
||||||
|
accept_save = kwargs.get("accept_save", None)
|
||||||
|
|
||||||
if accept_save and prototype:
|
if accept_save and prototype:
|
||||||
# we already validated and accepted the save, so this node acts as a goto callback and
|
# we already validated and accepted the save, so this node acts as a goto callback and
|
||||||
|
|
@ -1939,22 +1948,38 @@ def node_prototype_save(caller, **kwargs):
|
||||||
spawned_objects = protlib.search_objects_with_prototype(prototype_key)
|
spawned_objects = protlib.search_objects_with_prototype(prototype_key)
|
||||||
nspawned = spawned_objects.count()
|
nspawned = spawned_objects.count()
|
||||||
|
|
||||||
|
text = ["|gPrototype saved.|n"]
|
||||||
|
|
||||||
if nspawned:
|
if nspawned:
|
||||||
text = ("Do you want to update {} object(s) "
|
text.append("\nDo you want to update {} object(s) "
|
||||||
"already using this prototype?".format(nspawned))
|
"already using this prototype?".format(nspawned))
|
||||||
options = (
|
options = (
|
||||||
{"key": ("|wY|Wes|n", "yes", "y"),
|
{"key": ("|wY|Wes|n", "yes", "y"),
|
||||||
|
"desc": "Go to updating screen",
|
||||||
"goto": ("node_update_objects",
|
"goto": ("node_update_objects",
|
||||||
{"accept_update": True, "objects": spawned_objects,
|
{"accept_update": True, "objects": spawned_objects,
|
||||||
"prototype": prototype, "back_node": "node_prototype_save"})},
|
"prototype": prototype, "back_node": "node_prototype_save"})},
|
||||||
{"key": ("[|wN|Wo|n]", "n"),
|
{"key": ("[|wN|Wo|n]", "n"),
|
||||||
"goto": "node_spawn"},
|
"desc": "Return to index",
|
||||||
|
"goto": "node_index"},
|
||||||
{"key": "_default",
|
{"key": "_default",
|
||||||
"goto": "node_spawn"})
|
"goto": "node_index"})
|
||||||
else:
|
else:
|
||||||
text = "|gPrototype saved.|n"
|
text.append("(press Return to continue)")
|
||||||
options = {"key": "_default",
|
options = {"key": "_default",
|
||||||
"goto": "node_spawn"}
|
"goto": "node_index"}
|
||||||
|
|
||||||
|
text = "\n".join(text)
|
||||||
|
|
||||||
|
helptext = """
|
||||||
|
Updating objects means that the spawner will find all objects previously created by this
|
||||||
|
prototype. You will be presented with a list of the changes the system will try to apply to
|
||||||
|
each of these objects and you can choose to customize that change if needed. If you have
|
||||||
|
done a lot of manual changes to your objects after spawning, you might want to update those
|
||||||
|
objects manually instead.
|
||||||
|
"""
|
||||||
|
|
||||||
|
text = (text, helptext)
|
||||||
|
|
||||||
return text, options
|
return text, options
|
||||||
|
|
||||||
|
|
@ -1967,27 +1992,19 @@ def node_prototype_save(caller, **kwargs):
|
||||||
if error:
|
if error:
|
||||||
# abort save
|
# abort save
|
||||||
text.append(
|
text.append(
|
||||||
"Validation errors were found. They need to be corrected before this prototype "
|
"\n|yValidation errors were found. They need to be corrected before this prototype "
|
||||||
"can be saved (or used to spawn).")
|
"can be saved (or used to spawn).|n")
|
||||||
options = _wizard_options("prototype_save", "prototype_locks", "index")
|
options = _wizard_options("prototype_save", "index", None)
|
||||||
return "\n".join(text), options
|
return "\n".join(text), options
|
||||||
|
|
||||||
prototype_key = prototype['prototype_key']
|
prototype_key = prototype['prototype_key']
|
||||||
if protlib.search_prototype(prototype_key):
|
if protlib.search_prototype(prototype_key):
|
||||||
text.append("Do you want to save/overwrite the existing prototype '{name}'?".format(
|
text.append("\nDo you want to save/overwrite the existing prototype '{name}'?".format(
|
||||||
name=prototype_key))
|
name=prototype_key))
|
||||||
else:
|
else:
|
||||||
text.append("Do you want to save the prototype as '{name}'?".format(prototype_key))
|
text.append("\nDo you want to save the prototype as '{name}'?".format(name=prototype_key))
|
||||||
|
|
||||||
options = (
|
text = "\n".join(text)
|
||||||
{"key": ("[|wY|Wes|n]", "yes", "y"),
|
|
||||||
"goto": ("node_prototype_save",
|
|
||||||
{"accept": True, "prototype": prototype})},
|
|
||||||
{"key": ("|wN|Wo|n", "n"),
|
|
||||||
"goto": "node_spawn"},
|
|
||||||
{"key": "_default",
|
|
||||||
"goto": ("node_prototype_save",
|
|
||||||
{"accept": True, "prototype": prototype})})
|
|
||||||
|
|
||||||
helptext = """
|
helptext = """
|
||||||
Saving the prototype makes it available for use later. It can also be used to inherit from,
|
Saving the prototype makes it available for use later. It can also be used to inherit from,
|
||||||
|
|
@ -1999,6 +2016,18 @@ def node_prototype_save(caller, **kwargs):
|
||||||
|
|
||||||
text = (text, helptext)
|
text = (text, helptext)
|
||||||
|
|
||||||
|
options = (
|
||||||
|
{"key": ("[|wY|Wes|n]", "yes", "y"),
|
||||||
|
"desc": "Save prototype",
|
||||||
|
"goto": ("node_prototype_save",
|
||||||
|
{"accept_save": True, "prototype": prototype})},
|
||||||
|
{"key": ("|wN|Wo|n", "n"),
|
||||||
|
"desc": "Abort and return to Index",
|
||||||
|
"goto": "node_index"},
|
||||||
|
{"key": "_default",
|
||||||
|
"goto": ("node_prototype_save",
|
||||||
|
{"accept_save": True, "prototype": prototype})})
|
||||||
|
|
||||||
return text, options
|
return text, options
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2015,26 +2044,42 @@ def _spawn(caller, **kwargs):
|
||||||
obj = spawner.spawn(prototype)
|
obj = spawner.spawn(prototype)
|
||||||
if obj:
|
if obj:
|
||||||
obj = obj[0]
|
obj = obj[0]
|
||||||
caller.msg("|gNew instance|n {key} ({dbref}) |gspawned.|n".format(
|
text = "|gNew instance|n {key} ({dbref}) |gspawned.|n".format(
|
||||||
key=obj.key, dbref=obj.dbref))
|
key=obj.key, dbref=obj.dbref)
|
||||||
else:
|
else:
|
||||||
caller.msg("|rError: Spawner did not return a new instance.|n")
|
text = "|rError: Spawner did not return a new instance.|n"
|
||||||
return obj
|
return "node_examine_entity", {"text": text, "back": "prototype_spawn"}
|
||||||
|
|
||||||
|
|
||||||
def node_prototype_spawn(caller, **kwargs):
|
def node_prototype_spawn(caller, **kwargs):
|
||||||
"""Submenu for spawning the prototype"""
|
"""Submenu for spawning the prototype"""
|
||||||
|
|
||||||
prototype = _get_menu_prototype(caller)
|
prototype = _get_menu_prototype(caller)
|
||||||
error, text = _validate_prototype(prototype)
|
|
||||||
|
|
||||||
text = [text]
|
already_validated = kwargs.get("already_validated", False)
|
||||||
|
|
||||||
|
if already_validated:
|
||||||
|
error, text = None, []
|
||||||
|
else:
|
||||||
|
error, text = _validate_prototype(prototype)
|
||||||
|
text = [text]
|
||||||
|
|
||||||
if error:
|
if error:
|
||||||
text.append("|rPrototype validation failed. Correct the errors before spawning.|n")
|
text.append("\n|rPrototype validation failed. Correct the errors before spawning.|n")
|
||||||
options = _wizard_options("prototype_spawn", "prototype_locks", "index")
|
options = _wizard_options("prototype_spawn", "index", None)
|
||||||
return "\n".join(text), options
|
return "\n".join(text), options
|
||||||
|
|
||||||
|
text = "\n".join(text)
|
||||||
|
|
||||||
|
helptext = """
|
||||||
|
Spawning is the act of instantiating a prototype into an actual object. As a new object is
|
||||||
|
spawned, every $protfunc in the prototype is called anew. Since this is a common thing to
|
||||||
|
do, you may also temporarily change the |clocation|n of this prototype to bypass whatever
|
||||||
|
value is set in the prototype.
|
||||||
|
|
||||||
|
"""
|
||||||
|
text = (text, helptext)
|
||||||
|
|
||||||
# show spawn submenu options
|
# show spawn submenu options
|
||||||
options = []
|
options = []
|
||||||
prototype_key = prototype['prototype_key']
|
prototype_key = prototype['prototype_key']
|
||||||
|
|
@ -2064,18 +2109,10 @@ def node_prototype_spawn(caller, **kwargs):
|
||||||
options.append(
|
options.append(
|
||||||
{"desc": "Update {num} existing objects with this prototype".format(num=nspawned),
|
{"desc": "Update {num} existing objects with this prototype".format(num=nspawned),
|
||||||
"goto": ("node_update_objects",
|
"goto": ("node_update_objects",
|
||||||
dict(prototype=prototype, opjects=spawned_objects,
|
{"objects": list(spawned_objects),
|
||||||
back_node="node_prototype_spawn"))})
|
"prototype": prototype,
|
||||||
options.extend(_wizard_options("prototype_spawn", "prototype_save", "index"))
|
"back_node": "node_prototype_spawn"})})
|
||||||
|
options.extend(_wizard_options("prototype_spawn", "index", None))
|
||||||
helptext = """
|
|
||||||
Spawning is the act of instantiating a prototype into an actual object. As a new object is
|
|
||||||
spawned, every $protfunc in the prototype is called anew. Since this is a common thing to
|
|
||||||
do, you may also temporarily change the |clocation|n of this prototype to bypass whatever
|
|
||||||
value is set in the prototype.
|
|
||||||
|
|
||||||
"""
|
|
||||||
text = (text, helptext)
|
|
||||||
|
|
||||||
return text, options
|
return text, options
|
||||||
|
|
||||||
|
|
@ -2088,30 +2125,56 @@ def _prototype_load_select(caller, prototype_key):
|
||||||
if matches:
|
if matches:
|
||||||
prototype = matches[0]
|
prototype = matches[0]
|
||||||
_set_menu_prototype(caller, prototype)
|
_set_menu_prototype(caller, prototype)
|
||||||
caller.msg("|gLoaded prototype '{}'.".format(prototype_key))
|
return "node_examine_entity", \
|
||||||
return "node_index"
|
{"text": "|gLoaded prototype {}.|n".format(prototype['prototype_key']),
|
||||||
|
"back": "index"}
|
||||||
else:
|
else:
|
||||||
caller.msg("|rFailed to load prototype '{}'.".format(prototype_key))
|
caller.msg("|rFailed to load prototype '{}'.".format(prototype_key))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _prototype_load_actions(caller, raw_inp, **kwargs):
|
||||||
|
"""Parse the default Convert prototype to a string representation for closer inspection"""
|
||||||
|
choices = kwargs.get("available_choices", [])
|
||||||
|
prototype, action = _default_parse(
|
||||||
|
raw_inp, choices, ("examine", "e", "l"))
|
||||||
|
|
||||||
|
if prototype:
|
||||||
|
# a selection of parent was made
|
||||||
|
prototype = protlib.search_prototype(key=prototype)[0]
|
||||||
|
|
||||||
|
# which action to apply on the selection
|
||||||
|
if action == 'examine':
|
||||||
|
# examine the prototype
|
||||||
|
txt = protlib.prototype_to_str(prototype)
|
||||||
|
kwargs['text'] = txt
|
||||||
|
kwargs['back'] = 'prototype_load'
|
||||||
|
return "node_examine_entity", kwargs
|
||||||
|
|
||||||
|
return 'node_prototype_load'
|
||||||
|
|
||||||
|
|
||||||
@list_node(_all_prototype_parents, _prototype_load_select)
|
@list_node(_all_prototype_parents, _prototype_load_select)
|
||||||
def node_prototype_load(caller, **kwargs):
|
def node_prototype_load(caller, **kwargs):
|
||||||
"""Load prototype"""
|
"""Load prototype"""
|
||||||
|
|
||||||
text = """
|
text = """
|
||||||
Select a prototype to load. This will replace any prototype currently being edited!
|
Select a prototype to load. This will replace any prototype currently being edited!
|
||||||
"""
|
|
||||||
|
{actions}
|
||||||
|
""".format(actions=_format_list_actions("examine"))
|
||||||
|
|
||||||
helptext = """
|
helptext = """
|
||||||
Loading a prototype will load it and return you to the main index. It can be a good idea to
|
Loading a prototype will load it and return you to the main index. It can be a good idea
|
||||||
examine the prototype before loading it.
|
to examine the prototype before loading it.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
text = (text, helptext)
|
text = (text, helptext)
|
||||||
|
|
||||||
options = _wizard_options("prototype_load", "prototype_save", "index")
|
options = _wizard_options("prototype_load", "index", None)
|
||||||
options.append({"key": "_default",
|
options.append({"key": "_default",
|
||||||
"goto": _prototype_parent_actions})
|
"goto": _prototype_load_actions})
|
||||||
|
|
||||||
return text, options
|
return text, options
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -553,7 +553,9 @@ def spawn(*prototypes, **kwargs):
|
||||||
alias_string = init_spawn_value(val, make_iter)
|
alias_string = init_spawn_value(val, make_iter)
|
||||||
|
|
||||||
val = prot.pop("tags", [])
|
val = prot.pop("tags", [])
|
||||||
tags = init_spawn_value(val, make_iter)
|
tags = []
|
||||||
|
for (tag, category, data) in tags:
|
||||||
|
tags.append((init_spawn_value(val, str), category, data))
|
||||||
|
|
||||||
prototype_key = prototype.get('prototype_key', None)
|
prototype_key = prototype.get('prototype_key', None)
|
||||||
if prototype_key:
|
if prototype_key:
|
||||||
|
|
@ -567,9 +569,11 @@ def spawn(*prototypes, **kwargs):
|
||||||
nattributes = dict((key.split("_", 1)[1], init_spawn_value(val, value_to_obj))
|
nattributes = dict((key.split("_", 1)[1], init_spawn_value(val, value_to_obj))
|
||||||
for key, val in prot.items() if key.startswith("ndb_"))
|
for key, val in prot.items() if key.startswith("ndb_"))
|
||||||
|
|
||||||
# the rest are attributes
|
# the rest are attribute tuples (attrname, value, category, locks)
|
||||||
val = prot.pop("attrs", [])
|
val = make_iter(prot.pop("attrs", []))
|
||||||
attributes = init_spawn_value(val, list)
|
attributes = []
|
||||||
|
for (attrname, value, category, locks) in val:
|
||||||
|
attributes.append((attrname, init_spawn_value(val), category, locks))
|
||||||
|
|
||||||
simple_attributes = []
|
simple_attributes = []
|
||||||
for key, value in ((key, value) for key, value in prot.items()
|
for key, value in ((key, value) for key, value in prot.items()
|
||||||
|
|
|
||||||
|
|
@ -938,7 +938,7 @@ class EvMenu(object):
|
||||||
for key, desc in optionlist:
|
for key, desc in optionlist:
|
||||||
if not (key or desc):
|
if not (key or desc):
|
||||||
continue
|
continue
|
||||||
desc_string = ": %s" % (desc if desc else "")
|
desc_string = ": %s" % desc if desc else ""
|
||||||
table_width_max = max(table_width_max,
|
table_width_max = max(table_width_max,
|
||||||
max(m_len(p) for p in key.split("\n")) +
|
max(m_len(p) for p in key.split("\n")) +
|
||||||
max(m_len(p) for p in desc_string.split("\n")) + colsep)
|
max(m_len(p) for p in desc_string.split("\n")) + colsep)
|
||||||
|
|
@ -1140,9 +1140,12 @@ def list_node(option_generator, select=None, pagesize=10):
|
||||||
decorated_options = make_iter(decorated_options)
|
decorated_options = make_iter(decorated_options)
|
||||||
|
|
||||||
extra_options = []
|
extra_options = []
|
||||||
|
if isinstance(decorated_options, dict):
|
||||||
|
decorated_options = [decorated_options]
|
||||||
for eopt in decorated_options:
|
for eopt in decorated_options:
|
||||||
cback = ("goto" in eopt and "goto") or ("exec" in eopt and "exec") or None
|
cback = ("goto" in eopt and "goto") or ("exec" in eopt and "exec") or None
|
||||||
if cback:
|
if cback:
|
||||||
|
print("eopt, cback: {} {}".format(eopt, cback))
|
||||||
signature = eopt[cback]
|
signature = eopt[cback]
|
||||||
if callable(signature):
|
if callable(signature):
|
||||||
# callable with no kwargs defined
|
# callable with no kwargs defined
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue