From fd54f9e37c3f32f12744ba1ff6f370baf3641648 Mon Sep 17 00:00:00 2001 From: Liam Date: Tue, 26 Mar 2024 09:00:12 +0000 Subject: [PATCH] a wayy less jank impl of player colors and now supports a command to change it --- .idea/inspectionProfiles/Project_Default.xml | 11 + src/main/java/cc/fascinated/Aetheria.java | 7 +- .../java/cc/fascinated/account/Account.java | 127 ++++++++++ .../cc/fascinated/account/AccountManager.java | 92 +++++++ .../java/cc/fascinated/account/Profile.java | 41 +++ .../java/cc/fascinated/command/Command.java | 11 +- .../fascinated/command/impl/HelpCommand.java | 7 +- .../command/impl/TotalJoinsCommand.java | 5 +- .../java/cc/fascinated/metrics/Metric.java | 17 +- .../cc/fascinated/metrics/MetricManager.java | 3 +- .../impl/server/EntityCountMetric.java | 2 +- .../impl/server/LoadedChunksMetric.java | 2 +- .../metrics/impl/system/CpuUsageMetric.java | 14 +- .../fascinated/playercolor/PlayerColor.java | 89 +++++++ .../playercolor/PlayerColorManager.java | 79 ++++++ .../command/PlayerColorCommand.java | 49 ++++ .../fascinated/playercolors/ColorManager.java | 123 --------- .../java/cc/fascinated/utils/Manager.java | 22 ++ .../java/cc/fascinated/utils/io/Config.java | 235 ++++++++++++++++++ .../worldsize/impl/WorldSizeCommand.java | 11 +- src/main/resources/plugin.yml | 5 +- 21 files changed, 805 insertions(+), 147 deletions(-) create mode 100644 src/main/java/cc/fascinated/account/Account.java create mode 100644 src/main/java/cc/fascinated/account/AccountManager.java create mode 100644 src/main/java/cc/fascinated/account/Profile.java create mode 100644 src/main/java/cc/fascinated/playercolor/PlayerColor.java create mode 100644 src/main/java/cc/fascinated/playercolor/PlayerColorManager.java create mode 100644 src/main/java/cc/fascinated/playercolor/command/PlayerColorCommand.java delete mode 100644 src/main/java/cc/fascinated/playercolors/ColorManager.java create mode 100644 src/main/java/cc/fascinated/utils/Manager.java create mode 100644 src/main/java/cc/fascinated/utils/io/Config.java diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 6a35cd4..235baf6 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -1,6 +1,17 @@ \ No newline at end of file diff --git a/src/main/java/cc/fascinated/Aetheria.java b/src/main/java/cc/fascinated/Aetheria.java index 2f9be3e..419c255 100644 --- a/src/main/java/cc/fascinated/Aetheria.java +++ b/src/main/java/cc/fascinated/Aetheria.java @@ -1,9 +1,10 @@ package cc.fascinated; +import cc.fascinated.account.AccountManager; import cc.fascinated.command.CommandManager; import cc.fascinated.metrics.MetricManager; import cc.fascinated.placeholder.PlaceholderManager; -import cc.fascinated.playercolors.ColorManager; +import cc.fascinated.playercolor.PlayerColorManager; import cc.fascinated.worldsize.WorldSizeManager; import org.bukkit.plugin.java.JavaPlugin; @@ -31,10 +32,12 @@ public class Aetheria extends JavaPlugin { public void onEnable() { saveDefaultConfig(); + new AccountManager(); + new CommandManager(); new WorldSizeManager(); - new ColorManager(); new PlaceholderManager(); new MetricManager(); + new PlayerColorManager(); } } \ No newline at end of file diff --git a/src/main/java/cc/fascinated/account/Account.java b/src/main/java/cc/fascinated/account/Account.java new file mode 100644 index 0000000..f618db5 --- /dev/null +++ b/src/main/java/cc/fascinated/account/Account.java @@ -0,0 +1,127 @@ +package cc.fascinated.account; + +import cc.fascinated.Aetheria; +import cc.fascinated.playercolor.PlayerColor; +import lombok.Getter; +import lombok.SneakyThrows; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; + +import java.io.File; +import java.util.UUID; +@Getter +public class Account { + + /** + * The UUID of the player. + */ + private final UUID uuid; + + /** + * The first time the player joined the server. + */ + private long firstJoin; + + /** + * The last time the player logged in. + */ + private long lastLogin; + + /** + * The file for this account. + */ + private final File file; + + /** + * The configuration for this account. + */ + private final FileConfiguration config; + + /** + * Account profiles. + */ + private final PlayerColor playerColorProfile; + + public Account(UUID uuid) { + boolean newAccount = false; + + this.uuid = uuid; + + File file = new File(Aetheria.INSTANCE.getDataFolder(), "accounts/" + this.uuid.toString() + ".yml"); + this.file = file; + if (!file.exists()) { + newAccount = true; + file.getParentFile().mkdirs(); + try { + file.createNewFile(); + } catch (Exception e) { + e.printStackTrace(); + } + } + config = YamlConfiguration.loadConfiguration(file); + + if (newAccount) { + this.firstJoin = System.currentTimeMillis(); + this.lastLogin = System.currentTimeMillis(); + save(false); // Save default values + } + + this.firstJoin = config.getLong("firstJoin"); + this.lastLogin = config.getLong("lastLogin"); + + // Load profiles + this.playerColorProfile = config.contains("playerColor") ? + new PlayerColor(this, config.getConfigurationSection("playerColor")) : new PlayerColor(this); + } + + /** + * Get the name of the player. + * + * @return the name + */ + public String getName() { + return getPlayer().getName(); + } + + /** + * Get the bukkit player for this account. + * + * @return the player + */ + public Player getPlayer() { + return org.bukkit.Bukkit.getPlayer(uuid); + } + + /** + * Send a message to the player. + * + * @param message the message to send + */ + public void sendMessage(String message) { + getPlayer().sendPlainMessage(message); + } + + /** + * Save a profile to the configuration. + * + * @param profile the profile to save + * @param key the key to save the profile under + */ + private void saveProfile(Profile profile, String key) { + key += "Profile"; // append "Profile" to the key to signify it's a profile + profile.save(config.getConfigurationSection(key) == null ? config.createSection(key) : config.getConfigurationSection(key)); + } + + @SneakyThrows + public void save(boolean saveProfiles) { + this.config.set("firstJoin", this.firstJoin); + this.config.set("lastLogin", this.lastLogin); + + if (saveProfiles) { + this.saveProfile(this.playerColorProfile, "playerColor"); + } + + this.config.save(this.file); + } +} diff --git a/src/main/java/cc/fascinated/account/AccountManager.java b/src/main/java/cc/fascinated/account/AccountManager.java new file mode 100644 index 0000000..eb24841 --- /dev/null +++ b/src/main/java/cc/fascinated/account/AccountManager.java @@ -0,0 +1,92 @@ +package cc.fascinated.account; + +import cc.fascinated.Aetheria; +import cc.fascinated.utils.io.Config; +import cc.fascinated.utils.Manager; +import lombok.extern.log4j.Log4j2; +import lombok.extern.slf4j.Slf4j; +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.server.PluginDisableEvent; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +@Log4j2 +public class AccountManager extends Manager { + + private final int SAVE_INTERVAL = 60 * 5; // 5 minutes + private static final Map ACCOUNTS = new HashMap<>(); + + public AccountManager() { + for (Player player : Bukkit.getOnlinePlayers()) { + registerAccount(player); + } + + Bukkit.getAsyncScheduler().runAtFixedRate(Aetheria.INSTANCE, (task) -> { + this.saveAccounts(); + }, SAVE_INTERVAL, SAVE_INTERVAL, TimeUnit.SECONDS); + } + + /** + * Gets the account for the specified player. + * + * @param uuid the UUID of the player + * @return the account + */ + public static Account getAccount(UUID uuid) { + return ACCOUNTS.get(uuid); // todo: load account if not found + } + + /** + * Registers an account for the specified player. + * + * @param player the player to register the account for + */ + private void registerAccount(Player player) { + Account account = new Account(player.getUniqueId()); + ACCOUNTS.put(player.getUniqueId(), account); + } + + /** + * Save all accounts to disk. + */ + private void saveAccounts() { + log.info("Saving accounts..."); + for (Account account : ACCOUNTS.values()) { + account.save(true); // Save the account + } + log.info("Saved " + ACCOUNTS.size() + " accounts."); + } + + @EventHandler + public void onJoin(PlayerJoinEvent event) { + if (getAccount(event.getPlayer().getUniqueId()) == null) { + registerAccount(event.getPlayer()); + } + } + + @EventHandler + public void onQuit(PlayerQuitEvent event) { + Account account = getAccount(event.getPlayer().getUniqueId()); + account.save(true); + + ACCOUNTS.remove(event.getPlayer().getUniqueId()); + } + + @EventHandler + public void onPluginDisable(PluginDisableEvent event) { + if (event.getPlugin() != Aetheria.INSTANCE) { + return; + } + + this.saveAccounts(); + } +} diff --git a/src/main/java/cc/fascinated/account/Profile.java b/src/main/java/cc/fascinated/account/Profile.java new file mode 100644 index 0000000..397f054 --- /dev/null +++ b/src/main/java/cc/fascinated/account/Profile.java @@ -0,0 +1,41 @@ +package cc.fascinated.account; + +import cc.fascinated.account.Account; +import cc.fascinated.utils.Manager; +import lombok.Getter; +import org.bukkit.configuration.ConfigurationSection; + +@Getter +public abstract class Profile extends Manager { + + /** + * The account this profile is for. + */ + private final Account account; + + /** + * This constructor is used for loading a profile from file. + * + * @param account the account to load the profile for + * @param section the configuration section to load from + */ + public Profile(Account account, ConfigurationSection section) { + this.account = account; + } + + /** + * This constructor is used for creating a new profile. + * + * @param account the account to create the profile for + */ + public Profile(Account account) { + this.account = account; + } + + /** + * Saves this profile to file. + * + * @param section the configuration section to save to + */ + public abstract void save(ConfigurationSection section); +} diff --git a/src/main/java/cc/fascinated/command/Command.java b/src/main/java/cc/fascinated/command/Command.java index 8762a38..efb618c 100644 --- a/src/main/java/cc/fascinated/command/Command.java +++ b/src/main/java/cc/fascinated/command/Command.java @@ -1,8 +1,11 @@ package cc.fascinated.command; +import cc.fascinated.account.Account; +import cc.fascinated.account.AccountManager; import lombok.Getter; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; @Getter @@ -36,15 +39,17 @@ public abstract class Command implements CommandExecutor { } } - this.execute(commandSender, strings); + Player player = (Player) commandSender; + Account account = AccountManager.getAccount(player.getUniqueId()); + this.execute(account, strings); return true; } /** * Executes the command. * - * @param commandSender The sender of the command. + * @param account The account executing the command. * @param args The arguments of the command. */ - public abstract void execute(CommandSender commandSender, String[] args); + public abstract void execute(Account account, String[] args); } diff --git a/src/main/java/cc/fascinated/command/impl/HelpCommand.java b/src/main/java/cc/fascinated/command/impl/HelpCommand.java index 5b7047e..71e28cc 100644 --- a/src/main/java/cc/fascinated/command/impl/HelpCommand.java +++ b/src/main/java/cc/fascinated/command/impl/HelpCommand.java @@ -1,6 +1,7 @@ package cc.fascinated.command.impl; import cc.fascinated.Aetheria; +import cc.fascinated.account.Account; import cc.fascinated.command.Command; import org.bukkit.command.CommandSender; @@ -13,10 +14,10 @@ public class HelpCommand extends Command { } @Override - public void execute(CommandSender commandSender, String[] args) { - commandSender.sendPlainMessage("§6§lAetheria §7» §fCommands:"); + public void execute(Account account, String[] args) { + account.sendMessage("§6§lAetheria §7» §fCommands:"); for (String line : Objects.requireNonNull(Aetheria.INSTANCE.getConfig().getStringList("help-command"))) { - commandSender.sendPlainMessage(" " + line.replaceAll("&", "§")); + account.sendMessage(" " + line.replaceAll("&", "§")); } } } diff --git a/src/main/java/cc/fascinated/command/impl/TotalJoinsCommand.java b/src/main/java/cc/fascinated/command/impl/TotalJoinsCommand.java index 590d2fc..63b65fa 100644 --- a/src/main/java/cc/fascinated/command/impl/TotalJoinsCommand.java +++ b/src/main/java/cc/fascinated/command/impl/TotalJoinsCommand.java @@ -1,6 +1,7 @@ package cc.fascinated.command.impl; import cc.fascinated.Aetheria; +import cc.fascinated.account.Account; import cc.fascinated.command.Command; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; @@ -12,7 +13,7 @@ public class TotalJoinsCommand extends Command { } @Override - public void execute(CommandSender commandSender, String[] args) { - commandSender.sendPlainMessage(Aetheria.PREFIX + "§fTotal joins: §e" + Bukkit.getOfflinePlayers().length + "§f."); + public void execute(Account account, String[] args) { + account.sendMessage(Aetheria.PREFIX + "§fTotal joins: §e" + Bukkit.getOfflinePlayers().length + "§f."); } } diff --git a/src/main/java/cc/fascinated/metrics/Metric.java b/src/main/java/cc/fascinated/metrics/Metric.java index fd9311c..22ec3ca 100644 --- a/src/main/java/cc/fascinated/metrics/Metric.java +++ b/src/main/java/cc/fascinated/metrics/Metric.java @@ -3,8 +3,7 @@ package cc.fascinated.metrics; import com.influxdb.client.write.Point; import lombok.AllArgsConstructor; import lombok.Getter; - -@AllArgsConstructor +import lombok.RequiredArgsConstructor; @Getter public abstract class Metric { @@ -13,6 +12,20 @@ public abstract class Metric { */ private final String name; + /** + * Whether the metric should be collected asynchronously. + */ + private final boolean async; + + public Metric(String name, boolean async) { + this.name = name; + this.async = async; + } + + public Metric(String name) { + this(name, true); + } + /** * Collect and return the metric. * diff --git a/src/main/java/cc/fascinated/metrics/MetricManager.java b/src/main/java/cc/fascinated/metrics/MetricManager.java index e640fd7..3e79ca3 100644 --- a/src/main/java/cc/fascinated/metrics/MetricManager.java +++ b/src/main/java/cc/fascinated/metrics/MetricManager.java @@ -40,7 +40,6 @@ public class MetricManager implements Listener { log.error("InfluxDB configuration is missing"); return; } - InfluxDBClientOptions options = InfluxDBClientOptions.builder() .url(url) .authenticateToken(token.toCharArray()) @@ -82,7 +81,9 @@ public class MetricManager implements Listener { long before = System.currentTimeMillis(); List points = new ArrayList<>(); for (Metric metric : metrics) { + long start = System.currentTimeMillis(); points.add(metric.toPoint()); + log.info("Collected metric {} in {}ms", metric.getName(), System.currentTimeMillis() - start); } // write the points async Aetheria.EXECUTOR.execute(() -> { diff --git a/src/main/java/cc/fascinated/metrics/impl/server/EntityCountMetric.java b/src/main/java/cc/fascinated/metrics/impl/server/EntityCountMetric.java index d1678f1..501ac28 100644 --- a/src/main/java/cc/fascinated/metrics/impl/server/EntityCountMetric.java +++ b/src/main/java/cc/fascinated/metrics/impl/server/EntityCountMetric.java @@ -11,7 +11,7 @@ import java.util.Map; public class EntityCountMetric extends Metric { public EntityCountMetric() { - super("entity_count"); + super("entity_count", true); } @Override diff --git a/src/main/java/cc/fascinated/metrics/impl/server/LoadedChunksMetric.java b/src/main/java/cc/fascinated/metrics/impl/server/LoadedChunksMetric.java index b293be8..6de4057 100644 --- a/src/main/java/cc/fascinated/metrics/impl/server/LoadedChunksMetric.java +++ b/src/main/java/cc/fascinated/metrics/impl/server/LoadedChunksMetric.java @@ -11,7 +11,7 @@ import java.util.Map; public class LoadedChunksMetric extends Metric { public LoadedChunksMetric() { - super("loaded_chunks"); + super("loaded_chunks", true); } @Override diff --git a/src/main/java/cc/fascinated/metrics/impl/system/CpuUsageMetric.java b/src/main/java/cc/fascinated/metrics/impl/system/CpuUsageMetric.java index 71aed58..dd8881c 100644 --- a/src/main/java/cc/fascinated/metrics/impl/system/CpuUsageMetric.java +++ b/src/main/java/cc/fascinated/metrics/impl/system/CpuUsageMetric.java @@ -1,21 +1,29 @@ package cc.fascinated.metrics.impl.system; +import cc.fascinated.Aetheria; import cc.fascinated.Oshi; import cc.fascinated.metrics.Metric; import com.influxdb.client.write.Point; +import org.bukkit.Bukkit; import oshi.hardware.HardwareAbstractionLayer; +import java.util.concurrent.TimeUnit; + public class CpuUsageMetric extends Metric { + double cpuLoad; + public CpuUsageMetric() { super("cpu_usage"); + + Bukkit.getAsyncScheduler().runAtFixedRate(Aetheria.INSTANCE, (task) -> { + HardwareAbstractionLayer hardware = Oshi.SYSTEM_INFO.getHardware(); + cpuLoad = hardware.getProcessor().getSystemCpuLoad(500) * 100; // get the CPU load in percentage + },0, 30, TimeUnit.SECONDS); } @Override protected Point toPoint() { - HardwareAbstractionLayer hardware = Oshi.SYSTEM_INFO.getHardware(); - double cpuLoad = hardware.getProcessor().getSystemCpuLoad(500) * 100; // get the CPU load in percentage - return Point.measurement(getName()) .addField("value", cpuLoad); } diff --git a/src/main/java/cc/fascinated/playercolor/PlayerColor.java b/src/main/java/cc/fascinated/playercolor/PlayerColor.java new file mode 100644 index 0000000..3abb7b7 --- /dev/null +++ b/src/main/java/cc/fascinated/playercolor/PlayerColor.java @@ -0,0 +1,89 @@ +package cc.fascinated.playercolor; + +import cc.fascinated.account.Account; +import cc.fascinated.account.Profile; +import cc.fascinated.utils.Manager; +import lombok.Getter; +import lombok.Setter; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerLoginEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.scoreboard.Scoreboard; +import org.bukkit.scoreboard.Team; + +import java.util.List; + +@Getter @Setter +public class PlayerColor extends Profile { + + /** + * The current color of the player. + */ + private NamedTextColor color; + + public PlayerColor(Account account) { + super(account); + + this.color = PlayerColorManager.getRandomColor(); + } + + public PlayerColor(Account account, ConfigurationSection section) { + super(account, section); + + this.color = NamedTextColor.namedColor(section.getInt("color")); + } + + /** + * Sets the color of the player. + * + * @param color the new color + */ + public void setColor(NamedTextColor color) { + this.color = color; + + Team team = getScoreboardTeam(this.color); + team.addEntry(getAccount().getName()); + } + + @Override + public void save(ConfigurationSection section) { + section.set("color", this.color.value()); + } + + @EventHandler + public void onLogin(PlayerLoginEvent event) { + Player player = event.getPlayer(); + + Team team = getScoreboardTeam(this.color); + team.addEntry(player.getName()); + } + + @EventHandler + public void onQuit(PlayerQuitEvent event) { + Player player = event.getPlayer(); + + Team team = getScoreboardTeam(this.color); + team.removeEntry(player.getName()); + } + + /** + * Gets the scoreboard team for this color. + * + * @param color the color to get the team for + * @return the team + */ + private Team getScoreboardTeam(NamedTextColor color) { + Scoreboard scoreboard = Bukkit.getScoreboardManager().getMainScoreboard(); + Team team = scoreboard.getTeam(color.toString().toLowerCase()); + if (team == null) { + team = scoreboard.registerNewTeam(color.toString().toLowerCase()); + team.color(color); + } + + return team; + } +} diff --git a/src/main/java/cc/fascinated/playercolor/PlayerColorManager.java b/src/main/java/cc/fascinated/playercolor/PlayerColorManager.java new file mode 100644 index 0000000..7da10b4 --- /dev/null +++ b/src/main/java/cc/fascinated/playercolor/PlayerColorManager.java @@ -0,0 +1,79 @@ +package cc.fascinated.playercolor; + +import cc.fascinated.account.Account; +import cc.fascinated.account.AccountManager; +import cc.fascinated.playercolor.command.PlayerColorCommand; +import cc.fascinated.utils.Manager; +import io.papermc.paper.event.player.AsyncChatEvent; +import lombok.Getter; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; + +import java.util.List; + +public class PlayerColorManager extends Manager { + + /** + * List of possible colors that can be randomly picked + */ + @Getter + private static final List validColors = List.of( + NamedTextColor.RED, + NamedTextColor.GREEN, + NamedTextColor.BLUE, + NamedTextColor.YELLOW, + NamedTextColor.AQUA, + NamedTextColor.DARK_AQUA, + NamedTextColor.GRAY, + NamedTextColor.LIGHT_PURPLE, + NamedTextColor.WHITE + ); + + public PlayerColorManager() { + registerCommand(new PlayerColorCommand()); + } + + /** + * Gets a random color from the list of valid colors. + * + * @return the random color + */ + public static NamedTextColor getRandomColor() { + return validColors.get((int) (Math.random() * validColors.size())); + } + + /** + * Gets the text color from a string. + * + * @param color the color string + * @return the text color + */ + public static NamedTextColor getColor(String color) { + for (NamedTextColor textColor : validColors) { + if (textColor.toString().equalsIgnoreCase(color)) { + return textColor; + } + } + + return null; + } + + @EventHandler + public void onChat(AsyncChatEvent event) { + Player player = event.getPlayer(); + Account account = AccountManager.getAccount(player.getUniqueId()); + NamedTextColor color = account.getPlayerColorProfile().getColor(); + + event.renderer((source, sourceDisplayName, message, viewer) -> { + return Component.text() + .append(Component.text("<")) + .append(player.displayName().color(color)) + .append(Component.text(">")) + .append(Component.space()) + .append(message) + .asComponent(); + }); + } +} diff --git a/src/main/java/cc/fascinated/playercolor/command/PlayerColorCommand.java b/src/main/java/cc/fascinated/playercolor/command/PlayerColorCommand.java new file mode 100644 index 0000000..2958a78 --- /dev/null +++ b/src/main/java/cc/fascinated/playercolor/command/PlayerColorCommand.java @@ -0,0 +1,49 @@ +package cc.fascinated.playercolor.command; + +import cc.fascinated.account.Account; +import cc.fascinated.command.Command; +import cc.fascinated.playercolor.PlayerColor; +import cc.fascinated.playercolor.PlayerColorManager; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.command.CommandSender; +import org.checkerframework.checker.units.qual.A; + +import java.util.List; + +public class PlayerColorCommand extends Command { + + public PlayerColorCommand() { + super("playercolor"); + } + + @Override + public void execute(Account account, String[] args) { + PlayerColor playerColorProfile = account.getPlayerColorProfile(); + if (args.length == 0) { + account.sendMessage("§b§lPLAYERCOLOR §7» §fYour current color is: " + playerColorProfile.getColor() + "§f."); + return; + } + + List validColors = PlayerColorManager.getValidColors(); + if (args[0].equalsIgnoreCase("random")) { + playerColorProfile.setColor(validColors.get((int) (Math.random() * validColors.size()))); + account.sendMessage("§b§lPLAYERCOLOR §7» §fYour color has been set to: " + playerColorProfile.getColor() + "§f."); + return; + } + + NamedTextColor color = PlayerColorManager.getColor(args[0]); + if (color == null) { + account.sendMessage("§b§lPLAYERCOLOR §7» §cInvalid color."); + + StringBuilder builder = new StringBuilder("§fValid colors: "); + for (NamedTextColor validColor : validColors) { + builder.append(validColor).append(", "); + } + account.sendMessage(builder.substring(0, builder.length() - 2) + "."); + return; + } + + playerColorProfile.setColor(color); + account.sendMessage("§b§lPLAYERCOLOR §7» §fYour color has been set to: " + playerColorProfile.getColor() + "§f."); + } +} diff --git a/src/main/java/cc/fascinated/playercolors/ColorManager.java b/src/main/java/cc/fascinated/playercolors/ColorManager.java deleted file mode 100644 index 4dda6fa..0000000 --- a/src/main/java/cc/fascinated/playercolors/ColorManager.java +++ /dev/null @@ -1,123 +0,0 @@ -package cc.fascinated.playercolors; - -import cc.fascinated.Aetheria; -import io.papermc.paper.event.player.AsyncChatEvent; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerLoginEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.scoreboard.Scoreboard; -import org.bukkit.scoreboard.Team; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -public class ColorManager implements Listener { - - /** - * Cache of the chat colors for each player - */ - private final Map chatColors = new HashMap<>(); - - /** - * List of possible colors that can be randomly picked - */ - private final List validColors = List.of( - NamedTextColor.RED, - NamedTextColor.GREEN, - NamedTextColor.BLUE, - NamedTextColor.YELLOW, - NamedTextColor.AQUA, - NamedTextColor.DARK_AQUA, - NamedTextColor.GRAY, - NamedTextColor.LIGHT_PURPLE, - NamedTextColor.WHITE - ); - - public ColorManager() { - Aetheria.INSTANCE.getServer().getPluginManager().registerEvents(this, Aetheria.INSTANCE); - - Scoreboard scoreboard = Bukkit.getScoreboardManager().getMainScoreboard(); - for (NamedTextColor color : validColors) { - if (scoreboard.getTeam(color.toString().toLowerCase()) != null) { - // Unregister the old team - Objects.requireNonNull(scoreboard.getTeam(color.toString().toLowerCase())).unregister(); - } - scoreboard.registerNewTeam(color.toString().toLowerCase()).color(color); - } - - for (Player player : Bukkit.getOnlinePlayers()) { - setChatColor(player); - } - } - - /** - * Gets a random color for the player - * based on their uuid - * - * @param player the player to get the color for - * @return the color for the player - */ - private NamedTextColor getColorForPlayer(Player player) { - return chatColors.computeIfAbsent(player, (e) -> { - return validColors.get(Math.abs(player.getUniqueId().hashCode()) % validColors.size()); - }); - } - - /** - * Set the color for a player - * - * @param player the player to set the color for - */ - public void setChatColor(Player player) { - Scoreboard scoreboard = Bukkit.getScoreboardManager().getMainScoreboard(); - Team team = scoreboard.getTeam(getColorForPlayer(player).toString().toLowerCase()); - if (team == null) { - return; - } - if (team.getEntries().contains(player.getName())) { - return; - } - team.addEntry(player.getName()); - } - - @EventHandler - public void onLogin(PlayerLoginEvent event) { - Player player = event.getPlayer(); - - setChatColor(player); - } - - @EventHandler - public void onLeave(PlayerQuitEvent event) { - Player player = event.getPlayer(); - - chatColors.remove(player); - } - - @EventHandler - public void onChat(AsyncChatEvent event) { - Player player = event.getPlayer(); - - NamedTextColor color = chatColors.get(player); - if (color == null) { - return; - } - - event.renderer((source, sourceDisplayName, message, viewer) -> { - return Component.text() - .append(Component.text("<")) - .append(player.displayName().color(color)) - .append(Component.text(">")) - .append(Component.space()) - .append(message) - .asComponent(); - }); - } -} diff --git a/src/main/java/cc/fascinated/utils/Manager.java b/src/main/java/cc/fascinated/utils/Manager.java new file mode 100644 index 0000000..3c49592 --- /dev/null +++ b/src/main/java/cc/fascinated/utils/Manager.java @@ -0,0 +1,22 @@ +package cc.fascinated.utils; + +import cc.fascinated.Aetheria; +import cc.fascinated.command.Command; +import cc.fascinated.command.CommandManager; +import org.bukkit.event.Listener; + +public class Manager implements Listener { + + public Manager() { + Aetheria.INSTANCE.getServer().getPluginManager().registerEvents(this, Aetheria.INSTANCE); + } + + /** + * Register a command to the command manager. + * + * @param command The command to register. + */ + public void registerCommand(Command command) { + CommandManager.registerCommand(command); + } +} diff --git a/src/main/java/cc/fascinated/utils/io/Config.java b/src/main/java/cc/fascinated/utils/io/Config.java new file mode 100644 index 0000000..8402733 --- /dev/null +++ b/src/main/java/cc/fascinated/utils/io/Config.java @@ -0,0 +1,235 @@ +package cc.fascinated.utils.io; + +import lombok.Getter; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +@Getter +public class Config { + + private final JavaPlugin plugin; + private final String configName; + private final File file; + private FileConfiguration configuration; + + public Config(JavaPlugin plugin, String configName, String folderName) { + this.plugin = plugin; + this.configName = (folderName == null ? "" : folderName + File.separator) + configName; // managers/config.yml + this.file = new File(plugin.getDataFolder(), (folderName == null ? "" : File.separator) + this.configName); // plugins/Plugin/managers/config.yml + this.saveDefaultConfig(); + } + + /** + * @return {@link #configuration} + */ + public FileConfiguration getFileConfiguration() { + if (this.configuration == null) { + this.reloadConfig(); + } + return this.configuration; + } + + /** + * Reload this config file from disk + */ + public void reloadConfig() { + this.configuration = YamlConfiguration.loadConfiguration(this.file); + InputStream defConfigStream = this.plugin.getResource(this.configName); + if (defConfigStream == null) { + throw new NullPointerException("Resource is null for " + configName); + } + YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(new InputStreamReader(defConfigStream)); + this.configuration.setDefaults(defConfig); + } + + /** + * Save this configuration file to disk + */ + public void saveConfig() { + if (this.configuration != null && this.file != null) { + try { + this.getFileConfiguration().save(this.file); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + } + + /** + * Save the embedded config file shipped with the jar + */ + public void saveDefaultConfig() { + if (!this.file.exists()) { + this.plugin.saveResource(this.configName, false); + } + } + + /** + * Return the {@link ConfigurationSection} at the provided path + * + * @param path the path of the configuration section to fetch + * @param createIfAbsent whether the configuration section should be created if it is not present + * @return the configuration section at the provided path + */ + public ConfigurationSection getConfigurationSection(String path, boolean createIfAbsent) { + FileConfiguration file = this.getFileConfiguration(); + ConfigurationSection section = file.getConfigurationSection(path); + if (section == null && createIfAbsent) { + section = file.createSection(path); + } + return section; + } + + /** + * Set a {@link String} at the provided path + * + * @param path path for the node to be placed at + * @param value value of the node + * @param save whether the file should be saved after setting + */ + public void setString(String path, String value, boolean save) { + this.getFileConfiguration().set(path, value); + if (save) { + this.saveConfig(); + } + } + + /** + * Return the {@link String} at the provided path + * Returns null if the path is not present, + * + * @param path the path to fetch the string at + * @return the string at the provided path + * @see #getString(String, boolean, String) for a non null return + */ + public String getString(String path) { + return this.getFileConfiguration().getString(path); + } + + /** + * Return the {@link String} at the provided path + * If {@param createIfAbsent} is true, {@param defaultValue} will be placed at {@param path} if no value is present already + * Saves the file if a default value is placed + * + * @param path path for the node to be placed at + * @param createIfAbsent whether a default value should be placed if no value is found + * @param defaultValue the default value to return and place into the file if desired + * @return the value at the provided path or the default provided value if applicable + */ + public String getString(String path, boolean createIfAbsent, String defaultValue) { + String value = this.getString(path); + if (value == null && createIfAbsent) { + this.setString(path, defaultValue, true); + return defaultValue; + } + return value; + } + + /** + * @see #setString(String, String, boolean) + */ + public void setInt(String path, int value, boolean save) { + this.getFileConfiguration().set(path, value); + if (save) { + this.saveConfig(); + } + } + + /** + * @see #getString(String) + */ + public int getInt(String path) { + return this.getFileConfiguration().getInt(path); + } + + /** + * @see #getString(String, boolean, String) + */ + public int getInt(String path, boolean createIfAbsent, int defaultValue) { + FileConfiguration file = this.getFileConfiguration(); + if (file.contains(path)) { + return this.getInt(path); + } else if (createIfAbsent) { + this.setInt(path, defaultValue, true); + } + return -1; + } + + /** + * @see #setString(String, String, boolean) + */ + public void setDouble(String path, double value, boolean save) { + this.getFileConfiguration().set(path, value); + if (save) { + this.saveConfig(); + } + } + + /** + * @see #getString(String) + */ + public double getDouble(String path) { + return this.getFileConfiguration().getDouble(path); + } + + /** + * Default to -1 + * + * @see #getString(String, boolean, String) + */ + public double getDouble(String path, boolean createIfAbsent, double defaultValue) { + FileConfiguration file = this.getFileConfiguration(); + if (file.contains(path)) { + return this.getDouble(path); + } else if (createIfAbsent) { + this.setDouble(path, defaultValue, true); + } + return -1; + } + + /** + * @see #setString(String, String, boolean) + */ + public void setBoolean(String path, boolean value, boolean save) { + this.getFileConfiguration().set(path, value); + if (save) { + this.saveConfig(); + } + } + + /** + * @see #getString(String) + */ + public boolean getBoolean(String path) { + return this.getFileConfiguration().getBoolean(path); + } + + /** + * Default to false + * + * @see #getString(String, boolean, String) + */ + public boolean getBoolean(String path, boolean createIfAbsent, boolean defaultValue) { + FileConfiguration file = this.getFileConfiguration(); + if (file.contains(path)) { + return this.getBoolean(path); + } else if (createIfAbsent) { + this.setBoolean(path, defaultValue, true); + } + return false; + } + + /** + * Set a value at a path + */ + public void set(String path, Object value) { + this.getFileConfiguration().set(path, value); + } +} \ No newline at end of file diff --git a/src/main/java/cc/fascinated/worldsize/impl/WorldSizeCommand.java b/src/main/java/cc/fascinated/worldsize/impl/WorldSizeCommand.java index 75d1592..898d65a 100644 --- a/src/main/java/cc/fascinated/worldsize/impl/WorldSizeCommand.java +++ b/src/main/java/cc/fascinated/worldsize/impl/WorldSizeCommand.java @@ -1,6 +1,7 @@ package cc.fascinated.worldsize.impl; import cc.fascinated.Aetheria; +import cc.fascinated.account.Account; import cc.fascinated.command.Command; import cc.fascinated.utils.FormatterUtils; import cc.fascinated.utils.TimeUtils; @@ -17,15 +18,15 @@ public class WorldSizeCommand extends Command { } @Override - public void execute(CommandSender commandSender, String[] args) { - commandSender.sendPlainMessage(Aetheria.PREFIX + "§fWorld information:"); + public void execute(Account account, String[] args) { + account.sendMessage(Aetheria.PREFIX + "§fWorld information:"); long totalSize = 0; for (Map.Entry entry : WorldSizeManager.getWorldSizes().entrySet()) { long size = entry.getValue(); - commandSender.sendPlainMessage(" §7- §f" + entry.getKey().getName() + ": §e" + FormatterUtils.formatBytes(size) + "§f."); + account.sendMessage(" §7- §f" + entry.getKey().getName() + ": §e" + FormatterUtils.formatBytes(size) + "§f."); totalSize += size; } - commandSender.sendPlainMessage(" §fTotal size: §e" + FormatterUtils.formatBytes(totalSize) + "§f."); - commandSender.sendPlainMessage(" §fLast updated: §e" + TimeUtils.format(System.currentTimeMillis() - WorldSizeManager.getLastUpdated()) + " ago§f."); + account.sendMessage(" §fTotal size: §e" + FormatterUtils.formatBytes(totalSize) + "§f."); + account.sendMessage(" §fLast updated: §e" + TimeUtils.format(System.currentTimeMillis() - WorldSizeManager.getLastUpdated()) + " ago§f."); } } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index d26c4f8..f1d8a37 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -13,4 +13,7 @@ commands: usage: "/worldsize" help: description: "Shows the help message" - usage: "/help" \ No newline at end of file + usage: "/help" + playercolor: + description: "Changes your player color" + usage: "/playercolor " \ No newline at end of file