aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de/hysky/skyblocker/skyblock
diff options
context:
space:
mode:
authorKevinthegreat <92656833+kevinthegreat1@users.noreply.github.com>2024-02-02 16:40:24 -0500
committerKevinthegreat <92656833+kevinthegreat1@users.noreply.github.com>2024-02-19 13:50:54 -0500
commitca61d618df013434bce4fb6995bc40aec4dc07dc (patch)
tree5779ccd73906683d2db4e2eb46c4fe4857290d73 /src/main/java/de/hysky/skyblocker/skyblock
parent443753ad8ed3e9e98e70881a733003a9b6386499 (diff)
downloadSkyblocker-ca61d618df013434bce4fb6995bc40aec4dc07dc.tar.gz
Skyblocker-ca61d618df013434bce4fb6995bc40aec4dc07dc.tar.bz2
Skyblocker-ca61d618df013434bce4fb6995bc40aec4dc07dc.zip
Finish silverfish and ice fill solvers
Diffstat (limited to 'src/main/java/de/hysky/skyblocker/skyblock')
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java171
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Silverfish.java82
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/waterboard/Waterboard.java14
3 files changed, 204 insertions, 63 deletions
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<Void> 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<Vector2ic> iceFillPath1 = new ArrayList<>();
+ private final List<Vector2ic> iceFillPath2 = new ArrayList<>();
+ private final List<Vector2ic> 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<Vector2ic> 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<List<Vector2ic>> queue = new ArrayDeque<>();
+ queue.add(List.of(start));
+ while (!queue.isEmpty()) {
+ List<Vector2ic> 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<List<Vector2ic>> queue, List<Vector2ic> path, Vector2ic newPos) {
+ if (!path.contains(newPos)) {
+ List<Vector2ic> 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<Vector2ic> 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<Vector2ic> silverfishPath = new ArrayList<>();
+ private static final float[] RED_COLOR_COMPONENTS = DyeColor.RED.getColorComponents();
+ final boolean[][] silverfishBoard = new boolean[17][17];
+ Vector2ic silverfishPos;
+ final List<Vector2ic> 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<SilverfishEntity> entities = client.world.getEntitiesByClass(SilverfishEntity.class, Box.of(Vec3d.ofCenter(blockPos), 32, 32, 32), silverfishEntity -> true);
+ List<SilverfishEntity> 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<Vector2ic> visited = new HashSet<>();
Queue<List<Vector2ic>> queue = new ArrayDeque<>();
queue.add(List.of(silverfishPos));
+ visited.add(silverfishPos);
while (!queue.isEmpty()) {
List<Vector2ic> 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<Vector2ic> 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<Vector2ic> 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<Vector2ic> 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<Vector2ic> newPath = new ArrayList<>(path);
- newPath.add(new Vector2i(posMutable));
- queue.add(newPath);
- visited.add(posMutable);
- }
+ addQueue(visited, queue, path, posMutable);
+ }
+ }
+
+ private void addQueue(Set<Vector2ic> visited, Queue<List<Vector2ic>> queue, List<Vector2ic> path, Vector2ic newPos) {
+ if (!visited.contains(newPos)) {
+ List<Vector2ic> 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) {