From 3407ac6f73b5e924639d8d26d4e70ff2dceae91c Mon Sep 17 00:00:00 2001 From: Algent Date: Tue, 14 Jul 2026 17:00:39 +0200 Subject: [PATCH 01/10] JM6 Integration work --- .../model/layers/OreVeinLayerManager.java | 4 +- .../layers/UndergroundFluidLayerManager.java | 9 +- .../model/render/OreVeinMapMarker.java | 155 ++++++++++++++++++ .../render/UndergroundFluidImageOverlay.java | 78 +++++++++ .../render/UndergroundFluidRenderStep.java | 5 + 5 files changed, 249 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinMapMarker.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidImageOverlay.java diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java index 13cdb436..104ea6e6 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java @@ -18,6 +18,7 @@ import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; import com.sinthoras.visualprospecting.integration.model.buttons.OreVeinButtonManager; import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; +import com.sinthoras.visualprospecting.integration.model.render.OreVeinMapMarker; import com.sinthoras.visualprospecting.integration.model.render.OreVeinRenderStep; public class OreVeinLayerManager extends InteractableLayerManager { @@ -38,7 +39,8 @@ public void onOpenMap() { @Override protected LayerRenderer addLayerRenderer(InteractableLayerManager manager, SupportedMods mod) { return new UniversalInteractableRenderer(manager) - .withRenderStep(location -> new OreVeinRenderStep((OreVeinLocation) location)); + .withRenderStep(location -> new OreVeinRenderStep((OreVeinLocation) location)) + .withMapMarker(location -> OreVeinMapMarker.create((OreVeinLocation) location)); } @Nullable diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java index 0042fde6..267cfa23 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java @@ -15,12 +15,14 @@ import com.gtnewhorizons.navigator.api.model.layers.LayerRenderer; import com.gtnewhorizons.navigator.api.model.layers.UniversalLayerRenderer; import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; +import com.gtnewhorizons.navigator.api.util.Util; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; import com.sinthoras.visualprospecting.integration.model.buttons.UndergroundFluidButtonManager; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; +import com.sinthoras.visualprospecting.integration.model.render.UndergroundFluidImageOverlay; import com.sinthoras.visualprospecting.integration.model.render.UndergroundFluidRenderStep; import gregtech.api.enums.UndergroundFluidNames; @@ -40,8 +42,13 @@ public UndergroundFluidLayerManager() { @Nullable @Override protected LayerRenderer addLayerRenderer(LayerManager manager, SupportedMods mod) { - return new UniversalLayerRenderer(manager) + UniversalLayerRenderer renderer = new UniversalLayerRenderer(manager) .withRenderStep(location -> new UndergroundFluidRenderStep((UndergroundFluidLocation) location)); + if (Util.isJourneyMapV6Installed()) { + renderer.withJourneyMapV6Overlays( + location -> UndergroundFluidImageOverlay.create((UndergroundFluidLocation) location)); + } + return renderer; } @Override diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinMapMarker.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinMapMarker.java new file mode 100644 index 00000000..3552dfdc --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinMapMarker.java @@ -0,0 +1,155 @@ +package com.sinthoras.visualprospecting.integration.model.render; + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; + +import javax.annotation.Nullable; +import javax.imageio.ImageIO; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.util.IIcon; +import net.minecraft.util.ResourceLocation; + +import com.gtnewhorizons.navigator.api.model.markers.MapMarker; +import com.sinthoras.visualprospecting.Config; +import com.sinthoras.visualprospecting.Tags; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; + +import gregtech.api.interfaces.IIconContainer; +import gregtech.api.util.client.ResourceUtils; + +public final class OreVeinMapMarker { + + private static final ResourceLocation DEPLETED = new ResourceLocation(Tags.MODID, "textures/depleted.png"); + private static final ResourceLocation MARKED = new ResourceLocation(Tags.MODID, "textures/node_marked.png"); + private static final int ICON_SIZE = 32; + private static BufferedImage depletedImage; + private static BufferedImage markedImage; + + private OreVeinMapMarker() {} + + public static @Nullable MapMarker create(OreVeinLocation location) { + BufferedImage icon = createIcon(location); + if (icon == null) return null; + + MapMarker marker = new MapMarker(icon).setDisplaySize(ICON_SIZE, ICON_SIZE); + if (!location.isDepleted()) { + marker.setLabel(location.getName()).setLabelColor(location.drawSearchHighlight() ? 0xFFFFFF : 0x7F7F7F) + .setLabelScale(1.2F).setLabelOffsetY(24).setLabelMinZoom(Config.minZoomLevelForOreLabel) + .setLabelOnMinimap(false); + } + return marker; + } + + private static @Nullable BufferedImage createIcon(OreVeinLocation location) { + BufferedImage background = spriteImage( + DimensionStoneBackground.getBackgroundIcon(location.getDimensionId()), + 0xFFFFFF); + IIconContainer ore = location.getIconFromPrimaryOre(); + BufferedImage oreImage = spriteImage(ore.getIcon(), location.getColor()); + if (background == null || oreImage == null) return null; + + BufferedImage image = new BufferedImage(ICON_SIZE, ICON_SIZE, BufferedImage.TYPE_INT_ARGB); + Graphics2D graphics = image.createGraphics(); + try { + graphics.setRenderingHint( + RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); + draw(graphics, background); + draw(graphics, oreImage); + BufferedImage overlay = spriteImage(ore.getOverlayIcon(), 0xFFFFFF); + if (overlay != null) draw(graphics, overlay); + if (!location.drawSearchHighlight() || location.isDepleted()) { + graphics.setComposite(AlphaComposite.SrcOver); + graphics.setColor(new Color(0, 0, 0, 150)); + graphics.fillRect(0, 0, ICON_SIZE, ICON_SIZE); + } + if (location.isDepleted()) draw(graphics, getDepletedImage()); + if (location.isActiveAsWaypoint()) draw(graphics, getMarkedImage()); + } finally { + graphics.dispose(); + } + return image; + } + + private static void draw(Graphics2D graphics, @Nullable BufferedImage image) { + if (image != null) graphics.drawImage(image, 0, 0, ICON_SIZE, ICON_SIZE, null); + } + + private static @Nullable BufferedImage spriteImage(@Nullable IIcon icon, int tint) { + if (icon == null) return null; + BufferedImage source = loadSprite(icon); + if (source == null) source = atlasSpriteImage(icon); + if (source == null) return null; + + int red = tint >> 16 & 0xFF; + int green = tint >> 8 & 0xFF; + int blue = tint & 0xFF; + int width = source.getWidth(); + int height = source.getHeight(); + int[] pixels = source.getRGB(0, 0, width, height, null, 0, width); + for (int i = 0; i < pixels.length; i++) { + int pixel = pixels[i]; + pixels[i] = pixel & 0xFF000000 | (pixel >> 16 & 0xFF) * red / 255 << 16 + | (pixel >> 8 & 0xFF) * green / 255 << 8 + | (pixel & 0xFF) * blue / 255; + } + + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + image.setRGB(0, 0, width, height, pixels, 0, width); + return image; + } + + private static @Nullable BufferedImage loadSprite(IIcon icon) { + ResourceLocation location = ResourceUtils.getCompleteBlockTextureResourceLocation(icon.getIconName()); + try (InputStream stream = Minecraft.getMinecraft().getResourceManager().getResource(location) + .getInputStream()) { + BufferedImage image = ImageIO.read(stream); + if (image == null) return null; + int frameHeight = Math.min(image.getWidth(), image.getHeight()); + return image.getSubimage(0, 0, image.getWidth(), frameHeight); + } catch (IOException ignored) { + return null; + } + } + + private static @Nullable BufferedImage atlasSpriteImage(IIcon icon) { + if (!(icon instanceof TextureAtlasSprite sprite) || sprite.getFrameCount() == 0) return null; + + int width = sprite.getIconWidth(); + int height = sprite.getIconHeight(); + int[][] frame = sprite.getFrameTextureData(0); + if (frame.length == 0 || frame[0] == null || frame[0].length < width * height) return null; + + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + image.setRGB(0, 0, width, height, frame[0], 0, width); + return image; + } + + private static @Nullable BufferedImage getDepletedImage() { + if (depletedImage == null) depletedImage = load(DEPLETED); + return depletedImage; + } + + private static @Nullable BufferedImage getMarkedImage() { + if (markedImage == null) markedImage = load(MARKED); + return markedImage; + } + + private static @Nullable BufferedImage load(ResourceLocation location) { + try (InputStream stream = Minecraft.getMinecraft().getResourceManager().getResource(location) + .getInputStream()) { + return ImageIO.read(stream); + } catch (IOException e) { + VP.LOG.error("Could not load map marker image " + location, e); + return null; + } + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidImageOverlay.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidImageOverlay.java new file mode 100644 index 00000000..3946be2a --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidImageOverlay.java @@ -0,0 +1,78 @@ +package com.sinthoras.visualprospecting.integration.model.render; + +import java.awt.image.BufferedImage; +import java.util.Collection; +import java.util.Collections; + +import com.sinthoras.visualprospecting.Tags; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; + +import journeymap.api.v2.client.display.ImageOverlay; +import journeymap.api.v2.client.model.MapImage; +import journeymap.api.v2.common.Context; +import journeymap.api.v2.common.util.BlockPos; + +public final class UndergroundFluidImageOverlay { + + private static final int CELL_PIXELS = 8; + + private UndergroundFluidImageOverlay() {} + + public static Collection create(UndergroundFluidLocation location) { + BufferedImage image = new BufferedImage( + VP.undergroundFluidSizeChunkX * CELL_PIXELS, + VP.undergroundFluidSizeChunkZ * CELL_PIXELS, + BufferedImage.TYPE_INT_ARGB); + if (location.isActive()) { + int min = location.getMinProduction(); + int max = location.getMaxProduction(); + float range = max - min + 1; + for (int x = 0; x < VP.undergroundFluidSizeChunkX; x++) { + for (int z = 0; z < VP.undergroundFluidSizeChunkZ; z++) { + int amount = location.getChunks()[x][z]; + if (amount <= 0) continue; + int alpha = range > 1 ? (int) ((amount - min) / range * 255) : 10; + fillCell(image, x, z, alpha << 24 | location.getColor()); + } + } + } + drawBorder( + image, + (location.getMaxProduction() > 0 ? location.getColor() : 0xFFFFFF) + | (location.isActive() && location.getMaxProduction() > 0 ? 0xFF : 74) << 24); + + int x = (int) Math.floor(location.getBlockX()); + int z = (int) Math.floor(location.getBlockZ()); + int width = VP.undergroundFluidSizeChunkX * VP.chunkWidth; + int height = VP.undergroundFluidSizeChunkZ * VP.chunkWidth; + MapImage mapImage = new MapImage(image).setBlur(false); + ImageOverlay overlay = new ImageOverlay( + Tags.MODID, + new BlockPos(x, 64, z), + new BlockPos(x + width, 64, z + height), + mapImage); + overlay.setDimension(location.getDimensionId()).setOverlayGroupName(UndergroundFluidLocation.class.getName()) + .setActiveUIs(Context.UI.Minimap); + return Collections.singletonList(overlay); + } + + private static void fillCell(BufferedImage image, int cellX, int cellZ, int argb) { + for (int x = cellX * CELL_PIXELS; x < (cellX + 1) * CELL_PIXELS; x++) { + for (int z = cellZ * CELL_PIXELS; z < (cellZ + 1) * CELL_PIXELS; z++) { + image.setRGB(x, z, argb); + } + } + } + + private static void drawBorder(BufferedImage image, int argb) { + for (int x = 0; x < image.getWidth(); x++) { + image.setRGB(x, 0, argb); + image.setRGB(x, image.getHeight() - 1, argb); + } + for (int z = 0; z < image.getHeight(); z++) { + image.setRGB(0, z, argb); + image.setRGB(image.getWidth() - 1, z, argb); + } + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java index 963a4a2a..113060c9 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java @@ -20,6 +20,11 @@ public UndergroundFluidRenderStep(UndergroundFluidLocation location) { setFontScale(0.5f); } + @Override + public void preRender(double topX, double topY, float drawScale, double zoom) { + setOffset(isJourneyMap ? -blockSize / 2 : 0); + } + @Override public void draw(double topX, double topY, float drawScale, double zoom) { final Minecraft mc = Minecraft.getMinecraft(); From 466e28d223b6115fd61ebf6ee4cef8471eaf33d7 Mon Sep 17 00:00:00 2001 From: Algent Date: Sat, 18 Jul 2026 22:33:00 +0200 Subject: [PATCH 02/10] Progress on JM6 --- dependencies.gradle | 1 + repositories.gradle | 5 +++++ .../java/com/sinthoras/visualprospecting/Config.java | 9 +++++++++ .../integration/model/render/OreVeinMapMarker.java | 2 +- 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index 58b50f68..267baee2 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -4,6 +4,7 @@ dependencies { api('com.github.GTNewHorizons:GT5-Unofficial:5.09.54.29:dev') api('com.github.GTNewHorizons:NotEnoughItems:2.8.110-GTNH:dev') + compileOnly('info.journeymap:journeymap-api-forge:1.7.10-2.0.0') compileOnlyApi('com.github.GTNewHorizons:Galacticraft:3.4.31-GTNH:dev') { transitive = false } runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.18')) diff --git a/repositories.gradle b/repositories.gradle index 9fbd7d4a..5a77fd21 100644 --- a/repositories.gradle +++ b/repositories.gradle @@ -1,2 +1,7 @@ repositories { + maven { + name = "JourneyMap" + url = "https://maven.blamejared.com" + } + mavenLocal() } diff --git a/src/main/java/com/sinthoras/visualprospecting/Config.java b/src/main/java/com/sinthoras/visualprospecting/Config.java index c0dee5ab..691e3ed8 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Config.java +++ b/src/main/java/com/sinthoras/visualprospecting/Config.java @@ -20,6 +20,7 @@ private static class Defaults { public static final int uploadBandwidthBytes = 2000000; public static final int maxTransferCacheSizeMB = 50; public static final boolean enableVoxelMapWaypointsByDefault = false; + public static final boolean showOreLabelsOnJourneyMap6Minimap = false; public static final int maxRegionRowFileMBForInMemoryScan = 10000; } @@ -43,6 +44,7 @@ private static class Categories { public static int uploadPacketsPerSecond = uploadBandwidthBytes / VP.uploadSizePerPacketInBytes; public static int maxTransferCacheSizeMB = Defaults.maxTransferCacheSizeMB; public static boolean enableVoxelMapWaypointsByDefault = Defaults.enableVoxelMapWaypointsByDefault; + public static boolean showOreLabelsOnJourneyMap6Minimap = Defaults.showOreLabelsOnJourneyMap6Minimap; public static int maxRegionRowFileMBForInMemoryScan = Defaults.maxRegionRowFileMBForInMemoryScan; public static void syncronizeConfiguration(File configFile) { @@ -134,6 +136,13 @@ public static void syncronizeConfiguration(File configFile) { "[CLIENT / VoxelMap] Enable waypoints added by prospecting GT ore veins or underground fluids by default"); enableVoxelMapWaypointsByDefault = enableVoxelMapWaypointsByDefaultProperty.getBoolean(); + Property showOreLabelsOnJourneyMap6MinimapProperty = configuration.get( + Categories.integration, + "showOreLabelsOnJourneyMap6Minimap", + Defaults.showOreLabelsOnJourneyMap6Minimap, + "[CLIENT / JourneyMap 6] Show ore vein labels on the minimap. Labels may extend beyond the minimap edge."); + showOreLabelsOnJourneyMap6Minimap = showOreLabelsOnJourneyMap6MinimapProperty.getBoolean(); + Property maxRegionRowFileMBForInMemoryScanProperty = configuration.get( Categories.caching, "maxRegionRowFileMBForInMemoryScan", diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinMapMarker.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinMapMarker.java index 3552dfdc..8bd11db8 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinMapMarker.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinMapMarker.java @@ -43,7 +43,7 @@ private OreVeinMapMarker() {} if (!location.isDepleted()) { marker.setLabel(location.getName()).setLabelColor(location.drawSearchHighlight() ? 0xFFFFFF : 0x7F7F7F) .setLabelScale(1.2F).setLabelOffsetY(24).setLabelMinZoom(Config.minZoomLevelForOreLabel) - .setLabelOnMinimap(false); + .setLabelOnMinimap(Config.showOreLabelsOnJourneyMap6Minimap); } return marker; } From 6f229cceca717dffc8f2d97eff7d72db902368ec Mon Sep 17 00:00:00 2001 From: Algent Date: Thu, 23 Jul 2026 18:00:43 +0200 Subject: [PATCH 03/10] Improve label zoom handling --- .../model/render/OreVeinMapMarker.java | 6 ++- .../model/render/OreVeinRenderStep.java | 14 +++-- .../render/UndergroundFluidRenderStep.java | 51 +++++++++++++++---- 3 files changed, 55 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinMapMarker.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinMapMarker.java index 8bd11db8..a86f1dc5 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinMapMarker.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinMapMarker.java @@ -39,10 +39,12 @@ private OreVeinMapMarker() {} BufferedImage icon = createIcon(location); if (icon == null) return null; - MapMarker marker = new MapMarker(icon).setDisplaySize(ICON_SIZE, ICON_SIZE); + MapMarker marker = new MapMarker(icon).setDisplaySize(ICON_SIZE, ICON_SIZE).setDisplayZoomScale(1, 2, 3, 5); if (!location.isDepleted()) { marker.setLabel(location.getName()).setLabelColor(location.drawSearchHighlight() ? 0xFFFFFF : 0x7F7F7F) - .setLabelScale(1.2F).setLabelOffsetY(24).setLabelMinZoom(Config.minZoomLevelForOreLabel) + .setLabelScale(1.2F).setLabelZoomScale(1, 2.5, Math.min(Config.minZoomLevelForOreLabel, 4), 5) + .setLabelOffsetY(28).setLabelBackgroundOpacity(0.35F) + .setLabelMinZoom(Config.minZoomLevelForOreLabel) .setLabelOnMinimap(Config.showOreLabelsOnJourneyMap6Minimap); } return marker; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java index 8f88c8ea..56b940e2 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java @@ -36,7 +36,7 @@ public OreVeinRenderStep(OreVeinLocation location) { @Override public void preRender(double topX, double topY, float drawScale, double zoom) { - double iconSize = isXaero ? 10 * zoom : 32 * drawScale; + double iconSize = isXaero ? 10 * zoom : 32 * drawScale * getZoomScale(1, 2, 3, 5); setSize(iconSize); setOffset(-iconSize / 2); } @@ -49,22 +49,23 @@ public void draw(double topX, double topY, float drawScale, double zoom) { final double scale = 1.0; final double screenW = mc.displayWidth * scale; final double screenH = mc.displayHeight * scale; - final double topMargin = (fontHeight + 5) * getFontScale() * scale; + final double topMargin = (fontHeight + 5) * getLabelScale() * scale; if (topX + width < 0 || topX > screenW || topY + height < -topMargin || topY > screenH) { return; } } if (zoom >= Config.minZoomLevelForOreLabel && !location.isDepleted()) { + final double labelScale = getLabelScale(); final int fontColor = location.drawSearchHighlight() ? 0xFFFFFF : 0x7F7F7F; DrawUtils.drawLabel( location.getName(), topX + width / 2, - topY - fontHeight - 5, + topY - (fontHeight + 5) * (isXaero ? 1 : labelScale), fontColor, 0, true, - getFontScale()); + labelScale); } final IIcon blockIcon = DimensionStoneBackground.getBackgroundIcon(location.getDimensionId()); @@ -140,4 +141,9 @@ public boolean onKeyPressed(int keyCode) { private void playClickSound() { Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(clickSound, 1.0F)); } + + private double getLabelScale() { + return isXaero ? getFontScale() + : getFontScale() * getZoomScale(1.2, 3, Math.min(Config.minZoomLevelForOreLabel, 4), 5); + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java index 113060c9..2229037c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java @@ -47,14 +47,15 @@ public void draw(double topX, double topY, float drawScale, double zoom) { DrawUtils.drawHollowRect(topX, topY, getAdjustedWidth(), getAdjustedHeight(), 0xFFFFFF, 74, 2); } - if (!isMinimap()) { - String label = I18n.format("visualprospecting.empty"); + if (!isMinimap() && getZoomStep() >= Config.minZoomLevelForUndergroundFluidDetails - 3) { + String title = I18n.format("visualprospecting.empty"); + String values = null; if (maxAmountInField > 0) { - label = MessageFormat.format( - "{0}-{1} L/Op {2}", + title = location.getFluid().getLocalizedName(); + values = MessageFormat.format( + "{0}-{1} L/Op", formatAmount(location.getMinProduction()), - formatAmount(maxAmountInField), - location.getFluid().getLocalizedName()); + formatAmount(maxAmountInField)); } int textColor = 0xFFFFFFFF; @@ -62,14 +63,25 @@ public void draw(double topX, double topY, float drawScale, double zoom) { textColor = location.isActive() ? 0xFFFF00 : 0x444444; } + final double labelScale = getMainLabelScale(); DrawUtils.drawLabel( - label, + title, topX + getAdjustedWidth() / 2, topY + 1.5, textColor, 0xB4000000, true, - getFontScale()); + labelScale); + if (values != null) { + DrawUtils.drawLabel( + values, + topX + getAdjustedWidth() / 2, + topY + 1.5 + (mc.fontRenderer.FONT_HEIGHT + 2) * labelScale, + textColor, + 0xB4000000, + true, + labelScale); + } } } @@ -89,6 +101,14 @@ private void renderChunks(double x, double y) { final boolean highlightPeak = maxProduction >= 10; final Minecraft mc = Minecraft.getMinecraft(); + final double cellLabelScale = getCellLabelScale(); + final double cellLabelOffsetY = isXaero ? 0 + : (mc.fontRenderer.FONT_HEIGHT + 2) * cellLabelScale + * getZoomScale( + 1, + 0, + Config.minZoomLevelForUndergroundFluidDetails, + Config.minZoomLevelForUndergroundFluidDetails + 1); final double screenW = mc.displayWidth; final double screenH = mc.displayHeight; setSize(VP.chunkWidth); @@ -113,11 +133,11 @@ private void renderChunks(double x, double y) { DrawUtils.drawLabel( MessageFormat.format("{0} L/Op", formatAmount(amount)), cellX + cellW / 2, - cellY + cellH / 2, + cellY + cellH / 2 + cellLabelOffsetY, 0xFFFFFFFF, 0xB4000000, true, - getFontScale()); + cellLabelScale); } } } @@ -133,4 +153,15 @@ private String formatAmount(int amount) { } return (roundedTenths / 10) + "." + (roundedTenths % 10) + "k"; } + + private double getCellLabelScale() { + return isXaero ? getFontScale() * 0.7 + : getFontScale() * getZoomScale(1.2, 3, Math.min(Config.minZoomLevelForUndergroundFluidDetails, 4), 5); + } + + private double getMainLabelScale() { + return isXaero ? getFontScale() + : getFontScale() + * getZoomScale(1, 4.5, Math.min(Config.minZoomLevelForUndergroundFluidDetails - 3, 4), 5); + } } From 40d700b3accc75f16b1711c85930d7feb06c37d8 Mon Sep 17 00:00:00 2001 From: Algent Date: Thu, 23 Jul 2026 21:16:30 +0200 Subject: [PATCH 04/10] Square marker on veins --- .../visualprospecting/textures/node_marked.png | Bin 998 -> 202 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/main/resources/assets/visualprospecting/textures/node_marked.png b/src/main/resources/assets/visualprospecting/textures/node_marked.png index 2f2e7cd2db1347f85a22c41bff271e827caf77d2..0eed536bb87a3e16ef88e7a2e9ad14b9e82be775 100644 GIT binary patch delta 175 zcmaFHeu{B|ay`RDPZ!6Kh{JDZI`TCr@UVQ(tQD$1+K@l-NY#PnuJFl1?MoC{`A(;8 zntrPL&g-R0-=-Vi)w_QDaYpUbZ2PPE-IKy2Pj4!y4%}sZr#^{m*Pc^sDp7no7W+Al zJ@jYwKU&b3C^2tNVv$7q$wY~^M47fk3AOgb8BkiHO`{Mf`Xk-)j=Q(mrnZgOT}>cSOjiH^ delta 977 zcmV;?11|i^0pEX>4Tx04R}tkv&MmKpe$iQ>9WW4tA*G zkfAzR5EXHhDi*;)X)CnqU~=gfG-*guTpR`0f`cE6RRs^dzd7t}p^eY9E0X~st?f%Ws@Z4huXp zY-H2(#9?Bw)Wvcav$CNQPZLKKRik_%=d!|ii?dp-v-Umt3qu8MCBt=^BS>HgNu(e` zMjaJYVIfAVMt_QlH0{Sd{KJkvMJ}0K6)&@IM1rTE|~&0<)i_H#%DM2pHG~F0MP8ya!zF0FftMG9*Xx(-ewD z;QfrgDGvL%6xAs0xAAl@%wR{5{90Fq{%3k+)cYj}ZZ~vZY_xA&OU~;OEB5(`< z000SaNLh0L04^f{04^f|c%?sf00007bV*G`2jvPG3?B-~X+FUK000?uMObu0Z*6U5 zZgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}00006VoOIv00000008+zyMF)x0lrB@K~z}7 z)tRl1!+$Ug$E~uFN_~>jYOG*vU@9x=3-mpvp-JV(S2Wm17&tuXveSW}49Z)A!g?gYG)SJ{$Uqxfuu|6!_&}o7yQ7_b|r(X1J zvIJ;`x($HrQfn)l19XeJP6*1?+TKnDo1Iy##O_4~qi$;!n4~pk{rSyuuHH00000NkvXXu0mjf*z~78 From bfc4555d0e139deb2bb9f5c96ddedf6d36977274 Mon Sep 17 00:00:00 2001 From: Algent Date: Thu, 23 Jul 2026 21:19:09 +0200 Subject: [PATCH 05/10] Use events --- .../visualprospecting/hooks/HooksClient.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java index 7b9abb70..d024f6e0 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java @@ -1,5 +1,6 @@ package com.sinthoras.visualprospecting.hooks; +import net.minecraft.client.Minecraft; import net.minecraftforge.client.ClientCommandHandler; import net.minecraftforge.common.MinecraftForge; @@ -22,6 +23,7 @@ import cpw.mods.fml.common.event.FMLServerStartingEvent; import cpw.mods.fml.common.event.FMLServerStoppedEvent; import cpw.mods.fml.common.event.FMLServerStoppingEvent; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; public class HooksClient extends HooksShared { @@ -86,9 +88,28 @@ public void registerMapLayers() { NavigatorApi.registerLayerManager(OreVeinLayerManager.instance); NavigatorApi.registerLayerManager(UndergroundFluidLayerManager.instance); + MinecraftForge.EVENT_BUS.register(this); if (Util.isVoxelMapInstalled()) { MinecraftForge.EVENT_BUS.register(new VoxelMapEventHandler()); } } + + @SubscribeEvent + public void onVeinProspected(ProspectingNotificationEvent.OreVein event) { + Minecraft.getMinecraft().func_152344_a( + () -> OreVeinLayerManager.instance.invalidateLocation( + event.getPosition().dimensionId, + event.getPosition().chunkX, + event.getPosition().chunkZ)); + } + + @SubscribeEvent + public void onFluidProspected(ProspectingNotificationEvent.UndergroundFluid event) { + Minecraft.getMinecraft().func_152344_a( + () -> UndergroundFluidLayerManager.instance.invalidateLocation( + event.getPosition().dimensionId, + event.getPosition().chunkX, + event.getPosition().chunkZ)); + } } From 920b04132a31620afd39c4230d861b6ffff6fe99 Mon Sep 17 00:00:00 2001 From: Algent Date: Fri, 24 Jul 2026 01:53:51 +0200 Subject: [PATCH 06/10] Fix: Properly check center chunk --- .../integration/model/layers/OreVeinLayerManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java index 104ea6e6..bbd1ad8e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java @@ -57,7 +57,7 @@ protected WaypointManager addWaypointManager(InteractableLayerManager manager, S protected ILocationProvider generateLocation(int chunkX, int chunkZ, int dim) { int oreChunkX = Utils.mapToCenterOreChunkCoord(chunkX); int oreChunkZ = Utils.mapToCenterOreChunkCoord(chunkZ); - if (chunkX % oreChunkX != 0 || chunkZ % oreChunkZ != 0) { + if (chunkX != oreChunkX || chunkZ != oreChunkZ) { return null; } OreVeinPosition oreVeinPosition = ClientCache.instance.getOreVein(dim, oreChunkX, oreChunkZ); From 10b38c663767af2b39d1b087a4c36a3e25fdc83d Mon Sep 17 00:00:00 2001 From: Algent Date: Fri, 24 Jul 2026 22:09:29 +0200 Subject: [PATCH 07/10] Now that it's all fixed we can default this to true --- src/main/java/com/sinthoras/visualprospecting/Config.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/Config.java b/src/main/java/com/sinthoras/visualprospecting/Config.java index 691e3ed8..513e475b 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Config.java +++ b/src/main/java/com/sinthoras/visualprospecting/Config.java @@ -20,7 +20,7 @@ private static class Defaults { public static final int uploadBandwidthBytes = 2000000; public static final int maxTransferCacheSizeMB = 50; public static final boolean enableVoxelMapWaypointsByDefault = false; - public static final boolean showOreLabelsOnJourneyMap6Minimap = false; + public static final boolean showOreLabelsOnJourneyMap6Minimap = true; public static final int maxRegionRowFileMBForInMemoryScan = 10000; } @@ -140,7 +140,7 @@ public static void syncronizeConfiguration(File configFile) { Categories.integration, "showOreLabelsOnJourneyMap6Minimap", Defaults.showOreLabelsOnJourneyMap6Minimap, - "[CLIENT / JourneyMap 6] Show ore vein labels on the minimap. Labels may extend beyond the minimap edge."); + "[CLIENT / JourneyMap 6] Show ore vein labels on the minimap."); showOreLabelsOnJourneyMap6Minimap = showOreLabelsOnJourneyMap6MinimapProperty.getBoolean(); Property maxRegionRowFileMBForInMemoryScanProperty = configuration.get( From 8469e481c10d71a15a8bbd3b498f74581e6086d6 Mon Sep 17 00:00:00 2001 From: Algent Date: Mon, 27 Jul 2026 01:51:30 +0200 Subject: [PATCH 08/10] Adapt to navigator fix: Fix performance issue when zooming out a lot --- .../model/layers/OreVeinLayerManager.java | 28 +++++++++++-------- .../layers/UndergroundFluidLayerManager.java | 25 +++++++++-------- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java index bbd1ad8e..762002c3 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java @@ -1,5 +1,8 @@ package com.sinthoras.visualprospecting.integration.model.layers; +import java.util.ArrayList; +import java.util.Collection; + import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -54,18 +57,21 @@ protected WaypointManager addWaypointManager(InteractableLayerManager manager, S } @Override - protected ILocationProvider generateLocation(int chunkX, int chunkZ, int dim) { - int oreChunkX = Utils.mapToCenterOreChunkCoord(chunkX); - int oreChunkZ = Utils.mapToCenterOreChunkCoord(chunkZ); - if (chunkX != oreChunkX || chunkZ != oreChunkZ) { - return null; - } - OreVeinPosition oreVeinPosition = ClientCache.instance.getOreVein(dim, oreChunkX, oreChunkZ); - if (oreVeinPosition.veinType != VeinType.NO_VEIN) { - return new OreVeinLocation(oreVeinPosition); + protected Collection generateVisibleLocations(int minBlockX, int minBlockZ, + int maxBlockX, int maxBlockZ, int dimension) { + Collection locations = new ArrayList<>(); + for (OreVeinPosition vein : ClientCache.instance.getAllOreVeins()) { + int blockX = vein.getBlockX(); + int blockZ = vein.getBlockZ(); + if (vein.veinType != VeinType.NO_VEIN && vein.dimensionId == dimension + && blockX >= minBlockX + && blockX <= maxBlockX + && blockZ >= minBlockZ + && blockZ <= maxBlockZ) { + locations.add(new OreVeinLocation(vein)); + } } - - return null; + return locations; } @Override diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java index 267cfa23..7669e17a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java @@ -17,7 +17,6 @@ import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; import com.gtnewhorizons.navigator.api.util.Util; import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; import com.sinthoras.visualprospecting.integration.model.buttons.UndergroundFluidButtonManager; @@ -77,17 +76,21 @@ public void updateElement(ILocationProvider location) { } @Override - protected ILocationProvider generateLocation(int chunkX, int chunkZ, int dim) { - if (chunkX % VP.undergroundFluidSizeChunkX != 0 || chunkZ % VP.undergroundFluidSizeChunkZ != 0) { - return null; - } - - UndergroundFluidPosition undergroundFluid = ClientCache.instance.getUndergroundFluid(dim, chunkX, chunkZ); - if (undergroundFluid.isProspected()) { - return new UndergroundFluidLocation(undergroundFluid); + protected List generateVisibleLocations(int minBlockX, int minBlockZ, int maxBlockX, + int maxBlockZ, int dimension) { + List locations = new ArrayList<>(); + for (UndergroundFluidPosition fluid : ClientCache.instance.getAllUndergroundFluids()) { + int blockX = fluid.getBlockX(); + int blockZ = fluid.getBlockZ(); + if (fluid.isProspected() && fluid.dimensionId == dimension + && blockX >= minBlockX + && blockX <= maxBlockX + && blockZ >= minBlockZ + && blockZ <= maxBlockZ) { + locations.add(new UndergroundFluidLocation(fluid)); + } } - - return null; + return locations; } private void computeSearch(@Nullable Pattern filterPattern) { From 8462200f7d0beb34b807b684879c02355f2be81d Mon Sep 17 00:00:00 2001 From: Algent Date: Mon, 27 Jul 2026 22:26:48 +0200 Subject: [PATCH 09/10] Dep to merged upstream Navigator --- dependencies.gradle | 4 ++-- repositories.gradle | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 267baee2..f6cfae7a 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,5 +1,5 @@ dependencies { - api('com.github.GTNewHorizons:Navigator:1.1.4:dev') + api('com.github.GTNewHorizons:Navigator:1.1.7:dev') api('com.github.GTNewHorizons:GTNHLib:0.11.23:dev') api('com.github.GTNewHorizons:GT5-Unofficial:5.09.54.29:dev') api('com.github.GTNewHorizons:NotEnoughItems:2.8.110-GTNH:dev') @@ -7,5 +7,5 @@ dependencies { compileOnly('info.journeymap:journeymap-api-forge:1.7.10-2.0.0') compileOnlyApi('com.github.GTNewHorizons:Galacticraft:3.4.31-GTNH:dev') { transitive = false } - runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.18')) + runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.20')) } diff --git a/repositories.gradle b/repositories.gradle index 5a77fd21..1e870960 100644 --- a/repositories.gradle +++ b/repositories.gradle @@ -3,5 +3,4 @@ repositories { name = "JourneyMap" url = "https://maven.blamejared.com" } - mavenLocal() } From 45c5b6d0154fa7d1753e42cc856a9a814cb3057c Mon Sep 17 00:00:00 2001 From: Algent Date: Tue, 28 Jul 2026 03:40:47 +0200 Subject: [PATCH 10/10] Fix potential atlas rendering issue with fallback sprite --- dependencies.gradle | 2 +- .../model/render/OreVeinMapMarker.java | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index f6cfae7a..8623f1c5 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,5 +1,5 @@ dependencies { - api('com.github.GTNewHorizons:Navigator:1.1.7:dev') + api('com.github.GTNewHorizons:Navigator:1.1.8:dev') api('com.github.GTNewHorizons:GTNHLib:0.11.23:dev') api('com.github.GTNewHorizons:GT5-Unofficial:5.09.54.29:dev') api('com.github.GTNewHorizons:NotEnoughItems:2.8.110-GTNH:dev') diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinMapMarker.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinMapMarker.java index a86f1dc5..0fb10d4c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinMapMarker.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinMapMarker.java @@ -13,6 +13,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; @@ -125,13 +126,19 @@ private static void draw(Graphics2D graphics, @Nullable BufferedImage image) { private static @Nullable BufferedImage atlasSpriteImage(IIcon icon) { if (!(icon instanceof TextureAtlasSprite sprite) || sprite.getFrameCount() == 0) return null; - int width = sprite.getIconWidth(); - int height = sprite.getIconHeight(); + int sourceWidth = sprite.getIconWidth(); + int sourceHeight = sprite.getIconHeight(); int[][] frame = sprite.getFrameTextureData(0); - if (frame.length == 0 || frame[0] == null || frame[0].length < width * height) return null; - + if (frame.length == 0 || frame[0] == null || frame[0].length < sourceWidth * sourceHeight) return null; + + // The atlas location is irrelevant here; reuse MapMarker's normalized sprite region to exclude padding. + MapMarker spriteRegion = new MapMarker(TextureMap.locationBlocksTexture, sprite); + int width = spriteRegion.getTextureWidth(); + int height = spriteRegion.getTextureHeight(); + int offsetX = spriteRegion.getTextureX() - sprite.getOriginX(); + int offsetY = spriteRegion.getTextureY() - sprite.getOriginY(); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - image.setRGB(0, 0, width, height, frame[0], 0, width); + image.setRGB(0, 0, width, height, frame[0], offsetY * sourceWidth + offsetX, sourceWidth); return image; }