From 2ffb38db700cabd13438e04b6d04811294230230 Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Wed, 31 Jan 2024 22:59:34 -0500 Subject: Add solvers --- .../skyblock/dungeon/puzzle/Boulder.java | 21 +++++++++++++++++++++ .../skyblock/dungeon/puzzle/IceFill.java | 9 +++++++++ .../skyblock/dungeon/puzzle/Silverfish.java | 22 ++++++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Boulder.java create mode 100644 src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java create mode 100644 src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Silverfish.java (limited to 'src/main/java') diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Boulder.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Boulder.java new file mode 100644 index 00000000..8987599a --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Boulder.java @@ -0,0 +1,21 @@ +package de.hysky.skyblocker.skyblock.dungeon.puzzle; + +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; +import net.minecraft.client.MinecraftClient; + +// right: 5, 63, 8 +// left: 25, 63, 8 +// jungle, birch +public class Boulder extends DungeonPuzzle { + public Boulder() { + super("Boulder", "boxes-room"); + } + + @Override + public void tick(MinecraftClient client) { + } + + @Override + public void render(WorldRenderContext context) { + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java new file mode 100644 index 00000000..069b565e --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java @@ -0,0 +1,9 @@ +package de.hysky.skyblocker.skyblock.dungeon.puzzle; + +// 1: 15, 69, 7 +// 2: 15, 70, 12 +// 3: 15, 71, 19 +// ice -> packed_ice +// polished andesite +public class IceFill { +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Silverfish.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Silverfish.java new file mode 100644 index 00000000..0784f4ed --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Silverfish.java @@ -0,0 +1,22 @@ +package de.hysky.skyblocker.skyblock.dungeon.puzzle; + +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; +import net.minecraft.client.MinecraftClient; + +//right: 7, 66, 8 +//left: 23, 66, 8 +//right back: 7, 66, 24 +//polished andesite +public class Silverfish extends DungeonPuzzle { + public Silverfish() { + super("Silverfish", "ice-silverfish-room"); + } + + @Override + public void tick(MinecraftClient client) { + } + + @Override + public void render(WorldRenderContext context) { + } +} -- cgit From 443753ad8ed3e9e98e70881a733003a9b6386499 Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Thu, 1 Feb 2024 22:35:25 -0500 Subject: Add silverfish board parsing --- .../java/de/hysky/skyblocker/SkyblockerMod.java | 8 +- .../hysky/skyblocker/config/SkyblockerConfig.java | 6 + .../skyblock/dungeon/puzzle/Boulder.java | 21 --- .../skyblock/dungeon/puzzle/IceFill.java | 25 ++- .../skyblock/dungeon/puzzle/Silverfish.java | 177 ++++++++++++++++++++- 5 files changed, 209 insertions(+), 28 deletions(-) delete mode 100644 src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Boulder.java (limited to 'src/main/java') diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java index b8722fc6..dca41bd1 100644 --- a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java +++ b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java @@ -8,18 +8,16 @@ import de.hysky.skyblocker.skyblock.*; import de.hysky.skyblocker.skyblock.crimson.kuudra.Kuudra; import de.hysky.skyblocker.skyblock.dungeon.*; import de.hysky.skyblocker.skyblock.dungeon.partyfinder.PartyFinderScreen; +import de.hysky.skyblocker.skyblock.dungeon.puzzle.*; import de.hysky.skyblocker.skyblock.dungeon.puzzle.boulder.Boulder; -import de.hysky.skyblocker.skyblock.dungeon.puzzle.CreeperBeams; -import de.hysky.skyblocker.skyblock.dungeon.puzzle.DungeonBlaze; -import de.hysky.skyblocker.skyblock.dungeon.puzzle.TicTacToe; import de.hysky.skyblocker.skyblock.dungeon.puzzle.waterboard.Waterboard; import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonManager; import de.hysky.skyblocker.skyblock.dungeon.secrets.SecretsTracker; import de.hysky.skyblocker.skyblock.dwarven.CrystalsHud; import de.hysky.skyblocker.skyblock.dwarven.CrystalsLocationsManager; import de.hysky.skyblocker.skyblock.dwarven.DwarvenHud; -import de.hysky.skyblocker.skyblock.end.TheEnd; import de.hysky.skyblocker.skyblock.end.BeaconHighlighter; +import de.hysky.skyblocker.skyblock.end.TheEnd; import de.hysky.skyblocker.skyblock.item.*; import de.hysky.skyblocker.skyblock.item.tooltip.BackpackPreview; import de.hysky.skyblocker.skyblock.item.tooltip.ItemTooltip; @@ -117,6 +115,8 @@ public class SkyblockerMod implements ClientModInitializer { DungeonManager.init(); DungeonBlaze.init(); Waterboard.init(); + Silverfish.init(); + IceFill.init(); DungeonScore.init(); PartyFinderScreen.initClass(); ChestValue.init(); diff --git a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java index b5ddcf5d..78458291 100644 --- a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java @@ -722,6 +722,12 @@ public class SkyblockerConfig { @SerialEntry public boolean solveBoulder = true; + @SerialEntry + public boolean solveIceFill = true; + + @SerialEntry + public boolean solveSilverfish = true; + @SerialEntry public boolean fireFreezeStaffTimer = true; diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Boulder.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Boulder.java deleted file mode 100644 index 8987599a..00000000 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Boulder.java +++ /dev/null @@ -1,21 +0,0 @@ -package de.hysky.skyblocker.skyblock.dungeon.puzzle; - -import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; -import net.minecraft.client.MinecraftClient; - -// right: 5, 63, 8 -// left: 25, 63, 8 -// jungle, birch -public class Boulder extends DungeonPuzzle { - public Boulder() { - super("Boulder", "boxes-room"); - } - - @Override - public void tick(MinecraftClient client) { - } - - @Override - public void render(WorldRenderContext context) { - } -} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java index 069b565e..3eee8a7c 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java @@ -1,9 +1,32 @@ package de.hysky.skyblocker.skyblock.dungeon.puzzle; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; +import net.minecraft.client.MinecraftClient; + // 1: 15, 69, 7 // 2: 15, 70, 12 // 3: 15, 71, 19 // ice -> packed_ice // polished andesite -public class IceFill { +public class IceFill extends DungeonPuzzle { + public static final IceFill INSTANCE = new IceFill(); + + public IceFill() { + super("ice-fill", "ice-path"); + } + + public static void init() {} + + @Override + public void tick(MinecraftClient client) { + if (!SkyblockerConfigManager.get().locations.dungeons.solveIceFill) { + return; + } + } + + @Override + public void render(WorldRenderContext context) { + + } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Silverfish.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Silverfish.java index 0784f4ed..195e38f7 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Silverfish.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Silverfish.java @@ -1,22 +1,195 @@ package de.hysky.skyblocker.skyblock.dungeon.puzzle; +import com.mojang.brigadier.Command; +import de.hysky.skyblocker.SkyblockerMod; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.debug.Debug; +import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonManager; +import de.hysky.skyblocker.skyblock.dungeon.secrets.Room; +import de.hysky.skyblocker.utils.Constants; +import de.hysky.skyblocker.utils.render.RenderHelper; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.mob.SilverfishEntity; +import net.minecraft.util.DyeColor; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; +import org.joml.Vector2i; +import org.joml.Vector2ic; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; //right: 7, 66, 8 //left: 23, 66, 8 //right back: 7, 66, 24 //polished andesite public class Silverfish extends DungeonPuzzle { - public Silverfish() { - super("Silverfish", "ice-silverfish-room"); + private static final Logger LOGGER = LoggerFactory.getLogger(Silverfish.class); + public static final Silverfish INSTANCE = new Silverfish(); + private static final float[] LIME_COLOR_COMPONENTS = DyeColor.LIME.getColorComponents(); + private final boolean[][] silverfishBoard = new boolean[17][17]; + private Vector2ic silverfishPos; + private final List silverfishPath = new ArrayList<>(); + + private Silverfish() { + super("silverfish", "ice-silverfish-room"); + if (Debug.debugEnabled()) { + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(literal("dungeons").then(literal("puzzle").then(literal(puzzleName) + .then(literal("printBoard").executes(context -> { + context.getSource().sendFeedback(Constants.PREFIX.get().append(boardToString(silverfishBoard))); + return Command.SINGLE_SUCCESS; + })).then(literal("printPath").executes(context -> { + context.getSource().sendFeedback(Constants.PREFIX.get().append(silverfishPath.toString())); + return Command.SINGLE_SUCCESS; + })) + ))))); + } + } + + public static void init() {} + + private static String boardToString(boolean[][] silverfishBoard) { + StringBuilder sb = new StringBuilder(); + for (boolean[] row : silverfishBoard) { + sb.append("\n"); + for (boolean cell : row) { + sb.append(cell ? '#' : '.'); + } + } + return sb.toString(); } @Override public void tick(MinecraftClient client) { + if (!SkyblockerConfigManager.get().locations.dungeons.solveSilverfish || client.world == null || !DungeonManager.isCurrentRoomMatched()) { + return; + } + Room room = DungeonManager.getCurrentRoom(); + + boolean boardChanged = false; + BlockPos.Mutable pos = new BlockPos.Mutable(23, 67, 24); + for (int row = 0; row < silverfishBoard.length; pos.move(silverfishBoard[row].length, 0, -1), row++) { + for (int col = 0; col < silverfishBoard[row].length; pos.move(Direction.WEST), col++) { + boolean isBlock = !client.world.getBlockState(room.relativeToActual(pos)).isAir(); + if (silverfishBoard[row][col] != isBlock) { + silverfishBoard[row][col] = isBlock; + boardChanged = true; + } + } + } + + BlockPos blockPos = room.relativeToActual(new BlockPos(16, 16, 16)); + List entities = client.world.getEntitiesByClass(SilverfishEntity.class, Box.of(Vec3d.ofCenter(blockPos), 32, 32, 32), silverfishEntity -> true); + if (entities.isEmpty()) { + return; + } + BlockPos newSilverfishBlockPos = room.actualToRelative(entities.get(0).getBlockPos()); + Vector2ic newSilverfishPos = new Vector2i(23 - newSilverfishBlockPos.getX(), 24 - newSilverfishBlockPos.getZ()); + if (newSilverfishPos.x() < 0 || newSilverfishPos.x() >= 17 || newSilverfishPos.y() < 0 || newSilverfishPos.y() >= 17) { + return; + } + boolean silverfishChanged = !newSilverfishPos.equals(silverfishPos); + if (silverfishChanged) { + silverfishPos = newSilverfishPos; + } + if (silverfishChanged || boardChanged) { + solve(); + } + } + + private void solve() { + if (silverfishPos == null) { + return; + } + Set visited = new HashSet<>(); + Queue> queue = new ArrayDeque<>(); + queue.add(List.of(silverfishPos)); + while (!queue.isEmpty()) { + List path = queue.poll(); + Vector2ic pos = path.get(path.size() - 1); + if (pos.equals(8, 0)) { + silverfishPath.clear(); + silverfishPath.addAll(path); + return; + } + + Vector2i posMutable = new Vector2i(pos); + while (posMutable.x() < 17 && !silverfishBoard[posMutable.x()][posMutable.y()]) { + posMutable.add(1, 0); + } + posMutable.add(-1, 0); + if (!visited.contains(posMutable)) { + ArrayList newPath = new ArrayList<>(path); + newPath.add(new Vector2i(posMutable)); + queue.add(newPath); + visited.add(posMutable); + } + + posMutable.set(pos); + while (posMutable.x() >= 0 && !silverfishBoard[posMutable.x()][posMutable.y()]) { + posMutable.add(-1, 0); + } + posMutable.add(1, 0); + if (!visited.contains(posMutable)) { + ArrayList newPath = new ArrayList<>(path); + newPath.add(new Vector2i(posMutable)); + queue.add(newPath); + visited.add(posMutable); + } + + posMutable.set(pos); + while (posMutable.y() < 17 && !silverfishBoard[posMutable.x()][posMutable.y()]) { + posMutable.add(0, 1); + } + posMutable.add(0, -1); + if (!visited.contains(posMutable)) { + ArrayList newPath = new ArrayList<>(path); + newPath.add(new Vector2i(posMutable)); + queue.add(newPath); + visited.add(posMutable); + } + + posMutable.set(pos); + while (posMutable.y() >= 0 && !silverfishBoard[posMutable.x()][posMutable.y()]) { + posMutable.add(0, -1); + } + posMutable.add(0, 1); + if (!visited.contains(posMutable)) { + ArrayList newPath = new ArrayList<>(path); + newPath.add(new Vector2i(posMutable)); + queue.add(newPath); + visited.add(posMutable); + } + } } @Override public void render(WorldRenderContext context) { + if (!SkyblockerConfigManager.get().locations.dungeons.solveSilverfish || !DungeonManager.isCurrentRoomMatched() || silverfishPath.isEmpty()) { + return; + } + Room room = DungeonManager.getCurrentRoom(); + BlockPos.Mutable pos = new BlockPos.Mutable(); + for (int i = 0; i < silverfishPath.size() - 1; i++) { + Vec3d start = Vec3d.ofCenter(room.relativeToActual(pos.set(23 - silverfishPath.get(i).x(), 67, 24 - silverfishPath.get(i).y()))); + Vec3d end = Vec3d.ofCenter(room.relativeToActual(pos.set(23 - silverfishPath.get(i + 1).x(), 67, 24 - silverfishPath.get(i + 1).y()))); + RenderHelper.renderLinesFromPoints(context, new Vec3d[]{start, end}, LIME_COLOR_COMPONENTS, 1f, 5f, true); + } + } + + @Override + public void reset() { + super.reset(); + for (boolean[] silverfishBoardRow : silverfishBoard) { + Arrays.fill(silverfishBoardRow, false); + } + silverfishPos = null; } } -- cgit From ca61d618df013434bce4fb6995bc40aec4dc07dc Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Fri, 2 Feb 2024 16:40:24 -0500 Subject: Finish silverfish and ice fill solvers --- .../skyblock/dungeon/puzzle/IceFill.java | 171 ++++++++++++++++++++- .../skyblock/dungeon/puzzle/Silverfish.java | 82 ++++------ .../dungeon/puzzle/waterboard/Waterboard.java | 14 +- 3 files changed, 204 insertions(+), 63 deletions(-) (limited to 'src/main/java') diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java index 3eee8a7c..7ab96d78 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java @@ -1,32 +1,187 @@ package de.hysky.skyblocker.skyblock.dungeon.puzzle; +import com.google.common.primitives.Booleans; +import com.mojang.brigadier.Command; +import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.debug.Debug; +import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonManager; +import de.hysky.skyblocker.skyblock.dungeon.secrets.Room; +import de.hysky.skyblocker.utils.Constants; +import de.hysky.skyblocker.utils.render.RenderHelper; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; import net.minecraft.client.MinecraftClient; +import net.minecraft.util.DyeColor; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import org.joml.Vector2i; +import org.joml.Vector2ic; + +import java.util.*; +import java.util.concurrent.CompletableFuture; + +import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; -// 1: 15, 69, 7 -// 2: 15, 70, 12 -// 3: 15, 71, 19 -// ice -> packed_ice -// polished andesite public class IceFill extends DungeonPuzzle { public static final IceFill INSTANCE = new IceFill(); + private static final float[] RED_COLOR_COMPONENTS = DyeColor.RED.getColorComponents(); + private static final BlockPos BOARD_1_ORIGIN = new BlockPos(16, 70, 9); + private static final BlockPos BOARD_2_ORIGIN = new BlockPos(17, 71, 16); + private static final BlockPos BOARD_3_ORIGIN = new BlockPos(18, 72, 25); + private CompletableFuture solve; + private final boolean[][] iceFillBoard1 = new boolean[3][3]; + private final boolean[][] iceFillBoard2 = new boolean[5][5]; + private final boolean[][] iceFillBoard3 = new boolean[7][7]; + private final List iceFillPath1 = new ArrayList<>(); + private final List iceFillPath2 = new ArrayList<>(); + private final List iceFillPath3 = new ArrayList<>(); - public IceFill() { + private IceFill() { super("ice-fill", "ice-path"); } - public static void init() {} + public static void init() { + if (Debug.debugEnabled()) { + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(literal("dungeons").then(literal("puzzle").then(literal(INSTANCE.puzzleName) + .then(literal("printBoard1").executes(context -> { + context.getSource().sendFeedback(Constants.PREFIX.get().append(boardToString(INSTANCE.iceFillBoard1))); + return Command.SINGLE_SUCCESS; + })).then(literal("printBoard2").executes(context -> { + context.getSource().sendFeedback(Constants.PREFIX.get().append(boardToString(INSTANCE.iceFillBoard2))); + return Command.SINGLE_SUCCESS; + })).then(literal("printBoard3").executes(context -> { + context.getSource().sendFeedback(Constants.PREFIX.get().append(boardToString(INSTANCE.iceFillBoard3))); + return Command.SINGLE_SUCCESS; + })).then(literal("printPath1").executes(context -> { + context.getSource().sendFeedback(Constants.PREFIX.get().append(INSTANCE.iceFillPath1.toString())); + return Command.SINGLE_SUCCESS; + })).then(literal("printPath2").executes(context -> { + context.getSource().sendFeedback(Constants.PREFIX.get().append(INSTANCE.iceFillPath2.toString())); + return Command.SINGLE_SUCCESS; + })).then(literal("printPath3").executes(context -> { + context.getSource().sendFeedback(Constants.PREFIX.get().append(INSTANCE.iceFillPath3.toString())); + return Command.SINGLE_SUCCESS; + })) + ))))); + } + } + + private static String boardToString(boolean[][] iceFillBoard) { + StringBuilder sb = new StringBuilder(); + for (boolean[] row : iceFillBoard) { + sb.append("\n"); + for (boolean cell : row) { + sb.append(cell ? '#' : '.'); + } + } + return sb.toString(); + } @Override public void tick(MinecraftClient client) { - if (!SkyblockerConfigManager.get().locations.dungeons.solveIceFill) { + if (!SkyblockerConfigManager.get().locations.dungeons.solveIceFill || client.world == null || !DungeonManager.isCurrentRoomMatched() || solve != null && !solve.isDone()) { return; } + Room room = DungeonManager.getCurrentRoom(); + + solve = CompletableFuture.runAsync(() -> { + BlockPos.Mutable pos = new BlockPos.Mutable(); + boolean board1Changed = updateBoard(client.world, room, iceFillBoard1, pos.set(BOARD_1_ORIGIN)); + boolean board2Changed = updateBoard(client.world, room, iceFillBoard2, pos.set(BOARD_2_ORIGIN)); + boolean board3Changed = updateBoard(client.world, room, iceFillBoard3, pos.set(BOARD_3_ORIGIN)); + + if (board1Changed) { + solve(iceFillBoard1, iceFillPath1); + } + if (board2Changed) { + solve(iceFillBoard2, iceFillPath2); + } + if (board3Changed) { + solve(iceFillBoard3, iceFillPath3); + } + }); + } + + private boolean updateBoard(World world, Room room, boolean[][] iceFillBoard, BlockPos.Mutable pos) { + boolean boardChanged = false; + for (int row = 0; row < iceFillBoard.length; pos.move(iceFillBoard[row].length, 0, -1), row++) { + for (int col = 0; col < iceFillBoard[row].length; pos.move(Direction.WEST), col++) { + BlockPos actualPos = room.relativeToActual(pos); + boolean isBlock = !world.getBlockState(actualPos).isAir(); + if (iceFillBoard[row][col] != isBlock) { + iceFillBoard[row][col] = isBlock; + boardChanged = true; + } + } + } + return boardChanged; + } + + private void solve(boolean[][] iceFillBoard, List iceFillPath) { + Vector2ic start = new Vector2i(iceFillBoard.length - 1, iceFillBoard[0].length / 2); + int count = iceFillBoard.length * iceFillBoard[0].length - Arrays.stream(iceFillBoard).mapToInt(Booleans::countTrue).sum(); + + Queue> queue = new ArrayDeque<>(); + queue.add(List.of(start)); + while (!queue.isEmpty()) { + List path = queue.poll(); + Vector2ic pos = path.get(path.size() - 1); + if (pos.x() == 0 && pos.y() == iceFillBoard[0].length / 2 && path.size() == count) { + iceFillPath.clear(); + iceFillPath.addAll(path); + return; + } + + Vector2i posMutable = pos.add(1, 0, new Vector2i()); + if (posMutable.x() < iceFillBoard.length && !iceFillBoard[posMutable.x()][posMutable.y()]) { + addQueue(queue, path, posMutable); + } + + posMutable = pos.add(-1, 0, new Vector2i()); + if (posMutable.x() >= 0 && !iceFillBoard[posMutable.x()][posMutable.y()]) { + addQueue(queue, path, posMutable); + } + + posMutable = pos.add(0, 1, new Vector2i()); + if (posMutable.y() < iceFillBoard[0].length && !iceFillBoard[posMutable.x()][posMutable.y()]) { + addQueue(queue, path, posMutable); + } + + posMutable = pos.add(0, -1, new Vector2i()); + if (posMutable.y() >= 0 && !iceFillBoard[posMutable.x()][posMutable.y()]) { + addQueue(queue, path, posMutable); + } + } + } + + private void addQueue(Queue> queue, List path, Vector2ic newPos) { + if (!path.contains(newPos)) { + List newPath = new ArrayList<>(path); + newPath.add(newPos); + queue.add(newPath); + } } @Override public void render(WorldRenderContext context) { + if (!SkyblockerConfigManager.get().locations.dungeons.solveIceFill || !DungeonManager.isCurrentRoomMatched()) { + return; + } + Room room = DungeonManager.getCurrentRoom(); + renderPath(context, room, iceFillPath1, BOARD_1_ORIGIN); + renderPath(context, room, iceFillPath2, BOARD_2_ORIGIN); + renderPath(context, room, iceFillPath3, BOARD_3_ORIGIN); + } + private void renderPath(WorldRenderContext context, Room room, List iceFillPath, BlockPos originPos) { + BlockPos.Mutable pos = new BlockPos.Mutable(); + for (int i = 0; i < iceFillPath.size() - 1; i++) { + Vec3d start = Vec3d.ofCenter(room.relativeToActual(pos.set(originPos).move(-iceFillPath.get(i).y(), 0, -iceFillPath.get(i).x()))); + Vec3d end = Vec3d.ofCenter(room.relativeToActual(pos.set(originPos).move(-iceFillPath.get(i + 1).y(), 0, -iceFillPath.get(i + 1).x()))); + RenderHelper.renderLinesFromPoints(context, new Vec3d[]{start, end}, RED_COLOR_COMPONENTS, 1f, 5f, true); + } } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Silverfish.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Silverfish.java index 195e38f7..b5cbc8ee 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Silverfish.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Silverfish.java @@ -26,35 +26,32 @@ import java.util.*; import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; -//right: 7, 66, 8 -//left: 23, 66, 8 -//right back: 7, 66, 24 -//polished andesite public class Silverfish extends DungeonPuzzle { private static final Logger LOGGER = LoggerFactory.getLogger(Silverfish.class); public static final Silverfish INSTANCE = new Silverfish(); - private static final float[] LIME_COLOR_COMPONENTS = DyeColor.LIME.getColorComponents(); - private final boolean[][] silverfishBoard = new boolean[17][17]; - private Vector2ic silverfishPos; - private final List silverfishPath = new ArrayList<>(); + private static final float[] RED_COLOR_COMPONENTS = DyeColor.RED.getColorComponents(); + final boolean[][] silverfishBoard = new boolean[17][17]; + Vector2ic silverfishPos; + final List silverfishPath = new ArrayList<>(); private Silverfish() { super("silverfish", "ice-silverfish-room"); + } + + public static void init() { if (Debug.debugEnabled()) { - ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(literal("dungeons").then(literal("puzzle").then(literal(puzzleName) + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(literal("dungeons").then(literal("puzzle").then(literal(INSTANCE.puzzleName) .then(literal("printBoard").executes(context -> { - context.getSource().sendFeedback(Constants.PREFIX.get().append(boardToString(silverfishBoard))); + context.getSource().sendFeedback(Constants.PREFIX.get().append(boardToString(INSTANCE.silverfishBoard))); return Command.SINGLE_SUCCESS; })).then(literal("printPath").executes(context -> { - context.getSource().sendFeedback(Constants.PREFIX.get().append(silverfishPath.toString())); + context.getSource().sendFeedback(Constants.PREFIX.get().append(INSTANCE.silverfishPath.toString())); return Command.SINGLE_SUCCESS; })) ))))); } } - public static void init() {} - private static String boardToString(boolean[][] silverfishBoard) { StringBuilder sb = new StringBuilder(); for (boolean[] row : silverfishBoard) { @@ -85,13 +82,12 @@ public class Silverfish extends DungeonPuzzle { } } - BlockPos blockPos = room.relativeToActual(new BlockPos(16, 16, 16)); - List entities = client.world.getEntitiesByClass(SilverfishEntity.class, Box.of(Vec3d.ofCenter(blockPos), 32, 32, 32), silverfishEntity -> true); + List entities = client.world.getEntitiesByClass(SilverfishEntity.class, Box.of(Vec3d.ofCenter(room.relativeToActual(new BlockPos(15, 66, 16))), 16, 16, 16), silverfishEntity -> true); if (entities.isEmpty()) { return; } BlockPos newSilverfishBlockPos = room.actualToRelative(entities.get(0).getBlockPos()); - Vector2ic newSilverfishPos = new Vector2i(23 - newSilverfishBlockPos.getX(), 24 - newSilverfishBlockPos.getZ()); + Vector2ic newSilverfishPos = new Vector2i(24 - newSilverfishBlockPos.getZ(), 23 - newSilverfishBlockPos.getX()); if (newSilverfishPos.x() < 0 || newSilverfishPos.x() >= 17 || newSilverfishPos.y() < 0 || newSilverfishPos.y() >= 17) { return; } @@ -104,17 +100,18 @@ public class Silverfish extends DungeonPuzzle { } } - private void solve() { + void solve() { if (silverfishPos == null) { return; } Set visited = new HashSet<>(); Queue> queue = new ArrayDeque<>(); queue.add(List.of(silverfishPos)); + visited.add(silverfishPos); while (!queue.isEmpty()) { List path = queue.poll(); Vector2ic pos = path.get(path.size() - 1); - if (pos.equals(8, 0)) { + if (pos.x() == 0 && pos.y() >= 7 && pos.y() <= 9) { silverfishPath.clear(); silverfishPath.addAll(path); return; @@ -125,48 +122,37 @@ public class Silverfish extends DungeonPuzzle { posMutable.add(1, 0); } posMutable.add(-1, 0); - if (!visited.contains(posMutable)) { - ArrayList newPath = new ArrayList<>(path); - newPath.add(new Vector2i(posMutable)); - queue.add(newPath); - visited.add(posMutable); - } + addQueue(visited, queue, path, posMutable); - posMutable.set(pos); + posMutable = new Vector2i(pos); while (posMutable.x() >= 0 && !silverfishBoard[posMutable.x()][posMutable.y()]) { posMutable.add(-1, 0); } posMutable.add(1, 0); - if (!visited.contains(posMutable)) { - ArrayList newPath = new ArrayList<>(path); - newPath.add(new Vector2i(posMutable)); - queue.add(newPath); - visited.add(posMutable); - } + addQueue(visited, queue, path, posMutable); - posMutable.set(pos); + posMutable = new Vector2i(pos); while (posMutable.y() < 17 && !silverfishBoard[posMutable.x()][posMutable.y()]) { posMutable.add(0, 1); } posMutable.add(0, -1); - if (!visited.contains(posMutable)) { - ArrayList newPath = new ArrayList<>(path); - newPath.add(new Vector2i(posMutable)); - queue.add(newPath); - visited.add(posMutable); - } + addQueue(visited, queue, path, posMutable); - posMutable.set(pos); + posMutable = new Vector2i(pos); while (posMutable.y() >= 0 && !silverfishBoard[posMutable.x()][posMutable.y()]) { posMutable.add(0, -1); } posMutable.add(0, 1); - if (!visited.contains(posMutable)) { - ArrayList newPath = new ArrayList<>(path); - newPath.add(new Vector2i(posMutable)); - queue.add(newPath); - visited.add(posMutable); - } + addQueue(visited, queue, path, posMutable); + } + } + + private void addQueue(Set visited, Queue> queue, List path, Vector2ic newPos) { + if (!visited.contains(newPos)) { + List newPath = new ArrayList<>(path); + newPath.add(newPos); + queue.add(newPath); + visited.add(newPos); } } @@ -178,9 +164,9 @@ public class Silverfish extends DungeonPuzzle { Room room = DungeonManager.getCurrentRoom(); BlockPos.Mutable pos = new BlockPos.Mutable(); for (int i = 0; i < silverfishPath.size() - 1; i++) { - Vec3d start = Vec3d.ofCenter(room.relativeToActual(pos.set(23 - silverfishPath.get(i).x(), 67, 24 - silverfishPath.get(i).y()))); - Vec3d end = Vec3d.ofCenter(room.relativeToActual(pos.set(23 - silverfishPath.get(i + 1).x(), 67, 24 - silverfishPath.get(i + 1).y()))); - RenderHelper.renderLinesFromPoints(context, new Vec3d[]{start, end}, LIME_COLOR_COMPONENTS, 1f, 5f, true); + Vec3d start = Vec3d.ofCenter(room.relativeToActual(pos.set(23 - silverfishPath.get(i).y(), 67, 24 - silverfishPath.get(i).x()))); + Vec3d end = Vec3d.ofCenter(room.relativeToActual(pos.set(23 - silverfishPath.get(i + 1).y(), 67, 24 - silverfishPath.get(i + 1).x()))); + RenderHelper.renderLinesFromPoints(context, new Vec3d[]{start, end}, RED_COLOR_COMPONENTS, 1f, 5f, true); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/waterboard/Waterboard.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/waterboard/Waterboard.java index 3244996a..ba4b9a5f 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/waterboard/Waterboard.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/waterboard/Waterboard.java @@ -88,17 +88,20 @@ public class Waterboard extends DungeonPuzzle { private Waterboard() { super("waterboard", "water-puzzle"); - UseBlockCallback.EVENT.register(this::onUseBlock); + } + + public static void init() { + UseBlockCallback.EVENT.register(INSTANCE::onUseBlock); if (Debug.debugEnabled()) { - ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(literal("dungeons").then(literal("puzzle").then(literal(puzzleName) + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(literal("dungeons").then(literal("puzzle").then(literal(INSTANCE.puzzleName) .then(literal("printBoard").executes(context -> { - context.getSource().sendFeedback(Constants.PREFIX.get().append(boardToString(cells))); + context.getSource().sendFeedback(Constants.PREFIX.get().append(boardToString(INSTANCE.cells))); return Command.SINGLE_SUCCESS; })).then(literal("printDoors").executes(context -> { context.getSource().sendFeedback(Constants.PREFIX.get().append(Integer.toBinaryString(INSTANCE.doors))); return Command.SINGLE_SUCCESS; })).then(literal("printSimulationResults").then(argument("combination", IntegerArgumentType.integer(0, 63)).executes(context -> { - context.getSource().sendFeedback(Constants.PREFIX.get().append(results[IntegerArgumentType.getInteger(context, "combination")].toString())); + context.getSource().sendFeedback(Constants.PREFIX.get().append(INSTANCE.results[IntegerArgumentType.getInteger(context, "combination")].toString())); return Command.SINGLE_SUCCESS; }))).then(literal("printCurrentCombination").executes(context -> { context.getSource().sendFeedback(Constants.PREFIX.get().append(Integer.toBinaryString(INSTANCE.currentCombination))); @@ -111,9 +114,6 @@ public class Waterboard extends DungeonPuzzle { } } - public static void init() { - } - private static String boardToString(Cell[][] cells) { StringBuilder sb = new StringBuilder(); for (Cell[] row : cells) { -- cgit From b3132a89b5036e27d7efbb5dbe47f96e520bf851 Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Sat, 3 Feb 2024 11:55:32 -0500 Subject: Add config --- .../skyblocker/config/categories/DungeonsCategory.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src/main/java') diff --git a/src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java index 5eb9a066..3ebd5d76 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java @@ -416,6 +416,20 @@ public class DungeonsCategory { newValue -> config.locations.dungeons.solveBoulder = newValue) .controller(ConfigUtils::createBooleanController) .build()) + .option(Option.createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.locations.dungeons.solveIceFill")) + .binding(defaults.locations.dungeons.solveIceFill, + () -> config.locations.dungeons.solveIceFill, + newValue -> config.locations.dungeons.solveIceFill = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) + .option(Option.createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.locations.dungeons.solveSilverfish")) + .binding(defaults.locations.dungeons.solveSilverfish, + () -> config.locations.dungeons.solveSilverfish, + newValue -> config.locations.dungeons.solveSilverfish = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) .option(Option.createBuilder() .name(Text.translatable("text.autoconfig.skyblocker.option.locations.dungeons.fireFreezeStaffTimer")) .description(OptionDescription.of(Text.translatable("text.autoconfig.skyblocker.option.locations.dungeons.fireFreezeStaffTimer.@Tooltip"))) -- cgit From 2fa902328a4a4a76f5ae300db7810530183b47d2 Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Sat, 3 Feb 2024 13:43:41 -0500 Subject: Change IceFill from bfs to dfs --- .../skyblock/dungeon/puzzle/IceFill.java | 137 ++++++++++++++++----- 1 file changed, 109 insertions(+), 28 deletions(-) (limited to 'src/main/java') diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java index 7ab96d78..166047b2 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java @@ -120,50 +120,131 @@ public class IceFill extends DungeonPuzzle { return boardChanged; } - private void solve(boolean[][] iceFillBoard, List iceFillPath) { + void solve(boolean[][] iceFillBoard, List iceFillPath) { Vector2ic start = new Vector2i(iceFillBoard.length - 1, iceFillBoard[0].length / 2); int count = iceFillBoard.length * iceFillBoard[0].length - Arrays.stream(iceFillBoard).mapToInt(Booleans::countTrue).sum(); - Queue> queue = new ArrayDeque<>(); - queue.add(List.of(start)); - while (!queue.isEmpty()) { - List path = queue.poll(); - Vector2ic pos = path.get(path.size() - 1); - if (pos.x() == 0 && pos.y() == iceFillBoard[0].length / 2 && path.size() == count) { - iceFillPath.clear(); - iceFillPath.addAll(path); - return; - } + List newPath = solveDfs(iceFillBoard, count - 1, new ArrayList<>(List.of(start))); + if (newPath != null) { + iceFillPath.clear(); + iceFillPath.addAll(newPath); + } + } - Vector2i posMutable = pos.add(1, 0, new Vector2i()); - if (posMutable.x() < iceFillBoard.length && !iceFillBoard[posMutable.x()][posMutable.y()]) { - addQueue(queue, path, posMutable); + private List solveDfs(boolean[][] iceFillBoard, int count, List path) { + Vector2ic pos = path.get(path.size() - 1); + if (pos.x() == 0 && pos.y() == iceFillBoard[0].length / 2 && count == 0) { + return path; + } + + Vector2ic newPos = pos.add(1, 0, new Vector2i()); + if (newPos.x() < iceFillBoard.length && !iceFillBoard[newPos.x()][newPos.y()] && !path.contains(newPos)) { + path.add(newPos); + List newPath = solveDfs(iceFillBoard, count - 1, path); + if (newPath != null) { + return newPath; + } else { + path.remove(path.size() - 1); } + } - posMutable = pos.add(-1, 0, new Vector2i()); - if (posMutable.x() >= 0 && !iceFillBoard[posMutable.x()][posMutable.y()]) { - addQueue(queue, path, posMutable); + newPos = pos.add(-1, 0, new Vector2i()); + if (newPos.x() >= 0 && !iceFillBoard[newPos.x()][newPos.y()] && !path.contains(newPos)) { + path.add(newPos); + List newPath = solveDfs(iceFillBoard, count - 1, path); + if (newPath != null) { + return newPath; + } else { + path.remove(path.size() - 1); } + } - posMutable = pos.add(0, 1, new Vector2i()); - if (posMutable.y() < iceFillBoard[0].length && !iceFillBoard[posMutable.x()][posMutable.y()]) { - addQueue(queue, path, posMutable); + newPos = pos.add(0, 1, new Vector2i()); + if (newPos.y() < iceFillBoard[0].length && !iceFillBoard[newPos.x()][newPos.y()] && !path.contains(newPos)) { + path.add(newPos); + List newPath = solveDfs(iceFillBoard, count - 1, path); + if (newPath != null) { + return newPath; + } else { + path.remove(path.size() - 1); } + } - posMutable = pos.add(0, -1, new Vector2i()); - if (posMutable.y() >= 0 && !iceFillBoard[posMutable.x()][posMutable.y()]) { - addQueue(queue, path, posMutable); + newPos = pos.add(0, -1, new Vector2i()); + if (newPos.y() >= 0 && !iceFillBoard[newPos.x()][newPos.y()] && !path.contains(newPos)) { + path.add(newPos); + List newPath = solveDfs(iceFillBoard, count - 1, path); + if (newPath != null) { + return newPath; + } else { + path.remove(path.size() - 1); } } + + return null; + } + + /* + void solve(boolean[][] iceFillBoard, List iceFillPath) { + Vector2ic start = new Vector2i(iceFillBoard.length - 1, iceFillBoard[0].length / 2); + int count = iceFillBoard.length * iceFillBoard[0].length - Arrays.stream(iceFillBoard).mapToInt(Booleans::countTrue).sum(); + + Vector2ic[] newPath = solveDfs(iceFillBoard, count - 1, new Vector2ic[]{start}); + if (newPath != null) { + iceFillPath.clear(); + iceFillPath.addAll(Arrays.asList(newPath)); + } } - private void addQueue(Queue> queue, List path, Vector2ic newPos) { - if (!path.contains(newPos)) { - List newPath = new ArrayList<>(path); - newPath.add(newPos); - queue.add(newPath); + private Vector2ic[] solveDfs(boolean[][] iceFillBoard, int count, Vector2ic[] path) { + Vector2ic pos = path[path.length - 1]; + if (pos.x() == 0 && pos.y() == iceFillBoard[0].length / 2 && count == 0) { + return path; + } + + Vector2ic newPos = pos.add(1, 0, new Vector2i()); + if (newPos.x() < iceFillBoard.length && !iceFillBoard[newPos.x()][newPos.y()] && !ArrayUtils.contains(path, newPos)) { + Vector2ic[] newPath = Arrays.copyOf(path, path.length + 1); + newPath[path.length] = newPos; + newPath = solveDfs(iceFillBoard, count - 1, newPath); + if (newPath != null) { + return newPath; + } + } + + newPos = pos.add(-1, 0, new Vector2i()); + if (newPos.x() >= 0 && !iceFillBoard[newPos.x()][newPos.y()] && !ArrayUtils.contains(path, newPos)) { + Vector2ic[] newPath = Arrays.copyOf(path, path.length + 1); + newPath[path.length] = newPos; + newPath = solveDfs(iceFillBoard, count - 1, newPath); + if (newPath != null) { + return newPath; + } + } + + newPos = pos.add(0, 1, new Vector2i()); + if (newPos.y() < iceFillBoard[0].length && !iceFillBoard[newPos.x()][newPos.y()] && !ArrayUtils.contains(path, newPos)) { + Vector2ic[] newPath = Arrays.copyOf(path, path.length + 1); + newPath[path.length] = newPos; + newPath = solveDfs(iceFillBoard, count - 1, newPath); + if (newPath != null) { + return newPath; + } } + + newPos = pos.add(0, -1, new Vector2i()); + if (newPos.y() >= 0 && !iceFillBoard[newPos.x()][newPos.y()] && !ArrayUtils.contains(path, newPos)) { + Vector2ic[] newPath = Arrays.copyOf(path, path.length + 1); + newPath[path.length] = newPos; + newPath = solveDfs(iceFillBoard, count - 1, newPath); + if (newPath != null) { + return newPath; + } + } + + return null; } + */ @Override public void render(WorldRenderContext context) { -- cgit From b463261d5d1e70d6f0f350bc2a2507e4483d31c3 Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Sat, 3 Feb 2024 16:15:47 -0500 Subject: Optimize ice fill --- .../skyblock/dungeon/puzzle/IceFill.java | 110 ++++++--------------- 1 file changed, 28 insertions(+), 82 deletions(-) (limited to 'src/main/java') diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java index 166047b2..9b6e7b1f 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java @@ -124,127 +124,73 @@ public class IceFill extends DungeonPuzzle { Vector2ic start = new Vector2i(iceFillBoard.length - 1, iceFillBoard[0].length / 2); int count = iceFillBoard.length * iceFillBoard[0].length - Arrays.stream(iceFillBoard).mapToInt(Booleans::countTrue).sum(); - List newPath = solveDfs(iceFillBoard, count - 1, new ArrayList<>(List.of(start))); + List newPath = solveDfs(iceFillBoard, count - 1, new ArrayList<>(List.of(start)), new HashSet<>(List.of(start))); if (newPath != null) { iceFillPath.clear(); iceFillPath.addAll(newPath); } } - private List solveDfs(boolean[][] iceFillBoard, int count, List path) { + private List solveDfs(boolean[][] iceFillBoard, int count, List path, Set visited) { Vector2ic pos = path.get(path.size() - 1); - if (pos.x() == 0 && pos.y() == iceFillBoard[0].length / 2 && count == 0) { - return path; + if (count == 0) { + if (pos.x() == 0 && pos.y() == iceFillBoard[0].length / 2) { + return path; + } else { + return null; + } } Vector2ic newPos = pos.add(1, 0, new Vector2i()); - if (newPos.x() < iceFillBoard.length && !iceFillBoard[newPos.x()][newPos.y()] && !path.contains(newPos)) { + if (newPos.x() < iceFillBoard.length && !iceFillBoard[newPos.x()][newPos.y()] && !visited.contains(newPos)) { path.add(newPos); - List newPath = solveDfs(iceFillBoard, count - 1, path); + visited.add(newPos); + List newPath = solveDfs(iceFillBoard, count - 1, path, visited); if (newPath != null) { return newPath; - } else { - path.remove(path.size() - 1); } + path.remove(path.size() - 1); + visited.remove(newPos); } newPos = pos.add(-1, 0, new Vector2i()); - if (newPos.x() >= 0 && !iceFillBoard[newPos.x()][newPos.y()] && !path.contains(newPos)) { + if (newPos.x() >= 0 && !iceFillBoard[newPos.x()][newPos.y()] && !visited.contains(newPos)) { path.add(newPos); - List newPath = solveDfs(iceFillBoard, count - 1, path); + visited.add(newPos); + List newPath = solveDfs(iceFillBoard, count - 1, path, visited); if (newPath != null) { return newPath; - } else { - path.remove(path.size() - 1); } + path.remove(path.size() - 1); + visited.remove(newPos); } newPos = pos.add(0, 1, new Vector2i()); - if (newPos.y() < iceFillBoard[0].length && !iceFillBoard[newPos.x()][newPos.y()] && !path.contains(newPos)) { + if (newPos.y() < iceFillBoard[0].length && !iceFillBoard[newPos.x()][newPos.y()] && !visited.contains(newPos)) { path.add(newPos); - List newPath = solveDfs(iceFillBoard, count - 1, path); + visited.add(newPos); + List newPath = solveDfs(iceFillBoard, count - 1, path, visited); if (newPath != null) { return newPath; - } else { - path.remove(path.size() - 1); } + path.remove(path.size() - 1); + visited.remove(newPos); } newPos = pos.add(0, -1, new Vector2i()); - if (newPos.y() >= 0 && !iceFillBoard[newPos.x()][newPos.y()] && !path.contains(newPos)) { + if (newPos.y() >= 0 && !iceFillBoard[newPos.x()][newPos.y()] && !visited.contains(newPos)) { path.add(newPos); - List newPath = solveDfs(iceFillBoard, count - 1, path); - if (newPath != null) { - return newPath; - } else { - path.remove(path.size() - 1); - } - } - - return null; - } - - /* - void solve(boolean[][] iceFillBoard, List iceFillPath) { - Vector2ic start = new Vector2i(iceFillBoard.length - 1, iceFillBoard[0].length / 2); - int count = iceFillBoard.length * iceFillBoard[0].length - Arrays.stream(iceFillBoard).mapToInt(Booleans::countTrue).sum(); - - Vector2ic[] newPath = solveDfs(iceFillBoard, count - 1, new Vector2ic[]{start}); - if (newPath != null) { - iceFillPath.clear(); - iceFillPath.addAll(Arrays.asList(newPath)); - } - } - - private Vector2ic[] solveDfs(boolean[][] iceFillBoard, int count, Vector2ic[] path) { - Vector2ic pos = path[path.length - 1]; - if (pos.x() == 0 && pos.y() == iceFillBoard[0].length / 2 && count == 0) { - return path; - } - - Vector2ic newPos = pos.add(1, 0, new Vector2i()); - if (newPos.x() < iceFillBoard.length && !iceFillBoard[newPos.x()][newPos.y()] && !ArrayUtils.contains(path, newPos)) { - Vector2ic[] newPath = Arrays.copyOf(path, path.length + 1); - newPath[path.length] = newPos; - newPath = solveDfs(iceFillBoard, count - 1, newPath); - if (newPath != null) { - return newPath; - } - } - - newPos = pos.add(-1, 0, new Vector2i()); - if (newPos.x() >= 0 && !iceFillBoard[newPos.x()][newPos.y()] && !ArrayUtils.contains(path, newPos)) { - Vector2ic[] newPath = Arrays.copyOf(path, path.length + 1); - newPath[path.length] = newPos; - newPath = solveDfs(iceFillBoard, count - 1, newPath); - if (newPath != null) { - return newPath; - } - } - - newPos = pos.add(0, 1, new Vector2i()); - if (newPos.y() < iceFillBoard[0].length && !iceFillBoard[newPos.x()][newPos.y()] && !ArrayUtils.contains(path, newPos)) { - Vector2ic[] newPath = Arrays.copyOf(path, path.length + 1); - newPath[path.length] = newPos; - newPath = solveDfs(iceFillBoard, count - 1, newPath); - if (newPath != null) { - return newPath; - } - } - - newPos = pos.add(0, -1, new Vector2i()); - if (newPos.y() >= 0 && !iceFillBoard[newPos.x()][newPos.y()] && !ArrayUtils.contains(path, newPos)) { - Vector2ic[] newPath = Arrays.copyOf(path, path.length + 1); - newPath[path.length] = newPos; - newPath = solveDfs(iceFillBoard, count - 1, newPath); + visited.add(newPos); + List newPath = solveDfs(iceFillBoard, count - 1, path, visited); if (newPath != null) { return newPath; } + path.remove(path.size() - 1); + visited.remove(newPos); } return null; } - */ @Override public void render(WorldRenderContext context) { -- cgit From 15268d52e7529c11dd4734005ae7b0815c68b7a4 Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Thu, 15 Feb 2024 11:38:12 -0500 Subject: Refactor IceFill --- .../skyblock/dungeon/puzzle/IceFill.java | 106 ++++++--------------- 1 file changed, 31 insertions(+), 75 deletions(-) (limited to 'src/main/java') diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java index 9b6e7b1f..57386674 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java @@ -28,16 +28,14 @@ import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.lit public class IceFill extends DungeonPuzzle { public static final IceFill INSTANCE = new IceFill(); private static final float[] RED_COLOR_COMPONENTS = DyeColor.RED.getColorComponents(); - private static final BlockPos BOARD_1_ORIGIN = new BlockPos(16, 70, 9); - private static final BlockPos BOARD_2_ORIGIN = new BlockPos(17, 71, 16); - private static final BlockPos BOARD_3_ORIGIN = new BlockPos(18, 72, 25); + private static final BlockPos[] BOARD_ORIGINS = { + new BlockPos(16, 70, 9), + new BlockPos(17, 71, 16), + new BlockPos(18, 72, 25) + }; private CompletableFuture solve; - private final boolean[][] iceFillBoard1 = new boolean[3][3]; - private final boolean[][] iceFillBoard2 = new boolean[5][5]; - private final boolean[][] iceFillBoard3 = new boolean[7][7]; - private final List iceFillPath1 = new ArrayList<>(); - private final List iceFillPath2 = new ArrayList<>(); - private final List iceFillPath3 = new ArrayList<>(); + private final boolean[][][] iceFillBoards = {new boolean[3][3], new boolean[5][5], new boolean[7][7]}; + private final List> iceFillPaths = List.of(new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); private IceFill() { super("ice-fill", "ice-path"); @@ -47,22 +45,22 @@ public class IceFill extends DungeonPuzzle { if (Debug.debugEnabled()) { ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(literal("dungeons").then(literal("puzzle").then(literal(INSTANCE.puzzleName) .then(literal("printBoard1").executes(context -> { - context.getSource().sendFeedback(Constants.PREFIX.get().append(boardToString(INSTANCE.iceFillBoard1))); + context.getSource().sendFeedback(Constants.PREFIX.get().append(boardToString(INSTANCE.iceFillBoards[0]))); return Command.SINGLE_SUCCESS; })).then(literal("printBoard2").executes(context -> { - context.getSource().sendFeedback(Constants.PREFIX.get().append(boardToString(INSTANCE.iceFillBoard2))); + context.getSource().sendFeedback(Constants.PREFIX.get().append(boardToString(INSTANCE.iceFillBoards[1]))); return Command.SINGLE_SUCCESS; })).then(literal("printBoard3").executes(context -> { - context.getSource().sendFeedback(Constants.PREFIX.get().append(boardToString(INSTANCE.iceFillBoard3))); + context.getSource().sendFeedback(Constants.PREFIX.get().append(boardToString(INSTANCE.iceFillBoards[2]))); return Command.SINGLE_SUCCESS; })).then(literal("printPath1").executes(context -> { - context.getSource().sendFeedback(Constants.PREFIX.get().append(INSTANCE.iceFillPath1.toString())); + context.getSource().sendFeedback(Constants.PREFIX.get().append(INSTANCE.iceFillPaths.get(0).toString())); return Command.SINGLE_SUCCESS; })).then(literal("printPath2").executes(context -> { - context.getSource().sendFeedback(Constants.PREFIX.get().append(INSTANCE.iceFillPath2.toString())); + context.getSource().sendFeedback(Constants.PREFIX.get().append(INSTANCE.iceFillPaths.get(1).toString())); return Command.SINGLE_SUCCESS; })).then(literal("printPath3").executes(context -> { - context.getSource().sendFeedback(Constants.PREFIX.get().append(INSTANCE.iceFillPath3.toString())); + context.getSource().sendFeedback(Constants.PREFIX.get().append(INSTANCE.iceFillPaths.get(2).toString())); return Command.SINGLE_SUCCESS; })) ))))); @@ -89,18 +87,10 @@ public class IceFill extends DungeonPuzzle { solve = CompletableFuture.runAsync(() -> { BlockPos.Mutable pos = new BlockPos.Mutable(); - boolean board1Changed = updateBoard(client.world, room, iceFillBoard1, pos.set(BOARD_1_ORIGIN)); - boolean board2Changed = updateBoard(client.world, room, iceFillBoard2, pos.set(BOARD_2_ORIGIN)); - boolean board3Changed = updateBoard(client.world, room, iceFillBoard3, pos.set(BOARD_3_ORIGIN)); - - if (board1Changed) { - solve(iceFillBoard1, iceFillPath1); - } - if (board2Changed) { - solve(iceFillBoard2, iceFillPath2); - } - if (board3Changed) { - solve(iceFillBoard3, iceFillPath3); + for (int i = 0; i < 3; i++) { + if (updateBoard(client.world, room, iceFillBoards[i], pos.set(BOARD_ORIGINS[i]))) { + solve(iceFillBoards[i], iceFillPaths.get(i)); + } } }); } @@ -141,52 +131,18 @@ public class IceFill extends DungeonPuzzle { } } - Vector2ic newPos = pos.add(1, 0, new Vector2i()); - if (newPos.x() < iceFillBoard.length && !iceFillBoard[newPos.x()][newPos.y()] && !visited.contains(newPos)) { - path.add(newPos); - visited.add(newPos); - List newPath = solveDfs(iceFillBoard, count - 1, path, visited); - if (newPath != null) { - return newPath; - } - path.remove(path.size() - 1); - visited.remove(newPos); - } - - newPos = pos.add(-1, 0, new Vector2i()); - if (newPos.x() >= 0 && !iceFillBoard[newPos.x()][newPos.y()] && !visited.contains(newPos)) { - path.add(newPos); - visited.add(newPos); - List newPath = solveDfs(iceFillBoard, count - 1, path, visited); - if (newPath != null) { - return newPath; - } - path.remove(path.size() - 1); - visited.remove(newPos); - } - - newPos = pos.add(0, 1, new Vector2i()); - if (newPos.y() < iceFillBoard[0].length && !iceFillBoard[newPos.x()][newPos.y()] && !visited.contains(newPos)) { - path.add(newPos); - visited.add(newPos); - List newPath = solveDfs(iceFillBoard, count - 1, path, visited); - if (newPath != null) { - return newPath; - } - path.remove(path.size() - 1); - visited.remove(newPos); - } - - newPos = pos.add(0, -1, new Vector2i()); - if (newPos.y() >= 0 && !iceFillBoard[newPos.x()][newPos.y()] && !visited.contains(newPos)) { - path.add(newPos); - visited.add(newPos); - List newPath = solveDfs(iceFillBoard, count - 1, path, visited); - if (newPath != null) { - return newPath; + Vector2ic[] newPosArray = {pos.add(1, 0, new Vector2i()), pos.add(-1, 0, new Vector2i()), pos.add(0, 1, new Vector2i()), pos.add(0, -1, new Vector2i())}; + for (Vector2ic newPos : newPosArray) { + if (newPos.x() >= 0 && newPos.x() < iceFillBoard.length && newPos.y() >= 0 && newPos.y() < iceFillBoard[0].length && !iceFillBoard[newPos.x()][newPos.y()] && !visited.contains(newPos)) { + path.add(newPos); + visited.add(newPos); + List newPath = solveDfs(iceFillBoard, count - 1, path, visited); + if (newPath != null) { + return newPath; + } +