Exemple #1
0
 def make_equipment(self):
     prototype = prototypes.search_prototype("iron_large_weapon", require_single=True)
     armor_prototype = prototypes.search_prototype("iron_coat_of_plates", require_single=True)
     # Get prototype data
     large_data = prototype[0]
     armor_data = armor_prototype[0]
     # Spawn item using data
     weapon_item = spawn(large_data)
     armor_item = spawn(armor_data)
     # Move item to caller's inventory
     weapon_item[0].move_to(self, quiet=True)
     armor_item[0].move_to(self, quiet=True)
     # Equip items
     self.execute_cmd('equip iron large weapon')
     self.execute_cmd('equip iron coat of plates')
Exemple #2
0
def flatten_prototype(prototype, validate=False):
    """
    Produce a 'flattened' prototype, where all prototype parents in the inheritance tree have been
    merged into a final prototype.

    Args:
        prototype (dict): Prototype to flatten. Its `prototype_parent` field will be parsed.
        validate (bool, optional): Validate for valid keys etc.

    Returns:
        flattened (dict): The final, flattened prototype.

    """

    if prototype:
        prototype = protlib.homogenize_prototype(prototype)
        protparents = {
            prot['prototype_key'].lower(): prot
            for prot in protlib.search_prototype()
        }
        protlib.validate_prototype(prototype,
                                   None,
                                   protparents,
                                   is_prototype_base=validate,
                                   strict=validate)
        return _get_prototype(
            prototype,
            protparents,
            uninherited={"prototype_key": prototype.get("prototype_key")})
    return {}
Exemple #3
0
def mob_death(mob, killer=None):
    if killer:
        killer.msg(f"You killed {mob.key}!")
        xp = calculate_kill_xp(killer.db.xp, mob.db.xp)
        gain_xp(killer, xp)

    if mob.db.drop_gold:
        gold = create_object("typeclasses.objects.Gold", key="gold")
        gold.add(mob.db.drop_gold)
        # use move_to() so we invoke StackableObject accumulation
        gold.move_to(mob.location, quiet=True)
        mob.location.msg_contents(f"{mob.key} drops {mob.db.drop_gold} gold.")

    if mob.db.drop_object_id:
        tags = ["object", f"record_id_{mob.db.drop_object_id}"]
        prototypes = protlib.search_prototype(tags=tags)
        if prototypes:
            obj = spawner.spawn(prototypes[0]["prototype_key"])[0]
            obj.location = mob.location
            mob.location.msg_contents(f"{mob.key} drops {obj.name}.")

    mob.location.msg_contents(
        f"{mob.key} disappears in a cloud of greasy black smoke.",
        exclude=[mob])
    mob.location = None
    mob.delete()
Exemple #4
0
def prototype_from_object(obj):
    """
    Guess a minimal prototype from an existing object.

    Args:
        obj (Object): An object to analyze.

    Returns:
        prototype (dict): A prototype estimating the current state of the object.

    """
    # first, check if this object already has a prototype

    prot = obj.tags.get(category=_PROTOTYPE_TAG_CATEGORY, return_list=True)
    if prot:
        prot = protlib.search_prototype(prot[0])

    if not prot or len(prot) > 1:
        # no unambiguous prototype found - build new prototype
        prot = {}
        prot['prototype_key'] = "From-Object-{}-{}".format(
            obj.key,
            hashlib.md5(str(time.time())).hexdigest()[:7])
        prot['prototype_desc'] = "Built from {}".format(str(obj))
        prot['prototype_locks'] = "spawn:all();edit:all()"
        prot['prototype_tags'] = []
    else:
        prot = prot[0]

    prot['key'] = obj.db_key or hashlib.md5(str(time.time())).hexdigest()[:6]
    prot['typeclass'] = obj.db_typeclass_path

    location = obj.db_location
    if location:
        prot['location'] = location.dbref
    home = obj.db_home
    if home:
        prot['home'] = home.dbref
    destination = obj.db_destination
    if destination:
        prot['destination'] = destination.dbref
    locks = obj.locks.all()
    if locks:
        prot['locks'] = ";".join(locks)
    perms = obj.permissions.get(return_list=True)
    if perms:
        prot['permissions'] = make_iter(perms)
    aliases = obj.aliases.get(return_list=True)
    if aliases:
        prot['aliases'] = aliases
    tags = [(tag.db_key, tag.db_category, tag.db_data)
            for tag in obj.tags.all(return_objs=True)]
    if tags:
        prot['tags'] = tags
    attrs = [(attr.key, attr.value, attr.category, ';'.join(attr.locks.all()))
             for attr in obj.attributes.all()]
    if attrs:
        prot['attrs'] = attrs

    return prot
Exemple #5
0
def prototype_from_object(obj):
    """
    Guess a minimal prototype from an existing object.

    Args:
        obj (Object): An object to analyze.

    Returns:
        prototype (dict): A prototype estimating the current state of the object.

    """
    # first, check if this object already has a prototype

    prot = obj.tags.get(category=_PROTOTYPE_TAG_CATEGORY, return_list=True)
    if prot:
        prot = protlib.search_prototype(prot[0])

    if not prot or len(prot) > 1:
        # no unambiguous prototype found - build new prototype
        prot = {}
        prot['prototype_key'] = "From-Object-{}-{}".format(
                obj.key, hashlib.md5(str(time.time())).hexdigest()[:7])
        prot['prototype_desc'] = "Built from {}".format(str(obj))
        prot['prototype_locks'] = "spawn:all();edit:all()"
        prot['prototype_tags'] = []
    else:
        prot = prot[0]

    prot['key'] = obj.db_key or hashlib.md5(str(time.time())).hexdigest()[:6]
    prot['typeclass'] = obj.db_typeclass_path

    location = obj.db_location
    if location:
        prot['location'] = location.dbref
    home = obj.db_home
    if home:
        prot['home'] = home.dbref
    destination = obj.db_destination
    if destination:
        prot['destination'] = destination.dbref
    locks = obj.locks.all()
    if locks:
        prot['locks'] = ";".join(locks)
    perms = obj.permissions.get(return_list=True)
    if perms:
        prot['permissions'] = make_iter(perms)
    aliases = obj.aliases.get(return_list=True)
    if aliases:
        prot['aliases'] = aliases
    tags = [(tag.db_key, tag.db_category, tag.db_data)
            for tag in obj.tags.get(return_tagobj=True, return_list=True) if tag]
    if tags:
        prot['tags'] = tags
    attrs = [(attr.key, attr.value, attr.category, ';'.join(attr.locks.all()))
             for attr in obj.attributes.get(return_obj=True, return_list=True) if attr]
    if attrs:
        prot['attrs'] = attrs

    return prot
Exemple #6
0
def return_proto_dic(prototype):
    proto_dic = search_prototype(prototype)
    proto_dic = proto_dic[0]
    name = proto_dic['key']
    attrs = proto_dic['attrs']
    attr_dic = {'key': name}
    for i in attrs:
        attr_dic[i[0]] = i[1]
    return attr_dic
Exemple #7
0
def generate_mob(location, level):
    tags = [f"min_level_{x}" for x in range(level + 1)]
    mob_prototypes = protlib.search_prototype(tags=tags)
    if not mob_prototypes:
        # no valid prototypes found
        return
    proto_choice = random.choice(mob_prototypes)
    mob = spawner.spawn(proto_choice['prototype_key'])[0]
    mob.location = location
    location.msg_contents(f"A {mob.key} appears!")
Exemple #8
0
 def make_equipment(self):
     prototype = prototypes.search_prototype("bow", require_single=True)
     armor_prototype = prototypes.search_prototype("hardened_iron_coat_of_plates", require_single=True)
     arrow_prototype = prototypes.search_prototype("arrows", require_single=True)
     # Get prototype data
     bow_data = prototype[0]
     armor_data = armor_prototype[0]
     arrow_data = arrow_prototype[0]
     # Spawn item using data
     weapon_item = spawn(bow_data)
     armor_item = spawn(armor_data)
     arrow_item = spawn(arrow_data)
     # Move item to caller's inventory
     weapon_item[0].move_to(self, quiet=True)
     armor_item[0].move_to(self, quiet=True)
     arrow_item[0].move_to(self, quiet=True)
     # Equip items
     self.execute_cmd('equip bow')
     self.execute_cmd('equip hardened iron coat of plates')
     self.execute_cmd('equip arrows')
Exemple #9
0
 def make_equipment(self):
     prototype = prototypes.search_prototype("hardened_iron_medium_weapon", require_single=True)
     armor_prototype = prototypes.search_prototype("hardened_iron_coat_of_plates", require_single=True)
     shield_prototype = prototypes.search_prototype("hardened_iron_shield", require_single=True)
     # Get prototype data
     longsword_data = prototype[0]
     armor_data = armor_prototype[0]
     shield_data = shield_prototype[0]
     # Spawn item using data
     weapon_item = spawn(longsword_data)
     armor_item = spawn(armor_data)
     shield_item = spawn(shield_data)
     # Move item to caller's inventory
     weapon_item[0].move_to(self, quiet=True)
     armor_item[0].move_to(self, quiet=True)
     shield_item[0].move_to(self, quiet=True)
     # Equip items
     self.execute_cmd('equip hardened iron medium weapon')
     self.execute_cmd('equip hardened iron coat of plates')
     self.execute_cmd('equip hardened iron shield')
Exemple #10
0
def maybe_spawn_mob_in_lair(location):
    if not location.is_special_kind(SpecialRoomKind.MONSTER_LAIR):
        # not a lair
        return

    if has_players_or_mobs(location):
        # only spawn a new mob in a room devoid of players or mobs
        return

    mob_id = location.magnitude(SpecialRoomKind.MONSTER_LAIR)
    record_id_tag = f"record_id_{mob_id}"
    mob_prototypes = protlib.search_prototype(tags=[record_id_tag])
    if not mob_prototypes:
        return
    proto_choice = mob_prototypes[0]
    mob = spawner.spawn(proto_choice['prototype_key'])[0]
    # stay in the lair
    mob.location = location
    mob.db.moves_between_rooms = False
Exemple #11
0
 def inner_func(self):
     if not self.args:
         self.caller.msg("Make what?")
         return
     prototypes = protlib.search_prototype(key=self.args.strip())
     if not prototypes:
         self.caller.msg("No such object.")
         return
     prototype = prototypes[0]
     components = find_attr_value(prototype, "components")
     if not components:
         self.caller.msg("You can't make that.")
         return
     if not has_components(self.caller, components):
         self.caller.msg("You don't have all the components.")
         return
     consume_components(self.caller, components)
     obj = spawner.spawn(prototype['prototype_key'])[0]
     obj.location = self.caller
     self.caller.msg(f"You created {prototype['key']}.")
Exemple #12
0
def flatten_prototype(prototype, validate=False):
    """
    Produce a 'flattened' prototype, where all prototype parents in the inheritance tree have been
    merged into a final prototype.

    Args:
        prototype (dict): Prototype to flatten. Its `prototype_parent` field will be parsed.
        validate (bool, optional): Validate for valid keys etc.

    Returns:
        flattened (dict): The final, flattened prototype.

    """

    if prototype:
        prototype = protlib.homogenize_prototype(prototype)
        protparents = {prot['prototype_key'].lower(): prot for prot in protlib.search_prototype()}
        protlib.validate_prototype(prototype, None, protparents,
                                   is_prototype_base=validate, strict=validate)
        return _get_prototype(prototype, protparents,
                              uninherited={"prototype_key": prototype.get("prototype_key")})
    return {}
Exemple #13
0
    def test_prototype_storage(self):

        # from evennia import set_trace;set_trace(term_size=(180, 50))
        prot1 = protlib.create_prototype(self.prot1)

        self.assertTrue(bool(prot1))
        self.assertEqual(prot1, self.prot1)

        self.assertEqual(prot1["prototype_desc"], "testdesc1")

        self.assertEqual(prot1["prototype_tags"],
                         [("foo1", _PROTOTYPE_TAG_META_CATEGORY)])
        self.assertEqual(
            protlib.DbPrototype.objects.get_by_tag(
                "foo1", _PROTOTYPE_TAG_META_CATEGORY)[0].db.prototype,
            prot1,
        )

        prot2 = protlib.create_prototype(self.prot2)
        self.assertEqual(
            [
                pobj.db.prototype
                for pobj in protlib.DbPrototype.objects.get_by_tag(
                    "foo1", _PROTOTYPE_TAG_META_CATEGORY)
            ],
            [prot1, prot2],
        )

        # add to existing prototype
        prot1b = protlib.create_prototype({
            "prototype_key": "testprototype1",
            "foo": "bar",
            "prototype_tags": ["foo2"]
        })

        self.assertEqual(
            [
                pobj.db.prototype
                for pobj in protlib.DbPrototype.objects.get_by_tag(
                    "foo2", _PROTOTYPE_TAG_META_CATEGORY)
            ],
            [prot1b],
        )

        self.assertEqual(list(protlib.search_prototype("testprototype2")),
                         [prot2])
        self.assertNotEqual(list(protlib.search_prototype("testprototype1")),
                            [prot1])
        self.assertEqual(list(protlib.search_prototype("testprototype1")),
                         [prot1b])

        prot3 = protlib.create_prototype(self.prot3)

        # partial match
        with mock.patch("evennia.prototypes.prototypes._MODULE_PROTOTYPES",
                        {}):
            self.assertCountEqual(protlib.search_prototype("prot"),
                                  [prot1b, prot2, prot3])
            self.assertCountEqual(protlib.search_prototype(tags="foo1"),
                                  [prot1b, prot2, prot3])

        self.assertTrue(str(str(protlib.list_prototypes(self.char1))))
Exemple #14
0
def spawn(*prototypes, **kwargs):
    """
    Spawn a number of prototyped objects.

    Args:
        prototypes (dict): Each argument should be a prototype
            dictionary.
    Kwargs:
        prototype_modules (str or list): A python-path to a 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.
        prototype_parents (dict): A dictionary holding a custom
            prototype-parent dictionary. Will overload same-named
            prototypes from prototype_modules.
        return_parents (bool): Only return a dict of the
            prototype-parents (no object creation happens)
        only_validate (bool): Only run validation of prototype/parents
            (no object creation) and return the create-kwargs.

    Returns:
        object (Object, dict or list): Spawned object(s). If `only_validate` is given, return
            a list of the creation kwargs to build the object(s) without actually creating it. If
            `return_parents` is set, instead return dict of prototype parents.

    """
    # get available protparents
    protparents = {prot['prototype_key'].lower(): prot for prot in protlib.search_prototype()}

    # overload module's protparents with specifically given protparents
    # we allow prototype_key to be the key of the protparent dict, to allow for module-level
    # prototype imports. We need to insert prototype_key in this case
    for key, protparent in kwargs.get("prototype_parents", {}).items():
        key = str(key).lower()
        protparent['prototype_key'] = str(protparent.get("prototype_key", key)).lower()
        protparents[key] = protparent

    if "return_parents" in kwargs:
        # only return the parents
        return copy.deepcopy(protparents)

    objsparams = []
    for prototype in prototypes:

        protlib.validate_prototype(prototype, None, protparents, is_prototype_base=True)
        prot = _get_prototype(prototype, protparents,
                              uninherited={"prototype_key": prototype.get("prototype_key")})
        if not prot:
            continue

        # extract the keyword args we need to create the object itself. If we get a callable,
        # call that to get the value (don't catch errors)
        create_kwargs = {}
        # we must always add a key, so if not given we use a shortened md5 hash. There is a (small)
        # chance this is not unique but it should usually not be a problem.
        val = prot.pop("key", "Spawned-{}".format(
            hashlib.md5(str(time.time())).hexdigest()[:6]))
        create_kwargs["db_key"] = init_spawn_value(val, str)

        val = prot.pop("location", None)
        create_kwargs["db_location"] = init_spawn_value(val, value_to_obj)

        val = prot.pop("home", settings.DEFAULT_HOME)
        create_kwargs["db_home"] = init_spawn_value(val, value_to_obj)

        val = prot.pop("destination", None)
        create_kwargs["db_destination"] = init_spawn_value(val, value_to_obj)

        val = prot.pop("typeclass", settings.BASE_OBJECT_TYPECLASS)
        create_kwargs["db_typeclass_path"] = init_spawn_value(val, str)

        # extract calls to handlers
        val = prot.pop("permissions", [])
        permission_string = init_spawn_value(val, make_iter)
        val = prot.pop("locks", "")
        lock_string = init_spawn_value(val, str)
        val = prot.pop("aliases", [])
        alias_string = init_spawn_value(val, make_iter)

        val = prot.pop("tags", [])
        tags = []
        for (tag, category, data) in tags:
            tags.append((init_spawn_value(val, str), category, data))

        prototype_key = prototype.get('prototype_key', None)
        if prototype_key:
            # we make sure to add a tag identifying which prototype created this object
            tags.append((prototype_key, _PROTOTYPE_TAG_CATEGORY))

        val = prot.pop("exec", "")
        execs = init_spawn_value(val, make_iter)

        # extract ndb assignments
        nattributes = dict((key.split("_", 1)[1], init_spawn_value(val, value_to_obj))
                           for key, val in prot.items() if key.startswith("ndb_"))

        # the rest are attribute tuples (attrname, value, category, locks)
        val = make_iter(prot.pop("attrs", []))
        attributes = []
        for (attrname, value, category, locks) in val:
            attributes.append((attrname, init_spawn_value(val), category, locks))

        simple_attributes = []
        for key, value in ((key, value) for key, value in prot.items()
                           if not (key.startswith("ndb_"))):
            # we don't support categories, nor locks for simple attributes
            if key in _PROTOTYPE_META_NAMES:
                continue
            else:
                simple_attributes.append(
                    (key, init_spawn_value(value, value_to_obj_or_any), None, None))

        attributes = attributes + simple_attributes
        attributes = [tup for tup in attributes if not tup[0] in _NON_CREATE_KWARGS]

        # pack for call into _batch_create_object
        objsparams.append((create_kwargs, permission_string, lock_string,
                           alias_string, nattributes, attributes, tags, execs))

    if kwargs.get("only_validate"):
        return objsparams
    return batch_create_object(*objsparams)
    def func(self):
        use_err_msg = "|540Usage: forge <item>|n"

        # Do all checks
        if not self.caller.db.blacksmith:
            self.msg(
                "|400You are not trained in how to properly utilze a forge. Please find a blacksmith.|n"
            )
            return

        if not self.item:
            self.msg(use_err_msg)
            return

        # Search for designated prototypes
        try:
            prototype = prototypes.search_prototype(self.item,
                                                    require_single=True)
        except KeyError:
            self.msg(
                "Item not found, or more than one match. Please try again.")
        else:
            # Get search response
            prototype_data = prototype[0]

            # Check for items in callers inventory.
            character_resources = {
                "iron_ingots": self.caller.db.iron_ingots,
                "cloth": self.caller.db.cloth,
                "refined_wood": self.caller.db.refined_wood,
                "leather": self.caller.db.leather
            }

            # Get item requirements
            item_data = prototype_data['attrs']
            item_requirements = {
                "iron_ingots": item_data[1][1],
                "refined_wood": item_data[2][1],
                "leather": item_data[3][1],
                "cloth": item_data[4][1]
            }

            requirements_checker = [
                character_resources["iron_ingots"] >=
                item_requirements["iron_ingots"],
                character_resources["refined_wood"] >=
                item_requirements["refined_wood"],
                character_resources["leather"] >= item_requirements["leather"],
                character_resources["cloth"] >= item_requirements["cloth"]
            ]

            # Check that all conditions in above list are true.

            if all(requirements_checker) or self.caller.is_superuser:
                self.msg(f"You forge a {self.item}")
                # Get required resources and decrement from player totals.
                self.caller.db.iron_ingots -= item_requirements["iron_ingots"]
                self.caller.db.refined_wood -= item_requirements[
                    "refined_wood"]
                self.caller.db.leather -= item_requirements["leather"]
                self.caller.db.cloth -= item_requirements["cloth"]

                blacksmith_item = spawn(prototype[0])
                blacksmith_item[0].move_to(self.caller, quiet=True)

            else:
                self.msg(f"|400You don't have the required resources.|n")
Exemple #16
0
def batch_update_objects_with_prototype(prototype, diff=None, objects=None):
    """
    Update existing objects with the latest version of the prototype.

    Args:
        prototype (str or dict): Either the `prototype_key` to use or the
            prototype dict itself.
        diff (dict, optional): This a diff structure that describes how to update the protototype.
            If not given this will be constructed from the first object found.
        objects (list, optional): List of objects to update. If not given, query for these
            objects using the prototype's `prototype_key`.
    Returns:
        changed (int): The number of objects that had changes applied to them.

    """
    prototype = protlib.homogenize_prototype(prototype)

    if isinstance(prototype, basestring):
        new_prototype = protlib.search_prototype(prototype)
    else:
        new_prototype = prototype

    prototype_key = new_prototype['prototype_key']

    if not objects:
        objects = ObjectDB.objects.get_by_tag(prototype_key,
                                              category=_PROTOTYPE_TAG_CATEGORY)

    if not objects:
        return 0

    if not diff:
        diff, _ = prototype_diff_from_object(new_prototype, objects[0])

    # make sure the diff is flattened
    diff = flatten_diff(diff)
    changed = 0
    for obj in objects:
        do_save = False

        old_prot_key = obj.tags.get(category=_PROTOTYPE_TAG_CATEGORY,
                                    return_list=True)
        old_prot_key = old_prot_key[0] if old_prot_key else None
        if prototype_key != old_prot_key:
            obj.tags.clear(category=_PROTOTYPE_TAG_CATEGORY)
            obj.tags.add(prototype_key, category=_PROTOTYPE_TAG_CATEGORY)

        for key, directive in diff.items():
            if directive in ('UPDATE', 'REPLACE'):

                if key in _PROTOTYPE_META_NAMES:
                    # prototype meta keys are not stored on-object
                    continue

                val = new_prototype[key]
                do_save = True

                if key == 'key':
                    obj.db_key = init_spawn_value(val, str)
                elif key == 'typeclass':
                    obj.db_typeclass_path = init_spawn_value(val, str)
                elif key == 'location':
                    obj.db_location = init_spawn_value(val, value_to_obj)
                elif key == 'home':
                    obj.db_home = init_spawn_value(val, value_to_obj)
                elif key == 'destination':
                    obj.db_destination = init_spawn_value(val, value_to_obj)
                elif key == 'locks':
                    if directive == 'REPLACE':
                        obj.locks.clear()
                    obj.locks.add(init_spawn_value(val, str))
                elif key == 'permissions':
                    if directive == 'REPLACE':
                        obj.permissions.clear()
                    obj.permissions.batch_add(*(init_spawn_value(perm, str)
                                                for perm in val))
                elif key == 'aliases':
                    if directive == 'REPLACE':
                        obj.aliases.clear()
                    obj.aliases.batch_add(*(init_spawn_value(alias, str)
                                            for alias in val))
                elif key == 'tags':
                    if directive == 'REPLACE':
                        obj.tags.clear()
                    obj.tags.batch_add(*((init_spawn_value(ttag, str),
                                          tcategory, tdata)
                                         for ttag, tcategory, tdata in val))
                elif key == 'attrs':
                    if directive == 'REPLACE':
                        obj.attributes.clear()
                    obj.attributes.batch_add(
                        *((init_spawn_value(akey, str),
                           init_spawn_value(aval, value_to_obj), acategory,
                           alocks) for akey, aval, acategory, alocks in val))
                elif key == 'exec':
                    # we don't auto-rerun exec statements, it would be huge security risk!
                    pass
                else:
                    obj.attributes.add(key,
                                       init_spawn_value(val, value_to_obj))
            elif directive == 'REMOVE':
                do_save = True
                if key == 'key':
                    obj.db_key = ''
                elif key == 'typeclass':
                    # fall back to default
                    obj.db_typeclass_path = settings.BASE_OBJECT_TYPECLASS
                elif key == 'location':
                    obj.db_location = None
                elif key == 'home':
                    obj.db_home = None
                elif key == 'destination':
                    obj.db_destination = None
                elif key == 'locks':
                    obj.locks.clear()
                elif key == 'permissions':
                    obj.permissions.clear()
                elif key == 'aliases':
                    obj.aliases.clear()
                elif key == 'tags':
                    obj.tags.clear()
                elif key == 'attrs':
                    obj.attributes.clear()
                elif key == 'exec':
                    # we don't auto-rerun exec statements, it would be huge security risk!
                    pass
                else:
                    obj.attributes.remove(key)
        if do_save:
            changed += 1
            obj.save()

    return changed
    def func(self):

        if self.caller.db.blacksmith:
            pass
        elif self.caller.db.bowyer:
            pass
        elif self.caller.db.artificer:
            pass
        elif self.caller.db.gunsmith:
            pass
        else:
            self.msg(
                f"|400You don't have the proper skills to create a {self.item}.|n"
            )
            return

        use_err_msg = "|430Usage: craft <item>|n"

        if not self.item:
            self.msg(use_err_msg)
            return

        # Search for designated prototypes
        try:
            prototype = prototypes.search_prototype(self.item,
                                                    require_single=True)
        except KeyError:
            self.msg(
                "|430Item not found, or more than one match. Please try again.|n"
            )
        else:
            # Get search response
            prototype_data = prototype[0]

            # Get item attributes and who makes it.
            item_data = prototype_data['attrs']
            craft_source = item_data[0][1]

            # Check for correct kit in caller kit slot.
            kit = self.caller.db.kit_slot[0] if self.caller.db.kit_slot else []
            kit_type = kit.db.type if kit else []
            kit_uses = kit.db.uses if kit else 0

            if not kit:
                self.msg(
                    f"|430Please equip the kit needed to craft a {self.item}.")
                return

            if kit_uses <= 0 and (craft_source == kit_type):
                self.msg(f"|400Your {kit} is out of uses.|n")
                return

            # Passed checks. Make item.
            # Check for items in callers inventory.
            if craft_source == kit_type:
                character_resources = {
                    "iron_ingots": self.caller.db.iron_ingots,
                    "cloth": self.caller.db.cloth,
                    "refined_wood": self.caller.db.refined_wood,
                    "leather": self.caller.db.leather
                }

                # Get item requirements
                item_requirements = {
                    "iron_ingots": item_data[2][1],
                    "refined_wood": item_data[3][1],
                    "leather": item_data[4][1],
                    "cloth": item_data[5][1]
                }

                requirements_checker = [
                    character_resources["iron_ingots"] >=
                    item_requirements["iron_ingots"],
                    character_resources["refined_wood"] >=
                    item_requirements["refined_wood"],
                    character_resources["leather"] >=
                    item_requirements["leather"],
                    character_resources["cloth"] >= item_requirements["cloth"]
                ]

                # Check that all conditions in above list are true.

                if all(requirements_checker) or self.caller.is_superuser:
                    self.msg(f"You craft a {self.item}")
                    # Get required resources and decrement from player totals.
                    self.caller.db.iron_ingots -= item_requirements[
                        "iron_ingots"]
                    self.caller.db.refined_wood -= item_requirements[
                        "refined_wood"]
                    self.caller.db.leather -= item_requirements["leather"]
                    self.caller.db.cloth -= item_requirements["cloth"]
                    #
                    item = spawn(prototype[0])
                    item[0].move_to(self.caller, quiet=True)

                    # Decrement the kit of one use.
                    # kit.db.uses -= 1

                else:
                    self.msg(f"|400You don't have the required resources.|n")
            else:
                self.msg(
                    f"|430Please equip the correct kit before attempting to craft your item.|n"
                )
                return
    def func(self):

        if self.caller.db.blacksmith:
            pass
        elif self.caller.db.bowyer:
            pass
        elif self.caller.db.artificer:
            pass
        elif self.caller.db.gunsmith:
            pass
        else:
            self.msg(
                f"|400You don't have the proper skills to repair a {self.item}.|n"
            )
            return

        use_err_msg = "|430Usage: repair <item>|n"

        if not self.item:
            self.msg(use_err_msg)
            return

        # Search for designated prototypes
        try:
            item = self.caller.search(self.item, location=self.caller)
        except KeyError:
            self.msg(
                "|430Item not found, or more than one match. Please try again.|n"
            )
        else:
            if item:
                # Check that cooldown has expired.
                combatant = Combatant(self.caller)
                seconds_left = combatant.secondsUntilNextRepair(time.time())
                if seconds_left > 0:
                    combatant.message(
                        f"|430You cannot use this ability for another {math.floor(seconds_left/60)} minutes and {seconds_left % 60} seconds.|n"
                    )
                    return

                item_lower = item.key.lower().replace(" ", "_")
                prototype = prototypes.search_prototype(item_lower,
                                                        require_single=True)

                # Get search response
                prototype_data = prototype[0]

                # Get item attributes and who makes it.
                item_data = prototype_data['attrs']
                craft_source = item_data[0][1]

                # Make sure item has material value attribute.
                if item_data[9][0] == "material_value":
                    material_value = item_data[9][1]
                else:
                    self.msg(f"{item.key} cannot be repaired.")
                    return

                if craft_source in ("blacksmith", "bowyer", "gunsmith"):
                    # Set command time execution
                    now = time.time()
                    combatant.setRepairTimer(now)

                    # Reset stats
                    item.db.broken = False
                    item.db.patched = False
                    item.db.material_value = material_value
                    self.msg(f"You repair the {item}.")
                else:
                    self.msg("|430You cannot repair this item|n.")
            else:
                return
Exemple #19
0
def batch_update_objects_with_prototype(prototype, diff=None, objects=None, exact=False):
    """
    Update existing objects with the latest version of the prototype.

    Args:
        prototype (str or dict): Either the `prototype_key` to use or the
            prototype dict itself.
        diff (dict, optional): This a diff structure that describes how to update the protototype.
            If not given this will be constructed from the first object found.
        objects (list, optional): List of objects to update. If not given, query for these
            objects using the prototype's `prototype_key`.
        exact (bool, optional): By default (`False`), keys not explicitly in the prototype will
            not be applied to the object, but will be retained as-is. This is usually what is
            expected - for example, one usually do not want to remove the object's location even
            if it's not set in the prototype. With `exact=True`, all un-specified properties of the
            objects will be removed if they exist. This will lead to a more accurate 1:1 correlation
            between the  object and the prototype but is usually impractical.
    Returns:
        changed (int): The number of objects that had changes applied to them.

    """
    prototype = protlib.homogenize_prototype(prototype)

    if isinstance(prototype, str):
        new_prototype = protlib.search_prototype(prototype)
    else:
        new_prototype = prototype

    prototype_key = new_prototype["prototype_key"]

    if not objects:
        objects = ObjectDB.objects.get_by_tag(prototype_key, category=PROTOTYPE_TAG_CATEGORY)

    if not objects:
        return 0

    if not diff:
        diff, _ = prototype_diff_from_object(new_prototype, objects[0])

    # make sure the diff is flattened
    diff = flatten_diff(diff)

    changed = 0
    for obj in objects:
        do_save = False

        old_prot_key = obj.tags.get(category=PROTOTYPE_TAG_CATEGORY, return_list=True)
        old_prot_key = old_prot_key[0] if old_prot_key else None

        try:
            for key, directive in diff.items():

                if key not in new_prototype and not exact:
                    # we don't update the object if the prototype does not actually
                    # contain the key (the diff will report REMOVE but we ignore it
                    # since exact=False)
                    continue

                if directive in ("UPDATE", "REPLACE"):

                    if key in _PROTOTYPE_META_NAMES:
                        # prototype meta keys are not stored on-object
                        continue

                    val = new_prototype[key]
                    do_save = True

                    if key == "key":
                        obj.db_key = init_spawn_value(val, str)
                    elif key == "typeclass":
                        obj.db_typeclass_path = init_spawn_value(val, str)
                    elif key == "location":
                        obj.db_location = init_spawn_value(val, value_to_obj)
                    elif key == "home":
                        obj.db_home = init_spawn_value(val, value_to_obj)
                    elif key == "destination":
                        obj.db_destination = init_spawn_value(val, value_to_obj)
                    elif key == "locks":
                        if directive == "REPLACE":
                            obj.locks.clear()
                        obj.locks.add(init_spawn_value(val, str))
                    elif key == "permissions":
                        if directive == "REPLACE":
                            obj.permissions.clear()
                        obj.permissions.batch_add(*(init_spawn_value(perm, str) for perm in val))
                    elif key == "aliases":
                        if directive == "REPLACE":
                            obj.aliases.clear()
                        obj.aliases.batch_add(*(init_spawn_value(alias, str) for alias in val))
                    elif key == "tags":
                        if directive == "REPLACE":
                            obj.tags.clear()
                        obj.tags.batch_add(
                            *(
                                (init_spawn_value(ttag, str), tcategory, tdata)
                                for ttag, tcategory, tdata in val
                            )
                        )
                    elif key == "attrs":
                        if directive == "REPLACE":
                            obj.attributes.clear()
                        obj.attributes.batch_add(
                            *(
                                (
                                    init_spawn_value(akey, str),
                                    init_spawn_value(aval, value_to_obj),
                                    acategory,
                                    alocks,
                                )
                                for akey, aval, acategory, alocks in val
                            )
                        )
                    elif key == "exec":
                        # we don't auto-rerun exec statements, it would be huge security risk!
                        pass
                    else:
                        obj.attributes.add(key, init_spawn_value(val, value_to_obj))
                elif directive == "REMOVE":
                    do_save = True
                    if key == "key":
                        obj.db_key = ""
                    elif key == "typeclass":
                        # fall back to default
                        obj.db_typeclass_path = settings.BASE_OBJECT_TYPECLASS
                    elif key == "location":
                        obj.db_location = None
                    elif key == "home":
                        obj.db_home = None
                    elif key == "destination":
                        obj.db_destination = None
                    elif key == "locks":
                        obj.locks.clear()
                    elif key == "permissions":
                        obj.permissions.clear()
                    elif key == "aliases":
                        obj.aliases.clear()
                    elif key == "tags":
                        obj.tags.clear()
                    elif key == "attrs":
                        obj.attributes.clear()
                    elif key == "exec":
                        # we don't auto-rerun exec statements, it would be huge security risk!
                        pass
                    else:
                        obj.attributes.remove(key)
        except Exception:
            logger.log_trace(f"Failed to apply prototype '{prototype_key}' to {obj}.")
        finally:
            # we must always make sure to re-add the prototype tag
            obj.tags.clear(category=PROTOTYPE_TAG_CATEGORY)
            obj.tags.add(prototype_key, category=PROTOTYPE_TAG_CATEGORY)

        if do_save:
            changed += 1
            obj.save()

    return changed
Exemple #20
0
def spawn(*prototypes, **kwargs):
    """
    Spawn a number of prototyped objects.

    Args:
        prototypes (dict): Each argument should be a prototype
            dictionary.
    Kwargs:
        prototype_modules (str or list): A python-path to a 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.
        prototype_parents (dict): A dictionary holding a custom
            prototype-parent dictionary. Will overload same-named
            prototypes from prototype_modules.
        return_parents (bool): Only return a dict of the
            prototype-parents (no object creation happens)
        only_validate (bool): Only run validation of prototype/parents
            (no object creation) and return the create-kwargs.

    Returns:
        object (Object, dict or list): Spawned object(s). If `only_validate` is given, return
            a list of the creation kwargs to build the object(s) without actually creating it. If
            `return_parents` is set, instead return dict of prototype parents.

    """
    # get available protparents
    protparents = {
        prot['prototype_key'].lower(): prot
        for prot in protlib.search_prototype()
    }

    if not kwargs.get("only_validate"):
        # homogenization to be more lenient about prototype format when entering the prototype manually
        prototypes = [
            protlib.homogenize_prototype(prot) for prot in prototypes
        ]

    # overload module's protparents with specifically given protparents
    # we allow prototype_key to be the key of the protparent dict, to allow for module-level
    # prototype imports. We need to insert prototype_key in this case
    for key, protparent in kwargs.get("prototype_parents", {}).items():
        key = str(key).lower()
        protparent['prototype_key'] = str(protparent.get("prototype_key",
                                                         key)).lower()
        protparents[key] = protparent

    if "return_parents" in kwargs:
        # only return the parents
        return copy.deepcopy(protparents)

    objsparams = []
    for prototype in prototypes:

        protlib.validate_prototype(prototype,
                                   None,
                                   protparents,
                                   is_prototype_base=True)
        prot = _get_prototype(
            prototype,
            protparents,
            uninherited={"prototype_key": prototype.get("prototype_key")})
        if not prot:
            continue

        # extract the keyword args we need to create the object itself. If we get a callable,
        # call that to get the value (don't catch errors)
        create_kwargs = {}
        # we must always add a key, so if not given we use a shortened md5 hash. There is a (small)
        # chance this is not unique but it should usually not be a problem.
        val = prot.pop(
            "key",
            "Spawned-{}".format(hashlib.md5(str(time.time())).hexdigest()[:6]))
        create_kwargs["db_key"] = init_spawn_value(val, str)

        val = prot.pop("location", None)
        create_kwargs["db_location"] = init_spawn_value(val, value_to_obj)

        val = prot.pop("home", settings.DEFAULT_HOME)
        create_kwargs["db_home"] = init_spawn_value(val, value_to_obj)

        val = prot.pop("destination", None)
        create_kwargs["db_destination"] = init_spawn_value(val, value_to_obj)

        val = prot.pop("typeclass", settings.BASE_OBJECT_TYPECLASS)
        create_kwargs["db_typeclass_path"] = init_spawn_value(val, str)

        # extract calls to handlers
        val = prot.pop("permissions", [])
        permission_string = init_spawn_value(val, make_iter)
        val = prot.pop("locks", "")
        lock_string = init_spawn_value(val, str)
        val = prot.pop("aliases", [])
        alias_string = init_spawn_value(val, make_iter)

        val = prot.pop("tags", [])
        tags = []
        for (tag, category, data) in val:
            tags.append((init_spawn_value(tag, str), category, data))

        prototype_key = prototype.get('prototype_key', None)
        if prototype_key:
            # we make sure to add a tag identifying which prototype created this object
            tags.append((prototype_key, _PROTOTYPE_TAG_CATEGORY))

        val = prot.pop("exec", "")
        execs = init_spawn_value(val, make_iter)

        # extract ndb assignments
        nattributes = dict(
            (key.split("_", 1)[1], init_spawn_value(val, value_to_obj))
            for key, val in prot.items() if key.startswith("ndb_"))

        # the rest are attribute tuples (attrname, value, category, locks)
        val = make_iter(prot.pop("attrs", []))
        attributes = []
        for (attrname, value, category, locks) in val:
            attributes.append(
                (attrname, init_spawn_value(value), category, locks))

        simple_attributes = []
        for key, value in ((key, value) for key, value in prot.items()
                           if not (key.startswith("ndb_"))):
            # we don't support categories, nor locks for simple attributes
            if key in _PROTOTYPE_META_NAMES:
                continue
            else:
                simple_attributes.append(
                    (key, init_spawn_value(value,
                                           value_to_obj_or_any), None, None))

        attributes = attributes + simple_attributes
        attributes = [
            tup for tup in attributes if not tup[0] in _NON_CREATE_KWARGS
        ]

        # pack for call into _batch_create_object
        objsparams.append((create_kwargs, permission_string, lock_string,
                           alias_string, nattributes, attributes, tags, execs))

    if kwargs.get("only_validate"):
        return objsparams
    return batch_create_object(*objsparams)
Exemple #21
0
def batch_update_objects_with_prototype(prototype, diff=None, objects=None):
    """
    Update existing objects with the latest version of the prototype.

    Args:
        prototype (str or dict): Either the `prototype_key` to use or the
            prototype dict itself.
        diff (dict, optional): This a diff structure that describes how to update the protototype.
            If not given this will be constructed from the first object found.
        objects (list, optional): List of objects to update. If not given, query for these
            objects using the prototype's `prototype_key`.
    Returns:
        changed (int): The number of objects that had changes applied to them.

    """
    prototype = protlib.homogenize_prototype(prototype)

    if isinstance(prototype, basestring):
        new_prototype = protlib.search_prototype(prototype)
    else:
        new_prototype = prototype

    prototype_key = new_prototype['prototype_key']

    if not objects:
        objects = ObjectDB.objects.get_by_tag(prototype_key, category=_PROTOTYPE_TAG_CATEGORY)

    if not objects:
        return 0

    if not diff:
        diff, _ = prototype_diff_from_object(new_prototype, objects[0])

    # make sure the diff is flattened
    diff = flatten_diff(diff)
    changed = 0
    for obj in objects:
        do_save = False

        old_prot_key = obj.tags.get(category=_PROTOTYPE_TAG_CATEGORY, return_list=True)
        old_prot_key = old_prot_key[0] if old_prot_key else None
        if prototype_key != old_prot_key:
            obj.tags.clear(category=_PROTOTYPE_TAG_CATEGORY)
            obj.tags.add(prototype_key, category=_PROTOTYPE_TAG_CATEGORY)

        for key, directive in diff.items():
            if directive in ('UPDATE', 'REPLACE'):

                if key in _PROTOTYPE_META_NAMES:
                    # prototype meta keys are not stored on-object
                    continue

                val = new_prototype[key]
                do_save = True

                if key == 'key':
                    obj.db_key = init_spawn_value(val, str)
                elif key == 'typeclass':
                    obj.db_typeclass_path = init_spawn_value(val, str)
                elif key == 'location':
                    obj.db_location = init_spawn_value(val, value_to_obj)
                elif key == 'home':
                    obj.db_home = init_spawn_value(val, value_to_obj)
                elif key == 'destination':
                    obj.db_destination = init_spawn_value(val, value_to_obj)
                elif key == 'locks':
                    if directive == 'REPLACE':
                        obj.locks.clear()
                    obj.locks.add(init_spawn_value(val, str))
                elif key == 'permissions':
                    if directive == 'REPLACE':
                        obj.permissions.clear()
                    obj.permissions.batch_add(*(init_spawn_value(perm, str) for perm in val))
                elif key == 'aliases':
                    if directive == 'REPLACE':
                        obj.aliases.clear()
                    obj.aliases.batch_add(*(init_spawn_value(alias, str) for alias in val))
                elif key == 'tags':
                    if directive == 'REPLACE':
                        obj.tags.clear()
                    obj.tags.batch_add(*(
                        (init_spawn_value(ttag, str), tcategory, tdata)
                        for ttag, tcategory, tdata in val))
                elif key == 'attrs':
                    if directive == 'REPLACE':
                        obj.attributes.clear()
                    obj.attributes.batch_add(*(
                        (init_spawn_value(akey, str),
                         init_spawn_value(aval, value_to_obj),
                         acategory,
                         alocks)
                        for akey, aval, acategory, alocks in val))
                elif key == 'exec':
                    # we don't auto-rerun exec statements, it would be huge security risk!
                    pass
                else:
                    obj.attributes.add(key, init_spawn_value(val, value_to_obj))
            elif directive == 'REMOVE':
                do_save = True
                if key == 'key':
                    obj.db_key = ''
                elif key == 'typeclass':
                    # fall back to default
                    obj.db_typeclass_path = settings.BASE_OBJECT_TYPECLASS
                elif key == 'location':
                    obj.db_location = None
                elif key == 'home':
                    obj.db_home = None
                elif key == 'destination':
                    obj.db_destination = None
                elif key == 'locks':
                    obj.locks.clear()
                elif key == 'permissions':
                    obj.permissions.clear()
                elif key == 'aliases':
                    obj.aliases.clear()
                elif key == 'tags':
                    obj.tags.clear()
                elif key == 'attrs':
                    obj.attributes.clear()
                elif key == 'exec':
                    # we don't auto-rerun exec statements, it would be huge security risk!
                    pass
                else:
                    obj.attributes.remove(key)
        if do_save:
            changed += 1
            obj.save()

    return changed