Magic Diagram Viewer

This commit is contained in:
Kam committed 2025-03-04 21:03:36 -05:00
1 parent 080fa62771
commit f0547cf876
6 files changed
+291 -149

No files matched your search

@@ -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<Magic> 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<DiagramIcon> createIcons() {
List<DiagramIcon> 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<DiagramConnection> createConnections() {
List<DiagramConnection> conns = new ArrayList<>();
if (cycleMagics == null || cycleMagics.isEmpty())
return conns;
// Only add connections for interactions between magics in this cycle.
Map<Integer, Integer> 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<Integer, Float> 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<String> getIconTooltip(DiagramIcon icon) {
Magic magic = ((MagicIcon) icon).magic;
List<String> 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<String> text, int mouseX, int mouseY, FontRenderer fontRenderer) {
parent.renderHoveringText(text, mouseX, mouseY, fontRenderer);
}
}
@@ -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<Magic> 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<DiagramIcon> createIcons() {
List<DiagramIcon> 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<DiagramConnection> createConnections() {
List<DiagramConnection> 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<Integer, Float> 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<String> getIconTooltip(DiagramIcon icon) {
Magic magic = ((MagicIcon) icon).magic;
List<String> tooltip = new ArrayList<>();
tooltip.add(magic.getName());
return tooltip;
}
@Override
protected void drawHoveringText(List<String> 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;
}
}
}
@@ -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);
}
}
@@ -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();
@@ -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<Integer, Point> 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<String> text, int mouseX, int mouseY, FontRenderer fontRenderer) {}
protected void drawHoveringText(List<String> 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) {}
}
@@ -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;
}
}