package cc.fascinated.account; import cc.fascinated.Aetheria; import cc.fascinated.config.Config; import cc.fascinated.config.Lang; import cc.fascinated.utils.DiscordWebhook; import cc.fascinated.utils.Manager; import cc.fascinated.utils.Priority; import cc.fascinated.utils.Style; import lombok.extern.log4j.Log4j2; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.AsyncPlayerPreLoginEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerQuitEvent; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeUnit; @Log4j2 public class AccountManager extends Manager implements Listener { private final long SAVE_INTERVAL = 5; // in minutes private static final Map ACCOUNTS = new HashMap<>(); public AccountManager() { Aetheria.INSTANCE.getServer().getPluginManager().registerEvents(this, Aetheria.INSTANCE); for (Player player : Bukkit.getOnlinePlayers()) { loadAccount(player.getUniqueId()); } Bukkit.getAsyncScheduler().runAtFixedRate(Aetheria.INSTANCE, (task) -> { this.saveAccounts(); }, SAVE_INTERVAL, SAVE_INTERVAL, TimeUnit.MINUTES); } @Override public Priority getPriority() { return Priority.LOWEST; } /** * Gets the account for the specified player. * * @param uuid the player's UUID * @return the account */ public static Account getAccount(UUID uuid) { return ACCOUNTS.get(uuid); } /** * Checks if an account is already registered for the specified player. * * @param uuid the player's UUID * @return true if the account is already registered, false otherwise */ private boolean isAccountLoaded(UUID uuid) { return ACCOUNTS.containsKey(uuid); } /** * Registers an account for the specified player. * * @param uuid the player's UUID */ private static void loadAccount(UUID uuid) { Account account = new Account(uuid); ACCOUNTS.put(uuid, account); } /** * Save all accounts to disk. */ private void saveAccounts() { long before = System.currentTimeMillis(); log.info("Saving accounts..."); for (Account account : ACCOUNTS.values()) { account.save(true); // Save the account } log.info("Saved {} accounts. ({}ms)", ACCOUNTS.size(), System.currentTimeMillis() - before); } @EventHandler public void onAsyncPlayerPreLoginEvent(AsyncPlayerPreLoginEvent event) { UUID uuid = event.getUniqueId(); if (isAccountLoaded(uuid)) { // Account already loaded return; } loadAccount(uuid); } @Override public void onPlayerJoin(Account account, PlayerJoinEvent event) { Player player = event.getPlayer(); String joinMessage = Lang.JOIN_MESSAGE.getAsString(); if (!player.hasPlayedBefore()) { joinMessage = Lang.FIRST_JOIN_MESSAGE.getAsString(); // Send a notification to the discord log channel Aetheria.EXECUTOR.execute(() -> { // todo: re-code this it's so ugly DiscordWebhook discordWebhook = new DiscordWebhook(Config.DISCORD_LOG_WEBHOOK.getAsString()); DiscordWebhook.EmbedObject embed = new DiscordWebhook.EmbedObject(); embed.setTitle("New Player Joined"); embed.addField("Name", player.getName(), true); embed.addField("UUID", player.getUniqueId().toString(), true); discordWebhook.addEmbed(embed); try { discordWebhook.execute(); } catch (IOException e) { throw new RuntimeException(e); } }); } event.joinMessage(Style.getMiniMessage().deserialize(joinMessage .replace("%player%", player.getName()) .replace("player-color", account.getPlayerColorProfile().getColor().toString()) )); } @Override public void onPlayerQuit(Account account, PlayerQuitEvent event) { account.save(true); // Save the account ACCOUNTS.remove(account.getUuid()); event.quitMessage(Style.getMiniMessage().deserialize(Lang.QUIT_MESSAGE.getAsString() .replace("%player%", event.getPlayer().getName()) .replace("player-color", account.getPlayerColorProfile().getColor().toString()) )); } @Override public void onAetheriaDisable() { this.saveAccounts(); // Save the accounts to disk ACCOUNTS.clear(); // Remove the accounts from the cache } }