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 59046ef77..0d7b8f672 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/GuiNPCAbilities.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/GuiNPCAbilities.java @@ -7,6 +7,7 @@ import kamkeel.npcs.network.PacketClient; 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 net.minecraft.client.gui.GuiButton; import net.minecraft.client.resources.I18n; import net.minecraft.nbt.NBTTagCompound; @@ -568,7 +569,7 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC AbilitySlot slot = npcSlots.get(selectedAbilityIndex); if (slot.isReference()) { // For reference slots, save back to controller - // (The resolved copy was edited in-place) + PacketClient.sendClient(new CustomAbilitySavePacket(ability.writeNBT())); } else { // For inline slots, replace with the updated ability npcSlots.set(selectedAbilityIndex, AbilitySlot.inline(ability)); diff --git a/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityConfig.java b/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityConfig.java index d2e7d5dc4..c8802a1e0 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityConfig.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityConfig.java @@ -359,6 +359,7 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi @Override public void close() { + GuiNpcTextField.unfocus(); applyToAbility(); callback.onAbilitySaved(ability); super.close(); diff --git a/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityLoad.java b/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityLoad.java index 68a74cb8b..103d446fc 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityLoad.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityLoad.java @@ -10,6 +10,7 @@ import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.client.gui.util.GuiCustomScroll; import noppes.npcs.client.gui.util.GuiNpcButton; import noppes.npcs.client.gui.util.GuiNpcLabel; +import noppes.npcs.client.gui.util.GuiNpcTextField; import noppes.npcs.client.gui.util.ICustomScrollListener; import noppes.npcs.client.gui.util.IGuiData; import noppes.npcs.client.gui.util.IScrollData; @@ -39,6 +40,7 @@ public class SubGuiAbilityLoad extends SubGuiInterface implements ICustomScrollL private HashMap rawData = new HashMap<>(); private GuiCustomScroll scroll; + private String search = ""; private boolean waitingForLoad = false; private int pendingLoadMode = -1; @@ -48,7 +50,7 @@ public class SubGuiAbilityLoad extends SubGuiInterface implements ICustomScrollL setBackground("menubg.png"); xSize = 220; - ySize = 180; + ySize = 216; PacketClient.sendClient(new CustomAbilitiesGetPacket()); } @@ -59,7 +61,7 @@ public class SubGuiAbilityLoad extends SubGuiInterface implements ICustomScrollL setBackground("menubg.png"); xSize = 220; - ySize = 180; + ySize = 216; PacketClient.sendClient(new CustomAbilitiesGetPacket()); } @@ -75,7 +77,7 @@ public class SubGuiAbilityLoad extends SubGuiInterface implements ICustomScrollL if (scroll == null) { scroll = new GuiCustomScroll(this, 0); - scroll.setSize(200, 110); + scroll.setSize(200, 140); } scroll.guiLeft = guiLeft + 10; scroll.guiTop = y; @@ -85,7 +87,12 @@ public class SubGuiAbilityLoad extends SubGuiInterface implements ICustomScrollL } addScroll(scroll); - y += 115; + y += 143; + + // Search bar + addTextField(new GuiNpcTextField(10, this, fontRendererObj, guiLeft + 10, y, 200, 20, search)); + + y += 24; addButton(new GuiNpcButton(0, guiLeft + 10, y, 95, 20, "gui.load")); addButton(new GuiNpcButton(2, guiLeft + 115, y, 95, 20, "gui.cancel")); @@ -94,7 +101,16 @@ public class SubGuiAbilityLoad extends SubGuiInterface implements ICustomScrollL } private List getFilteredList() { - return new ArrayList<>(displayToUuid.keySet()); + if (search.isEmpty()) { + return new ArrayList<>(displayToUuid.keySet()); + } + List list = new ArrayList<>(); + for (String name : displayToUuid.keySet()) { + if (name.toLowerCase().contains(search.toLowerCase())) { + list.add(name); + } + } + return list; } @Override @@ -116,6 +132,19 @@ public class SubGuiAbilityLoad extends SubGuiInterface implements ICustomScrollL } } + @Override + public void keyTyped(char c, int i) { + super.keyTyped(c, i); + if (getTextField(10) != null && getTextField(10).isFocused()) { + String newSearch = getTextField(10).getText(); + if (!search.equals(newSearch)) { + search = newSearch; + scroll.resetScroll(); + scroll.setList(getFilteredList()); + } + } + } + @Override public void subGuiClosed(SubGuiInterface subgui) { if (subgui instanceof SubGuiAbilityLoadMode) { diff --git a/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityTypeSelect.java b/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityTypeSelect.java new file mode 100644 index 000000000..2bf724684 --- /dev/null +++ b/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityTypeSelect.java @@ -0,0 +1,95 @@ +package noppes.npcs.client.gui.advanced; + +import kamkeel.npcs.controllers.data.ability.AbilityController; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.resources.I18n; +import noppes.npcs.client.gui.util.GuiCustomScroll; +import noppes.npcs.client.gui.util.GuiNpcButton; +import noppes.npcs.client.gui.util.GuiNpcLabel; +import noppes.npcs.client.gui.util.ICustomScrollListener; +import noppes.npcs.client.gui.util.SubGuiInterface; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * SubGui for selecting an ability type when creating a new ability. + */ +public class SubGuiAbilityTypeSelect extends SubGuiInterface implements ICustomScrollListener { + + private GuiCustomScroll scroll; + private final HashMap displayNameToTypeId = new HashMap<>(); + private String selectedTypeId = null; + + public SubGuiAbilityTypeSelect() { + setBackground("menubg.png"); + xSize = 200; + ySize = 216; + } + + @Override + public void initGui() { + super.initGui(); + + addLabel(new GuiNpcLabel(0, "ability.selectType", guiLeft + 5, guiTop + 5)); + + if (scroll == null) { + scroll = new GuiCustomScroll(this, 0); + scroll.setSize(190, 165); + } + scroll.guiLeft = guiLeft + 5; + scroll.guiTop = guiTop + 16; + addScroll(scroll); + + List list = buildTypeList(); + scroll.setList(list); + + addButton(new GuiNpcButton(0, guiLeft + 5, guiTop + 188, 90, 20, "gui.add")); + getButton(0).setEnabled(scroll.hasSelected()); + addButton(new GuiNpcButton(1, guiLeft + 105, guiTop + 188, 90, 20, "gui.cancel")); + } + + private List buildTypeList() { + List list = new ArrayList<>(); + displayNameToTypeId.clear(); + String[] types = AbilityController.Instance.getTypes(); + for (String typeId : types) { + String displayName = I18n.format(typeId); + list.add(displayName); + displayNameToTypeId.put(displayName, typeId); + } + return list; + } + + @Override + public void buttonEvent(GuiButton guibutton) { + if (guibutton.id == 0 && scroll.hasSelected()) { + String displayName = scroll.getSelected(); + selectedTypeId = displayNameToTypeId.get(displayName); + close(); + } else if (guibutton.id == 1) { + selectedTypeId = null; + close(); + } + } + + @Override + public void customScrollClicked(int i, int j, int k, GuiCustomScroll guiCustomScroll) { + if (guiCustomScroll.id == 0) { + getButton(0).setEnabled(scroll.hasSelected()); + } + } + + @Override + public void customScrollDoubleClicked(String selection, GuiCustomScroll guiCustomScroll) { + if (guiCustomScroll.id == 0 && selection != null) { + selectedTypeId = displayNameToTypeId.get(selection); + close(); + } + } + + public String getSelectedTypeId() { + return selectedTypeId; + } +} diff --git a/src/main/java/noppes/npcs/client/gui/global/GuiNpcManageAbilities.java b/src/main/java/noppes/npcs/client/gui/global/GuiNpcManageAbilities.java index 8fa2e4e41..49857672d 100644 --- a/src/main/java/noppes/npcs/client/gui/global/GuiNpcManageAbilities.java +++ b/src/main/java/noppes/npcs/client/gui/global/GuiNpcManageAbilities.java @@ -3,6 +3,7 @@ package noppes.npcs.client.gui.global; import kamkeel.npcs.client.renderer.TelegraphRenderer; import kamkeel.npcs.controllers.data.ability.Ability; import kamkeel.npcs.controllers.data.ability.AbilityController; +import java.util.UUID; import kamkeel.npcs.controllers.data.telegraph.TelegraphInstance; import kamkeel.npcs.network.PacketClient; import kamkeel.npcs.network.packets.request.ability.CustomAbilitiesGetPacket; @@ -15,6 +16,7 @@ import net.minecraft.client.gui.GuiYesNoCallback; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.StatCollector; import noppes.npcs.client.NoppesUtil; +import noppes.npcs.client.gui.advanced.SubGuiAbilityTypeSelect; import noppes.npcs.client.gui.util.AbilityPreviewExecutor; import noppes.npcs.client.gui.util.GuiAbilityInterface; import noppes.npcs.client.gui.util.GuiCustomScroll; @@ -87,14 +89,17 @@ public class GuiNpcManageAbilities extends GuiAbilityInterface public void initGui() { super.initGui(); - // Edit button (above Remove) - addButton(new GuiNpcButton(100, guiLeft + 368, guiTop + 8, 45, 20, "gui.edit")); - getButton(100).setEnabled(selected != null && !selected.isEmpty() && selectedAbility != null); + // Add button + addButton(new GuiNpcButton(2, guiLeft + 368, guiTop + 8, 45, 20, "gui.add")); // Remove button addButton(new GuiNpcButton(1, guiLeft + 368, guiTop + 30, 45, 20, "gui.remove")); getButton(1).setEnabled(selected != null && !selected.isEmpty() && displayToUuid.containsKey(selected)); + // Edit button + addButton(new GuiNpcButton(100, guiLeft + 368, guiTop + 52, 45, 20, "gui.edit")); + getButton(100).setEnabled(selected != null && !selected.isEmpty() && selectedAbility != null); + // Scroll list of saved abilities (right side) if (scroll == null) { scroll = new GuiCustomScroll(this, 0); @@ -211,7 +216,10 @@ public class GuiNpcManageAbilities extends GuiAbilityInterface int id = guibutton.id; - if (id == 1 && selected != null && selectedUuid != null) { + if (id == 2) { + // Add — open type selection + setSubGui(new SubGuiAbilityTypeSelect()); + } else if (id == 1 && selected != null && selectedUuid != null) { GuiYesNo guiyesno = new GuiYesNo(this, selected, StatCollector.translateToLocal("gui.delete"), 1); displayGuiScreen(guiyesno); } else if (id == 100 && selectedAbility != null) { @@ -329,6 +337,24 @@ public class GuiNpcManageAbilities extends GuiAbilityInterface @Override public void subGuiClosed(SubGuiInterface subgui) { + if (subgui instanceof SubGuiAbilityTypeSelect) { + String typeId = ((SubGuiAbilityTypeSelect) subgui).getSelectedTypeId(); + if (typeId != null) { + Ability newAbility = AbilityController.Instance.create(typeId); + if (newAbility != null) { + newAbility.setId(UUID.randomUUID().toString()); + newAbility.setName(newAbility.getTypeId()); + // Save to server, then open config GUI + PacketClient.sendClient(new CustomAbilitySavePacket(newAbility.writeNBT())); + selectedAbility = newAbility; + selected = newAbility.getName(); + selectedUuid = newAbility.getId(); + previewExecutor.stop(); + setSubGui(selectedAbility.createConfigGui(this)); + return; + } + } + } initGui(); } diff --git a/src/main/java/noppes/npcs/client/gui/util/GuiContainerNPCInterface.java b/src/main/java/noppes/npcs/client/gui/util/GuiContainerNPCInterface.java index 54ca9da5d..cd3e7077c 100644 --- a/src/main/java/noppes/npcs/client/gui/util/GuiContainerNPCInterface.java +++ b/src/main/java/noppes/npcs/client/gui/util/GuiContainerNPCInterface.java @@ -246,7 +246,10 @@ public abstract class GuiContainerNPCInterface extends GuiContainer { } public void closeSubGui(SubGuiInterface gui) { - subgui = null; + // Only null out subgui if it wasn't replaced by a new one during subGuiClosed + if (subgui == gui) { + subgui = null; + } } public boolean hasSubGui() { diff --git a/src/main/java/noppes/npcs/client/gui/util/GuiNPCInterface.java b/src/main/java/noppes/npcs/client/gui/util/GuiNPCInterface.java index 06f74bffe..cf9143c66 100644 --- a/src/main/java/noppes/npcs/client/gui/util/GuiNPCInterface.java +++ b/src/main/java/noppes/npcs/client/gui/util/GuiNPCInterface.java @@ -536,7 +536,10 @@ public abstract class GuiNPCInterface extends GuiScreen { pendingSubGuiResult = null; handler.accept(gui); } - subgui = null; + // Only null out subgui if it wasn't replaced by a new one during subGuiClosed + if (subgui == gui) { + subgui = null; + } initGui(); } diff --git a/src/main/resources/assets/customnpcs/lang/en_US.lang b/src/main/resources/assets/customnpcs/lang/en_US.lang index ea433dc7e..38a38407c 100644 --- a/src/main/resources/assets/customnpcs/lang/en_US.lang +++ b/src/main/resources/assets/customnpcs/lang/en_US.lang @@ -1824,9 +1824,20 @@ ability.dualFireDelay=Fire Delay ability.save.confirm=Save ability preset ability.save.overwrite=Overwrite existing preset ability.load.select=Select ability to load: +ability.load.mode=How should this ability be loaded? +ability.clone=Clone +ability.reference=Reference ability.delete.confirm=Delete ability preset gui.load=Load +# Ability Edit Mode +ability.edit.mode=How should this ability be edited? +ability.cloneModify=Clone & Edit +ability.modifyParent=Edit Parent + +# Ability Type Selection +ability.selectType=Select Ability Type: + # Global Abilities Manager ability.manager.title=Ability Manager