Port to Hephaistos v2 (#424)

This commit is contained in:
Xavier Niochaut 2021-12-13 16:41:30 +01:00 committed by TheMode
parent f43ffd64cb
commit 9ab4277502
53 changed files with 583 additions and 450 deletions

View File

@ -152,13 +152,13 @@ dependencies {
api "org.jetbrains.kotlin:kotlin-reflect:${project.kotlinVersion}" api "org.jetbrains.kotlin:kotlin-reflect:${project.kotlinVersion}"
// NBT parsing/manipulation/saving // NBT parsing/manipulation/saving
api("com.github.jglrxavpok:Hephaistos:${project.hephaistosVersion}") api("io.github.jglrxavpok.hephaistos:common:${project.hephaistosVersion}")
api("com.github.jglrxavpok:Hephaistos:${project.hephaistosVersion}:gson") api("io.github.jglrxavpok.hephaistos:gson:${project.hephaistosVersion}")
api("com.github.jglrxavpok:Hephaistos:${project.hephaistosVersion}") { /* api("io.github.jglrxavpok.hephaistos:common:${project.hephaistosVersion}") {
capabilities { capabilities {
requireCapability("org.jglrxavpok.nbt:Hephaistos-gson") requireCapability("io.github.jglrxavpok.hephaistos:Hephaistos-gson")
} }
} }*/
api "com.github.Minestom:DependencyGetter:v1.0.1" api "com.github.Minestom:DependencyGetter:v1.0.1"
implementation 'com.github.Minestom:MinestomDataGenerator:801b8007cf' implementation 'com.github.Minestom:MinestomDataGenerator:801b8007cf'

View File

@ -3,6 +3,6 @@ mcVersion = 1.17
asmVersion=9.2 asmVersion=9.2
mixinVersion=0.8.4 mixinVersion=0.8.4
hephaistosVersion=v1.1.8 hephaistosVersion=2.3.0
kotlinVersion=1.5.31 kotlinVersion=1.5.31
adventureVersion=4.9.3 adventureVersion=4.9.3

View File

@ -11,7 +11,7 @@ import java.util.Objects;
import org.jglrxavpok.hephaistos.nbt.NBT; import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTException; import org.jglrxavpok.hephaistos.nbt.NBTException;
import org.jglrxavpok.hephaistos.nbt.SNBTParser; import org.jglrxavpok.hephaistos.parser.SNBTParser;
/** /**
* Adventure related constants, etc. * Adventure related constants, etc.

View File

@ -16,6 +16,7 @@ import org.jglrxavpok.hephaistos.nbt.NBTException;
import java.io.IOException; import java.io.IOException;
import java.util.Objects; import java.util.Objects;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
final class NBTLegacyHoverEventSerializer implements LegacyHoverEventSerializer { final class NBTLegacyHoverEventSerializer implements LegacyHoverEventSerializer {
static final NBTLegacyHoverEventSerializer INSTANCE = new NBTLegacyHoverEventSerializer(); static final NBTLegacyHoverEventSerializer INSTANCE = new NBTLegacyHoverEventSerializer();
@ -66,17 +67,23 @@ final class NBTLegacyHoverEventSerializer implements LegacyHoverEventSerializer
@Override @Override
public @NotNull Component serializeShowItem(HoverEvent.@NotNull ShowItem input) throws IOException { public @NotNull Component serializeShowItem(HoverEvent.@NotNull ShowItem input) throws IOException {
final NBTCompound tag = new NBTCompound(); AtomicReference<NBTException> exception = new AtomicReference<>(null);
tag.setString(ITEM_TYPE, input.item().asString()); final NBTCompound tag = NBT.Compound(t -> {
tag.setByte(ITEM_COUNT, (byte) input.count()); t.setString(ITEM_TYPE, input.item().asString());
t.setByte(ITEM_COUNT, (byte) input.count());
final BinaryTagHolder nbt = input.nbt(); final BinaryTagHolder nbt = input.nbt();
if (nbt != null) { if (nbt != null) {
try { try {
tag.set(ITEM_TAG, nbt.get(MinestomAdventure.NBT_CODEC)); t.set(ITEM_TAG, nbt.get(MinestomAdventure.NBT_CODEC));
} catch (NBTException e) { } catch (NBTException e) {
throw new IOException(e); exception.set(e);
}
} }
});
if(exception.get() != null) {
throw new IOException(exception.get());
} }
return Component.text(MinestomAdventure.NBT_CODEC.encode(tag)); return Component.text(MinestomAdventure.NBT_CODEC.encode(tag));
@ -84,14 +91,15 @@ final class NBTLegacyHoverEventSerializer implements LegacyHoverEventSerializer
@Override @Override
public @NotNull Component serializeShowEntity(HoverEvent.@NotNull ShowEntity input, Codec.Encoder<Component, String, ? extends RuntimeException> componentEncoder) throws IOException { public @NotNull Component serializeShowEntity(HoverEvent.@NotNull ShowEntity input, Codec.Encoder<Component, String, ? extends RuntimeException> componentEncoder) throws IOException {
final NBTCompound tag = new NBTCompound(); final NBTCompound tag = NBT.Compound(t -> {
tag.setString(ENTITY_ID, input.id().toString()); t.setString(ENTITY_ID, input.id().toString());
tag.setString(ENTITY_TYPE, input.type().asString()); t.setString(ENTITY_TYPE, input.type().asString());
final Component name = input.name(); final Component name = input.name();
if (name != null) { if (name != null) {
tag.setString(ENTITY_NAME, componentEncoder.encode(name)); t.setString(ENTITY_NAME, componentEncoder.encode(name));
} }
});
return Component.text(MinestomAdventure.NBT_CODEC.encode(tag)); return Component.text(MinestomAdventure.NBT_CODEC.encode(tag));
} }

View File

@ -9,6 +9,7 @@ import net.minestom.server.tag.Tag;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.mutable.MutableNBTCompound;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -23,7 +24,7 @@ public class ConsoleSender implements CommandSender {
private static final Logger LOGGER = LoggerFactory.getLogger(ConsoleSender.class); private static final Logger LOGGER = LoggerFactory.getLogger(ConsoleSender.class);
private final Set<Permission> permissions = new CopyOnWriteArraySet<>(); private final Set<Permission> permissions = new CopyOnWriteArraySet<>();
private final NBTCompound nbtCompound = new NBTCompound(); private final MutableNBTCompound nbtCompound = new MutableNBTCompound();
@Override @Override
public void sendMessage(@NotNull String message) { public void sendMessage(@NotNull String message) {

View File

@ -7,6 +7,7 @@ import net.minestom.server.tag.Tag;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.mutable.MutableNBTCompound;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
@ -22,7 +23,7 @@ import java.util.Set;
public class ServerSender implements CommandSender { public class ServerSender implements CommandSender {
private final Set<Permission> permissions = Collections.unmodifiableSet(new HashSet<>()); private final Set<Permission> permissions = Collections.unmodifiableSet(new HashSet<>());
private final NBTCompound nbtCompound = new NBTCompound(); private final MutableNBTCompound nbtCompound = new MutableNBTCompound();
@NotNull @NotNull
@Override @Override

View File

@ -9,7 +9,7 @@ import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.NBTException; import org.jglrxavpok.hephaistos.nbt.NBTException;
import org.jglrxavpok.hephaistos.nbt.SNBTParser; import org.jglrxavpok.hephaistos.parser.SNBTParser;
import java.io.StringReader; import java.io.StringReader;

View File

@ -8,7 +8,7 @@ import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBT; import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.NBTException; import org.jglrxavpok.hephaistos.nbt.NBTException;
import org.jglrxavpok.hephaistos.nbt.SNBTParser; import org.jglrxavpok.hephaistos.parser.SNBTParser;
import java.io.StringReader; import java.io.StringReader;

View File

@ -7,7 +7,7 @@ import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBT; import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTException; import org.jglrxavpok.hephaistos.nbt.NBTException;
import org.jglrxavpok.hephaistos.nbt.SNBTParser; import org.jglrxavpok.hephaistos.parser.SNBTParser;
import java.io.StringReader; import java.io.StringReader;

View File

@ -51,6 +51,7 @@ import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.mutable.MutableNBTCompound;
import java.time.Duration; import java.time.Duration;
import java.time.temporal.TemporalUnit; import java.time.temporal.TemporalUnit;
@ -143,7 +144,7 @@ public class Entity implements Viewable, Tickable, TagHandler, PermissionHandler
this instanceof Player player ? entity -> entity.viewEngine.viewableOption.addition.accept(player) : null, this instanceof Player player ? entity -> entity.viewEngine.viewableOption.addition.accept(player) : null,
this instanceof Player player ? entity -> entity.viewEngine.viewableOption.removal.accept(player) : null); this instanceof Player player ? entity -> entity.viewEngine.viewableOption.removal.accept(player) : null);
protected final Set<Player> viewers = viewEngine.asSet(); protected final Set<Player> viewers = viewEngine.asSet();
private final NBTCompound nbtCompound = new NBTCompound(); private final MutableNBTCompound nbtCompound = new MutableNBTCompound();
private final Set<Permission> permissions = new CopyOnWriteArraySet<>(); private final Set<Permission> permissions = new CopyOnWriteArraySet<>();
protected UUID uuid; protected UUID uuid;

View File

@ -161,7 +161,7 @@ public class Metadata {
EMPTY_VALUES.set(TYPE_DIRECTION, Direction(Direction.DOWN)); EMPTY_VALUES.set(TYPE_DIRECTION, Direction(Direction.DOWN));
EMPTY_VALUES.set(TYPE_OPTUUID, OptUUID(null)); EMPTY_VALUES.set(TYPE_OPTUUID, OptUUID(null));
EMPTY_VALUES.set(TYPE_OPTBLOCKID, OptBlockID(null)); EMPTY_VALUES.set(TYPE_OPTBLOCKID, OptBlockID(null));
EMPTY_VALUES.set(TYPE_NBT, NBT(new NBTEnd())); EMPTY_VALUES.set(TYPE_NBT, NBT(NBTEnd.INSTANCE));
//EMPTY_VALUES.set(TYPE_PARTICLE -> throw new UnsupportedOperationException(); //EMPTY_VALUES.set(TYPE_PARTICLE -> throw new UnsupportedOperationException();
EMPTY_VALUES.set(TYPE_VILLAGERDATA, VillagerData(0, 0, 0)); EMPTY_VALUES.set(TYPE_VILLAGERDATA, VillagerData(0, 0, 0));
EMPTY_VALUES.set(TYPE_OPTVARINT, OptVarInt(null)); EMPTY_VALUES.set(TYPE_OPTVARINT, OptVarInt(null));

View File

@ -84,6 +84,7 @@ import org.jctools.queues.MpscUnboundedXaddArrayQueue;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -237,11 +238,12 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
public void UNSAFE_init(@NotNull Instance spawnInstance) { public void UNSAFE_init(@NotNull Instance spawnInstance) {
this.dimensionType = spawnInstance.getDimensionType(); this.dimensionType = spawnInstance.getDimensionType();
NBTCompound nbt = new NBTCompound(); NBTCompound nbt = NBT.Compound(n -> {
NBTCompound dimensions = MinecraftServer.getDimensionTypeManager().toNBT(); NBTCompound dimensions = MinecraftServer.getDimensionTypeManager().toNBT();
NBTCompound biomes = MinecraftServer.getBiomeManager().toNBT(); NBTCompound biomes = MinecraftServer.getBiomeManager().toNBT();
nbt.set("minecraft:dimension_type", dimensions); n.set("minecraft:dimension_type", dimensions);
nbt.set("minecraft:worldgen/biome", biomes); n.set("minecraft:worldgen/biome", biomes);
});
final JoinGamePacket joinGamePacket = new JoinGamePacket(getEntityId(), gameMode.isHardcore(), gameMode, null, final JoinGamePacket joinGamePacket = new JoinGamePacket(getEntityId(), gameMode.isHardcore(), gameMode, null,
List.of("minestom:world"), nbt, dimensionType.toNBT(), dimensionType.getName().asString(), List.of("minestom:world"), nbt, dimensionType.toNBT(), dimensionType.getName().asString(),

View File

@ -10,6 +10,7 @@ import net.minestom.server.tag.TagHandler;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.mutable.MutableNBTCompound;
/** /**
* Represents a type of damage, required when calling {@link LivingEntity#damage(DamageType, float)} * Represents a type of damage, required when calling {@link LivingEntity#damage(DamageType, float)}
@ -29,7 +30,7 @@ public class DamageType implements TagHandler {
}; };
private final String identifier; private final String identifier;
private final Object nbtLock = new Object(); private final Object nbtLock = new Object();
private final NBTCompound nbt = new NBTCompound(); private final MutableNBTCompound nbt = new MutableNBTCompound();
/** /**
* Creates a new damage type. * Creates a new damage type.

View File

@ -470,7 +470,7 @@ public class ExtensionManager {
// While there are entries with no more elements (no more dependencies) // While there are entries with no more elements (no more dependencies)
while (!( while (!(
loadableExtensions = dependencyMap.entrySet().stream().filter(entry -> isLoaded(entry.getValue())).collect(Collectors.toList()) loadableExtensions = dependencyMap.entrySet().stream().filter(entry -> isLoaded(entry.getValue())).toList()
).isEmpty() ).isEmpty()
) { ) {
// Get all "loadable" (not actually being loaded!) extensions and put them in the sorted list. // Get all "loadable" (not actually being loaded!) extensions and put them in the sorted list.

View File

@ -6,6 +6,7 @@ import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.BlockHandler; import net.minestom.server.instance.block.BlockHandler;
import net.minestom.server.instance.block.BlockManager; import net.minestom.server.instance.block.BlockManager;
import net.minestom.server.tag.Tag; import net.minestom.server.tag.Tag;
import net.minestom.server.utils.NamespaceID;
import net.minestom.server.utils.async.AsyncUtils; import net.minestom.server.utils.async.AsyncUtils;
import net.minestom.server.world.biomes.Biome; import net.minestom.server.world.biomes.Biome;
import net.minestom.server.world.biomes.BiomeManager; import net.minestom.server.world.biomes.BiomeManager;
@ -13,6 +14,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.mca.*; import org.jglrxavpok.hephaistos.mca.*;
import org.jglrxavpok.hephaistos.nbt.*; import org.jglrxavpok.hephaistos.nbt.*;
import org.jglrxavpok.hephaistos.nbt.mutable.MutableNBTCompound;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -22,8 +24,7 @@ import java.io.RandomAccessFile;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.util.Map; import java.util.*;
import java.util.Objects;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -87,20 +88,31 @@ public class AnvilLoader implements IChunkLoader {
return CompletableFuture.completedFuture(null); return CompletableFuture.completedFuture(null);
Chunk chunk = new DynamicChunk(instance, chunkX, chunkZ); Chunk chunk = new DynamicChunk(instance, chunkX, chunkZ);
// TODO Biomes // TODO: Parallelize block, block entities and biome loading
if (fileChunk.getGenerationStatus().compareTo(ChunkColumn.GenerationStatus.Biomes) > 0) { if (fileChunk.getGenerationStatus().compareTo(ChunkColumn.GenerationStatus.Biomes) > 0) {
final int[] fileChunkBiomes = fileChunk.getBiomes(); HashMap<String, Biome> biomeCache = new HashMap<>();
for (int id : fileChunkBiomes) {
// ((y >> 2) & 63) << 4 | ((z >> 2) & 3) << 2 | ((x >> 2) & 3) for (ChunkSection section : fileChunk.getSections().values()) {
final Biome biome = Objects.requireNonNullElse(BIOME_MANAGER.getById(id), BIOME); for (int y = 0; y < Chunk.CHUNK_SECTION_SIZE; y++) {
chunk.setBiome(0, 0, 0, biome); for (int z = 0; z < Chunk.CHUNK_SIZE_Z; z++) {
for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
int finalX = fileChunk.getX() * Chunk.CHUNK_SIZE_X + x;
int finalZ = fileChunk.getZ() * Chunk.CHUNK_SIZE_Z + z;
int finalY = section.getY() * Chunk.CHUNK_SECTION_SIZE + y;
String biomeName = section.getBiome(x, y, z);
Biome biome = biomeCache.computeIfAbsent(biomeName, n -> Objects.requireNonNullElse(BIOME_MANAGER.getByName(NamespaceID.from(n)), BIOME));
chunk.setBiome(finalX, finalY, finalZ, biome);
}
}
}
} }
} }
// Blocks // Blocks
loadBlocks(chunk, fileChunk); loadBlocks(chunk, fileChunk);
loadTileEntities(chunk, fileChunk); loadTileEntities(chunk, fileChunk);
// Lights // Lights
for (var chunkSection : fileChunk.getSections()) { for (var chunkSection : fileChunk.getSections().values()) {
Section section = chunk.getSection(chunkSection.getY()); Section section = chunk.getSection(chunkSection.getY());
section.setSkyLight(chunkSection.getSkyLights()); section.setSkyLight(chunkSection.getSkyLights());
section.setBlockLight(chunkSection.getBlockLights()); section.setBlockLight(chunkSection.getBlockLights());
@ -127,7 +139,7 @@ public class AnvilLoader implements IChunkLoader {
} }
private void loadBlocks(Chunk chunk, ChunkColumn fileChunk) { private void loadBlocks(Chunk chunk, ChunkColumn fileChunk) {
for (var section : fileChunk.getSections()) { for (var section : fileChunk.getSections().values()) {
if (section.getEmpty()) continue; if (section.getEmpty()) continue;
final int yOffset = Chunk.CHUNK_SECTION_SIZE * section.getY(); final int yOffset = Chunk.CHUNK_SECTION_SIZE * section.getY();
for (int x = 0; x < Chunk.CHUNK_SECTION_SIZE; x++) { for (int x = 0; x < Chunk.CHUNK_SECTION_SIZE; x++) {
@ -172,12 +184,15 @@ public class AnvilLoader implements IChunkLoader {
block = block.withHandler(handler); block = block.withHandler(handler);
} }
// Remove anvil tags // Remove anvil tags
te.removeTag("id") MutableNBTCompound mutableCopy = te.toMutableCompound();
.removeTag("x").removeTag("y").removeTag("z") mutableCopy.remove("id");
.removeTag("keepPacked"); mutableCopy.remove("x");
mutableCopy.remove("y");
mutableCopy.remove("z");
mutableCopy.remove("keepPacked");
// Place block // Place block
final var finalBlock = te.getSize() > 0 ? final var finalBlock = mutableCopy.getSize() > 0 ?
block.withNbt(te) : block; block.withNbt(mutableCopy.toCompound()) : block;
loadedChunk.setBlock(x, y, z, finalBlock); loadedChunk.setBlock(x, y, z, finalBlock);
} }
} }
@ -247,7 +262,7 @@ public class AnvilLoader implements IChunkLoader {
} }
private void save(Chunk chunk, ChunkColumn chunkColumn) { private void save(Chunk chunk, ChunkColumn chunkColumn) {
NBTList<NBTCompound> tileEntities = new NBTList<>(NBTTypes.TAG_Compound); List<NBTCompound> tileEntities = new ArrayList<>();
chunkColumn.setGenerationStatus(ChunkColumn.GenerationStatus.Full); chunkColumn.setGenerationStatus(ChunkColumn.GenerationStatus.Full);
for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) { for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
for (int z = 0; z < Chunk.CHUNK_SIZE_Z; z++) { for (int z = 0; z < Chunk.CHUNK_SIZE_Z; z++) {
@ -255,13 +270,15 @@ public class AnvilLoader implements IChunkLoader {
final Block block = chunk.getBlock(x, y, z); final Block block = chunk.getBlock(x, y, z);
// Block // Block
chunkColumn.setBlockState(x, y, z, new BlockState(block.name(), block.properties())); chunkColumn.setBlockState(x, y, z, new BlockState(block.name(), block.properties()));
chunkColumn.setBiome(x, 0, z, chunk.getBiome(x, y, z).id()); chunkColumn.setBiome(x, 0, z, chunk.getBiome(x, y, z).name().asString());
// Tile entity // Tile entity
var nbt = block.nbt();
final BlockHandler handler = block.handler(); final BlockHandler handler = block.handler();
if (nbt != null || handler != null) { var originalNBT = block.nbt();
nbt = Objects.requireNonNullElseGet(nbt, NBTCompound::new); if (originalNBT != null || handler != null) {
MutableNBTCompound nbt = originalNBT != null ?
originalNBT.toMutableCompound() : new MutableNBTCompound();
if (handler != null) { if (handler != null) {
nbt.setString("id", handler.getNamespaceId().asString()); nbt.setString("id", handler.getNamespaceId().asString());
} }
@ -269,12 +286,12 @@ public class AnvilLoader implements IChunkLoader {
nbt.setInt("y", y); nbt.setInt("y", y);
nbt.setInt("z", z + Chunk.CHUNK_SIZE_Z * chunk.getChunkZ()); nbt.setInt("z", z + Chunk.CHUNK_SIZE_Z * chunk.getChunkZ());
nbt.setByte("keepPacked", (byte) 0); nbt.setByte("keepPacked", (byte) 0);
tileEntities.add(nbt); tileEntities.add(nbt.toCompound());
} }
} }
} }
} }
chunkColumn.setTileEntities(tileEntities); chunkColumn.setTileEntities(NBT.List(NBTType.TAG_Compound, tileEntities));
} }
@Override @Override

View File

@ -17,6 +17,7 @@ import net.minestom.server.world.biomes.Biome;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.mutable.MutableNBTCompound;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
@ -55,7 +56,7 @@ public abstract class Chunk implements Block.Getter, Block.Setter, Biome.Getter,
protected PFColumnarSpace columnarSpace; protected PFColumnarSpace columnarSpace;
// Data // Data
private final NBTCompound nbt = new NBTCompound(); private final MutableNBTCompound nbt = new MutableNBTCompound();
public Chunk(@NotNull Instance instance, int chunkX, int chunkZ, boolean shouldGenerate) { public Chunk(@NotNull Instance instance, int chunkX, int chunkZ, boolean shouldGenerate) {
this.identifier = UUID.randomUUID(); this.identifier = UUID.randomUUID();

View File

@ -22,6 +22,7 @@ import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.world.biomes.Biome; import net.minestom.server.world.biomes.Biome;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import java.util.*; import java.util.*;
@ -47,7 +48,7 @@ public class DynamicChunk extends Chunk {
public DynamicChunk(@NotNull Instance instance, int chunkX, int chunkZ) { public DynamicChunk(@NotNull Instance instance, int chunkX, int chunkZ) {
super(instance, chunkX, chunkZ, true); super(instance, chunkX, chunkZ, true);
this.minSection = instance.getDimensionType().getMinY() / CHUNK_SECTION_SIZE; this.minSection = instance.getDimensionType().getMinY() / CHUNK_SECTION_SIZE;
this.maxSection = instance.getDimensionType().getHeight() / CHUNK_SECTION_SIZE; this.maxSection = (instance.getDimensionType().getMinY() + instance.getDimensionType().getHeight()) / CHUNK_SECTION_SIZE;
this.sections = new Section[maxSection - minSection]; this.sections = new Section[maxSection - minSection];
Arrays.setAll(sections, value -> new Section()); Arrays.setAll(sections, value -> new Section());
} }
@ -121,7 +122,7 @@ public class DynamicChunk extends Chunk {
} }
} }
// Retrieve the block from state id // Retrieve the block from state id
final Section section = sections[ChunkUtils.getSectionAt(y) + minSection]; final Section section = sections[ChunkUtils.getSectionAt(y) - minSection];
final int blockStateId = section.blockPalette() final int blockStateId = section.blockPalette()
.get(toChunkRelativeCoordinate(x), y, toChunkRelativeCoordinate(z)); .get(toChunkRelativeCoordinate(x), y, toChunkRelativeCoordinate(z));
if (blockStateId == -1) return Block.AIR; // Section is empty if (blockStateId == -1) return Block.AIR; // Section is empty
@ -130,7 +131,7 @@ public class DynamicChunk extends Chunk {
@Override @Override
public @NotNull Biome getBiome(int x, int y, int z) { public @NotNull Biome getBiome(int x, int y, int z) {
final Section section = sections[ChunkUtils.getSectionAt(y) + minSection]; final Section section = sections[ChunkUtils.getSectionAt(y) - minSection];
final int id = section.biomePalette() final int id = section.biomePalette()
.get(toChunkRelativeCoordinate(x) / 4, y / 4, toChunkRelativeCoordinate(z) / 4); .get(toChunkRelativeCoordinate(x) / 4, y / 4, toChunkRelativeCoordinate(z) / 4);
return MinecraftServer.getBiomeManager().getById(id); return MinecraftServer.getBiomeManager().getById(id);
@ -186,9 +187,9 @@ public class DynamicChunk extends Chunk {
} }
} }
final int bitsForHeight = MathUtils.bitsToRepresent(dimensionHeight); final int bitsForHeight = MathUtils.bitsToRepresent(dimensionHeight);
heightmapsNBT = new NBTCompound() heightmapsNBT = NBT.Compound(Map.of(
.setLongArray("MOTION_BLOCKING", Utils.encodeBlocks(motionBlocking, bitsForHeight)) "MOTION_BLOCKING", NBT.LongArray(Utils.encodeBlocks(motionBlocking, bitsForHeight)),
.setLongArray("WORLD_SURFACE", Utils.encodeBlocks(worldSurface, bitsForHeight)); "WORLD_SURFACE", NBT.LongArray(Utils.encodeBlocks(worldSurface, bitsForHeight))));
} }
// Data // Data
final BinaryWriter writer = new BinaryWriter(); final BinaryWriter writer = new BinaryWriter();

View File

@ -32,6 +32,7 @@ import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.mutable.MutableNBTCompound;
import java.time.Duration; import java.time.Duration;
import java.util.*; import java.util.*;
@ -84,7 +85,7 @@ public abstract class Instance implements Block.Getter, Block.Setter, Tickable,
// instance custom data // instance custom data
private final Object nbtLock = new Object(); private final Object nbtLock = new Object();
private final NBTCompound nbt = new NBTCompound(); private final MutableNBTCompound nbt = new MutableNBTCompound();
// the explosion supplier // the explosion supplier
private ExplosionSupplier explosionSupplier; private ExplosionSupplier explosionSupplier;

View File

@ -9,6 +9,7 @@ import net.minestom.server.utils.block.BlockUtils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.mutable.MutableNBTCompound;
import java.time.Duration; import java.time.Duration;
import java.util.*; import java.util.*;
@ -105,9 +106,9 @@ final class BlockImpl implements Block {
@Override @Override
public @NotNull <T> Block withTag(@NotNull Tag<T> tag, @Nullable T value) { public @NotNull <T> Block withTag(@NotNull Tag<T> tag, @Nullable T value) {
var temporaryNbt = nbt != null ? nbt.deepClone() : new NBTCompound(); var temporaryNbt = new MutableNBTCompound(Objects.requireNonNullElse(nbt, NBTCompound.EMPTY));
tag.write(temporaryNbt, value); tag.write(temporaryNbt, value);
final var finalNbt = temporaryNbt.getSize() > 0 ? NBT_CACHE.get(temporaryNbt, Function.identity()) : null; final var finalNbt = temporaryNbt.getSize() > 0 ? NBT_CACHE.get(temporaryNbt.toCompound(), Function.identity()) : null;
return new BlockImpl(registry, propertyEntry, properties, finalNbt, handler); return new BlockImpl(registry, propertyEntry, properties, finalNbt, handler);
} }

View File

@ -10,6 +10,7 @@ import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.mutable.MutableNBTCompound;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -32,7 +33,7 @@ public sealed abstract class AbstractInventory implements InventoryClickHandler,
protected final InventoryClickProcessor clickProcessor = new InventoryClickProcessor(); protected final InventoryClickProcessor clickProcessor = new InventoryClickProcessor();
private final Object nbtLock = new Object(); private final Object nbtLock = new Object();
private final NBTCompound nbt = new NBTCompound(); private final MutableNBTCompound nbt = new MutableNBTCompound();
protected AbstractInventory(int size) { protected AbstractInventory(int size) {
this.size = size; this.size = size;

View File

@ -119,7 +119,7 @@ public class ItemMeta implements TagReadable, Writeable {
} }
public @NotNull NBTCompound toNBT() { public @NotNull NBTCompound toNBT() {
return nbt.deepClone(); return nbt;
} }
public @NotNull String toSNBT() { public @NotNull String toSNBT() {

View File

@ -12,6 +12,7 @@ import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.*; import org.jglrxavpok.hephaistos.nbt.*;
import org.jglrxavpok.hephaistos.nbt.mutable.MutableNBTCompound;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
@ -75,7 +76,7 @@ public abstract class ItemMetaBuilder implements TagWritable {
final String name = GsonComponentSerializer.gson().serialize(displayName); final String name = GsonComponentSerializer.gson().serialize(displayName);
nbtCompound.setString("Name", name); nbtCompound.setString("Name", name);
} else { } else {
nbtCompound.removeTag("Name"); nbtCompound.remove("Name");
} }
}); });
return this; return this;
@ -85,10 +86,11 @@ public abstract class ItemMetaBuilder implements TagWritable {
public @NotNull ItemMetaBuilder lore(@NotNull List<@NotNull Component> lore) { public @NotNull ItemMetaBuilder lore(@NotNull List<@NotNull Component> lore) {
this.lore = new ArrayList<>(lore); this.lore = new ArrayList<>(lore);
handleCompound("display", nbtCompound -> { handleCompound("display", nbtCompound -> {
final NBTList<NBTString> loreNBT = new NBTList<>(NBTTypes.TAG_String); final NBTList<NBTString> loreNBT = NBT.List(NBTType.TAG_String,
for (Component line : lore) { lore.stream()
loreNBT.add(new NBTString(GsonComponentSerializer.gson().serialize(line))); .map(line -> new NBTString(GsonComponentSerializer.gson().serialize(line)))
} .toList()
);
nbtCompound.set("Lore", loreNBT); nbtCompound.set("Lore", loreNBT);
}); });
return this; return this;
@ -104,8 +106,9 @@ public abstract class ItemMetaBuilder implements TagWritable {
public @NotNull ItemMetaBuilder enchantments(@NotNull Map<Enchantment, Short> enchantments) { public @NotNull ItemMetaBuilder enchantments(@NotNull Map<Enchantment, Short> enchantments) {
this.enchantmentMap = new HashMap<>(enchantments); this.enchantmentMap = new HashMap<>(enchantments);
handleMap(enchantmentMap, "Enchantments", () -> { handleMap(enchantmentMap, "Enchantments", () -> {
NBTUtils.writeEnchant(nbt, "Enchantments", enchantmentMap); MutableNBTCompound mutableCopy = new MutableNBTCompound(nbt);
return nbt.get("Enchantments"); NBTUtils.writeEnchant(mutableCopy, "Enchantments", enchantmentMap);
return mutableCopy.get("Enchantments");
}); });
return this; return this;
} }
@ -127,22 +130,19 @@ public abstract class ItemMetaBuilder implements TagWritable {
@Contract("_ -> this") @Contract("_ -> this")
public @NotNull ItemMetaBuilder attributes(@NotNull List<@NotNull ItemAttribute> attributes) { public @NotNull ItemMetaBuilder attributes(@NotNull List<@NotNull ItemAttribute> attributes) {
this.attributes = new ArrayList<>(attributes); this.attributes = new ArrayList<>(attributes);
handleCollection(attributes, "AttributeModifiers", () -> {
NBTList<NBTCompound> attributesNBT = new NBTList<>(NBTTypes.TAG_Compound); handleCollection(attributes, "AttributeModifiers", () -> NBT.List(
for (ItemAttribute itemAttribute : attributes) { NBTType.TAG_Compound,
final UUID uuid = itemAttribute.getUuid(); attributes.stream()
attributesNBT.add( .map(itemAttribute -> NBT.Compound(Map.of(
new NBTCompound() "UUID", NBT.IntArray(Utils.uuidToIntArray(itemAttribute.getUuid())),
.setIntArray("UUID", Utils.uuidToIntArray(uuid)) "Amount", NBT.Double(itemAttribute.getValue()),
.setDouble("Amount", itemAttribute.getValue()) "Slot", NBT.String(itemAttribute.getSlot().name().toLowerCase()),
.setString("Slot", itemAttribute.getSlot().name().toLowerCase()) "AttributeName", NBT.String(itemAttribute.getAttribute().getKey()),
.setString("AttributeName", itemAttribute.getAttribute().getKey()) "Operation", NBT.Int(itemAttribute.getOperation().getId()),
.setInt("Operation", itemAttribute.getOperation().getId()) "Name", NBT.String(itemAttribute.getInternalName()))))
.setString("Name", itemAttribute.getInternalName()) .toList()
); ));
}
return attributesNBT;
});
return this; return this;
} }
@ -157,11 +157,12 @@ public abstract class ItemMetaBuilder implements TagWritable {
@Contract("_ -> this") @Contract("_ -> this")
public @NotNull ItemMetaBuilder canPlaceOn(@NotNull Set<@NotNull Block> blocks) { public @NotNull ItemMetaBuilder canPlaceOn(@NotNull Set<@NotNull Block> blocks) {
this.canPlaceOn = new HashSet<>(blocks); this.canPlaceOn = new HashSet<>(blocks);
handleCollection(canPlaceOn, "CanPlaceOn", () -> { handleCollection(canPlaceOn, "CanPlaceOn", () -> NBT.List(
NBTList<NBTString> list = new NBTList<>(NBTTypes.TAG_String); NBTType.TAG_String,
canPlaceOn.forEach(block -> list.add(new NBTString(block.name()))); canPlaceOn.stream()
return list; .map(block -> new NBTString(block.name()))
}); .toList()
));
return this; return this;
} }
@ -173,11 +174,12 @@ public abstract class ItemMetaBuilder implements TagWritable {
@Contract("_ -> this") @Contract("_ -> this")
public @NotNull ItemMetaBuilder canDestroy(@NotNull Set<@NotNull Block> blocks) { public @NotNull ItemMetaBuilder canDestroy(@NotNull Set<@NotNull Block> blocks) {
this.canDestroy = new HashSet<>(blocks); this.canDestroy = new HashSet<>(blocks);
handleCollection(canDestroy, "CanDestroy", () -> { handleCollection(canPlaceOn, "CanPlaceOn", () -> NBT.List(
NBTList<NBTString> list = new NBTList<>(NBTTypes.TAG_String); NBTType.TAG_String,
canDestroy.forEach(block -> list.add(new NBTString(block.name()))); canDestroy.stream()
return list; .map(block -> new NBTString(block.name()))
}); .toList()
));
return this; return this;
} }
@ -203,13 +205,16 @@ public abstract class ItemMetaBuilder implements TagWritable {
protected abstract @NotNull Supplier<@NotNull ItemMetaBuilder> getSupplier(); protected abstract @NotNull Supplier<@NotNull ItemMetaBuilder> getSupplier();
protected synchronized void mutateNbt(Consumer<NBTCompound> consumer) { protected synchronized void mutateNbt(Consumer<MutableNBTCompound> consumer) {
MutableNBTCompound copy = new MutableNBTCompound(nbt);
consumer.accept(copy);
if (built) { if (built) {
built = false; built = false;
final var currentNbt = nbt; final var currentNbt = nbt;
NBT_UPDATER.compareAndSet(this, currentNbt, currentNbt.deepClone()); NBT_UPDATER.compareAndSet(this, currentNbt, copy.toCompound());
} else {
nbt = copy.toCompound();
} }
consumer.accept(nbt);
} }
protected synchronized NBTCompound nbt() { protected synchronized NBTCompound nbt() {
@ -222,28 +227,16 @@ public abstract class ItemMetaBuilder implements TagWritable {
} }
protected void handleCompound(@NotNull String key, protected void handleCompound(@NotNull String key,
@NotNull Consumer<@NotNull NBTCompound> consumer) { @NotNull Consumer<@NotNull MutableNBTCompound> consumer) {
mutateNbt(nbt -> { mutateNbt(nbt -> {
NBTCompound compound = null; MutableNBTCompound compoundToModify = nbt.get(key) instanceof NBTCompound compound ?
boolean newNbt = false; compound.toMutableCompound() : new MutableNBTCompound();
if (nbt.containsKey(key)) {
NBT dNbt = nbt.get(key); consumer.accept(compoundToModify);
if (dNbt instanceof NBTCompound) { if (compoundToModify.isEmpty()) {
compound = (NBTCompound) dNbt; nbt.remove(key);
}
} else { } else {
compound = new NBTCompound(); nbt.set(key, compoundToModify.toCompound());
newNbt = true;
}
if (compound != null) {
consumer.accept(compound);
if (newNbt && compound.getSize() > 0) {
this.nbt.set(key, compound);
} else if (!newNbt && compound.getSize() == 0) {
this.nbt.removeTag(key);
}
} }
}); });
} }
@ -255,7 +248,7 @@ public abstract class ItemMetaBuilder implements TagWritable {
if (value != null) { if (value != null) {
compound.set(key, supplier.get()); compound.set(key, supplier.get());
} else { } else {
compound.removeTag(key); compound.remove(key);
} }
}); });
} }
@ -267,7 +260,7 @@ public abstract class ItemMetaBuilder implements TagWritable {
if (!objects.isEmpty()) { if (!objects.isEmpty()) {
compound.set(key, supplier.get()); compound.set(key, supplier.get());
} else { } else {
compound.removeTag(key); compound.remove(key);
} }
}); });
} }
@ -279,7 +272,7 @@ public abstract class ItemMetaBuilder implements TagWritable {
if (!objects.isEmpty()) { if (!objects.isEmpty()) {
compound.set(key, supplier.get()); compound.set(key, supplier.get());
} else { } else {
compound.removeTag(key); compound.remove(key);
} }
}); });
} }
@ -287,7 +280,7 @@ public abstract class ItemMetaBuilder implements TagWritable {
@Contract(value = "_, _ -> new", pure = true) @Contract(value = "_, _ -> new", pure = true)
public static @NotNull ItemMetaBuilder fromNBT(@NotNull ItemMetaBuilder src, @NotNull NBTCompound nbtCompound) { public static @NotNull ItemMetaBuilder fromNBT(@NotNull ItemMetaBuilder src, @NotNull NBTCompound nbtCompound) {
ItemMetaBuilder dest = src.getSupplier().get(); ItemMetaBuilder dest = src.getSupplier().get();
dest.nbt = nbtCompound.deepClone(); dest.nbt = nbtCompound;
NBTUtils.loadDataIntoMeta(dest, dest.nbt); NBTUtils.loadDataIntoMeta(dest, dest.nbt);
return dest; return dest;
} }

View File

@ -12,9 +12,11 @@ import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.IntUnaryOperator; import java.util.function.IntUnaryOperator;
@ -254,11 +256,10 @@ public final class ItemStack implements TagReadable, HoverEventSource<HoverEvent
*/ */
@ApiStatus.Experimental @ApiStatus.Experimental
public @NotNull NBTCompound toItemNBT() { public @NotNull NBTCompound toItemNBT() {
final NBTCompound nbtCompound = new NBTCompound(); return NBT.Compound(Map.of(
nbtCompound.setString("id", getMaterial().name()); "id", NBT.String(getMaterial().name()),
nbtCompound.setByte("Count", (byte) getAmount()); "Count", NBT.Byte(getAmount()),
nbtCompound.set("tag", getMeta().toNBT()); "tag", getMeta().toNBT()));
return nbtCompound;
} }
@Contract(value = "-> new", pure = true) @Contract(value = "-> new", pure = true)

View File

@ -2,6 +2,8 @@ package net.minestom.server.item.firework;
import net.minestom.server.color.Color; import net.minestom.server.color.Color;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.collections.ImmutableIntArray;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import java.util.ArrayList; import java.util.ArrayList;
@ -47,14 +49,14 @@ public class FireworkEffect {
List<Color> secondaryColor = new ArrayList<>(); List<Color> secondaryColor = new ArrayList<>();
if (compound.containsKey("Colors")) { if (compound.containsKey("Colors")) {
final int[] color = compound.getIntArray("Colors"); ImmutableIntArray color = compound.getIntArray("Colors");
for (int j : color) { for (int j : color) {
primaryColor.add(new Color(j)); primaryColor.add(new Color(j));
} }
} }
if (compound.containsKey("FadeColors")) { if (compound.containsKey("FadeColors")) {
final int[] fadeColor = compound.getIntArray("FadeColors"); ImmutableIntArray fadeColor = compound.getIntArray("FadeColors");
for (int j : fadeColor) { for (int j : fadeColor) {
secondaryColor.add(new Color(j)); secondaryColor.add(new Color(j));
} }
@ -137,15 +139,14 @@ public class FireworkEffect {
* @return The firework effect as a nbt compound. * @return The firework effect as a nbt compound.
*/ */
public NBTCompound asCompound() { public NBTCompound asCompound() {
NBTCompound explosionCompound = new NBTCompound(); return NBT.Compound(explosionCompound -> {
explosionCompound.setByte("Flicker", this.getFlicker()); explosionCompound.setByte("Flicker", this.getFlicker());
explosionCompound.setByte("Trail", this.getTrail()); explosionCompound.setByte("Trail", this.getTrail());
explosionCompound.setByte("Type", this.getType()); explosionCompound.setByte("Type", this.getType());
explosionCompound.setIntArray("Colors", this.getColors()); explosionCompound.setIntArray("Colors", this.getColors());
explosionCompound.setIntArray("FadeColors", this.getFadeColors()); explosionCompound.setIntArray("FadeColors", this.getFadeColors());
});
return explosionCompound;
} }
/** /**

View File

@ -5,9 +5,7 @@ import net.minestom.server.item.ItemMetaBuilder;
import net.minestom.server.item.ItemStack; import net.minestom.server.item.ItemStack;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.*;
import org.jglrxavpok.hephaistos.nbt.NBTList;
import org.jglrxavpok.hephaistos.nbt.NBTTypes;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -58,11 +56,7 @@ public class BundleMeta extends ItemMeta implements ItemMetaBuilder.Provider<Bun
private void updateItems() { private void updateItems() {
mutateNbt(compound -> { mutateNbt(compound -> {
NBTList<NBTCompound> itemList = new NBTList<>(NBTTypes.TAG_Compound); compound.set("Items", NBT.List(NBTType.TAG_Compound, items.size(), i -> items.get(i).toItemNBT()));
for (ItemStack item : items) {
itemList.add(item.toItemNBT());
}
compound.set("Items", itemList);
}); });
} }

View File

@ -6,6 +6,7 @@ import net.minestom.server.item.ItemMeta;
import net.minestom.server.item.ItemMetaBuilder; import net.minestom.server.item.ItemMetaBuilder;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -57,7 +58,7 @@ public class CompassMeta extends ItemMeta implements ItemMetaBuilder.Provider<Co
if (lodestoneDimension != null) { if (lodestoneDimension != null) {
compound.setString("LodestoneDimension", lodestoneDimension); compound.setString("LodestoneDimension", lodestoneDimension);
} else { } else {
compound.removeTag("LodestoneDimension"); compound.remove("LodestoneDimension");
} }
}); });
@ -69,13 +70,13 @@ public class CompassMeta extends ItemMeta implements ItemMetaBuilder.Provider<Co
mutateNbt(compound -> { mutateNbt(compound -> {
if (lodestonePosition != null) { if (lodestonePosition != null) {
NBTCompound posCompound = new NBTCompound(); compound.set("LodestonePos", NBT.Compound(posCompound -> {
posCompound.setInt("X", lodestonePosition.blockX()); posCompound.setInt("X", lodestonePosition.blockX());
posCompound.setInt("Y", lodestonePosition.blockY()); posCompound.setInt("Y", lodestonePosition.blockY());
posCompound.setInt("Z", lodestonePosition.blockZ()); posCompound.setInt("Z", lodestonePosition.blockZ());
compound.set("LodestonePos", posCompound); }));
} else { } else {
compound.removeTag("LodestonePos"); compound.remove("LodestonePos");
} }
}); });

View File

@ -6,9 +6,10 @@ import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material; import net.minestom.server.item.Material;
import net.minestom.server.utils.validate.Check; import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.NBTList; import org.jglrxavpok.hephaistos.nbt.NBTList;
import org.jglrxavpok.hephaistos.nbt.NBTTypes; import org.jglrxavpok.hephaistos.nbt.NBTType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -94,11 +95,9 @@ public class CrossbowMeta extends ItemMeta implements ItemMetaBuilder.Provider<S
this.projectile1 = projectile; this.projectile1 = projectile;
this.triple = false; this.triple = false;
NBTList<NBTCompound> chargedProjectiles = new NBTList<>(NBTTypes.TAG_Compound); List<NBTCompound> chargedProjectiles =
if (!projectile.isAir()) { projectile.isAir() ? List.of() : List.of(getItemCompound(projectile));
chargedProjectiles.add(getItemCompound(projectile)); mutateNbt(compound -> compound.set("ChargedProjectiles", NBT.List(NBTType.TAG_Compound, chargedProjectiles)));
}
mutateNbt(compound -> compound.set("ChargedProjectiles", chargedProjectiles));
return this; return this;
} }
@ -120,11 +119,9 @@ public class CrossbowMeta extends ItemMeta implements ItemMetaBuilder.Provider<S
this.projectile3 = projectile3; this.projectile3 = projectile3;
this.triple = true; this.triple = true;
NBTList<NBTCompound> chargedProjectiles = new NBTList<>(NBTTypes.TAG_Compound); List<NBTCompound> chargedProjectiles =
chargedProjectiles.add(getItemCompound(projectile1)); List.of(getItemCompound(projectile1), getItemCompound(projectile2), getItemCompound(projectile3));
chargedProjectiles.add(getItemCompound(projectile2)); mutateNbt(compound -> compound.set("ChargedProjectiles", NBT.List(NBTType.TAG_Compound, chargedProjectiles)));
chargedProjectiles.add(getItemCompound(projectile3));
mutateNbt(compound -> compound.set("ChargedProjectiles", chargedProjectiles));
return this; return this;
} }
@ -181,9 +178,10 @@ public class CrossbowMeta extends ItemMeta implements ItemMetaBuilder.Provider<S
private @NotNull NBTCompound getItemCompound(@NotNull ItemStack itemStack) { private @NotNull NBTCompound getItemCompound(@NotNull ItemStack itemStack) {
NBTCompound compound = itemStack.getMeta().toNBT(); NBTCompound compound = itemStack.getMeta().toNBT();
compound.setByte("Count", (byte) itemStack.getAmount()); return compound.modify(n -> {
compound.setString("id", itemStack.getMaterial().name()); n.setByte("Count", (byte) itemStack.getAmount());
return compound; n.setString("id", itemStack.getMaterial().name());
});
} }
} }
} }

View File

@ -4,15 +4,17 @@ import net.minestom.server.item.ItemMeta;
import net.minestom.server.item.ItemMetaBuilder; import net.minestom.server.item.ItemMetaBuilder;
import net.minestom.server.item.firework.FireworkEffect; import net.minestom.server.item.firework.FireworkEffect;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.NBTList; import org.jglrxavpok.hephaistos.nbt.NBTList;
import org.jglrxavpok.hephaistos.nbt.NBTTypes; import org.jglrxavpok.hephaistos.nbt.NBTType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors;
public class FireworkMeta extends ItemMeta implements ItemMetaBuilder.Provider<FireworkMeta.Builder> { public class FireworkMeta extends ItemMeta implements ItemMetaBuilder.Provider<FireworkMeta.Builder> {
@ -42,11 +44,12 @@ public class FireworkMeta extends ItemMeta implements ItemMetaBuilder.Provider<F
public Builder effects(List<FireworkEffect> effects) { public Builder effects(List<FireworkEffect> effects) {
this.effects = effects; this.effects = effects;
handleCompound("Fireworks", nbtCompound -> { handleCompound("Fireworks", nbtCompound -> {
NBTList<NBTCompound> explosions = new NBTList<>(NBTTypes.TAG_Compound); nbtCompound.set("Explosions", NBT.List(
for (FireworkEffect effect : this.effects) { NBTType.TAG_Compound,
explosions.add(effect.asCompound()); effects.stream()
} .map(FireworkEffect::asCompound)
nbtCompound.set("Explosions", explosions); .toList()
));
}); });
return this; return this;
} }

View File

@ -32,7 +32,7 @@ public class LeatherArmorMeta extends ItemMeta implements ItemMetaBuilder.Provid
if (color != null) { if (color != null) {
nbtCompound.setInt("color", color.asRGB()); nbtCompound.setInt("color", color.asRGB());
} else { } else {
nbtCompound.removeTag("color"); nbtCompound.remove("color");
} }
}); });
return this; return this;

View File

@ -6,12 +6,14 @@ import net.minestom.server.item.ItemMeta;
import net.minestom.server.item.ItemMetaBuilder; import net.minestom.server.item.ItemMetaBuilder;
import net.minestom.server.utils.clone.PublicCloneable; import net.minestom.server.utils.clone.PublicCloneable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.NBTList; import org.jglrxavpok.hephaistos.nbt.NBTList;
import org.jglrxavpok.hephaistos.nbt.NBTTypes; import org.jglrxavpok.hephaistos.nbt.NBTType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -92,17 +94,17 @@ public class MapMeta extends ItemMeta implements ItemMetaBuilder.Provider<MapMet
public Builder decorations(List<MapDecoration> value) { public Builder decorations(List<MapDecoration> value) {
this.decorations = new ArrayList<>(value); this.decorations = new ArrayList<>(value);
NBTList<NBTCompound> decorationsList = new NBTList<>(NBTTypes.TAG_Compound); NBTList<NBTCompound> decorationsList = NBT.List(
for (MapDecoration decoration : decorations) { NBTType.TAG_Compound,
NBTCompound decorationCompound = new NBTCompound(); decorations.stream()
decorationCompound.setString("id", decoration.getId()); .map(decoration -> NBT.Compound(Map.of(
decorationCompound.setByte("type", decoration.getType()); "id", NBT.String(decoration.getId()),
decorationCompound.setByte("x", decoration.getX()); "type", NBT.Byte(decoration.getType()),
decorationCompound.setByte("z", decoration.getZ()); "x", NBT.Byte(decoration.getX()),
decorationCompound.setDouble("rot", decoration.getRotation()); "z", NBT.Byte(decoration.getZ()),
"rot", NBT.Double(decoration.getRotation()))))
decorationsList.add(decorationCompound); .toList()
} );
mutateNbt(compound -> compound.set("Decorations", decorationsList)); mutateNbt(compound -> compound.set("Decorations", decorationsList));
return this; return this;
@ -111,14 +113,7 @@ public class MapMeta extends ItemMeta implements ItemMetaBuilder.Provider<MapMet
public Builder mapColor(Color value) { public Builder mapColor(Color value) {
this.mapColor = value; this.mapColor = value;
mutateNbt(nbt -> { handleCompound("display", displayCompound -> {
NBTCompound displayCompound;
if (nbt.containsKey("display")) {
displayCompound = nbt.getCompound("display");
} else {
displayCompound = new NBTCompound();
nbt.set("display", displayCompound);
}
displayCompound.setInt("MapColor", mapColor.asRGB()); displayCompound.setInt("MapColor", mapColor.asRGB());
}); });

View File

@ -6,10 +6,13 @@ import net.minestom.server.item.ItemMetaBuilder;
import net.minestom.server.utils.Utils; import net.minestom.server.utils.Utils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.NBTList; import org.jglrxavpok.hephaistos.nbt.NBTList;
import org.jglrxavpok.hephaistos.nbt.NBTTypes; import org.jglrxavpok.hephaistos.nbt.NBTType;
import java.util.List;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.UUID; import java.util.UUID;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -50,15 +53,17 @@ public class PlayerHeadMeta extends ItemMeta implements ItemMetaBuilder.Provider
this.playerSkin = playerSkin; this.playerSkin = playerSkin;
handleCompound("SkullOwner", nbtCompound -> { handleCompound("SkullOwner", nbtCompound -> {
if (playerSkin == null) { if (playerSkin == null) {
nbtCompound.removeTag("Properties"); nbtCompound.remove("Properties");
return; return;
} }
NBTList<NBTCompound> textures = new NBTList<>(NBTTypes.TAG_Compound);
final String value = Objects.requireNonNullElse(this.playerSkin.textures(), ""); final String value = Objects.requireNonNullElse(this.playerSkin.textures(), "");
final String signature = Objects.requireNonNullElse(this.playerSkin.signature(), ""); final String signature = Objects.requireNonNullElse(this.playerSkin.signature(), "");
textures.add(new NBTCompound().setString("Value", value).setString("Signature", signature)); NBTList<NBTCompound> textures = new NBTList<>(NBTType.TAG_Compound,
nbtCompound.set("Properties", new NBTCompound().set("textures", textures)); List.of(NBT.Compound(Map.of(
"Value", NBT.String(value),
"Signature", NBT.String(signature)))));
nbtCompound.set("Properties", NBT.Compound(Map.of("textures", textures)));
}); });
return this; return this;
} }
@ -74,7 +79,7 @@ public class PlayerHeadMeta extends ItemMeta implements ItemMetaBuilder.Provider
NBTCompound skullOwnerCompound = nbtCompound.getCompound("SkullOwner"); NBTCompound skullOwnerCompound = nbtCompound.getCompound("SkullOwner");
if (skullOwnerCompound.containsKey("Id")) { if (skullOwnerCompound.containsKey("Id")) {
skullOwner(Utils.intArrayToUuid(skullOwnerCompound.getIntArray("Id"))); skullOwner(Utils.intArrayToUuid(skullOwnerCompound.getIntArray("Id").copyArray()));
} }
if (skullOwnerCompound.containsKey("Properties")) { if (skullOwnerCompound.containsKey("Properties")) {

View File

@ -7,14 +7,16 @@ import net.minestom.server.potion.CustomPotionEffect;
import net.minestom.server.potion.PotionType; import net.minestom.server.potion.PotionType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.NBTList; import org.jglrxavpok.hephaistos.nbt.NBTList;
import org.jglrxavpok.hephaistos.nbt.NBTTypes; import org.jglrxavpok.hephaistos.nbt.NBTType;
import java.time.Duration; import java.time.Duration;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors;
public class PotionMeta extends ItemMeta implements ItemMetaBuilder.Provider<PotionMeta.Builder> { public class PotionMeta extends ItemMeta implements ItemMetaBuilder.Provider<PotionMeta.Builder> {
@ -58,18 +60,19 @@ public class PotionMeta extends ItemMeta implements ItemMetaBuilder.Provider<Pot
public Builder effects(@NotNull List<CustomPotionEffect> customPotionEffects) { public Builder effects(@NotNull List<CustomPotionEffect> customPotionEffects) {
this.customPotionEffects = customPotionEffects; this.customPotionEffects = customPotionEffects;
NBTList<NBTCompound> potionList = new NBTList<>(NBTTypes.TAG_Compound); NBTList<NBTCompound> potionList = NBT.List(
for (CustomPotionEffect customPotionEffect : customPotionEffects) { NBTType.TAG_Compound,
NBTCompound potionCompound = new NBTCompound(); customPotionEffects.stream()
potionCompound.setByte("Id", customPotionEffect.getId()); .map(customPotionEffect -> NBT.Compound(potionCompound -> {
potionCompound.setByte("Amplifier", customPotionEffect.getAmplifier()); potionCompound.setByte("Id", customPotionEffect.getId());
potionCompound.setInt("Duration", customPotionEffect.getDuration()); potionCompound.setByte("Amplifier", customPotionEffect.getAmplifier());
potionCompound.setByte("Ambient", (byte) (customPotionEffect.isAmbient() ? 1 : 0)); potionCompound.setInt("Duration", customPotionEffect.getDuration());
potionCompound.setByte("ShowParticles", (byte) (customPotionEffect.showParticles() ? 1 : 0)); potionCompound.setByte("Ambient", (byte) (customPotionEffect.isAmbient() ? 1 : 0));
potionCompound.setByte("ShowIcon", (byte) (customPotionEffect.showIcon() ? 1 : 0)); potionCompound.setByte("ShowParticles", (byte) (customPotionEffect.showParticles() ? 1 : 0));
potionCompound.setByte("ShowIcon", (byte) (customPotionEffect.showIcon() ? 1 : 0));
potionList.add(potionCompound); }))
} .toList()
);
mutateNbt(compound -> compound.set("CustomPotionEffects", potionList)); mutateNbt(compound -> compound.set("CustomPotionEffects", potionList));
return this; return this;

View File

@ -6,16 +6,14 @@ import net.minestom.server.item.ItemMeta;
import net.minestom.server.item.ItemMetaBuilder; import net.minestom.server.item.ItemMetaBuilder;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.*;
import org.jglrxavpok.hephaistos.nbt.NBTList;
import org.jglrxavpok.hephaistos.nbt.NBTString;
import org.jglrxavpok.hephaistos.nbt.NBTTypes;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors;
public class WritableBookMeta extends ItemMeta implements ItemMetaBuilder.Provider<WritableBookMeta.Builder> { public class WritableBookMeta extends ItemMeta implements ItemMetaBuilder.Provider<WritableBookMeta.Builder> {
@ -67,13 +65,12 @@ public class WritableBookMeta extends ItemMeta implements ItemMetaBuilder.Provid
public Builder pages(@NotNull List<@NotNull Component> pages) { public Builder pages(@NotNull List<@NotNull Component> pages) {
this.pages = new ArrayList<>(pages); this.pages = new ArrayList<>(pages);
handleCollection(pages, "pages", () -> { handleCollection(pages, "pages", () -> NBT.List(
NBTList<NBTString> list = new NBTList<>(NBTTypes.TAG_String); NBTType.TAG_String,
for (Component page : pages) { pages.stream()
list.add(new NBTString(LegacyComponentSerializer.legacySection().serialize(page))); .map(page -> new NBTString(LegacyComponentSerializer.legacySection().serialize(page)))
} .toList()
return list; ));
});
return this; return this;
} }

View File

@ -14,6 +14,7 @@ import org.jglrxavpok.hephaistos.nbt.*;
import java.util.*; import java.util.*;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors;
public class WrittenBookMeta extends ItemMeta implements ItemMetaBuilder.Provider<WrittenBookMeta.Builder> { public class WrittenBookMeta extends ItemMeta implements ItemMetaBuilder.Provider<WrittenBookMeta.Builder> {
@ -115,13 +116,12 @@ public class WrittenBookMeta extends ItemMeta implements ItemMetaBuilder.Provide
public Builder pages(@NotNull List<@NotNull Component> pages) { public Builder pages(@NotNull List<@NotNull Component> pages) {
this.pages = new ArrayList<>(pages); this.pages = new ArrayList<>(pages);
handleCollection(pages, "pages", () -> { handleCollection(pages, "pages", () -> NBT.List(
NBTList<NBTString> list = new NBTList<>(NBTTypes.TAG_String); NBTType.TAG_String,
for (Component page : pages) { pages.stream()
list.add(new NBTString(GsonComponentSerializer.gson().serialize(page))); .map(page -> new NBTString(GsonComponentSerializer.gson().serialize(page)))
} .toList()
return list; ));
});
return this; return this;
} }

View File

@ -6,6 +6,7 @@ import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter; import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import java.util.List; import java.util.List;

View File

@ -9,6 +9,7 @@ import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.utils.binary.Writeable; import net.minestom.server.utils.binary.Writeable;
import net.minestom.server.utils.chunk.ChunkUtils; import net.minestom.server.utils.chunk.ChunkUtils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import java.util.HashMap; import java.util.HashMap;
@ -18,7 +19,6 @@ import java.util.Objects;
public record ChunkData(@NotNull NBTCompound heightmaps, byte @NotNull [] data, public record ChunkData(@NotNull NBTCompound heightmaps, byte @NotNull [] data,
@NotNull Map<Integer, Block> blockEntities) implements Writeable { @NotNull Map<Integer, Block> blockEntities) implements Writeable {
public ChunkData { public ChunkData {
heightmaps = heightmaps.deepClone();
data = data.clone(); data = data.clone();
blockEntities = Map.copyOf(blockEntities); blockEntities = Map.copyOf(blockEntities);
} }
@ -56,15 +56,16 @@ public record ChunkData(@NotNull NBTCompound heightmaps, byte @NotNull [] data,
// Append handler tags // Append handler tags
final BlockHandler handler = block.handler(); final BlockHandler handler = block.handler();
if (handler != null) { if (handler != null) {
resultNbt = new NBTCompound(); resultNbt = NBT.Compound(nbt -> {
final NBTCompound blockNbt = Objects.requireNonNullElseGet(block.nbt(), NBTCompound::new); final NBTCompound blockNbt = Objects.requireNonNullElseGet(block.nbt(), NBTCompound::new);
for (Tag<?> tag : handler.getBlockEntityTags()) { for (Tag<?> tag : handler.getBlockEntityTags()) {
final var value = tag.read(blockNbt); final var value = tag.read(blockNbt);
if (value != null) { if (value != null) {
// Tag is present and valid // Tag is present and valid
tag.writeUnsafe(resultNbt, value); tag.writeUnsafe(nbt, value);
}
} }
} });
} else { } else {
// Complete nbt shall be sent if the block has no handler // Complete nbt shall be sent if the block has no handler
// Necessary to support all vanilla blocks // Necessary to support all vanilla blocks

View File

@ -3,7 +3,7 @@ package net.minestom.server.permission;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.SNBTParser; import org.jglrxavpok.hephaistos.parser.SNBTParser;
import java.util.Set; import java.util.Set;

View File

@ -1,13 +1,16 @@
package net.minestom.server.tag; package net.minestom.server.tag;
import net.minestom.server.MinecraftServer;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBT; import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.NBTCompoundLike;
import org.jglrxavpok.hephaistos.nbt.NBTException; import org.jglrxavpok.hephaistos.nbt.NBTException;
import org.jglrxavpok.hephaistos.nbt.SNBTParser; import org.jglrxavpok.hephaistos.nbt.mutable.MutableNBTCompound;
import org.jglrxavpok.hephaistos.parser.SNBTParser;
import java.io.StringReader; import java.io.StringReader;
import java.util.Objects; import java.util.Objects;
@ -31,16 +34,15 @@ public class Tag<T> {
* Writing will override all tags. Proceed with caution. * Writing will override all tags. Proceed with caution.
*/ */
@ApiStatus.Experimental @ApiStatus.Experimental
public static final Tag<String> SNBT = new Tag<>(null, NBTCompound::toSNBT, (original, snbt) -> { public static final Tag<String> SNBT = new Tag<>(null, n -> n.toCompound().toSNBT(), (original, snbt) -> {
try { try {
final var updated = new SNBTParser(new StringReader(snbt)).parse(); final var updated = new SNBTParser(new StringReader(snbt)).parse();
if (!(updated instanceof NBTCompound updatedCompound)) if (!(updated instanceof NBTCompound updatedCompound))
throw new IllegalArgumentException("'" + snbt + "' is not a compound!"); throw new IllegalArgumentException("'" + snbt + "' is not a compound!");
original.clear(); original.clear();
updatedCompound.getKeys().forEach(s -> updatedCompound.forEach(original::set);
original.set(s, Objects.requireNonNull(updatedCompound.get(s))));
} catch (NBTException e) { } catch (NBTException e) {
e.printStackTrace(); MinecraftServer.getExceptionManager().handleException(e);
} }
}, null); }, null);
@ -50,20 +52,20 @@ public class Tag<T> {
* Writing will override all tags. Proceed with caution. * Writing will override all tags. Proceed with caution.
*/ */
@ApiStatus.Experimental @ApiStatus.Experimental
public static final Tag<NBTCompound> NBT = new Tag<>(null, NBTCompound::deepClone, (original, updated) -> { public static final Tag<NBTCompound> NBT = new Tag<>(null, NBTCompoundLike::toCompound, (original, updated) -> {
original.clear(); original.clear();
updated.getKeys().forEach(s -> original.set(s, Objects.requireNonNull(updated.get(s)))); updated.forEach(original::set);
}, null); }, null);
private final String key; private final String key;
private final Function<NBTCompound, T> readFunction; private final Function<NBTCompoundLike, T> readFunction;
private final BiConsumer<NBTCompound, T> writeConsumer; private final BiConsumer<MutableNBTCompound, T> writeConsumer;
private final Supplier<T> defaultValue; private final Supplier<T> defaultValue;
protected Tag(@Nullable String key, protected Tag(@Nullable String key,
@NotNull Function<NBTCompound, T> readFunction, @NotNull Function<NBTCompoundLike, T> readFunction,
@Nullable BiConsumer<NBTCompound, T> writeConsumer, @Nullable BiConsumer<MutableNBTCompound, T> writeConsumer,
@Nullable Supplier<T> defaultValue) { @Nullable Supplier<T> defaultValue) {
this.key = key; this.key = key;
this.readFunction = readFunction; this.readFunction = readFunction;
@ -73,8 +75,8 @@ public class Tag<T> {
} }
protected Tag(@Nullable String key, protected Tag(@Nullable String key,
@NotNull Function<NBTCompound, T> readFunction, @NotNull Function<NBTCompoundLike, T> readFunction,
@Nullable BiConsumer<NBTCompound, T> writeConsumer) { @Nullable BiConsumer<MutableNBTCompound, T> writeConsumer) {
this(key, readFunction, writeConsumer, null); this(key, readFunction, writeConsumer, null);
} }
@ -126,7 +128,7 @@ public class Tag<T> {
}); });
} }
public @Nullable T read(@NotNull NBTCompound nbtCompound) { public @Nullable T read(@NotNull NBTCompoundLike nbtCompound) {
T result = readFunction.apply(nbtCompound); T result = readFunction.apply(nbtCompound);
if (result == null) { if (result == null) {
final var supplier = defaultValue; final var supplier = defaultValue;
@ -135,15 +137,15 @@ public class Tag<T> {
return result; return result;
} }
public void write(@NotNull NBTCompound nbtCompound, @Nullable T value) { public void write(@NotNull MutableNBTCompound nbtCompound, @Nullable T value) {
if (key == null || value != null) { if (key == null || value != null) {
this.writeConsumer.accept(nbtCompound, value); this.writeConsumer.accept(nbtCompound, value);
} else { } else {
nbtCompound.removeTag(key); nbtCompound.remove(key);
} }
} }
public void writeUnsafe(@NotNull NBTCompound nbtCompound, @Nullable Object value) { public void writeUnsafe(@NotNull MutableNBTCompound nbtCompound, @Nullable Object value) {
write(nbtCompound, (T) value); write(nbtCompound, (T) value);
} }
@ -185,7 +187,7 @@ public class Tag<T> {
public static @NotNull Tag<byte[]> ByteArray(@NotNull String key) { public static @NotNull Tag<byte[]> ByteArray(@NotNull String key) {
return new Tag<>(key, return new Tag<>(key,
nbtCompound -> nbtCompound.getByteArray(key), nbtCompound -> nbtCompound.getByteArray(key).copyArray(),
(nbtCompound, value) -> nbtCompound.setByteArray(key, value)); (nbtCompound, value) -> nbtCompound.setByteArray(key, value));
} }
@ -199,24 +201,20 @@ public class Tag<T> {
return new Tag<>(key, return new Tag<>(key,
nbt -> { nbt -> {
final var currentNBT = nbt.get(key); final var currentNBT = nbt.get(key);
// Avoid a NPE when cloning a null variable. return (T) currentNBT;
if (currentNBT == null) {
return null;
}
return (T) currentNBT.deepClone();
}, },
((nbt, value) -> nbt.set(key, value.deepClone()))); ((nbt, value) -> nbt.set(key, value)));
} }
public static @NotNull Tag<int[]> IntArray(@NotNull String key) { public static @NotNull Tag<int[]> IntArray(@NotNull String key) {
return new Tag<>(key, return new Tag<>(key,
nbtCompound -> nbtCompound.getIntArray(key), nbtCompound -> nbtCompound.getIntArray(key).copyArray(),
(nbtCompound, value) -> nbtCompound.setIntArray(key, value)); (nbtCompound, value) -> nbtCompound.setIntArray(key, value));
} }
public static @NotNull Tag<long[]> LongArray(@NotNull String key) { public static @NotNull Tag<long[]> LongArray(@NotNull String key) {
return new Tag<>(key, return new Tag<>(key,
nbtCompound -> nbtCompound.getLongArray(key), nbtCompound -> nbtCompound.getLongArray(key).copyArray(),
(nbtCompound, value) -> nbtCompound.setLongArray(key, value)); (nbtCompound, value) -> nbtCompound.setLongArray(key, value));
} }
@ -231,19 +229,15 @@ public class Tag<T> {
public static <T> @NotNull Tag<T> Structure(@NotNull String key, @NotNull TagSerializer<T> serializer) { public static <T> @NotNull Tag<T> Structure(@NotNull String key, @NotNull TagSerializer<T> serializer) {
return new Tag<>(key, return new Tag<>(key,
nbtCompound -> { nbtCompound -> {
final var compound = nbtCompound.getCompound(key); final NBTCompound compound = nbtCompound.getCompound(key);
if (compound == null) { if (compound == null) return null;
return null;
}
return serializer.read(TagReadable.fromCompound(compound)); return serializer.read(TagReadable.fromCompound(compound));
}, },
(nbtCompound, value) -> { (nbtCompound, value) -> {
var compound = nbtCompound.getCompound(key); MutableNBTCompound mutableCopy = nbtCompound.get(key) instanceof NBTCompound c ?
if (compound == null) { c.toMutableCompound() : new MutableNBTCompound();
compound = new NBTCompound(); serializer.write(TagWritable.fromCompound(mutableCopy), value);
nbtCompound.set(key, compound); nbtCompound.set(key, mutableCopy.toCompound());
}
serializer.write(TagWritable.fromCompound(compound), value);
}); });
} }

View File

@ -3,6 +3,8 @@ package net.minestom.server.tag;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.NBTCompoundGetters;
import org.jglrxavpok.hephaistos.nbt.NBTCompoundLike;
/** /**
* Represents an element which can read {@link Tag tags}. * Represents an element which can read {@link Tag tags}.
@ -34,7 +36,7 @@ public interface TagReadable {
* @param compound the compound to convert * @param compound the compound to convert
* @return a {@link TagReadable} capable of reading {@code compound} * @return a {@link TagReadable} capable of reading {@code compound}
*/ */
static @NotNull TagReadable fromCompound(@NotNull NBTCompound compound) { static @NotNull TagReadable fromCompound(@NotNull NBTCompoundLike compound) {
return new TagReadable() { return new TagReadable() {
@Override @Override
public <T> @Nullable T getTag(@NotNull Tag<T> tag) { public <T> @Nullable T getTag(@NotNull Tag<T> tag) {

View File

@ -3,6 +3,7 @@ package net.minestom.server.tag;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.mutable.MutableNBTCompound;
/** /**
* Represents an element which can write {@link Tag tags}. * Represents an element which can write {@link Tag tags}.
@ -28,7 +29,7 @@ public interface TagWritable {
* @param compound the compound to convert * @param compound the compound to convert
* @return a {@link TagWritable} capable of writing {@code compound} * @return a {@link TagWritable} capable of writing {@code compound}
*/ */
static @NotNull TagWritable fromCompound(@NotNull NBTCompound compound) { static @NotNull TagWritable fromCompound(@NotNull MutableNBTCompound compound) {
return new TagWritable() { return new TagWritable() {
@Override @Override
public <T> void setTag(@NotNull Tag<T> tag, @Nullable T value) { public <T> void setTag(@NotNull Tag<T> tag, @Nullable T value) {

View File

@ -20,10 +20,12 @@ import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.*; import org.jglrxavpok.hephaistos.nbt.*;
import org.jglrxavpok.hephaistos.nbt.mutable.MutableNBTCompound;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
// for lack of a better name // for lack of a better name
public final class NBTUtils { public final class NBTUtils {
@ -79,34 +81,35 @@ public final class NBTUtils {
} }
} }
public static void saveAllItems(@NotNull NBTList<NBTCompound> list, @NotNull Inventory inventory) { public static void saveAllItems(@NotNull List<NBTCompound> list, @NotNull Inventory inventory) {
for (int i = 0; i < inventory.getSize(); i++) { for (int i = 0; i < inventory.getSize(); i++) {
final ItemStack stack = inventory.getItemStack(i); final ItemStack stack = inventory.getItemStack(i);
NBTCompound nbt = new NBTCompound();
NBTCompound tag = stack.getMeta().toNBT(); NBTCompound tag = stack.getMeta().toNBT();
nbt.set("tag", tag); final int slotIndex = i;
nbt.setByte("Slot", (byte) i); list.add(NBT.Compound(nbt -> {
nbt.setByte("Count", (byte) stack.getAmount()); nbt.set("tag", tag);
nbt.setString("id", stack.getMaterial().name()); nbt.setByte("Slot", (byte) slotIndex);
nbt.setByte("Count", (byte) stack.getAmount());
list.add(nbt); nbt.setString("id", stack.getMaterial().name());
}));
} }
} }
public static void writeEnchant(@NotNull NBTCompound nbt, @NotNull String listName, public static void writeEnchant(@NotNull MutableNBTCompound nbt, @NotNull String listName,
@NotNull Map<Enchantment, Short> enchantmentMap) { @NotNull Map<Enchantment, Short> enchantmentMap) {
NBTList<NBTCompound> enchantList = new NBTList<>(NBTTypes.TAG_Compound); nbt.set(listName, NBT.List(
for (var entry : enchantmentMap.entrySet()) { NBTType.TAG_Compound,
final Enchantment enchantment = entry.getKey(); enchantmentMap.entrySet().stream()
final short level = entry.getValue(); .map(entry ->
enchantList.add(new NBTCompound() NBT.Compound(n -> {
.setShort("lvl", level) n.setShort("lvl", entry.getValue());
.setString("id", enchantment.name()) n.setString("id", entry.getKey().name());
); })
} )
nbt.set(listName, enchantList); .toList()
));
} }
public static @NotNull ItemStack readItemStack(@NotNull BinaryReader reader) { public static @NotNull ItemStack readItemStack(@NotNull BinaryReader reader) {
@ -134,7 +137,7 @@ public final class NBTUtils {
if (nbt.containsKey("display")) { if (nbt.containsKey("display")) {
final NBTCompound display = nbt.getCompound("display"); final NBTCompound display = nbt.getCompound("display");
if (display.containsKey("Name")) { if (display.containsKey("Name")) {
final String rawName = StringUtils.unescapeJavaString(display.getString("Name")); final String rawName = display.getString("Name");
final Component displayName = GsonComponentSerializer.gson().deserialize(rawName); final Component displayName = GsonComponentSerializer.gson().deserialize(rawName);
metaBuilder.displayName(displayName); metaBuilder.displayName(displayName);
} }
@ -142,7 +145,7 @@ public final class NBTUtils {
NBTList<NBTString> loreList = display.getList("Lore"); NBTList<NBTString> loreList = display.getList("Lore");
List<Component> lore = new ArrayList<>(); List<Component> lore = new ArrayList<>();
for (NBTString s : loreList) { for (NBTString s : loreList) {
final String rawLore = StringUtils.unescapeJavaString(s.getValue()); final String rawLore = s.getValue();
lore.add(GsonComponentSerializer.gson().deserialize(rawLore)); lore.add(GsonComponentSerializer.gson().deserialize(rawLore));
} }
metaBuilder.lore(lore); metaBuilder.lore(lore);
@ -161,7 +164,7 @@ public final class NBTUtils {
for (NBTCompound attributeNBT : nbtAttributes) { for (NBTCompound attributeNBT : nbtAttributes) {
final UUID uuid; final UUID uuid;
{ {
final int[] uuidArray = attributeNBT.getIntArray("UUID"); final int[] uuidArray = attributeNBT.getIntArray("UUID").copyArray();
uuid = Utils.intArrayToUuid(uuidArray); uuid = Utils.intArrayToUuid(uuidArray);
} }

View File

@ -15,7 +15,7 @@ public final class SerializerUtils {
public static Point longToBlockPosition(long value) { public static Point longToBlockPosition(long value) {
final int x = (int) (value >> 38); final int x = (int) (value >> 38);
final int y = (int) (value & 0xFFF); final int y = (int) (value << 52 >> 52);
final int z = (int) (value << 26 >> 38); final int z = (int) (value << 26 >> 38);
return new Vec(x, y, z); return new Vec(x, y, z);
} }

View File

@ -10,6 +10,7 @@ import net.minestom.server.utils.SerializerUtils;
import net.minestom.server.utils.Utils; import net.minestom.server.utils.Utils;
import net.minestom.server.utils.validate.Check; import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.CompressedProcesser;
import org.jglrxavpok.hephaistos.nbt.NBT; import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTException; import org.jglrxavpok.hephaistos.nbt.NBTException;
import org.jglrxavpok.hephaistos.nbt.NBTReader; import org.jglrxavpok.hephaistos.nbt.NBTReader;
@ -32,7 +33,7 @@ import java.util.function.Supplier;
*/ */
public class BinaryReader extends InputStream { public class BinaryReader extends InputStream {
private final ByteBuffer buffer; private final ByteBuffer buffer;
private NBTReader nbtReader; private NBTReader nbtReader = null;
public BinaryReader(@NotNull ByteBuffer buffer) { public BinaryReader(@NotNull ByteBuffer buffer) {
this.buffer = buffer; this.buffer = buffer;
@ -257,7 +258,7 @@ public class BinaryReader extends InputStream {
public NBT readTag() { public NBT readTag() {
NBTReader reader = this.nbtReader; NBTReader reader = this.nbtReader;
if (reader == null) { if (reader == null) {
reader = new NBTReader(this, false); reader = new NBTReader(this, CompressedProcesser.NONE);
this.nbtReader = reader; this.nbtReader = reader;
} }
try { try {

View File

@ -9,6 +9,7 @@ import net.minestom.server.utils.SerializerUtils;
import net.minestom.server.utils.Utils; import net.minestom.server.utils.Utils;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.CompressedProcesser;
import org.jglrxavpok.hephaistos.nbt.NBT; import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTWriter; import org.jglrxavpok.hephaistos.nbt.NBTWriter;
@ -303,7 +304,7 @@ public class BinaryWriter extends OutputStream {
public void writeNBT(@NotNull String name, @NotNull NBT tag) { public void writeNBT(@NotNull String name, @NotNull NBT tag) {
if (nbtWriter == null) { if (nbtWriter == null) {
this.nbtWriter = new NBTWriter(this, false); this.nbtWriter = new NBTWriter(this, CompressedProcesser.NONE);
} }
try { try {
nbtWriter.writeNamed(name, tag); nbtWriter.writeNamed(name, tag);

View File

@ -3,8 +3,10 @@ package net.minestom.server.world;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.NamespaceID;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -26,8 +28,9 @@ public class DimensionType {
.ceilingEnabled(false) .ceilingEnabled(false)
.fixedTime(null) .fixedTime(null)
.ambientLight(0.0f) .ambientLight(0.0f)
.height(256) .height(384)
.logicalHeight(256) .minY(-64)
.logicalHeight(384)
.infiniburn(NamespaceID.from("minecraft:infiniburn_overworld")) .infiniburn(NamespaceID.from("minecraft:infiniburn_overworld"))
.build(); .build();
@ -107,35 +110,33 @@ public class DimensionType {
@NotNull @NotNull
public NBTCompound toIndexedNBT() { public NBTCompound toIndexedNBT() {
NBTCompound nbt = new NBTCompound(); return NBT.Compound(Map.of(
NBTCompound element = toNBT(); "name", NBT.String(name.toString()),
nbt.setString("name", name.toString()); "id", NBT.Int(id),
nbt.setInt("id", id); "element", toNBT()));
nbt.set("element", element);
return nbt;
} }
@NotNull @NotNull
public NBTCompound toNBT() { public NBTCompound toNBT() {
NBTCompound nbt = new NBTCompound() return NBT.Compound(nbt -> {
.setFloat("ambient_light", ambientLight) nbt.setFloat("ambient_light", ambientLight);
.setString("infiniburn", infiniburn.toString()) nbt.setString("infiniburn", infiniburn.toString());
.setByte("natural", (byte) (natural ? 0x01 : 0x00)) nbt.setByte("natural", (byte) (natural ? 0x01 : 0x00));
.setByte("has_ceiling", (byte) (ceilingEnabled ? 0x01 : 0x00)) nbt.setByte("has_ceiling", (byte) (ceilingEnabled ? 0x01 : 0x00));
.setByte("has_skylight", (byte) (skylightEnabled ? 0x01 : 0x00)) nbt.setByte("has_skylight", (byte) (skylightEnabled ? 0x01 : 0x00));
.setByte("ultrawarm", (byte) (ultrawarm ? 0x01 : 0x00)) nbt.setByte("ultrawarm", (byte) (ultrawarm ? 0x01 : 0x00));
.setByte("has_raids", (byte) (raidCapable ? 0x01 : 0x00)) nbt.setByte("has_raids", (byte) (raidCapable ? 0x01 : 0x00));
.setByte("respawn_anchor_works", (byte) (respawnAnchorSafe ? 0x01 : 0x00)) nbt.setByte("respawn_anchor_works", (byte) (respawnAnchorSafe ? 0x01 : 0x00));
.setByte("bed_works", (byte) (bedSafe ? 0x01 : 0x00)) nbt.setByte("bed_works", (byte) (bedSafe ? 0x01 : 0x00));
.setString("effects", effects) nbt.setString("effects", effects);
.setByte("piglin_safe", (byte) (piglinSafe ? 0x01 : 0x00)) nbt.setByte("piglin_safe", (byte) (piglinSafe ? 0x01 : 0x00));
.setInt("min_y", minY) nbt.setInt("min_y", minY);
.setInt("height", height) nbt.setInt("height", height);
.setInt("logical_height", logicalHeight) nbt.setInt("logical_height", logicalHeight);
.setInt("coordinate_scale", coordinateScale) nbt.setInt("coordinate_scale", coordinateScale);
.setString("name", name.toString()); nbt.setString("name", name.toString());
if (fixedTime != null) nbt.setLong("fixed_time", fixedTime); if (fixedTime != null) nbt.setLong("fixed_time", fixedTime);
return nbt; });
} }
@Override @Override

View File

@ -3,13 +3,15 @@ package net.minestom.server.world;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.NamespaceID;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.NBTList; import org.jglrxavpok.hephaistos.nbt.NBTList;
import org.jglrxavpok.hephaistos.nbt.NBTTypes; import org.jglrxavpok.hephaistos.nbt.NBTType;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
/** /**
* Allows servers to register custom dimensions. Also used during player login to send the list of all existing dimensions. * Allows servers to register custom dimensions. Also used during player login to send the list of all existing dimensions.
@ -88,13 +90,14 @@ public final class DimensionTypeManager {
* @return an nbt compound containing the registered dimensions * @return an nbt compound containing the registered dimensions
*/ */
public @NotNull NBTCompound toNBT() { public @NotNull NBTCompound toNBT() {
NBTCompound dimensions = new NBTCompound(); return NBT.Compound(dimensions -> {
dimensions.setString("type", "minecraft:dimension_type"); dimensions.setString("type", "minecraft:dimension_type");
NBTList<NBTCompound> dimensionList = new NBTList<>(NBTTypes.TAG_Compound); dimensions.set("value", NBT.List(
for (DimensionType dimensionType : dimensionTypes) { NBTType.TAG_Compound,
dimensionList.add(dimensionType.toIndexedNBT()); dimensionTypes.stream()
} .map(DimensionType::toIndexedNBT)
dimensions.set("value", dimensionList); .toList()
return dimensions; ));
});
} }
} }

View File

@ -4,6 +4,7 @@ import net.minestom.server.coordinate.Point;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.NamespaceID;
import net.minestom.server.utils.validate.Check; import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import java.util.Locale; import java.util.Locale;
@ -61,22 +62,22 @@ public final class Biome {
Check.notNull(name, "The biome namespace cannot be null"); Check.notNull(name, "The biome namespace cannot be null");
Check.notNull(effects, "The biome effects cannot be null"); Check.notNull(effects, "The biome effects cannot be null");
NBTCompound nbt = new NBTCompound(); return NBT.Compound(nbt -> {
nbt.setString("name", name.toString()); nbt.setString("name", name.toString());
nbt.setInt("id", id()); nbt.setInt("id", id());
NBTCompound element = new NBTCompound(); nbt.set("element", NBT.Compound(element -> {
element.setFloat("depth", depth); element.setFloat("depth", depth);
element.setFloat("temperature", temperature); element.setFloat("temperature", temperature);
element.setFloat("scale", scale); element.setFloat("scale", scale);
element.setFloat("downfall", downfall); element.setFloat("downfall", downfall);
element.setString("category", category.name().toLowerCase(Locale.ROOT)); element.setString("category", category.name().toLowerCase(Locale.ROOT));
element.setString("precipitation", precipitation.name().toLowerCase(Locale.ROOT)); element.setString("precipitation", precipitation.name().toLowerCase(Locale.ROOT));
if (temperatureModifier != TemperatureModifier.NONE) if (temperatureModifier != TemperatureModifier.NONE)
element.setString("temperature_modifier", temperatureModifier.name().toLowerCase(Locale.ROOT)); element.setString("temperature_modifier", temperatureModifier.name().toLowerCase(Locale.ROOT));
element.set("effects", effects.toNbt()); element.set("effects", effects.toNbt());
nbt.set("element", element); }));
return nbt; });
} }
public int id() { public int id() {

View File

@ -2,9 +2,11 @@ package net.minestom.server.world.biomes;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.NamespaceID;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import java.util.Locale; import java.util.Locale;
import java.util.Map;
public record BiomeEffects(int fogColor, int skyColor, int waterColor, int waterFogColor, int foliageColor, public record BiomeEffects(int fogColor, int skyColor, int waterColor, int waterFogColor, int foliageColor,
int grassColor, int grassColor,
@ -17,26 +19,28 @@ public record BiomeEffects(int fogColor, int skyColor, int waterColor, int water
} }
public NBTCompound toNbt() { public NBTCompound toNbt() {
NBTCompound nbt = new NBTCompound(); return NBT.Compound(nbt -> {
nbt.setInt("fog_color", fogColor); nbt.setInt("fog_color", fogColor);
if (foliageColor != -1) nbt.setInt("foliage_color", foliageColor); if (foliageColor != -1)
if (grassColor != -1) nbt.setInt("grass_color", grassColor); nbt.setInt("foliage_color", foliageColor);
nbt.setInt("sky_color", skyColor); if (grassColor != -1)
nbt.setInt("water_color", waterColor); nbt.setInt("grass_color", grassColor);
nbt.setInt("water_fog_color", waterFogColor); nbt.setInt("sky_color", skyColor);
if (grassColorModifier != null) nbt.setInt("water_color", waterColor);
nbt.setString("grass_color_modifier", grassColorModifier.name().toLowerCase(Locale.ROOT)); nbt.setInt("water_fog_color", waterFogColor);
if (biomeParticle != null) if (grassColorModifier != null)
nbt.set("particle", biomeParticle.toNbt()); nbt.setString("grass_color_modifier", grassColorModifier.name().toLowerCase(Locale.ROOT));
if (ambientSound != null) if (biomeParticle != null)
nbt.setString("ambient_sound", ambientSound.toString()); nbt.set("particle", biomeParticle.toNbt());
if (moodSound != null) if (ambientSound != null)
nbt.set("mood_sound", moodSound.toNbt()); nbt.setString("ambient_sound", ambientSound.toString());
if (additionsSound != null) if (moodSound != null)
nbt.set("additions_sound", additionsSound.toNbt()); nbt.set("mood_sound", moodSound.toNbt());
if (music != null) if (additionsSound != null)
nbt.set("music", music.toNbt()); nbt.set("additions_sound", additionsSound.toNbt());
return nbt; if (music != null)
nbt.set("music", music.toNbt());
});
} }
public enum GrassColorModifier { public enum GrassColorModifier {
@ -45,32 +49,29 @@ public record BiomeEffects(int fogColor, int skyColor, int waterColor, int water
public record MoodSound(NamespaceID sound, int tickDelay, int blockSearchExtent, double offset) { public record MoodSound(NamespaceID sound, int tickDelay, int blockSearchExtent, double offset) {
public @NotNull NBTCompound toNbt() { public @NotNull NBTCompound toNbt() {
NBTCompound nbt = new NBTCompound(); return NBT.Compound(Map.of(
nbt.setString("sound", sound.toString()); "sound", NBT.String(sound.toString()),
nbt.setInt("tick_delay", tickDelay); "tick_delay", NBT.Int(tickDelay),
nbt.setInt("block_search_extent", blockSearchExtent); "block_search_extent", NBT.Int(blockSearchExtent),
nbt.setDouble("offset", offset); "offset", NBT.Double(offset)));
return nbt;
} }
} }
public record AdditionsSound(NamespaceID sound, double tickChance) { public record AdditionsSound(NamespaceID sound, double tickChance) {
public @NotNull NBTCompound toNbt() { public @NotNull NBTCompound toNbt() {
NBTCompound nbt = new NBTCompound(); return NBT.Compound(Map.of(
nbt.setString("sound", sound.toString()); "sound", NBT.String(sound.toString()),
nbt.setDouble("tick_chance", tickChance); "tick_chance", NBT.Double(tickChance)));
return nbt;
} }
} }
public record Music(NamespaceID sound, int minDelay, int maxDelay, boolean replaceCurrentMusic) { public record Music(NamespaceID sound, int minDelay, int maxDelay, boolean replaceCurrentMusic) {
public @NotNull NBTCompound toNbt() { public @NotNull NBTCompound toNbt() {
NBTCompound nbt = new NBTCompound(); return NBT.Compound(Map.of(
nbt.setString("sound", sound.toString()); "sound", NBT.String(sound.toString()),
nbt.setInt("min_delay", minDelay); "min_delay", NBT.Int(minDelay),
nbt.setInt("max_delay", maxDelay); "max_delay", NBT.Int(maxDelay),
nbt.setByte("replace_current_music", replaceCurrentMusic ? (byte) 1 : (byte) 0); "replace_current_music", NBT.Boolean(replaceCurrentMusic)));
return nbt;
} }
} }

View File

@ -3,12 +3,14 @@ package net.minestom.server.world.biomes;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.NamespaceID;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.NBTList; import org.jglrxavpok.hephaistos.nbt.NBTType;
import org.jglrxavpok.hephaistos.nbt.NBTTypes;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Map;
/** /**
* Allows servers to register custom dimensions. Also used during player joining to send the list of all existing dimensions. * Allows servers to register custom dimensions. Also used during player joining to send the list of all existing dimensions.
@ -71,13 +73,8 @@ public final class BiomeManager {
} }
public synchronized NBTCompound toNBT() { public synchronized NBTCompound toNBT() {
NBTCompound biomes = new NBTCompound(); return NBT.Compound(Map.of(
biomes.setString("type", "minecraft:worldgen/biome"); "type", NBT.String("minecraft:worldgen/biome"),
NBTList<NBTCompound> biomesList = new NBTList<>(NBTTypes.TAG_Compound); "value", NBT.List(NBTType.TAG_Compound, biomes.values().stream().map(Biome::toNbt).toList())));
for (Biome biome : this.biomes.values()) {
biomesList.add(biome.toNbt());
}
biomes.set("value", biomesList);
return biomes;
} }
} }

View File

@ -3,16 +3,16 @@ package net.minestom.server.world.biomes;
import net.minestom.server.instance.block.Block; import net.minestom.server.instance.block.Block;
import net.minestom.server.item.ItemStack; import net.minestom.server.item.ItemStack;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.NamespaceID;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import java.util.Map; import java.util.Map;
public record BiomeParticle(float probability, Option option) { public record BiomeParticle(float probability, Option option) {
public NBTCompound toNbt() { public NBTCompound toNbt() {
NBTCompound nbt = new NBTCompound(); return NBT.Compound(Map.of(
nbt.setFloat("probability", probability); "probability", NBT.Float(probability),
nbt.set("options", option.toNbt()); "options", option.toNbt()));
return nbt;
} }
public interface Option { public interface Option {
@ -25,16 +25,16 @@ public record BiomeParticle(float probability, Option option) {
@Override @Override
public NBTCompound toNbt() { public NBTCompound toNbt() {
NBTCompound nbtCompound = new NBTCompound(); return NBT.Compound(nbtCompound -> {
nbtCompound.setString("type", type); nbtCompound.setString("type", type);
nbtCompound.setString("Name", block.name()); nbtCompound.setString("Name", block.name());
Map<String, String> propertiesMap = block.properties(); Map<String, String> propertiesMap = block.properties();
if (propertiesMap.size() != 0) { if (propertiesMap.size() != 0) {
NBTCompound properties = new NBTCompound(); nbtCompound.set("Properties", NBT.Compound(p -> {
propertiesMap.forEach(properties::setString); propertiesMap.forEach(p::setString);
nbtCompound.set("Properties", properties); }));
} }
return nbtCompound; });
} }
} }
@ -43,13 +43,12 @@ public record BiomeParticle(float probability, Option option) {
@Override @Override
public NBTCompound toNbt() { public NBTCompound toNbt() {
NBTCompound nbtCompound = new NBTCompound(); return NBT.Compound(Map.of(
nbtCompound.setString("type", type); "type", NBT.String(type),
nbtCompound.setFloat("r", red); "r", NBT.Float(red),
nbtCompound.setFloat("g", green); "g", NBT.Float(green),
nbtCompound.setFloat("b", blue); "b", NBT.Float(blue),
nbtCompound.setFloat("scale", scale); "scale", NBT.Float(scale)));
return nbtCompound;
} }
} }
@ -60,17 +59,16 @@ public record BiomeParticle(float probability, Option option) {
public NBTCompound toNbt() { public NBTCompound toNbt() {
//todo test count might be wrong type //todo test count might be wrong type
NBTCompound nbtCompound = item.getMeta().toNBT(); NBTCompound nbtCompound = item.getMeta().toNBT();
nbtCompound.setString("type", type); return nbtCompound.modify(n -> {
return nbtCompound; n.setString("type", type);
});
} }
} }
public record NormalOption(NamespaceID type) implements Option { public record NormalOption(NamespaceID type) implements Option {
@Override @Override
public NBTCompound toNbt() { public NBTCompound toNbt() {
NBTCompound nbtCompound = new NBTCompound(); return NBT.Compound(Map.of("type", NBT.String(type.toString())));
nbtCompound.setString("type", type.toString());
return nbtCompound;
} }
} }
} }

View File

@ -10,13 +10,15 @@ import net.minestom.server.tag.TagWritable;
import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.NamespaceID;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.NBTList; import org.jglrxavpok.hephaistos.nbt.NBTList;
import org.jglrxavpok.hephaistos.nbt.NBTTypes; import org.jglrxavpok.hephaistos.nbt.NBTType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
public class CampfireHandler implements BlockHandler { public class CampfireHandler implements BlockHandler {
@ -44,15 +46,16 @@ public class CampfireHandler implements BlockHandler {
writer.removeTag(internal); writer.removeTag(internal);
return; return;
} }
NBTList<NBTCompound> items = new NBTList<>(NBTTypes.TAG_Compound); writer.setTag(internal, NBT.List(
for (var item : value) { NBTType.TAG_Compound,
NBTCompound compound = new NBTCompound() value.stream()
.setByte("Count", (byte) item.getAmount()) .map(item -> NBT.Compound(nbt -> {
.setByte("Slot", (byte) 1) nbt.setByte("Count", (byte) item.getAmount());
.setString("id", item.getMaterial().name()); nbt.setByte("Slot", (byte) 1);
items.add(compound); nbt.setString("id", item.getMaterial().name());
} }))
writer.setTag(internal, items); .toList()
));
} }
}); });

View File

@ -3,6 +3,7 @@ package permissions;
import net.minestom.server.MinecraftServer; import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.Player; import net.minestom.server.entity.Player;
import net.minestom.server.permission.Permission; import net.minestom.server.permission.Permission;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
@ -36,9 +37,11 @@ public class TestPermissions {
}; };
permission1 = new Permission("perm.name", permission1 = new Permission("perm.name",
new NBTCompound() NBT.Compound(nbt -> {
.setString("name", "Minestom") nbt.setString("name", "Minestom");
.setInt("amount", 5)); nbt.setInt("amount", 5);
})
);
permission2 = new Permission("perm.name2"); permission2 = new Permission("perm.name2");
} }

View File

@ -0,0 +1,95 @@
package regressions;
import net.minestom.server.item.ItemMeta;
import net.minestom.server.item.ItemMetaBuilder;
import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.NBTShort;
import org.jglrxavpok.hephaistos.nbt.NBTString;
import org.jglrxavpok.hephaistos.nbt.mutable.MutableNBTCompound;
import org.junit.jupiter.api.Test;
import java.util.function.Consumer;
import java.util.function.Supplier;
import static org.junit.jupiter.api.Assertions.*;
public class ItemMetaBuilderRegressions {
private static class BasicMetaBuilder extends ItemMetaBuilder {
@Override
public @NotNull ItemMeta build() {
return new ItemMeta(this) {};
}
@Override
public void read(@NotNull NBTCompound nbtCompound) {
// don't care
}
@Override
protected @NotNull Supplier<@NotNull ItemMetaBuilder> getSupplier() {
// don't care
return () -> this;
}
@Override
public void handleCompound(@NotNull String key, @NotNull Consumer<@NotNull MutableNBTCompound> consumer) {
super.handleCompound(key, consumer);
}
}
@Test
public void handleCompoundShouldUsePreviousValue() {
BasicMetaBuilder builder = new BasicMetaBuilder();
builder.handleCompound("test", nbt -> {
nbt.setString("my_key", "AAA");
});
NBTCompound nbt = builder.build().toNBT().getCompound("test");
assertTrue(nbt.contains("my_key"));
assertEquals(1, nbt.getSize());
assertTrue(nbt.get("my_key") instanceof NBTString);
assertEquals("AAA", nbt.getString("my_key"));
builder.handleCompound("test", n -> {
n.setString("my_other_key", "BBB");
});
nbt = builder.build().toNBT().getCompound("test");
assertTrue(nbt.contains("my_key"));
assertTrue(nbt.contains("my_other_key"));
assertEquals(2, nbt.getSize());
assertTrue(nbt.get("my_key") instanceof NBTString);
assertTrue(nbt.get("my_other_key") instanceof NBTString);
assertEquals("AAA", nbt.getString("my_key"));
assertEquals("BBB", nbt.getString("my_other_key"));
}
@Test
public void clearingShouldRemoveData() {
BasicMetaBuilder builder = new BasicMetaBuilder();
builder.handleCompound("test", nbt -> {
nbt.setString("my_key", "AAA");
});
NBTCompound nbt = builder.build().toNBT().getCompound("test");
assertTrue(nbt.contains("my_key"));
assertEquals(1, nbt.getSize());
assertTrue(nbt.get("my_key") instanceof NBTString);
assertEquals("AAA", nbt.getString("my_key"));
builder.handleCompound("test", n -> {
n.clear();
});
NBTCompound rootNBT = builder.build().toNBT();
assertFalse(rootNBT.contains("test"));
assertEquals(0, rootNBT.getSize());
}
}