mirror of
https://github.com/itHotL/PlayerStats.git
synced 2025-01-07 19:27:47 +01:00
Reworked InternalStatRequest and the other classes dealing with StatRequests (#114)
This commit is contained in:
parent
b46a25d23f
commit
31713007f5
@ -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() {
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
@ -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);
|
||||
}
|
@ -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> {
|
||||
|
@ -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
|
@ -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 {
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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}
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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());
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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) {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user