From cacef8c8fcc698aca625b13ec1a5f453907fbc4d Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Mon, 25 Nov 2024 20:05:21 +0100 Subject: [PATCH] add legacy tile data reader --- .../iris/core/commands/CommandObject.java | 6 +- .../com/volmit/iris/core/service/WandSVC.java | 4 +- .../volmit/iris/engine/object/IrisObject.java | 4 +- .../iris/engine/object/LegacyTileData.java | 57 +++++++++++++++++-- .../volmit/iris/engine/object/TileData.java | 8 ++- .../iris/util/matter/slices/TileMatter.java | 2 +- 6 files changed, 68 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandObject.java b/core/src/main/java/com/volmit/iris/core/commands/CommandObject.java index 6c7270db8..cd8ef6058 100644 --- a/core/src/main/java/com/volmit/iris/core/commands/CommandObject.java +++ b/core/src/main/java/com/volmit/iris/core/commands/CommandObject.java @@ -376,9 +376,11 @@ public class CommandObject implements DecreeExecutor { @Param(description = "The file to store it in, can use / for subfolders") String name, @Param(description = "Overwrite existing object files", defaultValue = "false", aliases = "force") - boolean overwrite + boolean overwrite, + @Param(description = "Use legacy TileState serialization if possible", defaultValue = "true") + boolean legacy ) { - IrisObject o = WandSVC.createSchematic(player()); + IrisObject o = WandSVC.createSchematic(player(), legacy); if (o == null) { sender().sendMessage(C.YELLOW + "You need to hold your wand!"); diff --git a/core/src/main/java/com/volmit/iris/core/service/WandSVC.java b/core/src/main/java/com/volmit/iris/core/service/WandSVC.java index 1899941bc..f87bb3ef6 100644 --- a/core/src/main/java/com/volmit/iris/core/service/WandSVC.java +++ b/core/src/main/java/com/volmit/iris/core/service/WandSVC.java @@ -76,7 +76,7 @@ public class WandSVC implements IrisService { * @param p The wand player * @return The new object */ - public static IrisObject createSchematic(Player p) { + public static IrisObject createSchematic(Player p, boolean legacy) { if (!isHoldingWand(p)) { return null; } @@ -132,7 +132,7 @@ public class WandSVC implements IrisService { continue; BlockVector bv = b.getLocation().subtract(c.getLowerNE().toVector()).toVector().toBlockVector(); - s.setUnsigned(bv.getBlockX(), bv.getBlockY(), bv.getBlockZ(), b); + s.setUnsigned(bv.getBlockX(), bv.getBlockY(), bv.getBlockZ(), b, legacy); } finally { i++; } diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisObject.java b/core/src/main/java/com/volmit/iris/engine/object/IrisObject.java index aabae1998..ebd502a9b 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisObject.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisObject.java @@ -562,7 +562,7 @@ public class IrisObject extends IrisRegistrant { } } - public void setUnsigned(int x, int y, int z, Block block) { + public void setUnsigned(int x, int y, int z, Block block, boolean legacy) { BlockVector v = getSigned(x, y, z); if (block == null) { @@ -571,7 +571,7 @@ public class IrisObject extends IrisRegistrant { } else { BlockData data = block.getBlockData(); getBlocks().put(v, data); - TileData state = TileData.getTileState(block); + TileData state = TileData.getTileState(block, legacy); if (state != null) { Iris.debug("Saved State " + v); getStates().put(v, state); diff --git a/core/src/main/java/com/volmit/iris/engine/object/LegacyTileData.java b/core/src/main/java/com/volmit/iris/engine/object/LegacyTileData.java index 5820fc064..233f0b8d6 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/LegacyTileData.java +++ b/core/src/main/java/com/volmit/iris/engine/object/LegacyTileData.java @@ -1,8 +1,10 @@ package com.volmit.iris.engine.object; +import com.volmit.iris.core.nms.container.Pair; import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.scheduling.J; +import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.NonNull; import lombok.ToString; @@ -15,6 +17,7 @@ import org.bukkit.block.banner.Pattern; import org.bukkit.block.banner.PatternType; import org.bukkit.block.data.BlockData; import org.bukkit.entity.EntityType; +import org.jetbrains.annotations.Nullable; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -24,10 +27,10 @@ import java.util.Map; @ToString @EqualsAndHashCode(callSuper = false) public class LegacyTileData extends TileData { - private static final Map> legacy = Map.of( - 0, SignHandler::new, - 1, SpawnerHandler::new, - 2, BannerHandler::new); + private static final Map>> legacy = Map.of( + 0, new Pair<>(SignHandler::fromBukkit, SignHandler::new), + 1, new Pair<>(SpawnerHandler::fromBukkit, SpawnerHandler::new), + 2, new Pair<>(BannerHandler::fromBukkit, BannerHandler::new)); private final int id; private final Handler handler; @@ -36,7 +39,24 @@ public class LegacyTileData extends TileData { var factory = legacy.get(id); if (factory == null) throw new IOException("Unknown tile type: " + id); - handler = factory.apply(in); + handler = factory.getB().apply(in); + } + + private LegacyTileData(int id, Handler handler) { + this.id = id; + this.handler = handler; + } + + @Nullable + public static LegacyTileData fromBukkit(@NonNull BlockState tileState) { + var type = tileState.getType(); + for (var id : legacy.keySet()) { + var factory = legacy.get(id); + var handler = factory.getA().apply(tileState, type); + if (handler != null) + return new LegacyTileData(id, handler); + } + return null; } @Override @@ -77,8 +97,14 @@ public class LegacyTileData extends TileData { void toBukkit(Block block); } + @FunctionalInterface + private interface Builder { + @Nullable Handler apply(@NonNull BlockState blockState, @NonNull Material type); + } + @ToString @EqualsAndHashCode + @AllArgsConstructor private static class SignHandler implements Handler { private final String line1; private final String line2; @@ -94,6 +120,13 @@ public class LegacyTileData extends TileData { dyeColor = DyeColor.values()[in.readByte()]; } + @SuppressWarnings("deprecation") + private static SignHandler fromBukkit(BlockState blockState, Material type) { + if (!Tag.ALL_SIGNS.isTagged(type) || !(blockState instanceof Sign sign)) + return null; + return new SignHandler(sign.getLine(0), sign.getLine(1), sign.getLine(2), sign.getLine(3), sign.getColor()); + } + @Override public Material getMaterial() { return Material.OAK_SIGN; @@ -126,6 +159,7 @@ public class LegacyTileData extends TileData { } @ToString @EqualsAndHashCode + @AllArgsConstructor private static class SpawnerHandler implements Handler { private final EntityType type; @@ -133,6 +167,12 @@ public class LegacyTileData extends TileData { type = EntityType.values()[in.readShort()]; } + private static SpawnerHandler fromBukkit(BlockState blockState, Material material) { + if (material != Material.SPAWNER || !(blockState instanceof CreatureSpawner spawner)) + return null; + return new SpawnerHandler(spawner.getSpawnedType()); + } + @Override public Material getMaterial() { return Material.SPAWNER; @@ -157,6 +197,7 @@ public class LegacyTileData extends TileData { } @ToString @EqualsAndHashCode + @AllArgsConstructor private static class BannerHandler implements Handler { private final KList patterns; private final DyeColor baseColor; @@ -172,6 +213,12 @@ public class LegacyTileData extends TileData { } } + private static BannerHandler fromBukkit(BlockState blockState, Material type) { + if (!Tag.BANNERS.isTagged(type) || !(blockState instanceof Banner banner)) + return null; + return new BannerHandler(new KList<>(banner.getPatterns()), banner.getBaseColor()); + } + @Override public Material getMaterial() { return Material.WHITE_BANNER; diff --git a/core/src/main/java/com/volmit/iris/engine/object/TileData.java b/core/src/main/java/com/volmit/iris/engine/object/TileData.java index 9e330702e..094c48b00 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/TileData.java +++ b/core/src/main/java/com/volmit/iris/engine/object/TileData.java @@ -53,9 +53,15 @@ public class TileData implements Cloneable { return false; } - public static TileData getTileState(Block block) { + public static TileData getTileState(Block block, boolean useLegacy) { if (!INMS.get().hasTile(block.getType())) return null; + if (useLegacy) { + var legacy = LegacyTileData.fromBukkit(block.getState()); + if (legacy != null) + return legacy; + } + return new TileData().fromBukkit(block); } diff --git a/core/src/main/java/com/volmit/iris/util/matter/slices/TileMatter.java b/core/src/main/java/com/volmit/iris/util/matter/slices/TileMatter.java index 25e46a831..c5febf50b 100644 --- a/core/src/main/java/com/volmit/iris/util/matter/slices/TileMatter.java +++ b/core/src/main/java/com/volmit/iris/util/matter/slices/TileMatter.java @@ -40,7 +40,7 @@ public class TileMatter extends RawMatter { public TileMatter(int width, int height, int depth) { super(width, height, depth, TileWrapper.class); registerWriter(World.class, (w, d, x, y, z) -> TileData.setTileState(w.getBlockAt(new Location(w, x, y, z)), d.getData())); - registerReader(World.class, (w, x, y, z) -> new TileWrapper(TileData.getTileState(w.getBlockAt(new Location(w, x, y, z))))); + registerReader(World.class, (w, x, y, z) -> new TileWrapper(TileData.getTileState(w.getBlockAt(new Location(w, x, y, z)), false))); } @Override