diff options
20 files changed, 2567 insertions, 2539 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java index 8c23aa60..9701005f 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java @@ -27,7 +27,6 @@ import io.github.moulberry.notenoughupdates.commands.Commands; import io.github.moulberry.notenoughupdates.core.BackgroundBlur; import io.github.moulberry.notenoughupdates.cosmetics.CapeManager; import io.github.moulberry.notenoughupdates.cosmetics.ShaderManager; -import io.github.moulberry.notenoughupdates.dungeons.DungeonMap; import io.github.moulberry.notenoughupdates.listener.ChatListener; import io.github.moulberry.notenoughupdates.listener.ItemTooltipListener; import io.github.moulberry.notenoughupdates.listener.NEUEventListener; @@ -262,7 +261,6 @@ public class NotEnoughUpdates { MinecraftForge.EVENT_BUS.register(SBInfo.getInstance()); MinecraftForge.EVENT_BUS.register(CustomItemEffects.INSTANCE); MinecraftForge.EVENT_BUS.register(new Constants()); - MinecraftForge.EVENT_BUS.register(new DungeonMap()); MinecraftForge.EVENT_BUS.register(new SunTzu()); MinecraftForge.EVENT_BUS.register(new MiningStuff()); MinecraftForge.EVENT_BUS.register(FairySouls.getInstance()); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DiagCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DiagCommand.java index 326c00b4..fb546efb 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DiagCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DiagCommand.java @@ -41,7 +41,8 @@ public class DiagCommand extends ClientCommandBase { " center=<off | on> Disable / enable using center\n" + "/neudiag wishing Wishing Compass Solver diagnostics\n" + "/neudiag debug\n" + - " <no sub-command> Show current flags\n" + + " <no sub-command> Show all enabled flags\n" + + " <list> Show all flags\n"+ " <enable | disable> <flag> Enable/disable flag\n"; private void showUsage(ICommandSender sender) { @@ -86,6 +87,10 @@ public class DiagCommand extends ClientCommandBase { boolean enablingFlag = true; String action = args[1]; switch (action) { + case "list": + sender.addChatMessage(new ChatComponentText( + EnumChatFormatting.YELLOW + "Here are all flags:\n" + NEUDebugFlag.getFlagList())); + return; case "disable": enablingFlag = false; // falls through @@ -93,7 +98,7 @@ public class DiagCommand extends ClientCommandBase { if (args.length != 3) { sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "You must specify a flag:\n" + - NEUDebugFlag.FLAG_LIST)); + NEUDebugFlag.getFlagList())); return; } @@ -108,7 +113,7 @@ public class DiagCommand extends ClientCommandBase { } catch (IllegalArgumentException e) { sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + flagName + " is invalid. Valid flags are:\n" + - NEUDebugFlag.FLAG_LIST)); + NEUDebugFlag.getFlagList())); return; } break; @@ -118,8 +123,8 @@ public class DiagCommand extends ClientCommandBase { } } - sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "Effective debug flags: " + - NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.toString())); + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "Effective debug flags: \n" + + NEUDebugFlag.getEnabledFlags())); break; default: showUsage(sender); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java deleted file mode 100644 index 2693341a..00000000 --- a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java +++ /dev/null @@ -1,1717 +0,0 @@ -/* - * Copyright (C) 2022 NotEnoughUpdates contributors - * - * This file is part of NotEnoughUpdates. - * - * NotEnoughUpdates is free software: you can redistribute it - * and/or modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation, either - * version 3 of the License, or (at your option) any later version. - * - * NotEnoughUpdates is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. - */ - -package io.github.moulberry.notenoughupdates.dungeons; - -import com.google.common.collect.Iterables; -import com.google.gson.JsonObject; -import io.github.moulberry.notenoughupdates.NotEnoughUpdates; -import io.github.moulberry.notenoughupdates.core.BackgroundBlur; -import io.github.moulberry.notenoughupdates.core.config.Position; -import io.github.moulberry.notenoughupdates.util.NEUResourceManager; -import io.github.moulberry.notenoughupdates.util.SpecialColour; -import io.github.moulberry.notenoughupdates.util.Utils; -import net.minecraft.block.material.MapColor; -import net.minecraft.client.Minecraft; -import net.minecraft.client.entity.AbstractClientPlayer; -import net.minecraft.client.gui.Gui; -import net.minecraft.client.gui.ScaledResolution; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.OpenGlHelper; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.WorldRenderer; -import net.minecraft.client.renderer.texture.TextureUtil; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.client.resources.DefaultPlayerSkin; -import net.minecraft.client.shader.Framebuffer; -import net.minecraft.client.shader.Shader; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.Items; -import net.minecraft.item.Item; -import net.minecraft.item.ItemMap; -import net.minecraft.item.ItemStack; -import net.minecraft.scoreboard.Score; -import net.minecraft.scoreboard.ScoreObjective; -import net.minecraft.scoreboard.ScorePlayerTeam; -import net.minecraft.scoreboard.Scoreboard; -import net.minecraft.util.Matrix4f; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.Vec4b; -import net.minecraft.world.storage.MapData; -import net.minecraftforge.client.event.RenderGameOverlayEvent; -import net.minecraftforge.event.world.WorldEvent; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL14; - -import java.awt.*; -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; - -public class DungeonMap { - private static final ResourceLocation GREEN_CHECK = new ResourceLocation( - "notenoughupdates:dungeon_map/green_check.png"); - private static final ResourceLocation WHITE_CHECK = new ResourceLocation( - "notenoughupdates:dungeon_map/white_check.png"); - private static final ResourceLocation QUESTION = new ResourceLocation("notenoughupdates:dungeon_map/question.png"); - private static final ResourceLocation CROSS = new ResourceLocation("notenoughupdates:dungeon_map/cross.png"); - - private static final ResourceLocation ROOM_RED = new ResourceLocation( - "notenoughupdates:dungeon_map/rooms_default/red_room.png"); - private static final ResourceLocation ROOM_BROWN = new ResourceLocation( - "notenoughupdates:dungeon_map/rooms_default/brown_room.png"); - private static final ResourceLocation ROOM_GRAY = new ResourceLocation( - "notenoughupdates:dungeon_map/rooms_default/gray_room.png"); - private static final ResourceLocation ROOM_GREEN = new ResourceLocation( - "notenoughupdates:dungeon_map/rooms_default/green_room.png"); - private static final ResourceLocation ROOM_PINK = new ResourceLocation( - "notenoughupdates:dungeon_map/rooms_default/pink_room.png"); - private static final ResourceLocation ROOM_PURPLE = new ResourceLocation( - "notenoughupdates:dungeon_map/rooms_default/purple_room.png"); - private static final ResourceLocation ROOM_YELLOW = new ResourceLocation( - "notenoughupdates:dungeon_map/rooms_default/yellow_room.png"); - private static final ResourceLocation ROOM_ORANGE = new ResourceLocation( - "notenoughupdates:dungeon_map/rooms_default/orange_room.png"); - - private static final ResourceLocation CORRIDOR_RED = new ResourceLocation( - "notenoughupdates:dungeon_map/corridors_default/red_corridor.png"); - private static final ResourceLocation CORRIDOR_BROWN = new ResourceLocation( - "notenoughupdates:dungeon_map/corridors_default/brown_corridor.png"); - private static final ResourceLocation CORRIDOR_GRAY = new ResourceLocation( - "notenoughupdates:dungeon_map/corridors_default/gray_corridor.png"); - private static final ResourceLocation CORRIDOR_GREEN = new ResourceLocation( - "notenoughupdates:dungeon_map/corridors_default/green_corridor.png"); - private static final ResourceLocation CORRIDOR_PINK = new ResourceLocation( - "notenoughupdates:dungeon_map/corridors_default/pink_corridor.png"); - private static final ResourceLocation CORRIDOR_PURPLE = new ResourceLocation( - "notenoughupdates:dungeon_map/corridors_default/purple_corridor.png"); - private static final ResourceLocation CORRIDOR_YELLOW = new ResourceLocation( - "notenoughupdates:dungeon_map/corridors_default/yellow_corridor.png"); - private static final ResourceLocation CORRIDOR_ORANGE = new ResourceLocation( - "notenoughupdates:dungeon_map/corridors_default/orange_corridor.png"); - - private static final ResourceLocation DIVIDER_BROWN = new ResourceLocation( - "notenoughupdates:dungeon_map/dividers_default/brown_divider.png"); - - private static final ResourceLocation CORNER_BROWN = new ResourceLocation( - "notenoughupdates:dungeon_map/corners_default/brown_corner.png"); - - private final HashMap<RoomOffset, Room> roomMap = new HashMap<>(); - private Color[][] colourMap = new Color[128][128]; - private int startRoomX = -1; - private int startRoomY = -1; - private int connectorSize = 5; - private int roomSize = 0; - - //private final List<MapDecoration> decorations = new ArrayList<>(); - //private final List<MapDecoration> lastDecorations = new ArrayList<>(); - private long lastDecorationsMillis = -1; - private long lastLastDecorationsMillis = -1; - - private final Map<String, MapPosition> playerEntityMapPositions = new HashMap<>(); - private final Map<String, MapPosition> playerMarkerMapPositions = new HashMap<>(); - private final Set<MapPosition> rawPlayerMarkerMapPositions = new HashSet<>(); - private final Map<String, MapPosition> playerMarkerMapPositionsLast = new HashMap<>(); - private final HashMap<String, Integer> playerIdMap = new HashMap<>(); - - private final Map<String, ResourceLocation> playerSkinMap = new HashMap<>(); - - private static class RoomOffset { - int x; - int y; - - public RoomOffset(int x, int y) { - this.x = x; - this.y = y; - } - - public RoomOffset left() { - return new RoomOffset(x - 1, y); - } - - public RoomOffset right() { - return new RoomOffset(x + 1, y); - } - - public RoomOffset up() { - return new RoomOffset(x, y - 1); - } - - public RoomOffset down() { - return new RoomOffset(x, y + 1); - } - - public RoomOffset[] getNeighbors() { - return new RoomOffset[]{left(), right(), up(), down()}; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - RoomOffset that = (RoomOffset) o; - return x == that.x && y == that.y; - } - - @Override - public int hashCode() { - return Objects.hash(x, y); - } - } - - private enum RoomConnectionType { - NONE, WALL, CORRIDOR, ROOM_DIVIDER - } - - private static class RoomConnection { - RoomConnectionType type; - Color colour; - - public RoomConnection(RoomConnectionType type, Color colour) { - this.type = type; - this.colour = colour; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - RoomConnection that = (RoomConnection) o; - return type == that.type && - Objects.equals(colour, that.colour); - } - - @Override - public int hashCode() { - return Objects.hash(type, colour); - } - } - - private class Room { - Color colour = new Color(0, 0, 0, 0); - int tickColour = 0; - boolean fillCorner = false; - - RoomConnection left = new RoomConnection(RoomConnectionType.NONE, new Color(0, true)); - RoomConnection up = new RoomConnection(RoomConnectionType.NONE, new Color(0, true)); - RoomConnection right = new RoomConnection(RoomConnectionType.NONE, new Color(0, true)); - RoomConnection down = new RoomConnection(RoomConnectionType.NONE, new Color(0, true)); - - public void renderNoRotate(int roomSize, int connectorSize, int rotation) { - if (tickColour != 0) { - Color tick = new Color(tickColour, true); - ResourceLocation indicatorTex = null; - if (tick.getRed() == 255 && tick.getGreen() == 255 && tick.getBlue() == 255) { - indicatorTex = WHITE_CHECK; - } else if (tick.getRed() == 0 && tick.getGreen() == 124 && tick.getBlue() == 0) { - indicatorTex = GREEN_CHECK; - } else if (tick.getRed() == 13 && tick.getGreen() == 13 && tick.getBlue() == 13) { - indicatorTex = QUESTION; - } else if (tick.getRed() == 255 && tick.getGreen() == 0 && tick.getBlue() == 0) { - indicatorTex = CROSS; - } - if (indicatorTex != null) { - Minecraft.getMinecraft().getTextureManager().bindTexture(indicatorTex); - float x = 0; - float y = 0; - - if (NotEnoughUpdates.INSTANCE.config.dungeonMap.dmCenterCheck) { - if (fillCorner) { - x += -(roomSize + connectorSize) / 2f * Math.cos(Math.toRadians(rotation - 45)) * 1.414f; - y += (roomSize + connectorSize) / 2f * Math.sin(Math.toRadians(rotation - 45)) * 1.414; - } - if (down.type == RoomConnectionType.ROOM_DIVIDER && right.type != RoomConnectionType.ROOM_DIVIDER) { - x += -(roomSize + connectorSize) / 2f * Math.sin(Math.toRadians(rotation)); - y += -(roomSize + connectorSize) / 2f * Math.cos(Math.toRadians(rotation)); - } else if (down.type != RoomConnectionType.ROOM_DIVIDER && right.type == RoomConnectionType.ROOM_DIVIDER) { - x += -(roomSize + connectorSize) / 2f * Math.cos(Math.toRadians(rotation)); - y += (roomSize + connectorSize) / 2f * Math.sin(Math.toRadians(rotation)); - } - } - GlStateManager.translate(x, y, 0); - if (!NotEnoughUpdates.INSTANCE.config.dungeonMap.dmOrientCheck) { - GlStateManager.rotate(-rotation + 180, 0, 0, 1); - } - - GlStateManager.pushMatrix(); - GlStateManager.scale(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmIconScale, - NotEnoughUpdates.INSTANCE.config.dungeonMap.dmIconScale, 1 - ); - Utils.drawTexturedRect(-5, -5, 10, 10, GL11.GL_NEAREST); - GlStateManager.popMatrix(); - - if (!NotEnoughUpdates.INSTANCE.config.dungeonMap.dmOrientCheck) { - GlStateManager.rotate(rotation - 180, 0, 0, 1); - } - GlStateManager.translate(-x, -y, 0); - } - } - } - - public void render(int roomSize, int connectorSize) { - ResourceLocation roomTex = null; - if (colour.getRed() == 114 && colour.getGreen() == 67 && colour.getBlue() == 27) { - roomTex = ROOM_BROWN; - } else if (colour.getRed() == 65 && colour.getGreen() == 65 && colour.getBlue() == 65) { - roomTex = ROOM_GRAY; - } else if (colour.getRed() == 0 && colour.getGreen() == 124 && colour.getBlue() == 0) { - roomTex = ROOM_GREEN; - } else if (colour.getRed() == 242 && colour.getGreen() == 127 && colour.getBlue() == 165) { - roomTex = ROOM_PINK; - } else if (colour.getRed() == 178 && colour.getGreen() == 76 && colour.getBlue() == 216) { - roomTex = ROOM_PURPLE; - } else if (colour.getRed() == 255 && colour.getGreen() == 0 && colour.getBlue() == 0) { - roomTex = ROOM_RED; - } else if (colour.getRed() == 229 && colour.getGreen() == 229 && colour.getBlue() == 51) { - roomTex = ROOM_YELLOW; - } else if (colour.getRed() == 216 && colour.getGreen() == 127 && colour.getBlue() == 51) { - roomTex = ROOM_ORANGE; - } - - if (roomTex != null) { - Minecraft.getMinecraft().getTextureManager().bindTexture(roomTex); - GlStateManager.color(1, 1, 1, 1); - Utils.drawTexturedRect(0, 0, roomSize, roomSize, GL11.GL_LINEAR); - } else { - Gui.drawRect(0, 0, roomSize, roomSize, colour.getRGB()); - } - - if (fillCorner) { - GlStateManager.color(1, 1, 1, 1); - Minecraft.getMinecraft().getTextureManager().bindTexture(CORNER_BROWN); - Utils.drawTexturedRect(roomSize, roomSize, connectorSize, connectorSize, GL11.GL_NEAREST); - } - - for (int k = 0; k < 2; k++) { - RoomConnection connection = down; - if (k == 1) connection = right; - - if (connection.type == RoomConnectionType.NONE || connection.type == RoomConnectionType.WALL) continue; - - ResourceLocation corridorTex = null; - if (connection.colour.getRed() == 114 && connection.colour.getGreen() == 67 && - connection.colour.getBlue() == 27) { - corridorTex = connection.type == RoomConnectionType.CORRIDOR ? CORRIDOR_BROWN : DIVIDER_BROWN; - } else if (connection.colour.getRed() == 65 && connection.colour.getGreen() == 65 && - connection.colour.getBlue() == 65) { - corridorTex = CORRIDOR_GRAY; - } else if (connection.colour.getRed() == 0 && connection.colour.getGreen() == 124 && - connection.colour.getBlue() == 0) { - corridorTex = CORRIDOR_GREEN; - } else if (connection.colour.getRed() == 242 && connection.colour.getGreen() == 127 && - connection.colour.getBlue() == 165) { - corridorTex = CORRIDOR_PINK; - } else if (connection.colour.getRed() == 178 && connection.colour.getGreen() == 76 && - connection.colour.getBlue() == 216) { - corridorTex = CORRIDOR_PURPLE; - } else if (connection.colour.getRed() == 255 && connection.colour.getGreen() == 0 && - connection.colour.getBlue() == 0) { - corridorTex = CORRIDOR_RED; - } else if (connection.colour.getRed() == 229 && connection.colour.getGreen() == 229 && - connection.colour.getBlue() == 51) { - corridorTex = CORRIDOR_YELLOW; - } else if (connection.colour.getRed() == 216 && connection.colour.getGreen() == 127 && - connection.colour.getBlue() == 51) { - corridorTex = CORRIDOR_ORANGE; - } - - if (corridorTex == null) { - int xOffset = 0; - int yOffset = 0; - int width = 0; - int height = 0; - - if (connection == right) { - xOffset = roomSize; - width = connectorSize; - height = roomSize; - - if (connection.type == RoomConnectionType.CORRIDOR) { - height = 8; - yOffset += 4; - } - } else if (connection == down) { - yOffset = roomSize; - width = roomSize; - height = connectorSize; - - if (connection.type == RoomConnectionType.CORRIDOR) { - width = 8; - xOffset += 4; - } - } - - Gui.drawRect(xOffset, yOffset, xOffset + width, yOffset + height, connection.colour.getRGB()); - } else { - GlStateManager.color(1, 1, 1, 1); - Minecraft.getMinecraft().getTextureManager().bindTexture(corridorTex); - GlStateManager.pushMatrix(); - if (connection == right) { - GlStateManager.translate(roomSize / 2f, roomSize / 2f, 0); - GlStateManager.rotate(-90, 0, 0, 1); - GlStateManager.translate(-roomSize / 2f, -roomSize / 2f, 0); - } - Utils.drawTexturedRect(0, roomSize, roomSize, connectorSize, GL11.GL_NEAREST); - GlStateManager.popMatrix(); - } - } - } - } - - private static final ResourceLocation mapIcons = new ResourceLocation("textures/map/map_icons.png"); - - public static Framebuffer mapFramebuffer1 = null; - public static Framebuffer mapFramebuffer2 = null; - public static Matrix4f projectionMatrix = null; - public static Shader mapShader = null; - - private static Framebuffer checkFramebufferSizes(Framebuffer framebuffer, int width, int height) { - if (framebuffer == null || framebuffer.framebufferWidth != width || framebuffer.framebufferHeight != height) { - if (framebuffer == null) { - framebuffer = new Framebuffer(width, height, true); - } else { - framebuffer.createBindFramebuffer(width, height); - } - framebuffer.setFramebufferFilter(GL11.GL_NEAREST); - } - return framebuffer; - } - - private static void upload(Shader shader, int width, int height, int scale, float radiusSq) { - if (shader == null) return; - shader.getShaderManager().getShaderUniformOrDefault("ProjMat").set(projectionMatrix); - shader.getShaderManager().getShaderUniformOrDefault("InSize").set(width * scale, height * scale); - shader.getShaderManager().getShaderUniformOrDefault("OutSize").set(width, height); - shader.getShaderManager().getShaderUniformOrDefault("ScreenSize").set((float) width, (float) height); - shader.getShaderManager().getShaderUniformOrDefault("radiusSq").set(radiusSq); - } - - public int getRenderRoomSize() { - double roomSizeOption = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmRoomSize; - if (roomSizeOption <= 0) return 12; - return 12 + (int) Math.round(roomSizeOption * 4); - } - - public int getRenderConnSize() { - int roomSizeOption = Math.round(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmRoomSize); - if (roomSizeOption <= 0) return 3; - return 3 + roomSizeOption; - } - - private final HashMap<Integer, Float> borderRadiusCache = new HashMap<>(); - - public float getBorderRadius() { - int borderSizeOption = Math.round(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderSize); - String sizeId = borderSizeOption == 0 ? "small" : borderSizeOption == 2 ? "large" : "medium"; - - int style = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderStyle; - if (borderRadiusCache.containsKey(style)) { - return borderRadiusCache.get(style); - } - - try ( - BufferedReader reader = new BufferedReader(new InputStreamReader(Minecraft - .getMinecraft() - .getResourceManager() - .getResource( - new ResourceLocation("notenoughupdates:dungeon_map/borders/" + sizeId + "/" + style + ".json")) - .getInputStream(), StandardCharsets.UTF_8)) - ) { - JsonObject json = NotEnoughUpdates.INSTANCE.manager.gson.fromJson(reader, JsonObject.class); - float radiusSq = json.get("radiusSq").getAsFloat(); - - borderRadiusCache.put(style, radiusSq); - return radiusSq; - } catch (Exception ignored) { - } - - borderRadiusCache.put(style, 1f); - return 1f; - } - - public void render(int centerX, int centerY) { - boolean useFb = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmCompat <= 1 && OpenGlHelper.isFramebufferEnabled(); - boolean useShd = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmCompat <= 0 && OpenGlHelper.areShadersSupported(); - - /*if((useFb && !OpenGlHelper.isFramebufferEnabled()) || (useShd && !OpenGlHelper.areShadersSupported())) { - Utils.drawStringCentered(EnumChatFormatting.RED+"NEU Dungeon Map requires framebuffers & shaders", - Minecraft.getMinecraft().fontRendererObj, centerX, centerY-10, true, 0); - Utils.drawStringCentered(EnumChatFormatting.RED+"Turn off Optifine Fast Render", - Minecraft.getMinecraft().fontRendererObj, centerX, centerY, true, 0); - Utils.drawStringCentered(EnumChatFormatting.RED+"If that doesn't work, join NEU discord for support", - Minecraft.getMinecraft().fontRendererObj, centerX, centerY+10, true, 0); - return; - }*/ - - ScaledResolution scaledResolution = Utils.pushGuiScale(2); - - int minRoomX = 999; - int minRoomY = 999; - int maxRoomX = -999; - int maxRoomY = -999; - for (RoomOffset offset : roomMap.keySet()) { - minRoomX = Math.min(offset.x, minRoomX); - minRoomY = Math.min(offset.y, minRoomY); - maxRoomX = Math.max(offset.x, maxRoomX); - maxRoomY = Math.max(offset.y, maxRoomY); - } - - int borderSizeOption = Math.round(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderSize); - - int renderRoomSize = getRenderRoomSize(); - int renderConnSize = getRenderConnSize(); - - MapPosition playerPos = null; - if (playerEntityMapPositions.containsKey(Minecraft.getMinecraft().thePlayer.getName())) { - playerPos = playerEntityMapPositions.get(Minecraft.getMinecraft().thePlayer.getName()); - } else if (playerMarkerMapPositions.containsKey(Minecraft.getMinecraft().thePlayer.getName())) { - playerPos = playerMarkerMapPositions.get(Minecraft.getMinecraft().thePlayer.getName()); - } - - int rotation = 180; - if (playerPos != null && NotEnoughUpdates.INSTANCE.config.dungeonMap.dmRotatePlayer) { - rotation = (int) playerPos.rotation; - } - - int mapSizeX; - int mapSizeY; - if (NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderStyle <= 1) { - mapSizeX = 80 + Math.round(40 * NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderSize); - } else { - mapSizeX = borderSizeOption == 0 ? 90 : borderSizeOption == 1 ? 120 : borderSizeOption == 2 ? 160 : 240; - } - mapSizeY = mapSizeX; - int roomsSizeX = (maxRoomX - minRoomX) * (renderRoomSize + renderConnSize) + renderRoomSize; - int roomsSizeY = (maxRoomY - minRoomY) * (renderRoomSize + renderConnSize) + renderRoomSize; - int mapCenterX = mapSizeX / 2; - int mapCenterY = mapSizeY / 2; - int scaleFactor = 8; - - projectionMatrix = Utils.createProjectionMatrix(mapSizeX * scaleFactor, mapSizeY * scaleFactor); - mapFramebuffer1 = checkFramebufferSizes(mapFramebuffer1, mapSizeX * scaleFactor, mapSizeY * scaleFactor); - mapFramebuffer2 = checkFramebufferSizes(mapFramebuffer2, mapSizeX * scaleFactor, mapSizeY * scaleFactor); - mapFramebuffer1.framebufferColor[1] = 0; - mapFramebuffer1.framebufferColor[2] = 0; - - try { - if (mapShader == null) { - mapShader = new Shader(new NEUResourceManager(Minecraft.getMinecraft().getResourceManager()), - "dungeonmap", mapFramebuffer1, mapFramebuffer2 - ); - } - } catch (Exception e) { - e.printStackTrace(); - Utils.pushGuiScale(-1); - return; - } - - int backgroundColour = - SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundColour); - - mapFramebuffer1.framebufferColor[0] = ((backgroundColour >> 16) & 0xFF) / 255f; - mapFramebuffer1.framebufferColor[1] = ((backgroundColour >> 8) & 0xFF) / 255f; - mapFramebuffer1.framebufferColor[2] = (backgroundColour & 0xFF) / 255f; - mapFramebuffer2.framebufferColor[0] = ((backgroundColour >> 16) & 0xFF) / 255f; - mapFramebuffer2.framebufferColor[1] = ((backgroundColour >> 8) & 0xFF) / 255f; - mapFramebuffer2.framebufferColor[2] = (backgroundColour & 0xFF) / 255f; - - try { - if (useFb) { - mapFramebuffer1.framebufferClear(); - mapFramebuffer2.framebufferClear(); - } - - GlStateManager.pushMatrix(); - { - if (useFb) { - GlStateManager.matrixMode(5889); - GlStateManager.loadIdentity(); - GlStateManager.ortho(0.0D, mapSizeX * scaleFactor, mapSizeY * scaleFactor, 0.0D, 1000.0D, 3000.0D); - GlStateManager.matrixMode(5888); - GlStateManager.loadIdentity(); - GlStateManager.translate(0.0F, 0.0F, -2000.0F); - - GlStateManager.scale(scaleFactor, scaleFactor, 1); - mapFramebuffer1.bindFramebuffer(true); - - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - GlStateManager.disableBlend(); - } else { - GL11.glEnable(GL11.GL_SCISSOR_TEST); - GL11.glScissor( - (centerX - mapSizeX / 2) * 2, - Minecraft.getMinecraft().displayHeight - (centerY + mapSizeY / 2) * 2, - mapSizeX * 2, - mapSizeY * 2 - ); - - GlStateManager.translate(centerX - mapSizeX / 2, centerY - mapSizeY / 2, 100); - } - - if (NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur > 0.1 && - NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur < 100 && - NotEnoughUpdates.INSTANCE.config.dungeonMap.dmEnable) { - GlStateManager.translate(-centerX + mapSizeX / 2, -centerY + mapSizeY / 2, 0); - BackgroundBlur.renderBlurredBackground(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur, - scaledResolution.getScaledWidth(), scaledResolution.getScaledHeight(), - centerX - mapSizeX / 2, centerY - mapSizeY / 2, mapSizeX, mapSizeY - ); - BackgroundBlur.markDirty(); - GlStateManager.translate(centerX - mapSizeX / 2, centerY - mapSizeY / 2, 0); - } - - GlStateManager.translate(mapCenterX, mapCenterY, 10); - - if (!useFb || NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur > 0.1 && - NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur < 100) { - GlStateManager.enableBlend(); - GL14.glBlendFuncSeparate( - GL11.GL_SRC_ALPHA, - GL11.GL_ONE_MINUS_SRC_ALPHA, - GL11.GL_ONE, - GL11.GL_ONE_MINUS_SRC_ALPHA - ); - } - Utils.drawRectNoBlend(-mapCenterX, -mapCenterY, mapCenterX, mapCenterY, backgroundColour); - - GlStateManager.rotate(-rotation + 180, 0, 0, 1); - - if (NotEnoughUpdates.INSTANCE.config.dungeonMap.dmCenterPlayer && playerPos != null) { - float x = playerPos.getRenderX(0); - float y = playerPos.getRenderY(0); - x -= minRoomX * (renderRoomSize + renderConnSize); - y -= minRoomY * (renderRoomSize + renderConnSize); - - GlStateManager.translate(-x, -y, 0); - } else { - GlStateManager.translate(-roomsSizeX / 2, -roomsSizeY / 2, 0); - } - - for (Map.Entry<RoomOffset, Room> entry : roomMap.entrySet()) { - RoomOffset roomOffset = entry.getKey(); - Room room = entry.getValue(); - - int x = (roomOffset.x - minRoomX) * (renderRoomSize + renderConnSize); - int y = (roomOffset.y - minRoomY) * (renderRoomSize + renderConnSize); - - GlStateManager.pushMatrix(); - GlStateManager.translate(x, y, 0); - - room.render(renderRoomSize, renderConnSize); - - GlStateManager.translate(-x, -y, 0); - GlStateManager.popMatrix(); - } - - GlStateManager.translate(-mapCenterX + roomsSizeX / 2f, -mapCenterY + roomsSizeY / 2f, 0); - - GlStateManager.translate(mapCenterX, mapCenterY, 0); - GlStateManager.rotate(rotation - 180, 0, 0, 1); - GlStateManager.translate(-mapCenterX, -mapCenterY, 0); - - GlStateManager.translate(mapCenterX, mapCenterY, 0); - - for (Map.Entry<RoomOffset, Room> entry : roomMap.entrySet()) { - RoomOffset roomOffset = entry.getKey(); - Room room = entry.getValue(); - - float x = - (roomOffset.x - minRoomX) * (renderRoomSize + renderConnSize) - roomsSizeX / 2f + renderRoomSize / 2f; - float y = - (roomOffset.y - minRoomY) * (renderRoomSize + renderConnSize) - roomsSizeY / 2f + renderRoomSize / 2f; - float x2 = (float) (-x * Math.cos(Math.toRadians(-rotation)) + y * Math.sin(Math.toRadians(-rotation))); - float y2 = (float) (-x * Math.sin(Math.toRadians(-rotation)) - y * Math.cos(Math.toRadians(-rotation))); - - GlStateManager.pushMatrix(); - GlStateManager.translate(x2, y2, 0); - - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - room.renderNoRotate(renderRoomSize, renderConnSize, rotation); - - GlStateManager.translate(-x2, -y2, 0); - GlStateManager.popMatrix(); - } - - GlStateManager.translate(-mapCenterX, -mapCenterY, 0); - - GlStateManager.translate(mapCenterX, mapCenterY, 0); - GlStateManager.rotate(-rotation + 180, 0, 0, 1); - GlStateManager.translate(-mapCenterX, -mapCenterY, 0); - - GlStateManager.translate(mapCenterX - roomsSizeX / 2f, mapCenterY - roomsSizeY / 2f, 0); - - Tessellator tessellator = Tessellator.getInstance(); - WorldRenderer worldrenderer = tessellator.getWorldRenderer(); - int k = 0; - - for (Map.Entry<String, MapPosition> entry : playerMarkerMapPositions.entrySet()) { - String name = entry.getKey(); - MapPosition pos = entry.getValue(); - float x = pos.getRenderX(0); - float y = pos.getRenderY(0); - float angle = pos.rotation; - - boolean doInterp = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPlayerInterp; - if (!isFloorOne && playerEntityMapPositions.containsKey(name)) { - MapPosition entityPos = playerEntityMapPositions.get(name); - angle = entityPos.rotation; - - float deltaX = entityPos.getRenderX(9) - pos.getRenderX(0); - float deltaY = entityPos.getRenderY(9) - pos.getRenderY(0); - - x += deltaX; - y += deltaY; - - doInterp = false; - } - - float minU = 3 / 4f; - float minV = 0; - - if (name.equals(Minecraft.getMinecraft().thePlayer.getName())) { - minU = 1 / 4f; - } - - float maxU = minU + 1 / 4f; - float maxV = minV + 1 / 4f; - - if (doInterp && playerMarkerMapPositionsLast.containsKey(name)) { - MapPosition last = playerMarkerMapPositionsLast.get(name); - float xLast = last.getRenderX(0); - float yLast = last.getRenderY(0); - - float distSq = (x - xLast) * (x - xLast) + (y - yLast) * (y - yLast); - if (distSq < renderRoomSize * renderRoomSize / 4f) { - float angleLast = last.rotation; - if (angle > 180 && angleLast < 180) angleLast += 360; - if (angleLast > 180 && angle < 180) angle += 360; - - float interpFactor = Math.round((System.currentTimeMillis() - lastDecorationsMillis) * 100f) / 100f / - (lastDecorationsMillis - lastLastDecorationsMillis); - interpFactor = Math.max(0, Math.min(1, interpFactor)); - - x = xLast + (x - xLast) * interpFactor; - y = yLast + (y - yLast) * interpFactor; - angle = angleLast + (angle - angleLast) * interpFactor; - angle %= 360; - } - } - - boolean blackBorder = false; - boolean headLayer = false; - int pixelWidth = 8; - int pixelHeight = 8; - if (renderRoomSize >= 24) { - pixelWidth = pixelHeight = 12; - } - GlStateManager.color(1, 1, 1, 1); - if ((!NotEnoughUpdates.INSTANCE.config.dungeons.showOwnHeadAsMarker || - playerMarkerMapPositions.size() <= 1 || minU != 1 / 4f) && - NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPlayerHeads >= 1 && - playerSkinMap.containsKey(entry.getKey())) { - Minecraft.getMinecraft().getTextureManager().bindTexture(playerSkinMap.get(entry.getKey())); - - minU = 8 / 64f; - minV = 8 / 64f; - maxU = 16 / 64f; - maxV = 16 / 64f; - - headLayer = true; - if (NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPlayerHeads >= 2) { - blackBorder = true; - } - } else { - Minecraft.getMinecraft().getTextureManager().bindTexture(mapIcons); - } - - x -= minRoomX * (renderRoomSize + renderConnSize); - y -= minRoomY * (renderRoomSize + renderConnSize); - - GlStateManager.pushMatrix(); - - GlStateManager.disableDepth(); - GlStateManager.enableBlend(); - GL14.glBlendFuncSeparate( - GL11.GL_SRC_ALPHA, - GL11.GL_ONE_MINUS_SRC_ALPHA, - GL11.GL_ONE, - GL11.GL_ONE_MINUS_SRC_ALPHA - ); - - GlStateManager.translate(x, y, -0.02F); - GlStateManager.scale(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmIconScale, - NotEnoughUpdates.INSTANCE.config.dungeonMap.dmIconScale, 1 - ); - GlStateManager.rotate(angle, 0.0F, 0.0F, 1.0F); - GlStateManager.translate(-0.5F, 0.5F, 0.0F); - - if (blackBorder) { - Gui.drawRect( - -pixelWidth / 2 - 1, - -pixelHeight / 2 - 1, - pixelWidth / 2 + 1, - pixelHeight / 2 + 1, - 0xff111111 - ); - GlStateManager.color(1, 1, 1, 1); - } - - worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); - worldrenderer.pos(-pixelWidth / 2f, pixelHeight / 2f, 30 + ((float) k * -0.005F)).tex(minU, minV).endVertex(); - worldrenderer.pos(pixelWidth / 2f, pixelHeight / 2f, 30 + ((float) k * -0.005F)).tex(maxU, minV).endVertex(); - worldrenderer.pos(pixelWidth / 2f, -pixelHeight / 2f, 30 + ((float) k * -0.005F)).tex(maxU, maxV).endVertex(); - worldrenderer - .pos(-pixelWidth / 2f, -pixelHeight / 2f, 30 + ((float) k * -0.005F)) - .tex(minU, maxV) - .endVertex(); - tessellator.draw(); - - if (headLayer) { - worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); - worldrenderer.pos(-pixelWidth / 2f, pixelHeight / 2f, 30 + ((float) k * -0.005F) + 0.001f).tex( - minU + 0.5f, - minV - ).endVertex(); - worldrenderer.pos(pixelWidth / 2f, pixelHeight / 2f, 30 + ((float) k * -0.005F) + 0.001f).tex( - maxU + 0.5f, - minV - ).endVertex(); - worldrenderer.pos(pixelWidth / 2f, -pixelHeight / 2f, 30 + ((float) k * -0.005F) + 0.001f).tex( - maxU + 0.5f, - maxV - ).endVertex(); - worldrenderer.pos(-pixelWidth / 2f, -pixelHeight / 2f, 30 + ((float) k * -0.005F) + 0.001f).tex( - minU + 0.5f, - maxV - ).endVertex(); - tessellator.draw(); - } - GlStateManager.popMatrix(); - k--; - } - - if (useFb) { - GlStateManager.enableBlend(); - GL14.glBlendFuncSeparate( - GL11.GL_SRC_ALPHA, - GL11.GL_ONE_MINUS_SRC_ALPHA, - GL11.GL_ONE, - GL11.GL_ONE_MINUS_SRC_ALPHA - ); - } else { - GL11.glDisable(GL11.GL_SCISSOR_TEST); - } - } - GlStateManager.popMatrix(); - - if (useFb) { - Framebuffer renderFromBuffer = mapFramebuffer1; - if (useShd) { - GlStateManager.pushMatrix(); - { - try { - upload(mapShader, mapSizeX, mapSizeY, scaleFactor, getBorderRadius()); - mapShader.setProjectionMatrix(projectionMatrix); - mapShader.loadShader(0); - renderFromBuffer = mapFramebuffer2; - } catch (Exception ignored) { - } - } - GlStateManager.popMatrix(); - } - - Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); - - Utils.pushGuiScale(2); - - GlStateManager.translate(centerX, centerY, 100); - - renderFromBuffer.bindFramebufferTexture(); - Utils.drawTexturedRect(-mapSizeX / 2, -mapSizeY / 2, mapSizeX, mapSizeY, - 0, 1, 1, 0, GL11.GL_NEAREST - ); - GlStateManager.bindTexture(0); - - GlStateManager.translate(-centerX, -centerY, -100); - - Utils.pushGuiScale(-1); - } - - GlStateManager.translate(centerX, centerY, 100); - - if (NotEnoughUpdates.INSTANCE.config.dungeonMap.dmChromaBorder) { - int colour = SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderColour); - - Gui.drawRect(-mapCenterX - 2, -mapCenterY - 2, -mapCenterX, -mapCenterY, - colour - ); //topleft - Gui.drawRect(-mapCenterX - 2, mapCenterY + 2, -mapCenterX, mapCenterY, - SpecialColour.rotateHue(colour, -180) - ); //bottomleft - Gui.drawRect(mapCenterX, -mapCenterY - 2, mapCenterX + 2, mapCenterY, - SpecialColour.rotateHue(colour, -180) - ); //topright - Gui.drawRect(mapCenterX, mapCenterY, mapCenterX + 2, mapCenterY + 2, - colour - ); //bottomright - - for (int i = 0; i < 20; i++) { - int start1 = SpecialColour.rotateHue(colour, -9 * i); - int start2 = SpecialColour.rotateHue(colour, -9 * i - 9); - int end1 = SpecialColour.rotateHue(colour, -180 - 9 * i); - int end2 = SpecialColour.rotateHue(colour, -180 - 9 * i - 9); - - Utils.drawGradientRect(-mapCenterX - 2, -mapCenterY + (int) (mapSizeY * (i / 20f)), -mapCenterX, - -mapCenterY + (int) (mapSizeY * ((i + 1) / 20f)), start1, start2 - ); //left - Utils.drawGradientRect(mapCenterX, -mapCenterY + (int) (mapSizeX * (i / 20f)), mapCenterX + 2, - -mapCenterY + (int) (mapSizeX * ((i + 1) / 20f)), - end1, end2 - ); //right - Utils.drawGradientRectHorz(-mapCenterX + (int) (mapSizeX * (i / 20f)), -mapCenterY - 2, - -mapCenterX + (int) (mapSizeX * ((i + 1) / 20f)), -mapCenterY, start1, start2 - ); //top - Utils.drawGradientRectHorz(-mapCenterX + (int) (mapSizeX * (i / 20f)), - mapCenterY, -mapCenterX + (int) (mapSizeX * ((i + 1) / 20f)), mapCenterY + 2, - end1, end2 - ); //bottom - } - - } else { - Gui.drawRect(-mapCenterX - 2, -mapCenterY, -mapCenterX, mapCenterY, - SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderColour) - ); //left - Gui.drawRect(mapCenterX, -mapCenterY, mapCenterX + 2, mapCenterY, - SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderColour) - ); //right - Gui.drawRect(-mapCenterX - 2, -mapCenterY - 2, mapCenterX + 2, -mapCenterY, - SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderColour) - ); //top - Gui.drawRect(-mapCenterX - 2, mapCenterY, mapCenterX + 2, mapCenterY + 2, - SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderColour) - ); //bottom - } - - String sizeId = borderSizeOption == 0 ? "small" : borderSizeOption == 2 ? "large" : "medium"; - - ResourceLocation rl = new ResourceLocation("notenoughupdates:dungeon_map/borders/" + sizeId + "/" + - NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderStyle + ".png"); - if (Minecraft.getMinecraft().getTextureManager().getTexture(rl) != TextureUtil.missingTexture) { - Minecraft.getMinecraft().getTextureManager().bindTexture(rl); - GlStateManager.color(1, 1, 1, 1); - - int size = borderSizeOption == 0 ? 165 : borderSizeOption == 1 ? 220 : borderSizeOption == 2 ? 300 : 440; - Utils.drawTexturedRect(-size / 2, -size / 2, size, size, GL11.GL_NEAREST); - } - - GlStateManager.translate(-centerX, -centerY, -100); - } catch (Exception e) { - e.printStackTrace(); - Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); - Minecraft.getMinecraft().entityRenderer.setupOverlayRendering(); - } - - Utils.pushGuiScale(-1); - - GlStateManager.enableBlend(); - GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); - GlStateManager.enableDepth(); - GlStateManager.disableLighting(); - } - - public void updateRoomConnections(RoomOffset roomOffset) { - if (roomMap.containsKey(roomOffset)) { - Room room = roomMap.get(roomOffset); - - int otherPixelFilled = 0; - int otherPixelColour = 0; - for (int xOff = 0; xOff < roomSize; xOff++) { - for (int yOff = 0; yOff < roomSize; yOff++) { - int x = startRoomX + roomOffset.x * (roomSize + connectorSize) + xOff; - int y = startRoomY + roomOffset.y * (roomSize + connectorSize) + yOff; - - if (x > 0 && y > 0 && x < colourMap.length && y < colourMap[x].length) { - Color c = colourMap[x][y]; - if (!c.equals(room.colour)) { - if (otherPixelColour == c.getRGB()) { - otherPixelFilled++; - } else { - otherPixelFilled--; - if (otherPixelFilled <= 0) { - otherPixelFilled = 1; - otherPixelColour = c.getRGB(); - } - } - } - } - } - } - - room.tickColour = 0; - if ((float) otherPixelFilled / roomSize / connectorSize > 0.05) { - room.tickColour = otherPixelColour; - } - - for (int k = 0; k < 4; k++) { - Color colour = null; - int totalFilled = 0; - - for (int i = 0; i < roomSize; i++) { - for (int j = 1; j <= connectorSize; j++) { - int x = startRoomX + roomOffset.x * (roomSize + connectorSize); - int y = startRoomY + roomOffset.y * (roomSize + connectorSize); - - if (k == 0) { - x += i; - y -= j; - } else if (k == 1) { - x += roomSize + j - 1; - y += i; - } else if (k == 2) { - x += i; - y += roomSize + j - 1; - } else { - x -= j; - y += i; - } - - if (x > 0 && y > 0 && x < colourMap.length && y < colourMap[x].length) { - Color pixel = colourMap[x][y]; - if (pixel.getAlpha() > 40) { - if (colour == null) { - colour = pixel; - totalFilled = 1; - } else { - if (colour.equals(pixel)) { - totalFilled++; - } else { - totalFilled--; - if (totalFilled <= 0) { - colour = pixel; - totalFilled = 1; - } - } - } - } - } - } - } - float proportionFilled = (float) totalFilled / roomSize / connectorSize; - - RoomConnectionType type = RoomConnectionType.WALL; - if (proportionFilled > 0.8) { - type = RoomConnectionType.ROOM_DIVIDER; - } else if (proportionFilled > 0.1) { - type = RoomConnectionType.CORRIDOR; - } - if (k == 0) { - room.up = new RoomConnection(type, colour); - } else if (k == 1) { - room.right = new RoomConnection(type, colour); - } else if (k == 2) { - room.down = new RoomConnection(type, colour); - } else { - room.left = new RoomConnection(type, colour); - } - } - - int x = startRoomX + roomOffset.x * (roomSize + connectorSize) + roomSize + connectorSize / 2; - int y = startRoomY + roomOffset.y * (roomSize + connectorSize) + roomSize + connectorSize / 2; - - room.fillCorner = false; - if (x > 0 && y > 0 && x < colourMap.length && y < colourMap[x].length) { - Color pixel = colourMap[x][y]; - if (pixel.equals(room.colour)) { - room.fillCorner = true; - } - } - } - } - - public void loadNeighbors(RoomOffset room) { - if (!roomMap.containsKey(room)) { - roomMap.put(room, new Room()); - } - for (RoomOffset neighbor : room.getNeighbors()) { - if (!roomMap.containsKey(neighbor)) { - int x = startRoomX + neighbor.x * (roomSize + connectorSize); - int y = startRoomY + neighbor.y * (roomSize + connectorSize); - - if (x >= 0 && y >= 0 && x + roomSize < colourMap.length && y + roomSize < colourMap[x].length) { - if (colourMap[x][y].getAlpha() > 100) { - roomMap.put(neighbor, new Room()); - loadNeighbors(neighbor); - } - } - } - } - } - - public void updateRoomColours() { - for (Map.Entry<RoomOffset, Room> entry : roomMap.entrySet()) { - int x = startRoomX + entry.getKey().x * (roomSize + connectorSize); - int y = startRoomY + entry.getKey().y * (roomSize + connectorSize); - - try { - entry.getValue().colour = colourMap[x][y]; - } catch (Exception ignored) { - } - } - } - - private class MapPosition { - public float roomOffsetX; - public float connOffsetX; - - public float roomOffsetY; - public float connOffsetY; - - public float rotation; - - public MapPosition(float roomOffsetX, float connOffsetX, float roomOffsetY, float connOffsetY) { - this.roomOffsetX = roomOffsetX; - this.connOffsetX = connOffsetX; - this.roomOffsetY = roomOffsetY; - this.connOffsetY = connOffsetY; - } - - public float getRenderX(int blockOffset) { - return (roomOffsetX + blockOffset) * getRenderRoomSize() + connOffsetX * getRenderConnSize(); - } - - public float getRenderY(int blockOffset) { - return (roomOffsetY + blockOffset) * getRenderRoomSize() + connOffsetY * getRenderConnSize(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - MapPosition that = (MapPosition) o; - return Float.compare(that.roomOffsetX, roomOffsetX) == 0 && - Float.compare(that.connOffsetX, connOffsetX) == 0 && - Float.compare(that.roomOffsetY, roomOffsetY) == 0 && - Float.compare(that.connOffsetY, connOffsetY) == 0 && - Float.compare(that.rotation, rotation) == 0; - } - - @Override - public int hashCode() { - return Objects.hash(roomOffsetX, connOffsetX, roomOffsetY, connOffsetY, rotation); - } - } - - private boolean isFloorOne = false; - private boolean failMap = false; - private long lastClearCache = 0; - - public void renderMap( - int centerX, int centerY, Color[][] colourMap, Map<String, Vec4b> mapDecorations, - int roomSizeBlocks, Set<String> actualPlayers, boolean usePlayerPositions, float partialTicks - ) { - if (!NotEnoughUpdates.INSTANCE.config.dungeonMap.dmEnable) return; - if (colourMap == null) return; - if (colourMap.length != 128) return; - if (colourMap[0].length != 128) return; - this.colourMap = colourMap; - - boolean searchForPlayers = false; - if (System.currentTimeMillis() - lastClearCache > 1000) { - roomMap.clear(); - searchForPlayers = true; - startRoomX = -1; - startRoomY = -1; - connectorSize = -1; - roomSize = -1; - borderRadiusCache.clear(); - failMap = false; - - lastClearCache = System.currentTimeMillis(); - - isFloorOne = false; - Scoreboard scoreboard = Minecraft.getMinecraft().thePlayer.getWorldScoreboard(); - - ScoreObjective sidebarObjective = scoreboard.getObjectiveInDisplaySlot(1); - - List<Score> scores = new ArrayList<>(scoreboard.getSortedScores(sidebarObjective)); - - for (int i = scores.size() - 1; i >= 0; i--) { - Score score = scores.get(i); - ScorePlayerTeam scoreplayerteam1 = scoreboard.getPlayersTeam(score.getPlayerName()); - String line = ScorePlayerTeam.formatPlayerName(scoreplayerteam1, score.getPlayerName()); - line = Utils.cleanColour(line); - - if (line.contains("(F1)") || line.contains("(E)") || line.contains("(M1)")) { - isFloorOne = true; - break; - } - } - } - - if (failMap) { - return; - } - - int alphaPixels = 0; - for (int x = 0; x < 128; x++) { - for (int y = 0; y < 128; y++) { - Color c = colourMap[x][y]; - if (c == null) { - return; - } else if (c.getAlpha() < 50) { - alphaPixels++; - } - } - } - if (alphaPixels < 128 * 128 / 10) { - failMap = true; - return; - } - - if (startRoomX < 0 || startRoomY < 0 || roomSize <= 0) { - for (int x = 0; x < colourMap.length; x++) { - for (int y = 0; y < colourMap[x].length; y++) { - Color c = colourMap[x][y]; - if (c.getAlpha() > 80) { - if (startRoomX < 0 && startRoomY < 0 && c.getRed() == 0 && c.getGreen() == 124 && c.getBlue() == 0) { - roomSize = 0; - out: - for (int xd = 0; xd <= 20; xd++) { - for (int yd = 0; yd <= 20; yd++) { - if (x + xd >= colourMap.length || y + yd >= colourMap[x + xd].length) continue; - Color c2 = colourMap[x + xd][y + yd]; - - if (c2.getGreen() != 124 || c2.getAlpha() <= 80) { - if (xd < 10 && yd < 10) { - break out; - } - } else { - roomSize = Math.max(roomSize, Math.min(xd + 1, yd + 1)); - } - if (xd == 20 && yd == 20) { - if (roomSize == 0) roomSize = 20; - startRoomX = x; - startRoomY = y; - } - } - } - } - } - } - } - } - - if (startRoomX < 0 || startRoomY < 0) { - failMap = true; - return; - } - - if (connectorSize <= 0) { - for (int i = 0; i < roomSize; i++) { - for (int k = 0; k < 4; k++) { - for (int j = 1; j < 8; j++) { - int x; - int y; - - if (k == 0) { - x = startRoomX + i; - y = startRoomY - j; - } else if (k == 1) { - x = startRoomX + roomSize + j - 1; - y = startRoomY + i; - } else if (k == 2) { - x = startRoomX + i; - y = startRoomY + roomSize + j - 1; - } else { - x = startRoomX - j; - y = startRoomY + i; - } - - if (x > 0 && y > 0 && x < colourMap.length && y < colourMap[x].length) { - if (colourMap[x][y].getAlpha() > 80) { - if (j == 1) { - break; - } - connectorSize = Math.min(connectorSize, j - 1); - } - } - } - } - } - - if (connectorSize <= 0) { - connectorSize = 4; - } - } - - actualPlayers.add(Minecraft.getMinecraft().thePlayer.getName()); - if (searchForPlayers) { - for (EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) { - if (player instanceof AbstractClientPlayer && actualPlayers.contains(player.getName())) { - AbstractClientPlayer aplayer = (AbstractClientPlayer) player; - ResourceLocation skin = aplayer.getLocationSkin(); - if (skin != DefaultPlayerSkin.getDefaultSkin(aplayer.getUniqueID())) { - playerSkinMap.put(player.getName(), skin); - playerIdMap.put(player.getName(), player.getEntityId()); - } - } - } - } - - playerEntityMapPositions.clear(); - if (usePlayerPositions) { - for (String playerName : actualPlayers) { - if (playerIdMap.containsKey(playerName)) { - Entity entity = Minecraft.getMinecraft().theWorld.getEntityByID(playerIdMap.get(playerName)); - if (entity instanceof EntityPlayer) { - EntityPlayer player = (EntityPlayer) entity; - - float roomX = (float) player.posX / (roomSizeBlocks + 1); - float roomY = (float) player.posZ / (roomSizeBlocks + 1); - - float playerRoomOffsetX = (float) Math.floor(roomX); - float playerConnOffsetX = (float) Math.floor(roomX); - float playerRoomOffsetY = (float) Math.floor(roomY); - float playerConnOffsetY = (float) Math.floor(roomY); - - float roomXInBlocks = (float) player.posX % (roomSizeBlocks + 1); - if (roomXInBlocks < 2) { //0,1 - playerConnOffsetX -= 2 / 5f - roomXInBlocks / 5f; - } else if (roomXInBlocks > roomSizeBlocks - 2) { //31,30,29 - playerRoomOffsetX++; - playerConnOffsetX += (roomXInBlocks - (roomSizeBlocks - 2)) / 5f; - } else { - playerRoomOffsetX += (roomXInBlocks - 2) / (roomSizeBlocks - 4); - } - - float roomYInBlocks = (float) player.posZ % (roomSizeBlocks + 1); - if (roomYInBlocks < 2) { //0,1 - playerConnOffsetY -= 2 / 5f - roomYInBlocks / 5f; - } else if (roomYInBlocks > roomSizeBlocks - 2) { //31,30,29 - playerRoomOffsetY++; - playerConnOffsetY += (roomYInBlocks - (roomSizeBlocks - 2)) / 5f; - } else { - playerRoomOffsetY += (roomYInBlocks - 2) / (roomSizeBlocks - 4); - } - - playerRoomOffsetX -= startRoomX / (roomSize + connectorSize); - playerRoomOffsetY -= startRoomY / (roomSize + connectorSize); - playerConnOffsetX -= startRoomX / (roomSize + connectorSize); - playerConnOffsetY -= startRoomY / (roomSize + connectorSize); - - MapPosition pos = new MapPosition( - playerRoomOffsetX, - playerConnOffsetX, - playerRoomOffsetY, - playerConnOffsetY - ); - pos.rotation = - (player.prevRotationYawHead + (player.rotationYawHead - player.prevRotationYawHead) * partialTicks) % 360; - if (pos.rotation < 0) pos.rotation += 360; - playerEntityMapPositions.put(player.getName(), pos); - } - } - } - } - - loadNeighbors(new RoomOffset(0, 0)); - updateRoomColours(); - for (RoomOffset offset : roomMap.keySet()) { - updateRoomConnections(offset); - } - - if (roomMap.isEmpty()) { - failMap = true; - return; - } - - if (mapDecorations != null && mapDecorations.size() > 0) { - List<MapPosition> positions = new ArrayList<>(); - int decorations = 0; - for (Vec4b vec4b : mapDecorations.values()) { - byte id = vec4b.func_176110_a(); - if (id != 1 && id != 3) continue; - - float x = (float) vec4b.func_176112_b() / 2.0F + 64.0F; - float y = (float) vec4b.func_176113_c() / 2.0F + 64.0F; - - if (x < 0 || y < 0 || x > 128 || y > 128) { - continue; - } - - float deltaX = x - startRoomX; - float deltaY = y - startRoomY; - - float roomsOffsetX = (int) Math.floor(deltaX / (roomSize + connectorSize)); - float connOffsetX = (int) Math.floor(deltaX / (roomSize + connectorSize)); - float xRemainder = deltaX % (roomSize + connectorSize); - if (Math.abs(xRemainder) > roomSize) { - roomsOffsetX += Math.copySign(1, xRemainder); - connOffsetX += Math.copySign(1, xRemainder) * (Math.abs(xRemainder) - roomSize) / connectorSize; - } else { - roomsOffsetX += xRemainder / roomSize; - } - if (deltaX < 0 && xRemainder != 0) { - roomsOffsetX++; - connOffsetX++; - } - float roomsOffsetY = (int) Math.floor(deltaY / (roomSize + connectorSize)); - float connOffsetY = (int) Math.floor(deltaY / (roomSize + connectorSize)); - float yRemainder = deltaY % (roomSize + connectorSize); - if (Math.abs(yRemainder) > roomSize) { - roomsOffsetY += Math.copySign(1, yRemainder); - connOffsetY += Math.copySign(1, yRemainder) * (Math.abs(yRemainder) - roomSize) / connectorSize; - } else { - roomsOffsetY += yRemainder / roomSize; - } - if (deltaY < 0 && yRemainder != 0) { - roomsOffsetY++; - connOffsetY++; - } - - float angle = (float) (vec4b.func_176111_d() * 360) / 16.0F; - - MapPosition pos = new MapPosition(roomsOffsetX, connOffsetX, roomsOffsetY, connOffsetY); - pos.rotation = angle % 360; - if (pos.rotation < 0) pos.rotation += 360; - - if (decorations++ <= 6) { - positions.add(pos); - } - rawPlayerMarkerMapPositions.add(pos); - } - - boolean different = playerMarkerMapPositions.size() != positions.size(); - - if (!different) { - for (MapPosition pos : playerMarkerMapPositions.values()) { - if (!positions.contains(pos)) { - different = true; - break; - } - } - } - - if (different && positions.size() > 0) { - lastLastDecorationsMillis = lastDecorationsMillis; - lastDecorationsMillis = System.currentTimeMillis(); - - playerMarkerMapPositionsLast.clear(); - for (Map.Entry<String, MapPosition> entry : playerMarkerMapPositions.entrySet()) { - playerMarkerMapPositionsLast.put(entry.getKey(), entry.getValue()); - } - playerMarkerMapPositions.clear(); - - Set<String> foundPlayers = new HashSet<>(); - for (Map.Entry<String, MapPosition> entry : playerEntityMapPositions.entrySet()) { - playerMarkerMapPositions.put(entry.getKey(), entry.getValue()); - playerMarkerMapPositionsLast.put(entry.getKey(), entry.getValue()); - foundPlayers.add(entry.getKey()); - } - - HashMap<String, HashMap<Integer, Float>> distanceMap = new HashMap<>(); - for (Map.Entry<String, MapPosition> entry : playerMarkerMapPositionsLast.entrySet()) { - HashMap<Integer, Float> deltaDists = new HashMap<>(); - for (int i = 0; i < positions.size(); i++) { - float dx = entry.getValue().getRenderX(0) - positions.get(i).getRenderX(0); - float dy = entry.getValue().getRenderY(0) - positions.get(i).getRenderY(0); - deltaDists.put(i, dx * dx + dy * dy); - } - distanceMap.put(entry.getKey(), deltaDists); - } - - List<String> playerList = new ArrayList<>(playerMarkerMapPositionsLast.keySet()); - List<List<String>> playerPermutations = permutations(playerList); - - List<Integer> finalUsedIndexes = new ArrayList<>(); - if (playerPermutations.size() > 0) { - HashMap<String, Integer> smallestPermutation = null; - float smallestTotalDistance = 0; - - for (List<String> permutation : playerPermutations) { - HashMap<String, Integer> usedIndexes = new HashMap<>(); - - float totalDistance = 0; - for (String player : permutation) { - int smallestIndex = -1; - float smallestDist = 0; - for (Map.Entry<Integer, Float> entry : distanceMap.get(player).entrySet()) { - if (!usedIndexes.containsValue(entry.getKey())) { - if (smallestIndex == -1 || entry.getValue() < smallestDist) { - smallestIndex = entry.getKey(); - smallestDist = entry.getValue(); - } - } - } - if (smallestIndex != -1) { - usedIndexes.put(player, smallestIndex); - totalDistance += smallestDist; - } - } - - if (smallestPermutation == null || totalDistance < smallestTotalDistance) { - smallestPermutation = usedIndexes; - smallestTotalDistance = totalDistance; - } - } - - //System.out.println("--- PERM START ---"); - for (Map.Entry<String, Integer> entry : smallestPermutation.entrySet()) { - //System.out.println(entry.getKey() + ":" + entry.getValue() + " : Total dist: " + smallestTotalDistance); - finalUsedIndexes.add(entry.getValue()); - playerMarkerMapPositions.put(entry.getKey(), positions.get(entry.getValue())); - } - } - - List<Integer> nonUsedIndexes = new ArrayList<>(); - for (int i = 0; i < positions.size(); i++) { - if (!finalUsedIndexes.contains(i)) { - nonUsedIndexes.add(i); - } - } - - for (String missingPlayer : actualPlayers) { - if (!playerList.contains(missingPlayer)) { - if (nonUsedIndexes.isEmpty()) break; - playerMarkerMapPositions.put(missingPlayer, positions.get(nonUsedIndexes.get(0))); - nonUsedIndexes.remove(0); - } - } - } - } else if (mapDecorations == null) { - playerMarkerMapPositions.clear(); - playerMarkerMapPositionsLast.clear(); - - for (Map.Entry<String, MapPosition> entry : playerEntityMapPositions.entrySet()) { - playerMarkerMapPositions.put(entry.getKey(), entry.getValue()); - } - } - - if (!roomMap.isEmpty() && startRoomX >= 0 && startRoomY >= 0) { - render(centerX, centerY); - } - - this.colourMap = colourMap; - } - - @SubscribeEvent - public void onWorldChange(WorldEvent.Load event) { - colourMap = null; - } - - @SubscribeEvent - public void onRenderOverlay(RenderGameOverlayEvent.Post event) { - if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return; - if (event.type == RenderGameOverlayEvent.ElementType.ALL) { - if (!NotEnoughUpdates.INSTANCE.config.dungeonMap.dmEnable) return; - - if (Minecraft.getMinecraft().gameSettings.showDebugInfo || - (Minecraft.getMinecraft().gameSettings.keyBindPlayerList.isKeyDown() && - (!Minecraft.getMinecraft().isIntegratedServerRunning() || - Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap().size() > 1))) { - return; - } - - ItemStack stack = Minecraft.getMinecraft().thePlayer.inventory.mainInventory[8]; - boolean holdingBow = stack != null && stack.getItem() == Items.arrow && colourMap != null; - if (holdingBow || (stack != null && stack.getItem() instanceof ItemMap)) { - Map<String, Vec4b> decorations = null; - - Color[][] colourMap = new Color[128][128]; - if (holdingBow) { - for (int x = 0; x < 128; x++) { - for (int y = 0; y < 128; y++) { - if (this.colourMap[x][y] != null) { - colourMap[x][y] = this.colourMap[x][y]; - } else { - colourMap[x][y] = new Color(0, true); - } - } - } - } else { - ItemMap map = (ItemMap) stack.getItem(); - MapData mapData = map.getMapData(stack, Minecraft.getMinecraft().theWorld); - - if (mapData == null) return; - - decorations = mapData.mapDecorations; - - for (int i = 0; i < 16384; ++i) { - int x = i % 128; - int y = i / 128; - - int j = mapData.colors[i] & 255; - - Color c; - if (j / 4 == 0) { - c = new Color((i + i / 128 & 1) * 8 + 16 << 24, true); - } else { - c = new Color(MapColor.mapColorArray[j / 4].getMapColor(j & 3), true); - } - - colourMap[x][y] = c; - } - } - - int roomSizeBlocks = 31; - /*List<Integer> dists = new ArrayList<>(); - int currentBlockCount = 0; - for(int i=0; i<300; i++) { - IBlockState state = Minecraft.getMinecraft().theWorld.getBlockState(new BlockPos(0, 99, i)); - if(state == null || state.getBlock() == Blocks.air) { - if(currentBlockCount > 0) dists.add(currentBlockCount); - currentBlockCount = 0; - } else { - currentBlockCount++; - } - } - currentBlockCount = 0; - for(int i=0; i<300; i++) { - IBlockState state = Minecraft.getMinecraft().theWorld.getBlockState(new BlockPos(i, 99, 0)); - if(state == null || state.getBlock() == Blocks.air) { - if(currentBlockCount > 0) dists.add(currentBlockCount); - currentBlockCount = 0; - } else { - currentBlockCount++; - } - } - int count = 0; - int mostCommonDist = -1; - for(int dist : dists) { - if(dist == mostCommonDist) { - count++; - } else { - if(--count < 0) { - count = 1; - mostCommonDist = dist; - } - } - } - if(mostCommonDist > 31) roomSizeBlocks = mostCommonDist;*/ - - Set<String> actualPlayers = new HashSet<>(); - /*for(EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) { - if(player.getUniqueID().toString().charAt(14) == '4') { - actualPlayers.add(player.getName()); - System.out.println(player.getName()); - - } - }*/ - int players = 0; - for (ScorePlayerTeam team : Minecraft.getMinecraft().thePlayer.getWorldScoreboard().getTeams()) { - if (team.getTeamName().startsWith("a") && team.getMembershipCollection().size() == 1) { - String playerName = Iterables.get(team.getMembershipCollection(), 0); - boolean foundPlayer = false; - for (EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) { - if (player.getName().equals(playerName) && - (player == Minecraft.getMinecraft().thePlayer || !player.isPlayerSleeping())) { - actualPlayers.add(playerName); - foundPlayer = true; - break; - } - } - if (!foundPlayer) actualPlayers.add(playerName); - if (++players >= 6) break; - } - } - - Position pos = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPosition; - - int size = 80 + Math.round(40 * NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderSize); - ScaledResolution scaledResolution = Utils.pushGuiScale(2); - renderMap( - pos.getAbsX(scaledResolution, size / 2) + size / 2, - pos.getAbsY(scaledResolution, size / 2) + size / 2, - colourMap, - decorations, - roomSizeBlocks, - actualPlayers, - true, - event.partialTicks - ); - Utils.pushGuiScale(-1); - } else if (stack != null && Item.getIdFromItem(stack.getItem()) == 399) { - //This should clear the map if you're in the dungeon boss room - //so when you're holding a bow it doesnt show the map anymore - this.colourMap = null; - } - } - } - - public List<List<String>> permutations(List<String> values) { - List<List<String>> permutations = new ArrayList<>(); - - if (values.size() == 1) { - permutations.add(values); - return permutations; - } - - for (String first : values) { - List<String> newList = new ArrayList<>(); - for (String val : values) { - if (!val.equals(first)) { - newList.add(val); - } - } - - for (List<String> list2 : permutations(newList)) { - List<String> perm = new ArrayList<>(); - perm.add(first); - perm.addAll(list2); - permutations.add(perm); - } - } - - return permutations; - } - - Shader blurShaderHorz = null; - Framebuffer blurOutputHorz = null; - Shader blurShaderVert = null; - Framebuffer blurOutputVert = null; - - /** - * Creates a projection matrix that projects from our coordinate space [0->width; 0->height] to OpenGL coordinate - * space [-1 -> 1; 1 -> -1] (Note: flipped y-axis). - * <p> - * This is so that we can render to and from the framebuffer in a way that is familiar to us, instead of needing to - * apply scales and translations manually. - */ - private Matrix4f createProjectionMatrix(int width, int height) { - Matrix4f projMatrix = new Matrix4f(); - projMatrix.setIdentity(); - projMatrix.m00 = 2.0F / (float) width; - projMatrix.m11 = 2.0F / (float) (-height); - projMatrix.m22 = -0.0020001999F; - projMatrix.m33 = 1.0F; - projMatrix.m03 = -1.0F; - projMatrix.m13 = 1.0F; - projMatrix.m23 = -1.0001999F; - return projMatrix; - } -} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java index 47e85023..98a31545 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java @@ -26,6 +26,9 @@ import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption import io.github.moulberry.notenoughupdates.core.config.gui.GuiPositionEditor; import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; import io.github.moulberry.notenoughupdates.core.util.render.TextRenderUtils; +import io.github.moulberry.notenoughupdates.dungeons.map.DungeonMap; +import io.github.moulberry.notenoughupdates.dungeons.map.DungeonMapPlayers; +import io.github.moulberry.notenoughupdates.dungeons.map.DungeonMapStaticParser; import io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField; import io.github.moulberry.notenoughupdates.options.seperateSections.DungeonMapConfig; import io.github.moulberry.notenoughupdates.util.SpecialColour; @@ -60,813 +63,739 @@ import static io.github.moulberry.notenoughupdates.util.GuiTextures.slider_off_l import static io.github.moulberry.notenoughupdates.util.GuiTextures.slider_on_large; public class GuiDungeonMapEditor extends GuiScreen { - public static final ResourceLocation BACKGROUND = new ResourceLocation( - "notenoughupdates:dungeon_map/editor/background.png"); - public static final ResourceLocation BUTTON = new ResourceLocation("notenoughupdates:dungeon_map/editor/button.png"); - private static final DungeonMap demoMap = new DungeonMap(); - - private int sizeX; - private int sizeY; - private int guiLeft; - private int guiTop; - - private final List<Button> buttons = new ArrayList<>(); - - private final GuiElementTextField blurField = new GuiElementTextField( - "", - GuiElementTextField.NUM_ONLY | GuiElementTextField.NO_SPACE - ); - private GuiElementColour activeColourEditor = null; - - private Field clickedSlider; - - class Button { - private final int id; - private final int x; - private final int y; - private String text; - private Color colour = new Color(-1, true); - private final Field option; - private String displayName; - private String desc; - - public Button(int id, int x, int y, String text) { - this(id, x, y, text, null); - } - - public Button(int id, int x, int y, String text, Field option) { - this.id = id; - this.x = x; - this.y = y; - this.text = text; - this.option = option; - - if (option != null) { - ConfigOption optionAnnotation = option.getAnnotation(ConfigOption.class); - displayName = optionAnnotation.name(); - desc = optionAnnotation.desc(); - } - } - - public List<String> getTooltip() { - if (option == null) { - return null; - } - - List<String> tooltip = new ArrayList<>(); - tooltip.add(EnumChatFormatting.YELLOW + displayName); - for (String line : desc.split("\n")) { - tooltip.add(EnumChatFormatting.AQUA + line); - } - return tooltip; - } - - public void render() { - if (text == null) return; - - Minecraft.getMinecraft().getTextureManager().bindTexture(BUTTON); - if (isButtonPressed(id)) { - GlStateManager.color(colour.getRed() * 0.85f / 255f, colour.getGreen() * 0.85f / 255f, - colour.getBlue() * 0.85f / 255f, 1 - ); - Utils.drawTexturedRect(guiLeft + x, guiTop + y, 48, 16, 1, 0, 1, 0, GL11.GL_NEAREST); - } else { - GlStateManager.color(colour.getRed() / 255f, colour.getGreen() / 255f, colour.getBlue() / 255f, 1); - Utils.drawTexturedRect(guiLeft + x, guiTop + y, 48, 16, GL11.GL_NEAREST); - } - - if (text.length() > 0) { - Utils.drawStringCenteredScaledMaxWidth( - text, - Minecraft.getMinecraft().fontRendererObj, - guiLeft + x + 24, - guiTop + y + 8, - false, - 39, - 0xFF000000 - ); - } - } - - } - - public GuiDungeonMapEditor() { - DungeonMapConfig options = NotEnoughUpdates.INSTANCE.config.dungeonMap; - //Map Border Size - //buttons.add(new Button(0, 6, 37, "Small", options.dmBorderSize)); - //buttons.add(new Button(1, 52, 37, "Medium", options.dmBorderSize)); - //buttons.add(new Button(2, 98, 37, "Large", options.dmBorderSize)); - - //Map Rooms Size - //buttons.add(new Button(3, 6, 67+19, "Small", options.dmRoomSize)); - //buttons.add(new Button(4, 52, 67+19, "Medium", options.dmRoomSize)); - //buttons.add(new Button(5, 98, 67+19, "Large", options.dmRoomSize)); - - //Map Border Styles - buttons.add(new Button(6, 6, 97 + 30, "None")); - buttons.add(new Button(7, 52, 97 + 30, "Custom")); - buttons.add(new Button(8, 98, 97 + 30, "Stone")); - buttons.add(new Button(9, 6, 116 + 30, "Wood")); - buttons.add(new Button(10, 52, 116 + 30, "Rustic(S)")); - buttons.add(new Button(11, 98, 116 + 30, "Rustic(C)")); - buttons.add(new Button(12, 6, 135 + 30, "Fade")); - buttons.add(new Button(13, 52, 135 + 30, "Ribbons")); - buttons.add(new Button(14, 98, 135 + 30, "Paper")); - buttons.add(new Button(15, 6, 154 + 30, "Crimson")); - buttons.add(new Button(16, 52, 154 + 30, "Ornate")); - buttons.add(new Button(17, 98, 154 + 30, "Dragon")); - - try { - //Dungeon Map - buttons.add(new Button(18, 20 + 139, 36, "Yes/No", DungeonMapConfig.class.getDeclaredField("dmEnable"))); - //Center - buttons.add(new Button( - 19, - 84 + 139, - 36, - "Player/Map", - DungeonMapConfig.class.getDeclaredField("dmCenterPlayer") - )); - //Rotate - buttons.add(new Button( - 20, - 20 + 139, - 65, - "Player/No Rotate", - DungeonMapConfig.class.getDeclaredField("dmRotatePlayer") - )); - //Icon Style - buttons.add(new Button( - 21, - 84 + 139, - 65, - "Default/Heads", - DungeonMapConfig.class.getDeclaredField("dmPlayerHeads") - )); - //Check Orient - buttons.add(new Button( - 22, - 20 + 139, - 94, - "Normal/Reorient", - DungeonMapConfig.class.getDeclaredField("dmOrientCheck") - )); - //Check Center - buttons.add(new Button(23, 84 + 139, 94, "Yes/No", DungeonMapConfig.class.getDeclaredField("dmCenterCheck"))); - //Interpolation - buttons.add(new Button(24, 20 + 139, 123, "Yes/No", DungeonMapConfig.class.getDeclaredField("dmPlayerInterp"))); - //Compatibility - buttons.add(new Button( - 25, - 84 + 139, - 123, - "Normal/No SHD/No FB/SHD", - DungeonMapConfig.class.getDeclaredField("dmCompat") - )); - - //Background - buttons.add(new Button(26, 20 + 139, 152, "", DungeonMapConfig.class.getDeclaredField("dmBackgroundColour"))); - //Border - buttons.add(new Button(27, 84 + 139, 152, "", DungeonMapConfig.class.getDeclaredField("dmBorderColour"))); - - //Chroma Mode - buttons.add(new Button( - 28, - 84 + 139, - 181, - "Normal/Scroll", - DungeonMapConfig.class.getDeclaredField("dmChromaBorder") - )); - } catch (Exception e) { - e.printStackTrace(); - } - - //buttons.add(new Button(29, 52, 86+19, "XLarge", options.dmRoomSize)); - //buttons.add(new Button(30, 52, 56, "XLarge", options.dmBorderSize)); - - { - double val = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur; - String strVal; - if (val % 1 == 0) { - strVal = Integer.toString((int) val); - } else { - strVal = Double.toString(val); - strVal = strVal.replaceAll("(\\.\\d\\d\\d)(?:\\d)+", "$1"); - strVal = strVal.replaceAll("0+$", ""); - } - blurField.setText(strVal); - } - } - - @Override - public void drawScreen(int mouseX, int mouseY, float partialTicks) { - ScaledResolution scaledResolution = Utils.pushGuiScale(2); - this.width = scaledResolution.getScaledWidth(); - this.height = scaledResolution.getScaledHeight(); - - mouseX = Mouse.getEventX() * this.width / this.mc.displayWidth; - mouseY = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1; - - List<String> tooltipToDisplay = null; - for (Button button : buttons) { - if (mouseX >= guiLeft + button.x && mouseX <= guiLeft + button.x + 48 && - mouseY >= guiTop + button.y - 13 && mouseY <= guiTop + button.y + 16) { - if (button.id >= 6 && button.id <= 17) { - String mapDesc = null; - String mapCredit = null; - int id = button.id; - switch (id) { - case 6: - mapDesc = "No Border"; - break; - case 7: - mapDesc = "Used by custom Resource Packs"; - break; - case 8: - mapDesc = "Simple gray border"; - mapCredit = "TomEngMaster"; - break; - case 9: - mapDesc = "Viney wood border"; - mapCredit = "iDevil4Hell"; - break; - case 10: - mapDesc = "Steampunk-inspired square border"; - mapCredit = "ThatGravyBoat"; - break; - case 11: - mapDesc = "Steampunk-inspired circular border"; - mapCredit = "ThatGravyBoat"; - break; - case 12: - mapDesc = "Light fade border"; - mapCredit = "Qwiken"; - break; - case 13: - mapDesc = "Simple gray border with red ribbons"; - mapCredit = "Sai"; - break; - case 14: - mapDesc = "Paper border"; - mapCredit = "KingJames02st"; - break; - case 15: - mapDesc = "Nether-inspired border"; - mapCredit = "DTRW191"; - break; - case 16: - mapDesc = "Golden ornate border"; - mapCredit = "iDevil4Hell"; - break; - case 17: - mapDesc = "Stone dragon border"; - mapCredit = "ImperiaL"; - break; - } - - ArrayList<String> tooltip = new ArrayList<>(); - tooltip.add(EnumChatFormatting.YELLOW + "Border Style"); - tooltip.add(EnumChatFormatting.AQUA + "Customize the look of the dungeon border"); - tooltip.add(""); - if (mapDesc != null) - tooltip.add(EnumChatFormatting.YELLOW + "Set to: " + EnumChatFormatting.AQUA + mapDesc); - if (mapCredit != null) - tooltip.add(EnumChatFormatting.YELLOW + "Artist: " + EnumChatFormatting.GOLD + mapCredit); - tooltipToDisplay = tooltip; - } else { - tooltipToDisplay = button.getTooltip(); - } - break; - } - } - - this.sizeX = 431; - this.sizeY = 237; - this.guiLeft = (this.width - this.sizeX) / 2; - this.guiTop = (this.height - this.sizeY) / 2; - - super.drawScreen(mouseX, mouseY, partialTicks); - drawDefaultBackground(); - - blurBackground(); - renderBlurredBackground(width, height, guiLeft + 2, guiTop + 2, sizeX - 4, sizeY - 4); - - Minecraft.getMinecraft().getTextureManager().bindTexture(BACKGROUND); - GlStateManager.color(1, 1, 1, 1); - Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST); - - Minecraft.getMinecraft().fontRendererObj.drawString("NEU Dungeon Map Editor", guiLeft + 8, guiTop + 6, 0xFFB4B4B4); - - Utils.drawStringCenteredScaledMaxWidth("Border Size", Minecraft.getMinecraft().fontRendererObj, - guiLeft + 76, guiTop + 30, false, 137, 0xFFB4B4B4 - ); - Utils.drawStringCenteredScaledMaxWidth("Rooms Size", Minecraft.getMinecraft().fontRendererObj, - guiLeft + 76, guiTop + 60, false, 137, 0xFFB4B4B4 - ); - Utils.drawStringCenteredScaledMaxWidth("Icon Scale", Minecraft.getMinecraft().fontRendererObj, - guiLeft + 76, guiTop + 90, false, 137, 0xFFB4B4B4 - ); - Utils.drawStringCenteredScaledMaxWidth("Border Style", Minecraft.getMinecraft().fontRendererObj, - guiLeft + 76, guiTop + 120, false, 137, 0xFFB4B4B4 - ); - - Utils.drawStringCenteredScaledMaxWidth("Dungeon Map", Minecraft.getMinecraft().fontRendererObj, - guiLeft + 44 + 139, guiTop + 30, false, 60, 0xFFB4B4B4 - ); - Utils.drawStringCenteredScaledMaxWidth("Center", Minecraft.getMinecraft().fontRendererObj, - guiLeft + 108 + 139, guiTop + 30, false, 60, 0xFFB4B4B4 - ); - - Utils.drawStringCenteredScaledMaxWidth("Rotate", Minecraft.getMinecraft().fontRendererObj, - guiLeft + 44 + 139, guiTop + 59, false, 60, 0xFFB4B4B4 - ); - Utils.drawStringCenteredScaledMaxWidth("Icon Style", Minecraft.getMinecraft().fontRendererObj, - guiLeft + 108 + 139, guiTop + 59, false, 60, 0xFFB4B4B4 - ); - - Utils.drawStringCenteredScaledMaxWidth("Check Orient", Minecraft.getMinecraft().fontRendererObj, - guiLeft + 44 + 139, guiTop + 88, false, 60, 0xFFB4B4B4 - ); - Utils.drawStringCenteredScaledMaxWidth("Check Center", Minecraft.getMinecraft().fontRendererObj, - guiLeft + 108 + 139, guiTop + 88, false, 60, 0xFFB4B4B4 - ); - - Utils.drawStringCenteredScaledMaxWidth("Interpolation", Minecraft.getMinecraft().fontRendererObj, - guiLeft + 44 + 139, guiTop + 117, false, 60, 0xFFB4B4B4 - ); - Utils.drawStringCenteredScaledMaxWidth("Compatibility", Minecraft.getMinecraft().fontRendererObj, - guiLeft + 108 + 139, guiTop + 117, false, 60, 0xFFB4B4B4 - ); - - Utils.drawStringCenteredScaledMaxWidth("Background", Minecraft.getMinecraft().fontRendererObj, - guiLeft + 44 + 139, guiTop + 146, false, 60, 0xFFB4B4B4 - ); - Utils.drawStringCenteredScaledMaxWidth("Border", Minecraft.getMinecraft().fontRendererObj, - guiLeft + 108 + 139, guiTop + 146, false, 60, 0xFFB4B4B4 - ); - - Utils.drawStringCenteredScaledMaxWidth("BG Blur", Minecraft.getMinecraft().fontRendererObj, - guiLeft + 44 + 139, guiTop + 175, false, 60, 0xFFB4B4B4 - ); - Utils.drawStringCenteredScaledMaxWidth("Chroma Type", Minecraft.getMinecraft().fontRendererObj, - guiLeft + 108 + 139, guiTop + 175, false, 60, 0xFFB4B4B4 - ); - - Utils.drawStringCenteredScaledMaxWidth("Edit Map Position", Minecraft.getMinecraft().fontRendererObj, - guiLeft + 76, guiTop + 209, false, 200, 0xFFB4B4B4 - ); - - try { - drawSlider(DungeonMapConfig.class.getDeclaredField("dmBorderSize"), guiLeft + 76, guiTop + 45); - drawSlider(DungeonMapConfig.class.getDeclaredField("dmRoomSize"), guiLeft + 76, guiTop + 75); - drawSlider(DungeonMapConfig.class.getDeclaredField("dmIconScale"), guiLeft + 76, guiTop + 105); - } catch (Exception e) { - e.printStackTrace(); - } - - DungeonMapConfig options = NotEnoughUpdates.INSTANCE.config.dungeonMap; - buttons.get(18 - 6).text = options.dmEnable ? "Enabled" : "Disabled"; - buttons.get(19 - 6).text = options.dmCenterPlayer ? "Player" : "Map"; - buttons.get(20 - 6).text = options.dmRotatePlayer ? "Player" : "Vertical"; - buttons.get(21 - 6).text = - options.dmPlayerHeads <= 0 ? "Default" : options.dmPlayerHeads == 1 ? "Heads" : "Heads w/ Border"; - buttons.get(22 - 6).text = options.dmOrientCheck ? "Orient" : "Off"; - buttons.get(23 - 6).text = options.dmCenterCheck ? "Center" : "Off"; - buttons.get(24 - 6).text = options.dmPlayerInterp ? "Interp" : "No Interp"; - buttons.get(25 - 6).text = options.dmCompat <= 0 ? "Normal" : options.dmCompat >= 2 ? "No FB/SHD" : "No SHD"; - - buttons.get(26 - 6).colour = new Color(SpecialColour.specialToChromaRGB(options.dmBackgroundColour)); - buttons.get(27 - 6).colour = new Color(SpecialColour.specialToChromaRGB(options.dmBorderColour)); - - buttons.get(28 - 6).text = options.dmChromaBorder ? "Scroll" : "Normal"; - - blurField.setSize(48, 16); - blurField.render(guiLeft + 20 + 139, guiTop + 181); - - GlStateManager.color(1, 1, 1, 1); - Minecraft.getMinecraft().getTextureManager().bindTexture(button_tex); - RenderUtils.drawTexturedRect(guiLeft + 52, guiTop + 215, 48, 16); - TextRenderUtils.drawStringCenteredScaledMaxWidth("Edit", fontRendererObj, guiLeft + 76, guiTop + 223, - false, 48, 0xFF303030 - ); - - Map<String, Vec4b> decorations = new HashMap<>(); - Vec4b vec4b = new Vec4b((byte) 3, (byte) (((50) - 64) * 2), (byte) (((40) - 64) * 2), (byte) ((60) * 16 / 360)); - decorations.put(Minecraft.getMinecraft().thePlayer.getName(), vec4b); - - HashSet<String> players = new HashSet<>(); - players.add(Minecraft.getMinecraft().thePlayer.getName()); - GlStateManager.color(1, 1, 1, 1); - - demoMap.renderMap(guiLeft + 357, guiTop + 125, NotEnoughUpdates.INSTANCE.colourMap, decorations, 0, - players, false, partialTicks - ); - - for (Button button : buttons) { - button.render(); - } - - //List<String> textLines, final int mouseX, final int mouseY, final int screenWidth, final int screenHeight, final int maxTextWidth, FontRenderer font - if (tooltipToDisplay != null) { - Utils.drawHoveringText( - tooltipToDisplay, - mouseX, - mouseY, - width, - height, - 200, - Minecraft.getMinecraft().fontRendererObj + public static final ResourceLocation BACKGROUND = new ResourceLocation("notenoughupdates:dungeon_map/editor/background.png"); + public static final ResourceLocation BUTTON = new ResourceLocation("notenoughupdates:dungeon_map/editor/button.png"); + private static final DungeonMap demoMap = new DungeonMap(); + + private int sizeX; + private int sizeY; + private int guiLeft; + private int guiTop; + + private final List<Button> buttons = new ArrayList<>(); + + private final GuiElementTextField blurField = new GuiElementTextField("", GuiElementTextField.NUM_ONLY | GuiElementTextField.NO_SPACE); + private GuiElementColour activeColourEditor = null; + + private Field clickedSlider; + + class Button { + private final int id; + private final int x; + private final int y; + private String text; + private Color colour = new Color(-1, true); + private final Field option; + private String displayName; + private String desc; + + public Button(int id, int x, int y, String text) { + this(id, x, y, text, null); + } + + public Button(int id, int x, int y, String text, Field option) { + this.id = id; + this.x = x; + this.y = y; + this.text = text; + this.option = option; + + if (option != null) { + ConfigOption optionAnnotation = option.getAnnotation(ConfigOption.class); + displayName = optionAnnotation.name(); + desc = optionAnnotation.desc(); + } + } + + public List<String> getTooltip() { + if (option == null) { + return null; + } + + List<String> tooltip = new ArrayList<>(); + tooltip.add(EnumChatFormatting.YELLOW + displayName); + for (String line : desc.split("\n")) { + tooltip.add(EnumChatFormatting.AQUA + line); + } + return tooltip; + } + + public void render() { + if (text == null) return; + + Minecraft.getMinecraft().getTextureManager().bindTexture(BUTTON); + if (isButtonPressed(id)) { + GlStateManager.color(colour.getRed() * 0.85f / 255f, colour.getGreen() * 0.85f / 255f, + colour.getBlue() * 0.85f / 255f, 1); + Utils.drawTexturedRect(guiLeft + x, guiTop + y, 48, 16, 1, 0, 1, 0, GL11.GL_NEAREST); + } else { + GlStateManager.color(colour.getRed() / 255f, colour.getGreen() / 255f, colour.getBlue() / 255f, 1); + Utils.drawTexturedRect(guiLeft + x, guiTop + y, 48, 16, GL11.GL_NEAREST); + } + + if (text.length() > 0) { + Utils.drawStringCenteredScaledMaxWidth(text, Minecraft.getMinecraft().fontRendererObj, guiLeft + x + 24, guiTop + y + 8, false, 39, 0xFF000000); + } + } + + } + + public GuiDungeonMapEditor() { + DungeonMapConfig options = NotEnoughUpdates.INSTANCE.config.dungeonMap; + //Map Border Size + //buttons.add(new Button(0, 6, 37, "Small", options.dmBorderSize)); + //buttons.add(new Button(1, 52, 37, "Medium", options.dmBorderSize)); + //buttons.add(new Button(2, 98, 37, "Large", options.dmBorderSize)); + + //Map Rooms Size + //buttons.add(new Button(3, 6, 67+19, "Small", options.dmRoomSize)); + //buttons.add(new Button(4, 52, 67+19, "Medium", options.dmRoomSize)); + //buttons.add(new Button(5, 98, 67+19, "Large", options.dmRoomSize)); + + //Map Border Styles + buttons.add(new Button(6, 6, 97 + 30, "None")); + buttons.add(new Button(7, 52, 97 + 30, "Custom")); + buttons.add(new Button(8, 98, 97 + 30, "Stone")); + buttons.add(new Button(9, 6, 116 + 30, "Wood")); + buttons.add(new Button(10, 52, 116 + 30, "Rustic(S)")); + buttons.add(new Button(11, 98, 116 + 30, "Rustic(C)")); + buttons.add(new Button(12, 6, 135 + 30, "Fade")); + buttons.add(new Button(13, 52, 135 + 30, "Ribbons")); + buttons.add(new Button(14, 98, 135 + 30, "Paper")); + buttons.add(new Button(15, 6, 154 + 30, "Crimson")); + buttons.add(new Button(16, 52, 154 + 30, "Ornate")); + buttons.add(new Button(17, 98, 154 + 30, "Dragon")); + + try { + //Dungeon Map + buttons.add(new Button(18, 20 + 139, 36, "Yes/No", DungeonMapConfig.class.getDeclaredField("dmEnable"))); + //Center + buttons.add(new Button(19, 84 + 139, 36, "Player/Map", DungeonMapConfig.class.getDeclaredField("dmCenterPlayer"))); + //Rotate + buttons.add(new Button(20, 20 + 139, 65, "Player/No Rotate", DungeonMapConfig.class.getDeclaredField("dmRotatePlayer"))); + //Icon Style + buttons.add(new Button(21, 84 + 139, 65, "Default/Heads", DungeonMapConfig.class.getDeclaredField("dmPlayerHeads"))); + //Check Orient + buttons.add(new Button(22, 20 + 139, 94, "Normal/Reorient", DungeonMapConfig.class.getDeclaredField("dmOrientCheck"))); + //Check Center + buttons.add(new Button(23, 84 + 139, 94, "Yes/No", DungeonMapConfig.class.getDeclaredField("dmCenterCheck"))); + //Interpolation + buttons.add(new Button(24, 20 + 139, 123, "Yes/No", DungeonMapConfig.class.getDeclaredField("dmPlayerInterp"))); + //Compatibility + buttons.add(new Button(25, 84 + 139, 123, "Normal/No SHD/No FB/SHD", DungeonMapConfig.class.getDeclaredField("dmCompat"))); + + //Background + buttons.add(new Button(26, 20 + 139, 152, "", DungeonMapConfig.class.getDeclaredField("dmBackgroundColour"))); + //Border + buttons.add(new Button(27, 84 + 139, 152, "", DungeonMapConfig.class.getDeclaredField("dmBorderColour"))); + + //Chroma Mode + buttons.add(new Button(28, 84 + 139, 181, "Normal/Scroll", DungeonMapConfig.class.getDeclaredField("dmChromaBorder"))); + } catch (Exception e) { + e.printStackTrace(); + } + + //buttons.add(new Button(29, 52, 86+19, "XLarge", options.dmRoomSize)); + //buttons.add(new Button(30, 52, 56, "XLarge", options.dmBorderSize)); + + { + double val = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur; + String strVal; + if (val % 1 == 0) { + strVal = Integer.toString((int) val); + } else { + strVal = Double.toString(val); + strVal = strVal.replaceAll("(\\.\\d\\d\\d)(?:\\d)+", "$1"); + strVal = strVal.replaceAll("0+$", ""); + } + blurField.setText(strVal); + } + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + ScaledResolution scaledResolution = Utils.pushGuiScale(2); + this.width = scaledResolution.getScaledWidth(); + this.height = scaledResolution.getScaledHeight(); + + mouseX = Mouse.getEventX() * this.width / this.mc.displayWidth; + mouseY = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1; + + List<String> tooltipToDisplay = null; + for (Button button : buttons) { + if (mouseX >= guiLeft + button.x && mouseX <= guiLeft + button.x + 48 && + mouseY >= guiTop + button.y - 13 && mouseY <= guiTop + button.y + 16) { + if (button.id >= 6 && button.id <= 17) { + String mapDesc = null; + String mapCredit = null; + int id = button.id; + switch (id) { + case 6: + mapDesc = "No Border"; + break; + case 7: + mapDesc = "Used by custom Resource Packs"; + break; + case 8: + mapDesc = "Simple gray border"; + mapCredit = "LucyTightMistress"; + break; + case 9: + mapDesc = "Viney wood border"; + mapCredit = "iDevil4Hell"; + break; + case 10: + mapDesc = "Steampunk-inspired square border"; + mapCredit = "ThatGravyBoat"; + break; + case 11: + mapDesc = "Steampunk-inspired circular border"; + mapCredit = "ThatGravyBoat"; + break; + case 12: + mapDesc = "Light fade border"; + mapCredit = "Qwiken"; + break; + case 13: + mapDesc = "Simple gray border with red ribbons"; + mapCredit = "Sai"; + break; + case 14: + mapDesc = "Paper border"; + mapCredit = "KingJames02st"; + break; + case 15: + mapDesc = "Nether-inspired border"; + mapCredit = "DTRW191"; + break; + case 16: + mapDesc = "Golden ornate border"; + mapCredit = "iDevil4Hell"; + break; + case 17: + mapDesc = "Stone dragon border"; + mapCredit = "ImperiaL"; + break; + } + + ArrayList<String> tooltip = new ArrayList<>(); + tooltip.add(EnumChatFormatting.YELLOW + "Border Style"); + tooltip.add(EnumChatFormatting.AQUA + "Customize the look of the dungeon border"); + tooltip.add(""); + if (mapDesc != null) + tooltip.add(EnumChatFormatting.YELLOW + "Set to: " + EnumChatFormatting.AQUA + mapDesc); + if (mapCredit != null) + tooltip.add(EnumChatFormatting.YELLOW + "Artist: " + EnumChatFormatting.GOLD + mapCredit); + tooltipToDisplay = tooltip; + } else { + tooltipToDisplay = button.getTooltip(); + } + break; + } + } + + this.sizeX = 431; + this.sizeY = 237; + this.guiLeft = (this.width - this.sizeX) / 2; + this.guiTop = (this.height - this.sizeY) / 2; + + super.drawScreen(mouseX, mouseY, partialTicks); + drawDefaultBackground(); + + blurBackground(); + renderBlurredBackground(width, height, guiLeft + 2, guiTop + 2, sizeX - 4, sizeY - 4); + + Minecraft.getMinecraft().getTextureManager().bindTexture(BACKGROUND); + GlStateManager.color(1, 1, 1, 1); + Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST); + + DungeonMapStaticParser parser = new DungeonMapStaticParser( + demoMap, + "F1", + NotEnoughUpdates.INSTANCE.colourMap, + new HashMap<>() ); - } - - Utils.pushGuiScale(-1); - - if (activeColourEditor != null) { - activeColourEditor.render(); - } - } - - public void drawSlider(Field option, int centerX, int centerY) { - float value; - float minValue; - float maxValue; - try { - value = ((Number) option.get(NotEnoughUpdates.INSTANCE.config.dungeonMap)).floatValue(); - - ConfigEditorSlider sliderAnnotation = option.getAnnotation(ConfigEditorSlider.class); - minValue = sliderAnnotation.minValue(); - maxValue = sliderAnnotation.maxValue(); - } catch (Exception e) { - e.printStackTrace(); - return; - } - - float sliderAmount = Math.max(0, Math.min(1, (value - minValue) / (maxValue - minValue))); - int sliderAmountI = (int) (96 * sliderAmount); - - GlStateManager.color(1f, 1f, 1f, 1f); - Minecraft.getMinecraft().getTextureManager().bindTexture(slider_on_large); - Utils.drawTexturedRect(centerX - 48, centerY - 8, sliderAmountI, 16, - 0, sliderAmount, 0, 1, GL11.GL_NEAREST - ); - - Minecraft.getMinecraft().getTextureManager().bindTexture(slider_off_large); - Utils.drawTexturedRect(centerX - 48 + sliderAmountI, centerY - 8, 96 - sliderAmountI, 16, - sliderAmount, 1, 0, 1, GL11.GL_NEAREST - ); - - Minecraft.getMinecraft().getTextureManager().bindTexture(slider_button); - Utils.drawTexturedRect(centerX - 48 + sliderAmountI - 4, centerY - 8, 8, 16, - 0, 1, 0, 1, GL11.GL_NEAREST - ); - } - - @Override - protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) { - super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick); - - if (clickedSlider != null) { - float minValue; - float maxValue; - try { - ConfigEditorSlider sliderAnnotation = clickedSlider.getAnnotation(ConfigEditorSlider.class); - minValue = sliderAnnotation.minValue(); - maxValue = sliderAnnotation.maxValue(); - } catch (Exception e) { - e.printStackTrace(); - return; - } - - float sliderAmount = (mouseX - (guiLeft + 76 - 48)) / 96f; - double val = minValue + (maxValue - minValue) * sliderAmount; - if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) { - val = Math.round(val); - } - float value = (float) Math.max(minValue, Math.min(maxValue, val)); - try { - if (clickedSlider.getType() == int.class) { - clickedSlider.set(NotEnoughUpdates.INSTANCE.config.dungeonMap, Math.round(value)); - } else { - clickedSlider.set(NotEnoughUpdates.INSTANCE.config.dungeonMap, value); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - } - - @Override - protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { - for (Button button : buttons) { - if (mouseX >= guiLeft + button.x && mouseX <= guiLeft + button.x + 48 && - mouseY >= guiTop + button.y && mouseY <= guiTop + button.y + 16) { - buttonClicked(mouseX, mouseY, button.id); - - blurField.otherComponentClick(); - return; - } - } - - clickedSlider = null; - if (mouseX >= guiLeft + 76 - 48 && mouseX <= guiLeft + 76 + 48) { - try { - if (mouseY > guiTop + 45 - 8 && mouseY < guiTop + 45 + 8) { - clickedSlider = DungeonMapConfig.class.getDeclaredField("dmBorderSize"); - return; - } else if (mouseY > guiTop + 75 - 8 && mouseY < guiTop + 75 + 8) { - clickedSlider = DungeonMapConfig.class.getDeclaredField("dmRoomSize"); - return; - } else if (mouseY > guiTop + 105 - 8 && mouseY < guiTop + 105 + 8) { - clickedSlider = DungeonMapConfig.class.getDeclaredField("dmIconScale"); - return; - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - if (mouseY > guiTop + 181 && mouseY < guiTop + 181 + 16) { - if (mouseX > guiLeft + 20 + 139 && mouseX < guiLeft + 20 + 139 + 48) { - blurField.mouseClicked(mouseX, mouseY, mouseButton); - return; - } - } else if (mouseY > guiTop + 215 && mouseY < guiTop + 215 + 16) { - if (mouseX > guiLeft + 52 && mouseX < guiLeft + 100) { - int size = 80 + Math.round(40 * NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderSize); - - Map<String, Vec4b> decorations = new HashMap<>(); - Vec4b vec4b = new Vec4b((byte) 3, (byte) (((50) - 64) * 2), (byte) (((40) - 64) * 2), (byte) ((60) * 16 / 360)); - decorations.put(Minecraft.getMinecraft().thePlayer.getName(), vec4b); - - HashSet<String> players = new HashSet<>(); - players.add(Minecraft.getMinecraft().thePlayer.getName()); - GlStateManager.color(1, 1, 1, 1); - - Minecraft.getMinecraft().displayGuiScreen(new GuiPositionEditor( - NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPosition, - size, size, () -> { - ScaledResolution scaledResolution = Utils.pushGuiScale(2); - demoMap.renderMap( - NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPosition.getAbsX(scaledResolution, size) + size / 2, - NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPosition.getAbsY(scaledResolution, size) + size / 2, - NotEnoughUpdates.INSTANCE.colourMap, - decorations, - 0, - players, - false, - 0 - ); - Utils.pushGuiScale(-1); - }, () -> {}, () -> NotEnoughUpdates.INSTANCE.openGui = new GuiDungeonMapEditor() - ).withScale(2)); - return; - } - } - - blurField.otherComponentClick(); - } - - @Override - public void handleMouseInput() throws IOException { - super.handleMouseInput(); - - if (activeColourEditor != null) { - ScaledResolution realRes = new ScaledResolution(Minecraft.getMinecraft()); - int mouseX = Mouse.getEventX() * realRes.getScaledWidth() / this.mc.displayWidth; - int mouseY = - realRes.getScaledHeight() - Mouse.getEventY() * realRes.getScaledHeight() / this.mc.displayHeight - 1; - activeColourEditor.mouseInput(mouseX, mouseY); - } - } - - @Override - public void handleKeyboardInput() throws IOException { - super.handleKeyboardInput(); - - if (activeColourEditor != null) { - activeColourEditor.keyboardInput(); - } - } - - @Override - protected void keyTyped(char typedChar, int keyCode) throws IOException { - super.keyTyped(typedChar, keyCode); - - if (blurField.getFocus()) { - blurField.keyTyped(typedChar, keyCode); - - try { - blurField.setCustomBorderColour(-1); - NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur = Float.parseFloat(blurField.getText()); - } catch (Exception e) { - blurField.setCustomBorderColour(Color.RED.getRGB()); - } - } - } - - private void buttonClicked(int mouseX, int mouseY, int id) { - DungeonMapConfig options = NotEnoughUpdates.INSTANCE.config.dungeonMap; - switch (id) { - case 0: - options.dmBorderSize = 0; - break; - case 1: - options.dmBorderSize = 1; - break; - case 2: - options.dmBorderSize = 2; - break; - case 30: - options.dmBorderSize = 3; - break; - case 3: - options.dmRoomSize = 0; - break; - case 4: - options.dmRoomSize = 1; - break; - case 5: - options.dmRoomSize = 2; - break; - case 29: - options.dmRoomSize = 3; - break; - case 18: - options.dmEnable = !options.dmEnable; - break; - case 19: - options.dmCenterPlayer = !options.dmCenterPlayer; - break; - case 20: - options.dmRotatePlayer = !options.dmRotatePlayer; - break; - case 21: - options.dmPlayerHeads++; - if (options.dmPlayerHeads > 2) options.dmPlayerHeads = 0; - break; - case 22: - options.dmOrientCheck = !options.dmOrientCheck; - break; - case 23: - options.dmCenterCheck = !options.dmCenterCheck; - break; - case 24: - options.dmPlayerInterp = !options.dmPlayerInterp; - break; - case 25: - options.dmCompat++; - if (options.dmCompat > 2) options.dmCompat = 0; - break; - case 26: { - ScaledResolution realRes = new ScaledResolution(Minecraft.getMinecraft()); - mouseX = Mouse.getEventX() * realRes.getScaledWidth() / this.mc.displayWidth; - mouseY = realRes.getScaledHeight() - Mouse.getEventY() * realRes.getScaledHeight() / this.mc.displayHeight - 1; - activeColourEditor = new GuiElementColour(mouseX, mouseY, options.dmBackgroundColour, - (col) -> options.dmBackgroundColour = col, () -> activeColourEditor = null - ); - } - break; - case 27: { - ScaledResolution realRes = new ScaledResolution(Minecraft.getMinecraft()); - mouseX = Mouse.getEventX() * realRes.getScaledWidth() / this.mc.displayWidth; - mouseY = realRes.getScaledHeight() - Mouse.getEventY() * realRes.getScaledHeight() / this.mc.displayHeight - 1; - activeColourEditor = new GuiElementColour(mouseX, mouseY, options.dmBorderColour, - (col) -> options.dmBorderColour = col, () -> activeColourEditor = null - ); - } - break; - case 28: - options.dmChromaBorder = !options.dmChromaBorder; - break; - default: - if (id >= 6 && id <= 17) { - options.dmBorderStyle = id - 6; - break; - } - } - } - - private boolean isButtonPressed(int id) { - DungeonMapConfig options = NotEnoughUpdates.INSTANCE.config.dungeonMap; - - if (id >= 0 && id <= 2) { - return options.dmBorderSize == id; - } else if (id >= 3 && id <= 5) { - return options.dmRoomSize == id - 3; - } else if (id >= 6 && id <= 17) { - return options.dmBorderStyle == id - 6; - } else if (id == 29) { - return options.dmRoomSize == 3; - } else if (id == 30) { - return options.dmBorderSize == 3; - } - return false; - } - - Shader blurShaderHorz = null; - Framebuffer blurOutputHorz = null; - Shader blurShaderVert = null; - Framebuffer blurOutputVert = null; - - /** - * Creates a projection matrix that projects from our coordinate space [0->width; 0->height] to OpenGL coordinate - * space [-1 -> 1; 1 -> -1] (Note: flipped y-axis). - * <p> - * This is so that we can render to and from the framebuffer in a way that is familiar to us, instead of needing to - * apply scales and translations manually. - */ - private Matrix4f createProjectionMatrix(int width, int height) { - Matrix4f projMatrix = new Matrix4f(); - projMatrix.setIdentity(); - projMatrix.m00 = 2.0F / (float) width; - projMatrix.m11 = 2.0F / (float) (-height); - projMatrix.m22 = -0.0020001999F; - projMatrix.m33 = 1.0F; - projMatrix.m03 = -1.0F; - projMatrix.m13 = 1.0F; - projMatrix.m23 = -1.0001999F; - return projMatrix; - } - - private double lastBgBlurFactor = -1; - - private void blurBackground() { - if (!OpenGlHelper.isFramebufferEnabled()) return; - - int width = Minecraft.getMinecraft().displayWidth; - int height = Minecraft.getMinecraft().displayHeight; - - if (blurOutputHorz == null) { - blurOutputHorz = new Framebuffer(width, height, false); - blurOutputHorz.setFramebufferFilter(GL11.GL_NEAREST); - } - if (blurOutputVert == null) { - blurOutputVert = new Framebuffer(width, height, false); - blurOutputVert.setFramebufferFilter(GL11.GL_NEAREST); - } - if (blurOutputHorz.framebufferWidth != width || blurOutputHorz.framebufferHeight != height) { - blurOutputHorz.createBindFramebuffer(width, height); - blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height)); - Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false); - } - if (blurOutputVert.framebufferWidth != width || blurOutputVert.framebufferHeight != height) { - blurOutputVert.createBindFramebuffer(width, height); - blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height)); - Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false); - } - - if (blurShaderHorz == null) { - try { - blurShaderHorz = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur", - Minecraft.getMinecraft().getFramebuffer(), blurOutputHorz - ); - blurShaderHorz.getShaderManager().getShaderUniform("BlurDir").set(1, 0); - blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height)); - } catch (Exception ignored) { - } - } - if (blurShaderVert == null) { - try { - blurShaderVert = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur", - blurOutputHorz, blurOutputVert - ); - blurShaderVert.getShaderManager().getShaderUniform("BlurDir").set(0, 1); - blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height)); - } catch (Exception ignored) { - } - } - if (blurShaderHorz != null && blurShaderVert != null) { - if (15 != lastBgBlurFactor) { - blurShaderHorz.getShaderManager().getShaderUniform("Radius").set((float) 15); - blurShaderVert.getShaderManager().getShaderUniform("Radius").set((float) 15); - lastBgBlurFactor = 15; - } - GL11.glPushMatrix(); - blurShaderHorz.loadShader(0); - blurShaderVert.loadShader(0); - GlStateManager.enableDepth(); - GL11.glPopMatrix(); - - Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false); - } - } - - /** - * Renders a subsection of the blurred framebuffer on to the corresponding section of the screen. - * Essentially, this method will "blur" the background inside the bounds specified by [x->x+blurWidth, y->y+blurHeight] - */ - public void renderBlurredBackground(int width, int height, int x, int y, int blurWidth, int blurHeight) { - if (!OpenGlHelper.isFramebufferEnabled()) return; - - float uMin = x / (float) width; - float uMax = (x + blurWidth) / (float) width; - float vMin = (height - y) / (float) height; - float vMax = (height - y - blurHeight) / (float) height; - - blurOutputVert.bindFramebufferTexture(); - GlStateManager.color(1f, 1f, 1f, 1f); - Utils.drawTexturedRect(x, y, blurWidth, blurHeight, uMin, uMax, vMin, vMax); - blurOutputVert.unbindFramebufferTexture(); - } + parser.parseDungeonMap(); + DungeonMapConfig options = NotEnoughUpdates.INSTANCE.config.dungeonMap; + DungeonMapPlayers renderPlayer = new DungeonMapPlayers(); + renderPlayer.getRunnerPositions().put( + Minecraft.getMinecraft().thePlayer.getName(), + new DungeonMapPlayers.PlayerMarker(50, 40, 60F) + ); + renderPlayer.setMainPlayerX(50); + renderPlayer.setMainPlayerZ(40); + renderPlayer.setMainPlayerRotation(60); + float savedSize = options.dmBorderSize; + options.dmBorderSize = 1F; + demoMap.renderMap(options, parser, renderPlayer, guiLeft + 357, guiTop + 125); + options.dmBorderSize = savedSize; + + Minecraft.getMinecraft().fontRendererObj.drawString( + "NEU Dungeon Map Editor", + guiLeft + 8, + guiTop + 6, + 0xFFB4B4B4 + ); + + Utils.drawStringCenteredScaledMaxWidth("Border Size", Minecraft.getMinecraft().fontRendererObj, + guiLeft + 76, guiTop + 30, false, 137, 0xFFB4B4B4 + ); + Utils.drawStringCenteredScaledMaxWidth("Rooms Size", Minecraft.getMinecraft().fontRendererObj, + guiLeft + 76, guiTop + 60, false, 137, 0xFFB4B4B4 + ); + Utils.drawStringCenteredScaledMaxWidth("Icon Scale", Minecraft.getMinecraft().fontRendererObj, + guiLeft + 76, guiTop + 90, false, 137, 0xFFB4B4B4 + ); + Utils.drawStringCenteredScaledMaxWidth("Border Style", Minecraft.getMinecraft().fontRendererObj, + guiLeft + 76, guiTop + 120, false, 137, 0xFFB4B4B4); + + Utils.drawStringCenteredScaledMaxWidth("Dungeon Map", Minecraft.getMinecraft().fontRendererObj, + guiLeft + 44 + 139, guiTop + 30, false, 60, 0xFFB4B4B4); + Utils.drawStringCenteredScaledMaxWidth("Center", Minecraft.getMinecraft().fontRendererObj, + guiLeft + 108 + 139, guiTop + 30, false, 60, 0xFFB4B4B4); + + Utils.drawStringCenteredScaledMaxWidth("Rotate", Minecraft.getMinecraft().fontRendererObj, + guiLeft + 44 + 139, guiTop + 59, false, 60, 0xFFB4B4B4); + Utils.drawStringCenteredScaledMaxWidth("Icon Style", Minecraft.getMinecraft().fontRendererObj, + guiLeft + 108 + 139, guiTop + 59, false, 60, 0xFFB4B4B4); + + Utils.drawStringCenteredScaledMaxWidth("Check Orient", Minecraft.getMinecraft().fontRendererObj, + guiLeft + 44 + 139, guiTop + 88, false, 60, 0xFFB4B4B4); + Utils.drawStringCenteredScaledMaxWidth("Check Center", Minecraft.getMinecraft().fontRendererObj, + guiLeft + 108 + 139, guiTop + 88, false, 60, 0xFFB4B4B4); + + Utils.drawStringCenteredScaledMaxWidth("Interpolation", Minecraft.getMinecraft().fontRendererObj, + guiLeft + 44 + 139, guiTop + 117, false, 60, 0xFFB4B4B4); + Utils.drawStringCenteredScaledMaxWidth("Compatibility", Minecraft.getMinecraft().fontRendererObj, + guiLeft + 108 + 139, guiTop + 117, false, 60, 0xFFB4B4B4); + + Utils.drawStringCenteredScaledMaxWidth("Background", Minecraft.getMinecraft().fontRendererObj, + guiLeft + 44 + 139, guiTop + 146, false, 60, 0xFFB4B4B4); + Utils.drawStringCenteredScaledMaxWidth("Border", Minecraft.getMinecraft().fontRendererObj, + guiLeft + 108 + 139, guiTop + 146, false, 60, 0xFFB4B4B4); + + Utils.drawStringCenteredScaledMaxWidth("BG Blur", Minecraft.getMinecraft().fontRendererObj, + guiLeft + 44 + 139, guiTop + 175, false, 60, 0xFFB4B4B4); + Utils.drawStringCenteredScaledMaxWidth("Chroma Type", Minecraft.getMinecraft().fontRendererObj, + guiLeft + 108 + 139, guiTop + 175, false, 60, 0xFFB4B4B4); + + Utils.drawStringCenteredScaledMaxWidth("Edit Map Position", Minecraft.getMinecraft().fontRendererObj, + guiLeft + 76, guiTop + 209, false, 200, 0xFFB4B4B4); + + try { + drawSlider(DungeonMapConfig.class.getDeclaredField("dmBorderSize"), guiLeft + 76, guiTop + 45); + drawSlider(DungeonMapConfig.class.getDeclaredField("dmRoomSize"), guiLeft + 76, guiTop + 75); + drawSlider(DungeonMapConfig.class.getDeclaredField("dmIconScale"), guiLeft + 76, guiTop + 105); + } catch (Exception e) { + e.printStackTrace(); + } + + buttons.get(18 - 6).text = options.dmEnable ? "Enabled" : "Disabled"; + buttons.get(19 - 6).text = options.dmCenterPlayer ? "Player" : "Map"; + buttons.get(20 - 6).text = options.dmRotatePlayer ? "Player" : "Vertical"; + buttons.get(21 - 6).text = options.dmPlayerHeads <= 0 ? "Default" : options.dmPlayerHeads == 1 ? "Heads" : "Heads w/ Border"; + buttons.get(22 - 6).text = options.dmOrientCheck ? "Orient" : "Off"; + buttons.get(23 - 6).text = options.dmCenterCheck ? "Center" : "Off"; + buttons.get(24 - 6).text = options.dmPlayerInterp ? "Interp" : "No Interp"; + buttons.get(25 - 6).text = options.dmCompat <= 0 ? "Normal" : options.dmCompat >= 2 ? "No FB/SHD" : "No SHD"; + + buttons.get(26 - 6).colour = new Color(SpecialColour.specialToChromaRGB(options.dmBackgroundColour)); + buttons.get(27 - 6).colour = new Color(SpecialColour.specialToChromaRGB(options.dmBorderColour)); + + buttons.get(28 - 6).text = options.dmChromaBorder ? "Scroll" : "Normal"; + + blurField.setSize(48, 16); + blurField.render(guiLeft + 20 + 139, guiTop + 181); + + GlStateManager.color(1, 1, 1, 1); + Minecraft.getMinecraft().getTextureManager().bindTexture(button_tex); + RenderUtils.drawTexturedRect(guiLeft + 52, guiTop + 215, 48, 16); + TextRenderUtils.drawStringCenteredScaledMaxWidth("Edit", fontRendererObj, guiLeft + 76, guiTop + 223, + false, 48, 0xFF303030); + + + GlStateManager.color(1, 1, 1, 1); + for (Button button : buttons) { + button.render(); + } + + //List<String> textLines, final int mouseX, final int mouseY, final int screenWidth, final int screenHeight, final int maxTextWidth, FontRenderer font + if (tooltipToDisplay != null) { + Utils.drawHoveringText(tooltipToDisplay, mouseX, mouseY, width, height, 200, Minecraft.getMinecraft().fontRendererObj); + } + + Utils.pushGuiScale(-1); + + if (activeColourEditor != null) { + activeColourEditor.render(); + } + } + + public void drawSlider(Field option, int centerX, int centerY) { + float value; + float minValue; + float maxValue; + try { + value = ((Number) option.get(NotEnoughUpdates.INSTANCE.config.dungeonMap)).floatValue(); + + ConfigEditorSlider sliderAnnotation = option.getAnnotation(ConfigEditorSlider.class); + minValue = sliderAnnotation.minValue(); + maxValue = sliderAnnotation.maxValue(); + } catch (Exception e) { + e.printStackTrace(); + return; + } + + float sliderAmount = Math.max(0, Math.min(1, (value - minValue) / (maxValue - minValue))); + int sliderAmountI = (int) (96 * sliderAmount); + + GlStateManager.color(1f, 1f, 1f, 1f); + Minecraft.getMinecraft().getTextureManager().bindTexture(slider_on_large); + Utils.drawTexturedRect(centerX - 48, centerY - 8, sliderAmountI, 16, + 0, sliderAmount, 0, 1, GL11.GL_NEAREST); + + Minecraft.getMinecraft().getTextureManager().bindTexture(slider_off_large); + Utils.drawTexturedRect(centerX - 48 + sliderAmountI, centerY - 8, 96 - sliderAmountI, 16, + sliderAmount, 1, 0, 1, GL11.GL_NEAREST); + + Minecraft.getMinecraft().getTextureManager().bindTexture(slider_button); + Utils.drawTexturedRect(centerX - 48 + sliderAmountI - 4, centerY - 8, 8, 16, + 0, 1, 0, 1, GL11.GL_NEAREST); + } + + @Override + protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) { + super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick); + + if (clickedSlider != null) { + float minValue; + float maxValue; + try { + ConfigEditorSlider sliderAnnotation = clickedSlider.getAnnotation(ConfigEditorSlider.class); + minValue = sliderAnnotation.minValue(); + maxValue = sliderAnnotation.maxValue(); + } catch (Exception e) { + e.printStackTrace(); + return; + } + + float sliderAmount = (mouseX - (guiLeft + 76 - 48)) / 96f; + double val = minValue + (maxValue - minValue) * sliderAmount; + if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) { + val = Math.round(val); + } + float value = (float) Math.max(minValue, Math.min(maxValue, val)); + try { + if (clickedSlider.getType() == int.class) { + clickedSlider.set(NotEnoughUpdates.INSTANCE.config.dungeonMap, Math.round(value)); + } else { + clickedSlider.set(NotEnoughUpdates.INSTANCE.config.dungeonMap, value); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + } + + @Override + protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { + for (Button button : buttons) { + if (mouseX >= guiLeft + button.x && mouseX <= guiLeft + button.x + 48 && + mouseY >= guiTop + button.y && mouseY <= guiTop + button.y + 16) { + buttonClicked(mouseX, mouseY, button.id); + + blurField.otherComponentClick(); + return; + } + } + + clickedSlider = null; + if (mouseX >= guiLeft + 76 - 48 && mouseX <= guiLeft + 76 + 48) { + try { + if (mouseY > guiTop + 45 - 8 && mouseY < guiTop + 45 + 8) { + clickedSlider = DungeonMapConfig.class.getDeclaredField("dmBorderSize"); + return; + } else if (mouseY > guiTop + 75 - 8 && mouseY < guiTop + 75 + 8) { + clickedSlider = DungeonMapConfig.class.getDeclaredField("dmRoomSize"); + return; + } else if (mouseY > guiTop + 105 - 8 && mouseY < guiTop + 105 + 8) { + clickedSlider = DungeonMapConfig.class.getDeclaredField("dmIconScale"); + return; + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + if (mouseY > guiTop + 181 && mouseY < guiTop + 181 + 16) { + if (mouseX > guiLeft + 20 + 139 && mouseX < guiLeft + 20 + 139 + 48) { + blurField.mouseClicked(mouseX, mouseY, mouseButton); + return; + } + } else if (mouseY > guiTop + 215 && mouseY < guiTop + 215 + 16) { + if (mouseX > guiLeft + 52 && mouseX < guiLeft + 100) { + int size = 80 + Math.round(40 * NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderSize); + + Map<String, Vec4b> decorations = new HashMap<>(); + Vec4b vec4b = new Vec4b((byte) 3, (byte) (((50) - 64) * 2), (byte) (((40) - 64) * 2), (byte) ((60) * 16 / 360)); + decorations.put(Minecraft.getMinecraft().thePlayer.getName(), vec4b); + + HashSet<String> players = new HashSet<>(); + players.add(Minecraft.getMinecraft().thePlayer.getName()); + GlStateManager.color(1, 1, 1, 1); + + Minecraft.getMinecraft().displayGuiScreen(new GuiPositionEditor( + NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPosition, + size, size, () -> { + ScaledResolution scaledResolution = Utils.pushGuiScale(2); + /* demoMap.renderMap(NotEnoughUpdates.INSTANCE.config.dungeonMap, NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPosition.getAbsX(scaledResolution, size) + size / 2, + NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPosition.getAbsY(scaledResolution, size) + size / 2, + NotEnoughUpdates.INSTANCE.colourMap, decorations, 0, + players, false, 0);*/ + Utils.pushGuiScale(-1); + }, () -> {}, () -> NotEnoughUpdates.INSTANCE.openGui = new GuiDungeonMapEditor() + ).withScale(2)); + return; + } + } + + blurField.otherComponentClick(); + } + + @Override + public void handleMouseInput() throws IOException { + super.handleMouseInput(); + + if (activeColourEditor != null) { + ScaledResolution realRes = new ScaledResolution(Minecraft.getMinecraft()); + int mouseX = Mouse.getEventX() * realRes.getScaledWidth() / this.mc.displayWidth; + int mouseY = realRes.getScaledHeight() - Mouse.getEventY() * realRes.getScaledHeight() / this.mc.displayHeight - 1; + activeColourEditor.mouseInput(mouseX, mouseY); + } + } + + @Override + public void handleKeyboardInput() throws IOException { + super.handleKeyboardInput(); + + if (activeColourEditor != null) { + activeColourEditor.keyboardInput(); + } + } + + @Override + protected void keyTyped(char typedChar, int keyCode) throws IOException { + super.keyTyped(typedChar, keyCode); + + if (blurField.getFocus()) { + blurField.keyTyped(typedChar, keyCode); + + try { + blurField.setCustomBorderColour(-1); + NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur = Float.parseFloat(blurField.getText()); + } catch (Exception e) { + blurField.setCustomBorderColour(Color.RED.getRGB()); + } + } + } + + private void buttonClicked(int mouseX, int mouseY, int id) { + DungeonMapConfig options = NotEnoughUpdates.INSTANCE.config.dungeonMap; + switch (id) { + case 0: + options.dmBorderSize = 0; + break; + case 1: + options.dmBorderSize = 1; + break; + case 2: + options.dmBorderSize = 2; + break; + case 30: + options.dmBorderSize = 3; + break; + case 3: + options.dmRoomSize = 0; + break; + case 4: + options.dmRoomSize = 1; + break; + case 5: + options.dmRoomSize = 2; + break; + case 29: + options.dmRoomSize = 3; + break; + case 18: + options.dmEnable = !options.dmEnable; + break; + case 19: + options.dmCenterPlayer = !options.dmCenterPlayer; + break; + case 20: + options.dmRotatePlayer = !options.dmRotatePlayer; + break; + case 21: + options.dmPlayerHeads++; + if (options.dmPlayerHeads > 2) options.dmPlayerHeads = 0; + break; + case 22: + options.dmOrientCheck = !options.dmOrientCheck; + break; + case 23: + options.dmCenterCheck = !options.dmCenterCheck; + break; + case 24: + options.dmPlayerInterp = !options.dmPlayerInterp; + break; + case 25: + options.dmCompat++; + if (options.dmCompat > 2) options.dmCompat = 0; + break; + case 26: { + ScaledResolution realRes = new ScaledResolution(Minecraft.getMinecraft()); + mouseX = Mouse.getEventX() * realRes.getScaledWidth() / this.mc.displayWidth; + mouseY = realRes.getScaledHeight() - Mouse.getEventY() * realRes.getScaledHeight() / this.mc.displayHeight - 1; + activeColourEditor = new GuiElementColour(mouseX, mouseY, options.dmBackgroundColour, + (col) -> options.dmBackgroundColour = col, () -> activeColourEditor = null); + } + break; + case 27: { + ScaledResolution realRes = new ScaledResolution(Minecraft.getMinecraft()); + mouseX = Mouse.getEventX() * realRes.getScaledWidth() / this.mc.displayWidth; + mouseY = realRes.getScaledHeight() - Mouse.getEventY() * realRes.getScaledHeight() / this.mc.displayHeight - 1; + activeColourEditor = new GuiElementColour(mouseX, mouseY, options.dmBorderColour, + (col) -> options.dmBorderColour = col, () -> activeColourEditor = null); + } + break; + case 28: + options.dmChromaBorder = !options.dmChromaBorder; + break; + default: + if (id >= 6 && id <= 17) { + options.dmBorderStyle = id - 6; + break; + } + } + } + + private boolean isButtonPressed(int id) { + DungeonMapConfig options = NotEnoughUpdates.INSTANCE.config.dungeonMap; + + if (id >= 0 && id <= 2) { + return options.dmBorderSize == id; + } else if (id >= 3 && id <= 5) { + return options.dmRoomSize == id - 3; + } else if (id >= 6 && id <= 17) { + return options.dmBorderStyle == id - 6; + } else if (id == 29) { + return options.dmRoomSize == 3; + } else if (id == 30) { + return options.dmBorderSize == 3; + } + return false; + } + + Shader blurShaderHorz = null; + Framebuffer blurOutputHorz = null; + Shader blurShaderVert = null; + Framebuffer blurOutputVert = null; + + /** + * Creates a projection matrix that projects from our coordinate space [0->width; 0->height] to OpenGL coordinate + * space [-1 -> 1; 1 -> -1] (Note: flipped y-axis). + * <p> + * This is so that we can render to and from the framebuffer in a way that is familiar to us, instead of needing to + * apply scales and translations manually. + */ + private Matrix4f createProjectionMatrix(int width, int height) { + Matrix4f projMatrix = new Matrix4f(); + projMatrix.setIdentity(); + projMatrix.m00 = 2.0F / (float) width; + projMatrix.m11 = 2.0F / (float) (-height); + projMatrix.m22 = -0.0020001999F; + projMatrix.m33 = 1.0F; + projMatrix.m03 = -1.0F; + projMatrix.m13 = 1.0F; + projMatrix.m23 = -1.0001999F; + return projMatrix; + } + + private double lastBgBlurFactor = -1; + + private void blurBackground() { + if (!OpenGlHelper.isFramebufferEnabled()) return; + + int width = Minecraft.getMinecraft().displayWidth; + int height = Minecraft.getMinecraft().displayHeight; + + if (blurOutputHorz == null) { + blurOutputHorz = new Framebuffer(width, height, false); + blurOutputHorz.setFramebufferFilter(GL11.GL_NEAREST); + } + if (blurOutputVert == null) { + blurOutputVert = new Framebuffer(width, height, false); + blurOutputVert.setFramebufferFilter(GL11.GL_NEAREST); + } + if (blurOutputHorz.framebufferWidth != width || blurOutputHorz.framebufferHeight != height) { + blurOutputHorz.createBindFramebuffer(width, height); + blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height)); + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false); + } + if (blurOutputVert.framebufferWidth != width || blurOutputVert.framebufferHeight != height) { + blurOutputVert.createBindFramebuffer(width, height); + blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height)); + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false); + } + + if (blurShaderHorz == null) { + try { + blurShaderHorz = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur", + Minecraft.getMinecraft().getFramebuffer(), blurOutputHorz); + blurShaderHorz.getShaderManager().getShaderUniform("BlurDir").set(1, 0); + blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height)); + } catch (Exception ignored) {} + } + if (blurShaderVert == null) { + try { + blurShaderVert = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur", + blurOutputHorz, blurOutputVert); + blurShaderVert.getShaderManager().getShaderUniform("BlurDir").set(0, 1); + blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height)); + } catch (Exception ignored) {} + } + if (blurShaderHorz != null && blurShaderVert != null) { + if (15 != lastBgBlurFactor) { + blurShaderHorz.getShaderManager().getShaderUniform("Radius").set((float) 15); + blurShaderVert.getShaderManager().getShaderUniform("Radius").set((float) 15); + lastBgBlurFactor = 15; + } + GL11.glPushMatrix(); + blurShaderHorz.loadShader(0); + blurShaderVert.loadShader(0); + GlStateManager.enableDepth(); + GL11.glPopMatrix(); + + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false); + } + } + + /** + * Renders a subsection of the blurred framebuffer on to the corresponding section of the screen. + * Essentially, this method will "blur" the background inside the bounds specified by [x->x+blurWidth, y->y+blurHeight] + */ + public void renderBlurredBackground(int width, int height, int x, int y, int blurWidth, int blurHeight) { + if (!OpenGlHelper.isFramebufferEnabled()) return; + + float uMin = x / (float) width; + float uMax = (x + blurWidth) / (float) width; + float vMin = (height - y) / (float) height; + float vMax = (height - y - blurHeight) / (float) height; + + blurOutputVert.bindFramebufferTexture(); + GlStateManager.color(1f, 1f, 1f, 1f); + Utils.drawTexturedRect(x, y, blurWidth, blurHeight, uMin, uMax, vMin, vMax); + blurOutputVert.unbindFramebufferTexture(); + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/SpiritLeap.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/SpiritLeap.java new file mode 100644 index 00000000..a35ab34e --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/SpiritLeap.java @@ -0,0 +1,40 @@ +package io.github.moulberry.notenoughupdates.dungeons; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.dungeons.map.DungeonMap; +import io.github.moulberry.notenoughupdates.dungeons.map.DungeonMapPlayers; +import io.github.moulberry.notenoughupdates.options.seperateSections.DungeonMapConfig; +import io.github.moulberry.notenoughupdates.util.SBInfo; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.inventory.ContainerChest; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +public class SpiritLeap { + + DungeonMap dungeonMap = new DungeonMap(); + DungeonMapPlayers savedPlayers = null; + + @SubscribeEvent + public void onGuiRender(GuiScreenEvent.DrawScreenEvent.Post event) { + if (!(event.gui instanceof GuiChest)) return; + if (!SBInfo.getInstance().isInDungeon) return; + GuiChest gui = (GuiChest) event.gui; + ContainerChest chest = (ContainerChest) gui.inventorySlots; + if (!chest.getLowerChestInventory().getDisplayName().getUnformattedText().equals("Spirit Leap")) return; + DungeonMapConfig config = NotEnoughUpdates.INSTANCE.config.dungeonMap; + this.dungeonMap.renderMap( + config, + this.dungeonMap.parsedDungeon, + savedPlayers != null ? savedPlayers : this.dungeonMap.dungeonMapPlayers, + gui.guiLeft - Math.round(20 * config.dmBorderSize), + gui.guiTop + gui.height / 2 + ); + } + + @SubscribeEvent + public void onGuiClick(GuiScreenEvent.MouseInputEvent.Post event) { + + } + +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/DungeonMap.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/DungeonMap.java new file mode 100644 index 00000000..716a3274 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/DungeonMap.java @@ -0,0 +1,161 @@ +package io.github.moulberry.notenoughupdates.dungeons.map; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.config.Position; +import io.github.moulberry.notenoughupdates.options.seperateSections.DungeonMapConfig; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.block.material.MapColor; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.init.Items; +import net.minecraft.item.Item; +import net.minecraft.item.ItemMap; +import net.minecraft.item.ItemStack; +import net.minecraft.scoreboard.Score; +import net.minecraft.scoreboard.ScoreObjective; +import net.minecraft.scoreboard.ScorePlayerTeam; +import net.minecraft.scoreboard.Scoreboard; +import net.minecraft.world.storage.MapData; +import net.minecraftforge.client.event.RenderGameOverlayEvent; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class DungeonMap { + + public DungeonMapRenderer renderer = new DungeonMapRenderer(this, NotEnoughUpdates.INSTANCE.config.dungeonMap); + + public DungeonMapStaticParser parsedDungeon; + public DungeonMapPlayers dungeonMapPlayers; + public DungeonMapDebugOverlay dungeonMapDebugOverlay = new DungeonMapDebugOverlay(this); + + public void renderMap( + DungeonMapConfig config, + DungeonMapStaticParser parsedDungeonData, + DungeonMapPlayers players, + int centerX, + int centerY + ) { + if (!config.dmEnable) return; + if (parsedDungeonData == null) return; + if (players == null) return; + renderer.render(centerX, centerY, parsedDungeonData, players); + } + + @SubscribeEvent + public void onWorldChange(WorldEvent.Load event) { + this.parsedDungeon = null; + this.dungeonMapDebugOverlay.logFile = null; + this.dungeonMapPlayers = null; + } + + // \(([MASC]\d?)\) + // nea stop being so genderbrained + private static final Pattern FLOOR_REGEX = Pattern.compile("\\(([FEM]\\d?)\\)"); + + @SubscribeEvent + public void onTickEvent(TickEvent.ClientTickEvent event) { + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + if (thePlayer == null) return; + ItemStack stack = thePlayer.inventory.mainInventory[8]; + + Scoreboard scoreboard = Minecraft.getMinecraft().thePlayer.getWorldScoreboard(); + + ScoreObjective sidebarObjective = scoreboard.getObjectiveInDisplaySlot(1); + + List<Score> scores = new ArrayList<>(scoreboard.getSortedScores(sidebarObjective)); + + String floorName = null; + for (int i = scores.size() - 1; i >= 0; i--) { + Score score = scores.get(i); + ScorePlayerTeam scoreplayerteam1 = scoreboard.getPlayersTeam(score.getPlayerName()); + String line = ScorePlayerTeam.formatPlayerName(scoreplayerteam1, score.getPlayerName()); + line = Utils.cleanColour(line).replaceAll("[^ -~]+", ""); + + if (line.contains("The Catacombs")) { + Matcher matcher = FLOOR_REGEX.matcher(line); + if (matcher.find()) { + floorName = matcher.group(1); + break; + } + } + + } + Item item = stack != null ? stack.getItem() : null; + if (item instanceof ItemMap) { + ItemMap map = (ItemMap) stack.getItem(); + MapData mapData = map.getMapData(stack, Minecraft.getMinecraft().theWorld); + + if (mapData == null) return; + + Color[][] colors = new Color[128][128]; + for (int i = 0; i < 128 * 128; ++i) { + int x = i % 128; + int y = i / 128; + + int j = mapData.colors[i] & 255; + + Color c; + if (j / 4 == 0) { + c = new Color(((((i + i / 128) & 1) * 8) + 16) << 24, true); + } else { + c = new Color(MapColor.mapColorArray[j / 4].getMapColor(j & 3), true); + } + + colors[x][y] = c; + } + // TODO: do not parse static again if the colors are the same. + + DungeonMapStaticParser parser = new DungeonMapStaticParser(this, floorName, colors, mapData.mapDecorations); + if (parser.parseDungeonMap()) + parsedDungeon = parser; + DungeonMapPlayers players = new DungeonMapPlayers(); + players.parse(parser, this.dungeonMapPlayers); + this.dungeonMapPlayers = players; + } else if (item != Items.arrow) { + // This should clear the map if you're in the dungeon boss room + // The check for arrows is so that holding a bow will not hide the map (but it will stop the map from updating) + this.parsedDungeon = null; + } + + } + + @SubscribeEvent + public void onRenderOverlay(RenderGameOverlayEvent.Post event) { + if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return; + if (event.type == RenderGameOverlayEvent.ElementType.ALL) { + if (!NotEnoughUpdates.INSTANCE.config.dungeonMap.dmEnable) return; + + if (Minecraft.getMinecraft().gameSettings.showDebugInfo || + (Minecraft.getMinecraft().gameSettings.keyBindPlayerList.isKeyDown() && + (!Minecraft.getMinecraft().isIntegratedServerRunning() || + Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap().size() > 1))) { + return; + } + + DungeonMapStaticParser parsed = parsedDungeon; + if (parsed != null) { + Position pos = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPosition; + + int size = 80 + Math.round(40 * NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderSize); + ScaledResolution scaledResolution = Utils.pushGuiScale(2); + renderMap( + NotEnoughUpdates.INSTANCE.config.dungeonMap, + parsed, + dungeonMapPlayers, + pos.getAbsX(scaledResolution, size / 2) + size / 2, + pos.getAbsY(scaledResolution, size / 2) + size / 2 + ); + Utils.pushGuiScale(-1); + + } + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/DungeonMapDebugOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/DungeonMapDebugOverlay.java new file mode 100644 index 00000000..74c3b587 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/DungeonMapDebugOverlay.java @@ -0,0 +1,117 @@ +package io.github.moulberry.notenoughupdates.dungeons.map; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.config.Position; +import io.github.moulberry.notenoughupdates.options.customtypes.NEUDebugFlag; +import io.github.moulberry.notenoughupdates.overlays.OverlayManager; +import io.github.moulberry.notenoughupdates.overlays.TextOverlay; +import io.github.moulberry.notenoughupdates.overlays.TextOverlayStyle; +import io.github.moulberry.notenoughupdates.util.RecencyList; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.PrintStream; +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; + +public class DungeonMapDebugOverlay extends TextOverlay { + public DungeonMapDebugOverlay(DungeonMap map) { + super(new Position(10, 300), null, () -> TextOverlayStyle.BACKGROUND); + this.map = map; + OverlayManager.textOverlays.add(this); + } + + PrintStream logFile = null; + + public void finishDungeon() { + if (logFile != null) { + logFile.close(); + logFile = null; + } + } + + public void newDungeon() { + File file = new File(NotEnoughUpdates.INSTANCE.getNeuDir(), String.format( + "dungeonlog/log-%s.txt", + DateTimeFormatter.ofPattern("dd-MM-yyyy-HH-mm-ss").format(LocalDateTime.now()) + )); + file.getParentFile().mkdirs(); + try { + logFile = new PrintStream(file); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + } + + public void logAssignmentChange(String info) { + currentAssignmentChanges.add(info); + } + + DungeonMap map; + private RecencyList<String> recentAssignmentChanges = new RecencyList<>(Duration.ofSeconds(5)); + private List<String> currentAssignmentChanges = new ArrayList<>(); + + @Override + public void update() { + recentAssignmentChanges.addAll(currentAssignmentChanges); + if (!NEUDebugFlag.MAP.isSet() || map.dungeonMapPlayers == null) { + overlayStrings = null; + currentAssignmentChanges.clear(); + return; + } + overlayStrings = new ArrayList<>(); + overlayStrings.add("Icon Mappings:"); + for (Map.Entry<String, String> entry : map.dungeonMapPlayers.getPlayerNameToIconName().entrySet()) { + overlayStrings.add(entry.getValue() + " - " + entry.getKey()); + } + + overlayStrings.add(""); + + overlayStrings.add("Map Coords:"); + addMap(map.dungeonMapPlayers.getAllMapPositions()); + + overlayStrings.add(""); + + overlayStrings.add("Player Coords:"); + addMap(map.dungeonMapPlayers.getRunnerEntityPosition()); + + overlayStrings.add(""); + + overlayStrings.add("Rendered Coords:"); + addMap(map.dungeonMapPlayers.getRunnerPositions()); + overlayStrings.add(""); + + overlayStrings.add("Orphaned Coords:"); + addMap(map.dungeonMapPlayers.getOrphanedMarkers()); + + overlayStrings.add(""); + overlayStrings.add("Recent assignments:"); + + if (currentAssignmentChanges.size() > 0) { + if (logFile == null) { + newDungeon(); + } + overlayStrings.forEach(logFile::println); + currentAssignmentChanges.forEach(logFile::println); + logFile.println("------------------------"); + logFile.flush(); + } + currentAssignmentChanges.clear(); + overlayStrings.addAll(recentAssignmentChanges.getList()); + + } + + private void addMap(Map<String, DungeonMapPlayers.PlayerMarker> map) { + for (Map.Entry<String, DungeonMapPlayers.PlayerMarker> entry : map.entrySet()) { + overlayStrings.add(entry.getKey() + ": " + entry.getValue().x + " " + entry.getValue().z); + } + } + +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/DungeonMapPlayers.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/DungeonMapPlayers.java new file mode 100644 index 00000000..53b2e602 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/DungeonMapPlayers.java @@ -0,0 +1,267 @@ +package io.github.moulberry.notenoughupdates.dungeons.map; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.AbstractClientPlayer; +import net.minecraft.client.resources.DefaultPlayerSkin; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.scoreboard.Team; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.Vec4b; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class DungeonMapPlayers { + + public static class Linear { + private final float slope; + private final float intercept; + + public Linear(float slope, float intercept) { + this.slope = slope; + this.intercept = intercept; + } + + public float getSlope() { + return slope; + } + + public float getIntercept() { + return intercept; + } + + public float calculate(float x) { + return slope * x + intercept; + } + + public float calculateInverse(float y) { + return (y - intercept) / slope; + } + } + + public static Map<String, Linear> FLOOR_MAP_SCALINGS = new HashMap<String, Linear>() {{ + put("F1", new Linear(1.5F, -215F)); + put("F2", new Linear(1.5F, -215F)); + put("F3", new Linear(1.5F, -215F)); + put("F4", new Linear(1.6F, -206F)); + put("F5", new Linear(1.6F, -206F)); + put("F6", new Linear(1.6F, -206F)); + put("F7", new Linear(1.6F, -206F)); + }}; + + public static class PlayerMarker { + public final int x, z; + public final float angle; + + public PlayerMarker(int x, int z, float angle) { + this.x = x; + this.z = z; + this.angle = angle; + } + + public int squaredDistance(PlayerMarker marker) { + int deltaX = marker.x - x; + int deltaZ = marker.z - z; + return deltaX * deltaX + deltaZ * deltaZ; + } + + @Override + public int hashCode() { + return Objects.hash(x, z, angle); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + PlayerMarker that = (PlayerMarker) o; + + if (x != that.x) return false; + if (z != that.z) return false; + return Float.compare(that.angle, angle) == 0; + } + } + + private final Map<String, PlayerMarker> runnerPositions = new HashMap<>(); + private final Map<String, PlayerMarker> runnerEntityPosition = new HashMap<>(); + private final BiMap<String, String> playerNameToIconName = HashBiMap.create(); + private final Map<String, ResourceLocation> skinMap = new HashMap<>(); + private final Map<String, PlayerMarker> allMapPositions = new HashMap<>(); + private final Map<String, PlayerMarker> orphanedMarkers = new HashMap<>(); + private float mainPlayerRotation; + private float mainPlayerX; + private float mainPlayerZ; + + private boolean isRealPlayer(String playerName) { + return Minecraft.getMinecraft().thePlayer.getWorldScoreboard().getTeams().stream() + .anyMatch(it + -> it.getMembershipCollection().size() == 1 + && it.getMembershipCollection().contains(playerName) + && it.getTeamName().startsWith("a") + && it.getNameTagVisibility() == Team.EnumVisible.ALWAYS); + } + + public void parse(DungeonMapStaticParser mapData, DungeonMapPlayers last) { + mainPlayerRotation = Minecraft.getMinecraft().thePlayer.rotationYaw; + if (last != null) { + playerNameToIconName.putAll(last.playerNameToIconName); + skinMap.putAll(last.skinMap); + } + + if (mapData == null) return; + + parseEntityPositions(mapData); + + Map<String, Vec4b> mapDecorations = mapData.mapDecorations; + if (mapDecorations != null) { + parseMapPositions(mapDecorations); + assignKnownMapMarkers(mapData.dungeonMap); + findOrphanedMarkers(); + } else if (last != null) { + // If the map decorations aren't present, then add the past orphaned markers, so those don't flicker. + orphanedMarkers.putAll(last.orphanedMarkers); + } + + playerNameToIconName.forEach((playerName, markerName) -> { + if (runnerEntityPosition.containsKey(playerName)) { + runnerPositions.put(playerName, runnerEntityPosition.get(playerName)); + } else if (allMapPositions.containsKey(markerName)) { + runnerPositions.put(playerName, allMapPositions.get(markerName)); + } + }); + } + + private void findOrphanedMarkers() { + for (Map.Entry<String, PlayerMarker> marker : allMapPositions.entrySet()) { + if (!playerNameToIconName.containsValue(marker.getKey())) { + // We couldn't find a matching player, orphan this marker, so we can render it with the default marker. + orphanedMarkers.put(marker.getKey(), marker.getValue()); + } + } + } + + private void parseMapPositions(Map<String, Vec4b> mapDecorations) { + for (Map.Entry<String, Vec4b> entry : mapDecorations.entrySet()) { + byte id = entry.getValue().func_176110_a(); + if (id != 1 && id != 3) continue; + int mapX = (int) entry.getValue().func_176112_b() / 2 + 64; + int mapZ = (int) entry.getValue().func_176113_c() / 2 + 64; + float angle = entry.getValue().func_176111_d() * 360 / 16F; + allMapPositions.put(entry.getKey(), new PlayerMarker(mapX, mapZ, angle)); + } + } + + private static final float DISTANCE_SQUARED_THRESHOLD = 10; + + private void assignKnownMapMarkers(DungeonMap dungeonMap) { + for (Map.Entry<String, PlayerMarker> mapPos : allMapPositions.entrySet()) { + String oldPlayer = playerNameToIconName.inverse().get(mapPos.getKey()); + String newPlayer = findExclusivePlayerNextToPoint(mapPos.getValue()); + if (newPlayer == null && oldPlayer != null) { + dungeonMap.dungeonMapDebugOverlay.logAssignmentChange( + EnumChatFormatting.GOLD + "Player " + oldPlayer + " is far away from their respective marker (" + + mapPos.getKey() + "). Still keeping marker."); + } + + if (newPlayer != null && !Objects.equals(newPlayer, oldPlayer)) { + if (playerNameToIconName.containsKey(newPlayer)) { + String oldMarker = playerNameToIconName.remove(newPlayer); + dungeonMap.dungeonMapDebugOverlay.logAssignmentChange( + EnumChatFormatting.RED + "Unassigned " + newPlayer + " (previously " + + oldMarker + "), but seems to be " + mapPos.getKey()); + } + playerNameToIconName.inverse().remove(mapPos.getKey()); + playerNameToIconName.put(newPlayer, mapPos.getKey()); + dungeonMap.dungeonMapDebugOverlay.logAssignmentChange( + EnumChatFormatting.GREEN + "Assigned " + newPlayer + " to " + mapPos.getKey() + " (previously " + oldPlayer + + ")"); + } + } + } + + private String findExclusivePlayerNextToPoint(PlayerMarker referencePoint) { + String entityCandidate = null; + for (Map.Entry<String, PlayerMarker> entityPos : runnerEntityPosition.entrySet()) { + if (referencePoint.squaredDistance(entityPos.getValue()) > DISTANCE_SQUARED_THRESHOLD) continue; + if (entityCandidate != null) + return null; // Multiple candidates, people stepping on each other (kinda sus ngl) + entityCandidate = entityPos.getKey(); + } + return entityCandidate; + } + + private void parseEntityPositions(DungeonMapStaticParser mapData) { + Linear coordMapping = FLOOR_MAP_SCALINGS.get(mapData.floorName); + if (coordMapping == null) return; + for (EntityPlayer entity : Minecraft.getMinecraft().theWorld.playerEntities) { + if (entity.isPlayerSleeping() || !isRealPlayer(entity.getName())) continue; + if (entity instanceof AbstractClientPlayer) { + ResourceLocation skin = ((AbstractClientPlayer) entity).getLocationSkin(); + if (skin != null && !skin.equals(DefaultPlayerSkin.getDefaultSkin(entity.getUniqueID()))) + skinMap.put(entity.getName(), skin); + } + + float x = coordMapping.calculateInverse((float) entity.posX); + float z = coordMapping.calculateInverse((float) entity.posZ); + if (entity.getName().equals(Minecraft.getMinecraft().thePlayer.getName())) { + mainPlayerX = x; + mainPlayerZ = z; + } + runnerEntityPosition.put(entity.getName(), new PlayerMarker( + (int) x, (int) z, entity.rotationYaw)); + } + } + + public ResourceLocation getSkin(String name) { + return skinMap.getOrDefault(name, DefaultPlayerSkin.getDefaultSkinLegacy()); + } + + public float getMainPlayerX() { + return mainPlayerX; + } + + public void setMainPlayerX(float mainPlayerX) { + this.mainPlayerX = mainPlayerX; + } + + public void setMainPlayerZ(float mainPlayerZ) { + this.mainPlayerZ = mainPlayerZ; + } + + public void setMainPlayerRotation(float mainPlayerRotation) { + this.mainPlayerRotation = mainPlayerRotation; + } + + public float getMainPlayerZ() { + return mainPlayerZ; + } + + public float getMainPlayerRotation() { + return mainPlayerRotation; + } + + public Map<String, PlayerMarker> getRunnerPositions() { + return runnerPositions; + } + + public Map<String, PlayerMarker> getAllMapPositions() { + return allMapPositions; + } + + public BiMap<String, String> getPlayerNameToIconName() { + return playerNameToIconName; + } + + public Map<String, PlayerMarker> getRunnerEntityPosition() { + return runnerEntityPosition; + } + + public Map<String, PlayerMarker> getOrphanedMarkers() { + return orphanedMarkers; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/DungeonMapRenderer.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/DungeonMapRenderer.java new file mode 100644 index 00000000..b284a8b6 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/DungeonMapRenderer.java @@ -0,0 +1,526 @@ +package io.github.moulberry.notenoughupdates.dungeons.map; + +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.BackgroundBlur; +import io.github.moulberry.notenoughupdates.options.customtypes.NEUDebugFlag; +import io.github.moulberry.notenoughupdates.options.seperateSections.DungeonMapConfig; +import io.github.moulberry.notenoughupdates.util.NEUResourceManager; +import io.github.moulberry.notenoughupdates.util.SpecialColour; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.shader.Framebuffer; +import net.minecraft.client.shader.Shader; +import net.minecraft.util.Matrix4f; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +import static io.github.moulberry.notenoughupdates.util.Utils.ensureFramebufferSize; +import static org.lwjgl.opengl.GL11.GL_MODELVIEW; +import static org.lwjgl.opengl.GL11.GL_PROJECTION; + +public class DungeonMapRenderer { + + DungeonMap map; + + public Framebuffer mapFramebuffer1 = null; + public Framebuffer mapFramebuffer2 = null; + public Matrix4f projectionMatrix = null; + public Shader mapShader = null; + DungeonMapConfig config; + private final HashMap<Integer, Float> borderRadiusCache = new HashMap<>(); + + public DungeonMapRenderer(DungeonMap dungeonMap, DungeonMapConfig config) { + this.map = dungeonMap; + this.config = config; + } + + private static void upload( + Shader shader, + Matrix4f projectionMatrix, + int width, + int height, + int scale, + float radiusSq + ) { + if (shader == null) return; + shader.getShaderManager().getShaderUniformOrDefault("ProjMat").set(projectionMatrix); + shader.getShaderManager().getShaderUniformOrDefault("InSize").set(width * scale, height * scale); + shader.getShaderManager().getShaderUniformOrDefault("OutSize").set(width, height); + shader.getShaderManager().getShaderUniformOrDefault("ScreenSize").set((float) width, (float) height); + shader.getShaderManager().getShaderUniformOrDefault("radiusSq").set(radiusSq); + } + + public void render(int centerX, int centerY, DungeonMapStaticParser data, DungeonMapPlayers players) { + boolean useFb = config.dmCompat <= 1 && OpenGlHelper.isFramebufferEnabled(); + boolean useShd = config.dmCompat <= 0 && OpenGlHelper.areShadersSupported(); + + ScaledResolution scaledResolution = Utils.pushGuiScale(2); + + int borderSizeOption = Math.round(config.dmBorderSize); + + int backgroundSize; + if (config.dmBorderStyle <= 1) { + backgroundSize = 80 + Math.round(40 * config.dmBorderSize); + } else { + backgroundSize = borderSizeOption == 0 ? 90 : borderSizeOption == 1 ? 120 : borderSizeOption == 2 ? 160 : 240; + } + int backgroundCenter = backgroundSize / 2; + int scaleFactor = 8; + + float mapSize = backgroundSize * config.dmRoomSize; + float pixelToMapScale = mapSize / 128F; + float renderRoomSize = data.roomSize * pixelToMapScale; + float renderConnSize = data.connectorSize * pixelToMapScale; + + projectionMatrix = Utils.createProjectionMatrix(backgroundSize * scaleFactor, backgroundSize * scaleFactor); + mapFramebuffer1 = ensureFramebufferSize( + mapFramebuffer1, + backgroundSize * scaleFactor, + backgroundSize * scaleFactor + ); + mapFramebuffer2 = ensureFramebufferSize( + mapFramebuffer2, + backgroundSize * scaleFactor, + backgroundSize * scaleFactor + ); + mapFramebuffer1.framebufferColor[1] = 0; + mapFramebuffer1.framebufferColor[2] = 0; + + try { + if (mapShader == null) { + mapShader = new Shader(new NEUResourceManager(Minecraft.getMinecraft().getResourceManager()), + "dungeonmap", mapFramebuffer1, mapFramebuffer2 + ); + } + } catch (Exception e) { + e.printStackTrace(); + Utils.pushGuiScale(-1); + return; + } + + int backgroundColour = SpecialColour.specialToChromaRGB(config.dmBackgroundColour); + + mapFramebuffer1.framebufferColor[0] = ((backgroundColour >> 16) & 0xFF) / 255f; + mapFramebuffer1.framebufferColor[1] = ((backgroundColour >> 8) & 0xFF) / 255f; + mapFramebuffer1.framebufferColor[2] = (backgroundColour & 0xFF) / 255f; + mapFramebuffer2.framebufferColor[0] = ((backgroundColour >> 16) & 0xFF) / 255f; + mapFramebuffer2.framebufferColor[1] = ((backgroundColour >> 8) & 0xFF) / 255f; + mapFramebuffer2.framebufferColor[2] = (backgroundColour & 0xFF) / 255f; + + try { + if (useFb) { + mapFramebuffer1.framebufferClear(); + mapFramebuffer2.framebufferClear(); + } + + GlStateManager.pushMatrix(); + { + if (useFb) { + GlStateManager.matrixMode(GL_PROJECTION); + GlStateManager.loadIdentity(); + GlStateManager.ortho( + 0.0D, + backgroundSize * scaleFactor, + backgroundSize * scaleFactor, + 0.0D, + 1000.0D, + 3000.0D + ); + GlStateManager.matrixMode(GL_MODELVIEW); + GlStateManager.loadIdentity(); + GlStateManager.translate(0.0F, 0.0F, -2000.0F); + + GlStateManager.scale(scaleFactor, scaleFactor, 1); + mapFramebuffer1.bindFramebuffer(true); + + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + GlStateManager.disableBlend(); + } else { + GL11.glEnable(GL11.GL_SCISSOR_TEST); + GL11.glScissor( + (centerX - backgroundSize / 2) * 2, + Minecraft.getMinecraft().displayHeight - (centerY + backgroundSize / 2) * 2, + backgroundSize * 2, + backgroundSize * 2 + ); + + GlStateManager.translate(centerX - backgroundSize / 2F, centerY - backgroundSize / 2F, 100); + } + + if (config.dmBackgroundBlur > 0.1 && config.dmBackgroundBlur < 100 && config.dmEnable) { + GlStateManager.translate(-centerX + backgroundSize / 2F, -centerY + backgroundSize / 2F, 0); + BackgroundBlur.renderBlurredBackground(config.dmBackgroundBlur, + scaledResolution.getScaledWidth(), scaledResolution.getScaledHeight(), + centerX - backgroundSize / 2, centerY - backgroundSize / 2, backgroundSize, backgroundSize + ); + BackgroundBlur.markDirty(); + GlStateManager.translate(centerX - backgroundSize / 2F, centerY - backgroundSize / 2F, 0); + } + + GlStateManager.translate(backgroundCenter, backgroundCenter, 10); + + if (!useFb || config.dmBackgroundBlur > 0.1 && config.dmBackgroundBlur < 100) { + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate( + GL11.GL_SRC_ALPHA, + GL11.GL_ONE_MINUS_SRC_ALPHA, + GL11.GL_ONE, + GL11.GL_ONE_MINUS_SRC_ALPHA + ); + } + Utils.drawRectNoBlend( + -backgroundCenter, + -backgroundCenter, + backgroundCenter, + backgroundCenter, + backgroundColour + ); + + float rotation = players.getMainPlayerRotation() + 180; + + if (!config.dmRotatePlayer) + rotation = 0F; + GlStateManager.rotate(-rotation, 0, 0, 1); + + if (config.dmCenterPlayer) { + float x = players.getMainPlayerX() * pixelToMapScale; + float y = players.getMainPlayerZ() * pixelToMapScale; + + GlStateManager.translate(-x, -y, 0); + } else { + GlStateManager.translate(-mapSize / 2F, -mapSize / 2F, 0); + } + + for (Map.Entry<RoomOffset, Room> entry : data.roomMap.entrySet()) { + Room room = entry.getValue(); + + GlStateManager.pushMatrix(); + GlStateManager.translate(room.posX * pixelToMapScale, room.posY * pixelToMapScale, 0); + + room.render(renderRoomSize, renderConnSize); + + GlStateManager.popMatrix(); + } + + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + + for (Map.Entry<RoomOffset, Room> entry : data.roomMap.entrySet()) { + Room room = entry.getValue(); + + GlStateManager.pushMatrix(); + + GlStateManager.translate(room.posX * pixelToMapScale, room.posY * pixelToMapScale, 0); + room.renderCheckmark(renderRoomSize, renderConnSize, rotation); + + GlStateManager.popMatrix(); + } + + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + int k = 0; + for (Map.Entry<String, DungeonMapPlayers.PlayerMarker> entry : players.getRunnerPositions().entrySet()) { + renderPlayer( + players, + pixelToMapScale, + renderRoomSize, + tessellator, + worldrenderer, + k--, + entry.getKey(), + entry.getValue() + ); + } + for (DungeonMapPlayers.PlayerMarker orphanedMarker : players.getOrphanedMarkers().values()) { + renderPlayer( + players, + pixelToMapScale, + renderRoomSize, + tessellator, + worldrenderer, + k--, + null, + orphanedMarker + ); + } + if (NEUDebugFlag.MAP.isSet()) + players.getAllMapPositions().forEach((label, playerMarker) -> { + float x = playerMarker.x * pixelToMapScale; + float y = playerMarker.z * pixelToMapScale; + Utils.drawStringF(label, Minecraft.getMinecraft().fontRendererObj, x, y, true, 0xffd3d3d3); + }); + + if (useFb) { + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate( + GL11.GL_SRC_ALPHA, + GL11.GL_ONE_MINUS_SRC_ALPHA, + GL11.GL_ONE, + GL11.GL_ONE_MINUS_SRC_ALPHA + ); + } else { + GL11.glDisable(GL11.GL_SCISSOR_TEST); + } + } + GlStateManager.popMatrix(); + + if (useFb) { + Framebuffer renderFromBuffer = mapFramebuffer1; + if (useShd) { + GlStateManager.pushMatrix(); + { + try { + upload(mapShader, projectionMatrix, backgroundSize, backgroundSize, scaleFactor, getBorderRadius()); + mapShader.setProjectionMatrix(projectionMatrix); + mapShader.loadShader(0); + renderFromBuffer = mapFramebuffer2; + } catch (Exception ignored) { + } + } + GlStateManager.popMatrix(); + } + + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); + + Utils.pushGuiScale(2); + + GlStateManager.translate(centerX, centerY, 100); + + renderFromBuffer.bindFramebufferTexture(); + Utils.drawTexturedRect(-backgroundSize / 2F, -backgroundSize / 2F, backgroundSize, backgroundSize, + 0, 1, 1, 0, GL11.GL_NEAREST + ); + GlStateManager.bindTexture(0); + + GlStateManager.translate(-centerX, -centerY, -100); + + Utils.pushGuiScale(-1); + } + + GlStateManager.translate(centerX, centerY, 100); + + if (config.dmChromaBorder) { + int colour = SpecialColour.specialToChromaRGB(config.dmBorderColour); + + Gui.drawRect(-backgroundCenter - 2, -backgroundCenter - 2, -backgroundCenter, -backgroundCenter, + colour + ); //topleft + Gui.drawRect(-backgroundCenter - 2, backgroundCenter + 2, -backgroundCenter, backgroundCenter, + SpecialColour.rotateHue(colour, -180) + ); //bottomleft + Gui.drawRect(backgroundCenter, -backgroundCenter - 2, backgroundCenter + 2, backgroundCenter, + SpecialColour.rotateHue(colour, -180) + ); //topright + Gui.drawRect(backgroundCenter, backgroundCenter, backgroundCenter + 2, backgroundCenter + 2, + colour + ); //bottomright + + for (int i = 0; i < 20; i++) { + int start1 = SpecialColour.rotateHue(colour, -9 * i); + int start2 = SpecialColour.rotateHue(colour, -9 * i - 9); + int end1 = SpecialColour.rotateHue(colour, -180 - 9 * i); + int end2 = SpecialColour.rotateHue(colour, -180 - 9 * i - 9); + + Utils.drawGradientRect( + -backgroundCenter - 2, + -backgroundCenter + (int) (backgroundSize * (i / 20f)), + -backgroundCenter, + -backgroundCenter + (int) (backgroundSize * ((i + 1) / 20f)), + start1, + start2 + ); //left + Utils.drawGradientRect( + backgroundCenter, + -backgroundCenter + (int) (backgroundSize * (i / 20f)), + backgroundCenter + 2, + -backgroundCenter + (int) (backgroundSize * ((i + 1) / 20f)), + end1, + end2 + ); //right + Utils.drawGradientRectHorz(-backgroundCenter + (int) (backgroundSize * (i / 20f)), -backgroundCenter - 2, + -backgroundCenter + (int) (backgroundSize * ((i + 1) / 20f)), -backgroundCenter, start1, start2 + ); //top + Utils.drawGradientRectHorz(-backgroundCenter + (int) (backgroundSize * (i / 20f)), + backgroundCenter, -backgroundCenter + (int) (backgroundSize * ((i + 1) / 20f)), backgroundCenter + 2, + end1, end2 + ); //bottom + } + + } else { + Gui.drawRect(-backgroundCenter - 2, -backgroundCenter, -backgroundCenter, backgroundCenter, + SpecialColour.specialToChromaRGB(config.dmBorderColour) + ); //left + Gui.drawRect(backgroundCenter, -backgroundCenter, backgroundCenter + 2, backgroundCenter, + SpecialColour.specialToChromaRGB(config.dmBorderColour) + ); //right + Gui.drawRect(-backgroundCenter - 2, -backgroundCenter - 2, backgroundCenter + 2, -backgroundCenter, + SpecialColour.specialToChromaRGB(config.dmBorderColour) + ); //top + Gui.drawRect(-backgroundCenter - 2, backgroundCenter, backgroundCenter + 2, backgroundCenter + 2, + SpecialColour.specialToChromaRGB(config.dmBorderColour) + ); //bottom + } + + String sizeId = borderSizeOption == 0 ? "small" : borderSizeOption == 2 ? "large" : "medium"; + + ResourceLocation rl = new ResourceLocation("notenoughupdates:dungeon_map/borders/" + sizeId + "/" + + config.dmBorderStyle + ".png"); + if (Minecraft.getMinecraft().getTextureManager().getTexture(rl) != null) { + Minecraft.getMinecraft().getTextureManager().bindTexture(rl); + GlStateManager.color(1, 1, 1, 1); + + int size = borderSizeOption == 0 ? 165 : borderSizeOption == 1 ? 220 : borderSizeOption == 2 ? 300 : 440; + Utils.drawTexturedRect(-size / 2, -size / 2, size, size, GL11.GL_NEAREST); + } + + GlStateManager.translate(-centerX, -centerY, -100); + } catch (Exception e) { + e.printStackTrace(); + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); + Minecraft.getMinecraft().entityRenderer.setupOverlayRendering(); + } + + Utils.pushGuiScale(-1); + + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + GlStateManager.enableDepth(); + GlStateManager.disableLighting(); + } + + private void renderPlayer( + DungeonMapPlayers players, + float pixelToMapScale, + float renderRoomSize, + Tessellator tessellator, + WorldRenderer worldrenderer, + int k, + String name, + DungeonMapPlayers.PlayerMarker player + ) { + + float x = player.x * pixelToMapScale; + float y = player.z * pixelToMapScale; + float angle = player.angle; + + boolean isMainPlayer = name != null && name.equals(Minecraft.getMinecraft().thePlayer.getName()); + float minU = isMainPlayer ? 1 / 4F : 3 / 4f; + float minV = 0; + + float maxU = minU + 1 / 4f; + float maxV = minV + 1 / 4f; + + boolean blackBorder = false; + boolean headLayer = false; + int pixelWidth = 8; + int pixelHeight = 8; + if (renderRoomSize >= 24) { + pixelWidth = pixelHeight = 12; + } + GlStateManager.color(1, 1, 1, 1); + if (config.dmPlayerHeads > 0 && (!isMainPlayer || NotEnoughUpdates.INSTANCE.config.dungeons.showOwnHeadAsMarker) && + name != null) { + Minecraft.getMinecraft().getTextureManager().bindTexture(players.getSkin(name)); + + minU = 8 / 64f; + minV = 8 / 64f; + maxU = 16 / 64f; + maxV = 16 / 64f; + + headLayer = true; + if (config.dmPlayerHeads >= 2) { + blackBorder = true; + } + } else { + Minecraft.getMinecraft().getTextureManager().bindTexture(DungeonResources.MAP_ICONS); + } + + GlStateManager.pushMatrix(); + + GlStateManager.disableDepth(); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + + GlStateManager.translate(x, y, -0.02F); + GlStateManager.scale(config.dmIconScale, config.dmIconScale, 1); + GlStateManager.rotate(angle, 0.0F, 0.0F, 1.0F); + + if (blackBorder) { + Gui.drawRect(-pixelWidth / 2 - 1, -pixelHeight / 2 - 1, pixelWidth / 2 + 1, pixelHeight / 2 + 1, 0xff111111); + GlStateManager.color(1, 1, 1, 1); + } + + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); + worldrenderer.pos(-pixelWidth / 2f, pixelHeight / 2f, 30 + ((float) k * -0.005F)).tex(minU, minV).endVertex(); + worldrenderer.pos(pixelWidth / 2f, pixelHeight / 2f, 30 + ((float) k * -0.005F)).tex(maxU, minV).endVertex(); + worldrenderer.pos(pixelWidth / 2f, -pixelHeight / 2f, 30 + ((float) k * -0.005F)).tex(maxU, maxV).endVertex(); + worldrenderer.pos(-pixelWidth / 2f, -pixelHeight / 2f, 30 + ((float) k * -0.005F)).tex(minU, maxV).endVertex(); + tessellator.draw(); + + if (headLayer) { + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); + worldrenderer + .pos(-pixelWidth / 2f, pixelHeight / 2f, 30 + ((float) k * -0.005F) + 0.001f) + .tex(minU + 0.5f, minV) + .endVertex(); + worldrenderer + .pos(pixelWidth / 2f, pixelHeight / 2f, 30 + ((float) k * -0.005F) + 0.001f) + .tex(maxU + 0.5f, minV) + .endVertex(); + worldrenderer + .pos(pixelWidth / 2f, -pixelHeight / 2f, 30 + ((float) k * -0.005F) + 0.001f) + .tex(maxU + 0.5f, maxV) + .endVertex(); + worldrenderer + .pos(-pixelWidth / 2f, -pixelHeight / 2f, 30 + ((float) k * -0.005F) + 0.001f) + .tex(minU + 0.5f, maxV) + .endVertex(); + tessellator.draw(); + } + GlStateManager.popMatrix(); + } + + public float getBorderRadius() { + int borderSizeOption = Math.round(config.dmBorderSize); + String sizeId = borderSizeOption == 0 ? "small" : borderSizeOption == 2 ? "large" : "medium"; + + int style = config.dmBorderStyle; + if (borderRadiusCache.containsKey(style)) { + return borderRadiusCache.get(style); + } + + try ( + BufferedReader reader = new BufferedReader(new InputStreamReader(Minecraft + .getMinecraft() + .getResourceManager() + .getResource( + new ResourceLocation("notenoughupdates:dungeon_map/borders/" + sizeId + "/" + style + ".json")) + .getInputStream(), StandardCharsets.UTF_8)) + ) { + JsonObject json = NotEnoughUpdates.INSTANCE.manager.gson.fromJson(reader, JsonObject.class); + float radiusSq = json.get("radiusSq").getAsFloat(); + + borderRadiusCache.put(style, radiusSq); + return radiusSq; + } catch (Exception ignored) { + } + + borderRadiusCache.put(style, 1f); + return 1f; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/DungeonMapStaticParser.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/DungeonMapStaticParser.java new file mode 100644 index 00000000..c06d2e7a --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/DungeonMapStaticParser.java @@ -0,0 +1,228 @@ +package io.github.moulberry.notenoughupdates.dungeons.map; + +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.util.Vec4b; + +import java.awt.*; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +public class DungeonMapStaticParser { + + public final DungeonMap dungeonMap; + public final Color[][] colorMap; + public final Map<String, Vec4b> mapDecorations; + public final String floorName; + public Map<RoomOffset, Room> roomMap = new HashMap<>(); + int startRoomX, startRoomY; + int connectorSize = 5; + int roomSize = 0; + + public DungeonMapStaticParser(DungeonMap dungeonMap, String floorName, Color[][] colorMap, Map<String, Vec4b> mapDecorations) { + this.dungeonMap = dungeonMap; + this.floorName = floorName; + this.colorMap = colorMap; + this.mapDecorations = mapDecorations; + } + + public Color getColor(int x, int y) { + if (x < 0 || y < 0) return null; + if (x >= colorMap.length || y >= colorMap[0].length) return null; + return colorMap[x][y]; + } + + public Map<Color, Integer> aggregateColorInRectangle(int minX, int minY, int width, int height, int minAlpha) { + Map<Color, Integer> map = new HashMap<>(); + int maxX = Math.min(minX + width, colorMap.length); + int maxY = Math.min(minY + height, colorMap[0].length); + for (int x = Math.max(0, minX); x < maxX; x++) { + for (int y = Math.max(0, minY); y < maxY; y++) { + Color color = colorMap[x][y]; + if (color.getAlpha() < minAlpha) continue; + if (map.containsKey(color)) + map.put(color, map.get(color) + 1); + else + map.put(color, 1); + } + } + + return map; + } + + public void updateRoomConnections(RoomOffset roomOffset) { + if (!roomMap.containsKey(roomOffset)) return; + + Room room = roomMap.get(roomOffset); + + Map<Color, Integer> aggregateColors = aggregateColorInRectangle( + startRoomX + roomOffset.x * (roomSize + connectorSize), + startRoomY + roomOffset.y * (roomSize + connectorSize), + roomSize, roomSize, 0 + ); + + aggregateColors.entrySet().stream().filter(it -> !it.getKey().equals(room.colour)) + .max(Comparator.comparingInt(Map.Entry::getValue)) + .filter(it -> (float) it.getValue() / roomSize / connectorSize > 0.05) + .ifPresent(it -> { + room.checkmark = DungeonResources.Checkmark.valueOfColor(it.getKey()); + }); + + for (int k = 0; k < 4; k++) { + boolean isVerticalDirection = (k % 2) == 0; + + int width = isVerticalDirection ? roomSize : connectorSize; + int height = isVerticalDirection ? connectorSize : roomSize; + int x = startRoomX + roomOffset.x * (roomSize + connectorSize); + int y = startRoomY + roomOffset.y * (roomSize + connectorSize); + + if (k == 0) { + y -= connectorSize; + } else if (k == 1) { + x -= connectorSize; + } else if (k == 2) { + y += roomSize; + } else { + x += roomSize; + } + + Optional<Map.Entry<Color, Integer>> highestColor = aggregateColorInRectangle(x, y, width, height, 40).entrySet().stream().max(Comparator.comparingInt(Map.Entry::getValue)); + if (!highestColor.isPresent()) continue; + + float proportionFilled = (float) highestColor.get().getValue() / roomSize / connectorSize; + + RoomConnectionType type = RoomConnectionType.WALL; + if (proportionFilled > 0.8) { + type = RoomConnectionType.ROOM_DIVIDER; + } else if (proportionFilled > 0.1) { + type = RoomConnectionType.CORRIDOR; + } + Color color = highestColor.get().getKey(); + if (k == 0) { + room.up = new RoomConnection(type, color); + } else if (k == 1) { + room.left = new RoomConnection(type, color); + } else if (k == 2) { + room.down = new RoomConnection(type, color); + } else { + room.right = new RoomConnection(type, color); + } + } + + int x = startRoomX + roomOffset.x * (roomSize + connectorSize) + roomSize + connectorSize / 2; + int y = startRoomY + roomOffset.y * (roomSize + connectorSize) + roomSize + connectorSize / 2; + + room.fillCorner = false; + if (x > 0 && y > 0 && x < colorMap.length && y < colorMap[x].length) { + Color pixel = colorMap[x][y]; + if (pixel.equals(room.colour)) { + room.fillCorner = true; + } + } + } + + + public boolean recalculateStartRoom() { + for (int x = 0; x < colorMap.length; x++) { + for (int y = 0; y < colorMap[x].length; y++) { + Color c = colorMap[x][y]; + if (c.getAlpha() > 80) { + if (Utils.areRGBColorsEquals(c, DungeonResources.RoomColor.GREEN.getColor())) { + roomSize = 0; + out: + for (int xd = 0; xd <= 20; xd++) { + for (int yd = 0; yd <= 20; yd++) { + Color c2 = getColor(x + xd, y + yd); + if (c2 == null) continue; + + if (c2.getGreen() != 124 || c2.getAlpha() <= 80) { + if (xd < 10 && yd < 10) { + break out; + } + } else { + roomSize = Math.max(roomSize, Math.min(xd + 1, yd + 1)); + } + if (xd == 20 && yd == 20) { + if (roomSize == 0) roomSize = 20; + startRoomX = x; + startRoomY = y; + return true; + } + } + } + } + } + } + } + return false; + } + + public boolean parseDungeonMap() { + + if (!recalculateStartRoom()) + return false; + recalculateConnectorSize(); + + loadNeighbors(new RoomOffset(0, 0)); + for (RoomOffset offset : roomMap.keySet()) { + updateRoomConnections(offset); + } + + return !roomMap.isEmpty(); + } + + public void loadNeighbors(RoomOffset room) { + if (roomMap.containsKey(room)) return; + int x = startRoomX + room.x * (roomSize + connectorSize); + int y = startRoomY + room.y * (roomSize + connectorSize); + Color color = getColor(x, y); + if (color == null || color.getAlpha() <= 100) return; + Room newRoom = new Room(); + newRoom.colour = color; + newRoom.posX = x; + newRoom.posY = y; + roomMap.put(room, newRoom); + for (RoomOffset neighbor : room.getNeighbors()) { + loadNeighbors(neighbor); + } + } + + private void recalculateConnectorSize() { + for (int i = 0; i < roomSize; i++) { + for (int k = 0; k < 4; k++) { + for (int j = 1; j < 8; j++) { + int x; + int y; + + if (k == 0) { + x = startRoomX + i; + y = startRoomY - j; + } else if (k == 1) { + x = startRoomX + roomSize + j - 1; + y = startRoomY + i; + } else if (k == 2) { + x = startRoomX + i; + y = startRoomY + roomSize + j - 1; + } else { + x = startRoomX - j; + y = startRoomY + i; + } + + if (x > 0 && y > 0 && x < colorMap.length && y < colorMap[x].length) { + if (colorMap[x][y].getAlpha() > 80) { + if (j == 1) { + break; + } + connectorSize = Math.min(connectorSize, j - 1); + } + } + } + } + } + + if (connectorSize <= 0) { + connectorSize = 4; + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/DungeonResources.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/DungeonResources.java new file mode 100644 index 00000000..41a6e064 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/DungeonResources.java @@ -0,0 +1,86 @@ +package io.github.moulberry.notenoughupdates.dungeons.map; + +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.util.ResourceLocation; + +import java.awt.Color; +import java.util.Locale; + +public class DungeonResources { + public enum Checkmark { + CROSS("cross", 255, 0, 0), + GREEN("green_check", 0, 124, 0), + QUESTION("question", 13, 13, 13), + WHITE("white_check", 255, 255, 255); + + public final ResourceLocation texture; + public final int r, g, b; + + Checkmark(String name, int r, int g, int b) { + texture = new ResourceLocation("notenoughupdates", "dungeon_map/" + name + ".png"); + this.r = r; + this.g = g; + this.b = b; + } + + public Color getColor() { + return new Color(r, g, b); + } + + public static Checkmark valueOfColor(Color color) { + for (Checkmark checkmark : values()) { + if (Utils.areRGBColorsEquals(checkmark.getColor(), color)) + return checkmark; + } + return null; + } + } + + public enum RoomColor { + BROWN(114, 67, 27), + GRAY(65, 65, 65), + GREEN(0, 124, 0), + ORANGE(216, 127, 51), + PINK(242, 127, 165), + PURPLE(178, 76, 216), + RED(255, 0, 0), + YELLOW(229, 229, 51); + + private final int r, g, b; + private final ResourceLocation roomTexture, corridorTexture; + + RoomColor(int r, int g, int b) { + this.r = r; + this.g = g; + this.b = b; + this.roomTexture = new ResourceLocation("notenoughupdates", "dungeon_map/rooms_default/" + name().toLowerCase(Locale.ROOT) + "_room.png"); + this.corridorTexture = new ResourceLocation("notenoughupdates", "dungeon_map/corridors_default/" + name().toLowerCase(Locale.ROOT) + "_corridor.png"); + } + + public Color getColor() { + return new Color(r, g, b); + } + + public static RoomColor valueOfColor(Color color) { + for (DungeonResources.RoomColor roomColor : DungeonResources.RoomColor.values()) { + if (Utils.areRGBColorsEquals(roomColor.getColor(), color)) { + return roomColor; + } + } + return null; + } + + public ResourceLocation getRoomTexture() { + return roomTexture; + } + + public ResourceLocation getCorridorTexture() { + return corridorTexture; + } + } + + public static final ResourceLocation MAP_ICONS = new ResourceLocation("textures/map/map_icons.png"); + + public static final ResourceLocation DIVIDER_BROWN = new ResourceLocation("notenoughupdates:dungeon_map/dividers_default/brown_divider.png"); + public static final ResourceLocation CORNER_BROWN = new ResourceLocation("notenoughupdates:dungeon_map/corners_default/brown_corner.png"); +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/Room.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/Room.java new file mode 100644 index 00000000..585f3d72 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/Room.java @@ -0,0 +1,122 @@ +package io.github.moulberry.notenoughupdates.dungeons.map; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; + +import java.awt.Color; + +class Room { + Color colour = new Color(0, 0, 0, 0); + DungeonResources.Checkmark checkmark = null; + boolean fillCorner = false; + int posX, posY; + + RoomConnection left = new RoomConnection(RoomConnectionType.NONE, new Color(0, true)); + RoomConnection up = new RoomConnection(RoomConnectionType.NONE, new Color(0, true)); + RoomConnection right = new RoomConnection(RoomConnectionType.NONE, new Color(0, true)); + RoomConnection down = new RoomConnection(RoomConnectionType.NONE, new Color(0, true)); + + public void renderCheckmark(float roomSize, float connectorSize, float rotation) { + if (checkmark == null) return; + Minecraft.getMinecraft().getTextureManager().bindTexture(checkmark.texture); + float x = roomSize / 2; + float y = roomSize / 2; + + if (NotEnoughUpdates.INSTANCE.config.dungeonMap.dmCenterCheck) { // TODO extract config option + if (fillCorner) { + x += (roomSize + connectorSize) / 2F; + y += (roomSize + connectorSize) / 2F; + } + if (down.type == RoomConnectionType.ROOM_DIVIDER && right.type != RoomConnectionType.ROOM_DIVIDER) { + y += (roomSize + connectorSize) / 2f; + } else if (down.type != RoomConnectionType.ROOM_DIVIDER && right.type == RoomConnectionType.ROOM_DIVIDER) { + x += (roomSize + connectorSize) / 2f; + } + } + GlStateManager.translate(x, y, 0); + if (NotEnoughUpdates.INSTANCE.config.dungeonMap.dmOrientCheck) { + GlStateManager.rotate(rotation, 0, 0, 1); + } + GlStateManager.scale(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmIconScale, + NotEnoughUpdates.INSTANCE.config.dungeonMap.dmIconScale, 1); + Utils.drawTexturedRect(-5, -5, 10, 10, GL11.GL_NEAREST); + } + + public void render(float roomSize, float connectorSize) { + DungeonResources.RoomColor roomColor = DungeonResources.RoomColor.valueOfColor(this.colour); + if (roomColor != null) { + Minecraft.getMinecraft().getTextureManager().bindTexture(roomColor.getRoomTexture()); + GlStateManager.color(1, 1, 1, 1); + Utils.drawTexturedRect(0, 0, roomSize, roomSize, GL11.GL_LINEAR); + } else { + Gui.drawRect(0, 0, (int) roomSize, (int) roomSize, colour.getRGB()); + } + + if (fillCorner) { + GlStateManager.color(1, 1, 1, 1); + Minecraft.getMinecraft().getTextureManager().bindTexture(DungeonResources.CORNER_BROWN); + Utils.drawTexturedRect(roomSize, roomSize, connectorSize, connectorSize, GL11.GL_NEAREST); + } + + for (RoomConnection connection : new RoomConnection[]{down, right}) { + ResourceLocation corridorTex = null; + switch (connection.type) { + case CORRIDOR: + DungeonResources.RoomColor corridorColor = DungeonResources.RoomColor.valueOfColor(connection.colour); + if (corridorColor != null) + corridorTex = corridorColor.getCorridorTexture(); + break; + case ROOM_DIVIDER: + corridorTex = DungeonResources.DIVIDER_BROWN; + break; + default: + continue; + } + + if (corridorTex == null) { + int xOffset = 0; + int yOffset = 0; + int width = 0; + int height = 0; + + if (connection == right) { + xOffset = (int) roomSize; + width = (int) connectorSize; + height = (int) roomSize; + + if (connection.type == RoomConnectionType.CORRIDOR) { + height = 8; + yOffset += 4; + } + } else if (connection == down) { + yOffset = (int) roomSize; + width = (int) roomSize; + height = (int) connectorSize; + + if (connection.type == RoomConnectionType.CORRIDOR) { + width = 8; + xOffset += 4; + } + } + + Gui.drawRect(xOffset, yOffset, xOffset + width + 1, yOffset + height + 1, connection.colour.getRGB()); + } else { + GlStateManager.color(1, 1, 1, 1); + Minecraft.getMinecraft().getTextureManager().bindTexture(corridorTex); + GlStateManager.pushMatrix(); + if (connection == right) { + GlStateManager.translate(roomSize / 2f, roomSize / 2f, 0); + GlStateManager.rotate(-90, 0, 0, 1); + GlStateManager.translate(-roomSize / 2f, -roomSize / 2f, 0); + } + Utils.drawTexturedRect(0, roomSize, roomSize, connectorSize, GL11.GL_NEAREST); + GlStateManager.popMatrix(); + } + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/RoomConnection.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/RoomConnection.java new file mode 100644 index 00000000..04f701d2 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/RoomConnection.java @@ -0,0 +1,28 @@ +package io.github.moulberry.notenoughupdates.dungeons.map; + +import java.awt.Color; +import java.util.Objects; + +class RoomConnection { + RoomConnectionType type; + Color colour; + + public RoomConnection(RoomConnectionType type, Color colour) { + this.type = type; + this.colour = colour; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RoomConnection that = (RoomConnection) o; + return type == that.type && + Objects.equals(colour, that.colour); + } + + @Override + public int hashCode() { + return Objects.hash(type, colour); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/RoomConnectionType.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/RoomConnectionType.java new file mode 100644 index 00000000..6c283279 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/RoomConnectionType.java @@ -0,0 +1,5 @@ +package io.github.moulberry.notenoughupdates.dungeons.map; + +enum RoomConnectionType { + NONE, WALL, CORRIDOR, ROOM_DIVIDER +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/RoomOffset.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/RoomOffset.java new file mode 100644 index 00000000..32bb8e78 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/map/RoomOffset.java @@ -0,0 +1,46 @@ +package io.github.moulberry.notenoughupdates.dungeons.map; + +import java.util.Objects; + +class RoomOffset { + int x; + int y; + + public RoomOffset(int x, int y) { + this.x = x; + this.y = y; + } + + public RoomOffset left() { + return new RoomOffset(x - 1, y); + } + + public RoomOffset right() { + return new RoomOffset(x + 1, y); + } + + public RoomOffset up() { + return new RoomOffset(x, y - 1); + } + + public RoomOffset down() { + return new RoomOffset(x, y + 1); + } + + public RoomOffset[] getNeighbors() { + return new RoomOffset[]{left(), right(), up(), down()}; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RoomOffset that = (RoomOffset) o; + return x == that.x && y == that.y; + } + + @Override + public int hashCode() { + return Objects.hash(x, y); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/customtypes/NEUDebugFlag.java b/src/main/java/io/github/moulberry/notenoughupdates/options/customtypes/NEUDebugFlag.java index 8e0e4c11..07f9979e 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/customtypes/NEUDebugFlag.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/customtypes/NEUDebugFlag.java @@ -19,13 +19,54 @@ package io.github.moulberry.notenoughupdates.options.customtypes; +import io.github.moulberry.notenoughupdates.util.NEUDebugLogger; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + public enum NEUDebugFlag { // NOTE: Removing enum values causes gson to remove all debugFlags on load if any removed value is present - METAL, - WISHING, + METAL("Metal Detector Solver"), + WISHING("Wishing Compass Solver"), + MAP("Dungeon Map Player Information"), ; - public static final String FLAG_LIST = - "METAL - Metal Detector Solver\n" + - "WISHING - Wishing Compass Solver"; + private final String description; + + NEUDebugFlag(String description) { + this.description = description; + } + + public String getDescription() { + return description; + } + + public boolean isSet() { + return NEUDebugLogger.isFlagEnabled(this); + } + + public static String getFlagList() { + return renderFlagInformation(Arrays.asList(values())); + } + + public static String getEnabledFlags() { + return renderFlagInformation(Arrays.stream(values()) + .filter(NEUDebugFlag::isSet) + .collect(Collectors.toList())); + } + + public static String renderFlagInformation(List<NEUDebugFlag> flags) { + int maxNameLength = flags.stream() + .mapToInt(it -> it.name().length()) + .max() + .orElse(0); + return flags.stream() + .map(it -> (CharSequence) String.format( + "%-" + maxNameLength + "s" + " - %s", + it.name(), + it.getDescription() + )) + .collect(Collectors.joining("\n")); + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/NEUDebugLogger.java b/src/main/java/io/github/moulberry/notenoughupdates/util/NEUDebugLogger.java index 230b8ae5..17842f43 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/NEUDebugLogger.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/NEUDebugLogger.java @@ -38,11 +38,11 @@ public class NEUDebugLogger { } public static boolean isFlagEnabled(NEUDebugFlag flag) { - return NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.contains(flag); + return allFlagsEnabled || NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.contains(flag); } public static void log(NEUDebugFlag flag, String message) { - if (logMethod != null && (allFlagsEnabled || isFlagEnabled(flag))) { + if (logMethod != null && isFlagEnabled(flag)) { logAlways(message); } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/RecencyList.java b/src/main/java/io/github/moulberry/notenoughupdates/util/RecencyList.java new file mode 100644 index 00000000..00d555fe --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/RecencyList.java @@ -0,0 +1,130 @@ +package io.github.moulberry.notenoughupdates.util; + +import java.time.Duration; +import java.time.Instant; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.Objects; + +public class RecencyList<T> { + + public class Entry<T> { + private final T value; + private Instant timestamp; + private boolean toRemove; + + public Entry(T value, Instant timestamp) { + this.value = value; + this.timestamp = timestamp; + } + + public Instant timesOutAt() { + return timestamp.plus(timeout); + } + + public void refresh() { + timestamp = Instant.now(); + toRemove = false; + } + + public boolean isTimedOut(Instant at) { + return toRemove || timesOutAt().isBefore(at); + } + + @Override + @SuppressWarnings({"unchecked"}) + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Entry<?> entry = (Entry<?>) o; + return Objects.equals(timestamp, entry.timestamp) && Objects.equals(value, entry.value); + } + + @Override + public int hashCode() { + return Objects.hash(timestamp, value); + } + + public T getValue() { + return value; + } + } + + public class Finalized<T> extends AbstractList<T> { + private final List<RecencyList<T>.Entry<T>> unmodifiedCopy; + + public Finalized(List<RecencyList<T>.Entry<T>> unmodifiedCopy) {this.unmodifiedCopy = unmodifiedCopy;} + + @Override + public T get(int index) { + return unmodifiedCopy.get(index).value; + } + + @Override + public int size() { + return unmodifiedCopy.size(); + } + + public List<RecencyList<T>.Entry<T>> getTimedList() { + return unmodifiedCopy; + } + } + + public RecencyList(Duration keepAliveDuration) { + this.timeout = keepAliveDuration; + } + + // I feel like a Map<T, Entry<T>> would be faster, but I really don't care. + private final Duration timeout; + private final List<Entry<T>> entries = new ArrayList<>(); + private List<Entry<T>> unmodifiedCopy = new ArrayList<>(); + private Instant nextCheckAt = null; + private boolean checkNow = false; + + public void ensureTimedOrdering() { + Instant now = Instant.now(); + if (checkNow || (nextCheckAt != null && nextCheckAt.isBefore(now))) { + entries.removeIf(it -> it.isTimedOut(now)); + entries.sort(Comparator.comparing(Entry::timesOutAt)); + unmodifiedCopy = new ArrayList<>(entries); + + nextCheckAt = entries.isEmpty() ? null : entries.get(entries.size() - 1).timesOutAt(); + checkNow = false; + } + } + + public Finalized<T> getList() { + ensureTimedOrdering(); + return new Finalized<>(unmodifiedCopy); + } + + public void add(T value) { + for (Entry<T> entry : entries) { + if (Objects.equals(entry.value, value)) { + entry.refresh(); + return; + } + } + checkNow = true; + entries.add(new Entry<>(value, Instant.now())); + } + + public void remove(T value) { + for (Entry<T> entry : entries) { + if (Objects.equals(entry.value, value)) { + entry.toRemove = true; + checkNow = true; + return; + } + } + } + + public void addAll(Collection<? extends T> collection) { + for (T t : collection) { + add(t); + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java index f45b840c..d474b150 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java @@ -44,6 +44,7 @@ import net.minecraft.client.renderer.entity.RenderItem; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.resources.model.IBakedModel; +import net.minecraft.client.shader.Framebuffer; import net.minecraft.event.ClickEvent; import net.minecraft.event.HoverEvent; import net.minecraft.init.Items; @@ -1970,4 +1971,19 @@ public class Utils { } return -1; } + public static Framebuffer ensureFramebufferSize(Framebuffer framebuffer, int width, int height) { + if (framebuffer == null || framebuffer.framebufferWidth != width || framebuffer.framebufferHeight != height) { + if (framebuffer == null) { + framebuffer = new Framebuffer(width, height, true); + } else { + framebuffer.createBindFramebuffer(width, height); + } + framebuffer.setFramebufferFilter(GL11.GL_NEAREST); + } + return framebuffer; + } + + public static boolean areRGBColorsEquals(Color a, Color b) { + return (a.getRGB() & 0xFFFFFF) == (b.getRGB() & 0xFFFFFF); + } } diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/black_corridor.png b/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/black_corridor.png Binary files differnew file mode 100644 index 00000000..640c5388 --- /dev/null +++ b/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/black_corridor.png |