From d95da25e472904eb344f1c583c54164ba6a49663 Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 23 Aug 2026 19:19:15 -0600 Subject: [PATCH 1/8] Centralize edit GUI value behavior --- .../editgui/valuetypes/EditGUIValue.java | 378 +++++++++--------- 1 file changed, 193 insertions(+), 185 deletions(-) diff --git a/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/valuetypes/EditGUIValue.java b/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/valuetypes/EditGUIValue.java index f5191d73af..894b9fffc7 100644 --- a/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/valuetypes/EditGUIValue.java +++ b/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/valuetypes/EditGUIValue.java @@ -1,185 +1,193 @@ -package com.bencodez.advancedcore.api.inventory.editgui.valuetypes; - -import java.util.ArrayList; - -import com.bencodez.advancedcore.api.inventory.BInventory; -import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent; -import com.bencodez.advancedcore.api.rewards.RewardEditData; -import com.bencodez.simpleapi.valuerequest.InputMethod; - -import lombok.Getter; -import lombok.Setter; - -/** - * Abstract base class for GUI edit values. - */ -public abstract class EditGUIValue { - /** - * Whether the value can be retrieved. - */ - @Getter - @Setter - private boolean canGetValue = true; - - /** - * The current value. - */ - @Getter - @Setter - private Object currentValue; - - /** - * The input method. - */ - @Getter - @Setter - private InputMethod inputMethod = InputMethod.DIALOG; - - /** - * The inventory. - */ - @Getter - @Setter - private BInventory inv; - - /** - * The key. - */ - @Getter - @Setter - private String key; - - /** - * The lore lines. - */ - @Getter - @Setter - private ArrayList lores; - - /** - * The options. - */ - @Getter - private ArrayList options = new ArrayList(); - - /** - * Adds lore lines to this value. - * - * @param lore the lore lines to add - * @return this instance - */ - public EditGUIValue addLore(ArrayList lore) { - if (lores == null) { - lores = new ArrayList(); - } - lores.addAll(lore); - return this; - } - - /** - * Adds a lore line to this value. - * - * @param lore the lore line to add - * @return this instance - */ - public EditGUIValue addLore(String lore) { - if (lores == null) { - lores = new ArrayList(); - } - lores.add(lore); - return this; - } - - /** - * Adds options to this value. - * - * @param str the options to add - * @return this instance - */ - public EditGUIValue addOptions(String... str) { - for (String s : str) { - options.add(s); - } - return this; - } - - /** - * Checks if the reward edit data contains this key. - * - * @param rewardEditData the reward edit data - * @return true if key exists - */ - public boolean containsKey(RewardEditData rewardEditData) { - return rewardEditData.hasPath(getKey()); - } - - /** - * Uses the dialog input method. - * - * @return this instance - */ - public EditGUIValue dialog() { - return inputMethod(InputMethod.DIALOG); - } - - /** - * Uses the chat input method. - * - * @return this instance - */ - public EditGUIValue chat() { - return inputMethod(InputMethod.CHAT); - } - - /** - * Uses the inventory input method. - * - * @return this instance - */ - public EditGUIValue inventory() { - return inputMethod(InputMethod.INVENTORY); - } - - /** - * Uses the book input method. - * - * @return this instance - */ - public EditGUIValue book() { - return inputMethod(InputMethod.BOOK); - } - - /** - * Uses the sign input method. - * - * @return this instance - */ - public EditGUIValue sign() { - return inputMethod(InputMethod.SIGN); - } - - /** - * Gets the type of this value. - * - * @return the type - */ - public abstract String getType(); - - /** - * Sets the input method for this value. - * - * @param inputMethod the input method - * @return this instance - */ - public EditGUIValue inputMethod(InputMethod inputMethod) { - this.inputMethod = inputMethod; - return this; - } - - /** - * Handles click events for this value. - * - * @param event the click event - */ - public abstract void onClick(ClickEvent event); -} \ No newline at end of file +package com.bencodez.advancedcore.api.inventory.editgui.valuetypes; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.function.Consumer; + +import org.bukkit.entity.Player; + +import com.bencodez.advancedcore.AdvancedCorePlugin; +import com.bencodez.advancedcore.api.inventory.BInventory; +import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent; +import com.bencodez.advancedcore.api.rewards.RewardEditData; +import com.bencodez.simpleapi.messages.MessageAPI; +import com.bencodez.simpleapi.valuerequest.InputMethod; +import com.bencodez.simpleapi.valuerequest.ValueRequest; + +import lombok.Getter; +import lombok.Setter; + +/** + * Abstract base class for GUI edit values. + */ +public abstract class EditGUIValue { + @Getter + @Setter + private boolean canGetValue = true; + + @Getter + @Setter + private Object currentValue; + + @Getter + @Setter + private InputMethod inputMethod = InputMethod.DIALOG; + + @Getter + @Setter + private BInventory inv; + + @Getter + @Setter + private String key; + + @Getter + @Setter + private ArrayList lores; + + @Getter + private final ArrayList options = new ArrayList<>(); + + protected EditGUIValue() { + } + + protected EditGUIValue(String key, Object currentValue) { + this.key = key; + this.currentValue = currentValue; + } + + public EditGUIValue addLore(ArrayList lore) { + if (lore == null || lore.isEmpty()) { + return this; + } + if (lores == null) { + lores = new ArrayList<>(); + } + lores.addAll(lore); + return this; + } + + public EditGUIValue addLore(String lore) { + if (lore == null) { + return this; + } + if (lores == null) { + lores = new ArrayList<>(); + } + lores.add(lore); + return this; + } + + public EditGUIValue addOptions(String... values) { + if (values == null) { + return this; + } + for (String value : values) { + if (value != null) { + options.add(value); + } + } + return this; + } + + public boolean containsKey(RewardEditData rewardEditData) { + return rewardEditData != null && rewardEditData.hasPath(getKey()); + } + + public EditGUIValue dialog() { + return inputMethod(InputMethod.DIALOG); + } + + public EditGUIValue chat() { + return inputMethod(InputMethod.CHAT); + } + + public EditGUIValue inventory() { + return inputMethod(InputMethod.INVENTORY); + } + + public EditGUIValue book() { + return inputMethod(InputMethod.BOOK); + } + + public EditGUIValue sign() { + return inputMethod(InputMethod.SIGN); + } + + public abstract String getType(); + + /** + * Default display name used by {@link com.bencodez.advancedcore.api.inventory.editgui.EditGUIButton}. + */ + public String getButtonName() { + return "&cSet " + getType() + " for " + getKey(); + } + + /** + * Default display lore used by {@link com.bencodez.advancedcore.api.inventory.editgui.EditGUIButton}. + */ + public List getButtonLore() { + return List.of("&cCurrent value: " + String.valueOf(getCurrentValue())); + } + + public EditGUIValue inputMethod(InputMethod inputMethod) { + this.inputMethod = inputMethod == null ? InputMethod.DIALOG : inputMethod; + return this; + } + + public abstract void onClick(ClickEvent event); + + protected ValueRequest createValueRequest() { + return createValueRequest(getInputMethod()); + } + + protected ValueRequest createValueRequest(InputMethod method) { + AdvancedCorePlugin plugin = AdvancedCorePlugin.getInstance(); + return new ValueRequest(plugin, plugin.getDialogService(), method == null ? InputMethod.DIALOG : method); + } + + protected void applyValue(Player player, T value, Consumer saveAction) { + saveAction.accept(value); + setCurrentValue(value); + if (player != null) { + player.sendMessage(MessageAPI.colorize("&cSetting " + getKey() + " to " + String.valueOf(value))); + } + } + + protected String currentString(String defaultValue) { + Object current = getCurrentValue(); + return current == null ? defaultValue : String.valueOf(current); + } + + protected Number currentNumber(Number defaultValue) { + Object current = getCurrentValue(); + if (current instanceof Number) { + return (Number) current; + } + if (current != null) { + try { + return Double.valueOf(String.valueOf(current)); + } catch (NumberFormatException ignored) { + // Fall through to the supplied default. + } + } + return defaultValue; + } + + protected ArrayList currentStringList() { + return toStringList(getCurrentValue()); + } + + protected ArrayList toStringList(Object value) { + ArrayList values = new ArrayList<>(); + if (value instanceof Collection) { + for (Object entry : (Collection) value) { + if (entry != null) { + values.add(String.valueOf(entry)); + } + } + } + return values; + } +} From aa7b16306743decf92e39d6ab38b84c89835506f Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 23 Aug 2026 19:19:23 -0600 Subject: [PATCH 2/8] Use shared edit value request helpers --- .../valuetypes/EditGUIValueBoolean.java | 80 +++++++------------ 1 file changed, 29 insertions(+), 51 deletions(-) diff --git a/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/valuetypes/EditGUIValueBoolean.java b/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/valuetypes/EditGUIValueBoolean.java index c82cda4a50..6281a8b9e8 100644 --- a/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/valuetypes/EditGUIValueBoolean.java +++ b/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/valuetypes/EditGUIValueBoolean.java @@ -1,51 +1,29 @@ -package com.bencodez.advancedcore.api.inventory.editgui.valuetypes; - -import org.bukkit.entity.Player; - -import com.bencodez.advancedcore.AdvancedCorePlugin; -import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent; -import com.bencodez.simpleapi.messages.MessageAPI; -import com.bencodez.simpleapi.valuerequest.ValueRequest; - -/** - * Abstract GUI value for boolean editing. - */ -public abstract class EditGUIValueBoolean extends EditGUIValue { - /** - * Constructor for EditGUIValueBoolean. - * - * @param key the key - * @param value the initial value - */ - public EditGUIValueBoolean(String key, Object value) { - setKey(key); - setCurrentValue(value); - } - - @Override - public String getType() { - return "boolean"; - } - - @Override - public void onClick(ClickEvent clickEvent) { - if (getCurrentValue() == null) { - setCurrentValue(Boolean.FALSE); - } - new ValueRequest(AdvancedCorePlugin.getInstance(), AdvancedCorePlugin.getInstance().getDialogService(), - getInputMethod()).requestBoolean(clickEvent.getPlayer(), Boolean.valueOf(String.valueOf(getCurrentValue())), - "Type cancel to cancel", (Player player, boolean value) -> { - setValue(player, value); - setCurrentValue(Boolean.valueOf(value)); - player.sendMessage(MessageAPI.colorize("&cSetting " + getKey() + " to " + value)); - }); - } - - /** - * Sets the boolean value. - * - * @param player the player - * @param value the value to set - */ - public abstract void setValue(Player player, boolean value); -} \ No newline at end of file +package com.bencodez.advancedcore.api.inventory.editgui.valuetypes; + +import org.bukkit.entity.Player; + +import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent; + +/** + * Abstract GUI value for boolean editing. + */ +public abstract class EditGUIValueBoolean extends EditGUIValue { + public EditGUIValueBoolean(String key, Object value) { + super(key, value); + } + + @Override + public String getType() { + return "boolean"; + } + + @Override + public void onClick(ClickEvent clickEvent) { + boolean current = Boolean.parseBoolean(currentString("false")); + createValueRequest().requestBoolean(clickEvent.getPlayer(), current, "Type cancel to cancel", + (Player player, boolean value) -> applyValue(player, Boolean.valueOf(value), + newValue -> setValue(player, newValue.booleanValue()))); + } + + public abstract void setValue(Player player, boolean value); +} From aa025f5bc0b147138978f54d82eeed82a8876f9d Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 23 Aug 2026 19:19:33 -0600 Subject: [PATCH 3/8] Centralize number editor normalization --- .../valuetypes/EditGUIValueNumber.java | 136 ++++++------------ 1 file changed, 46 insertions(+), 90 deletions(-) diff --git a/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/valuetypes/EditGUIValueNumber.java b/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/valuetypes/EditGUIValueNumber.java index ff52f266d6..cbc0aadf7a 100644 --- a/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/valuetypes/EditGUIValueNumber.java +++ b/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/valuetypes/EditGUIValueNumber.java @@ -1,90 +1,46 @@ -package com.bencodez.advancedcore.api.inventory.editgui.valuetypes; - -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; - -import org.bukkit.entity.Player; - -import com.bencodez.advancedcore.AdvancedCorePlugin; -import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent; -import com.bencodez.simpleapi.messages.MessageAPI; -import com.bencodez.simpleapi.valuerequest.ValueRequest; - -/** - * Abstract GUI value for number editing. - */ -public abstract class EditGUIValueNumber extends EditGUIValue { - /** - * Constructor for EditGUIValueNumber. - * - * @param key the key - * @param value the initial value - */ - public EditGUIValueNumber(String key, Object value) { - setKey(key); - setCurrentValue(value); - } - - @Override - public String getType() { - return "number"; - } - - @Override - public void onClick(ClickEvent clickEvent) { - if (getCurrentValue() == null) { - setCurrentValue(Integer.valueOf(0)); - } - new ValueRequest(AdvancedCorePlugin.getInstance(), AdvancedCorePlugin.getInstance().getDialogService(), - getInputMethod()).requestNumber(clickEvent.getPlayer(), getCurrentNumber(), getDefaultOptions(), true, - "Type cancel to cancel", (Player player, Number number) -> { - setValue(player, number); - setCurrentValue(number); - player.sendMessage(MessageAPI.colorize("&cSetting " + getKey() + " to " + number.doubleValue())); - }); - } - - /** - * Gets the current value as a number. - * - * @return the current number value - */ - private Number getCurrentNumber() { - Object current = getCurrentValue(); - if (current instanceof Number) { - return (Number) current; - } - try { - return Double.valueOf(String.valueOf(current)); - } catch (NumberFormatException ex) { - return Integer.valueOf(0); - } - } - - /** - * Builds the default number options including the current value. - * - * @return the list of default number options - */ - private List getDefaultOptions() { - LinkedHashSet values = new LinkedHashSet(); - values.add(Integer.valueOf(0)); - values.add(Integer.valueOf(10)); - values.add(Integer.valueOf(25)); - values.add(Integer.valueOf(50)); - values.add(Integer.valueOf(100)); - values.add(Integer.valueOf(500)); - values.add(Integer.valueOf(1000)); - values.add(getCurrentNumber()); - return new ArrayList(values); - } - - /** - * Sets the number value. - * - * @param player the player - * @param num the number to set - */ - public abstract void setValue(Player player, Number num); -} \ No newline at end of file +package com.bencodez.advancedcore.api.inventory.editgui.valuetypes; + +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; + +import org.bukkit.entity.Player; + +import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent; + +/** + * Abstract GUI value for number editing. + */ +public abstract class EditGUIValueNumber extends EditGUIValue { + public EditGUIValueNumber(String key, Object value) { + super(key, value); + } + + @Override + public String getType() { + return "number"; + } + + @Override + public void onClick(ClickEvent clickEvent) { + Number current = currentNumber(Integer.valueOf(0)); + createValueRequest().requestNumber(clickEvent.getPlayer(), current, getDefaultOptions(current), true, + "Type cancel to cancel", (Player player, Number number) -> applyValue(player, number, + newValue -> setValue(player, newValue))); + } + + private List getDefaultOptions(Number current) { + LinkedHashSet values = new LinkedHashSet<>(); + values.add(Integer.valueOf(0)); + values.add(Integer.valueOf(10)); + values.add(Integer.valueOf(25)); + values.add(Integer.valueOf(50)); + values.add(Integer.valueOf(100)); + values.add(Integer.valueOf(500)); + values.add(Integer.valueOf(1000)); + values.add(current); + return new ArrayList<>(values); + } + + public abstract void setValue(Player player, Number num); +} From 327befd217678e7c9c3f1fec1bac6bfae105265c Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 23 Aug 2026 19:19:43 -0600 Subject: [PATCH 4/8] Centralize string editor request handling --- .../valuetypes/EditGUIValueString.java | 79 +++++++------------ 1 file changed, 28 insertions(+), 51 deletions(-) diff --git a/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/valuetypes/EditGUIValueString.java b/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/valuetypes/EditGUIValueString.java index c7c89b3705..d2ccd1240c 100644 --- a/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/valuetypes/EditGUIValueString.java +++ b/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/valuetypes/EditGUIValueString.java @@ -1,51 +1,28 @@ -package com.bencodez.advancedcore.api.inventory.editgui.valuetypes; - -import org.bukkit.entity.Player; - -import com.bencodez.advancedcore.AdvancedCorePlugin; -import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent; -import com.bencodez.simpleapi.messages.MessageAPI; -import com.bencodez.simpleapi.valuerequest.ValueRequest; - -/** - * Abstract GUI value for string editing. - */ -public abstract class EditGUIValueString extends EditGUIValue { - /** - * Constructor for EditGUIValueString. - * - * @param key the key - * @param value the initial value - */ - public EditGUIValueString(String key, Object value) { - setKey(key); - setCurrentValue(value); - } - - @Override - public String getType() { - return "string"; - } - - @Override - public void onClick(ClickEvent clickEvent) { - if (getCurrentValue() == null) { - setCurrentValue(""); - } - new ValueRequest(AdvancedCorePlugin.getInstance(), AdvancedCorePlugin.getInstance().getDialogService(), - getInputMethod()).requestString(clickEvent.getPlayer(), String.valueOf(getCurrentValue()), getOptions(), - true, "Type cancel to cancel", (Player player, String value) -> { - setValue(player, value); - setCurrentValue(value); - player.sendMessage(MessageAPI.colorize("&cSetting " + getKey() + " to " + value)); - }); - } - - /** - * Sets the string value. - * - * @param player the player - * @param value the value to set - */ - public abstract void setValue(Player player, String value); -} \ No newline at end of file +package com.bencodez.advancedcore.api.inventory.editgui.valuetypes; + +import org.bukkit.entity.Player; + +import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent; + +/** + * Abstract GUI value for string editing. + */ +public abstract class EditGUIValueString extends EditGUIValue { + public EditGUIValueString(String key, Object value) { + super(key, value); + } + + @Override + public String getType() { + return "string"; + } + + @Override + public void onClick(ClickEvent clickEvent) { + createValueRequest().requestString(clickEvent.getPlayer(), currentString(""), getOptions(), true, + "Type cancel to cancel", (Player player, String value) -> applyValue(player, value, + newValue -> setValue(player, newValue))); + } + + public abstract void setValue(Player player, String value); +} From 474b69a7adf597f7e2939953b2661610ad5210b5 Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 23 Aug 2026 19:20:01 -0600 Subject: [PATCH 5/8] Simplify list editor state handling --- .../editgui/valuetypes/EditGUIValueList.java | 183 +++++++++--------- 1 file changed, 91 insertions(+), 92 deletions(-) diff --git a/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/valuetypes/EditGUIValueList.java b/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/valuetypes/EditGUIValueList.java index a2e5819034..db00f0a973 100644 --- a/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/valuetypes/EditGUIValueList.java +++ b/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/valuetypes/EditGUIValueList.java @@ -1,92 +1,91 @@ -package com.bencodez.advancedcore.api.inventory.editgui.valuetypes; - -import java.util.ArrayList; - -import org.bukkit.Material; -import org.bukkit.entity.Player; - -import com.bencodez.advancedcore.AdvancedCorePlugin; -import com.bencodez.advancedcore.api.inventory.BInventory; -import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent; -import com.bencodez.advancedcore.api.inventory.BInventoryButton; -import com.bencodez.advancedcore.api.item.ItemBuilder; -import com.bencodez.simpleapi.valuerequest.InputMethod; -import com.bencodez.simpleapi.valuerequest.ValueRequest; - -/** - * Abstract GUI value for list editing. - */ -public abstract class EditGUIValueList extends EditGUIValue { - /** - * Constructor for EditGUIValueList. - * - * @param key the key - * @param value the initial value - */ - public EditGUIValueList(String key, Object value) { - setKey(key); - setCurrentValue(value); - } - - @Override - public String getType() { - return "list"; - } - - @Override - public void onClick(ClickEvent clickEvent) { - if (getCurrentValue() == null) { - setCurrentValue(new ArrayList()); - } - BInventory inv = new BInventory("Edit list: " + getKey()); - inv.setMeta(clickEvent.getPlayer(), "Value", getCurrentValue()); - inv.addButton(new BInventoryButton(new ItemBuilder(Material.EMERALD_BLOCK).setName("&cAdd value")) { - @Override - public void onClick(ClickEvent clickEvent) { - new ValueRequest(AdvancedCorePlugin.getInstance(), AdvancedCorePlugin.getInstance().getDialogService(), - getInputMethod()).requestString(clickEvent.getPlayer(), (String) null, null, true, - "Type cancel to cancel", (Player player, String add) -> { - @SuppressWarnings("unchecked") - ArrayList list = (ArrayList) getMeta(player, "Value"); - if (list == null) { - list = new ArrayList(); - } - list.add(add); - setCurrentValue(list); - setValue(player, list); - sendMessage(player, "&cAdded " + add + " to " + getKey()); - }); - } - }); - inv.addButton(new BInventoryButton(new ItemBuilder(Material.BARRIER).setName("&cRemove value")) { - @SuppressWarnings("unchecked") - @Override - public void onClick(ClickEvent clickEvent) { - ArrayList list = (ArrayList) getMeta(clickEvent.getPlayer(), "Value"); - if (!list.isEmpty()) { - InputMethod removeMethod = getInputMethod() == InputMethod.BOOK ? InputMethod.CHAT : getInputMethod(); - new ValueRequest(AdvancedCorePlugin.getInstance(), AdvancedCorePlugin.getInstance().getDialogService(), - removeMethod).requestString(clickEvent.getPlayer(), (String) null, new ArrayList(list), false, - "Type cancel to cancel", (Player player, String remove) -> { - ArrayList currentList = (ArrayList) getMeta(player, "Value"); - currentList.remove(remove); - setCurrentValue(currentList); - setValue(player, currentList); - sendMessage(player, "&cRemoved " + remove + " from " + getKey()); - }); - } else { - clickEvent.getPlayer().sendMessage("No values to remove"); - } - } - }); - inv.openInventory(clickEvent.getPlayer()); - } - - /** - * Sets the list value. - * - * @param player the player - * @param value the list to set - */ - public abstract void setValue(Player player, ArrayList value); -} \ No newline at end of file +package com.bencodez.advancedcore.api.inventory.editgui.valuetypes; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Material; +import org.bukkit.entity.Player; + +import com.bencodez.advancedcore.api.inventory.BInventory; +import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent; +import com.bencodez.advancedcore.api.inventory.BInventoryButton; +import com.bencodez.advancedcore.api.item.ItemBuilder; +import com.bencodez.simpleapi.valuerequest.InputMethod; + +/** + * Abstract GUI value for list editing. + */ +public abstract class EditGUIValueList extends EditGUIValue { + public EditGUIValueList(String key, Object value) { + super(key, value); + } + + @Override + public String getType() { + return "list"; + } + + @Override + public String getButtonName() { + return "&cEdit list for " + getKey(); + } + + @Override + public List getButtonLore() { + ArrayList current = currentStringList(); + return current.isEmpty() && getCurrentValue() == null ? List.of("&cCurrent value: null") : current; + } + + @Override + public void onClick(ClickEvent clickEvent) { + ArrayList initial = currentStringList(); + setCurrentValue(initial); + + BInventory inventory = new BInventory("Edit list: " + getKey()); + inventory.setMeta(clickEvent.getPlayer(), "Value", new ArrayList<>(initial)); + inventory.addButton(createAddButton()); + inventory.addButton(createRemoveButton()); + inventory.openInventory(clickEvent.getPlayer()); + } + + private BInventoryButton createAddButton() { + return new BInventoryButton(new ItemBuilder(Material.EMERALD_BLOCK).setName("&cAdd value")) { + @Override + public void onClick(ClickEvent clickEvent) { + createValueRequest().requestString(clickEvent.getPlayer(), (String) null, null, true, + "Type cancel to cancel", (Player player, String add) -> { + ArrayList list = EditGUIValueList.this.toStringList(getMeta(player, "Value")); + list.add(add); + setMeta(player, "Value", list); + applyValue(player, list, newValue -> setValue(player, new ArrayList<>(newValue))); + sendMessage(player, "&cAdded " + add + " to " + getKey()); + }); + } + }; + } + + private BInventoryButton createRemoveButton() { + return new BInventoryButton(new ItemBuilder(Material.BARRIER).setName("&cRemove value")) { + @Override + public void onClick(ClickEvent clickEvent) { + ArrayList list = EditGUIValueList.this.toStringList(getMeta(clickEvent.getPlayer(), "Value")); + if (list.isEmpty()) { + clickEvent.getPlayer().sendMessage("No values to remove"); + return; + } + + InputMethod removeMethod = getInputMethod() == InputMethod.BOOK ? InputMethod.CHAT : getInputMethod(); + createValueRequest(removeMethod).requestString(clickEvent.getPlayer(), (String) null, new ArrayList<>(list), + false, "Type cancel to cancel", (Player player, String remove) -> { + ArrayList current = EditGUIValueList.this.toStringList(getMeta(player, "Value")); + current.remove(remove); + setMeta(player, "Value", current); + applyValue(player, current, newValue -> setValue(player, new ArrayList<>(newValue))); + sendMessage(player, "&cRemoved " + remove + " from " + getKey()); + }); + } + }; + } + + public abstract void setValue(Player player, ArrayList value); +} From 00337aa3bc689947c49bb805f48eb5708c067b06 Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 23 Aug 2026 19:20:25 -0600 Subject: [PATCH 6/8] Use editor-provided display metadata --- .../api/inventory/editgui/EditGUIButton.java | 218 +++++++----------- 1 file changed, 89 insertions(+), 129 deletions(-) diff --git a/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/EditGUIButton.java b/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/EditGUIButton.java index b4ee42e61b..e29bfde28c 100644 --- a/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/EditGUIButton.java +++ b/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/EditGUIButton.java @@ -1,129 +1,89 @@ -package com.bencodez.advancedcore.api.inventory.editgui; - -import java.util.ArrayList; -import java.util.HashMap; - -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent; -import com.bencodez.advancedcore.api.inventory.BInventoryButton; -import com.bencodez.advancedcore.api.inventory.editgui.valuetypes.EditGUIValue; -import com.bencodez.advancedcore.api.inventory.editgui.valuetypes.EditGUIValueInventory; -import com.bencodez.advancedcore.api.inventory.editgui.valuetypes.EditGUIValueList; -import com.bencodez.advancedcore.api.item.ItemBuilder; -import com.bencodez.simpleapi.array.ArrayUtils; - -import lombok.Getter; -import lombok.Setter; - -/** - * Button for editing GUI values. - */ -public class EditGUIButton extends BInventoryButton { - - /** - * The editor for this button. - * - * @return the editor - * @param editor the editor - */ - @Getter - @Setter - private EditGUIValue editor; - - /** - * Constructor for EditGUIButton. - * - * @param editer the GUI value editor - */ - public EditGUIButton(EditGUIValue editer) { - super(new ItemBuilder(Material.PAPER)); - this.editor = editer; - } - - /** - * Constructor for EditGUIButton with custom item. - * - * @param item the item builder - * @param editer the GUI value editor - */ - public EditGUIButton(ItemBuilder item, EditGUIValue editer) { - super(item); - this.editor = editer; - } - - /** - * Adds a lore line to the button. - * - * @param lore the lore line - * @return this instance - */ - public EditGUIButton addLore(String lore) { - getEditor().addLore(lore); - return this; - } - - /** - * Adds options to the button. - * - * @param str the options - * @return this instance - */ - public EditGUIButton addOptions(String... str) { - getEditor().addOptions(str); - return this; - } - - @SuppressWarnings("unchecked") - @Override - public ItemStack getItem(Player player, HashMap placeholders) { - ItemBuilder builder = getBuilder(); - builder.addPlaceholder(placeholders); - if ((getEditor() instanceof EditGUIValueInventory)) { - if (!builder.hasCustomDisplayName()) { - builder.setName("&cSet " + getEditor().getKey()); - } - builder.setLore("&cClick to open"); - } else if (!(getEditor() instanceof EditGUIValueList)) { - if (!builder.hasCustomDisplayName()) { - builder.setName("&cSet " + getEditor().getType() + " for " + getEditor().getKey()); - } - builder.setLore("&cCurrent value: " + getEditor().getCurrentValue()); - } else { - if (!builder.hasCustomDisplayName()) { - builder.setName("&cEdit list for " + getEditor().getKey()); - } - if (getEditor().getCurrentValue() instanceof ArrayList) { - builder.setLore(ArrayUtils.makeStringList((ArrayList) getEditor().getCurrentValue())); - } else { - builder.setLore("&cCurrent value: null"); - } - } - ArrayList lores = getEditor().getLores(); - if (lores != null) { - for (String t : lores) { - builder.addLoreLine("&3" + t); - } - } - return builder.toItemStack(player); - } - - @Override - public void onClick(ClickEvent clickEvent) { - getEditor().setInv(getInv()); - getEditor().onClick(clickEvent); - } - - /** - * Sets the name of the button. - * - * @param name the name - * @return this instance - */ - public EditGUIButton setName(String name) { - this.getBuilder().setName(name); - return this; - } -} +package com.bencodez.advancedcore.api.inventory.editgui; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent; +import com.bencodez.advancedcore.api.inventory.BInventoryButton; +import com.bencodez.advancedcore.api.inventory.editgui.valuetypes.EditGUIValue; +import com.bencodez.advancedcore.api.inventory.editgui.valuetypes.EditGUIValueInventory; +import com.bencodez.advancedcore.api.item.ItemBuilder; + +import lombok.Getter; +import lombok.Setter; + +/** + * Button for editing GUI values. + */ +public class EditGUIButton extends BInventoryButton { + @Getter + @Setter + private EditGUIValue editor; + + public EditGUIButton(EditGUIValue editor) { + super(new ItemBuilder(Material.PAPER)); + this.editor = editor; + } + + public EditGUIButton(ItemBuilder item, EditGUIValue editor) { + super(item); + this.editor = editor; + } + + public EditGUIButton addLore(String lore) { + getEditor().addLore(lore); + return this; + } + + public EditGUIButton addOptions(String... values) { + getEditor().addOptions(values); + return this; + } + + @Override + public ItemStack getItem(Player player, HashMap placeholders) { + ItemBuilder builder = getBuilder(); + builder.addPlaceholder(placeholders); + + if (getEditor() instanceof EditGUIValueInventory) { + applyInventoryDisplay(builder); + } else { + if (!builder.hasCustomDisplayName()) { + builder.setName(getEditor().getButtonName()); + } + List lore = getEditor().getButtonLore(); + builder.setLore(lore == null ? new String[0] : lore.toArray(new String[0])); + } + + ArrayList customLore = getEditor().getLores(); + if (customLore != null) { + for (String line : customLore) { + builder.addLoreLine("&3" + line); + } + } + return builder.toItemStack(player); + } + + @Override + public void onClick(ClickEvent clickEvent) { + getEditor().setInv(getInv()); + getEditor().onClick(clickEvent); + } + + public EditGUIButton setName(String name) { + getBuilder().setName(name); + return this; + } + + private void applyInventoryDisplay(ItemBuilder builder) { + if (!builder.hasCustomDisplayName()) { + builder.setName("&cSet " + getEditor().getKey()); + } + builder.setLore("&cClick to open"); + } +} From 9299e2d21891f066edf10199fbb2cf8067b09e74 Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 23 Aug 2026 19:20:35 -0600 Subject: [PATCH 7/8] Simplify edit GUI sorting --- .../api/inventory/editgui/EditGUI.java | 102 +++++++++--------- 1 file changed, 50 insertions(+), 52 deletions(-) diff --git a/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/EditGUI.java b/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/EditGUI.java index 8719af591e..b2ec7a0116 100644 --- a/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/EditGUI.java +++ b/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/inventory/editgui/EditGUI.java @@ -1,52 +1,50 @@ -package com.bencodez.advancedcore.api.inventory.editgui; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; - -import com.bencodez.advancedcore.api.inventory.BInventory; -import com.bencodez.advancedcore.api.inventory.BInventoryButton; - -/** - * Edit GUI for sorting and organizing edit buttons. - */ -public class EditGUI extends BInventory { - - /** - * Constructor for EditGUI. - * - * @param name the inventory name - */ - public EditGUI(String name) { - super(name); - } - - /** - * Sorts the edit buttons alphabetically by key. - */ - public void sort() { - Map map = getButtons(); - setButtons(new HashMap<>()); - LinkedHashMap buttons = new LinkedHashMap<>(); - ArrayList sortedList = new ArrayList<>(); - for (BInventoryButton button : map.values()) { - if (button instanceof EditGUIButton) { - EditGUIButton b = (EditGUIButton) button; - String key = b.getEditor().getKey(); - sortedList.add(key); - b.setSlot(-1); - buttons.put(key, b); - } else { - addButton(button); - } - } - sortedList.sort(Comparator.naturalOrder()); - - for (String key : sortedList) { - addButton(buttons.get(key)); - } - } - -} +package com.bencodez.advancedcore.api.inventory.editgui; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.bencodez.advancedcore.api.inventory.BInventory; +import com.bencodez.advancedcore.api.inventory.BInventoryButton; + +/** + * Edit GUI for sorting and organizing edit buttons. + */ +public class EditGUI extends BInventory { + public EditGUI(String name) { + super(name); + } + + /** + * Sorts edit buttons alphabetically by editor key while retaining non-editor + * buttons and duplicate editor keys. + */ + public void sort() { + Map current = getButtons(); + List fixedButtons = new ArrayList<>(); + List editButtons = new ArrayList<>(); + + for (BInventoryButton button : current.values()) { + if (button instanceof EditGUIButton) { + EditGUIButton editButton = (EditGUIButton) button; + editButton.setSlot(-1); + editButtons.add(editButton); + } else { + fixedButtons.add(button); + } + } + + editButtons.sort(Comparator.comparing(button -> button.getEditor().getKey(), + Comparator.nullsLast(String.CASE_INSENSITIVE_ORDER))); + + setButtons(new HashMap<>()); + for (BInventoryButton button : fixedButtons) { + addButton(button); + } + for (EditGUIButton button : editButtons) { + addButton(button); + } + } +} From fafe3e16b063246eadeb570fbf8f3c22016ad7b8 Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 23 Aug 2026 19:20:53 -0600 Subject: [PATCH 8/8] Test edit GUI value normalization --- .../inventory/EditGUIValueBehaviorTest.java | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 AdvancedCore/src/test/java/com/bencodez/advancedcore/tests/inventory/EditGUIValueBehaviorTest.java diff --git a/AdvancedCore/src/test/java/com/bencodez/advancedcore/tests/inventory/EditGUIValueBehaviorTest.java b/AdvancedCore/src/test/java/com/bencodez/advancedcore/tests/inventory/EditGUIValueBehaviorTest.java new file mode 100644 index 0000000000..4a8098265c --- /dev/null +++ b/AdvancedCore/src/test/java/com/bencodez/advancedcore/tests/inventory/EditGUIValueBehaviorTest.java @@ -0,0 +1,122 @@ +package com.bencodez.advancedcore.tests.inventory; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; + +import org.bukkit.entity.Player; +import org.junit.jupiter.api.Test; + +import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent; +import com.bencodez.advancedcore.api.inventory.editgui.valuetypes.EditGUIValue; +import com.bencodez.advancedcore.api.inventory.editgui.valuetypes.EditGUIValueList; +import com.bencodez.simpleapi.valuerequest.InputMethod; + +public class EditGUIValueBehaviorTest { + + @Test + public void commonValueNormalizationHandlesNullsAndStringNumbers() { + TestValue value = new TestValue("Example", null); + + assertEquals("fallback", value.stringValue("fallback")); + assertEquals(Integer.valueOf(5), value.numberValue(Integer.valueOf(5))); + + value.setCurrentValue("12.5"); + assertEquals(12.5D, value.numberValue(Integer.valueOf(0)).doubleValue()); + + value.setCurrentValue("not-a-number"); + assertEquals(Integer.valueOf(7), value.numberValue(Integer.valueOf(7))); + } + + @Test + public void stringListNormalizationAcceptsAnyCollectionAndIgnoresNulls() { + TestValue value = new TestValue("List", List.of()); + ArrayList input = new ArrayList<>(); + input.add("one"); + input.add(Integer.valueOf(2)); + input.add(null); + value.setCurrentValue(input); + + assertEquals(List.of("one", "2"), value.stringListValue()); + } + + @Test + public void applyValueUpdatesCurrentValueAndInvokesPersistenceHook() { + TestValue value = new TestValue("Example", "old"); + AtomicReference saved = new AtomicReference<>(); + + value.apply(null, "new", saved::set); + + assertEquals("new", saved.get()); + assertEquals("new", value.getCurrentValue()); + } + + @Test + public void nullInputMethodFallsBackToDialog() { + TestValue value = new TestValue("Example", null); + value.inputMethod(null); + assertEquals(InputMethod.DIALOG, value.getInputMethod()); + } + + @Test + public void defaultAndListDisplayMetadataAreCentralized() { + TestValue value = new TestValue("Example", "value"); + assertEquals("&cSet test for Example", value.getButtonName()); + assertEquals(List.of("&cCurrent value: value"), value.getButtonLore()); + + EditGUIValueList list = new EditGUIValueList("Entries", new ArrayList<>(List.of("a", "b"))) { + @Override + public void setValue(Player player, ArrayList value) { + } + }; + assertEquals("&cEdit list for Entries", list.getButtonName()); + assertEquals(List.of("a", "b"), list.getButtonLore()); + + EditGUIValueList nullList = new EditGUIValueList("Entries", null) { + @Override + public void setValue(Player player, ArrayList value) { + } + }; + assertEquals(List.of("&cCurrent value: null"), nullList.getButtonLore()); + } + + @Test + public void containsKeyHandlesMissingEditData() { + TestValue value = new TestValue("Example", null); + assertFalse(value.containsKey(null)); + } + + private static final class TestValue extends EditGUIValue { + private TestValue(String key, Object value) { + super(key, value); + } + + @Override + public String getType() { + return "test"; + } + + @Override + public void onClick(ClickEvent event) { + } + + private String stringValue(String fallback) { + return currentString(fallback); + } + + private Number numberValue(Number fallback) { + return currentNumber(fallback); + } + + private ArrayList stringListValue() { + return currentStringList(); + } + + private void apply(Player player, T value, java.util.function.Consumer consumer) { + applyValue(player, value, consumer); + } + } +}