如何延迟检测放置的方块是否存在并执行命令(Bukkit开发)
解决Bukkit延迟检测方块状态的问题
直接在事件监听方法中使用Thread.sleep()是错误的,这会阻塞服务器主线程——整个游戏在延迟期间会完全停止响应,玩家操作、方块破坏等逻辑都无法执行,所以延迟后检测到的必然是延迟前的方块状态。
正确的做法是使用Bukkit自带的调度器(Scheduler)来实现延迟任务,它能在不阻塞主线程的前提下,在指定时间后执行检测逻辑。以下是修改后的实现代码:
import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.scheduler.BukkitRunnable; public class BlockListener implements Listener { // 替换为你需要执行的命令 private final String targetCommand = "say 玩家放置的头颅已被移除"; @EventHandler public void onPlayerHeadPlace(BlockPlaceEvent e) { Material placedBlockType = e.getBlockPlaced().getType(); // 只处理玩家头颅类型的方块 if (placedBlockType != Material.PLAYER_HEAD && placedBlockType != Material.PLAYER_WALL_HEAD) { return; } // 保存方块的位置信息,避免原Block对象失效 World world = e.getBlockPlaced().getWorld(); int blockX = e.getBlockPlaced().getX(); int blockY = e.getBlockPlaced().getY(); int blockZ = e.getBlockPlaced().getZ(); // 延迟1秒(20游戏刻)执行检测任务 new BukkitRunnable() { @Override public void run() { Material currentBlockType = world.getBlockAt(blockX, blockY, blockZ).getType(); // 检测方块是否已被替换/移除 if (currentBlockType != Material.PLAYER_HEAD && currentBlockType != Material.PLAYER_WALL_HEAD) { Bukkit.dispatchCommand(Bukkit.getConsoleSender(), targetCommand); } } }.runTaskLater(你的插件主类实例, 20L); // 20刻=1秒,替换第一个参数为你的插件实例 } }
关键注意事项
- 必须替换代码中的
你的插件主类实例:可以用主类的静态获取方法(比如Main.getPlugin(Main.class)),Bukkit需要通过插件实例绑定任务,避免内存泄漏。 - 游戏刻与现实时间的对应:1秒=20游戏刻,如果你需要调整延迟时长,直接修改
runTaskLater的第二个参数即可(比如40L=2秒)。 - 如果需要在命令中关联玩家信息,可以提前保存玩家的UUID,在延迟任务中通过UUID获取玩家对象(注意处理玩家离线的情况)。
内容的提问来源于stack exchange,提问作者Larssie
相关产品推荐
相关产品推荐

