Plex-FAWE/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/util/ItemUtil.java

117 lines
4.4 KiB
Java

package com.boydti.fawe.bukkit.util;
import com.boydti.fawe.util.ReflectionUtils;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import org.bukkit.inventory.ItemStack;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import static com.google.gson.internal.$Gson$Preconditions.checkNotNull;
public class ItemUtil {
private final Method methodAsNMSCopy;
private final Method methodGetTag;
private final Method methodHasTag;
private final Method methodSetTag;
private final Method methodAsBukkitCopy;
private final Field fieldHandle;
private final BukkitImplAdapter adapter;
private SoftReference<Int2ObjectOpenHashMap<WeakReference<Tag>>> hashToNMSTag = new SoftReference<>(new Int2ObjectOpenHashMap<>());
public ItemUtil() throws Exception {
this.adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
checkNotNull(adapter);
Class<?> classCraftItemStack = BukkitReflectionUtils.getCbClass("inventory.CraftItemStack");
Class<?> classNMSItem = BukkitReflectionUtils.getNmsClass("ItemStack");
this.methodAsNMSCopy = ReflectionUtils.setAccessible(classCraftItemStack.getDeclaredMethod("asNMSCopy", ItemStack.class));
this.methodHasTag = ReflectionUtils.setAccessible(classNMSItem.getDeclaredMethod("hasTag"));
this.methodGetTag = ReflectionUtils.setAccessible(classNMSItem.getDeclaredMethod("getTag"));
this.fieldHandle = ReflectionUtils.setAccessible(classCraftItemStack.getDeclaredField("handle"));
Class<?> classNBTTagCompound = BukkitReflectionUtils.getNmsClass("NBTTagCompound");
this.methodSetTag = ReflectionUtils.setAccessible(classNMSItem.getDeclaredMethod("setTag", classNBTTagCompound));
this.methodAsBukkitCopy = ReflectionUtils.setAccessible(classCraftItemStack.getDeclaredMethod("asBukkitCopy", classNMSItem));
}
public Object getNMSItem(ItemStack item) {
try {
Object nmsItem = fieldHandle.get(item);
if (nmsItem == null) {
nmsItem = methodAsNMSCopy.invoke(null, item);
}
return nmsItem;
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
public CompoundTag getNBT(ItemStack item) {
try {
if (!item.hasItemMeta()) {
return null;
}
Object nmsItem = fieldHandle.get(item);
if (nmsItem == null) {
nmsItem = methodAsNMSCopy.invoke(null, item);
}
if (methodHasTag.invoke(nmsItem).equals(true)) {
Object nmsTag = methodGetTag.invoke(nmsItem);
if (nmsTag == null) {
return null;
}
Int2ObjectOpenHashMap<WeakReference<Tag>> map = hashToNMSTag.get();
if (map == null) {
map = new Int2ObjectOpenHashMap<>();
hashToNMSTag = new SoftReference<>(new Int2ObjectOpenHashMap<>(map));
}
WeakReference<Tag> nativeTagRef = map.get(nmsTag.hashCode());
if (nativeTagRef != null) {
Tag nativeTag = nativeTagRef.get();
if (nativeTag != null) {
return (CompoundTag) nativeTag;
}
}
Tag nativeTag = adapter.toNative(nmsTag);
map.put(nmsTag.hashCode(), new WeakReference<>(nativeTag));
return null;
}
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
public ItemStack setNBT(ItemStack item, CompoundTag tag) {
try {
Object nmsItem = fieldHandle.get(item);
boolean copy = false;
if (nmsItem == null) {
copy = true;
nmsItem = methodAsNMSCopy.invoke(null, item);
}
Object nmsTag = adapter.fromNative(tag);
methodSetTag.invoke(nmsItem, nmsTag);
if (copy) {
return (ItemStack) methodAsBukkitCopy.invoke(null, nmsItem);
}
return item;
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
}