Improved serialization of VirtualInventories

This commit is contained in:
NichtStudioCode 2021-07-06 18:35:11 +02:00
parent 890553cd5c
commit af780f6b4b
11 changed files with 678 additions and 11 deletions

@ -0,0 +1,77 @@
package de.studiocode.invui.util;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.List;
public class DataUtils {
public static byte[] toByteArray(List<Integer> intList) {
byte[] array = new byte[intList.size()];
for (int i = 0; i < intList.size(); i++)
array[i] = intList.get(i).byteValue();
return array;
}
public static byte[] toByteArray(int[] intArray) {
byte[] array = new byte[intArray.length];
for (int i = 0; i < intArray.length; i++)
array[i] = (byte) intArray[i];
return array;
}
public static int[] toIntArray(byte[] byteArray) {
int[] array = new int[byteArray.length];
for (int i = 0; i < byteArray.length; i++)
array[i] = byteArray[i];
return array;
}
public static void writeIntArray(DataOutputStream dos, int[] array) throws IOException {
dos.writeInt(array.length);
for (int i : array) dos.writeInt(i);
}
public static int[] readIntArray(DataInputStream din) throws IOException {
int size = din.readInt();
int[] array = new int[size];
for (int i = 0; i < size; i++) {
array[i] = din.readInt();
}
return array;
}
public static void writeByteArray(DataOutputStream dos, byte[] array) throws IOException {
dos.writeInt(array.length);
dos.write(array);
}
public static byte[] readByteArray(DataInputStream din) throws IOException {
int size = din.readInt();
byte[] array = new byte[size];
din.readFully(array);
return array;
}
public static void write2DByteArray(DataOutputStream dos, byte[][] array2d) throws IOException {
dos.writeInt(array2d.length);
for (byte[] array : array2d) {
writeByteArray(dos, array);
}
}
public static byte[][] read2DByteArray(DataInputStream din) throws IOException {
int size2d = din.readInt();
byte[][] array2d = new byte[size2d][];
for (int i = 0; i < size2d; i++) {
array2d[i] = readByteArray(din);
}
return array2d;
}
}

@ -13,6 +13,8 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*; import java.util.*;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -62,7 +64,10 @@ public class VirtualInventory implements ConfigurationSerializable {
* *
* @param args The args which contain the data to deserialize * @param args The args which contain the data to deserialize
* @return The deserialized {@link VirtualInventory} * @return The deserialized {@link VirtualInventory}
* @deprecated Use {@link VirtualInventoryManager#serializeInventory(VirtualInventory, OutputStream)}
* and {@link VirtualInventoryManager#deserializeInventory(InputStream)} for serialization
*/ */
@Deprecated
public static VirtualInventory deserialize(@NotNull Map<String, Object> args) { public static VirtualInventory deserialize(@NotNull Map<String, Object> args) {
//noinspection unchecked //noinspection unchecked
return new VirtualInventory( return new VirtualInventory(
@ -77,7 +82,10 @@ public class VirtualInventory implements ConfigurationSerializable {
* Serializes this {@link VirtualInventory} to a {@link Map} * Serializes this {@link VirtualInventory} to a {@link Map}
* *
* @return A {@link Map} that contains the serialized data of this {@link VirtualInventory} * @return A {@link Map} that contains the serialized data of this {@link VirtualInventory}
* @deprecated Use {@link VirtualInventoryManager#serializeInventory(VirtualInventory, OutputStream)}
* and {@link VirtualInventoryManager#deserializeInventory(InputStream)} for serialization
*/ */
@Deprecated
@NotNull @NotNull
@Override @Override
public Map<String, Object> serialize() { public Map<String, Object> serialize() {
@ -170,6 +178,15 @@ public class VirtualInventory implements ConfigurationSerializable {
return size; return size;
} }
/**
* Gets the array of max stack sizes for this {@link VirtualInventory}.
*
* @return The array defining the max stack sizes for this {@link VirtualInventory}
*/
public int[] getStackSizes() {
return stackSizes;
}
/** /**
* Gets a copy of the contents of this {@link VirtualInventory}. * Gets a copy of the contents of this {@link VirtualInventory}.
* *

@ -1,13 +1,14 @@
package de.studiocode.invui.virtualinventory; package de.studiocode.invui.virtualinventory;
import de.studiocode.inventoryaccess.api.version.InventoryAccess;
import de.studiocode.invui.InvUI; import de.studiocode.invui.InvUI;
import de.studiocode.invui.util.DataUtils;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.configuration.serialization.ConfigurationSerialization; import org.bukkit.configuration.serialization.ConfigurationSerialization;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.io.File; import java.io.*;
import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -26,6 +27,8 @@ public class VirtualInventoryManager {
private final Map<UUID, VirtualInventory> inventories = new HashMap<>(); private final Map<UUID, VirtualInventory> inventories = new HashMap<>();
private VirtualInventoryManager() { private VirtualInventoryManager() {
SAVE_DIR.mkdirs();
ConfigurationSerialization.registerClass(VirtualInventory.class); ConfigurationSerialization.registerClass(VirtualInventory.class);
InvUI.getInstance().addDisableHandler(this::serializeAll); InvUI.getInstance().addDisableHandler(this::serializeAll);
deserializeAll(); deserializeAll();
@ -77,12 +80,23 @@ public class VirtualInventoryManager {
private void deserializeAll() { private void deserializeAll() {
if (SAVE_DIR.exists()) { if (SAVE_DIR.exists()) {
Arrays.stream(SAVE_DIR.listFiles()) Arrays.stream(SAVE_DIR.listFiles())
.filter(file -> file.getName().endsWith(".vi"))
.forEach(file -> { .forEach(file -> {
if (file.getName().endsWith(".vi")) {
YamlConfiguration config = YamlConfiguration.loadConfiguration(file); YamlConfiguration config = YamlConfiguration.loadConfiguration(file);
VirtualInventory virtualInventory = config.getSerializable("vi", VirtualInventory.class); VirtualInventory virtualInventory = config.getSerializable("vi", VirtualInventory.class);
inventories.put(virtualInventory.getUuid(), virtualInventory); inventories.put(virtualInventory.getUuid(), virtualInventory);
file.delete();
} else if (file.getName().endsWith(".vi2")) {
try {
FileInputStream in = new FileInputStream(file);
VirtualInventory virtualInventory = deserializeInventory(in);
inventories.put(virtualInventory.getUuid(), virtualInventory);
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}); });
} }
} }
@ -91,9 +105,10 @@ public class VirtualInventoryManager {
inventories.values().forEach(virtualInventory -> { inventories.values().forEach(virtualInventory -> {
try { try {
File file = getSaveFile(virtualInventory); File file = getSaveFile(virtualInventory);
YamlConfiguration config = new YamlConfiguration(); FileOutputStream out = new FileOutputStream(file);
config.set("vi", virtualInventory); serializeInventory(virtualInventory, out);
config.save(file); out.flush();
out.close();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -101,7 +116,53 @@ public class VirtualInventoryManager {
} }
private File getSaveFile(VirtualInventory virtualInventory) { private File getSaveFile(VirtualInventory virtualInventory) {
return new File(SAVE_DIR, virtualInventory.getUuid() + ".vi"); return new File(SAVE_DIR, virtualInventory.getUuid() + ".vi2");
}
public void serializeInventory(VirtualInventory vi, OutputStream out) {
try {
DataOutputStream dos = new DataOutputStream(out);
UUID uuid = vi.getUuid();
dos.writeLong(uuid.getMostSignificantBits());
dos.writeLong(uuid.getLeastSignificantBits());
DataUtils.writeByteArray(dos, DataUtils.toByteArray(vi.getStackSizes()));
byte[][] items = Arrays.stream(vi.getItems()).map(itemStack -> {
if (itemStack != null) {
return InventoryAccess.getItemUtils().serializeItemStack(itemStack, true);
} else return new byte[0];
}
).toArray(byte[][]::new);
DataUtils.write2DByteArray(dos, items);
dos.flush();
} catch (
IOException e) {
e.printStackTrace();
}
}
public VirtualInventory deserializeInventory(InputStream in) {
try {
DataInputStream din = new DataInputStream(in);
UUID uuid = new UUID(din.readLong(), din.readLong());
int[] stackSizes = DataUtils.toIntArray(DataUtils.readByteArray(din));
ItemStack[] items = Arrays.stream(DataUtils.read2DByteArray(din)).map(data -> {
if (data.length != 0) {
return InventoryAccess.getItemUtils().deserializeItemStack(data, true);
} else return null;
}
).toArray(ItemStack[]::new);
return new VirtualInventory(uuid, stackSizes.length, items, stackSizes);
} catch (IOException e) {
e.printStackTrace();
}
return null;
} }
} }

@ -0,0 +1,75 @@
package de.studiocode.inventoryaccess.v1_14_R1.util;
import de.studiocode.inventoryaccess.api.abstraction.util.ItemUtils;
import de.studiocode.inventoryaccess.api.version.ReflectionUtils;
import net.minecraft.server.v1_14_R1.ItemStack;
import net.minecraft.server.v1_14_R1.NBTCompressedStreamTools;
import net.minecraft.server.v1_14_R1.NBTTagCompound;
import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftItemStack;
import java.io.*;
import java.lang.reflect.Field;
public class ItemUtilsImpl implements ItemUtils {
private static final Field CRAFT_ITEM_STACK_HANDLE_FIELD = ReflectionUtils.getField(CraftItemStack.class, true, "handle");
@Override
public byte[] serializeItemStack(org.bukkit.inventory.ItemStack itemStack, boolean compressed) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
serializeItemStack(itemStack, out, compressed);
return out.toByteArray();
}
@Override
public void serializeItemStack(org.bukkit.inventory.ItemStack itemStack, OutputStream out, boolean compressed) {
try {
ItemStack nmsStack;
if (itemStack instanceof CraftItemStack)
nmsStack = (ItemStack) CRAFT_ITEM_STACK_HANDLE_FIELD.get(itemStack);
else nmsStack = CraftItemStack.asNMSCopy(itemStack);
NBTTagCompound nbt = nmsStack.save(new NBTTagCompound());
if (compressed) {
NBTCompressedStreamTools.a(nbt, out);
} else {
DataOutputStream dataOut = new DataOutputStream(out);
NBTCompressedStreamTools.a(nbt, (DataOutput) dataOut);
}
out.flush();
} catch (IllegalAccessException | IOException e) {
e.printStackTrace();
}
}
@Override
public org.bukkit.inventory.ItemStack deserializeItemStack(byte[] data, boolean compressed) {
ByteArrayInputStream in = new ByteArrayInputStream(data);
return deserializeItemStack(in, compressed);
}
@Override
public org.bukkit.inventory.ItemStack deserializeItemStack(InputStream in, boolean compressed) {
try {
NBTTagCompound nbt;
if (compressed) {
nbt = NBTCompressedStreamTools.a(in);
} else {
DataInputStream dataIn = new DataInputStream(in);
nbt = NBTCompressedStreamTools.a(dataIn);
}
ItemStack itemStack = ItemStack.a(nbt);
return CraftItemStack.asCraftMirror(itemStack);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}

@ -0,0 +1,75 @@
package de.studiocode.inventoryaccess.v1_15_R1.util;
import de.studiocode.inventoryaccess.api.abstraction.util.ItemUtils;
import de.studiocode.inventoryaccess.api.version.ReflectionUtils;
import net.minecraft.server.v1_15_R1.ItemStack;
import net.minecraft.server.v1_15_R1.NBTCompressedStreamTools;
import net.minecraft.server.v1_15_R1.NBTTagCompound;
import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
import java.io.*;
import java.lang.reflect.Field;
public class ItemUtilsImpl implements ItemUtils {
private static final Field CRAFT_ITEM_STACK_HANDLE_FIELD = ReflectionUtils.getField(CraftItemStack.class, true, "handle");
@Override
public byte[] serializeItemStack(org.bukkit.inventory.ItemStack itemStack, boolean compressed) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
serializeItemStack(itemStack, out, compressed);
return out.toByteArray();
}
@Override
public void serializeItemStack(org.bukkit.inventory.ItemStack itemStack, OutputStream out, boolean compressed) {
try {
ItemStack nmsStack;
if (itemStack instanceof CraftItemStack)
nmsStack = (ItemStack) CRAFT_ITEM_STACK_HANDLE_FIELD.get(itemStack);
else nmsStack = CraftItemStack.asNMSCopy(itemStack);
NBTTagCompound nbt = nmsStack.save(new NBTTagCompound());
if (compressed) {
NBTCompressedStreamTools.a(nbt, out);
} else {
DataOutputStream dataOut = new DataOutputStream(out);
NBTCompressedStreamTools.a(nbt, (DataOutput) dataOut);
}
out.flush();
} catch (IllegalAccessException | IOException e) {
e.printStackTrace();
}
}
@Override
public org.bukkit.inventory.ItemStack deserializeItemStack(byte[] data, boolean compressed) {
ByteArrayInputStream in = new ByteArrayInputStream(data);
return deserializeItemStack(in, compressed);
}
@Override
public org.bukkit.inventory.ItemStack deserializeItemStack(InputStream in, boolean compressed) {
try {
NBTTagCompound nbt;
if (compressed) {
nbt = NBTCompressedStreamTools.a(in);
} else {
DataInputStream dataIn = new DataInputStream(in);
nbt = NBTCompressedStreamTools.a(dataIn);
}
ItemStack itemStack = ItemStack.a(nbt);
return CraftItemStack.asCraftMirror(itemStack);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}

@ -0,0 +1,75 @@
package de.studiocode.inventoryaccess.v1_16_R1.util;
import de.studiocode.inventoryaccess.api.abstraction.util.ItemUtils;
import de.studiocode.inventoryaccess.api.version.ReflectionUtils;
import net.minecraft.server.v1_16_R1.ItemStack;
import net.minecraft.server.v1_16_R1.NBTCompressedStreamTools;
import net.minecraft.server.v1_16_R1.NBTTagCompound;
import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
import java.io.*;
import java.lang.reflect.Field;
public class ItemUtilsImpl implements ItemUtils {
private static final Field CRAFT_ITEM_STACK_HANDLE_FIELD = ReflectionUtils.getField(CraftItemStack.class, true, "handle");
@Override
public byte[] serializeItemStack(org.bukkit.inventory.ItemStack itemStack, boolean compressed) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
serializeItemStack(itemStack, out, compressed);
return out.toByteArray();
}
@Override
public void serializeItemStack(org.bukkit.inventory.ItemStack itemStack, OutputStream out, boolean compressed) {
try {
ItemStack nmsStack;
if (itemStack instanceof CraftItemStack)
nmsStack = (ItemStack) CRAFT_ITEM_STACK_HANDLE_FIELD.get(itemStack);
else nmsStack = CraftItemStack.asNMSCopy(itemStack);
NBTTagCompound nbt = nmsStack.save(new NBTTagCompound());
if (compressed) {
NBTCompressedStreamTools.a(nbt, out);
} else {
DataOutputStream dataOut = new DataOutputStream(out);
NBTCompressedStreamTools.a(nbt, (DataOutput) dataOut);
}
out.flush();
} catch (IllegalAccessException | IOException e) {
e.printStackTrace();
}
}
@Override
public org.bukkit.inventory.ItemStack deserializeItemStack(byte[] data, boolean compressed) {
ByteArrayInputStream in = new ByteArrayInputStream(data);
return deserializeItemStack(in, compressed);
}
@Override
public org.bukkit.inventory.ItemStack deserializeItemStack(InputStream in, boolean compressed) {
try {
NBTTagCompound nbt;
if (compressed) {
nbt = NBTCompressedStreamTools.a(in);
} else {
DataInputStream dataIn = new DataInputStream(in);
nbt = NBTCompressedStreamTools.a(dataIn);
}
ItemStack itemStack = ItemStack.a(nbt);
return CraftItemStack.asCraftMirror(itemStack);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}

@ -0,0 +1,75 @@
package de.studiocode.inventoryaccess.v1_16_R2.util;
import de.studiocode.inventoryaccess.api.abstraction.util.ItemUtils;
import de.studiocode.inventoryaccess.api.version.ReflectionUtils;
import net.minecraft.server.v1_16_R2.ItemStack;
import net.minecraft.server.v1_16_R2.NBTCompressedStreamTools;
import net.minecraft.server.v1_16_R2.NBTTagCompound;
import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftItemStack;
import java.io.*;
import java.lang.reflect.Field;
public class ItemUtilsImpl implements ItemUtils {
private static final Field CRAFT_ITEM_STACK_HANDLE_FIELD = ReflectionUtils.getField(CraftItemStack.class, true, "handle");
@Override
public byte[] serializeItemStack(org.bukkit.inventory.ItemStack itemStack, boolean compressed) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
serializeItemStack(itemStack, out, compressed);
return out.toByteArray();
}
@Override
public void serializeItemStack(org.bukkit.inventory.ItemStack itemStack, OutputStream out, boolean compressed) {
try {
ItemStack nmsStack;
if (itemStack instanceof CraftItemStack)
nmsStack = (ItemStack) CRAFT_ITEM_STACK_HANDLE_FIELD.get(itemStack);
else nmsStack = CraftItemStack.asNMSCopy(itemStack);
NBTTagCompound nbt = nmsStack.save(new NBTTagCompound());
if (compressed) {
NBTCompressedStreamTools.a(nbt, out);
} else {
DataOutputStream dataOut = new DataOutputStream(out);
NBTCompressedStreamTools.a(nbt, (DataOutput) dataOut);
}
out.flush();
} catch (IllegalAccessException | IOException e) {
e.printStackTrace();
}
}
@Override
public org.bukkit.inventory.ItemStack deserializeItemStack(byte[] data, boolean compressed) {
ByteArrayInputStream in = new ByteArrayInputStream(data);
return deserializeItemStack(in, compressed);
}
@Override
public org.bukkit.inventory.ItemStack deserializeItemStack(InputStream in, boolean compressed) {
try {
NBTTagCompound nbt;
if (compressed) {
nbt = NBTCompressedStreamTools.a(in);
} else {
DataInputStream dataIn = new DataInputStream(in);
nbt = NBTCompressedStreamTools.a((DataInput) dataIn);
}
ItemStack itemStack = ItemStack.a(nbt);
return CraftItemStack.asCraftMirror(itemStack);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}

@ -0,0 +1,75 @@
package de.studiocode.inventoryaccess.v1_16_R3.util;
import de.studiocode.inventoryaccess.api.abstraction.util.ItemUtils;
import de.studiocode.inventoryaccess.api.version.ReflectionUtils;
import net.minecraft.server.v1_16_R3.ItemStack;
import net.minecraft.server.v1_16_R3.NBTCompressedStreamTools;
import net.minecraft.server.v1_16_R3.NBTTagCompound;
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
import java.io.*;
import java.lang.reflect.Field;
public class ItemUtilsImpl implements ItemUtils {
private static final Field CRAFT_ITEM_STACK_HANDLE_FIELD = ReflectionUtils.getField(CraftItemStack.class, true, "handle");
@Override
public byte[] serializeItemStack(org.bukkit.inventory.ItemStack itemStack, boolean compressed) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
serializeItemStack(itemStack, out, compressed);
return out.toByteArray();
}
@Override
public void serializeItemStack(org.bukkit.inventory.ItemStack itemStack, OutputStream out, boolean compressed) {
try {
ItemStack nmsStack;
if (itemStack instanceof CraftItemStack)
nmsStack = (ItemStack) CRAFT_ITEM_STACK_HANDLE_FIELD.get(itemStack);
else nmsStack = CraftItemStack.asNMSCopy(itemStack);
NBTTagCompound nbt = nmsStack.save(new NBTTagCompound());
if (compressed) {
NBTCompressedStreamTools.a(nbt, out);
} else {
DataOutputStream dataOut = new DataOutputStream(out);
NBTCompressedStreamTools.a(nbt, (DataOutput) dataOut);
}
out.flush();
} catch (IllegalAccessException | IOException e) {
e.printStackTrace();
}
}
@Override
public org.bukkit.inventory.ItemStack deserializeItemStack(byte[] data, boolean compressed) {
ByteArrayInputStream in = new ByteArrayInputStream(data);
return deserializeItemStack(in, compressed);
}
@Override
public org.bukkit.inventory.ItemStack deserializeItemStack(InputStream in, boolean compressed) {
try {
NBTTagCompound nbt;
if (compressed) {
nbt = NBTCompressedStreamTools.a(in);
} else {
DataInputStream dataIn = new DataInputStream(in);
nbt = NBTCompressedStreamTools.a((DataInput) dataIn);
}
ItemStack itemStack = ItemStack.a(nbt);
return CraftItemStack.asCraftMirror(itemStack);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}

@ -0,0 +1,75 @@
package de.studiocode.inventoryaccess.v1_17_R1.util;
import de.studiocode.inventoryaccess.api.abstraction.util.ItemUtils;
import de.studiocode.inventoryaccess.api.version.ReflectionUtils;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtIo;
import net.minecraft.world.item.ItemStack;
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack;
import java.io.*;
import java.lang.reflect.Field;
public class ItemUtilsImpl implements ItemUtils {
private static final Field CRAFT_ITEM_STACK_HANDLE_FIELD = ReflectionUtils.getField(CraftItemStack.class, true, "handle");
@Override
public byte[] serializeItemStack(org.bukkit.inventory.ItemStack itemStack, boolean compressed) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
serializeItemStack(itemStack, out, compressed);
return out.toByteArray();
}
@Override
public void serializeItemStack(org.bukkit.inventory.ItemStack itemStack, OutputStream outputStream, boolean compressed) {
try {
ItemStack nmsStack;
if (itemStack instanceof CraftItemStack)
nmsStack = (ItemStack) CRAFT_ITEM_STACK_HANDLE_FIELD.get(itemStack);
else nmsStack = CraftItemStack.asNMSCopy(itemStack);
CompoundTag nbt = nmsStack.save(new CompoundTag());
if (compressed) {
NbtIo.writeCompressed(nbt, outputStream);
} else {
DataOutputStream dataOut = new DataOutputStream(outputStream);
NbtIo.write(nbt, dataOut);
}
outputStream.flush();
} catch (IllegalAccessException | IOException e) {
e.printStackTrace();
}
}
@Override
public org.bukkit.inventory.ItemStack deserializeItemStack(byte[] data, boolean compressed) {
ByteArrayInputStream in = new ByteArrayInputStream(data);
return deserializeItemStack(in, compressed);
}
@Override
public org.bukkit.inventory.ItemStack deserializeItemStack(InputStream inputStream, boolean compressed) {
try {
CompoundTag nbt;
if (compressed) {
nbt = NbtIo.readCompressed(inputStream);
} else {
DataInputStream dataIn = new DataInputStream(inputStream);
nbt = NbtIo.read(dataIn);
}
ItemStack itemStack = ItemStack.of(nbt);
return CraftItemStack.asCraftMirror(itemStack);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}

@ -0,0 +1,50 @@
package de.studiocode.inventoryaccess.api.abstraction.util;
import org.bukkit.inventory.ItemStack;
import java.io.InputStream;
import java.io.OutputStream;
public interface ItemUtils {
/**
* Serializes an {@link ItemStack} to a byte[]
*
* @param itemStack The {@link ItemStack} to serialize
* @param compressed If the data should be compressed
* @return The serialized data
* @see #deserializeItemStack(byte[], boolean)
*/
byte[] serializeItemStack(ItemStack itemStack, boolean compressed);
/**
* Serializes an {@link ItemStack} to a byte[]
*
* @param itemStack The {@link ItemStack} to serialize
* @param outputStream The {@link OutputStream} to write the serialized data to
* @param compressed If the data should be compressed
* @see #deserializeItemStack(InputStream, boolean)
*/
void serializeItemStack(ItemStack itemStack, OutputStream outputStream, boolean compressed);
/**
* Deserializes an {@link ItemStack} from a byte[]
*
* @param data The data to deserialize
* @param compressed If the data is compressed
* @return The {@link ItemStack}
* @see #serializeItemStack(ItemStack, boolean)
*/
ItemStack deserializeItemStack(byte[] data, boolean compressed);
/**
* Deserializes an {@link ItemStack} from a byte[]
*
* @param inputStream The {@link InputStream} to read the serialized data from
* @param compressed If the data is compressed
* @return The {@link ItemStack}
* @see #serializeItemStack(ItemStack, OutputStream, boolean)
*/
ItemStack deserializeItemStack(InputStream inputStream, boolean compressed);
}

@ -2,6 +2,7 @@ package de.studiocode.inventoryaccess.api.version;
import de.studiocode.inventoryaccess.api.abstraction.inventory.AnvilInventory; import de.studiocode.inventoryaccess.api.abstraction.inventory.AnvilInventory;
import de.studiocode.inventoryaccess.api.abstraction.util.InventoryUtils; import de.studiocode.inventoryaccess.api.abstraction.util.InventoryUtils;
import de.studiocode.inventoryaccess.api.abstraction.util.ItemUtils;
import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.BaseComponent;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -11,12 +12,14 @@ import java.util.function.Consumer;
public class InventoryAccess { public class InventoryAccess {
private static final Class<InventoryUtils> INVENTORY_UTILS_CLASS = ReflectionUtils.getImplClass("util.InventoryUtilsImpl"); private static final Class<InventoryUtils> INVENTORY_UTILS_CLASS = ReflectionUtils.getImplClass("util.InventoryUtilsImpl");
private static final Class<ItemUtils> ITEM_UTILS_CLASS = ReflectionUtils.getImplClass("util.ItemUtilsImpl");
private static final Class<AnvilInventory> ANVIL_INVENTORY_CLASS = ReflectionUtils.getImplClass("inventory.AnvilInventoryImpl"); private static final Class<AnvilInventory> ANVIL_INVENTORY_CLASS = ReflectionUtils.getImplClass("inventory.AnvilInventoryImpl");
private static final Constructor<AnvilInventory> ANVIL_INVENTORY_CONSTRUCTOR private static final Constructor<AnvilInventory> ANVIL_INVENTORY_CONSTRUCTOR
= ReflectionUtils.getConstructor(ANVIL_INVENTORY_CLASS, Player.class, BaseComponent[].class, Consumer.class); = ReflectionUtils.getConstructor(ANVIL_INVENTORY_CLASS, Player.class, BaseComponent[].class, Consumer.class);
private static final InventoryUtils INVENTORY_UTILS = ReflectionUtils.constructEmpty(INVENTORY_UTILS_CLASS); private static final InventoryUtils INVENTORY_UTILS = ReflectionUtils.constructEmpty(INVENTORY_UTILS_CLASS);
private static final ItemUtils ITEM_UTILS = ReflectionUtils.constructEmpty(ITEM_UTILS_CLASS);
/** /**
* Gets the {@link InventoryUtils} * Gets the {@link InventoryUtils}
@ -27,6 +30,15 @@ public class InventoryAccess {
return INVENTORY_UTILS; return INVENTORY_UTILS;
} }
/**
* Gets the {@link ItemUtils}
*
* @return The {@link ItemUtils}
*/
public static ItemUtils getItemUtils() {
return ITEM_UTILS;
}
/** /**
* Creates a new {@link AnvilInventory}. * Creates a new {@link AnvilInventory}.
* *