diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index f6e4ed33d..51c2ed804 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -339,26 +339,26 @@ public class PacketConsumers { if (sameItemSlot < 9) { inventory.setHeldItemSlot(sameItemSlot); ItemStack previousItem = inventory.getItem(slot - 36); - BukkitCraftEngine.instance().scheduler().sync().runDelayed(() -> inventory.setItem(slot - 36, previousItem)); + BukkitCraftEngine.instance().scheduler().sync().runDelayed(() -> ItemUtils.setItem(inventory, slot - 36, previousItem)); } else { ItemStack sameItem = inventory.getItem(sameItemSlot); int finalSameItemSlot = sameItemSlot; BukkitCraftEngine.instance().scheduler().sync().runDelayed(() -> { - inventory.setItem(finalSameItemSlot, new ItemStack(Material.AIR)); - inventory.setItem(slot - 36, sameItem); + ItemUtils.setItem(inventory, finalSameItemSlot, new ItemStack(Material.AIR)); + ItemUtils.setItem(inventory, slot - 36, sameItem); }); } } else { if (item.getAmount() == 1) { if (ItemUtils.isEmpty(inventory.getItem(slot - 36))) { - BukkitCraftEngine.instance().scheduler().sync().runDelayed(() -> inventory.setItem(slot - 36, itemStack)); + BukkitCraftEngine.instance().scheduler().sync().runDelayed(() -> ItemUtils.setItem(inventory, slot - 36, itemStack)); return; } if (emptySlot != -1) { inventory.setHeldItemSlot(emptySlot); - inventory.setItem(emptySlot, itemStack); + ItemUtils.setItem(inventory, emptySlot, itemStack); } else { - BukkitCraftEngine.instance().scheduler().sync().runDelayed(() -> inventory.setItem(slot - 36, itemStack)); + BukkitCraftEngine.instance().scheduler().sync().runDelayed(() -> ItemUtils.setItem(inventory, slot - 36, itemStack)); } } } @@ -395,9 +395,9 @@ public class PacketConsumers { if (picked == null) return; inventory.setHeldItemSlot(targetSlot); ItemStack previous = inventory.getItem(targetSlot); - inventory.setItem(targetSlot, picked.clone()); + ItemUtils.setItem(inventory, targetSlot, picked.clone()); if (previous != null) { - inventory.setItem(matchingSlot, previous); + ItemUtils.setItem(inventory, targetSlot, previous); } else { picked.setAmount(0); } @@ -405,13 +405,13 @@ public class PacketConsumers { } else if (player.getGameMode() == GameMode.CREATIVE) { inventory.setHeldItemSlot(targetSlot); ItemStack previous = inventory.getItem(targetSlot); - inventory.setItem(targetSlot, itemStack); + ItemUtils.setItem(inventory, targetSlot, itemStack); if (previous != null) { for (int j = 1; j <= 3; j++) { for (int i = j * 9; i < j * 9 + 9; i++) { ItemStack itemInSlot = inventory.getItem(i); if (ItemUtils.isEmpty(itemInSlot)) { - inventory.setItem(i, previous); + ItemUtils.setItem(inventory, i, previous); return; } } @@ -448,9 +448,9 @@ public class PacketConsumers { if (picked == null) return; inventory.setHeldItemSlot(targetSlot); ItemStack previous = inventory.getItem(targetSlot); - inventory.setItem(targetSlot, picked.clone()); + ItemUtils.setItem(inventory, targetSlot, picked.clone()); if (previous != null) { - inventory.setItem(matchingSlot, previous); + ItemUtils.setItem(inventory, matchingSlot, previous); } else { picked.setAmount(0); } @@ -458,13 +458,13 @@ public class PacketConsumers { } else if (player.getGameMode() == GameMode.CREATIVE) { inventory.setHeldItemSlot(targetSlot); ItemStack previous = inventory.getItem(targetSlot); - inventory.setItem(targetSlot, itemStack); + ItemUtils.setItem(inventory, targetSlot, itemStack); if (previous != null) { for (int j = 1; j <= 3; j++) { for (int i = j * 9; i < j * 9 + 9; i++) { ItemStack itemInSlot = inventory.getItem(i); if (ItemUtils.isEmpty(itemInSlot)) { - inventory.setItem(i, previous); + ItemUtils.setItem(inventory, i, previous); return; } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ItemUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ItemUtils.java index c88a13ee5..a46fce973 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ItemUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ItemUtils.java @@ -1,9 +1,14 @@ package net.momirealms.craftengine.bukkit.util; +import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.util.VersionHelper; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; import org.jetbrains.annotations.Contract; +import java.lang.reflect.InvocationTargetException; + public class ItemUtils { @Contract("null -> true") @@ -12,4 +17,23 @@ public class ItemUtils { if (item.getType() == Material.AIR) return true; return item.getAmount() == 0; } + + public static void setItem(PlayerInventory inventory, int slot, ItemStack itemStack) { + try { + Object nmsInventory$getInventory = Reflections.clazz$CraftInventoryPlayer + .getMethod("getInventory").invoke(inventory); + Object nmsInventory$items = Reflections.clazz$Inventory + .getDeclaredField(VersionHelper.isMojmap() ? "items" : "i") + .get(nmsInventory$getInventory); + Object nmsItemStack = Reflections.clazz$CraftItemStack + .getMethod("asNMSCopy", ItemStack.class) + .invoke(null, itemStack); + nmsInventory$items.getClass() + .getMethod("set", int.class, Object.class) + .invoke(nmsInventory$items, slot, nmsItemStack); + } catch (InvocationTargetException | IllegalAccessException | + NoSuchMethodException | NoSuchFieldException e) { + CraftEngine.instance().logger().warn("Failed to set item", e); + } + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index 09e4c9847..815e606b3 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -3881,4 +3881,17 @@ public class Reflections { ReflectionUtils.getDeclaredField( clazz$RecipeManager, clazz$FeatureFlagSet, 0 ); + + public static final Class clazz$CraftInventoryPlayer = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleCBClass("inventory.CraftInventoryPlayer") + ) + ); + + public static final Class clazz$Inventory = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("world.entity.player.Inventory"), + BukkitReflectionUtils.assembleMCClass("world.entity.player.PlayerInventory") + ) + ); }