我正在开发一个用于我的世界的Java / Spigot插件,每15分钟我想向播放器发送一条消息。它需要每15分钟一次,因为它们并非每15分钟一起加入,所以每个玩家都会使用不同的计时器。
我尝试了什么
[GOODS_TYPE] = CASE WHEN [_TYPE_NAME] IS NULL
THEN 'GRANT_TOTAL'
WHEN [GOODS_CODE] IS NULL
THEN 'TOTAL ' + [_TYPE_NAME]
END
但是自服务器启动以来每15分钟一次。如果有50多名玩家在线,我无法为每个不会落后于服务器的玩家找到办法。
修改
第二次尝试
@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分钟
答案 0 :(得分:4)
为每个玩家安排任务不是一个好主意,为什么你使用异步任务呢?这些设置成本特别高,除非您知道自己在做什么,否则可能会导致无意识的行为。如果可能,请务必改为使用同步任务。
对于最小的延迟,我使用单个调度程序,称为全局调度程序。
听取PlayerJoinEvent,我们需要了解每位玩家以及他们何时加入。我使用hashmap存储播放器UUID以及表示其加入日期的long。
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最稳健,因为它们是一致的。
现在我们需要检查hashmap是否为空,这可以在将值设置到地图后立即完成:
这使它只在必要时运行,减少滞后。
在调度程序中,我们想要遍历地图中的所有玩家并将他们的加入日期与当前日期进行比较,如果超过15分钟,则执行某些操作并将玩家加入日期设置为当前日期。 这个调度程序应该尽可能少地运行,但为了获得最准确的结果,目标是大约一秒钟(20个滴答)
答案 1 :(得分:1)
我个人并不熟悉Bukkit,但是,文档提供了getLastPlayed() method,它应该返回用户上次在服务器上看到的日期。我相信您可以使用此日期计算BukkitScheduler
中的delay
,如下所示:
@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
之后以及相应的模运算中更改该值。