From 79f1e9c301020376cf2d2315ede155eaddf66e0a Mon Sep 17 00:00:00 2001 From: ags816710 Date: Tue, 9 Jun 2026 18:12:15 +0100 Subject: [PATCH 1/2] feat: support searching enchantments by name and level (e.g., "fortune 3", "fortune iii", etc) - Update enchantment matching logic to parse search queries word-by-word. - Add Roman numeral conversion to support Minecraft's native level formatting (I, II, III, etc.) - hardcoded for now - Ensure both regular enchanted items and Enchanted Books are correctly filtered by their specific enchantment levels. --- .../networkstorage/gui/TerminalGUI.java | 27 +++++++++ .../networkstorage/util/ItemUtils.java | 57 +++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/src/main/java/com/dermoha/networkstorage/gui/TerminalGUI.java b/src/main/java/com/dermoha/networkstorage/gui/TerminalGUI.java index b30a373..d1045f5 100644 --- a/src/main/java/com/dermoha/networkstorage/gui/TerminalGUI.java +++ b/src/main/java/com/dermoha/networkstorage/gui/TerminalGUI.java @@ -6,10 +6,12 @@ import com.dermoha.networkstorage.util.ItemUtils; import org.bukkit.Bukkit; import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.EnchantmentStorageMeta; import org.bukkit.inventory.meta.ItemMeta; import java.util.*; @@ -81,6 +83,31 @@ public void updateInventory() { return true; } + // Check enchantments of enchanted books + if (item.hasItemMeta()) { + ItemMeta meta = item.getItemMeta(); + + // Normal Item Enchants + if (meta.hasEnchants()) { + for (Map.Entry enchEntry : meta.getEnchants().entrySet()) { + if (ItemUtils.matchesEnchantment(enchEntry.getKey(), enchEntry.getValue(), lowerCaseFilter)) { + return true; + } + } + } + + // Enchanted Books + if (meta instanceof EnchantmentStorageMeta storageMeta) { + if (storageMeta.hasStoredEnchants()) { + for (Map.Entry enchEntry : storageMeta.getStoredEnchants().entrySet()) { + if (ItemUtils.matchesEnchantment(enchEntry.getKey(), enchEntry.getValue(), lowerCaseFilter)) { + return true; + } + } + } + } + } + // Fallback check for formatted English name return getItemDisplayName(item).toLowerCase().contains(lowerCaseFilter); }) diff --git a/src/main/java/com/dermoha/networkstorage/util/ItemUtils.java b/src/main/java/com/dermoha/networkstorage/util/ItemUtils.java index 178683a..4460b14 100644 --- a/src/main/java/com/dermoha/networkstorage/util/ItemUtils.java +++ b/src/main/java/com/dermoha/networkstorage/util/ItemUtils.java @@ -1,5 +1,6 @@ package com.dermoha.networkstorage.util; +import org.bukkit.enchantments.Enchantment; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -29,4 +30,60 @@ public static void applyCustomModelData(ItemMeta meta, Integer customModelData) meta.setCustomModelData(customModelData); } } + + public static boolean matchesEnchantment(Enchantment enchantment, int level, String lowerCaseFilter) { + String formattedName = formatEnchantmentName(enchantment).toLowerCase(); + String rawName = enchantment.getKey().getKey().toLowerCase(); + String levelStr = String.valueOf(level); + String romanLevel = toRoman(level).toLowerCase(); + + String[] filterParts = lowerCaseFilter.trim().split("\\s+"); + boolean hasNamePart = false; + boolean hasLevelPart = false; + + for (String part : filterParts) { + if (formattedName.contains(part) || rawName.contains(part)) { + hasNamePart = true; + } + if (part.equals(levelStr) || part.equals(romanLevel)) { + hasLevelPart = true; + } + } + + if (hasNamePart && hasLevelPart) return true; + + return filterParts.length == 1 && (hasNamePart || hasLevelPart); + } + + public static String formatEnchantmentName(Enchantment enchantment) { + String rawName = enchantment.getKey().getKey(); + String[] words = rawName.replace('_', ' ').toLowerCase().split(" "); + StringBuilder displayName = new StringBuilder(); + + for (String word : words) { + if (!word.isEmpty()) { + if (!displayName.isEmpty()) { + displayName.append(" "); + } + displayName.append(Character.toUpperCase(word.charAt(0))).append(word.substring(1)).append(word.substring(1)); + } + } + return displayName.toString(); + } + + // feel free to replace if something better is available + public static String toRoman(int number) { + if (number <= 0) return ""; + if (number == 1) return "I"; + if (number == 2) return "II"; + if (number == 3) return "III"; + if (number == 4) return "IV"; + if (number == 5) return "V"; + if (number == 6) return "VI"; + if (number == 7) return "VII"; + if (number == 8) return "VIII"; + if (number == 9) return "IX"; + if (number == 10) return "X"; + return String.valueOf(number); + } } From 84d4e749ed9f29ad1272885d865d3cfb2df6d397 Mon Sep 17 00:00:00 2001 From: ags816710 Date: Tue, 9 Jun 2026 18:59:08 +0100 Subject: [PATCH 2/2] feat: sort enchanted books alphabetically by enchantment name and level - Add `getSortName` utility to append the primary enchantment name to the base item name and and zero-padded level for sorting. - Ensures enchanted books remain grouped together under "Enchanted Book" while sorting logically by their specific enchantment (e.g., "Enchanted Book - Mending" before "Enchanted Book - Sharpness"). - Ensures enchanted books display in ascending order of level (e.g. Efficiency IV appears after Efficiency II) - Applies to both stored enchants (books) and regular enchanted gear. --- .../networkstorage/gui/TerminalGUI.java | 2 +- .../networkstorage/util/ItemUtils.java | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/dermoha/networkstorage/gui/TerminalGUI.java b/src/main/java/com/dermoha/networkstorage/gui/TerminalGUI.java index d1045f5..5a5dd25 100644 --- a/src/main/java/com/dermoha/networkstorage/gui/TerminalGUI.java +++ b/src/main/java/com/dermoha/networkstorage/gui/TerminalGUI.java @@ -116,7 +116,7 @@ public void updateInventory() { switch (sortType) { case ALPHABETICAL: - sortedItems.sort(Comparator.comparing(a -> getItemDisplayName(a.getKey()), String.CASE_INSENSITIVE_ORDER)); + sortedItems.sort(Comparator.comparing(a -> ItemUtils.getSortableName(a.getKey()), String.CASE_INSENSITIVE_ORDER)); break; case COUNT_DESC: sortedItems.sort(Map.Entry.comparingByValue(Comparator.reverseOrder())); diff --git a/src/main/java/com/dermoha/networkstorage/util/ItemUtils.java b/src/main/java/com/dermoha/networkstorage/util/ItemUtils.java index 4460b14..007a6ef 100644 --- a/src/main/java/com/dermoha/networkstorage/util/ItemUtils.java +++ b/src/main/java/com/dermoha/networkstorage/util/ItemUtils.java @@ -2,8 +2,14 @@ import org.bukkit.enchantments.Enchantment; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.EnchantmentStorageMeta; import org.bukkit.inventory.meta.ItemMeta; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + public final class ItemUtils { private ItemUtils() { @@ -86,4 +92,38 @@ public static String toRoman(int number) { if (number == 10) return "X"; return String.valueOf(number); } + + public static String getSortableName(ItemStack item) { + String displayName = getItemDisplayName(item); + + if (item.hasItemMeta()) { + ItemMeta meta = item.getItemMeta(); + if (meta != null) { + List enchants = new ArrayList<>(); + + if (meta instanceof EnchantmentStorageMeta storageMeta) { + if (storageMeta.hasStoredEnchants()) { + for (Map.Entry entry : storageMeta.getStoredEnchants().entrySet()) { + String name = formatEnchantmentName(entry.getKey()); + String levelStr = String.format("%03d", entry.getValue()); + enchants.add(name + " " + levelStr); + } + } + } else if (meta.hasEnchants()) { + for (Map.Entry entry : meta.getEnchants().entrySet()) { + String name = formatEnchantmentName(entry.getKey()); + String levelStr = String.format("%03d", entry.getValue()); + enchants.add(name + " " + levelStr); + } + } + + if (!enchants.isEmpty()) { + Collections.sort(enchants); + return displayName + " - " + enchants.getFirst(); + } + } + } + + return displayName; + } }