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

Bukkit Runnable使用求助:实现延迟获取玩家Y坐标差值

解决Bukkit Runnable延迟计算玩家Y坐标差的问题

我懂你现在的困扰——原代码里y1和y2是在同一帧获取的,差值自然永远是0,而且完全没用到Bukkit的任务调度来实现延迟逻辑。下面我给你一步步修改代码,同时把关键要点讲清楚:

核心问题分析

你的初始代码没有实现延迟1秒的逻辑,y1和y2是在PlayerMoveEvent触发的同一时刻获取的,所以计算出来的差值始终为0,这就是你看不到预期效果的原因。我们需要用Bukkit的Scheduler来调度一个延迟任务,在1秒后再获取玩家的Y坐标。

修改后的完整代码

import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;

import java.util.HashMap;
import java.util.UUID;

public class FlyE implements Listener {
    // 记录玩家上次触发任务的时间,避免PlayerMoveEvent频繁触发导致任务堆积
    private final HashMap<UUID, Long> cooldown = new HashMap<>();
    private final JavaPlugin plugin;

    // 构造方法,必须传入插件实例(Bukkit调度任务需要依赖它)
    public FlyE(JavaPlugin plugin) {
        this.plugin = plugin;
    }

    @EventHandler
    public void onPlayerMovement(PlayerMoveEvent e) {
        Player p = e.getPlayer();
        UUID playerId = p.getUniqueId();
        long currentTime = System.currentTimeMillis();

        // 加1秒冷却,避免每秒触发几十次任务占用服务器资源
        if (cooldown.containsKey(playerId) && currentTime - cooldown.get(playerId) < 1000) {
            return;
        }
        cooldown.put(playerId, currentTime);

        // 获取当前时刻的Y坐标
        double y1 = p.getLocation().getY();

        // 调度延迟任务:20刻 = 1秒(Bukkit默认每秒运行20游戏刻)
        new BukkitRunnable() {
            @Override
            public void run() {
                // 延迟后先检查玩家是否还在线,避免调用离线玩家方法抛出空指针异常
                if (!p.isOnline()) {
                    return;
                }
                // 获取1秒后的Y坐标
                double y2 = p.getLocation().getY();
                // 按你原逻辑计算差值
                double yf = y1 - y2;
                // 广播结果,这里用玩家名字比直接输出Player对象更友好
                Bukkit.broadcastMessage(p.getName() + " 的Y坐标变化量 = " + yf);
            }
        }.runTaskLater(plugin, 20L); // 第二个参数是延迟的刻数,20L对应1秒
    }
}

关键要点解释

  • Bukkit任务调度:用BukkitRunnable配合runTaskLater实现延迟,第二个参数是延迟的游戏刻数,Bukkit默认每秒20刻,所以20L就是1秒。注意必须传入插件实例(JavaPlugin),这是Bukkit调度任务的硬性要求。
  • 玩家状态检查:延迟的1秒内玩家可能下线,所以在run()方法里先判断p.isOnline(),避免调用离线玩家的getLocation()抛出空指针异常。
  • 任务堆积防护:PlayerMoveEvent会在玩家移动时频繁触发(甚至每秒几十次),所以加了冷却机制,用HashMap记录玩家上次触发任务的时间,确保1秒内每个玩家只触发一次任务,避免服务器资源浪费。

额外注意事项

记得在你的主插件类里注册这个监听器,比如:

public class YourPlugin extends JavaPlugin {
    @Override
    public void onEnable() {
        getServer().getPluginManager().registerEvents(new FlyE(this), this);
    }
}

内容的提问来源于stack exchange,提问作者Darth

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:35:18