mirror of https://github.com/Minestom/Minestom.git
feat: initial conversion to adventure nbt. no tests, no anvil
This commit is contained in:
parent
54212ebc97
commit
687968eea0
|
@ -72,10 +72,7 @@ dependencies {
|
||||||
api(libs.jetbrainsAnnotations)
|
api(libs.jetbrainsAnnotations)
|
||||||
api(libs.bundles.adventure)
|
api(libs.bundles.adventure)
|
||||||
api(libs.hydrazine)
|
api(libs.hydrazine)
|
||||||
api(libs.bundles.kotlin)
|
|
||||||
api(libs.bundles.hephaistos)
|
|
||||||
implementation(libs.minestomData)
|
implementation(libs.minestomData)
|
||||||
implementation(libs.dependencyGetter)
|
|
||||||
|
|
||||||
// Performance/data structures
|
// Performance/data structures
|
||||||
implementation(libs.caffeine)
|
implementation(libs.caffeine)
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
package net.minestom.demo.block;
|
package net.minestom.demo.block;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.BinaryTag;
|
||||||
|
import net.kyori.adventure.nbt.BinaryTagTypes;
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
|
import net.kyori.adventure.nbt.ListBinaryTag;
|
||||||
import net.minestom.server.instance.block.BlockHandler;
|
import net.minestom.server.instance.block.BlockHandler;
|
||||||
import net.minestom.server.item.ItemStack;
|
import net.minestom.server.item.ItemStack;
|
||||||
import net.minestom.server.item.Material;
|
import net.minestom.server.item.Material;
|
||||||
|
@ -10,10 +14,6 @@ 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.NBTList;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTType;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -22,16 +22,17 @@ import java.util.List;
|
||||||
public class CampfireHandler implements BlockHandler {
|
public class CampfireHandler implements BlockHandler {
|
||||||
|
|
||||||
public static final Tag<List<ItemStack>> ITEMS = Tag.View(new TagSerializer<>() {
|
public static final Tag<List<ItemStack>> ITEMS = Tag.View(new TagSerializer<>() {
|
||||||
private final Tag<NBT> internal = Tag.NBT("Items");
|
private final Tag<BinaryTag> internal = Tag.NBT("Items");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable List<ItemStack> read(@NotNull TagReadable reader) {
|
public @Nullable List<ItemStack> read(@NotNull TagReadable reader) {
|
||||||
NBTList<NBTCompound> item = (NBTList<NBTCompound>) reader.getTag(internal);
|
ListBinaryTag item = (ListBinaryTag) reader.getTag(internal);
|
||||||
if (item == null)
|
if (item == null)
|
||||||
return null;
|
return null;
|
||||||
List<ItemStack> result = new ArrayList<>();
|
List<ItemStack> result = new ArrayList<>();
|
||||||
item.forEach(nbtCompound -> {
|
item.forEach(childTag -> {
|
||||||
int amount = nbtCompound.getAsByte("Count");
|
CompoundBinaryTag nbtCompound = (CompoundBinaryTag) childTag;
|
||||||
|
int amount = nbtCompound.getByte("Count");
|
||||||
String id = nbtCompound.getString("id");
|
String id = nbtCompound.getString("id");
|
||||||
Material material = Material.fromNamespaceId(id);
|
Material material = Material.fromNamespaceId(id);
|
||||||
result.add(ItemStack.of(material, amount));
|
result.add(ItemStack.of(material, amount));
|
||||||
|
@ -45,14 +46,14 @@ public class CampfireHandler implements BlockHandler {
|
||||||
writer.removeTag(internal);
|
writer.removeTag(internal);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
writer.setTag(internal, NBT.List(
|
writer.setTag(internal, ListBinaryTag.listBinaryTag(
|
||||||
NBTType.TAG_Compound,
|
BinaryTagTypes.COMPOUND,
|
||||||
value.stream()
|
value.stream()
|
||||||
.map(item -> NBT.Compound(nbt -> {
|
.map(item -> (BinaryTag) CompoundBinaryTag.builder()
|
||||||
nbt.setByte("Count", (byte) item.amount());
|
.putByte("Count", (byte) item.amount())
|
||||||
nbt.setByte("Slot", (byte) 1);
|
.putByte("Slot", (byte) 1)
|
||||||
nbt.setString("id", item.material().name());
|
.putString("id", item.material().name())
|
||||||
}))
|
.build())
|
||||||
.toList()
|
.toList()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ metadata.format.version = "1.1"
|
||||||
|
|
||||||
# Important dependencies
|
# Important dependencies
|
||||||
data = "1.20.4-rv4"
|
data = "1.20.4-rv4"
|
||||||
adventure = "4.15.0"
|
adventure = "4.16.0"
|
||||||
kotlin = "1.7.22"
|
kotlin = "1.7.22"
|
||||||
dependencyGetter = "v1.0.1"
|
dependencyGetter = "v1.0.1"
|
||||||
hydrazine = "1.7.2"
|
hydrazine = "1.7.2"
|
||||||
|
@ -41,22 +41,16 @@ nexuspublish = "1.3.0"
|
||||||
# Important Dependencies
|
# Important Dependencies
|
||||||
# Adventure
|
# Adventure
|
||||||
adventure-api = { group = "net.kyori", name = "adventure-api", version.ref = "adventure" }
|
adventure-api = { group = "net.kyori", name = "adventure-api", version.ref = "adventure" }
|
||||||
|
adventure-nbt = { group = "net.kyori", name = "adventure-nbt", version.ref = "adventure" }
|
||||||
adventure-serializer-gson = { group = "net.kyori", name = "adventure-text-serializer-gson", version.ref = "adventure" }
|
adventure-serializer-gson = { group = "net.kyori", name = "adventure-text-serializer-gson", version.ref = "adventure" }
|
||||||
adventure-serializer-legacy = { group = "net.kyori", name = "adventure-text-serializer-legacy", version.ref = "adventure" }
|
adventure-serializer-legacy = { group = "net.kyori", name = "adventure-text-serializer-legacy", version.ref = "adventure" }
|
||||||
adventure-serializer-plain = { group = "net.kyori", name = "adventure-text-serializer-plain", version.ref = "adventure" }
|
adventure-serializer-plain = { group = "net.kyori", name = "adventure-text-serializer-plain", version.ref = "adventure" }
|
||||||
adventure-text-logger-slf4j = { group = "net.kyori", name = "adventure-text-logger-slf4j", version.ref = "adventure" }
|
adventure-text-logger-slf4j = { group = "net.kyori", name = "adventure-text-logger-slf4j", version.ref = "adventure" }
|
||||||
|
|
||||||
# Kotlin
|
|
||||||
kotlin-reflect = { group = "org.jetbrains.kotlin", name = "kotlin-reflect", version.ref = "kotlin" }
|
|
||||||
kotlin-stdlib-jdk8 = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk8", version.ref = "kotlin" }
|
|
||||||
|
|
||||||
# Miscellaneous
|
# Miscellaneous
|
||||||
hydrazine = { group = "com.github.MadMartian", name = "hydrazine-path-finding", version.ref = "hydrazine" }
|
hydrazine = { group = "com.github.MadMartian", name = "hydrazine-path-finding", version.ref = "hydrazine" }
|
||||||
minestomData = { group = "net.minestom", name = "data", version.ref = "data" }
|
minestomData = { group = "net.minestom", name = "data", version.ref = "data" }
|
||||||
dependencyGetter = { group = "com.github.Minestom", name = "DependencyGetter", version.ref = "dependencyGetter" }
|
|
||||||
jetbrainsAnnotations = { group = "org.jetbrains", name = "annotations", version.ref = "jetbrainsAnnotations" }
|
jetbrainsAnnotations = { group = "org.jetbrains", name = "annotations", version.ref = "jetbrainsAnnotations" }
|
||||||
hephaistos-common = { group = "io.github.jglrxavpok.hephaistos", name = "common", version.ref = "hephaistos" }
|
|
||||||
hephaistos-gson = { group = "io.github.jglrxavpok.hephaistos", name = "gson", version.ref = "hephaistos" }
|
|
||||||
slf4j = { group = "org.slf4j", name = "slf4j-api", version.ref = "slf4j"}
|
slf4j = { group = "org.slf4j", name = "slf4j-api", version.ref = "slf4j"}
|
||||||
|
|
||||||
# Performance / Data Structures
|
# Performance / Data Structures
|
||||||
|
@ -86,11 +80,9 @@ logback-classic = { group = "ch.qos.logback", name = "logback-classic", version.
|
||||||
|
|
||||||
[bundles]
|
[bundles]
|
||||||
|
|
||||||
kotlin = ["kotlin-stdlib-jdk8", "kotlin-reflect"]
|
|
||||||
flare = ["flare", "flare-fastutil"]
|
flare = ["flare", "flare-fastutil"]
|
||||||
adventure = ["adventure-api", "adventure-serializer-gson", "adventure-serializer-legacy", "adventure-serializer-plain", "adventure-text-logger-slf4j"]
|
adventure = ["adventure-api", "adventure-nbt", "adventure-serializer-gson", "adventure-serializer-legacy", "adventure-serializer-plain", "adventure-text-logger-slf4j"]
|
||||||
junit = ["junit-api", "junit-engine", "junit-params", "junit-suite-api", "junit-suite-engine"]
|
junit = ["junit-api", "junit-engine", "junit-params", "junit-suite-api", "junit-suite-engine"]
|
||||||
hephaistos = ["hephaistos-common", "hephaistos-gson"]
|
|
||||||
logback = ["logback-core", "logback-classic"]
|
logback = ["logback-core", "logback-classic"]
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
|
|
|
@ -1,21 +1,18 @@
|
||||||
package net.minestom.server.adventure;
|
package net.minestom.server.adventure;
|
||||||
|
|
||||||
import java.io.StringReader;
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
|
import net.kyori.adventure.nbt.TagStringIO;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.translation.GlobalTranslator;
|
import net.kyori.adventure.translation.GlobalTranslator;
|
||||||
import net.kyori.adventure.util.Codec;
|
import net.kyori.adventure.util.Codec;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBT;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTException;
|
|
||||||
import org.jglrxavpok.hephaistos.parser.SNBTParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adventure related constants, etc.
|
* Adventure related constants, etc.
|
||||||
*/
|
*/
|
||||||
|
@ -23,8 +20,8 @@ public final class MinestomAdventure {
|
||||||
/**
|
/**
|
||||||
* A codec to convert between strings and NBT.
|
* A codec to convert between strings and NBT.
|
||||||
*/
|
*/
|
||||||
public static final Codec<NBT, String, NBTException, RuntimeException> NBT_CODEC
|
public static final Codec<CompoundBinaryTag, String, IOException, IOException> NBT_CODEC
|
||||||
= Codec.codec(encoded -> new SNBTParser(new StringReader(encoded)).parse(), NBT::toSNBT);
|
= Codec.codec(TagStringIO.get()::asCompound, TagStringIO.get()::asString);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If components should be automatically translated in outgoing packets.
|
* If components should be automatically translated in outgoing packets.
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package net.minestom.server.adventure.provider;
|
package net.minestom.server.adventure.provider;
|
||||||
|
|
||||||
import net.kyori.adventure.key.Key;
|
import net.kyori.adventure.key.Key;
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.kyori.adventure.nbt.api.BinaryTagHolder;
|
import net.kyori.adventure.nbt.api.BinaryTagHolder;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.event.HoverEvent;
|
import net.kyori.adventure.text.event.HoverEvent;
|
||||||
|
@ -9,14 +10,10 @@ import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||||
import net.kyori.adventure.util.Codec;
|
import net.kyori.adventure.util.Codec;
|
||||||
import net.minestom.server.adventure.MinestomAdventure;
|
import net.minestom.server.adventure.MinestomAdventure;
|
||||||
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.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();
|
||||||
|
@ -30,76 +27,46 @@ final class NBTLegacyHoverEventSerializer implements LegacyHoverEventSerializer
|
||||||
@Override
|
@Override
|
||||||
public HoverEvent.@NotNull ShowItem deserializeShowItem(@NotNull Component input) throws IOException {
|
public HoverEvent.@NotNull ShowItem deserializeShowItem(@NotNull Component input) throws IOException {
|
||||||
final String raw = PlainTextComponentSerializer.plainText().serialize(input);
|
final String raw = PlainTextComponentSerializer.plainText().serialize(input);
|
||||||
try {
|
// attempt the parse
|
||||||
// attempt the parse
|
final CompoundBinaryTag contents = MinestomAdventure.NBT_CODEC.decode(raw);
|
||||||
final NBT nbt = MinestomAdventure.NBT_CODEC.decode(raw);
|
final CompoundBinaryTag tag = contents.getCompound(ITEM_TAG);
|
||||||
if (!(nbt instanceof NBTCompound contents)) throw new IOException("contents were not a compound");
|
|
||||||
final NBTCompound tag = contents.getCompound(ITEM_TAG);
|
|
||||||
|
|
||||||
// create the event
|
// create the event
|
||||||
return HoverEvent.ShowItem.showItem(
|
return HoverEvent.ShowItem.showItem(
|
||||||
Key.key(Objects.requireNonNullElse(contents.getString(ITEM_TYPE), "")),
|
Key.key(contents.getString(ITEM_TYPE, "")),
|
||||||
Objects.requireNonNullElse(contents.getByte(ITEM_COUNT), (byte) 1),
|
contents.getByte(ITEM_COUNT, (byte) 1),
|
||||||
tag == null ? null : BinaryTagHolder.encode(tag, MinestomAdventure.NBT_CODEC)
|
tag.size() == 0 ? null : BinaryTagHolder.encode(tag, MinestomAdventure.NBT_CODEC)
|
||||||
);
|
);
|
||||||
} catch (final NBTException e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HoverEvent.@NotNull ShowEntity deserializeShowEntity(@NotNull Component input, Codec.Decoder<Component, String, ? extends RuntimeException> componentDecoder) throws IOException {
|
public HoverEvent.@NotNull ShowEntity deserializeShowEntity(@NotNull Component input, Codec.Decoder<Component, String, ? extends RuntimeException> componentDecoder) throws IOException {
|
||||||
final String raw = PlainTextComponentSerializer.plainText().serialize(input);
|
final String raw = PlainTextComponentSerializer.plainText().serialize(input);
|
||||||
try {
|
final CompoundBinaryTag contents = MinestomAdventure.NBT_CODEC.decode(raw);
|
||||||
final NBT nbt = MinestomAdventure.NBT_CODEC.decode(raw);
|
return HoverEvent.ShowEntity.showEntity(
|
||||||
if (!(nbt instanceof NBTCompound contents)) throw new IOException("contents were not a compound");
|
Key.key(contents.getString(ENTITY_TYPE, "")),
|
||||||
|
UUID.fromString(Objects.requireNonNullElse(contents.getString(ENTITY_ID), "")),
|
||||||
return HoverEvent.ShowEntity.showEntity(
|
componentDecoder.decode(Objects.requireNonNullElse(contents.getString(ENTITY_NAME), ""))
|
||||||
Key.key(Objects.requireNonNullElse(contents.getString(ENTITY_TYPE), "")),
|
);
|
||||||
UUID.fromString(Objects.requireNonNullElse(contents.getString(ENTITY_ID), "")),
|
|
||||||
componentDecoder.decode(Objects.requireNonNullElse(contents.getString(ENTITY_NAME), ""))
|
|
||||||
);
|
|
||||||
} catch (NBTException e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Component serializeShowItem(HoverEvent.@NotNull ShowItem input) throws IOException {
|
public @NotNull Component serializeShowItem(HoverEvent.@NotNull ShowItem input) throws IOException {
|
||||||
AtomicReference<NBTException> exception = new AtomicReference<>(null);
|
CompoundBinaryTag.Builder tag = CompoundBinaryTag.builder();
|
||||||
final NBTCompound tag = NBT.Compound(t -> {
|
tag.putString(ITEM_TYPE, input.item().asString());
|
||||||
t.setString(ITEM_TYPE, input.item().asString());
|
tag.putByte(ITEM_COUNT, (byte) input.count());
|
||||||
t.setByte(ITEM_COUNT, (byte) input.count());
|
final BinaryTagHolder nbt = input.nbt();
|
||||||
|
if (nbt != null) tag.put(ITEM_TAG, nbt.get(MinestomAdventure.NBT_CODEC));
|
||||||
final BinaryTagHolder nbt = input.nbt();
|
return Component.text(MinestomAdventure.NBT_CODEC.encode(tag.build()));
|
||||||
if (nbt != null) {
|
|
||||||
try {
|
|
||||||
t.set(ITEM_TAG, nbt.get(MinestomAdventure.NBT_CODEC));
|
|
||||||
} catch (NBTException e) {
|
|
||||||
exception.set(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (exception.get() != null) {
|
|
||||||
throw new IOException(exception.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
return Component.text(MinestomAdventure.NBT_CODEC.encode(tag));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Component serializeShowEntity(HoverEvent.@NotNull ShowEntity input, Codec.Encoder<Component, String, ? extends RuntimeException> componentEncoder) {
|
public @NotNull Component serializeShowEntity(HoverEvent.@NotNull ShowEntity input, Codec.Encoder<Component, String, ? extends RuntimeException> componentEncoder) throws IOException {
|
||||||
final NBTCompound tag = NBT.Compound(t -> {
|
CompoundBinaryTag.Builder tag = CompoundBinaryTag.builder();
|
||||||
t.setString(ENTITY_ID, input.id().toString());
|
tag.putString(ENTITY_ID, input.id().toString());
|
||||||
t.setString(ENTITY_TYPE, input.type().asString());
|
tag.putString(ENTITY_TYPE, input.type().asString());
|
||||||
|
final Component name = input.name();
|
||||||
final Component name = input.name();
|
if (name != null) tag.putString(ENTITY_NAME, componentEncoder.encode(name));
|
||||||
if (name != null) {
|
return Component.text(MinestomAdventure.NBT_CODEC.encode(tag.build()));
|
||||||
t.setString(ENTITY_NAME, componentEncoder.encode(name));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return Component.text(MinestomAdventure.NBT_CODEC.encode(tag));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package net.minestom.server.adventure.serializer.nbt;
|
package net.minestom.server.adventure.serializer.nbt;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.BinaryTag;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.serializer.ComponentSerializer;
|
import net.kyori.adventure.text.serializer.ComponentSerializer;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBT;
|
|
||||||
|
|
||||||
public interface NbtComponentSerializer extends ComponentSerializer<Component, Component, NBT> {
|
public interface NbtComponentSerializer extends ComponentSerializer<Component, Component, BinaryTag> {
|
||||||
static @NotNull NbtComponentSerializer nbt() {
|
static @NotNull NbtComponentSerializer nbt() {
|
||||||
return NbtComponentSerializerImpl.INSTANCE;
|
return NbtComponentSerializerImpl.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package net.minestom.server.adventure.serializer.nbt;
|
package net.minestom.server.adventure.serializer.nbt;
|
||||||
|
|
||||||
import net.kyori.adventure.key.Key;
|
import net.kyori.adventure.key.Key;
|
||||||
|
import net.kyori.adventure.nbt.*;
|
||||||
import net.kyori.adventure.nbt.api.BinaryTagHolder;
|
import net.kyori.adventure.nbt.api.BinaryTagHolder;
|
||||||
import net.kyori.adventure.text.*;
|
import net.kyori.adventure.text.*;
|
||||||
import net.kyori.adventure.text.event.ClickEvent;
|
import net.kyori.adventure.text.event.ClickEvent;
|
||||||
|
@ -12,14 +13,10 @@ import net.kyori.adventure.text.format.TextDecoration;
|
||||||
import net.minestom.server.utils.validate.Check;
|
import net.minestom.server.utils.validate.Check;
|
||||||
import org.intellij.lang.annotations.Subst;
|
import org.intellij.lang.annotations.Subst;
|
||||||
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.NBTList;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTType;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.mutable.MutableNBTCompound;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
//todo write tests for me!!
|
//todo write tests for me!!
|
||||||
|
@ -27,19 +24,19 @@ final class NbtComponentSerializerImpl implements NbtComponentSerializer {
|
||||||
static final NbtComponentSerializer INSTANCE = new NbtComponentSerializerImpl();
|
static final NbtComponentSerializer INSTANCE = new NbtComponentSerializerImpl();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Component deserialize(@NotNull NBT input) {
|
public @NotNull Component deserialize(@NotNull BinaryTag input) {
|
||||||
return deserializeAnyComponent(input);
|
return deserializeAnyComponent(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull NBT serialize(@NotNull Component component) {
|
public @NotNull BinaryTag serialize(@NotNull Component component) {
|
||||||
return serializeComponent(component);
|
return serializeComponent(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
// DESERIALIZATION
|
// DESERIALIZATION
|
||||||
|
|
||||||
private @NotNull Component deserializeAnyComponent(@NotNull NBT nbt) {
|
private @NotNull Component deserializeAnyComponent(@NotNull BinaryTag nbt) {
|
||||||
if (nbt instanceof NBTCompound compound) {
|
if (nbt instanceof CompoundBinaryTag compound) {
|
||||||
return deserializeComponent(compound);
|
return deserializeComponent(compound);
|
||||||
} else {
|
} else {
|
||||||
//todo raw string + list
|
//todo raw string + list
|
||||||
|
@ -47,12 +44,12 @@ final class NbtComponentSerializerImpl implements NbtComponentSerializer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull Component deserializeComponent(@NotNull NBTCompound compound) {
|
private @NotNull Component deserializeComponent(@NotNull CompoundBinaryTag compound) {
|
||||||
ComponentBuilder<?, ?> builder;
|
ComponentBuilder<?, ?> builder;
|
||||||
var type = compound.getString("type");
|
var type = compound.get("type");
|
||||||
if (type != null) {
|
if (type instanceof StringBinaryTag sType) {
|
||||||
// If type is specified, use that
|
// If type is specified, use that
|
||||||
builder = switch (type) {
|
builder = switch (sType.value()) {
|
||||||
case "text" -> deserializeTextComponent(compound);
|
case "text" -> deserializeTextComponent(compound);
|
||||||
case "translatable" -> deserializeTranslatableComponent(compound);
|
case "translatable" -> deserializeTranslatableComponent(compound);
|
||||||
case "score" -> deserializeScoreComponent(compound);
|
case "score" -> deserializeScoreComponent(compound);
|
||||||
|
@ -63,26 +60,25 @@ final class NbtComponentSerializerImpl implements NbtComponentSerializer {
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
// Try to infer the type from the fields present.
|
// Try to infer the type from the fields present.
|
||||||
if (compound.containsKey("text")) {
|
Set<String> keys = compound.keySet();
|
||||||
|
if (keys.contains("text")) {
|
||||||
builder = deserializeTextComponent(compound);
|
builder = deserializeTextComponent(compound);
|
||||||
} else if (compound.containsKey("translate")) {
|
} else if (keys.contains("translate")) {
|
||||||
builder = deserializeTranslatableComponent(compound);
|
builder = deserializeTranslatableComponent(compound);
|
||||||
} else if (compound.containsKey("score")) {
|
} else if (keys.contains("score")) {
|
||||||
builder = deserializeScoreComponent(compound);
|
builder = deserializeScoreComponent(compound);
|
||||||
} else if (compound.containsKey("selector")) {
|
} else if (keys.contains("selector")) {
|
||||||
builder = deserializeSelectorComponent(compound);
|
builder = deserializeSelectorComponent(compound);
|
||||||
} else if (compound.containsKey("keybind")) {
|
} else if (keys.contains("keybind")) {
|
||||||
builder = deserializeKeybindComponent(compound);
|
builder = deserializeKeybindComponent(compound);
|
||||||
} else if (compound.containsKey("nbt")) {
|
} else if (keys.contains("nbt")) {
|
||||||
builder = deserializeNbtComponent(compound);
|
builder = deserializeNbtComponent(compound);
|
||||||
} else throw new UnsupportedOperationException("Unable to infer component type");
|
} else throw new UnsupportedOperationException("Unable to infer component type");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Children
|
// Children
|
||||||
var extra = compound.getList("extra");
|
var extra = compound.getList("extra", BinaryTagTypes.COMPOUND);
|
||||||
Check.argCondition(extra != null && !extra.getSubtagType().equals(NBTType.TAG_Compound),
|
if (extra.size() > 0) {
|
||||||
"Extra field must be a list of compounds");
|
|
||||||
if (extra != null) {
|
|
||||||
var list = new ArrayList<ComponentLike>();
|
var list = new ArrayList<ComponentLike>();
|
||||||
for (var child : extra) list.add(deserializeAnyComponent(child));
|
for (var child : extra) list.add(deserializeAnyComponent(child));
|
||||||
builder.append(list);
|
builder.append(list);
|
||||||
|
@ -91,7 +87,7 @@ final class NbtComponentSerializerImpl implements NbtComponentSerializer {
|
||||||
// Formatting
|
// Formatting
|
||||||
var style = Style.style();
|
var style = Style.style();
|
||||||
var color = compound.getString("color");
|
var color = compound.getString("color");
|
||||||
if (color != null) {
|
if (!color.isEmpty()) {
|
||||||
var hexColor = TextColor.fromHexString(color);
|
var hexColor = TextColor.fromHexString(color);
|
||||||
if (hexColor != null) {
|
if (hexColor != null) {
|
||||||
style.color(hexColor);
|
style.color(hexColor);
|
||||||
|
@ -105,57 +101,60 @@ final class NbtComponentSerializerImpl implements NbtComponentSerializer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Subst("minecraft:default") var font = compound.getString("font");
|
@Subst("minecraft:default") var font = compound.getString("font");
|
||||||
if (font != null) style.font(Key.key(font));
|
if (!font.isEmpty()) style.font(Key.key(font));
|
||||||
var bold = compound.getByte("bold");
|
BinaryTag bold = compound.get("bold");
|
||||||
if (bold != null) style.decoration(TextDecoration.BOLD, bold == 1 ? TextDecoration.State.TRUE : TextDecoration.State.FALSE);
|
if (bold instanceof ByteBinaryTag b)
|
||||||
var italic = compound.getByte("italic");
|
style.decoration(TextDecoration.BOLD, b.value() == 1 ? TextDecoration.State.TRUE : TextDecoration.State.FALSE);
|
||||||
if (italic != null) style.decoration(TextDecoration.ITALIC, italic == 1 ? TextDecoration.State.TRUE : TextDecoration.State.FALSE);
|
BinaryTag italic = compound.get("italic");
|
||||||
var underlined = compound.getByte("underlined");
|
if (italic instanceof ByteBinaryTag b)
|
||||||
if (underlined != null) style.decoration(TextDecoration.UNDERLINED, underlined == 1 ? TextDecoration.State.TRUE : TextDecoration.State.FALSE);
|
style.decoration(TextDecoration.ITALIC, b.value() == 1 ? TextDecoration.State.TRUE : TextDecoration.State.FALSE);
|
||||||
var strikethrough = compound.getByte("strikethrough");
|
BinaryTag underlined = compound.get("underlined");
|
||||||
if (strikethrough != null) style.decoration(TextDecoration.STRIKETHROUGH, strikethrough == 1 ? TextDecoration.State.TRUE : TextDecoration.State.FALSE);
|
if (underlined instanceof ByteBinaryTag b)
|
||||||
var obfuscated = compound.getByte("obfuscated");
|
style.decoration(TextDecoration.UNDERLINED, b.value() == 1 ? TextDecoration.State.TRUE : TextDecoration.State.FALSE);
|
||||||
if (obfuscated != null) style.decoration(TextDecoration.OBFUSCATED, obfuscated == 1 ? TextDecoration.State.TRUE : TextDecoration.State.FALSE);
|
BinaryTag strikethrough = compound.get("strikethrough");
|
||||||
|
if (strikethrough instanceof ByteBinaryTag b)
|
||||||
|
style.decoration(TextDecoration.STRIKETHROUGH, b.value() == 1 ? TextDecoration.State.TRUE : TextDecoration.State.FALSE);
|
||||||
|
BinaryTag obfuscated = compound.get("obfuscated");
|
||||||
|
if (obfuscated instanceof ByteBinaryTag b)
|
||||||
|
style.decoration(TextDecoration.OBFUSCATED, b.value() == 1 ? TextDecoration.State.TRUE : TextDecoration.State.FALSE);
|
||||||
builder.style(style.build());
|
builder.style(style.build());
|
||||||
|
|
||||||
// Interactivity
|
// Interactivity
|
||||||
var insertion = compound.getString("insertion");
|
var insertion = compound.getString("insertion");
|
||||||
if (insertion != null) builder.insertion(insertion);
|
if (!insertion.isEmpty()) builder.insertion(insertion);
|
||||||
var clickEvent = compound.getCompound("clickEvent");
|
var clickEvent = compound.getCompound("clickEvent");
|
||||||
if (clickEvent != null) builder.clickEvent(deserializeClickEvent(clickEvent));
|
if (clickEvent.size() > 0) builder.clickEvent(deserializeClickEvent(clickEvent));
|
||||||
var hoverEvent = compound.getCompound("hoverEvent");
|
var hoverEvent = compound.getCompound("hoverEvent");
|
||||||
if (hoverEvent != null) builder.hoverEvent(deserializeHoverEvent(hoverEvent));
|
if (hoverEvent.size() > 0) builder.hoverEvent(deserializeHoverEvent(hoverEvent));
|
||||||
|
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull ComponentBuilder<?, ?> deserializeTextComponent(@NotNull NBTCompound compound) {
|
private @NotNull ComponentBuilder<?, ?> deserializeTextComponent(@NotNull CompoundBinaryTag compound) {
|
||||||
var text = compound.getString("text");
|
var text = compound.getString("text");
|
||||||
Check.notNull(text, "Text component must have a text field");
|
Check.notNull(text, "Text component must have a text field");
|
||||||
return Component.text().content(text);
|
return Component.text().content(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull ComponentBuilder<?, ?> deserializeTranslatableComponent(@NotNull NBTCompound compound) {
|
private @NotNull ComponentBuilder<?, ?> deserializeTranslatableComponent(@NotNull CompoundBinaryTag compound) {
|
||||||
var key = compound.getString("translate");
|
var key = compound.getString("translate");
|
||||||
Check.notNull(key, "Translatable component must have a translate field");
|
Check.notNull(key, "Translatable component must have a translate field");
|
||||||
var builder = Component.translatable().key(key);
|
var builder = Component.translatable().key(key);
|
||||||
|
|
||||||
var fallback = compound.getString("fallback");
|
var fallback = compound.get("fallback");
|
||||||
if (fallback != null) builder.fallback(fallback);
|
if (fallback instanceof StringBinaryTag s) builder.fallback(s.value());
|
||||||
|
|
||||||
NBTList<NBTCompound> args = compound.getList("with");
|
ListBinaryTag args = compound.getList("with", BinaryTagTypes.COMPOUND);
|
||||||
Check.argCondition(args != null && !args.getSubtagType().equals(NBTType.TAG_Compound),
|
if (args.size() > 0) {
|
||||||
"Translatable component with field must be a list of compounds");
|
|
||||||
if (args != null) {
|
|
||||||
var list = new ArrayList<ComponentLike>();
|
var list = new ArrayList<ComponentLike>();
|
||||||
for (var arg : args) list.add(deserializeComponent(arg));
|
for (var arg : args) list.add(deserializeComponent((CompoundBinaryTag) arg));
|
||||||
builder.arguments(list);
|
builder.arguments(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull ComponentBuilder<?, ?> deserializeScoreComponent(@NotNull NBTCompound compound) {
|
private @NotNull ComponentBuilder<?, ?> deserializeScoreComponent(@NotNull CompoundBinaryTag compound) {
|
||||||
var scoreCompound = compound.getCompound("score");
|
var scoreCompound = compound.getCompound("score");
|
||||||
Check.notNull(scoreCompound, "Score component must have a score field");
|
Check.notNull(scoreCompound, "Score component must have a score field");
|
||||||
var name = scoreCompound.getString("name");
|
var name = scoreCompound.getString("name");
|
||||||
|
@ -165,14 +164,14 @@ final class NbtComponentSerializerImpl implements NbtComponentSerializer {
|
||||||
var builder = Component.score().name(name).objective(objective);
|
var builder = Component.score().name(name).objective(objective);
|
||||||
|
|
||||||
var value = scoreCompound.getString("value");
|
var value = scoreCompound.getString("value");
|
||||||
if (value != null)
|
if (!value.isEmpty())
|
||||||
//noinspection deprecation
|
//noinspection deprecation
|
||||||
builder.value(value);
|
builder.value(value);
|
||||||
|
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull ComponentBuilder<?, ?> deserializeSelectorComponent(@NotNull NBTCompound compound) {
|
private @NotNull ComponentBuilder<?, ?> deserializeSelectorComponent(@NotNull CompoundBinaryTag compound) {
|
||||||
var selector = compound.getString("selector");
|
var selector = compound.getString("selector");
|
||||||
Check.notNull(selector, "Selector component must have a selector field");
|
Check.notNull(selector, "Selector component must have a selector field");
|
||||||
var builder = Component.selector().pattern(selector);
|
var builder = Component.selector().pattern(selector);
|
||||||
|
@ -183,17 +182,17 @@ final class NbtComponentSerializerImpl implements NbtComponentSerializer {
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull ComponentBuilder<?, ?> deserializeKeybindComponent(@NotNull NBTCompound compound) {
|
private @NotNull ComponentBuilder<?, ?> deserializeKeybindComponent(@NotNull CompoundBinaryTag compound) {
|
||||||
var keybind = compound.getString("keybind");
|
var keybind = compound.getString("keybind");
|
||||||
Check.notNull(keybind, "Keybind component must have a keybind field");
|
Check.notNull(keybind, "Keybind component must have a keybind field");
|
||||||
return Component.keybind().keybind(keybind);
|
return Component.keybind().keybind(keybind);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull ComponentBuilder<?, ?> deserializeNbtComponent(@NotNull NBTCompound compound) {
|
private @NotNull ComponentBuilder<?, ?> deserializeNbtComponent(@NotNull CompoundBinaryTag compound) {
|
||||||
throw new UnsupportedOperationException("NBTComponent is not implemented yet");
|
throw new UnsupportedOperationException("NBTComponent is not implemented yet");
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull ClickEvent deserializeClickEvent(@NotNull NBTCompound compound) {
|
private @NotNull ClickEvent deserializeClickEvent(@NotNull CompoundBinaryTag compound) {
|
||||||
var actionName = compound.getString("action");
|
var actionName = compound.getString("action");
|
||||||
Check.notNull(actionName, "Click event must have an action field");
|
Check.notNull(actionName, "Click event must have an action field");
|
||||||
var action = ClickEvent.Action.NAMES.value(actionName);
|
var action = ClickEvent.Action.NAMES.value(actionName);
|
||||||
|
@ -203,7 +202,7 @@ final class NbtComponentSerializerImpl implements NbtComponentSerializer {
|
||||||
return ClickEvent.clickEvent(action, value);
|
return ClickEvent.clickEvent(action, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull HoverEvent<?> deserializeHoverEvent(@NotNull NBTCompound compound) {
|
private @NotNull HoverEvent<?> deserializeHoverEvent(@NotNull CompoundBinaryTag compound) {
|
||||||
var actionName = compound.getString("action");
|
var actionName = compound.getString("action");
|
||||||
Check.notNull(actionName, "Hover event must have an action field");
|
Check.notNull(actionName, "Hover event must have an action field");
|
||||||
var contents = compound.getCompound("contents");
|
var contents = compound.getCompound("contents");
|
||||||
|
@ -216,13 +215,12 @@ final class NbtComponentSerializerImpl implements NbtComponentSerializer {
|
||||||
@Subst("minecraft:stick") var id = contents.getString("id");
|
@Subst("minecraft:stick") var id = contents.getString("id");
|
||||||
Check.notNull(id, "Show item hover event must have an id field");
|
Check.notNull(id, "Show item hover event must have an id field");
|
||||||
var count = contents.getInt("count");
|
var count = contents.getInt("count");
|
||||||
var countInt = count == null ? 1 : count;
|
|
||||||
var tag = contents.getString("tag");
|
var tag = contents.getString("tag");
|
||||||
var binaryTag = tag == null ? null : BinaryTagHolder.binaryTagHolder(tag);
|
var binaryTag = tag.isEmpty() ? null : BinaryTagHolder.binaryTagHolder(tag);
|
||||||
return HoverEvent.showItem(Key.key(id), countInt, binaryTag);
|
return HoverEvent.showItem(Key.key(id), count, binaryTag);
|
||||||
} else if (action == HoverEvent.Action.SHOW_ENTITY) {
|
} else if (action == HoverEvent.Action.SHOW_ENTITY) {
|
||||||
var name = contents.getCompound("name");
|
var name = contents.getCompound("name");
|
||||||
var nameComponent = name == null ? null : deserializeComponent(name);
|
var nameComponent = name.size() == 0 ? null : deserializeComponent(name);
|
||||||
@Subst("minecraft:pig") var type = contents.getString("type");
|
@Subst("minecraft:pig") var type = contents.getString("type");
|
||||||
Check.notNull(type, "Show entity hover event must have a type field");
|
Check.notNull(type, "Show entity hover event must have a type field");
|
||||||
var id = contents.getString("id");
|
var id = contents.getString("id");
|
||||||
|
@ -235,36 +233,36 @@ final class NbtComponentSerializerImpl implements NbtComponentSerializer {
|
||||||
|
|
||||||
// SERIALIZATION
|
// SERIALIZATION
|
||||||
|
|
||||||
private @NotNull NBT serializeComponent(@NotNull Component component) {
|
private @NotNull CompoundBinaryTag serializeComponent(@NotNull Component component) {
|
||||||
MutableNBTCompound compound = new MutableNBTCompound();
|
CompoundBinaryTag.Builder compound = CompoundBinaryTag.builder();
|
||||||
|
|
||||||
// Base component types
|
// Base component types
|
||||||
if (component instanceof TextComponent text) {
|
if (component instanceof TextComponent text) {
|
||||||
compound.setString("type", "text");
|
compound.putString("type", "text");
|
||||||
compound.setString("text", text.content());
|
compound.putString("text", text.content());
|
||||||
} else if (component instanceof TranslatableComponent translatable) {
|
} else if (component instanceof TranslatableComponent translatable) {
|
||||||
compound.setString("type", "translatable");
|
compound.putString("type", "translatable");
|
||||||
compound.setString("translate", translatable.key());
|
compound.putString("translate", translatable.key());
|
||||||
var fallback = translatable.fallback();
|
var fallback = translatable.fallback();
|
||||||
if (fallback != null) compound.setString("fallback", fallback);
|
if (fallback != null) compound.putString("fallback", fallback);
|
||||||
var args = translatable.arguments();
|
var args = translatable.arguments();
|
||||||
if (!args.isEmpty()) compound.set("with", serializeTranslationArgs(args));
|
if (!args.isEmpty()) compound.put("with", serializeTranslationArgs(args));
|
||||||
} else if (component instanceof ScoreComponent score) {
|
} else if (component instanceof ScoreComponent score) {
|
||||||
compound.setString("type", "score");
|
compound.putString("type", "score");
|
||||||
var scoreCompound = new MutableNBTCompound();
|
CompoundBinaryTag.Builder scoreCompound = CompoundBinaryTag.builder();
|
||||||
scoreCompound.setString("name", score.name());
|
scoreCompound.putString("name", score.name());
|
||||||
scoreCompound.setString("objective", score.objective());
|
scoreCompound.putString("objective", score.objective());
|
||||||
@SuppressWarnings("deprecation") var value = score.value();
|
@SuppressWarnings("deprecation") var value = score.value();
|
||||||
if (value != null) scoreCompound.setString("value", value);
|
if (value != null) scoreCompound.putString("value", value);
|
||||||
compound.set("score", scoreCompound.toCompound());
|
compound.put("score", scoreCompound.build());
|
||||||
} else if (component instanceof SelectorComponent selector) {
|
} else if (component instanceof SelectorComponent selector) {
|
||||||
compound.setString("type", "selector");
|
compound.putString("type", "selector");
|
||||||
compound.setString("selector", selector.pattern());
|
compound.putString("selector", selector.pattern());
|
||||||
var separator = selector.separator();
|
var separator = selector.separator();
|
||||||
if (separator != null) compound.set("separator", serializeComponent(separator));
|
if (separator != null) compound.put("separator", serializeComponent(separator));
|
||||||
} else if (component instanceof KeybindComponent keybind) {
|
} else if (component instanceof KeybindComponent keybind) {
|
||||||
compound.setString("type", "keybind");
|
compound.putString("type", "keybind");
|
||||||
compound.setString("keybind", keybind.keybind());
|
compound.putString("keybind", keybind.keybind());
|
||||||
} else if (component instanceof NBTComponent<?, ?> nbt) {
|
} else if (component instanceof NBTComponent<?, ?> nbt) {
|
||||||
//todo
|
//todo
|
||||||
throw new UnsupportedOperationException("NBTComponent is not implemented yet");
|
throw new UnsupportedOperationException("NBTComponent is not implemented yet");
|
||||||
|
@ -274,10 +272,10 @@ final class NbtComponentSerializerImpl implements NbtComponentSerializer {
|
||||||
|
|
||||||
// Children
|
// Children
|
||||||
if (!component.children().isEmpty()) {
|
if (!component.children().isEmpty()) {
|
||||||
var children = new ArrayList<NBT>();
|
ListBinaryTag.Builder<CompoundBinaryTag> children = ListBinaryTag.builder(BinaryTagTypes.COMPOUND);
|
||||||
for (var child : component.children())
|
for (var child : component.children())
|
||||||
children.add(serializeComponent(child));
|
children.add(serializeComponent(child));
|
||||||
compound.set("extra", new NBTList<>(NBTType.TAG_Compound, children));
|
compound.put("extra", children.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Formatting
|
// Formatting
|
||||||
|
@ -285,94 +283,89 @@ final class NbtComponentSerializerImpl implements NbtComponentSerializer {
|
||||||
var color = style.color();
|
var color = style.color();
|
||||||
if (color != null) {
|
if (color != null) {
|
||||||
if (color instanceof NamedTextColor named) {
|
if (color instanceof NamedTextColor named) {
|
||||||
compound.setString("color", named.toString());
|
compound.putString("color", named.toString());
|
||||||
} else {
|
} else {
|
||||||
compound.setString("color", color.asHexString());
|
compound.putString("color", color.asHexString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var font = style.font();
|
var font = style.font();
|
||||||
if (font != null)
|
if (font != null)
|
||||||
compound.setString("font", font.toString());
|
compound.putString("font", font.toString());
|
||||||
var bold = style.decoration(TextDecoration.BOLD);
|
var bold = style.decoration(TextDecoration.BOLD);
|
||||||
if (bold != TextDecoration.State.NOT_SET)
|
if (bold != TextDecoration.State.NOT_SET)
|
||||||
setBool(compound, "bold", bold == TextDecoration.State.TRUE);
|
compound.putBoolean("bold", bold == TextDecoration.State.TRUE);
|
||||||
var italic = style.decoration(TextDecoration.ITALIC);
|
var italic = style.decoration(TextDecoration.ITALIC);
|
||||||
if (italic != TextDecoration.State.NOT_SET)
|
if (italic != TextDecoration.State.NOT_SET)
|
||||||
setBool(compound, "italic", italic == TextDecoration.State.TRUE);
|
compound.putBoolean("italic", italic == TextDecoration.State.TRUE);
|
||||||
var underlined = style.decoration(TextDecoration.UNDERLINED);
|
var underlined = style.decoration(TextDecoration.UNDERLINED);
|
||||||
if (underlined != TextDecoration.State.NOT_SET)
|
if (underlined != TextDecoration.State.NOT_SET)
|
||||||
setBool(compound, "underlined", underlined == TextDecoration.State.TRUE);
|
compound.putBoolean("underlined", underlined == TextDecoration.State.TRUE);
|
||||||
var strikethrough = style.decoration(TextDecoration.STRIKETHROUGH);
|
var strikethrough = style.decoration(TextDecoration.STRIKETHROUGH);
|
||||||
if (strikethrough != TextDecoration.State.NOT_SET)
|
if (strikethrough != TextDecoration.State.NOT_SET)
|
||||||
setBool(compound, "strikethrough", strikethrough == TextDecoration.State.TRUE);
|
compound.putBoolean("strikethrough", strikethrough == TextDecoration.State.TRUE);
|
||||||
var obfuscated = style.decoration(TextDecoration.OBFUSCATED);
|
var obfuscated = style.decoration(TextDecoration.OBFUSCATED);
|
||||||
if (obfuscated != TextDecoration.State.NOT_SET)
|
if (obfuscated != TextDecoration.State.NOT_SET)
|
||||||
setBool(compound, "obfuscated", obfuscated == TextDecoration.State.TRUE);
|
compound.putBoolean("obfuscated", obfuscated == TextDecoration.State.TRUE);
|
||||||
|
|
||||||
// Interactivity
|
// Interactivity
|
||||||
var insertion = component.insertion();
|
var insertion = component.insertion();
|
||||||
if (insertion != null) compound.setString("insertion", insertion);
|
if (insertion != null) compound.putString("insertion", insertion);
|
||||||
var clickEvent = component.clickEvent();
|
var clickEvent = component.clickEvent();
|
||||||
if (clickEvent != null) compound.set("clickEvent", serializeClickEvent(clickEvent));
|
if (clickEvent != null) compound.put("clickEvent", serializeClickEvent(clickEvent));
|
||||||
var hoverEvent = component.hoverEvent();
|
var hoverEvent = component.hoverEvent();
|
||||||
if (hoverEvent != null) compound.set("hoverEvent", serializeHoverEvent(hoverEvent));
|
if (hoverEvent != null) compound.put("hoverEvent", serializeHoverEvent(hoverEvent));
|
||||||
|
|
||||||
return compound.toCompound();
|
return compound.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull NBT serializeTranslationArgs(@NotNull Collection<TranslationArgument> args) {
|
private @NotNull BinaryTag serializeTranslationArgs(@NotNull Collection<TranslationArgument> args) {
|
||||||
var list = new ArrayList<NBT>();
|
ListBinaryTag.Builder<CompoundBinaryTag> argList = ListBinaryTag.builder(BinaryTagTypes.COMPOUND);
|
||||||
for (var arg : args)
|
for (var arg : args)
|
||||||
list.add(serializeComponent(arg.asComponent()));
|
argList.add(serializeComponent(arg.asComponent()));
|
||||||
return new NBTList<>(NBTType.TAG_Compound, list);
|
return argList.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull NBT serializeClickEvent(@NotNull ClickEvent event) {
|
private @NotNull BinaryTag serializeClickEvent(@NotNull ClickEvent event) {
|
||||||
var compound = new MutableNBTCompound();
|
return CompoundBinaryTag.builder()
|
||||||
compound.setString("action", event.action().toString());
|
.putString("action", event.action().toString())
|
||||||
compound.setString("value", event.value());
|
.putString("value", event.value())
|
||||||
return compound.toCompound();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private @NotNull NBT serializeHoverEvent(@NotNull HoverEvent<?> event) {
|
private @NotNull BinaryTag serializeHoverEvent(@NotNull HoverEvent<?> event) {
|
||||||
var compound = new MutableNBTCompound();
|
CompoundBinaryTag.Builder compound = CompoundBinaryTag.builder();
|
||||||
|
|
||||||
//todo surely there is a better way to do this?
|
//todo surely there is a better way to do this?
|
||||||
compound.setString("action", event.action().toString());
|
compound.putString("action", event.action().toString());
|
||||||
if (event.action() == HoverEvent.Action.SHOW_TEXT) {
|
if (event.action() == HoverEvent.Action.SHOW_TEXT) {
|
||||||
var value = ((HoverEvent<Component>) event).value();
|
var value = ((HoverEvent<Component>) event).value();
|
||||||
compound.set("contents", serializeComponent(value));
|
compound.put("contents", serializeComponent(value));
|
||||||
} else if (event.action() == HoverEvent.Action.SHOW_ITEM) {
|
} else if (event.action() == HoverEvent.Action.SHOW_ITEM) {
|
||||||
var value = ((HoverEvent<HoverEvent.ShowItem>) event).value();
|
var value = ((HoverEvent<HoverEvent.ShowItem>) event).value();
|
||||||
|
|
||||||
var itemCompound = new MutableNBTCompound();
|
CompoundBinaryTag.Builder itemCompound = CompoundBinaryTag.builder();
|
||||||
itemCompound.setString("id", value.item().asString());
|
itemCompound.putString("id", value.item().asString());
|
||||||
if (value.count() != 1) itemCompound.setInt("count", value.count());
|
if (value.count() != 1) itemCompound.putInt("count", value.count());
|
||||||
var tag = value.nbt();
|
var tag = value.nbt();
|
||||||
if (tag != null) itemCompound.setString("tag", tag.string());
|
if (tag != null) itemCompound.putString("tag", tag.string());
|
||||||
|
|
||||||
compound.set("contents", itemCompound.toCompound());
|
compound.put("contents", itemCompound.build());
|
||||||
} else if (event.action() == HoverEvent.Action.SHOW_ENTITY) {
|
} else if (event.action() == HoverEvent.Action.SHOW_ENTITY) {
|
||||||
var value = ((HoverEvent<HoverEvent.ShowEntity>) event).value();
|
var value = ((HoverEvent<HoverEvent.ShowEntity>) event).value();
|
||||||
|
|
||||||
var entityCompound = new MutableNBTCompound();
|
CompoundBinaryTag.Builder entityCompound = CompoundBinaryTag.builder();
|
||||||
var name = value.name();
|
var name = value.name();
|
||||||
if (name != null) entityCompound.set("name", serializeComponent(name));
|
if (name != null) entityCompound.put("name", serializeComponent(name));
|
||||||
entityCompound.setString("type", value.type().asString());
|
entityCompound.putString("type", value.type().asString());
|
||||||
entityCompound.setString("id", value.id().toString());
|
entityCompound.putString("id", value.id().toString());
|
||||||
|
|
||||||
compound.set("contents", entityCompound.toCompound());
|
compound.put("contents", entityCompound.build());
|
||||||
} else {
|
} else {
|
||||||
throw new UnsupportedOperationException("Unknown hover event action: " + event.action());
|
throw new UnsupportedOperationException("Unknown hover event action: " + event.action());
|
||||||
}
|
}
|
||||||
|
|
||||||
return compound.toCompound();
|
return compound.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setBool(@NotNull MutableNBTCompound compound, @NotNull String key, boolean value) {
|
|
||||||
compound.setByte(key, value ? (byte) 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
package net.minestom.server.command.builder.arguments.minecraft;
|
package net.minestom.server.command.builder.arguments.minecraft;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
|
import net.kyori.adventure.nbt.TagStringIO;
|
||||||
import net.minestom.server.command.CommandSender;
|
import net.minestom.server.command.CommandSender;
|
||||||
import net.minestom.server.command.builder.arguments.Argument;
|
import net.minestom.server.command.builder.arguments.Argument;
|
||||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||||
import net.minestom.server.item.ItemStack;
|
import net.minestom.server.item.ItemStack;
|
||||||
import net.minestom.server.item.Material;
|
import net.minestom.server.item.Material;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTException;
|
|
||||||
import org.jglrxavpok.hephaistos.parser.SNBTParser;
|
|
||||||
|
|
||||||
import java.io.StringReader;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Argument which can be used to retrieve an {@link ItemStack} from its material and with NBT data.
|
* Argument which can be used to retrieve an {@link ItemStack} from its material and with NBT data.
|
||||||
|
@ -65,10 +64,10 @@ public class ArgumentItemStack extends Argument<ItemStack> {
|
||||||
|
|
||||||
final String sNBT = input.substring(nbtIndex).replace("\\\"", "\"");
|
final String sNBT = input.substring(nbtIndex).replace("\\\"", "\"");
|
||||||
|
|
||||||
NBTCompound compound;
|
CompoundBinaryTag compound;
|
||||||
try {
|
try {
|
||||||
compound = (NBTCompound) new SNBTParser(new StringReader(sNBT)).parse();
|
compound = TagStringIO.get().asCompound(sNBT);
|
||||||
} catch (NBTException e) {
|
} catch (IOException e) {
|
||||||
throw new ArgumentSyntaxException("Item NBT is invalid", input, INVALID_NBT);
|
throw new ArgumentSyntaxException("Item NBT is invalid", input, INVALID_NBT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,21 @@
|
||||||
package net.minestom.server.command.builder.arguments.minecraft;
|
package net.minestom.server.command.builder.arguments.minecraft;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.BinaryTag;
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
|
import net.kyori.adventure.nbt.TagStringIO;
|
||||||
import net.minestom.server.command.CommandSender;
|
import net.minestom.server.command.CommandSender;
|
||||||
import net.minestom.server.command.builder.arguments.Argument;
|
import net.minestom.server.command.builder.arguments.Argument;
|
||||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||||
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.NBTException;
|
|
||||||
import org.jglrxavpok.hephaistos.parser.SNBTParser;
|
|
||||||
|
|
||||||
import java.io.StringReader;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Argument used to retrieve a {@link NBTCompound} if you need key-value data.
|
* Argument used to retrieve a {@link CompoundBinaryTag} if you need key-value data.
|
||||||
* <p>
|
* <p>
|
||||||
* Example: {display:{Name:"{\"text\":\"Sword of Power\"}"}}
|
* Example: {display:{Name:"{\"text\":\"Sword of Power\"}"}}
|
||||||
*/
|
*/
|
||||||
public class ArgumentNbtCompoundTag extends Argument<NBTCompound> {
|
public class ArgumentNbtCompoundTag extends Argument<CompoundBinaryTag> {
|
||||||
|
|
||||||
public static final int INVALID_NBT = 1;
|
public static final int INVALID_NBT = 1;
|
||||||
|
|
||||||
|
@ -26,15 +25,15 @@ public class ArgumentNbtCompoundTag extends Argument<NBTCompound> {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public NBTCompound parse(@NotNull CommandSender sender, @NotNull String input) throws ArgumentSyntaxException {
|
public CompoundBinaryTag parse(@NotNull CommandSender sender, @NotNull String input) throws ArgumentSyntaxException {
|
||||||
try {
|
try {
|
||||||
NBT nbt = new SNBTParser(new StringReader(input)).parse();
|
BinaryTag nbt = TagStringIO.get().asCompound(input);
|
||||||
|
|
||||||
if (!(nbt instanceof NBTCompound))
|
if (!(nbt instanceof CompoundBinaryTag compound))
|
||||||
throw new ArgumentSyntaxException("NBTCompound is invalid", input, INVALID_NBT);
|
throw new ArgumentSyntaxException("NBTCompound is invalid", input, INVALID_NBT);
|
||||||
|
|
||||||
return (NBTCompound) nbt;
|
return compound;
|
||||||
} catch (NBTException e) {
|
} catch (IOException e) {
|
||||||
throw new ArgumentSyntaxException("NBTCompound is invalid", input, INVALID_NBT);
|
throw new ArgumentSyntaxException("NBTCompound is invalid", input, INVALID_NBT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,22 @@
|
||||||
package net.minestom.server.command.builder.arguments.minecraft;
|
package net.minestom.server.command.builder.arguments.minecraft;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.BinaryTag;
|
||||||
|
import net.kyori.adventure.nbt.TagStringIO;
|
||||||
import net.minestom.server.command.CommandSender;
|
import net.minestom.server.command.CommandSender;
|
||||||
import net.minestom.server.command.builder.arguments.Argument;
|
import net.minestom.server.command.builder.arguments.Argument;
|
||||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBT;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTException;
|
|
||||||
import org.jglrxavpok.hephaistos.parser.SNBTParser;
|
|
||||||
|
|
||||||
import java.io.StringReader;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Argument used to retrieve a {@link NBT} based object, can be any kind of tag like
|
* Argument used to retrieve a {@link BinaryTag} based object, can be any kind of tag like
|
||||||
* {@link org.jglrxavpok.hephaistos.nbt.NBTCompound}, {@link org.jglrxavpok.hephaistos.nbt.NBTList},
|
* {@link net.kyori.adventure.nbt.CompoundBinaryTag}, {@link net.kyori.adventure.nbt.ListBinaryTag},
|
||||||
* {@link org.jglrxavpok.hephaistos.nbt.NBTInt}, etc...
|
* {@link net.kyori.adventure.nbt.IntBinaryTag}, etc...
|
||||||
* <p>
|
* <p>
|
||||||
* Example: {display:{Name:"{\"text\":\"Sword of Power\"}"}} or [{display:{Name:"{\"text\":\"Sword of Power\"}"}}]
|
* Example: {display:{Name:"{\"text\":\"Sword of Power\"}"}} or [{display:{Name:"{\"text\":\"Sword of Power\"}"}}]
|
||||||
*/
|
*/
|
||||||
public class ArgumentNbtTag extends Argument<NBT> {
|
public class ArgumentNbtTag extends Argument<BinaryTag> {
|
||||||
|
|
||||||
public static final int INVALID_NBT = 1;
|
public static final int INVALID_NBT = 1;
|
||||||
|
|
||||||
|
@ -27,10 +26,10 @@ public class ArgumentNbtTag extends Argument<NBT> {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public NBT parse(@NotNull CommandSender sender, @NotNull String input) throws ArgumentSyntaxException {
|
public BinaryTag parse(@NotNull CommandSender sender, @NotNull String input) throws ArgumentSyntaxException {
|
||||||
try {
|
try {
|
||||||
return new SNBTParser(new StringReader(input)).parse();
|
return TagStringIO.get().asCompound(input);
|
||||||
} catch (NBTException e) {
|
} catch (IOException e) {
|
||||||
throw new ArgumentSyntaxException("Invalid NBT", input, INVALID_NBT);
|
throw new ArgumentSyntaxException("Invalid NBT", input, INVALID_NBT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package net.minestom.server.entity;
|
package net.minestom.server.entity;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.BinaryTag;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.minestom.server.coordinate.Point;
|
import net.minestom.server.coordinate.Point;
|
||||||
import net.minestom.server.entity.metadata.animal.FrogMeta;
|
import net.minestom.server.entity.metadata.animal.FrogMeta;
|
||||||
|
@ -15,7 +16,6 @@ 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.jetbrains.annotations.UnknownNullability;
|
import org.jetbrains.annotations.UnknownNullability;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBT;
|
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
import java.lang.invoke.VarHandle;
|
import java.lang.invoke.VarHandle;
|
||||||
|
@ -89,7 +89,7 @@ public final class Metadata {
|
||||||
return new MetadataImpl.EntryImpl<>(TYPE_OPTBLOCKSTATE, value, NetworkBuffer.OPT_BLOCK_STATE);
|
return new MetadataImpl.EntryImpl<>(TYPE_OPTBLOCKSTATE, value, NetworkBuffer.OPT_BLOCK_STATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Entry<NBT> NBT(@NotNull NBT nbt) {
|
public static Entry<BinaryTag> NBT(@NotNull BinaryTag nbt) {
|
||||||
return new MetadataImpl.EntryImpl<>(TYPE_NBT, nbt, NetworkBuffer.NBT);
|
return new MetadataImpl.EntryImpl<>(TYPE_NBT, nbt, NetworkBuffer.NBT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package net.minestom.server.entity;
|
package net.minestom.server.entity;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.EndBinaryTag;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.minestom.server.coordinate.Vec;
|
import net.minestom.server.coordinate.Vec;
|
||||||
import net.minestom.server.entity.metadata.animal.FrogMeta;
|
import net.minestom.server.entity.metadata.animal.FrogMeta;
|
||||||
|
@ -13,7 +14,6 @@ import net.minestom.server.utils.Direction;
|
||||||
import net.minestom.server.utils.collection.ObjectArray;
|
import net.minestom.server.utils.collection.ObjectArray;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.UnknownNullability;
|
import org.jetbrains.annotations.UnknownNullability;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTEnd;
|
|
||||||
|
|
||||||
import static net.minestom.server.entity.Metadata.*;
|
import static net.minestom.server.entity.Metadata.*;
|
||||||
import static net.minestom.server.network.NetworkBuffer.VAR_INT;
|
import static net.minestom.server.network.NetworkBuffer.VAR_INT;
|
||||||
|
@ -38,7 +38,7 @@ final class MetadataImpl {
|
||||||
EMPTY_VALUES.set(TYPE_OPTUUID, OptUUID(null));
|
EMPTY_VALUES.set(TYPE_OPTUUID, OptUUID(null));
|
||||||
EMPTY_VALUES.set(TYPE_BLOCKSTATE, BlockState(Block.AIR.id()));
|
EMPTY_VALUES.set(TYPE_BLOCKSTATE, BlockState(Block.AIR.id()));
|
||||||
EMPTY_VALUES.set(TYPE_OPTBLOCKSTATE, OptBlockState(null));
|
EMPTY_VALUES.set(TYPE_OPTBLOCKSTATE, OptBlockState(null));
|
||||||
EMPTY_VALUES.set(TYPE_NBT, NBT(NBTEnd.INSTANCE));
|
EMPTY_VALUES.set(TYPE_NBT, NBT(EndBinaryTag.endBinaryTag()));
|
||||||
//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));
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package net.minestom.server.entity.damage;
|
package net.minestom.server.entity.damage;
|
||||||
|
|
||||||
import net.minestom.server.registry.StaticProtocolObject;
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.minestom.server.registry.Registry;
|
import net.minestom.server.registry.Registry;
|
||||||
|
import net.minestom.server.registry.StaticProtocolObject;
|
||||||
import net.minestom.server.utils.NamespaceID;
|
import net.minestom.server.utils.NamespaceID;
|
||||||
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.NBTCompound;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ public sealed interface DamageType extends StaticProtocolObject, DamageTypes per
|
||||||
return registry().scaling();
|
return registry().scaling();
|
||||||
}
|
}
|
||||||
|
|
||||||
NBTCompound asNBT();
|
CompoundBinaryTag asNBT();
|
||||||
|
|
||||||
static @NotNull Collection<@NotNull DamageType> values() {
|
static @NotNull Collection<@NotNull DamageType> values() {
|
||||||
return DamageTypeImpl.values();
|
return DamageTypeImpl.values();
|
||||||
|
@ -54,7 +54,7 @@ public sealed interface DamageType extends StaticProtocolObject, DamageTypes per
|
||||||
return DamageTypeImpl.getId(id);
|
return DamageTypeImpl.getId(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static NBTCompound getNBT() {
|
static CompoundBinaryTag getNBT() {
|
||||||
return DamageTypeImpl.getNBT();
|
return DamageTypeImpl.getNBT();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,14 +1,12 @@
|
||||||
package net.minestom.server.entity.damage;
|
package net.minestom.server.entity.damage;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.BinaryTagTypes;
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
|
import net.kyori.adventure.nbt.ListBinaryTag;
|
||||||
import net.minestom.server.registry.Registry;
|
import net.minestom.server.registry.Registry;
|
||||||
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.NBTType;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
record DamageTypeImpl(Registry.DamageTypeEntry registry, int id) implements DamageType {
|
record DamageTypeImpl(Registry.DamageTypeEntry registry, int id) implements DamageType {
|
||||||
|
@ -33,12 +31,12 @@ record DamageTypeImpl(Registry.DamageTypeEntry registry, int id) implements Dama
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NBTCompound asNBT() {
|
public CompoundBinaryTag asNBT() {
|
||||||
var elem = new HashMap<String, NBT>();
|
return CompoundBinaryTag.builder()
|
||||||
elem.put("exhaustion", NBT.Float(registry.exhaustion()));
|
.putFloat("exhaustion", registry.exhaustion())
|
||||||
elem.put("message_id", NBT.String(registry.messageId()));
|
.putString("message_id", registry.messageId())
|
||||||
elem.put("scaling", NBT.String(registry.scaling()));
|
.putString("scaling", registry.scaling())
|
||||||
return NBT.Compound(elem);
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Collection<DamageType> values() {
|
static Collection<DamageType> values() {
|
||||||
|
@ -55,22 +53,23 @@ record DamageTypeImpl(Registry.DamageTypeEntry registry, int id) implements Dama
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static NBTCompound lazyNbt = null;
|
private static CompoundBinaryTag lazyNbt = null;
|
||||||
|
|
||||||
static NBTCompound getNBT() {
|
static CompoundBinaryTag getNBT() {
|
||||||
if (lazyNbt == null) {
|
if (lazyNbt == null) {
|
||||||
var damageTypes = values().stream()
|
var entries = ListBinaryTag.builder(BinaryTagTypes.COMPOUND);
|
||||||
.map((damageType) -> NBT.Compound(Map.of(
|
for (var damageType : values()) {
|
||||||
"id", NBT.Int(damageType.id()),
|
entries.add(CompoundBinaryTag.builder()
|
||||||
"name", NBT.String(damageType.name()),
|
.putInt("id", damageType.id())
|
||||||
"element", damageType.asNBT()
|
.putString("name", damageType.name())
|
||||||
)))
|
.put("element", damageType.asNBT())
|
||||||
.toList();
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
lazyNbt = NBT.Compound(Map.of(
|
lazyNbt = CompoundBinaryTag.builder()
|
||||||
"type", NBT.String("minecraft:damage_type"),
|
.putString("type", "minecraft:damage_type")
|
||||||
"value", NBT.List(NBTType.TAG_Compound, damageTypes)
|
.put("value", entries.build())
|
||||||
));
|
.build();
|
||||||
}
|
}
|
||||||
return lazyNbt;
|
return lazyNbt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
package net.minestom.server.entity.metadata;
|
package net.minestom.server.entity.metadata;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.BinaryTag;
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.minestom.server.entity.Entity;
|
import net.minestom.server.entity.Entity;
|
||||||
import net.minestom.server.entity.Metadata;
|
import net.minestom.server.entity.Metadata;
|
||||||
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 java.util.Map;
|
|
||||||
|
|
||||||
public class PlayerMeta extends LivingEntityMeta {
|
public class PlayerMeta extends LivingEntityMeta {
|
||||||
public static final byte OFFSET = LivingEntityMeta.MAX_OFFSET;
|
public static final byte OFFSET = LivingEntityMeta.MAX_OFFSET;
|
||||||
|
@ -109,23 +108,23 @@ public class PlayerMeta extends LivingEntityMeta {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public NBT getLeftShoulderEntityData() {
|
public BinaryTag getLeftShoulderEntityData() {
|
||||||
return super.metadata.getIndex(OFFSET + 4, null);
|
return super.metadata.getIndex(OFFSET + 4, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLeftShoulderEntityData(@Nullable NBT value) {
|
public void setLeftShoulderEntityData(@Nullable BinaryTag value) {
|
||||||
if (value == null) value = NBT.Compound(Map.of());
|
if (value == null) value = CompoundBinaryTag.empty();
|
||||||
|
|
||||||
super.metadata.setIndex(OFFSET + 4, Metadata.NBT(value));
|
super.metadata.setIndex(OFFSET + 4, Metadata.NBT(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public NBT getRightShoulderEntityData() {
|
public BinaryTag getRightShoulderEntityData() {
|
||||||
return super.metadata.getIndex(OFFSET + 5, null);
|
return super.metadata.getIndex(OFFSET + 5, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRightShoulderEntityData(@Nullable NBT value) {
|
public void setRightShoulderEntityData(@Nullable BinaryTag value) {
|
||||||
if (value == null) value = NBT.Compound(Map.of());
|
if (value == null) value = CompoundBinaryTag.empty();
|
||||||
|
|
||||||
super.metadata.setIndex(OFFSET + 5, Metadata.NBT(value));
|
super.metadata.setIndex(OFFSET + 5, Metadata.NBT(value));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,17 @@
|
||||||
package net.minestom.server.instance;
|
package net.minestom.server.instance;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
|
||||||
import it.unimi.dsi.fastutil.ints.IntIntImmutablePair;
|
import it.unimi.dsi.fastutil.ints.IntIntImmutablePair;
|
||||||
import net.minestom.server.MinecraftServer;
|
import net.minestom.server.MinecraftServer;
|
||||||
import net.minestom.server.instance.block.Block;
|
|
||||||
import net.minestom.server.instance.block.BlockHandler;
|
|
||||||
import net.minestom.server.utils.NamespaceID;
|
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 org.jetbrains.annotations.NotNull;
|
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.readers.ChunkReader;
|
|
||||||
import org.jglrxavpok.hephaistos.mca.readers.ChunkSectionReader;
|
|
||||||
import org.jglrxavpok.hephaistos.mca.readers.SectionBiomeInformation;
|
|
||||||
import org.jglrxavpok.hephaistos.mca.writer.ChunkSectionWriter;
|
|
||||||
import org.jglrxavpok.hephaistos.mca.writer.ChunkWriter;
|
|
||||||
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.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.RandomAccessFile;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.StandardCopyOption;
|
import java.util.Set;
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
@ -36,7 +19,7 @@ public class AnvilLoader implements IChunkLoader {
|
||||||
private final static Logger LOGGER = LoggerFactory.getLogger(AnvilLoader.class);
|
private final static Logger LOGGER = LoggerFactory.getLogger(AnvilLoader.class);
|
||||||
private final static Biome PLAINS = MinecraftServer.getBiomeManager().getByName(NamespaceID.from("minecraft:plains"));
|
private final static Biome PLAINS = MinecraftServer.getBiomeManager().getByName(NamespaceID.from("minecraft:plains"));
|
||||||
|
|
||||||
private final Map<String, RegionFile> alreadyLoaded = new ConcurrentHashMap<>();
|
// private final Map<String, RegionFile> alreadyLoaded = new ConcurrentHashMap<>();
|
||||||
private final Path path;
|
private final Path path;
|
||||||
private final Path levelPath;
|
private final Path levelPath;
|
||||||
private final Path regionPath;
|
private final Path regionPath;
|
||||||
|
@ -50,7 +33,7 @@ public class AnvilLoader implements IChunkLoader {
|
||||||
private final RegionCache perRegionLoadedChunks = new RegionCache();
|
private final RegionCache perRegionLoadedChunks = new RegionCache();
|
||||||
|
|
||||||
// thread local to avoid contention issues with locks
|
// thread local to avoid contention issues with locks
|
||||||
private final ThreadLocal<Int2ObjectMap<BlockState>> blockStateId2ObjectCacheTLS = ThreadLocal.withInitial(Int2ObjectArrayMap::new);
|
// private final ThreadLocal<Int2ObjectMap<BlockState>> blockStateId2ObjectCacheTLS = ThreadLocal.withInitial(Int2ObjectArrayMap::new);
|
||||||
|
|
||||||
public AnvilLoader(@NotNull Path path) {
|
public AnvilLoader(@NotNull Path path) {
|
||||||
this.path = path;
|
this.path = path;
|
||||||
|
@ -64,409 +47,409 @@ public class AnvilLoader implements IChunkLoader {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadInstance(@NotNull Instance instance) {
|
public void loadInstance(@NotNull Instance instance) {
|
||||||
if (!Files.exists(levelPath)) {
|
// if (!Files.exists(levelPath)) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
try (var reader = new NBTReader(Files.newInputStream(levelPath))) {
|
// try (var reader = new NBTReader(Files.newInputStream(levelPath))) {
|
||||||
final NBTCompound tag = (NBTCompound) reader.read();
|
// final NBTCompound tag = (NBTCompound) reader.read();
|
||||||
Files.copy(levelPath, path.resolve("level.dat_old"), StandardCopyOption.REPLACE_EXISTING);
|
// Files.copy(levelPath, path.resolve("level.dat_old"), StandardCopyOption.REPLACE_EXISTING);
|
||||||
instance.tagHandler().updateContent(tag);
|
// instance.tagHandler().updateContent(tag);
|
||||||
} catch (IOException | NBTException e) {
|
// } catch (IOException | NBTException e) {
|
||||||
MinecraftServer.getExceptionManager().handleException(e);
|
// MinecraftServer.getExceptionManager().handleException(e);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull CompletableFuture<@Nullable Chunk> loadChunk(@NotNull Instance instance, int chunkX, int chunkZ) {
|
public @NotNull CompletableFuture<@Nullable Chunk> loadChunk(@NotNull Instance instance, int chunkX, int chunkZ) {
|
||||||
if (!Files.exists(path)) {
|
// if (!Files.exists(path)) {
|
||||||
// No world folder
|
// // No world folder
|
||||||
return CompletableFuture.completedFuture(null);
|
// return CompletableFuture.completedFuture(null);
|
||||||
}
|
// }
|
||||||
try {
|
// try {
|
||||||
return loadMCA(instance, chunkX, chunkZ);
|
// return loadMCA(instance, chunkX, chunkZ);
|
||||||
} catch (Exception e) {
|
// } catch (Exception e) {
|
||||||
MinecraftServer.getExceptionManager().handleException(e);
|
// MinecraftServer.getExceptionManager().handleException(e);
|
||||||
}
|
// }
|
||||||
return CompletableFuture.completedFuture(null);
|
return CompletableFuture.completedFuture(null);
|
||||||
}
|
}
|
||||||
|
//
|
||||||
private @NotNull CompletableFuture<@Nullable Chunk> loadMCA(Instance instance, int chunkX, int chunkZ) throws IOException, AnvilException {
|
// private @NotNull CompletableFuture<@Nullable Chunk> loadMCA(Instance instance, int chunkX, int chunkZ) throws IOException, AnvilException {
|
||||||
final RegionFile mcaFile = getMCAFile(instance, chunkX, chunkZ);
|
// final RegionFile mcaFile = getMCAFile(instance, chunkX, chunkZ);
|
||||||
if (mcaFile == null)
|
// if (mcaFile == null)
|
||||||
return CompletableFuture.completedFuture(null);
|
// return CompletableFuture.completedFuture(null);
|
||||||
final NBTCompound chunkData = mcaFile.getChunkData(chunkX, chunkZ);
|
// final NBTCompound chunkData = mcaFile.getChunkData(chunkX, chunkZ);
|
||||||
if (chunkData == null)
|
// if (chunkData == null)
|
||||||
return CompletableFuture.completedFuture(null);
|
// return CompletableFuture.completedFuture(null);
|
||||||
|
//
|
||||||
final ChunkReader chunkReader = new ChunkReader(chunkData);
|
// final ChunkReader chunkReader = new ChunkReader(chunkData);
|
||||||
|
//
|
||||||
Chunk chunk = instance.getChunkSupplier().createChunk(instance, chunkX, chunkZ);
|
// Chunk chunk = instance.getChunkSupplier().createChunk(instance, chunkX, chunkZ);
|
||||||
synchronized (chunk) {
|
// synchronized (chunk) {
|
||||||
var yRange = chunkReader.getYRange();
|
// var yRange = chunkReader.getYRange();
|
||||||
if (yRange.getStart() < instance.getDimensionType().getMinY()) {
|
// if (yRange.getStart() < instance.getDimensionType().getMinY()) {
|
||||||
throw new AnvilException(
|
// throw new AnvilException(
|
||||||
String.format("Trying to load chunk with minY = %d, but instance dimension type (%s) has a minY of %d",
|
// String.format("Trying to load chunk with minY = %d, but instance dimension type (%s) has a minY of %d",
|
||||||
yRange.getStart(),
|
// yRange.getStart(),
|
||||||
instance.getDimensionType().getName().asString(),
|
// instance.getDimensionType().getName().asString(),
|
||||||
instance.getDimensionType().getMinY()
|
// instance.getDimensionType().getMinY()
|
||||||
));
|
// ));
|
||||||
}
|
// }
|
||||||
if (yRange.getEndInclusive() > instance.getDimensionType().getMaxY()) {
|
// if (yRange.getEndInclusive() > instance.getDimensionType().getMaxY()) {
|
||||||
throw new AnvilException(
|
// throw new AnvilException(
|
||||||
String.format("Trying to load chunk with maxY = %d, but instance dimension type (%s) has a maxY of %d",
|
// String.format("Trying to load chunk with maxY = %d, but instance dimension type (%s) has a maxY of %d",
|
||||||
yRange.getEndInclusive(),
|
// yRange.getEndInclusive(),
|
||||||
instance.getDimensionType().getName().asString(),
|
// instance.getDimensionType().getName().asString(),
|
||||||
instance.getDimensionType().getMaxY()
|
// instance.getDimensionType().getMaxY()
|
||||||
));
|
// ));
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// TODO: Parallelize block, block entities and biome loading
|
// // TODO: Parallelize block, block entities and biome loading
|
||||||
// Blocks + Biomes
|
// // Blocks + Biomes
|
||||||
loadSections(chunk, chunkReader);
|
// loadSections(chunk, chunkReader);
|
||||||
|
//
|
||||||
// Block entities
|
// // Block entities
|
||||||
loadBlockEntities(chunk, chunkReader);
|
// loadBlockEntities(chunk, chunkReader);
|
||||||
}
|
// }
|
||||||
synchronized (perRegionLoadedChunks) {
|
// synchronized (perRegionLoadedChunks) {
|
||||||
int regionX = CoordinatesKt.chunkToRegion(chunkX);
|
// int regionX = CoordinatesKt.chunkToRegion(chunkX);
|
||||||
int regionZ = CoordinatesKt.chunkToRegion(chunkZ);
|
// int regionZ = CoordinatesKt.chunkToRegion(chunkZ);
|
||||||
var chunks = perRegionLoadedChunks.computeIfAbsent(new IntIntImmutablePair(regionX, regionZ), r -> new HashSet<>()); // region cache may have been removed on another thread due to unloadChunk
|
// var chunks = perRegionLoadedChunks.computeIfAbsent(new IntIntImmutablePair(regionX, regionZ), r -> new HashSet<>()); // region cache may have been removed on another thread due to unloadChunk
|
||||||
chunks.add(new IntIntImmutablePair(chunkX, chunkZ));
|
// chunks.add(new IntIntImmutablePair(chunkX, chunkZ));
|
||||||
}
|
// }
|
||||||
return CompletableFuture.completedFuture(chunk);
|
// return CompletableFuture.completedFuture(chunk);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private @Nullable RegionFile getMCAFile(Instance instance, int chunkX, int chunkZ) {
|
// private @Nullable RegionFile getMCAFile(Instance instance, int chunkX, int chunkZ) {
|
||||||
final int regionX = CoordinatesKt.chunkToRegion(chunkX);
|
// final int regionX = CoordinatesKt.chunkToRegion(chunkX);
|
||||||
final int regionZ = CoordinatesKt.chunkToRegion(chunkZ);
|
// final int regionZ = CoordinatesKt.chunkToRegion(chunkZ);
|
||||||
return alreadyLoaded.computeIfAbsent(RegionFile.Companion.createFileName(regionX, regionZ), n -> {
|
// return alreadyLoaded.computeIfAbsent(RegionFile.Companion.createFileName(regionX, regionZ), n -> {
|
||||||
try {
|
// try {
|
||||||
final Path regionPath = this.regionPath.resolve(n);
|
// final Path regionPath = this.regionPath.resolve(n);
|
||||||
if (!Files.exists(regionPath)) {
|
// if (!Files.exists(regionPath)) {
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
synchronized (perRegionLoadedChunks) {
|
// synchronized (perRegionLoadedChunks) {
|
||||||
Set<IntIntImmutablePair> previousVersion = perRegionLoadedChunks.put(new IntIntImmutablePair(regionX, regionZ), new HashSet<>());
|
// Set<IntIntImmutablePair> previousVersion = perRegionLoadedChunks.put(new IntIntImmutablePair(regionX, regionZ), new HashSet<>());
|
||||||
assert previousVersion == null : "The AnvilLoader cache should not already have data for this region.";
|
// assert previousVersion == null : "The AnvilLoader cache should not already have data for this region.";
|
||||||
}
|
// }
|
||||||
return new RegionFile(new RandomAccessFile(regionPath.toFile(), "rw"), regionX, regionZ, instance.getDimensionType().getMinY(), instance.getDimensionType().getMaxY() - 1);
|
// return new RegionFile(new RandomAccessFile(regionPath.toFile(), "rw"), regionX, regionZ, instance.getDimensionType().getMinY(), instance.getDimensionType().getMaxY() - 1);
|
||||||
} catch (IOException | AnvilException e) {
|
// } catch (IOException | AnvilException e) {
|
||||||
MinecraftServer.getExceptionManager().handleException(e);
|
// MinecraftServer.getExceptionManager().handleException(e);
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private void loadSections(Chunk chunk, ChunkReader chunkReader) {
|
// private void loadSections(Chunk chunk, ChunkReader chunkReader) {
|
||||||
final HashMap<String, Biome> biomeCache = new HashMap<>();
|
// final HashMap<String, Biome> biomeCache = new HashMap<>();
|
||||||
for (NBTCompound sectionNBT : chunkReader.getSections()) {
|
// for (NBTCompound sectionNBT : chunkReader.getSections()) {
|
||||||
ChunkSectionReader sectionReader = new ChunkSectionReader(chunkReader.getMinecraftVersion(), sectionNBT);
|
// ChunkSectionReader sectionReader = new ChunkSectionReader(chunkReader.getMinecraftVersion(), sectionNBT);
|
||||||
|
//
|
||||||
if (sectionReader.isSectionEmpty()) continue;
|
// if (sectionReader.isSectionEmpty()) continue;
|
||||||
final int sectionY = sectionReader.getY();
|
// final int sectionY = sectionReader.getY();
|
||||||
final int yOffset = Chunk.CHUNK_SECTION_SIZE * sectionY;
|
// final int yOffset = Chunk.CHUNK_SECTION_SIZE * sectionY;
|
||||||
|
//
|
||||||
Section section = chunk.getSection(sectionY);
|
// Section section = chunk.getSection(sectionY);
|
||||||
|
//
|
||||||
if (sectionReader.getSkyLight() != null) {
|
// if (sectionReader.getSkyLight() != null) {
|
||||||
section.setSkyLight(sectionReader.getSkyLight().copyArray());
|
// section.setSkyLight(sectionReader.getSkyLight().copyArray());
|
||||||
}
|
// }
|
||||||
if (sectionReader.getBlockLight() != null) {
|
// if (sectionReader.getBlockLight() != null) {
|
||||||
section.setBlockLight(sectionReader.getBlockLight().copyArray());
|
// section.setBlockLight(sectionReader.getBlockLight().copyArray());
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Biomes
|
// // Biomes
|
||||||
if (chunkReader.getGenerationStatus().compareTo(ChunkColumn.GenerationStatus.Biomes) > 0) {
|
// if (chunkReader.getGenerationStatus().compareTo(ChunkColumn.GenerationStatus.Biomes) > 0) {
|
||||||
SectionBiomeInformation sectionBiomeInformation = chunkReader.readSectionBiomes(sectionReader);
|
// SectionBiomeInformation sectionBiomeInformation = chunkReader.readSectionBiomes(sectionReader);
|
||||||
|
//
|
||||||
if (sectionBiomeInformation != null && sectionBiomeInformation.hasBiomeInformation()) {
|
// if (sectionBiomeInformation != null && sectionBiomeInformation.hasBiomeInformation()) {
|
||||||
if (sectionBiomeInformation.isFilledWithSingleBiome()) {
|
// if (sectionBiomeInformation.isFilledWithSingleBiome()) {
|
||||||
for (int y = 0; y < Chunk.CHUNK_SECTION_SIZE; y++) {
|
// for (int y = 0; y < Chunk.CHUNK_SECTION_SIZE; y++) {
|
||||||
for (int z = 0; z < Chunk.CHUNK_SIZE_Z; z++) {
|
// for (int z = 0; z < Chunk.CHUNK_SIZE_Z; z++) {
|
||||||
for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
|
// for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
|
||||||
int finalX = chunk.chunkX * Chunk.CHUNK_SIZE_X + x;
|
// int finalX = chunk.chunkX * Chunk.CHUNK_SIZE_X + x;
|
||||||
int finalZ = chunk.chunkZ * Chunk.CHUNK_SIZE_Z + z;
|
// int finalZ = chunk.chunkZ * Chunk.CHUNK_SIZE_Z + z;
|
||||||
int finalY = sectionY * Chunk.CHUNK_SECTION_SIZE + y;
|
// int finalY = sectionY * Chunk.CHUNK_SECTION_SIZE + y;
|
||||||
String biomeName = sectionBiomeInformation.getBaseBiome();
|
// String biomeName = sectionBiomeInformation.getBaseBiome();
|
||||||
Biome biome = biomeCache.computeIfAbsent(biomeName, n ->
|
// Biome biome = biomeCache.computeIfAbsent(biomeName, n ->
|
||||||
Objects.requireNonNullElse(MinecraftServer.getBiomeManager().getByName(NamespaceID.from(n)), PLAINS));
|
// Objects.requireNonNullElse(MinecraftServer.getBiomeManager().getByName(NamespaceID.from(n)), PLAINS));
|
||||||
chunk.setBiome(finalX, finalY, finalZ, biome);
|
// chunk.setBiome(finalX, finalY, finalZ, biome);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
for (int y = 0; y < Chunk.CHUNK_SECTION_SIZE; y++) {
|
// for (int y = 0; y < Chunk.CHUNK_SECTION_SIZE; y++) {
|
||||||
for (int z = 0; z < Chunk.CHUNK_SIZE_Z; z++) {
|
// for (int z = 0; z < Chunk.CHUNK_SIZE_Z; z++) {
|
||||||
for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
|
// for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
|
||||||
int finalX = chunk.chunkX * Chunk.CHUNK_SIZE_X + x;
|
// int finalX = chunk.chunkX * Chunk.CHUNK_SIZE_X + x;
|
||||||
int finalZ = chunk.chunkZ * Chunk.CHUNK_SIZE_Z + z;
|
// int finalZ = chunk.chunkZ * Chunk.CHUNK_SIZE_Z + z;
|
||||||
int finalY = sectionY * Chunk.CHUNK_SECTION_SIZE + y;
|
// int finalY = sectionY * Chunk.CHUNK_SECTION_SIZE + y;
|
||||||
|
//
|
||||||
int index = x / 4 + (z / 4) * 4 + (y / 4) * 16;
|
// int index = x / 4 + (z / 4) * 4 + (y / 4) * 16;
|
||||||
String biomeName = sectionBiomeInformation.getBiomes()[index];
|
// String biomeName = sectionBiomeInformation.getBiomes()[index];
|
||||||
Biome biome = biomeCache.computeIfAbsent(biomeName, n ->
|
// Biome biome = biomeCache.computeIfAbsent(biomeName, n ->
|
||||||
Objects.requireNonNullElse(MinecraftServer.getBiomeManager().getByName(NamespaceID.from(n)), PLAINS));
|
// Objects.requireNonNullElse(MinecraftServer.getBiomeManager().getByName(NamespaceID.from(n)), PLAINS));
|
||||||
chunk.setBiome(finalX, finalY, finalZ, biome);
|
// chunk.setBiome(finalX, finalY, finalZ, biome);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Blocks
|
// // Blocks
|
||||||
final NBTList<NBTCompound> blockPalette = sectionReader.getBlockPalette();
|
// final NBTList<NBTCompound> blockPalette = sectionReader.getBlockPalette();
|
||||||
if (blockPalette != null) {
|
// if (blockPalette != null) {
|
||||||
final int[] blockStateIndices = sectionReader.getUncompressedBlockStateIDs();
|
// final int[] blockStateIndices = sectionReader.getUncompressedBlockStateIDs();
|
||||||
Block[] convertedPalette = new Block[blockPalette.getSize()];
|
// Block[] convertedPalette = new Block[blockPalette.getSize()];
|
||||||
for (int i = 0; i < convertedPalette.length; i++) {
|
// for (int i = 0; i < convertedPalette.length; i++) {
|
||||||
final NBTCompound paletteEntry = blockPalette.get(i);
|
// final NBTCompound paletteEntry = blockPalette.get(i);
|
||||||
String blockName = Objects.requireNonNull(paletteEntry.getString("Name"));
|
// String blockName = Objects.requireNonNull(paletteEntry.getString("Name"));
|
||||||
if (blockName.equals("minecraft:air")) {
|
// if (blockName.equals("minecraft:air")) {
|
||||||
convertedPalette[i] = Block.AIR;
|
// convertedPalette[i] = Block.AIR;
|
||||||
} else {
|
// } else {
|
||||||
if (blockName.equals("minecraft:grass")) {
|
// if (blockName.equals("minecraft:grass")) {
|
||||||
blockName = "minecraft:short_grass";
|
// blockName = "minecraft:short_grass";
|
||||||
}
|
// }
|
||||||
Block block = Objects.requireNonNull(Block.fromNamespaceId(blockName));
|
// Block block = Objects.requireNonNull(Block.fromNamespaceId(blockName));
|
||||||
// Properties
|
// // Properties
|
||||||
final Map<String, String> properties = new HashMap<>();
|
// final Map<String, String> properties = new HashMap<>();
|
||||||
NBTCompound propertiesNBT = paletteEntry.getCompound("Properties");
|
// NBTCompound propertiesNBT = paletteEntry.getCompound("Properties");
|
||||||
if (propertiesNBT != null) {
|
// if (propertiesNBT != null) {
|
||||||
for (var property : propertiesNBT) {
|
// for (var property : propertiesNBT) {
|
||||||
if (property.getValue().getID() != NBTType.TAG_String) {
|
// if (property.getValue().getID() != NBTType.TAG_String) {
|
||||||
LOGGER.warn("Fail to parse block state properties {}, expected a TAG_String for {}, but contents were {}",
|
// LOGGER.warn("Fail to parse block state properties {}, expected a TAG_String for {}, but contents were {}",
|
||||||
propertiesNBT,
|
// propertiesNBT,
|
||||||
property.getKey(),
|
// property.getKey(),
|
||||||
property.getValue().toSNBT());
|
// property.getValue().toSNBT());
|
||||||
} else {
|
// } else {
|
||||||
properties.put(property.getKey(), ((NBTString) property.getValue()).getValue());
|
// properties.put(property.getKey(), ((NBTString) property.getValue()).getValue());
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if (!properties.isEmpty()) block = block.withProperties(properties);
|
// if (!properties.isEmpty()) block = block.withProperties(properties);
|
||||||
// Handler
|
// // Handler
|
||||||
final BlockHandler handler = MinecraftServer.getBlockManager().getHandler(block.name());
|
// final BlockHandler handler = MinecraftServer.getBlockManager().getHandler(block.name());
|
||||||
if (handler != null) block = block.withHandler(handler);
|
// if (handler != null) block = block.withHandler(handler);
|
||||||
|
//
|
||||||
convertedPalette[i] = block;
|
// convertedPalette[i] = block;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
for (int y = 0; y < Chunk.CHUNK_SECTION_SIZE; y++) {
|
// for (int y = 0; y < Chunk.CHUNK_SECTION_SIZE; y++) {
|
||||||
for (int z = 0; z < Chunk.CHUNK_SECTION_SIZE; z++) {
|
// for (int z = 0; z < Chunk.CHUNK_SECTION_SIZE; z++) {
|
||||||
for (int x = 0; x < Chunk.CHUNK_SECTION_SIZE; x++) {
|
// for (int x = 0; x < Chunk.CHUNK_SECTION_SIZE; x++) {
|
||||||
try {
|
// try {
|
||||||
final int blockIndex = y * Chunk.CHUNK_SECTION_SIZE * Chunk.CHUNK_SECTION_SIZE + z * Chunk.CHUNK_SECTION_SIZE + x;
|
// final int blockIndex = y * Chunk.CHUNK_SECTION_SIZE * Chunk.CHUNK_SECTION_SIZE + z * Chunk.CHUNK_SECTION_SIZE + x;
|
||||||
final int paletteIndex = blockStateIndices[blockIndex];
|
// final int paletteIndex = blockStateIndices[blockIndex];
|
||||||
final Block block = convertedPalette[paletteIndex];
|
// final Block block = convertedPalette[paletteIndex];
|
||||||
|
//
|
||||||
chunk.setBlock(x, y + yOffset, z, block);
|
// chunk.setBlock(x, y + yOffset, z, block);
|
||||||
} catch (Exception e) {
|
// } catch (Exception e) {
|
||||||
MinecraftServer.getExceptionManager().handleException(e);
|
// MinecraftServer.getExceptionManager().handleException(e);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private void loadBlockEntities(Chunk loadedChunk, ChunkReader chunkReader) {
|
// private void loadBlockEntities(Chunk loadedChunk, ChunkReader chunkReader) {
|
||||||
for (NBTCompound te : chunkReader.getBlockEntities()) {
|
// for (NBTCompound te : chunkReader.getBlockEntities()) {
|
||||||
final var x = te.getInt("x");
|
// final var x = te.getInt("x");
|
||||||
final var y = te.getInt("y");
|
// final var y = te.getInt("y");
|
||||||
final var z = te.getInt("z");
|
// final var z = te.getInt("z");
|
||||||
if (x == null || y == null || z == null) {
|
// if (x == null || y == null || z == null) {
|
||||||
LOGGER.warn("Tile entity has failed to load due to invalid coordinate");
|
// LOGGER.warn("Tile entity has failed to load due to invalid coordinate");
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
Block block = loadedChunk.getBlock(x, y, z);
|
// Block block = loadedChunk.getBlock(x, y, z);
|
||||||
|
//
|
||||||
final String tileEntityID = te.getString("id");
|
// final String tileEntityID = te.getString("id");
|
||||||
if (tileEntityID != null) {
|
// if (tileEntityID != null) {
|
||||||
final BlockHandler handler = MinecraftServer.getBlockManager().getHandlerOrDummy(tileEntityID);
|
// final BlockHandler handler = MinecraftServer.getBlockManager().getHandlerOrDummy(tileEntityID);
|
||||||
block = block.withHandler(handler);
|
// block = block.withHandler(handler);
|
||||||
}
|
// }
|
||||||
// Remove anvil tags
|
// // Remove anvil tags
|
||||||
MutableNBTCompound mutableCopy = te.toMutableCompound();
|
// MutableNBTCompound mutableCopy = te.toMutableCompound();
|
||||||
mutableCopy.remove("id");
|
// mutableCopy.remove("id");
|
||||||
mutableCopy.remove("x");
|
// mutableCopy.remove("x");
|
||||||
mutableCopy.remove("y");
|
// mutableCopy.remove("y");
|
||||||
mutableCopy.remove("z");
|
// mutableCopy.remove("z");
|
||||||
mutableCopy.remove("keepPacked");
|
// mutableCopy.remove("keepPacked");
|
||||||
// Place block
|
// // Place block
|
||||||
final var finalBlock = mutableCopy.getSize() > 0 ?
|
// final var finalBlock = mutableCopy.getSize() > 0 ?
|
||||||
block.withNbt(mutableCopy.toCompound()) : block;
|
// block.withNbt(mutableCopy.toCompound()) : block;
|
||||||
loadedChunk.setBlock(x, y, z, finalBlock);
|
// loadedChunk.setBlock(x, y, z, finalBlock);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
@Override
|
||||||
public @NotNull CompletableFuture<Void> saveInstance(@NotNull Instance instance) {
|
public @NotNull CompletableFuture<Void> saveInstance(@NotNull Instance instance) {
|
||||||
final NBTCompound nbt = instance.tagHandler().asCompound();
|
// final NBTCompound nbt = instance.tagHandler().asCompound();
|
||||||
if (nbt.isEmpty()) {
|
// if (nbt.isEmpty()) {
|
||||||
// Instance has no data
|
// // Instance has no data
|
||||||
return AsyncUtils.VOID_FUTURE;
|
// return AsyncUtils.VOID_FUTURE;
|
||||||
}
|
// }
|
||||||
try (NBTWriter writer = new NBTWriter(Files.newOutputStream(levelPath))) {
|
// try (NBTWriter writer = new NBTWriter(Files.newOutputStream(levelPath))) {
|
||||||
writer.writeNamed("", nbt);
|
// writer.writeNamed("", nbt);
|
||||||
} catch (IOException e) {
|
// } catch (IOException e) {
|
||||||
e.printStackTrace();
|
// e.printStackTrace();
|
||||||
}
|
// }
|
||||||
return AsyncUtils.VOID_FUTURE;
|
return AsyncUtils.VOID_FUTURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull CompletableFuture<Void> saveChunk(@NotNull Chunk chunk) {
|
public @NotNull CompletableFuture<Void> saveChunk(@NotNull Chunk chunk) {
|
||||||
final int chunkX = chunk.getChunkX();
|
// final int chunkX = chunk.getChunkX();
|
||||||
final int chunkZ = chunk.getChunkZ();
|
// final int chunkZ = chunk.getChunkZ();
|
||||||
RegionFile mcaFile;
|
// RegionFile mcaFile;
|
||||||
synchronized (alreadyLoaded) {
|
// synchronized (alreadyLoaded) {
|
||||||
mcaFile = getMCAFile(chunk.instance, chunkX, chunkZ);
|
// mcaFile = getMCAFile(chunk.instance, chunkX, chunkZ);
|
||||||
if (mcaFile == null) {
|
// if (mcaFile == null) {
|
||||||
final int regionX = CoordinatesKt.chunkToRegion(chunkX);
|
// final int regionX = CoordinatesKt.chunkToRegion(chunkX);
|
||||||
final int regionZ = CoordinatesKt.chunkToRegion(chunkZ);
|
// final int regionZ = CoordinatesKt.chunkToRegion(chunkZ);
|
||||||
final String n = RegionFile.Companion.createFileName(regionX, regionZ);
|
// final String n = RegionFile.Companion.createFileName(regionX, regionZ);
|
||||||
File regionFile = new File(regionPath.toFile(), n);
|
// File regionFile = new File(regionPath.toFile(), n);
|
||||||
try {
|
// try {
|
||||||
if (!regionFile.exists()) {
|
// if (!regionFile.exists()) {
|
||||||
if (!regionFile.getParentFile().exists()) {
|
// if (!regionFile.getParentFile().exists()) {
|
||||||
regionFile.getParentFile().mkdirs();
|
// regionFile.getParentFile().mkdirs();
|
||||||
}
|
// }
|
||||||
regionFile.createNewFile();
|
// regionFile.createNewFile();
|
||||||
}
|
// }
|
||||||
mcaFile = new RegionFile(new RandomAccessFile(regionFile, "rw"), regionX, regionZ);
|
// mcaFile = new RegionFile(new RandomAccessFile(regionFile, "rw"), regionX, regionZ);
|
||||||
alreadyLoaded.put(n, mcaFile);
|
// alreadyLoaded.put(n, mcaFile);
|
||||||
} catch (AnvilException | IOException e) {
|
// } catch (AnvilException | IOException e) {
|
||||||
LOGGER.error("Failed to save chunk " + chunkX + ", " + chunkZ, e);
|
// LOGGER.error("Failed to save chunk " + chunkX + ", " + chunkZ, e);
|
||||||
MinecraftServer.getExceptionManager().handleException(e);
|
// MinecraftServer.getExceptionManager().handleException(e);
|
||||||
return AsyncUtils.VOID_FUTURE;
|
// return AsyncUtils.VOID_FUTURE;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
ChunkWriter writer = new ChunkWriter(SupportedVersion.Companion.getLatest());
|
// ChunkWriter writer = new ChunkWriter(SupportedVersion.Companion.getLatest());
|
||||||
save(chunk, writer);
|
// save(chunk, writer);
|
||||||
try {
|
// try {
|
||||||
LOGGER.debug("Attempt saving at {} {}", chunk.getChunkX(), chunk.getChunkZ());
|
// LOGGER.debug("Attempt saving at {} {}", chunk.getChunkX(), chunk.getChunkZ());
|
||||||
mcaFile.writeColumnData(writer.toNBT(), chunk.getChunkX(), chunk.getChunkZ());
|
// mcaFile.writeColumnData(writer.toNBT(), chunk.getChunkX(), chunk.getChunkZ());
|
||||||
} catch (IOException e) {
|
// } catch (IOException e) {
|
||||||
LOGGER.error("Failed to save chunk " + chunkX + ", " + chunkZ, e);
|
// LOGGER.error("Failed to save chunk " + chunkX + ", " + chunkZ, e);
|
||||||
MinecraftServer.getExceptionManager().handleException(e);
|
// MinecraftServer.getExceptionManager().handleException(e);
|
||||||
return AsyncUtils.VOID_FUTURE;
|
// return AsyncUtils.VOID_FUTURE;
|
||||||
}
|
// }
|
||||||
return AsyncUtils.VOID_FUTURE;
|
return AsyncUtils.VOID_FUTURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BlockState getBlockState(final Block block) {
|
// private BlockState getBlockState(final Block block) {
|
||||||
return blockStateId2ObjectCacheTLS.get().computeIfAbsent(block.stateId(), _unused -> new BlockState(block.name(), block.properties()));
|
// return blockStateId2ObjectCacheTLS.get().computeIfAbsent(block.stateId(), _unused -> new BlockState(block.name(), block.properties()));
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private void save(Chunk chunk, ChunkWriter chunkWriter) {
|
// private void save(Chunk chunk, ChunkWriter chunkWriter) {
|
||||||
final int minY = chunk.getMinSection() * Chunk.CHUNK_SECTION_SIZE;
|
// final int minY = chunk.getMinSection() * Chunk.CHUNK_SECTION_SIZE;
|
||||||
final int maxY = chunk.getMaxSection() * Chunk.CHUNK_SECTION_SIZE - 1;
|
// final int maxY = chunk.getMaxSection() * Chunk.CHUNK_SECTION_SIZE - 1;
|
||||||
chunkWriter.setYPos(minY);
|
// chunkWriter.setYPos(minY);
|
||||||
List<NBTCompound> blockEntities = new ArrayList<>();
|
// List<NBTCompound> blockEntities = new ArrayList<>();
|
||||||
chunkWriter.setStatus(ChunkColumn.GenerationStatus.Full);
|
// chunkWriter.setStatus(ChunkColumn.GenerationStatus.Full);
|
||||||
|
//
|
||||||
List<NBTCompound> sectionData = new ArrayList<>((maxY - minY + 1) / Chunk.CHUNK_SECTION_SIZE);
|
// List<NBTCompound> sectionData = new ArrayList<>((maxY - minY + 1) / Chunk.CHUNK_SECTION_SIZE);
|
||||||
int[] palettedBiomes = new int[ChunkSection.Companion.getBiomeArraySize()];
|
// int[] palettedBiomes = new int[ChunkSection.Companion.getBiomeArraySize()];
|
||||||
int[] palettedBlockStates = new int[Chunk.CHUNK_SIZE_X * Chunk.CHUNK_SECTION_SIZE * Chunk.CHUNK_SIZE_Z];
|
// int[] palettedBlockStates = new int[Chunk.CHUNK_SIZE_X * Chunk.CHUNK_SECTION_SIZE * Chunk.CHUNK_SIZE_Z];
|
||||||
for (int sectionY = chunk.getMinSection(); sectionY < chunk.getMaxSection(); sectionY++) {
|
// for (int sectionY = chunk.getMinSection(); sectionY < chunk.getMaxSection(); sectionY++) {
|
||||||
ChunkSectionWriter sectionWriter = new ChunkSectionWriter(SupportedVersion.Companion.getLatest(), (byte) sectionY);
|
// ChunkSectionWriter sectionWriter = new ChunkSectionWriter(SupportedVersion.Companion.getLatest(), (byte) sectionY);
|
||||||
|
//
|
||||||
Section section = chunk.getSection(sectionY);
|
// Section section = chunk.getSection(sectionY);
|
||||||
sectionWriter.setSkyLights(section.skyLight().array());
|
// sectionWriter.setSkyLights(section.skyLight().array());
|
||||||
sectionWriter.setBlockLights(section.blockLight().array());
|
// sectionWriter.setBlockLights(section.blockLight().array());
|
||||||
|
//
|
||||||
BiomePalette biomePalette = new BiomePalette();
|
// BiomePalette biomePalette = new BiomePalette();
|
||||||
BlockPalette blockPalette = new BlockPalette();
|
// BlockPalette blockPalette = new BlockPalette();
|
||||||
for (int sectionLocalY = 0; sectionLocalY < Chunk.CHUNK_SECTION_SIZE; sectionLocalY++) {
|
// for (int sectionLocalY = 0; sectionLocalY < Chunk.CHUNK_SECTION_SIZE; sectionLocalY++) {
|
||||||
for (int z = 0; z < Chunk.CHUNK_SIZE_Z; z++) {
|
// for (int z = 0; z < Chunk.CHUNK_SIZE_Z; z++) {
|
||||||
for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
|
// for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
|
||||||
final int y = sectionLocalY + sectionY * Chunk.CHUNK_SECTION_SIZE;
|
// final int y = sectionLocalY + sectionY * Chunk.CHUNK_SECTION_SIZE;
|
||||||
|
//
|
||||||
final int blockIndex = x + sectionLocalY * 16 * 16 + z * 16;
|
// final int blockIndex = x + sectionLocalY * 16 * 16 + z * 16;
|
||||||
|
//
|
||||||
final Block block = chunk.getBlock(x, y, z);
|
// final Block block = chunk.getBlock(x, y, z);
|
||||||
|
//
|
||||||
final BlockState hephaistosBlockState = getBlockState(block);
|
// final BlockState hephaistosBlockState = getBlockState(block);
|
||||||
blockPalette.increaseReference(hephaistosBlockState);
|
// blockPalette.increaseReference(hephaistosBlockState);
|
||||||
|
//
|
||||||
palettedBlockStates[blockIndex] = blockPalette.getPaletteIndex(hephaistosBlockState);
|
// palettedBlockStates[blockIndex] = blockPalette.getPaletteIndex(hephaistosBlockState);
|
||||||
|
//
|
||||||
// biome are stored for 4x4x4 volumes, avoid unnecessary work
|
// // biome are stored for 4x4x4 volumes, avoid unnecessary work
|
||||||
if (x % 4 == 0 && sectionLocalY % 4 == 0 && z % 4 == 0) {
|
// if (x % 4 == 0 && sectionLocalY % 4 == 0 && z % 4 == 0) {
|
||||||
int biomeIndex = (x / 4) + (sectionLocalY / 4) * 4 * 4 + (z / 4) * 4;
|
// int biomeIndex = (x / 4) + (sectionLocalY / 4) * 4 * 4 + (z / 4) * 4;
|
||||||
final Biome biome = chunk.getBiome(x, y, z);
|
// final Biome biome = chunk.getBiome(x, y, z);
|
||||||
final String biomeName = biome.name();
|
// final String biomeName = biome.name();
|
||||||
|
//
|
||||||
biomePalette.increaseReference(biomeName);
|
// biomePalette.increaseReference(biomeName);
|
||||||
palettedBiomes[biomeIndex] = biomePalette.getPaletteIndex(biomeName);
|
// palettedBiomes[biomeIndex] = biomePalette.getPaletteIndex(biomeName);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Block entities
|
// // Block entities
|
||||||
final BlockHandler handler = block.handler();
|
// final BlockHandler handler = block.handler();
|
||||||
final NBTCompound originalNBT = block.nbt();
|
// final NBTCompound originalNBT = block.nbt();
|
||||||
if (originalNBT != null || handler != null) {
|
// if (originalNBT != null || handler != null) {
|
||||||
MutableNBTCompound nbt = originalNBT != null ?
|
// MutableNBTCompound nbt = originalNBT != null ?
|
||||||
originalNBT.toMutableCompound() : new MutableNBTCompound();
|
// originalNBT.toMutableCompound() : new MutableNBTCompound();
|
||||||
|
//
|
||||||
if (handler != null) {
|
// if (handler != null) {
|
||||||
nbt.setString("id", handler.getNamespaceId().asString());
|
// nbt.setString("id", handler.getNamespaceId().asString());
|
||||||
}
|
// }
|
||||||
nbt.setInt("x", x + Chunk.CHUNK_SIZE_X * chunk.getChunkX());
|
// nbt.setInt("x", x + Chunk.CHUNK_SIZE_X * chunk.getChunkX());
|
||||||
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);
|
||||||
blockEntities.add(nbt.toCompound());
|
// blockEntities.add(nbt.toCompound());
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
sectionWriter.setPalettedBiomes(biomePalette, palettedBiomes);
|
// sectionWriter.setPalettedBiomes(biomePalette, palettedBiomes);
|
||||||
sectionWriter.setPalettedBlockStates(blockPalette, palettedBlockStates);
|
// sectionWriter.setPalettedBlockStates(blockPalette, palettedBlockStates);
|
||||||
|
//
|
||||||
sectionData.add(sectionWriter.toNBT());
|
// sectionData.add(sectionWriter.toNBT());
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
chunkWriter.setSectionsData(NBT.List(NBTType.TAG_Compound, sectionData));
|
// chunkWriter.setSectionsData(NBT.List(NBTType.TAG_Compound, sectionData));
|
||||||
chunkWriter.setBlockEntityData(NBT.List(NBTType.TAG_Compound, blockEntities));
|
// chunkWriter.setBlockEntityData(NBT.List(NBTType.TAG_Compound, blockEntities));
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* Unload a given chunk. Also unloads a region when no chunk from that region is loaded.
|
// * Unload a given chunk. Also unloads a region when no chunk from that region is loaded.
|
||||||
*
|
// *
|
||||||
* @param chunk the chunk to unload
|
// * @param chunk the chunk to unload
|
||||||
*/
|
// */
|
||||||
@Override
|
// @Override
|
||||||
public void unloadChunk(Chunk chunk) {
|
// public void unloadChunk(Chunk chunk) {
|
||||||
final int regionX = CoordinatesKt.chunkToRegion(chunk.chunkX);
|
// final int regionX = CoordinatesKt.chunkToRegion(chunk.chunkX);
|
||||||
final int regionZ = CoordinatesKt.chunkToRegion(chunk.chunkZ);
|
// final int regionZ = CoordinatesKt.chunkToRegion(chunk.chunkZ);
|
||||||
|
//
|
||||||
final IntIntImmutablePair regionKey = new IntIntImmutablePair(regionX, regionZ);
|
// final IntIntImmutablePair regionKey = new IntIntImmutablePair(regionX, regionZ);
|
||||||
synchronized (perRegionLoadedChunks) {
|
// synchronized (perRegionLoadedChunks) {
|
||||||
Set<IntIntImmutablePair> chunks = perRegionLoadedChunks.get(regionKey);
|
// Set<IntIntImmutablePair> chunks = perRegionLoadedChunks.get(regionKey);
|
||||||
if (chunks != null) { // if null, trying to unload a chunk from a region that was not created by the AnvilLoader
|
// if (chunks != null) { // if null, trying to unload a chunk from a region that was not created by the AnvilLoader
|
||||||
// don't check return value, trying to unload a chunk not created by the AnvilLoader is valid
|
// // don't check return value, trying to unload a chunk not created by the AnvilLoader is valid
|
||||||
chunks.remove(new IntIntImmutablePair(chunk.chunkX, chunk.chunkZ));
|
// chunks.remove(new IntIntImmutablePair(chunk.chunkX, chunk.chunkZ));
|
||||||
|
//
|
||||||
if (chunks.isEmpty()) {
|
// if (chunks.isEmpty()) {
|
||||||
perRegionLoadedChunks.remove(regionKey);
|
// perRegionLoadedChunks.remove(regionKey);
|
||||||
RegionFile regionFile = alreadyLoaded.remove(RegionFile.Companion.createFileName(regionX, regionZ));
|
// RegionFile regionFile = alreadyLoaded.remove(RegionFile.Companion.createFileName(regionX, regionZ));
|
||||||
if (regionFile != null) {
|
// if (regionFile != null) {
|
||||||
try {
|
// try {
|
||||||
regionFile.close();
|
// regionFile.close();
|
||||||
} catch (IOException e) {
|
// } catch (IOException e) {
|
||||||
MinecraftServer.getExceptionManager().handleException(e);
|
// MinecraftServer.getExceptionManager().handleException(e);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supportsParallelLoading() {
|
public boolean supportsParallelLoading() {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package net.minestom.server.instance;
|
||||||
|
|
||||||
import com.extollit.gaming.ai.path.model.ColumnarOcclusionFieldList;
|
import com.extollit.gaming.ai.path.model.ColumnarOcclusionFieldList;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.minestom.server.MinecraftServer;
|
import net.minestom.server.MinecraftServer;
|
||||||
import net.minestom.server.coordinate.Point;
|
import net.minestom.server.coordinate.Point;
|
||||||
import net.minestom.server.coordinate.Vec;
|
import net.minestom.server.coordinate.Vec;
|
||||||
|
@ -27,8 +28,6 @@ import net.minestom.server.world.biomes.Biome;
|
||||||
import net.minestom.server.world.biomes.BiomeManager;
|
import net.minestom.server.world.biomes.BiomeManager;
|
||||||
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.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -225,7 +224,7 @@ public class DynamicChunk extends Chunk {
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull ChunkDataPacket createChunkPacket() {
|
private @NotNull ChunkDataPacket createChunkPacket() {
|
||||||
final NBTCompound heightmapsNBT = computeHeightmap();
|
final CompoundBinaryTag heightmapsNBT = computeHeightmap();
|
||||||
// Data
|
// Data
|
||||||
|
|
||||||
final byte[] data;
|
final byte[] data;
|
||||||
|
@ -242,7 +241,7 @@ public class DynamicChunk extends Chunk {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected NBTCompound computeHeightmap() {
|
protected CompoundBinaryTag computeHeightmap() {
|
||||||
// TODO: don't hardcode heightmaps
|
// TODO: don't hardcode heightmaps
|
||||||
// Heightmap
|
// Heightmap
|
||||||
int dimensionHeight = getInstance().getDimensionType().getHeight();
|
int dimensionHeight = getInstance().getDimensionType().getHeight();
|
||||||
|
@ -255,9 +254,10 @@ public class DynamicChunk extends Chunk {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final int bitsForHeight = MathUtils.bitsToRepresent(dimensionHeight);
|
final int bitsForHeight = MathUtils.bitsToRepresent(dimensionHeight);
|
||||||
return NBT.Compound(Map.of(
|
return CompoundBinaryTag.builder()
|
||||||
"MOTION_BLOCKING", NBT.LongArray(encodeBlocks(motionBlocking, bitsForHeight)),
|
.putLongArray("MOTION_BLOCKING", encodeBlocks(motionBlocking, bitsForHeight))
|
||||||
"WORLD_SURFACE", NBT.LongArray(encodeBlocks(worldSurface, bitsForHeight))));
|
.putLongArray("WORLD_SURFACE", encodeBlocks(worldSurface, bitsForHeight))
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull UpdateLightPacket createLightPacket() {
|
@NotNull UpdateLightPacket createLightPacket() {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package net.minestom.server.instance;
|
package net.minestom.server.instance;
|
||||||
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface ExplosionSupplier {
|
public interface ExplosionSupplier {
|
||||||
|
@ -12,9 +12,9 @@ public interface ExplosionSupplier {
|
||||||
* @param centerY center Y of the explosion
|
* @param centerY center Y of the explosion
|
||||||
* @param centerZ center Z of the explosion
|
* @param centerZ center Z of the explosion
|
||||||
* @param strength strength of the explosion
|
* @param strength strength of the explosion
|
||||||
* @param additionalData data passed via {@link Instance#explode(float, float, float, float, NBTCompound)} )}. Can be null
|
* @param additionalData data passed via {@link Instance#explode(float, float, float, float, CompoundBinaryTag)} )}. Can be null
|
||||||
* @return Explosion object representing the algorithm to use
|
* @return Explosion object representing the algorithm to use
|
||||||
*/
|
*/
|
||||||
Explosion createExplosion(float centerX, float centerY, float centerZ, float strength, NBTCompound additionalData);
|
Explosion createExplosion(float centerX, float centerY, float centerZ, float strength, CompoundBinaryTag additionalData);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package net.minestom.server.instance;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectArraySet;
|
import it.unimi.dsi.fastutil.objects.ObjectArraySet;
|
||||||
import net.kyori.adventure.identity.Identity;
|
import net.kyori.adventure.identity.Identity;
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.kyori.adventure.pointer.Pointers;
|
import net.kyori.adventure.pointer.Pointers;
|
||||||
import net.minestom.server.MinecraftServer;
|
import net.minestom.server.MinecraftServer;
|
||||||
import net.minestom.server.ServerProcess;
|
import net.minestom.server.ServerProcess;
|
||||||
|
@ -45,7 +46,6 @@ import net.minestom.server.world.DimensionType;
|
||||||
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.NBTCompound;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -792,7 +792,7 @@ public abstract class Instance implements Block.Getter, Block.Setter,
|
||||||
* @param additionalData data to pass to the explosion supplier
|
* @param additionalData data to pass to the explosion supplier
|
||||||
* @throws IllegalStateException If no {@link ExplosionSupplier} was supplied
|
* @throws IllegalStateException If no {@link ExplosionSupplier} was supplied
|
||||||
*/
|
*/
|
||||||
public void explode(float centerX, float centerY, float centerZ, float strength, @Nullable NBTCompound additionalData) {
|
public void explode(float centerX, float centerY, float centerZ, float strength, @Nullable CompoundBinaryTag additionalData) {
|
||||||
final ExplosionSupplier explosionSupplier = getExplosionSupplier();
|
final ExplosionSupplier explosionSupplier = getExplosionSupplier();
|
||||||
Check.stateCondition(explosionSupplier == null, "Tried to create an explosion with no explosion supplier");
|
Check.stateCondition(explosionSupplier == null, "Tried to create an explosion with no explosion supplier");
|
||||||
final Explosion explosion = explosionSupplier.createExplosion(centerX, centerY, centerZ, strength, additionalData);
|
final Explosion explosion = explosionSupplier.createExplosion(centerX, centerY, centerZ, strength, additionalData);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package net.minestom.server.instance;
|
package net.minestom.server.instance;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.minestom.server.MinecraftServer;
|
import net.minestom.server.MinecraftServer;
|
||||||
import net.minestom.server.coordinate.Point;
|
import net.minestom.server.coordinate.Point;
|
||||||
import net.minestom.server.coordinate.Vec;
|
import net.minestom.server.coordinate.Vec;
|
||||||
|
@ -32,7 +33,6 @@ import net.minestom.server.world.DimensionType;
|
||||||
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.NBTCompound;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import space.vectrix.flare.fastutil.Long2ObjectSyncMap;
|
import space.vectrix.flare.fastutil.Long2ObjectSyncMap;
|
||||||
|
@ -186,7 +186,7 @@ public class InstanceContainer extends Instance {
|
||||||
chunk.sendPacketToViewers(new BlockChangePacket(blockPosition, block.stateId()));
|
chunk.sendPacketToViewers(new BlockChangePacket(blockPosition, block.stateId()));
|
||||||
var registry = block.registry();
|
var registry = block.registry();
|
||||||
if (registry.isBlockEntity()) {
|
if (registry.isBlockEntity()) {
|
||||||
final NBTCompound data = BlockUtils.extractClientNbt(block);
|
final CompoundBinaryTag data = BlockUtils.extractClientNbt(block);
|
||||||
chunk.sendPacketToViewers(new BlockEntityDataPacket(blockPosition, registry.blockEntityId(), data));
|
chunk.sendPacketToViewers(new BlockEntityDataPacket(blockPosition, registry.blockEntityId(), data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package net.minestom.server.instance;
|
package net.minestom.server.instance;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
|
import net.kyori.adventure.nbt.LongArrayBinaryTag;
|
||||||
import net.minestom.server.MinecraftServer;
|
import net.minestom.server.MinecraftServer;
|
||||||
import net.minestom.server.ServerFlag;
|
import net.minestom.server.ServerFlag;
|
||||||
import net.minestom.server.collision.Shape;
|
import net.minestom.server.collision.Shape;
|
||||||
|
@ -16,8 +18,6 @@ import net.minestom.server.utils.NamespaceID;
|
||||||
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.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBT;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
@ -202,14 +202,17 @@ public class LightingChunk extends DynamicChunk {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected NBTCompound computeHeightmap() {
|
protected CompoundBinaryTag computeHeightmap() {
|
||||||
// Heightmap
|
// Heightmap
|
||||||
int[] heightmap = getHeightmap();
|
int[] heightmap = getHeightmap();
|
||||||
int dimensionHeight = getInstance().getDimensionType().getHeight();
|
int dimensionHeight = getInstance().getDimensionType().getHeight();
|
||||||
final int bitsForHeight = MathUtils.bitsToRepresent(dimensionHeight);
|
final int bitsForHeight = MathUtils.bitsToRepresent(dimensionHeight);
|
||||||
return NBT.Compound(Map.of(
|
|
||||||
"MOTION_BLOCKING", NBT.LongArray(encodeBlocks(heightmap, bitsForHeight)),
|
LongArrayBinaryTag encoded = LongArrayBinaryTag.longArrayBinaryTag(encodeBlocks(heightmap, bitsForHeight));
|
||||||
"WORLD_SURFACE", NBT.LongArray(encodeBlocks(heightmap, bitsForHeight))));
|
return CompoundBinaryTag.builder()
|
||||||
|
.put("MOTION_BLOCKING", encoded)
|
||||||
|
.put("WORLD_SURFACE", encoded)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lazy compute heightmap
|
// Lazy compute heightmap
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
package net.minestom.server.instance.block;
|
package net.minestom.server.instance.block;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.minestom.server.coordinate.Point;
|
import net.minestom.server.coordinate.Point;
|
||||||
import net.minestom.server.instance.Instance;
|
import net.minestom.server.instance.Instance;
|
||||||
import net.minestom.server.instance.batch.Batch;
|
import net.minestom.server.instance.batch.Batch;
|
||||||
import net.minestom.server.registry.StaticProtocolObject;
|
|
||||||
import net.minestom.server.registry.Registry;
|
import net.minestom.server.registry.Registry;
|
||||||
|
import net.minestom.server.registry.StaticProtocolObject;
|
||||||
import net.minestom.server.tag.Tag;
|
import net.minestom.server.tag.Tag;
|
||||||
import net.minestom.server.tag.TagReadable;
|
import net.minestom.server.tag.TagReadable;
|
||||||
import net.minestom.server.utils.NamespaceID;
|
import net.minestom.server.utils.NamespaceID;
|
||||||
import org.jetbrains.annotations.*;
|
import org.jetbrains.annotations.*;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -67,7 +67,7 @@ public sealed interface Block extends StaticProtocolObject, TagReadable, Blocks
|
||||||
* @return a new block with different nbt
|
* @return a new block with different nbt
|
||||||
*/
|
*/
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
@NotNull Block withNbt(@Nullable NBTCompound compound);
|
@NotNull Block withNbt(@Nullable CompoundBinaryTag compound);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new block with the specified {@link BlockHandler handler}.
|
* Creates a new block with the specified {@link BlockHandler handler}.
|
||||||
|
@ -86,7 +86,7 @@ public sealed interface Block extends StaticProtocolObject, TagReadable, Blocks
|
||||||
* @return the block nbt, null if not present
|
* @return the block nbt, null if not present
|
||||||
*/
|
*/
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
@Nullable NBTCompound nbt();
|
@Nullable CompoundBinaryTag nbt();
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
default boolean hasNbt() {
|
default boolean hasNbt() {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import com.github.benmanes.caffeine.cache.Cache;
|
||||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
|
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.minestom.server.registry.Registry;
|
import net.minestom.server.registry.Registry;
|
||||||
import net.minestom.server.tag.Tag;
|
import net.minestom.server.tag.Tag;
|
||||||
import net.minestom.server.utils.ArrayUtils;
|
import net.minestom.server.utils.ArrayUtils;
|
||||||
|
@ -14,8 +15,6 @@ import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.annotations.UnknownNullability;
|
import org.jetbrains.annotations.UnknownNullability;
|
||||||
import org.jetbrains.annotations.Unmodifiable;
|
import org.jetbrains.annotations.Unmodifiable;
|
||||||
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.*;
|
||||||
|
@ -23,7 +22,7 @@ import java.util.function.Function;
|
||||||
|
|
||||||
record BlockImpl(@NotNull Registry.BlockEntry registry,
|
record BlockImpl(@NotNull Registry.BlockEntry registry,
|
||||||
byte @NotNull [] propertiesArray,
|
byte @NotNull [] propertiesArray,
|
||||||
@Nullable NBTCompound nbt,
|
@Nullable CompoundBinaryTag nbt,
|
||||||
@Nullable BlockHandler handler) implements Block {
|
@Nullable BlockHandler handler) implements Block {
|
||||||
// Block state -> block object
|
// Block state -> block object
|
||||||
private static final ObjectArray<Block> BLOCK_STATE_MAP = ObjectArray.singleThread();
|
private static final ObjectArray<Block> BLOCK_STATE_MAP = ObjectArray.singleThread();
|
||||||
|
@ -86,7 +85,7 @@ record BlockImpl(@NotNull Registry.BlockEntry registry,
|
||||||
final int defaultState = properties.getInt("defaultStateId");
|
final int defaultState = properties.getInt("defaultStateId");
|
||||||
return getState(defaultState);
|
return getState(defaultState);
|
||||||
});
|
});
|
||||||
private static final Cache<NBTCompound, NBTCompound> NBT_CACHE = Caffeine.newBuilder()
|
private static final Cache<CompoundBinaryTag, CompoundBinaryTag> NBT_CACHE = Caffeine.newBuilder()
|
||||||
.expireAfterWrite(Duration.ofMinutes(5))
|
.expireAfterWrite(Duration.ofMinutes(5))
|
||||||
.weakValues()
|
.weakValues()
|
||||||
.build();
|
.build();
|
||||||
|
@ -144,14 +143,16 @@ record BlockImpl(@NotNull Registry.BlockEntry registry,
|
||||||
|
|
||||||
@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 = new MutableNBTCompound(Objects.requireNonNullElse(nbt, NBTCompound.EMPTY));
|
var builder = CompoundBinaryTag.builder();
|
||||||
tag.write(temporaryNbt, value);
|
if (nbt != null) builder.put(nbt);
|
||||||
final var finalNbt = temporaryNbt.getSize() > 0 ? NBT_CACHE.get(temporaryNbt.toCompound(), Function.identity()) : null;
|
tag.write(builder, value);
|
||||||
|
var temporaryNbt = builder.build();
|
||||||
|
final var finalNbt = temporaryNbt.size() > 0 ? NBT_CACHE.get(temporaryNbt, Function.identity()) : null;
|
||||||
return new BlockImpl(registry, propertiesArray, finalNbt, handler);
|
return new BlockImpl(registry, propertiesArray, finalNbt, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Block withNbt(@Nullable NBTCompound compound) {
|
public @NotNull Block withNbt(@Nullable CompoundBinaryTag compound) {
|
||||||
return new BlockImpl(registry, propertiesArray, compound, handler);
|
return new BlockImpl(registry, propertiesArray, compound, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +184,7 @@ record BlockImpl(@NotNull Registry.BlockEntry registry,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> @UnknownNullability T getTag(@NotNull Tag<T> tag) {
|
public <T> @UnknownNullability T getTag(@NotNull Tag<T> tag) {
|
||||||
return tag.read(Objects.requireNonNullElse(nbt, NBTCompound.EMPTY));
|
return tag.read(Objects.requireNonNullElse(nbt, CompoundBinaryTag.empty()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<PropertiesHolder, BlockImpl> possibleProperties() {
|
private Map<PropertiesHolder, BlockImpl> possibleProperties() {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package net.minestom.server.item;
|
package net.minestom.server.item;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.minestom.server.instance.block.Block;
|
import net.minestom.server.instance.block.Block;
|
||||||
import net.minestom.server.item.attribute.ItemAttribute;
|
import net.minestom.server.item.attribute.ItemAttribute;
|
||||||
|
@ -12,7 +13,6 @@ 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.jetbrains.annotations.UnknownNullability;
|
import org.jetbrains.annotations.UnknownNullability;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
@ -26,7 +26,7 @@ public sealed interface ItemMeta extends TagReadable, NetworkBuffer.Writer
|
||||||
@Contract(value = "_, -> new", pure = true)
|
@Contract(value = "_, -> new", pure = true)
|
||||||
@NotNull ItemMeta with(@NotNull Consumer<@NotNull Builder> builderConsumer);
|
@NotNull ItemMeta with(@NotNull Consumer<@NotNull Builder> builderConsumer);
|
||||||
|
|
||||||
@NotNull NBTCompound toNBT();
|
@NotNull CompoundBinaryTag toNBT();
|
||||||
|
|
||||||
@NotNull String toSNBT();
|
@NotNull String toSNBT();
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
package net.minestom.server.item;
|
package net.minestom.server.item;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
|
import net.kyori.adventure.nbt.TagStringIO;
|
||||||
import net.minestom.server.network.NetworkBuffer;
|
import net.minestom.server.network.NetworkBuffer;
|
||||||
import net.minestom.server.tag.Tag;
|
import net.minestom.server.tag.Tag;
|
||||||
import net.minestom.server.tag.TagHandler;
|
import net.minestom.server.tag.TagHandler;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.UnknownNullability;
|
import org.jetbrains.annotations.UnknownNullability;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import static net.minestom.server.network.NetworkBuffer.BYTE;
|
|
||||||
import static net.minestom.server.network.NetworkBuffer.NBT;
|
import static net.minestom.server.network.NetworkBuffer.NBT;
|
||||||
|
|
||||||
record ItemMetaImpl(TagHandler tagHandler) implements ItemMeta {
|
record ItemMetaImpl(TagHandler tagHandler) implements ItemMeta {
|
||||||
|
@ -29,23 +30,22 @@ record ItemMetaImpl(TagHandler tagHandler) implements ItemMeta {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull NBTCompound toNBT() {
|
public @NotNull CompoundBinaryTag toNBT() {
|
||||||
return tagHandler.asCompound();
|
return tagHandler.asCompound();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull String toSNBT() {
|
public @NotNull String toSNBT() {
|
||||||
return toNBT().toSNBT();
|
try {
|
||||||
|
return TagStringIO.get().asString(toNBT());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Failed to convert to SNBT", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
public void write(@NotNull NetworkBuffer writer) {
|
||||||
final NBTCompound nbt = toNBT();
|
writer.write(NBT, toNBT());
|
||||||
if (nbt.isEmpty()) {
|
|
||||||
writer.write(BYTE, (byte) 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
writer.write(NBT, nbt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package net.minestom.server.item;
|
package net.minestom.server.item;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.kyori.adventure.nbt.api.BinaryTagHolder;
|
import net.kyori.adventure.nbt.api.BinaryTagHolder;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.event.HoverEvent;
|
import net.kyori.adventure.text.event.HoverEvent;
|
||||||
|
@ -11,8 +12,8 @@ import net.minestom.server.tag.TagReadable;
|
||||||
import net.minestom.server.tag.TagWritable;
|
import net.minestom.server.tag.TagWritable;
|
||||||
import net.minestom.server.utils.validate.Check;
|
import net.minestom.server.utils.validate.Check;
|
||||||
import org.jetbrains.annotations.*;
|
import org.jetbrains.annotations.*;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.IntUnaryOperator;
|
import java.util.function.IntUnaryOperator;
|
||||||
|
@ -47,13 +48,13 @@ public sealed interface ItemStack extends TagReadable, HoverEventSource<HoverEve
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract(value = "_, _, _ -> new", pure = true)
|
@Contract(value = "_, _, _ -> new", pure = true)
|
||||||
static @NotNull ItemStack fromNBT(@NotNull Material material, @Nullable NBTCompound nbtCompound, int amount) {
|
static @NotNull ItemStack fromNBT(@NotNull Material material, @Nullable CompoundBinaryTag nbtCompound, int amount) {
|
||||||
if (nbtCompound == null) return of(material, amount);
|
if (nbtCompound == null) return of(material, amount);
|
||||||
return builder(material).amount(amount).meta(nbtCompound).build();
|
return builder(material).amount(amount).meta(nbtCompound).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract(value = "_, _ -> new", pure = true)
|
@Contract(value = "_, _ -> new", pure = true)
|
||||||
static @NotNull ItemStack fromNBT(@NotNull Material material, @Nullable NBTCompound nbtCompound) {
|
static @NotNull ItemStack fromNBT(@NotNull Material material, @Nullable CompoundBinaryTag nbtCompound) {
|
||||||
return fromNBT(material, nbtCompound, 1);
|
return fromNBT(material, nbtCompound, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +64,7 @@ public sealed interface ItemStack extends TagReadable, HoverEventSource<HoverEve
|
||||||
* @param nbtCompound The nbt representation of the item
|
* @param nbtCompound The nbt representation of the item
|
||||||
*/
|
*/
|
||||||
@ApiStatus.Experimental
|
@ApiStatus.Experimental
|
||||||
static @NotNull ItemStack fromItemNBT(@NotNull NBTCompound nbtCompound) {
|
static @NotNull ItemStack fromItemNBT(@NotNull CompoundBinaryTag nbtCompound) {
|
||||||
String id = nbtCompound.getString("id");
|
String id = nbtCompound.getString("id");
|
||||||
Check.notNull(id, "Item NBT must contain an id field.");
|
Check.notNull(id, "Item NBT must contain an id field.");
|
||||||
Material material = Material.fromNamespaceId(id);
|
Material material = Material.fromNamespaceId(id);
|
||||||
|
@ -71,7 +72,7 @@ public sealed interface ItemStack extends TagReadable, HoverEventSource<HoverEve
|
||||||
|
|
||||||
Byte amount = nbtCompound.getByte("Count");
|
Byte amount = nbtCompound.getByte("Count");
|
||||||
if (amount == null) amount = 1;
|
if (amount == null) amount = 1;
|
||||||
final NBTCompound tag = nbtCompound.getCompound("tag");
|
final CompoundBinaryTag tag = nbtCompound.getCompound("tag");
|
||||||
return tag != null ? fromNBT(material, tag, amount) : of(material, amount);
|
return tag != null ? fromNBT(material, tag, amount) : of(material, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,8 +169,13 @@ public sealed interface ItemStack extends TagReadable, HoverEventSource<HoverEve
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default @NotNull HoverEvent<HoverEvent.ShowItem> asHoverEvent(@NotNull UnaryOperator<HoverEvent.ShowItem> op) {
|
default @NotNull HoverEvent<HoverEvent.ShowItem> asHoverEvent(@NotNull UnaryOperator<HoverEvent.ShowItem> op) {
|
||||||
final BinaryTagHolder tagHolder = BinaryTagHolder.encode(meta().toNBT(), MinestomAdventure.NBT_CODEC);
|
try {
|
||||||
return HoverEvent.showItem(op.apply(HoverEvent.ShowItem.showItem(material(), amount(), tagHolder)));
|
final BinaryTagHolder tagHolder = BinaryTagHolder.encode(meta().toNBT(), MinestomAdventure.NBT_CODEC);
|
||||||
|
return HoverEvent.showItem(op.apply(HoverEvent.ShowItem.showItem(material(), amount(), tagHolder)));
|
||||||
|
} catch (IOException e) {
|
||||||
|
//todo(matt): revisit,
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -178,7 +184,7 @@ public sealed interface ItemStack extends TagReadable, HoverEventSource<HoverEve
|
||||||
* @return The nbt representation of the item
|
* @return The nbt representation of the item
|
||||||
*/
|
*/
|
||||||
@ApiStatus.Experimental
|
@ApiStatus.Experimental
|
||||||
@NotNull NBTCompound toItemNBT();
|
@NotNull CompoundBinaryTag toItemNBT();
|
||||||
|
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
@ -208,7 +214,7 @@ public sealed interface ItemStack extends TagReadable, HoverEventSource<HoverEve
|
||||||
@NotNull Builder meta(@NotNull TagHandler tagHandler);
|
@NotNull Builder meta(@NotNull TagHandler tagHandler);
|
||||||
|
|
||||||
@Contract(value = "_ -> this")
|
@Contract(value = "_ -> this")
|
||||||
@NotNull Builder meta(@NotNull NBTCompound compound);
|
@NotNull Builder meta(@NotNull CompoundBinaryTag compound);
|
||||||
|
|
||||||
@Contract(value = "_ -> this")
|
@Contract(value = "_ -> this")
|
||||||
@NotNull Builder meta(@NotNull ItemMeta itemMeta);
|
@NotNull Builder meta(@NotNull ItemMeta itemMeta);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package net.minestom.server.item;
|
package net.minestom.server.item;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.minestom.server.ServerFlag;
|
import net.minestom.server.ServerFlag;
|
||||||
import net.minestom.server.item.rule.VanillaStackingRule;
|
import net.minestom.server.item.rule.VanillaStackingRule;
|
||||||
import net.minestom.server.tag.Tag;
|
import net.minestom.server.tag.Tag;
|
||||||
|
@ -7,12 +8,7 @@ import net.minestom.server.tag.TagHandler;
|
||||||
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.NBTByte;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTString;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
record ItemStackImpl(Material material, int amount, ItemMetaImpl meta) implements ItemStack {
|
record ItemStackImpl(Material material, int amount, ItemMetaImpl meta) implements ItemStack {
|
||||||
|
@ -89,12 +85,13 @@ record ItemStackImpl(Material material, int amount, ItemMetaImpl meta) implement
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull NBTCompound toItemNBT() {
|
public @NotNull CompoundBinaryTag toItemNBT() {
|
||||||
final NBTString material = NBT.String(material().name());
|
CompoundBinaryTag.Builder builder = CompoundBinaryTag.builder()
|
||||||
final NBTByte amount = NBT.Byte(amount());
|
.putString("id", material.name())
|
||||||
final NBTCompound nbt = meta().toNBT();
|
.putByte("Count", (byte) amount);
|
||||||
if (nbt.isEmpty()) return NBT.Compound(Map.of("id", material, "Count", amount));
|
CompoundBinaryTag nbt = meta.toNBT();
|
||||||
return NBT.Compound(Map.of("id", material, "Count", amount, "tag", nbt));
|
if (nbt.size() > 0) builder.put("tag", nbt);
|
||||||
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract(value = "-> new", pure = true)
|
@Contract(value = "-> new", pure = true)
|
||||||
|
@ -129,7 +126,7 @@ record ItemStackImpl(Material material, int amount, ItemMetaImpl meta) implement
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemStack.@NotNull Builder meta(@NotNull NBTCompound compound) {
|
public ItemStack.@NotNull Builder meta(@NotNull CompoundBinaryTag compound) {
|
||||||
return metaBuilder(new ItemMetaImpl.Builder(TagHandler.fromCompound(compound)));
|
return metaBuilder(new ItemMetaImpl.Builder(TagHandler.fromCompound(compound)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,19 @@
|
||||||
package net.minestom.server.item.armor;
|
package net.minestom.server.item.armor;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.BinaryTagTypes;
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
|
import net.kyori.adventure.nbt.ListBinaryTag;
|
||||||
import net.minestom.server.item.Material;
|
import net.minestom.server.item.Material;
|
||||||
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.NBTType;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class TrimManager {
|
public class TrimManager {
|
||||||
private final Set<TrimMaterial> trimMaterials;
|
private final Set<TrimMaterial> trimMaterials;
|
||||||
private final Set<TrimPattern> trimPatterns;
|
private final Set<TrimPattern> trimPatterns;
|
||||||
private NBTCompound trimMaterialCache = null;
|
private CompoundBinaryTag trimMaterialCache = null;
|
||||||
private NBTCompound trimPatternCache = null;
|
private CompoundBinaryTag trimPatternCache = null;
|
||||||
|
|
||||||
public TrimManager() {
|
public TrimManager() {
|
||||||
this.trimMaterials = new HashSet<>();
|
this.trimMaterials = new HashSet<>();
|
||||||
|
@ -30,38 +29,28 @@ public class TrimManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public NBTCompound getTrimMaterialNBT() {
|
public CompoundBinaryTag getTrimMaterialNBT() {
|
||||||
if (trimMaterialCache == null) {
|
if (trimMaterialCache == null) {
|
||||||
var trimMaterials = this.trimMaterials.stream()
|
ListBinaryTag.Builder<CompoundBinaryTag> entries = ListBinaryTag.builder(BinaryTagTypes.COMPOUND);
|
||||||
.map((trimMaterial) -> NBT.Compound(Map.of(
|
for (TrimMaterial trimMaterial : this.trimMaterials)
|
||||||
"id", NBT.Int(trimMaterial.id()),
|
entries.add(trimMaterial.asNBT());
|
||||||
"name", NBT.String(trimMaterial.name()),
|
trimMaterialCache = CompoundBinaryTag.builder()
|
||||||
"element", trimMaterial.asNBT()
|
.putString("type", "minecraft:trim_material")
|
||||||
)))
|
.put("value", entries.build())
|
||||||
.toList();
|
.build();
|
||||||
|
|
||||||
trimMaterialCache = NBT.Compound(Map.of(
|
|
||||||
"type", NBT.String("minecraft:trim_material"),
|
|
||||||
"value", NBT.List(NBTType.TAG_Compound, trimMaterials)
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
return trimMaterialCache;
|
return trimMaterialCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NBTCompound getTrimPatternNBT() {
|
public CompoundBinaryTag getTrimPatternNBT() {
|
||||||
if (trimPatternCache == null) {
|
if (trimPatternCache == null) {
|
||||||
var trimPatterns = this.trimPatterns.stream()
|
ListBinaryTag.Builder<CompoundBinaryTag> entries = ListBinaryTag.builder(BinaryTagTypes.COMPOUND);
|
||||||
.map((trimPattern) -> NBT.Compound(Map.of(
|
for (TrimPattern trimPattern : this.trimPatterns)
|
||||||
"id", NBT.Int(trimPattern.id()),
|
entries.add(trimPattern.asNBT());
|
||||||
"name", NBT.String(trimPattern.name()),
|
trimPatternCache = CompoundBinaryTag.builder()
|
||||||
"element", trimPattern.asNBT()
|
.putString("type", "minecraft:trim_pattern")
|
||||||
)))
|
.put("value", entries.build())
|
||||||
.toList();
|
.build();
|
||||||
|
|
||||||
trimPatternCache = NBT.Compound(Map.of(
|
|
||||||
"type", NBT.String("minecraft:trim_pattern"),
|
|
||||||
"value", NBT.List(NBTType.TAG_Compound, trimPatterns)
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return trimPatternCache;
|
return trimPatternCache;
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package net.minestom.server.item.armor;
|
package net.minestom.server.item.armor;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.minestom.server.item.Material;
|
import net.minestom.server.item.Material;
|
||||||
import net.minestom.server.registry.StaticProtocolObject;
|
|
||||||
import net.minestom.server.registry.Registry;
|
import net.minestom.server.registry.Registry;
|
||||||
|
import net.minestom.server.registry.StaticProtocolObject;
|
||||||
import net.minestom.server.utils.NamespaceID;
|
import net.minestom.server.utils.NamespaceID;
|
||||||
import org.jetbrains.annotations.Contract;
|
import org.jetbrains.annotations.Contract;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -84,6 +84,6 @@ public interface TrimMaterial extends StaticProtocolObject {
|
||||||
return registry().description();
|
return registry().description();
|
||||||
}
|
}
|
||||||
|
|
||||||
NBTCompound asNBT();
|
CompoundBinaryTag asNBT();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package net.minestom.server.item.armor;
|
package net.minestom.server.item.armor;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
|
import net.kyori.adventure.nbt.StringBinaryTag;
|
||||||
import net.minestom.server.adventure.serializer.nbt.NbtComponentSerializer;
|
import net.minestom.server.adventure.serializer.nbt.NbtComponentSerializer;
|
||||||
import net.minestom.server.registry.Registry;
|
import net.minestom.server.registry.Registry;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBT;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -31,19 +31,15 @@ record TrimMaterialImpl(Registry.TrimMaterialEntry registry, int id) implements
|
||||||
return CONTAINER.values();
|
return CONTAINER.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
public NBTCompound asNBT() {
|
public CompoundBinaryTag asNBT() {
|
||||||
return NBT.Compound(nbt -> {
|
return CompoundBinaryTag.builder()
|
||||||
nbt.setString("asset_name", assetName());
|
.putString("asset_name", assetName())
|
||||||
nbt.setString("ingredient", ingredient().namespace().asString());
|
.putString("ingredient", ingredient().namespace().asString())
|
||||||
nbt.setFloat("item_model_index", itemModelIndex());
|
.putFloat("item_model_index", itemModelIndex())
|
||||||
nbt.set("override_armor_materials", NBT.Compound(overrideArmorMaterials().entrySet().stream()
|
.put("override_armor_materials", CompoundBinaryTag.from(overrideArmorMaterials().entrySet().stream()
|
||||||
.collect(Collectors.toMap(
|
.collect(Collectors.toMap(Map.Entry::getKey, entry -> StringBinaryTag.stringBinaryTag(entry.getValue())))))
|
||||||
Map.Entry::getKey,
|
.put("description", NbtComponentSerializer.nbt().serialize(description()))
|
||||||
entry -> NBT.String(entry.getValue())
|
.build();
|
||||||
))
|
|
||||||
));
|
|
||||||
nbt.set("description", NbtComponentSerializer.nbt().serialize(description()));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package net.minestom.server.item.armor;
|
package net.minestom.server.item.armor;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.minestom.server.item.Material;
|
import net.minestom.server.item.Material;
|
||||||
import net.minestom.server.registry.StaticProtocolObject;
|
|
||||||
import net.minestom.server.registry.Registry;
|
import net.minestom.server.registry.Registry;
|
||||||
|
import net.minestom.server.registry.StaticProtocolObject;
|
||||||
import net.minestom.server.utils.NamespaceID;
|
import net.minestom.server.utils.NamespaceID;
|
||||||
import org.jetbrains.annotations.Contract;
|
import org.jetbrains.annotations.Contract;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
@ -61,6 +61,6 @@ public interface TrimPattern extends StaticProtocolObject {
|
||||||
return registry().decal();
|
return registry().decal();
|
||||||
}
|
}
|
||||||
|
|
||||||
NBTCompound asNBT();
|
CompoundBinaryTag asNBT();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
package net.minestom.server.item.armor;
|
package net.minestom.server.item.armor;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.minestom.server.adventure.serializer.nbt.NbtComponentSerializer;
|
import net.minestom.server.adventure.serializer.nbt.NbtComponentSerializer;
|
||||||
import net.minestom.server.registry.Registry;
|
import net.minestom.server.registry.Registry;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBT;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
@ -29,13 +28,13 @@ record TrimPatternImpl(Registry.TrimPatternEntry registry, int id) implements Tr
|
||||||
return CONTAINER.values();
|
return CONTAINER.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
public NBTCompound asNBT() {
|
public CompoundBinaryTag asNBT() {
|
||||||
return NBT.Compound(nbt -> {
|
return CompoundBinaryTag.builder()
|
||||||
nbt.setString("asset_id", assetID().asString());
|
.putString("asset_id", assetID().asString())
|
||||||
nbt.setString("template_item", template().namespace().asString());
|
.putString("template_item", template().namespace().asString())
|
||||||
nbt.set("description", NbtComponentSerializer.nbt().serialize(description()));
|
.put("description", NbtComponentSerializer.nbt().serialize(description()))
|
||||||
nbt.setByte("decal", (byte) (decal() ? 1 : 0));
|
.putBoolean("decal", decal())
|
||||||
});
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
package net.minestom.server.item.firework;
|
package net.minestom.server.item.firework;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
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.nbt.NBT;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTIntArray;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public record FireworkEffect(boolean flicker, boolean trail,
|
public record FireworkEffect(boolean flicker, boolean trail,
|
||||||
@NotNull FireworkEffectType type,
|
@NotNull FireworkEffectType type,
|
||||||
|
@ -25,36 +22,34 @@ public record FireworkEffect(boolean flicker, boolean trail,
|
||||||
* @param compound The NBT connection, which should be a fireworks effect.
|
* @param compound The NBT connection, which should be a fireworks effect.
|
||||||
* @return A new created firework effect.
|
* @return A new created firework effect.
|
||||||
*/
|
*/
|
||||||
public static @NotNull FireworkEffect fromCompound(@NotNull NBTCompound compound) {
|
public static @NotNull FireworkEffect fromCompound(@NotNull CompoundBinaryTag compound) {
|
||||||
List<Color> primaryColor = new ArrayList<>();
|
List<Color> primaryColor = new ArrayList<>();
|
||||||
List<Color> secondaryColor = new ArrayList<>();
|
List<Color> secondaryColor = new ArrayList<>();
|
||||||
|
|
||||||
if (compound.get("Colors") instanceof NBTIntArray colors) {
|
for (int rgb : compound.getIntArray("Colors"))
|
||||||
for (int rgb : colors) primaryColor.add(new Color(rgb));
|
primaryColor.add(new Color(rgb));
|
||||||
}
|
for (int rgb : compound.getIntArray("FadeColors"))
|
||||||
if (compound.get("FadeColors") instanceof NBTIntArray fadeColors) {
|
secondaryColor.add(new Color(rgb));
|
||||||
for (int rgb : fadeColors) secondaryColor.add(new Color(rgb));
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean flicker = compound.containsKey("Flicker") && compound.getBoolean("Flicker");
|
boolean flicker = compound.getBoolean("Flicker");
|
||||||
boolean trail = compound.containsKey("Trail") && compound.getBoolean("Trail");
|
boolean trail = compound.getBoolean("Trail");
|
||||||
FireworkEffectType type = compound.containsKey("Type") ?
|
FireworkEffectType type = FireworkEffectType.byId(compound.getByte("Type"));
|
||||||
FireworkEffectType.byId(compound.getAsByte("Type")) : FireworkEffectType.SMALL_BALL;
|
|
||||||
|
|
||||||
return new FireworkEffect(flicker, trail, type, primaryColor, secondaryColor);
|
return new FireworkEffect(flicker, trail, type, primaryColor, secondaryColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the {@link FireworkEffect} as a {@link NBTCompound}.
|
* Retrieves the {@link FireworkEffect} as a {@link CompoundBinaryTag}.
|
||||||
*
|
*
|
||||||
* @return The firework effect as a nbt compound.
|
* @return The firework effect as a nbt compound.
|
||||||
*/
|
*/
|
||||||
public @NotNull NBTCompound asCompound() {
|
public @NotNull CompoundBinaryTag asCompound() {
|
||||||
return NBT.Compound(Map.of(
|
return CompoundBinaryTag.builder()
|
||||||
"Flicker", NBT.Boolean(flicker),
|
.putBoolean("Flicker", flicker)
|
||||||
"Trail", NBT.Boolean(trail),
|
.putBoolean("Trail", trail)
|
||||||
"Type", NBT.Byte(type.getType()),
|
.putByte("Type", (byte) type.getType())
|
||||||
"Colors", NBT.IntArray(colors.stream().mapToInt(Color::asRGB).toArray()),
|
.putIntArray("Colors", colors.stream().mapToInt(Color::asRGB).toArray())
|
||||||
"FadeColors", NBT.IntArray(fadeColors.stream().mapToInt(Color::asRGB).toArray())));
|
.putIntArray("FadeColors", fadeColors.stream().mapToInt(Color::asRGB).toArray())
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,32 +1,30 @@
|
||||||
package net.minestom.server.item.metadata;
|
package net.minestom.server.item.metadata;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.BinaryTag;
|
||||||
|
import net.kyori.adventure.nbt.BinaryTagTypes;
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
|
import net.kyori.adventure.nbt.ListBinaryTag;
|
||||||
import net.minestom.server.entity.PlayerSkin;
|
import net.minestom.server.entity.PlayerSkin;
|
||||||
import net.minestom.server.item.ItemMetaView;
|
import net.minestom.server.item.ItemMetaView;
|
||||||
import net.minestom.server.tag.*;
|
import 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.jetbrains.annotations.UnknownNullability;
|
import org.jetbrains.annotations.UnknownNullability;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBT;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTList;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTType;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public record PlayerHeadMeta(TagReadable readable) implements ItemMetaView<PlayerHeadMeta.Builder> {
|
public record PlayerHeadMeta(TagReadable readable) implements ItemMetaView<PlayerHeadMeta.Builder> {
|
||||||
public static final Tag<UUID> SKULL_OWNER = Tag.UUID("Id").path("SkullOwner");
|
public static final Tag<UUID> SKULL_OWNER = Tag.UUID("Id").path("SkullOwner");
|
||||||
public static final Tag<PlayerSkin> SKIN = Tag.Structure("Properties", new TagSerializer<PlayerSkin>() {
|
public static final Tag<PlayerSkin> SKIN = Tag.Structure("Properties", new TagSerializer<PlayerSkin>() {
|
||||||
private static final Tag<NBT> TEXTURES = Tag.NBT("textures");
|
private static final Tag<BinaryTag> TEXTURES = Tag.NBT("textures");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable PlayerSkin read(@NotNull TagReadable reader) {
|
public @Nullable PlayerSkin read(@NotNull TagReadable reader) {
|
||||||
final NBT result = reader.getTag(TEXTURES);
|
final BinaryTag result = reader.getTag(TEXTURES);
|
||||||
if (!(result instanceof NBTList)) return null;
|
if (!(result instanceof ListBinaryTag textures)) return null;
|
||||||
final NBTList<NBTCompound> textures = (NBTList<NBTCompound>) result;
|
final CompoundBinaryTag texture = textures.getCompound(0);
|
||||||
final NBTCompound texture = textures.get(0);
|
|
||||||
final String value = texture.getString("Value");
|
final String value = texture.getString("Value");
|
||||||
final String signature = texture.getString("Signature");
|
final String signature = texture.getString("Signature");
|
||||||
return new PlayerSkin(value, signature);
|
return new PlayerSkin(value, signature);
|
||||||
|
@ -36,9 +34,9 @@ public record PlayerHeadMeta(TagReadable readable) implements ItemMetaView<Playe
|
||||||
public void write(@NotNull TagWritable writer, @NotNull PlayerSkin playerSkin) {
|
public void write(@NotNull TagWritable writer, @NotNull PlayerSkin playerSkin) {
|
||||||
final String value = Objects.requireNonNullElse(playerSkin.textures(), "");
|
final String value = Objects.requireNonNullElse(playerSkin.textures(), "");
|
||||||
final String signature = Objects.requireNonNullElse(playerSkin.signature(), "");
|
final String signature = Objects.requireNonNullElse(playerSkin.signature(), "");
|
||||||
NBTList<NBTCompound> textures = new NBTList<>(NBTType.TAG_Compound,
|
writer.setTag(TEXTURES, ListBinaryTag.listBinaryTag(BinaryTagTypes.COMPOUND, List.of(
|
||||||
List.of(NBT.Compound(Map.of("Value", NBT.String(value), "Signature", NBT.String(signature)))));
|
CompoundBinaryTag.builder().putString("Value", value).putString("Signature", signature).build()
|
||||||
writer.setTag(TEXTURES, textures);
|
)));
|
||||||
}
|
}
|
||||||
}).path("SkullOwner");
|
}).path("SkullOwner");
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package net.minestom.server.listener;
|
package net.minestom.server.listener;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.minestom.server.coordinate.Point;
|
import net.minestom.server.coordinate.Point;
|
||||||
import net.minestom.server.coordinate.Pos;
|
import net.minestom.server.coordinate.Pos;
|
||||||
import net.minestom.server.entity.GameMode;
|
import net.minestom.server.entity.GameMode;
|
||||||
|
@ -22,7 +23,6 @@ import net.minestom.server.network.packet.server.play.AcknowledgeBlockChangePack
|
||||||
import net.minestom.server.network.packet.server.play.BlockEntityDataPacket;
|
import net.minestom.server.network.packet.server.play.BlockEntityDataPacket;
|
||||||
import net.minestom.server.utils.block.BlockUtils;
|
import net.minestom.server.utils.block.BlockUtils;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
|
||||||
|
|
||||||
public final class PlayerDiggingListener {
|
public final class PlayerDiggingListener {
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ public final class PlayerDiggingListener {
|
||||||
// Refresh block on player screen in case it had special data (like a sign)
|
// Refresh block on player screen in case it had special data (like a sign)
|
||||||
var registry = diggingResult.block().registry();
|
var registry = diggingResult.block().registry();
|
||||||
if (registry.isBlockEntity()) {
|
if (registry.isBlockEntity()) {
|
||||||
final NBTCompound data = BlockUtils.extractClientNbt(diggingResult.block());
|
final CompoundBinaryTag data = BlockUtils.extractClientNbt(diggingResult.block());
|
||||||
player.sendPacketToViewersAndSelf(new BlockEntityDataPacket(blockPosition, registry.blockEntityId(), data));
|
player.sendPacketToViewersAndSelf(new BlockEntityDataPacket(blockPosition, registry.blockEntityId(), data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package net.minestom.server.message;
|
package net.minestom.server.message;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
|
import net.kyori.adventure.nbt.TagStringIO;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
import net.minestom.server.entity.Player;
|
import net.minestom.server.entity.Player;
|
||||||
|
@ -7,11 +9,8 @@ import net.minestom.server.network.packet.server.play.SystemChatPacket;
|
||||||
import net.minestom.server.utils.PacketUtils;
|
import net.minestom.server.utils.PacketUtils;
|
||||||
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.NBTException;
|
|
||||||
import org.jglrxavpok.hephaistos.parser.SNBTParser;
|
|
||||||
|
|
||||||
import java.io.StringReader;
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -27,11 +26,11 @@ public final class Messenger {
|
||||||
private static final UUID NO_SENDER = new UUID(0, 0);
|
private static final UUID NO_SENDER = new UUID(0, 0);
|
||||||
private static final SystemChatPacket CANNOT_SEND_PACKET = new SystemChatPacket(CANNOT_SEND_MESSAGE, false);
|
private static final SystemChatPacket CANNOT_SEND_PACKET = new SystemChatPacket(CANNOT_SEND_MESSAGE, false);
|
||||||
|
|
||||||
private static final NBTCompound CHAT_REGISTRY;
|
private static final CompoundBinaryTag CHAT_REGISTRY;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
CHAT_REGISTRY = (NBTCompound) new SNBTParser(new StringReader(
|
CHAT_REGISTRY = TagStringIO.get().asCompound(
|
||||||
"""
|
"""
|
||||||
{
|
{
|
||||||
"type": "minecraft:chat_type",
|
"type": "minecraft:chat_type",
|
||||||
|
@ -57,13 +56,13 @@ public final class Messenger {
|
||||||
}
|
}
|
||||||
} ]
|
} ]
|
||||||
}"""
|
}"""
|
||||||
)).parse();
|
);
|
||||||
} catch (NBTException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @NotNull NBTCompound chatRegistry() {
|
public static @NotNull CompoundBinaryTag chatRegistry() {
|
||||||
return CHAT_REGISTRY;
|
return CHAT_REGISTRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package net.minestom.server.network;
|
package net.minestom.server.network;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
import net.minestom.server.MinecraftServer;
|
import net.minestom.server.MinecraftServer;
|
||||||
|
@ -32,7 +33,8 @@ import org.jctools.queues.MpscUnboundedArrayQueue;
|
||||||
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.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
@ -280,14 +282,15 @@ public final class ConnectionManager {
|
||||||
|
|
||||||
// Registry data (if it should be sent)
|
// Registry data (if it should be sent)
|
||||||
if (event.willSendRegistryData()) {
|
if (event.willSendRegistryData()) {
|
||||||
var registry = new HashMap<String, NBT>();
|
var registryCompound = CompoundBinaryTag.builder()
|
||||||
registry.put("minecraft:chat_type", Messenger.chatRegistry());
|
.put("minecraft:chat_type", Messenger.chatRegistry())
|
||||||
registry.put("minecraft:dimension_type", MinecraftServer.getDimensionTypeManager().toNBT());
|
.put("minecraft:dimension_type", MinecraftServer.getDimensionTypeManager().toNBT())
|
||||||
registry.put("minecraft:worldgen/biome", MinecraftServer.getBiomeManager().toNBT());
|
.put("minecraft:worldgen/biome", MinecraftServer.getBiomeManager().toNBT())
|
||||||
registry.put("minecraft:damage_type", DamageType.getNBT());
|
.put("minecraft:damage_type", DamageType.getNBT())
|
||||||
registry.put("minecraft:trim_material", MinecraftServer.getTrimManager().getTrimMaterialNBT());
|
// .put("minecraft:trim_material", MinecraftServer.getTrimManager().getTrimMaterialNBT())
|
||||||
registry.put("minecraft:trim_pattern", MinecraftServer.getTrimManager().getTrimPatternNBT());
|
// .put("minecraft:trim_pattern", MinecraftServer.getTrimManager().getTrimPatternNBT())
|
||||||
player.sendPacket(new RegistryDataPacket(NBT.Compound(registry)));
|
.build();
|
||||||
|
player.sendPacket(new RegistryDataPacket(registryCompound));
|
||||||
|
|
||||||
player.sendPacket(TagsPacket.DEFAULT_TAGS);
|
player.sendPacket(TagsPacket.DEFAULT_TAGS);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package net.minestom.server.network;
|
package net.minestom.server.network;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.BinaryTag;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.minestom.server.coordinate.Point;
|
import net.minestom.server.coordinate.Point;
|
||||||
import net.minestom.server.entity.Entity;
|
import net.minestom.server.entity.Entity;
|
||||||
|
@ -15,10 +16,9 @@ import net.minestom.server.utils.validate.Check;
|
||||||
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.NBTReader;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTWriter;
|
|
||||||
|
|
||||||
|
import java.io.DataInput;
|
||||||
|
import java.io.DataOutput;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -40,7 +40,7 @@ public final class NetworkBuffer {
|
||||||
public static final Type<Long> VAR_LONG = new NetworkBufferTypeImpl.VarLongType();
|
public static final Type<Long> VAR_LONG = new NetworkBufferTypeImpl.VarLongType();
|
||||||
public static final Type<byte[]> RAW_BYTES = new NetworkBufferTypeImpl.RawBytesType();
|
public static final Type<byte[]> RAW_BYTES = new NetworkBufferTypeImpl.RawBytesType();
|
||||||
public static final Type<String> STRING = new NetworkBufferTypeImpl.StringType();
|
public static final Type<String> STRING = new NetworkBufferTypeImpl.StringType();
|
||||||
public static final Type<NBT> NBT = new NetworkBufferTypeImpl.NbtType();
|
public static final Type<BinaryTag> NBT = new NetworkBufferTypeImpl.NbtType();
|
||||||
public static final Type<Point> BLOCK_POSITION = new NetworkBufferTypeImpl.BlockPositionType();
|
public static final Type<Point> BLOCK_POSITION = new NetworkBufferTypeImpl.BlockPositionType();
|
||||||
public static final Type<Component> COMPONENT = new NetworkBufferTypeImpl.ComponentType();
|
public static final Type<Component> COMPONENT = new NetworkBufferTypeImpl.ComponentType();
|
||||||
public static final Type<Component> JSON_COMPONENT = new NetworkBufferTypeImpl.JsonComponentType();
|
public static final Type<Component> JSON_COMPONENT = new NetworkBufferTypeImpl.JsonComponentType();
|
||||||
|
@ -81,8 +81,8 @@ public final class NetworkBuffer {
|
||||||
int writeIndex;
|
int writeIndex;
|
||||||
int readIndex;
|
int readIndex;
|
||||||
|
|
||||||
NBTWriter nbtWriter;
|
DataOutput nbtWriter;
|
||||||
NBTReader nbtReader;
|
DataInput nbtReader;
|
||||||
|
|
||||||
public NetworkBuffer(@NotNull ByteBuffer buffer, boolean resizable) {
|
public NetworkBuffer(@NotNull ByteBuffer buffer, boolean resizable) {
|
||||||
this.nioBuffer = buffer.order(ByteOrder.BIG_ENDIAN);
|
this.nioBuffer = buffer.order(ByteOrder.BIG_ENDIAN);
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
package net.minestom.server.network.packet.server.configuration;
|
package net.minestom.server.network.packet.server.configuration;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.minestom.server.network.NetworkBuffer;
|
import net.minestom.server.network.NetworkBuffer;
|
||||||
import net.minestom.server.network.packet.server.ServerPacket;
|
import net.minestom.server.network.packet.server.ServerPacket;
|
||||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
|
||||||
|
|
||||||
import static net.minestom.server.network.NetworkBuffer.NBT;
|
import static net.minestom.server.network.NetworkBuffer.NBT;
|
||||||
|
|
||||||
public record RegistryDataPacket(@NotNull NBTCompound data) implements ServerPacket.Configuration {
|
public record RegistryDataPacket(@NotNull CompoundBinaryTag data) implements ServerPacket.Configuration {
|
||||||
public RegistryDataPacket(@NotNull NetworkBuffer buffer) {
|
public RegistryDataPacket(@NotNull NetworkBuffer buffer) {
|
||||||
this((NBTCompound) buffer.read(NBT));
|
this((CompoundBinaryTag) buffer.read(NBT));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
package net.minestom.server.network.packet.server.play;
|
package net.minestom.server.network.packet.server.play;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.minestom.server.coordinate.Point;
|
import net.minestom.server.coordinate.Point;
|
||||||
import net.minestom.server.network.NetworkBuffer;
|
import net.minestom.server.network.NetworkBuffer;
|
||||||
import net.minestom.server.network.packet.server.ServerPacket;
|
import net.minestom.server.network.packet.server.ServerPacket;
|
||||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||||
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 static net.minestom.server.network.NetworkBuffer.*;
|
import static net.minestom.server.network.NetworkBuffer.*;
|
||||||
|
|
||||||
public record BlockEntityDataPacket(@NotNull Point blockPosition, int action,
|
public record BlockEntityDataPacket(@NotNull Point blockPosition, int action,
|
||||||
@Nullable NBTCompound data) implements ServerPacket.Play {
|
@Nullable CompoundBinaryTag data) implements ServerPacket.Play {
|
||||||
public BlockEntityDataPacket(@NotNull NetworkBuffer reader) {
|
public BlockEntityDataPacket(@NotNull NetworkBuffer reader) {
|
||||||
this(reader.read(BLOCK_POSITION), reader.read(VAR_INT), (NBTCompound) reader.read(NBT));
|
this(reader.read(BLOCK_POSITION), reader.read(VAR_INT), (CompoundBinaryTag) reader.read(NBT));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
package net.minestom.server.network.packet.server.play;
|
package net.minestom.server.network.packet.server.play;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.minestom.server.network.NetworkBuffer;
|
import net.minestom.server.network.NetworkBuffer;
|
||||||
import net.minestom.server.network.packet.server.ServerPacket;
|
import net.minestom.server.network.packet.server.ServerPacket;
|
||||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||||
import net.minestom.server.potion.Potion;
|
import net.minestom.server.potion.Potion;
|
||||||
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 static net.minestom.server.network.NetworkBuffer.*;
|
import static net.minestom.server.network.NetworkBuffer.*;
|
||||||
|
|
||||||
public record EntityEffectPacket(int entityId, @NotNull Potion potion,
|
public record EntityEffectPacket(int entityId, @NotNull Potion potion,
|
||||||
@Nullable NBTCompound factorCodec) implements ServerPacket.Play {
|
@Nullable CompoundBinaryTag factorCodec) implements ServerPacket.Play {
|
||||||
public EntityEffectPacket(@NotNull NetworkBuffer reader) {
|
public EntityEffectPacket(@NotNull NetworkBuffer reader) {
|
||||||
this(reader.read(VAR_INT), new Potion(reader),
|
this(reader.read(VAR_INT), new Potion(reader),
|
||||||
reader.read(BOOLEAN) ? (NBTCompound) reader.read(NBT) : null);
|
reader.read(BOOLEAN) ? (CompoundBinaryTag) reader.read(NBT) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
package net.minestom.server.network.packet.server.play;
|
package net.minestom.server.network.packet.server.play;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
|
import net.minestom.server.network.ConnectionState;
|
||||||
import net.minestom.server.network.NetworkBuffer;
|
import net.minestom.server.network.NetworkBuffer;
|
||||||
import net.minestom.server.network.packet.server.ServerPacket;
|
import net.minestom.server.network.packet.server.ServerPacket;
|
||||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
|
||||||
|
|
||||||
import static net.minestom.server.network.NetworkBuffer.*;
|
import static net.minestom.server.network.NetworkBuffer.*;
|
||||||
|
|
||||||
public record NbtQueryResponsePacket(int transactionId, NBTCompound data) implements ServerPacket.Play {
|
public record NbtQueryResponsePacket(int transactionId, CompoundBinaryTag data) implements ServerPacket.Play {
|
||||||
public NbtQueryResponsePacket(@NotNull NetworkBuffer reader) {
|
public NbtQueryResponsePacket(@NotNull NetworkBuffer reader) {
|
||||||
this(reader.read(VAR_INT), (NBTCompound) reader.read(NBT));
|
this(reader.read(VAR_INT), (CompoundBinaryTag) reader.read(NBT));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package net.minestom.server.network.packet.server.play.data;
|
package net.minestom.server.network.packet.server.play.data;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.minestom.server.coordinate.Point;
|
import net.minestom.server.coordinate.Point;
|
||||||
import net.minestom.server.instance.block.Block;
|
import net.minestom.server.instance.block.Block;
|
||||||
import net.minestom.server.network.NetworkBuffer;
|
import net.minestom.server.network.NetworkBuffer;
|
||||||
import net.minestom.server.utils.block.BlockUtils;
|
import net.minestom.server.utils.block.BlockUtils;
|
||||||
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.NBTCompound;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -14,7 +14,7 @@ import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static net.minestom.server.network.NetworkBuffer.*;
|
import static net.minestom.server.network.NetworkBuffer.*;
|
||||||
|
|
||||||
public record ChunkData(@NotNull NBTCompound heightmaps, byte @NotNull [] data,
|
public record ChunkData(@NotNull CompoundBinaryTag heightmaps, byte @NotNull [] data,
|
||||||
@NotNull Map<Integer, Block> blockEntities) implements NetworkBuffer.Writer {
|
@NotNull Map<Integer, Block> blockEntities) implements NetworkBuffer.Writer {
|
||||||
public ChunkData {
|
public ChunkData {
|
||||||
blockEntities = blockEntities.entrySet()
|
blockEntities = blockEntities.entrySet()
|
||||||
|
@ -24,7 +24,7 @@ public record ChunkData(@NotNull NBTCompound heightmaps, byte @NotNull [] data,
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChunkData(@NotNull NetworkBuffer reader) {
|
public ChunkData(@NotNull NetworkBuffer reader) {
|
||||||
this((NBTCompound) reader.read(NBT), reader.read(BYTE_ARRAY),
|
this((CompoundBinaryTag) reader.read(NBT), reader.read(BYTE_ARRAY),
|
||||||
readBlockEntities(reader));
|
readBlockEntities(reader));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ public record ChunkData(@NotNull NBTCompound heightmaps, byte @NotNull [] data,
|
||||||
writer.write(SHORT, (short) point.blockY()); // y
|
writer.write(SHORT, (short) point.blockY()); // y
|
||||||
|
|
||||||
writer.write(VAR_INT, registry.blockEntityId());
|
writer.write(VAR_INT, registry.blockEntityId());
|
||||||
final NBTCompound nbt = BlockUtils.extractClientNbt(block);
|
final CompoundBinaryTag nbt = BlockUtils.extractClientNbt(block);
|
||||||
assert nbt != null;
|
assert nbt != null;
|
||||||
writer.write(NBT, nbt); // block nbt
|
writer.write(NBT, nbt); // block nbt
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ public record ChunkData(@NotNull NBTCompound heightmaps, byte @NotNull [] data,
|
||||||
final byte xz = reader.read(BYTE);
|
final byte xz = reader.read(BYTE);
|
||||||
final short y = reader.read(SHORT);
|
final short y = reader.read(SHORT);
|
||||||
final int blockEntityId = reader.read(VAR_INT);
|
final int blockEntityId = reader.read(VAR_INT);
|
||||||
final NBTCompound nbt = (NBTCompound) reader.read(NBT);
|
final CompoundBinaryTag nbt = (CompoundBinaryTag) reader.read(NBT);
|
||||||
// TODO create block object
|
// TODO create block object
|
||||||
}
|
}
|
||||||
return blockEntities;
|
return blockEntities;
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
package net.minestom.server.permission;
|
package net.minestom.server.permission;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.minestom.server.command.CommandSender;
|
import net.minestom.server.command.CommandSender;
|
||||||
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 java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Representation of a permission granted to a {@link CommandSender}.
|
* Representation of a permission granted to a {@link CommandSender}.
|
||||||
* Each permission has a string representation used as an identifier, and an optional
|
* Each permission has a string representation used as an identifier, and an optional
|
||||||
* {@link NBTCompound} used to store additional data.
|
* {@link CompoundBinaryTag} used to store additional data.
|
||||||
* <p>
|
* <p>
|
||||||
* The class is immutable.
|
* The class is immutable.
|
||||||
*/
|
*/
|
||||||
public class Permission {
|
public class Permission {
|
||||||
|
|
||||||
private final String permissionName;
|
private final String permissionName;
|
||||||
private final NBTCompound data;
|
private final CompoundBinaryTag data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new permission object with optional data.
|
* Creates a new permission object with optional data.
|
||||||
|
@ -25,7 +25,7 @@ public class Permission {
|
||||||
* @param permissionName the name of the permission
|
* @param permissionName the name of the permission
|
||||||
* @param data the optional data of the permission
|
* @param data the optional data of the permission
|
||||||
*/
|
*/
|
||||||
public Permission(@NotNull String permissionName, @Nullable NBTCompound data) {
|
public Permission(@NotNull String permissionName, @Nullable CompoundBinaryTag data) {
|
||||||
this.permissionName = permissionName;
|
this.permissionName = permissionName;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ public class Permission {
|
||||||
* @return the nbt data of this permission, can be null if not any
|
* @return the nbt data of this permission, can be null if not any
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public NBTCompound getNBTData() {
|
public CompoundBinaryTag getNBTData() {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,6 @@ 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.parser.SNBTParser;
|
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
@ -14,8 +12,7 @@ import java.util.regex.Pattern;
|
||||||
* Permissions are in-memory only by default.
|
* Permissions are in-memory only by default.
|
||||||
* You have however the capacity to store them persistently as the {@link Permission} object
|
* You have however the capacity to store them persistently as the {@link Permission} object
|
||||||
* is serializer-friendly, {@link Permission#getPermissionName()} being a {@link String}
|
* is serializer-friendly, {@link Permission#getPermissionName()} being a {@link String}
|
||||||
* and {@link Permission#getNBTData()} serializable into a string using {@link NBTCompound#toSNBT()}
|
* and {@link Permission#getNBTData()} serializable into a string using {@link net.kyori.adventure.nbt.TagStringIO}.
|
||||||
* and deserialized back with {@link SNBTParser#parse()}.
|
|
||||||
*/
|
*/
|
||||||
public interface PermissionHandler {
|
public interface PermissionHandler {
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package net.minestom.server.permission;
|
package net.minestom.server.permission;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface used to check if the {@link NBTCompound nbt data} of a {@link Permission} is correct.
|
* Interface used to check if the {@link CompoundBinaryTag nbt data} of a {@link Permission} is correct.
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface PermissionVerifier {
|
public interface PermissionVerifier {
|
||||||
|
@ -16,5 +16,5 @@ public interface PermissionVerifier {
|
||||||
* @return true if {@link PermissionHandler#hasPermission(String, PermissionVerifier)}
|
* @return true if {@link PermissionHandler#hasPermission(String, PermissionVerifier)}
|
||||||
* should return true, false otherwise
|
* should return true, false otherwise
|
||||||
*/
|
*/
|
||||||
boolean isValid(@Nullable NBTCompound nbtCompound);
|
boolean isValid(@Nullable CompoundBinaryTag nbtCompound);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package net.minestom.server.tag;
|
package net.minestom.server.tag;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.*;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||||
import net.minestom.server.ServerFlag;
|
import net.minestom.server.ServerFlag;
|
||||||
import net.minestom.server.item.ItemStack;
|
import net.minestom.server.item.ItemStack;
|
||||||
import org.jglrxavpok.hephaistos.nbt.*;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
@ -13,40 +13,41 @@ import java.util.function.Function;
|
||||||
* Basic serializers for {@link Tag tags}.
|
* Basic serializers for {@link Tag tags}.
|
||||||
*/
|
*/
|
||||||
final class Serializers {
|
final class Serializers {
|
||||||
static final Entry<Byte, NBTByte> BYTE = new Entry<>(NBTType.TAG_Byte, NBTByte::getValue, NBT::Byte);
|
static final Entry<Byte, ByteBinaryTag> BYTE = new Entry<>(BinaryTagTypes.BYTE, ByteBinaryTag::value, ByteBinaryTag::byteBinaryTag);
|
||||||
static final Entry<Boolean, NBTByte> BOOLEAN = new Entry<>(NBTType.TAG_Byte, NBTByte::asBoolean, NBT::Boolean);
|
static final Entry<Boolean, ByteBinaryTag> BOOLEAN = new Entry<>(BinaryTagTypes.BYTE, b -> b.value() != 0, b -> b ? ByteBinaryTag.ONE : ByteBinaryTag.ZERO);
|
||||||
static final Entry<Short, NBTShort> SHORT = new Entry<>(NBTType.TAG_Short, NBTShort::getValue, NBT::Short);
|
static final Entry<Short, ShortBinaryTag> SHORT = new Entry<>(BinaryTagTypes.SHORT, ShortBinaryTag::value, ShortBinaryTag::shortBinaryTag);
|
||||||
static final Entry<Integer, NBTInt> INT = new Entry<>(NBTType.TAG_Int, NBTInt::getValue, NBT::Int);
|
static final Entry<Integer, IntBinaryTag> INT = new Entry<>(BinaryTagTypes.INT, IntBinaryTag::value, IntBinaryTag::intBinaryTag);
|
||||||
static final Entry<Long, NBTLong> LONG = new Entry<>(NBTType.TAG_Long, NBTLong::getValue, NBT::Long);
|
static final Entry<Long, LongBinaryTag> LONG = new Entry<>(BinaryTagTypes.LONG, LongBinaryTag::value, LongBinaryTag::longBinaryTag);
|
||||||
static final Entry<Float, NBTFloat> FLOAT = new Entry<>(NBTType.TAG_Float, NBTFloat::getValue, NBT::Float);
|
static final Entry<Float, FloatBinaryTag> FLOAT = new Entry<>(BinaryTagTypes.FLOAT, FloatBinaryTag::value, FloatBinaryTag::floatBinaryTag);
|
||||||
static final Entry<Double, NBTDouble> DOUBLE = new Entry<>(NBTType.TAG_Double, NBTDouble::getValue, NBT::Double);
|
static final Entry<Double, DoubleBinaryTag> DOUBLE = new Entry<>(BinaryTagTypes.DOUBLE, DoubleBinaryTag::value, DoubleBinaryTag::doubleBinaryTag);
|
||||||
static final Entry<String, NBTString> STRING = new Entry<>(NBTType.TAG_String, NBTString::getValue, NBT::String);
|
static final Entry<String, StringBinaryTag> STRING = new Entry<>(BinaryTagTypes.STRING, StringBinaryTag::value, StringBinaryTag::stringBinaryTag);
|
||||||
static final Entry<NBT, NBT> NBT_ENTRY = new Entry<>(null, Function.identity(), Function.identity());
|
static final Entry<BinaryTag, BinaryTag> NBT_ENTRY = new Entry<>(null, Function.identity(), Function.identity());
|
||||||
|
|
||||||
static final Entry<java.util.UUID, NBTIntArray> UUID = new Entry<>(NBTType.TAG_Int_Array, intArray -> intArrayToUuid(intArray.getValue().copyArray()),
|
static final Entry<java.util.UUID, IntArrayBinaryTag> UUID = new Entry<>(BinaryTagTypes.INT_ARRAY,
|
||||||
uuid -> NBT.IntArray(uuidToIntArray(uuid)));
|
intArray -> intArrayToUuid(intArray.value()),
|
||||||
static final Entry<ItemStack, NBTCompound> ITEM = new Entry<>(NBTType.TAG_Compound, ItemStack::fromItemNBT, ItemStack::toItemNBT);
|
uuid -> IntArrayBinaryTag.intArrayBinaryTag(uuidToIntArray(uuid)));
|
||||||
static final Entry<Component, NBTString> COMPONENT = new Entry<>(NBTType.TAG_String, input -> GsonComponentSerializer.gson().deserialize(input.getValue()),
|
static final Entry<ItemStack, CompoundBinaryTag> ITEM = new Entry<>(BinaryTagTypes.COMPOUND, ItemStack::fromItemNBT, ItemStack::toItemNBT);
|
||||||
component -> NBT.String(GsonComponentSerializer.gson().serialize(component)));
|
static final Entry<Component, StringBinaryTag> COMPONENT = new Entry<>(BinaryTagTypes.STRING, input -> GsonComponentSerializer.gson().deserialize(input.value()),
|
||||||
|
component -> StringBinaryTag.stringBinaryTag(GsonComponentSerializer.gson().serialize(component)));
|
||||||
|
|
||||||
static final Entry<Object, NBTByte> EMPTY = new Entry<>(NBTType.TAG_Byte, unused -> null, component -> null);
|
static final Entry<Object, ByteBinaryTag> EMPTY = new Entry<>(BinaryTagTypes.BYTE, unused -> null, component -> null);
|
||||||
|
|
||||||
static <T> Entry<T, NBTCompound> fromTagSerializer(TagSerializer<T> serializer) {
|
static <T> Entry<T, CompoundBinaryTag> fromTagSerializer(TagSerializer<T> serializer) {
|
||||||
return new Serializers.Entry<>(NBTType.TAG_Compound,
|
return new Serializers.Entry<>(BinaryTagTypes.COMPOUND,
|
||||||
(NBTCompound compound) -> {
|
(CompoundBinaryTag compound) -> {
|
||||||
if ((!ServerFlag.SERIALIZE_EMPTY_COMPOUND) && compound.isEmpty()) return null;
|
if ((!ServerFlag.SERIALIZE_EMPTY_COMPOUND) && compound.size() == 0) return null;
|
||||||
return serializer.read(TagHandler.fromCompound(compound));
|
return serializer.read(TagHandler.fromCompound(compound));
|
||||||
},
|
},
|
||||||
(value) -> {
|
(value) -> {
|
||||||
if (value == null) return NBTCompound.EMPTY;
|
if (value == null) return CompoundBinaryTag.empty();
|
||||||
TagHandler handler = TagHandler.newHandler();
|
TagHandler handler = TagHandler.newHandler();
|
||||||
serializer.write(handler, value);
|
serializer.write(handler, value);
|
||||||
return handler.asCompound();
|
return handler.asCompound();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
record Entry<T, N extends NBT>(NBTType<N> nbtType, Function<N, T> reader, Function<T, N> writer, boolean isPath) {
|
record Entry<T, N extends BinaryTag>(BinaryTagType<N> nbtType, Function<N, T> reader, Function<T, N> writer, boolean isPath) {
|
||||||
Entry(NBTType<N> nbtType, Function<N, T> reader, Function<T, N> writer) {
|
Entry(BinaryTagType<N> nbtType, Function<N, T> reader, Function<T, N> writer) {
|
||||||
this(nbtType, reader, writer, false);
|
this(nbtType, reader, writer, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package net.minestom.server.tag;
|
package net.minestom.server.tag;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.*;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.minestom.server.item.ItemStack;
|
import net.minestom.server.item.ItemStack;
|
||||||
import net.minestom.server.utils.collection.AutoIncrementMap;
|
import net.minestom.server.utils.collection.AutoIncrementMap;
|
||||||
|
@ -7,11 +8,6 @@ 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.NBTCompoundLike;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTList;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTType;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.mutable.MutableNBTCompound;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -37,7 +33,7 @@ public class Tag<T> {
|
||||||
|
|
||||||
final int index;
|
final int index;
|
||||||
private final String key;
|
private final String key;
|
||||||
final Serializers.Entry<T, NBT> entry;
|
final Serializers.Entry<T, BinaryTag> entry;
|
||||||
private final Supplier<T> defaultValue;
|
private final Supplier<T> defaultValue;
|
||||||
|
|
||||||
final Function<?, ?> readComparator;
|
final Function<?, ?> readComparator;
|
||||||
|
@ -48,7 +44,7 @@ public class Tag<T> {
|
||||||
|
|
||||||
Tag(int index, String key,
|
Tag(int index, String key,
|
||||||
Function<?, ?> readComparator,
|
Function<?, ?> readComparator,
|
||||||
Serializers.Entry<T, NBT> entry,
|
Serializers.Entry<T, BinaryTag> entry,
|
||||||
Supplier<T> defaultValue, PathEntry[] path, UnaryOperator<T> copy, int listScope) {
|
Supplier<T> defaultValue, PathEntry[] path, UnaryOperator<T> copy, int listScope) {
|
||||||
assert index == INDEX_MAP.get(key);
|
assert index == INDEX_MAP.get(key);
|
||||||
this.index = index;
|
this.index = index;
|
||||||
|
@ -61,8 +57,8 @@ public class Tag<T> {
|
||||||
this.listScope = listScope;
|
this.listScope = listScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
static <T, N extends NBT> Tag<T> tag(@NotNull String key, @NotNull Serializers.Entry<T, N> entry) {
|
static <T, N extends BinaryTag> Tag<T> tag(@NotNull String key, @NotNull Serializers.Entry<T, N> entry) {
|
||||||
return new Tag<>(INDEX_MAP.get(key), key, entry.reader(), (Serializers.Entry<T, NBT>) entry,
|
return new Tag<>(INDEX_MAP.get(key), key, entry.reader(), (Serializers.Entry<T, BinaryTag>) entry,
|
||||||
null, null, null, 0);
|
null, null, null, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,11 +94,11 @@ public class Tag<T> {
|
||||||
public <R> Tag<R> map(@NotNull Function<T, R> readMap,
|
public <R> Tag<R> map(@NotNull Function<T, R> readMap,
|
||||||
@NotNull Function<R, T> writeMap) {
|
@NotNull Function<R, T> writeMap) {
|
||||||
var entry = this.entry;
|
var entry = this.entry;
|
||||||
final Function<NBT, R> readFunction = entry.reader().andThen(t -> {
|
final Function<BinaryTag, R> readFunction = entry.reader().andThen(t -> {
|
||||||
if (t == null) return null;
|
if (t == null) return null;
|
||||||
return readMap.apply(t);
|
return readMap.apply(t);
|
||||||
});
|
});
|
||||||
final Function<R, NBT> writeFunction = writeMap.andThen(entry.writer());
|
final Function<R, BinaryTag> writeFunction = writeMap.andThen(entry.writer());
|
||||||
return new Tag<>(index, key, readMap,
|
return new Tag<>(index, key, readMap,
|
||||||
new Serializers.Entry<>(entry.nbtType(), readFunction, writeFunction),
|
new Serializers.Entry<>(entry.nbtType(), readFunction, writeFunction),
|
||||||
// Default value
|
// Default value
|
||||||
|
@ -120,18 +116,18 @@ public class Tag<T> {
|
||||||
var entry = this.entry;
|
var entry = this.entry;
|
||||||
var readFunction = entry.reader();
|
var readFunction = entry.reader();
|
||||||
var writeFunction = entry.writer();
|
var writeFunction = entry.writer();
|
||||||
var listEntry = new Serializers.Entry<List<T>, NBTList<?>>(
|
var listEntry = new Serializers.Entry<List<T>, ListBinaryTag>(
|
||||||
NBTType.TAG_List,
|
BinaryTagTypes.LIST,
|
||||||
read -> {
|
read -> {
|
||||||
if (read.isEmpty()) return List.of();
|
if (read.size() == 0) return List.of();
|
||||||
return read.asListView().stream().map(readFunction).toList();
|
return read.stream().map(readFunction).toList();
|
||||||
},
|
},
|
||||||
write -> {
|
write -> {
|
||||||
if (write.isEmpty())
|
if (write.isEmpty())
|
||||||
return NBT.List(NBTType.TAG_String); // String is the default type for lists
|
return ListBinaryTag.empty();
|
||||||
final List<NBT> list = write.stream().map(writeFunction).toList();
|
final List<BinaryTag> list = write.stream().map(writeFunction).toList();
|
||||||
final NBTType<?> type = list.get(0).getID();
|
final BinaryTagType<?> type = list.get(0).type();
|
||||||
return NBT.List(type, list);
|
return ListBinaryTag.listBinaryTag(type, list);
|
||||||
});
|
});
|
||||||
UnaryOperator<List<T>> co = this.copy != null ? ts -> {
|
UnaryOperator<List<T>> co = this.copy != null ? ts -> {
|
||||||
final int size = ts.size();
|
final int size = ts.size();
|
||||||
|
@ -165,8 +161,8 @@ public class Tag<T> {
|
||||||
return new Tag<>(index, key, readComparator, entry, defaultValue, pathEntries, copy, listScope);
|
return new Tag<>(index, key, readComparator, entry, defaultValue, pathEntries, copy, listScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable T read(@NotNull NBTCompoundLike nbt) {
|
public @Nullable T read(@NotNull CompoundBinaryTag nbt) {
|
||||||
final NBT readable = isView() ? nbt.toCompound() : nbt.get(key);
|
final BinaryTag readable = isView() ? nbt : nbt.get(key);
|
||||||
final T result;
|
final T result;
|
||||||
try {
|
try {
|
||||||
if (readable == null || (result = entry.read(readable)) == null)
|
if (readable == null || (result = entry.read(readable)) == null)
|
||||||
|
@ -177,18 +173,20 @@ public class Tag<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(@NotNull MutableNBTCompound nbtCompound, @Nullable T value) {
|
public void write(@NotNull CompoundBinaryTag.Builder nbtCompound, @Nullable T value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
final NBT nbt = entry.write(value);
|
final BinaryTag nbt = entry.write(value);
|
||||||
if (isView()) nbtCompound.copyFrom((NBTCompoundLike) nbt);
|
if (isView()) nbtCompound.put((CompoundBinaryTag) nbt);
|
||||||
else nbtCompound.set(key, nbt);
|
else nbtCompound.put(key, nbt);
|
||||||
} else {
|
} else {
|
||||||
if (isView()) nbtCompound.clear();
|
if (isView()) {
|
||||||
else nbtCompound.remove(key);
|
// Adventure compound builder doesn't currently have a clear method.
|
||||||
|
nbtCompound.build().keySet().forEach(nbtCompound::remove);
|
||||||
|
} else nbtCompound.remove(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeUnsafe(@NotNull MutableNBTCompound nbtCompound, @Nullable Object value) {
|
public void writeUnsafe(@NotNull CompoundBinaryTag.Builder nbtCompound, @Nullable Object value) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
write(nbtCompound, (T) value);
|
write(nbtCompound, (T) value);
|
||||||
}
|
}
|
||||||
|
@ -279,11 +277,11 @@ public class Tag<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a flexible tag able to read and write any {@link NBT} objects.
|
* Creates a flexible tag able to read and write any {@link BinaryTag} objects.
|
||||||
* <p>
|
* <p>
|
||||||
* Specialized tags are recommended if the type is known as conversion will be required both way (read and write).
|
* Specialized tags are recommended if the type is known as conversion will be required both way (read and write).
|
||||||
*/
|
*/
|
||||||
public static @NotNull Tag<NBT> NBT(@NotNull String key) {
|
public static @NotNull Tag<BinaryTag> NBT(@NotNull String key) {
|
||||||
return tag(key, Serializers.NBT_ENTRY);
|
return tag(key, Serializers.NBT_ENTRY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
package net.minestom.server.tag;
|
package net.minestom.server.tag;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.UnknownNullability;
|
import org.jetbrains.annotations.UnknownNullability;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompoundLike;
|
|
||||||
|
|
||||||
import java.util.function.UnaryOperator;
|
import java.util.function.UnaryOperator;
|
||||||
|
|
||||||
|
@ -26,7 +25,7 @@ public interface TagHandler extends TagReadable, TagWritable {
|
||||||
/**
|
/**
|
||||||
* Creates a copy of this handler.
|
* Creates a copy of this handler.
|
||||||
* <p>
|
* <p>
|
||||||
* Similar to {@link #fromCompound(NBTCompoundLike)} using {@link #asCompound()}
|
* Similar to {@link #fromCompound(CompoundBinaryTag)} using {@link #asCompound()}
|
||||||
* with the advantage that cached objects and adaptive optimizations may be reused.
|
* with the advantage that cached objects and adaptive optimizations may be reused.
|
||||||
*
|
*
|
||||||
* @return a copy of this handler
|
* @return a copy of this handler
|
||||||
|
@ -36,18 +35,18 @@ public interface TagHandler extends TagReadable, TagWritable {
|
||||||
/**
|
/**
|
||||||
* Updates the content of this handler.
|
* Updates the content of this handler.
|
||||||
* <p>
|
* <p>
|
||||||
* Can be used as a clearing method with {@link NBTCompound#EMPTY}.
|
* Can be used as a clearing method with {@link CompoundBinaryTag#empty()}.
|
||||||
*
|
*
|
||||||
* @param compound the new content of this handler
|
* @param compound the new content of this handler
|
||||||
*/
|
*/
|
||||||
void updateContent(@NotNull NBTCompoundLike compound);
|
void updateContent(@NotNull CompoundBinaryTag compound);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the content of this handler into a {@link NBTCompound}.
|
* Converts the content of this handler into a {@link CompoundBinaryTag}.
|
||||||
*
|
*
|
||||||
* @return a nbt compound representation of this handler
|
* @return a nbt compound representation of this handler
|
||||||
*/
|
*/
|
||||||
@NotNull NBTCompound asCompound();
|
@NotNull CompoundBinaryTag asCompound();
|
||||||
|
|
||||||
@ApiStatus.Experimental
|
@ApiStatus.Experimental
|
||||||
<T> void updateTag(@NotNull Tag<T> tag,
|
<T> void updateTag(@NotNull Tag<T> tag,
|
||||||
|
@ -67,12 +66,12 @@ public interface TagHandler extends TagReadable, TagWritable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy the content of the given {@link NBTCompoundLike} into a new {@link TagHandler}.
|
* Copy the content of the given {@link CompoundBinaryTag} into a new {@link TagHandler}.
|
||||||
*
|
*
|
||||||
* @param compound the compound to read tags from
|
* @param compound the compound to read tags from
|
||||||
* @return a new tag handler with the content of the given compound
|
* @return a new tag handler with the content of the given compound
|
||||||
*/
|
*/
|
||||||
static @NotNull TagHandler fromCompound(@NotNull NBTCompoundLike compound) {
|
static @NotNull TagHandler fromCompound(@NotNull CompoundBinaryTag compound) {
|
||||||
return TagHandlerImpl.fromCompound(compound);
|
return TagHandlerImpl.fromCompound(compound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,21 @@
|
||||||
package net.minestom.server.tag;
|
package net.minestom.server.tag;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.BinaryTag;
|
||||||
|
import net.kyori.adventure.nbt.BinaryTagType;
|
||||||
|
import net.kyori.adventure.nbt.BinaryTagTypes;
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.minestom.server.ServerFlag;
|
import net.minestom.server.ServerFlag;
|
||||||
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.jetbrains.annotations.UnknownNullability;
|
import org.jetbrains.annotations.UnknownNullability;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBT;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompoundLike;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTType;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.mutable.MutableNBTCompound;
|
|
||||||
|
|
||||||
import java.lang.invoke.VarHandle;
|
import java.lang.invoke.VarHandle;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.UnaryOperator;
|
import java.util.function.UnaryOperator;
|
||||||
|
|
||||||
final class TagHandlerImpl implements TagHandler {
|
final class TagHandlerImpl implements TagHandler {
|
||||||
static final Serializers.Entry<Node, NBTCompound> NODE_SERIALIZER = new Serializers.Entry<>(NBTType.TAG_Compound, entries -> fromCompound(entries).root, Node::compound, true);
|
static final Serializers.Entry<Node, CompoundBinaryTag> NODE_SERIALIZER = new Serializers.Entry<>(BinaryTagTypes.COMPOUND, entries -> fromCompound(entries).root, Node::compound, true);
|
||||||
|
|
||||||
private final Node root;
|
private final Node root;
|
||||||
private volatile Node copy;
|
private volatile Node copy;
|
||||||
|
@ -29,8 +28,7 @@ final class TagHandlerImpl implements TagHandler {
|
||||||
this.root = new Node();
|
this.root = new Node();
|
||||||
}
|
}
|
||||||
|
|
||||||
static TagHandlerImpl fromCompound(NBTCompoundLike compoundLike) {
|
static TagHandlerImpl fromCompound(CompoundBinaryTag compound) {
|
||||||
final NBTCompound compound = compoundLike.toCompound();
|
|
||||||
TagHandlerImpl handler = new TagHandlerImpl();
|
TagHandlerImpl handler = new TagHandlerImpl();
|
||||||
TagNbtSeparator.separate(compound, entry -> handler.setTag(entry.tag(), entry.value()));
|
TagNbtSeparator.separate(compound, entry -> handler.setTag(entry.tag(), entry.value()));
|
||||||
handler.root.compound = compound;
|
handler.root.compound = compound;
|
||||||
|
@ -50,7 +48,7 @@ final class TagHandlerImpl implements TagHandler {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
Node syncNode = traversePathWrite(root, tag, value != null);
|
Node syncNode = traversePathWrite(root, tag, value != null);
|
||||||
if (syncNode != null) {
|
if (syncNode != null) {
|
||||||
syncNode.updateContent(value != null ? (NBTCompound) tag.entry.write(value) : NBTCompound.EMPTY);
|
syncNode.updateContent(value != null ? (CompoundBinaryTag) tag.entry.write(value) : CompoundBinaryTag.empty());
|
||||||
syncNode.invalidate();
|
syncNode.invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,7 +101,7 @@ final class TagHandlerImpl implements TagHandler {
|
||||||
if (tag.isView()) {
|
if (tag.isView()) {
|
||||||
final T previousValue = tag.read(node.compound());
|
final T previousValue = tag.read(node.compound());
|
||||||
final T newValue = value.apply(previousValue);
|
final T newValue = value.apply(previousValue);
|
||||||
node.updateContent((NBTCompoundLike) tag.entry.write(newValue));
|
node.updateContent((CompoundBinaryTag) tag.entry.write(newValue));
|
||||||
node.invalidate();
|
node.invalidate();
|
||||||
return returnPrevious ? previousValue : newValue;
|
return returnPrevious ? previousValue : newValue;
|
||||||
}
|
}
|
||||||
|
@ -116,7 +114,7 @@ final class TagHandlerImpl implements TagHandler {
|
||||||
if (previousEntry != null) {
|
if (previousEntry != null) {
|
||||||
final Object previousTmp = previousEntry.value;
|
final Object previousTmp = previousEntry.value;
|
||||||
if (previousTmp instanceof Node n) {
|
if (previousTmp instanceof Node n) {
|
||||||
final NBTCompound compound = NBT.Compound(Map.of(tag.getKey(), n.compound()));
|
final CompoundBinaryTag compound = CompoundBinaryTag.from(Map.of(tag.getKey(), n.compound()));
|
||||||
previousValue = tag.read(compound);
|
previousValue = tag.read(compound);
|
||||||
} else {
|
} else {
|
||||||
previousValue = (T) previousTmp;
|
previousValue = (T) previousTmp;
|
||||||
|
@ -149,12 +147,12 @@ final class TagHandlerImpl implements TagHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void updateContent(@NotNull NBTCompoundLike compound) {
|
public synchronized void updateContent(@NotNull CompoundBinaryTag compound) {
|
||||||
this.root.updateContent(compound);
|
this.root.updateContent(compound);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull NBTCompound asCompound() {
|
public @NotNull CompoundBinaryTag asCompound() {
|
||||||
VarHandle.fullFence();
|
VarHandle.fullFence();
|
||||||
return root.compound();
|
return root.compound();
|
||||||
}
|
}
|
||||||
|
@ -200,7 +198,7 @@ final class TagHandlerImpl implements TagHandler {
|
||||||
// Slow path is taken if the entry comes from a Structure tag, requiring conversion from NBT
|
// Slow path is taken if the entry comes from a Structure tag, requiring conversion from NBT
|
||||||
Node tmp = local;
|
Node tmp = local;
|
||||||
local = new Node(tmp);
|
local = new Node(tmp);
|
||||||
if (synEntry != null && synEntry.updatedNbt() instanceof NBTCompound compound) {
|
if (synEntry != null && synEntry.updatedNbt() instanceof CompoundBinaryTag compound) {
|
||||||
local.updateContent(compound);
|
local.updateContent(compound);
|
||||||
}
|
}
|
||||||
tmp.entries.put(pathIndex, Entry.makePathEntry(path.name(), local));
|
tmp.entries.put(pathIndex, Entry.makePathEntry(path.name(), local));
|
||||||
|
@ -211,8 +209,8 @@ final class TagHandlerImpl implements TagHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> Entry<?> valueToEntry(Node parent, Tag<T> tag, @NotNull T value) {
|
private <T> Entry<?> valueToEntry(Node parent, Tag<T> tag, @NotNull T value) {
|
||||||
if (value instanceof NBT nbt) {
|
if (value instanceof BinaryTag nbt) {
|
||||||
if (nbt instanceof NBTCompound compound) {
|
if (nbt instanceof CompoundBinaryTag compound) {
|
||||||
final TagHandlerImpl handler = fromCompound(compound);
|
final TagHandlerImpl handler = fromCompound(compound);
|
||||||
return Entry.makePathEntry(tag, new Node(parent, handler.root.entries));
|
return Entry.makePathEntry(tag, new Node(parent, handler.root.entries));
|
||||||
} else {
|
} else {
|
||||||
|
@ -227,7 +225,7 @@ final class TagHandlerImpl implements TagHandler {
|
||||||
final class Node implements TagReadable {
|
final class Node implements TagReadable {
|
||||||
final Node parent;
|
final Node parent;
|
||||||
final StaticIntMap<Entry<?>> entries;
|
final StaticIntMap<Entry<?>> entries;
|
||||||
NBTCompound compound;
|
CompoundBinaryTag compound;
|
||||||
|
|
||||||
public Node(Node parent, StaticIntMap<Entry<?>> entries) {
|
public Node(Node parent, StaticIntMap<Entry<?>> entries) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
|
@ -260,44 +258,43 @@ final class TagHandlerImpl implements TagHandler {
|
||||||
return (T) entry.value;
|
return (T) entry.value;
|
||||||
}
|
}
|
||||||
// Value must be parsed from nbt if the tag is different
|
// Value must be parsed from nbt if the tag is different
|
||||||
final NBT nbt = entry.updatedNbt();
|
final BinaryTag nbt = entry.updatedNbt();
|
||||||
final Serializers.Entry<T, NBT> serializerEntry = tag.entry;
|
final Serializers.Entry<T, BinaryTag> serializerEntry = tag.entry;
|
||||||
final NBTType<NBT> type = serializerEntry.nbtType();
|
final BinaryTagType<BinaryTag> type = serializerEntry.nbtType();
|
||||||
return type == null || type == nbt.getID() ? serializerEntry.read(nbt) : tag.createDefault();
|
return type == null || type.equals(nbt.type()) ? serializerEntry.read(nbt) : tag.createDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateContent(@NotNull NBTCompoundLike compoundLike) {
|
void updateContent(@NotNull CompoundBinaryTag compound) {
|
||||||
final NBTCompound compound = compoundLike.toCompound();
|
|
||||||
final TagHandlerImpl converted = fromCompound(compound);
|
final TagHandlerImpl converted = fromCompound(compound);
|
||||||
this.entries.updateContent(converted.root.entries);
|
this.entries.updateContent(converted.root.entries);
|
||||||
this.compound = compound;
|
this.compound = compound;
|
||||||
}
|
}
|
||||||
|
|
||||||
NBTCompound compound() {
|
CompoundBinaryTag compound() {
|
||||||
NBTCompound compound;
|
CompoundBinaryTag compound;
|
||||||
if (!ServerFlag.TAG_HANDLER_CACHE_ENABLED || (compound = this.compound) == null) {
|
if (!ServerFlag.TAG_HANDLER_CACHE_ENABLED || (compound = this.compound) == null) {
|
||||||
MutableNBTCompound tmp = new MutableNBTCompound();
|
CompoundBinaryTag.Builder tmp = CompoundBinaryTag.builder();
|
||||||
this.entries.forValues(entry -> {
|
this.entries.forValues(entry -> {
|
||||||
final Tag tag = entry.tag;
|
final Tag tag = entry.tag;
|
||||||
final NBT nbt = entry.updatedNbt();
|
final BinaryTag nbt = entry.updatedNbt();
|
||||||
if (nbt != null && (!tag.entry.isPath() || (!ServerFlag.SERIALIZE_EMPTY_COMPOUND) && !((NBTCompound) nbt).isEmpty())) {
|
if (nbt != null && (!tag.entry.isPath() || (!ServerFlag.SERIALIZE_EMPTY_COMPOUND) && ((CompoundBinaryTag) nbt).size() > 0)) {
|
||||||
tmp.put(tag.getKey(), nbt);
|
tmp.put(tag.getKey(), nbt);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.compound = compound = tmp.toCompound();
|
this.compound = compound = tmp.build();
|
||||||
}
|
}
|
||||||
return compound;
|
return compound;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract("null -> !null")
|
@Contract("null -> !null")
|
||||||
Node copy(Node parent) {
|
Node copy(Node parent) {
|
||||||
MutableNBTCompound tmp = new MutableNBTCompound();
|
CompoundBinaryTag.Builder tmp = CompoundBinaryTag.builder();
|
||||||
Node result = new Node(parent, new StaticIntMap.Array<>());
|
Node result = new Node(parent, new StaticIntMap.Array<>());
|
||||||
StaticIntMap<Entry<?>> entries = result.entries;
|
StaticIntMap<Entry<?>> entries = result.entries;
|
||||||
this.entries.forValues(entry -> {
|
this.entries.forValues(entry -> {
|
||||||
Tag tag = entry.tag;
|
Tag tag = entry.tag;
|
||||||
Object value = entry.value;
|
Object value = entry.value;
|
||||||
NBT nbt;
|
BinaryTag nbt;
|
||||||
if (value instanceof Node node) {
|
if (value instanceof Node node) {
|
||||||
Node copy = node.copy(result);
|
Node copy = node.copy(result);
|
||||||
if (copy == null)
|
if (copy == null)
|
||||||
|
@ -313,9 +310,10 @@ final class TagHandlerImpl implements TagHandler {
|
||||||
tmp.put(tag.getKey(), nbt);
|
tmp.put(tag.getKey(), nbt);
|
||||||
entries.put(tag.index, valueToEntry(result, tag, value));
|
entries.put(tag.index, valueToEntry(result, tag, value));
|
||||||
});
|
});
|
||||||
if ((!ServerFlag.SERIALIZE_EMPTY_COMPOUND) && tmp.isEmpty() && parent != null)
|
var compound = tmp.build();
|
||||||
|
if ((!ServerFlag.SERIALIZE_EMPTY_COMPOUND) && compound.size() == 0 && parent != null)
|
||||||
return null; // Empty child node
|
return null; // Empty child node
|
||||||
result.compound = tmp.toCompound();
|
result.compound = compound;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,7 +328,7 @@ final class TagHandlerImpl implements TagHandler {
|
||||||
private static final class Entry<T> {
|
private static final class Entry<T> {
|
||||||
private final Tag<T> tag;
|
private final Tag<T> tag;
|
||||||
T value;
|
T value;
|
||||||
NBT nbt;
|
BinaryTag nbt;
|
||||||
|
|
||||||
Entry(Tag<T> tag, T value) {
|
Entry(Tag<T> tag, T value) {
|
||||||
this.tag = tag;
|
this.tag = tag;
|
||||||
|
@ -345,9 +343,9 @@ final class TagHandlerImpl implements TagHandler {
|
||||||
return makePathEntry(tag.getKey(), node);
|
return makePathEntry(tag.getKey(), node);
|
||||||
}
|
}
|
||||||
|
|
||||||
NBT updatedNbt() {
|
BinaryTag updatedNbt() {
|
||||||
if (tag.entry.isPath()) return ((Node) value).compound();
|
if (tag.entry.isPath()) return ((Node) value).compound();
|
||||||
NBT nbt = this.nbt;
|
BinaryTag nbt = this.nbt;
|
||||||
if (nbt == null) this.nbt = nbt = tag.entry.write(value);
|
if (nbt == null) this.nbt = nbt = tag.entry.write(value);
|
||||||
return nbt;
|
return nbt;
|
||||||
}
|
}
|
||||||
|
@ -360,7 +358,7 @@ final class TagHandlerImpl implements TagHandler {
|
||||||
|
|
||||||
Node toNode() {
|
Node toNode() {
|
||||||
if (tag.entry.isPath()) return (Node) value;
|
if (tag.entry.isPath()) return (Node) value;
|
||||||
if (updatedNbt() instanceof NBTCompound compound) {
|
if (updatedNbt() instanceof CompoundBinaryTag compound) {
|
||||||
// Slow path forcing a conversion of the structure to NBTCompound
|
// Slow path forcing a conversion of the structure to NBTCompound
|
||||||
// TODO should the handler be cached inside the entry?
|
// TODO should the handler be cached inside the entry?
|
||||||
return fromCompound(compound).root;
|
return fromCompound(compound).root;
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
package net.minestom.server.tag;
|
package net.minestom.server.tag;
|
||||||
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBT;
|
import net.kyori.adventure.nbt.*;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
import net.minestom.server.utils.NBTUtils;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTList;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTType;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -15,30 +13,30 @@ import java.util.function.Function;
|
||||||
import static java.util.Map.entry;
|
import static java.util.Map.entry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles conversion of {@link NBT} subtypes into one or multiple primitive {@link Tag tags}.
|
* Handles conversion of {@link BinaryTag} subtypes into one or multiple primitive {@link Tag tags}.
|
||||||
*/
|
*/
|
||||||
final class TagNbtSeparator {
|
final class TagNbtSeparator {
|
||||||
static final Map<NBTType<?>, Function<String, Tag<?>>> SUPPORTED_TYPES = Map.ofEntries(
|
static final Map<BinaryTagType<?>, Function<String, Tag<?>>> SUPPORTED_TYPES = Map.ofEntries(
|
||||||
entry(NBTType.TAG_Byte, Tag::Byte),
|
entry(BinaryTagTypes.BYTE, Tag::Byte),
|
||||||
entry(NBTType.TAG_Short, Tag::Short),
|
entry(BinaryTagTypes.SHORT, Tag::Short),
|
||||||
entry(NBTType.TAG_Int, Tag::Integer),
|
entry(BinaryTagTypes.INT, Tag::Integer),
|
||||||
entry(NBTType.TAG_Long, Tag::Long),
|
entry(BinaryTagTypes.LONG, Tag::Long),
|
||||||
entry(NBTType.TAG_Float, Tag::Float),
|
entry(BinaryTagTypes.FLOAT, Tag::Float),
|
||||||
entry(NBTType.TAG_Double, Tag::Double),
|
entry(BinaryTagTypes.DOUBLE, Tag::Double),
|
||||||
entry(NBTType.TAG_String, Tag::String));
|
entry(BinaryTagTypes.STRING, Tag::String));
|
||||||
|
|
||||||
static void separate(NBTCompound nbtCompound, Consumer<Entry> consumer) {
|
static void separate(CompoundBinaryTag nbtCompound, Consumer<Entry> consumer) {
|
||||||
for (var ent : nbtCompound) {
|
for (var ent : nbtCompound) {
|
||||||
convert(new ArrayList<>(), ent.getKey(), ent.getValue(), consumer);
|
convert(new ArrayList<>(), ent.getKey(), ent.getValue(), consumer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void separate(String key, NBT nbt, Consumer<Entry> consumer) {
|
static void separate(String key, BinaryTag nbt, Consumer<Entry> consumer) {
|
||||||
convert(new ArrayList<>(), key, nbt, consumer);
|
convert(new ArrayList<>(), key, nbt, consumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Entry separateSingle(String key, NBT nbt) {
|
static Entry separateSingle(String key, BinaryTag nbt) {
|
||||||
assert !(nbt instanceof NBTCompound);
|
assert !(nbt instanceof CompoundBinaryTag);
|
||||||
AtomicReference<Entry<?>> entryRef = new AtomicReference<>();
|
AtomicReference<Entry<?>> entryRef = new AtomicReference<>();
|
||||||
convert(new ArrayList<>(), key, nbt, entry -> {
|
convert(new ArrayList<>(), key, nbt, entry -> {
|
||||||
assert entryRef.getPlain() == null : "Multiple entries found for nbt tag: " + key + " -> " + nbt;
|
assert entryRef.getPlain() == null : "Multiple entries found for nbt tag: " + key + " -> " + nbt;
|
||||||
|
@ -49,28 +47,28 @@ final class TagNbtSeparator {
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void convert(List<String> path, String key, NBT nbt, Consumer<Entry> consumer) {
|
private static void convert(List<String> path, String key, BinaryTag nbt, Consumer<Entry> consumer) {
|
||||||
var tagFunction = SUPPORTED_TYPES.get(nbt.getID());
|
var tagFunction = SUPPORTED_TYPES.get(nbt.type());
|
||||||
if (tagFunction != null) {
|
if (tagFunction != null) {
|
||||||
Tag tag = tagFunction.apply(key);
|
Tag tag = tagFunction.apply(key);
|
||||||
consumer.accept(makeEntry(path, tag, nbt.getValue()));
|
consumer.accept(makeEntry(path, tag, NBTUtils.nbtValueFromTag(nbt)));
|
||||||
} else if (nbt instanceof NBTCompound nbtCompound) {
|
} else if (nbt instanceof CompoundBinaryTag nbtCompound) {
|
||||||
for (var ent : nbtCompound) {
|
for (var ent : nbtCompound) {
|
||||||
var newPath = new ArrayList<>(path);
|
var newPath = new ArrayList<>(path);
|
||||||
newPath.add(key);
|
newPath.add(key);
|
||||||
convert(newPath, ent.getKey(), ent.getValue(), consumer);
|
convert(newPath, ent.getKey(), ent.getValue(), consumer);
|
||||||
}
|
}
|
||||||
} else if (nbt instanceof NBTList<?> nbtList) {
|
} else if (nbt instanceof ListBinaryTag nbtList) {
|
||||||
tagFunction = SUPPORTED_TYPES.get(nbtList.getSubtagType());
|
tagFunction = SUPPORTED_TYPES.get(nbtList.elementType());
|
||||||
if (tagFunction == null) {
|
if (tagFunction == null) {
|
||||||
// Invalid list subtype, fallback to nbt
|
// Invalid list subtype, fallback to nbt
|
||||||
consumer.accept(makeEntry(path, Tag.NBT(key), nbt));
|
consumer.accept(makeEntry(path, Tag.NBT(key), nbt));
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
var tag = tagFunction.apply(key).list();
|
var tag = tagFunction.apply(key).list();
|
||||||
Object[] values = new Object[nbtList.getSize()];
|
Object[] values = new Object[nbtList.size()];
|
||||||
for (int i = 0; i < values.length; i++) {
|
for (int i = 0; i < values.length; i++) {
|
||||||
values[i] = nbtList.get(i).getValue();
|
values[i] = NBTUtils.nbtValueFromTag(nbtList.get(i));
|
||||||
}
|
}
|
||||||
consumer.accept(makeEntry(path, Tag.class.cast(tag), List.of(values)));
|
consumer.accept(makeEntry(path, Tag.class.cast(tag), List.of(values)));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package net.minestom.server.tag;
|
package net.minestom.server.tag;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.BinaryTag;
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.minestom.server.item.ItemStack;
|
import net.minestom.server.item.ItemStack;
|
||||||
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 java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
@ -44,7 +44,7 @@ final class TagRecord {
|
||||||
final Tag<?> tag;
|
final Tag<?> tag;
|
||||||
if (componentType.isRecord()) {
|
if (componentType.isRecord()) {
|
||||||
tag = Tag.Structure(componentName, serializers.get(componentType));
|
tag = Tag.Structure(componentName, serializers.get(componentType));
|
||||||
} else if (NBT.class.isAssignableFrom(componentType)) {
|
} else if (BinaryTag.class.isAssignableFrom(componentType)) {
|
||||||
tag = Tag.NBT(componentName);
|
tag = Tag.NBT(componentName);
|
||||||
} else {
|
} else {
|
||||||
final var fun = SUPPORTED_TYPES.get(componentType);
|
final var fun = SUPPORTED_TYPES.get(componentType);
|
||||||
|
@ -73,7 +73,7 @@ final class TagRecord {
|
||||||
static final class Serializer<T extends Record> implements TagSerializer<T> {
|
static final class Serializer<T extends Record> implements TagSerializer<T> {
|
||||||
final Constructor<T> constructor;
|
final Constructor<T> constructor;
|
||||||
final Entry[] entries;
|
final Entry[] entries;
|
||||||
final Serializers.Entry<T, NBTCompound> serializerEntry;
|
final Serializers.Entry<T, CompoundBinaryTag> serializerEntry;
|
||||||
|
|
||||||
Serializer(Constructor<T> constructor, Entry[] entries) {
|
Serializer(Constructor<T> constructor, Entry[] entries) {
|
||||||
this.constructor = constructor;
|
this.constructor = constructor;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package net.minestom.server.tag;
|
package net.minestom.server.tag;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
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.NBTCompound;
|
|
||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
@ -31,11 +31,11 @@ public interface TagSerializer<T> {
|
||||||
void write(@NotNull TagWritable writer, @NotNull T value);
|
void write(@NotNull TagWritable writer, @NotNull T value);
|
||||||
|
|
||||||
@ApiStatus.Experimental
|
@ApiStatus.Experimental
|
||||||
TagSerializer<NBTCompound> COMPOUND = TagSerializerImpl.COMPOUND;
|
TagSerializer<CompoundBinaryTag> COMPOUND = TagSerializerImpl.COMPOUND;
|
||||||
|
|
||||||
@ApiStatus.Experimental
|
@ApiStatus.Experimental
|
||||||
static <T> TagSerializer<T> fromCompound(@NotNull Function<NBTCompound, T> reader,
|
static <T> TagSerializer<T> fromCompound(@NotNull Function<CompoundBinaryTag, T> reader,
|
||||||
@NotNull Function<T, NBTCompound> writer) {
|
@NotNull Function<T, CompoundBinaryTag> writer) {
|
||||||
return TagSerializerImpl.fromCompound(reader, writer);
|
return TagSerializerImpl.fromCompound(reader, writer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,35 +1,35 @@
|
||||||
package net.minestom.server.tag;
|
package net.minestom.server.tag;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
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 java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
final class TagSerializerImpl {
|
final class TagSerializerImpl {
|
||||||
public static final TagSerializer<NBTCompound> COMPOUND = new TagSerializer<>() {
|
public static final TagSerializer<CompoundBinaryTag> COMPOUND = new TagSerializer<>() {
|
||||||
@Override
|
@Override
|
||||||
public @NotNull NBTCompound read(@NotNull TagReadable reader) {
|
public @NotNull CompoundBinaryTag read(@NotNull TagReadable reader) {
|
||||||
return ((TagHandler) reader).asCompound();
|
return ((TagHandler) reader).asCompound();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(@NotNull TagWritable writer, @NotNull NBTCompound value) {
|
public void write(@NotNull TagWritable writer, @NotNull CompoundBinaryTag value) {
|
||||||
TagNbtSeparator.separate(value, entry -> writer.setTag(entry.tag(), entry.value()));
|
TagNbtSeparator.separate(value, entry -> writer.setTag(entry.tag(), entry.value()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static <T> TagSerializer<T> fromCompound(Function<NBTCompound, T> readFunc, Function<T, NBTCompound> writeFunc) {
|
static <T> TagSerializer<T> fromCompound(Function<CompoundBinaryTag, T> readFunc, Function<T, CompoundBinaryTag> writeFunc) {
|
||||||
return new TagSerializer<>() {
|
return new TagSerializer<>() {
|
||||||
@Override
|
@Override
|
||||||
public @Nullable T read(@NotNull TagReadable reader) {
|
public @Nullable T read(@NotNull TagReadable reader) {
|
||||||
final NBTCompound compound = COMPOUND.read(reader);
|
final CompoundBinaryTag compound = COMPOUND.read(reader);
|
||||||
return readFunc.apply(compound);
|
return readFunc.apply(compound);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(@NotNull TagWritable writer, @NotNull T value) {
|
public void write(@NotNull TagWritable writer, @NotNull T value) {
|
||||||
final NBTCompound compound = writeFunc.apply(value);
|
final CompoundBinaryTag compound = writeFunc.apply(value);
|
||||||
COMPOUND.write(writer, compound);
|
COMPOUND.write(writer, compound);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
package net.minestom.server.utils;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.*;
|
||||||
|
import net.minestom.server.utils.validate.Check;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
@ApiStatus.Internal
|
||||||
|
public final class NBTUtils {
|
||||||
|
private static final BinaryTagType<?>[] TYPES = new BinaryTagType[]{
|
||||||
|
BinaryTagTypes.END,
|
||||||
|
BinaryTagTypes.BYTE,
|
||||||
|
BinaryTagTypes.SHORT,
|
||||||
|
BinaryTagTypes.INT,
|
||||||
|
BinaryTagTypes.LONG,
|
||||||
|
BinaryTagTypes.FLOAT,
|
||||||
|
BinaryTagTypes.DOUBLE,
|
||||||
|
BinaryTagTypes.BYTE_ARRAY,
|
||||||
|
BinaryTagTypes.STRING,
|
||||||
|
BinaryTagTypes.LIST,
|
||||||
|
BinaryTagTypes.COMPOUND,
|
||||||
|
BinaryTagTypes.INT_ARRAY,
|
||||||
|
BinaryTagTypes.LONG_ARRAY,
|
||||||
|
};
|
||||||
|
|
||||||
|
public static @NotNull BinaryTagType<?> nbtTypeFromId(byte id) {
|
||||||
|
Check.argCondition(id < 0 || id >= TYPES.length, "Invalid NBT type id: " + id);
|
||||||
|
return TYPES[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @NotNull Object nbtValueFromTag(@NotNull BinaryTag tag) {
|
||||||
|
if (tag instanceof ByteBinaryTag byteTag) {
|
||||||
|
return byteTag.value();
|
||||||
|
} else if (tag instanceof ShortBinaryTag shortTag) {
|
||||||
|
return shortTag.value();
|
||||||
|
} else if (tag instanceof IntBinaryTag intTag) {
|
||||||
|
return intTag.value();
|
||||||
|
} else if (tag instanceof LongBinaryTag longTag) {
|
||||||
|
return longTag.value();
|
||||||
|
} else if (tag instanceof FloatBinaryTag floatTag) {
|
||||||
|
return floatTag.value();
|
||||||
|
} else if (tag instanceof DoubleBinaryTag doubleTag) {
|
||||||
|
return doubleTag.value();
|
||||||
|
} else if (tag instanceof ByteArrayBinaryTag byteArrayTag) {
|
||||||
|
return byteArrayTag.value();
|
||||||
|
} else if (tag instanceof StringBinaryTag stringTag) {
|
||||||
|
return stringTag.value();
|
||||||
|
} else if (tag instanceof IntArrayBinaryTag intArrayTag) {
|
||||||
|
return intArrayTag.value();
|
||||||
|
} else if (tag instanceof LongArrayBinaryTag longArrayTag) {
|
||||||
|
return longArrayTag.value();
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException("Unsupported NBT type: " + tag.getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private NBTUtils() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,8 +2,6 @@ package net.minestom.server.utils.binary;
|
||||||
|
|
||||||
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.NBTReader;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTWriter;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
@ -17,8 +15,6 @@ import java.nio.channels.WritableByteChannel;
|
||||||
@ApiStatus.Internal
|
@ApiStatus.Internal
|
||||||
public final class BinaryBuffer {
|
public final class BinaryBuffer {
|
||||||
private ByteBuffer nioBuffer; // To become a `MemorySegment` once released
|
private ByteBuffer nioBuffer; // To become a `MemorySegment` once released
|
||||||
private NBTReader nbtReader;
|
|
||||||
private NBTWriter nbtWriter;
|
|
||||||
|
|
||||||
private final int capacity;
|
private final int capacity;
|
||||||
private int readerOffset, writerOffset;
|
private int readerOffset, writerOffset;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package net.minestom.server.utils.binary;
|
package net.minestom.server.utils.binary;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.BinaryTag;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||||
import net.minestom.server.coordinate.Point;
|
import net.minestom.server.coordinate.Point;
|
||||||
|
@ -8,7 +9,6 @@ import net.minestom.server.network.NetworkBuffer;
|
||||||
import net.minestom.server.utils.Either;
|
import net.minestom.server.utils.Either;
|
||||||
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 java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.BufferUnderflowException;
|
import java.nio.BufferUnderflowException;
|
||||||
|
@ -263,7 +263,7 @@ public class BinaryReader extends InputStream {
|
||||||
return buffer.readableBytes();
|
return buffer.readableBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
public NBT readTag() {
|
public BinaryTag readTag() {
|
||||||
return buffer.read(NBT);
|
return buffer.read(NBT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package net.minestom.server.utils.binary;
|
package net.minestom.server.utils.binary;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.BinaryTag;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.minestom.server.coordinate.Point;
|
import net.minestom.server.coordinate.Point;
|
||||||
import net.minestom.server.coordinate.Vec;
|
import net.minestom.server.coordinate.Vec;
|
||||||
|
@ -8,7 +9,6 @@ import net.minestom.server.network.NetworkBuffer;
|
||||||
import net.minestom.server.utils.Either;
|
import net.minestom.server.utils.Either;
|
||||||
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.NBT;
|
|
||||||
|
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
@ -167,7 +167,7 @@ public class BinaryWriter extends OutputStream {
|
||||||
this.buffer.write(ITEM, itemStack);
|
this.buffer.write(ITEM, itemStack);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeNBT(@NotNull String name, @NotNull NBT tag) {
|
public void writeNBT(@NotNull String name, @NotNull BinaryTag tag) {
|
||||||
this.buffer.write(NBT, tag);
|
this.buffer.write(NBT, tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
package net.minestom.server.utils.block;
|
package net.minestom.server.utils.block;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.minestom.server.coordinate.Point;
|
import net.minestom.server.coordinate.Point;
|
||||||
import net.minestom.server.instance.Instance;
|
|
||||||
import net.minestom.server.instance.block.Block;
|
import net.minestom.server.instance.block.Block;
|
||||||
import net.minestom.server.instance.block.BlockHandler;
|
import net.minestom.server.instance.block.BlockHandler;
|
||||||
import net.minestom.server.tag.Tag;
|
import net.minestom.server.tag.Tag;
|
||||||
import net.minestom.server.utils.StringUtils;
|
import net.minestom.server.utils.StringUtils;
|
||||||
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 java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
@ -90,22 +88,22 @@ public class BlockUtils {
|
||||||
return new Object2ObjectArrayMap<>(keys, values, entryCount);
|
return new Object2ObjectArrayMap<>(keys, values, entryCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @Nullable NBTCompound extractClientNbt(@NotNull Block block) {
|
public static @Nullable CompoundBinaryTag extractClientNbt(@NotNull Block block) {
|
||||||
if (!block.registry().isBlockEntity()) return null;
|
if (!block.registry().isBlockEntity()) return null;
|
||||||
// Append handler tags
|
// Append handler tags
|
||||||
final BlockHandler handler = block.handler();
|
final BlockHandler handler = block.handler();
|
||||||
final NBTCompound blockNbt = Objects.requireNonNullElseGet(block.nbt(), NBTCompound::new);
|
final CompoundBinaryTag blockNbt = Objects.requireNonNullElseGet(block.nbt(), CompoundBinaryTag::empty);
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
// Extract explicitly defined tags and keep the rest server-side
|
// Extract explicitly defined tags and keep the rest server-side
|
||||||
return NBT.Compound(nbt -> {
|
var builder = CompoundBinaryTag.builder();
|
||||||
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(nbt, value);
|
tag.writeUnsafe(builder, value);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
return builder.build();
|
||||||
}
|
}
|
||||||
// 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
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
package net.minestom.server.world;
|
package net.minestom.server.world;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
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.mcdata.SizesKt;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBT;
|
|
||||||
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;
|
||||||
|
|
||||||
|
@ -18,6 +15,9 @@ public class DimensionType {
|
||||||
|
|
||||||
private static final AtomicInteger idCounter = new AtomicInteger(0);
|
private static final AtomicInteger idCounter = new AtomicInteger(0);
|
||||||
|
|
||||||
|
private static final int VANILLA_MIN_Y = -64;
|
||||||
|
private static final int VANILLA_MAX_Y = 319;
|
||||||
|
|
||||||
public static final DimensionType OVERWORLD = DimensionType.builder(NamespaceID.from("minecraft:overworld"))
|
public static final DimensionType OVERWORLD = DimensionType.builder(NamespaceID.from("minecraft:overworld"))
|
||||||
.ultrawarm(false)
|
.ultrawarm(false)
|
||||||
.natural(true)
|
.natural(true)
|
||||||
|
@ -91,55 +91,56 @@ public class DimensionType {
|
||||||
return new DimensionTypeBuilder();
|
return new DimensionTypeBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DimensionType fromNBT(NBTCompound nbt) {
|
public static DimensionType fromNBT(CompoundBinaryTag nbt) {
|
||||||
return DimensionType.builder(NamespaceID.from(nbt.getString("name")))
|
return DimensionType.builder(NamespaceID.from(nbt.getString("name")))
|
||||||
.ambientLight(nbt.getFloat("ambient_light"))
|
.ambientLight(nbt.getFloat("ambient_light"))
|
||||||
.infiniburn(NamespaceID.from(nbt.getString("infiniburn").replaceFirst("#", "")))
|
.infiniburn(NamespaceID.from(nbt.getString("infiniburn").replaceFirst("#", "")))
|
||||||
.natural(nbt.getByte("natural") != 0)
|
.natural(nbt.getBoolean("natural"))
|
||||||
.ceilingEnabled(nbt.getByte("has_ceiling") != 0)
|
.ceilingEnabled(nbt.getBoolean("has_ceiling"))
|
||||||
.skylightEnabled(nbt.getByte("has_skylight") != 0)
|
.skylightEnabled(nbt.getBoolean("has_skylight"))
|
||||||
.ultrawarm(nbt.getByte("ultrawarm") != 0)
|
.ultrawarm(nbt.getBoolean("ultrawarm"))
|
||||||
.raidCapable(nbt.getByte("has_raids") != 0)
|
.raidCapable(nbt.getBoolean("has_raids"))
|
||||||
.respawnAnchorSafe(nbt.getByte("respawn_anchor_works") != 0)
|
.respawnAnchorSafe(nbt.getBoolean("respawn_anchor_works"))
|
||||||
.bedSafe(nbt.getByte("bed_works") != 0)
|
.bedSafe(nbt.getBoolean("bed_works"))
|
||||||
.effects(nbt.getString("effects"))
|
.effects(nbt.getString("effects"))
|
||||||
.piglinSafe(nbt.getByte("piglin_safe") != 0)
|
.piglinSafe(nbt.getBoolean("piglin_safe"))
|
||||||
.logicalHeight(nbt.getInt("logical_height"))
|
.logicalHeight(nbt.getInt("logical_height"))
|
||||||
.coordinateScale(nbt.getDouble("coordinate_scale"))
|
.coordinateScale(nbt.getDouble("coordinate_scale"))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public NBTCompound toIndexedNBT() {
|
public CompoundBinaryTag toIndexedNBT() {
|
||||||
return NBT.Compound(Map.of(
|
return CompoundBinaryTag.builder()
|
||||||
"name", NBT.String(name.toString()),
|
.putString("name", name.toString())
|
||||||
"id", NBT.Int(id),
|
.putInt("id", id)
|
||||||
"element", toNBT()));
|
.put("element", toNBT())
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public NBTCompound toNBT() {
|
public CompoundBinaryTag toNBT() {
|
||||||
return NBT.Compound(nbt -> {
|
CompoundBinaryTag.Builder builder = CompoundBinaryTag.builder();
|
||||||
nbt.setFloat("ambient_light", ambientLight);
|
builder.putFloat("ambient_light", ambientLight);
|
||||||
nbt.setString("infiniburn", "#" + infiniburn.toString());
|
builder.putString("infiniburn", "#" + infiniburn.toString());
|
||||||
nbt.setByte("natural", (byte) (natural ? 0x01 : 0x00));
|
builder.putByte("natural", (byte) (natural ? 0x01 : 0x00));
|
||||||
nbt.setByte("has_ceiling", (byte) (ceilingEnabled ? 0x01 : 0x00));
|
builder.putByte("has_ceiling", (byte) (ceilingEnabled ? 0x01 : 0x00));
|
||||||
nbt.setByte("has_skylight", (byte) (skylightEnabled ? 0x01 : 0x00));
|
builder.putByte("has_skylight", (byte) (skylightEnabled ? 0x01 : 0x00));
|
||||||
nbt.setByte("ultrawarm", (byte) (ultrawarm ? 0x01 : 0x00));
|
builder.putByte("ultrawarm", (byte) (ultrawarm ? 0x01 : 0x00));
|
||||||
nbt.setByte("has_raids", (byte) (raidCapable ? 0x01 : 0x00));
|
builder.putByte("has_raids", (byte) (raidCapable ? 0x01 : 0x00));
|
||||||
nbt.setByte("respawn_anchor_works", (byte) (respawnAnchorSafe ? 0x01 : 0x00));
|
builder.putByte("respawn_anchor_works", (byte) (respawnAnchorSafe ? 0x01 : 0x00));
|
||||||
nbt.setByte("bed_works", (byte) (bedSafe ? 0x01 : 0x00));
|
builder.putByte("bed_works", (byte) (bedSafe ? 0x01 : 0x00));
|
||||||
nbt.setString("effects", effects);
|
builder.putString("effects", effects);
|
||||||
nbt.setByte("piglin_safe", (byte) (piglinSafe ? 0x01 : 0x00));
|
builder.putByte("piglin_safe", (byte) (piglinSafe ? 0x01 : 0x00));
|
||||||
nbt.setInt("min_y", minY);
|
builder.putInt("min_y", minY);
|
||||||
nbt.setInt("height", height);
|
builder.putInt("height", height);
|
||||||
nbt.setInt("logical_height", logicalHeight);
|
builder.putInt("logical_height", logicalHeight);
|
||||||
nbt.setDouble("coordinate_scale", coordinateScale);
|
builder.putDouble("coordinate_scale", coordinateScale);
|
||||||
nbt.setString("name", name.toString());
|
builder.putString("name", name.toString());
|
||||||
nbt.setInt("monster_spawn_block_light_limit", 0);
|
builder.putInt("monster_spawn_block_light_limit", 0);
|
||||||
nbt.setInt("monster_spawn_light_level", 11);
|
builder.putInt("monster_spawn_light_level", 11);
|
||||||
if (fixedTime != null) nbt.setLong("fixed_time", fixedTime);
|
if (fixedTime != null) builder.putLong("fixed_time", fixedTime);
|
||||||
});
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -261,9 +262,9 @@ public class DimensionType {
|
||||||
private boolean bedSafe = true;
|
private boolean bedSafe = true;
|
||||||
private String effects = "minecraft:overworld";
|
private String effects = "minecraft:overworld";
|
||||||
private boolean piglinSafe = false;
|
private boolean piglinSafe = false;
|
||||||
private int minY = SizesKt.getVanillaMinY();
|
private int minY = VANILLA_MIN_Y;
|
||||||
private int logicalHeight = SizesKt.getVanillaMaxY() - SizesKt.getVanillaMinY() + 1;
|
private int logicalHeight = VANILLA_MAX_Y - VANILLA_MIN_Y + 1;
|
||||||
private int height = SizesKt.getVanillaMaxY() - SizesKt.getVanillaMinY() + 1;
|
private int height = VANILLA_MAX_Y - VANILLA_MIN_Y + 1;
|
||||||
private double coordinateScale = 1.0;
|
private double coordinateScale = 1.0;
|
||||||
private NamespaceID infiniburn = NamespaceID.from("minecraft:infiniburn_overworld");
|
private NamespaceID infiniburn = NamespaceID.from("minecraft:infiniburn_overworld");
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package net.minestom.server.world;
|
package net.minestom.server.world;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.BinaryTagTypes;
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
|
import net.kyori.adventure.nbt.ListBinaryTag;
|
||||||
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.NBTType;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -81,21 +81,19 @@ public final class DimensionTypeManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the {@link NBTCompound} containing all the registered dimensions.
|
* Creates the {@link CompoundBinaryTag} containing all the registered dimensions.
|
||||||
* <p>
|
* <p>
|
||||||
* Used when a player connects.
|
* Used when a player connects.
|
||||||
*
|
*
|
||||||
* @return an nbt compound containing the registered dimensions
|
* @return an nbt compound containing the registered dimensions
|
||||||
*/
|
*/
|
||||||
public @NotNull NBTCompound toNBT() {
|
public @NotNull CompoundBinaryTag toNBT() {
|
||||||
return NBT.Compound(dimensions -> {
|
ListBinaryTag.Builder<CompoundBinaryTag> entries = ListBinaryTag.builder(BinaryTagTypes.COMPOUND);
|
||||||
dimensions.setString("type", "minecraft:dimension_type");
|
for (DimensionType dimensionType : dimensionTypes)
|
||||||
dimensions.set("value", NBT.List(
|
entries.add(dimensionType.toIndexedNBT());
|
||||||
NBTType.TAG_Compound,
|
return CompoundBinaryTag.builder()
|
||||||
dimensionTypes.stream()
|
.putString("type", "minecraft:dimension_type")
|
||||||
.map(DimensionType::toIndexedNBT)
|
.put("value", entries.build())
|
||||||
.toList()
|
.build();
|
||||||
));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package net.minestom.server.world.biomes;
|
package net.minestom.server.world.biomes;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.minestom.server.coordinate.Point;
|
import net.minestom.server.coordinate.Point;
|
||||||
import net.minestom.server.registry.ProtocolObject;
|
import net.minestom.server.registry.ProtocolObject;
|
||||||
import net.minestom.server.registry.Registry;
|
import net.minestom.server.registry.Registry;
|
||||||
|
@ -8,8 +9,6 @@ import net.minestom.server.utils.validate.Check;
|
||||||
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 java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
@ -54,18 +53,20 @@ sealed public interface Biome extends ProtocolObject permits BiomeImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default @NotNull NBTCompound toNbt() {
|
default @NotNull CompoundBinaryTag toNbt() {
|
||||||
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");
|
||||||
|
|
||||||
return NBT.Compound(element -> {
|
CompoundBinaryTag.Builder builder = CompoundBinaryTag.builder()
|
||||||
element.setFloat("temperature", temperature());
|
.putFloat("temperature", temperature())
|
||||||
element.setFloat("downfall", downfall());
|
.putFloat("downfall", downfall())
|
||||||
element.setByte("has_precipitation", (byte) (precipitation() == Precipitation.NONE ? 0 : 1));
|
.putByte("has_precipitation", (byte) (precipitation() == Precipitation.NONE ? 0 : 1))
|
||||||
if (temperatureModifier() != TemperatureModifier.NONE)
|
.putString("precipitation", precipitation().name().toLowerCase(Locale.ROOT));
|
||||||
element.setString("temperature_modifier", temperatureModifier().name().toLowerCase(Locale.ROOT));
|
if (temperatureModifier() != TemperatureModifier.NONE)
|
||||||
element.set("effects", effects().toNbt());
|
builder.putString("temperature_modifier", temperatureModifier().name().toLowerCase(Locale.ROOT));
|
||||||
});
|
return builder
|
||||||
|
.put("effects", effects().toNbt())
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
static @NotNull Builder builder() {
|
static @NotNull Builder builder() {
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
package net.minestom.server.world.biomes;
|
package net.minestom.server.world.biomes;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
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 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,
|
||||||
|
@ -18,29 +16,29 @@ public record BiomeEffects(int fogColor, int skyColor, int waterColor, int water
|
||||||
return new Builder();
|
return new Builder();
|
||||||
}
|
}
|
||||||
|
|
||||||
public NBTCompound toNbt() {
|
public CompoundBinaryTag toNbt() {
|
||||||
return NBT.Compound(nbt -> {
|
var builder = CompoundBinaryTag.builder();
|
||||||
nbt.setInt("fog_color", fogColor);
|
builder.putInt("fog_color", fogColor);
|
||||||
if (foliageColor != -1)
|
if (foliageColor != -1)
|
||||||
nbt.setInt("foliage_color", foliageColor);
|
builder.putInt("foliage_color", foliageColor);
|
||||||
if (grassColor != -1)
|
if (grassColor != -1)
|
||||||
nbt.setInt("grass_color", grassColor);
|
builder.putInt("grass_color", grassColor);
|
||||||
nbt.setInt("sky_color", skyColor);
|
builder.putInt("sky_color", skyColor);
|
||||||
nbt.setInt("water_color", waterColor);
|
builder.putInt("water_color", waterColor);
|
||||||
nbt.setInt("water_fog_color", waterFogColor);
|
builder.putInt("water_fog_color", waterFogColor);
|
||||||
if (grassColorModifier != null)
|
if (grassColorModifier != null)
|
||||||
nbt.setString("grass_color_modifier", grassColorModifier.name().toLowerCase(Locale.ROOT));
|
builder.putString("grass_color_modifier", grassColorModifier.name().toLowerCase(Locale.ROOT));
|
||||||
if (biomeParticle != null)
|
if (biomeParticle != null)
|
||||||
nbt.set("particle", biomeParticle.toNbt());
|
builder.put("particle", biomeParticle.toNbt());
|
||||||
if (ambientSound != null)
|
if (ambientSound != null)
|
||||||
nbt.setString("ambient_sound", ambientSound.toString());
|
builder.putString("ambient_sound", ambientSound.toString());
|
||||||
if (moodSound != null)
|
if (moodSound != null)
|
||||||
nbt.set("mood_sound", moodSound.toNbt());
|
builder.put("mood_sound", moodSound.toNbt());
|
||||||
if (additionsSound != null)
|
if (additionsSound != null)
|
||||||
nbt.set("additions_sound", additionsSound.toNbt());
|
builder.put("additions_sound", additionsSound.toNbt());
|
||||||
if (music != null)
|
if (music != null)
|
||||||
nbt.set("music", music.toNbt());
|
builder.put("music", music.toNbt());
|
||||||
});
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum GrassColorModifier {
|
public enum GrassColorModifier {
|
||||||
|
@ -48,30 +46,33 @@ 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 CompoundBinaryTag toNbt() {
|
||||||
return NBT.Compound(Map.of(
|
return CompoundBinaryTag.builder()
|
||||||
"sound", NBT.String(sound.toString()),
|
.putString("sound", sound.toString())
|
||||||
"tick_delay", NBT.Int(tickDelay),
|
.putInt("tick_delay", tickDelay)
|
||||||
"block_search_extent", NBT.Int(blockSearchExtent),
|
.putInt("block_search_extent", blockSearchExtent)
|
||||||
"offset", NBT.Double(offset)));
|
.putDouble("offset", offset)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record AdditionsSound(NamespaceID sound, double tickChance) {
|
public record AdditionsSound(NamespaceID sound, double tickChance) {
|
||||||
public @NotNull NBTCompound toNbt() {
|
public @NotNull CompoundBinaryTag toNbt() {
|
||||||
return NBT.Compound(Map.of(
|
return CompoundBinaryTag.builder()
|
||||||
"sound", NBT.String(sound.toString()),
|
.putString("sound", sound.toString())
|
||||||
"tick_chance", NBT.Double(tickChance)));
|
.putDouble("tick_chance", tickChance)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 CompoundBinaryTag toNbt() {
|
||||||
return NBT.Compound(Map.of(
|
return CompoundBinaryTag.builder()
|
||||||
"sound", NBT.String(sound.toString()),
|
.putString("sound", sound.toString())
|
||||||
"min_delay", NBT.Int(minDelay),
|
.putInt("min_delay", minDelay)
|
||||||
"max_delay", NBT.Int(maxDelay),
|
.putInt("max_delay", maxDelay)
|
||||||
"replace_current_music", NBT.Boolean(replaceCurrentMusic)));
|
.putBoolean("replace_current_music", replaceCurrentMusic)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package net.minestom.server.world.biomes;
|
package net.minestom.server.world.biomes;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.BinaryTagTypes;
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
|
import net.kyori.adventure.nbt.ListBinaryTag;
|
||||||
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.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.NBTType;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -25,7 +25,7 @@ public final class BiomeManager {
|
||||||
private final Map<NamespaceID, Integer> idMappings = new ConcurrentHashMap<>();
|
private final Map<NamespaceID, Integer> idMappings = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private final AtomicInteger ID_COUNTER = new AtomicInteger(0);
|
private final AtomicInteger ID_COUNTER = new AtomicInteger(0);
|
||||||
private NBTCompound nbtCache = null;
|
private CompoundBinaryTag nbtCache = null;
|
||||||
|
|
||||||
public BiomeManager() {
|
public BiomeManager() {
|
||||||
// Need to register plains for the client to work properly
|
// Need to register plains for the client to work properly
|
||||||
|
@ -101,18 +101,21 @@ public final class BiomeManager {
|
||||||
return getByName(namespace);
|
return getByName(namespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull NBTCompound toNBT() {
|
public @NotNull CompoundBinaryTag toNBT() {
|
||||||
if (nbtCache != null) return nbtCache;
|
if (nbtCache != null) return nbtCache;
|
||||||
nbtCache = NBT.Compound(Map.of(
|
|
||||||
"type", NBT.String("minecraft:worldgen/biome"),
|
|
||||||
"value", NBT.List(NBTType.TAG_Compound, biomes.values().stream().map(biome -> {
|
|
||||||
return NBT.Compound(Map.of(
|
|
||||||
"id", NBT.Int(getId(biome)),
|
|
||||||
"name", NBT.String(biome.namespace().toString()),
|
|
||||||
"element", biome.toNbt()
|
|
||||||
));
|
|
||||||
}).toList())));
|
|
||||||
|
|
||||||
|
ListBinaryTag.Builder<CompoundBinaryTag> entries = ListBinaryTag.builder(BinaryTagTypes.COMPOUND);
|
||||||
|
for (Biome biome : biomes.values()) {
|
||||||
|
entries.add(CompoundBinaryTag.builder()
|
||||||
|
.putInt("id", getId(biome))
|
||||||
|
.putString("name", biome.namespace().toString())
|
||||||
|
.put("element", biome.toNbt())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
nbtCache = CompoundBinaryTag.builder()
|
||||||
|
.putString("type", "minecraft:worldgen/biome")
|
||||||
|
.put("value", entries.build())
|
||||||
|
.build();
|
||||||
return nbtCache;
|
return nbtCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
package net.minestom.server.world.biomes;
|
package net.minestom.server.world.biomes;
|
||||||
|
|
||||||
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
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 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 CompoundBinaryTag toNbt() {
|
||||||
return NBT.Compound(Map.of(
|
return CompoundBinaryTag.builder()
|
||||||
"probability", NBT.Float(probability),
|
.putFloat("probability", probability)
|
||||||
"options", option.toNbt()));
|
.put("options", option.toNbt())
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface Option {
|
public interface Option {
|
||||||
NBTCompound toNbt();
|
CompoundBinaryTag toNbt();
|
||||||
}
|
}
|
||||||
|
|
||||||
public record BlockOption(Block block) implements Option {
|
public record BlockOption(Block block) implements Option {
|
||||||
|
@ -24,15 +24,17 @@ public record BiomeParticle(float probability, Option option) {
|
||||||
private static final String type = "block";
|
private static final String type = "block";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NBTCompound toNbt() {
|
public CompoundBinaryTag toNbt() {
|
||||||
return NBT.Compound(nbtCompound -> {
|
CompoundBinaryTag.Builder builder = CompoundBinaryTag.builder();
|
||||||
nbtCompound.setString("type", type);
|
builder.putString("type", type);
|
||||||
nbtCompound.setString("Name", block.name());
|
builder.putString("Name", block.name());
|
||||||
Map<String, String> propertiesMap = block.properties();
|
Map<String, String> propertiesMap = block.properties();
|
||||||
if (propertiesMap.size() != 0) {
|
if (!propertiesMap.isEmpty()) {
|
||||||
nbtCompound.set("Properties", NBT.Compound(p -> propertiesMap.forEach(p::setString)));
|
CompoundBinaryTag.Builder properties = CompoundBinaryTag.builder();
|
||||||
}
|
propertiesMap.forEach(properties::putString);
|
||||||
});
|
builder.put("Properties", properties.build());
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,13 +42,14 @@ public record BiomeParticle(float probability, Option option) {
|
||||||
private static final String type = "dust";
|
private static final String type = "dust";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NBTCompound toNbt() {
|
public CompoundBinaryTag toNbt() {
|
||||||
return NBT.Compound(Map.of(
|
return CompoundBinaryTag.builder()
|
||||||
"type", NBT.String(type),
|
.putString("type", type)
|
||||||
"r", NBT.Float(red),
|
.putFloat("r", red)
|
||||||
"g", NBT.Float(green),
|
.putFloat("g", green)
|
||||||
"b", NBT.Float(blue),
|
.putFloat("b", blue)
|
||||||
"scale", NBT.Float(scale)));
|
.putFloat("scale", scale)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,17 +57,19 @@ public record BiomeParticle(float probability, Option option) {
|
||||||
private static final String type = "item";
|
private static final String type = "item";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NBTCompound toNbt() {
|
public CompoundBinaryTag toNbt() {
|
||||||
//todo test count might be wrong type
|
//todo test count might be wrong type
|
||||||
NBTCompound nbtCompound = item.meta().toNBT();
|
return item.meta().toNBT()
|
||||||
return nbtCompound.modify(n -> n.setString("type", type));
|
.putString("type", type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record NormalOption(NamespaceID type) implements Option {
|
public record NormalOption(NamespaceID type) implements Option {
|
||||||
@Override
|
@Override
|
||||||
public NBTCompound toNbt() {
|
public CompoundBinaryTag toNbt() {
|
||||||
return NBT.Compound(Map.of("type", NBT.String(type.toString())));
|
return CompoundBinaryTag.builder()
|
||||||
|
.putString("type", type.toString())
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue