diff --git a/src/main/java/ch/njol/skript/expressions/ExprNamed.java b/src/main/java/ch/njol/skript/expressions/ExprNamed.java index c01724bb7f2..b4e1346c97b 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprNamed.java +++ b/src/main/java/ch/njol/skript/expressions/ExprNamed.java @@ -35,60 +35,84 @@ import ch.njol.skript.expressions.base.PropertyExpression; import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.Literal; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.util.Getter; import ch.njol.util.Kleenean; -/** - * @author Peter Güttinger - */ @Name("Named Item/Inventory") -@Description("Directly names an item/inventory, useful for defining a named item/inventory in a script. " + - "If you want to (re)name existing items/inventories you can either use this expression or use set name of <item/inventory> to <text>.") -@Examples({"give a diamond sword of sharpness 100 named \"<gold>Excalibur\" to the player", - "set tool of player to the player's tool named \"<gold>Wand\"", - "set the name of the player's tool to \"<gold>Wand\"", - "open hopper inventory named \"Magic Hopper\" to player"}) +@Description({ + "Directly names an item/inventory, useful for defining a named item/inventory in a script.", + "If you want to (re)name existing items/inventories you can either use this expression " + + "or use set name of <item/inventory> to <text>." +}) +@Examples({ + "give a diamond sword of sharpness 100 named \"<gold>Excalibur\" to the player", + "set tool of player to the player's tool named \"<gold>Wand\"", + "set the name of the player's tool to \"<gold>Wand\"", + "open hopper inventory named \"Magic Hopper\" to player" +}) @Since("2.0, 2.2-dev34 (inventories)") public class ExprNamed extends PropertyExpression { + static { - Skript.registerExpression(ExprNamed.class, Object.class, ExpressionType.PROPERTY, + Skript.registerExpression(ExprNamed.class, Object.class, ExpressionType.COMBINED, "%itemtype/inventorytype% (named|with name[s]) %string%"); } - - @SuppressWarnings("null") + private Expression name; - - @SuppressWarnings({"unchecked", "null"}) + @Override - public boolean init(final Expression[] exprs, final int matchedPattern, final Kleenean isDelayed, final ParseResult parseResult) { - setExpr(exprs[0]); + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + // See issue #1822 as to why this convert is required. + if (exprs[0].getReturnType().equals(ItemStack.class)) { + setExpr(exprs[0].getConvertedExpression(ItemType.class)); + } else { + setExpr(exprs[0]); + } name = (Expression) exprs[1]; + if (getExpr() instanceof Literal) { + Literal literal = (Literal) getExpr(); + Object object = literal.getSingle(); + if (object instanceof InventoryType && !((InventoryType) object).isCreatable()) { + // Spigot forgot to label some InventoryType's as non creatable in some versions < 1.19.4 + // So this throws NullPointerException aswell ontop of the IllegalArgumentException. + // See https://hub.spigotmc.org/jira/browse/SPIGOT-7301 + Skript.error("You can't create a '" + literal.toString() + "' inventory. It's not creatable!"); + return false; + } + } return true; } - + @Override - protected Object[] get(final Event e, final Object[] source) { - String name = this.name.getSingle(e); + protected Object[] get(Event event, Object[] source) { + String name = this.name.getSingle(event); if (name == null) - return get(source, obj -> obj); // No name provided, do nothing + return get(source, object -> { + if (object instanceof InventoryType) { + try { + return Bukkit.createInventory(null, (InventoryType) object); + } catch (NullPointerException | IllegalArgumentException e) { + return null; + } + } + return object; // Return the same ItemType they passed without applying a name. + }); return get(source, new Getter() { @Override @Nullable - public Object get(Object obj) { - if (obj instanceof InventoryType) - return Bukkit.createInventory(null, (InventoryType) obj, name); - if (obj instanceof ItemStack) { - ItemStack stack = (ItemStack) obj; - stack = stack.clone(); - ItemMeta meta = stack.getItemMeta(); - if (meta != null) { - meta.setDisplayName(name); - stack.setItemMeta(meta); + public Object get(Object object) { + if (object instanceof InventoryType) { + try { + return Bukkit.createInventory(null, (InventoryType) object, name); + } catch (NullPointerException | IllegalArgumentException e) { + return null; } - return new ItemType(stack); } - ItemType item = (ItemType) obj; + assert object instanceof ItemType; + ItemType item = (ItemType) object; item = item.clone(); ItemMeta meta = item.getItemMeta(); meta.setDisplayName(name); @@ -97,15 +121,15 @@ public Object get(Object obj) { } }); } - + @Override public Class getReturnType() { return getExpr().getReturnType() == InventoryType.class ? Inventory.class : ItemType.class; } - + @Override - public String toString(final @Nullable Event e, final boolean debug) { - return getExpr().toString(e, debug) + " named " + name; + public String toString(@Nullable Event event, boolean debug) { + return getExpr().toString(event, debug) + " named " + name.toString(event, debug); } - + }