aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de
diff options
context:
space:
mode:
authordaroche <94007359+GatienDoesStuff@users.noreply.github.com>2024-07-30 19:13:02 +0200
committerdaroche <94007359+GatienDoesStuff@users.noreply.github.com>2024-07-30 19:16:18 +0200
commit0ad4252991c01c092fa344eb2d1033785dd754b8 (patch)
tree848a37459d0ae8485e4b48a5d7eeaa324c75bfb5 /src/main/java/de
parent6715d16bd530f972b2ad8dcacc00106ebf3b422f (diff)
downloadSkyblocker-0ad4252991c01c092fa344eb2d1033785dd754b8.tar.gz
Skyblocker-0ad4252991c01c092fa344eb2d1033785dd754b8.tar.bz2
Skyblocker-0ad4252991c01c092fa344eb2d1033785dd754b8.zip
Revamp dungeon door detection
Diffstat (limited to 'src/main/java/de')
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonManager.java119
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonMapUtils.java32
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/Room.java39
3 files changed, 97 insertions, 93 deletions
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 11f31f34..bae6205d 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
@@ -22,6 +22,7 @@ import de.hysky.skyblocker.utils.Tickable;
import de.hysky.skyblocker.utils.Utils;
import de.hysky.skyblocker.utils.command.argumenttypes.blockpos.ClientBlockPosArgumentType;
import de.hysky.skyblocker.utils.command.argumenttypes.blockpos.ClientPosArgument;
+import de.hysky.skyblocker.utils.render.RenderHelper;
import de.hysky.skyblocker.utils.scheduler.Scheduler;
import it.unimi.dsi.fastutil.objects.Object2ByteMap;
import it.unimi.dsi.fastutil.objects.Object2ByteMaps;
@@ -59,12 +60,14 @@ import net.minecraft.util.Identifier;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.World;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.joml.Vector2i;
import org.joml.Vector2ic;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -82,6 +85,7 @@ import java.util.regex.Pattern;
import java.util.stream.Stream;
import java.util.zip.InflaterInputStream;
+import static de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonMapUtils.*;
import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument;
import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;
@@ -89,7 +93,9 @@ public class DungeonManager {
protected static final Logger LOGGER = LoggerFactory.getLogger(DungeonManager.class);
private static final String DUNGEONS_PATH = "dungeons";
private static Path CUSTOM_WAYPOINTS_DIR;
- private static final Pattern KEY_FOUND = Pattern.compile("^(?:\\[.+] )?(?<name>\\w+) has obtained (?<type>Wither|Blood) Key!$");
+ private static final Pattern KEY_FOUND = Pattern.compile("^RIGHT CLICK on (?:the BLOOD DOOR|a WITHER door) to open it. This key can only be used to open 1 door!$");
+ private static final Pattern WITHER_DOOR_OPENED = Pattern.compile("^\\w+ opened a WITHER door!$");
+ private static final String BLOOD_DOOR_OPENED = "The BLOOD DOOR has been opened!";
/**
* Maps the block identifier string to a custom numeric block id used in dungeon rooms data.
*
@@ -152,6 +158,12 @@ public class DungeonManager {
private static Room currentRoom;
@NotNull
private static DungeonBoss boss = DungeonBoss.NONE;
+ @Nullable
+ private static Box bloodRushDoorBox;
+ private static boolean bloodOpened;
+ protected static final float[] RED_COLOR_COMPONENTS = {1, 0, 0};
+ protected static final float[] GREEN_COLOR_COMPONENTS = {0, 1, 0};
+ private static boolean hasKey;
public static boolean isRoomsLoaded() {
return roomsLoaded != null && roomsLoaded.isDone();
@@ -551,6 +563,8 @@ public class DungeonManager {
LOGGER.info("[Skyblocker Dungeon Secrets] Started dungeon with map room size {}, map entrance pos {}, player pos {}, and physical entrance pos {}", mapRoomSize, mapEntrancePos, client.player.getPos(), physicalEntrancePos);
}
+ getBloodRushDoorPos();
+
Vector2ic physicalPos = DungeonMapUtils.getPhysicalRoomPos(client.player.getPos());
Vector2ic mapPos = DungeonMapUtils.getMapPosFromPhysical(physicalEntrancePos, mapEntrancePos, mapRoomSize, physicalPos);
Room room = rooms.get(physicalPos);
@@ -565,12 +579,6 @@ public class DungeonManager {
}
}
if (room != null && currentRoom != room) {
- if (currentRoom != null && room.getType() == Room.Type.FAIRY) {
- currentRoom.nextRoom = room;
- if (currentRoom.keyFound) {
- room.keyFound = true;
- }
- }
currentRoom = room;
}
currentRoom.tick(client);
@@ -604,14 +612,24 @@ public class DungeonManager {
if (shouldProcess() && currentRoom != null) {
currentRoom.render(context);
}
+
+ if (bloodRushDoorBox != null && !bloodOpened && SkyblockerConfigManager.get().dungeons.doorHighlight.enableDoorHighlight) {
+ float[] colorComponents = hasKey ? GREEN_COLOR_COMPONENTS : RED_COLOR_COMPONENTS;
+ switch (SkyblockerConfigManager.get().dungeons.doorHighlight.doorHighlightType) {
+ case HIGHLIGHT -> RenderHelper.renderFilled(context, bloodRushDoorBox, colorComponents, 0.5f, true);
+ case OUTLINED_HIGHLIGHT -> {
+ RenderHelper.renderFilled(context, bloodRushDoorBox, colorComponents, 0.5f, true);
+ RenderHelper.renderOutline(context, bloodRushDoorBox, colorComponents, 5, true);
+ }
+ case OUTLINE -> RenderHelper.renderOutline(context, bloodRushDoorBox, colorComponents, 5, true);
+ }
+ }
}
/**
* Calls {@link Room#onChatMessage(String)} on {@link #currentRoom} if the message is an overlay message and {@link #isCurrentRoomMatched()} and processes key obtained messages.
* <p>Used to detect when all secrets in a room are found and detect when a wither or blood door is unlocked.
* To process key obtained messages, this method checks if door highlight is enabled and if the message matches a key obtained message.
- * Then, it calls {@link Room#keyFound()} on {@link #currentRoom} if the client's player is the one who obtained the key.
- * Otherwise, it calls {@link Room#keyFound()} on the room the player who obtained the key is in.
*/
private static void onChatMessage(Text text, boolean overlay) {
if (!shouldProcess()) {
@@ -625,30 +643,17 @@ public class DungeonManager {
}
// Process key found messages for door highlight
- if (SkyblockerConfigManager.get().dungeons.doorHighlight.enableDoorHighlight) {
- Matcher matcher = KEY_FOUND.matcher(message);
- if (matcher.matches()) {
- String name = matcher.group("name");
- MinecraftClient client = MinecraftClient.getInstance();
- if (client.player != null && client.player.getGameProfile().getName().equals(name)) {
- if (currentRoom != null) {
- currentRoom.keyFound();
- } else {
- LOGGER.warn("[Skyblocker Dungeon Door] The current room at the current player {} does not exist", name);
- }
- } else if (client.world != null) {
- Optional<Vec3d> posOptional = client.world.getPlayers().stream().filter(player -> player.getGameProfile().getName().equals(name)).findAny().map(Entity::getPos);
- if (posOptional.isPresent()) {
- Room room = getRoomAtPhysical(posOptional.get());
- if (room != null) {
- room.keyFound();
- } else {
- LOGGER.warn("[Skyblocker Dungeon Door] Failed to find room at player {} with position {}", name, posOptional.get());
- }
- } else {
- LOGGER.warn("[Skyblocker Dungeon Door] Failed to find player {}", name);
- }
- }
+ if (SkyblockerConfigManager.get().dungeons.doorHighlight.enableDoorHighlight && !bloodOpened) {
+ if (BLOOD_DOOR_OPENED.equals(message)) {
+ bloodOpened = true;
+ }
+
+ if (KEY_FOUND.matcher(message).matches()) {
+ hasKey = true;
+ }
+
+ if (WITHER_DOOR_OPENED.matcher(message).matches()) {
+ hasKey = false;
}
}
@@ -770,5 +775,53 @@ public class DungeonManager {
rooms.clear();
currentRoom = null;
boss = DungeonBoss.NONE;
+ bloodRushDoorBox = null;
+ bloodOpened = false;
+ hasKey = false;
+ }
+
+ /**
+ * Determines where the current door of interest is
+ * @implNote Relies on the minimap to check for doors
+ */
+ private static void getBloodRushDoorPos() {
+ MinecraftClient client = MinecraftClient.getInstance();
+ if (client.player == null || client.world == null) {
+ return;
+ }
+
+ MapState map = FilledMapItem.getMapState(DungeonMap.getMapIdComponent(client.player.getInventory().main.get(8)), client.world);
+ if (map == null || mapEntrancePos == null || mapRoomSize == 0) {
+ LOGGER.error("[Skyblocker Dungeon Secrets] Failed to get map state.");
+ return;
+ }
+
+ Vector2i nWMostRoom = getMapPosForNWMostRoom(mapEntrancePos, mapRoomSize);
+
+ for (int x = nWMostRoom.x + mapRoomSize / 2; x < 127; x += mapRoomSize + 4) {
+ for (int y = nWMostRoom.y + mapRoomSize; y < 127; y += mapRoomSize + 4) {
+ byte color = getColor(map, x, y);
+
+ if (color == 119 || color == 18) {
+ Vector2ic doorPos = getPhysicalPosFromMap(mapEntrancePos, mapRoomSize, physicalEntrancePos, new Vector2i(x - mapRoomSize / 2, y - mapRoomSize));
+ bloodRushDoorBox = new Box(doorPos.x() + 14, 69, doorPos.y() + 30, doorPos.x() + 17, 73, doorPos.y() + 33);
+
+ return;
+ }
+ }
+ }
+
+ for (int x = nWMostRoom.x + mapRoomSize; x < 127; x += mapRoomSize + 4) {
+ for (int y = nWMostRoom.y + mapRoomSize / 2; y < 127; y += mapRoomSize + 4) {
+ byte color = getColor(map, x, y);
+
+ if (color == 119 || color == 18) {
+ Vector2ic doorpos = getPhysicalPosFromMap(mapEntrancePos, mapRoomSize, physicalEntrancePos, new Vector2i(x - mapRoomSize, y - mapRoomSize / 2));
+ bloodRushDoorBox = new Box(doorpos.x() + 30, 69, doorpos.y() + 14, doorpos.x() + 33, 73, doorpos.y() + 17);
+
+ return;
+ }
+ }
+ }
}
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonMapUtils.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonMapUtils.java
index 5474224a..d4ebbf6f 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonMapUtils.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonMapUtils.java
@@ -179,6 +179,17 @@ public class DungeonMapUtils {
return physicalPos.sub(Math.floorMod(physicalPos.x(), 32), Math.floorMod(physicalPos.y(), 32)).sub(8, 8);
}
+ /**
+ * Gets the map pos for the room that could be the furthest north-west on the map
+ * (doesn't mean the room has to exist, it's just the furthest possible room)
+ * @param mapEntrancePos The map pos of the entrance room
+ * @param mapRoomSize The size of a room on the map
+ * @return The map pos for the room that could be the furthest north-east on the map
+ */
+ public static Vector2i getMapPosForNWMostRoom(Vector2ic mapEntrancePos, int mapRoomSize) {
+ return new Vector2i(Math.floorMod(mapEntrancePos.x(), (mapRoomSize + 4)), Math.floorMod(mapEntrancePos.y(), (mapRoomSize + 4)));
+ }
+
public static Vector2ic[] getPhysicalPosFromMap(Vector2ic mapEntrancePos, int mapRoomSize, Vector2ic physicalEntrancePos, Vector2ic... mapPositions) {
for (int i = 0; i < mapPositions.length; i++) {
mapPositions[i] = getPhysicalPosFromMap(mapEntrancePos, mapRoomSize, physicalEntrancePos, mapPositions[i]);
@@ -275,25 +286,4 @@ public class DungeonMapUtils {
DungeonManager.LOGGER.debug("[Skyblocker] Found dungeon room segments: {}", Arrays.toString(segments.toArray()));
return segments.toArray(Vector2ic[]::new);
}
-
- public static BlockPos getWitherBloodDoorPos(World world, Collection<Vector2ic> physicalPositions) {
- BlockPos.Mutable doorPos = new BlockPos.Mutable();
- for (Vector2ic pos : physicalPositions) {
- if (hasWitherOrBloodDoor(world, pos, doorPos)) {
- return doorPos;
- }
- }
- return null;
- }
-
- private static boolean hasWitherOrBloodDoor(World world, Vector2ic pos, BlockPos.Mutable doorPos) {
- return isWitherOrBloodDoor(world, doorPos.set(pos.x() + 1, 72, pos.y() + 17)) ||
- isWitherOrBloodDoor(world, doorPos.set(pos.x() + 17, 72, pos.y() + 1)) ||
- isWitherOrBloodDoor(world, doorPos.set(pos.x() + 17, 72, pos.y() + 33)) ||
- isWitherOrBloodDoor(world, doorPos.set(pos.x() + 33, 72, pos.y() + 17));
- }
-
- private static boolean isWitherOrBloodDoor(World world, BlockPos.Mutable pos) {
- return world.getStatesInBox(Box.enclosing(pos, pos.move(-3, -3, -3))).allMatch(state -> state.isOf(Blocks.COAL_BLOCK) || state.isOf(Blocks.RED_TERRACOTTA));
- }
}
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 c0e54904..f8583e2c 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
@@ -53,7 +53,6 @@ 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 String LOCKED_CHEST = "That chest is locked!";
- private static final Vec3d DOOR_SIZE = new Vec3d(3, 4, 3);
protected static final float[] RED_COLOR_COMPONENTS = {1, 0, 0};
protected static final float[] GREEN_COLOR_COMPONENTS = {0, 1, 0};
@NotNull
@@ -100,16 +99,6 @@ public class Room implements Tickable, Renderable {
protected List<Renderable> renderables = new ArrayList<>();
private BlockPos lastChestSecret;
private long lastChestSecretTime;
- /**
- * Stores the next room in the dungeon. Currently only used if the next room is the fairy room.
- */
- @Nullable
- protected Room nextRoom;
- @Nullable
- private BlockPos doorPos;
- @Nullable
- private Box doorBox;
- protected boolean keyFound;
public Room(@NotNull Type type, @NotNull Vector2ic... physicalPositions) {
this.type = type;
@@ -309,14 +298,6 @@ public class Room implements Tickable, Renderable {
tickable.tick(client);
}
- // Wither and blood door
- if (SkyblockerConfigManager.get().dungeons.doorHighlight.enableDoorHighlight && doorPos == null) {
- doorPos = DungeonMapUtils.getWitherBloodDoorPos(client.world, segments);
- if (doorPos != null) {
- doorBox = new Box(doorPos.getX(), doorPos.getY(), doorPos.getZ(), doorPos.getX() + DOOR_SIZE.getX(), doorPos.getY() + DOOR_SIZE.getY(), doorPos.getZ() + DOOR_SIZE.getZ());
- }
- }
-
// Room scanning and matching
// Logical AND has higher precedence than logical OR
if (!type.needsScanning() || matchState != MatchState.MATCHING && matchState != MatchState.DOUBLE_CHECKING || !DungeonManager.isRoomsLoaded() || findRoom != null && !findRoom.isDone()) {
@@ -534,19 +515,6 @@ public class Room implements Tickable, Renderable {
}
}
}
-
- if (!SkyblockerConfigManager.get().dungeons.doorHighlight.enableDoorHighlight || doorPos == null) {
- return;
- }
- float[] colorComponents = keyFound ? GREEN_COLOR_COMPONENTS : RED_COLOR_COMPONENTS;
- switch (SkyblockerConfigManager.get().dungeons.doorHighlight.doorHighlightType) {
- case HIGHLIGHT -> RenderHelper.renderFilled(context, doorPos, DOOR_SIZE, colorComponents, 0.5f, true);
- case OUTLINED_HIGHLIGHT -> {
- RenderHelper.renderFilled(context, doorPos, DOOR_SIZE, colorComponents, 0.5f, true);
- RenderHelper.renderOutline(context, doorBox, colorComponents, 5, true);
- }
- case OUTLINE -> RenderHelper.renderOutline(context, doorBox, colorComponents, 5, true);
- }
}
/**
@@ -655,13 +623,6 @@ public class Room implements Tickable, Renderable {
}
}
- protected void keyFound() {
- if (nextRoom != null && nextRoom.type == Type.FAIRY) {
- nextRoom.keyFound = true;
- }
- keyFound = true;
- }
-
public enum Type {
ENTRANCE(MapColor.DARK_GREEN.getRenderColorByte(MapColor.Brightness.HIGH)),
ROOM(MapColor.ORANGE.getRenderColorByte(MapColor.Brightness.LOWEST)),