Повторяя задание каждые х минут для каждого игрока - PullRequest
0 голосов
/ 06 мая 2018

Я работаю над плагином 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 игроков.

Edit:

Вторая попытка

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);
}

Я не знаю, как проверить, прошло ли это 15 минут

Ответы [ 2 ]

0 голосов
/ 06 мая 2018

Планирование задачи для каждого игрока не очень хорошая идея, также почему вы используете асинхронную задачу? Они особенно дороги в настройке и могут привести к непреднамеренному поведению, если вы не знаете, что делаете. Всегда старайтесь использовать задачу синхронизации, если это возможно.

Для наименьшей задержки я использую один планировщик, называемый глобальным планировщиком.

Слушайте 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 тиков)

0 голосов
/ 06 мая 2018

Я лично не знаком с Bukkit, однако документация предоставляет метод getLastPlayed () , который должен возвращать дату, когда пользователь последний раз был замечен на сервере. Я полагаю, что вы можете использовать эту дату для вычисления delay в BukkitScheduler, например:

@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, а также в модульной арифметике соответственно.

...