diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/Main.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/Main.java index 01eb0ae..6802e3e 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/Main.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/Main.java @@ -4,13 +4,11 @@ import com.gmail.artemis.the.gr8.playerstats.commands.ReloadCommand; import com.gmail.artemis.the.gr8.playerstats.commands.ShareCommand; import com.gmail.artemis.the.gr8.playerstats.commands.StatCommand; import com.gmail.artemis.the.gr8.playerstats.commands.TabCompleter; -import com.gmail.artemis.the.gr8.playerstats.commands.cmdutils.TabCompleteHelper; import com.gmail.artemis.the.gr8.playerstats.config.ConfigHandler; -import com.gmail.artemis.the.gr8.playerstats.enums.DebugLevel; import com.gmail.artemis.the.gr8.playerstats.listeners.JoinListener; import com.gmail.artemis.the.gr8.playerstats.msg.MessageWriter; -import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger; import com.gmail.artemis.the.gr8.playerstats.statistic.ShareManager; +import com.gmail.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler; import net.kyori.adventure.platform.bukkit.BukkitAudiences; import org.bukkit.Bukkit; import org.bukkit.command.PluginCommand; @@ -19,9 +17,9 @@ import org.jetbrains.annotations.NotNull; public class Main extends JavaPlugin { - private BukkitAudiences adventure; + private static BukkitAudiences adventure; - public @NotNull BukkitAudiences adventure() { + public static @NotNull BukkitAudiences adventure() { if (adventure == null) { throw new IllegalStateException("Tried to access Adventure when the plugin was disabled!"); } @@ -33,27 +31,24 @@ public class Main extends JavaPlugin { //initialize the Adventure library adventure = BukkitAudiences.create(this); - //first get an instance of all the classes that need to be passed along to different classes + //first get an instance of all the classes that need to be initialized or passed along to different classes ConfigHandler config = new ConfigHandler(this); MessageWriter messageWriter = new MessageWriter(config); - ShareManager shareManager = new ShareManager(config); + OfflinePlayerHandler offlinePlayerHandler = new OfflinePlayerHandler(); - //initialize the threadManager - ThreadManager threadManager = new ThreadManager(adventure(), config, messageWriter, shareManager); - ThreadManager threadManager = new ThreadManager(adventure(), config, messageWriter, this); - TabCompleteHelper tab = new TabCompleteHelper(); - Bukkit.getLogger().info(tab.getEntityKilledSuggestions().toString()); + ThreadManager threadManager = ThreadManager.getInstance(config, messageWriter, offlinePlayerHandler); + ShareManager shareManager = ShareManager.getInstance(config); //register all commands and the tabCompleter PluginCommand statcmd = this.getCommand("statistic"); if (statcmd != null) { - statcmd.setExecutor(new StatCommand(adventure(), messageWriter, threadManager)); - statcmd.setTabCompleter(new TabCompleter()); + statcmd.setExecutor(new StatCommand(messageWriter, threadManager, offlinePlayerHandler)); + statcmd.setTabCompleter(new TabCompleter(offlinePlayerHandler)); } PluginCommand reloadcmd = this.getCommand("statisticreload"); if (reloadcmd != null) reloadcmd.setExecutor(new ReloadCommand(threadManager)); PluginCommand sharecmd = this.getCommand("statisticshare"); - if (sharecmd != null) sharecmd.setExecutor(new ShareCommand(adventure(), shareManager)); + if (sharecmd != null) sharecmd.setExecutor(new ShareCommand(shareManager)); //register the listener Bukkit.getPluginManager().registerEvents(new JoinListener(threadManager), this); diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/ThreadManager.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/ThreadManager.java index 8ef27df..2e06209 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/ThreadManager.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/ThreadManager.java @@ -3,36 +3,38 @@ package com.gmail.artemis.the.gr8.playerstats; import com.gmail.artemis.the.gr8.playerstats.config.ConfigHandler; import com.gmail.artemis.the.gr8.playerstats.msg.MessageWriter; import com.gmail.artemis.the.gr8.playerstats.reload.ReloadThread; -import com.gmail.artemis.the.gr8.playerstats.statistic.ShareManager; import com.gmail.artemis.the.gr8.playerstats.models.StatRequest; import com.gmail.artemis.the.gr8.playerstats.statistic.StatThread; import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger; +import com.gmail.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler; import net.kyori.adventure.platform.bukkit.BukkitAudiences; import org.bukkit.command.CommandSender; import java.util.HashMap; -public class ThreadManager { +public final class ThreadManager { - private final int threshold = 10; + private static volatile ThreadManager instance; + + private final static int threshold = 10; private int statThreadID; private int reloadThreadID; - private final BukkitAudiences adventure; + private static BukkitAudiences adventure; private static ConfigHandler config; private static MessageWriter messageWriter; - private final ShareManager shareManager; + private final OfflinePlayerHandler offlinePlayerHandler; private ReloadThread lastActiveReloadThread; private StatThread lastActiveStatThread; private final HashMap statThreads; private static long lastRecordedCalcTime; - public ThreadManager(BukkitAudiences a, ConfigHandler c, MessageWriter m, ShareManager s) { - adventure = a; + private ThreadManager(ConfigHandler c, MessageWriter m, OfflinePlayerHandler o) { + adventure = Main.adventure(); config = c; messageWriter = m; - shareManager = s; + offlinePlayerHandler = o; statThreads = new HashMap<>(); statThreadID = 0; @@ -42,11 +44,28 @@ public class ThreadManager { startReloadThread(null); } + public static ThreadManager getInstance(ConfigHandler config, MessageWriter messageWriter, OfflinePlayerHandler offlinePlayerHandler) { + ThreadManager threadManager = instance; + if (threadManager != null) { + return threadManager; + } + synchronized (ThreadManager.class) { + if (instance == null) { + instance = new ThreadManager(config, messageWriter, offlinePlayerHandler); + } + return instance; + } + } + + public static int getTaskThreshold() { + return threshold; + } + public void startReloadThread(CommandSender sender) { if (lastActiveReloadThread == null || !lastActiveReloadThread.isAlive()) { reloadThreadID += 1; - lastActiveReloadThread = new ReloadThread(adventure, config, messageWriter, threshold, reloadThreadID, lastActiveStatThread, sender); + lastActiveReloadThread = new ReloadThread(config, messageWriter, offlinePlayerHandler, reloadThreadID, lastActiveStatThread, sender); lastActiveReloadThread.start(); } else { @@ -83,7 +102,7 @@ public class ThreadManager { } private void startNewStatThread(StatRequest request) { - lastActiveStatThread = new StatThread(adventure, config, messageWriter, statThreadID, threshold, request, lastActiveReloadThread, shareManager); + lastActiveStatThread = new StatThread(config, messageWriter, offlinePlayerHandler, statThreadID, request, lastActiveReloadThread); statThreads.put(request.getCommandSender().getName(), lastActiveStatThread); lastActiveStatThread.start(); } diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/ReloadCommand.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/ReloadCommand.java index aedf310..54de10d 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/ReloadCommand.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/ReloadCommand.java @@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull; public class ReloadCommand implements CommandExecutor { - private final ThreadManager threadManager; + private static ThreadManager threadManager; public ReloadCommand(ThreadManager t) { threadManager = t; diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/ShareCommand.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/ShareCommand.java index 59f152d..6723587 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/ShareCommand.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/ShareCommand.java @@ -1,5 +1,6 @@ package com.gmail.artemis.the.gr8.playerstats.commands; +import com.gmail.artemis.the.gr8.playerstats.Main; import com.gmail.artemis.the.gr8.playerstats.statistic.ShareManager; import net.kyori.adventure.platform.bukkit.BukkitAudiences; import org.bukkit.command.Command; @@ -11,11 +12,11 @@ import java.util.UUID; public class ShareCommand implements CommandExecutor { - private final BukkitAudiences adventure; - private final ShareManager shareManager; + private static BukkitAudiences adventure; + private static ShareManager shareManager; - public ShareCommand(BukkitAudiences a, ShareManager s) { - adventure = a; + public ShareCommand(ShareManager s) { + adventure = Main.adventure(); shareManager = s; } diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/StatCommand.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/StatCommand.java index ebce446..8cd26e3 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/StatCommand.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/StatCommand.java @@ -1,5 +1,6 @@ package com.gmail.artemis.the.gr8.playerstats.commands; +import com.gmail.artemis.the.gr8.playerstats.Main; import com.gmail.artemis.the.gr8.playerstats.ThreadManager; import com.gmail.artemis.the.gr8.playerstats.enums.Target; import com.gmail.artemis.the.gr8.playerstats.utils.EnumHandler; @@ -23,14 +24,16 @@ import org.jetbrains.annotations.Nullable; public class StatCommand implements CommandExecutor { - private final BukkitAudiences adventure; + private static BukkitAudiences adventure; + private static ThreadManager threadManager; private final MessageWriter messageWriter; - private final ThreadManager threadManager; + private final OfflinePlayerHandler offlinePlayerHandler; - public StatCommand(BukkitAudiences a, MessageWriter m, ThreadManager t) { - adventure = a; - messageWriter = m; + public StatCommand(MessageWriter m, ThreadManager t, OfflinePlayerHandler o) { + adventure = Main.adventure(); threadManager = t; + messageWriter = m; + offlinePlayerHandler = o; } @Override @@ -90,7 +93,7 @@ public class StatCommand implements CommandExecutor { request.setSelection(Target.SERVER); } } - else if (OfflinePlayerHandler.isRelevantPlayer(arg) && request.getPlayerName() == null) { + else if (offlinePlayerHandler.isRelevantPlayer(arg) && request.getPlayerName() == null) { request.setPlayerName(arg); request.setSelection(Target.PLAYER); } diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/TabCompleter.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/TabCompleter.java index fb05915..17cf909 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/TabCompleter.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/TabCompleter.java @@ -14,18 +14,22 @@ import java.util.stream.Collectors; public class TabCompleter implements org.bukkit.command.TabCompleter { - private final List commandOptions; + private final OfflinePlayerHandler offlinePlayerHandler; private final TabCompleteHelper tabCompleteHelper; + private final List commandOptions; + //TODO add "example" to the list - public TabCompleter() { + public TabCompleter(OfflinePlayerHandler o) { + offlinePlayerHandler = o; + tabCompleteHelper = new TabCompleteHelper(); + commandOptions = new ArrayList<>(); commandOptions.add("top"); commandOptions.add("player"); commandOptions.add("server"); commandOptions.add("me"); - tabCompleteHelper = new TabCompleteHelper(); } //args[0] = statistic (length = 1) @@ -64,7 +68,7 @@ public class TabCompleter implements org.bukkit.command.TabCompleter { tabSuggestions = commandOptions; } else { - tabSuggestions = getTabSuggestions(OfflinePlayerHandler.getOfflinePlayerNames(), currentArg); + tabSuggestions = getTabSuggestions(offlinePlayerHandler.getOfflinePlayerNames(), currentArg); } } diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/cmdutils/TabCompleteHelper.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/cmdutils/TabCompleteHelper.java index c21c52e..dca6308 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/cmdutils/TabCompleteHelper.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/cmdutils/TabCompleteHelper.java @@ -8,7 +8,7 @@ import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; -public class TabCompleteHelper { +public final class TabCompleteHelper { private static List itemBrokenSuggestions; private static List entityKilledSuggestions; diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/config/ConfigHandler.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/config/ConfigHandler.java index c2a61d7..19f65f2 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/config/ConfigHandler.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/config/ConfigHandler.java @@ -12,18 +12,18 @@ import java.io.File; public class ConfigHandler { + private static Main plugin; + private static double configVersion; + private File configFile; private FileConfiguration config; - private final Main plugin; - private final double configVersion; public ConfigHandler(Main p) { plugin = p; + configVersion = 5; saveDefaultConfig(); config = YamlConfiguration.loadConfiguration(configFile); - - configVersion = 5; checkConfigVersion(); MyLogger.setDebugLevel(getDebugLevel()); diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/listeners/JoinListener.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/listeners/JoinListener.java index 9bb06e2..b3b11ba 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/listeners/JoinListener.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/listeners/JoinListener.java @@ -7,7 +7,7 @@ import org.bukkit.event.player.PlayerJoinEvent; public class JoinListener implements Listener { - private final ThreadManager threadManager; + private static ThreadManager threadManager; public JoinListener(ThreadManager t) { threadManager = t; diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/models/StatRequest.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/models/StatRequest.java index a854c99..cd2b3fa 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/models/StatRequest.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/models/StatRequest.java @@ -9,8 +9,7 @@ import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.EntityType; import org.jetbrains.annotations.NotNull; - -public class StatRequest { +public final class StatRequest { private final CommandSender sender; private Statistic statistic; diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/models/StatResult.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/models/StatResult.java index b6c1add..891efca 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/models/StatResult.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/models/StatResult.java @@ -4,6 +4,5 @@ import net.kyori.adventure.text.TextComponent; import java.util.UUID; - public record StatResult(String playerName, TextComponent statResult, int ID, UUID uuid) { } diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/msg/MessageWriter.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/msg/MessageWriter.java index e2e0cec..fe42af5 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/msg/MessageWriter.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/msg/MessageWriter.java @@ -1,17 +1,19 @@ package com.gmail.artemis.the.gr8.playerstats.msg; import com.gmail.artemis.the.gr8.playerstats.enums.DebugLevel; +import com.gmail.artemis.the.gr8.playerstats.enums.PluginColor; import com.gmail.artemis.the.gr8.playerstats.enums.Target; import com.gmail.artemis.the.gr8.playerstats.config.ConfigHandler; import com.gmail.artemis.the.gr8.playerstats.enums.Unit; -import com.gmail.artemis.the.gr8.playerstats.msg.msgutils.ExampleMessage; -import com.gmail.artemis.the.gr8.playerstats.msg.msgutils.HelpMessage; -import com.gmail.artemis.the.gr8.playerstats.msg.msgutils.LanguageKeyHandler; +import com.gmail.artemis.the.gr8.playerstats.msg.msgutils.*; import com.gmail.artemis.the.gr8.playerstats.models.StatRequest; +import com.gmail.artemis.the.gr8.playerstats.utils.EnumHandler; import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.event.HoverEvent; import org.bukkit.Bukkit; import org.bukkit.Statistic; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/msg/msgutils/LanguageKeyHandler.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/msg/msgutils/LanguageKeyHandler.java index 31c0ff5..44c3a0a 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/msg/msgutils/LanguageKeyHandler.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/msg/msgutils/LanguageKeyHandler.java @@ -13,11 +13,10 @@ import java.util.HashMap; public final class LanguageKeyHandler { - private final HashMap statNameKeys; + private static HashMap statNameKeys; public LanguageKeyHandler() { - statNameKeys = new HashMap<>(); - generateStatNameKeys(); + statNameKeys = generateStatNameKeys(); } public String getStatKey(@NotNull Statistic statistic) { @@ -72,47 +71,46 @@ public final class LanguageKeyHandler { } } - private void generateDefaultKeys() { - Arrays.stream(Statistic.values()).forEach(statistic -> statNameKeys.put(statistic, statistic.toString().toLowerCase())); - } - - private void generateStatNameKeys() { + private @NotNull HashMap generateStatNameKeys() { //get the enum names for all statistics first - generateDefaultKeys(); + HashMap statNames = new HashMap<>(Statistic.values().length); + Arrays.stream(Statistic.values()).forEach(statistic -> statNames.put(statistic, statistic.toString().toLowerCase())); //replace the ones for which the language key is different from the enum name - statNameKeys.put(Statistic.ARMOR_CLEANED, "clean_armor"); - statNameKeys.put(Statistic.BANNER_CLEANED, "clean_banner"); - statNameKeys.put(Statistic.DROP_COUNT, "drop"); - statNameKeys.put(Statistic.CAKE_SLICES_EATEN, "eat_cake_slice"); - statNameKeys.put(Statistic.ITEM_ENCHANTED, "enchant_item"); - statNameKeys.put(Statistic.CAULDRON_FILLED, "fill_cauldron"); - statNameKeys.put(Statistic.DISPENSER_INSPECTED, "inspect_dispenser"); - statNameKeys.put(Statistic.DROPPER_INSPECTED, "inspect_dropper"); - statNameKeys.put(Statistic.HOPPER_INSPECTED, "inspect_hopper"); - statNameKeys.put(Statistic.BEACON_INTERACTION, "interact_with_beacon"); - statNameKeys.put(Statistic.BREWINGSTAND_INTERACTION, "interact_with_brewingstand"); - statNameKeys.put(Statistic.CRAFTING_TABLE_INTERACTION, "interact_with_crafting_table"); - statNameKeys.put(Statistic.FURNACE_INTERACTION, "interact_with_furnace"); - statNameKeys.put(Statistic.CHEST_OPENED, "open_chest"); - statNameKeys.put(Statistic.ENDERCHEST_OPENED, "open_enderchest"); - statNameKeys.put(Statistic.SHULKER_BOX_OPENED, "open_shulker_box"); - statNameKeys.put(Statistic.NOTEBLOCK_PLAYED, "play_noteblock"); - statNameKeys.put(Statistic.PLAY_ONE_MINUTE, "play_time"); - statNameKeys.put(Statistic.RECORD_PLAYED, "play_record"); - statNameKeys.put(Statistic.FLOWER_POTTED, "pot_flower"); - statNameKeys.put(Statistic.TRAPPED_CHEST_TRIGGERED, "trigger_trapped_chest"); - statNameKeys.put(Statistic.NOTEBLOCK_TUNED, "tune_noteblock"); - statNameKeys.put(Statistic.CAULDRON_USED, "use_cauldron"); + statNames.put(Statistic.ARMOR_CLEANED, "clean_armor"); + statNames.put(Statistic.BANNER_CLEANED, "clean_banner"); + statNames.put(Statistic.DROP_COUNT, "drop"); + statNames.put(Statistic.CAKE_SLICES_EATEN, "eat_cake_slice"); + statNames.put(Statistic.ITEM_ENCHANTED, "enchant_item"); + statNames.put(Statistic.CAULDRON_FILLED, "fill_cauldron"); + statNames.put(Statistic.DISPENSER_INSPECTED, "inspect_dispenser"); + statNames.put(Statistic.DROPPER_INSPECTED, "inspect_dropper"); + statNames.put(Statistic.HOPPER_INSPECTED, "inspect_hopper"); + statNames.put(Statistic.BEACON_INTERACTION, "interact_with_beacon"); + statNames.put(Statistic.BREWINGSTAND_INTERACTION, "interact_with_brewingstand"); + statNames.put(Statistic.CRAFTING_TABLE_INTERACTION, "interact_with_crafting_table"); + statNames.put(Statistic.FURNACE_INTERACTION, "interact_with_furnace"); + statNames.put(Statistic.CHEST_OPENED, "open_chest"); + statNames.put(Statistic.ENDERCHEST_OPENED, "open_enderchest"); + statNames.put(Statistic.SHULKER_BOX_OPENED, "open_shulker_box"); + statNames.put(Statistic.NOTEBLOCK_PLAYED, "play_noteblock"); + statNames.put(Statistic.PLAY_ONE_MINUTE, "play_time"); + statNames.put(Statistic.RECORD_PLAYED, "play_record"); + statNames.put(Statistic.FLOWER_POTTED, "pot_flower"); + statNames.put(Statistic.TRAPPED_CHEST_TRIGGERED, "trigger_trapped_chest"); + statNames.put(Statistic.NOTEBLOCK_TUNED, "tune_noteblock"); + statNames.put(Statistic.CAULDRON_USED, "use_cauldron"); //do the same for the statistics that have a subtype - statNameKeys.put(Statistic.DROP, "dropped"); - statNameKeys.put(Statistic.PICKUP, "picked_up"); - statNameKeys.put(Statistic.MINE_BLOCK, "mined"); - statNameKeys.put(Statistic.USE_ITEM, "used"); - statNameKeys.put(Statistic.BREAK_ITEM, "broken"); - statNameKeys.put(Statistic.CRAFT_ITEM, "crafted"); - statNameKeys.put(Statistic.KILL_ENTITY, "killed"); - statNameKeys.put(Statistic.ENTITY_KILLED_BY, "killed_by"); + statNames.put(Statistic.DROP, "dropped"); + statNames.put(Statistic.PICKUP, "picked_up"); + statNames.put(Statistic.MINE_BLOCK, "mined"); + statNames.put(Statistic.USE_ITEM, "used"); + statNames.put(Statistic.BREAK_ITEM, "broken"); + statNames.put(Statistic.CRAFT_ITEM, "crafted"); + statNames.put(Statistic.KILL_ENTITY, "killed"); + statNames.put(Statistic.ENTITY_KILLED_BY, "killed_by"); + + return statNames; } } \ No newline at end of file diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/reload/ReloadAction.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/reload/ReloadAction.java index a061e0d..0bd3dd7 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/reload/ReloadAction.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/reload/ReloadAction.java @@ -1,5 +1,6 @@ package com.gmail.artemis.the.gr8.playerstats.reload; +import com.gmail.artemis.the.gr8.playerstats.ThreadManager; import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger; import com.gmail.artemis.the.gr8.playerstats.utils.UnixTimeHandler; import org.bukkit.OfflinePlayer; @@ -8,9 +9,9 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.RecursiveAction; -public class ReloadAction extends RecursiveAction { +public final class ReloadAction extends RecursiveAction { - private final int threshold; + private static int threshold; private final OfflinePlayer[] players; private final int start; @@ -20,21 +21,20 @@ public class ReloadAction extends RecursiveAction { private final ConcurrentHashMap offlinePlayerUUIDs; /** Fills a ConcurrentHashMap with PlayerNames and UUIDs for all OfflinePlayers that should be included in statistic calculations. - * @param threshold the maximum length of OfflinePlayers to process in one task * @param players array of all OfflinePlayers (straight from Bukkit) * @param lastPlayedLimit whether to set a limit based on last-played-date * @param offlinePlayerUUIDs the ConcurrentHashMap to put resulting playerNames and UUIDs on */ - public ReloadAction(int threshold, OfflinePlayer[] players, + public ReloadAction(OfflinePlayer[] players, int lastPlayedLimit, ConcurrentHashMap offlinePlayerUUIDs) { - this(threshold, players, 0, players.length, lastPlayedLimit, offlinePlayerUUIDs); + this(players, 0, players.length, lastPlayedLimit, offlinePlayerUUIDs); } - protected ReloadAction(int threshold, OfflinePlayer[] players, int start, int end, + private ReloadAction(OfflinePlayer[] players, int start, int end, int lastPlayedLimit, ConcurrentHashMap offlinePlayerUUIDs) { + threshold = ThreadManager.getTaskThreshold(); - this.threshold = threshold; this.players = players; this.start = start; this.end = end; @@ -53,9 +53,9 @@ public class ReloadAction extends RecursiveAction { } else { final int split = length / 2; - final ReloadAction subTask1 = new ReloadAction(threshold, players, start, (start + split), + final ReloadAction subTask1 = new ReloadAction(players, start, (start + split), lastPlayedLimit, offlinePlayerUUIDs); - final ReloadAction subTask2 = new ReloadAction(threshold, players, (start + split), end, + final ReloadAction subTask2 = new ReloadAction(players, (start + split), end, lastPlayedLimit, offlinePlayerUUIDs); //queue and compute all subtasks in the right order diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/reload/ReloadThread.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/reload/ReloadThread.java index 6d1ecaf..6b69530 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/reload/ReloadThread.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/reload/ReloadThread.java @@ -1,5 +1,6 @@ package com.gmail.artemis.the.gr8.playerstats.reload; +import com.gmail.artemis.the.gr8.playerstats.Main; import com.gmail.artemis.the.gr8.playerstats.ThreadManager; import com.gmail.artemis.the.gr8.playerstats.config.ConfigHandler; import com.gmail.artemis.the.gr8.playerstats.enums.DebugLevel; @@ -22,25 +23,28 @@ import java.util.function.Predicate; public class ReloadThread extends Thread { - private final int threshold; private final int reloadThreadID; private final StatThread statThread; - private final BukkitAudiences adventure; + private static BukkitAudiences adventure; private static ConfigHandler config; - private static MessageWriter messageWriter; + private final MessageWriter messageWriter; + private final OfflinePlayerHandler offlinePlayerHandler; + private final CommandSender sender; - public ReloadThread(BukkitAudiences a, ConfigHandler c, MessageWriter m, int threshold, int ID, @Nullable StatThread s, @Nullable CommandSender se) { - this.threshold = threshold; + + public ReloadThread(ConfigHandler c, MessageWriter m, OfflinePlayerHandler o, int ID, @Nullable StatThread s, @Nullable CommandSender se) { reloadThreadID = ID; statThread = s; - adventure = a; config = c; messageWriter = m; sender = se; + adventure = Main.adventure(); + offlinePlayerHandler = o; + this.setName("ReloadThread-" + reloadThreadID); MyLogger.threadCreated(this.getName()); } @@ -112,13 +116,13 @@ public class ReloadThread extends Thread { int size = offlinePlayers != null ? offlinePlayers.length : 16; ConcurrentHashMap playerMap = new ConcurrentHashMap<>(size); - ReloadAction task = new ReloadAction(threshold, offlinePlayers, config.getLastPlayedLimit(), playerMap); + ReloadAction task = new ReloadAction(offlinePlayers, config.getLastPlayedLimit(), playerMap); MyLogger.actionCreated((offlinePlayers != null) ? offlinePlayers.length : 0); ForkJoinPool.commonPool().invoke(task); MyLogger.actionFinished(1); - OfflinePlayerHandler.updateOfflinePlayerList(playerMap); + offlinePlayerHandler.updateOfflinePlayerList(playerMap); MyLogger.logTimeTaken("ReloadThread", - ("loaded " + OfflinePlayerHandler.getOfflinePlayerCount() + " offline players"), time); + ("loaded " + offlinePlayerHandler.getOfflinePlayerCount() + " offline players"), time); } } \ No newline at end of file diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/ShareManager.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/ShareManager.java index 39941ec..85985f5 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/ShareManager.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/ShareManager.java @@ -15,6 +15,8 @@ import java.util.concurrent.atomic.AtomicInteger; public class ShareManager { + private static volatile ShareManager instance; + private boolean isEnabled; private int waitingTime; @@ -22,9 +24,10 @@ public class ShareManager { private ConcurrentHashMap statResults = null; private ConcurrentHashMap shareTimeStamp = null; - public ShareManager(ConfigHandler config) { + private ShareManager(ConfigHandler config) { isEnabled = config.enableStatSharing(); waitingTime = config.getStatShareWaitingTime(); + if (isEnabled) { resultID = new AtomicInteger(); statResults = new ConcurrentHashMap<>(); @@ -32,17 +35,37 @@ public class ShareManager { } } - public boolean isEnabled() { - return this.isEnabled; + public static ShareManager getInstance(ConfigHandler config) { + ShareManager shareManager = instance; + if (shareManager != null) { + return shareManager; + } + synchronized (ShareManager.class) { + if (instance == null) { + instance = new ShareManager(config); + } + return instance; + } } - public void updateSettings(ConfigHandler config) { + public synchronized void updateSettings(ConfigHandler config) { isEnabled = config.enableStatSharing(); waitingTime = config.getStatShareWaitingTime(); + + //if we went from disabled to enabled, initialize the HashMaps if (isEnabled && statResults == null) { statResults = new ConcurrentHashMap<>(); shareTimeStamp = new ConcurrentHashMap<>(); } + //if we went from enabled to disabled, purge the existing data + else if (!isEnabled && statResults != null) { + statResults = null; + shareTimeStamp = null; + } + } + + public boolean isEnabled() { + return this.isEnabled; } public UUID saveStatResult(String playerName, TextComponent statResult) { diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/StatThread.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/StatThread.java index f19dd2a..8598b3a 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/StatThread.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/StatThread.java @@ -1,5 +1,6 @@ package com.gmail.artemis.the.gr8.playerstats.statistic; +import com.gmail.artemis.the.gr8.playerstats.Main; import com.gmail.artemis.the.gr8.playerstats.enums.Target; import com.gmail.artemis.the.gr8.playerstats.models.StatRequest; import com.gmail.artemis.the.gr8.playerstats.msg.MessageWriter; @@ -22,26 +23,28 @@ import java.util.stream.Collectors; public class StatThread extends Thread { - private final int threshold; - private final ReloadThread reloadThread; - private final ShareManager shareManager; - - private final BukkitAudiences adventure; private static ConfigHandler config; - private static MessageWriter messageWriter; + private final MessageWriter messageWriter; + private final OfflinePlayerHandler offlinePlayerHandler; + + private final ReloadThread reloadThread; private final StatRequest request; + private static ShareManager shareManager; + private static BukkitAudiences adventure; - public StatThread(BukkitAudiences a, ConfigHandler c, MessageWriter m, int ID, int threshold, StatRequest s, @Nullable ReloadThread r, @Nullable ShareManager sm) { - this.threshold = threshold; - reloadThread = r; - shareManager = sm; - adventure = a; + public StatThread(ConfigHandler c, MessageWriter m, OfflinePlayerHandler o, int ID, StatRequest s, @Nullable ReloadThread r) { config = c; messageWriter = m; + offlinePlayerHandler = o; + + reloadThread = r; request = s; + adventure = Main.adventure(); + shareManager = ShareManager.getInstance(config); + this.setName("StatThread-" + request.getCommandSender().getName() + "-" + ID); MyLogger.threadCreated(this.getName()); } @@ -112,11 +115,11 @@ public class StatThread extends Thread { private @NotNull ConcurrentHashMap getAllStats() throws ConcurrentModificationException { long time = System.currentTimeMillis(); - int size = OfflinePlayerHandler.getOfflinePlayerCount() != 0 ? OfflinePlayerHandler.getOfflinePlayerCount() : 16; + int size = offlinePlayerHandler.getOfflinePlayerCount() != 0 ? offlinePlayerHandler.getOfflinePlayerCount() : 16; ConcurrentHashMap playerStats = new ConcurrentHashMap<>(size); - ImmutableList playerNames = ImmutableList.copyOf(OfflinePlayerHandler.getOfflinePlayerNames()); + ImmutableList playerNames = ImmutableList.copyOf(offlinePlayerHandler.getOfflinePlayerNames()); - TopStatAction task = new TopStatAction(threshold, playerNames, request, playerStats); + TopStatAction task = new TopStatAction(offlinePlayerHandler, playerNames, request, playerStats); MyLogger.actionCreated(playerNames.size()); ForkJoinPool commonPool = ForkJoinPool.commonPool(); @@ -139,7 +142,7 @@ public class StatThread extends Thread { /** Gets the statistic data for an individual player. If somehow the player cannot be found, this returns 0.*/ private int getIndividualStat() { - OfflinePlayer player = OfflinePlayerHandler.getOfflinePlayer(request.getPlayerName()); + OfflinePlayer player = offlinePlayerHandler.getOfflinePlayer(request.getPlayerName()); if (player != null) { return switch (request.getStatistic().getType()) { case UNTYPED -> player.getStatistic(request.getStatistic()); diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/TopStatAction.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/TopStatAction.java index 0df89e1..d620723 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/TopStatAction.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/TopStatAction.java @@ -1,5 +1,6 @@ package com.gmail.artemis.the.gr8.playerstats.statistic; +import com.gmail.artemis.the.gr8.playerstats.ThreadManager; import com.gmail.artemis.the.gr8.playerstats.models.StatRequest; import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger; import com.gmail.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler; @@ -11,10 +12,11 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.RecursiveAction; -public class TopStatAction extends RecursiveAction { +public final class TopStatAction extends RecursiveAction { - private final int threshold; + private static int threshold; + private final OfflinePlayerHandler offlinePlayerHandler; private final ImmutableList playerNames; private final StatRequest request; private final ConcurrentHashMap playerStats; @@ -22,15 +24,16 @@ public class TopStatAction extends RecursiveAction { /** * Gets the statistic numbers for all players whose name is on the list, puts them in a ConcurrentHashMap * using the default ForkJoinPool, and returns the ConcurrentHashMap when everything is done - * @param threshold the maximum length of playerNames to process in one task + * @param offlinePlayerHandler the OfflinePlayerHandler to convert playerNames into Players * @param playerNames ImmutableList of playerNames for players that should be included in stat calculations * @param statRequest a validated statRequest * @param playerStats the ConcurrentHashMap to put the results on */ - public TopStatAction(int threshold, ImmutableList playerNames, StatRequest statRequest, ConcurrentHashMap playerStats) { - this.threshold = threshold; - this.playerNames = playerNames; + public TopStatAction(OfflinePlayerHandler offlinePlayerHandler, ImmutableList playerNames, StatRequest statRequest, ConcurrentHashMap playerStats) { + threshold = ThreadManager.getTaskThreshold(); + this.offlinePlayerHandler = offlinePlayerHandler; + this.playerNames = playerNames; this.request = statRequest; this.playerStats = playerStats; @@ -43,8 +46,8 @@ public class TopStatAction extends RecursiveAction { getStatsDirectly(); } else { - final TopStatAction subTask1 = new TopStatAction(threshold, playerNames.subList(0, playerNames.size()/2), request, playerStats); - final TopStatAction subTask2 = new TopStatAction(threshold, playerNames.subList(playerNames.size()/2, playerNames.size()), request, playerStats); + final TopStatAction subTask1 = new TopStatAction(offlinePlayerHandler, playerNames.subList(0, playerNames.size()/2), request, playerStats); + final TopStatAction subTask2 = new TopStatAction(offlinePlayerHandler, playerNames.subList(playerNames.size()/2, playerNames.size()), request, playerStats); //queue and compute all subtasks in the right order invokeAll(subTask1, subTask2); @@ -57,7 +60,7 @@ public class TopStatAction extends RecursiveAction { do { String playerName = iterator.next(); MyLogger.actionRunning(Thread.currentThread().getName(), playerName, 2); - OfflinePlayer player = OfflinePlayerHandler.getOfflinePlayer(playerName); + OfflinePlayer player = offlinePlayerHandler.getOfflinePlayer(playerName); if (player != null) { int statistic = 0; switch (request.getStatistic().getType()) { diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/EnumHandler.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/EnumHandler.java index 66c9528..1a581ca 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/EnumHandler.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/EnumHandler.java @@ -12,7 +12,7 @@ import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; -public class EnumHandler { +public final class EnumHandler { private final static List blockNames; private final static List entityNames; @@ -50,9 +50,6 @@ public class EnumHandler { .collect(Collectors.toList()); } - private EnumHandler() { - } - public static List getItemNames() { return itemNames; } diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/OfflinePlayerHandler.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/OfflinePlayerHandler.java index 39d93e7..8aa6719 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/OfflinePlayerHandler.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/OfflinePlayerHandler.java @@ -12,27 +12,24 @@ public class OfflinePlayerHandler { private static ConcurrentHashMap offlinePlayerUUIDs; private static ArrayList playerNames; - static { + public OfflinePlayerHandler() { offlinePlayerUUIDs = new ConcurrentHashMap<>(); playerNames = new ArrayList<>(); } - private OfflinePlayerHandler() { - } - /** Checks if a given playerName is on the private HashMap of players that should be included in statistic calculations @param playerName String, case-sensitive */ - public static boolean isRelevantPlayer(String playerName) { + public boolean isRelevantPlayer(String playerName) { return offlinePlayerUUIDs.containsKey(playerName); } /** Returns the number of OfflinePlayers that are included in statistic calculations */ - public static int getOfflinePlayerCount() { + public int getOfflinePlayerCount() { return offlinePlayerUUIDs.size(); } /** Get an ArrayList of names from all OfflinePlayers that should be included in statistic calculations */ - public static ArrayList getOfflinePlayerNames() { + public ArrayList getOfflinePlayerNames() { return playerNames; } @@ -41,7 +38,7 @@ public class OfflinePlayerHandler { * This HashMap is stored as a private variable in OfflinePlayerHandler. * @param playerList ConcurrentHashMap with keys: playerNames and values: UUIDs */ - public static void updateOfflinePlayerList(ConcurrentHashMap playerList) { + public void updateOfflinePlayerList(ConcurrentHashMap playerList) { offlinePlayerUUIDs = playerList; playerNames = Collections.list(offlinePlayerUUIDs.keys()); } @@ -51,7 +48,7 @@ public class OfflinePlayerHandler { * @param playerName name of the target player * @return OfflinePlayer (if this player is on the list, otherwise null) */ - public static @Nullable OfflinePlayer getOfflinePlayer(String playerName) { + public @Nullable OfflinePlayer getOfflinePlayer(String playerName) { if (offlinePlayerUUIDs.get(playerName) != null) { return Bukkit.getOfflinePlayer(offlinePlayerUUIDs.get(playerName)); } diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/UnixTimeHandler.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/UnixTimeHandler.java index e9e1281..321c16a 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/UnixTimeHandler.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/UnixTimeHandler.java @@ -1,7 +1,6 @@ package com.gmail.artemis.the.gr8.playerstats.utils; - -public class UnixTimeHandler { +public final class UnixTimeHandler { /** Calculates whether a player has played recently enough to fall within the lastPlayedLimit. If lastPlayedLimit == 0, this always returns true (since there is no limit).