package cc.fascinated.account; import cc.fascinated.Aetheria; import cc.fascinated.account.command.SaveAccountsCommand; import cc.fascinated.command.CommandManager; import cc.fascinated.config.Config; import cc.fascinated.config.Lang; import cc.fascinated.playercolor.PlayerColor; import cc.fascinated.utils.DiscordWebhook; import cc.fascinated.utils.Manager; import cc.fascinated.utils.Priority; import cc.fascinated.utils.Style; import com.viaversion.viaversion.api.Via; 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.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() { CommandManager.registerCommand(new SaveAccountsCommand()); Aetheria.INSTANCE.getServer().getPluginManager().registerEvents(this, Aetheria.INSTANCE); for (Player player : Bukkit.getOnlinePlayers()) { loadAccount(player.getUniqueId()); } Bukkit.getAsyncScheduler().runAtFixedRate(Aetheria.INSTANCE, (task) -> { 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. */ public static void saveAccounts() { long before = System.currentTimeMillis(), saved = 0; // The amount of accounts that were saved log.info("Saving accounts..."); for (Account account : ACCOUNTS.values()) { boolean didSave = account.save(); // Save the account if (didSave) { saved++; } } log.info("Saved {}/{} accounts. ({}ms)", saved, ACCOUNTS.size(), System.currentTimeMillis() - before); } @EventHandler public void onAsyncPlayerPreLoginEvent(AsyncPlayerPreLoginEvent event) { UUID uuid = event.getUniqueId(); if (isAccountLoaded(uuid)) { // Account already loaded return; } loadAccount(uuid); // Load the account into memory } @Override public void onPlayerJoin(Account account, PlayerJoinEvent event) { String joinMessage = Lang.JOIN_MESSAGE.getAsString(); PlayerColor playerColorProfile = account.getPlayerColorProfile(); if (!account.getPlayer().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", account.getName(), true); embed.addField("UUID", account.getUuid().toString(), true); discordWebhook.addEmbed(embed); try { discordWebhook.execute(); } catch (IOException e) { throw new RuntimeException(e); } }); } event.joinMessage(Style.getMiniMessage().deserialize(joinMessage .replace("%player%", account.getName()) .replace("player-color", playerColorProfile.getColor().toString()) )); // Check if the player is using an outdated version and send a warning message int version = Via.getAPI().getPlayerVersion(account.getUuid()); if (version < Config.VERSION_WARNING_VERSION.getAsInt()) { account.sendMessage(Style.getMiniMessage().deserialize(Config.VERSION_WARNING_MESSAGE.getAsString())); } } @Override public void onPlayerQuit(Account account, PlayerQuitEvent event) { event.quitMessage(Style.getMiniMessage().deserialize(Lang.QUIT_MESSAGE.getAsString() .replace("%player%", event.getPlayer().getName()) .replace("player-color", account.getPlayerColorProfile().getColor().toString()) )); account.save(); // Save the account ACCOUNTS.remove(account.getUuid()); // Remove the account from the cache } @Override public void onAetheriaDisable() { saveAccounts(); // Save the accounts to disk ACCOUNTS.clear(); // Remove the accounts from the cache } }