2020-07-06 23:43:56 +02:00
|
|
|
package net.minestom.server.utils;
|
|
|
|
|
2020-11-07 19:39:22 +01:00
|
|
|
import net.minestom.server.MinecraftServer;
|
2020-07-06 23:43:56 +02:00
|
|
|
import net.minestom.server.attribute.Attribute;
|
|
|
|
import net.minestom.server.attribute.AttributeOperation;
|
2020-07-06 23:55:43 +02:00
|
|
|
import net.minestom.server.chat.ChatParser;
|
2020-07-06 23:43:56 +02:00
|
|
|
import net.minestom.server.chat.ColoredText;
|
2020-12-31 19:50:26 +01:00
|
|
|
import net.minestom.server.chat.JsonMessage;
|
2020-11-07 19:39:22 +01:00
|
|
|
import net.minestom.server.data.Data;
|
|
|
|
import net.minestom.server.data.DataType;
|
2020-07-06 23:43:56 +02:00
|
|
|
import net.minestom.server.inventory.Inventory;
|
|
|
|
import net.minestom.server.item.Enchantment;
|
|
|
|
import net.minestom.server.item.ItemStack;
|
|
|
|
import net.minestom.server.item.Material;
|
|
|
|
import net.minestom.server.item.attribute.AttributeSlot;
|
|
|
|
import net.minestom.server.item.attribute.ItemAttribute;
|
2020-07-23 05:36:15 +02:00
|
|
|
import net.minestom.server.item.metadata.ItemMeta;
|
2020-07-06 23:43:56 +02:00
|
|
|
import net.minestom.server.registry.Registries;
|
2020-08-19 20:34:21 +02:00
|
|
|
import net.minestom.server.utils.binary.BinaryReader;
|
|
|
|
import net.minestom.server.utils.binary.BinaryWriter;
|
2020-11-07 19:39:22 +01:00
|
|
|
import net.minestom.server.utils.validate.Check;
|
|
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
import org.jetbrains.annotations.Nullable;
|
2020-07-06 23:43:56 +02:00
|
|
|
import org.jglrxavpok.hephaistos.nbt.*;
|
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
|
|
|
import java.io.IOException;
|
2020-07-23 05:48:47 +02:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Map;
|
|
|
|
import java.util.UUID;
|
2020-07-06 23:43:56 +02:00
|
|
|
|
|
|
|
// for lack of a better name
|
2020-08-07 08:10:10 +02:00
|
|
|
public final class NBTUtils {
|
2020-07-06 23:43:56 +02:00
|
|
|
|
2020-07-13 14:36:39 +02:00
|
|
|
private final static Logger LOGGER = LoggerFactory.getLogger(NBTUtils.class);
|
2020-07-06 23:43:56 +02:00
|
|
|
|
2020-08-07 08:10:10 +02:00
|
|
|
private NBTUtils() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-07-06 23:43:56 +02:00
|
|
|
/**
|
|
|
|
* Loads all the items from the 'items' list into the given inventory
|
2020-07-09 15:51:39 +02:00
|
|
|
*
|
2020-08-07 09:14:50 +02:00
|
|
|
* @param items the items to save
|
|
|
|
* @param destination the inventory destination
|
2020-07-06 23:43:56 +02:00
|
|
|
*/
|
2020-11-07 19:39:22 +01:00
|
|
|
public static void loadAllItems(@NotNull NBTList<NBTCompound> items, @NotNull Inventory destination) {
|
2020-07-06 23:43:56 +02:00
|
|
|
destination.clear();
|
2020-07-09 15:51:39 +02:00
|
|
|
for (NBTCompound tag : items) {
|
2020-07-06 23:43:56 +02:00
|
|
|
Material item = Registries.getMaterial(tag.getString("id"));
|
2020-07-09 15:51:39 +02:00
|
|
|
if (item == Material.AIR) {
|
2020-07-06 23:43:56 +02:00
|
|
|
item = Material.STONE;
|
|
|
|
}
|
|
|
|
ItemStack stack = new ItemStack(item, tag.getByte("Count"));
|
2020-07-09 15:51:39 +02:00
|
|
|
if (tag.containsKey("tag")) {
|
2020-07-06 23:50:32 +02:00
|
|
|
loadDataIntoItem(stack, tag.getCompound("tag"));
|
|
|
|
}
|
2020-07-06 23:43:56 +02:00
|
|
|
destination.setItemStack(tag.getByte("Slot"), stack);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-07 19:39:22 +01:00
|
|
|
public static void saveAllItems(@NotNull NBTList<NBTCompound> list, @NotNull Inventory inventory) {
|
2020-07-06 23:43:56 +02:00
|
|
|
for (int i = 0; i < inventory.getSize(); i++) {
|
2020-07-23 07:36:49 +02:00
|
|
|
final ItemStack stack = inventory.getItemStack(i);
|
2020-07-06 23:43:56 +02:00
|
|
|
NBTCompound nbt = new NBTCompound();
|
|
|
|
|
2020-07-06 23:50:32 +02:00
|
|
|
NBTCompound tag = new NBTCompound();
|
|
|
|
saveDataIntoNBT(stack, tag);
|
|
|
|
|
|
|
|
nbt.set("tag", tag);
|
2020-07-06 23:43:56 +02:00
|
|
|
nbt.setByte("Slot", (byte) i);
|
|
|
|
nbt.setByte("Count", stack.getAmount());
|
|
|
|
nbt.setString("id", stack.getMaterial().getName());
|
|
|
|
|
|
|
|
list.add(nbt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-07 19:39:22 +01:00
|
|
|
public static void writeEnchant(@NotNull NBTCompound nbt, @NotNull String listName,
|
|
|
|
@NotNull Map<Enchantment, Short> enchantmentMap) {
|
2020-07-06 23:43:56 +02:00
|
|
|
NBTList<NBTCompound> enchantList = new NBTList<>(NBTTypes.TAG_Compound);
|
|
|
|
for (Map.Entry<Enchantment, Short> entry : enchantmentMap.entrySet()) {
|
2020-07-23 07:36:49 +02:00
|
|
|
final Enchantment enchantment = entry.getKey();
|
|
|
|
final short level = entry.getValue();
|
2020-07-06 23:43:56 +02:00
|
|
|
|
|
|
|
enchantList.add(new NBTCompound()
|
|
|
|
.setShort("lvl", level)
|
|
|
|
.setString("id", "minecraft:" + enchantment.name().toLowerCase())
|
|
|
|
);
|
|
|
|
}
|
|
|
|
nbt.set(listName, enchantList);
|
|
|
|
}
|
|
|
|
|
2020-11-13 03:39:00 +01:00
|
|
|
@Nullable
|
2020-11-07 19:39:22 +01:00
|
|
|
public static ItemStack readItemStack(@NotNull BinaryReader reader) {
|
2020-07-23 05:36:15 +02:00
|
|
|
final boolean present = reader.readBoolean();
|
2020-07-06 23:43:56 +02:00
|
|
|
|
|
|
|
if (!present) {
|
|
|
|
return ItemStack.getAirItem();
|
|
|
|
}
|
|
|
|
|
2020-07-23 05:36:15 +02:00
|
|
|
final int id = reader.readVarInt();
|
2020-07-06 23:43:56 +02:00
|
|
|
if (id == -1) {
|
|
|
|
// Drop mode
|
|
|
|
return ItemStack.getAirItem();
|
|
|
|
}
|
|
|
|
|
2020-07-23 05:36:15 +02:00
|
|
|
final Material material = Material.fromId((short) id);
|
|
|
|
final byte count = reader.readByte();
|
|
|
|
ItemStack item = new ItemStack(material, count);
|
2020-07-06 23:43:56 +02:00
|
|
|
|
|
|
|
try {
|
2020-07-23 05:36:15 +02:00
|
|
|
final NBT itemNBT = reader.readTag();
|
2020-07-09 15:51:39 +02:00
|
|
|
if (itemNBT instanceof NBTCompound) { // can also be a TAG_End if no data
|
2020-07-06 23:43:56 +02:00
|
|
|
NBTCompound nbt = (NBTCompound) itemNBT;
|
|
|
|
loadDataIntoItem(item, nbt);
|
|
|
|
}
|
|
|
|
} catch (IOException | NBTException e) {
|
2021-01-19 18:25:54 +01:00
|
|
|
MinecraftServer.getExceptionManager().handleException(e);
|
2020-07-06 23:43:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
2020-11-07 19:39:22 +01:00
|
|
|
public static void loadDataIntoItem(@NotNull ItemStack item, @NotNull NBTCompound nbt) {
|
2020-07-09 15:51:39 +02:00
|
|
|
if (nbt.containsKey("Damage")) item.setDamage(nbt.getInt("Damage"));
|
2021-02-21 16:59:50 +01:00
|
|
|
if (nbt.containsKey("Unbreakable")) item.setUnbreakable(nbt.getAsByte("Unbreakable") == 1);
|
2020-07-09 15:51:39 +02:00
|
|
|
if (nbt.containsKey("HideFlags")) item.setHideFlag(nbt.getInt("HideFlags"));
|
|
|
|
if (nbt.containsKey("display")) {
|
2020-10-16 14:31:15 +02:00
|
|
|
final NBTCompound display = nbt.getCompound("display");
|
|
|
|
if (display.containsKey("Name")) {
|
|
|
|
final String rawName = display.getString("Name");
|
|
|
|
final ColoredText displayName = ChatParser.toColoredText(rawName);
|
|
|
|
item.setDisplayName(displayName);
|
|
|
|
}
|
2020-07-09 15:51:39 +02:00
|
|
|
if (display.containsKey("Lore")) {
|
2020-07-06 23:43:56 +02:00
|
|
|
NBTList<NBTString> loreList = display.getList("Lore");
|
2020-12-31 19:50:26 +01:00
|
|
|
List<JsonMessage> lore = new ArrayList<>();
|
2020-07-09 15:51:39 +02:00
|
|
|
for (NBTString s : loreList) {
|
2020-07-06 23:55:43 +02:00
|
|
|
lore.add(ChatParser.toColoredText(s.getValue()));
|
2020-07-06 23:43:56 +02:00
|
|
|
}
|
|
|
|
item.setLore(lore);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-04 20:26:17 +01:00
|
|
|
// Enchantments
|
2020-07-09 15:51:39 +02:00
|
|
|
if (nbt.containsKey("Enchantments")) {
|
2020-07-06 23:43:56 +02:00
|
|
|
loadEnchantments(nbt.getList("Enchantments"), item::setEnchantment);
|
|
|
|
}
|
2020-08-01 00:21:03 +02:00
|
|
|
|
2021-01-04 20:26:17 +01:00
|
|
|
// Attributes
|
2020-07-09 15:51:39 +02:00
|
|
|
if (nbt.containsKey("AttributeModifiers")) {
|
2020-07-06 23:43:56 +02:00
|
|
|
NBTList<NBTCompound> attributes = nbt.getList("AttributeModifiers");
|
|
|
|
for (NBTCompound attributeNBT : attributes) {
|
2020-10-04 03:04:51 +02:00
|
|
|
final UUID uuid;
|
|
|
|
{
|
|
|
|
final int[] uuidArray = attributeNBT.getIntArray("UUID");
|
|
|
|
uuid = Utils.intArrayToUuid(uuidArray);
|
|
|
|
}
|
2021-02-20 17:35:02 +01:00
|
|
|
|
2021-02-20 23:54:25 +01:00
|
|
|
final double value = attributeNBT.getAsDouble("Amount");
|
2021-02-20 17:35:02 +01:00
|
|
|
final String slot = attributeNBT.containsKey("Slot") ? attributeNBT.getString("Slot") : "MAINHAND";
|
2020-08-01 11:00:31 +02:00
|
|
|
final String attributeName = attributeNBT.getString("AttributeName");
|
2021-02-20 23:54:25 +01:00
|
|
|
final int operation = attributeNBT.getAsInt("Operation");
|
2020-08-01 11:00:31 +02:00
|
|
|
final String name = attributeNBT.getString("Name");
|
2020-07-06 23:43:56 +02:00
|
|
|
|
|
|
|
final Attribute attribute = Attribute.fromKey(attributeName);
|
|
|
|
// Wrong attribute name, stop here
|
|
|
|
if (attribute == null)
|
|
|
|
break;
|
2020-09-29 21:45:16 +02:00
|
|
|
final AttributeOperation attributeOperation = AttributeOperation.fromId(operation);
|
2020-07-06 23:43:56 +02:00
|
|
|
// Wrong attribute operation, stop here
|
2020-09-29 21:45:16 +02:00
|
|
|
if (attributeOperation == null) {
|
2020-07-06 23:43:56 +02:00
|
|
|
break;
|
2020-09-29 21:45:16 +02:00
|
|
|
}
|
2021-02-20 17:35:02 +01:00
|
|
|
|
2021-02-22 14:06:47 +01:00
|
|
|
// Find slot, default to the main hand if the nbt tag is invalid
|
|
|
|
AttributeSlot attributeSlot;
|
|
|
|
try {
|
|
|
|
attributeSlot = AttributeSlot.valueOf(slot.toUpperCase());
|
|
|
|
} catch (IllegalArgumentException e) {
|
2021-02-21 16:56:06 +01:00
|
|
|
attributeSlot = AttributeSlot.MAINHAND;
|
2021-02-22 14:06:47 +01:00
|
|
|
}
|
2021-02-21 16:56:06 +01:00
|
|
|
|
2020-07-06 23:43:56 +02:00
|
|
|
// Add attribute
|
|
|
|
final ItemAttribute itemAttribute =
|
|
|
|
new ItemAttribute(uuid, name, attribute, attributeOperation, value, attributeSlot);
|
|
|
|
item.addAttribute(itemAttribute);
|
|
|
|
}
|
|
|
|
}
|
2020-07-23 05:36:15 +02:00
|
|
|
|
2021-01-04 20:26:17 +01:00
|
|
|
// Hide flags
|
|
|
|
{
|
|
|
|
if (nbt.containsKey("HideFlags")) {
|
|
|
|
item.setHideFlag(nbt.getInt("HideFlags"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Custom model data
|
|
|
|
{
|
|
|
|
if (nbt.containsKey("CustomModelData")) {
|
|
|
|
item.setCustomModelData(nbt.getInt("CustomModelData"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-23 05:36:15 +02:00
|
|
|
// Meta specific field
|
|
|
|
final ItemMeta itemMeta = item.getItemMeta();
|
2020-11-11 00:29:06 +01:00
|
|
|
if (itemMeta != null) {
|
|
|
|
itemMeta.read(nbt);
|
|
|
|
}
|
2020-11-07 19:39:22 +01:00
|
|
|
|
2020-11-21 06:37:44 +01:00
|
|
|
// Ownership
|
|
|
|
{
|
|
|
|
if (nbt.containsKey(ItemStack.OWNERSHIP_DATA_KEY)) {
|
|
|
|
final String identifierString = nbt.getString(ItemStack.OWNERSHIP_DATA_KEY);
|
|
|
|
final UUID identifier = UUID.fromString(identifierString);
|
|
|
|
final Data data = ItemStack.DATA_OWNERSHIP.getOwnObject(identifier);
|
|
|
|
if (data != null) {
|
|
|
|
item.setData(data);
|
2020-11-07 19:39:22 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-07-06 23:43:56 +02:00
|
|
|
}
|
|
|
|
|
2020-08-01 00:21:03 +02:00
|
|
|
public static void loadEnchantments(NBTList<NBTCompound> enchantments, EnchantmentSetter setter) {
|
2020-07-09 15:51:39 +02:00
|
|
|
for (NBTCompound enchantment : enchantments) {
|
2020-10-16 14:31:15 +02:00
|
|
|
final short level = enchantment.getAsShort("lvl");
|
2020-07-23 07:36:49 +02:00
|
|
|
final String id = enchantment.getString("id");
|
|
|
|
final Enchantment enchant = Registries.getEnchantment(id);
|
2020-07-09 15:51:39 +02:00
|
|
|
if (enchant != null) {
|
2020-07-06 23:43:56 +02:00
|
|
|
setter.applyEnchantment(enchant, level);
|
|
|
|
} else {
|
2020-12-14 05:55:48 +01:00
|
|
|
LOGGER.warn("Unknown enchantment type: {}", id);
|
2020-07-06 23:43:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-19 20:34:21 +02:00
|
|
|
public static void writeItemStack(BinaryWriter packet, ItemStack itemStack) {
|
2020-07-06 23:43:56 +02:00
|
|
|
if (itemStack == null || itemStack.isAir()) {
|
|
|
|
packet.writeBoolean(false);
|
|
|
|
} else {
|
|
|
|
packet.writeBoolean(true);
|
2020-07-23 05:36:15 +02:00
|
|
|
packet.writeVarInt(itemStack.getMaterial().getId());
|
2020-07-06 23:43:56 +02:00
|
|
|
packet.writeByte(itemStack.getAmount());
|
|
|
|
|
|
|
|
if (!itemStack.hasNbtTag()) {
|
|
|
|
packet.writeByte((byte) NBTTypes.TAG_End); // No nbt
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
NBTCompound itemNBT = new NBTCompound();
|
2020-07-09 15:51:39 +02:00
|
|
|
|
|
|
|
// Vanilla compound
|
2020-07-06 23:43:56 +02:00
|
|
|
saveDataIntoNBT(itemStack, itemNBT);
|
2020-07-09 15:51:39 +02:00
|
|
|
|
2020-07-06 23:43:56 +02:00
|
|
|
// End custom model data
|
|
|
|
packet.writeNBT("", itemNBT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-07 19:39:22 +01:00
|
|
|
public static void saveDataIntoNBT(@NotNull ItemStack itemStack, @NotNull NBTCompound itemNBT) {
|
2020-07-06 23:43:56 +02:00
|
|
|
// Unbreakable
|
|
|
|
if (itemStack.isUnbreakable()) {
|
|
|
|
itemNBT.setInt("Unbreakable", 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start damage
|
|
|
|
{
|
2020-07-23 05:36:15 +02:00
|
|
|
final int damage = itemStack.getDamage();
|
|
|
|
if (damage > 0) {
|
|
|
|
itemNBT.setInt("Damage", damage);
|
|
|
|
}
|
2020-07-06 23:43:56 +02:00
|
|
|
}
|
|
|
|
// End damage
|
|
|
|
|
|
|
|
// Display
|
2020-07-23 05:36:15 +02:00
|
|
|
final boolean hasDisplayName = itemStack.hasDisplayName();
|
|
|
|
final boolean hasLore = itemStack.hasLore();
|
2020-07-06 23:43:56 +02:00
|
|
|
|
|
|
|
if (hasDisplayName || hasLore) {
|
|
|
|
NBTCompound displayNBT = new NBTCompound();
|
|
|
|
if (hasDisplayName) {
|
|
|
|
final String name = itemStack.getDisplayName().toString();
|
|
|
|
displayNBT.setString("Name", name);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hasLore) {
|
2020-12-31 19:50:26 +01:00
|
|
|
final List<JsonMessage> lore = itemStack.getLore();
|
2020-07-06 23:43:56 +02:00
|
|
|
|
|
|
|
final NBTList<NBTString> loreNBT = new NBTList<>(NBTTypes.TAG_String);
|
2020-12-31 19:50:26 +01:00
|
|
|
for (JsonMessage line : lore) {
|
2020-07-06 23:43:56 +02:00
|
|
|
loreNBT.add(new NBTString(line.toString()));
|
|
|
|
}
|
|
|
|
displayNBT.set("Lore", loreNBT);
|
|
|
|
}
|
|
|
|
|
|
|
|
itemNBT.set("display", displayNBT);
|
|
|
|
}
|
|
|
|
// End display
|
|
|
|
|
|
|
|
// Start enchantment
|
|
|
|
{
|
2020-07-23 05:36:15 +02:00
|
|
|
final Map<Enchantment, Short> enchantmentMap = itemStack.getEnchantmentMap();
|
2020-07-06 23:43:56 +02:00
|
|
|
if (!enchantmentMap.isEmpty()) {
|
|
|
|
writeEnchant(itemNBT, "Enchantments", enchantmentMap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// End enchantment
|
|
|
|
|
|
|
|
// Start attribute
|
|
|
|
{
|
2020-07-23 05:36:15 +02:00
|
|
|
final List<ItemAttribute> itemAttributes = itemStack.getAttributes();
|
2020-07-06 23:43:56 +02:00
|
|
|
if (!itemAttributes.isEmpty()) {
|
|
|
|
NBTList<NBTCompound> attributesNBT = new NBTList<>(NBTTypes.TAG_Compound);
|
|
|
|
|
|
|
|
for (ItemAttribute itemAttribute : itemAttributes) {
|
2020-07-23 05:36:15 +02:00
|
|
|
final UUID uuid = itemAttribute.getUuid();
|
2020-07-06 23:43:56 +02:00
|
|
|
attributesNBT.add(
|
|
|
|
new NBTCompound()
|
2020-10-04 03:04:51 +02:00
|
|
|
.setIntArray("UUID", Utils.uuidToIntArray(uuid))
|
2020-07-06 23:43:56 +02:00
|
|
|
.setDouble("Amount", itemAttribute.getValue())
|
|
|
|
.setString("Slot", itemAttribute.getSlot().name().toLowerCase())
|
2020-10-04 03:04:51 +02:00
|
|
|
.setString("AttributeName", itemAttribute.getAttribute().getKey())
|
2020-07-06 23:43:56 +02:00
|
|
|
.setInt("Operation", itemAttribute.getOperation().getId())
|
|
|
|
.setString("Name", itemAttribute.getInternalName())
|
|
|
|
);
|
|
|
|
}
|
|
|
|
itemNBT.set("AttributeModifiers", attributesNBT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// End attribute
|
|
|
|
|
|
|
|
// Start hide flags
|
|
|
|
{
|
2020-07-23 05:36:15 +02:00
|
|
|
final int hideFlag = itemStack.getHideFlag();
|
2020-07-06 23:43:56 +02:00
|
|
|
if (hideFlag != 0) {
|
|
|
|
itemNBT.setInt("HideFlags", hideFlag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// End hide flags
|
|
|
|
|
|
|
|
// Start custom model data
|
|
|
|
{
|
2020-07-23 05:36:15 +02:00
|
|
|
final int customModelData = itemStack.getCustomModelData();
|
2020-07-06 23:43:56 +02:00
|
|
|
if (customModelData != 0) {
|
|
|
|
itemNBT.setInt("CustomModelData", customModelData);
|
|
|
|
}
|
|
|
|
}
|
2020-07-23 05:48:47 +02:00
|
|
|
// End custom model data
|
2020-07-23 05:36:15 +02:00
|
|
|
|
|
|
|
// Start custom meta
|
2020-11-07 19:39:22 +01:00
|
|
|
{
|
|
|
|
final ItemMeta itemMeta = itemStack.getItemMeta();
|
|
|
|
if (itemMeta != null) {
|
|
|
|
itemMeta.write(itemNBT);
|
|
|
|
}
|
2020-07-23 05:36:15 +02:00
|
|
|
}
|
2020-07-23 05:48:47 +02:00
|
|
|
// End custom meta
|
2020-11-07 19:39:22 +01:00
|
|
|
|
2020-11-21 06:37:44 +01:00
|
|
|
// Start ownership
|
2020-11-07 19:39:22 +01:00
|
|
|
{
|
|
|
|
final Data data = itemStack.getData();
|
2020-11-21 06:37:44 +01:00
|
|
|
if (data != null && !data.isEmpty()) {
|
|
|
|
final UUID identifier = itemStack.getIdentifier();
|
|
|
|
itemNBT.setString(ItemStack.OWNERSHIP_DATA_KEY, identifier.toString());
|
2020-11-07 19:39:22 +01:00
|
|
|
}
|
|
|
|
}
|
2020-11-21 06:37:44 +01:00
|
|
|
// End ownership
|
2020-11-07 19:39:22 +01:00
|
|
|
}
|
|
|
|
|
2020-11-08 20:13:24 +01:00
|
|
|
/**
|
|
|
|
* Converts an object into its {@link NBT} equivalent.
|
2020-11-09 03:21:18 +01:00
|
|
|
* <p>
|
|
|
|
* If {@code type} is not a primitive type or primitive array and {@code supportDataType} is true,
|
|
|
|
* the data will be encoded with the appropriate {@link DataType} into a byte array.
|
2020-11-08 20:13:24 +01:00
|
|
|
*
|
2020-11-08 22:40:50 +01:00
|
|
|
* @param value the value to convert
|
|
|
|
* @param type the type of the value, used to know which {@link DataType} to use if {@code value} is not a primitive type
|
|
|
|
* @param supportDataType true to allow using a {@link DataType} to encode {@code value} into a byte array if not a primitive type
|
|
|
|
* @return the converted value, null if {@code type} is not a primitive type and {@code supportDataType} is false
|
2020-11-08 20:13:24 +01:00
|
|
|
*/
|
2020-11-07 19:39:22 +01:00
|
|
|
@Nullable
|
|
|
|
public static NBT toNBT(@NotNull Object value, @NotNull Class type, boolean supportDataType) {
|
|
|
|
type = PrimitiveConversion.getObjectClass(type);
|
|
|
|
if (type.equals(Boolean.class)) {
|
|
|
|
// No boolean type in NBT
|
|
|
|
return new NBTByte((byte) (((boolean) value) ? 1 : 0));
|
|
|
|
} else if (type.equals(Byte.class)) {
|
|
|
|
return new NBTByte((byte) value);
|
|
|
|
} else if (type.equals(Character.class)) {
|
|
|
|
// No char type in NBT
|
|
|
|
return new NBTShort((short) value);
|
|
|
|
} else if (type.equals(Short.class)) {
|
|
|
|
return new NBTShort((short) value);
|
|
|
|
} else if (type.equals(Integer.class)) {
|
|
|
|
return new NBTInt((int) value);
|
|
|
|
} else if (type.equals(Long.class)) {
|
|
|
|
return new NBTLong((long) value);
|
|
|
|
} else if (type.equals(Float.class)) {
|
|
|
|
return new NBTFloat((float) value);
|
|
|
|
} else if (type.equals(Double.class)) {
|
|
|
|
return new NBTDouble((double) value);
|
|
|
|
} else if (type.equals(String.class)) {
|
|
|
|
return new NBTString((String) value);
|
|
|
|
} else if (type.equals(Byte[].class)) {
|
|
|
|
return new NBTByteArray((byte[]) value);
|
|
|
|
} else if (type.equals(Integer[].class)) {
|
|
|
|
return new NBTIntArray((int[]) value);
|
|
|
|
} else if (type.equals(Long[].class)) {
|
|
|
|
return new NBTLongArray((long[]) value);
|
|
|
|
} else {
|
|
|
|
if (supportDataType) {
|
|
|
|
// Custom NBT type, try to encode using the data manager
|
|
|
|
DataType dataType = MinecraftServer.getDataManager().getDataType(type);
|
|
|
|
Check.notNull(dataType, "The type '" + type + "' is not registered in DataManager and not a primitive type.");
|
|
|
|
|
|
|
|
BinaryWriter writer = new BinaryWriter();
|
|
|
|
dataType.encode(writer, value);
|
|
|
|
|
|
|
|
final byte[] encodedValue = writer.toByteArray();
|
|
|
|
|
|
|
|
return new NBTByteArray(encodedValue);
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-08 20:13:24 +01:00
|
|
|
/**
|
|
|
|
* Converts a nbt object to its raw value.
|
|
|
|
* <p>
|
|
|
|
* Currently support number, string, byte/int/long array.
|
|
|
|
*
|
|
|
|
* @param nbt the nbt tag to convert
|
|
|
|
* @return the value representation of a tag
|
|
|
|
* @throws UnsupportedOperationException if the tag type is not supported
|
|
|
|
*/
|
2020-12-14 06:06:28 +01:00
|
|
|
@NotNull
|
2020-11-07 19:39:22 +01:00
|
|
|
public static Object fromNBT(@NotNull NBT nbt) {
|
|
|
|
if (nbt instanceof NBTNumber) {
|
|
|
|
return ((NBTNumber) nbt).getValue();
|
|
|
|
} else if (nbt instanceof NBTString) {
|
|
|
|
return ((NBTString) nbt).getValue();
|
|
|
|
} else if (nbt instanceof NBTByteArray) {
|
|
|
|
return ((NBTByteArray) nbt).getValue();
|
|
|
|
} else if (nbt instanceof NBTIntArray) {
|
|
|
|
return ((NBTIntArray) nbt).getValue();
|
|
|
|
} else if (nbt instanceof NBTLongArray) {
|
|
|
|
return ((NBTLongArray) nbt).getValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new UnsupportedOperationException("NBT type " + nbt.getClass() + " is not handled properly.");
|
2020-07-06 23:43:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@FunctionalInterface
|
2020-08-01 00:21:03 +02:00
|
|
|
public interface EnchantmentSetter {
|
2020-07-06 23:43:56 +02:00
|
|
|
void applyEnchantment(Enchantment name, short level);
|
|
|
|
}
|
|
|
|
}
|