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..0a7ccaaec 100644 --- a/core/src/main/java/com/nisovin/magicspells/spells/MenuSpell.java +++ b/core/src/main/java/com/nisovin/magicspells/spells/MenuSpell.java @@ -133,6 +133,14 @@ public MenuSpell(MagicConfig config, String spellName) { option.power = getConfigFloat(path + "power", 1); option.modifierList = getConfigStringList(path + "modifiers", null); 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; @@ -293,9 +301,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 +461,12 @@ private enum PostClickState { IGNORE } + private enum SortMode { + NONE, + FIRST, + LAST + } + private static class MenuOption { private String menuOptionName; @@ -456,6 +489,7 @@ private static class MenuOption { private float power; private List modifierList; private ModifierSet menuOptionModifiers; + private SortMode sortMode; private boolean stayOpen; } 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()));