Minecraft 1.20.2 Spigot插件问题:掉落物品触地未爆炸
问题分析与解决方案
核心问题点
- 延迟任务执行时机错误:你使用
scheduleSyncDelayedTask时未指定延迟tick数,默认会立刻执行,此时物品刚被玩家掉落,还处于初始位置,未开始下落,自然无法检测到落地状态。 - 循环逻辑完全错误:
while循环内每次将location重置为物品的初始位置,导致代码反复检查初始位置下方的方块,完全没有跟踪物品的实时位置,甚至可能陷入死循环。 - 落地判断逻辑不合理:手动循环检测下方方块的方式不符合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标签,比如:
然后在判断时读取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);NamespacedKey key = new NamespacedKey(yourPluginInstance, "unstable_tnt"); if (!droppedItem.getItemMeta().getPersistentDataContainer().has(key, PersistentDataType.BOOLEAN)) { return; } - 避免重复触发:物品落地后立刻调用
item.remove(),防止同一物品多次触发爆炸逻辑。
内容的提问来源于stack exchange,提问作者知識日常 Know Scratcher
相关产品推荐
相关产品推荐

