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

Minecraft 1.20.2 Spigot插件问题:掉落物品触地未爆炸

问题分析与解决方案

核心问题点

  1. 延迟任务执行时机错误:你使用scheduleSyncDelayedTask时未指定延迟tick数,默认会立刻执行,此时物品刚被玩家掉落,还处于初始位置,未开始下落,自然无法检测到落地状态。
  2. 循环逻辑完全错误:while循环内每次将location重置为物品的初始位置,导致代码反复检查初始位置下方的方块,完全没有跟踪物品的实时位置,甚至可能陷入死循环。
  3. 落地判断逻辑不合理:手动循环检测下方方块的方式不符合Minecraft的物理机制,物品可能因滑行、碰撞等改变位置,这种方式无法准确判断物品是否真的落地。

修正后的代码

使用EntityTickEvent监听物品实体的每tick状态,通过Minecraft内置的isOnGround()方法准确判断物品是否落地:

import org.bukkit.entity.EntityType;
import org.bukkit.entity.Item;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityTickEvent;
import org.bukkit.inventory.ItemStack;

public class ExplosiveDropListener implements Listener {

    @EventHandler
    public void onItemTick(EntityTickEvent e) {
        // 过滤非物品实体
        if (!(e.getEntity() instanceof Item item)) {
            return;
        }

        ItemStack droppedItem = item.getItemStack();
        // 跳过无Meta的物品
        if (!droppedItem.hasItemMeta()) {
            return;
        }

        // 判断是否为目标不稳定TNT(建议后续改用NBT标签替代DisplayName比较,避免颜色/格式问题)
        if (!droppedItem.getItemMeta().getDisplayName().equals(ItemControl.unstable_tnt.getItemMeta().getDisplayName())) {
            return;
        }

        // 检查物品是否落地
        if (item.isOnGround()) {
            // 移除物品实体,避免重复触发爆炸
            item.remove();

            Location explodeLoc = item.getLocation();
            if (explodeLoc.getWorld() == null) {
                return;
            }

            // 生成2个瞬爆TNT
            for (int i = 0; i < 2; i++) {
                TNTPrimed tnt = (TNTPrimed) explodeLoc.getWorld().spawnEntity(explodeLoc, EntityType.PRIMED_TNT);
                tnt.setFuseTicks(0);
            }
        }
    }
}

额外优化建议

  • 替换DisplayName判断方式:用DisplayName区分物品容易因颜色代码、客户端显示设置出现误差,建议给目标物品添加自定义NBT标签,比如:
    // 给不稳定TNT添加NBT标签
    ItemStack unstableTnt = new ItemStack(Material.TNT);
    ItemMeta meta = unstableTnt.getItemMeta();
    PersistentDataContainer pdc = meta.getPersistentDataContainer();
    NamespacedKey key = new NamespacedKey(yourPluginInstance, "unstable_tnt");
    pdc.set(key, PersistentDataType.BOOLEAN, true);
    unstableTnt.setItemMeta(meta);
    
    然后在判断时读取NBT:
    NamespacedKey key = new NamespacedKey(yourPluginInstance, "unstable_tnt");
    if (!droppedItem.getItemMeta().getPersistentDataContainer().has(key, PersistentDataType.BOOLEAN)) {
        return;
    }
    
  • 避免重复触发:物品落地后立刻调用item.remove(),防止同一物品多次触发爆炸逻辑。

内容的提问来源于stack exchange,提问作者知識日常 Know Scratcher

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 07:20:06