diff --git a/src/main/java/org/skriptlang/skript/bukkit/item/ItemModule.java b/src/main/java/org/skriptlang/skript/bukkit/item/ItemModule.java index d3b5d311cda..759f7a4b236 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/item/ItemModule.java +++ b/src/main/java/org/skriptlang/skript/bukkit/item/ItemModule.java @@ -24,7 +24,9 @@ public Iterable children() { @Override public void loadSelf(SkriptAddon addon) { register(addon, + ExprItemModel::register, ExprItemWithLore::register, + ExprItemWithModel::register, ExprLore::register ); } diff --git a/src/main/java/org/skriptlang/skript/bukkit/item/elements/ExprItemModel.java b/src/main/java/org/skriptlang/skript/bukkit/item/elements/ExprItemModel.java new file mode 100644 index 00000000000..fd74de59272 --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/item/elements/ExprItemModel.java @@ -0,0 +1,83 @@ +package org.skriptlang.skript.bukkit.item.elements; + +import ch.njol.skript.aliases.ItemType; +import ch.njol.skript.bukkitutil.NamespacedUtils; +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Example; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.expressions.base.SimplePropertyExpression; +import ch.njol.util.coll.CollectionUtils; +import org.bukkit.NamespacedKey; +import org.bukkit.event.Event; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.registration.SyntaxRegistry; + +import static ch.njol.skript.classes.Changer.ChangeMode.SET; + +@Name("Item Model") +@Description("The item model of an item. Accepts a Namespaced Key (e.g. 'minecraft:emerald').") +@Example(""" + set the item model of player's held item to "diamond" + set the item model of {_item} to "minecraft:dirt" + """) +@Since("INSERT VERSION") +public class ExprItemModel extends SimplePropertyExpression { + + public static void register(SyntaxRegistry syntaxRegistry) { + syntaxRegistry.register( + SyntaxRegistry.EXPRESSION, + infoBuilder(ExprItemModel.class, String.class, "item model", "itemtypes", true) + .supplier(ExprItemModel::new) + .build() + ); + } + + @Override + public @Nullable String convert(ItemType from) { + NamespacedKey key = from.getItemMeta().getItemModel(); + if (key == null) + return null; + + return key.asString(); + } + + @Override + public Class @Nullable [] acceptChange(ChangeMode mode) { + return switch (mode) { + case SET, DELETE, RESET -> CollectionUtils.array(String.class); + default -> null; + }; + } + + @Override + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { + NamespacedKey key = null; + if (mode == SET) { + //noinspection DataFlowIssue + key = NamespacedUtils.checkValidationAndSend((String) delta[0], this); + if (key == null) { + return; + } + } + + for (ItemType item : getExpr().getArray(event)) { + ItemMeta meta = item.getItemMeta(); + meta.setItemModel(key); + item.setItemMeta(meta); + } + } + + @Override + public Class getReturnType() { + return String.class; + } + + @Override + protected String getPropertyName() { + return "item model"; + } + +} diff --git a/src/main/java/org/skriptlang/skript/bukkit/item/elements/ExprItemWithModel.java b/src/main/java/org/skriptlang/skript/bukkit/item/elements/ExprItemWithModel.java new file mode 100644 index 00000000000..6cca83cf10f --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/item/elements/ExprItemWithModel.java @@ -0,0 +1,76 @@ +package org.skriptlang.skript.bukkit.item.elements; + +import ch.njol.skript.aliases.ItemType; +import ch.njol.skript.bukkitutil.NamespacedUtils; +import ch.njol.skript.doc.*; +import ch.njol.skript.expressions.base.PropertyExpression; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.util.Kleenean; +import org.bukkit.NamespacedKey; +import org.bukkit.event.Event; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.registration.DefaultSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; + +@Name("Item With Model") +@Description("Returns a copy of an item with a custom item model. Accepts a Namespaced Key (e.g. 'minecraft:emerald').") +@Example(""" + set {_item} to emerald with model "minecraft:diamond" named "fake diamond"' + give {_item} to player + """) +@Since("INSERT VERSION") +@Keywords("item model") +public class ExprItemWithModel extends PropertyExpression { + + public static void register(SyntaxRegistry syntaxRegistry) { + syntaxRegistry.register( + SyntaxRegistry.EXPRESSION, + DefaultSyntaxInfos.Expression.builder(ExprItemWithModel.class, ItemType.class) + .addPattern("%itemtype% with [the] [item] model %string%") + .supplier(ExprItemWithModel::new) + .build() + ); + } + + private Expression key; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + setExpr((Expression) exprs[0]); + key = (Expression) exprs[1]; + return true; + } + + @Override + protected ItemType[] get(Event event, ItemType[] source) { + String key = this.key.getSingle(event); + if (key == null) + return source; + + NamespacedKey namespacedKey = NamespacedUtils.checkValidationAndSend(key, this); + if (namespacedKey == null) + return source; + + return get(source, itemType -> { + itemType = itemType.clone(); + ItemMeta itemMeta = itemType.getItemMeta(); + itemMeta.setItemModel(namespacedKey); + itemType.setItemMeta(itemMeta); + return itemType; + }); + } + + @Override + public Class getReturnType() { + return ItemType.class; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return getExpr().toString(event, debug) + " with item model " + key.toString(event, debug); + } + +} diff --git a/src/test/skript/tests/bukkit/item/ExprItemModel.sk b/src/test/skript/tests/bukkit/item/ExprItemModel.sk new file mode 100644 index 00000000000..5236e990e07 --- /dev/null +++ b/src/test/skript/tests/bukkit/item/ExprItemModel.sk @@ -0,0 +1,46 @@ +using error catching + +test "ExprItemModel": + set {_item} to diamond + + set item model of {_item} to "emerald" + assert item model of {_item} is "minecraft:emerald" with "Set item model of item" + + set {_inv} to chest inventory with 1 row named "test slots" + set slot 1 of {_inv} to diamond + + set item model of slot 1 of {_inv} to "emerald" + + assert item model of slot 1 of {_inv} is "minecraft:emerald" with "Set item model of slot from container" + + set {_item} to dirt with item model "diamond" + assert item model of {_item} is "minecraft:diamond" with "ItemType with item model" + + reset item model of {_item} + assert item model of {_item} is not set with "Reset item model of item" + + set item model of {_item} to "minecraft:redstone" + delete item model of {_item} + assert item model of {_item} is not set with "Delete item model of item" + + set {_string} to "test_string" + set item model of {_item} to {_string} + assert item model of {_item} is "minecraft:test_string" with "Set item model from variable string" + + set item model of {_item} to {_} + assert item model of {_item} is not set with "Set item model of item to null" + + set {_item} to diamond with model {_} + assert item model of {_item} is not set with "Item with null item model" + + set {_item} to emerald with model {_string} + assert item model of {_item} is "minecraft:test_string" with "Item with item model of variable string" + + set {_item} to diamond + catch runtime errors: + set item model of {_item} to "with spaces" + assert last caught runtime errors are set with "Runtime errors produced for invalid key for item model" + + catch runtime errors: + set {_item} to diamond with model "with spaces" + assert last caught runtime errors are set with "Runtime errors produced for invalid key for item with model"