From 7135f1ad27fd991fd1a69fa265602d4b35a1acc0 Mon Sep 17 00:00:00 2001 From: Kam Date: Sun, 23 Feb 2025 05:58:56 -0500 Subject: [PATCH] Compass --- .../npcs/client/ClientEventHandler.java | 2 + .../client/gui/hud/CompassHudComponent.java | 214 ++++++++++++++++++ .../npcs/client/gui/hud/EnumHudComponent.java | 3 +- .../npcs/client/gui/hud/HudComponent.java | 3 +- .../gui/player/inventory/GuiSettings.java | 38 +--- .../java/noppes/npcs/config/ConfigClient.java | 103 +++++---- 6 files changed, 281 insertions(+), 82 deletions(-) create mode 100644 src/main/java/noppes/npcs/client/gui/hud/CompassHudComponent.java diff --git a/src/main/java/noppes/npcs/client/ClientEventHandler.java b/src/main/java/noppes/npcs/client/ClientEventHandler.java index 6d5bfedd8..b82e19e32 100644 --- a/src/main/java/noppes/npcs/client/ClientEventHandler.java +++ b/src/main/java/noppes/npcs/client/ClientEventHandler.java @@ -17,6 +17,7 @@ import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.event.*; import noppes.npcs.client.gui.customoverlay.OverlayCustom; import noppes.npcs.client.gui.hud.ClientHudManager; +import noppes.npcs.client.gui.hud.CompassHudComponent; import noppes.npcs.client.gui.hud.EnumHudComponent; import noppes.npcs.client.gui.hud.QuestTrackingComponent; import noppes.npcs.client.renderer.MarkRenderer; @@ -95,6 +96,7 @@ public class ClientEventHandler { if(ClientHudManager.getInstance().getHudComponents().isEmpty()){ ClientHudManager.getInstance().registerHud(EnumHudComponent.QuestTracker, new QuestTrackingComponent(Minecraft.getMinecraft())); + ClientHudManager.getInstance().registerHud(EnumHudComponent.QuestCompass, new CompassHudComponent(Minecraft.getMinecraft())); } ClientHudManager.getInstance().renderAllHUDs(event.partialTicks); diff --git a/src/main/java/noppes/npcs/client/gui/hud/CompassHudComponent.java b/src/main/java/noppes/npcs/client/gui/hud/CompassHudComponent.java new file mode 100644 index 000000000..87ab0532e --- /dev/null +++ b/src/main/java/noppes/npcs/client/gui/hud/CompassHudComponent.java @@ -0,0 +1,214 @@ +package noppes.npcs.client.gui.hud; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.MathHelper; +import noppes.npcs.config.ConfigClient; +import org.lwjgl.opengl.GL11; +import java.util.ArrayList; +import java.util.List; + +public class CompassHudComponent extends HudComponent { + private final Minecraft mc; + private final List targets = new ArrayList<>(); + private final int BAR_HEIGHT = 20; + private final int BASE_ICON_SIZE = 8; + private final int MAX_ICON_SIZE = 16; + private final int SCALE_DISTANCE_MIN = 10; + private final int SCALE_DISTANCE_MAX = 40; + private static final int HANDLE_SIZE = 10; + + public static class TargetEntry { + public int x, z; + public int color; + + public TargetEntry(int x, int z, int color) { + this.x = x; + this.z = z; + this.color = color; + } + } + + public CompassHudComponent(Minecraft minecraft) { + mc = minecraft; + overlayWidth = 200; + overlayHeight = BAR_HEIGHT; + load(); + } + + @Override + public void loadData(NBTTagCompound compound) { + targets.clear(); + NBTTagList list = compound.getTagList("Targets", 10); + for(int i = 0; i < list.tagCount(); i++) { + NBTTagCompound entry = list.getCompoundTagAt(i); + targets.add(new TargetEntry( + entry.getInteger("x"), + entry.getInteger("z"), + entry.getInteger("color") + )); + } + hasData = !targets.isEmpty(); + } + + @Override + public void load() { + posX = ConfigClient.CompassOverlayX; + posY = ConfigClient.CompassOverlayY; + scale = ConfigClient.CompassOverlayScale; + overlayWidth = ConfigClient.CompassOverlayWidth; + } + + @Override + public void save() { + // Save to config + ConfigClient.CompassOverlayX = posX; + ConfigClient.CompassOverlayY = posY; + ConfigClient.CompassOverlayScale = scale; + ConfigClient.CompassOverlayWidth = overlayWidth; + ConfigClient.config.save(); + } + + @Override + public void renderOnScreen(float partialTicks) { + if (!hasData || isEditting) return; + + ScaledResolution res = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight); + int actualX = (int)((float) posX / 100F * res.getScaledWidth()); + int actualY = (int)((float) posY / 100F * res.getScaledHeight()); + float scaleFactor = scale / 100.0F; + + GL11.glPushMatrix(); + GL11.glTranslatef(actualX, actualY, 0); + GL11.glScalef(scaleFactor, scaleFactor, scaleFactor); + + // Draw background bar + drawRect(0, 0, overlayWidth, BAR_HEIGHT, 0x80000000); + + // Render all targets + for(TargetEntry target : targets) { + renderTargetIcon(target); + } + + GL11.glPopMatrix(); + } + + private void renderTargetIcon(TargetEntry target) { + if (mc.thePlayer == null) return; + + // Calculate position on bar + float iconPos = calculateIconPosition(target.x, target.z); + int barWidth = overlayWidth; + + // Calculate dynamic size + float distance = (float) Math.sqrt( + Math.pow(target.x - mc.thePlayer.posX, 2) + + Math.pow(target.z - mc.thePlayer.posZ, 2) + ); + + int iconSize = calculateIconSize(distance); + int iconX = MathHelper.clamp_int((int)iconPos, iconSize/2, barWidth - iconSize/2); + + // Calculate vertical position + int iconY = (BAR_HEIGHT - iconSize)/2; + + // Draw icon + drawRect(iconX - iconSize/2, iconY, + iconX + iconSize/2, iconY + iconSize, target.color); + } + + private float calculateIconPosition(double targetX, double targetZ) { + double dx = targetX - mc.thePlayer.posX; + double dz = targetZ - mc.thePlayer.posZ; + + double angle = Math.toDegrees(Math.atan2(dz, dx)) - 90; + angle = (angle + 360) % 360; + + double playerYaw = (mc.thePlayer.rotationYaw % 360 + 360) % 360; + double relativeAngle = (angle - playerYaw + 360) % 360; + + return (float)(relativeAngle / 360.0 * overlayWidth); + } + + private int calculateIconSize(float distance) { + if(distance <= SCALE_DISTANCE_MIN) return MAX_ICON_SIZE; + if(distance >= SCALE_DISTANCE_MAX) return BASE_ICON_SIZE; + + float t = (distance - SCALE_DISTANCE_MIN) / + (SCALE_DISTANCE_MAX - SCALE_DISTANCE_MIN); + return (int)(MAX_ICON_SIZE - (MAX_ICON_SIZE - BASE_ICON_SIZE) * t); + } + + @Override + public void renderEditing() { + isEditting = true; + ScaledResolution res = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight); + int actualX = (int)((float) posX / 100F * res.getScaledWidth()); + int actualY = (int)((float) posY / 100F * res.getScaledHeight()); + float scaleFactor = scale / 100.0F; + + GL11.glPushMatrix(); + GL11.glTranslatef(actualX, actualY, 0); + GL11.glScalef(scaleFactor, scaleFactor, scaleFactor); + + // Draw editor background and handles + drawRect(0, 0, overlayWidth, overlayHeight, 0x80000000); + drawRectOutline(0, 0, overlayWidth, overlayHeight, 0xFF00FF00); + + // Add resize handle (bottom-right corner) + drawRect(overlayWidth - HANDLE_SIZE, overlayHeight - HANDLE_SIZE, + overlayWidth, overlayHeight, 0xFFCCCCCC); + + // Demo targets + renderDemoIcon(overlayWidth * 0.25f, 0xFF0000FF); + renderDemoIcon(overlayWidth * 0.75f, 0xFF00FF00); + + GL11.glPopMatrix(); + } + + private void renderDemoIcon(float position, int color) { + // Animate size + float pulse = (System.currentTimeMillis() % 1000) / 1000f; + int size = (int)(BASE_ICON_SIZE + (MAX_ICON_SIZE - BASE_ICON_SIZE) * pulse); + + int iconX = (int)position - size/2; + int iconY = (BAR_HEIGHT - size)/2; + drawRect(iconX, iconY, iconX + size, iconY + size, color); + } + + // Management methods + public void addTarget(int x, int z, int color) { + targets.add(new TargetEntry(x, z, color)); + hasData = true; + } + + public void removeTarget(int index) { + if(index >= 0 && index < targets.size()) { + targets.remove(index); + hasData = !targets.isEmpty(); + } + } + + public void clearTargets() { + targets.clear(); + hasData = false; + } + + // Helper drawing methods (same as in QuestTrackingComponent) + private void drawRect(int left, int top, int right, int bottom, int color) { + net.minecraft.client.gui.Gui.drawRect(left, top, right, bottom, color); + } + + private void drawRectOutline(int left, int top, int right, int bottom, int color) { + drawHorizontalLine(left, right, top, color); + drawHorizontalLine(left, right, bottom - 1, color); + net.minecraft.client.gui.Gui.drawRect(left, top, left + 1, bottom, color); + net.minecraft.client.gui.Gui.drawRect(right - 1, top, right, bottom, color); + } + + private void drawHorizontalLine(int left, int right, int y, int color) { + net.minecraft.client.gui.Gui.drawRect(left, y, right, y + 1, color); + } +} diff --git a/src/main/java/noppes/npcs/client/gui/hud/EnumHudComponent.java b/src/main/java/noppes/npcs/client/gui/hud/EnumHudComponent.java index c1ac41239..fe6eb07b6 100644 --- a/src/main/java/noppes/npcs/client/gui/hud/EnumHudComponent.java +++ b/src/main/java/noppes/npcs/client/gui/hud/EnumHudComponent.java @@ -1,5 +1,6 @@ package noppes.npcs.client.gui.hud; public enum EnumHudComponent { - QuestTracker + QuestTracker, + QuestCompass } diff --git a/src/main/java/noppes/npcs/client/gui/hud/HudComponent.java b/src/main/java/noppes/npcs/client/gui/hud/HudComponent.java index b004ecfa1..955a8e66d 100644 --- a/src/main/java/noppes/npcs/client/gui/hud/HudComponent.java +++ b/src/main/java/noppes/npcs/client/gui/hud/HudComponent.java @@ -11,8 +11,7 @@ public abstract class HudComponent { public boolean enabled = true; public boolean hasData = false; public boolean isEditting = false; - - protected final int overlayWidth = 200, overlayHeight = 120; + public int overlayWidth = 200, overlayHeight = 120; /** * Loads custom HUD data from an NBT compound. diff --git a/src/main/java/noppes/npcs/client/gui/player/inventory/GuiSettings.java b/src/main/java/noppes/npcs/client/gui/player/inventory/GuiSettings.java index 4451ecb18..5ad6c4882 100644 --- a/src/main/java/noppes/npcs/client/gui/player/inventory/GuiSettings.java +++ b/src/main/java/noppes/npcs/client/gui/player/inventory/GuiSettings.java @@ -39,17 +39,14 @@ public class GuiSettings extends GuiCNPCInventory implements ITextfieldListener, this.addLabel(new GuiNpcLabel(1, "settings.chatBubbles", guiLeft + 8, guiTop + 14 + y)); this.addButton(new GuiNpcButton(1, guiLeft + 105, guiTop + 9 + y, 50, 20, new String[]{"gui.no", "gui.yes"}, ConfigClient.EnableChatBubbles?1:0)); - this.addLabel(new GuiNpcLabel(3, "settings.trackAlignment", guiLeft + 8 + 155, guiTop + 14 + y)); - this.addButton(new GuiNpcButton(3, guiLeft + 105 + 160, guiTop + 9 + y, 50, 20, new String[]{"TLeft", "TCenter", "TRight", "Left", "Center", "Right", "BLeft", "BCenter", "BRight"}, ConfigClient.TrackingInfoAlignment)); - y += 22; this.addLabel(new GuiNpcLabel(2, "settings.dialogSound", guiLeft + 8, guiTop + 14 + y)); this.addButton(new GuiNpcButton(2, guiLeft + 105, guiTop + 9 + y, 50, 20, new String[]{"gui.no", "gui.yes"}, ConfigClient.DialogSound?1:0)); - this.addLabel(new GuiNpcLabel(12,"settings.alignmentX", guiLeft + 8 + 155, guiTop + 14 + y)); - this.addTextField(new GuiNpcTextField(12, this, this.fontRendererObj, guiLeft + 107 + 160, guiTop + 9 + y, 45, 20, ConfigClient.TrackingInfoX + "")); - getTextField(12).integersOnly = true; - getTextField(12).setMinMaxDefault(-2000, 2000, 0); +// this.addLabel(new GuiNpcLabel(12,"settings.alignmentX", guiLeft + 8 + 155, guiTop + 14 + y)); +// this.addTextField(new GuiNpcTextField(12, this, this.fontRendererObj, guiLeft + 107 + 160, guiTop + 9 + y, 45, 20, ConfigClient.TrackingInfoX + "")); +// getTextField(12).integersOnly = true; +// getTextField(12).setMinMaxDefault(-2000, 2000, 0); y += 22; this.addLabel(new GuiNpcLabel(10,"settings.dialogSpeed", guiLeft + 8, guiTop + 14 + y)); @@ -57,21 +54,12 @@ public class GuiSettings extends GuiCNPCInventory implements ITextfieldListener, getTextField(10).integersOnly = true; getTextField(10).setMinMaxDefault(1, 20, 10); - this.addLabel(new GuiNpcLabel(13,"settings.alignmentY", guiLeft + 8 + 155, guiTop + 14 + y)); - this.addTextField(new GuiNpcTextField(13, this, this.fontRendererObj, guiLeft + 107 + 160, guiTop + 9 + y, 45, 20, ConfigClient.TrackingInfoY + "")); - getTextField(13).integersOnly = true; - getTextField(13).setMinMaxDefault(-2000, 2000, 0); y += 22; this.addLabel(new GuiNpcLabel(6, "settings.chatAlerts", guiLeft + 8, guiTop + 14 + y)); this.addButton(new GuiNpcButton(6, guiLeft + 105, guiTop + 9 + y, 50, 20, new String[]{"gui.no", "gui.yes"}, ConfigClient.ChatAlerts?1:0)); - this.addLabel(new GuiNpcLabel(14,"settings.trackScale", guiLeft + 8 + 155, guiTop + 14 + y)); - this.addTextField(new GuiNpcTextField(14, this, this.fontRendererObj, guiLeft + 107 + 160, guiTop + 9 + y, 45, 20, ConfigClient.TrackingScale + "")); - getTextField(14).integersOnly = true; - getTextField(14).setMinMaxDefault(0, 300, 100); - y += 22; this.addLabel(new GuiNpcLabel(7, "settings.bannerAlerts", guiLeft + 8, guiTop + 14 + y)); @@ -142,10 +130,6 @@ public class GuiSettings extends GuiCNPCInventory implements ITextfieldListener, ConfigClient.DialogSound = button.getValue() == 1; ConfigClient.DialogSoundProperty.set(ConfigClient.DialogSound); } - if(button.id == 3){ - ConfigClient.TrackingInfoAlignment = button.getValue(); - ConfigClient.TrackingInfoAlignmentProperty.set(ConfigClient.TrackingInfoAlignment); - } if(button.id == 4){ GuiYesNo yesNoTrack = new GuiYesNo(this, "Confirm", StatCollector.translateToLocal("settings.confirmClearTrack"), 0); displayGuiScreen(yesNoTrack); @@ -194,19 +178,5 @@ public class GuiSettings extends GuiCNPCInventory implements ITextfieldListener, ConfigClient.DialogSpeed = textfield.getInteger(); ConfigClient.DialogSpeedProperty.set(ConfigClient.DialogSound); } - - // Quest Tracking - if(textfield.id == 12){ - ConfigClient.TrackingInfoX = textfield.getInteger(); - ConfigClient.TrackingInfoXProperty.set(ConfigClient.TrackingInfoX); - } - if(textfield.id == 13){ - ConfigClient.TrackingInfoY = textfield.getInteger(); - ConfigClient.TrackingInfoYProperty.set(ConfigClient.TrackingInfoY); - } - if(textfield.id == 14){ - ConfigClient.TrackingScale = textfield.getInteger(); - ConfigClient.TrackingScaleProperty.set(ConfigClient.TrackingScale); - } } } diff --git a/src/main/java/noppes/npcs/config/ConfigClient.java b/src/main/java/noppes/npcs/config/ConfigClient.java index 6a36160d7..7b0a0f641 100644 --- a/src/main/java/noppes/npcs/config/ConfigClient.java +++ b/src/main/java/noppes/npcs/config/ConfigClient.java @@ -18,6 +18,7 @@ public class ConfigClient public final static String QUESTING = "Questing"; public final static String MODEL = "Model"; public final static String TEXTURE = "Texture"; + public final static String HUD = "Hud"; /** @@ -53,18 +54,6 @@ public class ConfigClient /** * Questing Properties **/ - public static Property TrackingInfoAlignmentProperty; - public static int TrackingInfoAlignment = 3; - - public static Property TrackingInfoXProperty; - public static int TrackingInfoX = 0; - - public static Property TrackingInfoYProperty; - public static int TrackingInfoY = 0; - - public static Property TrackingScaleProperty; - public static int TrackingScale = 100; - public static Property DialogSpeedProperty; public static int DialogSpeed = 10; @@ -77,7 +66,7 @@ public class ConfigClient public static Property BannerAlertsProperty; public static boolean BannerAlerts = true; - // New Quest Overlay configuration properties + // HUD PROPERTIES public static Property QuestOverlayXProperty; public static int QuestOverlayX = 100; @@ -90,6 +79,16 @@ public class ConfigClient public static Property QuestOverlayTextAlignProperty; public static int QuestOverlayTextAlign = 1; // 0: Left, 1: Center, 2: Right + public static Property CompassOverlayXProperty; + public static Property CompassOverlayYProperty; + public static Property CompassOverlayScaleProperty; + public static Property CompassOverlayWidthProperty; + + public static int CompassOverlayX; + public static int CompassOverlayY; + public static int CompassOverlayScale; + public static int CompassOverlayWidth; + /** * Texture Properties @@ -121,19 +120,60 @@ public class ConfigClient { config.load(); - // Load new Quest Overlay settings - QuestOverlayXProperty = config.get(QUESTING, "QuestOverlayX", 100, "X position of the quest overlay."); + // Hud Quest Overlay settings + QuestOverlayXProperty = config.get(HUD, "Quest Hud X", 100, "X position of the quest overlay."); QuestOverlayX = QuestOverlayXProperty.getInt(100); - QuestOverlayYProperty = config.get(QUESTING, "QuestOverlayY", 100, "Y position of the quest overlay."); + QuestOverlayYProperty = config.get(HUD, "Quest Hud Y", 100, "Y position of the quest overlay."); QuestOverlayY = QuestOverlayYProperty.getInt(100); - QuestOverlayScaleProperty = config.get(QUESTING, "QuestOverlayScale", 100, "Scale percentage of the quest overlay."); + QuestOverlayScaleProperty = config.get(HUD, "Quest Hud Scale", 100, "Scale percentage of the quest overlay."); QuestOverlayScale = QuestOverlayScaleProperty.getInt(100); - QuestOverlayTextAlignProperty = config.get(QUESTING, "QuestOverlayTextAlign", 1, "Text alignment in quest overlay (0: Left, 1: Center, 2: Right)."); + QuestOverlayTextAlignProperty = config.get(HUD, "Quest Hud Text Alignment", 1, "Text alignment in quest overlay (0: Left, 1: Center, 2: Right)."); QuestOverlayTextAlign = QuestOverlayTextAlignProperty.getInt(1); + // Compass HUD Configs + CompassOverlayXProperty = config.get( + HUD, + "Compass Hud X", + 50, + "Horizontal position of compass overlay (0-100 percentage)", + 0, + 100 + ); + CompassOverlayX = CompassOverlayXProperty.getInt(); + + CompassOverlayYProperty = config.get( + HUD, + "Compass Hud Y", + 5, + "Vertical position of compass overlay (0-100 percentage)", + 0, + 100 + ); + CompassOverlayY = CompassOverlayYProperty.getInt(); + + CompassOverlayScaleProperty = config.get( + HUD, + "Compass Hud Scale", + 100, + "Scale percentage of compass overlay", + 50, + 300 + ); + CompassOverlayScale = CompassOverlayScaleProperty.getInt(); + + CompassOverlayWidthProperty = config.get( + HUD, + "Compass Hud Width", + 200, + "Base width of compass bar in pixels", + 100, + 1000 + ); + CompassOverlayWidth = CompassOverlayWidthProperty.getInt(); + // General CacheLifeProperty = config.get(GENERAL, "Cache Life", 10, "How long should downloaded imagery data be saved client side? (In minutes)"); @@ -161,19 +201,6 @@ public class ConfigClient HideEffectsBarProperty = config.get(VISUAL, "Hide Effects Bar", false, "Hides CNPC+ Inventory Effects Bar"); HideEffectsBar = HideEffectsBarProperty.getBoolean(false); - // Questing - TrackingInfoAlignmentProperty = config.get(QUESTING, "Tracking Info Alignment", 3, "Client sided! Determines where tracking quest info shows up on the screen based on a number from 0 to 8. Default: 3"); - TrackingInfoAlignment = TrackingInfoAlignmentProperty.getInt(3); - - TrackingInfoXProperty = config.get(QUESTING, "Tracking Info X", 0, "Client sided! Offsets the tracking info GUI by this amount in the X direction."); - TrackingInfoX = TrackingInfoXProperty.getInt(0); - - TrackingInfoYProperty = config.get(QUESTING, "Tracking Info Y", 0, "Client sided! Offsets the tracking info GUI by this amount in the Y direction."); - TrackingInfoY = TrackingInfoYProperty.getInt(0); - - TrackingScaleProperty = config.get(QUESTING, "Tracking Scale", 100, "Client sided! Adjusts the scaling of the Quest Tracking"); - TrackingScale = TrackingScaleProperty.getInt(100); - DialogSpeedProperty = config.get(VISUAL, "Dialog Speed", true, "Only set for gradual dialogs"); DialogSpeed = DialogSpeedProperty.getInt(10); @@ -215,21 +242,7 @@ public class ConfigClient FontSize = LegacyConfig.FontSize; FontSizeProperty.set(FontSize); - - TrackingInfoAlignment = LegacyConfig.TrackingInfoAlignment; - TrackingInfoAlignmentProperty.set(TrackingInfoAlignment); - - TrackingInfoX = LegacyConfig.TrackingInfoX; - TrackingInfoXProperty.set(TrackingInfoX); - - TrackingInfoY = LegacyConfig.TrackingInfoY; - TrackingInfoYProperty.set(TrackingInfoY); } - - if (TrackingInfoAlignment < 0) - TrackingInfoAlignment = 0; - if (TrackingInfoAlignment > 8) - TrackingInfoAlignment = 8; } catch (Exception e) {