diff --git a/src/main/java/com/artemis/the/gr8/playerstats/Main.java b/src/main/java/com/artemis/the/gr8/playerstats/Main.java index f3d30e5..d3e9f2b 100644 --- a/src/main/java/com/artemis/the/gr8/playerstats/Main.java +++ b/src/main/java/com/artemis/the/gr8/playerstats/Main.java @@ -26,6 +26,7 @@ import org.bukkit.Bukkit; import org.bukkit.command.PluginCommand; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitRunnable; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; /** @@ -85,8 +86,8 @@ public final class Main extends JavaPlugin implements PlayerStats { MyLogger.setDebugLevel(config.getDebugLevel()); languageKeyHandler.reload(); offlinePlayerHandler.reload(); - outputManager.update(); - ShareManager.updateSettings(config); + outputManager.updateSettings(); + shareManager.updateSettings(config); } /** @@ -146,8 +147,9 @@ public final class Main extends JavaPlugin implements PlayerStats { }.runTaskLaterAsynchronously(this, 200); } + @Contract(pure = true) @Override - public String getVersion() { + public @NotNull String getVersion() { return "1.8"; } diff --git a/src/main/java/com/artemis/the/gr8/playerstats/commands/ExcludeCommand.java b/src/main/java/com/artemis/the/gr8/playerstats/commands/ExcludeCommand.java new file mode 100644 index 0000000..45459b8 --- /dev/null +++ b/src/main/java/com/artemis/the/gr8/playerstats/commands/ExcludeCommand.java @@ -0,0 +1,23 @@ +package com.artemis.the.gr8.playerstats.commands; + + +import com.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +public final class ExcludeCommand implements CommandExecutor { + + private final OfflinePlayerHandler offlinePlayerHandler; + + public ExcludeCommand(OfflinePlayerHandler offlinePlayerHandler) { + this.offlinePlayerHandler = offlinePlayerHandler; + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + + return false; + } +} diff --git a/src/main/java/com/artemis/the/gr8/playerstats/commands/ReloadCommand.java b/src/main/java/com/artemis/the/gr8/playerstats/commands/ReloadCommand.java index 6b13458..6a3774a 100644 --- a/src/main/java/com/artemis/the/gr8/playerstats/commands/ReloadCommand.java +++ b/src/main/java/com/artemis/the/gr8/playerstats/commands/ReloadCommand.java @@ -16,7 +16,7 @@ public final class ReloadCommand implements CommandExecutor { } @Override - public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { threadManager.startReloadThread(sender); return true; } diff --git a/src/main/java/com/artemis/the/gr8/playerstats/commands/ShareCommand.java b/src/main/java/com/artemis/the/gr8/playerstats/commands/ShareCommand.java index 4285f4f..b60e7c8 100644 --- a/src/main/java/com/artemis/the/gr8/playerstats/commands/ShareCommand.java +++ b/src/main/java/com/artemis/the/gr8/playerstats/commands/ShareCommand.java @@ -21,7 +21,7 @@ public final class ShareCommand implements CommandExecutor { } @Override - public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, String[] args) { + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, @NotNull String[] args) { if (args.length == 1 && ShareManager.isEnabled()) { int shareCode; try { diff --git a/src/main/java/com/artemis/the/gr8/playerstats/commands/StatCommand.java b/src/main/java/com/artemis/the/gr8/playerstats/commands/StatCommand.java index ede5e8d..5a3cdc4 100644 --- a/src/main/java/com/artemis/the/gr8/playerstats/commands/StatCommand.java +++ b/src/main/java/com/artemis/the/gr8/playerstats/commands/StatCommand.java @@ -26,7 +26,7 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -public class StatCommand implements CommandExecutor { +public final class StatCommand implements CommandExecutor { private static final Pattern pattern = Pattern.compile("top|server|me|player"); @@ -45,7 +45,7 @@ public class StatCommand implements CommandExecutor { } @Override - public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { if (args.length == 0 || args[0].equalsIgnoreCase("help")) { //in case of less than 1 argument or "help", display the help message outputManager.sendHelp(sender); } diff --git a/src/main/java/com/artemis/the/gr8/playerstats/commands/TabCompleter.java b/src/main/java/com/artemis/the/gr8/playerstats/commands/TabCompleter.java index 2a53914..e8169c1 100644 --- a/src/main/java/com/artemis/the/gr8/playerstats/commands/TabCompleter.java +++ b/src/main/java/com/artemis/the/gr8/playerstats/commands/TabCompleter.java @@ -8,6 +8,7 @@ import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.EntityType; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Arrays; @@ -34,7 +35,7 @@ public final class TabCompleter implements org.bukkit.command.TabCompleter { //args[2] = playerName OR target (player/server/top) (length = 3) //args[3] = playerName (length = 4) @Override - public List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { if (args.length >= 1) { String currentArg = args[args.length-1]; diff --git a/src/main/java/com/artemis/the/gr8/playerstats/config/ConfigHandler.java b/src/main/java/com/artemis/the/gr8/playerstats/config/ConfigHandler.java index 56c9085..0035f62 100644 --- a/src/main/java/com/artemis/the/gr8/playerstats/config/ConfigHandler.java +++ b/src/main/java/com/artemis/the/gr8/playerstats/config/ConfigHandler.java @@ -48,8 +48,7 @@ public final class ConfigHandler extends FileHandler { Map defaultValues = defaultValueGetter.getValuesToAdjust(); defaultValues.put("config-version", configVersion); - super.addValues(defaultValues); - super.updateFile(); + super.addValuesToFile(defaultValues); reload(); MyLogger.logLowLevelMsg("Your config has been updated to version " + configVersion + diff --git a/src/main/java/com/artemis/the/gr8/playerstats/config/DefaultValueGetter.java b/src/main/java/com/artemis/the/gr8/playerstats/config/DefaultValueGetter.java index b0038dd..c2761c1 100644 --- a/src/main/java/com/artemis/the/gr8/playerstats/config/DefaultValueGetter.java +++ b/src/main/java/com/artemis/the/gr8/playerstats/config/DefaultValueGetter.java @@ -5,7 +5,7 @@ import org.bukkit.configuration.file.FileConfiguration; import java.util.HashMap; import java.util.Map; -public class DefaultValueGetter { +public final class DefaultValueGetter { private final FileConfiguration config; private final Map defaultValuesToAdjust; @@ -53,4 +53,4 @@ public class DefaultValueGetter { defaultValuesToAdjust.put(path, newValue); } } -} +} \ No newline at end of file diff --git a/src/main/java/com/artemis/the/gr8/playerstats/msg/OutputManager.java b/src/main/java/com/artemis/the/gr8/playerstats/msg/OutputManager.java index 57aec04..e3858c0 100644 --- a/src/main/java/com/artemis/the/gr8/playerstats/msg/OutputManager.java +++ b/src/main/java/com/artemis/the/gr8/playerstats/msg/OutputManager.java @@ -49,7 +49,7 @@ public final class OutputManager { prepareFunctions(); } - public void update() { + public void updateSettings() { getMessageBuilders(); } diff --git a/src/main/java/com/artemis/the/gr8/playerstats/reload/PlayerLoadAction.java b/src/main/java/com/artemis/the/gr8/playerstats/reload/PlayerLoadAction.java index 6d3dc4f..2d7bd71 100644 --- a/src/main/java/com/artemis/the/gr8/playerstats/reload/PlayerLoadAction.java +++ b/src/main/java/com/artemis/the/gr8/playerstats/reload/PlayerLoadAction.java @@ -28,8 +28,8 @@ public final class PlayerLoadAction extends RecursiveAction { * Fills a ConcurrentHashMap with PlayerNames and UUIDs for all OfflinePlayers * that should be included in statistic calculations. * - * @param players array of all OfflinePlayers (straight from Bukkit) - * @param lastPlayedLimit whether to set a limit based on last-played-date + * @param players array of all OfflinePlayers to filter and load + * @param lastPlayedLimit optional limit for amount of days ago players last played * @param offlinePlayerUUIDs the ConcurrentHashMap to put playerNames and UUIDs in * @see OfflinePlayerHandler */ @@ -76,8 +76,7 @@ public final class PlayerLoadAction extends RecursiveAction { OfflinePlayer player = players[i]; String playerName = player.getName(); MyLogger.actionRunning(Thread.currentThread().getName()); - if (playerName != null && - (lastPlayedLimit == 0 || UnixTimeHandler.hasPlayedSince(lastPlayedLimit, player.getLastPlayed()))) { + if (playerName != null && UnixTimeHandler.hasPlayedSince(lastPlayedLimit, player.getLastPlayed())) { offlinePlayerUUIDs.put(playerName, player.getUniqueId()); } } diff --git a/src/main/java/com/artemis/the/gr8/playerstats/share/ShareManager.java b/src/main/java/com/artemis/the/gr8/playerstats/share/ShareManager.java index 9b91bb9..2c2c87c 100644 --- a/src/main/java/com/artemis/the/gr8/playerstats/share/ShareManager.java +++ b/src/main/java/com/artemis/the/gr8/playerstats/share/ShareManager.java @@ -26,12 +26,12 @@ import static java.time.temporal.ChronoUnit.SECONDS; public final class ShareManager { private static boolean isEnabled; - private static int waitingTime; + private int waitingTime; - private static volatile AtomicInteger resultID; - private static ConcurrentHashMap statResultQueue; - private static ConcurrentHashMap shareTimeStamp; - private static ArrayBlockingQueue sharedResults; + private volatile AtomicInteger NumberOfStoredResults; + private ConcurrentHashMap statResultQueue; + private ConcurrentHashMap shareTimeStamp; + private ArrayBlockingQueue sharedResults; public ShareManager(ConfigHandler config) { updateSettings(config); @@ -41,14 +41,14 @@ public final class ShareManager { return isEnabled; } - public static synchronized void updateSettings(ConfigHandler config) { + public void updateSettings(ConfigHandler config) { isEnabled = config.allowStatSharing() && config.useHoverText(); waitingTime = config.getStatShareWaitingTime(); if (isEnabled) { sharedResults = new ArrayBlockingQueue<>(500); //reset the sharedResultsQueue - if (resultID == null) { //if we went from disabled to enabled, initialize - resultID = new AtomicInteger(); //always starts with value 0 + if (NumberOfStoredResults == null) { //if we went from disabled to enabled, initialize + NumberOfStoredResults = new AtomicInteger(); //always starts with value 0 statResultQueue = new ConcurrentHashMap<>(); shareTimeStamp = new ConcurrentHashMap<>(); } @@ -148,6 +148,6 @@ public final class ShareManager { } private int getNextIDNumber() { - return resultID.incrementAndGet(); + return NumberOfStoredResults.incrementAndGet(); } } \ No newline at end of file diff --git a/src/main/java/com/artemis/the/gr8/playerstats/statistic/RequestProcessor.java b/src/main/java/com/artemis/the/gr8/playerstats/statistic/RequestProcessor.java index a36c988..4f32dec 100644 --- a/src/main/java/com/artemis/the/gr8/playerstats/statistic/RequestProcessor.java +++ b/src/main/java/com/artemis/the/gr8/playerstats/statistic/RequestProcessor.java @@ -19,7 +19,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ForkJoinPool; import java.util.stream.Collectors; -public class RequestProcessor { +public final class RequestProcessor { private final OfflinePlayerHandler offlinePlayerHandler; private static OutputManager outputManager; diff --git a/src/main/java/com/artemis/the/gr8/playerstats/utils/FileHandler.java b/src/main/java/com/artemis/the/gr8/playerstats/utils/FileHandler.java index ebe26b3..7acdbab 100644 --- a/src/main/java/com/artemis/the/gr8/playerstats/utils/FileHandler.java +++ b/src/main/java/com/artemis/the/gr8/playerstats/utils/FileHandler.java @@ -9,6 +9,8 @@ import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.Map; public abstract class FileHandler { @@ -45,22 +47,31 @@ public abstract class FileHandler { return fileConfiguration; } - /** - * Add new key-value pairs to the config without losing comments, - * using tchristofferson's Config-Updater - */ - public void updateFile() { - JavaPlugin plugin = Main.getPluginInstance(); - try { - ConfigUpdater.update(plugin, fileName, file); - } catch (IOException e) { - e.printStackTrace(); - } - } - - public void addValues(@NotNull Map keyValuePairs) { + public void addValuesToFile(@NotNull Map keyValuePairs) { keyValuePairs.forEach(this::addValue); save(); + updateFile(); + } + + /** + * @param key the Key under which the List will be stored + * (or expanded if it already exists) + * @param value the value(s) to expand the List with + */ + public void addValueToListInFile(@NotNull String key, @NotNull Object value) { + List currentValues = fileConfiguration.getList(key); + + List updatedValues; + if (currentValues != null) { + updatedValues = new ArrayList<>(currentValues); + } else { + updatedValues = new ArrayList<>(); + } + updatedValues.add(value); + + addValue(key, updatedValues); + save(); + updateFile(); } private void addValue(String key, Object value) { @@ -74,4 +85,17 @@ public abstract class FileHandler { e.printStackTrace(); } } + + /** + * Add new key-value pairs to the config without losing comments, + * using tchristofferson's Config-Updater + */ + private void updateFile() { + JavaPlugin plugin = Main.getPluginInstance(); + try { + ConfigUpdater.update(plugin, fileName, file); + } catch (IOException e) { + e.printStackTrace(); + } + } } \ No newline at end of file diff --git a/src/main/java/com/artemis/the/gr8/playerstats/utils/OfflinePlayerHandler.java b/src/main/java/com/artemis/the/gr8/playerstats/utils/OfflinePlayerHandler.java index f6765f7..821b49e 100644 --- a/src/main/java/com/artemis/the/gr8/playerstats/utils/OfflinePlayerHandler.java +++ b/src/main/java/com/artemis/the/gr8/playerstats/utils/OfflinePlayerHandler.java @@ -4,6 +4,8 @@ import com.artemis.the.gr8.playerstats.config.ConfigHandler; import com.artemis.the.gr8.playerstats.reload.PlayerLoadAction; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; +import org.bukkit.configuration.file.FileConfiguration; +import org.jetbrains.annotations.NotNull; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -20,11 +22,13 @@ import java.util.function.Predicate; public final class OfflinePlayerHandler extends FileHandler { private static ConfigHandler config; + private static FileConfiguration excludedPlayers; private ConcurrentHashMap offlinePlayerUUIDs; private ArrayList playerNames; public OfflinePlayerHandler(ConfigHandler configHandler) { super("excluded_players.yml"); + excludedPlayers = super.getFileConfiguration(); config = configHandler; loadOfflinePlayers(); } @@ -32,6 +36,7 @@ public final class OfflinePlayerHandler extends FileHandler { @Override public void reload() { super.reload(); + excludedPlayers = super.getFileConfiguration(); loadOfflinePlayers(); } @@ -46,6 +51,23 @@ public final class OfflinePlayerHandler extends FileHandler { return offlinePlayerUUIDs.containsKey(playerName); } + public void excludePlayer(UUID uniqueID) { + super.addValueToListInFile("excluded", uniqueID); + } + + public static boolean isExcluded(UUID uniqueID) { + List excluded = excludedPlayers.getList("excluded"); + if (excluded == null) { + return false; + } + for (Object obj : excluded) { + if (obj.equals(uniqueID)) { + return true; + } + } + return false; + } + /** * Gets the number of OfflinePlayers that are included in * statistic calculations. @@ -75,7 +97,7 @@ public final class OfflinePlayerHandler extends FileHandler { * @throws IllegalArgumentException if this player is not on the list * of players that should be included in statistic calculations */ - public OfflinePlayer getOfflinePlayer(String playerName) throws IllegalArgumentException { + public @NotNull OfflinePlayer getOfflinePlayer(String playerName) throws IllegalArgumentException { if (offlinePlayerUUIDs.get(playerName) != null) { return Bukkit.getOfflinePlayer(offlinePlayerUUIDs.get(playerName)); } @@ -119,7 +141,7 @@ public final class OfflinePlayerHandler extends FileHandler { return Bukkit.getWhitelistedPlayers().toArray(OfflinePlayer[]::new); } - private OfflinePlayer[] getNonBannedPlayers() { + private @NotNull OfflinePlayer[] getNonBannedPlayers() { if (Bukkit.getPluginManager().isPluginEnabled("LiteBans")) { return Arrays.stream(Bukkit.getOfflinePlayers()) .parallel() diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 38521e6..0c90827 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -11,13 +11,13 @@ commands: aliases: - stat - stats - description: general statistic command + description: show player statistics in private chat permission: playerstats.stat statisticshare: aliases: - statshare - statsshare - description: shares last stat lookup in chat + description: share last stat lookup in chat usage: "§b/statshare" permission: playerstats.share statisticreload: @@ -27,6 +27,13 @@ commands: description: reloads the config usage: "§a/statreload" permission: playerstats.reload + statisticexclude: + aliases: + - statexclude + - statsexclude + description: hide this player's statistics from /stat results + usage: "§c/statexclude" + permission: playerstats.exclude permissions: playerstats.stat: description: allows usage of /statistic @@ -34,6 +41,9 @@ permissions: playerstats.share: description: allows sharing stats in chat default: true + playerstats.exclude: + description: allows usage of /statexclude + default: op playerstats.reload: description: allows usage of /statreload default: op \ No newline at end of file