diff options
author | bowser0000 <bowser0000@gmail.com> | 2021-04-08 08:43:19 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-08 08:43:19 -0400 |
commit | 14efcd8b81763d1c06a4291eeb6a0f1aaeb770fe (patch) | |
tree | 5b58218f51e6f358e5dd15946580dd7b7159c79a /src/main/java/me/Danker/features/puzzlesolvers | |
parent | 435d8dfd5a7f36803ceefcbd245e814ec735aced (diff) | |
parent | 8b1c19bff9ca13034e794ef76086e75aaf59bd14 (diff) | |
download | SkyblockMod-14efcd8b81763d1c06a4291eeb6a0f1aaeb770fe.tar.gz SkyblockMod-14efcd8b81763d1c06a4291eeb6a0f1aaeb770fe.tar.bz2 SkyblockMod-14efcd8b81763d1c06a4291eeb6a0f1aaeb770fe.zip |
Merge pull request #91 from bowser0000/developmentv1.8.6
1.8.6
Diffstat (limited to 'src/main/java/me/Danker/features/puzzlesolvers')
16 files changed, 1933 insertions, 0 deletions
diff --git a/src/main/java/me/Danker/features/puzzlesolvers/BlazeSolver.java b/src/main/java/me/Danker/features/puzzlesolvers/BlazeSolver.java new file mode 100644 index 0000000..0910fc7 --- /dev/null +++ b/src/main/java/me/Danker/features/puzzlesolvers/BlazeSolver.java @@ -0,0 +1,86 @@ +package me.Danker.features.puzzlesolvers; + +import me.Danker.DankersSkyblockMod; +import me.Danker.commands.ToggleCommand; +import me.Danker.utils.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.StringUtils; +import net.minecraft.world.World; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.util.List; + +public class BlazeSolver { + + static Entity highestBlaze = null; + static Entity lowestBlaze = null; + public static int LOWEST_BLAZE_COLOUR; + public static int HIGHEST_BLAZE_COLOUR; + + @SubscribeEvent + public void onWorldChange(WorldEvent.Load event) { + lowestBlaze = null; + highestBlaze = null; + } + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + if (event.phase != TickEvent.Phase.START) return; + + World world = Minecraft.getMinecraft().theWorld; + if (DankersSkyblockMod.tickAmount % 4 == 0) { + if (ToggleCommand.blazeToggled && Utils.inDungeons && world != null) { + List<Entity> entities = world.getLoadedEntityList(); + int highestHealth = 0; + highestBlaze = null; + int lowestHealth = 99999999; + lowestBlaze = null; + + for (Entity entity : entities) { + if (entity.getName().contains("Blaze") && entity.getName().contains("/")) { + String blazeName = StringUtils.stripControlCodes(entity.getName()); + try { + int health = Integer.parseInt(blazeName.substring(blazeName.indexOf("/") + 1, blazeName.length() - 1)); + if (health > highestHealth) { + highestHealth = health; + highestBlaze = entity; + } + if (health < lowestHealth) { + lowestHealth = health; + lowestBlaze = entity; + } + } catch (NumberFormatException ex) { + ex.printStackTrace(); + } + } + } + } + } + } + + @SubscribeEvent + public void onWorldRender(RenderWorldLastEvent event) { + if (ToggleCommand.blazeToggled && Utils.inDungeons) { + if (lowestBlaze != null) { + BlockPos stringPos = new BlockPos(lowestBlaze.posX, lowestBlaze.posY + 1, lowestBlaze.posZ); + Utils.draw3DString(stringPos, EnumChatFormatting.BOLD + "Smallest", LOWEST_BLAZE_COLOUR, event.partialTicks); + AxisAlignedBB aabb = new AxisAlignedBB(lowestBlaze.posX - 0.5, lowestBlaze.posY - 2, lowestBlaze.posZ - 0.5, lowestBlaze.posX + 0.5, lowestBlaze.posY, lowestBlaze.posZ + 0.5); + Utils.draw3DBox(aabb, LOWEST_BLAZE_COLOUR, event.partialTicks); + } + if (highestBlaze != null) { + BlockPos stringPos = new BlockPos(highestBlaze.posX, highestBlaze.posY + 1, highestBlaze.posZ); + Utils.draw3DString(stringPos, EnumChatFormatting.BOLD + "Biggest", HIGHEST_BLAZE_COLOUR, event.partialTicks); + AxisAlignedBB aabb = new AxisAlignedBB(highestBlaze.posX - 0.5, highestBlaze.posY - 2, highestBlaze.posZ - 0.5, highestBlaze.posX + 0.5, highestBlaze.posY, highestBlaze.posZ + 0.5); + Utils.draw3DBox(aabb, HIGHEST_BLAZE_COLOUR, event.partialTicks); + } + } + } + +} diff --git a/src/main/java/me/Danker/features/puzzlesolvers/BoulderSolver.java b/src/main/java/me/Danker/features/puzzlesolvers/BoulderSolver.java new file mode 100644 index 0000000..0089038 --- /dev/null +++ b/src/main/java/me/Danker/features/puzzlesolvers/BoulderSolver.java @@ -0,0 +1,188 @@ +package me.Danker.features.puzzlesolvers; + +import me.Danker.DankersSkyblockMod; +import me.Danker.commands.ToggleCommand; +import me.Danker.utils.BoulderUtils; +import me.Danker.utils.Utils; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.init.Blocks; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.world.World; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class BoulderSolver { + + static boolean prevInBoulderRoom = false; + static boolean inBoulderRoom = false; + static BlockPos chest = null; + static String boulderRoomDirection = null; + public static List<int[]> route = new ArrayList<>(); + static int currentStep = 0; + public static int BOULDER_COLOUR; + public static int BOULDER_ARROW_COLOUR; + + @SubscribeEvent + public void onWorldChange(WorldEvent.Load event) { + reset(); + } + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + if (event.phase != TickEvent.Phase.START) return; + + Minecraft mc = Minecraft.getMinecraft(); + EntityPlayerSP player = mc.thePlayer; + World world = mc.theWorld; + if (DankersSkyblockMod.tickAmount % 20 == 0) { + if (ToggleCommand.boulderToggled && Utils.inDungeons && world != null && player != null) { + // multi thread block checking + new Thread(() -> { + prevInBoulderRoom = inBoulderRoom; + int quartzBlocksFound = 0; + int barriersFound = 0; + BlockPos plusPlusQuartz = null; + BlockPos minusMinusQuartz = null; + Iterable<BlockPos> blocks = BlockPos.getAllInBox(new BlockPos(player.posX - 25, 68, player.posZ - 25), new BlockPos(player.posX + 25, 68, player.posZ + 25)); + // Detect boulder room + for (BlockPos blockPos : blocks) { + if (world.getBlockState(blockPos).getBlock() == Blocks.quartz_block) { + quartzBlocksFound++; + if (plusPlusQuartz == null || (blockPos.getX() >= plusPlusQuartz.getX() && blockPos.getZ() >= plusPlusQuartz.getZ())) { + plusPlusQuartz = blockPos; + } + if (minusMinusQuartz == null || (blockPos.getX() <= minusMinusQuartz.getX() && blockPos.getZ() <= minusMinusQuartz.getZ())) { + minusMinusQuartz = blockPos; + } + if (quartzBlocksFound == 8) { + break; + } + } else if (world.getBlockState(blockPos).getBlock() == Blocks.barrier) { + barriersFound++; + } + } + + if (quartzBlocksFound == 8 && barriersFound >= 350) { + inBoulderRoom = true; + if (!prevInBoulderRoom) { + // Get boulder locations + char[][] board = new char[7][7]; + for (int x = plusPlusQuartz.getX() - 1, iterationX = 0; iterationX < 7; x -= 3, iterationX++) { + for (int z = plusPlusQuartz.getZ() - 1, iterationZ = 0; iterationZ < 7; z -= 3, iterationZ++) { + BlockPos boulderPos = new BlockPos(x, 66, z); + if (world.getBlockState(boulderPos).getBlock() == Blocks.planks) { + board[iterationX][iterationZ] = 'X'; + } + } + } + + // Detect rotation of room + BlockPos northChest = minusMinusQuartz.add(11, -2, -2); + BlockPos eastChest = plusPlusQuartz.add(2, -2, -11); + BlockPos southChest = plusPlusQuartz.add(-11, -2, 2); + BlockPos westChest = minusMinusQuartz.add(-2, -2, 11); + if (world.getBlockState(northChest).getBlock() == Blocks.chest) { + boulderRoomDirection = "north"; + chest = northChest; + board = BoulderUtils.flipVertically(BoulderUtils.rotateClockwise(board)); + } else if (world.getBlockState(eastChest).getBlock() == Blocks.chest) { + boulderRoomDirection = "east"; + chest = eastChest; + board = BoulderUtils.flipHorizontally(board); + } else if (world.getBlockState(southChest).getBlock() == Blocks.chest) { + boulderRoomDirection = "south"; + chest = southChest; + board = BoulderUtils.flipHorizontally(BoulderUtils.rotateClockwise(board)); + } else if (world.getBlockState(westChest).getBlock() == Blocks.chest) { + boulderRoomDirection = "west"; + chest = westChest; + board = BoulderUtils.flipVertically(board); + } else { + player.addChatMessage(new ChatComponentText(DankersSkyblockMod.ERROR_COLOUR + "Could not determine orientation of boulder room.")); + return; + } + board = BoulderUtils.removeFirstRow(board); + if (BoulderUtils.hasOpenPath(board)) return; + + long startTime = System.currentTimeMillis(); + reset(); + int length = BoulderUtils.findSolution(board, 0, route); + long endTime = System.currentTimeMillis(); + System.out.println("Time elapsed: " + (endTime - startTime) + "ms, " + BoulderUtils.iterations + " iterations."); + if (length == 10) { + player.addChatMessage(new ChatComponentText(DankersSkyblockMod.ERROR_COLOUR + "No solution to puzzle found, most likely puzzle failed.")); + } else { + System.out.println("Solved " + boulderRoomDirection + " facing boulder room in " + length + " steps. Path:"); + for (int[] block : route) { + System.out.println(Arrays.toString(block)); + } + } + } + } else { + chest = null; + boulderRoomDirection = null; + inBoulderRoom = false; + } + }).start(); + } + } + } + + @SubscribeEvent + public void onWorldRender(RenderWorldLastEvent event) { + if (ToggleCommand.boulderToggled && Utils.inDungeons && route.size() > 0 && currentStep < route.size() && chest != null) { + int[] currentBlockArray = route.get(currentStep); + AxisAlignedBB currentBoulder = BoulderUtils.getBoulder(currentBlockArray[0], currentBlockArray[1], chest, boulderRoomDirection); + if (currentBoulder == null) return; + Utils.drawFilled3DBox(currentBoulder, BOULDER_COLOUR, true, false, event.partialTicks); + char direction; + switch (currentBlockArray[2]) { + case 1: + direction = 'u'; + break; + case 2: + direction = 'd'; + break; + case 3: + direction = 'l'; + break; + case 4: + direction = 'r'; + break; + default: + return; + } + BoulderUtils.drawArrow(currentBoulder, boulderRoomDirection, direction, 0xFF000000 + BOULDER_ARROW_COLOUR, event.partialTicks); + } + } + + @SubscribeEvent + public void onInteract(PlayerInteractEvent event) { + if (Minecraft.getMinecraft().thePlayer != event.entityPlayer || !inBoulderRoom || !ToggleCommand.boulderToggled) return; + + if (event.action == PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) { + Block block = Minecraft.getMinecraft().theWorld.getBlockState(event.pos).getBlock(); + if (block == Blocks.stone_button) currentStep++; + } + } + + static void reset() { + route.clear(); + currentStep = 0; + BoulderUtils.seenBoardStates.clear(); + BoulderUtils.iterations = 0; + BoulderUtils.fastestSolution = 10; + } + +} diff --git a/src/main/java/me/Danker/features/puzzlesolvers/ChronomatronSolver.java b/src/main/java/me/Danker/features/puzzlesolvers/ChronomatronSolver.java new file mode 100644 index 0000000..208cf9b --- /dev/null +++ b/src/main/java/me/Danker/features/puzzlesolvers/ChronomatronSolver.java @@ -0,0 +1,103 @@ +package me.Danker.features.puzzlesolvers; + +import me.Danker.commands.ToggleCommand; +import me.Danker.events.ChestSlotClickedEvent; +import me.Danker.events.GuiChestBackgroundDrawnEvent; +import me.Danker.handlers.TextRenderer; +import me.Danker.utils.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.init.Blocks; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.StringUtils; +import net.minecraftforge.client.event.GuiOpenEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import java.util.ArrayList; +import java.util.List; + +public class ChronomatronSolver { + + static int lastChronomatronRound = 0; + static List<String> chronomatronPattern = new ArrayList<>(); + static int chronomatronMouseClicks = 0; + public static int CHRONOMATRON_NEXT; + public static int CHRONOMATRON_NEXT_TO_NEXT; + + @SubscribeEvent + public void onSlotClick(ChestSlotClickedEvent event) { + if (ToggleCommand.chronomatronToggled && event.inventoryName.startsWith("Chronomatron (")) { + IInventory inventory = event.inventory; + ItemStack item = event.item; + if (item == null) return; + + if (inventory.getStackInSlot(49).getDisplayName().startsWith("§7Timer: §a") && (item.getItem() == Item.getItemFromBlock(Blocks.stained_glass) || item.getItem() == Item.getItemFromBlock(Blocks.stained_hardened_clay))) { + chronomatronMouseClicks++; + } + } + } + + @SubscribeEvent + public void onGuiRender(GuiChestBackgroundDrawnEvent event) { + if (ToggleCommand.chronomatronToggled && event.displayName.startsWith("Chronomatron (")) { + int chestSize = event.chestSize; + List<Slot> invSlots = event.slots; + if (invSlots.size() > 48 && invSlots.get(49).getStack() != null) { + if (invSlots.get(49).getStack().getDisplayName().startsWith("§7Timer: §a") && invSlots.get(4).getStack() != null) { + int round = invSlots.get(4).getStack().stackSize; + int timerSeconds = Integer.parseInt(StringUtils.stripControlCodes(invSlots.get(49).getStack().getDisplayName()).replaceAll("[^\\d]", "")); + if (round != lastChronomatronRound && timerSeconds == round + 2) { + lastChronomatronRound = round; + for (int i = 10; i <= 43; i++) { + ItemStack stack = invSlots.get(i).getStack(); + if (stack == null) continue; + if (stack.getItem() == Item.getItemFromBlock(Blocks.stained_hardened_clay)) { + chronomatronPattern.add(stack.getDisplayName()); + break; + } + } + } + if (chronomatronMouseClicks < chronomatronPattern.size()) { + for (int i = 10; i <= 43; i++) { + ItemStack glass = invSlots.get(i).getStack(); + if (glass == null) continue; + + Slot glassSlot = invSlots.get(i); + + if (chronomatronMouseClicks + 1 < chronomatronPattern.size()) { + if (chronomatronPattern.get(chronomatronMouseClicks).equals(chronomatronPattern.get(chronomatronMouseClicks + 1))) { + if (glass.getDisplayName().equals(chronomatronPattern.get(chronomatronMouseClicks))) { + Utils.drawOnSlot(chestSize, glassSlot.xDisplayPosition, glassSlot.yDisplayPosition, CHRONOMATRON_NEXT + 0xE5000000); + } + } else if (glass.getDisplayName().equals(chronomatronPattern.get(chronomatronMouseClicks))) { + Utils.drawOnSlot(chestSize, glassSlot.xDisplayPosition, glassSlot.yDisplayPosition, CHRONOMATRON_NEXT + 0xE5000000); + } else if (glass.getDisplayName().equals(chronomatronPattern.get(chronomatronMouseClicks + 1))) { + Utils.drawOnSlot(chestSize, glassSlot.xDisplayPosition, glassSlot.yDisplayPosition, CHRONOMATRON_NEXT_TO_NEXT + 0XBE000000); + } + } else if (glass.getDisplayName().equals(chronomatronPattern.get(chronomatronMouseClicks))) { + Utils.drawOnSlot(chestSize, glassSlot.xDisplayPosition, glassSlot.yDisplayPosition, CHRONOMATRON_NEXT + 0xE5000000); + } + } + } + } else if (invSlots.get(49).getStack().getDisplayName().equals("§aRemember the pattern!")) { + chronomatronMouseClicks = 0; + } + } + Minecraft mc = Minecraft.getMinecraft(); + ScaledResolution sr = new ScaledResolution(mc); + int guiLeft = (sr.getScaledWidth() - 176) / 2; + new TextRenderer(mc, String.join("\n", chronomatronPattern), (int) (guiLeft * 0.8), 10, 1); + } + } + + @SubscribeEvent + public void onGuiOpen(GuiOpenEvent event) { + lastChronomatronRound = 0; + chronomatronPattern.clear(); + chronomatronMouseClicks = 0; + } + +} diff --git a/src/main/java/me/Danker/features/puzzlesolvers/ClickInOrderSolver.java b/src/main/java/me/Danker/features/puzzlesolvers/ClickInOrderSolver.java new file mode 100644 index 0000000..e503b37 --- /dev/null +++ b/src/main/java/me/Danker/features/puzzlesolvers/ClickInOrderSolver.java @@ -0,0 +1,107 @@ +package me.Danker.features.puzzlesolvers; + +import me.Danker.commands.ToggleCommand; +import me.Danker.events.GuiChestBackgroundDrawnEvent; +import me.Danker.utils.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.init.Blocks; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraftforge.client.event.GuiOpenEvent; +import net.minecraftforge.event.entity.player.ItemTooltipEvent; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.util.List; + +public class ClickInOrderSolver { + + static Slot[] clickInOrderSlots = new Slot[36]; + static int[] terminalNumberNeeded = new int[4]; + public static int CLICK_IN_ORDER_NEXT; + public static int CLICK_IN_ORDER_NEXT_TO_NEXT; + + @SubscribeEvent(priority = EventPriority.LOW) + public void onTooltipLow(ItemTooltipEvent event) { + if (!Utils.inSkyblock) return; + if (event.toolTip == null) return; + + Minecraft mc = Minecraft.getMinecraft(); + EntityPlayerSP player = mc.thePlayer; + + if (mc.currentScreen instanceof GuiChest) { + ContainerChest chest = (ContainerChest) player.openContainer; + IInventory inv = chest.getLowerChestInventory(); + String chestName = inv.getDisplayName().getUnformattedText(); + + if (ToggleCommand.clickInOrderToggled && chestName.equals("Click in order!")) { + event.toolTip.clear(); + } + } + } + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + if (event.phase != TickEvent.Phase.START) return; + + Minecraft mc = Minecraft.getMinecraft(); + EntityPlayerSP player = mc.thePlayer; + if (mc.currentScreen instanceof GuiChest) { + if (player == null) return; + ContainerChest chest = (ContainerChest) player.openContainer; + List<Slot> invSlots = ((GuiChest) mc.currentScreen).inventorySlots.inventorySlots; + String chestName = chest.getLowerChestInventory().getDisplayName().getUnformattedText().trim(); + + if (ToggleCommand.clickInOrderToggled && chestName.equals("Click in order!")) { + if (terminalNumberNeeded[0] == 0) terminalNumberNeeded[0] = 15; + if (terminalNumberNeeded[2] == 0) terminalNumberNeeded[2] = 15; + for (int i = 10; i <= 25; i++) { + if (i == 17 || i == 18) continue; + ItemStack prevStack = invSlots.get(terminalNumberNeeded[1]).getStack(); + if (prevStack == null) terminalNumberNeeded[0] = 15; + else if (prevStack.getItem() != Item.getItemFromBlock(Blocks.stained_glass_pane)) + terminalNumberNeeded[0] = 15; + else if (prevStack.getItemDamage() == 5) terminalNumberNeeded[0] = 15; + + ItemStack itemStack = invSlots.get(i).getStack(); + if (itemStack == null) continue; + if (itemStack.getItem() != Item.getItemFromBlock(Blocks.stained_glass_pane)) continue; + if (itemStack.getItemDamage() != 14) continue; + if (itemStack.stackSize < terminalNumberNeeded[0]) { + terminalNumberNeeded[0] = itemStack.stackSize; + terminalNumberNeeded[1] = i; + } else if (itemStack.stackSize == terminalNumberNeeded[0] + 1) { + terminalNumberNeeded[2] = itemStack.stackSize; + terminalNumberNeeded[3] = i; + } + } + } + } + } + + @SubscribeEvent + public void onGuiRender(GuiChestBackgroundDrawnEvent event) { + if (ToggleCommand.clickInOrderToggled && event.displayName.equals("Click in order!")) { + int chestSize = event.chestSize; + List<Slot> invSlots = event.slots; + Slot slot = invSlots.get(terminalNumberNeeded[1]); + Utils.drawOnSlot(chestSize, slot.xDisplayPosition, slot.yDisplayPosition, CLICK_IN_ORDER_NEXT + 0xFF000000); + Slot nextSlot = invSlots.get(terminalNumberNeeded[3]); + if (nextSlot != slot && nextSlot.getSlotIndex() != 0) { + Utils.drawOnSlot(chestSize, nextSlot.xDisplayPosition, nextSlot.yDisplayPosition, CLICK_IN_ORDER_NEXT_TO_NEXT + 0xFF000000); + } + } + } + + @SubscribeEvent + public void onGuiOpen(GuiOpenEvent event) { + terminalNumberNeeded = new int[4]; + } + +} diff --git a/src/main/java/me/Danker/features/puzzlesolvers/CreeperSolver.java b/src/main/java/me/Danker/features/puzzlesolvers/CreeperSolver.java new file mode 100644 index 0000000..7ff7e7a --- /dev/null +++ b/src/main/java/me/Danker/features/puzzlesolvers/CreeperSolver.java @@ -0,0 +1,86 @@ +package me.Danker.features.puzzlesolvers; + +import me.Danker.DankersSkyblockMod; +import me.Danker.commands.ToggleCommand; +import me.Danker.utils.Utils; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.entity.monster.EntityCreeper; +import net.minecraft.init.Blocks; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.util.ArrayList; +import java.util.List; + +public class CreeperSolver { + + // Among Us colours + static final int[] CREEPER_COLOURS = {0x50EF39, 0xC51111, 0x132ED1, 0x117F2D, 0xED54BA, 0xEF7D0D, 0xF5F557, 0xD6E0F0, 0x6B2FBB, 0x39FEDC}; + static boolean drawCreeperLines = false; + static Vec3 creeperLocation = new Vec3(0, 0, 0); + static List<Vec3[]> creeperLines = new ArrayList<>(); + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + if (event.phase != TickEvent.Phase.START) return; + + Minecraft mc = Minecraft.getMinecraft(); + World world = mc.theWorld; + EntityPlayerSP player = mc.thePlayer; + if (DankersSkyblockMod.tickAmount % 20 == 0) { + if (ToggleCommand.creeperToggled && Utils.inDungeons && world != null && player != null) { + double x = player.posX; + double y = player.posY; + double z = player.posZ; + // Find creepers nearby + AxisAlignedBB creeperScan = new AxisAlignedBB(x - 14, y - 8, z - 13, x + 14, y + 8, z + 13); // 28x16x26 cube + List<EntityCreeper> creepers = world.getEntitiesWithinAABB(EntityCreeper.class, creeperScan); + // Check if creeper is nearby + if (creepers.size() > 0 && !creepers.get(0).isInvisible()) { // Don't show Wither Cloak creepers + EntityCreeper creeper = creepers.get(0); + // Start creeper line drawings + creeperLines.clear(); + if (!drawCreeperLines) creeperLocation = new Vec3(creeper.posX, creeper.posY + 1, creeper.posZ); + drawCreeperLines = true; + // Search for nearby sea lanterns and prismarine blocks + BlockPos point1 = new BlockPos(creeper.posX - 14, creeper.posY - 7, creeper.posZ - 13); + BlockPos point2 = new BlockPos(creeper.posX + 14, creeper.posY + 10, creeper.posZ + 13); + Iterable<BlockPos> blocks = BlockPos.getAllInBox(point1, point2); + for (BlockPos blockPos : blocks) { + Block block = world.getBlockState(blockPos).getBlock(); + if (block == Blocks.sea_lantern || block == Blocks.prismarine) { + // Connect block to nearest block on opposite side + Vec3 startBlock = new Vec3(blockPos.getX() + 0.5, blockPos.getY() + 0.5, blockPos.getZ() + 0.5); + BlockPos oppositeBlock = Utils.getFirstBlockPosAfterVectors(mc, startBlock, creeperLocation, 10, 20); + BlockPos endBlock = Utils.getNearbyBlock(mc, oppositeBlock, Blocks.sea_lantern, Blocks.prismarine); + if (endBlock != null && startBlock.yCoord > 68 && endBlock.getY() > 68) { // Don't create line underground + // Add to list for drawing + Vec3[] insertArray = {startBlock, new Vec3(endBlock.getX() + 0.5, endBlock.getY() + 0.5, endBlock.getZ() + 0.5)}; + creeperLines.add(insertArray); + } + } + } + } else { + drawCreeperLines = false; + } + } + } + } + + @SubscribeEvent + public void onWorldRender(RenderWorldLastEvent event) { + if (ToggleCommand.creeperToggled && drawCreeperLines && !creeperLines.isEmpty()) { + for (int i = 0; i < creeperLines.size(); i++) { + Utils.draw3DLine(creeperLines.get(i)[0], creeperLines.get(i)[1], CREEPER_COLOURS[i % 10], 2, true, event.partialTicks); + } + } + } + +} diff --git a/src/main/java/me/Danker/features/puzzlesolvers/IceWalkSolver.java b/src/main/java/me/Danker/features/puzzlesolvers/IceWalkSolver.java new file mode 100644 index 0000000..eaabf6e --- /dev/null +++ b/src/main/java/me/Danker/features/puzzlesolvers/IceWalkSolver.java @@ -0,0 +1,287 @@ +package me.Danker.features.puzzlesolvers; + +import me.Danker.DankersSkyblockMod; +import me.Danker.commands.ToggleCommand; +import me.Danker.utils.IceWalkUtils; +import me.Danker.utils.Utils; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class IceWalkSolver { + + static boolean prevInIceWalkRoom = false; + static boolean inIceWalkRoom = false; + static BlockPos chest = null; + static EnumFacing silverfishRoomDirection = null; + static List<IceWalkUtils.Point> threeByThreeRoute = new ArrayList<>(); + static List<IceWalkUtils.Point> fiveByFiveRoute = new ArrayList<>(); + static List<IceWalkUtils.Point> sevenBySevenRoute = new ArrayList<>(); + public static int ICE_WALK_LINE_COLOUR; + + @SubscribeEvent + public void onWorldChange(WorldEvent.Load event) { + reset(); + } + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + if (event.phase != TickEvent.Phase.START) return; + + Minecraft mc = Minecraft.getMinecraft(); + EntityPlayerSP player = mc.thePlayer; + World world = mc.theWorld; + if (DankersSkyblockMod.tickAmount % 20 == 0) { + if (ToggleCommand.iceWalkToggled && Utils.inDungeons && world != null && player != null) { + // multi thread block checking + new Thread(() -> { + boolean foundRoom = false; + prevInIceWalkRoom = inIceWalkRoom; + Iterable<BlockPos> blocks = BlockPos.getAllInBox(new BlockPos(player.posX - 27, 75, player.posZ - 27), new BlockPos(player.posX + 27, 75, player.posZ + 27)); + for (BlockPos blockPos : blocks) { + Block block = world.getBlockState(blockPos).getBlock(); + if (block == Blocks.chest) { + char[][] threeByThreeBoard = new char[4][3]; + char[][] fiveByFiveBoard = new char[6][5]; + char[][] sevenBySevenBoard = new char[8][7]; + + if (world.getBlockState(blockPos.add(0, 7, 2)).getBlock() == Blocks.iron_bars && world.getBlockState(blockPos.add(0, -3, 2)).getBlock() == Blocks.stone_brick_stairs) { + silverfishRoomDirection = EnumFacing.NORTH; + } else if (world.getBlockState(blockPos.add(-2, 7, 0)).getBlock() == Blocks.iron_bars && world.getBlockState(blockPos.add(-2, -3, 0)).getBlock() == Blocks.stone_brick_stairs) { + silverfishRoomDirection = EnumFacing.EAST; + } else if (world.getBlockState(blockPos.add(0, 7, -2)).getBlock() == Blocks.iron_bars && world.getBlockState(blockPos.add(0, -3, -2)).getBlock() == Blocks.stone_brick_stairs) { + silverfishRoomDirection = EnumFacing.SOUTH; + } else if (world.getBlockState(blockPos.add(2, 7, 0)).getBlock() == Blocks.iron_bars && world.getBlockState(blockPos.add(2, -3, 0)).getBlock() == Blocks.stone_brick_stairs) { + silverfishRoomDirection = EnumFacing.WEST; + } else { + return; + } + + foundRoom = true; + inIceWalkRoom = true; + if (!prevInIceWalkRoom) { + chest = blockPos; + switch (silverfishRoomDirection) { + case NORTH: + for (int row = chest.getZ() + 3, xIteration = 0; xIteration < 8; row++, xIteration++) { + for (int column = chest.getX() - 3, yIteration = 0; yIteration < 7; column++, yIteration++) { + if (world.getBlockState(new BlockPos(column, 72, row)).getBlock() != Blocks.air) { + sevenBySevenBoard[xIteration][yIteration] = 'X'; + } + } + } + for (int row = chest.getZ() + 12, xIteration = 0; xIteration < 6; row++, xIteration++) { + for (int column = chest.getX() - 2, yIteration = 0; yIteration < 5; column++, yIteration++) { + if (world.getBlockState(new BlockPos(column, 71, row)).getBlock() != Blocks.air) { + fiveByFiveBoard[xIteration][yIteration] = 'X'; + } + } + } + for (int row = chest.getZ() + 19, xIteration = 0; xIteration < 4; row++, xIteration++) { + for (int column = chest.getX() - 1, yIteration = 0; yIteration < 3; column++, yIteration++) { + if (world.getBlockState(new BlockPos(column, 70, row)).getBlock() != Blocks.air) { + threeByThreeBoard[xIteration][yIteration] = 'X'; + } + } + } + break; + case EAST: + for (int row = chest.getX() - 3, xIteration = 0; xIteration < 8; row--, xIteration++) { + for (int column = chest.getZ() - 3, yIteration = 0; yIteration < 7; column++, yIteration++) { + if (world.getBlockState(new BlockPos(row, 72, column)).getBlock() != Blocks.air) { + sevenBySevenBoard[xIteration][yIteration] = 'X'; + } + } + } + for (int row = chest.getX() - 12, xIteration = 0; xIteration < 6; row--, xIteration++) { + for (int column = chest.getZ() - 2, yIteration = 0; yIteration < 5; column++, yIteration++) { + if (world.getBlockState(new BlockPos(row, 71, column)).getBlock() != Blocks.air) { + fiveByFiveBoard[xIteration][yIteration] = 'X'; + } + } + } + for (int row = chest.getX() - 19, xIteration = 0; xIteration < 4; row--, xIteration++) { + for (int column = chest.getZ() - 1, yIteration = 0; yIteration < 3; column++, yIteration++) { + if (world.getBlockState(new BlockPos(row, 70, column)).getBlock() != Blocks.air) { + threeByThreeBoard[xIteration][yIteration] = 'X'; + } + } + } + break; + case SOUTH: + for (int row = chest.getZ() - 3, xIteration = 0; xIteration < 8; row--, xIteration++) { + for (int column = chest.getX() + 3, yIteration = 0; yIteration < 7; column--, yIteration++) { + if (world.getBlockState(new BlockPos(column, 72, row)).getBlock() != Blocks.air) { + sevenBySevenBoard[xIteration][yIteration] = 'X'; + } + } + } + for (int row = chest.getZ() - 12, xIteration = 0; xIteration < 6; row--, xIteration++) { + for (int column = chest.getX() + 2, yIteration = 0; yIteration < 5; column--, yIteration++) { + if (world.getBlockState(new BlockPos(column, 71, row)).getBlock() != Blocks.air) { + fiveByFiveBoard[xIteration][yIteration] = 'X'; + } + } + } + for (int row = chest.getZ() - 19, xIteration = 0; xIteration < 4; row--, xIteration++) { + for (int column = chest.getX() + 1, yIteration = 0; yIteration < 3; column--, yIteration++) { + if (world.getBlockState(new BlockPos(column, 70, row)).getBlock() != Blocks.air) { + threeByThreeBoard[xIteration][yIteration] = 'X'; + } + } + } + break; + case WEST: + for (int row = chest.getX() + 3, xIteration = 0; xIteration < 8; row++, xIteration++) { + for (int column = chest.getZ() + 3, yIteration = 0; yIteration < 7; column--, yIteration++) { + if (world.getBlockState(new BlockPos(row, 72, column)).getBlock() != Blocks.air) { + sevenBySevenBoard[xIteration][yIteration] = 'X'; + } + } + } + for (int row = chest.getX() + 12, xIteration = 0; xIteration < 6; row++, xIteration++) { + for (int column = chest.getZ() + 2, yIteration = 0; yIteration < 5; column--, yIteration++) { + if (world.getBlockState(new BlockPos(row, 71, column)).getBlock() != Blocks.air) { + fiveByFiveBoard[xIteration][yIteration] = 'X'; + } + } + } + for (int row = chest.getX() + 19, xIteration = 0; xIteration < 4; row++, xIteration++) { + for (int column = chest.getZ() + 1, yIteration = 0; yIteration < 3; column--, yIteration++) { + if (world.getBlockState(new BlockPos(row, 70, column)).getBlock() != Blocks.air) { + threeByThreeBoard[xIteration][yIteration] = 'X'; + } + } + } + break; + } + System.out.println(Arrays.deepToString(threeByThreeBoard)); + System.out.println(Arrays.deepToString(fiveByFiveBoard)); + System.out.println(Arrays.deepToString(sevenBySevenBoard)); + + threeByThreeRoute = IceWalkUtils.solve(threeByThreeBoard); + fiveByFiveRoute = IceWalkUtils.solve(fiveByFiveBoard); + sevenBySevenRoute = IceWalkUtils.solve(sevenBySevenBoard); + } + } + } + if (!foundRoom) { + inIceWalkRoom = false; + reset(); + } + }).start(); + } + } + } + + @SubscribeEvent + public void onWorldRender(RenderWorldLastEvent event) { + if (ToggleCommand.iceWalkToggled && Utils.inDungeons && chest != null) { + if (threeByThreeRoute != null && threeByThreeRoute.size() > 1) { + for (int i = 0; i < threeByThreeRoute.size() - 1; i++) { + Vec3 pos1; + Vec3 pos2; + switch (silverfishRoomDirection) { + case NORTH: + pos1 = new Vec3(chest.getX() - 0.5 + threeByThreeRoute.get(i).column, 70.5, chest.getZ() + 19.5 + threeByThreeRoute.get(i).row); + pos2 = new Vec3(chest.getX() - 0.5 + threeByThreeRoute.get(i + 1).column, 70.5, chest.getZ() + 19.5 + threeByThreeRoute.get(i + 1).row); + break; + case EAST: + pos1 = new Vec3(chest.getX() - 18.5 - threeByThreeRoute.get(i).row, 70.5, chest.getZ() - 0.5 + threeByThreeRoute.get(i).column); + pos2 = new Vec3(chest.getX() - 18.5 - threeByThreeRoute.get(i + 1).row, 70.5, chest.getZ() - 0.5 + threeByThreeRoute.get(i + 1).column); + break; + case SOUTH: + pos1 = new Vec3(chest.getX() + 1.5 - threeByThreeRoute.get(i).column, 70.5, chest.getZ() - 18.5 - threeByThreeRoute.get(i).row); + pos2 = new Vec3(chest.getX() + 1.5 - threeByThreeRoute.get(i + 1).column, 70.5, chest.getZ() - 18.5 - threeByThreeRoute.get(i + 1).row); + break; + case WEST: + pos1 = new Vec3(chest.getX() + 19.5 + threeByThreeRoute.get(i).row, 70.5, chest.getZ() + 1.5 - threeByThreeRoute.get(i).column); + pos2 = new Vec3(chest.getX() + 19.5 + threeByThreeRoute.get(i + 1).row, 70.5, chest.getZ() + 1.5 - threeByThreeRoute.get(i + 1).column); + break; + default: + return; + } + Utils.draw3DLine(pos1, pos2, ICE_WALK_LINE_COLOUR, 5, true, event.partialTicks); + } + } + + if (fiveByFiveRoute != null && fiveByFiveRoute.size() > 1) { + for (int i = 0; i < fiveByFiveRoute.size() - 1; i++) { + Vec3 pos1; + Vec3 pos2; + switch (silverfishRoomDirection) { + case NORTH: + pos1 = new Vec3(chest.getX() - 1.5 + fiveByFiveRoute.get(i).column, 71.5, chest.getZ() + 12.5 + fiveByFiveRoute.get(i).row); + pos2 = new Vec3(chest.getX() - 1.5 + fiveByFiveRoute.get(i + 1).column, 71.5, chest.getZ() + 12.5 + fiveByFiveRoute.get(i + 1).row); + break; + case EAST: + pos1 = new Vec3(chest.getX() - 11.5 - fiveByFiveRoute.get(i).row, 71.5, chest.getZ() - 1.5 + fiveByFiveRoute.get(i).column); + pos2 = new Vec3(chest.getX() - 11.5 - fiveByFiveRoute.get(i + 1).row, 71.5, chest.getZ() - 1.5 + fiveByFiveRoute.get(i + 1).column); + break; + case SOUTH: + pos1 = new Vec3(chest.getX() + 2.5 - fiveByFiveRoute.get(i).column, 71.5, chest.getZ() - 11.5 - fiveByFiveRoute.get(i).row); + pos2 = new Vec3(chest.getX() + 2.5 - fiveByFiveRoute.get(i + 1).column, 71.5, chest.getZ() - 11.5 - fiveByFiveRoute.get(i + 1).row); + break; + case WEST: + pos1 = new Vec3(chest.getX() + 12.5 + fiveByFiveRoute.get(i).row, 71.5, chest.getZ() + 2.5 - fiveByFiveRoute.get(i).column); + pos2 = new Vec3(chest.getX() + 12.5 + fiveByFiveRoute.get(i + 1).row, 71.5, chest.getZ() + 2.5 - fiveByFiveRoute.get(i + 1).column); + break; + default: + return; + } + Utils.draw3DLine(pos1, pos2, ICE_WALK_LINE_COLOUR, 5, true, event.partialTicks); + } + } + + if (sevenBySevenRoute != null && sevenBySevenRoute.size() > 1) { + for (int i = 0; i < sevenBySevenRoute.size() - 1; i++) { + Vec3 pos1; + Vec3 pos2; + switch (silverfishRoomDirection) { + case NORTH: + pos1 = new Vec3(chest.getX() - 2.5 + sevenBySevenRoute.get(i).column, 72.5, chest.getZ() + 3.5 + sevenBySevenRoute.get(i).row); + pos2 = new Vec3(chest.getX() - 2.5 + sevenBySevenRoute.get(i + 1).column, 72.5, chest.getZ() + 3.5 + sevenBySevenRoute.get(i + 1).row); + break; + case EAST: + pos1 = new Vec3(chest.getX() - 2.5 - sevenBySevenRoute.get(i).row, 72.5, chest.getZ() - 2.5 + sevenBySevenRoute.get(i).column); + pos2 = new Vec3(chest.getX() - 2.5 - sevenBySevenRoute.get(i + 1).row, 72.5, chest.getZ() - 2.5 + sevenBySevenRoute.get(i + 1).column); + break; + case SOUTH: + pos1 = new Vec3(chest.getX() + 3.5 - sevenBySevenRoute.get(i).column, 72.5, chest.getZ() - 2.5 - sevenBySevenRoute.get(i).row); + pos2 = new Vec3(chest.getX() + 3.5 - sevenBySevenRoute.get(i + 1).column, 72.5, chest.getZ() - 2.5 - sevenBySevenRoute.get(i + 1).row); + break; + case WEST: + pos1 = new Vec3(chest.getX() + 3.5 + sevenBySevenRoute.get(i).row, 72.5, chest.getZ() + 3.5 - sevenBySevenRoute.get(i).column); + pos2 = new Vec3(chest.getX() + 3.5 + sevenBySevenRoute.get(i + 1).row, 72.5, chest.getZ() + 3.5 - sevenBySevenRoute.get(i + 1).column); + break; + default: + return; + } + Utils.draw3DLine(pos1, pos2, ICE_WALK_LINE_COLOUR, 5, true, event.partialTicks); + } + } + } + } + + static void reset() { + silverfishRoomDirection = null; + chest = null; + threeByThreeRoute.clear(); + fiveByFiveRoute.clear(); + sevenBySevenRoute.clear(); + } + +} diff --git a/src/main/java/me/Danker/features/puzzlesolvers/LividSolver.java b/src/main/java/me/Danker/features/puzzlesolvers/LividSolver.java new file mode 100644 index 0000000..b537198 --- /dev/null +++ b/src/main/java/me/Danker/features/puzzlesolvers/LividSolver.java @@ -0,0 +1,89 @@ +package me.Danker.features.puzzlesolvers; + +import me.Danker.DankersSkyblockMod; +import me.Danker.commands.MoveCommand; +import me.Danker.commands.ScaleCommand; +import me.Danker.commands.ToggleCommand; +import me.Danker.events.RenderOverlay; +import me.Danker.handlers.ScoreboardHandler; +import me.Danker.handlers.TextRenderer; +import me.Danker.utils.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.world.World; +import net.minecraftforge.client.event.RenderLivingEvent; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.util.ArrayList; +import java.util.List; + +public class LividSolver { + + static boolean foundLivid = false; + static Entity livid = null; + + @SubscribeEvent + public void onWorldChange(WorldEvent.Load event) { + foundLivid = false; + livid = null; + } + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + if (event.phase != TickEvent.Phase.START) return; + + World world = Minecraft.getMinecraft().theWorld; + if (DankersSkyblockMod.tickAmount % 20 == 0) { + if (ToggleCommand.lividSolverToggled && Utils.inDungeons && !foundLivid && world != null) { + boolean inF5 = false; + + List<String> scoreboard = ScoreboardHandler.getSidebarLines(); + for (String s : scoreboard) { + String sCleaned = ScoreboardHandler.cleanSB(s); + if (sCleaned.contains("The Catacombs (F5)")) { + inF5 = true; + break; + } + } + + if (inF5) { + List<Entity> loadedLivids = new ArrayList<>(); + List<Entity> entities = world.getLoadedEntityList(); + for (Entity entity : entities) { + String name = entity.getName(); + if (name.contains("Livid") && name.length() > 5 && name.charAt(1) == name.charAt(5) && !loadedLivids.contains(entity)) { + loadedLivids.add(entity); + } + } + if (loadedLivids.size() > 8) { + livid = loadedLivids.get(0); + foundLivid = true; + } + } + } + } + } + + @SubscribeEvent + public void renderPlayerInfo(RenderOverlay event) { + if (ToggleCommand.lividSolverToggled && foundLivid && livid != null) { + new TextRenderer(Minecraft.getMinecraft(), livid.getName().replace("" + EnumChatFormatting.BOLD, ""), MoveCommand.lividHpXY[0], MoveCommand.lividHpXY[1], ScaleCommand.lividHpScale); + } + } + + @SubscribeEvent + public void onRenderEntity(RenderLivingEvent.Pre event) { + Entity entity = event.entity; + String name = entity.getName(); + if (entity instanceof EntityArmorStand) { + if (ToggleCommand.lividSolverToggled && !entity.isEntityEqual(livid) && name.contains("Livid") && name.length() > 5 && name.charAt(1) == name.charAt(5)) { + event.setCanceled(true); + } + } + } + +} diff --git a/src/main/java/me/Danker/features/puzzlesolvers/SelectAllColourSolver.java b/src/main/java/me/Danker/features/puzzlesolvers/SelectAllColourSolver.java new file mode 100644 index 0000000..16125db --- /dev/null +++ b/src/main/java/me/Danker/features/puzzlesolvers/SelectAllColourSolver.java @@ -0,0 +1,59 @@ +package me.Danker.features.puzzlesolvers; + +import me.Danker.commands.ToggleCommand; +import me.Danker.events.GuiChestBackgroundDrawnEvent; +import me.Danker.utils.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.StringUtils; +import net.minecraftforge.client.event.GuiOpenEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class SelectAllColourSolver { + + static Pattern selectAllTerminalPattern = Pattern.compile("[A-Z]{2,}"); + static String terminalColorNeeded; + + @SubscribeEvent + public void onGuiRender(GuiChestBackgroundDrawnEvent event) { + String displayName = event.displayName; + if (ToggleCommand.selectAllToggled && Utils.inDungeons && displayName.startsWith("Select all the")) { + String colour; + List<String> colourParts = new ArrayList<>(); + Matcher colourMatcher = selectAllTerminalPattern.matcher(displayName); + while (colourMatcher.find()) { + colourParts.add(colourMatcher.group()); + } + colour = String.join(" ", colourParts); + terminalColorNeeded = colour; + + for (Slot slot : event.slots) { + if (slot.inventory == Minecraft.getMinecraft().thePlayer.inventory) continue; + ItemStack item = slot.getStack(); + if (item == null) continue; + if (item.isItemEnchanted()) continue; + String itemName = StringUtils.stripControlCodes(item.getDisplayName()).toUpperCase(); + if (itemName.contains(terminalColorNeeded) || + (terminalColorNeeded.equals("SILVER") && itemName.contains("LIGHT GRAY")) || + (terminalColorNeeded.equals("WHITE") && (itemName.equals("WOOL") || itemName.equals("BONE MEAL"))) || + (terminalColorNeeded.equals("BLACK") && itemName.equals("INK SACK")) || + (terminalColorNeeded.equals("BLUE") && itemName.equals("LAPIS LAZULI")) || + (terminalColorNeeded.equals("BROWN") && itemName.equals("COCOA BEAN"))) { + Utils.drawOnSlot(event.chestSize, slot.xDisplayPosition, slot.yDisplayPosition, 0xBF40FF40); + } + } + } + } + + @SubscribeEvent + public void onGuiOpen(GuiOpenEvent event) { + terminalColorNeeded = null; + } + +} diff --git a/src/main/java/me/Danker/features/puzzlesolvers/SilverfishSolver.java b/src/main/java/me/Danker/features/puzzlesolvers/SilverfishSolver.java new file mode 100644 index 0000000..575dcd3 --- /dev/null +++ b/src/main/java/me/Danker/features/puzzlesolvers/SilverfishSolver.java @@ -0,0 +1,186 @@ +package me.Danker.features.puzzlesolvers; + +import me.Danker.DankersSkyblockMod; +import me.Danker.commands.ToggleCommand; +import me.Danker.utils.SilverfishUtils; +import me.Danker.utils.Utils; +import net.minecraft.block.BlockHopper; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.monster.EntitySilverfish; +import net.minecraft.init.Blocks; +import net.minecraft.item.Item; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class SilverfishSolver { + + static boolean prevInSilverfishRoom = false; + static boolean inSilverfishRoom = false; + static BlockPos chest = null; + static EnumFacing silverfishRoomDirection = null; + static List<SilverfishUtils.Point> route = new ArrayList<>(); + public static int SILVERFISH_LINE_COLOUR; + + @SubscribeEvent + public void onWorldChange(WorldEvent.Load event) { + reset(); + } + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + if (event.phase != TickEvent.Phase.START) return; + + Minecraft mc = Minecraft.getMinecraft(); + World world = mc.theWorld; + EntityPlayerSP player = mc.thePlayer; + if (DankersSkyblockMod.tickAmount % 20 == 0) { + if (ToggleCommand.silverfishToggled && Utils.inDungeons && world != null && player != null) { + new Thread(() -> { + boolean foundRoom = false; + prevInSilverfishRoom = inSilverfishRoom; + double x = player.posX; + double z = player.posZ; + // Find creepers nearby + AxisAlignedBB entityScan = new AxisAlignedBB(x - 25, 67, z - 25, x + 25, 68, z + 25); // 50x1x50 + List<EntitySilverfish> silverfishes = world.getEntitiesWithinAABB(EntitySilverfish.class, entityScan); + List<EntityItem> items = world.getEntitiesWithinAABB(EntityItem.class, entityScan); + if (silverfishes.size() > 0 && items.size() > 0) { + double silverfishX = silverfishes.get(0).posX; + double silverfishZ = silverfishes.get(0).posZ; + for (EntityItem item : items) { + if (Item.getIdFromItem(item.getEntityItem().getItem()) == 46 && Math.abs(item.posX - silverfishX) < 1 && Math.abs(item.posZ - silverfishZ) < 1) { + Iterable<BlockPos> blocks = BlockPos.getAllInBox(new BlockPos(player.posX - 27, 67, player.posZ - 27), new BlockPos(player.posX + 27, 67, player.posZ + 27)); + for (BlockPos blockPos : blocks) { + if (world.getBlockState(blockPos).getBlock() == Blocks.chest && world.getBlockState(blockPos.add(0, 2, 0)).getBlock() == Blocks.hopper) { + foundRoom = true; + inSilverfishRoom = true; + if (!prevInSilverfishRoom) { + chest = blockPos; + BlockPos silverfishBlock = new BlockPos(silverfishX, 67, silverfishZ); + TileEntity hopper = world.getTileEntity(blockPos.add(0, 2, 0)); + silverfishRoomDirection = BlockHopper.getFacing(hopper.getBlockMetadata()); + char[][] board = new char[19][19]; + SilverfishUtils.Point silverfishPoint = null; + + switch (silverfishRoomDirection) { + case NORTH: + for (int row = chest.getZ() + 3, xIteration = 0; xIteration < 19; row++, xIteration++) { + for (int column = chest.getX() - 9, yIteration = 0; yIteration < 19; column++, yIteration++) { + if (world.getBlockState(new BlockPos(column, 67, row)).getBlock() != Blocks.air) { + board[xIteration][yIteration] = 'X'; + } else if (silverfishBlock.equals(new BlockPos(column, 67, row))) { + silverfishPoint = new SilverfishUtils.Point(xIteration, yIteration); + } + } + } + break; + case EAST: + for (int row = chest.getX() - 3, xIteration = 0; xIteration < 19; row--, xIteration++) { + for (int column = chest.getZ() - 9, yIteration = 0; yIteration < 19; column++, yIteration++) { + if (world.getBlockState(new BlockPos(row, 67, column)).getBlock() != Blocks.air) { + board[xIteration][yIteration] = 'X'; + } else if (silverfishBlock.equals(new BlockPos(row, 67, column))) { + silverfishPoint = new SilverfishUtils.Point(xIteration, yIteration); + } + } + } + break; + case SOUTH: + for (int row = chest.getZ() - 3, xIteration = 0; xIteration < 19; row--, xIteration++) { + for (int column = chest.getX() + 9, yIteration = 0; yIteration < 19; column--, yIteration++) { + if (world.getBlockState(new BlockPos(column, 67, row)).getBlock() != Blocks.air) { + board[xIteration][yIteration] = 'X'; + } else if (silverfishBlock.equals(new BlockPos(column, 67, row))) { + silverfishPoint = new SilverfishUtils.Point(xIteration, yIteration); + } + } + } + break; + case WEST: + for (int row = chest.getX() + 3, xIteration = 0; xIteration < 19; row++, xIteration++) { + for (int column = chest.getZ() + 9, yIteration = 0; yIteration < 19; column--, yIteration++) { + if (world.getBlockState(new BlockPos(row, 67, column)).getBlock() != Blocks.air) { + board[xIteration][yIteration] = 'X'; + } else if (silverfishBlock.equals(new BlockPos(row, 67, column))) { + board[xIteration][yIteration] = 'S'; + silverfishPoint = new SilverfishUtils.Point(xIteration, yIteration); + } + } + } + break; + default: + return; + } + System.out.println(Arrays.deepToString(board)); + + List<SilverfishUtils.Point> endPoints = new ArrayList<>(); + for (int column = 0; column < 19; column++) { + if (board[0][column] != 'X') endPoints.add(new SilverfishUtils.Point(0, column)); + } + + route = SilverfishUtils.solve(board, silverfishPoint, endPoints); + } + } + } + } + } + } + if (!foundRoom) reset(); + }).start(); + } + } + } + + @SubscribeEvent + public void onWorldRender(RenderWorldLastEvent event) { + if (ToggleCommand.silverfishToggled && Utils.inDungeons && route != null && route.size() > 0 && chest != null) { + for (int i = 0; i < route.size() - 1; i++) { + Vec3 pos1 = null; + Vec3 pos2 = null; + switch (silverfishRoomDirection) { + case NORTH: + pos1 = new Vec3(chest.getX() - 8.5 + route.get(i).column, 67.5, chest.getZ() + 3.5 + route.get(i).row); + pos2 = new Vec3(chest.getX() - 8.5 + route.get(i + 1).column, 67.5, chest.getZ() + 3.5 + route.get(i + 1).row); + break; + case EAST: + pos1 = new Vec3(chest.getX() - 2.5 - route.get(i).row, 67.5, chest.getZ() - 8.5 + route.get(i).column); + pos2 = new Vec3(chest.getX() - 2.5 - route.get(i + 1).row, 67.5, chest.getZ() - 8.5 + route.get(i + 1).column); + break; + case SOUTH: + pos1 = new Vec3(chest.getX() + 9.5 - route.get(i).column, 67.5, chest.getZ() - 2.5 - route.get(i).row); + pos2 = new Vec3(chest.getX() + 9.5 - route.get(i + 1).column, 67.5, chest.getZ() - 2.5 - route.get(i + 1).row); + break; + case WEST: + pos1 = new Vec3(chest.getX() + 3.5 + route.get(i).row, 67.5, chest.getZ() + 9.5 - route.get(i).column); + pos2 = new Vec3(chest.getX() + 3.5 + route.get(i + 1).row, 67.5, chest.getZ() + 9.5 - route.get(i + 1).column); + break; + default: + return; + } + Utils.draw3DLine(pos1, pos2, SILVERFISH_LINE_COLOUR, 5, true, event.partialTicks); + } + } + } + + static void reset() { + inSilverfishRoom = false; + chest = null; + silverfishRoomDirection = null; + route.clear(); + } + +} diff --git a/src/main/java/me/Danker/features/puzzlesolvers/StartsWithSolver.java b/src/main/java/me/Danker/features/puzzlesolvers/StartsWithSolver.java new file mode 100644 index 0000000..8f15fa7 --- /dev/null +++ b/src/main/java/me/Danker/features/puzzlesolvers/StartsWithSolver.java @@ -0,0 +1,31 @@ +package me.Danker.features.puzzlesolvers; + +import me.Danker.commands.ToggleCommand; +import me.Danker.events.GuiChestBackgroundDrawnEvent; +import me.Danker.utils.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.StringUtils; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +public class StartsWithSolver { + + @SubscribeEvent + public void onGuiRender(GuiChestBackgroundDrawnEvent event) { + String displayName = event.displayName; + if (ToggleCommand.startsWithToggled && Utils.inDungeons && displayName.startsWith("What starts with:")) { + char letter = displayName.charAt(displayName.indexOf("'") + 1); + for (Slot slot : event.slots) { + if (slot.inventory == Minecraft.getMinecraft().thePlayer.inventory) continue; + ItemStack item = slot.getStack(); + if (item == null) continue; + if (item.isItemEnchanted()) continue; + if (StringUtils.stripControlCodes(item.getDisplayName()).charAt(0) == letter) { + Utils.drawOnSlot(event.chestSize, slot.xDisplayPosition, slot.yDisplayPosition, 0xBF40FF40); + } + } + } + } + +} diff --git a/src/main/java/me/Danker/features/puzzlesolvers/SuperpairsSolver.java b/src/main/java/me/Danker/features/puzzlesolvers/SuperpairsSolver.java new file mode 100644 index 0000000..c6e1d76 --- /dev/null +++ b/src/main/java/me/Danker/features/puzzlesolvers/SuperpairsSolver.java @@ -0,0 +1,150 @@ +package me.Danker.features.puzzlesolvers; + +import me.Danker.commands.ToggleCommand; +import me.Danker.events.GuiChestBackgroundDrawnEvent; +import me.Danker.utils.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.StringUtils; +import net.minecraftforge.client.event.GuiOpenEvent; +import net.minecraftforge.event.entity.player.ItemTooltipEvent; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.awt.*; +import java.util.List; +import java.util.*; + +public class SuperpairsSolver { + + static ItemStack[] experimentTableSlots = new ItemStack[54]; + + @SubscribeEvent(priority = EventPriority.HIGHEST) + public void onTooltip(ItemTooltipEvent event) { + if (!Utils.inSkyblock) return; + if (event.toolTip == null) return; + + ItemStack item = event.itemStack; + Minecraft mc = Minecraft.getMinecraft(); + EntityPlayerSP player = mc.thePlayer; + + if (mc.currentScreen instanceof GuiChest) { + ContainerChest chest = (ContainerChest) player.openContainer; + IInventory inv = chest.getLowerChestInventory(); + String chestName = inv.getDisplayName().getUnformattedText(); + + if (ToggleCommand.superpairsToggled && chestName.contains("Superpairs (")) { + if (Item.getIdFromItem(item.getItem()) != 95) return; + if (item.getDisplayName().contains("Click any button") || item.getDisplayName().contains("Click a second button") || item.getDisplayName().contains("Next button is instantly rewarded") || item.getDisplayName().contains("Stained Glass")) { + Slot slot = ((GuiChest) mc.currentScreen).getSlotUnderMouse(); + ItemStack itemStack = experimentTableSlots[slot.getSlotIndex()]; + if (itemStack == null) return; + String itemName = itemStack.getDisplayName(); + + if (event.toolTip.stream().anyMatch(x -> StringUtils.stripControlCodes(x).equals(StringUtils.stripControlCodes(itemName)))) + return; + event.toolTip.removeIf(x -> { + x = StringUtils.stripControlCodes(x); + if (x.equals("minecraft:stained_glass")) return true; + return x.startsWith("NBT: "); + }); + event.toolTip.add(itemName); + event.toolTip.add(itemStack.getItem().getRegistryName()); + } + + } + } + } + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + if (event.phase != TickEvent.Phase.START) return; + + Minecraft mc = Minecraft.getMinecraft(); + EntityPlayerSP player = mc.thePlayer; + if (mc.currentScreen instanceof GuiChest) { + if (player == null) return; + ContainerChest chest = (ContainerChest) player.openContainer; + List<Slot> invSlots = ((GuiChest) mc.currentScreen).inventorySlots.inventorySlots; + String chestName = chest.getLowerChestInventory().getDisplayName().getUnformattedText().trim(); + + if (ToggleCommand.superpairsToggled && chestName.startsWith("Superpairs (")) { + for (int i = 0; i < 53; i++) { + ItemStack itemStack = invSlots.get(i).getStack(); + if (itemStack == null) continue; + String itemName = itemStack.getDisplayName(); + if (Item.getIdFromItem(itemStack.getItem()) == 95 || Item.getIdFromItem(itemStack.getItem()) == 160) continue; + if (itemName.contains("Instant Find") || itemName.contains("Gained +")) continue; + if (itemName.contains("Enchanted Book")) { + itemName = itemStack.getTooltip(mc.thePlayer, false).get(3); + } + if (itemStack.stackSize > 1) { + itemName = itemStack.stackSize + " " + itemName; + } + if (experimentTableSlots[i] != null) continue; + experimentTableSlots[i] = itemStack.copy().setStackDisplayName(itemName); + } + } + } + } + + @SubscribeEvent + public void onGuiRender(GuiChestBackgroundDrawnEvent event) { + if (ToggleCommand.superpairsToggled && event.displayName.contains("Superpairs (")) { + HashMap<String, HashSet<Integer>> matches = new HashMap<>(); + for (int i = 0; i < 53; i++) { + ItemStack itemStack = experimentTableSlots[i]; + if (itemStack == null) continue; + + //Utils.renderItem(itemStack, x, y, -100); + + String itemName = itemStack.getDisplayName(); + String keyName = itemName + itemStack.getUnlocalizedName(); + matches.computeIfAbsent(keyName, k -> new HashSet<>()); + matches.get(keyName).add(i); + } + + Color[] colors = { + new Color(255, 0, 0, 100), + new Color(0, 0, 255, 100), + new Color(100, 179, 113, 100), + new Color(255, 114, 255, 100), + new Color(255, 199, 87, 100), + new Color(119, 105, 198, 100), + new Color(135, 199, 112, 100), + new Color(240, 37, 240, 100), + new Color(178, 132, 190, 100), + new Color(63, 135, 163, 100), + new Color(146, 74, 10, 100), + new Color(255, 255, 255, 100), + new Color(217, 252, 140, 100), + new Color(255, 82, 82, 100) + }; + + Iterator<Color> colorIterator = Arrays.stream(colors).iterator(); + + matches.forEach((itemName, slotSet) -> { + if (slotSet.size() < 2) return; + ArrayList<Slot> slots = new ArrayList<>(); + slotSet.forEach(slotNum -> slots.add(event.slots.get(slotNum))); + Color color = colorIterator.next(); + slots.forEach(slot -> { + Utils.drawOnSlot(event.chestSize, slot.xDisplayPosition, slot.yDisplayPosition, color.getRGB()); + }); + }); + } + } + + @SubscribeEvent + public void onGuiOpen(GuiOpenEvent event) { + experimentTableSlots = new ItemStack[54]; + } + +} diff --git a/src/main/java/me/Danker/features/puzzlesolvers/ThreeManSolver.java b/src/main/java/me/Danker/features/puzzlesolvers/ThreeManSolver.java new file mode 100644 index 0000000..8f7de95 --- /dev/null +++ b/src/main/java/me/Danker/features/puzzlesolvers/ThreeManSolver.java @@ -0,0 +1,75 @@ +package me.Danker.features.puzzlesolvers; + +import me.Danker.DankersSkyblockMod; +import me.Danker.commands.ToggleCommand; +import me.Danker.utils.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; +import net.minecraft.init.Blocks; +import net.minecraft.util.*; +import net.minecraftforge.client.event.ClientChatReceivedEvent; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import java.util.List; + +public class ThreeManSolver { + + static String[] riddleSolutions = {"The reward is not in my chest!", "At least one of them is lying, and the reward is not in", + "My chest doesn't have the reward. We are all telling the truth", "My chest has the reward and I'm telling the truth", + "The reward isn't in any of our chests", "Both of them are telling the truth."}; + static BlockPos riddleChest = null; + + @SubscribeEvent + public void onWorldChange(WorldEvent.Load event) { + riddleChest = null; + } + + @SubscribeEvent + public void onChat(ClientChatReceivedEvent event) { + String message = StringUtils.stripControlCodes(event.message.getUnformattedText()); + + if (!Utils.inDungeons) return; + + if (ToggleCommand.threeManToggled && message.contains("[NPC]")) { + for (String solution : riddleSolutions) { + if (message.contains(solution)) { + Minecraft mc = Minecraft.getMinecraft(); + String npcName = message.substring(message.indexOf("]") + 2, message.indexOf(":")); + mc.thePlayer.addChatMessage(new ChatComponentText(DankersSkyblockMod.ANSWER_COLOUR + EnumChatFormatting.BOLD + StringUtils.stripControlCodes(npcName) + DankersSkyblockMod.MAIN_COLOUR + " has the blessing.")); + if (riddleChest == null) { + List<Entity> entities = mc.theWorld.getLoadedEntityList(); + for (Entity entity : entities) { + if (entity == null || !entity.hasCustomName()) continue; + if (entity.getCustomNameTag().contains(npcName)) { + BlockPos npcLocation = new BlockPos(entity.posX, 69, entity.posZ); + if (mc.theWorld.getBlockState(npcLocation.north()).getBlock() == Blocks.chest) { + riddleChest = npcLocation.north(); + } else if (mc.theWorld.getBlockState(npcLocation.east()).getBlock() == Blocks.chest) { + riddleChest = npcLocation.east(); + } else if (mc.theWorld.getBlockState(npcLocation.south()).getBlock() == Blocks.chest) { + riddleChest = npcLocation.south(); + } else if (mc.theWorld.getBlockState(npcLocation.west()).getBlock() == Blocks.chest) { + riddleChest = npcLocation.west(); + } else { + System.out.print("Could not find correct riddle chest."); + } + break; + } + } + } + break; + } + } + } + } + + @SubscribeEvent + public void onWorldRender(RenderWorldLastEvent event) { + if (ToggleCommand.threeManToggled && riddleChest != null) { + Utils.drawFilled3DBox(new AxisAlignedBB(riddleChest.getX() - 0.05, riddleChest.getY(), riddleChest.getZ() - 0.05, riddleChest.getX() + 1.05, riddleChest.getY() + 1, riddleChest.getZ() + 1.05), 0x197F19, true, true, event.partialTicks); + } + } + +} diff --git a/src/main/java/me/Danker/features/puzzlesolvers/TicTacToeSolver.java b/src/main/java/me/Danker/features/puzzlesolvers/TicTacToeSolver.java new file mode 100644 index 0000000..1b4a2e1 --- /dev/null +++ b/src/main/java/me/Danker/features/puzzlesolvers/TicTacToeSolver.java @@ -0,0 +1,135 @@ +package me.Danker.features.puzzlesolvers; + +import me.Danker.DankersSkyblockMod; +import me.Danker.commands.ToggleCommand; +import me.Danker.utils.TicTacToeUtils; +import me.Danker.utils.Utils; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.entity.item.EntityItemFrame; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemMap; +import net.minecraft.item.ItemStack; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; +import net.minecraft.world.storage.MapData; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class TicTacToeSolver { + + static AxisAlignedBB correctTicTacToeButton = null; + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + if (event.phase != TickEvent.Phase.START) return; + + Minecraft mc = Minecraft.getMinecraft(); + World world = mc.theWorld; + EntityPlayerSP player = mc.thePlayer; + if (DankersSkyblockMod.tickAmount % 20 == 0) { + if (ToggleCommand.ticTacToeToggled && Utils.inDungeons && world != null && player != null) { + correctTicTacToeButton = null; + AxisAlignedBB aabb = new AxisAlignedBB(player.posX - 6, player.posY - 6, player.posZ - 6, player.posX + 6, player.posY + 6, player.posZ + 6); + List<EntityItemFrame> itemFrames = world.getEntitiesWithinAABB(EntityItemFrame.class, aabb); + List<EntityItemFrame> itemFramesWithMaps = new ArrayList<>(); + // Find how many item frames have maps already placed + for (EntityItemFrame itemFrame : itemFrames) { + ItemStack item = itemFrame.getDisplayedItem(); + if (item == null || !(item.getItem() instanceof ItemMap)) continue; + MapData mapData = ((ItemMap) item.getItem()).getMapData(item, world); + if (mapData == null) continue; + + itemFramesWithMaps.add(itemFrame); + } + + // Only run when it's your turn + if (itemFramesWithMaps.size() != 9 && itemFramesWithMaps.size() % 2 == 1) { + char[][] board = new char[3][3]; + BlockPos leftmostRow = null; + int sign = 1; + char facing = 'X'; + for (EntityItemFrame itemFrame : itemFramesWithMaps) { + ItemStack map = itemFrame.getDisplayedItem(); + MapData mapData = ((ItemMap) map.getItem()).getMapData(map, world); + + // Find position on board + // I mixed up row and column here and I'm too lazy to fix it + int row = 0; + int column; + sign = 1; + + if (itemFrame.facingDirection == EnumFacing.SOUTH || itemFrame.facingDirection == EnumFacing.WEST) { + sign = -1; + } + + BlockPos itemFramePos = new BlockPos(itemFrame.posX, Math.floor(itemFrame.posY), itemFrame.posZ); + for (int i = 2; i >= 0; i--) { + int realI = i * sign; + BlockPos blockPos = itemFramePos; + if (itemFrame.posX % 0.5 == 0) { + blockPos = itemFramePos.add(realI, 0, 0); + } else if (itemFrame.posZ % 0.5 == 0) { + blockPos = itemFramePos.add(0, 0, realI); + facing = 'Z'; + } + Block block = world.getBlockState(blockPos).getBlock(); + if (block == Blocks.air || block == Blocks.stone_button) { + leftmostRow = blockPos; + row = i; + break; + } + } + + if (itemFrame.posY == 72.5) { + column = 0; + } else if (itemFrame.posY == 71.5) { + column = 1; + } else if (itemFrame.posY == 70.5) { + column = 2; + } else { + continue; + } + + // Get colour + // Middle pixel = 64*128 + 64 = 8256 + int colourInt = mapData.colors[8256] & 255; + if (colourInt == 114) { + board[column][row] = 'X'; + } else if (colourInt == 33) { + board[column][row] = 'O'; + } + } + System.out.println("Board: " + Arrays.deepToString(board)); + + // Draw best move + int bestMove = TicTacToeUtils.getBestMove(board) - 1; + System.out.println("Best move slot: " + bestMove); + if (leftmostRow != null) { + double drawX = facing == 'X' ? leftmostRow.getX() - sign * (bestMove % 3) : leftmostRow.getX(); + double drawY = 72 - Math.floor(bestMove / 3); + double drawZ = facing == 'Z' ? leftmostRow.getZ() - sign * (bestMove % 3) : leftmostRow.getZ(); + + correctTicTacToeButton = new AxisAlignedBB(drawX, drawY, drawZ, drawX + 1, drawY + 1, drawZ + 1); + } + } + } + } + } + + @SubscribeEvent + public void onWorldRender(RenderWorldLastEvent event) { + if (ToggleCommand.ticTacToeToggled && correctTicTacToeButton != null) { + Utils.draw3DBox(correctTicTacToeButton, 0x40FF40, event.partialTicks); + } + } + +} diff --git a/src/main/java/me/Danker/features/puzzlesolvers/TriviaSolver.java b/src/main/java/me/Danker/features/puzzlesolvers/TriviaSolver.java new file mode 100644 index 0000000..9adc555 --- /dev/null +++ b/src/main/java/me/Danker/features/puzzlesolvers/TriviaSolver.java @@ -0,0 +1,102 @@ +package me.Danker.features.puzzlesolvers; + +import me.Danker.commands.ToggleCommand; +import me.Danker.utils.Utils; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.StringUtils; +import net.minecraftforge.client.event.ClientChatReceivedEvent; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import java.util.HashMap; +import java.util.Map; + +public class TriviaSolver { + + static Map<String, String[]> triviaSolutions = new HashMap<>(); + static String[] triviaAnswers = null; + public static String TRIVIA_WRONG_ANSWER_COLOUR; + + public static void init() { + triviaSolutions.put("What is the status of The Watcher?", new String[]{"Stalker"}); + triviaSolutions.put("What is the status of Bonzo?", new String[]{"New Necromancer"}); + triviaSolutions.put("What is the status of Scarf?", new String[]{"Apprentice Necromancer"}); + triviaSolutions.put("What is the status of The Professor?", new String[]{"Professor"}); + triviaSolutions.put("What is the status of Thorn?", new String[]{"Shaman Necromancer"}); + triviaSolutions.put("What is the status of Livid?", new String[]{"Master Necromancer"}); + triviaSolutions.put("What is the status of Sadan?", new String[]{"Necromancer Lord"}); + triviaSolutions.put("What is the status of Maxor?", new String[]{"Young Wither"}); + triviaSolutions.put("What is the status of Goldor?", new String[]{"Wither Soldier"}); + triviaSolutions.put("What is the status of Storm?", new String[]{"Elementalist"}); + triviaSolutions.put("What is the status of Necron?", new String[]{"Wither Lord"}); + triviaSolutions.put("How many total Fairy Souls are there?", new String[]{"222 Fairy Souls"}); + triviaSolutions.put("How many Fairy Souls are there in Spider's Den?", new String[]{"19 Fairy Souls"}); + triviaSolutions.put("How many Fairy Souls are there in The End?", new String[]{"12 Fairy Souls"}); + triviaSolutions.put("How many Fairy Souls are there in The Barn?", new String[]{"7 Fairy Souls"}); + triviaSolutions.put("How many Fairy Souls are there in Mushroom Desert?", new String[]{"8 Fairy Souls"}); + triviaSolutions.put("How many Fairy Souls are there in Blazing Fortress?", new String[]{"19 Fairy Souls"}); + triviaSolutions.put("How many Fairy Souls are there in The Park?", new String[]{"11 Fairy Souls"}); + triviaSolutions.put("How many Fairy Souls are there in Jerry's Workshop?", new String[]{"5 Fairy Souls"}); + triviaSolutions.put("How many Fairy Souls are there in Hub?", new String[]{"79 Fairy Souls"}); + triviaSolutions.put("How many Fairy Souls are there in The Hub?", new String[]{"79 Fairy Souls"}); + triviaSolutions.put("How many Fairy Souls are there in Deep Caverns?", new String[]{"21 Fairy Souls"}); + triviaSolutions.put("How many Fairy Souls are there in Gold Mine?", new String[]{"12 Fairy Souls"}); + triviaSolutions.put("How many Fairy Souls are there in Dungeon Hub?", new String[]{"7 Fairy Souls"}); + triviaSolutions.put("Which brother is on the Spider's Den?", new String[]{"Rick"}); + triviaSolutions.put("What is the name of Rick's brother?", new String[]{"Pat"}); + triviaSolutions.put("What is the name of the Painter in the Hub?", new String[]{"Marco"}); + triviaSolutions.put("What is the name of the person that upgrades pets?", new String[]{"Kat"}); + triviaSolutions.put("What is the name of the lady of the Nether?", new String[]{"Elle"}); + triviaSolutions.put("Which villager in the Village gives you a Rogue Sword?", new String[]{"Jamie"}); + triviaSolutions.put("How many unique minions are there?", new String[]{"53 Minions"}); + triviaSolutions.put("Which of these enemies does not spawn in the Spider's Den?", new String[]{"Zombie Spider", "Cave Spider", "Wither Skeleton", + "Dashing Spooder", "Broodfather", "Night Spider"}); + triviaSolutions.put("Which of these monsters only spawns at night?", new String[]{"Zombie Villager", "Ghast"}); + triviaSolutions.put("Which of these is not a dragon in The End?", new String[]{"Zoomer Dragon", "Weak Dragon", "Stonk Dragon", "Holy Dragon", "Boomer Dragon", + "Booger Dragon", "Older Dragon", "Elder Dragon", "Stable Dragon", "Professor Dragon"}); + } + + @SubscribeEvent(priority = EventPriority.HIGHEST) + public void onChat(ClientChatReceivedEvent event) { + String message = StringUtils.stripControlCodes(event.message.getUnformattedText()); + + if (!Utils.inDungeons) return; + if (event.type == 2) return; + + if (ToggleCommand.oruoToggled) { + if (message.contains("What SkyBlock year is it?")) { + double currentTime = System.currentTimeMillis() /1000L; + + double diff = Math.floor(currentTime - 1560276000); + + int year = (int) (diff / 446400 + 1); + triviaAnswers = new String[]{"Year " + year}; + } else { + for (String question : triviaSolutions.keySet()) { + if (message.contains(question)) { + triviaAnswers = triviaSolutions.get(question); + break; + } + } + } + + // Set wrong answers to red and remove click events + if (triviaAnswers != null && (message.contains("ⓐ") || message.contains("ⓑ") || message.contains("ⓒ"))) { + boolean isSolution = false; + for (String solution : triviaAnswers) { + if (message.contains(solution)) { + isSolution = true; + break; + } + } + if (!isSolution) { + char letter = message.charAt(5); + String option = message.substring(6); + event.message = new ChatComponentText(" " + EnumChatFormatting.GOLD + letter + TRIVIA_WRONG_ANSWER_COLOUR + option); + } + } + } + } + +} diff --git a/src/main/java/me/Danker/features/puzzlesolvers/UltrasequencerSolver.java b/src/main/java/me/Danker/features/puzzlesolvers/UltrasequencerSolver.java new file mode 100644 index 0000000..3df6fc4 --- /dev/null +++ b/src/main/java/me/Danker/features/puzzlesolvers/UltrasequencerSolver.java @@ -0,0 +1,87 @@ +package me.Danker.features.puzzlesolvers; + +import me.Danker.commands.ToggleCommand; +import me.Danker.events.GuiChestBackgroundDrawnEvent; +import me.Danker.utils.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.Slot; +import net.minecraft.util.StringUtils; +import net.minecraftforge.client.event.GuiOpenEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.util.List; + +public class UltrasequencerSolver { + + static Slot[] clickInOrderSlots = new Slot[36]; + static int lastUltraSequencerClicked = 0; + public static int ULTRASEQUENCER_NEXT; + public static int ULTRASEQUENCER_NEXT_TO_NEXT; + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + if (event.phase != TickEvent.Phase.START) return; + + Minecraft mc = Minecraft.getMinecraft(); + EntityPlayerSP player = mc.thePlayer; + if (mc.currentScreen instanceof GuiChest) { + if (player == null) return; + ContainerChest chest = (ContainerChest) player.openContainer; + List<Slot> invSlots = ((GuiChest) mc.currentScreen).inventorySlots.inventorySlots; + String chestName = chest.getLowerChestInventory().getDisplayName().getUnformattedText().trim(); + + if (ToggleCommand.ultrasequencerToggled && chestName.startsWith("Ultrasequencer (")) { + if (invSlots.get(49).getStack() != null && invSlots.get(49).getStack().getDisplayName().equals("§aRemember the pattern!")) { + for (int i = 9; i <= 44; i++) { + if (invSlots.get(i) == null || invSlots.get(i).getStack() == null) continue; + String itemName = StringUtils.stripControlCodes(invSlots.get(i).getStack().getDisplayName()); + if (itemName.matches("\\d+")) { + int number = Integer.parseInt(itemName); + clickInOrderSlots[number - 1] = invSlots.get(i); + } + } + } + } + } + } + + @SubscribeEvent + public void onGuiRender(GuiChestBackgroundDrawnEvent event) { + if (ToggleCommand.ultrasequencerToggled && event.displayName.startsWith("Ultrasequencer (")) { + List<Slot> invSlots = event.slots; + if (invSlots.size() > 48 && invSlots.get(49).getStack() != null) { + if (invSlots.get(49).getStack().getDisplayName().startsWith("§7Timer: §a")) { + lastUltraSequencerClicked = 0; + for (Slot slot : clickInOrderSlots) { + if (slot != null && slot.getStack() != null && StringUtils.stripControlCodes(slot.getStack().getDisplayName()).matches("\\d+")) { + int number = Integer.parseInt(StringUtils.stripControlCodes(slot.getStack().getDisplayName())); + if (number > lastUltraSequencerClicked) { + lastUltraSequencerClicked = number; + } + } + } + if (clickInOrderSlots[lastUltraSequencerClicked] != null) { + Slot nextSlot = clickInOrderSlots[lastUltraSequencerClicked]; + Utils.drawOnSlot(event.chestSize, nextSlot.xDisplayPosition, nextSlot.yDisplayPosition, ULTRASEQUENCER_NEXT + 0xE5000000); + } + if (lastUltraSequencerClicked + 1 < clickInOrderSlots.length) { + if (clickInOrderSlots[lastUltraSequencerClicked + 1] != null) { + Slot nextSlot = clickInOrderSlots[lastUltraSequencerClicked + 1]; + Utils.drawOnSlot(event.chestSize, nextSlot.xDisplayPosition, nextSlot.yDisplayPosition, ULTRASEQUENCER_NEXT_TO_NEXT + 0xD7000000); + } + } + } + } + } + } + + @SubscribeEvent + public void onGuiOpen(GuiOpenEvent event) { + clickInOrderSlots = new Slot[36]; + } + +} diff --git a/src/main/java/me/Danker/features/puzzlesolvers/WaterSolver.java b/src/main/java/me/Danker/features/puzzlesolvers/WaterSolver.java new file mode 100644 index 0000000..2be92f9 --- /dev/null +++ b/src/main/java/me/Danker/features/puzzlesolvers/WaterSolver.java @@ -0,0 +1,162 @@ +package me.Danker.features.puzzlesolvers; + +import me.Danker.DankersSkyblockMod; +import me.Danker.commands.MoveCommand; +import me.Danker.commands.ScaleCommand; +import me.Danker.commands.ToggleCommand; +import me.Danker.events.RenderOverlay; +import me.Danker.handlers.TextRenderer; +import me.Danker.utils.Utils; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +public class WaterSolver { + + static boolean prevInWaterRoom = false; + static boolean inWaterRoom = false; + static String waterAnswers = null; + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + if (event.phase != TickEvent.Phase.START) return; + + Minecraft mc = Minecraft.getMinecraft(); + EntityPlayerSP player = mc.thePlayer; + World world = mc.theWorld; + if (DankersSkyblockMod.tickAmount % 20 == 0) { + if (ToggleCommand.waterToggled && Utils.inDungeons && world != null && player != null) { + // multi thread block checking + new Thread(() -> { + prevInWaterRoom = inWaterRoom; + inWaterRoom = false; + boolean foundPiston = false; + boolean done = false; + for (int x = (int) (player.posX - 13); x <= player.posX + 13; x++) { + for (int z = (int) (player.posZ - 13); z <= player.posZ + 13; z++) { + BlockPos blockPos = new BlockPos(x, 54, z); + if (world.getBlockState(blockPos).getBlock() == Blocks.sticky_piston) { + foundPiston = true; + break; + } + } + if (foundPiston) break; + } + + if (foundPiston) { + for (int x = (int) (player.posX - 25); x <= player.posX + 25; x++) { + for (int z = (int) (player.posZ - 25); z <= player.posZ + 25; z++) { + BlockPos blockPos = new BlockPos(x, 82, z); + if (world.getBlockState(blockPos).getBlock() == Blocks.piston_head) { + inWaterRoom = true; + if (!prevInWaterRoom) { + boolean foundGold = false; + boolean foundClay = false; + boolean foundEmerald = false; + boolean foundQuartz = false; + boolean foundDiamond = false; + + // Detect first blocks near water stream + BlockPos scan1 = new BlockPos(x + 1, 78, z + 1); + BlockPos scan2 = new BlockPos(x - 1, 77, z - 1); + Iterable<BlockPos> blocks = BlockPos.getAllInBox(scan1, scan2); + for (BlockPos puzzleBlockPos : blocks) { + Block block = world.getBlockState(puzzleBlockPos).getBlock(); + if (block == Blocks.gold_block) { + foundGold = true; + } else if (block == Blocks.hardened_clay) { + foundClay = true; + } else if (block == Blocks.emerald_block) { + foundEmerald = true; + } else if (block == Blocks.quartz_block) { + foundQuartz = true; + } else if (block == Blocks.diamond_block) { + foundDiamond = true; + } + } + + int variant = 0; + if (foundGold && foundClay) { + variant = 1; + } else if (foundEmerald && foundQuartz) { + variant = 2; + } else if (foundQuartz && foundDiamond) { + variant = 3; + } else if (foundGold && foundQuartz) { + variant = 4; + } + + // Return solution + String purple; + String orange; + String blue; + String green; + String red; + switch (variant) { + case 1: + purple = EnumChatFormatting.WHITE + "Quartz, " + EnumChatFormatting.YELLOW + "Gold, " + EnumChatFormatting.AQUA + "Diamond, " + EnumChatFormatting.RED + "Clay"; + orange = EnumChatFormatting.YELLOW + "Gold, " + EnumChatFormatting.DARK_GRAY + "Coal, " + EnumChatFormatting.GREEN + "Emerald"; + blue = EnumChatFormatting.WHITE + "Quartz, " + EnumChatFormatting.YELLOW + "Gold, " + EnumChatFormatting.GREEN + "Emerald, " + EnumChatFormatting.RED + "Clay"; + green = EnumChatFormatting.GREEN + "Emerald"; + red = EnumChatFormatting.GRAY + "None"; + break; + case 2: + purple = EnumChatFormatting.DARK_GRAY + "Coal"; + orange = EnumChatFormatting.WHITE + "Quartz, " + EnumChatFormatting.YELLOW + "Gold, " + EnumChatFormatting.GREEN + "Emerald, " + EnumChatFormatting.RED + "Clay"; + blue = EnumChatFormatting.WHITE + "Quartz, " + EnumChatFormatting.AQUA + "Diamond, " + EnumChatFormatting.GREEN + "Emerald"; + green = EnumChatFormatting.WHITE + "Quartz, " + EnumChatFormatting.GREEN + "Emerald"; + red = EnumChatFormatting.WHITE + "Quartz, " + EnumChatFormatting.DARK_GRAY + "Coal, " + EnumChatFormatting.GREEN + "Emerald"; + break; + case 3: + purple = EnumChatFormatting.WHITE + "Quartz, " + EnumChatFormatting.YELLOW + "Gold, " + EnumChatFormatting.AQUA + "Diamond"; + orange = EnumChatFormatting.GREEN + "Emerald"; + blue = EnumChatFormatting.WHITE + "Quartz, " + EnumChatFormatting.AQUA + "Diamond"; + green = EnumChatFormatting.GRAY + "None"; + red = EnumChatFormatting.YELLOW + "Gold, " + EnumChatFormatting.GREEN + "Emerald"; + break; + case 4: + purple = EnumChatFormatting.WHITE + "Quartz, " + EnumChatFormatting.YELLOW + "Gold, " + EnumChatFormatting.GREEN + "Emerald, " + EnumChatFormatting.RED + "Clay"; + orange = EnumChatFormatting.YELLOW + "Gold, " + EnumChatFormatting.DARK_GRAY + "Coal"; + blue = EnumChatFormatting.WHITE + "Quartz, " + EnumChatFormatting.YELLOW + "Gold, " + EnumChatFormatting.DARK_GRAY + "Coal, " + EnumChatFormatting.GREEN + "Emerald, " + EnumChatFormatting.RED + "Clay"; + green = EnumChatFormatting.YELLOW + "Gold, " + EnumChatFormatting.GREEN + "Emerald"; + red = EnumChatFormatting.YELLOW + "Gold, " + EnumChatFormatting.AQUA + "Diamond, " + EnumChatFormatting.GREEN + "Emerald, " + EnumChatFormatting.RED + "Clay"; + break; + default: + purple = orange = blue = green = red = DankersSkyblockMod.ERROR_COLOUR + "Error detecting water puzzle variant."; + break; + } + waterAnswers = DankersSkyblockMod.MAIN_COLOUR + "The following levers must be down:\n" + + EnumChatFormatting.DARK_PURPLE + "Purple: " + purple + "\n" + + EnumChatFormatting.GOLD + "Orange: " + orange + "\n" + + EnumChatFormatting.BLUE + "Blue: " + blue + "\n" + + EnumChatFormatting.GREEN + "Green: " + green + "\n" + + EnumChatFormatting.RED + "Red: " + red; + done = true; + break; + } + } + } + if (done) break; + } + } else { + waterAnswers = null; + } + }).start(); + } + } + } + + @SubscribeEvent + public void renderPlayerInfo(RenderOverlay event) { + if (ToggleCommand.waterToggled && Utils.inDungeons && waterAnswers != null) { + new TextRenderer(Minecraft.getMinecraft(), waterAnswers, MoveCommand.waterAnswerXY[0], MoveCommand.waterAnswerXY[1], ScaleCommand.waterAnswerScale); + } + } + +} |