The exclude function now works completely, the only thing left is give fancier feedback (#88)

This commit is contained in:
Artemis-the-gr8 2022-10-26 12:59:10 +02:00
parent da49c46539
commit f69367cb31
10 changed files with 135 additions and 99 deletions

View File

@ -127,7 +127,7 @@ public final class Main extends JavaPlugin implements PlayerStats {
}
PluginCommand excludecmd = this.getCommand("statisticexclude");
if (excludecmd != null) {
excludecmd.setExecutor(new ExcludeCommand());
excludecmd.setExecutor(new ExcludeCommand(outputManager));
excludecmd.setTabCompleter(tabCompleter);
}

View File

@ -1,44 +1,55 @@
package com.artemis.the.gr8.playerstats.commands;
import com.artemis.the.gr8.playerstats.utils.MyLogger;
import com.artemis.the.gr8.playerstats.msg.OutputManager;
import com.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.ArrayList;
public final class ExcludeCommand implements CommandExecutor {
private static OutputManager outputManager;
private final OfflinePlayerHandler offlinePlayerHandler;
public ExcludeCommand() {
public ExcludeCommand(OutputManager outputManager) {
ExcludeCommand.outputManager = outputManager;
this.offlinePlayerHandler = OfflinePlayerHandler.getInstance();
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (args.length == 1 && args[0].equalsIgnoreCase("list")) {
List<String> excludedPlayers = offlinePlayerHandler.getListOfExcludedPlayerNames();
for (String player : excludedPlayers) {
MyLogger.logLowLevelMsg(player);
}
ArrayList<String> excludedPlayers = offlinePlayerHandler.getExcludedPlayerNames();
sender.sendMessage(String.valueOf(excludedPlayers));
return true;
}
//this is going to return false for all UUIDs in file at boot-up - that's an issue
else if (args.length >= 2 && offlinePlayerHandler.isLoadedPlayer(args[1])) {
String playerName = args[1];
OfflinePlayer player = offlinePlayerHandler.getOfflinePlayer(playerName);
else if (args.length >= 2) {
String playerName = args[1];
switch (args[0]) {
case "add" -> offlinePlayerHandler.addPlayerToExcludeList(player.getUniqueId());
case "remove" -> offlinePlayerHandler.removePlayerFromExcludeList(player.getUniqueId());
case "add" -> {
if (offlinePlayerHandler.isLoadedPlayer(playerName)) {
offlinePlayerHandler.addLoadedPlayerToExcludeList(playerName);
sender.sendMessage("Excluded " + playerName + "!");
return true;
}
}
case "remove" -> {
if (offlinePlayerHandler.isExcludedPlayer(playerName)) {
offlinePlayerHandler.addExcludedPlayerToLoadedList(playerName);
sender.sendMessage("Removed " + playerName + " from the exclude list again!");
return true;
}
}
case "info" -> {
boolean isExcluded = offlinePlayerHandler.isExcluded(player.getUniqueId());
MyLogger.logLowLevelMsg(player.getName() + " is excluded: " + isExcluded);
boolean isExcluded = offlinePlayerHandler.isExcludedPlayer(playerName);
sender.sendMessage(playerName+ " is excluded: " + isExcluded);
return true;
}
}
}

View File

@ -45,11 +45,13 @@ public final class StatCommand implements CommandExecutor {
@Override
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
if (args.length == 0 ||
args[0].equalsIgnoreCase("help") ||
args[0].equalsIgnoreCase("info")) {
outputManager.sendHelp(sender);
}
else if (args[0].equalsIgnoreCase("examples") ||
args[0].equalsIgnoreCase("example")) { //in case of "statistic examples", show examples
args[0].equalsIgnoreCase("example")) {
outputManager.sendExamples(sender);
}
else {

View File

@ -7,7 +7,6 @@ import org.bukkit.Statistic;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.EntityType;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -29,14 +28,9 @@ public final class TabCompleter implements org.bukkit.command.TabCompleter {
public TabCompleter() {
offlinePlayerHandler = OfflinePlayerHandler.getInstance();
enumHandler = EnumHandler.getInstance();
prepareLists();
}
//args[0] = statistic (length = 1)
//args[1] = target (player/server/top) OR sub-stat (block/item/entity) (length = 2)
//args[2] = playerName OR target (player/server/top) (length = 3)
//args[3] = playerName (length = 4)
@Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (command.getName().equalsIgnoreCase("statistic")) {
@ -59,8 +53,13 @@ public final class TabCompleter implements org.bukkit.command.TabCompleter {
}
else if (args.length == 2) {
tabSuggestions = switch (args[0]) {
case "add" -> offlinePlayerHandler.getOfflinePlayerNames();
case "remove" -> removablePlayerNames();
case "add" -> offlinePlayerHandler.getLoadedOfflinePlayerNames();
case "remove" -> offlinePlayerHandler.getExcludedPlayerNames();
case "info" -> {
ArrayList<String> loadedPlayers = offlinePlayerHandler.getLoadedOfflinePlayerNames();
loadedPlayers.addAll(offlinePlayerHandler.getExcludedPlayerNames());
yield loadedPlayers;
}
default -> tabSuggestions;
};
}
@ -91,7 +90,7 @@ public final class TabCompleter implements org.bukkit.command.TabCompleter {
tabSuggestions = statCommandTargets; //if arg before "player" was entity-sub-stat, suggest targets
}
else { //otherwise "player" is the target: suggest playerNames
tabSuggestions = offlinePlayerHandler.getOfflinePlayerNames();
tabSuggestions = offlinePlayerHandler.getLoadedOfflinePlayerNames();
}
}
@ -117,6 +116,7 @@ public final class TabCompleter implements org.bukkit.command.TabCompleter {
private @NotNull List<String> firstStatCommandArgSuggestions() {
List<String> suggestions = enumHandler.getAllStatNames();
suggestions.add("examples");
suggestions.add("info");
suggestions.add("help");
return suggestions;
}
@ -142,11 +142,6 @@ public final class TabCompleter implements org.bukkit.command.TabCompleter {
}
}
@Contract(pure = true)
private @Nullable List<String> removablePlayerNames() {
return statCommandTargets;
}
private void prepareLists() {
statCommandTargets = new ArrayList<>();
statCommandTargets.add("top");
@ -158,6 +153,7 @@ public final class TabCompleter implements org.bukkit.command.TabCompleter {
excludeCommandOptions.add("add");
excludeCommandOptions.add("list");
excludeCommandOptions.add("remove");
excludeCommandOptions.add("info");
//breaking an item means running its durability negative
itemsThatCanBreak = Arrays.stream(Material.values())

View File

@ -63,7 +63,7 @@ public final class ConfigHandler extends FileHandler {
Map<String, Object> defaultValues = defaultValueGetter.getValuesToAdjust();
defaultValues.put("config-version", configVersion);
super.addValuesToFile(defaultValues);
super.addValues(defaultValues);
reload();
MyLogger.logLowLevelMsg("Your config has been updated to version " + configVersion +

View File

@ -6,6 +6,8 @@ import com.artemis.the.gr8.playerstats.enums.PluginColor;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.util.Random;
@ -85,7 +87,8 @@ public class PrideComponentFactory extends ComponentFactory {
.build();
}
private TextComponent backwardsPluginPrefixComponent() {
@Contract(" -> new")
private @NotNull TextComponent backwardsPluginPrefixComponent() {
return text()
.append(MiniMessage.miniMessage()
.deserialize("<#631ae6>[</#631ae6>" +

View File

@ -73,7 +73,7 @@ final class PlayerLoadAction extends RecursiveAction {
String playerName = player.getName();
MyLogger.actionRunning(Thread.currentThread().getName());
if (playerName != null &&
!offlinePlayerHandler.isExcluded(player.getUniqueId()) &&
!offlinePlayerHandler.isExcludedPlayer(player.getUniqueId()) &&
UnixTimeHandler.hasPlayedSince(lastPlayedLimit, player.getLastPlayed())) {
offlinePlayerUUIDs.put(playerName, player.getUniqueId());
}

View File

@ -58,7 +58,7 @@ public final class ThreadManager {
public static @NotNull StatAction getStatAction(StatRequest.Settings requestSettings) {
OfflinePlayerHandler offlinePlayerHandler = OfflinePlayerHandler.getInstance();
ImmutableList<String> relevantPlayerNames = ImmutableList.copyOf(offlinePlayerHandler.getOfflinePlayerNames());
ImmutableList<String> relevantPlayerNames = ImmutableList.copyOf(offlinePlayerHandler.getLoadedOfflinePlayerNames());
ConcurrentHashMap<String, Integer> resultingStatNumbers = new ConcurrentHashMap<>(relevantPlayerNames.size());
StatAction task = new StatAction(relevantPlayerNames, requestSettings, resultingStatNumbers);

View File

@ -25,7 +25,7 @@ public abstract class FileHandler {
loadFile();
}
public void loadFile() {
private void loadFile() {
JavaPlugin plugin = Main.getPluginInstance();
file = new File(plugin.getDataFolder(), fileName);
@ -48,7 +48,7 @@ public abstract class FileHandler {
return fileConfiguration;
}
public void addValuesToFile(@NotNull Map<String, Object> keyValuePairs) {
public void addValues(@NotNull Map<String, Object> keyValuePairs) {
keyValuePairs.forEach(this::setValue);
save();
updateFile();
@ -59,7 +59,7 @@ public abstract class FileHandler {
* (or expanded if it already exists)
* @param value the value(s) to expand the List with
*/
public void addEntryToListInFile(@NotNull String key, @NotNull String value) {
public void writeEntryToList(@NotNull String key, @NotNull String value) {
List<String> existingList = fileConfiguration.getStringList(key);
List<String> updatedList = existingList.stream()
@ -72,7 +72,7 @@ public abstract class FileHandler {
updateFile();
}
public void removeEntryFromListInFile(@NotNull String key, @NotNull String value) {
public void removeEntryFromList(@NotNull String key, @NotNull String value) {
List<String> currentValues = fileConfiguration.getStringList(key);
if (currentValues.remove(value)) {

View File

@ -4,7 +4,6 @@ import com.artemis.the.gr8.playerstats.config.ConfigHandler;
import com.artemis.the.gr8.playerstats.multithreading.ThreadManager;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
@ -13,7 +12,6 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ForkJoinPool;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* A utility class that deals with OfflinePlayers. It stores a list
@ -25,14 +23,13 @@ public final class OfflinePlayerHandler extends FileHandler {
private static volatile OfflinePlayerHandler instance;
private final ConfigHandler config;
private static FileConfiguration excludedPlayers;
private static ConcurrentHashMap<String, UUID> offlinePlayerUUIDs;
private static ConcurrentHashMap<String, UUID> includedPlayerUUIDs;
private static ConcurrentHashMap<String, UUID> excludedPlayerUUIDs;
private OfflinePlayerHandler() {
super("excluded_players.yml");
config = ConfigHandler.getInstance();
excludedPlayers = super.getFileConfiguration();
loadOfflinePlayers();
}
@ -53,8 +50,6 @@ public final class OfflinePlayerHandler extends FileHandler {
@Override
public void reload() {
super.reload();
excludedPlayers = super.getFileConfiguration();
loadOfflinePlayers();
}
@ -66,43 +61,40 @@ public final class OfflinePlayerHandler extends FileHandler {
* @return true if this player is included
*/
public boolean isLoadedPlayer(String playerName) {
return offlinePlayerUUIDs.containsKey(playerName);
return includedPlayerUUIDs.containsKey(playerName);
}
public void addPlayerToExcludeList(UUID uniqueID) {
super.addEntryToListInFile("excluded", uniqueID.toString());
public boolean isExcludedPlayer(String playerName) {
return excludedPlayerUUIDs.containsKey(playerName);
}
public void removePlayerFromExcludeList(UUID uniqueID) {
super.removeEntryFromListInFile("excluded", uniqueID.toString());
public boolean isExcludedPlayer(UUID uniqueID) {
return excludedPlayerUUIDs.containsValue(uniqueID);
}
public List<String> getListOfExcludedPlayerNames() {
List<String> excludedUUIDs = excludedPlayers.getStringList("excluded");
return excludedUUIDs.stream()
.map(UUID::fromString)
.map(Bukkit::getOfflinePlayer)
.map(OfflinePlayer::getName)
.collect(Collectors.toList());
public void addLoadedPlayerToExcludeList(String playerName) throws IllegalArgumentException {
UUID uuid = includedPlayerUUIDs.get(playerName);
if (uuid == null) {
throw new IllegalArgumentException("This player is not loaded, and therefore cannot be excluded!");
}
super.writeEntryToList("excluded", uuid.toString());
includedPlayerUUIDs.remove(playerName);
excludedPlayerUUIDs.put(playerName, uuid);
}
public boolean isExcluded(UUID uniqueID) {
List<String> excluded = excludedPlayers.getStringList("excluded");
return excluded.stream()
.filter(Objects::nonNull)
.map(UUID::fromString)
.anyMatch(uuid -> uuid.equals(uniqueID));
public void addExcludedPlayerToLoadedList(String playerName) {
UUID uuid = excludedPlayerUUIDs.get(playerName);
if (uuid == null) {
throw new IllegalArgumentException("This player is not excluded, and therefore cannot be un-excluded!");
}
super.removeEntryFromList("excluded", uuid.toString());
excludedPlayerUUIDs.remove(playerName);
includedPlayerUUIDs.put(playerName, uuid);
}
/**
* Gets the number of OfflinePlayers that are
* currently included in statistic calculations.
*
* @return the number of included OfflinePlayers
*/
public int getOfflinePlayerCount() {
return offlinePlayerUUIDs.size();
@Contract(" -> new")
public @NotNull ArrayList<String> getExcludedPlayerNames() {
return Collections.list(excludedPlayerUUIDs.keys());
}
/**
@ -112,8 +104,18 @@ public final class OfflinePlayerHandler extends FileHandler {
* @return the ArrayList
*/
@Contract(" -> new")
public @NotNull ArrayList<String> getOfflinePlayerNames() {
return Collections.list(offlinePlayerUUIDs.keys());
public @NotNull ArrayList<String> getLoadedOfflinePlayerNames() {
return Collections.list(includedPlayerUUIDs.keys());
}
/**
* Gets the number of OfflinePlayers that are
* currently included in statistic calculations.
*
* @return the number of included OfflinePlayers
*/
public int getOfflinePlayerCount() {
return includedPlayerUUIDs.size();
}
/**
@ -126,8 +128,8 @@ public final class OfflinePlayerHandler extends FileHandler {
* of players that should be included in statistic calculations
*/
public @NotNull OfflinePlayer getOfflinePlayer(String playerName) throws IllegalArgumentException {
if (offlinePlayerUUIDs.get(playerName) != null) {
return Bukkit.getOfflinePlayer(offlinePlayerUUIDs.get(playerName));
if (includedPlayerUUIDs.get(playerName) != null) {
return Bukkit.getOfflinePlayer(includedPlayerUUIDs.get(playerName));
}
else {
MyLogger.logWarning("Cannot calculate statistics for player-name: " + playerName +
@ -139,29 +141,51 @@ public final class OfflinePlayerHandler extends FileHandler {
private void loadOfflinePlayers() {
Executors.newSingleThreadExecutor().execute(() -> {
long time = System.currentTimeMillis();
OfflinePlayer[] offlinePlayers;
if (config.whitelistOnly()) {
offlinePlayers = getWhitelistedPlayers();
}
else if (config.excludeBanned()) {
offlinePlayers = getNonBannedPlayers();
}
else {
offlinePlayers = Bukkit.getOfflinePlayers();
}
int size = offlinePlayerUUIDs != null ? offlinePlayerUUIDs.size() : 16;
offlinePlayerUUIDs = new ConcurrentHashMap<>(size);
ForkJoinPool.commonPool().invoke(ThreadManager.getPlayerLoadAction(offlinePlayers, offlinePlayerUUIDs));
MyLogger.actionFinished();
MyLogger.logLowLevelTask(("Loaded " + offlinePlayerUUIDs.size() + " offline players"), time);
loadExcludedPlayerNames();
loadIncludedOfflinePlayers();
});
}
private void loadIncludedOfflinePlayers() {
long time = System.currentTimeMillis();
OfflinePlayer[] offlinePlayers;
if (config.whitelistOnly()) {
offlinePlayers = getWhitelistedPlayers();
} else if (config.excludeBanned()) {
offlinePlayers = getNonBannedPlayers();
} else {
offlinePlayers = Bukkit.getOfflinePlayers();
}
int size = includedPlayerUUIDs != null ? includedPlayerUUIDs.size() : 16;
includedPlayerUUIDs = new ConcurrentHashMap<>(size);
ForkJoinPool.commonPool().invoke(ThreadManager.getPlayerLoadAction(offlinePlayers, includedPlayerUUIDs));
MyLogger.actionFinished();
MyLogger.logLowLevelTask(("Loaded " + includedPlayerUUIDs.size() + " offline players"), time);
}
private void loadExcludedPlayerNames() {
long time = System.currentTimeMillis();
excludedPlayerUUIDs = new ConcurrentHashMap<>();
List<String> excluded = super.getFileConfiguration().getStringList("excluded");
excluded.stream()
.filter(Objects::nonNull)
.map(UUID::fromString)
.forEach(uuid -> {
OfflinePlayer player = Bukkit.getOfflinePlayer(uuid);
String playerName = player.getName();
if (playerName != null) {
excludedPlayerUUIDs.put(playerName, uuid);
}
});
MyLogger.logLowLevelTask("Loaded " + excludedPlayerUUIDs.size() + " excluded players from file", time);
}
private OfflinePlayer[] getWhitelistedPlayers() {
return Bukkit.getWhitelistedPlayers().toArray(OfflinePlayer[]::new);
}