-
-
Notifications
You must be signed in to change notification settings - Fork 115
Adds weapon, break_sound, equippable, and swing_animation item components.
#2821
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| package com.denizenscript.denizen.paper.datacomponents; | ||
|
|
||
| import com.denizenscript.denizen.utilities.Utilities; | ||
| import com.denizenscript.denizencore.objects.Mechanism; | ||
| import com.denizenscript.denizencore.objects.core.ElementTag; | ||
| import io.papermc.paper.datacomponent.DataComponentTypes; | ||
| import net.kyori.adventure.key.Key; | ||
|
|
||
| public class BreakSoundAdapter extends DataComponentAdapter.Valued<ElementTag, Key> { | ||
|
|
||
| // <--[property] | ||
| // @object ItemTag | ||
| // @name break_sound | ||
| // @input ElementTag | ||
| // @description | ||
| // Controls an item's break sound <@link language Item Components> in namespaced key format. | ||
| // The default namespace is "minecraft", so for example an input of "block.anvil.land" becomes "minecraft:block.anvil.land". | ||
| // @mechanism | ||
| // Provide no input to reset the item to its default value. | ||
| // --> | ||
|
|
||
| public BreakSoundAdapter() { | ||
| super(ElementTag.class, DataComponentTypes.BREAK_SOUND, "break_sound"); | ||
| } | ||
|
|
||
| @Override | ||
| public ElementTag toDenizen(Key value) { | ||
| return new ElementTag(value.asMinimalString(), true); | ||
| } | ||
|
|
||
| @Override | ||
| public Key fromDenizen(ElementTag value, Mechanism mechanism) { | ||
| return Utilities.parseNamespacedKey(value.asString()); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| package com.denizenscript.denizen.paper.datacomponents; | ||
|
|
||
| import com.denizenscript.denizen.utilities.Utilities; | ||
| import com.denizenscript.denizencore.objects.Mechanism; | ||
| import com.denizenscript.denizencore.objects.core.ElementTag; | ||
| import com.denizenscript.denizencore.objects.core.ListTag; | ||
| import com.denizenscript.denizencore.objects.core.MapTag; | ||
| import io.papermc.paper.datacomponent.DataComponentTypes; | ||
| import io.papermc.paper.datacomponent.item.Equippable; | ||
| import io.papermc.paper.registry.RegistryKey; | ||
| import io.papermc.paper.registry.TypedKey; | ||
| import io.papermc.paper.registry.set.RegistrySet; | ||
| import org.bukkit.entity.EntityType; | ||
| import org.bukkit.inventory.EquipmentSlot; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
| public class EquippableAdapter extends DataComponentAdapter.Valued<MapTag, Equippable> { | ||
|
|
||
| // <--[property] | ||
| // @object ItemTag | ||
| // @name equippable | ||
| // @input MapTag | ||
| // @description | ||
| // Controls the properties of an item's equippable <@link language Item Components>. | ||
| // The map includes keys: | ||
| // - "slot", an ElementTag representing the equipment slot. Valid values: HAND, OFF_HAND, FEET, LEGS, CHEST, HEAD, BODY. | ||
| // - "equip_sound", an ElementTag representing the sound played when equipping this item in namespaced key format. | ||
| // - "asset_id", an ElementTag representing the asset id for this item in namespaced key format. | ||
| // - "camera_overlay", an ElementTag representing the camera overlay to use when the item is equipped in namespaced key format. | ||
| // - "allowed_entities", a ListTag(EntityTag) representing entity types that can equip this item. If not set, all entities are allowed to wear this item. | ||
| // - "dispensable", a ElementTag(Boolean) controlling whether the item can be dispensed. | ||
| // - "swappable", a ElementTag(Boolean) controlling whether the item can be swapped. | ||
| // - "damage_on_hurt", a ElementTag(Boolean) controlling whether the item takes damage when the wearer is hurt. | ||
| // - "equip_on_interact", a ElementTag(Boolean) controlling whether the item is equipped on entity interaction. | ||
| // - "can_be_sheared", a ElementTag(Boolean) controlling whether the item can be sheared off an entity. | ||
| // - "shear_sound", an ElementTag representing the sound played when shearing using this item in namespaced key format. | ||
| // @mechanism | ||
| // Provide no input to reset the item to its default value. | ||
| // --> | ||
|
|
||
| public EquippableAdapter() { | ||
| super(MapTag.class, DataComponentTypes.EQUIPPABLE, "equippable"); | ||
| } | ||
|
|
||
| @Override | ||
| public MapTag toDenizen(Equippable value) { | ||
| MapTag map = new MapTag(); | ||
| map.putObject("slot", new ElementTag(value.slot())); | ||
| map.putObject("equip_sound", new ElementTag(value.equipSound().asMinimalString(), true)); | ||
| if (value.assetId() != null) { | ||
| map.putObject("asset_id", new ElementTag(value.assetId().asMinimalString(), true)); | ||
| } | ||
| if (value.cameraOverlay() != null) { | ||
| map.putObject("camera_overlay", new ElementTag(value.cameraOverlay().asMinimalString(), true)); | ||
| } | ||
| if (value.allowedEntities() != null) { | ||
| ListTag entities = new ListTag(); | ||
| value.allowedEntities().forEach(key -> entities.addObject(new ElementTag(key.key().asMinimalString(), true))); | ||
| map.putObject("allowed_entities", entities); | ||
| } | ||
| map.putObject("dispensable", new ElementTag(value.dispensable())); | ||
| map.putObject("swappable", new ElementTag(value.swappable())); | ||
| map.putObject("damage_on_hurt", new ElementTag(value.damageOnHurt())); | ||
| map.putObject("equip_on_interact", new ElementTag(value.equipOnInteract())); | ||
| map.putObject("can_be_sheared", new ElementTag(value.canBeSheared())); | ||
| map.putObject("shear_sound", new ElementTag(value.shearSound().asMinimalString(), true)); | ||
| return map; | ||
| } | ||
|
|
||
| @Override | ||
| public Equippable fromDenizen(MapTag value, Mechanism mechanism) { | ||
| ElementTag slot = value.getObjectAs("slot", ElementTag.class, mechanism.context); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this can just be |
||
| if (slot == null) { | ||
| mechanism.echoError("Equippable map must have a 'slot' key."); | ||
| return null; | ||
| } | ||
| if (!slot.matchesEnum(EquipmentSlot.class)) { | ||
| mechanism.echoError("Invalid 'slot' specified for equippable: must be a valid EquipmentSlot."); | ||
| return null; | ||
| } | ||
| Equippable.Builder builder = Equippable.equippable(slot.asEnum(EquipmentSlot.class)); | ||
| setIfValid(builder::equipSound, value, "equip_sound", ElementTag.class, null, element -> Utilities.parseNamespacedKey(element.asString()), "namespaced key", mechanism); | ||
| setIfValid(builder::assetId, value, "asset_id", ElementTag.class, null, element -> Utilities.parseNamespacedKey(element.asString()), "namespaced key", mechanism); | ||
| setIfValid(builder::cameraOverlay, value, "camera_overlay", ElementTag.class, null, element -> Utilities.parseNamespacedKey(element.asString()), "namespaced key", mechanism); | ||
| setIfValid(builder::dispensable, value, "dispensable", ElementTag.class, ElementTag::isBoolean, ElementTag::asBoolean, "boolean", mechanism); | ||
| setIfValid(builder::swappable, value, "swappable", ElementTag.class, ElementTag::isBoolean, ElementTag::asBoolean, "boolean", mechanism); | ||
| setIfValid(builder::damageOnHurt, value, "damage_on_hurt", ElementTag.class, ElementTag::isBoolean, ElementTag::asBoolean, "boolean", mechanism); | ||
| setIfValid(builder::equipOnInteract, value, "equip_on_interact", ElementTag.class, ElementTag::isBoolean, ElementTag::asBoolean, "boolean", mechanism); | ||
| setIfValid(builder::canBeSheared, value, "can_be_sheared", ElementTag.class, ElementTag::isBoolean, ElementTag::asBoolean, "boolean", mechanism); | ||
| setIfValid(builder::shearSound, value, "shear_sound", ElementTag.class, null, element -> Utilities.parseNamespacedKey(element.asString()), "namespaced key", mechanism); | ||
| ListTag entityList = value.getObjectAs("allowed_entities", ListTag.class, mechanism.context); | ||
| if (entityList != null) { | ||
| List<TypedKey<EntityType>> keys = new ArrayList<>(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nitpick, but can initialize to the correct size here |
||
| for (String entry : entityList) { | ||
| keys.add(TypedKey.create(RegistryKey.ENTITY_TYPE, Utilities.parseNamespacedKey(entry))); | ||
| } | ||
| builder.allowedEntities(RegistrySet.keySet(RegistryKey.ENTITY_TYPE, keys)); | ||
| } | ||
| return builder.build(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| package com.denizenscript.denizen.paper.datacomponents; | ||
|
|
||
| import com.denizenscript.denizencore.objects.Mechanism; | ||
| import com.denizenscript.denizencore.objects.core.ElementTag; | ||
| import com.denizenscript.denizencore.objects.core.MapTag; | ||
| import io.papermc.paper.datacomponent.DataComponentTypes; | ||
| import io.papermc.paper.datacomponent.item.SwingAnimation; | ||
|
|
||
| public class SwingAnimationAdapter extends DataComponentAdapter.Valued<MapTag, SwingAnimation> { | ||
|
|
||
| // <--[property] | ||
| // @object ItemTag | ||
| // @name swing_animation | ||
| // @input ElementTag | ||
| // @description | ||
| // Controls an item's swing animation <@link language Item Components>. | ||
| // The map includes keys: | ||
| // - "animation_type", an ElementTag representing the animation type. Valid animation types can be found at <@link url https://jd.papermc.io/paper/io/papermc/paper/datacomponent/item/SwingAnimation.Animation.html> | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing |
||
| // - "duration", an ElementTag(Number) representing the duration of the animation. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| // @mechanism | ||
| // Provide no input to reset the item to its default value. | ||
| // --> | ||
|
|
||
| public SwingAnimationAdapter() { | ||
| super(MapTag.class, DataComponentTypes.SWING_ANIMATION, "swing_animation"); | ||
| } | ||
|
|
||
| @Override | ||
| public MapTag toDenizen(SwingAnimation value) { | ||
| MapTag result = new MapTag(); | ||
| result.putObject("animation_type", new ElementTag(value.type())); | ||
| result.putObject("duration", new ElementTag(value.duration())); | ||
| return result; | ||
| } | ||
|
|
||
| @Override | ||
| public SwingAnimation fromDenizen(MapTag value, Mechanism mechanism) { | ||
| SwingAnimation.Builder builder = SwingAnimation.swingAnimation(); | ||
| setIfValid(builder::type, value, "animation_type", ElementTag.class, | ||
| element -> element.matchesEnum(SwingAnimation.Animation.class), | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can test, but pretty sure this is redundant - |
||
| element -> element.asEnum(SwingAnimation.Animation.class), | ||
| "animation type", mechanism); | ||
| setIfValid(builder::duration, value, "duration", ElementTag.class, ElementTag::isInt, ElementTag::asInt, "number", mechanism); | ||
| return builder.build(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| package com.denizenscript.denizen.paper.datacomponents; | ||
|
|
||
| import com.denizenscript.denizencore.objects.Mechanism; | ||
| import com.denizenscript.denizencore.objects.core.ElementTag; | ||
| import com.denizenscript.denizencore.objects.core.MapTag; | ||
| import io.papermc.paper.datacomponent.DataComponentTypes; | ||
| import io.papermc.paper.datacomponent.item.Weapon; | ||
|
|
||
| public class WeaponAdapter extends DataComponentAdapter.Valued<MapTag, Weapon> { | ||
|
|
||
| // <--[property] | ||
| // @object ItemTag | ||
| // @name weapon | ||
| // @input MapTag | ||
| // @description | ||
| // Controls an item's weapon <@link language Item Components>. | ||
| // The map includes keys: | ||
| // - "disable_blocking_duration", an ElementTag(Decimal) representing the number of seconds that a shield will be disabled for after blocking an attack from this item. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| // - "item_damage_per_attack", an ElementTag(Number) representing the amount of durability damage this item will take when used to attack an entity or break a block. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| // @mechanism | ||
| // Provide no input to reset the item to its default value. | ||
| // --> | ||
|
|
||
| public WeaponAdapter() { | ||
| super(MapTag.class, DataComponentTypes.WEAPON, "weapon"); | ||
| } | ||
|
|
||
| @Override | ||
| public MapTag toDenizen(Weapon value) { | ||
| MapTag weaponData = new MapTag(); | ||
| weaponData.putObject("disable_blocking_duration", new ElementTag(value.disableBlockingForSeconds())); | ||
| weaponData.putObject("item_damage_per_attack", new ElementTag(value.itemDamagePerAttack())); | ||
| return weaponData; | ||
| } | ||
|
|
||
| @Override | ||
| public Weapon fromDenizen(MapTag value, Mechanism mechanism) { | ||
| Weapon.Builder builder = Weapon.weapon(); | ||
| setIfValid(builder::disableBlockingForSeconds, value, "disable_blocking_duration", ElementTag.class, ElementTag::isFloat, ElementTag::asFloat, "decimal number", mechanism); | ||
| setIfValid(builder::itemDamagePerAttack, value, "item_damage_per_attack", ElementTag.class, ElementTag::isInt, ElementTag::asInt, "number", mechanism); | ||
| return builder.build(); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Meta says
ListTag(EntityTag)(which is probably correct for this), but these areElementTagsAlso, should be able to use
RegistryKeySet#valueswith theLisTagconvertor constructor instead of looping over