From fc05f78a6304230b7eb9b49b8b6dea9545812cda Mon Sep 17 00:00:00 2001 From: DragonsAscent Date: Tue, 8 Sep 2026 20:26:13 -0400 Subject: [PATCH 1/2] feat: Add sorting options for menu items in MenuSpell --- .../nisovin/magicspells/spells/MenuSpell.java | 43 +++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/com/nisovin/magicspells/spells/MenuSpell.java b/core/src/main/java/com/nisovin/magicspells/spells/MenuSpell.java index d2683161e..3e80503aa 100644 --- a/core/src/main/java/com/nisovin/magicspells/spells/MenuSpell.java +++ b/core/src/main/java/com/nisovin/magicspells/spells/MenuSpell.java @@ -132,6 +132,7 @@ public MenuSpell(MagicConfig config, String spellName) { option.spellSwapName = getConfigString(path + "spell-swap", ""); option.power = getConfigFloat(path + "power", 1); option.modifierList = getConfigStringList(path + "modifiers", null); + option.sortMode = SortMode.fromConfigValue(getConfigString(path + "sort-mode", "none")); option.stayOpen = getConfigBoolean(path + "stay-open", false); options.put(optionName, option); } @@ -293,9 +294,28 @@ private void applyOptionsToInventory(Player opener, MenuInventory menu) { } else quantity = (int) Math.round(variable.getValue(opener)); item.setAmount(quantity); - // Set item for all defined slots. - for (int slot : option.slots) { - if (inv.getItem(slot) == null) inv.setItem(slot, item); + // Set item for the defined slots based on the configured fill behavior. + switch (option.sortMode) { + case FIRST -> { + for (int slot : option.slots) { + if (inv.getItem(slot) != null) continue; + inv.setItem(slot, item); + break; + } + } + case LAST -> { + for (int index = option.slots.size() - 1; index >= 0; index--) { + int slot = option.slots.get(index); + if (inv.getItem(slot) != null) continue; + inv.setItem(slot, item); + break; + } + } + case NONE -> { + for (int slot : option.slots) { + if (inv.getItem(slot) == null) inv.setItem(slot, item); + } + } } } // Fill inventory. @@ -434,6 +454,22 @@ private enum PostClickState { IGNORE } + private enum SortMode { + NONE, + FIRST, + LAST; + + private static SortMode fromConfigValue(String value) { + if (value == null) return NONE; + + return switch (value.toLowerCase()) { + case "first" -> FIRST; + case "last" -> LAST; + default -> NONE; + }; + } + } + private static class MenuOption { private String menuOptionName; @@ -456,6 +492,7 @@ private static class MenuOption { private float power; private List modifierList; private ModifierSet menuOptionModifiers; + private SortMode sortMode; private boolean stayOpen; } From f028bc6f1dc196b81a6864f349bbc3ba76b2c04d Mon Sep 17 00:00:00 2001 From: JasperLorelai Date: Tue, 22 Sep 2026 04:30:27 +0200 Subject: [PATCH 2/2] refactor: Cleanup and debug --- .../nisovin/magicspells/spells/MenuSpell.java | 21 ++++++++----------- .../spells/targeted/MobGoalEditSpell.java | 2 +- .../com/nisovin/magicspells/util/Util.java | 2 +- .../util/recipes/CustomRecipes.java | 2 +- .../util/recipes/types/RecipeFactory.java | 2 +- 5 files changed, 13 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/com/nisovin/magicspells/spells/MenuSpell.java b/core/src/main/java/com/nisovin/magicspells/spells/MenuSpell.java index 3e80503aa..0a7ccaaec 100644 --- a/core/src/main/java/com/nisovin/magicspells/spells/MenuSpell.java +++ b/core/src/main/java/com/nisovin/magicspells/spells/MenuSpell.java @@ -132,8 +132,15 @@ public MenuSpell(MagicConfig config, String spellName) { option.spellSwapName = getConfigString(path + "spell-swap", ""); option.power = getConfigFloat(path + "power", 1); option.modifierList = getConfigStringList(path + "modifiers", null); - option.sortMode = SortMode.fromConfigValue(getConfigString(path + "sort-mode", "none")); option.stayOpen = getConfigBoolean(path + "stay-open", false); + + String modeString = getConfigString(path + "sort-mode", "none"); + option.sortMode = Util.enumValueSafe(SortMode.class, modeString); + if (option.sortMode == null) { + MagicSpells.error("MenuSpell '" + internalName + "' has an invalid 'sort-mode' defined for '" + optionName + "': '" + modeString + "'. Falling back to 'none'."); + option.sortMode = SortMode.NONE; + } + options.put(optionName, option); } size = (int) Math.ceil((maxSlot + 1) / 9.0) * 9; @@ -457,17 +464,7 @@ private enum PostClickState { private enum SortMode { NONE, FIRST, - LAST; - - private static SortMode fromConfigValue(String value) { - if (value == null) return NONE; - - return switch (value.toLowerCase()) { - case "first" -> FIRST; - case "last" -> LAST; - default -> NONE; - }; - } + LAST } private static class MenuOption { diff --git a/core/src/main/java/com/nisovin/magicspells/spells/targeted/MobGoalEditSpell.java b/core/src/main/java/com/nisovin/magicspells/spells/targeted/MobGoalEditSpell.java index 2e93a36d6..7c1b6007c 100644 --- a/core/src/main/java/com/nisovin/magicspells/spells/targeted/MobGoalEditSpell.java +++ b/core/src/main/java/com/nisovin/magicspells/spells/targeted/MobGoalEditSpell.java @@ -38,7 +38,7 @@ public MobGoalEditSpell(MagicConfig config, String spellName) { List removeTypeStrings = getConfigStringList("remove-types", null); if (removeTypeStrings != null) { for (String string : removeTypeStrings) { - GoalType type = Util.enumValueSafe(GoalType.class, string.toUpperCase()); + GoalType type = Util.enumValueSafe(GoalType.class, string); if (type == null) { MagicSpells.error("MobGoalEditSpell '" + internalName + "' lists an invalid value in 'remove-types': " + string); continue; diff --git a/core/src/main/java/com/nisovin/magicspells/util/Util.java b/core/src/main/java/com/nisovin/magicspells/util/Util.java index ae07fe927..ba3bdfbb4 100644 --- a/core/src/main/java/com/nisovin/magicspells/util/Util.java +++ b/core/src/main/java/com/nisovin/magicspells/util/Util.java @@ -576,7 +576,7 @@ public static > C getMaterialList(List st public static > E enumValueSafe(Class clazz, String name) { try { - return Enum.valueOf(clazz, name); + return Enum.valueOf(clazz, name.toUpperCase()); } catch (Exception e) { return null; } diff --git a/core/src/main/java/com/nisovin/magicspells/util/recipes/CustomRecipes.java b/core/src/main/java/com/nisovin/magicspells/util/recipes/CustomRecipes.java index 7b678fad8..43358d08c 100644 --- a/core/src/main/java/com/nisovin/magicspells/util/recipes/CustomRecipes.java +++ b/core/src/main/java/com/nisovin/magicspells/util/recipes/CustomRecipes.java @@ -26,7 +26,7 @@ public static void load(ConfigurationSection recipesSection) { } String typeName = config.getString("type", "none"); - RecipeType type = Util.enumValueSafe(RecipeType.class, typeName.toUpperCase()); + RecipeType type = Util.enumValueSafe(RecipeType.class, typeName); if (type == null) { MagicSpells.error("Recipe '%s' has an invalid 'type' defined: %s".formatted(recipeKey, typeName)); continue; diff --git a/core/src/main/java/com/nisovin/magicspells/util/recipes/types/RecipeFactory.java b/core/src/main/java/com/nisovin/magicspells/util/recipes/types/RecipeFactory.java index 273b81513..06e0af95a 100644 --- a/core/src/main/java/com/nisovin/magicspells/util/recipes/types/RecipeFactory.java +++ b/core/src/main/java/com/nisovin/magicspells/util/recipes/types/RecipeFactory.java @@ -158,7 +158,7 @@ protected final > E resolveEnum(ConfigurationSection config, S String received = config.getString(path); if (received == null) return null; - E value = Util.enumValueSafe(enumClass, received.toUpperCase()); + E value = Util.enumValueSafe(enumClass, received); if (value != null) return value; MagicSpells.error("Invalid %s '%s' for option '%s' on custom recipe '%s'.".formatted(enumClass.getSimpleName(), received, path, config.getName()));