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