From f0547cf876047d8c904844cedb0bf96ba3661bba Mon Sep 17 00:00:00 2001 From: Kam Date: Tue, 4 Mar 2025 21:03:36 -0500 Subject: [PATCH] Magic Diagram Viewer --- .../npcs/client/gui/GuiMagicCycleMap.java | 196 ++++++++++++++++++ .../noppes/npcs/client/gui/GuiMagicMap.java | 132 ------------ .../client/gui/SubGuiMagicCycleViewer.java | 68 ++++++ .../client/gui/global/GuiNpcManageMagic.java | 11 + .../npcs/client/gui/util/GuiDiagram.java | 29 ++- .../npcs/constants/EnumDiagramLayout.java | 4 + 6 files changed, 291 insertions(+), 149 deletions(-) create mode 100644 src/main/java/noppes/npcs/client/gui/GuiMagicCycleMap.java delete mode 100644 src/main/java/noppes/npcs/client/gui/GuiMagicMap.java create mode 100644 src/main/java/noppes/npcs/client/gui/SubGuiMagicCycleViewer.java diff --git a/src/main/java/noppes/npcs/client/gui/GuiMagicCycleMap.java b/src/main/java/noppes/npcs/client/gui/GuiMagicCycleMap.java new file mode 100644 index 000000000..522bf2a62 --- /dev/null +++ b/src/main/java/noppes/npcs/client/gui/GuiMagicCycleMap.java @@ -0,0 +1,196 @@ +package noppes.npcs.client.gui; + +import noppes.npcs.client.ClientCacheHandler; +import noppes.npcs.client.gui.util.GuiDiagram; +import noppes.npcs.client.gui.util.GuiNPCInterface; +import noppes.npcs.client.renderer.ImageData; +import noppes.npcs.controllers.MagicController; +import noppes.npcs.controllers.data.Magic; +import noppes.npcs.controllers.data.MagicAssociation; +import noppes.npcs.controllers.data.MagicCycle; +import noppes.npcs.constants.EnumDiagramLayout; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import org.lwjgl.opengl.GL11; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class GuiMagicCycleMap extends GuiDiagram { + + private List cycleMagics; + private MagicCycle cycle; + + /** + * Constructor using a MagicCycle object. + */ + public GuiMagicCycleMap(GuiNPCInterface parent, int x, int y, int width, int height, MagicCycle cycle) { + super(parent, x, y, width, height); + this.cycle = cycle; + cycleMagics = new ArrayList<>(); + // If cycle is null, leave cycleMagics empty. + if (this.cycle == null) { + setLayout(EnumDiagramLayout.CIRCULAR_MANUAL); + setCurvedArrows(true); + setCurveAngle(-20); + invalidateCache(); + return; + } + MagicController mc = MagicController.getInstance(); + // Get magics from the cycle's associations if associations are not null. + if (cycle.associations != null) { + for (MagicAssociation assoc : cycle.associations.values()) { + Magic m = mc.getMagic(assoc.magicId); + if (m != null) { + cycleMagics.add(m); + } + } + } + + // Use the cycle's layout if set; otherwise default to CIRCULAR_MANUAL. + setLayout(cycle.layout != null ? cycle.layout : EnumDiagramLayout.CIRCULAR_MANUAL); + setCurvedArrows(true); + setCurveAngle(-20); + invalidateCache(); + + this.iconSize = 20; + this.slotSize = iconSize + slotPadding; + } + + /** + * Constructor using a cycle ID. + */ + public GuiMagicCycleMap(GuiNPCInterface parent, int x, int y, int width, int height, int cycleId) { + this(parent, x, y, width, height, MagicController.getInstance().getCycle(cycleId)); + } + + @Override + protected List createIcons() { + List icons = new ArrayList<>(); + // If the magic list is empty, simply return an empty list. + if (cycleMagics == null || cycleMagics.isEmpty()) { + return icons; + } + // For each magic in the cycle, create an icon. + for (Magic m : cycleMagics) { + if (m == null) continue; + MagicIcon icon = new MagicIcon(m); + icon.enabled = true; + icon.pressable = true; + // If available, set manual ordering data from the cycle association. + MagicAssociation assoc = cycle.associations.get(m.id); + if (assoc != null) { + icon.index = assoc.index; + icon.priority = assoc.priority; + } + icons.add(icon); + } + return icons; + } + + @Override + protected List createConnections() { + List conns = new ArrayList<>(); + if (cycleMagics == null || cycleMagics.isEmpty()) + return conns; + // Only add connections for interactions between magics in this cycle. + Map orderMap = new HashMap<>(); + for (int i = 0; i < cycleMagics.size(); i++) { + orderMap.put(cycleMagics.get(i).id, i); + } + for (Magic m : cycleMagics) { + if (m == null || m.interactions == null) continue; + for (Map.Entry entry : m.interactions.entrySet()) { + int targetId = entry.getKey(); + if (!orderMap.containsKey(targetId)) continue; + float percent = entry.getValue(); + String hover = "+" + (int) (percent * 100) + "%"; + conns.add(new DiagramConnection(m.id, targetId, percent, hover)); + } + } + return conns; + } + + @Override + protected void renderIcon(DiagramIcon icon, int posX, int posY, IconRenderState state) { + Magic magic = ((MagicIcon) icon).magic; + Minecraft mc = Minecraft.getMinecraft(); + FontRenderer fontRenderer = mc.fontRenderer; + int size = this.iconSize; + float scale = (float) size / 16.0f; + float renderX = posX - 8 * scale; + float renderY = posY - 8 * scale; + + if (magic.item != null) { + RenderHelper.enableGUIStandardItemLighting(); + GL11.glPushMatrix(); + GL11.glTranslatef(renderX, renderY, 0); + GL11.glScalef(scale, scale, 1.0f); + renderItem.renderItemAndEffectIntoGUI(fontRenderer, mc.getTextureManager(), magic.item, 0, 0); + GL11.glPopMatrix(); + RenderHelper.disableStandardItemLighting(); + } else if (magic.iconTexture != null && !magic.iconTexture.isEmpty()) { + ImageData imageData = ClientCacheHandler.getImageData(magic.iconTexture); + if (imageData != null && imageData.imageLoaded()) { + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS); + GL11.glEnable(GL11.GL_ALPHA_TEST); + imageData.bindTexture(); + int texWidth = imageData.getTotalWidth(); + int texX = posX - size / 2; + int texY = posY - size / 2; + func_152125_a(texX, texY, 0, 0, texWidth, texWidth, size, size, texWidth, texWidth); + GL11.glPopAttrib(); + } + } else { + RenderHelper.enableGUIStandardItemLighting(); + GL11.glPushMatrix(); + GL11.glTranslatef(renderX, renderY, 0); + GL11.glScalef(scale, scale, 1.0f); + ItemStack sword = new ItemStack(Items.iron_sword); + renderItem.renderItemAndEffectIntoGUI(fontRenderer, mc.getTextureManager(), sword, 0, 0); + GL11.glPopMatrix(); + RenderHelper.disableStandardItemLighting(); + } + + if (state == IconRenderState.NOT_HIGHLIGHTED) { + int rectX = posX - size / 2; + int rectY = posY - size / 2; + drawRect(rectX, rectY, rectX + size, rectY + size, 0x80202020); + } + GL11.glColor4f(1f, 1f, 1f, 1f); + } + + @Override + protected List getIconTooltip(DiagramIcon icon) { + Magic magic = ((MagicIcon) icon).magic; + List tooltip = new ArrayList<>(); + tooltip.add(magic.getDisplayName()); + return tooltip; + } + + @Override + protected String getIconName(DiagramIcon icon) { + Magic magic = ((MagicIcon) icon).magic; + return magic.getName(); + } + + // Inner class wrapping a Magic as a DiagramIcon. + private class MagicIcon extends DiagramIcon { + public Magic magic; + public MagicIcon(Magic magic) { + super(magic.id, 0, 0); + this.magic = magic; + } + } + + @Override + protected void drawHoveringText(List text, int mouseX, int mouseY, FontRenderer fontRenderer) { + parent.renderHoveringText(text, mouseX, mouseY, fontRenderer); + } +} diff --git a/src/main/java/noppes/npcs/client/gui/GuiMagicMap.java b/src/main/java/noppes/npcs/client/gui/GuiMagicMap.java deleted file mode 100644 index 9758e9800..000000000 --- a/src/main/java/noppes/npcs/client/gui/GuiMagicMap.java +++ /dev/null @@ -1,132 +0,0 @@ -package noppes.npcs.client.gui; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.FontRenderer; -import net.minecraft.client.renderer.RenderHelper; -import net.minecraft.client.renderer.entity.RenderItem; -import net.minecraft.init.Items; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; -import noppes.npcs.client.gui.util.GuiDiagram; -import noppes.npcs.client.gui.util.GuiNPCInterface; -import noppes.npcs.constants.EnumDiagramLayout; -import noppes.npcs.controllers.MagicController; -import noppes.npcs.controllers.data.Magic; -import org.lwjgl.opengl.GL11; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -public class GuiMagicMap extends GuiDiagram { - - private List magics; - - // Single RenderItem instance for efficiency. - private RenderItem renderItem = new RenderItem(); - - public GuiMagicMap(GuiNPCInterface parent, int x, int y, int width, int height) { - super(parent, x, y, width, height); - magics = new ArrayList<>(); - - // Cache all magics from the MagicController. - for (Magic magic : MagicController.getInstance().magics.values()) { - magics.add(magic); - } - setLayout(EnumDiagramLayout.CIRCULAR_MANUAL); - this.setCurvedArrows(true); - this.setCurveAngle(-20); - } - - @Override - protected List createIcons() { - List icons = new ArrayList<>(); - for (Magic magic : magics) { - MagicIcon icon = new MagicIcon(magic); - // Set your desired flags (for example, enabled and pressable). - icon.enabled = true; - icon.pressable = true; - icons.add(icon); - } - return icons; - } - - @Override - protected List createConnections() { - List conns = new ArrayList<>(); - // For each Magic, generate connections from each weakness (attacker) to this magic. - for (Magic magic : magics) { - if (magic.interactions == null) - continue; - for (Map.Entry entry : magic.interactions.entrySet()) { - int attackerId = entry.getKey(); - float percent = entry.getValue(); - String hover = "+" + (int) (percent * 100) + "%"; - conns.add(new DiagramConnection(attackerId, magic.id, percent, hover)); - } - } - return conns; - } - - @Override - protected void renderIcon(DiagramIcon icon, int posX, int posY, IconRenderState state) { - Magic magic = ((MagicIcon) icon).magic; - Minecraft mc = Minecraft.getMinecraft(); - FontRenderer fontRenderer = mc.fontRenderer; - int size = this.iconSize; - int iconX = posX - size / 2; - int iconY = posY - size / 2; - - RenderHelper.enableGUIStandardItemLighting(); - - if (magic.item != null) { - renderItem.renderItemAndEffectIntoGUI(fontRenderer, mc.getTextureManager(), magic.item, iconX, iconY); - } else if (magic.iconTexture != null && !magic.iconTexture.isEmpty()) { - mc.getTextureManager().bindTexture(new ResourceLocation(magic.iconTexture)); - this.drawTexturedModalRect(iconX, iconY, 0, 0, size, size); - } else { - ItemStack sword = new ItemStack(Items.iron_sword); - renderItem.renderItemAndEffectIntoGUI(fontRenderer, mc.getTextureManager(), sword, iconX, iconY); - } - RenderHelper.disableStandardItemLighting(); - - // If the icon is not highlighted, draw a translucent overlay. - if (state == IconRenderState.NOT_HIGHLIGHTED) { - drawRect(iconX, iconY, iconX + size, iconY + size, 0x80202020); - } - - // Reset color. - GL11.glColor4f(1f, 1f, 1f, 1f); - } - - @Override - protected List getIconTooltip(DiagramIcon icon) { - Magic magic = ((MagicIcon) icon).magic; - List tooltip = new ArrayList<>(); - tooltip.add(magic.getName()); - return tooltip; - } - - @Override - protected void drawHoveringText(List text, int mouseX, int mouseY, FontRenderer fontRenderer) { - parent.renderHoveringText(text, mouseX, mouseY, fontRenderer); - } - - /** - * Override getIconName so that connection tooltips can show Magic names. - */ - @Override - protected String getIconName(DiagramIcon icon) { - Magic magic = ((MagicIcon) icon).magic; - return magic.getName(); - } - - // Wrap a Magic object as a DiagramIcon. - private class MagicIcon extends DiagramIcon { - public Magic magic; - public MagicIcon(Magic magic) { - super(magic.id, 0, 0); - this.magic = magic; - } - } -} diff --git a/src/main/java/noppes/npcs/client/gui/SubGuiMagicCycleViewer.java b/src/main/java/noppes/npcs/client/gui/SubGuiMagicCycleViewer.java new file mode 100644 index 000000000..e86022344 --- /dev/null +++ b/src/main/java/noppes/npcs/client/gui/SubGuiMagicCycleViewer.java @@ -0,0 +1,68 @@ +package noppes.npcs.client.gui; + +import kamkeel.npcs.network.PacketClient; +import kamkeel.npcs.network.packets.request.magic.MagicSavePacket; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.client.gui.global.GuiNpcManageMagic; +import noppes.npcs.client.gui.util.*; +import noppes.npcs.constants.EnumTextureType; +import noppes.npcs.controllers.MagicController; +import noppes.npcs.controllers.data.Magic; +import noppes.npcs.controllers.data.MagicCycle; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class SubGuiMagicCycleViewer extends SubGuiInterface { + + private final MagicCycle magicCycle; + private GuiMagicCycleMap magicMap; + + public SubGuiMagicCycleViewer(MagicCycle cycle) { + this.magicCycle = cycle; + setBackground("menubg.png"); + xSize = 256; + ySize = 222; + + closeOnEsc = true; + } + + public SubGuiMagicCycleViewer(int cycleID) { + this(MagicController.getInstance().getCycle(cycleID)); + } + + @Override + public void initGui() { + super.initGui(); + + if(magicCycle == null) + return; + + // Position the map in a designated area (e.g., right panel) + int mapX = guiLeft + 6; + int mapY = guiTop + 6; + int mapWidth = xSize - 13; + int mapHeight = ySize - 17; + + magicMap = new GuiMagicCycleMap(this, mapX, mapY, mapWidth, mapHeight, magicCycle); + addDiagram(0, magicMap); + } + + @Override + public void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) { + if (magicMap != null) { + magicMap.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick); + } + super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick); + } + + @Override + protected void mouseMovedOrUp(int mouseX, int mouseY, int state) { + if (magicMap != null) { + magicMap.mouseReleased(mouseX, mouseY, state); + } + super.mouseMovedOrUp(mouseX, mouseY, state); + } +} diff --git a/src/main/java/noppes/npcs/client/gui/global/GuiNpcManageMagic.java b/src/main/java/noppes/npcs/client/gui/global/GuiNpcManageMagic.java index c4cd09d58..7026acacb 100644 --- a/src/main/java/noppes/npcs/client/gui/global/GuiNpcManageMagic.java +++ b/src/main/java/noppes/npcs/client/gui/global/GuiNpcManageMagic.java @@ -9,6 +9,7 @@ import kamkeel.npcs.network.PacketClient; import kamkeel.npcs.network.packets.request.magic.*; import noppes.npcs.client.gui.SubGuiMagicCycle; import noppes.npcs.client.gui.SubGuiMagic; +import noppes.npcs.client.gui.SubGuiMagicCycleViewer; import noppes.npcs.client.gui.util.*; import noppes.npcs.constants.EnumScrollData; import noppes.npcs.controllers.data.Magic; @@ -107,6 +108,7 @@ public class GuiNpcManageMagic extends GuiNPCInterface2 implements ISubGuiListen addButton(new GuiNpcButton(4, guiLeft + 3, guiTop + 38, 58, 20, "gui.add")); addButton(new GuiNpcButton(5, guiLeft + 3, guiTop + 61, 58, 20, "gui.remove")); addButton(new GuiNpcButton(6, guiLeft + 3, guiTop + 94, 58, 20, "gui.edit")); + addButton(new GuiNpcButton(20, guiLeft + 3, guiTop + 117, 58, 20, "gui.view")); // Right side magic management buttons. addButton(new GuiNpcButton(33, guiLeft + 358, guiTop + 8, 58, 20, "menu.magics")); @@ -223,6 +225,10 @@ public class GuiNpcManageMagic extends GuiNPCInterface2 implements ISubGuiListen button.enabled = selectedCycle != null; } + button = getButton(20); + if(button != null){ + button.enabled = selectedCycle != null; + } if(getLabel(201) != null){ if(selectedCycle != null){ @@ -411,6 +417,11 @@ public class GuiNpcManageMagic extends GuiNPCInterface2 implements ISubGuiListen setSubGui(new SubGuiMagic(this, selectedMagic)); } break; + case 20: + if (selectedCycle != null) { + setSubGui(new SubGuiMagicCycleViewer(selectedCycle)); + } + break; } updateButtons(); diff --git a/src/main/java/noppes/npcs/client/gui/util/GuiDiagram.java b/src/main/java/noppes/npcs/client/gui/util/GuiDiagram.java index 07a3f9f89..a68820d14 100644 --- a/src/main/java/noppes/npcs/client/gui/util/GuiDiagram.java +++ b/src/main/java/noppes/npcs/client/gui/util/GuiDiagram.java @@ -4,9 +4,12 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.entity.RenderItem; import noppes.npcs.constants.EnumDiagramLayout; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; import java.awt.*; import java.util.List; @@ -33,6 +36,8 @@ import java.util.*; */ public abstract class GuiDiagram extends Gui { + protected RenderItem renderItem = new RenderItem(); + // --- Diagram Area & Controls --- protected int x, y, width, height; // Drawing area for the diagram protected float panX = 0, panY = 0; // Panning offsets @@ -179,7 +184,7 @@ public abstract class GuiDiagram extends Gui { Map positions = new HashMap<>(); int count = icons.size(); int centerX = x + width/2, centerY = y + height/2; - int radius = Math.min(width, height)/2 - iconSize - 10; + int radius = Math.min(width, height)/2 - (int)(0.8 * slotSize); for (int i = 0; i < count; i++) { double angle = 2 * Math.PI * i / count; int posX = centerX + (int)(radius * Math.cos(angle)); @@ -1248,7 +1253,7 @@ public abstract class GuiDiagram extends Gui { /** * Override to render tooltips. */ - protected void drawHoveringText(List text, int mouseX, int mouseY, FontRenderer fontRenderer) {} + protected void drawHoveringText(List textLines, int mouseX, int mouseY, FontRenderer font) {} // --- Flag Setters --- public void setShowArrowHeads(boolean showArrowHeads) { @@ -1262,31 +1267,21 @@ public abstract class GuiDiagram extends Gui { /** * Called when an icon is clicked. */ - protected void onIconClick(DiagramIcon icon) { - System.out.println("Icon " + icon.id + " clicked."); - } + protected void onIconClick(DiagramIcon icon) {} /** * Called when an icon is held. */ - protected void onIconHeld(DiagramIcon icon) { - System.out.println("Icon " + icon.id + " held."); - } + protected void onIconHeld(DiagramIcon icon) {} /** * Called when an icon is released. */ - protected void onIconRelease(DiagramIcon icon) { - System.out.println("Icon " + icon.id + " released."); - } + protected void onIconRelease(DiagramIcon icon) {} /** * Called when an icon is hovered over. */ - protected void onIconHover(DiagramIcon icon) { - // Override to handle icon hovering events. - } + protected void onIconHover(DiagramIcon icon) {} /** * Called when a connection is hovered over. */ - protected void onConnectionHover(DiagramConnection conn) { - // Override to handle connection hovering events. - } + protected void onConnectionHover(DiagramConnection conn) {} } diff --git a/src/main/java/noppes/npcs/constants/EnumDiagramLayout.java b/src/main/java/noppes/npcs/constants/EnumDiagramLayout.java index c27422317..0db6f669a 100644 --- a/src/main/java/noppes/npcs/constants/EnumDiagramLayout.java +++ b/src/main/java/noppes/npcs/constants/EnumDiagramLayout.java @@ -28,4 +28,8 @@ public enum EnumDiagramLayout { return list.toArray(new String[list.size()]); } + + public boolean isManual(){ + return this == CIRCULAR_MANUAL || this == SQUARE_MANUAL || this == TREE_MANUAL; + } }