Loads of minor internal changes regarding static/final classes and variables (#89)

This commit is contained in:
Artemis-the-gr8 2022-07-12 00:29:41 +02:00
parent 3fe8afe216
commit bc0918c4f6
21 changed files with 199 additions and 153 deletions

View File

@ -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.ShareCommand;
import com.gmail.artemis.the.gr8.playerstats.commands.StatCommand; 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.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.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.listeners.JoinListener;
import com.gmail.artemis.the.gr8.playerstats.msg.MessageWriter; 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.statistic.ShareManager;
import com.gmail.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler;
import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.PluginCommand; import org.bukkit.command.PluginCommand;
@ -19,9 +17,9 @@ import org.jetbrains.annotations.NotNull;
public class Main extends JavaPlugin { public class Main extends JavaPlugin {
private BukkitAudiences adventure; private static BukkitAudiences adventure;
public @NotNull BukkitAudiences adventure() { public static @NotNull BukkitAudiences adventure() {
if (adventure == null) { if (adventure == null) {
throw new IllegalStateException("Tried to access Adventure when the plugin was disabled!"); 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 //initialize the Adventure library
adventure = BukkitAudiences.create(this); 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); ConfigHandler config = new ConfigHandler(this);
MessageWriter messageWriter = new MessageWriter(config); MessageWriter messageWriter = new MessageWriter(config);
ShareManager shareManager = new ShareManager(config); OfflinePlayerHandler offlinePlayerHandler = new OfflinePlayerHandler();
//initialize the threadManager ThreadManager threadManager = ThreadManager.getInstance(config, messageWriter, offlinePlayerHandler);
ThreadManager threadManager = new ThreadManager(adventure(), config, messageWriter, shareManager); ShareManager shareManager = ShareManager.getInstance(config);
ThreadManager threadManager = new ThreadManager(adventure(), config, messageWriter, this);
TabCompleteHelper tab = new TabCompleteHelper();
Bukkit.getLogger().info(tab.getEntityKilledSuggestions().toString());
//register all commands and the tabCompleter //register all commands and the tabCompleter
PluginCommand statcmd = this.getCommand("statistic"); PluginCommand statcmd = this.getCommand("statistic");
if (statcmd != null) { if (statcmd != null) {
statcmd.setExecutor(new StatCommand(adventure(), messageWriter, threadManager)); statcmd.setExecutor(new StatCommand(messageWriter, threadManager, offlinePlayerHandler));
statcmd.setTabCompleter(new TabCompleter()); statcmd.setTabCompleter(new TabCompleter(offlinePlayerHandler));
} }
PluginCommand reloadcmd = this.getCommand("statisticreload"); PluginCommand reloadcmd = this.getCommand("statisticreload");
if (reloadcmd != null) reloadcmd.setExecutor(new ReloadCommand(threadManager)); if (reloadcmd != null) reloadcmd.setExecutor(new ReloadCommand(threadManager));
PluginCommand sharecmd = this.getCommand("statisticshare"); 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 //register the listener
Bukkit.getPluginManager().registerEvents(new JoinListener(threadManager), this); Bukkit.getPluginManager().registerEvents(new JoinListener(threadManager), this);

View File

@ -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.config.ConfigHandler;
import com.gmail.artemis.the.gr8.playerstats.msg.MessageWriter; 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.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.models.StatRequest;
import com.gmail.artemis.the.gr8.playerstats.statistic.StatThread; 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.MyLogger;
import com.gmail.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler;
import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import java.util.HashMap; 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 statThreadID;
private int reloadThreadID; private int reloadThreadID;
private final BukkitAudiences adventure; private static BukkitAudiences adventure;
private static ConfigHandler config; private static ConfigHandler config;
private static MessageWriter messageWriter; private static MessageWriter messageWriter;
private final ShareManager shareManager; private final OfflinePlayerHandler offlinePlayerHandler;
private ReloadThread lastActiveReloadThread; private ReloadThread lastActiveReloadThread;
private StatThread lastActiveStatThread; private StatThread lastActiveStatThread;
private final HashMap<String, Thread> statThreads; private final HashMap<String, Thread> statThreads;
private static long lastRecordedCalcTime; private static long lastRecordedCalcTime;
public ThreadManager(BukkitAudiences a, ConfigHandler c, MessageWriter m, ShareManager s) { private ThreadManager(ConfigHandler c, MessageWriter m, OfflinePlayerHandler o) {
adventure = a; adventure = Main.adventure();
config = c; config = c;
messageWriter = m; messageWriter = m;
shareManager = s; offlinePlayerHandler = o;
statThreads = new HashMap<>(); statThreads = new HashMap<>();
statThreadID = 0; statThreadID = 0;
@ -42,11 +44,28 @@ public class ThreadManager {
startReloadThread(null); 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) { public void startReloadThread(CommandSender sender) {
if (lastActiveReloadThread == null || !lastActiveReloadThread.isAlive()) { if (lastActiveReloadThread == null || !lastActiveReloadThread.isAlive()) {
reloadThreadID += 1; reloadThreadID += 1;
lastActiveReloadThread = new ReloadThread(adventure, config, messageWriter, threshold, reloadThreadID, lastActiveStatThread, sender); lastActiveReloadThread = new ReloadThread(config, messageWriter, offlinePlayerHandler, reloadThreadID, lastActiveStatThread, sender);
lastActiveReloadThread.start(); lastActiveReloadThread.start();
} }
else { else {
@ -83,7 +102,7 @@ public class ThreadManager {
} }
private void startNewStatThread(StatRequest request) { 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); statThreads.put(request.getCommandSender().getName(), lastActiveStatThread);
lastActiveStatThread.start(); lastActiveStatThread.start();
} }

View File

@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull;
public class ReloadCommand implements CommandExecutor { public class ReloadCommand implements CommandExecutor {
private final ThreadManager threadManager; private static ThreadManager threadManager;
public ReloadCommand(ThreadManager t) { public ReloadCommand(ThreadManager t) {
threadManager = t; threadManager = t;

View File

@ -1,5 +1,6 @@
package com.gmail.artemis.the.gr8.playerstats.commands; 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 com.gmail.artemis.the.gr8.playerstats.statistic.ShareManager;
import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.command.Command; import org.bukkit.command.Command;
@ -11,11 +12,11 @@ import java.util.UUID;
public class ShareCommand implements CommandExecutor { public class ShareCommand implements CommandExecutor {
private final BukkitAudiences adventure; private static BukkitAudiences adventure;
private final ShareManager shareManager; private static ShareManager shareManager;
public ShareCommand(BukkitAudiences a, ShareManager s) { public ShareCommand(ShareManager s) {
adventure = a; adventure = Main.adventure();
shareManager = s; shareManager = s;
} }

View File

@ -1,5 +1,6 @@
package com.gmail.artemis.the.gr8.playerstats.commands; 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.ThreadManager;
import com.gmail.artemis.the.gr8.playerstats.enums.Target; import com.gmail.artemis.the.gr8.playerstats.enums.Target;
import com.gmail.artemis.the.gr8.playerstats.utils.EnumHandler; import com.gmail.artemis.the.gr8.playerstats.utils.EnumHandler;
@ -23,14 +24,16 @@ import org.jetbrains.annotations.Nullable;
public class StatCommand implements CommandExecutor { public class StatCommand implements CommandExecutor {
private final BukkitAudiences adventure; private static BukkitAudiences adventure;
private static ThreadManager threadManager;
private final MessageWriter messageWriter; private final MessageWriter messageWriter;
private final ThreadManager threadManager; private final OfflinePlayerHandler offlinePlayerHandler;
public StatCommand(BukkitAudiences a, MessageWriter m, ThreadManager t) { public StatCommand(MessageWriter m, ThreadManager t, OfflinePlayerHandler o) {
adventure = a; adventure = Main.adventure();
messageWriter = m;
threadManager = t; threadManager = t;
messageWriter = m;
offlinePlayerHandler = o;
} }
@Override @Override
@ -90,7 +93,7 @@ public class StatCommand implements CommandExecutor {
request.setSelection(Target.SERVER); request.setSelection(Target.SERVER);
} }
} }
else if (OfflinePlayerHandler.isRelevantPlayer(arg) && request.getPlayerName() == null) { else if (offlinePlayerHandler.isRelevantPlayer(arg) && request.getPlayerName() == null) {
request.setPlayerName(arg); request.setPlayerName(arg);
request.setSelection(Target.PLAYER); request.setSelection(Target.PLAYER);
} }

View File

@ -14,18 +14,22 @@ import java.util.stream.Collectors;
public class TabCompleter implements org.bukkit.command.TabCompleter { public class TabCompleter implements org.bukkit.command.TabCompleter {
private final List<String> commandOptions; private final OfflinePlayerHandler offlinePlayerHandler;
private final TabCompleteHelper tabCompleteHelper; private final TabCompleteHelper tabCompleteHelper;
private final List<String> commandOptions;
//TODO add "example" to the list //TODO add "example" to the list
public TabCompleter() { public TabCompleter(OfflinePlayerHandler o) {
offlinePlayerHandler = o;
tabCompleteHelper = new TabCompleteHelper();
commandOptions = new ArrayList<>(); commandOptions = new ArrayList<>();
commandOptions.add("top"); commandOptions.add("top");
commandOptions.add("player"); commandOptions.add("player");
commandOptions.add("server"); commandOptions.add("server");
commandOptions.add("me"); commandOptions.add("me");
tabCompleteHelper = new TabCompleteHelper();
} }
//args[0] = statistic (length = 1) //args[0] = statistic (length = 1)
@ -64,7 +68,7 @@ public class TabCompleter implements org.bukkit.command.TabCompleter {
tabSuggestions = commandOptions; tabSuggestions = commandOptions;
} }
else { else {
tabSuggestions = getTabSuggestions(OfflinePlayerHandler.getOfflinePlayerNames(), currentArg); tabSuggestions = getTabSuggestions(offlinePlayerHandler.getOfflinePlayerNames(), currentArg);
} }
} }

View File

@ -8,7 +8,7 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class TabCompleteHelper { public final class TabCompleteHelper {
private static List<String> itemBrokenSuggestions; private static List<String> itemBrokenSuggestions;
private static List<String> entityKilledSuggestions; private static List<String> entityKilledSuggestions;

View File

@ -12,18 +12,18 @@ import java.io.File;
public class ConfigHandler { public class ConfigHandler {
private static Main plugin;
private static double configVersion;
private File configFile; private File configFile;
private FileConfiguration config; private FileConfiguration config;
private final Main plugin;
private final double configVersion;
public ConfigHandler(Main p) { public ConfigHandler(Main p) {
plugin = p; plugin = p;
configVersion = 5;
saveDefaultConfig(); saveDefaultConfig();
config = YamlConfiguration.loadConfiguration(configFile); config = YamlConfiguration.loadConfiguration(configFile);
configVersion = 5;
checkConfigVersion(); checkConfigVersion();
MyLogger.setDebugLevel(getDebugLevel()); MyLogger.setDebugLevel(getDebugLevel());

View File

@ -7,7 +7,7 @@ import org.bukkit.event.player.PlayerJoinEvent;
public class JoinListener implements Listener { public class JoinListener implements Listener {
private final ThreadManager threadManager; private static ThreadManager threadManager;
public JoinListener(ThreadManager t) { public JoinListener(ThreadManager t) {
threadManager = t; threadManager = t;

View File

@ -9,8 +9,7 @@ import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public final class StatRequest {
public class StatRequest {
private final CommandSender sender; private final CommandSender sender;
private Statistic statistic; private Statistic statistic;

View File

@ -4,6 +4,5 @@ import net.kyori.adventure.text.TextComponent;
import java.util.UUID; import java.util.UUID;
public record StatResult(String playerName, TextComponent statResult, int ID, UUID uuid) { public record StatResult(String playerName, TextComponent statResult, int ID, UUID uuid) {
} }

View File

@ -1,17 +1,19 @@
package com.gmail.artemis.the.gr8.playerstats.msg; 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.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.enums.Target;
import com.gmail.artemis.the.gr8.playerstats.config.ConfigHandler; 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.enums.Unit;
import com.gmail.artemis.the.gr8.playerstats.msg.msgutils.ExampleMessage; import com.gmail.artemis.the.gr8.playerstats.msg.msgutils.*;
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.models.StatRequest; 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 com.gmail.artemis.the.gr8.playerstats.utils.MyLogger;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent; 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.Bukkit;
import org.bukkit.Statistic; import org.bukkit.Statistic;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;

View File

@ -13,11 +13,10 @@ import java.util.HashMap;
public final class LanguageKeyHandler { public final class LanguageKeyHandler {
private final HashMap<Statistic, String> statNameKeys; private static HashMap<Statistic, String> statNameKeys;
public LanguageKeyHandler() { public LanguageKeyHandler() {
statNameKeys = new HashMap<>(); statNameKeys = generateStatNameKeys();
generateStatNameKeys();
} }
public String getStatKey(@NotNull Statistic statistic) { public String getStatKey(@NotNull Statistic statistic) {
@ -72,47 +71,46 @@ public final class LanguageKeyHandler {
} }
} }
private void generateDefaultKeys() { private @NotNull HashMap<Statistic, String> generateStatNameKeys() {
Arrays.stream(Statistic.values()).forEach(statistic -> statNameKeys.put(statistic, statistic.toString().toLowerCase()));
}
private void generateStatNameKeys() {
//get the enum names for all statistics first //get the enum names for all statistics first
generateDefaultKeys(); HashMap<Statistic, String> 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 //replace the ones for which the language key is different from the enum name
statNameKeys.put(Statistic.ARMOR_CLEANED, "clean_armor"); statNames.put(Statistic.ARMOR_CLEANED, "clean_armor");
statNameKeys.put(Statistic.BANNER_CLEANED, "clean_banner"); statNames.put(Statistic.BANNER_CLEANED, "clean_banner");
statNameKeys.put(Statistic.DROP_COUNT, "drop"); statNames.put(Statistic.DROP_COUNT, "drop");
statNameKeys.put(Statistic.CAKE_SLICES_EATEN, "eat_cake_slice"); statNames.put(Statistic.CAKE_SLICES_EATEN, "eat_cake_slice");
statNameKeys.put(Statistic.ITEM_ENCHANTED, "enchant_item"); statNames.put(Statistic.ITEM_ENCHANTED, "enchant_item");
statNameKeys.put(Statistic.CAULDRON_FILLED, "fill_cauldron"); statNames.put(Statistic.CAULDRON_FILLED, "fill_cauldron");
statNameKeys.put(Statistic.DISPENSER_INSPECTED, "inspect_dispenser"); statNames.put(Statistic.DISPENSER_INSPECTED, "inspect_dispenser");
statNameKeys.put(Statistic.DROPPER_INSPECTED, "inspect_dropper"); statNames.put(Statistic.DROPPER_INSPECTED, "inspect_dropper");
statNameKeys.put(Statistic.HOPPER_INSPECTED, "inspect_hopper"); statNames.put(Statistic.HOPPER_INSPECTED, "inspect_hopper");
statNameKeys.put(Statistic.BEACON_INTERACTION, "interact_with_beacon"); statNames.put(Statistic.BEACON_INTERACTION, "interact_with_beacon");
statNameKeys.put(Statistic.BREWINGSTAND_INTERACTION, "interact_with_brewingstand"); statNames.put(Statistic.BREWINGSTAND_INTERACTION, "interact_with_brewingstand");
statNameKeys.put(Statistic.CRAFTING_TABLE_INTERACTION, "interact_with_crafting_table"); statNames.put(Statistic.CRAFTING_TABLE_INTERACTION, "interact_with_crafting_table");
statNameKeys.put(Statistic.FURNACE_INTERACTION, "interact_with_furnace"); statNames.put(Statistic.FURNACE_INTERACTION, "interact_with_furnace");
statNameKeys.put(Statistic.CHEST_OPENED, "open_chest"); statNames.put(Statistic.CHEST_OPENED, "open_chest");
statNameKeys.put(Statistic.ENDERCHEST_OPENED, "open_enderchest"); statNames.put(Statistic.ENDERCHEST_OPENED, "open_enderchest");
statNameKeys.put(Statistic.SHULKER_BOX_OPENED, "open_shulker_box"); statNames.put(Statistic.SHULKER_BOX_OPENED, "open_shulker_box");
statNameKeys.put(Statistic.NOTEBLOCK_PLAYED, "play_noteblock"); statNames.put(Statistic.NOTEBLOCK_PLAYED, "play_noteblock");
statNameKeys.put(Statistic.PLAY_ONE_MINUTE, "play_time"); statNames.put(Statistic.PLAY_ONE_MINUTE, "play_time");
statNameKeys.put(Statistic.RECORD_PLAYED, "play_record"); statNames.put(Statistic.RECORD_PLAYED, "play_record");
statNameKeys.put(Statistic.FLOWER_POTTED, "pot_flower"); statNames.put(Statistic.FLOWER_POTTED, "pot_flower");
statNameKeys.put(Statistic.TRAPPED_CHEST_TRIGGERED, "trigger_trapped_chest"); statNames.put(Statistic.TRAPPED_CHEST_TRIGGERED, "trigger_trapped_chest");
statNameKeys.put(Statistic.NOTEBLOCK_TUNED, "tune_noteblock"); statNames.put(Statistic.NOTEBLOCK_TUNED, "tune_noteblock");
statNameKeys.put(Statistic.CAULDRON_USED, "use_cauldron"); statNames.put(Statistic.CAULDRON_USED, "use_cauldron");
//do the same for the statistics that have a subtype //do the same for the statistics that have a subtype
statNameKeys.put(Statistic.DROP, "dropped"); statNames.put(Statistic.DROP, "dropped");
statNameKeys.put(Statistic.PICKUP, "picked_up"); statNames.put(Statistic.PICKUP, "picked_up");
statNameKeys.put(Statistic.MINE_BLOCK, "mined"); statNames.put(Statistic.MINE_BLOCK, "mined");
statNameKeys.put(Statistic.USE_ITEM, "used"); statNames.put(Statistic.USE_ITEM, "used");
statNameKeys.put(Statistic.BREAK_ITEM, "broken"); statNames.put(Statistic.BREAK_ITEM, "broken");
statNameKeys.put(Statistic.CRAFT_ITEM, "crafted"); statNames.put(Statistic.CRAFT_ITEM, "crafted");
statNameKeys.put(Statistic.KILL_ENTITY, "killed"); statNames.put(Statistic.KILL_ENTITY, "killed");
statNameKeys.put(Statistic.ENTITY_KILLED_BY, "killed_by"); statNames.put(Statistic.ENTITY_KILLED_BY, "killed_by");
return statNames;
} }
} }

View File

@ -1,5 +1,6 @@
package com.gmail.artemis.the.gr8.playerstats.reload; 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.MyLogger;
import com.gmail.artemis.the.gr8.playerstats.utils.UnixTimeHandler; import com.gmail.artemis.the.gr8.playerstats.utils.UnixTimeHandler;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
@ -8,9 +9,9 @@ import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.RecursiveAction; 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 OfflinePlayer[] players;
private final int start; private final int start;
@ -20,21 +21,20 @@ public class ReloadAction extends RecursiveAction {
private final ConcurrentHashMap<String, UUID> offlinePlayerUUIDs; private final ConcurrentHashMap<String, UUID> offlinePlayerUUIDs;
/** Fills a ConcurrentHashMap with PlayerNames and UUIDs for all OfflinePlayers that should be included in statistic calculations. /** 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 players array of all OfflinePlayers (straight from Bukkit)
* @param lastPlayedLimit whether to set a limit based on last-played-date * @param lastPlayedLimit whether to set a limit based on last-played-date
* @param offlinePlayerUUIDs the ConcurrentHashMap to put resulting playerNames and UUIDs on * @param offlinePlayerUUIDs the ConcurrentHashMap to put resulting playerNames and UUIDs on
*/ */
public ReloadAction(int threshold, OfflinePlayer[] players, public ReloadAction(OfflinePlayer[] players,
int lastPlayedLimit, ConcurrentHashMap<String, UUID> offlinePlayerUUIDs) { int lastPlayedLimit, ConcurrentHashMap<String, UUID> 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<String, UUID> offlinePlayerUUIDs) { int lastPlayedLimit, ConcurrentHashMap<String, UUID> offlinePlayerUUIDs) {
threshold = ThreadManager.getTaskThreshold();
this.threshold = threshold;
this.players = players; this.players = players;
this.start = start; this.start = start;
this.end = end; this.end = end;
@ -53,9 +53,9 @@ public class ReloadAction extends RecursiveAction {
} }
else { else {
final int split = length / 2; 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); lastPlayedLimit, offlinePlayerUUIDs);
final ReloadAction subTask2 = new ReloadAction(threshold, players, (start + split), end, final ReloadAction subTask2 = new ReloadAction(players, (start + split), end,
lastPlayedLimit, offlinePlayerUUIDs); lastPlayedLimit, offlinePlayerUUIDs);
//queue and compute all subtasks in the right order //queue and compute all subtasks in the right order

View File

@ -1,5 +1,6 @@
package com.gmail.artemis.the.gr8.playerstats.reload; 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.ThreadManager;
import com.gmail.artemis.the.gr8.playerstats.config.ConfigHandler; 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.enums.DebugLevel;
@ -22,25 +23,28 @@ import java.util.function.Predicate;
public class ReloadThread extends Thread { public class ReloadThread extends Thread {
private final int threshold;
private final int reloadThreadID; private final int reloadThreadID;
private final StatThread statThread; private final StatThread statThread;
private final BukkitAudiences adventure; private static BukkitAudiences adventure;
private static ConfigHandler config; private static ConfigHandler config;
private static MessageWriter messageWriter; private final MessageWriter messageWriter;
private final OfflinePlayerHandler offlinePlayerHandler;
private final CommandSender sender; 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; reloadThreadID = ID;
statThread = s; statThread = s;
adventure = a;
config = c; config = c;
messageWriter = m; messageWriter = m;
sender = se; sender = se;
adventure = Main.adventure();
offlinePlayerHandler = o;
this.setName("ReloadThread-" + reloadThreadID); this.setName("ReloadThread-" + reloadThreadID);
MyLogger.threadCreated(this.getName()); MyLogger.threadCreated(this.getName());
} }
@ -112,13 +116,13 @@ public class ReloadThread extends Thread {
int size = offlinePlayers != null ? offlinePlayers.length : 16; int size = offlinePlayers != null ? offlinePlayers.length : 16;
ConcurrentHashMap<String, UUID> playerMap = new ConcurrentHashMap<>(size); ConcurrentHashMap<String, UUID> 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); MyLogger.actionCreated((offlinePlayers != null) ? offlinePlayers.length : 0);
ForkJoinPool.commonPool().invoke(task); ForkJoinPool.commonPool().invoke(task);
MyLogger.actionFinished(1); MyLogger.actionFinished(1);
OfflinePlayerHandler.updateOfflinePlayerList(playerMap); offlinePlayerHandler.updateOfflinePlayerList(playerMap);
MyLogger.logTimeTaken("ReloadThread", MyLogger.logTimeTaken("ReloadThread",
("loaded " + OfflinePlayerHandler.getOfflinePlayerCount() + " offline players"), time); ("loaded " + offlinePlayerHandler.getOfflinePlayerCount() + " offline players"), time);
} }
} }

View File

@ -15,6 +15,8 @@ import java.util.concurrent.atomic.AtomicInteger;
public class ShareManager { public class ShareManager {
private static volatile ShareManager instance;
private boolean isEnabled; private boolean isEnabled;
private int waitingTime; private int waitingTime;
@ -22,9 +24,10 @@ public class ShareManager {
private ConcurrentHashMap<UUID, StatResult> statResults = null; private ConcurrentHashMap<UUID, StatResult> statResults = null;
private ConcurrentHashMap<String, Instant> shareTimeStamp = null; private ConcurrentHashMap<String, Instant> shareTimeStamp = null;
public ShareManager(ConfigHandler config) { private ShareManager(ConfigHandler config) {
isEnabled = config.enableStatSharing(); isEnabled = config.enableStatSharing();
waitingTime = config.getStatShareWaitingTime(); waitingTime = config.getStatShareWaitingTime();
if (isEnabled) { if (isEnabled) {
resultID = new AtomicInteger(); resultID = new AtomicInteger();
statResults = new ConcurrentHashMap<>(); statResults = new ConcurrentHashMap<>();
@ -32,17 +35,37 @@ public class ShareManager {
} }
} }
public boolean isEnabled() { public static ShareManager getInstance(ConfigHandler config) {
return this.isEnabled; 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(); isEnabled = config.enableStatSharing();
waitingTime = config.getStatShareWaitingTime(); waitingTime = config.getStatShareWaitingTime();
//if we went from disabled to enabled, initialize the HashMaps
if (isEnabled && statResults == null) { if (isEnabled && statResults == null) {
statResults = new ConcurrentHashMap<>(); statResults = new ConcurrentHashMap<>();
shareTimeStamp = 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) { public UUID saveStatResult(String playerName, TextComponent statResult) {

View File

@ -1,5 +1,6 @@
package com.gmail.artemis.the.gr8.playerstats.statistic; 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.enums.Target;
import com.gmail.artemis.the.gr8.playerstats.models.StatRequest; import com.gmail.artemis.the.gr8.playerstats.models.StatRequest;
import com.gmail.artemis.the.gr8.playerstats.msg.MessageWriter; import com.gmail.artemis.the.gr8.playerstats.msg.MessageWriter;
@ -22,26 +23,28 @@ import java.util.stream.Collectors;
public class StatThread extends Thread { 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 ConfigHandler config;
private static MessageWriter messageWriter; private final MessageWriter messageWriter;
private final OfflinePlayerHandler offlinePlayerHandler;
private final ReloadThread reloadThread;
private final StatRequest request; 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; config = c;
messageWriter = m; messageWriter = m;
offlinePlayerHandler = o;
reloadThread = r;
request = s; request = s;
adventure = Main.adventure();
shareManager = ShareManager.getInstance(config);
this.setName("StatThread-" + request.getCommandSender().getName() + "-" + ID); this.setName("StatThread-" + request.getCommandSender().getName() + "-" + ID);
MyLogger.threadCreated(this.getName()); MyLogger.threadCreated(this.getName());
} }
@ -112,11 +115,11 @@ public class StatThread extends Thread {
private @NotNull ConcurrentHashMap<String, Integer> getAllStats() throws ConcurrentModificationException { private @NotNull ConcurrentHashMap<String, Integer> getAllStats() throws ConcurrentModificationException {
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
int size = OfflinePlayerHandler.getOfflinePlayerCount() != 0 ? OfflinePlayerHandler.getOfflinePlayerCount() : 16; int size = offlinePlayerHandler.getOfflinePlayerCount() != 0 ? offlinePlayerHandler.getOfflinePlayerCount() : 16;
ConcurrentHashMap<String, Integer> playerStats = new ConcurrentHashMap<>(size); ConcurrentHashMap<String, Integer> playerStats = new ConcurrentHashMap<>(size);
ImmutableList<String> playerNames = ImmutableList.copyOf(OfflinePlayerHandler.getOfflinePlayerNames()); ImmutableList<String> 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()); MyLogger.actionCreated(playerNames.size());
ForkJoinPool commonPool = ForkJoinPool.commonPool(); 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 /** Gets the statistic data for an individual player. If somehow the player
cannot be found, this returns 0.*/ cannot be found, this returns 0.*/
private int getIndividualStat() { private int getIndividualStat() {
OfflinePlayer player = OfflinePlayerHandler.getOfflinePlayer(request.getPlayerName()); OfflinePlayer player = offlinePlayerHandler.getOfflinePlayer(request.getPlayerName());
if (player != null) { if (player != null) {
return switch (request.getStatistic().getType()) { return switch (request.getStatistic().getType()) {
case UNTYPED -> player.getStatistic(request.getStatistic()); case UNTYPED -> player.getStatistic(request.getStatistic());

View File

@ -1,5 +1,6 @@
package com.gmail.artemis.the.gr8.playerstats.statistic; 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.models.StatRequest;
import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger; import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger;
import com.gmail.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler; import com.gmail.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler;
@ -11,10 +12,11 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.RecursiveAction; 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<String> playerNames; private final ImmutableList<String> playerNames;
private final StatRequest request; private final StatRequest request;
private final ConcurrentHashMap<String, Integer> playerStats; private final ConcurrentHashMap<String, Integer> 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 * 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 * 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 playerNames ImmutableList of playerNames for players that should be included in stat calculations
* @param statRequest a validated statRequest * @param statRequest a validated statRequest
* @param playerStats the ConcurrentHashMap to put the results on * @param playerStats the ConcurrentHashMap to put the results on
*/ */
public TopStatAction(int threshold, ImmutableList<String> playerNames, StatRequest statRequest, ConcurrentHashMap<String, Integer> playerStats) { public TopStatAction(OfflinePlayerHandler offlinePlayerHandler, ImmutableList<String> playerNames, StatRequest statRequest, ConcurrentHashMap<String, Integer> playerStats) {
this.threshold = threshold; threshold = ThreadManager.getTaskThreshold();
this.playerNames = playerNames;
this.offlinePlayerHandler = offlinePlayerHandler;
this.playerNames = playerNames;
this.request = statRequest; this.request = statRequest;
this.playerStats = playerStats; this.playerStats = playerStats;
@ -43,8 +46,8 @@ public class TopStatAction extends RecursiveAction {
getStatsDirectly(); getStatsDirectly();
} }
else { else {
final TopStatAction subTask1 = new TopStatAction(threshold, playerNames.subList(0, playerNames.size()/2), request, playerStats); final TopStatAction subTask1 = new TopStatAction(offlinePlayerHandler, 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 subTask2 = new TopStatAction(offlinePlayerHandler, playerNames.subList(playerNames.size()/2, playerNames.size()), request, playerStats);
//queue and compute all subtasks in the right order //queue and compute all subtasks in the right order
invokeAll(subTask1, subTask2); invokeAll(subTask1, subTask2);
@ -57,7 +60,7 @@ public class TopStatAction extends RecursiveAction {
do { do {
String playerName = iterator.next(); String playerName = iterator.next();
MyLogger.actionRunning(Thread.currentThread().getName(), playerName, 2); MyLogger.actionRunning(Thread.currentThread().getName(), playerName, 2);
OfflinePlayer player = OfflinePlayerHandler.getOfflinePlayer(playerName); OfflinePlayer player = offlinePlayerHandler.getOfflinePlayer(playerName);
if (player != null) { if (player != null) {
int statistic = 0; int statistic = 0;
switch (request.getStatistic().getType()) { switch (request.getStatistic().getType()) {

View File

@ -12,7 +12,7 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
public class EnumHandler { public final class EnumHandler {
private final static List<String> blockNames; private final static List<String> blockNames;
private final static List<String> entityNames; private final static List<String> entityNames;
@ -50,9 +50,6 @@ public class EnumHandler {
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
private EnumHandler() {
}
public static List<String> getItemNames() { public static List<String> getItemNames() {
return itemNames; return itemNames;
} }

View File

@ -12,27 +12,24 @@ public class OfflinePlayerHandler {
private static ConcurrentHashMap<String, UUID> offlinePlayerUUIDs; private static ConcurrentHashMap<String, UUID> offlinePlayerUUIDs;
private static ArrayList<String> playerNames; private static ArrayList<String> playerNames;
static { public OfflinePlayerHandler() {
offlinePlayerUUIDs = new ConcurrentHashMap<>(); offlinePlayerUUIDs = new ConcurrentHashMap<>();
playerNames = new ArrayList<>(); playerNames = new ArrayList<>();
} }
private OfflinePlayerHandler() {
}
/** Checks if a given playerName is on the private HashMap of players that should be included in statistic calculations /** Checks if a given playerName is on the private HashMap of players that should be included in statistic calculations
@param playerName String, case-sensitive */ @param playerName String, case-sensitive */
public static boolean isRelevantPlayer(String playerName) { public boolean isRelevantPlayer(String playerName) {
return offlinePlayerUUIDs.containsKey(playerName); return offlinePlayerUUIDs.containsKey(playerName);
} }
/** Returns the number of OfflinePlayers that are included in statistic calculations */ /** Returns the number of OfflinePlayers that are included in statistic calculations */
public static int getOfflinePlayerCount() { public int getOfflinePlayerCount() {
return offlinePlayerUUIDs.size(); return offlinePlayerUUIDs.size();
} }
/** Get an ArrayList of names from all OfflinePlayers that should be included in statistic calculations */ /** Get an ArrayList of names from all OfflinePlayers that should be included in statistic calculations */
public static ArrayList<String> getOfflinePlayerNames() { public ArrayList<String> getOfflinePlayerNames() {
return playerNames; return playerNames;
} }
@ -41,7 +38,7 @@ public class OfflinePlayerHandler {
* This HashMap is stored as a private variable in OfflinePlayerHandler. * This HashMap is stored as a private variable in OfflinePlayerHandler.
* @param playerList ConcurrentHashMap with keys: playerNames and values: UUIDs * @param playerList ConcurrentHashMap with keys: playerNames and values: UUIDs
*/ */
public static void updateOfflinePlayerList(ConcurrentHashMap<String, UUID> playerList) { public void updateOfflinePlayerList(ConcurrentHashMap<String, UUID> playerList) {
offlinePlayerUUIDs = playerList; offlinePlayerUUIDs = playerList;
playerNames = Collections.list(offlinePlayerUUIDs.keys()); playerNames = Collections.list(offlinePlayerUUIDs.keys());
} }
@ -51,7 +48,7 @@ public class OfflinePlayerHandler {
* @param playerName name of the target player * @param playerName name of the target player
* @return OfflinePlayer (if this player is on the list, otherwise null) * @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) { if (offlinePlayerUUIDs.get(playerName) != null) {
return Bukkit.getOfflinePlayer(offlinePlayerUUIDs.get(playerName)); return Bukkit.getOfflinePlayer(offlinePlayerUUIDs.get(playerName));
} }

View File

@ -1,7 +1,6 @@
package com.gmail.artemis.the.gr8.playerstats.utils; package com.gmail.artemis.the.gr8.playerstats.utils;
public final class UnixTimeHandler {
public class UnixTimeHandler {
/** Calculates whether a player has played recently enough to fall within the lastPlayedLimit. /** 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). If lastPlayedLimit == 0, this always returns true (since there is no limit).