aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKevinthegreat <92656833+kevinthegreat1@users.noreply.github.com>2023-12-21 14:53:52 +0800
committerKevinthegreat <92656833+kevinthegreat1@users.noreply.github.com>2023-12-21 14:53:52 +0800
commit003834e36b145791dd603858c924926be70e1281 (patch)
treef8fff7b26d3d3880259498c2f3ab18738d20184e /src
parent66b6be50ed9480d2d6e442c21ad16ed4bd48b2d6 (diff)
downloadSkyblocker-003834e36b145791dd603858c924926be70e1281.tar.gz
Skyblocker-003834e36b145791dd603858c924926be70e1281.tar.bz2
Skyblocker-003834e36b145791dd603858c924926be70e1281.zip
Refactor puzzle solvers
Diffstat (limited to 'src')
-rw-r--r--src/main/java/de/hysky/skyblocker/SkyblockerMod.java8
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/CreeperBeams.java (renamed from src/main/java/de/hysky/skyblocker/skyblock/dungeon/CreeperBeams.java)34
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/DungeonBlaze.java (renamed from src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonBlaze.java)30
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/DungeonPuzzle.java58
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/ThreeWeirdos.java (renamed from src/main/java/de/hysky/skyblocker/skyblock/dungeon/ThreeWeirdos.java)2
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/TicTacToe.java (renamed from src/main/java/de/hysky/skyblocker/skyblock/dungeon/TicTacToe.java)30
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Trivia.java (renamed from src/main/java/de/hysky/skyblocker/skyblock/dungeon/Trivia.java)2
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DebugRoom.java26
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonManager.java67
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/Room.java28
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/Tickable.java5
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/chat/ChatMessageListener.java4
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/render/Renderable.java7
-rw-r--r--src/test/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/ThreeWeirdosTest.java (renamed from src/test/java/de/hysky/skyblocker/skyblock/dungeon/ThreeWeirdosTest.java)2
-rw-r--r--src/test/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/TriviaTest.java (renamed from src/test/java/de/hysky/skyblocker/skyblock/dungeon/TriviaTest.java)2
15 files changed, 197 insertions, 108 deletions
diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java
index d1aa3153..9ce0df8d 100644
--- a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java
+++ b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java
@@ -5,7 +5,13 @@ import com.google.gson.GsonBuilder;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.debug.Debug;
import de.hysky.skyblocker.skyblock.*;
-import de.hysky.skyblocker.skyblock.dungeon.*;
+import de.hysky.skyblocker.skyblock.dungeon.DungeonMap;
+import de.hysky.skyblocker.skyblock.dungeon.FireFreezeStaffTimer;
+import de.hysky.skyblocker.skyblock.dungeon.GuardianHealth;
+import de.hysky.skyblocker.skyblock.dungeon.LividColor;
+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.secrets.DungeonManager;
import de.hysky.skyblocker.skyblock.dungeon.secrets.SecretsTracker;
import de.hysky.skyblocker.skyblock.dwarven.DwarvenHud;
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/CreeperBeams.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/CreeperBeams.java
index 5c7a01f9..8de1e3fe 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/CreeperBeams.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/CreeperBeams.java
@@ -1,13 +1,10 @@
-package de.hysky.skyblocker.skyblock.dungeon;
+package de.hysky.skyblocker.skyblock.dungeon.puzzle;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.utils.Utils;
import de.hysky.skyblocker.utils.render.RenderHelper;
-import de.hysky.skyblocker.utils.scheduler.Scheduler;
import it.unimi.dsi.fastutil.objects.ObjectDoublePair;
-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.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.client.MinecraftClient;
@@ -27,8 +24,7 @@ import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
-public class CreeperBeams {
-
+public class CreeperBeams extends DungeonPuzzle {
private static final Logger LOGGER = LoggerFactory.getLogger(CreeperBeams.class.getName());
private static final float[][] COLORS = {
@@ -41,27 +37,30 @@ public class CreeperBeams {
private static final int FLOOR_Y = 68;
private static final int BASE_Y = 74;
+ private static final CreeperBeams INSTANCE = new CreeperBeams("creeper", "creeper-room");
private static ArrayList<Beam> beams = new ArrayList<>();
private static BlockPos base = null;
- private static boolean solved = false;
+
+ private CreeperBeams(String puzzleName, String... roomName) {
+ super(puzzleName, roomName);
+ }
public static void init() {
- Scheduler.INSTANCE.scheduleCyclic(CreeperBeams::update, 20);
- WorldRenderEvents.BEFORE_DEBUG_RENDER.register(CreeperBeams::render);
- ClientPlayConnectionEvents.JOIN.register(((handler, sender, client) -> reset()));
}
- private static void reset() {
+ @Override
+ public void reset() {
+ super.reset();
beams.clear();
base = null;
- solved = false;
}
- private static void update() {
+ @Override
+ public void tick() {
// don't do anything if the room is solved
- if (solved) {
+ if (!shouldSolve()) {
return;
}
@@ -90,7 +89,7 @@ public class CreeperBeams {
// check if the room is solved
if (!isTarget(world, base)) {
- solved = true;
+ reset();
}
}
@@ -176,10 +175,11 @@ public class CreeperBeams {
return result;
}
- private static void render(WorldRenderContext wrc) {
+ @Override
+ public void render(WorldRenderContext wrc) {
// don't render if solved or disabled
- if (solved || !SkyblockerConfigManager.get().locations.dungeons.creeperSolver) {
+ if (!shouldSolve() || !SkyblockerConfigManager.get().locations.dungeons.creeperSolver) {
return;
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonBlaze.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/DungeonBlaze.java
index aabef183..5774eaef 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonBlaze.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/DungeonBlaze.java
@@ -1,14 +1,10 @@
-package de.hysky.skyblocker.skyblock.dungeon;
+package de.hysky.skyblocker.skyblock.dungeon.puzzle;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
-import de.hysky.skyblocker.events.DungeonEvents;
import de.hysky.skyblocker.utils.Utils;
import de.hysky.skyblocker.utils.render.RenderHelper;
-import de.hysky.skyblocker.utils.scheduler.Scheduler;
import it.unimi.dsi.fastutil.objects.ObjectIntPair;
-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.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.world.ClientWorld;
@@ -26,33 +22,30 @@ import java.util.List;
/**
* This class provides functionality to render outlines around Blaze entities
*/
-public class DungeonBlaze {
+public class DungeonBlaze extends DungeonPuzzle {
private static final Logger LOGGER = LoggerFactory.getLogger(DungeonBlaze.class.getName());
private static final float[] GREEN_COLOR_COMPONENTS = {0.0F, 1.0F, 0.0F};
private static final float[] WHITE_COLOR_COMPONENTS = {1.0f, 1.0f, 1.0f};
+ private static final DungeonBlaze INSTANCE = new DungeonBlaze("blaze", "blaze-room-1-high", "blaze-room-1-low");
- private static boolean inBlaze;
private static ArmorStandEntity highestBlaze = null;
private static ArmorStandEntity lowestBlaze = null;
private static ArmorStandEntity nextHighestBlaze = null;
private static ArmorStandEntity nextLowestBlaze = null;
+ private DungeonBlaze(String puzzleName, String... roomName) {
+ super(puzzleName, roomName);
+ }
+
public static void init() {
- DungeonEvents.PUZZLE_MATCHED.register(room -> {
- if (room.getName().startsWith("blaze-room")) {
- inBlaze = true;
- }
- });
- Scheduler.INSTANCE.scheduleCyclic(DungeonBlaze::update, 4);
- WorldRenderEvents.BEFORE_DEBUG_RENDER.register(DungeonBlaze::blazeRenderer);
- ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> inBlaze = false);
}
/**
* Updates the state of Blaze entities and triggers the rendering process if necessary.
*/
- public static void update() {
- if (!inBlaze) {
+ @Override
+ public void tick() {
+ if (!shouldSolve()) {
return;
}
ClientWorld world = MinecraftClient.getInstance().world;
@@ -116,7 +109,8 @@ public class DungeonBlaze {
*
* @param wrc The WorldRenderContext used for rendering.
*/
- public static void blazeRenderer(WorldRenderContext wrc) {
+ @Override
+ public void render(WorldRenderContext wrc) {
try {
if (highestBlaze != null && lowestBlaze != null && highestBlaze.isAlive() && lowestBlaze.isAlive() && SkyblockerConfigManager.get().locations.dungeons.blazeSolver) {
if (highestBlaze.getY() < 69) {
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/DungeonPuzzle.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/DungeonPuzzle.java
new file mode 100644
index 00000000..04446e60
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/DungeonPuzzle.java
@@ -0,0 +1,58 @@
+package de.hysky.skyblocker.skyblock.dungeon.puzzle;
+
+import com.mojang.brigadier.Command;
+import de.hysky.skyblocker.SkyblockerMod;
+import de.hysky.skyblocker.events.DungeonEvents;
+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.Tickable;
+import de.hysky.skyblocker.utils.render.Renderable;
+import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
+import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Set;
+
+import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;
+
+public abstract class DungeonPuzzle implements Tickable, Renderable {
+ private final String puzzleName;
+ @NotNull
+ private final Set<String> roomNames;
+ private boolean shouldSolve;
+
+ public DungeonPuzzle(String puzzleName, String... roomName) {
+ this(puzzleName, Set.of(roomName));
+ }
+
+ public DungeonPuzzle(String puzzleName, @NotNull Set<String> roomNames) {
+ this.puzzleName = puzzleName;
+ this.roomNames = roomNames;
+ DungeonEvents.PUZZLE_MATCHED.register(room -> {
+ if (roomNames.contains(room.getName())) {
+ room.addSubProcess(this);
+ shouldSolve = true;
+ }
+ });
+ ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(literal("dungeons").then(literal("solvePuzzle").then(literal(puzzleName).executes(context -> {
+ Room currentRoom = DungeonManager.getCurrentRoom();
+ if (currentRoom != null) {
+ currentRoom.addSubProcess(this);
+ context.getSource().sendFeedback(Constants.PREFIX.get().append("§aSolving " + puzzleName + " puzzle in the current room."));
+ } else {
+ context.getSource().sendError(Constants.PREFIX.get().append("§cCurrent room is null."));
+ }
+ return Command.SINGLE_SUCCESS;
+ }))))));
+ ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> reset());
+ }
+
+ public boolean shouldSolve() {
+ return shouldSolve;
+ }
+
+ public void reset() {
+ shouldSolve = false;
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/ThreeWeirdos.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/ThreeWeirdos.java
index e1ab2fa8..c5e55f93 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/ThreeWeirdos.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/ThreeWeirdos.java
@@ -1,4 +1,4 @@
-package de.hysky.skyblocker.skyblock.dungeon;
+package de.hysky.skyblocker.skyblock.dungeon.puzzle;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.utils.chat.ChatFilterResult;
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/TicTacToe.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/TicTacToe.java
index 2bb3e4e0..90028a4f 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/TicTacToe.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/TicTacToe.java
@@ -1,14 +1,10 @@
-package de.hysky.skyblocker.skyblock.dungeon;
+package de.hysky.skyblocker.skyblock.dungeon.puzzle;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
-import de.hysky.skyblocker.events.DungeonEvents;
import de.hysky.skyblocker.utils.Utils;
import de.hysky.skyblocker.utils.render.RenderHelper;
-import de.hysky.skyblocker.utils.scheduler.Scheduler;
import de.hysky.skyblocker.utils.tictactoe.TicTacToeUtils;
-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.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.client.MinecraftClient;
@@ -28,25 +24,22 @@ import java.util.List;
/**
* Thanks to Danker for a reference implementation!
*/
-public class TicTacToe {
+public class TicTacToe extends DungeonPuzzle {
private static final Logger LOGGER = LoggerFactory.getLogger(TicTacToe.class);
private static final float[] RED_COLOR_COMPONENTS = {1.0F, 0.0F, 0.0F};
- private static boolean inTicTacToe;
+ private static final TicTacToe INSTANCE = new TicTacToe("tic-tac-toe", "tic-tac-toe-1");
private static Box nextBestMoveToMake = null;
+ private TicTacToe(String puzzleName, String... roomName) {
+ super(puzzleName, roomName);
+ }
+
public static void init() {
- DungeonEvents.PUZZLE_MATCHED.register(room -> {
- if (room.getName().startsWith("tic-tac-toe")) {
- inTicTacToe = true;
- }
- });
- Scheduler.INSTANCE.scheduleCyclic(TicTacToe::tick, 4);
- WorldRenderEvents.BEFORE_DEBUG_RENDER.register(TicTacToe::solutionRenderer);
- ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> inTicTacToe = false);
}
- public static void tick() {
- if (!inTicTacToe) {
+ @Override
+ public void tick() {
+ if (!shouldSolve()) {
return;
}
@@ -139,7 +132,8 @@ public class TicTacToe {
}
}
- private static void solutionRenderer(WorldRenderContext context) {
+ @Override
+ public void render(WorldRenderContext context) {
try {
if (SkyblockerConfigManager.get().locations.dungeons.solveTicTacToe && nextBestMoveToMake != null) {
RenderHelper.renderOutline(context, nextBestMoveToMake, RED_COLOR_COMPONENTS, 5, false);
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/Trivia.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Trivia.java
index 21bbdce0..0f73457c 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/Trivia.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Trivia.java
@@ -1,4 +1,4 @@
-package de.hysky.skyblocker.skyblock.dungeon;
+package de.hysky.skyblocker.skyblock.dungeon.puzzle;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.skyblock.waypoint.FairySouls;
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DebugRoom.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DebugRoom.java
index b686607b..931d1d69 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DebugRoom.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DebugRoom.java
@@ -1,26 +1,38 @@
package de.hysky.skyblocker.skyblock.dungeon.secrets;
import de.hysky.skyblocker.utils.waypoint.Waypoint;
+import it.unimi.dsi.fastutil.ints.IntRBTreeSet;
+import it.unimi.dsi.fastutil.ints.IntSortedSet;
+import it.unimi.dsi.fastutil.ints.IntSortedSets;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.registry.Registries;
import net.minecraft.util.math.BlockPos;
import org.apache.commons.lang3.tuple.MutableTriple;
-import org.jetbrains.annotations.NotNull;
import org.joml.Vector2ic;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
public class DebugRoom extends Room {
private final List<Waypoint> checkedBlocks = Collections.synchronizedList(new ArrayList<>());
- public DebugRoom(@NotNull Type type, @NotNull Vector2ic... physicalPositions) {
+ public DebugRoom(Type type, Vector2ic... physicalPositions) {
super(type, physicalPositions);
}
+ public static DebugRoom ofSinglePossibleRoom(Type type, Vector2ic physicalPositions, String roomName, int[] roomData, Direction direction) {
+ return ofSinglePossibleRoom(type, new Vector2ic[]{physicalPositions}, roomName, roomData, direction);
+ }
+
+ public static DebugRoom ofSinglePossibleRoom(Type type, Vector2ic[] physicalPositions, String roomName, int[] roomData, Direction direction) {
+ DebugRoom room = new DebugRoom(type, physicalPositions);
+ IntSortedSet segmentsX = IntSortedSets.unmodifiable(new IntRBTreeSet(room.segments.stream().mapToInt(Vector2ic::x).toArray()));
+ IntSortedSet segmentsY = IntSortedSets.unmodifiable(new IntRBTreeSet(room.segments.stream().mapToInt(Vector2ic::y).toArray()));
+ room.roomsData = Map.of(roomName, roomData);
+ room.possibleRooms = List.of(MutableTriple.of(direction, DungeonMapUtils.getPhysicalCornerPos(direction, segmentsX, segmentsY), List.of(roomName)));
+ return room;
+ }
+
@Override
protected boolean checkBlock(ClientWorld world, BlockPos pos) {
byte id = DungeonManager.NUMERIC_ID.getByte(Registries.BLOCK.getId(world.getBlockState(pos).getBlock()).toString());
@@ -37,7 +49,7 @@ public class DebugRoom extends Room {
}
@Override
- protected void render(WorldRenderContext context) {
+ public void render(WorldRenderContext context) {
super.render(context);
synchronized (checkedBlocks) {
for (Waypoint checkedBlock : checkedBlocks) {
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonManager.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonManager.java
index 52915b98..722ecd85 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonManager.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonManager.java
@@ -18,9 +18,6 @@ import de.hysky.skyblocker.debug.Debug;
import de.hysky.skyblocker.utils.Constants;
import de.hysky.skyblocker.utils.Utils;
import de.hysky.skyblocker.utils.scheduler.Scheduler;
-import it.unimi.dsi.fastutil.ints.IntRBTreeSet;
-import it.unimi.dsi.fastutil.ints.IntSortedSet;
-import it.unimi.dsi.fastutil.ints.IntSortedSets;
import it.unimi.dsi.fastutil.objects.Object2ByteMap;
import it.unimi.dsi.fastutil.objects.Object2ByteOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectIntPair;
@@ -43,6 +40,7 @@ import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.mob.AmbientEntity;
import net.minecraft.entity.passive.BatEntity;
+import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.FilledMapItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
@@ -59,7 +57,6 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.World;
-import org.apache.commons.lang3.tuple.MutableTriple;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -200,6 +197,10 @@ public class DungeonManager {
return customWaypoints.remove(room, pos);
}
+ public static Room getCurrentRoom() {
+ return currentRoom;
+ }
+
/**
* Loads the dungeon secrets asynchronously from {@code /assets/skyblocker/dungeons}.
* Use {@link #isRoomsLoaded()} to check for completion of loading.
@@ -232,12 +233,13 @@ public class DungeonManager {
if (Debug.debugEnabled()) {
ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(literal("dungeons").then(literal("secrets")
.then(literal("matchAgainst").then(matchAgainstCommand()))
- .then(literal("clearSubRooms").executes(context -> {
+ .then(literal("clearSubProcesses").executes(context -> {
if (currentRoom != null) {
- currentRoom.subRooms.clear();
- context.getSource().sendFeedback(Constants.PREFIX.get().append("§rCleared sub rooms in the current room"));
+ currentRoom.tickables.clear();
+ currentRoom.renderables.clear();
+ context.getSource().sendFeedback(Constants.PREFIX.get().append("§rCleared sub processes in the current room."));
} else {
- context.getSource().sendError(Constants.PREFIX.get().append("§cCurrent room is null"));
+ context.getSource().sendError(Constants.PREFIX.get().append("§cCurrent room is null."));
}
return Command.SINGLE_SUCCESS;
}))
@@ -427,57 +429,58 @@ public class DungeonManager {
private static RequiredArgumentBuilder<FabricClientCommandSource, String> matchAgainstCommand() {
return argument("room", StringArgumentType.string()).suggests((context, builder) -> CommandSource.suggestMatching(ROOMS_DATA.values().stream().map(Map::values).flatMap(Collection::stream).map(Map::keySet).flatMap(Collection::stream), builder)).then(argument("direction", Room.Direction.DirectionArgumentType.direction()).executes(context -> {
if (physicalEntrancePos == null || mapEntrancePos == null || mapRoomSize == 0) {
- context.getSource().sendError(Constants.PREFIX.get().append("§cYou are not in a dungeon"));
+ context.getSource().sendError(Constants.PREFIX.get().append("§cYou are not in a dungeon."));
return Command.SINGLE_SUCCESS;
}
MinecraftClient client = MinecraftClient.getInstance();
if (client.player == null || client.world == null) {
- context.getSource().sendError(Constants.PREFIX.get().append("§cFailed to get player or world"));
+ context.getSource().sendError(Constants.PREFIX.get().append("§cFailed to get player or world."));
return Command.SINGLE_SUCCESS;
}
ItemStack stack = client.player.getInventory().main.get(8);
if (!stack.isOf(Items.FILLED_MAP)) {
- context.getSource().sendError(Constants.PREFIX.get().append("§cFailed to get dungeon map"));
+ context.getSource().sendError(Constants.PREFIX.get().append("§cFailed to get dungeon map."));
return Command.SINGLE_SUCCESS;
}
MapState map = FilledMapItem.getMapState(FilledMapItem.getMapId(stack), client.world);
if (map == null) {
- context.getSource().sendError(Constants.PREFIX.get().append("§cFailed to get dungeon map state"));
+ context.getSource().sendError(Constants.PREFIX.get().append("§cFailed to get dungeon map state."));
return Command.SINGLE_SUCCESS;
}
String roomName = StringArgumentType.getString(context, "room");
Room.Direction direction = Room.Direction.DirectionArgumentType.getDirection(context, "direction");
- Room room = null;
- int[] roomData;
- if ((roomData = ROOMS_DATA.get("catacombs").get(Room.Shape.PUZZLE.shape).get(roomName)) != null) {
- room = new DebugRoom(Room.Type.PUZZLE, DungeonMapUtils.getPhysicalRoomPos(client.player.getPos()));
- } else if ((roomData = ROOMS_DATA.get("catacombs").get(Room.Shape.TRAP.shape).get(roomName)) != null) {
- room = new DebugRoom(Room.Type.TRAP, DungeonMapUtils.getPhysicalRoomPos(client.player.getPos()));
- } else if ((roomData = ROOMS_DATA.get("catacombs").values().stream().map(Map::entrySet).flatMap(Collection::stream).filter(entry -> entry.getKey().equals(roomName)).findAny().map(Map.Entry::getValue).orElse(null)) != null) {
- room = new DebugRoom(Room.Type.ROOM, DungeonMapUtils.getPhysicalPosFromMap(mapEntrancePos, mapRoomSize, physicalEntrancePos, DungeonMapUtils.getRoomSegments(map, DungeonMapUtils.getMapRoomPos(map, mapEntrancePos, mapRoomSize), mapRoomSize, Room.Type.ROOM.color)));
- }
-
+ Room room = newDebugRoom(roomName, direction, client.player, map);
if (room == null) {
- context.getSource().sendError(Constants.PREFIX.get().append("§cFailed to find room with name " + roomName));
+ context.getSource().sendError(Constants.PREFIX.get().append("§cFailed to find room with name " + roomName + "."));
return Command.SINGLE_SUCCESS;
}
- IntSortedSet segmentsX = IntSortedSets.unmodifiable(new IntRBTreeSet(room.segments.stream().mapToInt(Vector2ic::x).toArray()));
- IntSortedSet segmentsY = IntSortedSets.unmodifiable(new IntRBTreeSet(room.segments.stream().mapToInt(Vector2ic::y).toArray()));
- room.roomsData = Map.of(roomName, roomData);
- room.possibleRooms = List.of(MutableTriple.of(direction, DungeonMapUtils.getPhysicalCornerPos(direction, segmentsX, segmentsY), List.of(roomName)));
if (currentRoom != null) {
- currentRoom.subRooms.add(room);
- context.getSource().sendFeedback(Constants.PREFIX.get().append("§rMatching room " + roomName + " with direction " + direction + " against current room"));
+ currentRoom.addSubProcess(room);
+ context.getSource().sendFeedback(Constants.PREFIX.get().append("§rMatching room " + roomName + " with direction " + direction + " against current room."));
} else {
- context.getSource().sendError(Constants.PREFIX.get().append("§cCurrent room is null"));
+ context.getSource().sendError(Constants.PREFIX.get().append("§cCurrent room is null."));
}
return Command.SINGLE_SUCCESS;
}));
}
+ @Nullable
+ private static Room newDebugRoom(String roomName, Room.Direction direction, PlayerEntity player, MapState map) {
+ Room room = null;
+ int[] roomData;
+ if ((roomData = ROOMS_DATA.get("catacombs").get(Room.Shape.PUZZLE.shape).get(roomName)) != null) {
+ room = DebugRoom.ofSinglePossibleRoom(Room.Type.PUZZLE, DungeonMapUtils.getPhysicalRoomPos(player.getPos()), roomName, roomData, direction);
+ } else if ((roomData = ROOMS_DATA.get("catacombs").get(Room.Shape.TRAP.shape).get(roomName)) != null) {
+ room = DebugRoom.ofSinglePossibleRoom(Room.Type.TRAP, DungeonMapUtils.getPhysicalRoomPos(player.getPos()), roomName, roomData, direction);
+ } else if ((roomData = ROOMS_DATA.get("catacombs").values().stream().map(Map::entrySet).flatMap(Collection::stream).filter(entry -> entry.getKey().equals(roomName)).findAny().map(Map.Entry::getValue).orElse(null)) != null) {
+ room = DebugRoom.ofSinglePossibleRoom(Room.Type.ROOM, DungeonMapUtils.getPhysicalPosFromMap(mapEntrancePos, mapRoomSize, physicalEntrancePos, DungeonMapUtils.getRoomSegments(map, DungeonMapUtils.getMapRoomPos(map, mapEntrancePos, mapRoomSize), mapRoomSize, Room.Type.ROOM.color)), roomName, roomData, direction);
+ }
+ return room;
+ }
+
/**
* Updates the dungeon. The general idea is similar to the Dungeon Rooms Mod.
* <p></p>
@@ -499,7 +502,7 @@ public class DungeonManager {
* <li> Create a new room. </li>
* </ul>
* <li> Sets {@link #currentRoom} to the current room, either created from the previous step or from {@link #rooms}. </li>
- * <li> Calls {@link Room#update()} on {@link #currentRoom}. </li>
+ * <li> Calls {@link Room#tick()} on {@link #currentRoom}. </li>
* </ul>
*/
@SuppressWarnings("JavadocReference")
@@ -553,7 +556,7 @@ public class DungeonManager {
if (room != null && currentRoom != room) {
currentRoom = room;
}
- currentRoom.update();
+ currentRoom.tick();
}
/**
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/Room.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/Room.java
index 40488717..d59bf7bf 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/Room.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/Room.java
@@ -11,7 +11,9 @@ import com.mojang.serialization.Codec;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.events.DungeonEvents;
import de.hysky.skyblocker.utils.Constants;
+import de.hysky.skyblocker.utils.Tickable;
import de.hysky.skyblocker.utils.render.RenderHelper;
+import de.hysky.skyblocker.utils.render.Renderable;
import de.hysky.skyblocker.utils.scheduler.Scheduler;
import it.unimi.dsi.fastutil.ints.IntRBTreeSet;
import it.unimi.dsi.fastutil.ints.IntSortedSet;
@@ -49,7 +51,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-public class Room {
+public class Room implements Tickable, Renderable {
private static final Pattern SECRET_INDEX = Pattern.compile("^(\\d+)");
private static final Pattern SECRETS = Pattern.compile("§7(\\d{1,2})/(\\d{1,2}) Secrets");
private static final Vec3d DOOR_SIZE = new Vec3d(3, 4, 3);
@@ -80,7 +82,7 @@ public class Room {
/**
* The task that is used to check blocks. This is used to ensure only one such task can run at a time.
*/
- private CompletableFuture<Void> findRoom;
+ protected CompletableFuture<Void> findRoom;
private int doubleCheckBlocks;
/**
* Represents the matching state of the room with the following possible values:
@@ -95,7 +97,8 @@ public class Room {
private Direction direction;
private Vector2ic physicalCornerPos;
- protected List<Room> subRooms = new ArrayList<>();
+ protected List<Tickable> tickables = new ArrayList<>();
+ protected List<Renderable> renderables = new ArrayList<>();
@Nullable
private BlockPos doorPos;
@Nullable
@@ -266,6 +269,11 @@ public class Room {
secretWaypoints.remove(secretIndex, actualPos);
}
+ public <T extends Tickable & Renderable> void addSubProcess(T process) {
+ tickables.add(process);
+ renderables.add(process);
+ }
+
/**
* Updates the room.
* <p></p>
@@ -285,15 +293,16 @@ public class Room {
* </ul>
*/
@SuppressWarnings("JavadocReference")
- protected void update() {
+ @Override
+ public void tick() {
MinecraftClient client = MinecraftClient.getInstance();
ClientWorld world = client.world;
if (world == null) {
return;
}
- for (Room subRoom : subRooms) {
- subRoom.update();
+ for (Tickable tickable : tickables) {
+ tickable.tick();
}
// Wither and blood door
@@ -506,9 +515,10 @@ public class Room {
/**
* Calls {@link SecretWaypoint#render(WorldRenderContext)} on {@link #secretWaypoints all secret waypoints} and renders a highlight around the wither or blood door, if it exists.
*/
- protected void render(WorldRenderContext context) {
- for (Room subRoom : subRooms) {
- subRoom.render(context);
+ @Override
+ public void render(WorldRenderContext context) {
+ for (Renderable renderable : renderables) {
+ renderable.render(context);
}
if (SkyblockerConfigManager.get().locations.dungeons.secretWaypoints.enableSecretWaypoints && isMatched()) {
diff --git a/src/main/java/de/hysky/skyblocker/utils/Tickable.java b/src/main/java/de/hysky/skyblocker/utils/Tickable.java
new file mode 100644
index 00000000..9b7b2e3f
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/utils/Tickable.java
@@ -0,0 +1,5 @@
+package de.hysky.skyblocker.utils;
+
+public interface Tickable {
+ void tick();
+}
diff --git a/src/main/java/de/hysky/skyblocker/utils/chat/ChatMessageListener.java b/src/main/java/de/hysky/skyblocker/utils/chat/ChatMessageListener.java
index 2c75ef0a..42f890b7 100644
--- a/src/main/java/de/hysky/skyblocker/utils/chat/ChatMessageListener.java
+++ b/src/main/java/de/hysky/skyblocker/utils/chat/ChatMessageListener.java
@@ -5,8 +5,8 @@ import de.hysky.skyblocker.utils.Utils;
import de.hysky.skyblocker.skyblock.barn.HungryHiker;
import de.hysky.skyblocker.skyblock.barn.TreasureHunter;
import de.hysky.skyblocker.skyblock.dungeon.Reparty;
-import de.hysky.skyblocker.skyblock.dungeon.ThreeWeirdos;
-import de.hysky.skyblocker.skyblock.dungeon.Trivia;
+import de.hysky.skyblocker.skyblock.dungeon.puzzle.ThreeWeirdos;
+import de.hysky.skyblocker.skyblock.dungeon.puzzle.Trivia;
import de.hysky.skyblocker.skyblock.dwarven.Fetchur;
import de.hysky.skyblocker.skyblock.dwarven.Puzzler;
import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents;
diff --git a/src/main/java/de/hysky/skyblocker/utils/render/Renderable.java b/src/main/java/de/hysky/skyblocker/utils/render/Renderable.java
new file mode 100644
index 00000000..b7743153
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/utils/render/Renderable.java
@@ -0,0 +1,7 @@
+package de.hysky.skyblocker.utils.render;
+
+import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
+
+public interface Renderable {
+ void render(WorldRenderContext context);
+}
diff --git a/src/test/java/de/hysky/skyblocker/skyblock/dungeon/ThreeWeirdosTest.java b/src/test/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/ThreeWeirdosTest.java
index 3772fd75..22683698 100644
--- a/src/test/java/de/hysky/skyblocker/skyblock/dungeon/ThreeWeirdosTest.java
+++ b/src/test/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/ThreeWeirdosTest.java
@@ -1,4 +1,4 @@
-package de.hysky.skyblocker.skyblock.dungeon;
+package de.hysky.skyblocker.skyblock.dungeon.puzzle;
import de.hysky.skyblocker.utils.chat.ChatPatternListenerTest;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/de/hysky/skyblocker/skyblock/dungeon/TriviaTest.java b/src/test/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/TriviaTest.java
index 1df5a8e1..55a59a68 100644
--- a/src/test/java/de/hysky/skyblocker/skyblock/dungeon/TriviaTest.java
+++ b/src/test/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/TriviaTest.java
@@ -1,4 +1,4 @@
-package de.hysky.skyblocker.skyblock.dungeon;
+package de.hysky.skyblocker.skyblock.dungeon.puzzle;
import de.hysky.skyblocker.utils.chat.ChatPatternListenerTest;
import org.junit.jupiter.api.Test;