aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de
diff options
context:
space:
mode:
authorAaron <51387595+AzureAaron@users.noreply.github.com>2024-08-09 02:35:41 -0400
committerGitHub <noreply@github.com>2024-08-09 02:35:41 -0400
commit367197df7cdcde1ea25850e34802cd89e07db9d8 (patch)
treeeb90f703fbd0e0b6764ced0d63fba3e4850cb615 /src/main/java/de
parent38626e02f060f36520271099c0e2385fbeb0ebda (diff)
parentbd787c213029185ad07b5b9a281ab289b0b102cb (diff)
downloadSkyblocker-367197df7cdcde1ea25850e34802cd89e07db9d8.tar.gz
Skyblocker-367197df7cdcde1ea25850e34802cd89e07db9d8.tar.bz2
Skyblocker-367197df7cdcde1ea25850e34802cd89e07db9d8.zip
Merge pull request #879 from GatienDoesStuff/better-door-detection
[WORKING DRAFT] Better dungeon door detection/overlay
Diffstat (limited to 'src/main/java/de')
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonManager.java117
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonMapUtils.java36
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/Room.java46
3 files changed, 97 insertions, 102 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..fbe99909 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;
@@ -41,7 +42,6 @@ import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.command.CommandSource;
import net.minecraft.command.argument.TextArgumentType;
import net.minecraft.component.DataComponentTypes;
-import net.minecraft.entity.Entity;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.mob.AmbientEntity;
@@ -59,12 +59,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;
@@ -77,11 +79,11 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.concurrent.CompletableFuture;
-import java.util.regex.Matcher;
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 +91,11 @@ 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!";
+ protected static final float[] RED_COLOR_COMPONENTS = {1, 0, 0};
+ protected static final float[] GREEN_COLOR_COMPONENTS = {0, 1, 0};
/**
* Maps the block identifier string to a custom numeric block id used in dungeon rooms data.
*
@@ -152,6 +158,10 @@ public class DungeonManager {
private static Room currentRoom;
@NotNull
private static DungeonBoss boss = DungeonBoss.NONE;
+ @Nullable
+ private static Box bloodRushDoorBox;
+ private static boolean bloodOpened;
+ private static boolean hasKey;
public static boolean isRoomsLoaded() {
return roomsLoaded != null && roomsLoaded.isDone();
@@ -551,6 +561,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(map);
+
Vector2ic physicalPos = DungeonMapUtils.getPhysicalRoomPos(client.player.getPos());
Vector2ic mapPos = DungeonMapUtils.getMapPosFromPhysical(physicalEntrancePos, mapEntrancePos, mapRoomSize, physicalPos);
Room room = rooms.get(physicalPos);
@@ -565,12 +577,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 +610,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 +641,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 +773,49 @@ 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(@NotNull MapState map) {
+ if (mapEntrancePos == null || mapRoomSize == 0) {
+ LOGGER.error("[Skyblocker Dungeon Secrets] Dungeon map info missing with map entrance pos {} and map room size {}", mapEntrancePos, mapRoomSize);
+ return;
+ }
+
+ Vector2i nWMostRoom = getMapPosForNWMostRoom(mapEntrancePos, mapRoomSize);
+
+ for (int x = nWMostRoom.x + mapRoomSize / 2; x < 128; x += mapRoomSize + 4) {
+ for (int y = nWMostRoom.y + mapRoomSize; y < 128; y += mapRoomSize + 4) {
+ byte color = getColor(map, x, y);
+
+ // 119 is the black found on wither doors on the map, 18 is the blood door red
+ 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 < 128; x += mapRoomSize + 4) {
+ for (int y = nWMostRoom.y + mapRoomSize / 2; y < 128; 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..ca63d971 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
@@ -3,16 +3,13 @@ package de.hysky.skyblocker.skyblock.dungeon.secrets;
import com.google.gson.JsonObject;
import it.unimi.dsi.fastutil.ints.IntSortedSet;
import it.unimi.dsi.fastutil.objects.ObjectIntPair;
-import net.minecraft.block.Blocks;
import net.minecraft.block.MapColor;
import net.minecraft.item.map.MapDecoration;
import net.minecraft.item.map.MapDecorationTypes;
import net.minecraft.item.map.MapState;
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.NotNull;
import org.jetbrains.annotations.Nullable;
import org.joml.RoundingMode;
@@ -148,6 +145,18 @@ public class DungeonMapUtils {
}
/**
+ * 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)));
+ }
+
+ /**
* @see #getPhysicalRoomPos(double, double)
*/
@NotNull
@@ -275,25 +284,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..1f4f9ed6 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
@@ -12,7 +12,6 @@ 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;
@@ -34,8 +33,6 @@ import net.minecraft.registry.Registries;
import net.minecraft.text.Text;
import net.minecraft.util.StringIdentifiable;
import net.minecraft.util.math.BlockPos;
-import net.minecraft.util.math.Box;
-import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import org.apache.commons.lang3.tuple.MutableTriple;
import org.apache.commons.lang3.tuple.Triple;
@@ -53,7 +50,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 +96,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 +295,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()) {
@@ -416,7 +394,8 @@ public class Room implements Tickable, Renderable {
Scheduler.INSTANCE.schedule(() -> matchState = MatchState.MATCHING, 50);
reset();
return true;
- } else if (matchingRoomsSize == 1) {
+ }
+ else if (matchingRoomsSize == 1) {
if (matchState == MatchState.MATCHING) {
// If one room matches, load the secrets for that room and set state to double-checking.
Triple<Direction, Vector2ic, List<String>> directionRoom = possibleRooms.stream().filter(directionRooms -> directionRooms.getRight().size() == 1).findAny().orElseThrow();
@@ -534,19 +513,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);
- }
}
/**
@@ -635,6 +601,7 @@ public class Room implements Tickable, Renderable {
/**
* Marks all secret waypoints with the same index as the given {@link SecretWaypoint} as found or missing and logs the given message.
+ *
* @param secretWaypoint the secret waypoint to read the index from.
* @param found whether to mark the secret as found or missing
* @param msg the message to log
@@ -655,13 +622,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)),