Reworked InternalStatRequest and the other classes dealing with StatRequests (#114)

This commit is contained in:
Artemis-the-gr8 2022-10-11 13:08:11 +02:00
parent b46a25d23f
commit 31713007f5
19 changed files with 197 additions and 217 deletions

View File

@ -1,17 +1,16 @@
package com.artemis.the.gr8.playerstats;
import com.artemis.the.gr8.playerstats.api.PlayerStats;
import com.artemis.the.gr8.playerstats.api.PlayerStatsImpl;
import com.artemis.the.gr8.playerstats.msg.OutputManager;
import com.artemis.the.gr8.playerstats.api.PlayerStatsAPI;
import com.artemis.the.gr8.playerstats.commands.ReloadCommand;
import com.artemis.the.gr8.playerstats.commands.ShareCommand;
import com.artemis.the.gr8.playerstats.commands.StatCommand;
import com.artemis.the.gr8.playerstats.commands.TabCompleter;
import com.artemis.the.gr8.playerstats.config.ConfigHandler;
import com.artemis.the.gr8.playerstats.listeners.JoinListener;
import com.artemis.the.gr8.playerstats.msg.MessageBuilder;
import com.artemis.the.gr8.playerstats.msg.msgutils.LanguageKeyHandler;
import com.artemis.the.gr8.playerstats.statistic.StatCalculator;
import com.artemis.the.gr8.playerstats.statistic.RequestProcessor;
import com.artemis.the.gr8.playerstats.utils.EnumHandler;
import com.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler;
import me.clip.placeholderapi.PlaceholderAPIPlugin;
@ -35,14 +34,14 @@ public final class Main extends JavaPlugin {
private static BukkitAudiences adventure;
private static ConfigHandler config;
private static ThreadManager threadManager;
private static LanguageKeyHandler languageKeyHandler;
private static OfflinePlayerHandler offlinePlayerHandler;
private static EnumHandler enumHandler;
private static OutputManager outputManager;
private static ShareManager shareManager;
private static StatCalculator statCalculator;
private static ThreadManager threadManager;
private static RequestProcessor requestProcessor;
private static PlayerStats playerStatsAPI;
@ -110,11 +109,11 @@ public final class Main extends JavaPlugin {
return playerStatsAPI;
}
public static @NotNull OutputManager getOutputManager() throws IllegalStateException {
if (outputManager == null) {
public static @NotNull RequestProcessor getRequestProcessor() throws IllegalStateException {
if (requestProcessor == null) {
throw new IllegalStateException("PlayerStats does not seem to be loaded!");
}
return outputManager;
return requestProcessor;
}
/**
@ -152,29 +151,21 @@ public final class Main extends JavaPlugin {
return enumHandler;
}
public static @NotNull StatCalculator getStatCalculator() {
if (statCalculator == null) {
statCalculator = new StatCalculator(getOfflinePlayerHandler());
}
return statCalculator;
}
private void initializeMainClasses() {
pluginInstance = this;
adventure = BukkitAudiences.create(this);
config = new ConfigHandler();
enumHandler = new EnumHandler();
languageKeyHandler = new LanguageKeyHandler();
config = new ConfigHandler();
offlinePlayerHandler = new OfflinePlayerHandler(config);
shareManager = new ShareManager(config);
statCalculator = new StatCalculator(offlinePlayerHandler);
outputManager = new OutputManager(adventure, config, shareManager);
threadManager = new ThreadManager(config, statCalculator, outputManager);
MessageBuilder apiMessageBuilder = MessageBuilder.defaultBuilder(config);
playerStatsAPI = new PlayerStatsAPI(apiMessageBuilder, offlinePlayerHandler);
outputManager = new OutputManager(adventure, config, shareManager);
requestProcessor = new RequestProcessor(offlinePlayerHandler, outputManager);
threadManager = new ThreadManager(config, requestProcessor, outputManager);
playerStatsAPI = new PlayerStatsImpl(outputManager, offlinePlayerHandler);
}
private void setupMetrics() {

View File

@ -4,11 +4,12 @@ import com.artemis.the.gr8.playerstats.msg.OutputManager;
import com.artemis.the.gr8.playerstats.config.ConfigHandler;
import com.artemis.the.gr8.playerstats.enums.StandardMessage;
import com.artemis.the.gr8.playerstats.reload.ReloadThread;
import com.artemis.the.gr8.playerstats.statistic.StatCalculator;
import com.artemis.the.gr8.playerstats.statistic.RequestProcessor;
import com.artemis.the.gr8.playerstats.statistic.StatThread;
import com.artemis.the.gr8.playerstats.statistic.request.StatRequest;
import com.artemis.the.gr8.playerstats.utils.MyLogger;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
@ -29,17 +30,17 @@ public final class ThreadManager {
private static ConfigHandler config;
private static OutputManager outputManager;
private static StatCalculator statCalculator;
private static RequestProcessor requestProcessor;
private ReloadThread lastActiveReloadThread;
private StatThread lastActiveStatThread;
private ReloadThread activatedReloadThread;
private StatThread activatedStatThread;
private final HashMap<String, Thread> statThreads;
private static long lastRecordedCalcTime;
public ThreadManager(ConfigHandler config, StatCalculator statCalculator, OutputManager outputManager) {
public ThreadManager(ConfigHandler config, RequestProcessor requestProcessor, OutputManager outputManager) {
ThreadManager.config = config;
ThreadManager.outputManager = outputManager;
ThreadManager.statCalculator = statCalculator;
ThreadManager.requestProcessor = requestProcessor;
statThreads = new HashMap<>();
statThreadID = 0;
@ -52,25 +53,26 @@ public final class ThreadManager {
}
public void startReloadThread(CommandSender sender) {
if (lastActiveReloadThread == null || !lastActiveReloadThread.isAlive()) {
if (activatedReloadThread == null || !activatedReloadThread.isAlive()) {
reloadThreadID += 1;
lastActiveReloadThread = new ReloadThread(config, outputManager, reloadThreadID, lastActiveStatThread, sender);
lastActiveReloadThread.start();
activatedReloadThread = new ReloadThread(config, outputManager, reloadThreadID, activatedStatThread, sender);
activatedReloadThread.start();
}
else {
MyLogger.logLowLevelMsg("Another reloadThread is already running! (" + lastActiveReloadThread.getName() + ")");
MyLogger.logLowLevelMsg("Another reloadThread is already running! (" + activatedReloadThread.getName() + ")");
}
}
public void startStatThread(StatRequest<?> request) {
public void startStatThread(@NotNull StatRequest<?> request) {
statThreadID += 1;
String cmdSender = request.getSettings().getCommandSender().getName();
CommandSender sender = request.getSettings().getCommandSender();
if (config.limitStatRequests() && statThreads.containsKey(sender.getName())) {
Thread runningThread = statThreads.get(sender.getName());
if (config.limitStatRequests() && statThreads.containsKey(cmdSender)) {
Thread runningThread = statThreads.get(cmdSender);
if (runningThread.isAlive()) {
outputManager.sendFeedbackMsg(request.getSettings().getCommandSender(), StandardMessage.REQUEST_ALREADY_RUNNING);
outputManager.sendFeedbackMsg(sender, StandardMessage.REQUEST_ALREADY_RUNNING);
} else {
startNewStatThread(request);
}
@ -95,9 +97,9 @@ public final class ThreadManager {
return lastRecordedCalcTime;
}
private void startNewStatThread(StatRequest<?> requestSettings) {
lastActiveStatThread = new StatThread(outputManager, statCalculator, statThreadID, requestSettings, lastActiveReloadThread);
statThreads.put(requestSettings.getSettings().getCommandSender().getName(), lastActiveStatThread);
lastActiveStatThread.start();
private void startNewStatThread(StatRequest<?> request) {
activatedStatThread = new StatThread(outputManager, requestProcessor, statThreadID, request, activatedReloadThread);
statThreads.put(request.getSettings().getCommandSender().getName(), activatedStatThread);
activatedStatThread.start();
}
}

View File

@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull;
* The outgoing API that represents the core functionality of PlayerStats!
*
* <p> To work with it, you'll need to call PlayerStats.{@link #getAPI()} and get an instance of
* {@link PlayerStatsAPI}. You can then use this object to access any of the further methods.
* {@link PlayerStatsImpl}. You can then use this object to access any of the further methods.
*
* <p> Since calculating a top or server statistics can take some time, I strongly
* encourage you to call {@link StatRequest#execute()} asynchronously.
@ -17,11 +17,11 @@ import org.jetbrains.annotations.NotNull;
* and this can severely impact server performance.
*
* @see StatManager
* @see ApiFormatter
* @see StatFormatter
*/
public interface PlayerStats {
/** Gets an instance of the {@link PlayerStatsAPI}.
/** Gets an instance of the {@link PlayerStatsImpl}.
* @return the PlayerStats API
* @throws IllegalStateException if PlayerStats is not loaded on the server when this method is called*/
@ -31,13 +31,13 @@ public interface PlayerStats {
}
/**
* Gets the current version of PlayerStatsAPI.
* Gets the current version of PlayerStatsImpl.
* Use this method to ensure the correct version of
* PlayerStats is running on the server before
* accessing further API methods, to prevent
* <code>ClassDefNotFoundExceptions</code>.
*
* @return the version of PlayerStatsAPI present on the server
* @return the version of PlayerStatsImpl present on the server
*/
default String getVersion() {
return "1.8";
@ -45,5 +45,5 @@ public interface PlayerStats {
StatManager getStatManager();
ApiFormatter getFormatter();
StatFormatter getFormatter();
}

View File

@ -1,25 +1,28 @@
package com.artemis.the.gr8.playerstats.api;
import com.artemis.the.gr8.playerstats.msg.OutputManager;
import com.artemis.the.gr8.playerstats.statistic.request.*;
import com.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler;
import java.util.LinkedHashMap;
import static org.jetbrains.annotations.ApiStatus.Internal;
/** The implementation of the API Interface */
public final class PlayerStatsAPI implements PlayerStats, StatManager {
public final class PlayerStatsImpl implements PlayerStats, StatManager {
private final OfflinePlayerHandler offlinePlayerHandler;
private static ApiFormatter apiFormatter;
private static OutputManager outputManager;
@Internal
public PlayerStatsAPI(ApiFormatter formatter, OfflinePlayerHandler offlinePlayers) {
apiFormatter = formatter;
public PlayerStatsImpl(OutputManager outputManager, OfflinePlayerHandler offlinePlayers) {
PlayerStatsImpl.outputManager = outputManager;
offlinePlayerHandler = offlinePlayers;
}
@Override
public ApiFormatter getFormatter() {
return apiFormatter;
public StatFormatter getFormatter() {
return outputManager.getCurrentMainMessageBuilder();
}
@Override
@ -28,22 +31,22 @@ public final class PlayerStatsAPI implements PlayerStats, StatManager {
}
@Override
public PlayerStatRequest playerStatRequest(String playerName) {
public RequestGenerator<Integer> playerStatRequest(String playerName) {
return new PlayerStatRequest(playerName);
}
@Override
public ServerStatRequest serverStatRequest() {
public RequestGenerator<Long> serverStatRequest() {
return new ServerStatRequest();
}
@Override
public TopStatRequest topStatRequest(int topListSize) {
public RequestGenerator<LinkedHashMap<String, Integer>> topStatRequest(int topListSize) {
return new TopStatRequest(topListSize);
}
@Override
public TopStatRequest totalTopStatRequest() {
public RequestGenerator<LinkedHashMap<String, Integer>> totalTopStatRequest() {
int playerCount = offlinePlayerHandler.getOfflinePlayerCount();
return topStatRequest(playerCount);
}

View File

@ -1,6 +1,6 @@
package com.artemis.the.gr8.playerstats.api;
import com.artemis.the.gr8.playerstats.statistic.StatCalculator;
import com.artemis.the.gr8.playerstats.statistic.RequestProcessor;
import com.artemis.the.gr8.playerstats.statistic.request.StatRequest;
import org.bukkit.Material;
import org.bukkit.Statistic;
@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull;
/**
* Creates an executable {@link StatRequest}. This Request holds all
* the information PlayerStats needs to work with, and is used by the {@link StatCalculator}
* the information PlayerStats needs to work with, and is used by the {@link RequestProcessor}
* to get the desired statistic data.
*/
public interface RequestGenerator<T> {

View File

@ -16,7 +16,7 @@ import org.jetbrains.annotations.Nullable;
* @see StatResult
*/
public interface ApiFormatter {
public interface StatFormatter {
/**
* Turns a TextComponent into its String representation. This method is equipped

View File

@ -5,7 +5,8 @@ import com.artemis.the.gr8.playerstats.statistic.request.StatRequest;
import java.util.LinkedHashMap;
/**
* Turns user input into a {@link StatRequest} that can be used to get statistic data
* Turns user input into a {@link StatRequest} that can be
* used to get statistic data.
*/
public interface StatManager {

View File

@ -5,6 +5,7 @@ import com.artemis.the.gr8.playerstats.enums.StandardMessage;
import com.artemis.the.gr8.playerstats.enums.Target;
import com.artemis.the.gr8.playerstats.msg.OutputManager;
import com.artemis.the.gr8.playerstats.statistic.request.*;
import net.kyori.adventure.text.TextComponent;
import org.bukkit.Statistic;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
@ -31,11 +32,11 @@ public class StatCommand implements CommandExecutor {
outputManager.sendExamples(sender);
}
else {
InternalStatRequest request = new InternalStatRequest(sender, args);
StatRequest<TextComponent> request = new InternalStatRequest(sender, args);
if (request.isValid()) {
threadManager.startStatThread(request);
} else {
sendFeedback(request);
sendFeedback(sender, request);
return false;
}
}
@ -52,11 +53,11 @@ public class StatCommand implements CommandExecutor {
* <li>If the <code>target</code> is Player, is a valid <code>playerName</code> provided?
* </ul>
*
* @param sender the CommandSender to send feedback to
* @param request the StatRequest to give feedback on
*/
private void sendFeedback(InternalStatRequest request) {
private void sendFeedback(CommandSender sender, StatRequest<?> request) {
StatRequest.Settings settings = request.getSettings();
CommandSender sender = settings.getCommandSender();
if (settings.getStatistic() == null) {
outputManager.sendFeedbackMsg(sender, StandardMessage.MISSING_STAT_NAME);

View File

@ -1,7 +1,7 @@
package com.artemis.the.gr8.playerstats.msg;
import com.artemis.the.gr8.playerstats.Main;
import com.artemis.the.gr8.playerstats.api.ApiFormatter;
import com.artemis.the.gr8.playerstats.api.StatFormatter;
import com.artemis.the.gr8.playerstats.msg.components.ComponentFactory;
import com.artemis.the.gr8.playerstats.msg.components.ExampleMessage;
import com.artemis.the.gr8.playerstats.msg.components.HelpMessage;
@ -39,7 +39,7 @@ import static net.kyori.adventure.text.Component.*;
* @see PrideComponentFactory
* @see BukkitConsoleComponentFactory
*/
public final class MessageBuilder implements ApiFormatter {
public final class MessageBuilder implements StatFormatter {
private static ConfigHandler config;
private boolean useHoverText;

View File

@ -54,6 +54,12 @@ public final class OutputManager {
getMessageBuilders();
}
public MessageBuilder getCurrentMainMessageBuilder() {
return messageBuilder;
}
//TODO separate formatting from internal saving for sharing
/** @return a TextComponent with the following parts:
* <br>[player-name]: [number] [stat-name] {sub-stat-name}
*/

View File

@ -5,7 +5,7 @@ import com.artemis.the.gr8.playerstats.ShareManager;
import com.artemis.the.gr8.playerstats.enums.StandardMessage;
import com.artemis.the.gr8.playerstats.msg.OutputManager;
import com.artemis.the.gr8.playerstats.msg.msgutils.LanguageKeyHandler;
import com.artemis.the.gr8.playerstats.statistic.StatCalculator;
import com.artemis.the.gr8.playerstats.statistic.RequestProcessor;
import com.artemis.the.gr8.playerstats.statistic.StatThread;
import com.artemis.the.gr8.playerstats.utils.MyLogger;
import com.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler;
@ -40,7 +40,7 @@ public final class ReloadThread extends Thread {
* Then, it will reload the config, update the {@link LanguageKeyHandler},
* the {@link OfflinePlayerHandler}, the {@link DebugLevel}, update
* the share-settings in {@link ShareManager} and topListSize-settings
* in {@link StatCalculator}, and update the MessageBuilders in the
* in {@link RequestProcessor}, and update the MessageBuilders in the
* {@link OutputManager}.
*/
@Override

View File

@ -1,27 +1,68 @@
package com.artemis.the.gr8.playerstats.statistic;
import com.artemis.the.gr8.playerstats.ThreadManager;
import com.artemis.the.gr8.playerstats.msg.OutputManager;
import com.artemis.the.gr8.playerstats.msg.components.ComponentUtils;
import com.artemis.the.gr8.playerstats.statistic.request.StatRequest;
import com.artemis.the.gr8.playerstats.statistic.result.StatResult;
import com.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler;
import com.artemis.the.gr8.playerstats.utils.MyLogger;
import com.google.common.collect.ImmutableList;
import net.kyori.adventure.text.TextComponent;
import org.bukkit.OfflinePlayer;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ForkJoinPool;
import java.util.stream.Collectors;
public final class StatCalculator {
public final class RequestProcessor {
private final OfflinePlayerHandler offlinePlayerHandler;
private static OutputManager outputManager;
public StatCalculator(OfflinePlayerHandler offlinePlayerHandler) {
public RequestProcessor(OfflinePlayerHandler offlinePlayerHandler, OutputManager outputManager) {
this.offlinePlayerHandler = offlinePlayerHandler;
RequestProcessor.outputManager = outputManager;
}
public int getPlayerStat(StatRequest.Settings requestSettings) {
public @NotNull StatResult<TextComponent> getInternalResult(@NotNull StatRequest.Settings requestSettings) {
StatResult<?> result = switch (requestSettings.getTarget()) {
case PLAYER -> getPlayerResult(requestSettings);
case SERVER -> getServerResult(requestSettings);
case TOP -> getTopResult(requestSettings);
};
return new StatResult<>(result.formattedComponent(), result.formattedComponent(), result.formattedString());
}
public @NotNull StatResult<Integer> getPlayerResult(StatRequest.Settings requestSettings) {
int stat = getPlayerStat(requestSettings);
TextComponent result = outputManager.formatAndSavePlayerStat(requestSettings, stat);
String serializedResult = ComponentUtils.getTranslatableComponentSerializer().serialize(result);
return new StatResult<>(stat, result, serializedResult);
}
public @NotNull StatResult<Long> getServerResult(StatRequest.Settings requestSettings) {
long stat = getServerStat(requestSettings);
TextComponent result = outputManager.formatAndSaveServerStat(requestSettings, stat);
String serializedResult = ComponentUtils.getTranslatableComponentSerializer().serialize(result);
return new StatResult<>(stat, result, serializedResult);
}
public @NotNull StatResult<LinkedHashMap<String, Integer>> getTopResult(StatRequest.Settings requestSettings) {
LinkedHashMap<String, Integer> stats = getTopStats(requestSettings);
TextComponent result = outputManager.formatAndSaveTopStat(requestSettings, stats);
String serializedResult = ComponentUtils.getTranslatableComponentSerializer().serialize(result);
return new StatResult<>(stats, result, serializedResult);
}
private int getPlayerStat(@NotNull StatRequest.Settings requestSettings) {
OfflinePlayer player = offlinePlayerHandler.getOfflinePlayer(requestSettings.getPlayerName());
return switch (requestSettings.getStatistic().getType()) {
case UNTYPED -> player.getStatistic(requestSettings.getStatistic());
@ -31,14 +72,7 @@ public final class StatCalculator {
};
}
public LinkedHashMap<String, Integer> getTopStats(StatRequest.Settings requestSettings) {
return getAllStatsAsync(requestSettings).entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.limit(requestSettings.getTopListSize())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
}
public long getServerStat(StatRequest.Settings requestSettings) {
private long getServerStat(StatRequest.Settings requestSettings) {
List<Integer> numbers = getAllStatsAsync(requestSettings)
.values()
.parallelStream()
@ -46,6 +80,13 @@ public final class StatCalculator {
return numbers.parallelStream().mapToLong(Integer::longValue).sum();
}
private LinkedHashMap<String, Integer> getTopStats(StatRequest.Settings requestSettings) {
return getAllStatsAsync(requestSettings).entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.limit(requestSettings.getTopListSize())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
}
/**
* Invokes a bunch of worker pool threads to get the statistics for
* all players that are stored in the {@link OfflinePlayerHandler}).
@ -72,7 +113,7 @@ public final class StatCalculator {
return allStats;
}
private StatAction getStatTask(StatRequest.Settings requestSettings) {
private @NotNull StatAction getStatTask(StatRequest.Settings requestSettings) {
int size = offlinePlayerHandler.getOfflinePlayerCount() != 0 ? offlinePlayerHandler.getOfflinePlayerCount() : 16;
ConcurrentHashMap<String, Integer> allStats = new ConcurrentHashMap<>(size);
ImmutableList<String> playerNames = ImmutableList.copyOf(offlinePlayerHandler.getOfflinePlayerNames());

View File

@ -3,11 +3,11 @@ package com.artemis.the.gr8.playerstats.statistic;
import com.artemis.the.gr8.playerstats.ThreadManager;
import com.artemis.the.gr8.playerstats.msg.OutputManager;
import com.artemis.the.gr8.playerstats.statistic.request.StatRequest;
import com.artemis.the.gr8.playerstats.statistic.result.StatResult;
import com.artemis.the.gr8.playerstats.utils.MyLogger;
import com.artemis.the.gr8.playerstats.enums.StandardMessage;
import com.artemis.the.gr8.playerstats.enums.Target;
import com.artemis.the.gr8.playerstats.reload.ReloadThread;
import net.kyori.adventure.text.TextComponent;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.Nullable;
import java.util.*;
@ -18,14 +18,14 @@ import java.util.*;
public final class StatThread extends Thread {
private static OutputManager outputManager;
private static StatCalculator statCalculator;
private static RequestProcessor requestProcessor;
private final ReloadThread reloadThread;
private final StatRequest<?> statRequest;
public StatThread(OutputManager m, StatCalculator t, int ID, StatRequest<?> s, @Nullable ReloadThread r) {
public StatThread(OutputManager m, RequestProcessor t, int ID, StatRequest<?> s, @Nullable ReloadThread r) {
outputManager = m;
statCalculator = t;
requestProcessor = t;
reloadThread = r;
statRequest = s;
@ -35,16 +35,14 @@ public final class StatThread extends Thread {
}
@Override
public void run() throws IllegalStateException, NullPointerException {
public void run() throws IllegalStateException {
MyLogger.logHighLevelMsg(this.getName() + " started!");
CommandSender statRequester = statRequest.getSettings().getCommandSender();
if (statRequest == null) {
throw new NullPointerException("No statistic requestSettings was found!");
}
if (reloadThread != null && reloadThread.isAlive()) {
try {
MyLogger.logLowLevelMsg(this.getName() + ": Waiting for " + reloadThread.getName() + " to finish up...");
outputManager.sendFeedbackMsg(statRequest.getSettings().getCommandSender(), StandardMessage.STILL_RELOADING);
outputManager.sendFeedbackMsg(statRequester, StandardMessage.STILL_RELOADING);
reloadThread.join();
} catch (InterruptedException e) {
@ -55,21 +53,16 @@ public final class StatThread extends Thread {
long lastCalc = ThreadManager.getLastRecordedCalcTime();
if (lastCalc > 2000) {
outputManager.sendFeedbackMsgWaitAMoment(statRequest.getSettings().getCommandSender(), lastCalc > 20000);
outputManager.sendFeedbackMsgWaitAMoment(statRequester, lastCalc > 20000);
}
Target selection = statRequest.getSettings().getTarget();
try {
TextComponent statResult = switch (selection) {
case PLAYER -> outputManager.formatAndSavePlayerStat(statRequest.getSettings(), statCalculator.getPlayerStat(statRequest.getSettings()));
case TOP -> outputManager.formatAndSaveTopStat(statRequest.getSettings(), statCalculator.getTopStats(statRequest.getSettings()));
case SERVER -> outputManager.formatAndSaveServerStat(statRequest.getSettings(), statCalculator.getServerStat(statRequest.getSettings()));
};
outputManager.sendToCommandSender(statRequest.getSettings().getCommandSender(), statResult);
StatResult<?> result = statRequest.execute();
outputManager.sendToCommandSender(statRequester, result.formattedComponent());
}
catch (ConcurrentModificationException e) {
if (!statRequest.getSettings().isConsoleSender()) {
outputManager.sendFeedbackMsg(statRequest.getSettings().getCommandSender(), StandardMessage.UNKNOWN_ERROR);
outputManager.sendFeedbackMsg(statRequester, StandardMessage.UNKNOWN_ERROR);
}
}
}

View File

@ -4,6 +4,7 @@ import com.artemis.the.gr8.playerstats.Main;
import com.artemis.the.gr8.playerstats.statistic.result.StatResult;
import com.artemis.the.gr8.playerstats.utils.EnumHandler;
import com.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler;
import net.kyori.adventure.text.TextComponent;
import org.bukkit.Material;
import org.bukkit.Statistic;
import org.bukkit.command.CommandSender;
@ -18,7 +19,7 @@ import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public final class InternalStatRequest extends StatRequest<Object> {
public final class InternalStatRequest extends StatRequest<TextComponent> {
private final OfflinePlayerHandler offlinePlayerHandler;
private final EnumHandler enumHandler;
@ -30,14 +31,17 @@ public final class InternalStatRequest extends StatRequest<Object> {
enumHandler = Main.getEnumHandler();
targetPattern = Pattern.compile("top|server|me|player");
String[] argsMinusTarget = extractAndStoreTarget(sender, args);
String[] argsMinusStatistic = extractAndStoreStatistic(argsMinusTarget);
findAndStoreSubStat(argsMinusStatistic);
processArgs(sender, args);
}
@Override
public StatResult<Object> execute() {
return null;
public @NotNull StatResult<TextComponent> execute() {
return Main.getRequestProcessor().getInternalResult(settings);
}
private void processArgs(CommandSender sender, String[] args) {
String[] argsMinusTarget = extractAndStoreTarget(sender, args);
findStatAndSubStat(argsMinusTarget);
}
private String[] extractAndStoreTarget(CommandSender sender, @NotNull String[] leftoverArgs) {
@ -80,18 +84,17 @@ public final class InternalStatRequest extends StatRequest<Object> {
return leftoverArgs;
}
private String[] extractAndStoreStatistic(@NotNull String[] leftoverArgs) {
private void findStatAndSubStat(@NotNull String[] leftoverArgs) {
for (String arg : leftoverArgs) {
if (enumHandler.isStatistic(arg)) {
super.settings.setStatistic(EnumHandler.getStatEnum(arg));
return removeArg(leftoverArgs, arg);
Statistic stat = EnumHandler.getStatEnum(arg);
String[] argsWithoutStat = removeArg(leftoverArgs, arg);
findAndStoreSubStat(argsWithoutStat, stat);
}
}
return leftoverArgs;
}
private void findAndStoreSubStat(@NotNull String[] leftoverArgs) {
Statistic statistic = super.settings.getStatistic();
private void findAndStoreSubStat(String[] leftoverArgs, Statistic statistic) {
if (statistic == null || leftoverArgs.length == 0) {
return;
}
@ -139,4 +142,5 @@ public final class InternalStatRequest extends StatRequest<Object> {
currentArgs.remove(argToRemove);
return currentArgs.toArray(String[]::new);
}
}

View File

@ -2,9 +2,7 @@ package com.artemis.the.gr8.playerstats.statistic.request;
import com.artemis.the.gr8.playerstats.Main;
import com.artemis.the.gr8.playerstats.api.RequestGenerator;
import com.artemis.the.gr8.playerstats.msg.components.ComponentUtils;
import com.artemis.the.gr8.playerstats.statistic.result.StatResult;
import net.kyori.adventure.text.TextComponent;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Statistic;
@ -40,18 +38,6 @@ public final class PlayerStatRequest extends StatRequest<Integer> implements Req
@Override
public @NotNull StatResult<Integer> execute() {
int stat = Main
.getStatCalculator()
.getPlayerStat(settings);
TextComponent prettyComponent = Main
.getOutputManager()
.formatAndSavePlayerStat(settings, stat);
String prettyString = ComponentUtils
.getTranslatableComponentSerializer()
.serialize(prettyComponent);
return new StatResult<>(stat, prettyComponent, prettyString);
return Main.getRequestProcessor().getPlayerResult(settings);
}
}

View File

@ -2,9 +2,7 @@ package com.artemis.the.gr8.playerstats.statistic.request;
import com.artemis.the.gr8.playerstats.Main;
import com.artemis.the.gr8.playerstats.api.RequestGenerator;
import com.artemis.the.gr8.playerstats.msg.components.ComponentUtils;
import com.artemis.the.gr8.playerstats.statistic.result.StatResult;
import net.kyori.adventure.text.TextComponent;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Statistic;
@ -40,18 +38,6 @@ public final class ServerStatRequest extends StatRequest<Long> implements Reques
@Override
public @NotNull StatResult<Long> execute() {
long stat = Main
.getStatCalculator()
.getServerStat(settings);
TextComponent prettyComponent = Main
.getOutputManager()
.formatAndSaveServerStat(settings, stat);
String prettyString = ComponentUtils
.getTranslatableComponentSerializer()
.serialize(prettyComponent);
return new StatResult<>(stat, prettyComponent, prettyString);
return Main.getRequestProcessor().getServerResult(settings);
}
}

View File

@ -28,43 +28,9 @@ public abstract class StatRequest<T> {
settings = new Settings(requester);
}
protected StatRequest<T> configureUntyped(@NotNull Statistic statistic) {
if (statistic.getType() == Statistic.Type.UNTYPED) {
settings.setStatistic(statistic);
return this;
}
throw new IllegalArgumentException("This statistic is not of Type.Untyped");
}
protected StatRequest<T> configureBlockOrItemType(@NotNull Statistic statistic, @NotNull Material material) throws IllegalArgumentException {
Statistic.Type type = statistic.getType();
if (type == Statistic.Type.BLOCK && material.isBlock()) {
settings.setBlock(material);
}
else if (type == Statistic.Type.ITEM && material.isItem()){
settings.setItem(material);
}
else {
throw new IllegalArgumentException("Either this statistic is not of Type.Block or Type.Item, or no valid block or item has been provided");
}
settings.setStatistic(statistic);
settings.setSubStatEntryName(material.toString());
return this;
}
protected StatRequest<T> configureEntityType(@NotNull Statistic statistic, @NotNull EntityType entityType) throws IllegalArgumentException {
if (statistic.getType() == Statistic.Type.ENTITY) {
settings.setStatistic(statistic);
settings.setSubStatEntryName(entityType.toString());
settings.setEntity(entityType);
return this;
}
throw new IllegalArgumentException("This statistic is not of Type.Entity");
}
/**
* Executes this StatRequest. For a Top- or ServerRequest, this can
* take some time!
* Executes this StatRequest. This calculation can take some time,
* so don't call this from the main Thread if you can help it!
*
* @return a StatResult containing the value of this lookup, both as
* numerical value and as formatted message
@ -111,6 +77,40 @@ public abstract class StatRequest<T> {
}
}
protected StatRequest<T> configureUntyped(@NotNull Statistic statistic) {
if (statistic.getType() == Statistic.Type.UNTYPED) {
settings.statistic = statistic;
return this;
}
throw new IllegalArgumentException("This statistic is not of Type.Untyped");
}
protected StatRequest<T> configureBlockOrItemType(@NotNull Statistic statistic, @NotNull Material material) throws IllegalArgumentException {
Statistic.Type type = statistic.getType();
if (type == Statistic.Type.BLOCK && material.isBlock()) {
settings.block = material;
}
else if (type == Statistic.Type.ITEM && material.isItem()){
settings.item = material;
}
else {
throw new IllegalArgumentException("Either this statistic is not of Type.Block or Type.Item, or no valid block or item has been provided");
}
settings.statistic = statistic;
settings.subStatEntryName = material.toString();
return this;
}
protected StatRequest<T> configureEntityType(@NotNull Statistic statistic, @NotNull EntityType entityType) throws IllegalArgumentException {
if (statistic.getType() == Statistic.Type.ENTITY) {
settings.statistic = statistic;
settings.entity = entityType;
settings.subStatEntryName = entityType.toString();
return this;
}
throw new IllegalArgumentException("This statistic is not of Type.Entity");
}
public static final class Settings {
private final CommandSender sender;
private Statistic statistic;
@ -158,18 +158,10 @@ public abstract class StatRequest<T> {
return sender instanceof ConsoleCommandSender;
}
void setStatistic(Statistic statistic) {
this.statistic = statistic;
}
public Statistic getStatistic() {
return statistic;
}
private void setSubStatEntryName(String subStatEntry) {
this.subStatEntryName = subStatEntry;
}
public @Nullable String getSubStatEntryName() {
return subStatEntryName;
}
@ -186,26 +178,14 @@ public abstract class StatRequest<T> {
return this.topListSize;
}
void setEntity(EntityType entity) {
this.entity = entity;
}
public EntityType getEntity() {
return entity;
}
void setBlock(Material block) {
this.block = block;
}
public Material getBlock() {
return block;
}
void setItem(Material item) {
this.item = item;
}
public Material getItem() {
return item;
}

View File

@ -3,8 +3,6 @@ package com.artemis.the.gr8.playerstats.statistic.request;
import com.artemis.the.gr8.playerstats.Main;
import com.artemis.the.gr8.playerstats.statistic.result.StatResult;
import com.artemis.the.gr8.playerstats.api.RequestGenerator;
import com.artemis.the.gr8.playerstats.msg.components.ComponentUtils;
import net.kyori.adventure.text.TextComponent;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Statistic;
@ -42,18 +40,6 @@ public final class TopStatRequest extends StatRequest<LinkedHashMap<String, Inte
@Override
public @NotNull StatResult<LinkedHashMap<String, Integer>> execute() {
LinkedHashMap<String, Integer> stat = Main
.getStatCalculator()
.getTopStats(settings);
TextComponent prettyComponent = Main
.getOutputManager()
.formatAndSaveTopStat(settings, stat);
String prettyString = ComponentUtils
.getTranslatableComponentSerializer()
.serialize(prettyComponent);
return new StatResult<>(stat, prettyComponent, prettyString);
return Main.getRequestProcessor().getTopResult(settings);
}
}

View File

@ -1,6 +1,6 @@
package com.artemis.the.gr8.playerstats.statistic.result;
import com.artemis.the.gr8.playerstats.api.ApiFormatter;
import com.artemis.the.gr8.playerstats.api.StatFormatter;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.kyori.adventure.text.TextComponent;
@ -31,7 +31,7 @@ import net.kyori.adventure.text.TextComponent;
* To send a Component, you need to get a {@link BukkitAudiences} object,
* and use that to send the desired Component. Normally you would have to add
* Adventure as a dependency to your project, but since the library is included
* in PlayerStats, you can access it through the PlayerStatsAPI. Information
* in PlayerStats, you can access it through the PlayerStatsImpl. Information
* on how to get and use the BukkitAudiences object can be found on
* <a href="https://docs.adventure.kyori.net/platform/bukkit.html">Adventure's website</a>.
*
@ -39,7 +39,7 @@ import net.kyori.adventure.text.TextComponent;
* same information in String-format. Don't use Adventure's <code>#content()</code>
* or <code>#toString()</code> methods on the Components - those won't get the actual
* message. And finally, if you want the results to be formatted differently,
* you can get an instance of the {@link ApiFormatter}.
* you can get an instance of the {@link StatFormatter}.
*/
public record StatResult<T>(T value, TextComponent formattedComponent, String formattedString) {