Rework of API design

This commit is contained in:
Artemis-the-gr8 2022-07-23 21:28:32 +02:00
parent de150bfe51
commit 7b796c15dc
5 changed files with 70 additions and 17 deletions

View File

@ -2,16 +2,28 @@ package com.gmail.artemis.the.gr8.playerstats.api;
import com.gmail.artemis.the.gr8.playerstats.Main; import com.gmail.artemis.the.gr8.playerstats.Main;
import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.TextComponent;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.Statistic;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.EntityType;
import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
/** This Interface is the outgoing API and represents the heart of PlayerStats. /** This Interface is the outgoing API that provides access to the core functionality of PlayerStats.
To work with it, you can call {@link #getAPI()} to get an instance of {@link PlayerStatsAPI}.*/ To work with it, you can call PlayerStats.{@link #getAPI()} to get an instance of {@link PlayerStatsAPI}.
You can then use this object to call any of the below methods. Since calculating a
top or server statistics can take some time, it is recommended to call any of the
getServerStat() or getTopStats() methods asynchronously. Otherwise, the main Thread will have
to wait until all calculations are done, and this might cause lag spikes on the server.
<p>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 with the Adventure library,
or turned into a String with {@link #statResultComponentToString(TextComponent)}.</p>*/
public interface PlayerStats { public interface PlayerStats {
/** Returns an instance of the {@link PlayerStatsAPI}. /** Returns an instance of the {@link PlayerStatsAPI}.
@throws IllegalStateException if PlayerStats is not loaded on the server while you're trying to access the API*/ @throws IllegalStateException if PlayerStats is not loaded on the server when this method is called*/
@Contract(pure = true) @Contract(pure = true)
static @NotNull PlayerStats getAPI() throws IllegalStateException { static @NotNull PlayerStats getAPI() throws IllegalStateException {
return Main.getPlayerStatsAPI(); return Main.getPlayerStatsAPI();
@ -20,8 +32,7 @@ public interface PlayerStats {
/** Returns a stat-result as if the caller ran the /stat command in Minecraft chat. Since calculating the /** Returns a stat-result as if the caller ran the /stat command in Minecraft chat. Since calculating the
top or server statistics can take some time, it is recommended to call this method asynchronously top or server statistics can take some time, it is recommended to call this method asynchronously
(otherwise the main Thread will have to wait until the calculations are done). (otherwise the main Thread will have to wait until the calculations are done).
The result of this method is returned in the form of a TextComponent,
which can be sent directly to a Minecraft client, or turned into a String with {@link #componentToString(TextComponent)}.
@param args an Array of args very similar to the input a CommandSender would put in Minecraft chat: @param args an Array of args very similar to the input a CommandSender would put in Minecraft chat:
<p>- a stat-name (example: "mine_block")</p> <p>- a stat-name (example: "mine_block")</p>
<p>- if applicable, a sub-stat-name (example: diorite)(</p> <p>- if applicable, a sub-stat-name (example: diorite)(</p>
@ -31,7 +42,38 @@ public interface PlayerStats {
@throws IllegalArgumentException if the args do not result in a valid statistic look-up*/ @throws IllegalArgumentException if the args do not result in a valid statistic look-up*/
TextComponent getFancyStat(CommandSender sender, String[] args) throws IllegalArgumentException; TextComponent getFancyStat(CommandSender sender, String[] args) throws IllegalArgumentException;
/** Turns a TextComponent into its String representation. It will lose all color and style,
but it will keep line-breaks.*/ /** Get a formatted player-statistic of Statistic.Type UNTYPED.*/
String componentToString(TextComponent component); TextComponent getPlayerStat(@NotNull Statistic statistic, @NotNull OfflinePlayer player);
/** Get a formatted player-statistic of Statistic.Type BLOCK or ITEM.*/
TextComponent getPlayerStat(@NotNull Statistic statistic, @NotNull Material material, @NotNull OfflinePlayer player);
/** Get a formatted player-statistic of Statistic.Type ENTITY.*/
TextComponent getPlayerStat(@NotNull Statistic statistic, @NotNull EntityType entity, @NotNull OfflinePlayer player);
/** Get a formatted server-statistic of Statistic.Type UNTYPED. Not recommended to call this from the main Thread (see class description).*/
TextComponent getServerStat(@NotNull Statistic statistic);
/** Get a formatted server-statistic of Statistic.Type BLOCK or ITEM. Not recommended to call this from the main Thread (see class description).*/
TextComponent getServerStat(@NotNull Statistic statistic, @NotNull Material material);
/** Get a formatted server-statistic of Statistic.Type ENTITY. Not recommended to call this from the main Thread (see class description).*/
TextComponent getServerStat(@NotNull Statistic statistic, @NotNull EntityType entity);
/** Get a formatted top-statistic of Statistic.Type UNTYPED. Not recommended to call this from the main Thread (see class description).*/
TextComponent getTopStats(@NotNull Statistic statistic);
/** Get a formatted top-statistic of Statistic.Type BLOCK or ITEM. Not recommended to call this from the main Thread (see class description).*/
TextComponent getTopStats(@NotNull Statistic statistic, @NotNull Material material);
/** Get a formatted top-statistic of Statistic.Type ENTITY. Not recommended to call this from the main Thread (see class description).*/
TextComponent getTopStats(@NotNull Statistic statistic, @NotNull EntityType entity);
/** 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.
It will lose all color and style, but it will keep line-breaks.*/
String statResultComponentToString(TextComponent component);
} }

View File

@ -1,9 +1,13 @@
package com.gmail.artemis.the.gr8.playerstats.api; 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.models.StatRequest;
import com.gmail.artemis.the.gr8.playerstats.statistic.StatManager; import com.gmail.artemis.the.gr8.playerstats.statistic.StatManager;
import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.TextComponent;
import org.bukkit.OfflinePlayer;
import org.bukkit.Statistic;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.Nullable;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@ -27,6 +31,7 @@ public final class PlayerStatsAPI implements PlayerStats {
return new PlayerStatsAPI(statManager, statFormatter); return new PlayerStatsAPI(statManager, statFormatter);
} }
@Override @Override
public TextComponent getFancyStat(CommandSender sender, String[] args) throws IllegalArgumentException { public TextComponent getFancyStat(CommandSender sender, String[] args) throws IllegalArgumentException {
StatRequest request = statManager.generateRequest(sender, args); StatRequest request = statManager.generateRequest(sender, args);
@ -49,7 +54,7 @@ public final class PlayerStatsAPI implements PlayerStats {
throw new IllegalArgumentException("This is not a valid stat-request!"); throw new IllegalArgumentException("This is not a valid stat-request!");
} }
public String componentToString(TextComponent component) { public String statResultComponentToString(TextComponent component) {
return statFormatter.toString(component); return statFormatter.toString(component);
} }
} }

View File

@ -1,7 +1,9 @@
package com.gmail.artemis.the.gr8.playerstats.api; 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.models.StatRequest;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.Nullable;
/** The {@link RequestGenerator} will help you turn a String (such as "stat animals_bred") into a specific {@link StatRequest} /** The {@link RequestGenerator} will help you turn a String (such as "stat animals_bred") into a specific {@link StatRequest}
with all the information {@link PlayerStatsAPI} needs to work with. You'll need this StatRequest Object to get the statistic with all the information {@link PlayerStatsAPI} needs to work with. You'll need this StatRequest Object to get the statistic
@ -16,11 +18,5 @@ public interface RequestGenerator {
@param sender the CommandSender that requested this specific statistic*/ @param sender the CommandSender that requested this specific statistic*/
StatRequest generateRequest(CommandSender sender, String[] args); StatRequest generateRequest(CommandSender sender, String[] args);
/** This method validates the {@link StatRequest} and returns feedback to the player if it returns false. StatRequest generateRequest(CommandSender sender, String statName, @Nullable String subStatName, Target selection, @Nullable String PlayerName);
It checks the following:
<p>1. Is a Statistic set?</p>
<p>2. Is a subStat needed, and is a subStat Enum constant present? (block/entity/item)</p>
<p>3. If the target is PLAYER, is a valid PlayerName provided? </p>
@return true if the StatRequest is valid, and false + an explanation message otherwise. */
boolean requestIsValid(StatRequest request);
} }

View File

@ -25,7 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinPool;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public final class StatManager implements RequestGenerator, StatGetter { public final class StatManager implements StatGetter {
private final OfflinePlayerHandler offlinePlayerHandler; private final OfflinePlayerHandler offlinePlayerHandler;
private static OutputManager outputManager; private static OutputManager outputManager;
@ -120,6 +120,12 @@ public final class StatManager implements RequestGenerator, StatGetter {
} }
} }
/** This method validates the {@link StatRequest} and returns feedback to the player if it returns false.
It checks the following:
<p>1. Is a Statistic set?</p>
<p>2. Is a subStat needed, and is a subStat Enum constant present? (block/entity/item)</p>
<p>3. If the target is PLAYER, is a valid PlayerName provided? </p>
@return true if the StatRequest is valid, and false + an explanation message otherwise. */
public boolean requestIsValid(StatRequest request) { public boolean requestIsValid(StatRequest request) {
if (request.getStatistic() == null) { if (request.getStatistic() == null) {
outputManager.sendFeedbackMsg(request.getCommandSender(), StandardMessage.MISSING_STAT_NAME); outputManager.sendFeedbackMsg(request.getCommandSender(), StandardMessage.MISSING_STAT_NAME);

View File

@ -0,0 +1,4 @@
package com.gmail.artemis.the.gr8.playerstats.statistic;
public class StatRequestGenerator {
}