diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/api/PlayerStats.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/api/PlayerStats.java index 314d4e2..7c36aca 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/api/PlayerStats.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/api/PlayerStats.java @@ -1,34 +1,19 @@ package com.gmail.artemis.the.gr8.playerstats.api; import com.gmail.artemis.the.gr8.playerstats.Main; -import net.kyori.adventure.platform.bukkit.BukkitAudiences; -import net.kyori.adventure.text.*; -import org.bukkit.Material; -import org.bukkit.Statistic; -import org.bukkit.entity.EntityType; +import com.gmail.artemis.the.gr8.playerstats.enums.Target; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; - /** This is the outgoing API that you can use to access the core functionality of PlayerStats. - To work with it, you need to call PlayerStats.{@link #getAPI()} to get an instance of {@link PlayerStatsAPI}. - You can then use this object to access any of the further methods. + To work with it, you need to call PlayerStats.{@link #getAPI()} to get an instance of + {@link PlayerStatsAPI}. You can then use this object to access any of the further methods.
-
Since calculating a top or server statistics can take some time, it is recommended to call all the - getServerStat() or getTopStats() methods asynchronously. Otherwise, the main Thread will have - to wait until all calculations are done, and this might cause some lag spikes on the server. -
-
The result of the methods in PlayerStats' API are returned in the form of a TextComponent, - which can be sent directly to a Minecraft client or console with the Adventure library. - To send a Component, you need to get a {@link BukkitAudiences} object. Normally you would - have to add the library as a dependency, but since the library is included in PlayerStats, you can - access it directly. Information on how to get and use the BukkitAudiences object can be found on - Adventure's website. -
-
Alternatively, you can also turn your TextComponent into a plain String with - {@link #statResultComponentToString(TextComponent)}. Don't use Adventure's method .content() - on your statResult to do this - because of the way the TextComponent is built by PlayerStats, - you won't be able to get the full content that way.

*/ +
Since calculating a top or server statistics can take some time, I strongly + encourage you to call all the getServerStat() and getTopStats() methods from the + {@link StatCalculator} asynchronously. Otherwise, the main Thread will have to wait + until all calculations are done, and this might severely impact server performance. +*/ public interface PlayerStats { /** Returns an instance of the {@link PlayerStatsAPI}. @@ -38,68 +23,15 @@ public interface PlayerStats { return Main.getPlayerStatsAPI(); } - String statResultComponentToString(TextComponent component); + /** The {@link StatCalculator} is responsible for getting, calculating and/or ordering raw numbers. + It gets its data from the vanilla statistic files (stored by the server). It can return three kinds of data, + depending on the chosen {@link Target}: +
- int (for {@link Target#PLAYER}) +
- long (for {@link Target#SERVER}) +
- LinkedHashMap[String player-name, Integer number] (for {@link Target#TOP})*/ + StatCalculator statCalculator(); - /** Get a formatted player-statistic of Statistic.Type Untyped. - @return a TextComponent with the following parts: -
[player-name]: [number] [stat-name] - @throws NullPointerException if statistic or playerName is null*/ - TextComponent getPlayerStat(@NotNull Statistic statistic, @NotNull String playerName) throws NullPointerException; + RequestGenerator requestGenerator(); - /** Get a formatted player-statistic of Statistic.Type Block or Item. - @return a TextComponent with the following parts: -
[player-name]: [number] [stat-name] [sub-stat-name] - @throws NullPointerException if statistic, material or playerName is null*/ - TextComponent getPlayerStat(@NotNull Statistic statistic, @NotNull Material material, @NotNull String playerName) throws NullPointerException; - - /** Get a formatted player-statistic of Statistic.Type Entity. - @return a TextComponent with the following parts: -
[player-name]: [number] [stat-name] [sub-stat-name] - @throws NullPointerException if statistic, entity or playerName is null*/ - TextComponent getPlayerStat(@NotNull Statistic statistic, @NotNull EntityType entity, @NotNull String playerName) throws NullPointerException; - - /** Get a formatted server-statistic of Statistic.Type Untyped. Don't call this from the main Thread (see class description)! - @return a TextComponent with the following parts: -
[Total on] [server-name]: [number] [stat-name] - @throws NullPointerException if statistic is null*/ - TextComponent getServerStat(@NotNull Statistic statistic) throws NullPointerException; - - /** Get a formatted server-statistic of Statistic.Type Block or Item. Don't call this from the main Thread (see class description)! - @return a TextComponent with the following parts: -
[Total on] [server-name]: [number] [stat-name] [sub-stat-name] - @throws NullPointerException if statistic or material is null*/ - TextComponent getServerStat(@NotNull Statistic statistic, @NotNull Material material) throws NullPointerException; - - /** Get a formatted server-statistic of Statistic.Type Entity. Don't call this from the main Thread (see class description)! - @return a TextComponent with the following parts: -
[Total on] [server-name]: [number] [stat-name] [sub-stat-name] - @throws NullPointerException if statistic or entity is null*/ - TextComponent getServerStat(@NotNull Statistic statistic, @NotNull EntityType entity) throws NullPointerException; - - /** Get a formatted top-statistic of Statistic.Type Untyped. Don't call this from the main Thread (see class description)! - @return a TextComponent with the following parts: -
[PlayerStats] [Top 10] [stat-name] -
[1.] [player-name] [number] -
[2.] [player-name] [number] -
[3.] etc... - @throws NullPointerException if statistic is null*/ - TextComponent getTopStats(@NotNull Statistic statistic) throws NullPointerException; - - /** Get a formatted top-statistic of Statistic.Type Block or Item. Don't call this from the main Thread (see class description)! - @return a TextComponent with the following parts: -
[PlayerStats] [Top 10] [stat-name] [sub-stat-name] -
[1.] [player-name] [number] -
[2.] [player-name] [number] -
[3.] etc... - @throws NullPointerException if statistic or material is null*/ - TextComponent getTopStats(@NotNull Statistic statistic, @NotNull Material material) throws NullPointerException; - - /** Get a formatted top-statistic of Statistic.Type Entity. Don't call this from the main Thread (see class description)! - @return a TextComponent with the following parts: -
[PlayerStats] [Top 10] [stat-name] [sub-stat-name] -
[1.] [player-name] [number] -
[2.] [player-name] [number] -
[3.] etc... - @throws NullPointerException if statistic or entity is null*/ - TextComponent getTopStats(@NotNull Statistic statistic, @NotNull EntityType entity) throws NullPointerException; + StatFormatter statFormatter(); } \ No newline at end of file diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/api/PlayerStatsAPI.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/api/PlayerStatsAPI.java index fa359bf..d443e3e 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/api/PlayerStatsAPI.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/api/PlayerStatsAPI.java @@ -1,19 +1,7 @@ package com.gmail.artemis.the.gr8.playerstats.api; -import com.gmail.artemis.the.gr8.playerstats.enums.Target; -import com.gmail.artemis.the.gr8.playerstats.models.StatRequest; import com.gmail.artemis.the.gr8.playerstats.statistic.RequestManager; import com.gmail.artemis.the.gr8.playerstats.statistic.StatManager; -import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger; -import net.kyori.adventure.text.TextComponent; -import org.bukkit.Material; -import org.bukkit.Statistic; -import org.bukkit.entity.EntityType; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - - -import java.util.LinkedHashMap; import static org.jetbrains.annotations.ApiStatus.Internal; @@ -32,76 +20,17 @@ public final class PlayerStatsAPI implements PlayerStats { } @Override - public String statResultComponentToString(TextComponent component) { - return statFormatter.statResultComponentToString(component); + public StatCalculator statCalculator() { + return statManager; } @Override - public TextComponent getPlayerStat(@NotNull Statistic statistic, @NotNull String playerName) throws NullPointerException { - return getFormattedStatistic(Target.PLAYER, statistic, null, null, playerName); + public RequestGenerator requestGenerator() { + return requestManager; } @Override - public TextComponent getPlayerStat(@NotNull Statistic statistic, @NotNull Material material, @NotNull String playerName) throws NullPointerException { - return getFormattedStatistic(Target.PLAYER, statistic, material, null, playerName); - } - - @Override - public TextComponent getPlayerStat(@NotNull Statistic statistic, @NotNull EntityType entity, @NotNull String playerName) throws NullPointerException { - return getFormattedStatistic(Target.PLAYER, statistic, null, entity, playerName); - } - - @Override - public TextComponent getServerStat(@NotNull Statistic statistic) throws NullPointerException { - return getFormattedStatistic(Target.SERVER, statistic, null, null, null); - } - - @Override - public TextComponent getServerStat(@NotNull Statistic statistic, @NotNull Material material) throws NullPointerException { - return getFormattedStatistic(Target.SERVER, statistic, material, null, null); - } - - @Override - public TextComponent getServerStat(@NotNull Statistic statistic, @NotNull EntityType entity) throws NullPointerException { - return getFormattedStatistic(Target.SERVER, statistic, null, entity, null); - } - - @Override - public TextComponent getTopStats(@NotNull Statistic statistic) throws NullPointerException { - return getFormattedStatistic(Target.TOP, statistic, null, null, null); - } - - @Override - public TextComponent getTopStats(@NotNull Statistic statistic, @NotNull Material material) throws NullPointerException { - return getFormattedStatistic(Target.TOP, statistic, material, null, null); - } - - @Override - public TextComponent getTopStats(@NotNull Statistic statistic, @NotNull EntityType entity) throws NullPointerException { - return getFormattedStatistic(Target.TOP, statistic, null, entity, null); - } - - private TextComponent getFormattedStatistic(@NotNull Target selection, @NotNull Statistic statistic, - @Nullable Material material, @Nullable EntityType entity, @Nullable String playerName) throws NullPointerException { - StatRequest request = requestManager.generateRequest(selection, statistic, material, entity, playerName); - if (requestManager.validateAPIRequest(request)) { - MyLogger.logMsg("API is being called! We are calculating a " + selection + "for " + statistic); - switch (selection) { - case PLAYER -> { - int stat = statManager.getPlayerStat(request); - return statFormatter.formatPlayerStat(request, stat); - } - case SERVER -> { - long stat = statManager.getServerStat(request); - return statFormatter.formatServerStat(request, stat); - } - case TOP -> { - LinkedHashMap stats = statManager.getTopStats(request); - return statFormatter.formatTopStat(request, stats); - } - } - } - throw new NullPointerException("Not enough parameters are present for a valid statistic look-up! " + - "Make sure you include a block/item/entity if Statistic.Type is not Untyped, and include a playerName if you want a player-statistic"); + public StatFormatter statFormatter() { + return statFormatter; } } \ No newline at end of file diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/api/RequestGenerator.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/api/RequestGenerator.java index 7e8ddbb..bba937a 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/api/RequestGenerator.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/api/RequestGenerator.java @@ -1,29 +1,32 @@ package com.gmail.artemis.the.gr8.playerstats.api; -import com.gmail.artemis.the.gr8.playerstats.enums.Target; import com.gmail.artemis.the.gr8.playerstats.models.StatRequest; import org.bukkit.Material; import org.bukkit.Statistic; import org.bukkit.command.CommandSender; import org.bukkit.entity.EntityType; -import org.jetbrains.annotations.NotNull; -/** The {@link RequestGenerator} can turn some user input, such as a String - (for example: "stat animals_bred") into a specific {@link StatRequest} that holds - all the information {@link PlayerStatsAPI} needs to work with. - This StatRequest is then used by the {@link StatCalculator} to get the desired statistic data.*/ +/** Turns user input into a valid {@link StatRequest}. This StatRequest should hold all + the information PlayerStats needs to work with, and is used by the {@link StatCalculator} + to get the desired statistic data.*/ public interface RequestGenerator { /** This will create a {@link StatRequest} from the provided args, with the requesting Player (or Console) - as CommandSender. This CommandSender will receive feedback messages if the SimpleStatRequest could not be created. + as CommandSender. This CommandSender will receive feedback messages if the StatRequest could not be created. + @param args an Array of args such as a CommandSender would put in Minecraft chat:

- a stat-name (example: "mine_block")

- if applicable, a sub-stat-name (example: diorite)(

- a target for this lookup: can be "top", "server", "player" (or "me" to indicate the current CommandSender)

- if "player" was chosen, include a player-name

@param sender the CommandSender that requested this specific statistic + @return the generated StatRequest @throws IllegalArgumentException if the args do not result in a valid statistic look-up*/ StatRequest generateRequest(CommandSender sender, String[] args); - StatRequest generateRequest(@NotNull Target selection, @NotNull Statistic statistic, Material material, EntityType entity, String playerName); + StatRequest createPlayerStatRequest(String playerName, Statistic statistic, Material material, EntityType entity); + + StatRequest createServerStatRequest(Statistic statistic, Material material, EntityType entityType); + + StatRequest createTopStatRequest(Statistic statistic, Material material, EntityType entityType); } diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/api/StatCalculator.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/api/StatCalculator.java index 93e9b4b..d2aabc4 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/api/StatCalculator.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/api/StatCalculator.java @@ -5,12 +5,16 @@ import com.gmail.artemis.the.gr8.playerstats.models.StatRequest; import java.util.LinkedHashMap; /** The {@link StatCalculator} represents the actual statistic-getting magic that happens once a valid - {@link StatRequest} has been obtained. It takes a valid StatRequest, and returns (a map of) numbers. */ + {@link StatRequest} is passed to it. It takes a valid StatRequest, and returns (a map of) numbers. + For more information on how to create a valid StatRequest, see the class description for {@link StatRequest}.*/ public interface StatCalculator { + /** Returns the requested Statistic*/ int getPlayerStat(StatRequest request); + /** Don't call from main Thread!*/ long getServerStat(StatRequest request); + /** Don't call from main Thread!*/ LinkedHashMap getTopStats(StatRequest request); } diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/api/StatFormatter.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/api/StatFormatter.java index 3af9399..7672ac5 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/api/StatFormatter.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/api/StatFormatter.java @@ -1,25 +1,47 @@ package com.gmail.artemis.the.gr8.playerstats.api; import com.gmail.artemis.the.gr8.playerstats.models.StatRequest; +import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.text.*; import java.util.LinkedHashMap; -/** The {@link StatFormatter} defines what the output of any given statistic look-up should be. -

-

The Formatter takes a {@link StatRequest} and the result of {@link StatCalculator} calculations, and transforms the - request object and raw numbers into a pretty message (TextComponent) with all the relevant information in it. - This output is ready to be sent to a Player or Console, or can be turned into a String representation if necessary.*/ +/** The {@link StatFormatter} formats raw numbers into pretty messages. + This Formatter takes a {@link StatRequest} and combines it with the raw number(s) + returned by the {@link StatCalculator}, and transforms those into a pretty message + (by default a TextComponent) with all the relevant information in it. +
+
The output is ready to be sent to a Minecraft client or console with the Adventure library. + To send a Component, you need to get a {@link BukkitAudiences} object. Normally you would + have to add the library as a dependency, but since the library is included in PlayerStats, you can + access it directly. Information on how to get and use the BukkitAudiences object can be found on + Adventure's website. +
+
Alternatively, you can also turn your TextComponent into a plain String with + {@link #statResultComponentToString(TextComponent)}. Don't use Adventure's method .content() + on your statResult to do this - because of the way the TextComponent is built by PlayerStats, + you won't be able to get the full content that way.*/ public interface StatFormatter { /** Turns a TextComponent into its String representation. If you don't want to work with Adventure's TextComponents, you can call this method to turn any stat-result into a String. - @return a String representation of this TextComponent, without hover/click events, but with color, style and formatting */ + @return a String representation of this TextComponent, without hover/click events, + but with color, style and formatting. TranslatableComponents will be turned into + plain English.*/ String statResultComponentToString(TextComponent statResult); + /** @return a TextComponent with the following parts: +
[player-name]: [number] [stat-name] {sub-stat-name}*/ TextComponent formatPlayerStat(StatRequest request, int playerStat); + /** @return a TextComponent with the following parts: +
[Total on] [server-name]: [number] [stat-name] [sub-stat-name]*/ TextComponent formatServerStat(StatRequest request, long serverStat); + /** @return a TextComponent with the following parts: +
[PlayerStats] [Top 10] [stat-name] [sub-stat-name] +
[1.] [player-name] [number] +
[2.] [player-name] [number] +
[3.] etc...*/ TextComponent formatTopStat(StatRequest request, LinkedHashMap topStats); } \ No newline at end of file diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/models/StatRequest.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/models/StatRequest.java index 588cf98..183042d 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/models/StatRequest.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/models/StatRequest.java @@ -1,40 +1,70 @@ package com.gmail.artemis.the.gr8.playerstats.models; import com.gmail.artemis.the.gr8.playerstats.enums.Target; +import com.gmail.artemis.the.gr8.playerstats.api.RequestGenerator; import org.bukkit.Material; import org.bukkit.Statistic; import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.EntityType; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -/** The Object PlayerStats uses to calculate the appropriate statistic. - It is generated from the args provided by a CommandSender when /stat is called, - and always contains this CommandSender. By default, {@link #getSelection()} - will return {@link Target#TOP}, unless another selection is specified in the args.*/ -public final class StatRequest { +/** A StatRequest is the object PlayerStats uses to calculate and format the requested statistic. + This object can be generated from two different sources: +
- Internally: by PlayerStats itself when /stat is called, using the args provided by the CommandSender. +
- Externally: through the API methods provided by the {@link RequestGenerator} interface. +
+
For this StatRequest to be valid, it needs the following values: +

*/ +public class StatRequest { private final CommandSender sender; private boolean isAPIRequest; private Statistic statistic; private String playerName; - private Target selection; + private Target target; - private String subStatEntry; + private String subStatEntryName; private EntityType entity; private Material block; private Material item; private boolean playerFlag; - //make a SimpleStatRequest for a given CommandSender with some default values + /** Create a new {@link StatRequest} with default values: +
- CommandSender sender (provided) +
- Target target = {@link Target#TOP} +
- boolean playerFlag = false +
- boolean isAPIRequest = false + + @param sender the CommandSender who prompted this RequestGenerator + */ public StatRequest(@NotNull CommandSender sender) { this(sender, false); } + /** Create a new {@link StatRequest} with default values: +
- CommandSender sender (provided) +
- Target target = {@link Target#TOP} +
- boolean playerFlag = false +
- boolean isAPIRequest (provided) + + @param sender the CommandSender who prompted this RequestGenerator + @param isAPIRequest whether this RequestGenerator is coming through the API or the onCommand + */ public StatRequest(@NotNull CommandSender sender, boolean isAPIRequest) { this.sender = sender; this.isAPIRequest = isAPIRequest; - selection = Target.TOP; + target = Target.TOP; playerFlag = false; } @@ -54,23 +84,30 @@ public final class StatRequest { return sender instanceof ConsoleCommandSender; } + /** Set a {@link Statistic} for this StatRequest.*/ public void setStatistic(Statistic statistic) { this.statistic = statistic; } - /** Returns the set enum constant Statistic, or null if none was set. */ + /** If a {@link Statistic} was set, this will return it. + + @return the statistic for this RequestGenerator*/ public Statistic getStatistic() { return statistic; } - /** Sets the subStatEntry, and automatically tries to get the corresponding item/block/entity if there is a valid statType present. - If the subStatEntry is set to null, any present item/block/entity is set to null again. */ - public void setSubStatEntry(String subStatEntry) { - this.subStatEntry = subStatEntry; + /** Sets the subStatEntryName (a block-, item- or entity-name). */ + public void setSubStatEntryName(String subStatEntry) { + this.subStatEntryName = subStatEntry; } - public String getSubStatEntry() { - return subStatEntry; + /** If a {@link Statistic} is set, and this Statistic is of Type Block, Item or Entity, + this will return the name of said block, item or entity + (in the way .toString would for the given enum constant). + + @return the subStatEntryName*/ + public @Nullable String getSubStatEntryName() { + return subStatEntryName; } public void setPlayerName(String playerName) { @@ -86,18 +123,24 @@ public final class StatRequest { this.playerFlag = playerFlag; } - /** The "player" arg is a special case, because it could either be a valid subStatEntry, or indicate that the lookup action should target a specific player. - This is why the playerFlag exists - if this is true, and playerName is null, subStatEntry should be set to "player". */ + /** For internal use. The "player" arg is a special case, because it could either be + a valid subStatEntry, or indicate that the lookup action should target + a specific player. This is why the playerFlag exists - if this flag true, + and playerName is null, the subStatEntry should be set to "player". */ public boolean getPlayerFlag() { return playerFlag; } - public void setSelection(Target selection) { - this.selection = selection; + public void setTarget(Target target) { + this.target = target; } - public @NotNull Target getSelection() { - return selection; + /** Returns the {@link Target} for this StatRequest. + If no Target is explicitly set, this will return {@link Target#TOP}. + All static factory methods that create a {@link StatRequest} set the + appropriate Target for themselves, so there is no need to manually set the Target.*/ + public @NotNull Target getTarget() { + return target; } public void setEntity(EntityType entity) { diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/msg/MessageBuilder.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/msg/MessageBuilder.java index 4462a6d..fe30fb2 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/msg/MessageBuilder.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/msg/MessageBuilder.java @@ -177,7 +177,7 @@ public class MessageBuilder { .append(getStatNumberComponent(request.getStatistic(), stat, Target.PLAYER, request.isConsoleSender())) .append(space()) .append(getStatNameComponent(request)) - .append(getStatUnitComponent(request.getStatistic(), request.getSelection(), request.isConsoleSender())) //space is provided by statUnitComponent + .append(getStatUnitComponent(request.getStatistic(), request.getTarget(), request.isConsoleSender())) //space is provided by statUnitComponent .build(); return getFormattingFunction(playerStat, Target.PLAYER); @@ -197,7 +197,7 @@ public class MessageBuilder { .append(getStatNumberComponent(request.getStatistic(), stat, Target.SERVER, request.isConsoleSender())) .append(space()) .append(getStatNameComponent(request)) - .append(getStatUnitComponent(request.getStatistic(), request.getSelection(), request.isConsoleSender())) //space is provided by statUnit + .append(getStatUnitComponent(request.getStatistic(), request.getTarget(), request.isConsoleSender())) //space is provided by statUnit .build(); return getFormattingFunction(serverStat, Target.SERVER); @@ -308,7 +308,7 @@ public class MessageBuilder { .append(componentFactory.title(config.getTopStatsTitle(), Target.TOP)).append(space()) .append(componentFactory.titleNumber(statListSize)).append(space()) .append(getStatNameComponent(request)) //space is provided by statUnitComponent - .append(getStatUnitComponent(request.getStatistic(), request.getSelection(), request.isConsoleSender())) + .append(getStatUnitComponent(request.getStatistic(), request.getTarget(), request.isConsoleSender())) .build(); } @@ -353,7 +353,7 @@ public class MessageBuilder { private TextComponent getStatNameComponent(StatRequest request) { if (config.useTranslatableComponents()) { String statKey = languageKeyHandler.getStatKey(request.getStatistic()); - String subStatKey = request.getSubStatEntry(); + String subStatKey = request.getSubStatEntryName(); if (subStatKey != null) { switch (request.getStatistic().getType()) { case BLOCK -> subStatKey = languageKeyHandler.getBlockKey(request.getBlock()); @@ -363,13 +363,13 @@ public class MessageBuilder { } } } - return componentFactory.statAndSubStatNameTranslatable(statKey, subStatKey, request.getSelection()); + return componentFactory.statAndSubStatNameTranslatable(statKey, subStatKey, request.getTarget()); } else { return componentFactory.statAndSubStatName( StringUtils.prettify(request.getStatistic().toString()), - StringUtils.prettify(request.getSubStatEntry()), - request.getSelection()); + StringUtils.prettify(request.getSubStatEntryName()), + request.getTarget()); } } diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/reload/ReloadAction.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/reload/ReloadAction.java index 03b55c2..784398b 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/reload/ReloadAction.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/reload/ReloadAction.java @@ -10,7 +10,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.RecursiveAction; /** The action that is executed when a reload-command is triggered. */ -public final class ReloadAction extends RecursiveAction { +final class ReloadAction extends RecursiveAction { private static int threshold; diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/RequestManager.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/RequestManager.java index dce94d2..833f0e8 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/RequestManager.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/RequestManager.java @@ -16,18 +16,31 @@ import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -public class RequestManager implements RequestGenerator { +public final class RequestManager extends StatRequest implements RequestGenerator { private final EnumHandler enumHandler; private final OfflinePlayerHandler offlinePlayerHandler; private static OutputManager outputManager; public RequestManager(EnumHandler enumHandler, OfflinePlayerHandler offlinePlayerHandler, OutputManager outputManager) { + super(Bukkit.getConsoleSender()); this.enumHandler = enumHandler; this.offlinePlayerHandler = offlinePlayerHandler; RequestManager.outputManager = outputManager; } + /** This will create a {@link StatRequest} from the provided args, with the requesting Player (or Console) + as CommandSender. This CommandSender will receive feedback messages if the StatRequest could not be created. + + @param args an Array of args such as a CommandSender would put in Minecraft chat: +

- a statName (example: "mine_block")

+

- if applicable, a subStatEntryName (example: diorite)(

+

- a target for this lookup: can be "top", "server", "player" (or "me" to indicate the current CommandSender)

+

- if "player" was chosen, include a playerName

+ + @param sender the CommandSender that requested this specific statistic + @return the generated StatRequest + */ public StatRequest generateRequest(CommandSender sender, String[] args) { StatRequest request = new StatRequest(sender); for (String arg : args) { @@ -41,28 +54,28 @@ public class RequestManager implements RequestGenerator { request.setPlayerFlag(true); } else { - if (request.getSubStatEntry() == null) request.setSubStatEntry(arg); + if (request.getSubStatEntryName() == null) request.setSubStatEntryName(arg); } } //check for selection else if (arg.equalsIgnoreCase("top")) { - request.setSelection(Target.TOP); + request.setTarget(Target.TOP); } else if (arg.equalsIgnoreCase("server")) { - request.setSelection(Target.SERVER); + request.setTarget(Target.SERVER); } else if (arg.equalsIgnoreCase("me")) { if (sender instanceof Player) { request.setPlayerName(sender.getName()); - request.setSelection(Target.PLAYER); + request.setTarget(Target.PLAYER); } else if (sender instanceof ConsoleCommandSender) { - request.setSelection(Target.SERVER); + request.setTarget(Target.SERVER); } } else if (offlinePlayerHandler.isRelevantPlayer(arg) && request.getPlayerName() == null) { request.setPlayerName(arg); - request.setSelection(Target.PLAYER); + request.setTarget(Target.PLAYER); } else if (arg.equalsIgnoreCase("api")) { request.setAPIRequest(); @@ -72,23 +85,38 @@ public class RequestManager implements RequestGenerator { return request; } - /** This method will generate a {@link StatRequest} for a stat-request arriving through the API.*/ - public StatRequest generateRequest(@NotNull Target selection, @NotNull Statistic statistic, Material material, EntityType entity, String playerName) { + @Override + public StatRequest createPlayerStatRequest(String playerName, Statistic statistic, Material material, EntityType entity) { + return generateRequest(Target.PLAYER, statistic, material, entity, playerName); + } + + @Override + public StatRequest createServerStatRequest(Statistic statistic, Material material, EntityType entityType) { + return generateRequest(Target.SERVER, statistic, material, entityType, null); + } + + @Override + public StatRequest createTopStatRequest(Statistic statistic, Material material, EntityType entityType) { + return generateRequest(Target.TOP, statistic, material, entityType, null); + } + + /** This method will generate a {@link StatRequest} for a request arriving through the API.*/ + private StatRequest generateRequest(@NotNull Target selection, @NotNull Statistic statistic, Material material, EntityType entity, String playerName) { StatRequest request = new StatRequest(Bukkit.getConsoleSender(), true); - request.setSelection(selection); + request.setTarget(selection); request.setStatistic(statistic); switch (statistic.getType()) { case BLOCK -> { request.setBlock(material); - request.setSubStatEntry(material.toString()); + request.setSubStatEntryName(material.toString()); } case ITEM -> { request.setItem(material); - request.setSubStatEntry(material.toString()); + request.setSubStatEntryName(material.toString()); } case ENTITY -> { request.setEntity(entity); - request.setSubStatEntry(entity.toString()); + request.setSubStatEntryName(entity.toString()); } } if (selection == Target.PLAYER) request.setPlayerName(playerName); @@ -97,22 +125,30 @@ public class RequestManager implements RequestGenerator { /** Checks if a given {@link StatRequest} would result in a valid statistic look-up, and sends a feedback message to the CommandSender that prompted the request if it is invalid. -

The following is checked: -
1. Is a Statistic set?
-
2. Is a sub-Statistic needed, and if so, is a corresponding Material/EntityType present?
-
3. If the target is PLAYER, is a valid PlayerName provided?
- @return true if the StatRequest is valid, and false otherwise. */ +
The following is checked: +

+ @param request the StatRequest to check + @return true if the StatRequest is valid, and false otherwise. + */ public boolean validateRequest(StatRequest request) { return validateRequestAndSendMessage(request, request.getCommandSender()); } /** Checks if a given {@link StatRequest} would result in a valid statistic look-up, and sends a feedback message in the server console if it is invalid. -

The following is checked: -
1. Is a Statistic set?
-
2. Is a sub-Statistic needed, and if so, is a corresponding Material/EntityType present?
-
3. If the target is PLAYER, is a valid PlayerName provided?
- @return true if the StatRequest is valid, and false otherwise. */ +
The following is checked: +

+ @param request the StatRequest to check + @return true if the StatRequest is valid, and false otherwise. + */ public boolean validateAPIRequest(StatRequest request) { return validateRequestAndSendMessage(request, Bukkit.getConsoleSender()); } @@ -123,15 +159,15 @@ public class RequestManager implements RequestGenerator { return false; } Statistic.Type type = request.getStatistic().getType(); - if (request.getSubStatEntry() == null && type != Statistic.Type.UNTYPED) { + if (request.getSubStatEntryName() == null && type != Statistic.Type.UNTYPED) { outputManager.sendFeedbackMsgMissingSubStat(sender, type); return false; } else if (!hasMatchingSubStat(request)) { - outputManager.sendFeedbackMsgWrongSubStat(sender, type, request.getSubStatEntry()); + outputManager.sendFeedbackMsgWrongSubStat(sender, type, request.getSubStatEntryName()); return false; } - else if (request.getSelection() == Target.PLAYER && request.getPlayerName() == null) { + else if (request.getTarget() == Target.PLAYER && request.getPlayerName() == null) { outputManager.sendFeedbackMsg(sender, StandardMessage.MISSING_PLAYER_NAME); return false; } @@ -148,15 +184,15 @@ public class RequestManager implements RequestGenerator { Statistic.Type type = request.getStatistic().getType(); if (request.getPlayerFlag()) { //unpack the playerFlag - if (type == Statistic.Type.ENTITY && request.getSubStatEntry() == null) { - request.setSubStatEntry("player"); + if (type == Statistic.Type.ENTITY && request.getSubStatEntryName() == null) { + request.setSubStatEntryName("player"); } else { - request.setSelection(Target.PLAYER); + request.setTarget(Target.PLAYER); } } - String subStatEntry = request.getSubStatEntry(); + String subStatEntry = request.getSubStatEntryName(); switch (type) { //attempt to convert relevant subStatEntries into their corresponding Enum Constant case BLOCK -> { Material block = EnumHandler.getBlockEnum(subStatEntry); @@ -171,7 +207,7 @@ public class RequestManager implements RequestGenerator { if (item != null) request.setItem(item); } case UNTYPED -> { //remove unnecessary subStatEntries - if (subStatEntry != null) request.setSubStatEntry(null); + if (subStatEntry != null) request.setSubStatEntryName(null); } } } diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/StatAction.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/StatAction.java index 25b0c13..49adf19 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/StatAction.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/StatAction.java @@ -12,7 +12,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.RecursiveTask; /** The action that is executed when a stat-command is triggered. */ -public final class StatAction extends RecursiveTask> { +final class StatAction extends RecursiveTask> { private static int threshold; diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/StatThread.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/StatThread.java index 67f22e9..002d4a0 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/StatThread.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/StatThread.java @@ -14,7 +14,7 @@ import org.jetbrains.annotations.Nullable; import java.util.*; /** The Thread that is in charge of getting and calculating statistics.*/ -public class StatThread extends Thread { +public final class StatThread extends Thread { private static OutputManager outputManager; private static StatManager statManager; @@ -57,7 +57,7 @@ public class StatThread extends Thread { outputManager.sendFeedbackMsgWaitAMoment(request.getCommandSender(), lastCalc > 20000); } - Target selection = request.getSelection(); + Target selection = request.getTarget(); try { TextComponent statResult = switch (selection) { case PLAYER -> outputManager.formatPlayerStat(request, statManager.getPlayerStat(request)); @@ -65,7 +65,7 @@ public class StatThread extends Thread { case SERVER -> outputManager.formatServerStat(request, statManager.getServerStat(request)); }; if (request.isAPIRequest()) { - String msg = PlayerStats.getAPI().statResultComponentToString(statResult); + String msg = PlayerStats.getAPI().statFormatter().statResultComponentToString(statResult); request.getCommandSender().sendMessage(msg); } else { diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/OfflinePlayerHandler.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/OfflinePlayerHandler.java index 22a4f80..bccbce3 100644 --- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/OfflinePlayerHandler.java +++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/OfflinePlayerHandler.java @@ -56,6 +56,7 @@ public final class OfflinePlayerHandler { return Bukkit.getOfflinePlayer(offlinePlayerUUIDs.get(playerName)); } else { + MyLogger.logMsg("Cannot calculate statistics for player-name: " + playerName, true); return null; } }