diff options
author | Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> | 2023-12-20 23:00:48 +0800 |
---|---|---|
committer | Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> | 2023-12-21 09:57:36 +0800 |
commit | 66b6be50ed9480d2d6e442c21ad16ed4bd48b2d6 (patch) | |
tree | 61d5609bd7ee393a06327d95010dcb44d0becbb4 | |
parent | 88eb4ce59bead62d86b8cece7a8be8e30a740e01 (diff) | |
download | Skyblocker-66b6be50ed9480d2d6e442c21ad16ed4bd48b2d6.tar.gz Skyblocker-66b6be50ed9480d2d6e442c21ad16ed4bd48b2d6.tar.bz2 Skyblocker-66b6be50ed9480d2d6e442c21ad16ed4bd48b2d6.zip |
Render match against command
7 files changed, 117 insertions, 38 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 93e4be6e..b686607b 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,10 +1,48 @@ package de.hysky.skyblocker.skyblock.dungeon.secrets; +import de.hysky.skyblocker.utils.waypoint.Waypoint; +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; + public class DebugRoom extends Room { + private final List<Waypoint> checkedBlocks = Collections.synchronizedList(new ArrayList<>()); + public DebugRoom(@NotNull Type type, @NotNull Vector2ic... physicalPositions) { super(type, physicalPositions); } + + @Override + protected boolean checkBlock(ClientWorld world, BlockPos pos) { + byte id = DungeonManager.NUMERIC_ID.getByte(Registries.BLOCK.getId(world.getBlockState(pos).getBlock()).toString()); + if (id == 0) { + return false; + } + for (MutableTriple<Direction, Vector2ic, List<String>> directionRooms : possibleRooms) { + int block = posIdToInt(DungeonMapUtils.actualToRelative(directionRooms.getLeft(), directionRooms.getMiddle(), pos), id); + for (String room : directionRooms.getRight()) { + checkedBlocks.add(new Waypoint(pos, SecretWaypoint.TYPE_SUPPLIER, Arrays.binarySearch(roomsData.get(room), block) >= 0 ? Room.GREEN_COLOR_COMPONENTS : Room.RED_COLOR_COMPONENTS)); + } + } + return false; + } + + @Override + protected void render(WorldRenderContext context) { + super.render(context); + synchronized (checkedBlocks) { + for (Waypoint checkedBlock : checkedBlocks) { + checkedBlock.render(context); + } + } + } } 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 4364abff..52915b98 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 @@ -14,6 +14,7 @@ import com.mojang.serialization.JsonOps; import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.config.SkyblockerConfig; import de.hysky.skyblocker.config.SkyblockerConfigManager; +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; @@ -158,11 +159,13 @@ public class DungeonManager { @SuppressWarnings("unused") public static JsonObject getRoomMetadata(String room) { - return roomsJson.get(room).getAsJsonObject(); + JsonElement value = roomsJson.get(room); + return value != null ? value.getAsJsonObject() : null; } public static JsonArray getRoomWaypoints(String room) { - return waypointsJson.get(room).getAsJsonArray(); + JsonElement value = waypointsJson.get(room); + return value != null ? value.getAsJsonArray() : null; } /** @@ -225,8 +228,21 @@ public class DungeonManager { .then(literal("addWaypointRelatively").then(addCustomWaypointCommand(true))) .then(literal("removeWaypoint").then(removeCustomWaypointCommand(false))) .then(literal("removeWaypointRelatively").then(removeCustomWaypointCommand(true))) - .then(literal("matchAgainst").then(matchAgainstCommand())) )))); + 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 -> { + if (currentRoom != null) { + currentRoom.subRooms.clear(); + context.getSource().sendFeedback(Constants.PREFIX.get().append("§rCleared sub rooms 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())); } @@ -341,7 +357,7 @@ public class DungeonManager { Room room = getRoomAtPhysical(pos); if (isRoomMatched(room)) { BlockPos relativePos = currentRoom.actualToRelative(pos); - source.sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.dungeons.secrets.posMessage", currentRoom.getName(), relativePos.getX(), relativePos.getY(), relativePos.getZ()))); + source.sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.dungeons.secrets.posMessage", currentRoom.getName(), currentRoom.getDirection().asString(), relativePos.getX(), relativePos.getY(), relativePos.getZ()))); } else { source.sendError(Constants.PREFIX.get().append(Text.translatable("skyblocker.dungeons.secrets.notMatched"))); } @@ -411,22 +427,22 @@ 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(Text.literal("§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(Text.literal("§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(Text.literal("§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(Text.literal("§cFailed to get dungeon map state"))); + context.getSource().sendError(Constants.PREFIX.get().append("§cFailed to get dungeon map state")); return Command.SINGLE_SUCCESS; } @@ -440,18 +456,23 @@ public class DungeonManager { } 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.getMapPosFromPhysical(physicalEntrancePos, mapEntrancePos, mapRoomSize, DungeonMapUtils.getPhysicalRoomPos(client.player.getPos())), mapRoomSize, Room.Type.ROOM.color))); + room = new DebugRoom(Room.Type.ROOM, DungeonMapUtils.getPhysicalPosFromMap(mapEntrancePos, mapRoomSize, physicalEntrancePos, DungeonMapUtils.getRoomSegments(map, DungeonMapUtils.getMapRoomPos(map, mapEntrancePos, mapRoomSize), mapRoomSize, Room.Type.ROOM.color))); } if (room == null) { - context.getSource().sendError(Constants.PREFIX.get().append(Text.literal("§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))); - Scheduler.INSTANCE.scheduleCyclic(room::update, 10); + if (currentRoom != null) { + currentRoom.subRooms.add(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")); + } return Command.SINGLE_SUCCESS; })); 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 516c3bad..b12bba62 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 @@ -130,7 +130,7 @@ public class DungeonMapUtils { return null; } Vector2ic offset = new Vector2i(mapEntrancePos.x() % mapRoomSizeWithGap, mapEntrancePos.y() % mapRoomSizeWithGap); - return mapPos.add(2, 2).sub(offset).sub(mapPos.x() % mapRoomSizeWithGap, mapPos.y() % mapRoomSizeWithGap).add(offset); + return mapPos.add(2, 2).sub(offset).sub(Math.floorMod(mapPos.x(), mapRoomSizeWithGap), Math.floorMod(mapPos.y(), mapRoomSizeWithGap)).add(offset); } /** 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 23302182..40488717 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 @@ -2,6 +2,7 @@ package de.hysky.skyblocker.skyblock.dungeon.secrets; import com.google.common.collect.HashBasedTable; import com.google.common.collect.Table; +import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.mojang.brigadier.arguments.IntegerArgumentType; @@ -52,8 +53,8 @@ public class Room { 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); - private static final float[] RED_COLOR_COMPONENTS = {1, 0, 0}; - private static final float[] GREEN_COLOR_COMPONENTS = {0, 1, 0}; + protected static final float[] RED_COLOR_COMPONENTS = {1, 0, 0}; + protected static final float[] GREEN_COLOR_COMPONENTS = {0, 1, 0}; @NotNull private final Type type; @NotNull @@ -67,11 +68,11 @@ public class Room { /** * The room data containing all rooms for a specific dungeon and {@link #shape}. */ - Map<String, int[]> roomsData; + protected Map<String, int[]> roomsData; /** * Contains all possible dungeon rooms for this room. The list is gradually shrunk by checking blocks until only one room is left. */ - List<MutableTriple<Direction, Vector2ic, List<String>>> possibleRooms; + protected List<MutableTriple<Direction, Vector2ic, List<String>>> possibleRooms; /** * Contains all blocks that have been checked to prevent checking the same block multiple times. */ @@ -88,12 +89,13 @@ public class Room { * <li>{@link MatchState#MATCHED} means that the room has a unique match ans has been double checked.</li> * <li>{@link MatchState#FAILED} means that the room has been checked and there is no match.</li> */ - private MatchState matchState = MatchState.MATCHING; + protected MatchState matchState = MatchState.MATCHING; private Table<Integer, BlockPos, SecretWaypoint> secretWaypoints; private String name; private Direction direction; private Vector2ic physicalCornerPos; + protected List<Room> subRooms = new ArrayList<>(); @Nullable private BlockPos doorPos; @Nullable @@ -126,6 +128,13 @@ public class Room { return name; } + /** + * Not null if {@link #isMatched()}. + */ + public Direction getDirection() { + return direction; + } + @Override public String toString() { return "Room{type=%s, segments=%s, shape=%s, matchState=%s, name=%s, direction=%s, physicalCornerPos=%s}".formatted(type, Arrays.toString(segments.toArray()), shape, matchState, name, direction, physicalCornerPos); @@ -283,6 +292,10 @@ public class Room { return; } + for (Room subRoom : subRooms) { + subRoom.update(); + } + // Wither and blood door if (SkyblockerConfigManager.get().locations.dungeons.doorHighlight.enableDoorHighlight && doorPos == null) { doorPos = DungeonMapUtils.getWitherBloodDoorPos(world, segments); @@ -366,7 +379,7 @@ public class Room { * @param pos the position of the block to check * @return whether room matching should end. Either a match is found or there are no valid rooms left */ - private boolean checkBlock(ClientWorld world, BlockPos pos) { + protected boolean checkBlock(ClientWorld world, BlockPos pos) { byte id = DungeonManager.NUMERIC_ID.getByte(Registries.BLOCK.getId(world.getBlockState(pos).getBlock()).toString()); if (id == 0) { return false; @@ -422,7 +435,7 @@ public class Room { * @param id the custom numeric block id * @return the encoded integer */ - private int posIdToInt(BlockPos pos, byte id) { + protected int posIdToInt(BlockPos pos, byte id) { return pos.getX() << 24 | pos.getY() << 16 | pos.getZ() << 8 | id; } @@ -435,13 +448,16 @@ public class Room { @SuppressWarnings("JavadocReference") private void roomMatched() { secretWaypoints = HashBasedTable.create(); - for (JsonElement waypointElement : DungeonManager.getRoomWaypoints(name)) { - JsonObject waypoint = waypointElement.getAsJsonObject(); - String secretName = waypoint.get("secretName").getAsString(); - Matcher secretIndexMatcher = SECRET_INDEX.matcher(secretName); - int secretIndex = secretIndexMatcher.find() ? Integer.parseInt(secretIndexMatcher.group(1)) : 0; - BlockPos pos = DungeonMapUtils.relativeToActual(direction, physicalCornerPos, waypoint); - secretWaypoints.put(secretIndex, pos, new SecretWaypoint(secretIndex, waypoint, secretName, pos)); + JsonArray secretWaypointsJson = DungeonManager.getRoomWaypoints(name); + if (secretWaypointsJson != null) { + for (JsonElement waypointElement : secretWaypointsJson) { + JsonObject waypoint = waypointElement.getAsJsonObject(); + String secretName = waypoint.get("secretName").getAsString(); + Matcher secretIndexMatcher = SECRET_INDEX.matcher(secretName); + int secretIndex = secretIndexMatcher.find() ? Integer.parseInt(secretIndexMatcher.group(1)) : 0; + BlockPos pos = DungeonMapUtils.relativeToActual(direction, physicalCornerPos, waypoint); + secretWaypoints.put(secretIndex, pos, new SecretWaypoint(secretIndex, waypoint, secretName, pos)); + } } DungeonManager.getCustomWaypoints(name).values().forEach(this::addCustomWaypoint); matchState = MatchState.DOUBLE_CHECKING; @@ -450,7 +466,7 @@ public class Room { /** * Resets fields for another round of matching after room matching fails. */ - private void reset() { + protected void reset() { IntSortedSet segmentsX = IntSortedSets.unmodifiable(new IntRBTreeSet(segments.stream().mapToInt(Vector2ic::x).toArray())); IntSortedSet segmentsY = IntSortedSets.unmodifiable(new IntRBTreeSet(segments.stream().mapToInt(Vector2ic::y).toArray())); possibleRooms = getPossibleRooms(segmentsX, segmentsY); @@ -491,6 +507,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); + } + if (SkyblockerConfigManager.get().locations.dungeons.secretWaypoints.enableSecretWaypoints && isMatched()) { for (SecretWaypoint secretWaypoint : secretWaypoints.values()) { if (secretWaypoint.shouldRender()) { @@ -632,7 +652,7 @@ public class Room { } } - enum Shape { + protected enum Shape { ONE_BY_ONE("1x1"), ONE_BY_TWO("1x2"), ONE_BY_THREE("1x3"), @@ -653,7 +673,7 @@ public class Room { } } - enum Direction implements StringIdentifiable { + public enum Direction implements StringIdentifiable { NW("northwest"), NE("northeast"), SW("southwest"), SE("southeast"); private static final Codec<Direction> CODEC = StringIdentifiable.createCodec(Direction::values); private final String name; @@ -682,7 +702,7 @@ public class Room { } } - private enum MatchState { + protected enum MatchState { MATCHING, DOUBLE_CHECKING, MATCHED, FAILED } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/SecretWaypoint.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/SecretWaypoint.java index b7c19210..98ffa157 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/SecretWaypoint.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/SecretWaypoint.java @@ -29,7 +29,7 @@ import java.util.function.Supplier; import java.util.function.ToDoubleFunction; public class SecretWaypoint extends Waypoint { - protected static final Logger LOGGER = LoggerFactory.getLogger(SecretWaypoint.class); + private static final Logger LOGGER = LoggerFactory.getLogger(SecretWaypoint.class); public static final Codec<SecretWaypoint> CODEC = RecordCodecBuilder.create(instance -> instance.group( Codec.INT.fieldOf("secretIndex").forGetter(secretWaypoint -> secretWaypoint.secretIndex), Category.CODEC.fieldOf("category").forGetter(secretWaypoint -> secretWaypoint.category), @@ -39,7 +39,7 @@ public class SecretWaypoint extends Waypoint { public static final Codec<List<SecretWaypoint>> LIST_CODEC = CODEC.listOf(); static final List<String> SECRET_ITEMS = List.of("Decoy", "Defuse Kit", "Dungeon Chest Key", "Healing VIII", "Inflatable Jerry", "Spirit Leap", "Training Weights", "Trap", "Treasure Talisman"); private static final Supplier<SkyblockerConfig.SecretWaypoints> CONFIG = () -> SkyblockerConfigManager.get().locations.dungeons.secretWaypoints; - private static final Supplier<Type> TYPE_SUPPLIER = () -> CONFIG.get().waypointType; + static final Supplier<Type> TYPE_SUPPLIER = () -> CONFIG.get().waypointType; final int secretIndex; final Category category; final Text name; diff --git a/src/main/java/de/hysky/skyblocker/utils/waypoint/Waypoint.java b/src/main/java/de/hysky/skyblocker/utils/waypoint/Waypoint.java index eb30cf8d..3a1d364f 100644 --- a/src/main/java/de/hysky/skyblocker/utils/waypoint/Waypoint.java +++ b/src/main/java/de/hysky/skyblocker/utils/waypoint/Waypoint.java @@ -19,15 +19,15 @@ public class Waypoint { final boolean throughWalls; private boolean shouldRender; - protected Waypoint(BlockPos pos, Supplier<Type> typeSupplier, float[] colorComponents) { + public Waypoint(BlockPos pos, Supplier<Type> typeSupplier, float[] colorComponents) { this(pos, typeSupplier, colorComponents, DEFAULT_HIGHLIGHT_ALPHA, DEFAULT_LINE_WIDTH); } - protected Waypoint(BlockPos pos, Type type, float[] colorComponents, float alpha) { + public Waypoint(BlockPos pos, Type type, float[] colorComponents, float alpha) { this(pos, () -> type, colorComponents, alpha, DEFAULT_LINE_WIDTH); } - protected Waypoint(BlockPos pos, Supplier<Type> typeSupplier, float[] colorComponents, float alpha, float lineWidth) { + public Waypoint(BlockPos pos, Supplier<Type> typeSupplier, float[] colorComponents, float alpha, float lineWidth) { this(pos, typeSupplier, colorComponents, alpha, lineWidth, true); } @@ -35,11 +35,11 @@ public class Waypoint { this(pos, typeSupplier, colorComponents, DEFAULT_HIGHLIGHT_ALPHA, DEFAULT_LINE_WIDTH, throughWalls); } - protected Waypoint(BlockPos pos, Supplier<Type> typeSupplier, float[] colorComponents, float alpha, float lineWidth, boolean throughWalls) { + public Waypoint(BlockPos pos, Supplier<Type> typeSupplier, float[] colorComponents, float alpha, float lineWidth, boolean throughWalls) { this(pos, typeSupplier, colorComponents, alpha, lineWidth, throughWalls, true); } - protected Waypoint(BlockPos pos, Supplier<Type> typeSupplier, float[] colorComponents, float alpha, float lineWidth, boolean throughWalls, boolean shouldRender) { + public Waypoint(BlockPos pos, Supplier<Type> typeSupplier, float[] colorComponents, float alpha, float lineWidth, boolean throughWalls, boolean shouldRender) { this.pos = pos; this.box = new Box(pos); this.typeSupplier = typeSupplier; diff --git a/src/main/resources/assets/skyblocker/lang/en_us.json b/src/main/resources/assets/skyblocker/lang/en_us.json index 8692c4f8..31f4f6ca 100644 --- a/src/main/resources/assets/skyblocker/lang/en_us.json +++ b/src/main/resources/assets/skyblocker/lang/en_us.json @@ -303,7 +303,7 @@ "skyblocker.dungeons.secrets.markSecretMissing": "§rMarked secret #%d as missing.", "skyblocker.dungeons.secrets.markSecretFoundUnable": "§cUnable to mark secret #%d as found.", "skyblocker.dungeons.secrets.markSecretMissingUnable": "§cUnable to mark secret #%d as missing.", - "skyblocker.dungeons.secrets.posMessage": "§rRoom: %s, X: %d, Y: %d, Z: %d", + "skyblocker.dungeons.secrets.posMessage": "§rRoom: %s, Direction: %s, X: %d, Y: %d, Z: %d", "skyblocker.dungeons.secrets.noTarget": "§cNo target block found! (Are you pointing at a block in range?)", "skyblocker.dungeons.secrets.notMatched": "§cThe current room is not matched! (Are you in a dungeon room?)", "skyblocker.dungeons.secrets.customWaypointAdded": "§rAdded a custom waypoint at X: %d, Y: %d, Z: %d for room %s secret #%d of category %s with name '%s'.", |