繁体   English   中英

每位玩家每x分钟重复一次任务

[英]Repeating task every x minutes for every player

我正在为我的世界开发Java / Spigot插件,我希望每15分钟向播放器发送一条消息。 需要每15分钟一次,因为他们并不是每15分钟才加入一次,因此每个玩家都将使用不同的计时器。

我尝试过的

@SuppressWarnings("deprecation")
public static void setup()
{
    Bukkit.getScheduler().scheduleAsyncRepeatingTask(MyPlugin.getPlugin(), new BukkitRunnable()
    {
        public void run() {
            for (final String string : online.keySet()) {
                Utils.sendMessage(string, "It's been 15 minutes")
            }
        }
    }, 1L, 1200L);
}

但是自服务器启动以来,这每15分钟执行一次。 如果有50多个在线玩家,我无法找到一种方法来为每个不会落后于服务器的玩家做到这一点。

编辑:

第二次尝试

private static boolean taskStarted = false;
private static HashMap<UUID, Long> map = new HashMap<UUID, Long>();

@EventHandler
public void onJoin(PlayerJoinEvent event) {
    map.put(event.getPlayer().getUniqueId(), Calendar.getInstance().getTime().getTime());
}

@EventHandler
public void onQuit(PlayerQuitEvent event) {
    map.remove(event.getPlayer().getUniqueId());
}



@SuppressWarnings("deprecation")
public static void startPowerTask() {
    if(taskStarted)
        return;
    taskStarted = true;
    Bukkit.getScheduler().scheduleSyncRepeatingTask(ServerCore.getPlugin(), new BukkitRunnable() {

        @Override
        public void run() {
            for(UUID uuid : map.keySet()) {
                long time = map.get(uuid);
                if(time == ???)
                    Utils.sendMessage(uuid, "It's been 15 minutes");
            }
        }
    }, 20, 20);
}

我不知道怎么检查了十五分钟

为每个玩家安排任务不是一个好主意,为什么还要使用异步任务? 这些设置特别昂贵,除非您知道自己在做什么,否则可能会导致意外行为。 如果可能,请始终以使用同步任务为目标。

为了尽量减少延迟,我使用了一个称为全局调度程序的调度程序。

PlayerJoinEvent ,我们需要了解每个玩家以及他们何时加入。 我正在使用哈希图存储玩家UUID以及代表他们加入日期的长整数。

private HashMap<UUID, Long> map = new HashMap<UUID, Long>();

@EventHandler
public void onJoin(PlayerJoinEvent event) {
    map.put(event.getPlayer().getUniqueID(), Calendar.getInstance().getTime().getTime());
}

您可以存储播放器名称,甚至可以存储播放器对象,但是UUID最为稳定,因为它们是一致的。

现在我们需要检查哈希图是否为空,这可以在将值设置为映射后立即完成:

  • 如果映射不为空并且全局调度程序未运行,请启动它。
  • 如果映射为空并且调度程序正在运行,请停止它。

这使得它仅在必要时运行,从而减少了延迟。

在排程器中,我们要遍历地图中的所有玩家,并将其加入日期与当前日期进行比较,如果超过15分钟,请执行一些操作并将玩家加入日期设置为当前日期。 此调度程序最好应尽可能少地运行,但要获得最准确的结果,请瞄准大约一秒钟(20滴答)

我个人并不熟悉Bukkit,但是文档提供了getLastPlayed()方法 ,该方法应返回在服务器上看到用户的最后一次日期。 我相信您可以使用此日期来计算BukkitSchedulerdelay ,如下所示:

@SuppressWarnings("deprecation")
public static void setup()
{
    // calculate delay amount
    static long delay = somePlayer.getLastPlayed();
    // figure out remaining time post calculation
    delay = (System.currentTimeMillis() - delay) % 1200;
    // proceed with your code as before
    Bukkit.getScheduler().scheduleAsyncRepeatingTask(MyPlugin.getPlugin(), new BukkitRunnable()
    {
        public void run() {
            for (final String string : online.keySet()) {
                Utils.sendMessage(string, "It's been 15 minutes")
            }
        }
    }, delay, 1200L);
}

请注意,我假设1200滴答声会为您提供所需的时间,但是如果没有,您可以在delay后以及相应的模块化算术中更改该值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM