diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java index 4c2dc73f8..bf998a186 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java @@ -16,6 +16,7 @@ import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.loot.parameter.LootParameters; import net.momirealms.craftengine.core.plugin.config.ConfigManager; +import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.context.ContextHolder; import net.momirealms.craftengine.core.world.BlockPos; import net.momirealms.craftengine.core.world.CEWorld; @@ -120,8 +121,14 @@ public class BlockEventListener implements Listener { BukkitServerPlayer serverPlayer = plugin.adapt(player); Item itemInHand = serverPlayer.getItemInHand(InteractionHand.MAIN_HAND); + Key itemId; + if (itemInHand == null) { + itemId = Key.of("minecraft:air"); + } else { + itemId = itemInHand.id(); + } // do not drop if it's not the correct tool - if (!state.settings().isCorrectTool(itemInHand.id())) { + if (!state.settings().isCorrectTool(itemId)) { return; } // drop items 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..86e42bb67 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 @@ -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, matchingSlot, 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..d9dc9695e 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,13 @@ package net.momirealms.craftengine.bukkit.util; +import net.momirealms.craftengine.core.plugin.CraftEngine; 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 +16,19 @@ 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 = Reflections.method$CraftInventoryPlayer$getInventory + .invoke(inventory); + Object nmsInventory$items = Reflections.field$Inventory$items + .get(nmsInventory); + Object nmsItemStack = Reflections.method$CraftItemStack$asNMSMirror + .invoke(null, itemStack); + Reflections.method$NonNullList$set + .invoke(nmsInventory$items, slot, nmsItemStack); + } catch (InvocationTargetException | IllegalAccessException 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..f0ffe7c24 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 @@ -41,6 +41,7 @@ public class Reflections { } public static final Unsafe UNSAFE; + public static final String INVENTORY$ITEMS = VersionHelper.isMojmap() ? "items" : "i"; static { try { @@ -3881,4 +3882,45 @@ 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") + ) + ); + public static final Method method$CraftInventoryPlayer$getInventory = requireNonNull( + ReflectionUtils.getMethod( + clazz$CraftInventoryPlayer, + new String[]{ "getInventory" } + ) + ); + + public static final Field field$Inventory$items = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$Inventory, + INVENTORY$ITEMS + ) + ); + + public static final Class clazz$NonNullList = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("core.NonNullList") + ) + ); + + public static final Method method$NonNullList$set = requireNonNull( + ReflectionUtils.getMethod( + clazz$NonNullList, + Object.class, + int.class, + Object.class + ) + ); }