Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions dependencies.gradle
Original file line number Diff line number Diff line change
@@ -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'))
}
4 changes: 4 additions & 0 deletions repositories.gradle
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
repositories {
maven {
name = "JourneyMap"
url = "https://maven.blamejared.com"
}
}
9 changes: 9 additions & 0 deletions src/main/java/com/sinthoras/visualprospecting/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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) {
Expand Down Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.sinthoras.visualprospecting.hooks;

import net.minecraft.client.Minecraft;
import net.minecraftforge.client.ClientCommandHandler;
import net.minecraftforge.common.MinecraftForge;

Expand All @@ -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 {

Expand Down Expand Up @@ -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));
}
}
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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 {
Expand All @@ -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
Expand All @@ -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<? extends ILocationProvider> generateVisibleLocations(int minBlockX, int minBlockZ,
int maxBlockX, int maxBlockZ, int dimension) {
Collection<OreVeinLocation> 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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<? extends ILocationProvider> generateVisibleLocations(int minBlockX, int minBlockZ, int maxBlockX,
int maxBlockZ, int dimension) {
List<UndergroundFluidLocation> 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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
Loading
Loading