You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 02:15:05