diff --git a/pom.xml b/pom.xml
index 2166e1c..80a4f23 100644
--- a/pom.xml
+++ b/pom.xml
@@ -77,6 +77,12 @@
2.0.0-SNAPSHOT
provided
+
+ de.iani.cubeside
+ CubesideStatistics
+ 1.0.0-SNAPSHOT
+ provided
+
diff --git a/src/main/java/de/fanta/challengesjoinentities/ChallengesJoinEntities.java b/src/main/java/de/fanta/challengesjoinentities/ChallengesJoinEntities.java
index aedb9d8..f93019e 100644
--- a/src/main/java/de/fanta/challengesjoinentities/ChallengesJoinEntities.java
+++ b/src/main/java/de/fanta/challengesjoinentities/ChallengesJoinEntities.java
@@ -11,6 +11,7 @@
import de.fanta.challengesjoinentities.commands.AdventureCommand.AdventureMapsCommand;
import de.fanta.challengesjoinentities.commands.AdventureCommand.AdventureTestMapCommand;
import de.fanta.challengesjoinentities.commands.AdventureCommand.ChallengesRemovePlayerServer;
+import de.fanta.challengesjoinentities.commands.ChallengesCommand.ChallengesStatsCommand;
import de.fanta.challengesjoinentities.commands.ChallengesCommand.ChallengesloadCommand;
import de.fanta.challengesjoinentities.commands.PiglinCommand.AddEntityCommand;
import de.fanta.challengesjoinentities.commands.PiglinCommand.Entitytphere;
@@ -23,6 +24,8 @@
import de.fanta.challengesjoinentities.listeners.PlayerListener;
import de.fanta.challengesjoinentities.loadgui.AdventureLoadGUI;
import de.fanta.challengesjoinentities.loadgui.ChallengeLoadGUI;
+import de.fanta.challengesjoinentities.utils.Statistics;
+import de.iani.cubesidestats.api.CubesideStatisticsAPI;
import de.iani.cubesideutils.bukkit.commands.CommandRouter;
import de.iani.playerUUIDCache.PlayerUUIDCache;
import net.kyori.adventure.text.Component;
@@ -67,6 +70,9 @@
private AdventureMapsConfig adventureMapsConfig;
private PlayerUUIDCache playerUUIDCache;
+ private CubesideStatisticsAPI cubesideStatistics;
+ private Statistics statistics;
+
public ChallengesJoinEntities() {
this.entityData = new HashMap<>();
@@ -83,6 +89,10 @@
plugin = this;
playerUUIDCache = (PlayerUUIDCache) getServer().getPluginManager().getPlugin("PlayerUUIDCache");
nmsUtils = getServer().getServicesManager().load(NMSUtils.class);
+
+ cubesideStatistics = getServer().getServicesManager().load(CubesideStatisticsAPI.class);
+ statistics = new Statistics(this);
+
this.globalDataHelper = new ChallengesGlobalDataHelper(this);
this.config = new Config(this);
loadCategoriesAndMaps();
@@ -101,6 +111,7 @@
CommandRouter challengesrouter = new CommandRouter(getCommand("challenges"));
challengesrouter.addCommandMapping(new ChallengesloadCommand(this), "load");
+ challengesrouter.addCommandMapping(new ChallengesStatsCommand(plugin.getStatistics()), "stats");
CommandRouter adventurerouter = new CommandRouter(getCommand("adventure"));
adventurerouter.addCommandMapping(new AdventureLoadCommand(this), "load");
@@ -357,4 +368,12 @@
public Set getAvailableServers() {
return availableServers;
}
+
+ public CubesideStatisticsAPI getCubesideStatistics() {
+ return cubesideStatistics;
+ }
+
+ public Statistics getStatistics() {
+ return statistics;
+ }
}
diff --git a/src/main/java/de/fanta/challengesjoinentities/commands/ChallengesCommand/ChallengesStatsCommand.java b/src/main/java/de/fanta/challengesjoinentities/commands/ChallengesCommand/ChallengesStatsCommand.java
new file mode 100644
index 0000000..c3a0a02
--- /dev/null
+++ b/src/main/java/de/fanta/challengesjoinentities/commands/ChallengesCommand/ChallengesStatsCommand.java
@@ -0,0 +1,107 @@
+package de.fanta.challengesjoinentities.commands.ChallengesCommand;
+
+import de.fanta.challengesjoinentities.ChatUtil;
+import de.fanta.challengesjoinentities.utils.PlayerStatisticsData;
+import de.fanta.challengesjoinentities.utils.Statistics;
+import de.iani.cubesideutils.StringUtil;
+import de.iani.cubesideutils.bukkit.commands.SubCommand;
+import de.iani.cubesideutils.commands.ArgsParser;
+import org.bukkit.ChatColor;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import java.util.ArrayList;
+import java.util.function.Consumer;
+
+public class ChallengesStatsCommand extends SubCommand {
+
+ private final Statistics statistics;
+
+ public ChallengesStatsCommand(Statistics statistics) {
+ this.statistics = statistics;
+ }
+
+ @Override
+ public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) {
+ Statistics.StatType statType = Statistics.StatType.valueOf(args.getNext("SOLO").toUpperCase());
+ String playerName = args.getNext(null);
+
+ Consumer callback = data -> {
+ if (data == null) {
+ ChatUtil.sendErrorMessage(sender, "Für Spieler '" + playerName + "' existieren keine Daten.");
+ return;
+ }
+ if (playerName == null) {
+ ChatUtil.sendNormalMessage(sender, "Deine Speedrun-Statistik " + "(" + statType.getPrefix() + ")");
+ } else {
+ ChatUtil.sendNormalMessage(sender, "Speedrun-Statistik von " + data.getPlayerName() + " (" + statType.getPrefix() + ")");
+ }
+
+
+ int bestTimeThisMonth = data.getBestTimeMonth();
+ if (bestTimeThisMonth < 0) {
+ ChatUtil.sendNormalMessage(sender, ChatUtil.ORANGE + " Beste Zeit: " + ChatUtil.GREEN + formatTime(data.getBestTime()));
+ } else {
+ ChatUtil.sendNormalMessage(sender, ChatUtil.ORANGE + " Beste Zeit: " + ChatUtil.GREEN + (data.getBestTime() < 0 ? "-" : formatTime(data.getBestTime())) + " (Dieser Monat: " + formatTime(bestTimeThisMonth) + ")");
+ }
+
+ int runsPlayerThisMonth = data.getRunsPlayedMonth();
+ if (bestTimeThisMonth < 0) {
+ ChatUtil.sendNormalMessage(sender, ChatUtil.ORANGE + " Speedruns gespielt: " + ChatUtil.GREEN + data.getRunsPlayed());
+ } else {
+ ChatUtil.sendNormalMessage(sender, ChatUtil.ORANGE + " Speedruns gespielt: " + ChatUtil.GREEN + (data.getRunsPlayed() < 0 ? "-" : data.getRunsPlayed()) + " (Dieser Monat: " + runsPlayerThisMonth + ")");
+ }
+
+ int runsWonThisMonth = data.getRunsWonMonth();
+ if (bestTimeThisMonth < 0) {
+ ChatUtil.sendNormalMessage(sender, ChatUtil.ORANGE + " Speedruns gewonnen: " + ChatUtil.GREEN + data.getRunsWon());
+ } else {
+ ChatUtil.sendNormalMessage(sender, ChatUtil.ORANGE + " Speedruns gewonnen: " + ChatUtil.GREEN + (data.getRunsWon() < 0 ? "-" : data.getRunsWon()) + " (Dieser Monat: " + runsWonThisMonth + ")");
+ }
+
+ int positionThisMonth = data.getRunsWonMonth();
+ if (bestTimeThisMonth < 0) {
+ ChatUtil.sendNormalMessage(sender, ChatUtil.ORANGE + " Position: " + ChatUtil.GREEN + data.getPosition());
+ } else {
+ ChatUtil.sendNormalMessage(sender, ChatUtil.ORANGE + " Position: " + ChatUtil.GREEN + (data.getPosition() < 0 ? "-" : data.getPosition()) + " (Dieser Monat: " + positionThisMonth + ")");
+ }
+ };
+ if (playerName == null) {
+ if (sender instanceof Player player) {
+ statistics.getDataForPlayer(player, statType, callback);
+ } else {
+ sender.sendMessage(ChatColor.GREEN + "Für die Konsole existieren keine Daten.");
+ }
+ } else {
+ try {
+ int pos = Integer.parseInt(playerName);
+ statistics.getDataForPositionIfExists(pos, statType, callback);
+ } catch (NumberFormatException e) {
+ statistics.getDataForPlayerIfExists(playerName, statType, callback);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public ArrayList onTabComplete(CommandSender sender, Command command, String alias, ArgsParser args) {
+ int i = args.remaining();
+ if (i == 1) {
+ ArrayList li = new ArrayList<>();
+ for (Statistics.StatType statType : Statistics.StatType.values()) {
+ li.add(statType.getPrefix());
+ }
+ return li;
+ }
+ return new ArrayList<>();
+ }
+
+ public String formatTime(long time) {
+ String formattime = StringUtil.formatTimespan((time / 1000) * 1000, "1 Tage, ", ":", "", "", "", ":", false, true);
+ if (formattime.startsWith("1 Tage")) {
+ return StringUtil.formatTimespan((time / 1000) * 1000, " Tag, ", ":", "", "", "", ":", false, true);
+ }
+ return formattime;
+ }
+}
diff --git a/src/main/java/de/fanta/challengesjoinentities/utils/PlayerStatisticsData.java b/src/main/java/de/fanta/challengesjoinentities/utils/PlayerStatisticsData.java
new file mode 100644
index 0000000..3b39b99
--- /dev/null
+++ b/src/main/java/de/fanta/challengesjoinentities/utils/PlayerStatisticsData.java
@@ -0,0 +1,69 @@
+package de.fanta.challengesjoinentities.utils;
+
+import java.util.UUID;
+
+public class PlayerStatisticsData {
+ private final UUID playerUUID;
+ private final String playerName;
+ private final int runsPlayed;
+ private final int runsPlayedMonth;
+ private final int runsWon;
+ private final int runsWonMonth;
+ private final int bestTime;
+ private final int bestTimeMonth;
+ private final int position;
+ private final int positionMonth;
+
+ public PlayerStatisticsData(UUID uniqueId, String name, int runsPlayed, int runsPlayedMonth, int runsWon, int runsWonMonth, int bestTime, int bestTimeMonth, int position, int positionMonth) {
+ this.playerUUID = uniqueId;
+ this.playerName = name;
+ this.runsPlayed = runsPlayed;
+ this.runsPlayedMonth = runsPlayedMonth;
+ this.runsWon = runsWon;
+ this.runsWonMonth = runsWonMonth;
+ this.bestTime = bestTime;
+ this.bestTimeMonth = bestTimeMonth;
+ this.position = position;
+ this.positionMonth = positionMonth;
+ }
+
+ public UUID getPlayerId() {
+ return playerUUID;
+ }
+
+ public String getPlayerName() {
+ return playerName;
+ }
+
+ public int getRunsPlayed() {
+ return runsPlayed;
+ }
+
+ public int getRunsPlayedMonth() {
+ return runsPlayedMonth;
+ }
+
+ public int getRunsWon() {
+ return runsWon;
+ }
+
+ public int getRunsWonMonth() {
+ return runsWonMonth;
+ }
+
+ public int getBestTime() {
+ return bestTime;
+ }
+
+ public int getBestTimeMonth() {
+ return bestTimeMonth;
+ }
+
+ public int getPosition() {
+ return position;
+ }
+
+ public int getPositionMonth() {
+ return positionMonth;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/fanta/challengesjoinentities/utils/Statistics.java b/src/main/java/de/fanta/challengesjoinentities/utils/Statistics.java
new file mode 100644
index 0000000..bf3763c
--- /dev/null
+++ b/src/main/java/de/fanta/challengesjoinentities/utils/Statistics.java
@@ -0,0 +1,207 @@
+package de.fanta.challengesjoinentities.utils;
+
+import de.fanta.challengesjoinentities.ChallengesJoinEntities;
+import de.iani.cubesidestats.api.CubesideStatisticsAPI;
+import de.iani.cubesidestats.api.Ordering;
+import de.iani.cubesidestats.api.PlayerStatistics;
+import de.iani.cubesidestats.api.PlayerStatisticsQueryKey;
+import de.iani.cubesidestats.api.StatisticKey;
+import de.iani.cubesidestats.api.StatisticsQueryKey;
+import de.iani.cubesidestats.api.TimeFrame;
+import org.bukkit.Bukkit;
+import org.bukkit.OfflinePlayer;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+
+public class Statistics {
+ private final CubesideStatisticsAPI statistics;
+
+ private final StatisticKey speedRunsPlayedSolo;
+ private final StatisticKey speedRunsWonSolo;
+ private final StatisticKey speedRunsTimeSolo;
+
+ private final StatisticKey speedRunsPlayedDuo;
+ private final StatisticKey speedRunsWonDuo;
+ private final StatisticKey speedRunsTimeDuo;
+
+ private final StatisticKey speedRunsPlayedTeam;
+ private final StatisticKey speedRunsWonTeam;
+ private final StatisticKey speedRunsTimeTeam;
+
+ public Statistics(ChallengesJoinEntities plugin) {
+ statistics = plugin.getCubesideStatistics();
+
+ speedRunsPlayedSolo = statistics.getStatisticKey("challenge.speedruns.solo.played");
+ speedRunsPlayedSolo.setDisplayName("Challenge - SpeedRun's gespielt (Solo)");
+ speedRunsPlayedSolo.setIsMonthlyStats(true);
+
+ speedRunsWonSolo = statistics.getStatisticKey("challenge.speedruns.solo.won");
+ speedRunsWonSolo.setDisplayName("Challenge - SpeedRun's gewonnen (Solo)");
+ speedRunsWonSolo.setIsMonthlyStats(true);
+
+ speedRunsTimeSolo = statistics.getStatisticKey("challenge.speedruns.solo.time");
+ speedRunsTimeSolo.setDisplayName("Beste Zeit (Solo)");
+ speedRunsTimeSolo.setIsMonthlyStats(true);
+
+
+ speedRunsPlayedDuo = statistics.getStatisticKey("challenge.speedruns.duo.played");
+ speedRunsPlayedDuo.setDisplayName("Challenge - SpeedRun's gespielt (Duo)");
+ speedRunsPlayedDuo.setIsMonthlyStats(true);
+
+ speedRunsWonDuo = statistics.getStatisticKey("challenge.speedruns.duo.won");
+ speedRunsWonDuo.setDisplayName("Challenge - SpeedRun's gewonnen (Duo)");
+ speedRunsWonDuo.setIsMonthlyStats(true);
+
+ speedRunsTimeDuo = statistics.getStatisticKey("challenge.speedruns.duo.time");
+ speedRunsTimeDuo.setDisplayName("Beste Zeit (Duo)");
+ speedRunsTimeDuo.setIsMonthlyStats(true);
+
+
+ speedRunsPlayedTeam = statistics.getStatisticKey("challenge.speedruns.team.played");
+ speedRunsPlayedTeam.setDisplayName("Challenge - SpeedRun's gespielt (Team)");
+ speedRunsPlayedTeam.setIsMonthlyStats(true);
+
+ speedRunsWonTeam = statistics.getStatisticKey("challenge.speedruns.team.won");
+ speedRunsWonTeam.setDisplayName("Challenge - SpeedRun's gewonnen (Team)");
+ speedRunsWonTeam.setIsMonthlyStats(true);
+
+ speedRunsTimeTeam = statistics.getStatisticKey("challenge.speedruns.team.time");
+ speedRunsTimeTeam.setDisplayName("Beste Zeit (Team)");
+ speedRunsTimeTeam.setIsMonthlyStats(true);
+ }
+
+ public void getDataForPlayer(OfflinePlayer player, StatType statType, Consumer callback) {
+ List keys = new ArrayList<>();
+ PlayerStatistics ps = statistics.getStatistics(player.getUniqueId());
+
+ PlayerStatisticsQueryKey kRunsPlayed = null;
+ PlayerStatisticsQueryKey kRunsPlayedMonth = null;
+
+ PlayerStatisticsQueryKey kRunsWon = null;
+ PlayerStatisticsQueryKey kRunsWonMonth = null;
+
+ PlayerStatisticsQueryKey kBestTime = null;
+ PlayerStatisticsQueryKey kBestTimeMonth = null;
+
+ PlayerStatisticsQueryKey kPosition = null;
+ PlayerStatisticsQueryKey kPositionMonth = null;
+
+ if (statType == StatType.SOLO) {
+ keys.add(kRunsPlayed = new PlayerStatisticsQueryKey(ps, speedRunsPlayedSolo, PlayerStatisticsQueryKey.QueryType.SCORE));
+ keys.add(kRunsPlayedMonth = new PlayerStatisticsQueryKey(ps, speedRunsPlayedSolo, PlayerStatisticsQueryKey.QueryType.SCORE, TimeFrame.MONTH));
+
+ keys.add(kRunsWon = new PlayerStatisticsQueryKey(ps, speedRunsWonSolo, PlayerStatisticsQueryKey.QueryType.SCORE));
+ keys.add(kRunsWonMonth = new PlayerStatisticsQueryKey(ps, speedRunsWonSolo, PlayerStatisticsQueryKey.QueryType.SCORE, TimeFrame.MONTH));
+
+ keys.add(kBestTime = new PlayerStatisticsQueryKey(ps, speedRunsTimeSolo, PlayerStatisticsQueryKey.QueryType.SCORE));
+ keys.add(kBestTimeMonth = new PlayerStatisticsQueryKey(ps, speedRunsTimeSolo, PlayerStatisticsQueryKey.QueryType.SCORE, TimeFrame.MONTH));
+
+ keys.add(kPosition = new PlayerStatisticsQueryKey(ps, speedRunsTimeSolo, PlayerStatisticsQueryKey.QueryType.POSITION_MAX));
+ keys.add(kPositionMonth = new PlayerStatisticsQueryKey(ps, speedRunsTimeSolo, PlayerStatisticsQueryKey.QueryType.POSITION_MAX, TimeFrame.MONTH));
+ } else if (statType == StatType.DUO) {
+ keys.add(kRunsPlayed = new PlayerStatisticsQueryKey(ps, speedRunsPlayedDuo, PlayerStatisticsQueryKey.QueryType.SCORE));
+ keys.add(kRunsPlayedMonth = new PlayerStatisticsQueryKey(ps, speedRunsPlayedDuo, PlayerStatisticsQueryKey.QueryType.SCORE, TimeFrame.MONTH));
+
+ keys.add(kRunsWon = new PlayerStatisticsQueryKey(ps, speedRunsWonDuo, PlayerStatisticsQueryKey.QueryType.SCORE));
+ keys.add(kRunsWonMonth = new PlayerStatisticsQueryKey(ps, speedRunsWonDuo, PlayerStatisticsQueryKey.QueryType.SCORE, TimeFrame.MONTH));
+
+ keys.add(kBestTime = new PlayerStatisticsQueryKey(ps, speedRunsTimeDuo, PlayerStatisticsQueryKey.QueryType.SCORE));
+ keys.add(kBestTimeMonth = new PlayerStatisticsQueryKey(ps, speedRunsTimeDuo, PlayerStatisticsQueryKey.QueryType.SCORE, TimeFrame.MONTH));
+
+ keys.add(kPosition = new PlayerStatisticsQueryKey(ps, speedRunsTimeDuo, PlayerStatisticsQueryKey.QueryType.POSITION_MAX));
+ keys.add(kPositionMonth = new PlayerStatisticsQueryKey(ps, speedRunsTimeDuo, PlayerStatisticsQueryKey.QueryType.POSITION_MAX, TimeFrame.MONTH));
+ } else if (statType == StatType.TEAM) {
+ keys.add(kRunsPlayed = new PlayerStatisticsQueryKey(ps, speedRunsPlayedTeam, PlayerStatisticsQueryKey.QueryType.SCORE));
+ keys.add(kRunsPlayedMonth = new PlayerStatisticsQueryKey(ps, speedRunsPlayedTeam, PlayerStatisticsQueryKey.QueryType.SCORE, TimeFrame.MONTH));
+
+ keys.add(kRunsWon = new PlayerStatisticsQueryKey(ps, speedRunsWonTeam, PlayerStatisticsQueryKey.QueryType.SCORE));
+ keys.add(kRunsWonMonth = new PlayerStatisticsQueryKey(ps, speedRunsWonTeam, PlayerStatisticsQueryKey.QueryType.SCORE, TimeFrame.MONTH));
+
+ keys.add(kBestTime = new PlayerStatisticsQueryKey(ps, speedRunsTimeTeam, PlayerStatisticsQueryKey.QueryType.SCORE));
+ keys.add(kBestTimeMonth = new PlayerStatisticsQueryKey(ps, speedRunsTimeTeam, PlayerStatisticsQueryKey.QueryType.SCORE, TimeFrame.MONTH));
+
+ keys.add(kPosition = new PlayerStatisticsQueryKey(ps, speedRunsTimeTeam, PlayerStatisticsQueryKey.QueryType.POSITION_MAX));
+ keys.add(kPositionMonth = new PlayerStatisticsQueryKey(ps, speedRunsTimeTeam, PlayerStatisticsQueryKey.QueryType.POSITION_MAX, TimeFrame.MONTH));
+ }
+
+ PlayerStatisticsQueryKey finalKRunsPlayed = kRunsPlayed;
+ PlayerStatisticsQueryKey finalKRunsPlayedMonth = kRunsPlayedMonth;
+
+ PlayerStatisticsQueryKey finalKRunsWon = kRunsWon;
+ PlayerStatisticsQueryKey finalKRunsWonMonth = kRunsWonMonth;
+
+ PlayerStatisticsQueryKey finalKBestTime = kBestTime;
+ PlayerStatisticsQueryKey finalKBestTimeMonth = kBestTimeMonth;
+
+ PlayerStatisticsQueryKey finalKPosition = kPosition;
+ PlayerStatisticsQueryKey finalKPositionMonth = kPositionMonth;
+
+ statistics.queryStats(keys, (c) -> {
+ int runsPlayed = c.getOrDefault(finalKRunsPlayed, 0);
+ int runsPlayedMonth = c.getOrDefault(finalKRunsPlayedMonth, 0);
+
+ int runsWon = c.getOrDefault(finalKRunsWon, 0);
+ int runsWonMonth = c.getOrDefault(finalKRunsWonMonth, 0);
+
+ int bestTime = c.getOrDefault(finalKBestTime, 0);
+ int bestTimeMonth = c.getOrDefault(finalKBestTimeMonth, 0);
+
+ int position = c.getOrDefault(finalKPosition, -1);
+ int positionMonth = c.getOrDefault(finalKPositionMonth, -1);
+
+ callback.accept(new PlayerStatisticsData(player.getUniqueId(), player.getName(), runsPlayed, runsPlayedMonth, runsWon, runsWonMonth, bestTime, bestTimeMonth, position, positionMonth));
+ });
+ }
+
+ public void getDataForPositionIfExists(int pos, StatType statType, Consumer callback) {
+ if (pos < 1) {
+ callback.accept(null);
+ return;
+ }
+
+ StatisticKey score = null;
+
+ if (statType == StatType.SOLO) {
+ score = speedRunsTimeSolo;
+ } else if (statType == StatType.DUO) {
+ score = speedRunsTimeDuo;
+ } else if (statType == StatType.TEAM) {
+ score = speedRunsTimeTeam;
+ }
+
+ if (score != null) {
+ score.getTop(pos - 1, 1, Ordering.DESCENDING, TimeFrame.ALL_TIME, (s) -> {
+ if (s.isEmpty()) {
+ callback.accept(null);
+ } else {
+ OfflinePlayer cplayer = Bukkit.getOfflinePlayer(s.get(0).getPlayer().getOwner());
+ getDataForPlayer(cplayer, statType, callback);
+ }
+ });
+ }
+ }
+
+ public void getDataForPlayerIfExists(String player, StatType statType, Consumer callback) {
+ OfflinePlayer cplayer = Bukkit.getOfflinePlayer(player);
+ getDataForPlayer(cplayer, statType, callback);
+ }
+
+ public enum StatType {
+ SOLO("Solo"),
+ DUO("Duo"),
+ TEAM("Team");
+
+ private final String prefix;
+
+ StatType(String prefix) {
+ this.prefix = prefix;
+ }
+
+ public String getPrefix() {
+ return prefix;
+ }
+ }
+}
+
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index 5c49cad..21595e8 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -4,7 +4,7 @@
author: ${project.author}
api-version: 1.13
-depend: [GlobalClient, CubesideUtils, GlobalPort, CubesideNMSUtils]
+depend: [GlobalClient, CubesideUtils, GlobalPort, CubesideNMSUtils, CubesideStatistics]
softdepend: [Challenges, CubesideNPCs]
commands: