Mechanisms And Properties¶
Table of Contents
Mechanisms are a way to directly change a single value on an object. They're kind of like mini-commands, designed to work as part of the property system.
Here are a few examples of simple mechanisms, used in script containers:
ultra_sword: type: item display name: Ultra Sword material: diamond_sword mechanisms: unbreakable: true
This script, using the
mechanisms key of
item script containers, has the mechanism named
unbreakable set to the value
true, which makes the item never take durability damage.
undead_golden_swordsman: type: entity entity_type: zombie mechanisms: item_in_hand: golden_sword item_in_offhand: golden_sword health_data: 80/80
entity script creates a zombie and uses the
item_in_offhand mechanisms to put golden swords in both hands. It also spawns with 80 health, and has 80 health at maximum, using the
Mechanisms can be used in more than just script containers! If you need to alter the value of a mechanism, the
adjust command is the way to go.
For example, if we want to write a script that changes the color of a sheep when right-clicked:
random_sheep_colors: type: world events: after player right clicks sheep with:stick: - adjust <context.entity> color:<context.entity.allowed_colors.random>
Using this script, when a player right-clicks any sheep mob with a stick in hand, the sheep mob will change to a random color.
adjust command can be used to adjust mechanisms on most object types (players, entities, the server, ...) but some situations call for different ways of applying mechanisms.
adjustblock command is a variant of the normal
adjust command. It's built specifically to adjust
material mechanisms on blocks (a list of which can be found here).
While the applicability of
adjustblock is more niche, it can still be quite useful. For a quick usage example, you can use this script to force a plant block to immediately change to its maximum age (eg. to cause newly-planted wheat to fully grow):
plant_grower: type: world events: after player right clicks block with:stick: - if <player.cursor_on.material.supports[age]>: - adjustblock <player.cursor_on> age:<player.cursor_on.material.maximum_age>
You can also adjust the properties of items in inventories. Doing so uses the
inventory command with the
You might assume that the way to modify an item held by a player is by adjusting the item itself:
flint_fancifier_bad: type: world events: after player right clicks block with:flint: - adjust <player.item_in_hand> "display:Fancy Flint" - adjust <player.item_in_hand> "lore:Built with Denizen!"
However, the tag
<player.item_in_hand> will just return "flint", with no indication of which flint item. In effect, the above script is attempting to modify the abstract concept of flint items, rather than the specific flint in the player's hand. If you're not adjusting a specific item that exists in the world somehow, nothing is going to change in the world!
So instead, the usual way to adjust an item is to use the
adjust argument to adjust the specific item that you want to change.
The below example will correctly modify a player's held item when they right click with it:
flint_fancifier: type: world events: after player right clicks block with:flint: - inventory adjust slot:hand "display:Fancy Flint" - inventory adjust slot:hand "lore:Built with Denizen!"
inventory adjust command will specifically change the item at issue, because that's what it is designed to do! Because you identify the unique object of the item as it exists in the player's inventory (as a reference a specific slot within an inventory), the
inventory adjust command is therefore able to modify it as desired.
In some cases, the
.with tag is convenient for adjusting mechanisms on an item. Unlike the
inventory adjust command, which has to operate on a real pre-existing item, the
with tag takes any conceptual item, and returns a copy of that conceptual item with the mechanisms applied, which can then be put into any command that accepts items as normal.
Say for example that rather than changing the name of the player's held item, you instead want to give them a new copy of that item with a different name or with repairs.
sword_duplicator: type: world events: after player right clicks bedrock with:diamond_sword: - ratelimit <player> 1h - give "<player.item_in_hand.with[display=Your Free Duplicate Sword].with[durability=0]>" - narrate "<&b>Sword duplicated!"
The above script example allows players to take a diamond sword down to bedrock level to get a repaired duplicate made, no more than once per hour.
As you can see in the example above, like any tag, the
with tag can simply be placed on the end of any
ItemTag, and because it returns an
ItemTag, you can also chain multiple
with tags in a row.
Note also that there is also a
with tag available for
MaterialTag objects, to achieve similar logic with blocks.
adjust command can also be used to modify an object stored in a definition and automatically apply the resultant object back into the definition.
This is a relatively niche use case, but it can come in handy at times. In particular, this allows for
if commands to be used to choose which mechanisms need to be applied to an object prior to actually performing changes.
sword_duplicator: type: world events: after player right clicks bedrock with:diamond_sword: - ratelimit <player> 1h - define sword <player.item_in_hand> - adjust def:sword "display:Your Free Duplicate Sword" - if <player.location> matches lava: - adjust def:sword "lore:<&c>Forged in lava." - adjust def:sword durability:0 - give <[sword]> - narrate "<&b>Sword duplicated!"
This script is similar to the sword duplicator in the
with tag example, but now only repairs the duplicate sword if the player is daring enough to jump into lava before clicking bedrock. (You can comment out the
ratelimit by putting a
# symbol before the
-, to be able to test the script without having to wait.)
This way of adjusting items also has the advantage of being slightly cleaner when changing many mechanisms at once, thanks to the more linear format.
"Properties" are a system to track the details of an object that doesn't have a unique identity of its own.
Generally, every properties consist of one tag and one mechanism. The tag reads the current value, and the mechanism applies a new value. In many cases, they will also be associated with additional helpful tags and/or mechanisms to make things easier when trying to interact with a property through a script. Note that while every property has a tag and mechanism, not every tag or mechanism is related to a property.
Properties are most noticeable from their usage in Denizen internal object descriptions. Object descriptions are the full reusable description of any object, generally marked with object notation (like
i@) in front of it. This is primarily for internal data tracking, and you will most often only see it in your debug console.
The most common place that properties are seen in use is with items. In Denizen, an item is a material and a series of properties. For example, if you hit an entity with a freshly-crafted diamond sword in survival mode and then run
/ex narrate <player.item_in_hand> to view the Denizen internal description of that item, you'll see it return
i@diamond_sword[durability=1]. In this case,
durability is the only property of the item, and its value is
1, the amount of durability the item has lost thus far. Multiple properties are separated by semicolons. For example,
i@diamond_sword[durability=1;display_name=Skullbuster]. (Remember, don't type raw object notation into a script - these are examples of internal data formats, not anything that can be put in a script directly)
Items are, fundamentally, their material and their properties. Any item a player has in their inventory can be parsed in this manner, and any item's properties can be read or modified as desired.
Materials, like items, lack unique identities. A stone block is just a material at a location. A wheat block is only slightly more complicated - it's a material at a location with an
age property. As you saw above in the
adjustblock example, using the
age mechanism allows you to modify that property for a block in the world. When you read block materials from locations, they will return any associated properties. This could be used, for example, to check whether a campfire is sending up smoke signals, or various redstone properties, or even the faces of a mushroom block.
Materials with properties, when parsed by a tag like
<player.cursor_on.material>, will return an output like
m@wheat[age=7] for a fully-grown wheat block. In this case, the
age of the wheat is
Entities have properties too! Entity properties can be read and modified just like material properties, and you can see a list of all of an entity's properties with the
<EntityTag.describe> tag. For example, here's a sample output of
/ex narrate <player.target.describe> when targeting a sheep modified by our color script:
As you can see above, all of the data about the sheep is captured by Denizen and output in the format of an EntityTag with various properties. Each property is separated by a semicolon, and the data stored in each property varies based on the nature of the property.
These properties can be adjusted using the
adjust command or read by using their corresponding tags. As the property is named
color, we can assume that there is both a mechanism and a tag named
color for EntityTag objects.
/ex narrate "The <player.target.entity_type> you're looking at is colored <player.target.color>" will narrate, for example,
The SHEEP you're looking at is colored orange based on the data above.
It can sometimes be helpful to use properties directly in a script. When you just need an object with a few properties, it can be more convenient to type them in-line rather than building an entire script container for it.
Consider the following examples:
sand_cannon: type: world events: after player right clicks air with:sand: - shoot falling_block[fallingblock_type=sand] origin:<player> speed:1
The above script, when a player clicks open air while holding sand, launches
falling_block entities, and specifies that they should use the
sand material via property syntax.
pumpkin_meloner: type: world events: after player right clicks pumpkin_stem with:golden_hoe: - modifyblock <context.location> melon_stem[age=7]
The above script lets players click on a pumpkin stem with a golden hoe to turn it into a melon stem, and uses property syntax to specify that the melon stem should be fully grown.
Note that this style of inline property specification doesn't work when you need tags for the values - at which point, use the relevant tags like