From 8232282d13c5fa9d226027965fb6c326643997f2 Mon Sep 17 00:00:00 2001 From: "its.bread" <38575088+cyljacky02@users.noreply.github.com> Date: Thu, 4 Dec 2025 23:28:06 +0800 Subject: [PATCH] Fix locked maps not rendering after server restart (#620) --- .../husksync/maps/BukkitMapHandler.java | 50 ++++++++----------- .../husksync/database/Database.java | 4 +- .../husksync/database/MongoDbDatabase.java | 4 +- .../husksync/database/MySqlDatabase.java | 4 +- .../husksync/database/PostgresDatabase.java | 5 +- 5 files changed, 30 insertions(+), 37 deletions(-) diff --git a/bukkit/src/main/java/net/william278/husksync/maps/BukkitMapHandler.java b/bukkit/src/main/java/net/william278/husksync/maps/BukkitMapHandler.java index d7a55682..5466b767 100644 --- a/bukkit/src/main/java/net/william278/husksync/maps/BukkitMapHandler.java +++ b/bukkit/src/main/java/net/william278/husksync/maps/BukkitMapHandler.java @@ -124,8 +124,8 @@ public interface BukkitMapHandler { @Nullable @Blocking - private Map.Entry readMapData(@NotNull String serverName, int mapId) { - final Map.Entry readData = fetchMapData(serverName, mapId); + private MapData readMapData(@NotNull String serverName, int mapId) { + final byte[] readData = fetchMapData(serverName, mapId); if (readData == null) { return null; } @@ -134,23 +134,23 @@ public interface BukkitMapHandler { @Nullable @Blocking - private Map.Entry fetchMapData(@NotNull String serverName, int mapId) { + private byte[] fetchMapData(@NotNull String serverName, int mapId) { return fetchMapData(serverName, mapId, true); } @Nullable @Blocking - private Map.Entry fetchMapData(@NotNull String serverName, int mapId, boolean doReverseLookup) { + private byte[] fetchMapData(@NotNull String serverName, int mapId, boolean doReverseLookup) { // Read from Redis cache final byte[] redisData = getRedisManager().getMapData(serverName, mapId); if (redisData != null) { - return new AbstractMap.SimpleImmutableEntry<>(redisData, true); + return redisData; } // Read from database and set to Redis - @Nullable Map.Entry databaseData = getPlugin().getDatabase().getMapData(serverName, mapId); + final byte[] databaseData = getPlugin().getDatabase().getMapData(serverName, mapId); if (databaseData != null) { - getRedisManager().setMapData(serverName, mapId, databaseData.getKey()); + getRedisManager().setMapData(serverName, mapId, databaseData); return databaseData; } @@ -162,7 +162,7 @@ public interface BukkitMapHandler { } @Nullable - private Map.Entry fetchReversedMapData(@NotNull String serverName, int mapId) { + private byte[] fetchReversedMapData(@NotNull String serverName, int mapId) { // Lookup binding from Redis cache, then fetch data if found Map.Entry binding = getRedisManager().getReversedMapBound(serverName, mapId); if (binding != null) { @@ -179,13 +179,10 @@ public interface BukkitMapHandler { } @Nullable - private Map.Entry deserializeMapData(@NotNull Map.Entry data) { + private MapData deserializeMapData(byte @NotNull [] data) { try { - return new AbstractMap.SimpleImmutableEntry<>( - getPlugin().getDataAdapter().fromBytes(data.getKey(), AdaptableMapData.class) - .getData(getPlugin().getDataVersion(getPlugin().getMinecraftVersion())), - data.getValue() - ); + return getPlugin().getDataAdapter().fromBytes(data, AdaptableMapData.class) + .getData(getPlugin().getDataVersion(getPlugin().getMinecraftVersion())); } catch (IOException e) { getPlugin().log(Level.WARNING, "Failed to deserialize map data", e); return null; @@ -297,7 +294,7 @@ public interface BukkitMapHandler { } getPlugin().debug("Deserializing map data from NBT and generating view..."); - Map.Entry mapData = readMapData(originServer, originalId); + MapData mapData = readMapData(originServer, originalId); if (mapData == null && nbt.hasTag(MAP_LEGACY_PIXEL_DATA_KEY)) { mapData = readLegacyMapItemData(nbt); } @@ -308,14 +305,14 @@ public interface BukkitMapHandler { } MapView newView = view != null ? view : Bukkit.createMap(getDefaultMapWorld()); - generateRenderedMap(Objects.requireNonNull(mapData).getKey(), newView); + generateRenderedMap(mapData, newView); meta.setMapView(newView); } private void handleUnboundMap(@NotNull MapMeta meta, @NotNull ReadableItemNBT nbt, @NotNull String originServer, int originalId, @NotNull String currentServer) { getPlugin().debug("Deserializing map data from NBT and generating view..."); - Map.Entry mapData = readMapData(originServer, originalId); + MapData mapData = readMapData(originServer, originalId); if (mapData == null && nbt.hasTag(MAP_LEGACY_PIXEL_DATA_KEY)) { mapData = readLegacyMapItemData(nbt); } @@ -325,7 +322,7 @@ public interface BukkitMapHandler { return; } - final MapView view = generateRenderedMap(Objects.requireNonNull(mapData, "Pixel data null!").getKey()); + final MapView view = generateRenderedMap(Objects.requireNonNull(mapData, "Pixel data null!")); meta.setMapView(view); final int id = view.getId(); @@ -351,7 +348,7 @@ public interface BukkitMapHandler { return; } - Map.Entry data = readMapData(getPlugin().getServerName(), view.getId()); + MapData data = readMapData(getPlugin().getServerName(), view.getId()); if (data == null) { data = readLegacyMapFileData(view.getId()); } @@ -362,10 +359,7 @@ public interface BukkitMapHandler { .formatted(world.getName(), view.getId())); return; } - if (data.getValue()) { - return; - } - renderMapView(view, data.getKey()); + renderMapView(view, data); } @NotNull @@ -471,11 +465,11 @@ public interface BukkitMapHandler { // Legacy - read maps from item stacks @Nullable @Blocking - private Map.Entry readLegacyMapItemData(@NotNull ReadableItemNBT nbt) { + private MapData readLegacyMapItemData(@NotNull ReadableItemNBT nbt) { final int dataVer = getPlugin().getDataVersion(getPlugin().getMinecraftVersion()); try { - return new AbstractMap.SimpleImmutableEntry<>(MapData.fromByteArray(dataVer, - Objects.requireNonNull(nbt.getByteArray(MAP_LEGACY_PIXEL_DATA_KEY))), false); + return MapData.fromByteArray(dataVer, + Objects.requireNonNull(nbt.getByteArray(MAP_LEGACY_PIXEL_DATA_KEY))); } catch (IOException e) { getPlugin().log(Level.WARNING, "Failed to read legacy map data", e); return null; @@ -484,14 +478,14 @@ public interface BukkitMapHandler { // Legacy - read maps from files @Nullable - private Map.Entry readLegacyMapFileData(int mapId) { + private MapData readLegacyMapFileData(int mapId) { final Path path = getPlugin().getDataFolder().toPath().resolve("maps").resolve(mapId + ".dat"); final File file = path.toFile(); if (!file.exists()) { return null; } try { - return new AbstractMap.SimpleImmutableEntry<>(MapData.fromNbt(file), false); + return MapData.fromNbt(file); } catch (IOException e) { getPlugin().log(Level.WARNING, "Failed to read legacy map file", e); return null; diff --git a/common/src/main/java/net/william278/husksync/database/Database.java b/common/src/main/java/net/william278/husksync/database/Database.java index 27ee84bf..38e909ca 100644 --- a/common/src/main/java/net/william278/husksync/database/Database.java +++ b/common/src/main/java/net/william278/husksync/database/Database.java @@ -274,10 +274,10 @@ public abstract class Database { * * @param serverName Name of the server the map originates from * @param mapId Original map ID - * @return Map.Entry (key: map data, value: is from current world) + * @return the map data bytes, or null if not found */ @Blocking - public abstract @Nullable Map.Entry getMapData(@NotNull String serverName, int mapId); + public abstract byte @Nullable [] getMapData(@NotNull String serverName, int mapId); /** * Get a map server -> ID binding in the database diff --git a/common/src/main/java/net/william278/husksync/database/MongoDbDatabase.java b/common/src/main/java/net/william278/husksync/database/MongoDbDatabase.java index c4019c4d..32987059 100644 --- a/common/src/main/java/net/william278/husksync/database/MongoDbDatabase.java +++ b/common/src/main/java/net/william278/husksync/database/MongoDbDatabase.java @@ -376,14 +376,14 @@ public class MongoDbDatabase extends Database { @Blocking @Override - public @Nullable Map.Entry getMapData(@NotNull String serverName, int mapId) { + public byte @Nullable [] getMapData(@NotNull String serverName, int mapId) { try { Document filter = new Document("server_name", serverName).append("map_id", mapId); FindIterable iterable = mongoCollectionHelper.getCollection(mapDataTable).find(filter); Document doc = iterable.first(); if (doc != null) { final Binary bin = doc.get("data", Binary.class); - return Map.entry(bin.getData(), true); + return bin.getData(); } } catch (MongoException e) { plugin.log(Level.SEVERE, "Failed to get map data from the database", e); diff --git a/common/src/main/java/net/william278/husksync/database/MySqlDatabase.java b/common/src/main/java/net/william278/husksync/database/MySqlDatabase.java index eee3459a..4562c78d 100644 --- a/common/src/main/java/net/william278/husksync/database/MySqlDatabase.java +++ b/common/src/main/java/net/william278/husksync/database/MySqlDatabase.java @@ -473,7 +473,7 @@ public class MySqlDatabase extends Database { @Blocking @Override - public @Nullable Map.Entry getMapData(@NotNull String serverName, int mapId) { + public byte @Nullable [] getMapData(@NotNull String serverName, int mapId) { try (Connection connection = getConnection()) { try (PreparedStatement statement = connection.prepareStatement(formatStatementTables(""" SELECT `data` @@ -488,7 +488,7 @@ public class MySqlDatabase extends Database { final Blob blob = resultSet.getBlob("data"); final byte[] dataByteArray = blob.getBytes(1, (int) blob.length()); blob.free(); - return Map.entry(dataByteArray, true); + return dataByteArray; } } } catch (SQLException | DataAdapter.AdaptionException e) { diff --git a/common/src/main/java/net/william278/husksync/database/PostgresDatabase.java b/common/src/main/java/net/william278/husksync/database/PostgresDatabase.java index 13c06f9e..ddab60a1 100644 --- a/common/src/main/java/net/william278/husksync/database/PostgresDatabase.java +++ b/common/src/main/java/net/william278/husksync/database/PostgresDatabase.java @@ -469,7 +469,7 @@ public class PostgresDatabase extends Database { @Blocking @Override - public @Nullable Map.Entry getMapData(@NotNull String serverName, int mapId) { + public byte @Nullable [] getMapData(@NotNull String serverName, int mapId) { try (Connection connection = getConnection()) { try (PreparedStatement statement = connection.prepareStatement(formatStatementTables(""" SELECT data @@ -480,8 +480,7 @@ public class PostgresDatabase extends Database { statement.setInt(2, mapId); final ResultSet resultSet = statement.executeQuery(); if (resultSet.next()) { - final byte[] data = resultSet.getBytes("data"); - return new AbstractMap.SimpleImmutableEntry<>(data, true); + return resultSet.getBytes("data"); } return null; }