Reworked all javadoc comments to follow official guidelines (#100)

This commit is contained in:
Artemis-the-gr8 2022-08-16 15:16:57 +02:00
parent 5eb4a1705c
commit 93b44da8c7
47 changed files with 1342 additions and 645 deletions

View File

@ -3,7 +3,28 @@
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.artemis-the-gr8</groupId>
<artifactId>PlayerStats</artifactId>
<version>1.6.1</version>
<name>PlayerStats</name>
<version>1.7</version>
<description>Statistics Plugin</description>
<url>https://www.spigotmc.org/resources/playerstats.102347/</url>
<developers>
<developer>
<name>Artemis</name>
<email>artemis.the.gr8@gmail.com</email>
<url>https://github.com/Artemis-the-gr8</url>
</developer>
</developers>
<licenses>
<license>
<name>MIT License</name>
<url>http://www.opensource.org/licenses/mit-license.php</url>
</license>
</licenses>
<scm>
<connection>scm:git:git://github.com/itHotL/PlayerStats.git</connection>
<developerConnection>scm:git:git://github.com/itHotL/PlayerStats.git</developerConnection>
<url>https://github.com/itHotL/PlayerStats/tree/main</url>
</scm>
<build>
<plugins>
<plugin>
@ -92,6 +113,18 @@
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>

View File

@ -6,7 +6,7 @@
<groupId>io.github.artemis-the-gr8</groupId>
<artifactId>PlayerStats</artifactId>
<version>1.6.1</version>
<version>1.7</version>
<name>PlayerStats</name>
<description>Statistics Plugin</description>

View File

@ -77,10 +77,6 @@ public final class Main extends JavaPlugin {
this.getLogger().info("Disabled PlayerStats!");
}
public static @NotNull Main getInstance() {
return instance;
}
public static @NotNull BukkitAudiences getAdventure() throws IllegalStateException {
if (adventure == null) {
throw new IllegalStateException("Tried to access Adventure without PlayerStats being enabled!");
@ -104,7 +100,7 @@ public final class Main extends JavaPlugin {
public static @NotNull LanguageKeyHandler getLanguageKeyHandler() {
if (languageKeyHandler == null) {
languageKeyHandler = new LanguageKeyHandler();
languageKeyHandler = new LanguageKeyHandler(instance);
}
return languageKeyHandler;
}
@ -143,7 +139,7 @@ public final class Main extends JavaPlugin {
config = new ConfigHandler(this);
enumHandler = new EnumHandler();
languageKeyHandler = new LanguageKeyHandler();
languageKeyHandler = new LanguageKeyHandler(instance);
offlinePlayerHandler = new OfflinePlayerHandler();
shareManager = new ShareManager(config);
@ -159,7 +155,7 @@ public final class Main extends JavaPlugin {
new BukkitRunnable() {
@Override
public void run() {
final Metrics metrics = new Metrics(getInstance(), 15923);
final Metrics metrics = new Metrics(instance, 15923);
final boolean placeholderExpansionActive;
if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) {
PlaceholderExpansion expansion = PlaceholderAPIPlugin

View File

@ -18,8 +18,12 @@ import java.util.concurrent.atomic.AtomicInteger;
import static java.time.temporal.ChronoUnit.SECONDS;
/** The manager of all Player-prompted statistic-sharing. If sharing is enabled, this class will save the
results of past stat-lookups, so the results can be retrieved and shared when a Player clicks the share-button.*/
/**
* The manager of all Player-prompted statistic-sharing.
* If sharing is enabled, this class will save the results
* of past stat-lookups, so the results can be retrieved
* and shared when a Player clicks the share-button.
*/
public final class ShareManager {
private static boolean isEnabled;
@ -92,10 +96,13 @@ public final class ShareManager {
return sharedResults.contains(shareCode);
}
/** Takes a formattedComponent from the internal ConcurrentHashmap,
puts the current time in the shareTimeStamp (ConcurrentHashMap),
puts the shareCode (int hashCode) in the sharedResults (ArrayBlockingQueue),
and returns the formattedComponent. If no formattedComponent was found, returns null.*/
/**
* Takes a formattedComponent from the internal ConcurrentHashmap,
* puts the current time in the shareTimeStamp (ConcurrentHashMap),
* puts the shareCode (int hashCode) in the sharedResults (ArrayBlockingQueue),
* and returns the formattedComponent. If no formattedComponent was found,
* returns null.
*/
public @Nullable InternalStatResult getStatResult(String playerName, int shareCode) {
if (statResultQueue.containsKey(shareCode)) {
shareTimeStamp.put(playerName, Instant.now());
@ -122,8 +129,10 @@ public final class ShareManager {
}
}
/** If the given player already has more than x (in this case 25) StatResults saved,
remove the oldest one.*/
/**
* If the given player already has more than x (in this case 25)
* StatResults saved, remove the oldest one.
*/
private void removeExcessResults(String playerName) {
List<InternalStatResult> alreadySavedResults = statResultQueue.values()
.parallelStream()

View File

@ -12,11 +12,15 @@ import org.bukkit.command.CommandSender;
import java.util.HashMap;
/** The ThreadManager is in charge of the Threads that PlayerStats can utilize.
It keeps track of past and currently active Threads, to ensure a Player cannot
start multiple Threads at the same time (thereby limiting them to one stat-lookup at a time).
It also passes appropriate references along to the {@link StatThread} or {@link ReloadThread},
to ensure those will never run at the same time. */
/**
* The ThreadManager is in charge of the Threads that PlayerStats
* can utilize. It keeps track of past and currently active Threads,
* to ensure a Player cannot start multiple Threads at the same time
* (thereby limiting them to one stat-lookup at a time). It also
* passes appropriate references along to the {@link StatThread}
* or {@link ReloadThread}, to ensure those will never run at the
* same time.
*/
public final class ThreadManager {
private final static int threshold = 10;
@ -77,14 +81,18 @@ public final class ThreadManager {
}
}
/** Store the duration in milliseconds of the last top-stat-lookup
(or of loading the offline-player-list if no look-ups have been done yet). */
/**
* Store the duration in milliseconds of the last top-stat-lookup
* (or of loading the offline-player-list if no look-ups have been done yet).
*/
public static void recordCalcTime(long time) {
lastRecordedCalcTime = time;
}
/** Returns the duration in milliseconds of the last top-stat-lookup
(or of loading the offline-player-list if no look-ups have been done yet). */
/**
* Returns the duration in milliseconds of the last top-stat-lookup
* (or of loading the offline-player-list if no look-ups have been done yet).
*/
public static long getLastRecordedCalcTime() {
return lastRecordedCalcTime;
}

View File

@ -8,142 +8,243 @@ import net.kyori.adventure.text.TextComponent;
import org.bukkit.Statistic;
import org.jetbrains.annotations.Nullable;
/** Formats messages meant for usage outside PlayerStats. For more information about
the default formatting PlayerStats uses, see the class description of {@link StatResult}.*/
/**
* Formats messages meant for usage outside PlayerStats. For more information
* about the default formatting PlayerStats uses, see the class description of
* StatResult.
* @see StatResult
*/
public interface ApiFormatter {
/** Turns a TextComponent into its String representation. This method is equipped
to turn all PlayerStats' formatted statResults into String.
/**
* Turns a TextComponent into its String representation. This method is equipped
* to turn all PlayerStats' formatted statResults into String.
@return a String representation of this TextComponent, without hover/click events,
but with color, style and formatting. TranslatableComponents will be turned into
plain English.*/
* @param component the Component to turn into String
* @return a String representation of this TextComponent, without hover/click events,
* but with color, style and formatting. TranslatableComponents will be turned into
* plain English.
*/
default String TextComponentToString(TextComponent component) {
return ComponentUtils.getTranslatableComponentSerializer()
.serialize(component);
}
/** Gets a {@link NumberFormatter} to format raw numbers into something more readable.*/
/**
* Gets a {@link NumberFormatter} to format raw numbers into something more readable.
* @return the <code>NumberFormatter</code>
*/
default NumberFormatter getNumberFormatter() {
return new NumberFormatter();
}
/** Gets the default prefix PlayerStats uses.
@return [PlayerStats]*/
/**
* Gets the default prefix PlayerStats uses.
* @return [PlayerStats]
*/
TextComponent getPluginPrefix();
/** Gets the special rainbow version of PlayerStats' prefix.
@return [PlayerStats] in rainbow colors*/
/**
* Gets the special rainbow version of PlayerStats' prefix.
* @return [PlayerStats] in rainbow color
* s*/
TextComponent getRainbowPluginPrefix();
/** Gets the version of the prefix that is surrounded by underscores. This is
meant to be used as a title above a message or statistic display.
@return ________ [PlayerStats] ________ */
/**
* Gets the version of the prefix that is surrounded by underscores.
* This is meant to be used as a title above a message or statistic display.
* @return ________ [PlayerStats] ________
*/
TextComponent getPluginPrefixAsTitle();
/** Gets the special rainbow version of the title-prefix.
@return ________ [PlayerStats] ________ in rainbow colors*/
/**
* Gets the special rainbow version of the title-prefix.
* @return ________ [PlayerStats] ________ in rainbow colors
*/
TextComponent getRainbowPluginPrefixAsTitle();
/** Gets a formatted message that displays the name of this Statistic as it is
displayed by PlayerStats. If this Statistic is not of Type.Untyped,
include the name of the relevant sub-statistic (block, item or entity).
@param statistic the Statistic enum constant to display the name of
@param subStatName where necessary, the name of the Material or EntityType to include,
acquired by doing #toString() on the Material/EntityType in question
@return [stat-name] [sub-stat-name]*/
/**
* Gets a formatted message that displays the name of this Statistic as it is
* displayed by PlayerStats. If this Statistic is not of Type.Untyped,
* include the name of the relevant sub-statistic (block, item or entity).
* @param statistic the Statistic enum constant to display the name of
* @param subStatName where necessary, the name of the Material or EntityType
* to include, acquired by doing #toString() on the Material/EntityType in question
* @return [stat-name] [sub-stat-name]
*/
TextComponent getStatTitle(Statistic statistic, @Nullable String subStatName);
/** Gets a formatted message that displays the name of this Statistic as it is
displayed by PlayerStats in a top-stat-message. If this Statistic is not of Type.Untyped,
include the name of the relevant sub-statistic (block, item or entity).
@param statistic the Statistic enum constant for this message
@param subStatName the name of the Material or EntityType to include,
acquired by doing #toString() on the Material/EntityType in question
@param topStatSize the size of the top-list this title is for
@return Top [topStatSize] [stat-name] [sub-stat-name] */
/**
* Gets a formatted message that displays the name of this Statistic as it is
* displayed by PlayerStats in a top-stat-message. If this Statistic is not
* of Type.Untyped, include the name of the relevant sub-statistic
* (block, item or entity).
* @param statistic the Statistic enum constant for this message
* @param subStatName the name of the Material or EntityType to include,
* acquired by doing #toString() on the Material/EntityType in question
* @param topStatSize the size of the top-list this title is for
* @return Top [topStatSize] [stat-name] [sub-stat-name]
*/
TextComponent getTopStatTitle(int topStatSize, Statistic statistic, @Nullable String subStatName);
/** Formats the input into a single top-statistic line. The stat-number
is formatted into the most suitable {@link Unit} based on the provided Statistic.
For Type.Time, the resulting formatted number will have one additional smaller
Unit, unless <code>formatTopStatLineForTypeTime()</code> is used.
@return a single line from a top-x statistic:
* <br> [positionInTopList]. [player-name] ......... [stat-number] */
/**
* Formats the input into a single top-statistic line. The stat-number
* is formatted into the most suitable {@link Unit} based on the provided
* Statistic. For Type.Time, the resulting formatted number will have as
* many additional smaller units as are specified in the config,
* unless <code>formatTopStatLineForTypeTime()</code> is used.
* @param positionInTopList the rank-number in this list of the Player
* @param playerName the name of the Player on this line
* @param statNumber the result of Player#getStatistic()
* @param statistic the Statistic enum constant for this message
* @return a single line from a top-x statistic:
* <br> [positionInTopList]. [player-name] ......... [stat-number]
*/
TextComponent formatTopStatLine(int positionInTopList, String playerName, long statNumber, Statistic statistic);
/** Formats the input into a single top-statistic line. The stat-number is formatted
into the provided {@link Unit}. For Type.Time, the resulting formatted number
will have one additional smaller Unit, unless <code>formatTopStatLineForTypeTime()</code>
is used.
@return a single line from a top-x statistic:
* <br> [positionInTopList]. [player-name] ......... [stat-number] */
/**
* Formats the input into a single top-statistic line. The stat-number
* is formatted into the provided {@link Unit}. For Type.Time, the
* resulting formatted number will have as many additional smaller
* units as are specified in the config, unless
* <code>formatTopStatLineForTypeTime()</code> is used.
* @param positionInTopList the rank-number in this list of the Player
* @param playerName the name of the Player on this line
* @param statNumber the result of Player#getStatistic()
* @param unit the Unit to format the <code>statNumber</code> with
* @return a single line from a top-x statistic:
* <br> [positionInTopList]. [player-name] ......... [stat-number]
* */
TextComponent formatTopStatLine(int positionInTopList, String playerName, long statNumber, Unit unit);
/** Formats the input into a single top-statistic line for a time-based statistic with the Unit-range
that is between <code>bigUnit</code> and <code>smallUnit</code> (both inclusive).
@param bigUnit the biggest Unit to use of {@link Unit.Type#TIME}
@param smallUnit the smallest Unit to use of {@link Unit.Type#TIME}
@return a single line from a stop-x statistic:
<br>[positionInTopList]. [player-name] ......... [1D 2H 3M 4S]*/
TextComponent formatTopStatLineForTypeTime(int positionInList, String playerName, long statNumber, Unit bigUnit, Unit smallUnit);
/**
* Formats the input into a single top-statistic line for a time-based
* statistic with the Unit-range that is between <code>bigUnit</code>
* and <code>smallUnit</code> (both inclusive).
/** Formats the input into a server statistic message. The stat-number
is formatted into the most suitable {@link Unit} based on the provided Statistic.
For Type.Time, the resulting formatted number will have one additional smaller
Unit, unless <code>formatServerStatForTypeTime()</code> is used.
@return [Total on this server]: [stat-number] [stat-name] */
* @param positionInTopList the rank-number in this list of the Player
* @param playerName the name of the Player on this line
* @param statNumber the result of Player#getStatistic()
* @param bigUnit the biggest Unit to use of {@link Unit.Type#TIME}
* @param smallUnit the smallest Unit to use of {@link Unit.Type#TIME}
* @return a single line from a stop-x statistic:
* <br>[positionInTopList]. [player-name] ......... [1D 2H 3M 4S]
*/
TextComponent formatTopStatLineForTypeTime(int positionInTopList, String playerName, long statNumber, Unit bigUnit, Unit smallUnit);
/**
* Formats the input into a server statistic message. The stat-number
* is formatted into the most suitable {@link Unit} based on the provided
* Statistic. For Type.Time, the resulting formatted number will have as
* many additional smaller units as are specified in the config,
* unless <code>formatServerStatForTypeTime()</code> is used.
* @param statNumber the result of all Player#getStatistic() values combined
* @param statistic te Statistic enum constant for this message
* @return [Total on this server]: [stat-number] [stat-name]
*/
TextComponent formatServerStat(long statNumber, Statistic statistic);
/** Formats the input into a server statistic message for a statistic that has a
sub-statistic (block, item or entity).
@param statistic the Statistic enum constant for this message
@param statNumber the result of the statistic-lookup
@param subStatName the name of the Material or EntityType of this statistic-lookup,
acquired by doing #toString() on the Material/EntityType in question
@return [Total on this server]: [stat-number] [stat-name] [sub-stat-name]*/
/**
* Formats the input into a server statistic message for a statistic
* that has a sub-statistic (block, item or entity).
* @param statistic the Statistic enum constant for this message
* @param statNumber the result of all Player#getStatistic() values combined
* @param subStatName the name of the Material or EntityType of this
* statistic-lookup, acquired by doing #toString() on the Material/
* EntityType in question
* @return [Total on this server]: [stat-number] [stat-name] [sub-stat-name]
*/
TextComponent formatServerStat(long statNumber, Statistic statistic, String subStatName);
/** Formats the input into a server statistic message with the specified {@link Unit}.
The stat-number is formatted into the most suitable {@link Unit} based on the provided Statistic.
For Type.Time, the resulting formatted number will have one additional smaller Unit,
unless <code>formatServerStatForTypeTime()</code> is used.
@return [Total on this server]: [stat-number] [stat-name] [unit-name]*/
/**
* Formats the input into a server statistic message with the specified
* {@link Unit}. The stat-number is formatted into the most suitable
* {@link Unit} based on the provided Statistic. For Type.Time, the
* resulting formatted number will have as many additional smaller
* units as are specified in the config, unless
* <code>formatServerStatForTypeTime()</code> is used.
* @param statistic the Statistic enum constant for this message
* @param statNumber the result of all Player#getStatistic() values combined
* @param unit the Unit to use to format te <code>statNumber</code>
* @return [Total on this server]: [stat-number] [stat-name] [unit-name]
*/
TextComponent formatServerStat(long statNumber, Statistic statistic, Unit unit);
/** Formats the input into a server statistic message for a time-based statistic with the Unit-range
that is between <code>bigUnit</code> and <code>smallUnit</code> (both inclusive).
@param bigUnit the biggest Unit to use of {@link Unit.Type#TIME}
@param smallUnit the smallest Unit to use of {@link Unit.Type#TIME}
@return [Total on this server]: [1D 2H 3M 4S] [stat-name] */
/**
* Formats the input into a server statistic message for a time-based
* statistic with the Unit-range that is between <code>bigUnit</code>
* and <code>smallUnit</code> (both inclusive).
* @param statistic the Statistic enum constant for this message
* @param statNumber the result of all Player#getStatistic() values combined
* @param bigUnit the biggest Unit to use of {@link Unit.Type#TIME}
* @param smallUnit the smallest Unit to use of {@link Unit.Type#TIME}
* @return [Total on this server]: [1D 2H 3M 4S] [stat-name]
*/
TextComponent formatServerStatForTypeTime(long statNumber, Statistic statistic, Unit bigUnit, Unit smallUnit);
/** Formats the input into a player statistic message. For Unit.Type.Time,
the resulting formatted number will have one additional smaller Unit,
unless <code>formatPlayerStatForTypeTime</code> is used.
@return [player-name]: [stat-number] [stat-name]*/
/**
* Formats the input into a player statistic message. For Unit.Type.Time,
* the resulting formatted number will have as many additional smaller
* units as are specified in the config, unless
* <code>formatPlayerStatForTypeTime</code> is used.
* @param playerName the name of the Player
* @param statistic the Statistic enum constant for this message
* @param statNumber the result of Player#getStatistic()
* @return [player-name]: [stat-number] [stat-name]
*/
TextComponent formatPlayerStat(String playerName, int statNumber, Statistic statistic);
/** Formats the input into a player statistic message for a statistic that has a sub-statistic (block, item
or entity).
@param playerName the name of the Player
@param statistic the Statistic enum constant
@param statNumber the result of Player#getStatistic()
@param subStatName the name of the Material or EntityType of this statistic-lookup,
acquired by doing #toString() on the Material/EntityType in question
@return [player-name]: [stat-number] [stat-name] [sub-stat-name]*/
/**
* Formats the input into a player statistic message for a statistic
* that has a sub-statistic (block, item or entity).
* @param playerName the name of the Player
* @param statistic the Statistic enum constant for this message
* @param statNumber the result of Player#getStatistic()
* @param subStatName the name of the Material or EntityType of
* this statistic-lookup, acquired by doing #toString() on the
* Material/EntityType in question
* @return [player-name]: [stat-number] [stat-name] [sub-stat-name]
*/
TextComponent formatPlayerStat(String playerName, int statNumber, Statistic statistic, String subStatName);
/** Formats the input into a player statistic message with the specified {@link Unit}.
For Unit.Type.Time, the resulting formatted number will have one additional smaller Unit,
unless <code>formatPlayerStatForTypeTime</code> is used.
@return [player-name]: [stat-number] [stat-name] [stat-unit] */
/**
* Formats the input into a player statistic message with the specified
* {@link Unit}. For Unit.Type.Time, the resulting formatted number will
* have as many additional smaller units as are specified in the config,
* unless <code>formatPlayerStatForTypeTime</code> is used.
* @param playerName the name of the Player
* @param statistic the Statistic enum constant for this message
* @param statNumber the result of Player#getStatistic()
* @param unit the Unit to use when formatting the <code>statNumber</code>
* @return [player-name]: [stat-number] [stat-name] [stat-unit]
*/
TextComponent formatPlayerStat(String playerName, int statNumber, Statistic statistic, Unit unit);
/** Formats the input into a player statistic message for a time-based statistic with the Unit-range
that is between <code>bigUnit</code> and <code>smallUnit</code> (both inclusive).
@param bigUnit the biggest Unit to use of {@link Unit.Type#TIME}
@param smallUnit the smallest Unit to use of {@link Unit.Type#TIME}
@return [player-name]: [1D 2H 3M 4S] [stat-name]*/
/**
* Formats the input into a player statistic message for a time-based
* statistic with the Unit-range that is between <code>bigUnit</code>
* and <code>smallUnit</code> (both inclusive).
* @param playerName the name of the Player
* @param statNumber the result of Player#getStatistic()
* @param statistic the Statistic enum constant for this message
* @param bigUnit the biggest Unit to use of {@link Unit.Type#TIME}
* @param smallUnit the smallest Unit to use of {@link Unit.Type#TIME}
* @return [player-name]: [1D 2H 3M 4S] [stat-name]
*/
TextComponent formatPlayerStatForTypeTime(String playerName, int statNumber, Statistic statistic, Unit bigUnit, Unit smallUnit);
}

View File

@ -6,20 +6,20 @@ import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
/** The outgoing API that you can use to access the core functionality of PlayerStats!
To work with the API, 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.
<br>
<br>Since calculating a top or server statistics can take some time, I strongly
encourage you to call {@link StatRequest#execute()} asynchronously.
Otherwise, the main Thread will have to wait until all calculations are done,
and this can severely impact server performance.
* To work with the API, 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.
* <br>
* <br>Since calculating a top or server statistics can take some time, I strongly
* encourage you to call {@link StatRequest#execute()} asynchronously.
* Otherwise, the main Thread will have to wait until all calculations are done,
* and this can severely impact server performance.
*/
public interface PlayerStats {
/** Gets an instance of the {@link PlayerStatsAPI}.
@return the PlayerStats API
@throws IllegalStateException if PlayerStats is not loaded on the server when this method is called*/
* @return the PlayerStats API
* @throws IllegalStateException if PlayerStats is not loaded on the server when this method is called*/
@Contract(pure = true)
static @NotNull PlayerStats getAPI() throws IllegalStateException {
return Main.getPlayerStatsAPI();

View File

@ -8,33 +8,33 @@ import org.bukkit.entity.EntityType;
import org.jetbrains.annotations.NotNull;
/** Is responsible for creating an executable {@link StatRequest}. This Request holds all
the information PlayerStats needs to work with, and is used by the {@link StatCalculator}
to get the desired statistic data.*/
* the information PlayerStats needs to work with, and is used by the {@link StatCalculator}
* to get the desired statistic data.*/
public interface RequestGenerator<T> {
/** Gets an executable Request object for a Statistic of Statistic.Type {@code Untyped}.
@param statistic a Statistic of Type.Untyped
@return a {@link StatRequest}
@throws IllegalArgumentException if <code>statistic</code> is not of Type.Untyped*/
* @param statistic a Statistic of Type.Untyped
* @return a {@link StatRequest}
* @throws IllegalArgumentException if <code>statistic</code> is not of Type.Untyped*/
StatRequest<T> untyped(@NotNull Statistic statistic) throws IllegalArgumentException;
/** Gets an executable Request object for a Statistic of Statistic.Type Block or Item.
@param statistic a Statistic of Type.Block or Type.Item
@param material a block if the <code>statistic</code> is of Type.Block,
and an item if the <code>statistic</code> is of Type.Item
@return a {@link StatRequest}
@throws IllegalArgumentException if <code>statistic</code> is not of Type.Block
(with a block as <code>material</code>), or <code>statistic</code> is not of Type.Item
(with an item as <code>material</code>) */
* @param statistic a Statistic of Type.Block or Type.Item
* @param material a block if the <code>statistic</code> is of Type.Block,
* and an item if the <code>statistic</code> is of Type.Item
* @return a {@link StatRequest}
* @throws IllegalArgumentException if <code>statistic</code> is not of Type.Block
* (with a block as <code>material</code>), or <code>statistic</code> is not of Type.Item
* (with an item as <code>material</code>) */
StatRequest<T> blockOrItemType(@NotNull Statistic statistic, @NotNull Material material) throws IllegalArgumentException;
/** Gets an executable Request object for a Statistic of Statistic.Type Entity.
@param statistic a Statistic of Type.Entity
@param entityType an EntityType
@return a {@link StatRequest}
@throws IllegalArgumentException if <code>statistic</code> is not of Type.Entity*/
* @param statistic a Statistic of Type.Entity
* @param entityType an EntityType
* @return a {@link StatRequest}
* @throws IllegalArgumentException if <code>statistic</code> is not of Type.Entity*/
StatRequest<T> entityType(@NotNull Statistic statistic, @NotNull EntityType entityType) throws IllegalArgumentException;
}

View File

@ -5,34 +5,33 @@ import java.util.LinkedHashMap;
public interface StatManager {
/** Gets a RequestGenerator that can be used to create a PlayerStatRequest.
This RequestGenerator will make sure all default settings
for a player-statistic-lookup are configured.
@param playerName the player whose statistic is being requested
@return the RequestGenerator */
* This RequestGenerator will make sure all default settings
* for a player-statistic-lookup are configured.
*
* @param playerName the player whose statistic is being requested
* @return the RequestGenerator */
RequestGenerator<Integer> playerStatRequest(String playerName);
/** Gets a RequestGenerator that can be used to create a ServerStatRequest.
This RequestGenerator will make sure all default settings
for a server-statistic-lookup are configured.
@return the RequestGenerator*/
* This RequestGenerator will make sure all default settings
* for a server-statistic-lookup are configured.
*
* @return the RequestGenerator*/
RequestGenerator<Long> serverStatRequest();
/** Gets a RequestGenerator that can be used to create a TopStatRequest
for a top-list of the specified size. This RequestGenerator will
make sure all default settings for a top-statistic-lookup are configured.
@param topListSize how big the top-x should be (10 by default)
@return the RequestGenerator*/
* for a top-list of the specified size. This RequestGenerator will
* make sure all default settings for a top-statistic-lookup are configured.
*
* @param topListSize how big the top-x should be (10 by default)
* @return the RequestGenerator*/
RequestGenerator<LinkedHashMap<String, Integer>> topStatRequest(int topListSize);
/** Gets a RequestGenerator that can be used to create a TopStatRequest
for all offline players on the server (those that are included by
PlayerStats' settings). This RequestGenerator will make sure
all default settings for a top-statistic-lookup are configured.
@return the RequestGenerator*/
* for all offline players on the server (those that are included by
* PlayerStats' settings). This RequestGenerator will make sure
* all default settings for a top-statistic-lookup are configured.
*
* @return the RequestGenerator*/
RequestGenerator<LinkedHashMap<String, Integer>> totalTopStatRequest();
}

View File

@ -46,15 +46,17 @@ public final class StatCommand implements CommandExecutor {
return true;
}
/** If a given {@link RequestSettings} does not result in a valid statistic look-up,
this will send a feedback message to the CommandSender that made the request.
<br> The following is checked:
<ul>
<li>Is a <code>statistic</code> set?
<li>Is a <code>subStatEntry</code> needed, and if so, is a corresponding Material/EntityType present?
<li>If the <code>target</code> is Player, is a valid <code>playerName</code> provided?
</ul>
@param requestSettings the RequestSettings to give feedback on
/**
* If a given {@link RequestSettings} does not result in a valid statistic look-up,
* this will send a feedback message to the CommandSender that made the request.
* <br> The following is checked:
* <ul>
* <li>Is a <code>statistic</code> set?
* <li>Is a <code>subStatEntry</code> needed, and if so, is a corresponding Material/EntityType present?
* <li>If the <code>target</code> is Player, is a valid <code>playerName</code> provided?
* </ul>
*
* @param requestSettings the RequestSettings to give feedback on
*/
private void sendFeedback(RequestSettings requestSettings) {
CommandSender sender = requestSettings.getCommandSender();

View File

@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable;
import java.io.File;
/** Handles all PlayerStats' config-settings. */
public final class ConfigHandler {
private static Main plugin;
@ -30,12 +31,17 @@ public final class ConfigHandler {
MyLogger.setDebugLevel(getDebugLevel());
}
/** Checks the number that "config-version" returns to see if the config needs updating, and if so, send it to the {@link ConfigUpdateHandler}.
<br></br>
<br>PlayerStats 1.1: "config-version" doesn't exist.</br>
<br>PlayerStats 1.2: "config-version" is 2.</br>
<br>PlayerStats 1.3: "config-version" is 3. </br>
<br>PlayerStats 1.4: "config-version" is 4.</br>*/
/**
* Checks the number that "config-version" returns to see if the
* config needs updating, and if so, send it to the {@link ConfigUpdateHandler}.
* <br>
* <br>PlayerStats 1.1: "config-version" doesn't exist.
* <br>PlayerStats 1.2: "config-version" is 2.
* <br>PlayerStats 1.3: "config-version" is 3.
* <br>PlayerStats 1.4: "config-version" is 4.
* <br>PlayerStats 1.5: "config-version" is 5.
* <br>PlayerStats 1.6 and up: "config-version" is 6.
*/
private void checkConfigVersion() {
if (!config.contains("config-version") || config.getInt("config-version") != configVersion) {
new ConfigUpdateHandler(plugin, configFile, configVersion);
@ -43,15 +49,23 @@ public final class ConfigHandler {
}
}
/** Create a config file if none exists yet (from the config.yml in the plugin's resources). */
/**
* Create a config file if none exists yet
* (from the config.yml in the plugin's resources).
*/
private void saveDefaultConfig() {
config = plugin.getConfig();
plugin.saveDefaultConfig();
configFile = new File(plugin.getDataFolder(), "config.yml");
}
/** Reloads the config from file, or creates a new file with default values if there is none.
Also reads the value for debug-level and passes it on to {@link MyLogger}. */
/**
* Reloads the config from file, or creates a new file with default values
* if there is none. Also reads the value for debug-level and passes it
* on to {@link MyLogger}.
*
* @return true if the config has been reloaded from disk, false if it failed
*/
public boolean reloadConfig() {
if (!configFile.exists()) {
saveDefaultConfig();
@ -67,81 +81,108 @@ public final class ConfigHandler {
}
/** Returns the desired debugging level.
<br></br>
<br>1 = low (only show unexpected errors)</br>
<br>2 = medium (detail all encountered exceptions, log main tasks and show time taken)</br>
<br>3 = high (log all tasks and time taken)</br>
<br></br>
<br>Default: 1</br>*/
*
* <br> 1 = low (only show unexpected errors)
* <br> 2 = medium (detail all encountered exceptions, log main tasks and show time taken)
* <br> 3 = high (log all tasks and time taken)
*
* @return the DebugLevel (default: 1)
*/
public int getDebugLevel() {
return config.getInt("debug-level", 1);
}
/** Returns true if command-senders should be limited to one stat-request at a time.
<br>Default: true</br>*/
/**
* Whether command-senders should be limited to one stat-request at a time.
* @return the config setting (default: true)
*/
public boolean limitStatRequests() {
return config.getBoolean("only-allow-one-lookup-at-a-time-per-player", true);
}
/** Returns true if stat-sharing is allowed.
<br>Default: true</br>*/
/**
* Whether stat-sharing is allowed.
* @return the config setting (default: true)
*/
public boolean allowStatSharing() {
return config.getBoolean("enable-stat-sharing", true);
}
/** Returns the number of minutes a player has to wait before being able to
share another stat-result.
<br>Default: 0</br>*/
/**
* The number of minutes a player has to wait before being able to
* share another stat-result.
* @return the number (default: 0)
*/
public int getStatShareWaitingTime() {
return config.getInt("waiting-time-before-sharing-again", 0);
}
/** Returns the config setting for include-whitelist-only.
<br>Default: false</br>*/
/**
* Whether to limit stat-calculations to whitelisted players only.
* @return the config setting (default: true)
*/
public boolean whitelistOnly() {
return config.getBoolean("include-whitelist-only", false);
}
/** Returns the config setting for exclude-banned-players.
<br>Default: false</br>*/
/**
* Whether to exclude banned players from stat-calculations.
* @return the config setting for exclude-banned-players (default: false)
*/
public boolean excludeBanned() {
return config.getBoolean("exclude-banned-players", false);
}
/** Returns the number of maximum days since a player has last been online.
<br>Default: 0 (which signals not to use this limit)</br>*/
/**
* The number of maximum days since a player has last been online.
* @return the number (default: 0 - which signals not to use this limit)
*/
public int getLastPlayedLimit() {
return config.getInt("number-of-days-since-last-joined", 0);
}
/** Whether to use TranslatableComponents wherever possible.
Currently supported: statistic, block, item and entity names.
<br>Default: true</br>*/
/**
* Whether to use TranslatableComponents wherever possible.
*
* @return the config setting (default: true)
* @implNote Currently supported: statistic, block, item and entity names.
*/
public boolean useTranslatableComponents() {
return config.getBoolean("translate-to-client-language", true);
}
/** Whether to use HoverComponents for additional information.
<br>Default: true</br>*/
/**
* Whether to use HoverComponents for additional information
* @return the config setting (default: true)
*/
public boolean useHoverText() {
return config.getBoolean("enable-hover-text", true);
}
/** Whether to use festive formatting, such as pride colors.
<br>Default: true</br> */
/**
* Whether to use festive formatting, such as pride colors
* @return the config setting (default: true)
*/
public boolean useFestiveFormatting() {
return config.getBoolean("enable-festive-formatting", true);
}
/** Whether to use rainbow colors for the [PlayerStats] prefix rather than the default gold/purple.
<br>Default: false</br> */
/**
* Whether to use rainbow colors for the [PlayerStats] prefix rather than the
* default gold/purple
* @return the config setting (default: false)
*/
public boolean useRainbowMode() {
return config.getBoolean("rainbow-mode", false);
}
/** Whether to use enters before the statistic output in chat.
Enters create some separation between the previous things that have been said in chat and the stat-result.
<br>Default: true for non-shared top statistics, false for everything else</br>*/
/**
* Whether to use enters before the statistic output in chat
*
* @param selection the Target (Player, Server or Top)
* @return the config setting (default: true for non-shared top
* statistics, false for everything else)
*/
public boolean useEnters(Target selection, boolean getSharedSetting) {
ConfigurationSection section = config.getConfigurationSection("use-enters");
boolean def = selection == Target.TOP && !getSharedSetting;
@ -159,50 +200,77 @@ public final class ConfigHandler {
return def;
}
/** Returns the config setting for use-dots.
<br>Default: true</br>*/
/**
* Whether dots should be used to align the numbers in a top-stat-result.
* @return the config setting (default: true)
*/
public boolean useDots() {
return config.getBoolean("use-dots", true);
}
/** Returns the config setting for top-list-max-size.
<br>Default: 10</br> */
/**
* The maximum size for the top-stat-list.
* @return the config setting (default: 10)
*/
public int getTopListMaxSize() {
return config.getInt("top-list-max-size", 10);
}
/** Returns a String that represents the title for a top statistic.
<br>Default: "Top"</br>*/
/**
* The title that a top-statistic should start with.
* @return a String that represents the title for a top statistic
* (default: "Top")
*/
public String getTopStatsTitle() {
return config.getString("top-list-title", "Top");
}
/** Returns a String that represents the title for a server stat.
<br>Default: "Total on"</br> */
/**
* The title that a server statistic should start with.
* @return the title (default: "Total on")
*/
public String getServerTitle() {
return config.getString("total-server-stat-title", "Total on");
}
/** Returns the specified server name for a server stat title.
<br>Default: "this server"</br>*/
/**
* The specified server name for a server stat title.
* @return the title (default: "this server")
*/
public String getServerName() {
return config.getString("your-server-name", "this server");
}
/** Returns the unit that should be used for distance-related statistics.
<br>Default: Blocks for plain text, km for hover-text</br>*/
/**
* The unit that should be used for distance-related statistics.
*
* @param isUnitForHoverText whether the number formatted with this
* Unit is inside a HoverComponent
* @return the Unit (default: Blocks for plain text, km for hover-text)
*/
public String getDistanceUnit(boolean isUnitForHoverText) {
return getUnitString(isUnitForHoverText, "blocks", "km", "distance-unit");
}
/** Returns the unit that should be used for damage-based statistics.
<br>Default: Hearts for plain text, HP for hover-text.</br>*/
/**
* The unit that should be used for damage-based statistics.
*
* @param isUnitForHoverText whether the number formatted with this
* Unit is inside a HoverComponent
* @return the Unit (default: Hearts for plain text, HP for hover-text)
*/
public String getDamageUnit(boolean isUnitForHoverText) {
return getUnitString(isUnitForHoverText, "hearts", "hp", "damage-unit");
}
/** Whether PlayerStats should automatically detect the most suitable unit to use for time-based statistics.
<br>Default: true</br>*/
/**
* Whether PlayerStats should automatically detect the most suitable
* unit to use for time-based statistics
*
* @param isUnitForHoverText whether the number formatted with this
* Unit is inside a HoverComponent
* @return the config setting (default: true)
*/
public boolean autoDetectTimeUnit(boolean isUnitForHoverText) {
String path = "auto-detect-biggest-time-unit";
if (isUnitForHoverText) {
@ -212,8 +280,15 @@ public final class ConfigHandler {
return config.getBoolean(path, defaultValue);
}
/** How many additional units should be displayed next to the most suitable largest unit for time-based statistics.
<br>Default: 1 for plain text, 0 for hover-text</br>*/
/**
* How many additional units should be displayed next to the most
* suitable largest unit for time-based statistics
*
* @param isUnitForHoverText whether the number formatted with this
* Unit is inside a HoverComponent
* @return the config setting (default: 1 for plain text,
* 0 for hover-text)
*/
public int getNumberOfExtraTimeUnits(boolean isUnitForHoverText) {
String path = "number-of-extra-units";
if (isUnitForHoverText) {
@ -223,16 +298,28 @@ public final class ConfigHandler {
return config.getInt(path, defaultValue);
}
/** Returns the unit that should be used for time-based statistics.
(this will return the largest unit that should be used).
<br>Default: days for plain text, hours for hover-text</br>*/
/**
* The largest unit that should be used for time-based statistics.
*
* @param isUnitForHoverText whether the number formatted with this
* Unit is inside a HoverComponent
* @return a String representation of the largest time-unit
* (default: days for plain text, hours for hover-text)
*/
public String getTimeUnit(boolean isUnitForHoverText) {
return getTimeUnit(isUnitForHoverText, false);
}
/** Returns the unit that should be used for time-based statistics. If the optional smallUnit flag is true,
this will return the smallest unit (and otherwise the largest).
<br>Default: hours for plain text, seconds for hover-text</br>*/
/**
* The unit that should be used for time-based statistics.
* If the optional smallUnit flag is true, this will return
* the smallest unit (and otherwise the biggest).
*
* @param isUnitForHoverText whether the number formatted with this
* Unit is inside a HoverComponent
* @param smallUnit if this is true, get the minimum time-unit
* @return the Unit (default: hours for plain text, seconds for hover-text)
*/
public String getTimeUnit(boolean isUnitForHoverText, boolean smallUnit) {
if (smallUnit) {
return getUnitString(isUnitForHoverText, "hours", "seconds", "smallest-time-unit");
@ -240,32 +327,51 @@ public final class ConfigHandler {
return getUnitString(isUnitForHoverText, "days", "hours", "biggest-time-unit");
}
/** Returns an integer between 0 and 100 that represents how much lighter a hoverColor should be.
So 20 would mean 20% lighter.
<br>Default: 20</br>*/
/**
* Returns an integer between 0 and 100 that represents how much lighter
* a hoverColor should be.
* @return an {@code int} that represents a percentage (default: 20)
*/
public int getHoverTextAmountLighter() {
return config.getInt("hover-text-amount-lighter", 20);
}
/** Returns a String that represents either a Chat Color, hex color code, or a Style. Default values are:
* <br>Style: "italic"</br>
* <br>Color: "gray"</br>*/
/**
* Gets a String that represents either a Chat Color, hex color code,
* or a Style.
*
* @param getStyleSetting if true, returns a Style instead of a Color
* @return the config setting. Default:
* <br>Style: "italic"
* <br>Color: "gray"
*/
public String getSharedByTextDecoration(boolean getStyleSetting) {
String def = getStyleSetting ? "italic" : "gray";
return getDecorationString(null, getStyleSetting, def, "shared-by");
}
/** Returns a String that represents either a Chat Color, hex color code, or a Style. Default values are:
* <br>Style: "none"</br>
* <br>Color: "#845EC2"</br>*/
/**
* Gets a String that represents either a Chat Color, hex color code, or a Style.
*
* @param getStyleSetting if true, returns a Style instead of a Color
* @return the config setting. Default:
* <br>Style: "none"
* <br>Color: "#845EC2"
*/
public String getSharerNameDecoration(boolean getStyleSetting) {
return getDecorationString(null, getStyleSetting, "#845EC2", "player-name");
}
/** Returns a String that represents either a Chat Color, hex color code, or a Style. Default values are:
<br>Style: "none"</br>
<br>Color Top: "green"</br>
<br>Color Individual/Server: "gold"</br>*/
/**
* Gets a String that represents either a Chat Color, hex color code, or a Style.
*
* @param selection the Target (Player, Server or Top)
* @param getStyleSetting if true, returns a Style instead of a Color
* @return the config setting. Default:
* <br>Style: "none"
* <br>Color Top: "green"
* <br>Color Individual/Server: "gold"
*/
public String getPlayerNameDecoration(Target selection, boolean getStyleSetting) {
String def;
if (selection == Target.TOP) {
@ -277,8 +383,10 @@ public final class ConfigHandler {
return getDecorationString(selection, getStyleSetting, def, "player-names");
}
/** Returns true if playerNames Style is "bold" for a top-stat, false if it is not.
<br>Default: false</br>*/
/**
* Whether the playerNames Style is "bold" for a top-stat.
* @return the config setting (default: false)
*/
public boolean playerNameIsBold() {
ConfigurationSection style = getRelevantSection(Target.TOP);
@ -289,24 +397,45 @@ public final class ConfigHandler {
return false;
}
/** Returns a String that represents either a Chat Color, hex color code, or a Style. Default values are:
<br>Style: "none"</br>
<br>Color: "yellow"</br>*/
/**
* Gets a String that represents either a Chat Color, hex color code,
* or a Style.
*
* @param selection the Target (Player, Server or Top)
* @param getStyleSetting if true, returns a Style instead of a Color
* @return the config setting. Default:
* <br>Style: "none"
* <br>Color: "yellow"
*/
public String getStatNameDecoration(Target selection, boolean getStyleSetting) {
return getDecorationString(selection, getStyleSetting, "yellow", "stat-names");
}
/** Returns a String that represents either a Chat Color, hex color code, or a Style. Default values are:
<br>Style: "none"</br>
<br>Color: "#FFD52B"</br>*/
/**
* Gets a String that represents either a Chat Color, hex color code,
* or a Style.
*
* @param selection the Target (Player, Server or Top)
* @param getStyleSetting if true, returns a Style instead of a Color
* @return the config setting. Default:
* <br>Style: "none"
* <br>Color: "#FFD52B"
*/
public String getSubStatNameDecoration(Target selection, boolean getStyleSetting) {
return getDecorationString(selection, getStyleSetting, "#FFD52B", "sub-stat-names");
}
/** Returns a String that represents either a Chat Color, hex color code, or Style. Default values are:
<br>Style: "none"</br>
<br>Color Top: "#55AAFF"</br>
<br>Color Individual/Server: "#ADE7FF"</br> */
/**
* Gets a String that represents either a Chat Color, hex color code,
* or Style.
*
* @param selection the Target (Player, Server or Top)
* @param getStyleSetting if true, returns a Style instead of a Color
* @return the config setting. Default:
* <br>Style: "none"
* <br>Color Top: "#55AAFF"
* <br>Color Individual/Server: "#ADE7FF"
*/
public String getStatNumberDecoration(Target selection, boolean getStyleSetting) {
String def;
if (selection == Target.TOP) {
@ -318,10 +447,17 @@ public final class ConfigHandler {
return getDecorationString(selection, getStyleSetting, def,"stat-numbers");
}
/** Returns a String that represents either a Chat Color, hex color code, or Style. Default values are:
<br>Style: "none"</br>
<br>Color Top: "yellow"</br>
<br>Color Server: "gold"</br>*/
/**
* Gets a String that represents either a Chat Color, hex color code,
* or Style.
*
* @param selection the Target (Player, Server or Top)
* @param getStyleSetting if true, returns a Style instead of a Color
* @return the config setting. Default:
* <br>Style: "none"
* <br>Color Top: "yellow"
* <br>Color Server: "gold"
*/
public String getTitleDecoration(Target selection, boolean getStyleSetting) {
String def;
if (selection == Target.TOP) {
@ -333,41 +469,71 @@ public final class ConfigHandler {
return getDecorationString(selection, getStyleSetting, def, "title");
}
/** Returns a String that represents either a Chat Color, hex color code, or Style. Default values are:
<br>Style: "none"</br>
<br>Color: "gold"</br>*/
/**
* Gets a String that represents either a Chat Color, hex color code,
* or Style.
*
* @param getStyleSetting if true, returns a Style instead of a Color
* @return the config setting. Default:
* <br>Style: "none"
* <br>Color: "gold"
*/
public String getTitleNumberDecoration(boolean getStyleSetting) {
return getDecorationString(Target.TOP, getStyleSetting, "gold", "title-number");
}
/** Returns a String that represents either a Chat Color, hex color code, or Style. Default values are:
<br>Style: "none"</br>
<br>Color: "#FFB80E"</br>*/
/**
* Gets a String that represents either a Chat Color, hex color code,
* or Style.
*
* @param getStyleSetting if true, returns a Style instead of a Color
* @return the config setting. Default:
* <br>Style: "none"
* <br>Color: "#FFB80E"
*/
public String getServerNameDecoration(boolean getStyleSetting) {
return getDecorationString(Target.SERVER, getStyleSetting, "#FFB80E", "server-name");
}
/** Returns a String that represents either a Chat Color, hex color code, or Style. Default values are:
<br>Style: "none"</br>
<br>Color: "gold"</br>*/
/**
* Gets a String that represents either a Chat Color, hex color code,
* or Style.
*
* @param getStyleSetting if true, returns a Style instead of a Color
* @return the config setting. Default:
* <br>Style: "none"
* <br>Color: "gold"
*/
public String getRankNumberDecoration(boolean getStyleSetting) {
return getDecorationString(Target.TOP, getStyleSetting, "gold", "rank-numbers");
}
/** Returns a String that represents either a Chat Color, hex color code, or Style. Default values are:
<br>Style: "none"</br>
<br>Color: "dark_gray"</br> */
/**
* Gets a String that represents either a Chat Color, hex color code,
* or Style.
*
* @param getStyleSetting if true, returns a Style instead of a Color
* @return the config setting. Default:
* <br>Style: "none"
* <br>Color: "dark_gray"
*/
public String getDotsDecoration(boolean getStyleSetting) {
return getDecorationString(Target.TOP, getStyleSetting, "dark_gray", "dots");
}
/** Returns a String representing the {@link Unit} that should be used for a certain {@link Unit.Type}.
If no String can be retrieved from the config, the supplied defaultValue will be returned.
If the defaultValue is different for hoverText, an optional String defaultHoverValue can be supplied.
@param isHoverText if true, the unit for hovering text is returned, otherwise the unit for plain text
@param defaultValue the default unit for plain text
@param defaultHoverValue the default unit for hovering text
@param pathName the config path to retrieve the value from*/
/**
* Gets a String representing a {@link Unit}.
*
* @return a String representing the {@link Unit} that should be used for a
* certain {@link Unit.Type}. If no String can be retrieved from the config,
* the supplied defaultValue will be returned. If the defaultValue is different
* for hoverText, an optional String defaultHoverValue can be supplied.
* @param isHoverText if true, the unit for hovering text is returned,
* otherwise the unit for plain text
* @param defaultValue the default unit for plain text
* @param defaultHoverValue the default unit for hovering text
* @param pathName the config path to retrieve the value from
*/
private String getUnitString(boolean isHoverText, String defaultValue, String defaultHoverValue, String pathName) {
String path = isHoverText ? pathName + "-for-hover-text" : pathName;
String def = defaultValue;
@ -377,12 +543,16 @@ public final class ConfigHandler {
return config.getString(path, def);
}
/** Returns the config value for a color or style option in string-format, the supplied default value,
or null if no configSection was found.
@param selection the Target this decoration is meant for (Player, Server or Top)
@param getStyleSetting if true, the result will be a style String, otherwise a color String
@param defaultColor the default color to return if the config value cannot be found (for style, the default is always "none")
@param pathName the config path to retrieve the value from*/
/**
* @return the config value for a color or style option in string-format,
* the supplied default value, or null if no configSection was found.
* @param selection the Target this decoration is meant for (Player, Server or Top)
* @param getStyleSetting if true, the result will be a style String,
* otherwise a color String
* @param defaultColor the default color to return if the config value cannot be found
* (for style, the default is always "none")
* @param pathName the config path to retrieve the value from
*/
private @Nullable String getDecorationString(Target selection, boolean getStyleSetting, String defaultColor, String pathName){
String path = getStyleSetting ? pathName + "-style" : pathName;
String defaultValue = getStyleSetting ? "none" : defaultColor;
@ -391,7 +561,9 @@ public final class ConfigHandler {
return section != null ? section.getString(path, defaultValue) : null;
}
/** Returns the config section that contains the relevant color or style option. */
/**
* @return the config section that contains the relevant color or style option.
*/
private @Nullable ConfigurationSection getRelevantSection(Target selection) {
if (selection == null) { //rather than rework the whole Target enum, I have added shared-stats as the null-option for now
return config.getConfigurationSection("shared-stats");

View File

@ -11,7 +11,10 @@ import com.tchristofferson.configupdater.ConfigUpdater;
public final class ConfigUpdateHandler {
/** Add new key-value pairs to the config without losing comments, using <a href="https://github.com/tchristofferson/Config-Updater">tchristofferson's Config-Updater</a> */
/**
* Add new key-value pairs to the config without losing comments,
* using <a href="https://github.com/tchristofferson/Config-Updater">tchristofferson's Config-Updater</a>
*/
public ConfigUpdateHandler(Main plugin, File configFile, int configVersion) {
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(configFile);
updateTopListDefault(configuration);
@ -27,7 +30,10 @@ public final class ConfigUpdateHandler {
}
}
/** Adjusts the value for "top-list" to migrate the config file from versions 1 or 2 to version 3 and above.*/
/**
* Adjusts the value for "top-list" to migrate the config file from
* versions 1 or 2 to version 3 and above.
*/
private void updateTopListDefault(YamlConfiguration configuration) {
String oldTitle = configuration.getString("top-list-title");
if (oldTitle != null && oldTitle.equalsIgnoreCase("Top [x]")) {
@ -35,7 +41,10 @@ public final class ConfigUpdateHandler {
}
}
/** Adjusts some of the default colors to migrate from versions 2 or 3 to version 4 and above.*/
/**
* Adjusts some of the default colors to migrate from versions 2
* or 3 to version 4 and above.
*/
private void updateDefaultColors(YamlConfiguration configuration) {
updateColor(configuration, "top-list.title", "yellow", "#FFD52B");
updateColor(configuration, "top-list.title", "#FFEA40", "#FFD52B");

View File

@ -1,10 +1,12 @@
package com.github.artemis.the.gr8.playerstats.enums;
/** Represents the debugging level that PlayerStats can use.
<br></br>
<br>1 = low (only show unexpected errors)</br>
<br>2 = medium (detail all encountered exceptions, log main tasks and show time taken)</br>
<br>3 = high (log all tasks and time taken)</br>*/
/**
* Represents the debugging level that PlayerStats can use.
* <br>
* <br>1 = low (only show unexpected errors)
* <br>2 = medium (detail all encountered exceptions, log main tasks and show time taken)
* <br>3 = high (log all tasks and time taken)
*/
public enum DebugLevel {
LOW, MEDIUM, HIGH
}

View File

@ -5,63 +5,102 @@ import net.kyori.adventure.text.format.TextColor;
import java.util.Random;
/** This enum represents the colorscheme PlayerStats uses in its output messages.
The first set of colors is used throughout the plugin, while the set of NAME-colors
represents the colors that player-names can be in the "shared by player-name" section of shared statistics.*/
/**
* This enum represents the colorscheme PlayerStats uses in its output messages.
* The first set of colors is used throughout the plugin, while the set of NAME-colors
* represents the colors that player-names can be in the "shared by player-name"
* section of shared statistics
*/
public enum PluginColor {
/** ChatColor Gray (#AAAAAA) */
/**
* ChatColor Gray (#AAAAAA)
*/
GRAY (NamedTextColor.GRAY),
/** A Dark Purple that is mainly used for title-underscores (#6E3485).*/
/**
* A Dark Purple that is mainly used for title-underscores (#6E3485).
*/
DARK_PURPLE (TextColor.fromHexString("#6E3485")),
/** A Light Purple that is meant to simulate the color of a clicked link.
Used for the "Hover Here" part of shared statistics (#845EC2).*/
/**
* A Light Purple that is meant to simulate the color of a clicked link.
* Used for the "Hover Here" part of shared statistics (#845EC2)
* */
LIGHT_PURPLE (TextColor.fromHexString("#845EC2")),
/** ChatColor Blue (#5555FF)*/
/**
* ChatColor Blue (#5555FF)
*/
BLUE (NamedTextColor.BLUE),
/** A Medium Blue that is used for default feedback and error messages (#55AAFF).*/
/**
* A Medium Blue that is used for default feedback and error messages (#55AAFF).
*/
MEDIUM_BLUE (TextColor.fromHexString("#55AAFF")),
/** A Light Blue that is used for hover-messages and the share-button (#55C6FF). */
/**
* A Light Blue that is used for hover-messages and the share-button (#55C6FF).
*/
LIGHT_BLUE (TextColor.fromHexString("#55C6FF")),
/** ChatColor Gold (#FFAA00)*/
/**
* ChatColor Gold (#FFAA00)
*/
GOLD (NamedTextColor.GOLD),
/** A Medium Gold that is used for the example message and for hover-text accents (#FFD52B).*/
/**
* A Medium Gold that is used for the example message and for hover-text accents (#FFD52B).
*/
MEDIUM_GOLD (TextColor.fromHexString("#FFD52B")),
/** A Light Gold that is used for the example message and for hover-text accents (#FFEA40).*/
/**
* A Light Gold that is used for the example message and for hover-text accents (#FFEA40).
*/
LIGHT_GOLD (TextColor.fromHexString("#FFEA40")),
/** A Light Yellow that is used for final accents in the example message (#FFFF8E).*/
/**
* A Light Yellow that is used for final accents in the example message (#FFFF8E).
*/
LIGHT_YELLOW (TextColor.fromHexString("#FFFF8E")),
/** The color of vanilla Minecraft hearts (#FF1313). */
/**
* The color of vanilla Minecraft hearts (#FF1313).
*/
RED (TextColor.fromHexString("#FF1313")),
/** ChatColor Blue (#5555FF)*/
/**
* ChatColor Blue (#5555FF)
*/
NAME_1 (NamedTextColor.BLUE), //#5555FF - blue
/** A shade of blue between Blue and Medium Blue (#4287F5)*/
/**
* A shade of blue between Blue and Medium Blue (#4287F5)
*/
NAME_2 (TextColor.fromHexString("#4287F5")),
/** Medium Blue (#55AAFF)*/
/**
* Medium Blue (#55AAFF)
*/
NAME_3 (TextColor.fromHexString("#55AAFF")),
/** A shade of magenta/purple (#D65DB1)*/
/**
* A shade of magenta/purple (#D65DB1)
*/
NAME_4 (TextColor.fromHexString("#D65DB1")),
/** A dark shade of orange (#EE8A19)*/
/**
* A dark shade of orange (#EE8A19)
*/
NAME_5 (TextColor.fromHexString("#EE8A19")),
/** A shade of green/aqua/cyan-ish (#01C1A7)*/
/**
* A shade of green/aqua/cyan-ish (#01C1A7)
*/
NAME_6 (TextColor.fromHexString("#01C1A7")),
/** A light shade of green (#46D858)*/
/**
* A light shade of green (#46D858)
*/
NAME_7 (TextColor.fromHexString("#46D858"));
@ -71,23 +110,31 @@ public enum PluginColor {
this.color = color;
}
/** Returns the TextColor value belonging to the corresponding enum constant.*/
/**
* Returns the TextColor value belonging to the corresponding enum constant.
*/
public TextColor getColor() {
return color;
}
/** Gets the nearest NamedTextColor for the corresponding enum constant.*/
/**
* Gets the nearest NamedTextColor for the corresponding enum constant.
*/
public TextColor getConsoleColor() {
return NamedTextColor.nearestTo(color);
}
/** Randomly selects one of the 7 different NAME-colors.*/
/**
* Randomly selects one of the 7 different NAME-colors.
*/
public static TextColor getRandomNameColor() {
return getRandomNameColor(false);
}
/** Randomly selects one of the 7 different NAME-colors, and if isConsole is true,
returns the closest NamedTextColor.*/
/**
* Randomly selects one of the 7 different NAME-colors, and if isConsole is true,
* returns the closest NamedTextColor
*/
public static TextColor getRandomNameColor(boolean isConsole) {
Random randomizer = new Random();
PluginColor color = switch (randomizer.nextInt(7)) {

View File

@ -1,7 +1,10 @@
package com.github.artemis.the.gr8.playerstats.enums;
/** All standard messages PlayerStats can send as feedback.
These are all the messages that can be sent without needing additional parameters.*/
/**
* All standard messages PlayerStats can send as feedback.
* These are all the messages that can be sent without needing
* additional parameters.
*/
public enum StandardMessage {
RELOADED_CONFIG,
STILL_RELOADING,

View File

@ -1,6 +1,9 @@
package com.github.artemis.the.gr8.playerstats.enums;
/** This enum represents the targets PlayerStats accepts for a stat-lookup (Player, Server and Top).*/
/**
* This enum represents the targets PlayerStats accepts
* for a stat-lookup (Player, Server and Top).
*/
public enum Target {
PLAYER, SERVER, TOP
}

View File

@ -3,7 +3,9 @@ package com.github.artemis.the.gr8.playerstats.enums;
import org.bukkit.Statistic;
import org.jetbrains.annotations.NotNull;
/** All the units PlayerStats can display statistics in, separated by Type.*/
/**
* All the units PlayerStats can display statistics in, separated by Type.
*/
public enum Unit {
NUMBER (Type.UNTYPED, "Times"),
KM (Type.DISTANCE, "km"),
@ -26,21 +28,28 @@ public enum Unit {
this.label = label;
}
/** Returns a pretty name belonging to this enum constant. If the Unit is
NUMBER, it will return null. */
/**
* Returns a pretty name belonging to this enum constant. If the Unit is
* NUMBER, it will return null.
*/
public String getLabel() {
return this.label;
}
/** Returns the Type this enum constant belongs to.*/
/**
* Returns the Type this enum constant belongs to.
*/
public Type getType() {
return this.type;
}
/** For Type Time, Damage and Distance, this will return a smaller Unit than the current one
(if there is a smaller Unit, that is, otherwise it will return itself).
So for DAY, for example, it can return HOUR, MINUTE or SECOND.
@param stepsSmaller how many steps smaller the returned Unit should be*/
/**
* For Type Time, Damage and Distance, this will return a smaller Unit than the current one
* (if there is a smaller Unit, that is, otherwise it will return itself).
* So for DAY, for example, it can return HOUR, MINUTE or SECOND.
*
* @param stepsSmaller how many steps smaller the returned Unit should be
*/
public Unit getSmallerUnit(int stepsSmaller) {
switch (this) {
case DAY -> {
@ -99,7 +108,10 @@ public enum Unit {
}
}
/** Converts the current Unit into seconds (and returns -1 if the current Unit is not of Type TIME)*/
/**
* Converts the current Unit into seconds (and returns
* -1 if the current Unit is not of Type TIME)
*/
public double getSeconds() {
return switch (this) {
case DAY -> 86400;
@ -111,9 +123,13 @@ public enum Unit {
};
}
/** Returns the Unit corresponding to the given String. This String does NOT need to
match exactly (it can be "day" or "days", for example), and is case-insensitive.
@param unitName an approximation of the name belonging to the desired Unit, case-insensitive */
/**
* Returns the Unit corresponding to the given String. This String does NOT need to
* match exactly (it can be "day" or "days", for example), and is case-insensitive.
*
* @param unitName an approximation of the name belonging to the desired Unit,
* case-insensitive
*/
public static @NotNull Unit fromString(@NotNull String unitName) {
return switch (unitName.toLowerCase()) {
case "cm" -> Unit.CM;
@ -131,8 +147,12 @@ public enum Unit {
};
}
/** Returns the Unit.Type of this Statistic, which can be Untyped, Distance, Damage, or Time.
@param statistic the Statistic enum constant*/
/**
* Returns the Unit.Type of this Statistic, which can be Untyped,
* Distance, Damage, or Time.
*
* @param statistic the Statistic enum constant
*/
public static @NotNull Type getTypeFromStatistic(Statistic statistic) {
String name = statistic.toString().toLowerCase();
if (name.contains("one_cm")) {
@ -146,9 +166,12 @@ public enum Unit {
}
}
/** Returns the most suitable Unit for this number.
@param type the Unit.Type of the statistic this number belongs to
@param number the statistic number as returned by Player.getStatistic()*/
/**
* Returns the most suitable Unit for this number.
*
* @param type the Unit.Type of the statistic this number belongs to
* @param number the statistic number as returned by Player.getStatistic()
*/
public static Unit getMostSuitableUnit(Unit.Type type, long number) {
switch (type) {
case TIME -> {

View File

@ -5,7 +5,9 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
/** Listens for new Players that join, and reloads PlayerStats if someone joins that hasn't joined before.*/
/** Listens for new Players that join, and reloads PlayerStats
* if someone joins that hasn't joined before.
*/
public class JoinListener implements Listener {
private static ThreadManager threadManager;

View File

@ -8,24 +8,28 @@ import org.jetbrains.annotations.ApiStatus.Internal;
import java.util.LinkedHashMap;
/** The {@link InternalFormatter} formats raw numbers into pretty messages.
This ApiFormatter takes a {@link RequestSettings} object and combines it with the raw data
returned by the {@link StatCalculator}, and transforms those into a pretty message
with all the relevant information in it.*/
* This ApiFormatter takes a {@link RequestSettings} object and combines it with the raw data
* returned by the {@link StatCalculator}, and transforms those into a pretty message
* with all the relevant information in it.
*/
@Internal
public interface InternalFormatter {
/** @return a TextComponent with the following parts:
<br>[player-name]: [number] [stat-name] {sub-stat-name}*/
* <br>[player-name]: [number] [stat-name] {sub-stat-name}
*/
TextComponent formatAndSavePlayerStat(RequestSettings requestSettings, int playerStat);
/** @return a TextComponent with the following parts:
<br>[Total on] [server-name]: [number] [stat-name] [sub-stat-name]*/
* <br>[Total on] [server-name]: [number] [stat-name] [sub-stat-name]
*/
TextComponent formatAndSaveServerStat(RequestSettings requestSettings, long serverStat);
/** @return a TextComponent with the following parts:
<br>[PlayerStats] [Top 10] [stat-name] [sub-stat-name]
<br> [1.] [player-name] [number]
<br> [2.] [player-name] [number]
<br> [3.] etc...*/
* <br>[PlayerStats] [Top 10] [stat-name] [sub-stat-name]
* <br> [1.] [player-name] [number]
* <br> [2.] [player-name] [number]
* <br> [3.] etc...
*/
TextComponent formatAndSaveTopStat(RequestSettings requestSettings, LinkedHashMap<String, Integer> topStats);
}

View File

@ -27,11 +27,13 @@ import java.util.function.BiFunction;
import static net.kyori.adventure.text.Component.*;
/** Composes messages to send to a Player or Console. This class is responsible
for constructing a final Component with the text content of the desired message.
The component parts (with appropriate formatting) are supplied by a {@link ComponentFactory}.
By default, this class works with the default ComponentFactory, but you can
give it a different ComponentFactory upon creation.*/
/**
* Composes messages to send to a Player or Console. This class is responsible
* for constructing a final Component with the text content of the desired message.
* The component parts (with appropriate formatting) are supplied by a
* {@link ComponentFactory}. By default, this class works with the default
* ComponentFactory, but you can give it a different ComponentFactory upon creation.
*/
public final class MessageBuilder implements ApiFormatter {
private static ConfigHandler config;
@ -63,8 +65,10 @@ public final class MessageBuilder implements ApiFormatter {
return new MessageBuilder(config, factory);
}
/** Set whether this {@link MessageBuilder} should use hoverText.
By default, this follows the setting specified in the {@link ConfigHandler}. */
/**
* Set whether this {@link MessageBuilder} should use hoverText.
* By default, this follows the setting specified in the {@link ConfigHandler}.
*/
public void toggleHoverUse(boolean desiredSetting) {
useHoverText = desiredSetting;
}
@ -223,11 +227,13 @@ public final class MessageBuilder implements ApiFormatter {
return getTopStatLineComponent(positionInTopList, playerName, statNumberComponent);
}
/** Time-number does not hover */
/**
* Time-number does not hover
*/
@Override
public TextComponent formatTopStatLineForTypeTime(int positionInList, String playerName, long statNumber, Unit bigUnit, Unit smallUnit) {
public TextComponent formatTopStatLineForTypeTime(int positionInTopList, String playerName, long statNumber, Unit bigUnit, Unit smallUnit) {
TextComponent statNumberComponent = getBasicTimeNumberComponent(statNumber, Target.TOP, bigUnit, smallUnit);
return getTopStatLineComponent(positionInList, playerName, statNumberComponent);
return getTopStatLineComponent(positionInTopList, playerName, statNumberComponent);
}
@Override
@ -278,31 +284,49 @@ public final class MessageBuilder implements ApiFormatter {
return getPlayerStatComponent(playerName, statNumberComponent, statistic, null, null);
}
/** Returns a BiFunction for a player statistic. This BiFunction will return a formattedComponent,
the shape of which is determined by the 2 parameters the BiFunction gets.
<p>- Integer shareCode: if a shareCode is provided, a clickable "share" button will be added.
<br>- CommandSender sender: if a sender is provided, a signature with "shared by sender-name" will be added.</br>
<br>- If both parameters are null, the formattedComponent will be returned as is.</br>*/
/**
* Returns a BiFunction for a player statistic. This BiFunction will return
* a formattedComponent, the shape of which is determined by the 2 parameters
* the BiFunction gets.
* <p>- Integer shareCode: if a shareCode is provided, a clickable "share"
* button will be added.
* <br>- CommandSender sender: if a sender is provided, a signature with
* "shared by sender-name" will be added.
* <br>- If both parameters are null, the formattedComponent will be returned
* as is.
*/
public BiFunction<Integer, CommandSender, TextComponent> formattedPlayerStatFunction(int stat, @NotNull RequestSettings request) {
TextComponent playerStat = formatPlayerStat(request.getPlayerName(), stat, request.getStatistic(), request.getSubStatEntryName());
return getFormattingFunction(playerStat, Target.PLAYER);
}
/** Returns a BiFunction for a server statistic. This BiFunction will return a formattedComponent,
the shape of which is determined by the 2 parameters the BiFunction gets.
<p>- Integer shareCode: if a shareCode is provided, a clickable "share" button will be added.
<br>- CommandSender sender: if a sender is provided, a signature with "shared by sender-name" will be added.</br>
<br>- If both parameters are null, the formattedComponent will be returned as is.</br>*/
/**
* Returns a BiFunction for a server statistic. This BiFunction will return
* a formattedComponent, the shape of which is determined by the 2 parameters
* the BiFunction gets.
* <p>- Integer shareCode: if a shareCode is provided, a clickable "share"
* button will be added.
* <br>- CommandSender sender: if a sender is provided, a signature with
* "shared by sender-name" will be added.
* <br>- If both parameters are null, the formattedComponent will be returned
* as is.
*/
public BiFunction<Integer, CommandSender, TextComponent> formattedServerStatFunction(long stat, @NotNull RequestSettings request) {
TextComponent serverStat = formatServerStat(stat, request.getStatistic(), request.getSubStatEntryName());
return getFormattingFunction(serverStat, Target.SERVER);
}
/** Returns a BiFunction for a top statistic. This BiFunction will return a formattedComponent,
the shape of which is determined by the 2 parameters the BiFunction gets.
<p>- Integer shareCode: if a shareCode is provided, a clickable "share" button will be added.
<br>- CommandSender sender: if a sender is provided, a signature with "shared by sender-name" will be added.</br>
<br>- If both parameters are null, the formattedComponent will be returned as is.</br>*/
/**
* Returns a BiFunction for a top statistic. This BiFunction will return
* a formattedComponent, the shape of which is determined by the 2 parameters
* the BiFunction gets.
* <p>- Integer shareCode: if a shareCode is provided, a clickable "share"
* button will be added.
* <br>- CommandSender sender: if a sender is provided, a signature with
* "shared by sender-name" will be added.
* <br>- If both parameters are null, the formattedComponent will be returned
* as is.
*/
public BiFunction<Integer, CommandSender, TextComponent> formattedTopStatFunction(@NotNull LinkedHashMap<String, Integer> topStats, @NotNull RequestSettings request) {
final TextComponent title = getTopStatTitle(topStats.size(), request.getStatistic(), request.getSubStatEntryName());
final TextComponent list = getTopStatListComponent(topStats, request.getStatistic());
@ -562,7 +586,9 @@ public final class MessageBuilder implements ApiFormatter {
return componentFactory.statNumber(formatter.formatNumber(statNumber), target);
}
/** Provides its own space in front of it! */
/**
* Provides its own space in front of it!
*/
private TextComponent getStatUnitComponent(Statistic statistic, Target target) {
Unit unit = switch (Unit.getTypeFromStatistic(statistic)) {
case DAMAGE -> Unit.fromString(config.getDamageUnit(false));
@ -580,7 +606,9 @@ public final class MessageBuilder implements ApiFormatter {
};
}
/** Provides its own space in front of it! */
/**
* Provides its own space in front of it!
*/
private TextComponent getDistanceUnitComponent(Unit unit, Target target) {
if (config.useTranslatableComponents()) {
String unitKey = languageKeyHandler.getUnitKey(unit);
@ -593,7 +621,9 @@ public final class MessageBuilder implements ApiFormatter {
.append(componentFactory.statUnit(unit.getLabel(), target));
}
/** Provides its own space in front of it! */
/**
* Provides its own space in front of it!
*/
private TextComponent getDamageUnitComponent(Unit unit, Target target) {
if (unit == Unit.HEART) {
TextComponent heartUnit;
@ -668,11 +698,13 @@ public final class MessageBuilder implements ApiFormatter {
}
}
/** Get an ArrayList consisting of 2 or 4 timeUnits. The order of items is:
<p>0. maxUnit</p>
<p>1. minUnit</p>
<p>2. maxHoverUnit</p>
<p>3. minHoverUnit</p>*/
/**
* Get an ArrayList consisting of 2 or 4 timeUnits. The order of items is:
* <p>0. maxUnit</p>
* <p>1. minUnit</p>
* <p>2. maxHoverUnit</p>
* <p>3. minHoverUnit</p>
*/
private ArrayList<Unit> getTimeUnitRange(long statNumber) {
ArrayList<Unit> unitRange = new ArrayList<>();
if (!config.autoDetectTimeUnit(false)) {

View File

@ -24,9 +24,13 @@ import java.util.function.Function;
import static com.github.artemis.the.gr8.playerstats.enums.StandardMessage.*;
/** This class manages all PlayerStats output. It is the only place where messages are sent.
It gets its messages from a {@link MessageBuilder} configured for either a Console or for Players
(mainly to deal with the lack of hover-text, and for Bukkit consoles to make up for the lack of hex-colors).*/
/**
* This class manages all PlayerStats output. It is the only
* place where messages are sent. It gets its messages from a
* {@link MessageBuilder} configured for either a Console or
* for Players (mainly to deal with the lack of hover-text,
* and for Bukkit consoles to make up for the lack of hex-colors).
* */
public final class OutputManager implements InternalFormatter {
private static BukkitAudiences adventure;

View File

@ -11,8 +11,11 @@ import org.jetbrains.annotations.Nullable;
import static net.kyori.adventure.text.Component.text;
/** The {@link ComponentFactory} that is used to build messages for a Bukkit Console.
Bukkit consoles don't support hex colors, unlike Paper consoles.*/
/**
* The {@link ComponentFactory} that is used to build messages for
* a Bukkit Console. Bukkit consoles don't support hex colors,
* unlike Paper consoles.
*/
public class BukkitConsoleComponentFactory extends ComponentFactory {
public BukkitConsoleComponentFactory(ConfigHandler config) {

View File

@ -22,9 +22,12 @@ import org.jetbrains.annotations.Nullable;
import static net.kyori.adventure.text.Component.*;
/** Creates Components with the desired formatting for the {@link MessageBuilder} to build messages with.
This class can put Strings into formatted Components with TextColor
and TextDecoration, or return empty Components with the desired formatting.*/
/** Creates Components with the desired formatting for the
* {@link MessageBuilder} to build messages with. This class
* can put Strings into formatted Components with TextColor
* and TextDecoration, or return empty Components with the
* desired formatting.
* */
public class ComponentFactory {
private static ConfigHandler config;
@ -76,7 +79,9 @@ public class ComponentFactory {
return getColorFromString(config.getSharerNameDecoration(false));
}
/** Returns [PlayerStats]. */
/**
* Returns [PlayerStats].
*/
public TextComponent pluginPrefix() {
return text("[")
.color(BRACKETS)
@ -84,7 +89,9 @@ public class ComponentFactory {
.append(text("]"));
}
/** Returns [PlayerStats] surrounded by underscores on both sides. */
/**
* Returns [PlayerStats] surrounded by underscores on both sides.
*/
public TextComponent pluginPrefixAsTitle() {
//12 underscores for both console and in-game
return text("____________").color(UNDERSCORE)
@ -94,12 +101,18 @@ public class ComponentFactory {
.append(text("____________"));
}
/** Returns a TextComponent with the input String as content, with color Gray and decoration Italic.*/
/**
* Returns a TextComponent with the input String as content,
* with color Gray and decoration Italic.
*/
public TextComponent subTitle(String content) {
return text(content).color(BRACKETS).decorate(TextDecoration.ITALIC);
}
/** Returns a TextComponents in the style of a default plugin message, with color Medium_Blue. */
/**
* Returns a TextComponents in the style of a default plugin message,
* with color Medium_Blue.
*/
public TextComponent message() {
return text().color(MSG_MAIN).build();
}
@ -181,8 +194,12 @@ public class ComponentFactory {
.build());
}
/** @param prettyStatName a statName with underscores removed and each word capitalized
@param prettySubStatName if present, a subStatName with underscores removed and each word capitalized*/
/**
* @param prettyStatName a statName with underscores removed and each
* word capitalized
* @param prettySubStatName if present, a subStatName with underscores
* removed and each word capitalized
*/
public TextComponent statAndSubStatName(String prettyStatName, @Nullable String prettySubStatName, Target target) {
TextComponent.Builder totalStatNameBuilder = getComponentBuilder(prettyStatName,
getColorFromString(config.getStatNameDecoration(target, false)),
@ -197,7 +214,9 @@ public class ComponentFactory {
return totalStatNameBuilder.build();
}
/** Returns a TextComponent with TranslatableComponent as a child.*/
/**
* Returns a TextComponent with TranslatableComponent as a child.
* */
public TextComponent statAndSubStatNameTranslatable(String statKey, @Nullable String subStatKey, Target target) {
TextComponent.Builder totalStatNameBuilder = getComponentBuilder(null,
getColorFromString(config.getStatNameDecoration(target, false)),
@ -307,7 +326,9 @@ public class ComponentFactory {
.build();
}
/** Returns a TextComponent for the subStatName, or an empty component.*/
/**
* Returns a TextComponent for the subStatName, or an empty component.
*/
private TextComponent subStatName(@Nullable String prettySubStatName, Target target) {
if (prettySubStatName == null) {
return Component.empty();
@ -322,7 +343,9 @@ public class ComponentFactory {
}
}
/** Returns a TranslatableComponent for the subStatName, or an empty component.*/
/**
* Returns a TranslatableComponent for the subStatName, or an empty component.
*/
private TextComponent subStatNameTranslatable(@Nullable String subStatKey, Target target) {
if (subStatKey != null) {
return getComponentBuilder(null,
@ -337,18 +360,26 @@ public class ComponentFactory {
return Component.empty();
}
/** Construct a custom translation for kill_entity with the language key for commands.kill.success.single ("Killed %s").
@return a TranslatableComponent Builder with the subStat Component as args.*/
/**
* Construct a custom translation for kill_entity with the language key
* for commands.kill.success.single ("Killed %s").
*
* @return a TranslatableComponent Builder with the subStat Component as args.
*/
private TranslatableComponent.Builder killEntityBuilder(@NotNull TextComponent subStat) {
return translatable()
.key(LanguageKeyHandler.getAlternativeKeyForKillEntity()) //"Killed %s"
.args(subStat);
}
/** Construct a custom translation for entity_killed_by with the language keys for stat.minecraft.deaths
("Number of Deaths") and book.byAuthor ("by %s").
@return a TranslatableComponent Builder with stat.minecraft.deaths as key, with a ChildComponent
with book.byAuthor as key and the subStat Component as args.*/
/**
* Construct a custom translation for entity_killed_by with the language
* keys for stat.minecraft.deaths ("Number of Deaths") and book.byAuthor
* ("by %s").
*
* @return a TranslatableComponent Builder with stat.minecraft.deaths as key,
* with a ChildComponent with book.byAuthor as key and the subStat Component as args.
*/
private TranslatableComponent.Builder entityKilledByBuilder(@NotNull TextComponent subStat) {
return translatable()
.key(LanguageKeyHandler.getAlternativeKeyForEntityKilledBy()) //"Number of Deaths"

View File

@ -6,13 +6,18 @@ import net.kyori.adventure.text.*;
import net.kyori.adventure.text.flattener.ComponentFlattener;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
/** A small utility class for turning PlayerStats' custom Components into String. */
/**
* A small utility class for turning PlayerStats' custom Components into String.
*/
public final class ComponentUtils {
/** Returns a LegacyComponentSerializer that is capable of serializing TranslatableComponents,
and capable of dealing with the custom language-keys I am using to improve the entity-related
statistic names. This serializer will create a String with hex colors and styles, and it will
turn language keys into prettified, readable English. */
/**
* Returns a LegacyComponentSerializer that is capable of serializing
* TranslatableComponents, and capable of dealing with the custom
* language-keys I am using to improve the entity-related statistic
* names. This serializer will create a String with hex colors and styles,
* and it will turn language keys into prettified, readable English.
*/
public static LegacyComponentSerializer getTranslatableComponentSerializer() {
LegacyComponentSerializer serializer = getTextComponentSerializer();

View File

@ -11,7 +11,9 @@ import java.util.List;
import static net.kyori.adventure.text.Component.text;
/** A fully constructed message with examples on how to use PlayerStats.*/
/**
* A fully constructed message with examples on how to use PlayerStats.
*/
public final class ExampleMessage implements TextComponent {
private final TextComponent exampleMessage;

View File

@ -13,7 +13,9 @@ import java.util.List;
import static net.kyori.adventure.text.Component.text;
/** The help message that explains how to use PlayerStats.*/
/**
* The help message that explains how to use PlayerStats.
*/
public final class HelpMessage implements TextComponent {
private final TextComponent helpMessage;

View File

@ -11,7 +11,9 @@ import java.util.Random;
import static net.kyori.adventure.text.Component.*;
/** A festive version of the {@link ComponentFactory}*/
/**
* A festive version of the {@link ComponentFactory}
*/
public class PrideComponentFactory extends ComponentFactory {
public PrideComponentFactory(ConfigHandler c) {

View File

@ -12,8 +12,11 @@ import org.jetbrains.annotations.NotNull;
import java.util.Random;
/**This class is just for fun and adds some silly names for players on my server.
It does not impact the rest of the plugin, and will only be used for the players mentioned in here.*/
/**
* This class is just for fun and adds some silly names for
* players on my server. It does not impact the rest of the plugin,
* and will only be used for the players mentioned in here.
*/
public final class EasterEggProvider {
private static boolean isEnabled;

View File

@ -2,7 +2,10 @@ package com.github.artemis.the.gr8.playerstats.msg.msgutils;
import org.bukkit.map.MinecraftFont;
/** A small utility class that helps calculate how many dots to use to get the numbers of a top-statistic aligned. */
/**
* A small utility class that helps calculate how many dots
* to use to get the numbers of a top-statistic aligned.
*/
public final class FontUtils {
private FontUtils() {

View File

@ -16,21 +16,25 @@ import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
/** A utility class that provides language keys to be put in a TranslatableComponent.*/
/**
*
* A utility class that provides language keys to be
* put in a TranslatableComponent.
*/
public final class LanguageKeyHandler {
private static Main plugin;
private static HashMap<Statistic, String> statNameKeys;
private static File languageKeyFile;
private static FileConfiguration languageKeys;
public LanguageKeyHandler() {
public LanguageKeyHandler(Main plugin) {
LanguageKeyHandler.plugin = plugin;
statNameKeys = generateStatNameKeys();
loadFile();
}
private static void loadFile() {
Main plugin = Main.getInstance();
languageKeyFile = new File(plugin.getDataFolder(), "language.yml");
if (!languageKeyFile.exists()) {
plugin.saveResource("language.yml", false);
@ -47,42 +51,57 @@ public final class LanguageKeyHandler {
}
}
/** Checks if a given Key is the language key "stat_type.minecraft.killed"
or "commands.kill.success.single" (which results in "Killed %s").*/
/**
* Checks if a given Key is the language key "stat_type.minecraft.killed"
* or "commands.kill.success.single" (which results in "Killed %s").
*/
public static boolean isKeyForKillEntity(String statKey) {
return statKey.equalsIgnoreCase("stat_type.minecraft.killed") ||
statKey.equalsIgnoreCase("commands.kill.success.single");
}
/** Returns a language key to replace the default Statistic.Kill_Entity key.
@return the key "commands.kill.success.single", which results in "Killed %s" */
/**
* Returns a language key to replace the default Statistic.Kill_Entity key.
*
* @return the key "commands.kill.success.single", which results in "Killed %s"
*/
public static String getAlternativeKeyForKillEntity() {
return "commands.kill.success.single";
}
/** Checks if a given Key is the language key "stat_type.minecraft.killed_by"
or "stat.minecraft.deaths" (which results in "Number of Deaths").*/
/**
* Checks if a given Key is the language key "stat_type.minecraft.killed_by"
* or "stat.minecraft.deaths" (which results in "Number of Deaths").
*/
public static boolean isKeyForEntityKilledBy(String statKey) {
return statKey.equalsIgnoreCase("stat_type.minecraft.killed_by") ||
statKey.equalsIgnoreCase("stat.minecraft.deaths");
}
/** Returns a language key to replace the default Statistic.Entity_Killed_By key.
@return the key "stat.minecraft.deaths", which results in "Number of Deaths"
(meant to be followed by {@link #getAlternativeKeyForEntityKilledByArg()})*/
/**
* Returns a language key to replace the default Statistic.Entity_Killed_By key.
*
* @return the key "stat.minecraft.deaths", which results in "Number of Deaths"
* (meant to be followed by {@link #getAlternativeKeyForEntityKilledByArg()})
*/
public static String getAlternativeKeyForEntityKilledBy() {
return "stat.minecraft.deaths";
}
/** Checks if a given Key is the language key "book.byAuthor"
(which results in "by %s"). */
/**
* Checks if a given Key is the language key "book.byAuthor"
* (which results in "by %s").
*/
public static boolean isKeyForEntityKilledByArg(String statKey) {
return statKey.equalsIgnoreCase("book.byAuthor");
}
/** Returns a language key to complete the alternative key for Statistic.Entity_Killed_By.
@return the key "book.byAuthor", which results in "by %". If used after
{@link #getAlternativeKeyForEntityKilledBy()}, you will get "Number of Deaths" "by %s"*/
/**
* Returns a language key to complete the alternative key for Statistic.Entity_Killed_By.
*
* @return the key "book.byAuthor", which results in "by %". If used after
* {@link #getAlternativeKeyForEntityKilledBy()}, you will get "Number of Deaths" "by %s"
*/
public static String getAlternativeKeyForEntityKilledByArg() {
return "book.byAuthor";
}
@ -144,8 +163,10 @@ public final class LanguageKeyHandler {
}
}
/** Get the official Key from the NameSpacedKey for this entityType,
or return null if no enum constant can be retrieved or entityType is UNKNOWN.*/
/**
* Get the official Key from the NameSpacedKey for this entityType,
* or return null if no enum constant can be retrieved or entityType is UNKNOWN.
*/
public @Nullable String getEntityKey(EntityType entity) {
if (entity == null || entity == EntityType.UNKNOWN) return null;
else {
@ -153,8 +174,10 @@ public final class LanguageKeyHandler {
}
}
/** Get the official Key from the NameSpacedKey for this item Material,
or return null if no enum constant can be retrieved.*/
/**
* Get the official Key from the NameSpacedKey for this item Material,
* or return null if no enum constant can be retrieved.
*/
public @Nullable String getItemKey(Material item) {
if (item == null) return null;
else if (item.isBlock()) {
@ -165,8 +188,10 @@ public final class LanguageKeyHandler {
}
}
/** Returns the official Key from the NameSpacedKey for the block Material provided,
or return null if no enum constant can be retrieved.*/
/**
* Returns the official Key from the NameSpacedKey for the block Material provided,
* or return null if no enum constant can be retrieved.
*/
public @Nullable String getBlockKey(Material block) {
if (block == null) return null;
else if (block.toString().toLowerCase().contains("wall_banner")) { //replace wall_banner with regular banner, since there is no key for wall banners

View File

@ -5,9 +5,10 @@ import com.github.artemis.the.gr8.playerstats.enums.Unit;
import java.text.DecimalFormat;
/** A utility class that formats statistic numbers into something more readable.
It transforms numbers of {@link Unit.Type} Time, Damage, and Distance into numbers
that are easier to understand (for example: from ticks to hours) and adds commas
to break up large numbers.*/
* It transforms numbers of {@link Unit.Type} Time, Damage, and Distance into numbers
* that are easier to understand (for example: from ticks to hours) and adds commas
* to break up large numbers.
*/
public final class NumberFormatter {
private final DecimalFormat format;
@ -19,14 +20,16 @@ public final class NumberFormatter {
}
/** Turns the input number into a more readable format depending on its type
(number-of-times, time-, damage- or distance-based) according to the
corresponding config settings, and adds commas in groups of 3.*/
* (number-of-times, time-, damage- or distance-based) according to the
* corresponding config settings, and adds commas in groups of 3.
*/
public String formatNumber(long number) {
return format.format(number);
}
/** The unit of damage-based statistics is half a heart by default.
This method turns the number into hearts. */
* This method turns the number into hearts.
*/
public String formatDamageNumber(long number, Unit statUnit) { //7 statistics
if (statUnit == Unit.HEART) {
return format.format(Math.round(number / 2.0));
@ -35,8 +38,11 @@ public final class NumberFormatter {
}
}
/** The unit of distance-based statistics is cm by default. This method turns it into blocks by default,
and turns it into km or leaves it as cm otherwise, depending on the config settings. */
/** The unit of distance-based statistics is cm by default.
* This method turns it into blocks by default,
* and turns it into km or leaves it as cm otherwise,
* depending on the config settings.
*/
public String formatDistanceNumber(long number, Unit statUnit) { //15 statistics
switch (statUnit) {
case CM -> {
@ -55,7 +61,10 @@ public final class NumberFormatter {
}
/** The unit of time-based statistics is ticks by default.
@return a String with the form "1D 2H 3M 4S" (depending on the Unit range selected)*/
*
* @return a String with the form "1D 2H 3M 4S"
* (depending on the Unit range selected)
*/
public String formatTimeNumber(long number, Unit bigUnit, Unit smallUnit) { //5 statistics
if (number == 0) {
return "-";

View File

@ -2,14 +2,20 @@ package com.github.artemis.the.gr8.playerstats.msg.msgutils;
import com.github.artemis.the.gr8.playerstats.utils.MyLogger;
/** A small utility class that helps make enum constant names prettier for output in stat-messages.*/
/**
* A small utility class that helps make enum constant
* names prettier for output in stat-messages.
*/
public final class StringUtils {
private StringUtils() {
}
/** Replace "_" with " " and capitalize each first letter of the input.
@param input String to prettify, case-insensitive*/
/**
* Replace "_" with " " and capitalize each first letter of the input.
*
* @param input String to prettify, case-insensitive
*/
public static String prettify(String input) {
if (input == null) return null;
StringBuilder capitals = new StringBuilder(input.toLowerCase());

View File

@ -9,7 +9,9 @@ import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.RecursiveAction;
/** The action that is executed when a reload-command is triggered. */
/**
* The action that is executed when a reload-command is triggered.
*/
final class ReloadAction extends RecursiveAction {
private static int threshold;
@ -21,10 +23,13 @@ final class ReloadAction extends RecursiveAction {
private final int lastPlayedLimit;
private final ConcurrentHashMap<String, UUID> offlinePlayerUUIDs;
/** Fills a ConcurrentHashMap with PlayerNames and UUIDs for all OfflinePlayers that should be included in statistic calculations.
/**
* Fills a ConcurrentHashMap with PlayerNames and UUIDs for all OfflinePlayers
* that should be included in statistic calculations.
*
* @param players array of all OfflinePlayers (straight from Bukkit)
* @param lastPlayedLimit whether to set a limit based on last-played-date
* @param offlinePlayerUUIDs the ConcurrentHashMap to put resulting playerNames and UUIDs on
* @param offlinePlayerUUIDs the ConcurrentHashMap to put playerNames and UUIDs in
*/
public ReloadAction(OfflinePlayer[] players,
int lastPlayedLimit, ConcurrentHashMap<String, UUID> offlinePlayerUUIDs) {

View File

@ -45,11 +45,15 @@ public final class ReloadThread extends Thread {
MyLogger.logHighLevelMsg(this.getName() + " created!");
}
/** This method will perform a series of tasks. If a {@link StatThread} is still running,
it will join the statThread and wait for it to finish. Then, it will reload the config,
update the offlinePlayerList in the {@link OfflinePlayerHandler}, update the {@link DebugLevel},
update the share-settings in {@link ShareManager} and topListSize-settings in {@link StatCalculator},
and update the MessageBuilders in the {@link OutputManager}.*/
/**
* This method will perform a series of tasks. If a {@link StatThread}
* is still running, it will join the statThread and wait for it to finish.
* Then, it will reload the config, update the offlinePlayerList in the
* {@link OfflinePlayerHandler}, update the {@link DebugLevel}, update
* the share-settings in {@link ShareManager} and topListSize-settings
* in {@link StatCalculator}, and update the MessageBuilders in the
* {@link OutputManager}.
*/
@Override
public void run() {
long time = System.currentTimeMillis();

View File

@ -11,7 +11,9 @@ import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.RecursiveTask;
/** The action that is executed when a stat-command is triggered. */
/**
* The action that is executed when a stat-command is triggered.
*/
final class StatAction extends RecursiveTask<ConcurrentHashMap<String, Integer>> {
private static int threshold;
@ -23,7 +25,8 @@ final class StatAction extends RecursiveTask<ConcurrentHashMap<String, Integer>>
/**
* Gets the statistic numbers for all players whose name is on the list, puts them in a ConcurrentHashMap
* using the default ForkJoinPool, and returns the ConcurrentHashMap when everything is done
* using the default ForkJoinPool, and returns the ConcurrentHashMap when everything is done.
*
* @param offlinePlayerHandler the OfflinePlayerHandler to convert playerNames into Players
* @param playerNames ImmutableList of playerNames for players that should be included in stat calculations
* @param requestSettings a validated requestSettings

View File

@ -46,8 +46,11 @@ public final class StatCalculator {
return numbers.parallelStream().mapToLong(Integer::longValue).sum();
}
/** Invokes a bunch of worker pool threads to divide and conquer (get the statistics for all players
that are stored in the {@link OfflinePlayerHandler}) */
/**
* Invokes a bunch of worker pool threads to divide and conquer
* (get the statistics for all players that are stored in the
* {@link OfflinePlayerHandler})
*/
private @NotNull ConcurrentHashMap<String, Integer> getAllStatsAsync(RequestSettings requestSettings) {
long time = System.currentTimeMillis();

View File

@ -12,7 +12,9 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
/** The Thread that is in charge of getting and calculating statistics.*/
/**
* The Thread that is in charge of getting and calculating statistics.
*/
public final class StatThread extends Thread {
private static OutputManager outputManager;

View File

@ -1,9 +1,9 @@
package com.github.artemis.the.gr8.playerstats.statistic.request;
import com.github.artemis.the.gr8.playerstats.Main;
import com.github.artemis.the.gr8.playerstats.enums.Target;
import com.github.artemis.the.gr8.playerstats.utils.EnumHandler;
import com.github.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler;
import com.github.artemis.the.gr8.playerstats.enums.Target;
import org.bukkit.Material;
import org.bukkit.Statistic;
import org.bukkit.command.CommandSender;
@ -41,7 +41,7 @@ public final class RequestHandler {
}
/**
@param sender the CommandSender that requested this specific statistic
* @param sender the CommandSender that requested this specific statistic
*/
public static RequestSettings getBasicInternalStatRequest(CommandSender sender) {
RequestSettings request = RequestSettings.getBasicRequest(sender);
@ -84,15 +84,19 @@ public final class RequestHandler {
}
/**
This will create a {@link RequestSettings} object from the provided args, with the requesting Player (or Console)
as CommandSender. This CommandSender will receive feedback messages if the RequestSettings could not be created.
@param args an Array of args such as a CommandSender would put in Minecraft chat:
<p>- a <code>statName</code> (example: "mine_block")</p>
<p>- if applicable, a <code>subStatEntryName</code> (example: diorite)(</p>
<p>- a <code>target</code> for this lookup: can be "top", "server", "player" (or "me" to indicate the current CommandSender)</p>
<p>- if "player" was chosen, include a <code>playerName</code></p>
@return the generated RequestSettings
* This will create a {@link RequestSettings} object from the provided args,
* with the requesting Player (or Console) as CommandSender. This CommandSender
* will receive feedback messages if the RequestSettings could not be created.
*
* @param args an Array of args such as a CommandSender would put in Minecraft chat:
* <ul>
* <li> a <code>statName</code> (example: "mine_block")
* <li> if applicable, a <code>subStatEntryName</code> (example: diorite)
* <li> a <code>target</code> for this lookup: can be "top", "server", "player"
* (or "me" to indicate the current CommandSender)
* <li> if "player" was chosen, include a <code>playerName</code>
* </ul>
* @return the generated RequestSettings
*/
public RequestSettings getRequestFromArgs(String[] args) {
EnumHandler enumHandler = Main.getEnumHandler();
@ -134,9 +138,10 @@ public final class RequestHandler {
}
/**
Adjust the RequestSettings object if needed: unpack the playerFlag into a subStatEntry,
try to retrieve the corresponding Enum Constant for any relevant block/entity/item,
and remove any unnecessary subStatEntries.
* Adjust the RequestSettings object if needed: unpack the playerFlag
* into a subStatEntry, try to retrieve the corresponding Enum Constant
* for any relevant block/entity/item, and remove any unnecessary
* subStatEntries.
*/
private void patchRequest(RequestSettings requestSettings) {
if (requestSettings.getStatistic() != null) {

View File

@ -10,22 +10,30 @@ import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.EntityType;
import org.jetbrains.annotations.NotNull;
/** The object PlayerStats uses to calculate and format the requested statistic.
The settings in this RequestSettings object can be configured from two different sources:
<br>- Internally: by PlayerStats itself when /stat is called, using the args provided by the CommandSender.
<br>- Externally: through the API methods provided by the {@link RequestGenerator} interface.
<br>
<br>For this RequestSettings object to be valid, the following values need to be set:
<ul>
<li> a {@link Statistic} <code>statistic</code> </li>
<li> if this Statistic is not of {@link Statistic.Type} Untyped, a <code>subStatEntryName</code> needs to be set,
together with one of the following values:
<br>- for Type.Block: a {@link Material} <code>blockMaterial</code>
<br>- for Type.Item: a {@link Material} <code>itemMaterial</code>
<br>- for Type.Entity: an {@link EntityType} <code>entityType</code>
<li> a {@link Target} <code>target</code> (automatically set for all API-requests)
<li> if the <code>target</code> is Target.Player, a <code>playerName</code> needs to be added
</ul>*/
/**
* The object PlayerStats uses to calculate and format the requested
* statistic. The settings in this RequestSettings object can be
* configured from two different sources:
* <br>- Internally: by PlayerStats itself when /stat is called,
* using the args provided by the CommandSender.
* <br>- Externally: through the API methods provided by the
* {@link RequestGenerator} interface.
* <br>
* <br>For this RequestSettings object to be valid, the following
* values need to be set:
* <ul>
* <li> a {@link Statistic} <code>statistic</code> </li>
* <li> if this Statistic is not of {@link Statistic.Type} Untyped,
* a <code>subStatEntryName</code> needs to be set, together with one
* of the following values:
* <br>- for Type.Block: a {@link Material} <code>blockMaterial</code>
* <br>- for Type.Item: a {@link Material} <code>itemMaterial</code>
* <br>- for Type.Entity: an {@link EntityType} <code>entityType</code>
* <li> a {@link Target} <code>target</code> (defaults to Top)
* <li> if the <code>target</code> is Target.Player, a
* <code>playerName</code> needs to be added
* </ul>
*/
public final class RequestSettings {
private final CommandSender sender;
@ -40,14 +48,15 @@ public final class RequestSettings {
private Material item;
private boolean playerFlag;
/** Create a new {@link RequestSettings} with default values:
<br>- CommandSender sender (provided)
<br>- Target target = {@link Target#TOP}
<br>- int topListSize = 10
<br>- boolean playerFlag = false
<br>- boolean isAPIRequest
@param sender the CommandSender who prompted this RequestGenerator
/**
* Create a new {@link RequestSettings} with default values:
* <br>- CommandSender sender (provided)
* <br>- Target target = {@link Target#TOP}
* <br>- int topListSize = 10
* <br>- boolean playerFlag = false
* <br>- boolean isAPIRequest
*
* @param sender the CommandSender who prompted this RequestGenerator
*/
private RequestSettings(@NotNull CommandSender sender) {
this.sender = sender;

View File

@ -7,10 +7,14 @@ import org.bukkit.Statistic;
import org.bukkit.entity.EntityType;
import org.jetbrains.annotations.Nullable;
/** Holds all the information PlayerStats needs to perform a lookup, and can be executed
to get the results. Calling {@link #execute()} on a Top- or ServerRequest can take some
time (especially if there is a substantial amount of OfflinePlayers on this particular server),
so I strongly advice you to call this asynchronously! */
/**
* Holds all the information PlayerStats needs to perform
* a lookup, and can be executed to get the results. Calling
* {@link #execute()} on a Top- or ServerRequest can take some
* time (especially if there is a substantial amount of
* OfflinePlayers on this particular server), so I strongly
* advice you to call this asynchronously!
*/
public abstract class StatRequest<T> {
protected final RequestSettings requestSettings;
@ -19,38 +23,56 @@ public abstract class StatRequest<T> {
requestSettings = request;
}
/** Executes this StatRequest. Don't call this from the Main Thread!
@return a StatResult containing the value of this lookup, both as numerical value
and as formatted message*/
/**
* Executes this StatRequest. Don't call this from the Main Thread!
*
* @return a StatResult containing the value of this lookup, both as
* numerical value and as formatted message
*/
public abstract StatResult<T> execute();
/** @return the Statistic this StatRequest will get the data of */
/**
* @return the Statistic this StatRequest will get the data of
* */
public Statistic getStatisticSetting() {
return requestSettings.getStatistic();
}
/** If the Statistic setting for this StatRequest is of Type.Block,
this will get the Material that was set
@return a Material for which #isBlock is true, or null if no Material was set*/
/**
* If the Statistic setting for this StatRequest is of Type.Block,
* this will get the Material that was set.
*
* @return a Material for which #isBlock is true, or null if no
* Material was set
*/
public @Nullable Material getBlockSetting() {
return requestSettings.getBlock();
}
/** If the Statistic setting for this StatRequest is of Type.Item,
this will get the Material that was set
@return a Material for which #isItem is true, or null if no Material was set*/
/**
* If the Statistic setting for this StatRequest is of Type.Item,
* this will get the Material that was set.
*
* @return a Material for which #isItem is true, or null if no
* Material was set
*/
public @Nullable Material getItemSetting() {
return requestSettings.getItem();
}
/** If the Statistic setting for this StatRequest is of Type.Entity,
this will get the EntityType that was set
@return an EntityType, or null if no EntityType was set*/
/**
* If the Statistic setting for this StatRequest is of Type.Entity,
* this will get the EntityType that was set.
*
* @return an EntityType, or null if no EntityType was set
*/
public @Nullable EntityType getEntitySetting() {
return requestSettings.getEntity();
}
/** @return the Target for this lookup (either Player, Server or Top)*/
/**
* @return the Target for this lookup (either Player, Server or Top)
*/
public Target getTargetSetting() {
return requestSettings.getTarget();
}

View File

@ -3,13 +3,20 @@ package com.github.artemis.the.gr8.playerstats.statistic.result;
import com.github.artemis.the.gr8.playerstats.msg.components.ComponentUtils;
import net.kyori.adventure.text.TextComponent;
/** This Record is used to store stat-results internally, so Players can share them by clicking a share-button.*/
/**
* This Record is used to store stat-results internally,
* so Players can share them by clicking a share-button.
*/
public record InternalStatResult(String executorName, TextComponent formattedValue, int ID) implements StatResult<Integer> {
/** Gets the ID number for this StatResult. Unlike for the other {@link StatResult} implementations,
this one does not return the actual statistic data, because this implementation is meant for internal
saving-and-sharing only. This method is only for Interface-consistency, InternalStatResult#ID is better.
/**
* Gets the ID number for this StatResult. Unlike for the
* other {@link StatResult} implementations, this one does
* not return the actual statistic data, because this
* implementation is meant for internal saving-and-sharing only.
* This method is only for Interface-consistency,
* InternalStatResult#ID is better.
*
@return Integer that represents this StatResult's ID number
*/
@Override

View File

@ -4,60 +4,73 @@ import com.github.artemis.the.gr8.playerstats.api.ApiFormatter;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.kyori.adventure.text.TextComponent;
/** Holds the result of a completed stat-lookup. The <code>Type</code> parameter
<code>T</code> of this StatResult represents the data type of the stored number:
<ul>
<li> <code>Integer</code> for playerStat
<li> <code>Long</code> for serverStat
<li> <code>LinkedHashMap(String, Integer)</code> for topStat
</ul>
You can get these raw numbers with {@link #getNumericalValue()}. Additionally,
you can get a formatted message that contains the following information:
<ul>
<li> for playerStat:
<br> [player-name]: [formatted-number] [stat-name] [sub-stat-name]
<li> for serverStat:
<br> [Total on] [server-name]: [formatted-number] [stat-name] [sub-stat-name]
<li> for topStat:
<br> [PlayerStats] [Top x] [stat-name] [sub-stat-name]
<br> [1.] [player-name] [.....] [formatted-number]
<br> [2.] [player-name] [.....] [formatted-number]
<br> [3.] etc...
</ul>
/**
* Holds the result of a completed stat-lookup. The <code>Type</code> parameter
* <code>T</code> of this StatResult represents the data type of the stored number:
* <ul>
* <li> <code>Integer</code> for playerStat
* <li> <code>Long</code> for serverStat
* <li> <code>LinkedHashMap(String, Integer)</code> for topStat
* </ul>
* You can get these raw numbers with {@link #getNumericalValue()}. Additionally,
* you can get a formatted message that contains the following information:
* <ul>
* <li> for playerStat:
* <br> [player-name]: [formatted-number] [stat-name] [sub-stat-name]
* <li> for serverStat:
* <br> [Total on] [server-name]: [formatted-number] [stat-name] [sub-stat-name]
* <li> for topStat:
* <br> [PlayerStats] [Top x] [stat-name] [sub-stat-name]
* <br> [1.] [player-name] [.....] [formatted-number]
* <br> [2.] [player-name] [.....] [formatted-number]
* <br> [3.] etc...
* </ul>
By default, the resulting message is a {@link 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, 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 directly.
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>.
<p>You can also use the provided {@link #getFormattedString()} method to get the same information
in String-format. Don't use Adventure's .content() or .toString() 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}.
* By default, the resulting message is a {@link 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,
* 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
* 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>.
*
* <p>You can also use the provided {@link #getFormattedString()} method to
* get the same information in String-format. Don't use Adventure's .content()
* or .toString() 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}.
*/
public interface StatResult<T> {
/** Gets the raw number for the completed stat-lookup this {@link StatResult} stores.
@return {@code Integer} for playerStat, {@code Long} for serverStat,
and {@code LinkedHashMap<String, Integer>} for topStat*/
/**
* Gets the raw number for the completed stat-lookup this {@link StatResult}
* stores.
*
* @return {@code Integer} for playerStat, {@code Long} for serverStat,
* and {@code LinkedHashMap<String, Integer>} for topStat
*/
T getNumericalValue();
/** Gets the formatted message for the completed stat-lookup this {@link StatResult} stores.
/**
* Gets the formatted message for the completed stat-lookup this
* {@link StatResult} stores.
@return a {@code TextComponent} message containing the formatted number.
This message follows the same style/color/language settings that are specified in the
PlayerStats config. See class description for more information. */
* @return a {@code TextComponent} message containing the formatted number.
* This message follows the same style/color/language settings that are
* specified in the PlayerStats config. See class description for more
* information.
*/
TextComponent getFormattedTextComponent();
/** Gets the formatted message for the completed stat-lookup this {@link StatResult} stores.
/**
* Gets the formatted message for the completed stat-lookup this
* {@link StatResult} stores.
@return a String message containing the formatted number. This message follows
the same style and color settings that are specified in the PlayerStats config,
but it is not translatable (it is always plain English). See class description
for more information.*/
* @return a String message containing the formatted number. This message
* follows the same style and color settings that are specified in the
* PlayerStats config, but it is not translatable (it is always plain English).
* See class description for more information.
*/
String getFormattedString();
}

View File

@ -12,11 +12,13 @@ import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/** This class deals with Bukkit Enumerators. It holds private lists of all
block-, item-, entity- and statistic-names, and has one big list of all
possible sub-statistic-entries (block/item/entity). It can give the names
of all aforementioned enums, check if something is a valid enum constant,
and turn a name into its corresponding enum constant. */
/**
* This class deals with Bukkit Enumerators. It holds private lists of all
* block-, item-, entity- and statistic-names, and has one big list of all
* possible sub-statistic-entries (block/item/entity). It can give the names
* of all aforementioned enums, check if something is a valid enum constant,
* and turn a name into its corresponding enum constant.
*/
public final class EnumHandler {
private static List<String> blockNames;
@ -28,24 +30,33 @@ public final class EnumHandler {
prepareLists();
}
/** Returns all block-names in lowercase */
/**
* Returns all block-names in lowercase.
*/
public List<String> getBlockNames() {
return blockNames;
}
/** Returns all item-names in lowercase*/
/**
* Returns all item-names in lowercase.
*/
public List<String> getItemNames() {
return itemNames;
}
/** Returns all statistic-names in lowercase */
/**
* Returns all statistic-names in lowercase.
*/
public List<String> getStatNames() {
return statNames;
}
/** Returns the corresponding Material enum constant for an itemName
@param itemName String, case-insensitive
@return Material enum constant, uppercase */
/**
* Returns the corresponding Material enum constant for an itemName.
*
* @param itemName String, case-insensitive
* @return Material enum constant, uppercase
*/
public static @Nullable Material getItemEnum(String itemName) {
if (itemName == null) return null;
@ -53,9 +64,12 @@ public final class EnumHandler {
return (item != null && item.isItem()) ? item : null;
}
/** Returns the corresponding EntityType enum constant for an entityName
@param entityName String, case-insensitive
@return EntityType enum constant, uppercase */
/**
* Returns the corresponding EntityType enum constant for an entityName.
*
* @param entityName String, case-insensitive
* @return EntityType enum constant, uppercase
*/
public static @Nullable EntityType getEntityEnum(String entityName) {
try {
return EntityType.valueOf(entityName.toUpperCase());
@ -65,9 +79,12 @@ public final class EnumHandler {
}
}
/** Returns the corresponding Material enum constant for a materialName
@param materialName String, case-insensitive
@return Material enum constant, uppercase */
/**
* Returns the corresponding Material enum constant for a materialName.
*
* @param materialName String, case-insensitive
* @return Material enum constant, uppercase
*/
public static @Nullable Material getBlockEnum(String materialName) {
if (materialName == null) return null;
@ -75,8 +92,11 @@ public final class EnumHandler {
return (block != null && block.isBlock()) ? block : null;
}
/** Returns the statistic enum constant, or null if that failed.
@param statName String, case-insensitive */
/**
* Returns the statistic enum constant, or null if that failed.
*
* @param statName String, case-insensitive
*/
public static @Nullable Statistic getStatEnum(@NotNull String statName) {
try {
return Statistic.valueOf(statName.toUpperCase());
@ -86,25 +106,37 @@ public final class EnumHandler {
}
}
/** Checks if string is a valid statistic
@param statName String, case-insensitive */
/**
* Checks if string is a valid statistic.
*
* @param statName String, case-insensitive
*/
public boolean isStatistic(@NotNull String statName) {
return statNames.contains(statName.toLowerCase());
}
/** Checks whether the given String equals the name of an entity-type statistic. */
/**
* Checks whether the given String equals the name of an entity-type statistic.
*/
public boolean isEntityStatistic(String statName) {
return statName.equalsIgnoreCase(Statistic.ENTITY_KILLED_BY.toString()) ||
statName.equalsIgnoreCase(Statistic.KILL_ENTITY.toString());
}
/** Checks if this statistic is a subStatEntry, meaning it is a block, item or entity
@param statName String, case-insensitive*/
/**
* Checks if this statistic is a subStatEntry, meaning it is a block,
* item or entity.
*
* @param statName String, case-insensitive
*/
public boolean isSubStatEntry(@NotNull String statName) {
return subStatNames.contains(statName.toLowerCase());
}
/** Returns "block", "entity", "item", or "sub-statistic" if the provided Type is null. */
/**
* Returns "block", "entity", "item", or "sub-statistic" if the
* provided Type is null.
*/
public static String getSubStatTypeName(Statistic.Type statType) {
String subStat = "sub-statistic";
if (statType == null) return subStat;

View File

@ -10,7 +10,9 @@ import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
/** The PlayerStats Logger*/
/**
* The PlayerStats Logger
*/
public final class MyLogger {
private static final Logger logger;
@ -28,11 +30,13 @@ public final class MyLogger {
private MyLogger() {
}
/** Sets the desired debugging level.
<br>1 = low (only show unexpected errors)</br>
<br>2 = medium (detail all encountered exceptions, log main tasks and show time taken)</br>
<br>3 = high (log all tasks and time taken)</br>
<br>Default: 1</br>*/
/**
* Sets the desired debugging level.
* <br>1 = low (only show unexpected errors)
* <br>2 = medium (detail all encountered exceptions, log main tasks and show time taken)
* <br>3 = high (log all tasks and time taken)
* <br>Default: 1
*/
public static void setDebugLevel(int level) {
if (level == 2) {
debugLevel = DebugLevel.MEDIUM;
@ -65,12 +69,16 @@ public final class MyLogger {
logger.warning(content);
}
/** Log the encountered exception as a warning to console,
with some information about which class/method caught it
and with a printStackTrace if DebugLevel is HIGH.
@param exception The encountered exception
@param caughtBy The name of the class that caught the exception
@param additionalInfo e.g. the method-name or line where the exception is caught */
/**
* Log the encountered exception as a warning to console,
* with some information about which class/method caught it
* and with a printStackTrace if DebugLevel is HIGH.
*
* @param exception The encountered exception
* @param caughtBy The name of the class that caught the exception
* @param additionalInfo e.g. the method-name or line where the
* exception is caught
*/
public static void logException(@NotNull Exception exception, String caughtBy, @Nullable String additionalInfo) {
String extraInfo = (additionalInfo != null) ? " [" + additionalInfo + "]" : "";
String info = " (" + caughtBy + extraInfo + ")";
@ -81,8 +89,13 @@ public final class MyLogger {
}
}
/** If DebugLevel is MEDIUM or HIGH, output to console that an action has started.
@param taskLength Length of the action (in terms of units-to-process)*/
/**
* If DebugLevel is MEDIUM or HIGH, output to console that an
* action has started.
*
* @param taskLength Length of the action (in terms of
* units-to-process)
*/
public static void actionCreated(int taskLength) {
if (debugLevel != DebugLevel.LOW) {
threadNames = new ConcurrentHashMap<>();
@ -90,9 +103,13 @@ public final class MyLogger {
}
}
/** Internally save the name of the executing thread for later logging of this action.
The list of names is reset upon the start of every new action.
@param threadName Name of the executing thread*/
/**
* Internally save the name of the executing thread for later
* logging of this action. The list of names is reset upon the
* start of every new action.
*
* @param threadName Name of the executing thread
*/
public static void subActionCreated(String threadName) {
if (debugLevel == DebugLevel.HIGH) {
if (!threadNames.containsKey(threadName)) {
@ -101,8 +118,11 @@ public final class MyLogger {
}
}
/** Internally save the name of the executing thread for logging.
@param threadName Name of the executing thread */
/**
* Internally save the name of the executing thread for logging.
*
* @param threadName Name of the executing thread
*/
public static void actionRunning(String threadName) {
if (debugLevel != DebugLevel.LOW) {
if (!threadNames.containsKey(threadName)) {
@ -111,8 +131,11 @@ public final class MyLogger {
}
}
/** Output to console that an action has finished if DebugLevel is MEDIUM or higher.
If DebugLevel is HIGH, also output the names of the threads that were used. */
/**
* Output to console that an action has finished if DebugLevel is
* MEDIUM or higher. If DebugLevel is HIGH, also output the names
* of the threads that were used.
*/
public static void actionFinished() {
if (debugLevel != DebugLevel.LOW) {
logger.info("Finished Recursive Action! In total " +
@ -133,10 +156,13 @@ public final class MyLogger {
printTime(className, methodName, startTime);
}
/** Output to console how long a certain task has taken.
@param className Name of the class executing the task
@param methodName Name or description of the task
@param startTime Timestamp marking the beginning of the task */
/**
* Output to console how long a certain task has taken.
*
* @param className Name of the class executing the task
* @param methodName Name or description of the task
* @param startTime Timestamp marking the beginning of the task
*/
private static void printTime(String className, String methodName, long startTime) {
logger.info(className + " " + methodName + ": " + (System.currentTimeMillis() - startTime) + "ms");
}

View File

@ -6,9 +6,12 @@ import org.bukkit.OfflinePlayer;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/** A utility class that deals with OfflinePlayers. It stores a list of all OfflinePlayer-names
that need to be included in statistic calculations, and can retrieve the corresponding OfflinePlayer
object for a given player-name.*/
/**
* A utility class that deals with OfflinePlayers. It stores a list
* of all OfflinePlayer-names that need to be included in statistic
* calculations, and can retrieve the corresponding OfflinePlayer
* object for a given player-name.
*/
public final class OfflinePlayerHandler {
private static ConcurrentHashMap<String, UUID> offlinePlayerUUIDs;
@ -22,6 +25,7 @@ public final class OfflinePlayerHandler {
/**
* Get a new HashMap that stores the players to include in stat calculations.
* This HashMap is stored as a private variable in OfflinePlayerHandler.
*
* @param playerList ConcurrentHashMap with keys: playerNames and values: UUIDs
*/
public static void updateOfflinePlayerList(ConcurrentHashMap<String, UUID> playerList) {
@ -29,27 +33,40 @@ public final class OfflinePlayerHandler {
playerNames = Collections.list(offlinePlayerUUIDs.keys());
}
/** Checks if a given playerName is on the private HashMap of players that should be included in statistic calculations
@param playerName String, case-sensitive */
/**
* Checks if a given playerName is on the private HashMap of players
* that should be included in statistic calculations.
*
* @param playerName String, case-sensitive
*/
public boolean isRelevantPlayer(String playerName) {
return offlinePlayerUUIDs.containsKey(playerName);
}
/** Returns the number of OfflinePlayers that are included in statistic calculations */
/**
* Returns the number of OfflinePlayers that are included in
* statistic calculations
*/
public int getOfflinePlayerCount() {
return offlinePlayerUUIDs.size();
}
/** Get an ArrayList of names from all OfflinePlayers that should be included in statistic calculations */
/**
* Gets an ArrayList of names from all OfflinePlayers that should
* be included in statistic calculations.
*/
public ArrayList<String> getOfflinePlayerNames() {
return playerNames;
}
/**
* Uses the playerName to get the player's UUID from a private HashMap, and uses the UUID to get the corresponding OfflinePlayer Object.
* Uses the playerName to get the player's UUID from a private HashMap,
* and uses the UUID to get the corresponding OfflinePlayer Object.
*
* @param playerName name of the target player (case-sensitive)
* @return OfflinePlayer
* @throws IllegalArgumentException if this player is not on the list of players that should be included in statistic calculations
* @throws IllegalArgumentException if this player is not on the list
* of players that should be included in statistic calculations
*/
public OfflinePlayer getOfflinePlayer(String playerName) throws IllegalArgumentException {
if (offlinePlayerUUIDs.get(playerName) != null) {

View File

@ -1,15 +1,24 @@
package com.github.artemis.the.gr8.playerstats.utils;
/** A small utility class that calculates with unix time.*/
/**
* A small utility class that calculates with unix time.
*/
public final class UnixTimeHandler {
private UnixTimeHandler() {
}
/** Calculates whether a player has played recently enough to fall within the lastPlayedLimit.
If lastPlayedLimit == 0, this always returns true (since there is no limit).
@param lastPlayed a long that represents the amount of milliseconds between the unix start point and the time this player last joined
@param lastPlayedLimit a long that represents the maximum-number-of-days-since-last-joined */
/**
* Calculates whether a player has played recently enough
* to fall within the lastPlayedLimit. If lastPlayedLimit == 0,
* this always returns true (since there is no limit).
*
* @param lastPlayed a long that represents the amount of
* milliseconds between the unix start point
* and the time this player last joined
* @param lastPlayedLimit a long that represents the maximum-
* number-of-days-since-last-joined
*/
public static boolean hasPlayedSince(long lastPlayedLimit, long lastPlayed) {
long maxLastPlayed = System.currentTimeMillis() - lastPlayedLimit * 24 * 60 * 60 * 1000;
return lastPlayedLimit == 0 || lastPlayed >= maxLastPlayed;

View File

@ -1,6 +1,6 @@
main: com.github.artemis.the.gr8.playerstats.Main
name: PlayerStats
version: 1.6.1
version: 1.7
api-version: 1.13
description: adds commands to view player statistics in chat
author: Artemis_the_gr8