[英]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.