diff --git a/src/main/java/twilightforest/item/MagicMapItem.java b/src/main/java/twilightforest/item/MagicMapItem.java index f54218a59b..2a637e2337 100644 --- a/src/main/java/twilightforest/item/MagicMapItem.java +++ b/src/main/java/twilightforest/item/MagicMapItem.java @@ -25,6 +25,7 @@ import twilightforest.init.TFBiomes; import twilightforest.init.TFDataMaps; import twilightforest.init.TFItems; +import twilightforest.item.mapdata.MapDataManager; import twilightforest.item.mapdata.TFMagicMapData; import twilightforest.tags.TFStructureTags; import twilightforest.util.datamaps.MagicMapBiomeColor; @@ -53,7 +54,16 @@ public static ItemStack setupNewMap(ServerLevel level, int worldX, int worldZ, b @Nullable public static TFMagicMapData getData(ItemStack stack, Level level) { MapId mapid = stack.get(DataComponents.MAP_ID); - return mapid == null ? null : TFMagicMapData.getMagicMapData(level, getMapName(mapid.id())); + + if (mapid == null) { + return null; + } + + if (level instanceof ServerLevel serverLevel) { + return MapDataManager.getServerMagicMapData(serverLevel, mapid); + } + + return MapDataManager.getClientMagicMapData(mapid); } @Nullable @@ -89,7 +99,7 @@ private static TFMagicMapData createMapData(ItemStack stack, ServerLevel level, ColumnPos pos = getMagicMapCenter(x, z); TFMagicMapData mapdata = new TFMagicMapData(pos.x(), pos.z(), (byte) scale, trackingPosition, unlimitedTracking, false, dimension); - TFMagicMapData.registerMagicMapData(level, mapdata, getMapName(freeMapId.id())); // call our own register method + MapDataManager.saveServerMagicMapData(level, freeMapId, mapdata); // call our own save method stack.set(DataComponents.MAP_ID, freeMapId); return mapdata; } diff --git a/src/main/java/twilightforest/item/MazeMapItem.java b/src/main/java/twilightforest/item/MazeMapItem.java index d23a3a21e3..f0f2d81259 100644 --- a/src/main/java/twilightforest/item/MazeMapItem.java +++ b/src/main/java/twilightforest/item/MazeMapItem.java @@ -27,6 +27,7 @@ import org.jspecify.annotations.Nullable; import twilightforest.init.TFDataMaps; import twilightforest.init.TFItems; +import twilightforest.item.mapdata.MapDataManager; import twilightforest.item.mapdata.TFMazeMapData; import twilightforest.util.datamaps.OreMapOreColor; @@ -53,8 +54,17 @@ public static ItemStack setupNewMap(ServerLevel level, int worldX, int worldZ, b @Nullable public static TFMazeMapData getData(ItemStack stack, Level level) { - MapId id = stack.get(DataComponents.MAP_ID); - return id == null ? null : TFMazeMapData.getMazeMapData(level, getMapName(id.id())); + MapId mapId = stack.get(DataComponents.MAP_ID); + + if (mapId == null) { + return null; + } + + if (level instanceof ServerLevel serverLevel) { + return MapDataManager.getServerMazeMapData(serverLevel, mapId); + } + + return MapDataManager.getClientMazeMapData(mapId); } @Nullable @@ -70,7 +80,7 @@ protected TFMazeMapData getCustomMapData(ItemStack stack, Level level) { } private static TFMazeMapData createMapData(ItemStack stack, ServerLevel level, int x, int z, int scale, boolean trackingPosition, boolean unlimitedTracking, ResourceKey dimension, int y, boolean ore) { - MapId i = level.getFreeMapId(); + MapId freeMapId = level.getFreeMapId(); int mapSize = 128 * (1 << scale); int roundX = Mth.floor((x + 64.0D) / (double) mapSize); @@ -81,8 +91,8 @@ private static TFMazeMapData createMapData(ItemStack stack, ServerLevel level, i TFMazeMapData mapdata = new TFMazeMapData(scaledX, scaledZ, (byte) scale, trackingPosition, unlimitedTracking, false, dimension); mapdata.calculateMapCenter(level, x, y, z); // call our own map center calculation mapdata.ore = ore; - TFMazeMapData.registerMazeMapData(level, mapdata, getMapName(i.id())); // call our own register method - stack.set(DataComponents.MAP_ID, i); + MapDataManager.saveServerMazeMapData(level, freeMapId, mapdata); // call our own save method + stack.set(DataComponents.MAP_ID, freeMapId); return mapdata; } @@ -166,7 +176,7 @@ public void update(Level level, Entity viewer, MapItemSavedData data) { if (this.mapOres) { // recolor ores - OreMapOreColor color = state.getBlock().builtInRegistryHolder().getData(TFDataMaps.ORE_MAP_ORE_COLOR); + OreMapOreColor color = state.typeHolder().getData(TFDataMaps.ORE_MAP_ORE_COLOR); if (color != null) { multiset.add(color.color(), 1000); } else if (!state.isAir() && state.is(Tags.Blocks.ORES)) { diff --git a/src/main/java/twilightforest/item/mapdata/MapDataManager.java b/src/main/java/twilightforest/item/mapdata/MapDataManager.java new file mode 100644 index 0000000000..291a288c5b --- /dev/null +++ b/src/main/java/twilightforest/item/mapdata/MapDataManager.java @@ -0,0 +1,48 @@ +package twilightforest.item.mapdata; + +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.saveddata.maps.MapId; +import org.jspecify.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; + +/* +* Most of the content in this class is adapted from implementations in ServerLevel and ClientLevel. +*/ +public final class MapDataManager { + private static final Map MAGIC_MAP_CLIENT_DATA = new HashMap<>(); + private static final Map MAZE_MAP_CLIENT_DATA = new HashMap<>(); + + public static @Nullable TFMagicMapData getServerMagicMapData(ServerLevel serverLevel, MapId id) { + return serverLevel.getServer().getDataStorage().get(TFMagicMapData.magicMapType(id)); + } + + public static @Nullable TFMazeMapData getServerMazeMapData(ServerLevel serverLevel, MapId id) { + return serverLevel.getServer().getDataStorage().get(TFMazeMapData.mazeMapType(id)); + } + + public static @Nullable TFMagicMapData getClientMagicMapData(MapId id) { + return MAGIC_MAP_CLIENT_DATA.get(id); + } + + public static @Nullable TFMazeMapData getClientMazeMapData(MapId id) { + return MAZE_MAP_CLIENT_DATA.get(id); + } + + public static void saveServerMagicMapData(ServerLevel serverLevel, MapId id, TFMagicMapData data) { + serverLevel.getServer().getDataStorage().set(TFMagicMapData.magicMapType(id), data); + } + + public static void saveServerMazeMapData(ServerLevel serverLevel, MapId id, TFMazeMapData data) { + serverLevel.getServer().getDataStorage().set(TFMazeMapData.mazeMapType(id), data); + } + + public static void saveClientMagicMapData(MapId id, TFMagicMapData data) { + MAGIC_MAP_CLIENT_DATA.put(id, data); + } + + public static void saveClientMazeMapData(MapId id, TFMazeMapData data) { + MAZE_MAP_CLIENT_DATA.put(id, data); + } +} \ No newline at end of file diff --git a/src/main/java/twilightforest/item/mapdata/TFMagicMapData.java b/src/main/java/twilightforest/item/mapdata/TFMagicMapData.java index b8f9040ed7..c958541b7e 100644 --- a/src/main/java/twilightforest/item/mapdata/TFMagicMapData.java +++ b/src/main/java/twilightforest/item/mapdata/TFMagicMapData.java @@ -3,124 +3,129 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.Holder; -import net.minecraft.core.HolderLookup; -import net.minecraft.nbt.*; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientboundMapItemDataPacket; import net.minecraft.resources.ResourceKey; -import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.Mth; import net.minecraft.util.datafix.DataFixTypes; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.saveddata.SavedData; -import net.minecraft.world.level.saveddata.maps.MapDecoration; -import net.minecraft.world.level.saveddata.maps.MapDecorationType; -import net.minecraft.world.level.saveddata.maps.MapId; -import net.minecraft.world.level.saveddata.maps.MapItemSavedData; -import org.jetbrains.annotations.Nullable; +import net.minecraft.world.level.saveddata.SavedDataType; +import net.minecraft.world.level.saveddata.maps.*; +import org.jspecify.annotations.Nullable; import twilightforest.TwilightForestMod; import twilightforest.item.MagicMapItem; import twilightforest.network.MagicMapPacket; import twilightforest.util.Codecs; +import java.nio.ByteBuffer; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; public class TFMagicMapData extends MapItemSavedData { - private static final Map CLIENT_DATA = new HashMap<>(); public final List conqueredStructures = new ArrayList<>(); - public TFMagicMapData(int x, int z, byte scale, boolean trackpos, boolean unlimited, boolean locked, ResourceKey dim) { - super(x, z, scale, trackpos, unlimited, locked, dim); + // [VanillaCopy] from MapItemSavedData but with our own fields and constructor + public static final Codec CODEC = RecordCodecBuilder.create(i -> + i.group( + Level.RESOURCE_KEY_CODEC + .fieldOf("dimension") + .forGetter(m -> m.dimension), + Codec.INT + .fieldOf("xCenter") + .forGetter(m -> m.centerX), + Codec.INT + .fieldOf("zCenter") + .forGetter(m -> m.centerZ), + Codec.BYTE + .optionalFieldOf("scale", (byte) 0) + .forGetter(m -> m.scale), + Codec.BYTE_BUFFER + .fieldOf("colors") + .forGetter(m -> ByteBuffer.wrap(m.colors)), + Codec.BOOL + .optionalFieldOf("trackingPosition", true) + .forGetter(m -> m.trackingPosition), + Codec.BOOL + .optionalFieldOf("unlimitedTracking", false) + .forGetter(m -> m.unlimitedTracking), + Codec.BOOL + .optionalFieldOf("locked", false) + .forGetter(m -> m.locked), + MapBanner.CODEC + .listOf() + .optionalFieldOf("banners", List.of()) + .forGetter(m -> List.copyOf(m.bannerMarkers.values())), + MapFrame.CODEC + .listOf() + .optionalFieldOf("frames", List.of()) + .forGetter(m -> List.copyOf(m.frameMarkers.values())), + DecorationHolder.CODEC + .listOf() + .optionalFieldOf("decorations", List.of()) + .forGetter(m -> { + List holders = new ArrayList<>(); + m.decorations.forEach((id, decoration) -> { + if (decoration.type().value().showOnItemFrame()) { + holders.add(new DecorationHolder(id, decoration)); + } + }); + return holders; + }), + Codec.STRING + .listOf() + .optionalFieldOf("conquered_structures", List.of()) + .forGetter(m -> List.copyOf(m.conqueredStructures)) + ).apply(i, TFMagicMapData::new) + ); + + // [VanillaCopy] from MapItemSavedData but changed to use our Codec and namespace + public static SavedDataType magicMapType(MapId id) { + return new SavedDataType<>(TwilightForestMod.prefix(id.key()), () -> { + throw new IllegalStateException("Should never create an empty map saved data"); + }, CODEC, DataFixTypes.SAVED_DATA_MAP_DATA); } - public static TFMagicMapData load(CompoundTag nbt, HolderLookup.Provider provider) { - MapItemSavedData data = MapItemSavedData.load(nbt, provider); - final boolean trackingPosition = !nbt.contains("trackingPosition", 1) || nbt.getBoolean("trackingPosition"); - final boolean unlimitedTracking = nbt.getBoolean("unlimitedTracking"); - final boolean locked = nbt.getBoolean("locked"); - TFMagicMapData tfdata = new TFMagicMapData(data.centerX, data.centerZ, data.scale, trackingPosition, unlimitedTracking, locked, data.dimension); - - tfdata.colors = data.colors; - tfdata.bannerMarkers.putAll(data.bannerMarkers); - tfdata.frameMarkers.putAll(data.frameMarkers); - - for (DecorationHolder decoration : DecorationHolder.CODEC.listOf() - .parse(provider.createSerializationContext(NbtOps.INSTANCE), nbt.get("decorations")) - .resultOrPartial(error -> TwilightForestMod.LOGGER.warn("Failed to parse map decoration: '{}'", error)) - .orElse(List.of())) { - MapDecoration mapdecoration1 = decoration.decoration(); - MapDecoration mapdecoration = tfdata.decorations.put(decoration.id(), mapdecoration1); - if (!mapdecoration1.equals(mapdecoration)) { - if (mapdecoration != null && mapdecoration.type().value().trackCount()) { - tfdata.trackedDecorationCount--; - } + // [VanillaCopy] from MapItemSavedData + public TFMagicMapData(int centerX, int centerZ, byte scale, boolean trackingPosition, boolean unlimitedTracking, boolean locked, ResourceKey dimension) { + super(centerX, centerZ, scale, trackingPosition, unlimitedTracking, locked, dimension); + } - if (decoration.decoration().type().value().trackCount()) { - tfdata.trackedDecorationCount++; - } - tfdata.setDecorationsDirty(); - } + // [VanillaCopy] from MapItemSavedData but with our own fields + private TFMagicMapData(ResourceKey dimension, int centerX, int centerZ, byte scale, ByteBuffer colors, boolean trackingPosition, boolean unlimitedTracking, boolean locked, List banners, List frames, List decorations, List conqueredStructures) { + this(centerX, centerZ, (byte) Mth.clamp(scale, 0, 4), trackingPosition, unlimitedTracking, locked, dimension); + + if (colors.array().length == 16384) { + this.colors = colors.array(); } - if (nbt.contains("conquered_structures", Tag.TAG_LIST)) { - tfdata.conqueredStructures.clear(); - ListTag tag = nbt.getList("conquered_structures", Tag.TAG_STRING); - tag.forEach(tag1 -> tfdata.conqueredStructures.add(tag1.getAsString())); + for(MapBanner banner : banners) { + this.bannerMarkers.put(banner.getId(), banner); + this.addDecoration(banner.getDecoration(), null, banner.getId(), banner.pos().getX(), banner.pos().getZ(), 180.0F, banner.name().orElse(null)); } - return tfdata; - } + for(MapFrame frame : frames) { + this.frameMarkers.put(frame.getId(), frame); + this.addDecoration(MapDecorationTypes.FRAME, null, getFrameKey(frame.entityId()), frame.pos().getX(), frame.pos().getZ(), frame.rotation(), null); + } - @Override - public CompoundTag save(CompoundTag tag, HolderLookup.Provider provider) { - tag = super.save(tag, provider); + for (DecorationHolder holder : decorations) { + MapDecoration newDecoration = holder.decoration(); + MapDecoration oldDecoration = this.decorations.put(holder.id(), newDecoration); - List holders = new ArrayList<>(); - this.decorations.forEach((s, decoration) -> { - if (decoration.type().value().showOnItemFrame()) { - holders.add(new DecorationHolder(s, decoration)); - } - }); - tag.put("decorations", DecorationHolder.CODEC.listOf().encodeStart(NbtOps.INSTANCE, holders).getOrThrow()); + if (!newDecoration.equals(oldDecoration)) { + if (oldDecoration != null && oldDecoration.type().value().trackCount()) { + this.trackedDecorationCount--; + } - if (!this.conqueredStructures.isEmpty()) { - ListTag conqueredTag = new ListTag(); - for (String structure : this.conqueredStructures) { - conqueredTag.add(StringTag.valueOf(structure)); + if (newDecoration.type().value().trackCount()) { + this.trackedDecorationCount++; + } } - tag.put("conquered_structures", conqueredTag); } - return tag; - } - - // [VanillaCopy] Adapted from World.getMapData - @Nullable - public static TFMagicMapData getMagicMapData(Level level, String name) { - if (level instanceof ServerLevel serverLevel) return (TFMagicMapData) serverLevel.getServer().overworld().getDataStorage().get(TFMagicMapData.factory(), name); - else return CLIENT_DATA.get(name); - } - - // Like the method above, but if we know we're on client - @Nullable - public static TFMagicMapData getClientMagicMapData(String name) { - return CLIENT_DATA.get(name); - } - - // [VanillaCopy] Adapted from World.registerMapData - public static void registerMagicMapData(Level level, TFMagicMapData data, String id) { - if (level instanceof ServerLevel serverLevel) serverLevel.getServer().overworld().getDataStorage().set(id, data); - else CLIENT_DATA.put(id, data); - } - - public static Factory factory() { - return new SavedData.Factory<>(() -> { - throw new IllegalStateException("Should never create an empty map saved data"); - }, TFMagicMapData::load, DataFixTypes.SAVED_DATA_MAP_DATA); + this.conqueredStructures.addAll(conqueredStructures); } @Nullable @@ -149,4 +154,4 @@ public record DecorationHolder(String id, MapDecoration decoration) { Codecs.DECORATION_CODEC.fieldOf("decoration").forGetter(DecorationHolder::decoration) ).apply(instance, DecorationHolder::new)); } -} +} \ No newline at end of file diff --git a/src/main/java/twilightforest/item/mapdata/TFMazeMapData.java b/src/main/java/twilightforest/item/mapdata/TFMazeMapData.java index 5c40cbf91a..18cbf2b1ed 100644 --- a/src/main/java/twilightforest/item/mapdata/TFMazeMapData.java +++ b/src/main/java/twilightforest/item/mapdata/TFMazeMapData.java @@ -1,61 +1,107 @@ package twilightforest.item.mapdata; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.BlockPos; -import net.minecraft.core.HolderLookup; -import net.minecraft.nbt.CompoundTag; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientboundMapItemDataPacket; import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.Mth; import net.minecraft.util.datafix.DataFixTypes; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; -import net.minecraft.world.level.saveddata.SavedData; -import net.minecraft.world.level.saveddata.maps.MapId; -import net.minecraft.world.level.saveddata.maps.MapItemSavedData; -import org.jetbrains.annotations.Nullable; +import net.minecraft.world.level.saveddata.SavedDataType; +import net.minecraft.world.level.saveddata.maps.*; +import org.jspecify.annotations.Nullable; +import twilightforest.TwilightForestMod; import twilightforest.init.TFStructures; import twilightforest.network.MazeMapPacket; import twilightforest.util.landmarks.LegacyLandmarkPlacements; -import java.util.HashMap; -import java.util.Map; +import java.nio.ByteBuffer; +import java.util.List; public class TFMazeMapData extends MapItemSavedData { - private static final Map CLIENT_DATA = new HashMap<>(); - public int yCenter; public boolean ore; - public TFMazeMapData(int x, int z, byte scale, boolean trackpos, boolean unlimited, boolean locked, ResourceKey dim) { - super(x, z, scale, trackpos, unlimited, locked, dim); + // [VanillaCopy] from MapItemSavedData but with our own fields and constructor + public static final Codec CODEC = RecordCodecBuilder.create(i -> + i.group( + Level.RESOURCE_KEY_CODEC + .fieldOf("dimension") + .forGetter(m -> m.dimension), + Codec.INT + .fieldOf("xCenter") + .forGetter(m -> m.centerX), + Codec.INT + .fieldOf("zCenter") + .forGetter(m -> m.centerZ), + Codec.BYTE + .optionalFieldOf("scale", (byte) 0) + .forGetter(m -> m.scale), + Codec.BYTE_BUFFER + .fieldOf("colors") + .forGetter(m -> ByteBuffer.wrap(m.colors)), + Codec.BOOL + .optionalFieldOf("trackingPosition", true) + .forGetter(m -> m.trackingPosition), + Codec.BOOL + .optionalFieldOf("unlimitedTracking", false) + .forGetter(m -> m.unlimitedTracking), + Codec.BOOL + .optionalFieldOf("locked", false) + .forGetter(m -> m.locked), + MapBanner.CODEC + .listOf() + .optionalFieldOf("banners", List.of()) + .forGetter(m -> List.copyOf(m.bannerMarkers.values())), + MapFrame.CODEC + .listOf() + .optionalFieldOf("frames", List.of()) + .forGetter(m -> List.copyOf(m.frameMarkers.values())), + Codec.INT + .optionalFieldOf("yCenter", 0) + .forGetter(m -> m.yCenter), + Codec.BOOL + .optionalFieldOf("mapOres", false) + .forGetter(m -> m.ore) + ).apply(i, TFMazeMapData::new) + ); + + // [VanillaCopy] from MapItemSavedData but changed to use our Codec and namespace + public static SavedDataType mazeMapType(MapId id) { + return new SavedDataType<>(TwilightForestMod.prefix(id.key()), () -> { + throw new IllegalStateException("Should never create an empty map saved data"); + }, CODEC, DataFixTypes.SAVED_DATA_MAP_DATA); } - public static TFMazeMapData load(CompoundTag nbt, HolderLookup.Provider provider) { - MapItemSavedData data = MapItemSavedData.load(nbt, provider); - final boolean trackingPosition = !nbt.contains("trackingPosition", 1) || nbt.getBoolean("trackingPosition"); - final boolean unlimitedTracking = nbt.getBoolean("unlimitedTracking"); - final boolean locked = nbt.getBoolean("locked"); - TFMazeMapData tfdata = new TFMazeMapData(data.centerX, data.centerZ, data.scale, trackingPosition, unlimitedTracking, locked, data.dimension); + // [VanillaCopy] from MapItemSavedData + public TFMazeMapData(int centerX, int centerZ, byte scale, boolean trackingPosition, boolean unlimitedTracking, boolean locked, ResourceKey dimension) { + super(centerX, centerZ, scale, trackingPosition, unlimitedTracking, locked, dimension); + } - tfdata.colors = data.colors; - tfdata.bannerMarkers.putAll(data.bannerMarkers); - tfdata.decorations.putAll(data.decorations); - tfdata.frameMarkers.putAll(data.frameMarkers); - tfdata.trackedDecorationCount = data.trackedDecorationCount; + // [VanillaCopy] from MapItemSavedData but with our own fields + private TFMazeMapData(ResourceKey dimension, int centerX, int centerZ, byte scale, ByteBuffer colors, boolean trackingPosition, boolean unlimitedTracking, boolean locked, List banners, List frames, int yCenter, boolean ore) { + this(centerX, centerZ, (byte) Mth.clamp(scale, 0, 4), trackingPosition, unlimitedTracking, locked, dimension); - tfdata.yCenter = nbt.getInt("yCenter"); - tfdata.ore = nbt.getBoolean("mapOres"); + if (colors.array().length == 16384) { + this.colors = colors.array(); + } - return tfdata; - } + for(MapBanner banner : banners) { + this.bannerMarkers.put(banner.getId(), banner); + this.addDecoration(banner.getDecoration(), null, banner.getId(), banner.pos().getX(), banner.pos().getZ(), 180.0F, banner.name().orElse(null)); + } - @Override - public CompoundTag save(CompoundTag nbt, HolderLookup.Provider provider) { - CompoundTag ret = super.save(nbt, provider); - ret.putInt("yCenter", this.yCenter); - ret.putBoolean("mapOres", this.ore); - return ret; + for(MapFrame frame : frames) { + this.frameMarkers.put(frame.getId(), frame); + this.addDecoration(MapDecorationTypes.FRAME, null, getFrameKey(frame.entityId()), frame.pos().getX(), frame.pos().getZ(), frame.rotation(), null); + } + + this.yCenter = yCenter; + this.ore = ore; } public void calculateMapCenter(Level world, int x, int y, int z) { @@ -71,35 +117,10 @@ public void calculateMapCenter(Level world, int x, int y, int z) { } } - // [VanillaCopy] Adapted from World.getMapData - @Nullable - public static TFMazeMapData getMazeMapData(Level level, String name) { - if (level.isClientSide()) return CLIENT_DATA.get(name); - else return (TFMazeMapData) ((ServerLevel) level).getServer().overworld().getDataStorage().get(TFMazeMapData.factory(), name); - } - - // Like the method above, but if we know we're on client - @Nullable - public static TFMazeMapData getClientMagicMapData(String name) { - return CLIENT_DATA.get(name); - } - - public static SavedData.Factory factory() { - return new SavedData.Factory<>(() -> { - throw new IllegalStateException("Should never create an empty map saved data"); - }, TFMazeMapData::load, DataFixTypes.SAVED_DATA_MAP_DATA); - } - - // [VanillaCopy] Adapted from World.registerMapData - public static void registerMazeMapData(Level level, TFMazeMapData data, String id) { - if (level.isClientSide()) CLIENT_DATA.put(id, data); - else ((ServerLevel) level).getServer().overworld().getDataStorage().set(id, data); - } - @Nullable @Override public Packet getUpdatePacket(MapId mapId, Player player) { Packet packet = super.getUpdatePacket(mapId, player); return packet instanceof ClientboundMapItemDataPacket mapItemDataPacket ? new MazeMapPacket(mapItemDataPacket, this.ore, this.yCenter).toVanillaClientbound() : packet; } -} +} \ No newline at end of file diff --git a/src/main/java/twilightforest/network/MagicMapPacket.java b/src/main/java/twilightforest/network/MagicMapPacket.java index d4ea0f60f5..b677deb720 100644 --- a/src/main/java/twilightforest/network/MagicMapPacket.java +++ b/src/main/java/twilightforest/network/MagicMapPacket.java @@ -1,15 +1,16 @@ package twilightforest.network; +import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.network.protocol.game.ClientboundMapItemDataPacket; -import net.minecraft.world.level.Level; +import net.minecraft.world.level.saveddata.maps.MapId; import net.minecraft.world.level.saveddata.maps.MapItemSavedData; import net.neoforged.neoforge.network.handling.IPayloadContext; import twilightforest.TwilightForestMod; -import twilightforest.item.MagicMapItem; +import twilightforest.item.mapdata.MapDataManager; import twilightforest.item.mapdata.TFMagicMapData; import java.util.List; @@ -36,13 +37,13 @@ public static void handle(MagicMapPacket message, IPayloadContext ctx) { ctx.enqueueWork(new Runnable() { @Override public void run() { - Level level = ctx.player().level(); + if (!(ctx.player().level() instanceof ClientLevel clientLevel)) return; - String s = MagicMapItem.getMapName(message.inner.mapId().id()); - TFMagicMapData mapdata = TFMagicMapData.getMagicMapData(level, s); + MapId mapId = message.inner.mapId(); + TFMagicMapData mapdata = MapDataManager.getClientMagicMapData(mapId); if (mapdata == null) { - mapdata = new TFMagicMapData(0, 0, message.inner.scale(), false, false, message.inner.locked(), level.dimension()); - TFMagicMapData.registerMagicMapData(level, mapdata, s); + mapdata = new TFMagicMapData(0, 0, message.inner.scale(), false, false, message.inner.locked(), clientLevel.dimension()); + MapDataManager.saveClientMagicMapData(mapId, mapdata); } message.inner.applyToMap(mapdata); @@ -50,7 +51,7 @@ public void run() { mapdata.conqueredStructures.clear(); mapdata.conqueredStructures.addAll(message.conqueredStructures()); - MapItemSavedData saved = level.getMapData(message.inner.mapId()); + MapItemSavedData saved = clientLevel.getMapData(message.inner.mapId()); if (saved != null) { saved.addClientSideDecorations( diff --git a/src/main/java/twilightforest/network/MazeMapPacket.java b/src/main/java/twilightforest/network/MazeMapPacket.java index 61a325b3c1..a4b7e8c4d8 100644 --- a/src/main/java/twilightforest/network/MazeMapPacket.java +++ b/src/main/java/twilightforest/network/MazeMapPacket.java @@ -1,15 +1,16 @@ package twilightforest.network; +import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.network.protocol.game.ClientboundMapItemDataPacket; -import net.minecraft.world.level.Level; +import net.minecraft.world.level.saveddata.maps.MapId; import net.minecraft.world.level.saveddata.maps.MapItemSavedData; import net.neoforged.neoforge.network.handling.IPayloadContext; import twilightforest.TwilightForestMod; -import twilightforest.item.MazeMapItem; +import twilightforest.item.mapdata.MapDataManager; import twilightforest.item.mapdata.TFMazeMapData; import java.util.stream.StreamSupport; @@ -38,10 +39,10 @@ public static void handle(MazeMapPacket message, IPayloadContext ctx) { ctx.enqueueWork(new Runnable() { @Override public void run() { - Level level = ctx.player().level(); + if (!(ctx.player().level() instanceof ClientLevel clientLevel)) return; - String s = MazeMapItem.getMapName(message.inner().mapId().id()); - TFMazeMapData mapdata = TFMazeMapData.getMazeMapData(level, s); + MapId mapId = message.inner.mapId(); + TFMazeMapData mapdata = MapDataManager.getClientMazeMapData(mapId); if (mapdata == null) { mapdata = new TFMazeMapData( 0, 0, @@ -49,16 +50,16 @@ public void run() { false, false, message.inner().locked(), - level.dimension() + clientLevel.dimension() ); - TFMazeMapData.registerMazeMapData(level, mapdata, s); + MapDataManager.saveClientMazeMapData(mapId, mapdata); } mapdata.ore = message.ore(); mapdata.yCenter = message.yCenter(); message.inner().applyToMap(mapdata); - MapItemSavedData saved = level.getMapData(message.inner().mapId()); + MapItemSavedData saved = clientLevel.getMapData(message.inner().mapId()); if (saved != null) { saved.addClientSideDecorations( diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 38538af1b6..e8763e801e 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -276,3 +276,6 @@ protected net.minecraft.world.level.block.entity.SkullBlockEntity owner # ClientLevel (Used in MagicPaintingRenderer) public net.minecraft.client.multiplayer.ClientLevel getSkyFlashTime()I + +# TFMagicMapData & TFMazeMapData (avoids a VanillaCopy for a helper method) +public net.minecraft.world.level.saveddata.maps.MapItemSavedData getFrameKey(I)Ljava/lang/String;