mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-31 21:48:08 +01:00
Added a small nbt utils package
This commit is contained in:
parent
1c3099f61a
commit
639629ccf6
@ -11,6 +11,8 @@ import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.potion.PotionType;
|
||||
import net.minestom.server.utils.buffer.BufferWrapper;
|
||||
import net.minestom.server.utils.item.NbtReaderUtils;
|
||||
import net.minestom.server.utils.nbt.NBT;
|
||||
import net.minestom.server.utils.nbt.NbtWriter;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@ -104,163 +106,128 @@ public class Utils {
|
||||
return;
|
||||
}
|
||||
|
||||
packet.writeByte((byte) 0x0A); // Compound
|
||||
packet.writeShort((short) 0); // Empty compound name
|
||||
NbtWriter mainWriter = new NbtWriter(packet);
|
||||
|
||||
// Unbreakable
|
||||
if (itemStack.isUnbreakable()) {
|
||||
packet.writeByte((byte) 0x03); // Integer
|
||||
packet.writeShortSizedString("Unbreakable");
|
||||
packet.writeInt(1);
|
||||
}
|
||||
|
||||
// Start damage
|
||||
{
|
||||
packet.writeByte((byte) 0x02);
|
||||
packet.writeShortSizedString("Damage");
|
||||
packet.writeShort(itemStack.getDamage());
|
||||
}
|
||||
// End damage
|
||||
|
||||
// Display
|
||||
boolean hasDisplayName = itemStack.hasDisplayName();
|
||||
boolean hasLore = itemStack.hasLore();
|
||||
|
||||
if (hasDisplayName || hasLore) {
|
||||
packet.writeByte((byte) 0x0A); // Start display compound
|
||||
packet.writeShortSizedString("display");
|
||||
|
||||
if (hasDisplayName) {
|
||||
packet.writeByte((byte) 0x08);
|
||||
packet.writeShortSizedString("Name");
|
||||
packet.writeShortSizedString(Chat.toJsonString(Chat.fromLegacyText(itemStack.getDisplayName())));
|
||||
mainWriter.writeCompound(null, writer -> {
|
||||
// Unbreakable
|
||||
if (itemStack.isUnbreakable()) {
|
||||
writer.writeInt("Unbreakable", 1);
|
||||
}
|
||||
|
||||
if (hasLore) {
|
||||
ArrayList<String> lore = itemStack.getLore();
|
||||
// Start damage
|
||||
{
|
||||
writer.writeShort("Damage", itemStack.getDamage());
|
||||
}
|
||||
// End damage
|
||||
|
||||
packet.writeByte((byte) 0x09);
|
||||
packet.writeShortSizedString("Lore");
|
||||
packet.writeByte((byte) 0x08);
|
||||
packet.writeInt(lore.size());
|
||||
for (String line : lore) {
|
||||
packet.writeShortSizedString(Chat.toJsonString(Chat.fromLegacyText(line)));
|
||||
// Display
|
||||
boolean hasDisplayName = itemStack.hasDisplayName();
|
||||
boolean hasLore = itemStack.hasLore();
|
||||
|
||||
if (hasDisplayName || hasLore) {
|
||||
writer.writeCompound("display", displayWriter -> {
|
||||
if (hasDisplayName) {
|
||||
final String name = Chat.toJsonString(Chat.fromLegacyText(itemStack.getDisplayName()));
|
||||
displayWriter.writeString("Name", name);
|
||||
}
|
||||
|
||||
if (hasLore) {
|
||||
final ArrayList<String> lore = itemStack.getLore();
|
||||
|
||||
displayWriter.writeList("Lore", NBT.NBT_STRING, lore.size(), () -> {
|
||||
for (String line : lore) {
|
||||
line = Chat.toJsonString(Chat.fromLegacyText(line));
|
||||
packet.writeShortSizedString(line);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
// End display
|
||||
|
||||
// Start enchantment
|
||||
{
|
||||
Map<Enchantment, Short> enchantmentMap = itemStack.getEnchantmentMap();
|
||||
if (!enchantmentMap.isEmpty()) {
|
||||
writeEnchant(writer, "Enchantments", enchantmentMap);
|
||||
}
|
||||
|
||||
Map<Enchantment, Short> storedEnchantmentMap = itemStack.getStoredEnchantmentMap();
|
||||
if (!storedEnchantmentMap.isEmpty()) {
|
||||
writeEnchant(writer, "StoredEnchantments", storedEnchantmentMap);
|
||||
}
|
||||
}
|
||||
// End enchantment
|
||||
|
||||
packet.writeByte((byte) 0); // End display compound
|
||||
}
|
||||
// End display
|
||||
// Start attribute
|
||||
{
|
||||
List<ItemAttribute> itemAttributes = itemStack.getAttributes();
|
||||
if (!itemAttributes.isEmpty()) {
|
||||
packet.writeByte((byte) 0x09); // Type id (list)
|
||||
packet.writeShortSizedString("AttributeModifiers");
|
||||
|
||||
// Start enchantment
|
||||
{
|
||||
Map<Enchantment, Short> enchantmentMap = itemStack.getEnchantmentMap();
|
||||
if (!enchantmentMap.isEmpty()) {
|
||||
writeEnchant(packet, "Enchantments", enchantmentMap);
|
||||
}
|
||||
packet.writeByte((byte) 0x0A); // Compound
|
||||
packet.writeInt(itemAttributes.size());
|
||||
|
||||
Map<Enchantment, Short> storedEnchantmentMap = itemStack.getStoredEnchantmentMap();
|
||||
if (!storedEnchantmentMap.isEmpty()) {
|
||||
writeEnchant(packet, "StoredEnchantments", storedEnchantmentMap);
|
||||
}
|
||||
}
|
||||
// End enchantment
|
||||
for (ItemAttribute itemAttribute : itemAttributes) {
|
||||
UUID uuid = itemAttribute.getUuid();
|
||||
|
||||
// Start attribute
|
||||
{
|
||||
List<ItemAttribute> itemAttributes = itemStack.getAttributes();
|
||||
if (!itemAttributes.isEmpty()) {
|
||||
packet.writeByte((byte) 0x09); // Type id (list)
|
||||
packet.writeShortSizedString("AttributeModifiers");
|
||||
writer.writeLong("UUIDMost", uuid.getMostSignificantBits());
|
||||
|
||||
packet.writeByte((byte) 0x0A); // Compound
|
||||
packet.writeInt(itemAttributes.size());
|
||||
writer.writeLong("UUIDLeast", uuid.getLeastSignificantBits());
|
||||
|
||||
for (ItemAttribute itemAttribute : itemAttributes) {
|
||||
UUID uuid = itemAttribute.getUuid();
|
||||
writer.writeDouble("Amount", itemAttribute.getValue());
|
||||
|
||||
packet.writeByte((byte) 0x04); // Type id (long)
|
||||
packet.writeShortSizedString("UUIDMost");
|
||||
packet.writeLong(uuid.getMostSignificantBits());
|
||||
writer.writeString("Slot", itemAttribute.getSlot().name().toLowerCase());
|
||||
|
||||
packet.writeByte((byte) 0x04); // Type id (long)
|
||||
packet.writeShortSizedString("UUIDLeast");
|
||||
packet.writeLong(uuid.getLeastSignificantBits());
|
||||
writer.writeString("itemAttribute", itemAttribute.getAttribute().getKey());
|
||||
|
||||
packet.writeByte((byte) 0x06); // Type id (double)
|
||||
packet.writeShortSizedString("Amount");
|
||||
packet.writeDouble(itemAttribute.getValue());
|
||||
writer.writeInt("Operation", itemAttribute.getOperation().getId());
|
||||
|
||||
packet.writeByte((byte) 0x08); // Type id (string)
|
||||
packet.writeShortSizedString("Slot");
|
||||
packet.writeShortSizedString(itemAttribute.getSlot().name().toLowerCase());
|
||||
|
||||
packet.writeByte((byte) 0x08); // Type id (string)
|
||||
packet.writeShortSizedString("AttributeName");
|
||||
packet.writeShortSizedString(itemAttribute.getAttribute().getKey());
|
||||
|
||||
packet.writeByte((byte) 0x03); // Type id (int)
|
||||
packet.writeShortSizedString("Operation");
|
||||
packet.writeInt(itemAttribute.getOperation().getId());
|
||||
|
||||
packet.writeByte((byte) 0x08); // Type id (string)
|
||||
packet.writeShortSizedString("Name");
|
||||
packet.writeShortSizedString(itemAttribute.getInternalName());
|
||||
}
|
||||
packet.writeByte((byte) 0x00); // End compound
|
||||
}
|
||||
}
|
||||
// End attribute
|
||||
|
||||
// Start potion
|
||||
{
|
||||
Set<PotionType> potionTypes = itemStack.getPotionTypes();
|
||||
if (!potionTypes.isEmpty()) {
|
||||
for (PotionType potionType : potionTypes) {
|
||||
packet.writeByte((byte) 0x08); // type id (string)
|
||||
packet.writeShortSizedString("Potion");
|
||||
packet.writeShortSizedString("minecraft:" + potionType.name().toLowerCase());
|
||||
writer.writeString("Name", itemAttribute.getInternalName());
|
||||
}
|
||||
packet.writeByte((byte) 0x00); // End compound
|
||||
}
|
||||
}
|
||||
}
|
||||
// End potion
|
||||
// End attribute
|
||||
|
||||
// Start hide flags
|
||||
{
|
||||
int hideFlag = itemStack.getHideFlag();
|
||||
if (hideFlag != 0) {
|
||||
packet.writeByte((byte) 3); // Type id (int)
|
||||
packet.writeShortSizedString("HideFlags");
|
||||
packet.writeInt(hideFlag);
|
||||
// Start potion
|
||||
{
|
||||
Set<PotionType> potionTypes = itemStack.getPotionTypes();
|
||||
if (!potionTypes.isEmpty()) {
|
||||
for (PotionType potionType : potionTypes) {
|
||||
packet.writeByte((byte) 0x08); // type id (string)
|
||||
packet.writeShortSizedString("Potion");
|
||||
packet.writeShortSizedString("minecraft:" + potionType.name().toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// End potion
|
||||
|
||||
packet.writeByte((byte) 0); // End nbt
|
||||
// Start hide flags
|
||||
{
|
||||
int hideFlag = itemStack.getHideFlag();
|
||||
if (hideFlag != 0) {
|
||||
writer.writeInt("HideFlags", hideFlag);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeEnchant(PacketWriter packet, String listName, Map<Enchantment, Short> enchantmentMap) {
|
||||
packet.writeByte((byte) 0x09); // Type id (list)
|
||||
packet.writeShortSizedString(listName);
|
||||
private static void writeEnchant(NbtWriter writer, String listName, Map<Enchantment, Short> enchantmentMap) {
|
||||
writer.writeList(listName, NBT.NBT_COMPOUND, enchantmentMap.size(), () -> {
|
||||
for (Map.Entry<Enchantment, Short> entry : enchantmentMap.entrySet()) {
|
||||
Enchantment enchantment = entry.getKey();
|
||||
short level = entry.getValue();
|
||||
|
||||
packet.writeByte((byte) 0x0A); // Compound
|
||||
packet.writeInt(enchantmentMap.size()); // Map size
|
||||
writer.writeShort("lvl", level);
|
||||
|
||||
for (Map.Entry<Enchantment, Short> entry : enchantmentMap.entrySet()) {
|
||||
Enchantment enchantment = entry.getKey();
|
||||
short level = entry.getValue();
|
||||
writer.writeString("id", "minecraft:" + enchantment.name().toLowerCase());
|
||||
|
||||
packet.writeByte((byte) 0x02); // Type id (short)
|
||||
packet.writeShortSizedString("lvl");
|
||||
packet.writeShort(level);
|
||||
|
||||
packet.writeByte((byte) 0x08); // Type id (string)
|
||||
packet.writeShortSizedString("id");
|
||||
packet.writeShortSizedString("minecraft:" + enchantment.name().toLowerCase());
|
||||
|
||||
}
|
||||
|
||||
packet.writeByte((byte) 0); // End enchantment compound
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static ItemStack readItemStack(PacketReader reader) {
|
||||
|
18
src/main/java/net/minestom/server/utils/nbt/NBT.java
Normal file
18
src/main/java/net/minestom/server/utils/nbt/NBT.java
Normal file
@ -0,0 +1,18 @@
|
||||
package net.minestom.server.utils.nbt;
|
||||
|
||||
public class NBT {
|
||||
|
||||
public static final byte NBT_BYTE = 0x01;
|
||||
public static final byte NBT_SHORT = 0x02;
|
||||
public static final byte NBT_INT = 0x03;
|
||||
public static final byte NBT_LONG = 0x04;
|
||||
public static final byte NBT_FLOAT = 0x05;
|
||||
public static final byte NBT_DOUBLE = 0x06;
|
||||
public static final byte NBT_BYTE_ARRAY = 0x07;
|
||||
public static final byte NBT_STRING = 0x08;
|
||||
public static final byte NBT_LIST = 0x09;
|
||||
public static final byte NBT_COMPOUND = 0x0A;
|
||||
public static final byte NBT_INT_ARRAY = 0x0B;
|
||||
public static final byte NBT_LONG_ARRAY = 0x0C;
|
||||
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package net.minestom.server.utils.nbt;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface NbtConsumer {
|
||||
void accept(NbtWriter writer);
|
||||
}
|
84
src/main/java/net/minestom/server/utils/nbt/NbtWriter.java
Normal file
84
src/main/java/net/minestom/server/utils/nbt/NbtWriter.java
Normal file
@ -0,0 +1,84 @@
|
||||
package net.minestom.server.utils.nbt;
|
||||
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
|
||||
import static net.minestom.server.utils.nbt.NBT.*;
|
||||
|
||||
public class NbtWriter {
|
||||
|
||||
private PacketWriter packet;
|
||||
|
||||
public NbtWriter(PacketWriter packet) {
|
||||
this.packet = packet;
|
||||
}
|
||||
|
||||
public void writeByte(String name, byte value) {
|
||||
packet.writeByte(NBT_BYTE);
|
||||
packet.writeShortSizedString(name);
|
||||
packet.writeByte(value);
|
||||
}
|
||||
|
||||
public void writeShort(String name, short value) {
|
||||
packet.writeByte(NBT_SHORT);
|
||||
packet.writeShortSizedString(name);
|
||||
packet.writeShort(value);
|
||||
}
|
||||
|
||||
public void writeInt(String name, int value) {
|
||||
packet.writeByte(NBT_INT);
|
||||
packet.writeShortSizedString(name);
|
||||
packet.writeInt(value);
|
||||
}
|
||||
|
||||
public void writeLong(String name, long value) {
|
||||
packet.writeByte(NBT_LONG);
|
||||
packet.writeShortSizedString(name);
|
||||
packet.writeLong(value);
|
||||
}
|
||||
|
||||
public void writeFloat(String name, float value) {
|
||||
packet.writeByte(NBT_FLOAT);
|
||||
packet.writeShortSizedString(name);
|
||||
packet.writeFloat(value);
|
||||
}
|
||||
|
||||
public void writeDouble(String name, double value) {
|
||||
packet.writeByte(NBT_DOUBLE);
|
||||
packet.writeShortSizedString(name);
|
||||
packet.writeDouble(value);
|
||||
}
|
||||
|
||||
// FIXME: not sure
|
||||
public void writeByteArray(String name, byte[] value) {
|
||||
packet.writeByte(NBT_BYTE_ARRAY);
|
||||
packet.writeShortSizedString(name);
|
||||
packet.writeInt(value.length);
|
||||
for (byte val : value) {
|
||||
packet.writeByte(val);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeString(String name, String value) {
|
||||
packet.writeByte(NBT_STRING);
|
||||
packet.writeShortSizedString(name);
|
||||
packet.writeShortSizedString(value);
|
||||
}
|
||||
|
||||
public void writeList(String name, byte type, int size, Runnable callback) {
|
||||
packet.writeByte(NBT_LIST);
|
||||
packet.writeShortSizedString(name == null ? "" : name);
|
||||
packet.writeByte(type);
|
||||
packet.writeInt(size);
|
||||
callback.run();
|
||||
if (type == NBT_COMPOUND)
|
||||
packet.writeByte((byte) 0x00); // End compount
|
||||
}
|
||||
|
||||
public void writeCompound(String name, NbtConsumer consumer) {
|
||||
packet.writeByte(NBT_COMPOUND);
|
||||
packet.writeShortSizedString(name == null ? "" : name);
|
||||
consumer.accept(this);
|
||||
packet.writeByte((byte) 0x00); // End compound
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user