From 804f11c87ba934a27037c1495d8505b703f9a7c8 Mon Sep 17 00:00:00 2001 From: TheMode Date: Wed, 23 Jun 2021 02:20:51 +0200 Subject: [PATCH 1/9] Potentially fix explosion packet --- .../server/network/packet/server/play/ExplosionPacket.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/minestom/server/network/packet/server/play/ExplosionPacket.java b/src/main/java/net/minestom/server/network/packet/server/play/ExplosionPacket.java index fbf32107c..acd4fee22 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/ExplosionPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/ExplosionPacket.java @@ -13,7 +13,8 @@ public class ExplosionPacket implements ServerPacket { public byte[] records = new byte[0]; public float playerMotionX, playerMotionY, playerMotionZ; - public ExplosionPacket() {} + public ExplosionPacket() { + } @Override public void write(@NotNull BinaryWriter writer) { @@ -21,7 +22,7 @@ public class ExplosionPacket implements ServerPacket { writer.writeFloat(y); writer.writeFloat(z); writer.writeFloat(radius); - writer.writeInt(records.length/3); // each record is 3 bytes long + writer.writeVarInt(records.length / 3); // each record is 3 bytes long for (byte record : records) writer.writeByte(record); writer.writeFloat(playerMotionX); From 6526a2658a75d787cf9356b355240b03e6b26905 Mon Sep 17 00:00:00 2001 From: TheMode Date: Fri, 25 Jun 2021 06:45:02 +0200 Subject: [PATCH 2/9] Replace netty to jdk thread local random --- .../java/net/minestom/server/attribute/AttributeModifier.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/minestom/server/attribute/AttributeModifier.java b/src/main/java/net/minestom/server/attribute/AttributeModifier.java index 9ea5aab56..3cdd9be0f 100644 --- a/src/main/java/net/minestom/server/attribute/AttributeModifier.java +++ b/src/main/java/net/minestom/server/attribute/AttributeModifier.java @@ -1,10 +1,10 @@ package net.minestom.server.attribute; -import io.netty.util.internal.ThreadLocalRandom; import net.minestom.server.utils.UniqueIdUtils; import org.jetbrains.annotations.NotNull; import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; /** * Represent an attribute modifier. From d84964d55b07784a543180b52ce815daeffd73ee Mon Sep 17 00:00:00 2001 From: BuildTools Date: Fri, 25 Jun 2021 20:32:13 +0800 Subject: [PATCH 3/9] Add sendGroupedPacket convenience method to PacketGroupingAudience --- .../server/adventure/audience/PacketGroupingAudience.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/net/minestom/server/adventure/audience/PacketGroupingAudience.java b/src/main/java/net/minestom/server/adventure/audience/PacketGroupingAudience.java index cd18eeec1..9f4c4dc0f 100644 --- a/src/main/java/net/minestom/server/adventure/audience/PacketGroupingAudience.java +++ b/src/main/java/net/minestom/server/adventure/audience/PacketGroupingAudience.java @@ -14,6 +14,7 @@ import net.minestom.server.adventure.AdventurePacketConvertor; import net.minestom.server.entity.Player; import net.minestom.server.message.ChatPosition; import net.minestom.server.message.Messenger; +import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.network.packet.server.play.*; import net.minestom.server.utils.PacketUtils; import org.jetbrains.annotations.NotNull; @@ -44,6 +45,10 @@ public interface PacketGroupingAudience extends ForwardingAudience { */ @NotNull Collection getPlayers(); + default void sendGroupedPacket(ServerPacket packet) { + PacketUtils.sendGroupedPacket(this.getPlayers(), packet); + } + @Override default void sendMessage(@NotNull Identity source, @NotNull Component message, @NotNull MessageType type) { Messenger.sendMessage(this.getPlayers(), message, ChatPosition.fromMessageType(type), source.uuid()); From 07a2b37f3582c63ed8bbccc3216090683b94e64e Mon Sep 17 00:00:00 2001 From: BuildTools Date: Fri, 25 Jun 2021 20:34:19 +0800 Subject: [PATCH 4/9] Add Javadoc --- .../server/adventure/audience/PacketGroupingAudience.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/net/minestom/server/adventure/audience/PacketGroupingAudience.java b/src/main/java/net/minestom/server/adventure/audience/PacketGroupingAudience.java index 9f4c4dc0f..9e20b2567 100644 --- a/src/main/java/net/minestom/server/adventure/audience/PacketGroupingAudience.java +++ b/src/main/java/net/minestom/server/adventure/audience/PacketGroupingAudience.java @@ -45,6 +45,10 @@ public interface PacketGroupingAudience extends ForwardingAudience { */ @NotNull Collection getPlayers(); + /** + * Broadcast a ServerPacket to all players of this audience + * @param packet the packet to broadcast + */ default void sendGroupedPacket(ServerPacket packet) { PacketUtils.sendGroupedPacket(this.getPlayers(), packet); } From e69c02f46d597e73b6455a00f04bd7333775b7ec Mon Sep 17 00:00:00 2001 From: BuildTools Date: Fri, 25 Jun 2021 20:41:54 +0800 Subject: [PATCH 5/9] Change other usages of PacketUtils#sendGroupedPacket to use new convenience method --- .../audience/PacketGroupingAudience.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/net/minestom/server/adventure/audience/PacketGroupingAudience.java b/src/main/java/net/minestom/server/adventure/audience/PacketGroupingAudience.java index 9e20b2567..40775bf96 100644 --- a/src/main/java/net/minestom/server/adventure/audience/PacketGroupingAudience.java +++ b/src/main/java/net/minestom/server/adventure/audience/PacketGroupingAudience.java @@ -60,28 +60,28 @@ public interface PacketGroupingAudience extends ForwardingAudience { @Override default void sendActionBar(@NotNull Component message) { - PacketUtils.sendGroupedPacket(this.getPlayers(), new ActionBarPacket(message)); + sendGroupedPacket(new ActionBarPacket(message)); } @Override default void sendPlayerListHeaderAndFooter(@NotNull Component header, @NotNull Component footer) { - PacketUtils.sendGroupedPacket(this.getPlayers(), new PlayerListHeaderAndFooterPacket(header, footer)); + sendGroupedPacket(new PlayerListHeaderAndFooterPacket(header, footer)); } @Override default void showTitle(@NotNull Title title) { - PacketUtils.sendGroupedPacket(this.getPlayers(), new SetTitleTextPacket(title.title())); - PacketUtils.sendGroupedPacket(this.getPlayers(), new SetTitleSubTitlePacket(title.subtitle())); + sendGroupedPacket(new SetTitleTextPacket(title.title())); + sendGroupedPacket(new SetTitleSubTitlePacket(title.subtitle())); } @Override default void clearTitle() { - PacketUtils.sendGroupedPacket(this.getPlayers(), new ClearTitlesPacket()); + sendGroupedPacket(new ClearTitlesPacket()); } @Override default void resetTitle() { - PacketUtils.sendGroupedPacket(this.getPlayers(), new ClearTitlesPacket(true)); + sendGroupedPacket(new ClearTitlesPacket(true)); } @Override @@ -96,13 +96,13 @@ public interface PacketGroupingAudience extends ForwardingAudience { @Override default void playSound(@NotNull Sound sound, double x, double y, double z) { - PacketUtils.sendGroupedPacket(this.getPlayers(), AdventurePacketConvertor.createSoundPacket(sound, x, y, z)); + sendGroupedPacket(AdventurePacketConvertor.createSoundPacket(sound, x, y, z)); } @Override default void playSound(@NotNull Sound sound, Sound.@NotNull Emitter emitter) { if (emitter != Sound.Emitter.self()) { - PacketUtils.sendGroupedPacket(this.getPlayers(), AdventurePacketConvertor.createSoundPacket(sound, emitter)); + sendGroupedPacket(AdventurePacketConvertor.createSoundPacket(sound, emitter)); } else { // if we're playing on self, we need to delegate to each audience member for (Audience audience : this.audiences()) { @@ -113,7 +113,7 @@ public interface PacketGroupingAudience extends ForwardingAudience { @Override default void stopSound(@NotNull SoundStop stop) { - PacketUtils.sendGroupedPacket(this.getPlayers(), AdventurePacketConvertor.createSoundStopPacket(stop)); + sendGroupedPacket(AdventurePacketConvertor.createSoundStopPacket(stop)); } From 76bec5425406ec0d2804a1e8a0b2e6ac2f0ff465 Mon Sep 17 00:00:00 2001 From: TheMode Date: Sat, 26 Jun 2021 00:31:04 +0200 Subject: [PATCH 6/9] Add more TagHandler implementations --- .../minestom/server/data/DataContainer.java | 8 ++++--- .../server/entity/damage/DamageType.java | 21 ++++++++++++++++++- .../net/minestom/server/instance/Chunk.java | 16 +++++++++++++- .../minestom/server/instance/Instance.java | 21 ++++++++++++++++++- .../server/inventory/AbstractInventory.java | 21 ++++++++++++++++++- 5 files changed, 80 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/minestom/server/data/DataContainer.java b/src/main/java/net/minestom/server/data/DataContainer.java index 050712399..772c86f6d 100644 --- a/src/main/java/net/minestom/server/data/DataContainer.java +++ b/src/main/java/net/minestom/server/data/DataContainer.java @@ -19,9 +19,10 @@ public interface DataContainer { * meaning that this will be null if no data has been defined. * * @return the {@link Data} of this container, can be null + * @deprecated use the tag API https://wiki.minestom.com/feature/tags */ - @Nullable - Data getData(); + @Deprecated + @Nullable Data getData(); /** * Sets the {@link Data} of this container. @@ -30,7 +31,8 @@ public interface DataContainer { * on your use-case. * * @param data the new {@link Data} of this container, null to remove it + * @deprecated use the tag API https://wiki.minestom.com/feature/tags */ + @Deprecated void setData(@Nullable Data data); - } \ No newline at end of file diff --git a/src/main/java/net/minestom/server/entity/damage/DamageType.java b/src/main/java/net/minestom/server/entity/damage/DamageType.java index e1850622a..f311059f8 100644 --- a/src/main/java/net/minestom/server/entity/damage/DamageType.java +++ b/src/main/java/net/minestom/server/entity/damage/DamageType.java @@ -8,8 +8,11 @@ import net.minestom.server.entity.Entity; import net.minestom.server.entity.LivingEntity; import net.minestom.server.entity.Player; import net.minestom.server.sound.SoundEvent; +import net.minestom.server.tag.Tag; +import net.minestom.server.tag.TagHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jglrxavpok.hephaistos.nbt.NBTCompound; /** * Represents a type of damage, required when calling {@link LivingEntity#damage(DamageType, float)} @@ -19,7 +22,7 @@ import org.jetbrains.annotations.Nullable; * Be aware that this class implements {@link DataContainer} * so you can add your own data to an already existing damage type without any wrapper. */ -public class DamageType implements DataContainer { +public class DamageType implements TagHandler, DataContainer { public static final DamageType VOID = new DamageType("attack.outOfWorld"); public static final DamageType GRAVITY = new DamageType("attack.fall"); @@ -30,6 +33,8 @@ public class DamageType implements DataContainer { } }; private final String identifier; + private final Object nbtLock = new Object(); + private final NBTCompound nbt = new NBTCompound(); private Data data; /** @@ -159,4 +164,18 @@ public class DamageType implements DataContainer { public void setData(Data data) { this.data = data; } + + @Override + public @Nullable T getTag(@NotNull Tag tag) { + synchronized (nbtLock) { + return tag.read(nbt); + } + } + + @Override + public void setTag(@NotNull Tag tag, @Nullable T value) { + synchronized (nbtLock) { + tag.write(nbt, value); + } + } } diff --git a/src/main/java/net/minestom/server/instance/Chunk.java b/src/main/java/net/minestom/server/instance/Chunk.java index 18bb9d98c..7d0b0c1cf 100644 --- a/src/main/java/net/minestom/server/instance/Chunk.java +++ b/src/main/java/net/minestom/server/instance/Chunk.java @@ -16,6 +16,8 @@ import net.minestom.server.instance.block.CustomBlock; import net.minestom.server.network.packet.server.play.ChunkDataPacket; import net.minestom.server.network.packet.server.play.UpdateLightPacket; import net.minestom.server.network.player.PlayerConnection; +import net.minestom.server.tag.Tag; +import net.minestom.server.tag.TagHandler; import net.minestom.server.utils.PacketUtils; import net.minestom.server.utils.Position; import net.minestom.server.utils.binary.BinaryReader; @@ -27,6 +29,7 @@ import net.minestom.server.world.biomes.Biome; import net.minestom.server.world.biomes.BiomeManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jglrxavpok.hephaistos.nbt.NBTCompound; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -47,7 +50,7 @@ import java.util.concurrent.ConcurrentHashMap; * You generally want to avoid storing references of this object as this could lead to a huge memory leak, * you should store the chunk coordinates instead. */ -public abstract class Chunk implements Viewable, Tickable, DataContainer { +public abstract class Chunk implements Viewable, Tickable, TagHandler, DataContainer { protected static final BlockManager BLOCK_MANAGER = MinecraftServer.getBlockManager(); protected static final BiomeManager BIOME_MANAGER = MinecraftServer.getBiomeManager(); @@ -75,6 +78,7 @@ public abstract class Chunk implements Viewable, Tickable, DataContainer { protected PFColumnarSpace columnarSpace; // Data + private final NBTCompound nbt = new NBTCompound(); protected Data data; public Chunk(@NotNull Instance instance, @Nullable Biome[] biomes, int chunkX, int chunkZ, boolean shouldGenerate) { @@ -480,6 +484,16 @@ public abstract class Chunk implements Viewable, Tickable, DataContainer { return unmodifiableViewers; } + @Override + public @Nullable T getTag(@NotNull Tag tag) { + return tag.read(nbt); + } + + @Override + public void setTag(@NotNull Tag tag, @Nullable T value) { + tag.write(nbt, value); + } + @Nullable @Override public Data getData() { diff --git a/src/main/java/net/minestom/server/instance/Instance.java b/src/main/java/net/minestom/server/instance/Instance.java index d0f9352b3..cae571ff2 100644 --- a/src/main/java/net/minestom/server/instance/Instance.java +++ b/src/main/java/net/minestom/server/instance/Instance.java @@ -28,6 +28,8 @@ import net.minestom.server.instance.block.CustomBlock; import net.minestom.server.network.packet.server.play.BlockActionPacket; import net.minestom.server.network.packet.server.play.TimeUpdatePacket; import net.minestom.server.storage.StorageLocation; +import net.minestom.server.tag.Tag; +import net.minestom.server.tag.TagHandler; import net.minestom.server.thread.ThreadProvider; import net.minestom.server.utils.BlockPosition; import net.minestom.server.utils.PacketUtils; @@ -43,6 +45,7 @@ import net.minestom.server.world.DimensionType; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jglrxavpok.hephaistos.nbt.NBTCompound; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -60,7 +63,7 @@ import java.util.function.Consumer; * you need to be sure to signal the {@link UpdateManager} of the changes using * {@link UpdateManager#signalChunkLoad(Chunk)} and {@link UpdateManager#signalChunkUnload(Chunk)}. */ -public abstract class Instance implements BlockModifier, Tickable, EventHandler, DataContainer, PacketGroupingAudience { +public abstract class Instance implements BlockModifier, Tickable, TagHandler, PacketGroupingAudience, EventHandler, DataContainer { protected static final BlockManager BLOCK_MANAGER = MinecraftServer.getBlockManager(); protected static final UpdateManager UPDATE_MANAGER = MinecraftServer.getUpdateManager(); @@ -101,6 +104,8 @@ public abstract class Instance implements BlockModifier, Tickable, EventHandler< protected final Queue> nextTick = new ConcurrentLinkedQueue<>(); // instance custom data + private final Object nbtLock = new Object(); + private final NBTCompound nbt = new NBTCompound(); private Data data; // the explosion supplier @@ -1061,6 +1066,20 @@ public abstract class Instance implements BlockModifier, Tickable, EventHandler< this.worldBorder.update(); } + @Override + public @Nullable T getTag(@NotNull Tag tag) { + synchronized (nbtLock) { + return tag.read(nbt); + } + } + + @Override + public void setTag(@NotNull Tag tag, @Nullable T value) { + synchronized (nbtLock) { + tag.write(nbt, value); + } + } + /** * Creates an explosion at the given position with the given strength. * The algorithm used to compute damages is provided by {@link #getExplosionSupplier()}. diff --git a/src/main/java/net/minestom/server/inventory/AbstractInventory.java b/src/main/java/net/minestom/server/inventory/AbstractInventory.java index b4cc7a641..bb5112dde 100644 --- a/src/main/java/net/minestom/server/inventory/AbstractInventory.java +++ b/src/main/java/net/minestom/server/inventory/AbstractInventory.java @@ -5,10 +5,13 @@ import net.minestom.server.data.DataContainer; import net.minestom.server.inventory.click.InventoryClickProcessor; import net.minestom.server.inventory.condition.InventoryCondition; import net.minestom.server.item.ItemStack; +import net.minestom.server.tag.Tag; +import net.minestom.server.tag.TagHandler; import net.minestom.server.utils.MathUtils; import net.minestom.server.utils.validate.Check; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jglrxavpok.hephaistos.nbt.NBTCompound; import java.util.ArrayList; import java.util.Arrays; @@ -19,7 +22,7 @@ import java.util.function.UnaryOperator; /** * Represents an inventory where items can be modified/retrieved. */ -public abstract class AbstractInventory implements InventoryClickHandler, DataContainer { +public abstract class AbstractInventory implements InventoryClickHandler, TagHandler, DataContainer { private final int size; protected final ItemStack[] itemStacks; @@ -29,6 +32,8 @@ public abstract class AbstractInventory implements InventoryClickHandler, DataCo // the click processor which process all the clicks in the inventory protected final InventoryClickProcessor clickProcessor = new InventoryClickProcessor(); + private final Object nbtLock = new Object(); + private final NBTCompound nbt = new NBTCompound(); private Data data; protected AbstractInventory(int size) { @@ -210,6 +215,20 @@ public abstract class AbstractInventory implements InventoryClickHandler, DataCo } } + @Override + public @Nullable T getTag(@NotNull Tag tag) { + synchronized (nbtLock) { + return tag.read(nbt); + } + } + + @Override + public void setTag(@NotNull Tag tag, @Nullable T value) { + synchronized (nbtLock) { + tag.write(nbt, value); + } + } + @Override public @Nullable Data getData() { return data; From bf446257308cf87d671c9244e14eea959682699c Mon Sep 17 00:00:00 2001 From: TheMode Date: Sat, 26 Jun 2021 05:08:33 +0200 Subject: [PATCH 7/9] Add experimental tags --- .../net/minestom/server/item/ItemMeta.java | 7 +--- .../java/net/minestom/server/tag/Tag.java | 41 +++++++++++++++---- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/src/main/java/net/minestom/server/item/ItemMeta.java b/src/main/java/net/minestom/server/item/ItemMeta.java index 862e9709e..443e15bb3 100644 --- a/src/main/java/net/minestom/server/item/ItemMeta.java +++ b/src/main/java/net/minestom/server/item/ItemMeta.java @@ -164,12 +164,7 @@ public class ItemMeta implements TagReadable, Writeable { @Deprecated @Contract(pure = true) public T getOrDefault(@NotNull Tag tag, @Nullable T defaultValue) { - var key = tag.getKey(); - if (nbt.containsKey(key)) { - return tag.read(toNBT()); - } else { - return defaultValue; - } + return tag.defaultValue(defaultValue).read(toNBT()); } /** diff --git a/src/main/java/net/minestom/server/tag/Tag.java b/src/main/java/net/minestom/server/tag/Tag.java index 641952cbe..5af525a88 100644 --- a/src/main/java/net/minestom/server/tag/Tag.java +++ b/src/main/java/net/minestom/server/tag/Tag.java @@ -7,6 +7,7 @@ import org.jetbrains.annotations.Nullable; import org.jglrxavpok.hephaistos.nbt.NBT; import org.jglrxavpok.hephaistos.nbt.NBTCompound; +import java.util.Objects; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.Supplier; @@ -21,7 +22,21 @@ import java.util.function.Supplier; @ApiStatus.NonExtendable public class Tag { - private static final String EMPTY_KEY = ""; + /** + * Reads the snbt of the tags holder. + *

+ * Writing is not supported. + */ + @ApiStatus.Experimental + public static final Tag SNBT = new Tag<>(null, NBTCompound::toSNBT, null, null); + + /** + * Reads the complete tag holder compound. + *

+ * Writing is not supported. + */ + @ApiStatus.Experimental + public static final Tag NBT = new Tag<>(null, NBTCompound::deepClone, null, null); private final String key; private final Function readFunction; @@ -29,23 +44,31 @@ public class Tag { private final Supplier defaultValue; - protected Tag(@NotNull String key, + protected Tag(@Nullable String key, @NotNull Function readFunction, - @NotNull BiConsumer writeConsumer, + @Nullable BiConsumer writeConsumer, @Nullable Supplier defaultValue) { this.key = key; this.readFunction = readFunction; - this.writeConsumer = writeConsumer; + this.writeConsumer = Objects.requireNonNullElse(writeConsumer, (compound, t) -> { + }); this.defaultValue = defaultValue; } - protected Tag(@NotNull String key, + protected Tag(@Nullable String key, @NotNull Function readFunction, - @NotNull BiConsumer writeConsumer) { + @Nullable BiConsumer writeConsumer) { this(key, readFunction, writeConsumer, null); } - public @NotNull String getKey() { + /** + * Returns the key used to navigate inside the holder nbt. + *

+ * Can be null if unused (e.g. {@link #View(TagSerializer)}, {@link #SNBT} and {@link #NBT}). + * + * @return the tag key + */ + public @Nullable String getKey() { return key; } @@ -96,7 +119,7 @@ public class Tag { } public void write(@NotNull NBTCompound nbtCompound, @Nullable T value) { - if (value != null || key.equals(EMPTY_KEY)) { + if (key == null || value != null) { this.writeConsumer.accept(nbtCompound, value); } else { nbtCompound.removeTag(key); @@ -208,7 +231,7 @@ public class Tag { } public static @NotNull Tag View(@NotNull TagSerializer serializer) { - return new Tag<>(EMPTY_KEY, + return new Tag<>(null, nbtCompound -> serializer.read(TagReadable.fromCompound(nbtCompound)), (nbtCompound, value) -> serializer.write(TagWritable.fromCompound(nbtCompound), value)); } From 5ddfff22f2a14f6188a0d96b16d6458070bf2606 Mon Sep 17 00:00:00 2001 From: TheMode Date: Sat, 26 Jun 2021 19:44:35 +0200 Subject: [PATCH 8/9] Add Tag#NBT write support --- src/main/java/net/minestom/server/tag/Tag.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/minestom/server/tag/Tag.java b/src/main/java/net/minestom/server/tag/Tag.java index 5af525a88..fcea2241d 100644 --- a/src/main/java/net/minestom/server/tag/Tag.java +++ b/src/main/java/net/minestom/server/tag/Tag.java @@ -33,10 +33,13 @@ public class Tag { /** * Reads the complete tag holder compound. *

- * Writing is not supported. + * Writing will override all tags. Proceed with caution. */ @ApiStatus.Experimental - public static final Tag NBT = new Tag<>(null, NBTCompound::deepClone, null, null); + public static final Tag NBT = new Tag<>(null, NBTCompound::deepClone, (original, updated) -> { + original.clear(); + updated.getKeys().forEach(s -> original.set(s, Objects.requireNonNull(updated.get(s)))); + }, null); private final String key; private final Function readFunction; From fbf8ddefcec2e71f156ca23b4a3154346f13c968 Mon Sep 17 00:00:00 2001 From: TheMode Date: Sat, 26 Jun 2021 19:52:35 +0200 Subject: [PATCH 9/9] Add Tag#SNBT write support --- .../java/net/minestom/server/tag/Tag.java | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/minestom/server/tag/Tag.java b/src/main/java/net/minestom/server/tag/Tag.java index fcea2241d..7b03a175b 100644 --- a/src/main/java/net/minestom/server/tag/Tag.java +++ b/src/main/java/net/minestom/server/tag/Tag.java @@ -6,7 +6,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jglrxavpok.hephaistos.nbt.NBT; import org.jglrxavpok.hephaistos.nbt.NBTCompound; +import org.jglrxavpok.hephaistos.nbt.NBTException; +import org.jglrxavpok.hephaistos.nbt.SNBTParser; +import java.io.StringReader; import java.util.Objects; import java.util.function.BiConsumer; import java.util.function.Function; @@ -23,15 +26,27 @@ import java.util.function.Supplier; public class Tag { /** - * Reads the snbt of the tags holder. + * Handles the snbt of the tag holder. *

- * Writing is not supported. + * Writing will override all tags. Proceed with caution. */ @ApiStatus.Experimental - public static final Tag SNBT = new Tag<>(null, NBTCompound::toSNBT, null, null); + public static final Tag SNBT = new Tag<>(null, NBTCompound::toSNBT, (original, snbt) -> { + try { + final var updated = new SNBTParser(new StringReader(snbt)).parse(); + if (!(updated instanceof NBTCompound)) + throw new IllegalArgumentException("'" + snbt + "' is not a compound!"); + NBTCompound updatedCompound = (NBTCompound) updated; + original.clear(); + updatedCompound.getKeys().forEach(s -> + original.set(s, Objects.requireNonNull(updatedCompound.get(s)))); + } catch (NBTException e) { + e.printStackTrace(); + } + }, null); /** - * Reads the complete tag holder compound. + * Handles the complete tag holder compound. *

* Writing will override all tags. Proceed with caution. */