[英]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()方法 ,该方法应返回在服务器上看到用户的最后一次日期。 我相信您可以使用此日期来计算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
后以及相应的模块化算术中更改该值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.