From c018ca20806cd502323c2b81b7ca9d1c72511718 Mon Sep 17 00:00:00 2001 From: SirSmurfy2 Date: Wed, 23 Jul 2025 16:12:33 -0400 Subject: [PATCH 1/4] Update EffOpenInventory.java --- .../njol/skript/effects/EffOpenInventory.java | 262 ++++++++++-------- 1 file changed, 152 insertions(+), 110 deletions(-) diff --git a/src/main/java/ch/njol/skript/effects/EffOpenInventory.java b/src/main/java/ch/njol/skript/effects/EffOpenInventory.java index 29a8f59bc11..f3d35fc1130 100644 --- a/src/main/java/ch/njol/skript/effects/EffOpenInventory.java +++ b/src/main/java/ch/njol/skript/effects/EffOpenInventory.java @@ -1,9 +1,17 @@ package ch.njol.skript.effects; -import java.util.Locale; - +import ch.njol.skript.Skript; +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.lang.Effect; +import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.SyntaxStringBuilder; import ch.njol.skript.registrations.Classes; +import ch.njol.util.Kleenean; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.Event; @@ -11,136 +19,170 @@ import org.bukkit.inventory.Inventory; import org.jetbrains.annotations.Nullable; -import ch.njol.skript.Skript; -import ch.njol.skript.doc.Description; -import ch.njol.skript.doc.Examples; -import ch.njol.skript.doc.Name; -import ch.njol.skript.doc.Since; -import ch.njol.skript.lang.Effect; -import ch.njol.skript.lang.Expression; -import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.util.Kleenean; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; @Name("Open/Close Inventory") -@Description({"Opens an inventory to a player. The player can then access and modify the inventory as if it was a chest that he just opened.", - "Please note that currently 'show' and 'open' have the same effect, but 'show' will eventually show an unmodifiable view of the inventory in the future."}) -@Examples({"show the victim's inventory to the player", - "open the player's inventory for the player"}) -@Since("2.0, 2.1.1 (closing), 2.2-Fixes-V10 (anvil), 2.4 (hopper, dropper, dispenser") +@Description(""" + Opens an inventory to a player. The player can then access and modify the inventory as if it was a chest that he just opened. + Please note that currently 'show' and 'open' have the same effect, but 'show' will eventually show an unmodifiable view of the inventory in the future. + """) +@Example("open the player's inventory for the player") +@Example("open an anvil window for all players") +@Example("show grindstone view to {_player}") +@Example("open a dropper inventory for player") +@Example("close the inventory for all players") +@Since("2.0, 2.1.1 (closing), 2.2-Fixes-V10 (anvil), 2.4 (hopper, dropper, dispenser)") public class EffOpenInventory extends Effect { - - private final static int WORKBENCH = 0, CHEST = 1, ANVIL = 2, HOPPER = 3, DROPPER = 4, DISPENSER = 5; + + // TODO: Add support for Paper's MenuType (1.21.3+) + + private enum OpenableType { + ANVIL("anvil", InventoryType.ANVIL), + CARTOGRAPHY("cartography [table]", "cartography table", InventoryType.CARTOGRAPHY), + CRAFTING("(crafting [table]|workbench)", "crafting table", InventoryType.CRAFTING), + DISPENSER("dispenser", InventoryType.DISPENSER), + DROPPER("dropper", InventoryType.DROPPER), + ENCHANTING("enchant(ing|ment) [table]", "enchantment table", InventoryType.ENCHANTING), + GRINDSTONE("grindstone", InventoryType.GRINDSTONE), + HOPPER("hopper", InventoryType.HOPPER), + LOOM("loom", InventoryType.LOOM), + SMITHING("smithing [table]", "smithing table", InventoryType.SMITHING), + STONECUTTER("stonecutter", InventoryType.STONECUTTER) + ; + + + private final String pattern; + private final String toString; + private final InventoryType inventoryType; + + OpenableType(String pattern, String toString, InventoryType inventoryType) { + this.pattern = "(open|show) [a[n]] " + pattern + "[view|window|inventory] (to|for) %players%"; + this.toString = toString; + this.inventoryType = inventoryType; + } + + OpenableType(String pattern, InventoryType inventoryType) { + this(pattern, pattern, inventoryType); + } + + } + + private static final OpenableType[] TYPES = OpenableType.values(); static { - Skript.registerEffect(EffOpenInventory.class, - "(open|show) ((0¦(crafting [table]|workbench)|1¦chest|2¦anvil|3¦hopper|4¦dropper|5¦dispenser) (view|window|inventory|)|%-inventory/inventorytype%) (to|for) %players%", - "close [the] inventory [view] (to|of|for) %players%", "close %players%'[s] inventory [view]"); + List patterns = new ArrayList<>(); + for (OpenableType type : TYPES) { + patterns.add(type.pattern); + } + patterns.add("(open|show) %inventory/inventorytype% (to|for) %players%"); + patterns.add("close [the] inventory [view] (to|of|for) %players%"); + patterns.add("close %players%'[s] inventory [view]"); + Skript.registerEffect(EffOpenInventory.class, patterns.toArray(String[]::new)); } - - @Nullable - private Expression invi; - - boolean open; - private int invType; - - @SuppressWarnings("null") + + private @Nullable OpenableType openableType = null; + private @Nullable Expression invObject = null; private Expression players; - - @SuppressWarnings({"unchecked", "null"}) + private boolean open = true; + @Override - public boolean init(final Expression[] exprs, final int matchedPattern, final Kleenean isDelayed, final ParseResult parseResult) { - int openFlag = 0; - if(parseResult.mark >= 5) { - openFlag = parseResult.mark ^ 5; - invType = DISPENSER; - } else if(parseResult.mark >= 4) { - openFlag = parseResult.mark ^ 4; - invType = DROPPER; - } else if(parseResult.mark >= 3) { - openFlag = parseResult.mark ^ 3; - invType = HOPPER; - } else if (parseResult.mark >= 2) { - openFlag = parseResult.mark ^ 2; - invType = ANVIL; - } else if (parseResult.mark >= 1) { - openFlag = parseResult.mark ^ 1; - invType = CHEST; - } else if (parseResult.mark >= 0) { - invType = WORKBENCH; - openFlag = parseResult.mark ^ 0; + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + if (matchedPattern <= TYPES.length) { + if (matchedPattern < TYPES.length) { + openableType = TYPES[matchedPattern]; + //noinspection unchecked + players = (Expression) exprs[0]; + } else { + invObject = exprs[0]; + //noinspection unchecked + players = (Expression) exprs[1]; + if (invObject instanceof Literal literal && literal.getSingle() instanceof InventoryType inventoryType && !inventoryType.isCreatable()) { + Skript.error("Cannot create an inventory of type " + Classes.toString(inventoryType)); + return false; + } + } } else { - openFlag = parseResult.mark; - } - - open = matchedPattern == 0; - invi = open ? exprs[0] : null; - players = (Expression) exprs[exprs.length - 1]; - if (openFlag == 1 && invi != null) { - Skript.warning("Using 'show' inventory instead of 'open' is not recommended as it will eventually show an unmodifiable view of the inventory in the future."); - } - if (exprs[0] instanceof Literal lit && lit.getSingle() instanceof InventoryType inventoryType && !inventoryType.isCreatable()) { - Skript.error("Cannot create an inventory of type " + Classes.toString(inventoryType)); - return false; + open = false; + //noinspection unchecked + players = (Expression) exprs[0]; } return true; } @Override - protected void execute(final Event e) { - if (invi != null) { - Inventory i; - - assert invi != null; - Object o = invi.getSingle(e); - if (o instanceof Inventory) { - i = (Inventory) o; - } else if (o instanceof InventoryType inventoryType && inventoryType.isCreatable()) { - i = Bukkit.createInventory(null, inventoryType); + protected void execute(Event event) { + Consumer consumer = null; + if (open) { + if (openableType != null) { + consumer = getPlayerConsumer(openableType.inventoryType); } else { - return; - } - - if (i == null) - return; - for (final Player p : players.getArray(e)) { - try { - p.openInventory(i); - } catch (IllegalArgumentException ex){ - Skript.error("You can't open a " + i.getType().name().toLowerCase(Locale.ENGLISH).replaceAll("_", "") + " inventory to a player."); + assert invObject != null; + Object object = invObject.getSingle(event); + if (object == null) + return; + if (object instanceof Inventory inventory) { + consumer = player -> player.openInventory(inventory); + } else if (object instanceof InventoryType inventoryType) { + consumer = getPlayerConsumer(inventoryType); + if (consumer == null) { + error("Cannot create an inventory of type " + Classes.toString(inventoryType)); + return; + } } } } else { - for (final Player p : players.getArray(e)) { - if (open) { - switch (invType) { - case WORKBENCH: - p.openWorkbench(null, true); - break; - case CHEST: - p.openInventory(Bukkit.createInventory(p, InventoryType.CHEST)); - break; - case ANVIL: - p.openInventory(Bukkit.createInventory(p, InventoryType.ANVIL)); - break; - case HOPPER: - p.openInventory(Bukkit.createInventory(p, InventoryType.HOPPER)); - break; - case DROPPER: - p.openInventory(Bukkit.createInventory(p, InventoryType.DROPPER)); - break; - case DISPENSER: - p.openInventory(Bukkit.createInventory(p, InventoryType.DISPENSER)); - - } - } else - p.closeInventory(); - } + consumer = Player::closeInventory; + } + assert consumer != null; + + for (Player player : players.getArray(event)) { + consumer.accept(player); } } + + /** + * Handles how to open {@code inventoryType} for a {@link Player}. + * + * @param inventoryType The {@link InventoryType} to open for a {@link Player}. + * @return {@link Consumer} for a {@link Player} or {@code null} if {@code inventoryType} is not creatable. + */ + @SuppressWarnings("deprecation") + private @Nullable Consumer getPlayerConsumer(InventoryType inventoryType) { + if (!inventoryType.isCreatable()) + return null; + + // Having 'switch' outside rather than inside the consumer reduces any re-iterating + return switch (inventoryType) { + //case ANVIL -> player -> player.openAnvil(null, true); + case CARTOGRAPHY -> player -> player.openCartographyTable(null, true); + case CRAFTING -> player -> player.openWorkbench(null, true); + case ENCHANTING -> player -> player.openEnchanting(null, true); + case GRINDSTONE -> player -> player.openGrindstone(null, true); + case LOOM -> player -> player.openLoom(null, true); + case SMITHING -> player -> player.openSmithingTable(null, true); + case STONECUTTER -> player -> player.openStonecutter(null, true); + default -> player -> player.openInventory(Bukkit.createInventory(player, inventoryType)); + }; + } @Override - public String toString(final @Nullable Event e, final boolean debug) { - return (open ? "open " + (invi != null ? invi.toString(e, debug) : "crafting table") + " to " : "close inventory view of ") + players.toString(e, debug); + public String toString(@Nullable Event event, boolean debug) { + SyntaxStringBuilder builder = new SyntaxStringBuilder(event, debug); + if (open) { + builder.append("open"); + if (openableType != null) { + builder.append(openableType.toString, "inventory"); + } else { + assert invObject != null; + builder.append(invObject); + } + } else { + builder.append("close the inventory"); + } + builder.append("for", players); + return builder.toString(); } } From 3654335ad07a7d3e2fde22ec0383d851ee280cc3 Mon Sep 17 00:00:00 2001 From: SirSmurfy2 Date: Wed, 23 Jul 2025 16:34:00 -0400 Subject: [PATCH 2/4] Update EffOpenInventory.java --- src/main/java/ch/njol/skript/effects/EffOpenInventory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ch/njol/skript/effects/EffOpenInventory.java b/src/main/java/ch/njol/skript/effects/EffOpenInventory.java index f3d35fc1130..15800a1f951 100644 --- a/src/main/java/ch/njol/skript/effects/EffOpenInventory.java +++ b/src/main/java/ch/njol/skript/effects/EffOpenInventory.java @@ -155,7 +155,7 @@ protected void execute(Event event) { // Having 'switch' outside rather than inside the consumer reduces any re-iterating return switch (inventoryType) { - //case ANVIL -> player -> player.openAnvil(null, true); + case ANVIL -> player -> player.openAnvil(null, true); case CARTOGRAPHY -> player -> player.openCartographyTable(null, true); case CRAFTING -> player -> player.openWorkbench(null, true); case ENCHANTING -> player -> player.openEnchanting(null, true); From 6b1926a5fd8a6d9f235a5cf9627cd58deab8bfc3 Mon Sep 17 00:00:00 2001 From: SirSmurfy2 Date: Fri, 22 Aug 2025 14:54:09 -0400 Subject: [PATCH 3/4] Update EffOpenInventory.java --- .../ch/njol/skript/effects/EffOpenInventory.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/ch/njol/skript/effects/EffOpenInventory.java b/src/main/java/ch/njol/skript/effects/EffOpenInventory.java index 15800a1f951..e4194f969cd 100644 --- a/src/main/java/ch/njol/skript/effects/EffOpenInventory.java +++ b/src/main/java/ch/njol/skript/effects/EffOpenInventory.java @@ -25,8 +25,9 @@ @Name("Open/Close Inventory") @Description(""" - Opens an inventory to a player. The player can then access and modify the inventory as if it was a chest that he just opened. - Please note that currently 'show' and 'open' have the same effect, but 'show' will eventually show an unmodifiable view of the inventory in the future. + Opens an inventory to a player. The player can then access and modify the inventory as if it was a chest that they opened. + Please note that currently 'show' and 'open' have the same effect,\ + but 'show' will eventually show an unmodifiable view of the inventory in the future. """) @Example("open the player's inventory for the player") @Example("open an anvil window for all players") @@ -52,21 +53,20 @@ private enum OpenableType { STONECUTTER("stonecutter", InventoryType.STONECUTTER) ; - private final String pattern; private final String toString; private final InventoryType inventoryType; + OpenableType(String pattern, InventoryType inventoryType) { + this(pattern, pattern, inventoryType); + } + OpenableType(String pattern, String toString, InventoryType inventoryType) { this.pattern = "(open|show) [a[n]] " + pattern + "[view|window|inventory] (to|for) %players%"; this.toString = toString; this.inventoryType = inventoryType; } - OpenableType(String pattern, InventoryType inventoryType) { - this(pattern, pattern, inventoryType); - } - } private static final OpenableType[] TYPES = OpenableType.values(); From af64905aa7f3127a7d0116ff4463e2c4defc4915 Mon Sep 17 00:00:00 2001 From: SirSmurfy2 Date: Fri, 22 Aug 2025 16:03:25 -0400 Subject: [PATCH 4/4] Update EffOpenInventory.java --- .../ch/njol/skript/effects/EffOpenInventory.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/ch/njol/skript/effects/EffOpenInventory.java b/src/main/java/ch/njol/skript/effects/EffOpenInventory.java index e4194f969cd..79c37a8c98a 100644 --- a/src/main/java/ch/njol/skript/effects/EffOpenInventory.java +++ b/src/main/java/ch/njol/skript/effects/EffOpenInventory.java @@ -40,16 +40,16 @@ public class EffOpenInventory extends Effect { // TODO: Add support for Paper's MenuType (1.21.3+) private enum OpenableType { - ANVIL("anvil", InventoryType.ANVIL), - CARTOGRAPHY("cartography [table]", "cartography table", InventoryType.CARTOGRAPHY), - CRAFTING("(crafting [table]|workbench)", "crafting table", InventoryType.CRAFTING), + ANVIL("[an] anvil", "anvil", InventoryType.ANVIL), + CARTOGRAPHY("[a] cartography [table]", "cartography table", InventoryType.CARTOGRAPHY), + CRAFTING("[a] (crafting [table]|workbench)", "crafting table", InventoryType.CRAFTING), DISPENSER("dispenser", InventoryType.DISPENSER), DROPPER("dropper", InventoryType.DROPPER), - ENCHANTING("enchant(ing|ment) [table]", "enchantment table", InventoryType.ENCHANTING), + ENCHANTING("[an] enchant(ing|ment) [table]", "enchantment table", InventoryType.ENCHANTING), GRINDSTONE("grindstone", InventoryType.GRINDSTONE), HOPPER("hopper", InventoryType.HOPPER), LOOM("loom", InventoryType.LOOM), - SMITHING("smithing [table]", "smithing table", InventoryType.SMITHING), + SMITHING("[a] smithing [table]", "smithing table", InventoryType.SMITHING), STONECUTTER("stonecutter", InventoryType.STONECUTTER) ; @@ -58,11 +58,11 @@ private enum OpenableType { private final InventoryType inventoryType; OpenableType(String pattern, InventoryType inventoryType) { - this(pattern, pattern, inventoryType); + this(pattern, "[a] " + pattern, inventoryType); } OpenableType(String pattern, String toString, InventoryType inventoryType) { - this.pattern = "(open|show) [a[n]] " + pattern + "[view|window|inventory] (to|for) %players%"; + this.pattern = "(open|show) " + pattern + "[view|window|inventory] (to|for) %players%"; this.toString = toString; this.inventoryType = inventoryType; }