package codes.biscuit.skyblockaddons.utils; import codes.biscuit.skyblockaddons.SkyblockAddons; import codes.biscuit.skyblockaddons.core.Feature; import codes.biscuit.skyblockaddons.core.Location; import lombok.Getter; import net.minecraft.client.Minecraft; import net.minecraft.entity.Entity; import net.minecraft.entity.monster.EntityIronGolem; import net.minecraft.init.Blocks; import net.minecraft.util.BlockPos; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class EndstoneProtectorManager { @Getter private static boolean canDetectSkull = false; @Getter private static Stage minibossStage = null; @Getter private static int zealotCount = 0; private static long lastWaveStart = -1; public static void checkGolemStatus() { Minecraft mc = Minecraft.getMinecraft(); SkyblockAddons main = SkyblockAddons.getInstance(); if (mc.theWorld != null && (main.getUtils().getLocation() == Location.THE_END || main.getUtils().getLocation() == Location.DRAGONS_NEST) && main.getConfigValues().isEnabled(Feature.ENDSTONE_PROTECTOR_DISPLAY)) { World world = mc.theWorld; Chunk chunk = world.getChunkFromBlockCoords(new BlockPos(-689, 5, -273)); // This is the original spawn. if (chunk == null || !chunk.isLoaded()) { canDetectSkull = false; return; } Stage newStage = Stage.detectStage(); for (Entity entity : world.loadedEntityList) { if (entity instanceof EntityIronGolem) { newStage = Stage.GOLEM_ALIVE; break; } } canDetectSkull = true; if (minibossStage != newStage) { int timeTaken = (int) (System.currentTimeMillis()-lastWaveStart); String previousStage = (minibossStage == null ? "null" : minibossStage.name()); String zealotsKilled = "N/A"; if (minibossStage != null) { zealotsKilled = String.valueOf(zealotCount); } int totalSeconds = timeTaken/1000; int minutes = totalSeconds/60; int seconds = totalSeconds%60; main.getLogger().info("Endstone Protector stage updated from "+previousStage+" to "+newStage.name()+". " + "Your zealot kill count was "+zealotsKilled+". This took "+minutes+"m "+seconds+"s."); if (minibossStage == Stage.GOLEM_ALIVE && newStage == Stage.NO_HEAD) { zealotCount = 0; } minibossStage = newStage; lastWaveStart = System.currentTimeMillis(); } } else { canDetectSkull = false; } } public static void onKill() { zealotCount++; } public static void reset() { minibossStage = null; zealotCount = 0; canDetectSkull = false; } public enum Stage { NO_HEAD(-1), STAGE_1(0), STAGE_2(1), STAGE_3(2), STAGE_4(3), STAGE_5(4), GOLEM_ALIVE(-1); private int blocksUp; Stage(int blocksUp) { this.blocksUp = blocksUp; } private static Stage lastStage = null; private static BlockPos lastPos = null; private static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor(); public static Stage detectStage() { EXECUTOR.submit(() -> { try { World world = Minecraft.getMinecraft().theWorld; if (lastStage != null && lastPos != null) { if (Blocks.skull == world.getBlockState(lastPos).getBlock()) { return; } } for (Stage stage : values()) { if (stage.blocksUp != -1) { // These 4 coordinates are the bounds of the dragon's nest. for (int x = -749; x < -602; x++) { for (int z = -353; z < -202; z++) { BlockPos blockPos = new BlockPos(x, 5 + stage.blocksUp, z); if (Blocks.skull.equals(world.getBlockState(blockPos).getBlock())) { lastStage = stage; lastPos = blockPos; return; } } } } } lastStage = Stage.NO_HEAD; lastPos = null; } catch (Throwable ex) { ex.printStackTrace(); // It's fine I guess, just try checking next tick... } }); return lastStage; } } }