Сохранение и сброс хэшмапов

BlackBaroness

Модератор
Разработчик
Сообщения
1,680
Решения
72
Веб-сайт
vk.com
Сап спигот, раз нет альтернатив, хочу написать плагин на выдачу наград за наигранные часы, заодно улучшив уже существующий. У меня есть вот такой код:

Java:
public class handler implements Listener {

    private static final Baroness pluginInstance = Baroness.getInstance();
    HashMap<Player, Integer> clock = new HashMap<>();

    @EventHandler
    public void join(PlayerJoinEvent e) throws InterruptedException {
        Player p = e.getPlayer();
        clock.put(p, -1);
        new BukkitRunnable() {
            @Override
            public void run() {
                int some = clock.get(p);
                some++;
                clock.put(p, some);
                if (clock.get(p) == 1) {
                    p.sendMessage(ChatColor.AQUA + "Вы играете " + ChatColor.GOLD + clock.get(p) + ChatColor.AQUA + " час.");
                }
                if (clock.get(p) == 2 || clock.get(p) == 3 || clock.get(p) == 4) {
                    p.sendMessage(ChatColor.AQUA + "Вы играете уже " + ChatColor.GOLD + clock.get(p) + ChatColor.AQUA + " часа.");
                }
                if (clock.get(p) >= 5 && clock.get(p) <= 10) {
                    p.sendMessage(ChatColor.AQUA + "Вы играете уже " + ChatColor.GOLD + clock.get(p) + ChatColor.AQUA + " часов.");
                }
                if (clock.get(p) != 0) {
                    p.sendMessage(ChatColor.DARK_GREEN + "Не забывайте отдыхать.");
                }
            }
        }.runTaskTimer(pluginInstance, 0, 36000000 * 20);

Надо сделать, чтобы эта прелесть сохранялась при релоге и при этом сбрасывалась в определённое время. Например, в 0:00.
 
Решение
Black_Baroness, типа есть класс

Java:
public class PlayTime {
    private long start = System.currentTimeMillis();

    public long getStart() {
        return start;
}
}

Потом при в главный класс:

Java:
public class Main extends JavaPlugin implements Listener {

    private Map<UUID, PlayTime> playerTime = new HashMap<>();

    @Override
    public void onEnable() {
        Bukkit.getScheduler().runTaskTimerAsynchronously(this, () -> {
            playerTime.forEach((player, playTime) -> {
                long now = System.currentTimeMillis();
                long differenceInHours = TimeUnit.MILLISECONDS.toHours(now - playTime.getStart()));
                switch(differenceInHours) {
                    case 1...
Ну, я бы не создавал при входе постоянно таймер это 3.14#дец полнейший, 100 игроков и 100 синхронных таймеров, к черту эту реализацию.
Для начала создай HashMap<UUID, PlayTime>, где PlayTime - условный класс, при создании объекта которого переменной start внутри него присваивается значение System.currentTimeMillis(). Потом в одном асинхронном потоке, который сунешь в onEnable(), итерируй по игрокам в этой мапе и элементарными математическими действиями определяй количество сыгранных часов и делай что душе угодно.

UPD: Используй TimeUnit чтобы красиво перекидывать из одной системы времени в другую.
 
Black_Baroness, типа есть класс

Java:
public class PlayTime {
    private long start = System.currentTimeMillis();

    public long getStart() {
        return start;
}
}

Потом при в главный класс:

Java:
public class Main extends JavaPlugin implements Listener {

    private Map<UUID, PlayTime> playerTime = new HashMap<>();

    @Override
    public void onEnable() {
        Bukkit.getScheduler().runTaskTimerAsynchronously(this, () -> {
            playerTime.forEach((player, playTime) -> {
                long now = System.currentTimeMillis();
                long differenceInHours = TimeUnit.MILLISECONDS.toHours(now - playTime.getStart()));
                switch(differenceInHours) {
                    case 1:
                        //твой код и бла бла бла
                    default:
                        break;
                }
            })
        }, 0L, 36000L /*
        В идеале брать половину цены деления,
        так как тебе нужны часы,
        значит выполняем каждые 30 минут*/ );
    }
}
В мапу суем игрока при входе и удаляем при выходе.
P.S накалякал пофасту, мб где-то есть ошибки.
UPD: Забыл про инстанс, прост свой эксекьютор юзаю руку давно набил на него :p
 
Последнее редактирование модератором:
mc923,
напомни, что такое L? в бакките вроде в тиках указывают
Авто объединение сообщений:

И, имея такой код
Java:
        Bukkit.getScheduler().runTaskTimerAsynchronously(this, () -> {
            playerTime.forEach((player, playTime) -> {
                long now = System.currentTimeMillis();
                long differenceInHours = TimeUnit.MILLISECONDS.toHours(now - playTime.getStart());
                switch((int) differenceInHours) {
                    case 1:
                    default:
                        break;
                }
            });
        }, 0L, 36000L);
    }

каким образом обращаться к игроку? player не работает
Авто объединение сообщений:

я разобрал старый плагин OnlineTime:
Java:
package Main;

import Main.Main.1;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;

public class Main extends JavaPlugin implements CommandExecutor {
    static Main main;
    String sprache = "";
    String perfix = "§8§l[§b§l!§8§l] §r";

    public Main() {
    }

    public void onEnable() {
        main = this;
        System.out.print("[OnlineTime] >>>>>> Enable <<<<<<");
        Config.loadConfig();
        this.OnlineTimer();
        this.sprache = this.getConfig().getString("Online.language");
    }

    public void onDisable() {
        System.out.print("[OnlineTime] >>>>>> Disable <<<<<<");
    }

    public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
        Player p = (Player)sender;
        if (cmd.getName().equalsIgnoreCase("online")) {
            int day = this.getConfig().getInt(p.getName() + ".tage");
            int std = this.getConfig().getInt(p.getName() + ".stunden");
            int min = this.getConfig().getInt(p.getName() + ".minuten");
            if (this.sprache.equals("de")) {
                p.sendMessage(this.perfix + "§6" + day + " §bTage §6" + std + " §bStunden §6" + min + " §bMinuten");
            } else if (this.sprache.equals("en")) {
                p.sendMessage(this.perfix + "§6" + day + " §bdays §6" + std + " §bhours §6" + min + " §bminutes");
            } else if (this.sprache.equals("jp")) {
                p.sendMessage(this.perfix + "§6" + day + " §b日 §6" + std + " §b時間 §6" + min + " §b分");
            } else {
                p.sendMessage(this.perfix + "§cNo language select");
            }
        }

        return true;
    }

    public void OnlineTimer() {
        Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new 1(this), 1200L, 1200L);
    }

    public static Main getInsatnce() {
        return main;
    }
}
 
Последнее редактирование:
Спасибо, туплю сегодня немного. Я так и не нашёл рабочего метода с взаимодействием с игроком, сейчас пытаюсь понять работу OnlineTime, но там про таймер лишь одна строчка
Java:
Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new 1(this), 1200L, 1200L);
И я не понимаю, каким образом тогда работает плагин
Авто объединение сообщений:

Я не вижу переменных, которые он затрагивает и хэшмапов
 
напомни, что такое L? в бакките вроде в тиках указывают
Аля показывает что число типа long

каким образом обращаться к игроку? player не работает
Работает, код полностью рабочий, проверь еще раз.
Это переменные внутри лямбды.
Ты точно хэшмапу типа <Player, PlayTime> создал?

UPD, моя ошибка, я наверху сделал мапу через <UUID, PlayTime>. Меняй на Player или получай игрока через UUID
 
Java:
        Bukkit.getScheduler().runTaskTimerAsynchronously(this, () -> {
            playerTime.forEach((player, playTime) -> {
                long now = System.currentTimeMillis();
                long differenceInHours = TimeUnit.MILLISECONDS.toHours(now - playTime.getStart());
                Player p = Bukkit.getPlayer(player);
                switch((int) differenceInHours) {
                    case 1:
                        p.sendMessage("");
                    default:
                        break;
                }
            });
        }, 0L, 36000L);

Ошибок вроде не показывает. Чтобы час указать, писать 36000000 * 20L или как?
BuseSo, я знаю, не нужно)
 
Java:
//это в OnEnable
Bukkit.getScheduler().runTaskTimerAsynchronously(this, () -> playerTime.forEach((player, playTime) -> {
            long now = System.currentTimeMillis();
            long differenceInHours = TimeUnit.MILLISECONDS.toHours(now - playTime.getStart());
            Player p = Bukkit.getPlayer(player);
            switch((int) differenceInHours) {
                case 1:
                    p.sendMessage("письки");
                case 1:
                    p.sendMessage("письки 2");
                default:
                    break;
            }
        }), 0L,  72000L );

Java:
//это другой класс
public class PlayTime {
    private long start = System.currentTimeMillis();

    public long getStart() { return start; }
}

вот так получилось. не могу пока проверить работает ли, ибо час в игре торчать не могу, а он часы считает
 
Назад
Сверху Снизу