diff --git a/dependencies.gradle b/dependencies.gradle index 58b50f68..8623f1c5 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,10 +1,11 @@ dependencies { - api('com.github.GTNewHorizons:Navigator:1.1.4: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') + 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 9fbd7d4a..1e870960 100644 --- a/repositories.gradle +++ b/repositories.gradle @@ -1,2 +1,6 @@ repositories { + maven { + name = "JourneyMap" + url = "https://maven.blamejared.com" + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/Config.java b/src/main/java/com/sinthoras/visualprospecting/Config.java index c0dee5ab..513e475b 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 = true; 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."); + showOreLabelsOnJourneyMap6Minimap = showOreLabelsOnJourneyMap6MinimapProperty.getBoolean(); + Property maxRegionRowFileMBForInMemoryScanProperty = configuration.get( Categories.caching, "maxRegionRowFileMBForInMemoryScan", 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)); + } } 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..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; @@ -18,6 +21,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 +42,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 @@ -52,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 != 0 || chunkZ % oreChunkZ != 0) { - 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 0042fde6..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 @@ -15,12 +15,13 @@ 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 +41,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 @@ -70,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) { 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..0fb10d4c --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinMapMarker.java @@ -0,0 +1,164 @@ +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.client.renderer.texture.TextureMap; +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).setDisplayZoomScale(1, 2, 3, 5); + if (!location.isDepleted()) { + marker.setLabel(location.getName()).setLabelColor(location.drawSearchHighlight() ? 0xFFFFFF : 0x7F7F7F) + .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; + } + + 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 sourceWidth = sprite.getIconWidth(); + int sourceHeight = sprite.getIconHeight(); + int[][] frame = sprite.getFrameTextureData(0); + 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], offsetY * sourceWidth + offsetX, sourceWidth); + 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/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/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..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 @@ -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(); @@ -42,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; @@ -57,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); + } } } @@ -84,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); @@ -108,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); } } } @@ -128,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); + } } diff --git a/src/main/resources/assets/visualprospecting/textures/node_marked.png b/src/main/resources/assets/visualprospecting/textures/node_marked.png index 2f2e7cd2..0eed536b 100644 Binary files a/src/main/resources/assets/visualprospecting/textures/node_marked.png and b/src/main/resources/assets/visualprospecting/textures/node_marked.png differ