2025-03-04 17:42:03 -05:00
|
|
|
|
package noppes.npcs.client.gui;
|
2025-03-04 17:41:17 -05:00
|
|
|
|
|
|
|
|
|
|
import kamkeel.npcs.network.PacketClient;
|
|
|
|
|
|
import kamkeel.npcs.network.packets.request.magic.MagicCycleSavePacket;
|
|
|
|
|
|
import net.minecraft.client.gui.GuiButton;
|
|
|
|
|
|
import net.minecraft.nbt.NBTTagCompound;
|
|
|
|
|
|
import noppes.npcs.client.gui.global.GuiNpcManageMagic;
|
2025-07-23 14:22:52 -04:00
|
|
|
|
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.ISubGuiListener;
|
|
|
|
|
|
import noppes.npcs.client.gui.util.ITextfieldListener;
|
|
|
|
|
|
import noppes.npcs.client.gui.util.SubGuiInterface;
|
2025-03-04 17:41:17 -05:00
|
|
|
|
import noppes.npcs.constants.EnumDiagramLayout;
|
|
|
|
|
|
import noppes.npcs.controllers.data.MagicAssociation;
|
|
|
|
|
|
import noppes.npcs.controllers.data.MagicCycle;
|
|
|
|
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
|
|
|
|
public class SubGuiMagicCycle extends SubGuiInterface implements ITextfieldListener, ISubGuiListener, ICustomScrollListener {
|
|
|
|
|
|
|
|
|
|
|
|
// Reference to the parent GUI (for accessing magicData)
|
|
|
|
|
|
public GuiNpcManageMagic parent;
|
|
|
|
|
|
// Scroll for available magics (to add as associations)
|
|
|
|
|
|
private GuiCustomScroll allMagic;
|
|
|
|
|
|
// Scroll for magics already associated with the cycle
|
|
|
|
|
|
private GuiCustomScroll associationScroll;
|
|
|
|
|
|
|
|
|
|
|
|
// The MagicCycle we are editing
|
|
|
|
|
|
private MagicCycle cycle;
|
|
|
|
|
|
|
|
|
|
|
|
// Search string for available magics
|
|
|
|
|
|
private String search = "";
|
|
|
|
|
|
|
|
|
|
|
|
// Text fields for basic cycle data
|
|
|
|
|
|
// ID 1: cycle name, ID 2: cycle display name
|
|
|
|
|
|
// Button ID 13 will cycle through the layouts
|
|
|
|
|
|
// IDs 91 & 92 for editing selected association’s index and priority
|
|
|
|
|
|
private GuiNpcTextField indexField;
|
|
|
|
|
|
private GuiNpcTextField priorityField;
|
|
|
|
|
|
|
|
|
|
|
|
// The currently selected associated magic (by its name)
|
|
|
|
|
|
private String selectedAssociation;
|
|
|
|
|
|
// A mapping of magic names (from parent.magicData) to their MagicAssociation objects.
|
|
|
|
|
|
private HashMap<String, MagicAssociation> associationMap = new HashMap<>();
|
|
|
|
|
|
|
|
|
|
|
|
public SubGuiMagicCycle(GuiNpcManageMagic parent, MagicCycle cycle) {
|
|
|
|
|
|
this.parent = parent;
|
|
|
|
|
|
this.cycle = cycle;
|
|
|
|
|
|
setBackground("menubg.png");
|
|
|
|
|
|
xSize = 415;
|
|
|
|
|
|
ySize = 216;
|
|
|
|
|
|
closeOnEsc = true;
|
|
|
|
|
|
processAssociations();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void initGui() {
|
|
|
|
|
|
super.initGui();
|
|
|
|
|
|
int y = guiTop + 6;
|
|
|
|
|
|
|
|
|
|
|
|
// --- Basic Cycle Data ---
|
|
|
|
|
|
addLabel(new GuiNpcLabel(1, "gui.name", guiLeft + 4, y + 5));
|
|
|
|
|
|
addTextField(new GuiNpcTextField(1, this, fontRendererObj, guiLeft + 80, y, 200, 20, cycle.name));
|
|
|
|
|
|
|
2025-03-13 17:14:45 -04:00
|
|
|
|
addLabel(new GuiNpcLabel(-10, "ID", guiLeft + 200 + 80 + 5, y + 2));
|
2025-03-04 17:41:17 -05:00
|
|
|
|
addLabel(new GuiNpcLabel(-11, cycle.id + "", guiLeft + 200 + 80 + 5, y + 12));
|
|
|
|
|
|
|
|
|
|
|
|
// Layout button – cycles through available layouts
|
|
|
|
|
|
addLabel(new GuiNpcLabel(3, "magic.diagram", guiLeft + 307, y + 5));
|
|
|
|
|
|
|
|
|
|
|
|
y += 25;
|
|
|
|
|
|
|
|
|
|
|
|
addButton(new GuiNpcButton(13, guiLeft + 307, y, 100, 20, EnumDiagramLayout.names(), cycle.layout.ordinal()));
|
|
|
|
|
|
getButton(13).setHoverText("diagram.info");
|
|
|
|
|
|
|
|
|
|
|
|
addLabel(new GuiNpcLabel(2, "gui.displayName", guiLeft + 4, y + 5));
|
|
|
|
|
|
addTextField(new GuiNpcTextField(2, this, fontRendererObj, guiLeft + 80, y, 200, 20, cycle.displayName));
|
|
|
|
|
|
|
|
|
|
|
|
y += 27;
|
|
|
|
|
|
|
2025-04-15 20:02:34 -04:00
|
|
|
|
String index = "gui.unused";
|
|
|
|
|
|
String priority = "gui.unused";
|
2025-05-20 13:53:32 -04:00
|
|
|
|
if (cycle.layout == EnumDiagramLayout.MANUAL) {
|
2025-04-15 20:02:34 -04:00
|
|
|
|
index = "X";
|
|
|
|
|
|
priority = "Y";
|
2025-05-20 13:53:32 -04:00
|
|
|
|
} else if (cycle.layout.isManual()) {
|
2025-04-15 20:02:34 -04:00
|
|
|
|
index = "magic.index";
|
|
|
|
|
|
priority = "magic.priority";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
addLabel(new GuiNpcLabel(50, index, guiLeft + 5, y + 5));
|
2025-03-04 17:41:17 -05:00
|
|
|
|
indexField = new GuiNpcTextField(91, this, fontRendererObj, guiLeft + 100, y, 45, 20, "");
|
|
|
|
|
|
indexField.setIntegersOnly();
|
|
|
|
|
|
addTextField(indexField);
|
|
|
|
|
|
|
2025-04-15 20:02:34 -04:00
|
|
|
|
addLabel(new GuiNpcLabel(51, priority, guiLeft + 150, y + 5));
|
2025-03-04 17:41:17 -05:00
|
|
|
|
priorityField = new GuiNpcTextField(92, this, fontRendererObj, guiLeft + 250, y, 45, 20, "");
|
|
|
|
|
|
priorityField.setIntegersOnly();
|
|
|
|
|
|
addTextField(priorityField);
|
|
|
|
|
|
|
|
|
|
|
|
indexField.enabled = false;
|
|
|
|
|
|
priorityField.enabled = false;
|
|
|
|
|
|
|
2025-04-15 20:02:34 -04:00
|
|
|
|
if (selectedAssociation != null && associationMap.containsKey(selectedAssociation)) {
|
|
|
|
|
|
indexField.enabled = true;
|
|
|
|
|
|
priorityField.enabled = true;
|
|
|
|
|
|
indexField.setText(associationMap.get(selectedAssociation).index + "");
|
|
|
|
|
|
priorityField.setText(associationMap.get(selectedAssociation).priority + "");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-03-04 17:41:17 -05:00
|
|
|
|
y += 27;
|
|
|
|
|
|
|
|
|
|
|
|
// --- Association Management ---
|
|
|
|
|
|
// Scroll for available magics to add
|
2025-03-13 17:14:45 -04:00
|
|
|
|
if (allMagic == null) {
|
2025-03-04 17:41:17 -05:00
|
|
|
|
allMagic = new GuiCustomScroll(this, 0);
|
|
|
|
|
|
allMagic.setSize(150, 100);
|
|
|
|
|
|
}
|
|
|
|
|
|
allMagic.guiLeft = guiLeft + 5;
|
|
|
|
|
|
allMagic.guiTop = y;
|
|
|
|
|
|
// Set list based on parent's magicData filtered by search
|
|
|
|
|
|
allMagic.setList(getAvailableMagicList());
|
|
|
|
|
|
this.addScroll(allMagic);
|
|
|
|
|
|
|
|
|
|
|
|
// Search field for available magics (ID 34)
|
|
|
|
|
|
addTextField(new GuiNpcTextField(34, this, fontRendererObj, guiLeft + 5, y + 105, 150, 20, search));
|
|
|
|
|
|
|
|
|
|
|
|
// Scroll for current associations
|
2025-03-13 17:14:45 -04:00
|
|
|
|
if (associationScroll == null) {
|
2025-03-04 17:41:17 -05:00
|
|
|
|
associationScroll = new GuiCustomScroll(this, 1);
|
|
|
|
|
|
associationScroll.setSize(150, 125);
|
|
|
|
|
|
}
|
|
|
|
|
|
associationScroll.guiLeft = guiLeft + 205;
|
|
|
|
|
|
associationScroll.guiTop = y;
|
|
|
|
|
|
// Populate with keys from associationMap
|
|
|
|
|
|
associationScroll.setList(new ArrayList<>(associationMap.keySet()));
|
|
|
|
|
|
this.addScroll(associationScroll);
|
|
|
|
|
|
|
|
|
|
|
|
// Buttons to add/remove associations (IDs 60, 61, 62, 63)
|
|
|
|
|
|
addButton(new GuiNpcButton(60, guiLeft + 160, y + 20, 30, 20, ">"));
|
|
|
|
|
|
addButton(new GuiNpcButton(61, guiLeft + 160, y + 45, 30, 20, "<"));
|
|
|
|
|
|
addButton(new GuiNpcButton(62, guiLeft + 160, y + 70, 30, 20, ">>"));
|
|
|
|
|
|
addButton(new GuiNpcButton(63, guiLeft + 160, y + 95, 30, 20, "<<"));
|
|
|
|
|
|
|
|
|
|
|
|
// Done Button to save changes
|
|
|
|
|
|
addButton(new GuiNpcButton(99, guiLeft + xSize - 50 - 4, guiTop + ySize - 20 - 4, 50, 20, "gui.done"));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void actionPerformed(GuiButton button) {
|
|
|
|
|
|
// Layout button: update cycle layout.
|
2025-03-13 17:14:45 -04:00
|
|
|
|
if (button.id == 13) {
|
|
|
|
|
|
cycle.layout = EnumDiagramLayout.values()[((GuiNpcButton) button).getValue()];
|
2025-04-15 20:02:34 -04:00
|
|
|
|
initGui();
|
2025-03-04 17:41:17 -05:00
|
|
|
|
}
|
|
|
|
|
|
// Add single association
|
2025-03-13 17:14:45 -04:00
|
|
|
|
if (button.id == 60 && allMagic.hasSelected() && !associationMap.containsKey(allMagic.getSelected())
|
|
|
|
|
|
&& parent.magicData.containsKey(allMagic.getSelected())) {
|
2025-03-04 17:41:17 -05:00
|
|
|
|
MagicAssociation assoc = new MagicAssociation();
|
|
|
|
|
|
assoc.magicId = parent.magicData.get(allMagic.getSelected());
|
|
|
|
|
|
assoc.index = 0;
|
|
|
|
|
|
assoc.priority = 0;
|
|
|
|
|
|
associationMap.put(allMagic.getSelected(), assoc);
|
|
|
|
|
|
associationScroll.list.add(allMagic.getSelected());
|
|
|
|
|
|
}
|
|
|
|
|
|
// Remove single association
|
2025-03-13 17:14:45 -04:00
|
|
|
|
if (button.id == 61 && associationScroll.hasSelected()) {
|
2025-03-04 17:41:17 -05:00
|
|
|
|
associationMap.remove(associationScroll.getSelected());
|
|
|
|
|
|
associationScroll.list.remove(associationScroll.selected);
|
|
|
|
|
|
associationScroll.selected = -1;
|
|
|
|
|
|
indexField.enabled = false;
|
|
|
|
|
|
indexField.setText("");
|
|
|
|
|
|
priorityField.enabled = false;
|
|
|
|
|
|
priorityField.setText("");
|
|
|
|
|
|
}
|
|
|
|
|
|
// Add All available associations
|
2025-03-13 17:14:45 -04:00
|
|
|
|
if (button.id == 62) {
|
|
|
|
|
|
for (String name : parent.magicData.keySet()) {
|
|
|
|
|
|
if (!associationMap.containsKey(name)) {
|
2025-03-04 17:41:17 -05:00
|
|
|
|
MagicAssociation assoc = new MagicAssociation();
|
|
|
|
|
|
assoc.magicId = parent.magicData.get(name);
|
|
|
|
|
|
assoc.index = 0;
|
|
|
|
|
|
assoc.priority = 0;
|
|
|
|
|
|
associationMap.put(name, assoc);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
associationScroll.setList(new ArrayList<>(associationMap.keySet()));
|
|
|
|
|
|
}
|
|
|
|
|
|
// Remove All associations
|
2025-03-13 17:14:45 -04:00
|
|
|
|
if (button.id == 63) {
|
2025-03-04 17:41:17 -05:00
|
|
|
|
associationMap.clear();
|
|
|
|
|
|
associationScroll.setList(new ArrayList<>());
|
|
|
|
|
|
associationScroll.selected = -1;
|
|
|
|
|
|
indexField.enabled = false;
|
|
|
|
|
|
indexField.setText("");
|
|
|
|
|
|
priorityField.enabled = false;
|
|
|
|
|
|
priorityField.setText("");
|
|
|
|
|
|
}
|
|
|
|
|
|
// Done – save changes and close
|
2025-03-13 17:14:45 -04:00
|
|
|
|
if (button.id == 99) {
|
2025-03-04 17:41:17 -05:00
|
|
|
|
close();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void unFocused(GuiNpcTextField textField) {
|
|
|
|
|
|
// Update cycle basic data.
|
2025-03-13 17:14:45 -04:00
|
|
|
|
if (textField.id == 1) {
|
2025-03-04 17:41:17 -05:00
|
|
|
|
cycle.name = textField.getText();
|
|
|
|
|
|
}
|
2025-03-13 17:14:45 -04:00
|
|
|
|
if (textField.id == 2) {
|
2025-03-04 17:41:17 -05:00
|
|
|
|
cycle.displayName = textField.getText();
|
|
|
|
|
|
}
|
|
|
|
|
|
// Update association ordering values when fields lose focus.
|
2025-03-13 17:14:45 -04:00
|
|
|
|
if (textField.id == 91 && selectedAssociation != null) {
|
2025-03-04 17:41:17 -05:00
|
|
|
|
try {
|
|
|
|
|
|
int idx = Integer.parseInt(textField.getText());
|
|
|
|
|
|
associationMap.get(selectedAssociation).index = idx;
|
2025-03-13 17:14:45 -04:00
|
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
|
|
}
|
2025-03-04 17:41:17 -05:00
|
|
|
|
}
|
2025-03-13 17:14:45 -04:00
|
|
|
|
if (textField.id == 92 && selectedAssociation != null) {
|
2025-03-04 17:41:17 -05:00
|
|
|
|
try {
|
|
|
|
|
|
int prio = Integer.parseInt(textField.getText());
|
|
|
|
|
|
associationMap.get(selectedAssociation).priority = prio;
|
2025-03-13 17:14:45 -04:00
|
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
|
|
}
|
2025-03-04 17:41:17 -05:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void keyTyped(char c, int i) {
|
|
|
|
|
|
super.keyTyped(c, i);
|
|
|
|
|
|
// Available magic search (text field ID 34)
|
2025-03-13 17:14:45 -04:00
|
|
|
|
if (getTextField(34) != null && getTextField(34).isFocused()) {
|
|
|
|
|
|
if (search.equals(getTextField(34).getText()))
|
2025-03-04 17:41:17 -05:00
|
|
|
|
return;
|
|
|
|
|
|
search = getTextField(34).getText().toLowerCase();
|
|
|
|
|
|
allMagic.setList(getAvailableMagicList());
|
|
|
|
|
|
allMagic.resetScroll();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Returns a filtered list of available magic names based on parent's magicData and the search string.
|
|
|
|
|
|
* Only those not already in the associationMap are shown.
|
|
|
|
|
|
*/
|
2025-03-13 17:14:45 -04:00
|
|
|
|
private List<String> getAvailableMagicList() {
|
2025-03-04 17:41:17 -05:00
|
|
|
|
List<String> original = new ArrayList<>(parent.magicData.keySet());
|
|
|
|
|
|
List<String> filtered = new ArrayList<>();
|
2025-03-13 17:14:45 -04:00
|
|
|
|
for (String name : original) {
|
|
|
|
|
|
if (!associationMap.containsKey(name) && name.toLowerCase().contains(search)) {
|
2025-03-04 17:41:17 -05:00
|
|
|
|
filtered.add(name);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return filtered;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Populates associationMap from cycle.associations using parent's magicData.
|
|
|
|
|
|
*/
|
2025-03-13 17:14:45 -04:00
|
|
|
|
public void processAssociations() {
|
2025-03-04 17:41:17 -05:00
|
|
|
|
associationMap.clear();
|
|
|
|
|
|
// For each association stored in the cycle, find the corresponding magic name.
|
2025-03-13 17:14:45 -04:00
|
|
|
|
for (MagicAssociation assoc : cycle.associations.values()) {
|
|
|
|
|
|
for (String name : parent.magicData.keySet()) {
|
|
|
|
|
|
if (parent.magicData.get(name) == assoc.magicId) {
|
2025-03-04 17:41:17 -05:00
|
|
|
|
associationMap.put(name, assoc);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void customScrollClicked(int id, int index, int clickType, GuiCustomScroll scroll) {
|
|
|
|
|
|
// When clicking the association scroll, update the ordering text fields.
|
2025-03-13 17:14:45 -04:00
|
|
|
|
if (scroll.id == 1) {
|
2025-03-04 17:41:17 -05:00
|
|
|
|
selectedAssociation = scroll.getSelected();
|
2025-03-13 17:14:45 -04:00
|
|
|
|
if (selectedAssociation != null && associationMap.containsKey(selectedAssociation)) {
|
2025-03-04 17:41:17 -05:00
|
|
|
|
indexField.enabled = true;
|
|
|
|
|
|
priorityField.enabled = true;
|
|
|
|
|
|
indexField.setText(associationMap.get(selectedAssociation).index + "");
|
|
|
|
|
|
priorityField.setText(associationMap.get(selectedAssociation).priority + "");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
2025-03-13 17:14:45 -04:00
|
|
|
|
public void customScrollDoubleClicked(String selection, GuiCustomScroll scroll) {
|
|
|
|
|
|
}
|
2025-03-04 17:41:17 -05:00
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void subGuiClosed(SubGuiInterface subgui) {
|
|
|
|
|
|
// No subgui handling in this example.
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Called when the user clicks "Done". Updates the cycle's associations from associationMap,
|
|
|
|
|
|
* writes the NBT data, and sends a MagicCycleSavePacket.
|
|
|
|
|
|
*/
|
2025-03-13 17:14:45 -04:00
|
|
|
|
public void close() {
|
2025-03-04 17:41:17 -05:00
|
|
|
|
// Clear the cycle's associations and update them from our associationMap.
|
|
|
|
|
|
cycle.associations.clear();
|
2025-03-13 17:14:45 -04:00
|
|
|
|
for (String name : associationMap.keySet()) {
|
2025-03-04 17:41:17 -05:00
|
|
|
|
cycle.associations.put(associationMap.get(name).magicId, associationMap.get(name));
|
|
|
|
|
|
}
|
|
|
|
|
|
NBTTagCompound compound = new NBTTagCompound();
|
|
|
|
|
|
cycle.writeNBT(compound);
|
|
|
|
|
|
PacketClient.sendClient(new MagicCycleSavePacket(compound));
|
|
|
|
|
|
super.close();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|