Add extractClientNbt utils

Signed-off-by: TheMode <themode@outlook.fr>
This commit is contained in:
TheMode 2022-01-22 05:46:26 +01:00
parent d3fa4c810f
commit be1495a385
3 changed files with 83 additions and 27 deletions

View File

@ -2,19 +2,16 @@ package net.minestom.server.network.packet.server.play.data;
import net.minestom.server.coordinate.Point;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.BlockHandler;
import net.minestom.server.tag.Tag;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.utils.binary.Writeable;
import net.minestom.server.utils.block.BlockUtils;
import net.minestom.server.utils.chunk.ChunkUtils;
import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
public record ChunkData(@NotNull NBTCompound heightmaps, byte @NotNull [] data,
@ -47,33 +44,13 @@ public record ChunkData(@NotNull NBTCompound heightmaps, byte @NotNull [] data,
final var registry = block.registry();
final Point point = ChunkUtils.getBlockPosition(index, 0, 0);
writer.writeByte((byte) ((point.blockX() & 15) << 4 | point.blockZ() & 15)); // xz
writer.writeShort((short) point.blockY()); // y
writer.writeVarInt(registry.blockEntityId());
NBTCompound resultNbt;
// Append handler tags
final BlockHandler handler = block.handler();
if (handler != null) {
resultNbt = NBT.Compound(nbt -> {
final NBTCompound blockNbt = Objects.requireNonNullElseGet(block.nbt(), NBTCompound::new);
for (Tag<?> tag : handler.getBlockEntityTags()) {
final var value = tag.read(blockNbt);
if (value != null) {
// Tag is present and valid
tag.writeUnsafe(nbt, value);
}
}
});
} else {
// Complete nbt shall be sent if the block has no handler
// Necessary to support all vanilla blocks
final NBTCompound blockNbt = block.nbt();
resultNbt = blockNbt == null ? new NBTCompound() : blockNbt;
}
writer.writeNBT("", resultNbt); // block nbt
final NBTCompound nbt = BlockUtils.extractClientNbt(block);
assert nbt != null;
writer.writeNBT("", nbt); // block nbt
}
}

View File

@ -3,10 +3,17 @@ package net.minestom.server.utils.block;
import net.minestom.server.coordinate.Point;
import net.minestom.server.instance.Instance;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.BlockHandler;
import net.minestom.server.tag.Tag;
import net.minestom.server.utils.ArrayUtils;
import net.minestom.server.utils.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import java.util.Map;
import java.util.Objects;
public class BlockUtils {
@ -83,4 +90,26 @@ public class BlockUtils {
}
return ArrayUtils.toMap(keys, values, entryCount);
}
public static @Nullable NBTCompound extractClientNbt(@NotNull Block block) {
if (!block.registry().isBlockEntity()) return null;
// Append handler tags
final BlockHandler handler = block.handler();
final NBTCompound blockNbt = Objects.requireNonNullElseGet(block.nbt(), NBTCompound::new);
if (handler != null) {
// Extract explicitly defined tags and keep the rest server-side
return NBT.Compound(nbt -> {
for (Tag<?> tag : handler.getBlockEntityTags()) {
final var value = tag.read(blockNbt);
if (value != null) {
// Tag is present and valid
tag.writeUnsafe(nbt, value);
}
}
});
}
// Complete nbt shall be sent if the block has no handler
// Necessary to support all vanilla blocks
return blockNbt;
}
}

View File

@ -0,0 +1,50 @@
package net.minestom.server.instance;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.BlockHandler;
import net.minestom.server.tag.Tag;
import net.minestom.server.utils.NamespaceID;
import net.minestom.server.utils.block.BlockUtils;
import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.junit.jupiter.api.Test;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
public class BlockClientNbtTest {
@Test
public void basic() {
assertNull(BlockUtils.extractClientNbt(Block.STONE));
assertNull(BlockUtils.extractClientNbt(Block.GRASS));
assertEquals(NBTCompound.EMPTY, BlockUtils.extractClientNbt(Block.CHEST));
var nbt = NBT.Compound(Map.of("test", NBT.String("test")));
assertEquals(nbt, BlockUtils.extractClientNbt(Block.CHEST.withNbt(nbt)));
}
@Test
public void handler() {
var handler = new BlockHandler() {
@Override
public @NotNull Collection<Tag<?>> getBlockEntityTags() {
return List.of(Tag.String("test"));
}
@Override
public @NotNull NamespaceID getNamespaceId() {
return NamespaceID.from("minestom:test");
}
};
var nbt = NBT.Compound(Map.of("test", NBT.String("test")));
assertNull(BlockUtils.extractClientNbt(Block.STONE.withNbt(nbt).withHandler(handler)));
assertEquals(nbt, BlockUtils.extractClientNbt(Block.CHEST.withNbt(nbt).withHandler(handler)));
}
}