簡體   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