diff options
Diffstat (limited to 'src/main/java/me/xmrvizzy/skyblocker')
-rw-r--r-- | src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/secrets/DungeonMapUtils.java | 52 | ||||
-rw-r--r-- | src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/secrets/DungeonSecrets.java | 109 |
2 files changed, 124 insertions, 37 deletions
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/secrets/DungeonMapUtils.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/secrets/DungeonMapUtils.java new file mode 100644 index 00000000..9d1c7ccb --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/secrets/DungeonMapUtils.java @@ -0,0 +1,52 @@ +package me.xmrvizzy.skyblocker.skyblock.dungeon.secrets; + +import net.minecraft.block.MapColor; +import net.minecraft.item.map.MapIcon; +import net.minecraft.item.map.MapState; +import org.joml.Vector2i; + +public class DungeonMapUtils { + public static final byte ENTRANCE_COLOR = MapColor.DARK_GREEN.getRenderColorByte(MapColor.Brightness.HIGH); + public static final byte ROOM_COLOR = MapColor.ORANGE.getRenderColorByte(MapColor.Brightness.LOWEST); + public static final byte PUZZLE_COLOR = MapColor.MAGENTA.getRenderColorByte(MapColor.Brightness.HIGH); + public static final byte MINIBOSS_COLOR = MapColor.YELLOW.getRenderColorByte(MapColor.Brightness.HIGH); + public static final byte FAIRY_COLOR = MapColor.PINK.getRenderColorByte(MapColor.Brightness.HIGH); + public static final byte BLOOD_COLOR = MapColor.BRIGHT_RED.getRenderColorByte(MapColor.Brightness.HIGH); + public static final byte UNKNOWN_COLOR = MapColor.GRAY.getRenderColorByte(MapColor.Brightness.NORMAL); + public static final byte BLACK_COLOR = MapColor.BLACK.getRenderColorByte(MapColor.Brightness.LOWEST); + public static final byte WHITE_COLOR = MapColor.WHITE.getRenderColorByte(MapColor.Brightness.HIGH); + + public static Vector2i getEntrancePos(MapState map) { + for (MapIcon icon : map.getIcons()) { + if (icon.getType() == MapIcon.Type.FRAME) { + int x = (icon.getX() >> 1) + 64; + int z = (icon.getZ() >> 1) + 64; + if (getColor(map, x, z) == ENTRANCE_COLOR) { + while (getColor(map, x - 1, z) == ENTRANCE_COLOR) { + x--; + } + while (getColor(map, x, z - 1) == ENTRANCE_COLOR) { + z--; + } + return new Vector2i(x, z); + } + } + } + return null; + } + + public static int getRoomWidth(MapState map, Vector2i entrancePos) { + int i = 0; + while (getColor(map, entrancePos.x + i, entrancePos.y) == ENTRANCE_COLOR) { + i++; + } + return i; + } + + private static byte getColor(MapState map, int x, int z) { + if (x < 0 || z < 0 || x >= 128 || z >= 128) { + return -1; + } + return map.colors[x + (z << 7)]; + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/secrets/DungeonSecrets.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/secrets/DungeonSecrets.java index 8be626d2..d293bb88 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/secrets/DungeonSecrets.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/secrets/DungeonSecrets.java @@ -3,9 +3,15 @@ package me.xmrvizzy.skyblocker.skyblock.dungeon.secrets; import com.google.gson.JsonObject; import me.xmrvizzy.skyblocker.SkyblockerMod; import me.xmrvizzy.skyblocker.config.SkyblockerConfig; +import me.xmrvizzy.skyblocker.utils.Utils; import net.minecraft.client.MinecraftClient; +import net.minecraft.item.FilledMapItem; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.item.map.MapState; import net.minecraft.util.Identifier; import org.jetbrains.annotations.Nullable; +import org.joml.Vector2i; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,13 +27,15 @@ import java.util.concurrent.CompletableFuture; import java.util.zip.InflaterInputStream; public class DungeonSecrets { - private static final Logger LOGGER = LoggerFactory.getLogger(DungeonSecrets.class); + protected static final Logger LOGGER = LoggerFactory.getLogger(DungeonSecrets.class); private static final String DUNGEONS_DATA_DIR = "/assets/skyblocker/dungeons"; private static final HashMap<String, HashMap<String, HashMap<String, long[]>>> ROOMS = new HashMap<>(); private static JsonObject roomsJson; private static JsonObject waypointsJson; @Nullable private static CompletableFuture<Void> roomsLoaded; + private static Vector2i mapEntrancePos; + private static int mapRoomWidth; public static boolean isRoomsLoaded() { return roomsLoaded != null && roomsLoaded.isDone(); @@ -41,44 +49,47 @@ public class DungeonSecrets { if (SkyblockerConfig.get().locations.dungeons.noLoadSecretWaypoints) { return; } - CompletableFuture.runAsync(() -> { - try { - List<CompletableFuture<Void>> dungeonFutures = new ArrayList<>(); - //noinspection DataFlowIssue - File dungeons = new File(SkyblockerMod.class.getResource(DUNGEONS_DATA_DIR).getFile()); - int resourcePathIndex = dungeons.getPath().indexOf(DUNGEONS_DATA_DIR); - //noinspection DataFlowIssue - for (File dungeon : dungeons.listFiles()) { - if (!dungeon.isDirectory()) { - continue; - } - File[] roomShapes = dungeon.listFiles(); - if (roomShapes == null) { - LOGGER.error("Failed to load dungeon secrets for dungeon {}", dungeon.getName()); - continue; - } - ROOMS.put(dungeon.getName(), new HashMap<>()); - List<CompletableFuture<Void>> roomShapeFutures = new ArrayList<>(); - for (File roomShape : roomShapes) { - roomShapeFutures.add(CompletableFuture.supplyAsync(() -> readRooms(roomShape, resourcePathIndex)).thenAccept(rooms -> ROOMS.get(dungeon.getName()).put(roomShape.getName(), rooms))); - } - dungeonFutures.add(CompletableFuture.allOf(roomShapeFutures.toArray(CompletableFuture[]::new)).thenRun(() -> LOGGER.debug("Loaded dungeon secrets for dungeon {} with {} room shapes and {} rooms total", dungeon.getName(), ROOMS.get(dungeon.getName()).size(), ROOMS.get(dungeon.getName()).values().stream().mapToInt(HashMap::size).sum()))); + CompletableFuture.runAsync(DungeonSecrets::load); + SkyblockerMod.getInstance().scheduler.scheduleCyclic(DungeonSecrets::update, 10); + } + + private static void load() { + try { + List<CompletableFuture<Void>> dungeonFutures = new ArrayList<>(); + //noinspection DataFlowIssue + File dungeons = new File(SkyblockerMod.class.getResource(DUNGEONS_DATA_DIR).getFile()); + int resourcePathIndex = dungeons.getPath().indexOf(DUNGEONS_DATA_DIR); + //noinspection DataFlowIssue + for (File dungeon : dungeons.listFiles()) { + if (!dungeon.isDirectory()) { + continue; + } + File[] roomShapes = dungeon.listFiles(); + if (roomShapes == null) { + LOGGER.error("Failed to load dungeon secrets for dungeon {}", dungeon.getName()); + continue; + } + ROOMS.put(dungeon.getName(), new HashMap<>()); + List<CompletableFuture<Void>> roomShapeFutures = new ArrayList<>(); + for (File roomShape : roomShapes) { + roomShapeFutures.add(CompletableFuture.supplyAsync(() -> readRooms(roomShape, resourcePathIndex)).thenAccept(rooms -> ROOMS.get(dungeon.getName()).put(roomShape.getName(), rooms))); } - // Execute with MinecraftClient as executor since we need to wait for MinecraftClient#resourceManager to be set - dungeonFutures.add(CompletableFuture.runAsync(() -> { - try (BufferedReader roomsReader = MinecraftClient.getInstance().getResourceManager().openAsReader(new Identifier(SkyblockerMod.NAMESPACE, "dungeons/dungeonrooms.json")); BufferedReader waypointsReader = MinecraftClient.getInstance().getResourceManager().openAsReader(new Identifier(SkyblockerMod.NAMESPACE, "dungeons/secretlocations.json"))) { - roomsJson = SkyblockerMod.GSON.fromJson(roomsReader, JsonObject.class); - waypointsJson = SkyblockerMod.GSON.fromJson(waypointsReader, JsonObject.class); - LOGGER.debug("Loaded dungeon secrets json"); - } catch (Exception e) { - LOGGER.error("Failed to load dungeon secrets json", e); - } - }, MinecraftClient.getInstance())); - roomsLoaded = CompletableFuture.allOf(dungeonFutures.toArray(CompletableFuture[]::new)).thenRun(() -> LOGGER.info("Loaded dungeon secrets for {} dungeon(s), {} room shapes, and {} rooms total", ROOMS.size(), ROOMS.values().stream().mapToInt(HashMap::size).sum(), ROOMS.values().stream().map(HashMap::values).flatMap(Collection::stream).mapToInt(HashMap::size).sum())); - } catch (Exception e) { - LOGGER.error("Failed to load dungeon secrets", e); + dungeonFutures.add(CompletableFuture.allOf(roomShapeFutures.toArray(CompletableFuture[]::new)).thenRun(() -> LOGGER.debug("Loaded dungeon secrets for dungeon {} with {} room shapes and {} rooms total", dungeon.getName(), ROOMS.get(dungeon.getName()).size(), ROOMS.get(dungeon.getName()).values().stream().mapToInt(HashMap::size).sum()))); } - }); + // Execute with MinecraftClient as executor since we need to wait for MinecraftClient#resourceManager to be set + dungeonFutures.add(CompletableFuture.runAsync(() -> { + try (BufferedReader roomsReader = MinecraftClient.getInstance().getResourceManager().openAsReader(new Identifier(SkyblockerMod.NAMESPACE, "dungeons/dungeonrooms.json")); BufferedReader waypointsReader = MinecraftClient.getInstance().getResourceManager().openAsReader(new Identifier(SkyblockerMod.NAMESPACE, "dungeons/secretlocations.json"))) { + roomsJson = SkyblockerMod.GSON.fromJson(roomsReader, JsonObject.class); + waypointsJson = SkyblockerMod.GSON.fromJson(waypointsReader, JsonObject.class); + LOGGER.debug("Loaded dungeon secrets json"); + } catch (Exception e) { + LOGGER.error("Failed to load dungeon secrets json", e); + } + }, MinecraftClient.getInstance())); + roomsLoaded = CompletableFuture.allOf(dungeonFutures.toArray(CompletableFuture[]::new)).thenRun(() -> LOGGER.info("Loaded dungeon secrets for {} dungeon(s), {} room shapes, and {} rooms total", ROOMS.size(), ROOMS.values().stream().mapToInt(HashMap::size).sum(), ROOMS.values().stream().map(HashMap::values).flatMap(Collection::stream).mapToInt(HashMap::size).sum())); + } catch (Exception e) { + LOGGER.error("Failed to load dungeon secrets", e); + } } private static HashMap<String, long[]> readRooms(File roomShape, int resourcePathIndex) { @@ -101,4 +112,28 @@ public class DungeonSecrets { LOGGER.debug("Loaded dungeon secrets room shape {} with {} rooms", roomShape.getName(), data.size()); return data; } + + private static void update() { + if (!SkyblockerConfig.get().locations.dungeons.secretWaypoints || !Utils.isInDungeons()) { + return; + } + MinecraftClient client = MinecraftClient.getInstance(); + if (client.player == null || client.world == null) { + return; + } + ItemStack stack = client.player.getInventory().main.get(8); + if (!stack.isOf(Items.FILLED_MAP)) { + return; + } + MapState map = FilledMapItem.getMapState(FilledMapItem.getMapId(stack), client.world); + if (map == null) { + return; + } + if (mapEntrancePos == null && (mapEntrancePos = DungeonMapUtils.getEntrancePos(map)) == null) { + return; + } + if (mapRoomWidth == 0 && (mapRoomWidth = DungeonMapUtils.getRoomWidth(map, mapEntrancePos)) == 0) { + return; + } + } } |