Skip to content

Instantly share code, notes, and snippets.

@RealAlphaUA
Last active June 6, 2024 16:42
Show Gist options
  • Save RealAlphaUA/e54d0e6747d668e209d678e5db9d04ea to your computer and use it in GitHub Desktop.
Save RealAlphaUA/e54d0e6747d668e209d678e5db9d04ea to your computer and use it in GitHub Desktop.
Small tool 🧩to read stack items in bukkit and nbt format depending on the context 👓
import org.bukkit.Bukkit;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.io.BukkitObjectInputStream;
import org.bukkit.util.io.BukkitObjectOutputStream;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Map;
public class InventoryMarshal {
private static Class<?> NBT_COMPRESSED_STREAM_TOOLS_CLAZZ;
private static Method WRITE_COMPRESSED_METHOD;
private static Method READ_COMPRESSED_METHOD;
private static Class<?> NTB_TAG_COMPOUND_CLAZZ;
private static Class<?> NMS_ITEM_STACK_CLAZZ;
private static Constructor<?> NMS_ITEM_STACK_CONSTRUCTOR;
private static Method SAVE_METHOD;
private static Class<?> CRAFT_ITEM_STACK_CLAZZ;
private static Method AS_BUKKIT_COPY_METHOD;
private static Method AS_NMS_COPY_METHOD;
static {
try {
NBT_COMPRESSED_STREAM_TOOLS_CLAZZ = getNmsClazz("NBTCompressedStreamTools");
NTB_TAG_COMPOUND_CLAZZ = getNmsClazz("NBTTagCompound");
WRITE_COMPRESSED_METHOD = NBT_COMPRESSED_STREAM_TOOLS_CLAZZ.getDeclaredMethod("a", NTB_TAG_COMPOUND_CLAZZ, OutputStream.class);
WRITE_COMPRESSED_METHOD.setAccessible(true);
READ_COMPRESSED_METHOD = NBT_COMPRESSED_STREAM_TOOLS_CLAZZ.getDeclaredMethod("a", InputStream.class);
READ_COMPRESSED_METHOD.setAccessible(true);
NMS_ITEM_STACK_CLAZZ = getNmsClazz("ItemStack");
NMS_ITEM_STACK_CONSTRUCTOR = NMS_ITEM_STACK_CLAZZ.getDeclaredConstructor(NTB_TAG_COMPOUND_CLAZZ);
NMS_ITEM_STACK_CONSTRUCTOR.setAccessible(true);
SAVE_METHOD = NMS_ITEM_STACK_CLAZZ.getDeclaredMethod("save", NTB_TAG_COMPOUND_CLAZZ);
SAVE_METHOD.setAccessible(true);
CRAFT_ITEM_STACK_CLAZZ = getCraftBukkitClazz("inventory.CraftItemStack");
AS_BUKKIT_COPY_METHOD = CRAFT_ITEM_STACK_CLAZZ.getDeclaredMethod("asBukkitCopy", NMS_ITEM_STACK_CLAZZ);
AS_BUKKIT_COPY_METHOD.setAccessible(true);
AS_NMS_COPY_METHOD = CRAFT_ITEM_STACK_CLAZZ.getDeclaredMethod("asNMSCopy", ItemStack.class);
AS_NMS_COPY_METHOD.setAccessible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Class<?> getNmsClazz(String className) throws ClassNotFoundException {
return Class.forName("net.minecraft.server." + Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3] + "." + className);
}
public static Class<?> getCraftBukkitClazz(String className) throws ClassNotFoundException {
return Class.forName("org.bukkit.craftbukkit." + Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3] + "." + className);
}
public static Object getNBTTAGCompound() throws Exception {
return NTB_TAG_COMPOUND_CLAZZ.newInstance();
}
public static Object newNMSItemStack(Object nbtTagCompound) throws Exception {
return NMS_ITEM_STACK_CONSTRUCTOR.newInstance(nbtTagCompound);
}
public static ItemStack newBukkitItemStack(Object nmsItemStack) throws Exception {
return (ItemStack) AS_BUKKIT_COPY_METHOD.invoke(null, nmsItemStack);
}
public static Object getNMSItemStack(ItemStack itemStack) throws Exception {
return AS_NMS_COPY_METHOD.invoke(null, itemStack);
}
public static byte[] serialize(ItemStack itemStack) throws Exception {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Object nmsItemStack = getNMSItemStack(itemStack);
Object nbtTagCompound = getNBTTAGCompound();
SAVE_METHOD.invoke(nmsItemStack, nbtTagCompound);
WRITE_COMPRESSED_METHOD.invoke(null, nbtTagCompound, byteArrayOutputStream);
return byteArrayOutputStream.toByteArray();
}
public static ItemStack deserialize(byte[] byteArray) throws Exception {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArray);
Object nbtTagCompound = READ_COMPRESSED_METHOD.invoke(null, byteArrayInputStream);
Object nmsItemStack = newNMSItemStack(nbtTagCompound);
return newBukkitItemStack(nmsItemStack);
}
public static byte[] marshal(Inventory inventory) throws Exception {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream);
dataOutputStream.writeInt(inventory.getSize());
for (int i = 0; i < inventory.getSize(); i++) {
ItemStack itemStack = inventory.getItem(i);
if (itemStack == null) {
dataOutputStream.writeInt(0);
continue;
}
byte[] bytes = serialize(itemStack);
dataOutputStream.writeInt(bytes.length);
dataOutputStream.write(bytes);
}
return byteArrayOutputStream.toByteArray();
}
public static ItemStack[] unMarshal(byte[] byteArray) throws Exception {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArray);
DataInputStream dataInputStream = new DataInputStream(byteArrayInputStream);
int size = dataInputStream.readInt();
ItemStack[] itemStacks = new ItemStack[size];
for (int i = 0; i < size; i++) {
int length = dataInputStream.readInt();
if (length == 0) {
continue;
}
byte[] bytes = new byte[length];
dataInputStream.readFully(bytes);
itemStacks[i] = deserialize(bytes);
}
return itemStacks;
}
public static byte[] bukkitMarshal(Inventory inventory) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try (BukkitObjectOutputStream objectOutputStream = new BukkitObjectOutputStream(byteArrayOutputStream)) {
objectOutputStream.writeInt(inventory.getSize());
for (ItemStack obj : inventory) {
objectOutputStream.writeObject(obj != null ? obj.serialize() : null);
}
return byteArrayOutputStream.toByteArray();
}
}
public static ItemStack[] bukkitUnMarshal(byte[] byteArray) throws IOException, ClassNotFoundException {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArray);
try (BukkitObjectInputStream objectInputStream = new BukkitObjectInputStream(byteArrayInputStream)) {
int size = objectInputStream.readInt();
ItemStack[] content = new ItemStack[size];
for (int i = 0; i < size; i++) {
Object readObject = objectInputStream.readObject();
if (readObject != null) {
try {
content[i] = ItemStack.deserialize((Map<String, Object>) readObject);
} catch (NullPointerException e) {
//not found meta of item
}
}
}
return content;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment