Finalized the spawner API and made the @spawn command also take prototypes directly, e.g. @spawn GOBLIN.

This commit is contained in:
Griatch 2014-07-01 19:39:12 +02:00
parent 221d56fecd
commit b9c8c1695c
2 changed files with 55 additions and 31 deletions

View file

@ -6,11 +6,12 @@ Building and world design commands
""" """
from django.conf import settings from django.conf import settings
from src.objects.models import ObjectDB from src.objects.models import ObjectDB
from src.utils import create, utils, search
from src.utils.ansi import raw
from src.locks.lockhandler import LockException from src.locks.lockhandler import LockException
from src.commands.default.muxcommand import MuxCommand from src.commands.default.muxcommand import MuxCommand
from src.commands.cmdhandler import get_and_merge_cmdsets from src.commands.cmdhandler import get_and_merge_cmdsets
from src.utils import create, utils, search
from src.utils.spawner import spawn
from src.utils.ansi import raw
# limit symbol import for API # limit symbol import for API
__all__ = ("ObjManipCommand", "CmdSetObjAlias", "CmdCopy", __all__ = ("ObjManipCommand", "CmdSetObjAlias", "CmdCopy",
@ -2258,14 +2259,16 @@ class CmdSpawn(MuxCommand):
spawn objects from prototype spawn objects from prototype
Usage: Usage:
@spawn[/switches] {prototype dictionary} @spawn
@spawn[/switch] prototype_name
@spawn[/switch] {prototype dictionary}
Switches: Switch:
noloc - allow location to None. Otherwise, location will default to noloc - allow location to be None if not specified explicitly. Otherwise,
caller's current location location will default to caller's current location.
parents - show all available prototype parents
Example: Example:
@spawn GOBLIN
@spawn {"key":"goblin", "typeclass":"monster.Monster", "location":"#2"} @spawn {"key":"goblin", "typeclass":"monster.Monster", "location":"#2"}
Dictionary keys: Dictionary keys:
@ -2282,34 +2285,30 @@ class CmdSpawn(MuxCommand):
{wndb_{n<name> - value of a nattribute (ndb_ is stripped) {wndb_{n<name> - value of a nattribute (ndb_ is stripped)
any other keywords are interpreted as Attributes and their values. any other keywords are interpreted as Attributes and their values.
The parent prototypes are taken as dictionaries defined globally in The available prototypes are defined globally in modules set in
the settings.PROTOTYPE_MODULES. settings.PROTOTYPE_MODULES. If @spawn is used without arguments it
displays a list of available prototypes.
""" """
key = "@spawn" key = "@spawn"
aliases = ["spawn"]
locks = "cmd:perm(spawn) or perm(Builders)" locks = "cmd:perm(spawn) or perm(Builders)"
help_category = "Building" help_category = "Building"
def func(self): def func(self):
"Implements the spawner" "Implements the spawner"
global _PROTOTYPE_PARENTS def _show_prototypes(prototypes):
if _PROTOTYPE_PARENTS is None: "Helper to show a list of available prototypes"
if hasattr(settings, "PROTOTYPE_MODULES"): string = "\nAvailable prototypes:\n %s"
# read prototype parents from setting string = string % utils.fill(", ".join(sorted(prototypes.keys())))
_PROTOTYPE_PARENTS = {} return string
for prototype_module in utils.make_iter(settings.PROTOTYPE_MODULES):
_PROTOTYPE_PARENTS.update(dict((key, val)
for key, val in utils.all_from_module(prototype_module).items() if isinstance(val, dict)))
prototypes = spawn(return_prototypes=True)
if not self.args: if not self.args:
string = "Usage: @spawn {key:value, key, value, ...}\n" \ string = "Usage: @spawn {key:value, key, value, ... }"
"Available prototypes: %s" self.caller.msg(string + _show_prototypes(prototypes))
self.caller.msg(string % ", ".join(_PROTOTYPE_PARENTS.keys())
if _PROTOTYPE_PARENTS else None)
return return
from src.utils.spawner import spawn
try: try:
# make use of _convert_from_string from the SetAttribute command # make use of _convert_from_string from the SetAttribute command
prototype = _convert_from_string(self, self.args) prototype = _convert_from_string(self, self.args)
@ -2323,14 +2322,22 @@ class CmdSpawn(MuxCommand):
self.caller.msg(string) self.caller.msg(string)
return return
if not isinstance(prototype, dict): if isinstance(prototype, basestring):
self.caller.msg("The prototype must be a Python dictionary.") # A prototype key
keystr = prototype
prototype = prototypes.get(prototype, None)
if not prototype:
string = "No prototype named '%s'." % keystr
self.caller.msg(string + _show_prototypes(prototypes))
return
elif not isinstance(prototype, dict):
self.caller.msg("The prototype must be a prototype key or a Python dictionary.")
return return
if not "noloc" in self.switches and not "location" in prototype: if not "noloc" in self.switches and not "location" in prototype:
prototype["location"] = self.caller.location prototype["location"] = self.caller.location
for obj in spawn(prototype, prototype_parents=_PROTOTYPE_PARENTS): for obj in spawn(prototype):
self.caller.msg("Spawned %s." % obj.key) self.caller.msg("Spawned %s." % obj.key)

View file

@ -77,6 +77,7 @@ from django.conf import settings
from random import randint from random import randint
from src.objects.models import ObjectDB from src.objects.models import ObjectDB
from src.utils.create import handle_dbref from src.utils.create import handle_dbref
from src.utils.utils import make_iter, all_from_module
_CREATE_OBJECT_KWARGS = ("key", "location", "home", "destination") _CREATE_OBJECT_KWARGS = ("key", "location", "home", "destination")
@ -155,14 +156,30 @@ def spawn(*prototypes, **kwargs):
Spawn a number of prototyped objects. Each argument should be a Spawn a number of prototyped objects. Each argument should be a
prototype dictionary. prototype dictionary.
The keyword argument "prototype_parents" holds a dictionary of keyword args:
prototype dictionaries, each with a unique key. The given prototype_modules - a python-path to a
prototypes may call these as parents using the "prototype" key. prototype module, or a list of such paths. These will be used
to build the global protparents dictionary accessible by the
input prototypes. If not given, it will instead look for modules
defined by settings.PROTOTYPE_MODULES.
return_prototypes - only return a list of the prototype-parents
(no object creation happens)
""" """
objsparams = []
protparents = {}
protmodules = make_iter(kwargs.get("prototype_modules", []))
if not protmodules and hasattr(settings, "PROTOTYPE_MODULES"):
protmodules = make_iter(settings.PROTOTYPE_MODULES)
for prototype_module in protmodules:
protparents.update(dict((key, val)
for key, val in all_from_module(prototype_module).items() if isinstance(val, dict)))
if "return_prototypes" in kwargs:
# only return the parents
return protparents
objsparams = []
for prototype in prototypes: for prototype in prototypes:
protparents = kwargs.get("prototype_parents", None)
prot = _get_prototype(prototype, {}, protparents) prot = _get_prototype(prototype, {}, protparents)
if not prot: if not prot: