From 2c3ca1b5ed96e34bc062f53b8199690ce2352713 Mon Sep 17 00:00:00 2001 From: Vidal Date: Wed, 4 Feb 2026 06:18:00 -0300 Subject: [PATCH] Added a filter to browse through abilities from different mods --- src/main/java/kamkeel/npcs/util/Register.java | 80 ++++++++++++++--- .../java/noppes/npcs/NoppesUtilServer.java | 3 +- .../client/gui/advanced/GuiNPCAbilities.java | 85 +++++++++++++++++-- 3 files changed, 150 insertions(+), 18 deletions(-) diff --git a/src/main/java/kamkeel/npcs/util/Register.java b/src/main/java/kamkeel/npcs/util/Register.java index 0f1400ab3..69dbd1991 100644 --- a/src/main/java/kamkeel/npcs/util/Register.java +++ b/src/main/java/kamkeel/npcs/util/Register.java @@ -5,45 +5,92 @@ import kamkeel.npcs.controllers.data.ability.AbilityController; import noppes.npcs.LogWriter; import noppes.npcs.controllers.AnimationController; import noppes.npcs.controllers.data.Animation; -import noppes.npcs.controllers.data.BuiltInAnimation; -import java.util.LinkedHashMap; -import java.util.Map; +import java.util.*; import java.util.function.Supplier; public class Register { + public static final Map> REGISTERED_NAMESPACES = new LinkedHashMap<>(); private final String registryKey; protected final String namespace; protected final Map> entries = new LinkedHashMap<>(); - public Register(String registryKey, String namespace) { + private Register(String registryKey, String namespace) { this.registryKey = registryKey; this.namespace = namespace; } public T register(String factoryName, Supplier factory) { - entries.put(registryKey + "." + namespace + ":" + factoryName, factory); + entries.put(registryKey + "." + namespace + "." + factoryName, factory); return factory.get(); } + public static boolean isEmpty(String registryKey) { + if (REGISTERED_NAMESPACES.isEmpty()) return true; + + if (REGISTERED_NAMESPACES.get(registryKey).isEmpty()) return true; + + return false; + } + + public List catalogue() { + List list = new ArrayList<>(); + for (String regKey : REGISTERED_NAMESPACES.keySet()) { + List nameSp = REGISTERED_NAMESPACES.get(regKey); + for (String name : nameSp) { + List nameSpContent = catalogue(regKey, name); + list.addAll(nameSpContent); + } + } + + return list; + } + + public List catalogue(String namespace) { + return catalogue(registryKey, namespace); + } + + public List catalogue(String registryKey, String namespace) { + List list = new ArrayList<>(); + for (Map.Entry> entry : entries.entrySet()) { + if (entry.getKey().startsWith(registryKey + "." + namespace + ":")) + list.add(entry.getValue().get()); + } + + return list; + } + public static class Abilities extends Register { - public Abilities(String namespace) { + private Abilities(String namespace) { super("ability", namespace); } public void register() { for (Map.Entry> entry : entries.entrySet()) { - AbilityController.Instance.registerType(entry.getKey(), entry.getValue()); + AbilityController.Instance.registerType(entry.getValue().get().getTypeId(), entry.getValue()); } } + + public static Register.Abilities create(String namespace) { + if (!REGISTERED_NAMESPACES.containsKey("ability")) + REGISTERED_NAMESPACES.put("ability", new ArrayList<>()); + + if (REGISTERED_NAMESPACES.get("ability").contains(namespace)) { + LogWriter.error("REGISTER ABILITIES: Namespace " + namespace + " already registered!"); + } + + REGISTERED_NAMESPACES.get("ability").add(namespace); + + return new Register.Abilities(namespace); + } } public static class Animations extends Register { private final Class modClass; private final String animationsPath; - public Animations(Class modClass, String animationsPath, String namespace) { - super("ability", namespace); + private Animations(Class modClass, String animationsPath, String namespace) { + super("animation", namespace); this.animationsPath = animationsPath; this.modClass = modClass; } @@ -57,12 +104,25 @@ public class Register { try { String path = "/assets/" + namespace + "/" + animationsPath; for (Map.Entry> entry : entries.entrySet()) { - String name = entry.getKey().substring(entry.getKey().indexOf(":") + 1); + String name = entry.getKey().substring(entry.getKey().indexOf(namespace + ".") + 1); AnimationController.Instance.loadBuiltInAnimation(modClass, path, name); } } catch (Exception e) { LogWriter.error("Error scanning built-in animations folder", e); } } + + public static Register.Animations create(Class modClass, String animationsPath, String namespace) { + if (!REGISTERED_NAMESPACES.containsKey("animation")) + REGISTERED_NAMESPACES.put("animation", new ArrayList<>()); + + if (REGISTERED_NAMESPACES.get("animation").contains(namespace)) { + LogWriter.error("REGISTER ANIMATIONS: Namespace " + namespace + " already registered!"); + } + + REGISTERED_NAMESPACES.get("animation").add(namespace); + + return new Register.Animations(modClass, animationsPath, namespace); + } } } diff --git a/src/main/java/noppes/npcs/NoppesUtilServer.java b/src/main/java/noppes/npcs/NoppesUtilServer.java index 0799e7a6c..4b93ad2b5 100644 --- a/src/main/java/noppes/npcs/NoppesUtilServer.java +++ b/src/main/java/noppes/npcs/NoppesUtilServer.java @@ -2,6 +2,7 @@ package noppes.npcs; import io.netty.buffer.ByteBuf; import kamkeel.npcs.controllers.SyncController; +import kamkeel.npcs.controllers.data.ability.AbilityController; import kamkeel.npcs.network.PacketHandler; import kamkeel.npcs.network.packets.data.ParticlePacket; import kamkeel.npcs.network.packets.data.PlayerDataInfoPacket; @@ -775,7 +776,7 @@ public class NoppesUtilServer { public static void sendAbilityTypesInfo(EntityPlayerMP player) { HashMap map = new HashMap(); - kamkeel.npcs.controllers.data.ability.AbilityController controller = kamkeel.npcs.controllers.data.ability.AbilityController.Instance; + AbilityController controller = AbilityController.Instance; if (controller != null) { int index = 0; for (String typeId : controller.getTypes()) { diff --git a/src/main/java/noppes/npcs/client/gui/advanced/GuiNPCAbilities.java b/src/main/java/noppes/npcs/client/gui/advanced/GuiNPCAbilities.java index 0d7b8f672..6349872ea 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/GuiNPCAbilities.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/GuiNPCAbilities.java @@ -8,6 +8,7 @@ import kamkeel.npcs.network.packets.request.ability.AbilitiesGetAllPacket; import kamkeel.npcs.network.packets.request.ability.AbilitiesNpcGetPacket; import kamkeel.npcs.network.packets.request.ability.AbilitiesNpcSavePacket; import kamkeel.npcs.network.packets.request.ability.CustomAbilitySavePacket; +import kamkeel.npcs.util.Register; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.resources.I18n; import net.minecraft.nbt.NBTTagCompound; @@ -27,11 +28,7 @@ import noppes.npcs.client.gui.util.SubGuiInterface; import noppes.npcs.constants.EnumScrollData; import noppes.npcs.entity.EntityNPCInterface; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.UUID; -import java.util.Vector; +import java.util.*; /** * GUI for managing NPC abilities. @@ -44,6 +41,7 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC // All available ability types (typeId -> index) private final HashMap allAbilityTypes = new HashMap<>(); + private final HashMap filteredAbilityTypes = new HashMap<>(); // Display name to typeId mapping for the available types scroll private final HashMap displayNameToTypeId = new HashMap<>(); @@ -59,12 +57,35 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC private String search = ""; private int selectedAbilityIndex = -1; + public static int modIndex = 0; + public static ScrollType scrollType = ScrollType.CNPC; + public GuiNPCAbilities(EntityNPCInterface npc) { super(npc); PacketClient.sendClient(new AbilitiesGetAllPacket()); PacketClient.sendClient(new AbilitiesNpcGetPacket()); } + public enum ScrollType { + CNPC, + MODDED, + ALL; + + @Override + public String toString() { + switch (this) { + case CNPC: return "CustomNPCs"; + case MODDED: + if (Register.isEmpty("ability")) + return "modded"; + + return Register.REGISTERED_NAMESPACES.get("ability").get(modIndex); + case ALL: return "filter.all"; + default: return name(); + } + } + } + @Override public void initGui() { super.initGui(); @@ -94,13 +115,15 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC addLabel(new GuiNpcLabel(1, "ability.availableTypes", guiLeft + 5, y)); if (availableTypesScroll == null) { availableTypesScroll = new GuiCustomScroll(this, 0); - availableTypesScroll.setSize(140, 130); + availableTypesScroll.setSize(140, 103); } availableTypesScroll.guiLeft = guiLeft + 5; availableTypesScroll.guiTop = y + 12; availableTypesScroll.setList(getFilteredTypeList()); addScroll(availableTypesScroll); + addButton(new GuiNpcButton(50, guiLeft + 5, y + 120, 140, 20, scrollType.toString())); + // Search bar for types addTextField(new GuiNpcTextField(4, this, fontRendererObj, guiLeft + 5, y + 145, 140, 18, search)); @@ -275,6 +298,27 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC return; } + if (id == 50) { + if (scrollType != ScrollType.MODDED) { + ScrollType[] values = ScrollType.values(); + scrollType = values[(scrollType.ordinal() + 1) % values.length]; + } else { + List list = Register.REGISTERED_NAMESPACES.get("ability"); + + if (list != null && !list.isEmpty()) { + modIndex = (modIndex + 1) % list.size(); + } else { + modIndex = 0; + scrollType = ScrollType.ALL; + } + } + + Map dummyMap = new HashMap<>(allAbilityTypes); + filteredAbilityTypes.clear(); + filteredAbilityTypes.putAll(getFilteredData(dummyMap)); + } + + initGui(); } @@ -283,6 +327,8 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC if (type == EnumScrollData.ABILITY_TYPES) { allAbilityTypes.clear(); allAbilityTypes.putAll(data); + + filteredAbilityTypes.putAll(getFilteredData(allAbilityTypes)); if (availableTypesScroll != null) { availableTypesScroll.setList(getFilteredTypeList()); } @@ -341,10 +387,35 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC } } + private HashMap getFilteredData(Map data) { + HashMap filteredData = new HashMap<>(); + if (scrollType == ScrollType.CNPC) { + data.entrySet().stream() + .filter(e -> e.getKey().startsWith("ability.cnpc.")) + .forEach(e -> filteredData.put(e.getKey(), e.getValue())); + } else if (scrollType == ScrollType.MODDED) { + if (!Register.isEmpty("ability")) { + List registerList = Register.REGISTERED_NAMESPACES.get("ability"); + + if (!registerList.isEmpty()) { + String namespace = registerList.get(modIndex); + + data.entrySet().stream() + .filter(e -> e.getKey().startsWith("ability." + namespace + ".")) + .forEach(e -> filteredData.put(e.getKey(), e.getValue())); + } + } + } else { + filteredData.putAll(data); + } + + return filteredData; + } + private List getFilteredTypeList() { List list = new ArrayList<>(); displayNameToTypeId.clear(); - for (String typeId : allAbilityTypes.keySet()) { + for (String typeId : filteredAbilityTypes.keySet()) { String displayName = I18n.format(typeId); // Search matches either the display name or the typeId if (search.isEmpty() || displayName.toLowerCase().contains(search) || typeId.toLowerCase().contains(search)) {