diff --git a/src/main/java/de/epiceric/shopchest/listeners/ShopInteractListener.java b/src/main/java/de/epiceric/shopchest/listeners/ShopInteractListener.java index e5c1958..5e7575f 100644 --- a/src/main/java/de/epiceric/shopchest/listeners/ShopInteractListener.java +++ b/src/main/java/de/epiceric/shopchest/listeners/ShopInteractListener.java @@ -660,7 +660,7 @@ public class ShopInteractListener implements Listener { double newPrice = (shop.getSellPrice() / product.getAmount()) * newAmount; - if (freeSpace >= product.getAmount() || (config.auto_calculate_item_amount && freeSpace >= newAmount)) { + if (freeSpace >= product.getAmount() || (config.auto_calculate_item_amount && freeSpace >= newAmount) || shop.getShopType() == ShopType.ADMIN) { plugin.debug("Chest has enough inventory space for " + freeSpace + " items (#" + shop.getID() + ")"); ItemStack newProduct = new ItemStack(product); @@ -775,7 +775,7 @@ public class ShopInteractListener implements Listener { while (added < amount) { ItemStack item = inventory.getItem(slot); - if (item != null) { + if (item != null && item.getType() != Material.AIR) { if (Utils.isItemSimilar(item, itemStack, false)) { if (item.getAmount() != item.getMaxStackSize()) { ItemStack newItemStack = new ItemStack(item); @@ -833,7 +833,7 @@ public class ShopInteractListener implements Listener { while (removed < amount) { ItemStack item = inventory.getItem(slot); - if (item != null) { + if (item != null && item.getType() != Material.AIR) { if (Utils.isItemSimilar(item, itemStack, false)) { if (item.getAmount() > 0) { int newAmount = item.getAmount() - 1; diff --git a/src/main/java/de/epiceric/shopchest/nms/CustomBookMeta.java b/src/main/java/de/epiceric/shopchest/nms/CustomBookMeta.java new file mode 100644 index 0000000..e12f2bd --- /dev/null +++ b/src/main/java/de/epiceric/shopchest/nms/CustomBookMeta.java @@ -0,0 +1,61 @@ +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; + +// For versions below 1.9.4, since Bukkit's BookMeta +// didn't have generations in those versions + +public class CustomBookMeta { + + public enum Generation { + ORIGINAL, + COPY_OF_ORIGINAL, + COPY_OF_COPY, + TATTERED + } + + public static Generation getGeneration(ItemStack book) { + try { + Class craftItemStackClass = Utils.getCraftClass("inventory.CraftItemStack"); + + if (craftItemStackClass == null) { + ShopChest.getInstance().debug("Failed to get NBTGeneration: Could not find CraftItemStack class"); + return null; + } + + Object nmsStack = craftItemStackClass.getMethod("asNMSCopy", ItemStack.class).invoke(null, book); + + Object nbtTagCompound = nmsStack.getClass().getMethod("getTag").invoke(nmsStack); + if (nbtTagCompound == null) { + ShopChest.getInstance().debug("Failed to get NBTGeneration: getTag returned null"); + return null; + } + + Object generationObject = nbtTagCompound.getClass().getMethod("getInt", String.class).invoke(nbtTagCompound, "generation"); + if (generationObject == null) { + ShopChest.getInstance().debug("Failed to get NBTGeneration: getInt returned null"); + return null; + } + + if (generationObject instanceof Integer) { + int generation = (Integer) generationObject; + + if (generation > 3) generation = 3; + + return Generation.values()[generation]; + } + + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + ShopChest.getInstance().getLogger().severe("Failed to get NBTEntityID with reflection"); + ShopChest.getInstance().debug("Failed to get NBTEntityID with reflection"); + ShopChest.getInstance().debug(e); + } + + return null; + } + +} diff --git a/src/main/java/de/epiceric/shopchest/utils/Utils.java b/src/main/java/de/epiceric/shopchest/utils/Utils.java index a59cc29..f588f31 100644 --- a/src/main/java/de/epiceric/shopchest/utils/Utils.java +++ b/src/main/java/de/epiceric/shopchest/utils/Utils.java @@ -1,6 +1,7 @@ package de.epiceric.shopchest.utils; import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.nms.CustomBookMeta; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.configuration.InvalidConfigurationException; @@ -11,6 +12,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import org.bukkit.inventory.meta.*; import org.bukkit.material.MaterialData; +import org.bukkit.potion.Potion; import javax.xml.bind.DatatypeConverter; import java.lang.reflect.InvocationTargetException; @@ -72,7 +74,7 @@ public class Utils { similar = (bannerMeta1.getBaseColor() == bannerMeta2.getBaseColor()); similar &= (bannerMeta1.getPatterns().equals(bannerMeta2.getPatterns())); - } else if (itemMeta1 instanceof BlockStateMeta) { + } else if (!getServerVersion().equals("v1_8_R1") && itemMeta1 instanceof BlockStateMeta) { BlockStateMeta bsMeta1 = (BlockStateMeta) itemMeta1; BlockStateMeta bsMeta2 = (BlockStateMeta) itemMeta2; @@ -88,7 +90,21 @@ public class Utils { if (bookMeta1.hasTitle()) similar &= (bookMeta1.getTitle().equals(bookMeta2.getTitle())); if (bookMeta1.hasPages()) similar &= (bookMeta1.getPages().equals(bookMeta2.getPages())); - similar &= (bookMeta1.getGeneration() == bookMeta2.getGeneration()); + if ((getMajorVersion() == 9 && getRevision() == 1) || getMajorVersion() == 8) { + CustomBookMeta.Generation generation1 = CustomBookMeta.getGeneration(itemStack1); + CustomBookMeta.Generation generation2 = CustomBookMeta.getGeneration(itemStack2); + + if (generation1 == null) generation1 = CustomBookMeta.Generation.ORIGINAL; + if (generation2 == null) generation2 = CustomBookMeta.Generation.ORIGINAL; + + similar &= (generation1 == generation2); + + } else if (getMajorVersion() >= 10) { + if (!bookMeta1.hasGeneration()) bookMeta1.setGeneration(BookMeta.Generation.ORIGINAL); + if (!bookMeta2.hasGeneration()) bookMeta2.setGeneration(BookMeta.Generation.ORIGINAL); + + similar &= (bookMeta1.getGeneration() == bookMeta2.getGeneration()); + } } else if (itemMeta1 instanceof EnchantmentStorageMeta) { EnchantmentStorageMeta esMeta1 = (EnchantmentStorageMeta) itemMeta1; @@ -124,7 +140,17 @@ public class Utils { PotionMeta potionMeta2 = (PotionMeta) itemMeta2; if (potionMeta1.hasCustomEffects()) similar = (potionMeta1.getCustomEffects().equals(potionMeta2.getCustomEffects())); - similar &= (potionMeta1.getBasePotionData().equals(potionMeta2.getBasePotionData())); + + if (getMajorVersion() >= 9) { + similar &= (potionMeta1.getBasePotionData().equals(potionMeta2.getBasePotionData())); + } else { + Potion potion1 = Potion.fromItemStack(itemStack1); + Potion potion2 = Potion.fromItemStack(itemStack2); + + similar &= (potion1.getType() == potion2.getType()); + similar &= (potion1.getEffects().equals(potion2.getEffects())); + similar &= (potion1.getLevel() == potion2.getLevel()); + } } else if (itemMeta1 instanceof SkullMeta) { SkullMeta skullMeta1 = (SkullMeta) itemMeta1; @@ -185,7 +211,7 @@ public class Utils { if (inventory instanceof PlayerInventory) { for (int i = 0; i < 36; i++) { ItemStack item = inventory.getItem(i); - if (item == null) { + if (item == null || item.getType() == Material.AIR) { slotFree.put(i, itemStack.getMaxStackSize()); } else { if (isItemSimilar(item, itemStack, false)) { @@ -198,7 +224,7 @@ public class Utils { if (getMajorVersion() >= 9) { ItemStack item = inventory.getItem(40); - if (item == null) { + if (item == null || item.getType() == Material.AIR) { slotFree.put(40, itemStack.getMaxStackSize()); } else { if (isItemSimilar(item, itemStack, false)) { @@ -211,7 +237,7 @@ public class Utils { } else { for (int i = 0; i < inventory.getSize(); i++) { ItemStack item = inventory.getItem(i); - if (item == null) { + if (item == null || item.getType() == Material.AIR) { slotFree.put(i, itemStack.getMaxStackSize()); } else { if (isItemSimilar(item, itemStack, false)) { @@ -346,11 +372,18 @@ public class Utils { return packageName.substring(packageName.lastIndexOf('.') + 1); } + /** + * @return The revision of the current server version (e.g. 2 for v1_9_R2, 1 for v1_10_R1) + */ + public static int getRevision() { + return Integer.parseInt(getServerVersion().substring(getServerVersion().length() - 1)); + } + /** * @return The major version of the server (e.g. 9 for 1.9.2, 10 for 1.10) */ public static int getMajorVersion() { - return Integer.valueOf(getServerVersion().split("_")[1]); + return Integer.parseInt(getServerVersion().split("_")[1]); } /**