Added a small nbt utils package

This commit is contained in:
Felix Cravic 2020-05-30 00:01:38 +02:00
parent 1c3099f61a
commit 639629ccf6
4 changed files with 205 additions and 130 deletions

View File

@ -11,6 +11,8 @@ import net.minestom.server.network.packet.PacketWriter;
import net.minestom.server.potion.PotionType; import net.minestom.server.potion.PotionType;
import net.minestom.server.utils.buffer.BufferWrapper; import net.minestom.server.utils.buffer.BufferWrapper;
import net.minestom.server.utils.item.NbtReaderUtils; import net.minestom.server.utils.item.NbtReaderUtils;
import net.minestom.server.utils.nbt.NBT;
import net.minestom.server.utils.nbt.NbtWriter;
import java.util.*; import java.util.*;
@ -104,163 +106,128 @@ public class Utils {
return; return;
} }
packet.writeByte((byte) 0x0A); // Compound NbtWriter mainWriter = new NbtWriter(packet);
packet.writeShort((short) 0); // Empty compound name
// Unbreakable mainWriter.writeCompound(null, writer -> {
if (itemStack.isUnbreakable()) { // Unbreakable
packet.writeByte((byte) 0x03); // Integer if (itemStack.isUnbreakable()) {
packet.writeShortSizedString("Unbreakable"); writer.writeInt("Unbreakable", 1);
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())));
} }
if (hasLore) { // Start damage
ArrayList<String> lore = itemStack.getLore(); {
writer.writeShort("Damage", itemStack.getDamage());
}
// End damage
packet.writeByte((byte) 0x09); // Display
packet.writeShortSizedString("Lore"); boolean hasDisplayName = itemStack.hasDisplayName();
packet.writeByte((byte) 0x08); boolean hasLore = itemStack.hasLore();
packet.writeInt(lore.size());
for (String line : lore) { if (hasDisplayName || hasLore) {
packet.writeShortSizedString(Chat.toJsonString(Chat.fromLegacyText(line))); 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 // Start attribute
} {
// End display List<ItemAttribute> itemAttributes = itemStack.getAttributes();
if (!itemAttributes.isEmpty()) {
packet.writeByte((byte) 0x09); // Type id (list)
packet.writeShortSizedString("AttributeModifiers");
// Start enchantment packet.writeByte((byte) 0x0A); // Compound
{ packet.writeInt(itemAttributes.size());
Map<Enchantment, Short> enchantmentMap = itemStack.getEnchantmentMap();
if (!enchantmentMap.isEmpty()) {
writeEnchant(packet, "Enchantments", enchantmentMap);
}
Map<Enchantment, Short> storedEnchantmentMap = itemStack.getStoredEnchantmentMap(); for (ItemAttribute itemAttribute : itemAttributes) {
if (!storedEnchantmentMap.isEmpty()) { UUID uuid = itemAttribute.getUuid();
writeEnchant(packet, "StoredEnchantments", storedEnchantmentMap);
}
}
// End enchantment
// Start attribute writer.writeLong("UUIDMost", uuid.getMostSignificantBits());
{
List<ItemAttribute> itemAttributes = itemStack.getAttributes();
if (!itemAttributes.isEmpty()) {
packet.writeByte((byte) 0x09); // Type id (list)
packet.writeShortSizedString("AttributeModifiers");
packet.writeByte((byte) 0x0A); // Compound writer.writeLong("UUIDLeast", uuid.getLeastSignificantBits());
packet.writeInt(itemAttributes.size());
for (ItemAttribute itemAttribute : itemAttributes) { writer.writeDouble("Amount", itemAttribute.getValue());
UUID uuid = itemAttribute.getUuid();
packet.writeByte((byte) 0x04); // Type id (long) writer.writeString("Slot", itemAttribute.getSlot().name().toLowerCase());
packet.writeShortSizedString("UUIDMost");
packet.writeLong(uuid.getMostSignificantBits());
packet.writeByte((byte) 0x04); // Type id (long) writer.writeString("itemAttribute", itemAttribute.getAttribute().getKey());
packet.writeShortSizedString("UUIDLeast");
packet.writeLong(uuid.getLeastSignificantBits());
packet.writeByte((byte) 0x06); // Type id (double) writer.writeInt("Operation", itemAttribute.getOperation().getId());
packet.writeShortSizedString("Amount");
packet.writeDouble(itemAttribute.getValue());
packet.writeByte((byte) 0x08); // Type id (string) writer.writeString("Name", itemAttribute.getInternalName());
packet.writeShortSizedString("Slot"); }
packet.writeShortSizedString(itemAttribute.getSlot().name().toLowerCase()); packet.writeByte((byte) 0x00); // End compound
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());
} }
} }
} // End attribute
// End potion
// Start hide flags // Start potion
{ {
int hideFlag = itemStack.getHideFlag(); Set<PotionType> potionTypes = itemStack.getPotionTypes();
if (hideFlag != 0) { if (!potionTypes.isEmpty()) {
packet.writeByte((byte) 3); // Type id (int) for (PotionType potionType : potionTypes) {
packet.writeShortSizedString("HideFlags"); packet.writeByte((byte) 0x08); // type id (string)
packet.writeInt(hideFlag); 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) { private static void writeEnchant(NbtWriter writer, String listName, Map<Enchantment, Short> enchantmentMap) {
packet.writeByte((byte) 0x09); // Type id (list) writer.writeList(listName, NBT.NBT_COMPOUND, enchantmentMap.size(), () -> {
packet.writeShortSizedString(listName); for (Map.Entry<Enchantment, Short> entry : enchantmentMap.entrySet()) {
Enchantment enchantment = entry.getKey();
short level = entry.getValue();
packet.writeByte((byte) 0x0A); // Compound writer.writeShort("lvl", level);
packet.writeInt(enchantmentMap.size()); // Map size
for (Map.Entry<Enchantment, Short> entry : enchantmentMap.entrySet()) { writer.writeString("id", "minecraft:" + enchantment.name().toLowerCase());
Enchantment enchantment = entry.getKey();
short level = entry.getValue();
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) { public static ItemStack readItemStack(PacketReader reader) {

View 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;
}

View File

@ -0,0 +1,6 @@
package net.minestom.server.utils.nbt;
@FunctionalInterface
public interface NbtConsumer {
void accept(NbtWriter writer);
}

View 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
}
}