diff options
| author | daroche <94007359+GatienDoesStuff@users.noreply.github.com> | 2024-07-30 19:13:02 +0200 |
|---|---|---|
| committer | daroche <94007359+GatienDoesStuff@users.noreply.github.com> | 2024-07-30 19:16:18 +0200 |
| commit | 0ad4252991c01c092fa344eb2d1033785dd754b8 (patch) | |
| tree | 848a37459d0ae8485e4b48a5d7eeaa324c75bfb5 /src/main/java/de | |
| parent | 6715d16bd530f972b2ad8dcacc00106ebf3b422f (diff) | |
| download | Skyblocker-0ad4252991c01c092fa344eb2d1033785dd754b8.tar.gz Skyblocker-0ad4252991c01c092fa344eb2d1033785dd754b8.tar.bz2 Skyblocker-0ad4252991c01c092fa344eb2d1033785dd754b8.zip | |
Revamp dungeon door detection
Diffstat (limited to 'src/main/java/de')
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)), |
