aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/me/Danker/features/puzzlesolvers
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/me/Danker/features/puzzlesolvers')
-rw-r--r--src/main/java/me/Danker/features/puzzlesolvers/BlazeSolver.java86
-rw-r--r--src/main/java/me/Danker/features/puzzlesolvers/BoulderSolver.java188
-rw-r--r--src/main/java/me/Danker/features/puzzlesolvers/ChronomatronSolver.java103
-rw-r--r--src/main/java/me/Danker/features/puzzlesolvers/ClickInOrderSolver.java107
-rw-r--r--src/main/java/me/Danker/features/puzzlesolvers/CreeperSolver.java86
-rw-r--r--src/main/java/me/Danker/features/puzzlesolvers/IceWalkSolver.java287
-rw-r--r--src/main/java/me/Danker/features/puzzlesolvers/LividSolver.java89
-rw-r--r--src/main/java/me/Danker/features/puzzlesolvers/SelectAllColourSolver.java59
-rw-r--r--src/main/java/me/Danker/features/puzzlesolvers/SilverfishSolver.java186
-rw-r--r--src/main/java/me/Danker/features/puzzlesolvers/StartsWithSolver.java31
-rw-r--r--src/main/java/me/Danker/features/puzzlesolvers/SuperpairsSolver.java150
-rw-r--r--src/main/java/me/Danker/features/puzzlesolvers/ThreeManSolver.java75
-rw-r--r--src/main/java/me/Danker/features/puzzlesolvers/TicTacToeSolver.java135
-rw-r--r--src/main/java/me/Danker/features/puzzlesolvers/TriviaSolver.java102
-rw-r--r--src/main/java/me/Danker/features/puzzlesolvers/UltrasequencerSolver.java87
-rw-r--r--src/main/java/me/Danker/features/puzzlesolvers/WaterSolver.java162
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';
+ }
+ }