如何在Bukkit事件中识别自定义ItemStack放置的箱子方块?
判断自定义箱子方块的两种实现方案
针对你在Minecraft 1.20.6插件开发中遇到的问题,以下是两种可靠的判断方案,根据你的自定义箱子实现方式选择:
方案一:给原版箱子添加自定义标记(适合复用原版箱子模型的场景)
如果你的自定义箱子基于原版Material.CHEST,通过自定义物品放置,核心思路是给放置后的箱子实体添加持久化数据标记,点击时读取该标记判断是否为自定义箱子。
点击判断代码
@EventHandler public static void onChestClick(PlayerInteractEvent e) { Player player = e.getPlayer(); Block block = e.getClickedBlock(); if (block != null && block.getType() == Material.CHEST) { // 获取箱子的实体数据容器 Chest chestEntity = (Chest) block.getState(); PersistentDataContainer dataContainer = chestEntity.getPersistentDataContainer(); // 定义你的插件专属标记键(替换成你的插件实例和自定义键名) NamespacedKey shopChestKey = new NamespacedKey(YourPlugin.getInstance(), "is_shop_chest"); // 检查标记是否存在且为true if (dataContainer.has(shopChestKey, PersistentDataType.BOOLEAN) && dataContainer.get(shopChestKey, PersistentDataType.BOOLEAN)) { player.sendMessage("Shop Chest Clicked"); e.setCancelled(true); // 取消原版箱子打开行为,避免冲突 } } }
配套:放置自定义箱子时添加标记
需要在玩家放置自定义箱子物品的事件中,给生成的箱子实体添加标记:
@EventHandler public static void onPlaceShopChest(PlayerInteractEvent e) { Player player = e.getPlayer(); ItemStack heldItem = player.getInventory().getItemInMainHand(); // 判断手持物品是否为你的自定义箱子物品(这里用持久化标记判断,也可以用自定义名称/lore) NamespacedKey itemKey = new NamespacedKey(YourPlugin.getInstance(), "shop_chest_item"); if (e.getAction() == Action.RIGHT_CLICK_BLOCK && heldItem.getType() == Material.CHEST && heldItem.getItemMeta().getPersistentDataContainer().has(itemKey, PersistentDataType.BOOLEAN)) { // 延迟1tick执行,确保方块已完成放置 Bukkit.getScheduler().runTaskLater(YourPlugin.getInstance(), () -> { Block placedBlock = e.getClickedBlock().getRelative(e.getBlockFace()); if (placedBlock.getType() == Material.CHEST) { Chest chestEntity = (Chest) placedBlock.getState(); PersistentDataContainer dataContainer = chestEntity.getPersistentDataContainer(); NamespacedKey blockKey = new NamespacedKey(YourPlugin.getInstance(), "is_shop_chest"); dataContainer.set(blockKey, PersistentDataType.BOOLEAN, true); chestEntity.update(); // 保存数据到方块 } }, 1L); } }
方案二:使用自定义方块类型(适合完全自定义的箱子)
如果你的插件注册了独立的自定义方块(继承ChestBlock),可以直接通过方块类型判断:
点击判断代码
// 假设你已注册自定义方块,对应的Material为SHOP_CHEST @EventHandler public static void onChestClick(PlayerInteractEvent e) { Player player = e.getPlayer(); Block block = e.getClickedBlock(); if (block != null && block.getType() == YourPlugin.getInstance().getShopChestMaterial()) { player.sendMessage("Shop Chest Clicked"); e.setCancelled(true); // 取消原版交互 } }
关键提示
- 无论哪种方案,都必须调用
e.setCancelled(true),否则会同时触发原版箱子界面和你的自定义背包。 - 使用
PersistentDataContainer而非直接修改NBT,是Bukkit官方推荐的自定义数据存储方式,能避免与其他插件的NBT冲突。
内容的提问来源于stack exchange,提问作者ZevDev
相关产品推荐
相关产品推荐

