2020-07-06 23:43:56 +02:00
|
|
|
package net.minestom.server.utils;
|
|
|
|
|
2021-03-11 18:07:04 +01:00
|
|
|
import net.kyori.adventure.nbt.api.BinaryTagHolder;
|
|
|
|
import net.kyori.adventure.util.Codec;
|
2021-06-11 16:11:21 +02:00
|
|
|
import net.minestom.server.adventure.MinestomAdventure;
|
2020-07-06 23:43:56 +02:00
|
|
|
import net.minestom.server.inventory.Inventory;
|
2021-04-09 23:57:05 +02:00
|
|
|
import net.minestom.server.item.Enchantment;
|
|
|
|
import net.minestom.server.item.ItemStack;
|
|
|
|
import net.minestom.server.item.Material;
|
2020-08-19 20:34:21 +02:00
|
|
|
import net.minestom.server.utils.binary.BinaryReader;
|
2021-03-23 13:29:07 +01:00
|
|
|
import org.jetbrains.annotations.Contract;
|
2020-11-07 19:39:22 +01:00
|
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
import org.jetbrains.annotations.Nullable;
|
2020-07-06 23:43:56 +02:00
|
|
|
import org.jglrxavpok.hephaistos.nbt.*;
|
2021-12-13 16:41:30 +01:00
|
|
|
import org.jglrxavpok.hephaistos.nbt.mutable.MutableNBTCompound;
|
2020-07-06 23:43:56 +02:00
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
2021-12-19 21:52:10 +01:00
|
|
|
import java.util.List;
|
|
|
|
import java.util.Map;
|
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-13 14:36:39 +02:00
|
|
|
private final static Logger LOGGER = LoggerFactory.getLogger(NBTUtils.class);
|
2020-07-06 23:43:56 +02:00
|
|
|
|
2021-03-11 18:07:04 +01:00
|
|
|
/**
|
|
|
|
* An Adventure codec to convert between NBT and SNBT.
|
2021-06-11 16:11:21 +02:00
|
|
|
*
|
|
|
|
* @deprecated Use {@link MinestomAdventure#NBT_CODEC}
|
2021-03-11 18:07:04 +01:00
|
|
|
*/
|
2021-06-11 16:11:21 +02:00
|
|
|
@Deprecated(forRemoval = true)
|
|
|
|
public static final Codec<NBT, String, NBTException, RuntimeException> SNBT_CODEC = MinestomAdventure.NBT_CODEC;
|
2021-03-11 18:07:04 +01:00
|
|
|
|
2020-08-07 08:10:10 +02:00
|
|
|
private NBTUtils() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-03-11 18:07:04 +01:00
|
|
|
/**
|
|
|
|
* Turns an {@link NBTCompound} into an Adventure {@link BinaryTagHolder}.
|
2021-04-02 18:13:02 +02:00
|
|
|
*
|
2021-03-11 18:07:04 +01:00
|
|
|
* @param tag the tag, if any
|
|
|
|
* @return the binary tag holder, or {@code null} if the tag was null
|
|
|
|
*/
|
2021-03-23 13:29:07 +01:00
|
|
|
@Contract("null -> null; !null -> !null")
|
|
|
|
public static BinaryTagHolder asBinaryTagHolder(@Nullable NBTCompound tag) {
|
2021-03-11 18:07:04 +01:00
|
|
|
if (tag == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2021-06-11 16:11:21 +02:00
|
|
|
return BinaryTagHolder.encode(tag, MinestomAdventure.NBT_CODEC);
|
2021-03-11 18:07:04 +01:00
|
|
|
}
|
|
|
|
|
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) {
|
2021-07-27 09:55:01 +02:00
|
|
|
Material material = Material.fromNamespaceId(tag.getString("id"));
|
2021-04-02 22:14:48 +02:00
|
|
|
if (material == Material.AIR) {
|
|
|
|
material = Material.STONE;
|
2020-07-06 23:43:56 +02:00
|
|
|
}
|
2021-04-02 22:14:48 +02:00
|
|
|
byte count = tag.getByte("Count");
|
|
|
|
NBTCompound nbtCompound = null;
|
2020-07-09 15:51:39 +02:00
|
|
|
if (tag.containsKey("tag")) {
|
2021-04-02 22:14:48 +02:00
|
|
|
nbtCompound = tag.getCompound("tag");
|
2020-07-06 23:50:32 +02:00
|
|
|
}
|
2021-04-18 04:44:16 +02:00
|
|
|
ItemStack itemStack = ItemStack.fromNBT(material, nbtCompound, count);
|
2021-04-02 22:14:48 +02:00
|
|
|
destination.setItemStack(tag.getByte("Slot"), itemStack);
|
2020-07-06 23:43:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-13 16:41:30 +01:00
|
|
|
public static void saveAllItems(@NotNull List<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
|
|
|
|
2021-04-10 00:24:29 +02:00
|
|
|
NBTCompound tag = stack.getMeta().toNBT();
|
2020-07-06 23:50:32 +02:00
|
|
|
|
2021-12-13 16:41:30 +01:00
|
|
|
final int slotIndex = i;
|
|
|
|
list.add(NBT.Compound(nbt -> {
|
|
|
|
nbt.set("tag", tag);
|
|
|
|
nbt.setByte("Slot", (byte) slotIndex);
|
|
|
|
nbt.setByte("Count", (byte) stack.getAmount());
|
|
|
|
nbt.setString("id", stack.getMaterial().name());
|
|
|
|
}));
|
2020-07-06 23:43:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-13 16:41:30 +01:00
|
|
|
public static void writeEnchant(@NotNull MutableNBTCompound nbt, @NotNull String listName,
|
2020-11-07 19:39:22 +01:00
|
|
|
@NotNull Map<Enchantment, Short> enchantmentMap) {
|
2021-12-13 16:41:30 +01:00
|
|
|
nbt.set(listName, NBT.List(
|
|
|
|
NBTType.TAG_Compound,
|
|
|
|
enchantmentMap.entrySet().stream()
|
2021-12-19 19:52:45 +01:00
|
|
|
.map(entry -> NBT.Compound(Map.of(
|
|
|
|
"lvl", NBT.Short(entry.getValue()),
|
|
|
|
"id", NBT.String(entry.getKey().name()))))
|
2021-12-13 16:41:30 +01:00
|
|
|
.toList()
|
|
|
|
));
|
2020-07-06 23:43:56 +02:00
|
|
|
}
|
|
|
|
|
2021-11-30 17:49:41 +01:00
|
|
|
public static @NotNull ItemStack readItemStack(@NotNull BinaryReader reader) {
|
2020-07-23 05:36:15 +02:00
|
|
|
final boolean present = reader.readBoolean();
|
2021-11-30 17:49:41 +01:00
|
|
|
if (!present) return ItemStack.AIR;
|
2020-07-06 23:43:56 +02:00
|
|
|
|
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
|
2021-04-02 18:13:02 +02:00
|
|
|
return ItemStack.AIR;
|
2020-07-06 23:43:56 +02:00
|
|
|
}
|
|
|
|
|
2020-07-23 05:36:15 +02:00
|
|
|
final Material material = Material.fromId((short) id);
|
|
|
|
final byte count = reader.readByte();
|
2021-11-30 17:49:41 +01:00
|
|
|
NBTCompound nbtCompound = reader.readTag() instanceof NBTCompound compound ?
|
|
|
|
compound : null;
|
2021-04-18 04:44:16 +02:00
|
|
|
return ItemStack.fromNBT(material, nbtCompound, count);
|
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");
|
2021-07-28 13:27:49 +02:00
|
|
|
final Enchantment enchant = Enchantment.fromNamespaceId(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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@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);
|
|
|
|
}
|
|
|
|
}
|