aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de/hysky/skyblocker/skyblock
diff options
context:
space:
mode:
authorAaron <51387595+AzureAaron@users.noreply.github.com>2024-07-13 15:12:17 -0400
committerGitHub <noreply@github.com>2024-07-13 15:12:17 -0400
commitb9378e6f8c57fe811ee87dbcce0b328edd06489b (patch)
tree493a450a813ad1971685c186e62afac2515e6975 /src/main/java/de/hysky/skyblocker/skyblock
parent66b1e05d468ea7a959e560b029eb1da908bc6caf (diff)
parent6be49ddc41c0ee9d574af9b84cfe0933f89eb162 (diff)
downloadSkyblocker-b9378e6f8c57fe811ee87dbcce0b328edd06489b.tar.gz
Skyblocker-b9378e6f8c57fe811ee87dbcce0b328edd06489b.tar.bz2
Skyblocker-b9378e6f8c57fe811ee87dbcce0b328edd06489b.zip
Merge pull request #724 from AzureAaron/simon-says
Simon Says Solver & Lights On Solver
Diffstat (limited to 'src/main/java/de/hysky/skyblocker/skyblock')
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/LightsOn.java46
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java122
2 files changed, 168 insertions, 0 deletions
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..555a8e4b
--- /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.block.Blocks;
+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);
+
+ if (state.getBlock().equals(Blocks.LEVER) && state.contains(Properties.POWERED) && !state.get(Properties.POWERED)) {
+ RenderHelper.renderFilled(context, lever, RED, 0.5f, false);
+ }
+ }
+ }
+ }
+}
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..5aa97dd9
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java
@@ -0,0 +1,122 @@
+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.ColorUtils;
+import de.hysky.skyblocker.utils.Utils;
+import de.hysky.skyblocker.utils.render.RenderHelper;
+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;
+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 = ColorUtils.getFloatComponents(DyeColor.LIME);
+ private static final float[] YELLOW = ColorUtils.getFloatComponents(DyeColor.YELLOW);
+ private static final ObjectSet<BlockPos> CLICKED_BUTTONS = new ObjectOpenHashSet<>();
+ private static final ObjectList<BlockPos> SIMON_PATTERN = new ObjectArrayList<>();
+
+ 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)) {
+ 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
+ reset();
+ }
+ }
+ }
+
+ private static void render(WorldRenderContext context) {
+ if (shouldProcess()) {
+ int buttonsRendered = 0;
+
+ for (BlockPos pos : SIMON_PATTERN) {
+ //Offset to west (x - 1) to get the position of the button from the sea lantern block
+ BlockPos buttonPos = pos.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 = RenderHelper.getBlockBoundingBox(world, state, 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();
+ }
+}