diff options
| author | CraftyOldMiner <85420839+CraftyOldMiner@users.noreply.github.com> | 2022-03-07 21:44:17 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-03-07 22:44:17 -0500 |
| commit | 73fad7064fb47d9d79ccdb3bab5988df1b9eea6f (patch) | |
| tree | 8b192d2304de3823339f238653e6d55dcfdfd04a /src | |
| parent | 8b630cb7c39e73346d43b1e083b62b30fc3cde8f (diff) | |
| download | NotEnoughUpdates-73fad7064fb47d9d79ccdb3bab5988df1b9eea6f.tar.gz NotEnoughUpdates-73fad7064fb47d9d79ccdb3bab5988df1b9eea6f.tar.bz2 NotEnoughUpdates-73fad7064fb47d9d79ccdb3bab5988df1b9eea6f.zip | |
Wishing Compass Solver, Metal Detector Solver improvements, add /neudiag, other misc changes (#90)
Diffstat (limited to 'src')
17 files changed, 1095 insertions, 204 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java index 5ad82d56..0ed68e06 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java @@ -25,6 +25,7 @@ import io.github.moulberry.notenoughupdates.listener.ItemTooltipListener; import io.github.moulberry.notenoughupdates.listener.NEUEventListener; import io.github.moulberry.notenoughupdates.listener.RenderListener; import io.github.moulberry.notenoughupdates.miscfeatures.CrystalOverlay; +import io.github.moulberry.notenoughupdates.miscfeatures.CrystalWishingCompassSolver; import io.github.moulberry.notenoughupdates.miscfeatures.CustomItemEffects; import io.github.moulberry.notenoughupdates.miscfeatures.DwarvenMinesWaypoints; import io.github.moulberry.notenoughupdates.miscfeatures.EnchantingSolvers; @@ -226,6 +227,7 @@ public class NotEnoughUpdates { MinecraftForge.EVENT_BUS.register(InventoryStorageSelector.getInstance()); MinecraftForge.EVENT_BUS.register(SlotLocking.getInstance()); MinecraftForge.EVENT_BUS.register(FishingHelper.getInstance()); + MinecraftForge.EVENT_BUS.register(CrystalWishingCompassSolver.getInstance()); MinecraftForge.EVENT_BUS.register(new DwarvenMinesTextures()); MinecraftForge.EVENT_BUS.register(CustomBiomes.INSTANCE); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java index de017cb5..5c2bf5c0 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java @@ -40,6 +40,7 @@ public class Commands { ClientCommandHandler.instance.registerCommand(new StatsCommand()); ClientCommandHandler.instance.registerCommand(new DevTestCommand()); ClientCommandHandler.instance.registerCommand(new NullzeeSphereCommand()); + ClientCommandHandler.instance.registerCommand(new DiagCommand()); // Repo Commands ClientCommandHandler.instance.registerCommand(new ResetRepoCommand()); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java index 7caf09cb..53a7894b 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java @@ -24,7 +24,7 @@ import java.util.List; public class DevTestCommand extends ClientCommandBase { private static final List<String> DEV_TESTERS = - Arrays.asList("moulberry", "lucycoconut", "ironm00n", "ariyio", "throwpo", "lrg89", "dediamondpro", "lulonaut"); + Arrays.asList("moulberry", "lucycoconut", "ironm00n", "ariyio", "throwpo", "lrg89", "dediamondpro", "lulonaut", "craftyoldminer"); private static final String[] DEV_FAIL_STRINGS = { "No.", 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 new file mode 100644 index 00000000..88264538 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DiagCommand.java @@ -0,0 +1,90 @@ +package io.github.moulberry.notenoughupdates.commands.dev; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import io.github.moulberry.notenoughupdates.miscfeatures.CrystalMetalDetectorSolver; +import io.github.moulberry.notenoughupdates.miscfeatures.CrystalWishingCompassSolver; +import io.github.moulberry.notenoughupdates.options.customtypes.NEUDebugFlag; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; + +public class DiagCommand extends ClientCommandBase { + public DiagCommand() { + super("neudiag"); + } + + private static final String USAGE_TEXT = EnumChatFormatting.WHITE + + "Usage: /neudiag <metal | wishing | debug>\n\n" + + "/neudiag metal Metal Detector Solver diagnostics\n" + + "/neudiag wishing Wishing Compass Solver diagnostics\n" + + "/neudiag debug\n" + + " <no sub-command> Show current flags\n" + + " <enable | disable> <flag> Enable/disable flag\n"; + + private void showUsage(ICommandSender sender) { + sender.addChatMessage(new ChatComponentText(USAGE_TEXT)); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + if (args.length == 0) { + showUsage(sender); + return; + } + + String command = args[0].toLowerCase(); + switch (command) { + case "metal": + CrystalMetalDetectorSolver.logDiagnosticData(true); + break; + case "wishing": + CrystalWishingCompassSolver.getInstance().logDiagnosticData(true); + break; + case "debug": + if (args.length > 1) { + boolean enablingFlag = true; + String action = args[1]; + switch (action) { + case "disable": + enablingFlag = false; + // falls through + case "enable": + if (args.length != 3) { + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + "You must specify a flag:\n" + + NEUDebugFlag.FLAG_LIST)); + return; + } + + String flagName = args[2].toUpperCase(); + try { + NEUDebugFlag debugFlag = NEUDebugFlag.valueOf(flagName); + if (enablingFlag) { + NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.add(debugFlag); + } else { + NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.remove(debugFlag); + } + } catch (IllegalArgumentException e) { + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + flagName + " is invalid. Valid flags are:\n" + + NEUDebugFlag.FLAG_LIST)); + return; + } + break; + default: + showUsage(sender); + return; + } + } + + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "Effective debug flags: " + + NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.toString())); + break; + default: + showUsage(sender); + return; + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/Line.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/Line.java new file mode 100644 index 00000000..fb134e85 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/Line.java @@ -0,0 +1,90 @@ +package io.github.moulberry.notenoughupdates.core.util; + +import net.minecraft.util.Vec3; + +/** + * Represents a line using two points along the line or a segment with endpoints. + */ +public class Line { + private static final double DOUBLE_EPSILON = 4.94065645841247E-324; + public Vec3 point1; + public Vec3 point2; + + public Line(Vec3 first, Vec3 second) { + point1 = first; + point2 = second; + } + + public Vec3 getMidpoint() { + return new Vec3((point1.xCoord + point2.xCoord) / 2.0, + (point1.yCoord + point2.yCoord) / 2.0, + (point1.zCoord + point2.zCoord) / 2.0); + } + + /** + * Calculates the intersection line segment between 2 lines + * Based on http://paulbourke.net/geometry/pointlineplane/calclineline.cs + * + * @return The intersection {@link Line} or {@code null} if no solution found + */ + public Line getIntersectionLineSegment(Line other) + { + Vec3 p1 = this.point1; + Vec3 p2 = this.point2; + Vec3 p3 = other.point1; + Vec3 p4 = other.point2; + Vec3 p13 = p1.subtract(p3); + Vec3 p43 = p4.subtract(p3); + + if (lengthSquared(p43) < DOUBLE_EPSILON) { + return null; + } + + Vec3 p21 = p2.subtract(p1); + if (lengthSquared(p21) < DOUBLE_EPSILON) { + return null; + } + + double d1343 = p13.xCoord * p43.xCoord + p13.yCoord * p43.yCoord + p13.zCoord * p43.zCoord; + double d4321 = p43.xCoord * p21.xCoord + p43.yCoord * p21.yCoord + p43.zCoord * p21.zCoord; + double d1321 = p13.xCoord * p21.xCoord + p13.yCoord * p21.yCoord + p13.zCoord * p21.zCoord; + double d4343 = p43.xCoord * p43.xCoord + p43.yCoord * p43.yCoord + p43.zCoord * p43.zCoord; + double d2121 = p21.xCoord * p21.xCoord + p21.yCoord * p21.yCoord + p21.zCoord * p21.zCoord; + + double denom = d2121 * d4343 - d4321 * d4321; + if (Math.abs(denom) < DOUBLE_EPSILON) { + return null; + } + double numer = d1343 * d4321 - d1321 * d4343; + + double mua = numer / denom; + double mub = (d1343 + d4321 * (mua)) / d4343; + + Line resultSegment = new Line( + new Vec3 ( + (float)(p1.xCoord + mua * p21.xCoord), + (float)(p1.yCoord + mua * p21.yCoord), + (float)(p1.zCoord + mua * p21.zCoord)), + new Vec3 ( + (float)(p3.xCoord + mub * p43.xCoord), + (float)(p3.yCoord + mub * p43.yCoord), + (float)(p3.zCoord + mub * p43.zCoord))); + + return resultSegment; + } + + public Line getImmutable() { + return new Line(point1, point2); + } + + private static double lengthSquared(Vec3 vec) { + return vec.dotProduct(vec); + } + + public String toString() { + return String.format("point1 = %s, point2 = %s, midpoint = %s", + point1 == null ? "NULL" : point1.toString(), + point2 == null ? "NULL" : point2.toString(), + (point1 == null || point2 == null) ? "NULL" : getMidpoint()); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java index 633cd80f..ebb537dc 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java @@ -209,7 +209,7 @@ public class ChatListener { } if (unformatted.startsWith("You found ") && SBInfo.getInstance().getLocation() != null && SBInfo.getInstance().getLocation().equals("crystal_hollows")) { - CrystalMetalDetectorSolver.reset(true); + CrystalMetalDetectorSolver.resetSolution(true); } if (unformatted.startsWith("[NPC] Keeper of ") | unformatted.startsWith("[NPC] Professor Robot: ") || unformatted.startsWith(" ") || unformatted.startsWith("✦") || unformatted.equals( diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java index ffebdd6b..eeb80abd 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java @@ -140,7 +140,7 @@ public class NEUEventListener { @SubscribeEvent public void onWorldLoad(WorldEvent.Unload event) { NotEnoughUpdates.INSTANCE.saveConfig(); - CrystalMetalDetectorSolver.reset(false); + CrystalMetalDetectorSolver.initWorld(); } @SubscribeEvent diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalMetalDetectorSolver.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalMetalDetectorSolver.java index 4586d190..27c334ad 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalMetalDetectorSolver.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalMetalDetectorSolver.java @@ -2,31 +2,119 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; +import io.github.moulberry.notenoughupdates.options.customtypes.NEUDebugFlag; +import io.github.moulberry.notenoughupdates.util.NEUDebugLogger; import io.github.moulberry.notenoughupdates.util.SBInfo; import net.minecraft.client.Minecraft; -import net.minecraft.util.*; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.IChatComponent; +import net.minecraft.util.Vec3; +import net.minecraft.util.Vec3i; -import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.stream.Collectors; public class CrystalMetalDetectorSolver { private static final Minecraft mc = Minecraft.getMinecraft(); + private static BlockPos prevPlayerPos; private static double prevDistToTreasure = 0; - private static List<BlockPos> possibleBlocks = new ArrayList<>(); - private static final List<BlockPos> locations = new ArrayList<>(); - + private static HashSet<BlockPos> possibleBlocks = new HashSet<>(); + private static final HashMap<BlockPos, Double> evaluatedPlayerPositions = new HashMap<>(); + private static BlockPos blockPosIfLastSolutionInvalid; private static Boolean chestRecentlyFound = false; private static long chestLastFoundMillis = 0; + private static final HashSet<BlockPos> openedChestPositions = new HashSet<>(); + + // Keeper and Mines of Divan center location info + private static Vec3i minesCenter; + private static boolean visitKeeperMessagePrinted = false; + private static String KEEPER_OF_STRING = "Keeper of "; + private static String DIAMOND_STRING = "diamond"; + private static String LAPIS_STRING = "lapis"; + private static String EMERALD_STRING = "emerald"; + private static String GOLD_STRING = "gold"; + private static final HashMap<String, Vec3i> keeperOffsets = new HashMap<String, Vec3i>() {{ + put(DIAMOND_STRING, new Vec3i(33,0,3)); + put(LAPIS_STRING, new Vec3i(-33,0,-3)); + put(EMERALD_STRING, new Vec3i(-3,0,33)); + put(GOLD_STRING, new Vec3i(3,0,-33)); + }}; + + // Chest offsets from center + private static final HashSet<Long> knownChestOffsets = new HashSet<>(Arrays.asList( + -10171958951910L, // x=-38, y=-22, z=26 + 10718829084646L, // x=38, y=-22, z=-26 + -10721714765806L, // x=-40, y=-22, z=18 + -10996458455018L, // x=-41, y=-20, z=22 + -1100920913904L, // x=-5, y=-21, z=16 + 11268584898530L, // x=40, y=-22, z=-30 + -11271269253148L, // x=-42, y=-20, z=-28 + -11546281377832L, // x=-43, y=-22, z=-40 + 11818542038999L, // x=42, y=-19, z=-41 + 12093285728240L, // x=43, y=-21, z=-16 + -1409286164L, // x=-1, y=-22, z=-20 + 1922736062492L, // x=6, y=-21, z=28 + 2197613969419L, // x=7, y=-21, z=11 + 2197613969430L, // x=7, y=-21, z=22 + -3024999153708L, // x=-12, y=-21, z=-44 + 3571936395295L, // x=12, y=-22, z=31 + 3572003504106L, // x=12, y=-22, z=-22 + 3572003504135L, // x=12, y=-21, z=7 + 3572070612949L, // x=12, y=-21, z=-43 + -3574822076373L, // x=-14, y=-21, z=43 + -3574822076394L, // x=-14, y=-21, z=22 + -4399455797228L, // x=-17, y=-21, z=20 + -5224156626944L, // x=-20, y=-22, z=0 + 548346527764L, // x=1, y=-21, z=20 + 5496081743901L, // x=19, y=-22, z=29 + 5770959650816L, // x=20, y=-22, z=0 + 5771093868518L, // x=20, y=-21, z=-26 + -6048790347736L, // x=-23, y=-22, z=40 + 6320849682418L, // x=22, y=-21, z=-14 + -6323668254708L, // x=-24, y=-22, z=12 + 6595593371674L, // x=23, y=-22, z=26 + 6595660480473L, // x=23, y=-22, z=-39 + 6870471278619L, // x=24, y=-22, z=27 + 7145349185553L, // x=25, y=-22, z=17 + 8244995030996L, // x=29, y=-21, z=-44 + -8247679385612L, // x=-31, y=-21, z=-12 + -8247679385640L, // x=-31, y=-21, z=-40 + 8519872937959L, // x=30, y=-21, z=-25 + -8522557292584L, // x=-32, y=-21, z=-40 + -9622068920278L, // x=-36, y=-20, z=42 + -9896946827278L, // x=-37, y=-21, z=-14 + -9896946827286L // x=-37, y=-21, z=-22 + )); public static void process(IChatComponent message) { + if (SBInfo.getInstance().getLocation() == null || + !NotEnoughUpdates.INSTANCE.config.mining.metalDetectorEnabled || + !SBInfo.getInstance().getLocation().equals("crystal_hollows") || + !message.getUnformattedText().contains("TREASURE: ")) { + return; + } + + locateMinesCenterIfNeeded(); + + double distToTreasure = Double.parseDouble(message + .getUnformattedText() + .split("TREASURE: ")[1].split("m")[0].replaceAll("(?!\\.)\\D", "")); + // Delay to keep old chest location from being treated as the new chest location if (chestRecentlyFound) { long currentTimeMillis = System.currentTimeMillis(); if (chestLastFoundMillis == 0) { chestLastFoundMillis = currentTimeMillis; return; - } else if (currentTimeMillis - chestLastFoundMillis < 1000) { + } else if (currentTimeMillis - chestLastFoundMillis < 1000 && distToTreasure < 5.0) { return; } @@ -34,80 +122,239 @@ public class CrystalMetalDetectorSolver { chestRecentlyFound = false; } - if (SBInfo.getInstance().getLocation() != null && SBInfo.getInstance().getLocation().equals("crystal_hollows") - && message.getUnformattedText().contains("TREASURE: ")) { - double distToTreasure = Double.parseDouble(message - .getUnformattedText() - .split("TREASURE: ")[1].split("m")[0].replaceAll("(?!\\.)\\D", "")); - if (NotEnoughUpdates.INSTANCE.config.mining.metalDetectorEnabled && prevDistToTreasure == distToTreasure && - prevPlayerPos.getX() == mc.thePlayer.getPosition().getX() && - prevPlayerPos.getY() == mc.thePlayer.getPosition().getY() && - prevPlayerPos.getZ() == mc.thePlayer.getPosition().getZ() && !locations.contains(mc.thePlayer.getPosition())) { - if (possibleBlocks.size() == 0) { - locations.add(mc.thePlayer.getPosition()); - for (int zOffset = (int) Math.floor(-distToTreasure); zOffset <= Math.ceil(distToTreasure); zOffset++) { - for (int y = 65; y <= 75; y++) { - double calculatedDist = 0; - int xOffset = 0; - while (calculatedDist < distToTreasure) { - BlockPos pos = new BlockPos(Math.floor(mc.thePlayer.posX) + xOffset, - y, Math.floor(mc.thePlayer.posZ) + zOffset - ); - calculatedDist = getPlayerPos().distanceTo(new Vec3(pos).addVector(0D, 1D, 0D)); - if (round(calculatedDist, 1) == distToTreasure && !possibleBlocks.contains(pos) && - treasureAllowed(pos) && mc.theWorld. - getBlockState(pos.add(0, 1, 0)).getBlock().getRegistryName().equals("minecraft:air")) { - possibleBlocks.add(pos); - } - xOffset++; - } - xOffset = 0; - calculatedDist = 0; - while (calculatedDist < distToTreasure) { - BlockPos pos = new BlockPos(Math.floor(mc.thePlayer.posX) - xOffset, - y, Math.floor(mc.thePlayer.posZ) + zOffset - ); - calculatedDist = getPlayerPos().distanceTo(new Vec3(pos).addVector(0D, 1D, 0D)); - if (round(calculatedDist, 1) == distToTreasure && !possibleBlocks.contains(pos) && - treasureAllowed(pos) && mc.theWorld. - getBlockState(pos.add(0, 1, 0)).getBlock().getRegistryName().equals("minecraft:air")) { - possibleBlocks.add(pos); - } - xOffset++; + if (prevDistToTreasure == distToTreasure && + prevPlayerPos.equals(mc.thePlayer.getPosition()) && + !evaluatedPlayerPositions.keySet().contains(mc.thePlayer.getPosition())) { + if (possibleBlocks.size() == 0) { + evaluatedPlayerPositions.put(mc.thePlayer.getPosition(), distToTreasure); + for (int zOffset = (int) Math.floor(-distToTreasure); zOffset <= Math.ceil(distToTreasure); zOffset++) { + for (int y = 65; y <= 75; y++) { + double calculatedDist = 0; + int xOffset = 0; + while (calculatedDist < distToTreasure) { + BlockPos pos = new BlockPos(Math.floor(mc.thePlayer.posX) + xOffset, + y, Math.floor(mc.thePlayer.posZ) + zOffset); + calculatedDist = getPlayerPos().distanceTo(new Vec3(pos).addVector(0D, 1D, 0D)); + if (round(calculatedDist, 1) == distToTreasure && treasureAllowed(pos)) { + possibleBlocks.add(pos); } + xOffset++; } - } - sendMessage(); - } else if (possibleBlocks.size() != 1) { - locations.add(mc.thePlayer.getPosition()); - List<BlockPos> temp = new ArrayList<>(); - for (BlockPos pos : possibleBlocks) { - if (round(getPlayerPos().distanceTo(new Vec3(pos).addVector(0D, 1D, 0D)), 1) == distToTreasure) { - temp.add(pos); + xOffset = 0; + calculatedDist = 0; + while (calculatedDist < distToTreasure) { + BlockPos pos = new BlockPos(Math.floor(mc.thePlayer.posX) - xOffset, + y, Math.floor(mc.thePlayer.posZ) + zOffset); + calculatedDist = getPlayerPos().distanceTo(new Vec3(pos).addVector(0D, 1D, 0D)); + if (round(calculatedDist, 1) == distToTreasure && treasureAllowed(pos)) { + possibleBlocks.add(pos); + } + xOffset++; } } - possibleBlocks = temp; - sendMessage(); - } else { - BlockPos pos = possibleBlocks.get(0); - if (Math.abs(distToTreasure - (getPlayerPos().distanceTo(new Vec3(pos)))) > 5) { - mc.thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.RED + "[NEU] Previous solution is invalid.")); - reset(false); + } + + checkAndDisplaySolutionState(); + } else if (possibleBlocks.size() != 1) { + evaluatedPlayerPositions.put(mc.thePlayer.getPosition().getImmutable(), distToTreasure); + HashSet<BlockPos> temp = new HashSet<>(); + for (BlockPos pos : possibleBlocks) { + if (round(getPlayerPos().distanceTo(new Vec3(pos).addVector(0D, 1D, 0D)), 1) == distToTreasure) { + temp.add(pos); } } + possibleBlocks = temp; + checkAndDisplaySolutionState(); + } else { + BlockPos pos = possibleBlocks.iterator().next(); + if (Math.abs(distToTreasure - (getPlayerPos().distanceTo(new Vec3(pos)))) > 5) { + mc.thePlayer.addChatMessage(new ChatComponentText( + EnumChatFormatting.RED + "[NEU] Previous solution is invalid.")); + blockPosIfLastSolutionInvalid = pos.getImmutable(); + logDiagnosticData(false); + resetSolution(false); + } } + } + + prevPlayerPos = mc.thePlayer.getPosition().getImmutable(); + prevDistToTreasure = distToTreasure; + } + + private static void checkForSingleKnownLocationMatch() { + if (minesCenter == BlockPos.NULL_VECTOR || possibleBlocks.size() < 2) { + return; + } - prevPlayerPos = mc.thePlayer.getPosition(); - prevDistToTreasure = distToTreasure; + HashSet<BlockPos> temp = possibleBlocks.stream() + .filter(block -> knownChestOffsets.contains(block.subtract(minesCenter).toLong())) + .collect(Collectors.toCollection(HashSet::new)); + if (temp.size() == 1) { + possibleBlocks = temp; + NEUDebugLogger.log(NEUDebugFlag.METAL, "Known location identified."); + } else if (temp.size() > 1) { + NEUDebugLogger.log(NEUDebugFlag.METAL, temp.size() + " known locations identified:"); } } - public static void reset(Boolean chestFound) { + private static String getFriendlyBlockPositions(Collection<BlockPos> positions) { + if (!NEUDebugLogger.isFlagEnabled(NEUDebugFlag.METAL) || positions.size() == 0) { + return ""; + } + + StringBuilder sb = new StringBuilder(); + sb.append("\n"); + for (BlockPos blockPos : positions) { + sb.append("Absolute: " + blockPos.toString()); + if (minesCenter != Vec3i.NULL_VECTOR) { + BlockPos relativeOffset = blockPos.subtract(minesCenter); + sb.append(", Relative: " + relativeOffset.toString() + " (" + relativeOffset.toLong() + ")"); + } + sb.append("\n"); + } + + return sb.toString(); + } + + private static String getFriendlyEvaluatedPositions(HashMap<BlockPos, Double> positions) { + if (!NEUDebugLogger.isFlagEnabled(NEUDebugFlag.METAL) || positions.size() == 0) { + return ""; + } + + StringBuilder sb = new StringBuilder(); + sb.append("\n"); + for (BlockPos blockPos : positions.keySet()) { + sb.append("Absolute: " + blockPos.toString()); + if (minesCenter != Vec3i.NULL_VECTOR) { + BlockPos relativeOffset = blockPos.subtract(minesCenter); + sb.append(", Relative: " + relativeOffset.toString() + " (" + relativeOffset.toLong() + ")"); + } + + sb.append(" Distance: "); + sb.append(positions.get(blockPos)); + + sb.append("\n"); + } + + return sb.toString(); + } + + public static void logDiagnosticData(boolean outputAlways) { + if (SBInfo.getInstance().getLocation() == null) { + mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + "[NEU] This command is not available outside SkyBlock")); + return; + } + + if (!NotEnoughUpdates.INSTANCE.config.mining.metalDetectorEnabled) + { + mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + "[NEU] Metal Detector Solver is not enabled.")); + return; + } + + if (!outputAlways && !NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.contains(NEUDebugFlag.METAL)) { + return; + } + + boolean originalDebugFlag = !NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.add(NEUDebugFlag.METAL); + + StringBuilder diagsMessage = new StringBuilder(); + + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("Mines Center: "); + diagsMessage.append(EnumChatFormatting.WHITE); + diagsMessage.append((minesCenter == Vec3i.NULL_VECTOR) ? "<NOT DISCOVERED>" : minesCenter.toString()); + diagsMessage.append("\n"); + + diagsMessage.append("\n"); + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("Previous Player Position: "); + diagsMessage.append(EnumChatFormatting.WHITE); + diagsMessage.append((prevPlayerPos == null) ? "<NONE>" : prevPlayerPos.toString()); + diagsMessage.append("\n"); + + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("Previous Distance To Treasure: "); + diagsMessage.append(EnumChatFormatting.WHITE); + diagsMessage.append((prevDistToTreasure == 0) ? "<NONE>" : prevDistToTreasure); + diagsMessage.append("\n"); + + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("Last Solution Invalid Position: "); + diagsMessage.append(EnumChatFormatting.WHITE); + diagsMessage.append((blockPosIfLastSolutionInvalid == null) ? "<NONE>" : blockPosIfLastSolutionInvalid.toString()); + diagsMessage.append("\n"); + + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("Current Possible Blocks: "); + diagsMessage.append(EnumChatFormatting.WHITE); + diagsMessage.append(possibleBlocks.size()); + diagsMessage.append(getFriendlyBlockPositions(possibleBlocks)); + diagsMessage.append("\n"); + + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("Evaluated player positions: "); + diagsMessage.append(EnumChatFormatting.WHITE); + diagsMessage.append(evaluatedPlayerPositions.size()); + diagsMessage.append(getFriendlyEvaluatedPositions(evaluatedPlayerPositions)); + diagsMessage.append("\n"); + + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("Chest locations not on known list:\n"); + diagsMessage.append(EnumChatFormatting.WHITE); + if (minesCenter != Vec3i.NULL_VECTOR) { + HashSet<BlockPos> locationsNotOnKnownList = openedChestPositions + .stream() + .filter(block -> !knownChestOffsets.contains(block.subtract(minesCenter).toLong())) + .map(block -> block.subtract(minesCenter)) + .collect(Collectors.toCollection(HashSet::new)); + if (locationsNotOnKnownList.size() > 0) { + for (BlockPos blockPos : locationsNotOnKnownList) { + diagsMessage.append(String.format( + "%dL,\t\t// x=%d, y=%d, z=%d", + blockPos.toLong(), + blockPos.getX(), + blockPos.getY(), + blockPos.getZ() + )); + } + } + } else { + diagsMessage.append("<REQUIRES MINES CENTER>"); + } + + NEUDebugLogger.log(NEUDebugFlag.METAL, diagsMessage.toString()); + + if (!originalDebugFlag) { + NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.remove(NEUDebugFlag.METAL); + } + } + + public static void resetSolution(Boolean chestFound) { + if (chestFound) { + blockPosIfLastSolutionInvalid = null; + prevPlayerPos = null; + prevDistToTreasure = 0; + if (possibleBlocks.size() == 1) { + openedChestPositions.add(possibleBlocks.iterator().next().getImmutable());< |
