aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets
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/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets
parent66b6be50ed9480d2d6e442c21ad16ed4bd48b2d6 (diff)
downloadSkyblocker-003834e36b145791dd603858c924926be70e1281.tar.gz
Skyblocker-003834e36b145791dd603858c924926be70e1281.tar.bz2
Skyblocker-003834e36b145791dd603858c924926be70e1281.zip
Refactor puzzle solvers
Diffstat (limited to 'src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets')
-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
3 files changed, 73 insertions, 48 deletions
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()) {