Fixed Shulker Boxes

Closes #53
This commit is contained in:
Eric 2017-01-02 17:50:46 +01:00
parent bedf207210
commit 222b553a8e
2 changed files with 135 additions and 0 deletions

View File

@ -0,0 +1,106 @@
package de.epiceric.shopchest.nms;
import de.epiceric.shopchest.ShopChest;
import de.epiceric.shopchest.utils.Utils;
import org.bukkit.inventory.ItemStack;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
public class ShulkerBoxMeta {
public static Map<Integer, ItemStack> getContents(ItemStack shulkerBox) {
try {
Class<?> craftItemStackClass = Utils.getCraftClass("inventory.CraftItemStack");
if (craftItemStackClass == null) {
ShopChest.getInstance().debug("Failed to get NBTContents: Could not find CraftItemStack class");
return null;
}
Object nmsStack = craftItemStackClass.getMethod("asNMSCopy", ItemStack.class).invoke(null, shulkerBox);
if (nmsStack == null) {
ShopChest.getInstance().debug("Failed to get NBTContents: asNMSCopy returned null");
return null;
}
Object hasTag = nmsStack.getClass().getMethod("hasTag").invoke(nmsStack);
if (hasTag == null || !(hasTag instanceof Boolean)) {
ShopChest.getInstance().debug("Failed to get NBTContents: hasTag returned null");
return null;
}
if (!(boolean) hasTag) {
ShopChest.getInstance().debug("Failed to get NBTContents: ItemStack has no tag");
return null;
}
Object nbtTagCompound = nmsStack.getClass().getMethod("getTag").invoke(nmsStack);
if (nbtTagCompound == null) {
ShopChest.getInstance().debug("Failed to get NBTContents: getTag returned null");
return null;
}
Object blockEntityTagObject = nbtTagCompound.getClass().getMethod("getCompound", String.class).invoke(nbtTagCompound, "BlockEntityTag");
if (blockEntityTagObject == null) {
ShopChest.getInstance().debug("Failed to get NBTContents: getCompound returned null");
return null;
}
Object itemsObject = blockEntityTagObject.getClass().getMethod("getList", String.class, int.class).invoke(blockEntityTagObject, "Items", 10);
if (itemsObject == null) {
ShopChest.getInstance().debug("Failed to get NBTContents: getList returned null");
return null;
}
Object sizeObject = itemsObject.getClass().getMethod("size").invoke(itemsObject);
if (sizeObject == null) {
ShopChest.getInstance().debug("Failed to get NBTContents: size returned null or not an integer");
return null;
}
int size = (Integer) sizeObject;
Map<Integer, ItemStack> contentSlots = new HashMap<>();
for (int i = 0; i < size; i++) {
Object itemTag = itemsObject.getClass().getMethod("get", int.class).invoke(itemsObject, i);
if (itemTag == null) {
ShopChest.getInstance().debug("Failed to get NBTContents: get returned null");
continue;
}
Object nmsStack2 = nmsStack.getClass().getConstructor(nbtTagCompound.getClass()).newInstance(itemTag);
if (nmsStack2 == null) {
ShopChest.getInstance().debug("Failed to get NBTContents: Could not instantiate ItemStack with compound");
continue;
}
Object slotObject = itemTag.getClass().getMethod("getInt", String.class).invoke(itemTag, "Slot");
if (slotObject == null || !(slotObject instanceof Integer)) {
ShopChest.getInstance().debug("Failed to get NBTContents: getInt returned null or not an integer");
continue;
}
Object itemStack = craftItemStackClass.getMethod("asBukkitCopy", nmsStack2.getClass()).invoke(null, nmsStack2);
if (itemStack == null || !(itemStack instanceof ItemStack)) {
ShopChest.getInstance().debug("Failed to get NBTContents: asBukkitCopy returned null or not an ItemStack");
continue;
}
contentSlots.put((Integer) slotObject, (ItemStack) itemStack);
}
return contentSlots;
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) {
ShopChest.getInstance().getLogger().severe("Failed to get NBTContents with reflection");
ShopChest.getInstance().debug("Failed to get NBTContents with reflection");
ShopChest.getInstance().debug(e);
}
return null;
}
}

View File

@ -1,7 +1,9 @@
package de.epiceric.shopchest.utils;
import com.google.common.collect.ImmutableList;
import de.epiceric.shopchest.ShopChest;
import de.epiceric.shopchest.nms.CustomBookMeta;
import de.epiceric.shopchest.nms.ShulkerBoxMeta;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.configuration.InvalidConfigurationException;
@ -19,9 +21,29 @@ import java.lang.reflect.InvocationTargetException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class Utils {
private static final ImmutableList<Material> SHULKER_BOX_MATERIALS = new ImmutableList.Builder<Material>()
.add(Material.BLACK_SHULKER_BOX)
.add(Material.BLUE_SHULKER_BOX)
.add(Material.BROWN_SHULKER_BOX)
.add(Material.CYAN_SHULKER_BOX)
.add(Material.GRAY_SHULKER_BOX)
.add(Material.GREEN_SHULKER_BOX)
.add(Material.LIGHT_BLUE_SHULKER_BOX)
.add(Material.LIME_SHULKER_BOX)
.add(Material.MAGENTA_SHULKER_BOX)
.add(Material.ORANGE_SHULKER_BOX)
.add(Material.PINK_SHULKER_BOX)
.add(Material.PURPLE_SHULKER_BOX)
.add(Material.RED_SHULKER_BOX)
.add(Material.SILVER_SHULKER_BOX)
.add(Material.WHITE_SHULKER_BOX)
.add(Material.YELLOW_SHULKER_BOX)
.build();
/**
* Check if two items are similar to each other
* @param itemStack1 The first item
@ -82,6 +104,13 @@ public class Utils {
if (bsMeta1.hasBlockState()) similar &= (bsMeta1.getBlockState().equals(bsMeta2.getBlockState()));
if (getMajorVersion() >= 11 && SHULKER_BOX_MATERIALS.contains(itemStack1.getType())) {
Map<Integer, ItemStack> contents1 = ShulkerBoxMeta.getContents(itemStack1);
Map<Integer, ItemStack> contents2 = ShulkerBoxMeta.getContents(itemStack2);
if (contents1 != null) similar &= contents1.equals(contents2);
}
} else if (itemMeta1 instanceof BookMeta) {
BookMeta bookMeta1 = (BookMeta) itemMeta1;
BookMeta bookMeta2 = (BookMeta) itemMeta2;