From e1b951f6124c28a5cc1ec9d9ca3416f5104b27b3 Mon Sep 17 00:00:00 2001 From: Aaron <51387595+AzureAaron@users.noreply.github.com> Date: Sun, 19 May 2024 11:45:42 -0400 Subject: Simon Says Solver --- .../skyblock/dungeon/device/SimonSays.java | 124 +++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java (limited to 'src/main/java/de/hysky/skyblocker/skyblock') diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java new file mode 100644 index 00000000..341c6025 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java @@ -0,0 +1,124 @@ +package de.hysky.skyblocker.skyblock.dungeon.device; + +import java.util.Objects; + +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.dungeon.DungeonBoss; +import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonManager; +import de.hysky.skyblocker.utils.Boxes; +import de.hysky.skyblocker.utils.Utils; +import de.hysky.skyblocker.utils.render.RenderHelper; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectRBTreeMap; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import it.unimi.dsi.fastutil.objects.ObjectSet; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.fabricmc.fabric.api.event.player.UseBlockCallback; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.ActionResult; +import net.minecraft.util.DyeColor; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class SimonSays { + private static final Box BOARD_AREA = Box.enclosing(new BlockPos(111, 123, 92), new BlockPos(111, 120, 95)); + private static final Box BUTTONS_AREA = Box.enclosing(new BlockPos(110, 123, 92), new BlockPos(110, 120, 95)); + private static final BlockPos START_BUTTON = new BlockPos(110, 121, 91); + private static final float[] GREEN = DyeColor.LIME.getColorComponents(); + private static final float[] YELLOW = DyeColor.YELLOW.getColorComponents(); + private static final ObjectSet CLICKED_BUTTONS = new ObjectOpenHashSet<>(); + private static final Int2ObjectRBTreeMap SIMON_PATTERN = new Int2ObjectRBTreeMap<>(); + + public static void init() { + UseBlockCallback.EVENT.register(SimonSays::onBlockInteract); + ClientPlayConnectionEvents.JOIN.register((_handler, _sender, _client) -> reset()); + WorldRenderEvents.AFTER_TRANSLUCENT.register(SimonSays::render); + } + + //When another player is pressing the buttons hypixel doesnt send block or block state updates + //so you can't see it which means the solver can only count the buttons you press yourself + private static ActionResult onBlockInteract(PlayerEntity player, World world, Hand hand, BlockHitResult hitResult) { + if (shouldProcess()) { + BlockPos pos = hitResult.getBlockPos(); + Block block = world.getBlockState(pos).getBlock(); + + if (block.equals(Blocks.STONE_BUTTON)) { + if (BUTTONS_AREA.contains(Vec3d.of(pos))) { + CLICKED_BUTTONS.add(new BlockPos(pos)); //Copy just in case it becomes mutable in the future + } else if (pos.equals(START_BUTTON)) { + reset(); + } + } + } + + //This could also be used to cancel incorrect clicks in the future + return ActionResult.PASS; + } + + //If the player goes out of the range required to receive block/chunk updates then their solver won't detect stuff but that + //doesn't matter because if they're doing pre-4 or something they won't be doing the ss, and if they end up needing to they can + //just reset it or have the other person finish the current sequence first then let them do it. + public static void onBlockUpdate(BlockPos pos, BlockState state) { + if (shouldProcess()) { + Vec3d posVec = Vec3d.of(pos); + Block block = state.getBlock(); + + if (BOARD_AREA.contains(posVec) && block.equals(Blocks.SEA_LANTERN)) { + int nextIndex = SIMON_PATTERN.size() + 1; + + SIMON_PATTERN.put(nextIndex, new BlockPos(pos)); //Copy it because it can be mutable in chunk delta updates + } else if (BUTTONS_AREA.contains(posVec) && block.equals(Blocks.AIR)) { + //Upon reaching the showing of the next sequence we need to reset the state so that we don't show old data + //Otherwise, the nextIndex will go beyond 5 and that can cause bugs, it also helps with the other case noted above + reset(); + } + } + } + + private static void render(WorldRenderContext context) { + if (shouldProcess()) { + int buttonsRendered = 0; + + //Tree maps iterate in natural order of key - so it goes from the lowest to the highest int :) + for (Int2ObjectMap.Entry entry : SIMON_PATTERN.int2ObjectEntrySet()) { + //Offset to west (x - 1) to get the position of the button from the sea lantern block + BlockPos buttonPos = entry.getValue().west(); + ClientWorld world = Objects.requireNonNull(MinecraftClient.getInstance().world); //Should never be null here + BlockState state = world.getBlockState(buttonPos); + + //If the button hasn't been clicked yet + //Also don't do anything if the button isn't there which means the device is showing the sequence + if (!CLICKED_BUTTONS.contains(buttonPos) && state.getBlock().equals(Blocks.STONE_BUTTON)) { + Box outline = state.getOutlineShape(world, buttonPos).asCuboid().getBoundingBox().offset(buttonPos); + float[] colour = buttonsRendered == 0 ? GREEN : YELLOW; + + RenderHelper.renderFilled(context, Boxes.getMinVec(outline), Boxes.getLengthVec(outline), colour, 0.5f, true); + RenderHelper.renderOutline(context, outline, colour, 5f, true); + + if (++buttonsRendered == 2) return; + } + } + } + } + + private static boolean shouldProcess() { + return SkyblockerConfigManager.get().dungeons.devices.solveSimonSays && + Utils.isInDungeons() && DungeonManager.isInBoss() && DungeonManager.getBoss() == DungeonBoss.MAXOR; + } + + private static void reset() { + CLICKED_BUTTONS.clear(); + SIMON_PATTERN.clear(); + } +} -- cgit From 41b575e41545fbea3b38deb516ba580251a9cd0b Mon Sep 17 00:00:00 2001 From: Aaron <51387595+AzureAaron@users.noreply.github.com> Date: Wed, 29 May 2024 14:53:18 -0400 Subject: Move block bounding box into RenderHelper --- .../java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/de/hysky/skyblocker/skyblock') diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java index 341c6025..20bd9ebc 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java @@ -100,7 +100,7 @@ public class SimonSays { //If the button hasn't been clicked yet //Also don't do anything if the button isn't there which means the device is showing the sequence if (!CLICKED_BUTTONS.contains(buttonPos) && state.getBlock().equals(Blocks.STONE_BUTTON)) { - Box outline = state.getOutlineShape(world, buttonPos).asCuboid().getBoundingBox().offset(buttonPos); + Box outline = RenderHelper.getBlockBoundingBox(world, state, buttonPos); float[] colour = buttonsRendered == 0 ? GREEN : YELLOW; RenderHelper.renderFilled(context, Boxes.getMinVec(outline), Boxes.getLengthVec(outline), colour, 0.5f, true); -- cgit From 99e70f1d9aaafa5f9f39500efbc474eda561eda8 Mon Sep 17 00:00:00 2001 From: Aaron <51387595+AzureAaron@users.noreply.github.com> Date: Wed, 10 Jul 2024 15:49:11 -0400 Subject: Port Simon Says solver to 1.21 --- .../java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/main/java/de/hysky/skyblocker/skyblock') diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java index 20bd9ebc..0c78c2d3 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java @@ -6,6 +6,7 @@ import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.dungeon.DungeonBoss; import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonManager; import de.hysky.skyblocker.utils.Boxes; +import de.hysky.skyblocker.utils.ColorUtils; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.render.RenderHelper; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; @@ -35,8 +36,8 @@ public class SimonSays { private static final Box BOARD_AREA = Box.enclosing(new BlockPos(111, 123, 92), new BlockPos(111, 120, 95)); private static final Box BUTTONS_AREA = Box.enclosing(new BlockPos(110, 123, 92), new BlockPos(110, 120, 95)); private static final BlockPos START_BUTTON = new BlockPos(110, 121, 91); - private static final float[] GREEN = DyeColor.LIME.getColorComponents(); - private static final float[] YELLOW = DyeColor.YELLOW.getColorComponents(); + private static final float[] GREEN = ColorUtils.getFloatComponents(DyeColor.LIME); + private static final float[] YELLOW = ColorUtils.getFloatComponents(DyeColor.YELLOW); private static final ObjectSet CLICKED_BUTTONS = new ObjectOpenHashSet<>(); private static final Int2ObjectRBTreeMap SIMON_PATTERN = new Int2ObjectRBTreeMap<>(); -- cgit From 8f8b583c31955c192856126d3ce48810d301f016 Mon Sep 17 00:00:00 2001 From: Aaron <51387595+AzureAaron@users.noreply.github.com> Date: Wed, 10 Jul 2024 16:03:19 -0400 Subject: Refactor Simon Says solver Should be less conflicting with other things --- .../skyblocker/skyblock/dungeon/device/SimonSays.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'src/main/java/de/hysky/skyblocker/skyblock') diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java index 0c78c2d3..da07e13d 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java @@ -9,8 +9,8 @@ import de.hysky.skyblocker.utils.Boxes; import de.hysky.skyblocker.utils.ColorUtils; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.render.RenderHelper; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectRBTreeMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectList; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import it.unimi.dsi.fastutil.objects.ObjectSet; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; @@ -39,7 +39,7 @@ public class SimonSays { private static final float[] GREEN = ColorUtils.getFloatComponents(DyeColor.LIME); private static final float[] YELLOW = ColorUtils.getFloatComponents(DyeColor.YELLOW); private static final ObjectSet CLICKED_BUTTONS = new ObjectOpenHashSet<>(); - private static final Int2ObjectRBTreeMap SIMON_PATTERN = new Int2ObjectRBTreeMap<>(); + private static final ObjectList SIMON_PATTERN = new ObjectArrayList<>(); public static void init() { UseBlockCallback.EVENT.register(SimonSays::onBlockInteract); @@ -76,9 +76,7 @@ public class SimonSays { Block block = state.getBlock(); if (BOARD_AREA.contains(posVec) && block.equals(Blocks.SEA_LANTERN)) { - int nextIndex = SIMON_PATTERN.size() + 1; - - SIMON_PATTERN.put(nextIndex, new BlockPos(pos)); //Copy it because it can be mutable in chunk delta updates + SIMON_PATTERN.add(pos); } else if (BUTTONS_AREA.contains(posVec) && block.equals(Blocks.AIR)) { //Upon reaching the showing of the next sequence we need to reset the state so that we don't show old data //Otherwise, the nextIndex will go beyond 5 and that can cause bugs, it also helps with the other case noted above @@ -91,10 +89,9 @@ public class SimonSays { if (shouldProcess()) { int buttonsRendered = 0; - //Tree maps iterate in natural order of key - so it goes from the lowest to the highest int :) - for (Int2ObjectMap.Entry entry : SIMON_PATTERN.int2ObjectEntrySet()) { + for (BlockPos pos : SIMON_PATTERN) { //Offset to west (x - 1) to get the position of the button from the sea lantern block - BlockPos buttonPos = entry.getValue().west(); + BlockPos buttonPos = pos.west(); ClientWorld world = Objects.requireNonNull(MinecraftClient.getInstance().world); //Should never be null here BlockState state = world.getBlockState(buttonPos); -- cgit From c4103bd4c2a8e114806b79f693b6cb2c6552c208 Mon Sep 17 00:00:00 2001 From: Aaron <51387595+AzureAaron@users.noreply.github.com> Date: Wed, 10 Jul 2024 21:49:47 -0400 Subject: Lights On Solver --- .../skyblock/dungeon/device/LightsOn.java | 46 ++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/LightsOn.java (limited to 'src/main/java/de/hysky/skyblocker/skyblock') diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/LightsOn.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/LightsOn.java new file mode 100644 index 00000000..debbc13d --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/LightsOn.java @@ -0,0 +1,46 @@ +package de.hysky.skyblocker.skyblock.dungeon.device; + +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.dungeon.DungeonBoss; +import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonManager; +import de.hysky.skyblocker.utils.ColorUtils; +import de.hysky.skyblocker.utils.Utils; +import de.hysky.skyblocker.utils.render.RenderHelper; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.minecraft.block.BlockState; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.state.property.Properties; +import net.minecraft.util.DyeColor; +import net.minecraft.util.math.BlockPos; + +public class LightsOn { + private static final MinecraftClient CLIENT = MinecraftClient.getInstance(); + private static final BlockPos TOP_LEFT = new BlockPos(62, 136, 142); + private static final BlockPos TOP_RIGHT = new BlockPos(58, 136, 142); + private static final BlockPos MIDDLE_TOP = new BlockPos(60, 135, 142); + private static final BlockPos MIDDLE_BOTTOM = new BlockPos(60, 134, 142); + private static final BlockPos BOTTOM_LEFT = new BlockPos(62, 133, 142); + private static final BlockPos BOTTOM_RIGHT = new BlockPos(58, 133, 142); + private static final BlockPos[] LEVERS = { TOP_LEFT, TOP_RIGHT, MIDDLE_TOP, MIDDLE_BOTTOM, BOTTOM_LEFT, BOTTOM_RIGHT }; + private static final float[] RED = ColorUtils.getFloatComponents(DyeColor.RED); + + public static void init() { + WorldRenderEvents.AFTER_TRANSLUCENT.register(LightsOn::render); + } + + private static void render(WorldRenderContext context) { + if (SkyblockerConfigManager.get().dungeons.devices.solveLightsOn && Utils.isInDungeons() && DungeonManager.isInBoss() && DungeonManager.getBoss() == DungeonBoss.MAXOR) { + for (BlockPos lever : LEVERS) { + ClientWorld world = CLIENT.world; + BlockState state = world.getBlockState(lever); + boolean powered = state.get(Properties.POWERED); + + if (!powered) { + RenderHelper.renderFilled(context, lever, RED, 0.5f, false); + } + } + } + } +} -- cgit From b21e5206e0f433873b71d2f5ed84ca3ccb6105a3 Mon Sep 17 00:00:00 2001 From: Aaron <51387595+AzureAaron@users.noreply.github.com> Date: Wed, 10 Jul 2024 22:00:02 -0400 Subject: Well that would've never worked ;( --- .../java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/de/hysky/skyblocker/skyblock') diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java index da07e13d..5aa97dd9 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java @@ -76,7 +76,7 @@ public class SimonSays { Block block = state.getBlock(); if (BOARD_AREA.contains(posVec) && block.equals(Blocks.SEA_LANTERN)) { - SIMON_PATTERN.add(pos); + SIMON_PATTERN.add(pos.toImmutable()); //Convert to immutable because chunk delta updates use the mutable variant } else if (BUTTONS_AREA.contains(posVec) && block.equals(Blocks.AIR)) { //Upon reaching the showing of the next sequence we need to reset the state so that we don't show old data //Otherwise, the nextIndex will go beyond 5 and that can cause bugs, it also helps with the other case noted above -- cgit From 6be49ddc41c0ee9d574af9b84cfe0933f89eb162 Mon Sep 17 00:00:00 2001 From: Aaron <51387595+AzureAaron@users.noreply.github.com> Date: Thu, 11 Jul 2024 04:53:06 -0400 Subject: Fix crash when lever blocks aren't loaded --- .../java/de/hysky/skyblocker/skyblock/dungeon/device/LightsOn.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/main/java/de/hysky/skyblocker/skyblock') diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/LightsOn.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/LightsOn.java index debbc13d..555a8e4b 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/LightsOn.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/LightsOn.java @@ -9,6 +9,7 @@ import de.hysky.skyblocker.utils.render.RenderHelper; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; import net.minecraft.client.MinecraftClient; import net.minecraft.client.world.ClientWorld; import net.minecraft.state.property.Properties; @@ -35,9 +36,8 @@ public class LightsOn { for (BlockPos lever : LEVERS) { ClientWorld world = CLIENT.world; BlockState state = world.getBlockState(lever); - boolean powered = state.get(Properties.POWERED); - if (!powered) { + if (state.getBlock().equals(Blocks.LEVER) && state.contains(Properties.POWERED) && !state.get(Properties.POWERED)) { RenderHelper.renderFilled(context, lever, RED, 0.5f, false); } } -- cgit