Improved annotations and method names, experimented with MessageFactory related reload settings, looked into ways to improve config updates, and implemented ConfigUpdater (#48)

This commit is contained in:
Artemis-the-gr8 2022-06-15 01:08:00 +02:00
parent 8b34457f8b
commit 7ef2094e79
22 changed files with 199 additions and 151 deletions

View File

@ -16,6 +16,11 @@
<option name="name" value="sonatype-oss-snapshots1" />
<option name="url" value="https://s01.oss.sonatype.org/content/repositories/snapshots/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven-central" />
<option name="name" value="maven-central" />
<option name="url" value="https://oss.sonatype.org/content/groups/public" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />

View File

@ -49,6 +49,10 @@
<id>sonatype-oss-snapshots1</id>
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
<repository>
<id>maven-central</id>
<url>https://oss.sonatype.org/content/groups/public</url>
</repository>
</repositories>
<dependencies>
<dependency>

13
pom.xml
View File

@ -16,7 +16,7 @@
<repositories>
<repository>
<id>spigot-repo</id>
<id>spigot-repo</id> <!-- Spigot API -->
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
@ -24,6 +24,11 @@
<id>sonatype-oss-snapshots1</id> <!-- the Adventure repository for development builds -->
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
<repository>
<id>maven-central</id> <!-- Config-Updater -->
<url>https://oss.sonatype.org/content/groups/public</url>
</repository>
</repositories>
<dependencies>
@ -46,6 +51,12 @@
<version>4.11.0</version>
</dependency>
<dependency>
<groupId>com.tchristofferson</groupId>
<artifactId>ConfigUpdater</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>

View File

@ -3,7 +3,7 @@ package com.gmail.artemis.the.gr8.playerstats;
import com.gmail.artemis.the.gr8.playerstats.commands.ReloadCommand;
import com.gmail.artemis.the.gr8.playerstats.commands.StatCommand;
import com.gmail.artemis.the.gr8.playerstats.commands.TabCompleter;
import com.gmail.artemis.the.gr8.playerstats.filehandlers.ConfigHandler;
import com.gmail.artemis.the.gr8.playerstats.config.ConfigHandler;
import com.gmail.artemis.the.gr8.playerstats.listeners.JoinListener;
import com.gmail.artemis.the.gr8.playerstats.msg.MessageFactory;
import com.gmail.artemis.the.gr8.playerstats.msg.PrideMessageFactory;
@ -34,20 +34,22 @@ public class Main extends JavaPlugin {
//get instances of the classes that should be initialized
ConfigHandler config = new ConfigHandler(this);
MessageFactory messageFactory = new PrideMessageFactory(config);
ThreadManager threadManager = new ThreadManager(this, adventure(), config, messageFactory);
MessageFactory messageFactory = config.useFestiveFormatting() ? new PrideMessageFactory(config) : new MessageFactory(config);
ThreadManager threadManager = new ThreadManager(adventure(), config, messageFactory, this);
//register the commands
PluginCommand statcmd = this.getCommand("statistic");
if (statcmd != null) {
statcmd.setExecutor(new StatCommand(threadManager, adventure(), messageFactory));
statcmd.setExecutor(new StatCommand(adventure(), messageFactory, threadManager));
statcmd.setTabCompleter(new TabCompleter());
}
PluginCommand reloadcmd = this.getCommand("statisticreload");
if (reloadcmd != null) reloadcmd.setExecutor(new ReloadCommand(threadManager));
//register the listener
Bukkit.getPluginManager().registerEvents(new JoinListener(adventure(), config, messageFactory, threadManager), this);
Bukkit.getPluginManager().registerEvents(new JoinListener(threadManager), this);
//finish up
logTimeTaken("onEnable", "time taken", time);
this.getLogger().info("Enabled PlayerStats!");
}

View File

@ -1,6 +1,6 @@
package com.gmail.artemis.the.gr8.playerstats;
import com.gmail.artemis.the.gr8.playerstats.filehandlers.ConfigHandler;
import com.gmail.artemis.the.gr8.playerstats.config.ConfigHandler;
import com.gmail.artemis.the.gr8.playerstats.reload.ReloadThread;
import com.gmail.artemis.the.gr8.playerstats.statistic.StatRequest;
import com.gmail.artemis.the.gr8.playerstats.statistic.StatThread;
@ -22,31 +22,31 @@ public class ThreadManager {
private StatThread statThread;
private static long lastRecordedCalcTime;
public ThreadManager(Main p, BukkitAudiences b, ConfigHandler c, MessageFactory m) {
plugin = p;
adventure = b;
public ThreadManager(BukkitAudiences a, ConfigHandler c, MessageFactory m, Main p) {
adventure = a;
config = c;
messageFactory = m;
plugin = p;
startReloadThread(null, true);
}
public void startReloadThread(CommandSender sender, boolean firstTimeLoading) {
reloadThread = new ReloadThread(threshold, adventure, config, messageFactory, plugin, statThread, sender, firstTimeLoading);
reloadThread = new ReloadThread(adventure, config, messageFactory, plugin, threshold, firstTimeLoading, statThread, sender);
reloadThread.start();
}
public void startStatThread(StatRequest request) {
statThread = new StatThread(threshold, request, reloadThread, adventure, config, messageFactory, plugin);
statThread = new StatThread(adventure, config, messageFactory, plugin, threshold, request, reloadThread);
statThread.start();
}
//store the time in milliseconds that the last top-stat-lookup took (or loading the offline-player-list if no look-ups have been done yet)
/** Store the time in milliseconds that the last top-stat-lookup took (or loading the offline-player-list if no look-ups have been done yet). */
public static void recordCalcTime(long time) {
lastRecordedCalcTime = time;
}
//returns the time in milliseconds the last top-stat-lookup took (or loading the offline-player-list if no look-ups have been done yet)
/** Returns the time in milliseconds the last top-stat-lookup took (or loading the offline-player-list if no look-ups have been done yet). */
public static long getLastRecordedCalcTime() {
return lastRecordedCalcTime;
}

View File

@ -19,14 +19,14 @@ import org.jetbrains.annotations.NotNull;
public class StatCommand implements CommandExecutor {
private final ThreadManager threadManager;
private final BukkitAudiences adventure;
private static MessageFactory messageFactory;
private final MessageFactory messageFactory;
private final ThreadManager threadManager;
public StatCommand(ThreadManager t, BukkitAudiences b, MessageFactory m) {
threadManager = t;
adventure = b;
public StatCommand(BukkitAudiences a, MessageFactory m, ThreadManager t) {
adventure = a;
messageFactory = m;
threadManager = t;
}
@Override

View File

@ -48,14 +48,14 @@ public class TabCompleter implements org.bukkit.command.TabCompleter {
block.contains(args[args.length - 1])).collect(Collectors.toList());
case ITEM -> EnumHandler.getItemNames().stream().filter(item ->
item.contains(args[args.length - 1])).collect(Collectors.toList());
case ENTITY -> EnumHandler.getEntityTypeNames().stream().filter(entity ->
case ENTITY -> EnumHandler.getEntityNames().stream().filter(entity ->
entity.contains(args[args.length - 1])).collect(Collectors.toList());
};
}
//if previous arg = "player", suggest playerNames
else if (args[args.length-2].equalsIgnoreCase("player")) {
if (args.length >= 3 && EnumHandler.getEntityStatNames().contains(args[args.length-3].toLowerCase())) {
if (args.length >= 3 && EnumHandler.getEntitySubStatNames().contains(args[args.length-3].toLowerCase())) {
tabSuggestions = commandOptions;
}
else {

View File

@ -1,4 +1,4 @@
package com.gmail.artemis.the.gr8.playerstats.filehandlers;
package com.gmail.artemis.the.gr8.playerstats.config;
import com.gmail.artemis.the.gr8.playerstats.Main;
import com.gmail.artemis.the.gr8.playerstats.enums.Query;
@ -7,7 +7,6 @@ import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.Nullable;
import java.io.File;
public class ConfigHandler {
@ -15,24 +14,26 @@ public class ConfigHandler {
private File configFile;
private FileConfiguration config;
private final Main plugin;
private final int configVersion;
public ConfigHandler(Main p) {
plugin = p;
saveDefaultConfig();
config = YamlConfiguration.loadConfiguration(configFile);
configVersion = 3;
checkConfigVersion();
}
public boolean isConfigUpdated() {
return config.contains("config-version");
}
/** Sends a message in console if the latest version of the config is not present */
/** Checks the number that "config-version" returns, to see if the config needs updating.
<p></p>
<p>PlayerStats 1.1: "config-version" doesn't exist.</p>
<p>PlayerStats 1.2: "config-version" is 2.</p>
<p>PlayerStats 1.3: "config-version" is 3. </P>*/
private void checkConfigVersion() {
if (!config.contains("config-version")) {
plugin.getLogger().warning("Your config version is outdated! " +
"Please delete your current config.yml (or rename it/copy it to another folder) and do /statreload");
if (!config.contains("config-version") || config.getInt("config-version") != configVersion) {
new ConfigUpdateHandler(plugin, configFile, configVersion);
}
}
@ -71,6 +72,7 @@ public class ConfigHandler {
return config.getBoolean("enable-festive-formatting", true);
}
/** Gets a String representation of an integer (with or without "!" in front of it) that can determine rainbow phase in Adventure. */
public String getRainbowPhase() {
return config.getString("rainbow-phase", "");
}
@ -112,6 +114,7 @@ public class ConfigHandler {
return getStringFromConfig(selection, isStyle, def, "player-names");
}
/** Returns true if playerNames style is bold, false if it is not (and false by default). */
public boolean playerNameIsBold() {
ConfigurationSection style = getRelevantSection(Query.PLAYER);

View File

@ -0,0 +1,25 @@
package com.gmail.artemis.the.gr8.playerstats.config;
import com.gmail.artemis.the.gr8.playerstats.Main;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
import java.io.IOException;
import com.tchristofferson.configupdater.ConfigUpdater;
public 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> */
public ConfigUpdateHandler(Main plugin, File configFile, int configVersion) {
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(configFile);
configuration.set("config-version", configVersion);
try {
configuration.save(configFile);
ConfigUpdater.update(plugin, configFile.getName(), configFile);
//some logging statement
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@ -1,25 +1,15 @@
package com.gmail.artemis.the.gr8.playerstats.listeners;
import com.gmail.artemis.the.gr8.playerstats.ThreadManager;
import com.gmail.artemis.the.gr8.playerstats.filehandlers.ConfigHandler;
import com.gmail.artemis.the.gr8.playerstats.msg.MessageFactory;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
public class JoinListener implements Listener {
private final BukkitAudiences adventure;
private final ThreadManager threadManager;
private static ConfigHandler config;
private static MessageFactory messageFactory;
public JoinListener(BukkitAudiences a, ConfigHandler c, MessageFactory m, ThreadManager t) {
adventure = a;
config = c;
messageFactory = m;
public JoinListener(ThreadManager t) {
threadManager = t;
}
@ -28,9 +18,5 @@ public class JoinListener implements Listener {
if (!joinEvent.getPlayer().hasPlayedBefore()) {
threadManager.startReloadThread(null, false);
}
else if (joinEvent.getPlayer().isOp() && !config.isConfigUpdated()) {
adventure.player(joinEvent.getPlayer()).sendMessage(messageFactory.configIsOutdated());
}
}
}

View File

@ -1,7 +1,7 @@
package com.gmail.artemis.the.gr8.playerstats.msg;
import com.gmail.artemis.the.gr8.playerstats.enums.Query;
import com.gmail.artemis.the.gr8.playerstats.filehandlers.ConfigHandler;
import com.gmail.artemis.the.gr8.playerstats.config.ConfigHandler;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.event.HoverEvent;

View File

@ -1,6 +1,6 @@
package com.gmail.artemis.the.gr8.playerstats.msg;
import com.gmail.artemis.the.gr8.playerstats.filehandlers.ConfigHandler;
import com.gmail.artemis.the.gr8.playerstats.config.ConfigHandler;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.minimessage.MiniMessage;

View File

@ -20,6 +20,10 @@ public class ReloadAction extends RecursiveAction {
private final int lastPlayedLimit;
private final ConcurrentHashMap<String, UUID> offlinePlayerUUIDs;
/**
* @param threshold the maximum length of playerNames to process in one task
* @param players array of OfflinePlayers
*/
public ReloadAction(int threshold, OfflinePlayer[] players,
boolean whitelistOnly, boolean excludeBanned, int lastPlayedLimit,
ConcurrentHashMap<String, UUID> offlinePlayerUUIDs) {

View File

@ -2,7 +2,7 @@ package com.gmail.artemis.the.gr8.playerstats.reload;
import com.gmail.artemis.the.gr8.playerstats.Main;
import com.gmail.artemis.the.gr8.playerstats.ThreadManager;
import com.gmail.artemis.the.gr8.playerstats.filehandlers.ConfigHandler;
import com.gmail.artemis.the.gr8.playerstats.config.ConfigHandler;
import com.gmail.artemis.the.gr8.playerstats.statistic.StatThread;
import com.gmail.artemis.the.gr8.playerstats.msg.MessageFactory;
import com.gmail.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler;
@ -23,16 +23,16 @@ public class ReloadThread extends Thread {
private final BukkitAudiences adventure;
private static ConfigHandler config;
private final MessageFactory messageFactory;
private static MessageFactory messageFactory;
private final Main plugin;
private final StatThread statThread;
private final CommandSender sender;
private final boolean firstTimeLoading;
public ReloadThread(int threshold, BukkitAudiences b, ConfigHandler c, MessageFactory m, Main p, @Nullable StatThread s, @Nullable CommandSender se, boolean firstTime) {
public ReloadThread(BukkitAudiences a, ConfigHandler c, MessageFactory m, Main p, int threshold, boolean firstTime, @Nullable StatThread s, @Nullable CommandSender se) {
this.threshold = threshold;
adventure = b;
adventure = a;
config = c;
messageFactory = m;
plugin = p;
@ -48,6 +48,7 @@ public class ReloadThread extends Thread {
public void run() {
long time = System.currentTimeMillis();
//if reload is triggered by /statreload...
if (!firstTimeLoading) {
if (statThread != null && statThread.isAlive()) {
try {
@ -63,7 +64,8 @@ public class ReloadThread extends Thread {
try {
OfflinePlayerHandler.updateOfflinePlayerList(getPlayerMap(false));
} catch (ConcurrentModificationException e) {
}
catch (ConcurrentModificationException e) {
plugin.getLogger().warning("The request could not be fully executed due to a ConcurrentModificationException");
if (sender != null) {
adventure.sender(sender).sendMessage(messageFactory.partiallyReloaded());
@ -71,18 +73,19 @@ public class ReloadThread extends Thread {
}
plugin.getLogger().info("Amount of relevant players: " + OfflinePlayerHandler.getOfflinePlayerCount());
plugin.logTimeTaken("ReloadThread", "loading offline players", time);
plugin.logTimeTaken("ReloadThread", "loaded offline players", time);
if (sender != null) {
adventure.sender(sender).sendMessage(messageFactory.reloadedConfig());
}
}
}
//during first start-up...
else {
plugin.getLogger().info("Loading offline players...");
OfflinePlayerHandler.updateOfflinePlayerList(getPlayerMap(true));
plugin.getLogger().info("Amount of relevant players: " + OfflinePlayerHandler.getOfflinePlayerCount());
plugin.logTimeTaken("ReloadThread", "loading offline players", time);
plugin.logTimeTaken("ReloadThread", "loaded offline players", time);
ThreadManager.recordCalcTime(System.currentTimeMillis() - time);
}
}

View File

@ -25,13 +25,13 @@ public class StatRequest {
private Material block;
private Material item;
//playerFlag and topFlag are false by default, will be set to true if "player" or "top" is in the args
//playerFlag is set to false by default, will be set to true if "player" is in the args
public StatRequest(@NotNull CommandSender s) {
sender = s;
playerFlag = false;
}
//sets the statName, and automatically tries to set the correct statType and get the corresponding item/block/entity if there is a subStatEntry
/** Sets the statName, and automatically tries to set the correct statType and get the corresponding item/block/entity if there is a subStatEntry. */
public void setStatName(String statName) {
this.statName = statName;
if (statName != null) {
@ -51,8 +51,8 @@ public class StatRequest {
}
}
//sets the subStatEntry, and automatically tries to get the corresponding item/block/entity if there is a valid statType present
//if the subStatEntry is set to null, any present item/block/entity is set to null again
/** Sets the subStatEntry, and automatically tries to get the corresponding item/block/entity if there is a valid statType present.
If the subStatEntry is set to null, any present item/block/entity is set to null again. */
public void setSubStatEntry(String subStatEntry) {
this.subStatEntry = subStatEntry;
if (subStatEntry != null && statType != null) {
@ -69,21 +69,21 @@ public class StatRequest {
switch (statType) {
case ENTITY -> {
try {
entity = EnumHandler.getEntityType(subStatEntry);
entity = EnumHandler.getEntityEnum(subStatEntry);
} catch (IllegalArgumentException e) {
Bukkit.getLogger().warning(e.toString());
}
}
case ITEM -> {
try {
item = EnumHandler.getItem(subStatEntry);
item = EnumHandler.getItemEnum(subStatEntry);
} catch (IllegalArgumentException e) {
Bukkit.getLogger().warning(e.toString());
}
}
case BLOCK -> {
try {
block = EnumHandler.getBlock(subStatEntry);
block = EnumHandler.getBlockEnum(subStatEntry);
} catch (IllegalArgumentException e) {
Bukkit.getLogger().warning(e.toString());
}
@ -95,8 +95,7 @@ public class StatRequest {
this.playerName = playerName;
}
//the "player" arg is a special case, because it could either be a valid subStatEntry, or indicate that the lookup action should target a specific player
//this is why the playerFlag exists - if this is true, and playerName is null, subStatEntry should be set to "player"
/** False by default, set to true if args[] contains "player". */
public void setPlayerFlag(boolean playerFlag) {
this.playerFlag = playerFlag;
}
@ -113,7 +112,7 @@ public class StatRequest {
return statName;
}
//returns the type of the stored statistic, or null if no statName has been set
/** Returns the type of the stored statistic, or null if no statName has been set. */
public Statistic.Type getStatType() {
return statType;
}
@ -142,6 +141,8 @@ public class StatRequest {
return playerName;
}
/** The "player" arg is a special case, because it could either be a valid subStatEntry, or indicate that the lookup action should target a specific player.
This is why the playerFlag exists - if this is true, and playerName is null, subStatEntry should be set to "player". */
public boolean playerFlag() {
return playerFlag;
}

View File

@ -4,7 +4,7 @@ import com.gmail.artemis.the.gr8.playerstats.Main;
import com.gmail.artemis.the.gr8.playerstats.enums.Query;
import com.gmail.artemis.the.gr8.playerstats.reload.ReloadThread;
import com.gmail.artemis.the.gr8.playerstats.ThreadManager;
import com.gmail.artemis.the.gr8.playerstats.filehandlers.ConfigHandler;
import com.gmail.artemis.the.gr8.playerstats.config.ConfigHandler;
import com.gmail.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler;
import com.gmail.artemis.the.gr8.playerstats.msg.MessageFactory;
import com.google.common.collect.ImmutableList;
@ -27,18 +27,18 @@ public class StatThread extends Thread {
private final BukkitAudiences adventure;
private static ConfigHandler config;
private final MessageFactory messageFactory;
private static MessageFactory messageFactory;
private final Main plugin;
//constructor (called on thread creation)
public StatThread(int threshold, StatRequest s, @Nullable ReloadThread r, BukkitAudiences b, ConfigHandler c, MessageFactory o, Main p) {
public StatThread(BukkitAudiences a, ConfigHandler c, MessageFactory m, Main p, int threshold, StatRequest s, @Nullable ReloadThread r) {
this.threshold = threshold;
request = s;
reloadThread = r;
adventure = b;
adventure = a;
config = c;
messageFactory = o;
messageFactory = m;
plugin = p;
plugin.getLogger().info("StatThread created!");
}

View File

@ -20,6 +20,7 @@ public class TopStatAction extends RecursiveAction {
/**
* 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
* @param threshold the maximum length of playerNames to process in one task
* @param playerNames ImmutableList of playerNames of players that should be included in the stat calculations
* @param statRequest a validated statRequest
* @param playerStats the ConcurrentHashMap to put the results on
@ -46,7 +47,7 @@ public class TopStatAction extends RecursiveAction {
}
}
private void getStatsDirectly() {
private void getStatsDirectly() throws UnsupportedOperationException {
try {
Iterator<String> iterator = playerNames.iterator();
if (iterator.hasNext()) {

View File

@ -14,38 +14,43 @@ import java.util.stream.Stream;
public class EnumHandler {
private final static List<String> blockNames;
private final static List<String> entityTypeNames;
private final static List<String> entityNames;
private final static List<String> itemNames;
private final static List<String> statNames;
private final static List<String> entityStatNames;
private final static List<String> subStatEntryNames;
private final static List<String> entitySubStatNames;
private final static List<String> subStatNames;
static{
blockNames = Arrays.stream(Material.values()).filter(
Material::isBlock).map(Material::toString).map(String::toLowerCase).toList();
entityTypeNames = Arrays.stream(EntityType.values()).map(
entityNames = Arrays.stream(EntityType.values()).map(
EntityType::toString).map(String::toLowerCase).toList();
itemNames = Arrays.stream(Material.values()).filter(
Material::isItem).map(Material::toString).map(String::toLowerCase).toList();
statNames = Arrays.stream(Statistic.values()).map(
Statistic::toString).map(String::toLowerCase).toList();
entityStatNames = Arrays.stream(Statistic.values()).filter(statistic ->
entitySubStatNames = Arrays.stream(Statistic.values()).filter(statistic ->
statistic.getType().equals(Statistic.Type.ENTITY)).map(
Statistic::toString).map(String::toLowerCase).collect(Collectors.toList());
subStatEntryNames = Stream.of(blockNames, entityTypeNames, itemNames).flatMap(Collection::stream).toList();
subStatNames = Stream.of(blockNames, entityNames, itemNames).flatMap(Collection::stream).toList();
}
private EnumHandler() {
}
//checks whether the provided string is a valid item
/** Checks whether the provided string is a valid item */
public static boolean isItem(String itemName) {
return itemNames.contains(itemName.toLowerCase());
}
//returns corresponding item enum constant (uppercase), otherwise throws exception (param: itemName, case insensitive)
public static Material getItem(String itemName) throws IllegalArgumentException {
/** Returns all item names in lowercase */
public static List<String> getItemNames() {
return itemNames;
}
/** Returns corresponding item enum constant (uppercase), otherwise throws exception (param: itemName, case insensitive) */
public static Material getItemEnum(String itemName) throws IllegalArgumentException {
Material material = Material.matchMaterial(itemName);
if (material != null) {
return material;
@ -55,18 +60,18 @@ public class EnumHandler {
}
}
//returns all item names in lowercase
public static List<String> getItemNames() {
return itemNames;
/** Checks whether the provided string is a valid entity */
public static boolean isEntity(String entityName) {
return entityNames.contains(entityName.toLowerCase());
}
//checks whether the provided string is a valid entity
public static boolean isEntityType(String entityName) {
return entityTypeNames.contains(entityName.toLowerCase());
/** Returns all entitytype names in lowercase */
public static List<String> getEntityNames() {
return entityNames;
}
//returns EntityType enum constant (uppercase) if the input name is valid, otherwise throws exception (param: entityName, case insensitive)
public static EntityType getEntityType(@NotNull String entityName) throws IllegalArgumentException {
/** Returns EntityType enum constant (uppercase) if the input name is valid, otherwise throws exception (param: entityName, case insensitive) */
public static EntityType getEntityEnum(@NotNull String entityName) throws IllegalArgumentException {
try {
return EntityType.valueOf(entityName.toUpperCase());
}
@ -75,18 +80,18 @@ public class EnumHandler {
}
}
//returns all entitytype names in lowercase
public static List<String> getEntityTypeNames() {
return entityTypeNames;
}
//checks whether the provided string is a valid block
/** Checks whether the provided string is a valid block */
public static boolean isBlock(String materialName) {
return blockNames.contains(materialName.toLowerCase());
}
//returns corresponding block enum constant (uppercase), otherwise throws exception (param: materialName, case insensitive)
public static Material getBlock(String materialName) throws IllegalArgumentException {
/** Returns all block names in lowercase */
public static List<String> getBlockNames() {
return blockNames;
}
/** Returns corresponding block enum constant (uppercase), otherwise throws exception (param: materialName, case insensitive) */
public static Material getBlockEnum(String materialName) throws IllegalArgumentException {
Material material = Material.matchMaterial(materialName);
if (material != null) {
return material;
@ -96,12 +101,17 @@ public class EnumHandler {
}
}
//returns all block names in lowercase
public static List<String> getBlockNames() {
return blockNames;
/** Checks if string is a valid statistic (param: statName, not case sensitive) */
public static boolean isStatistic(String statName) {
return statNames.contains(statName.toLowerCase());
}
//returns the statistic enum constant, otherwise throws exception (param: statName, case insensitive)
/** Returns the names of all general statistics in lowercase */
public static List<String> getStatNames() {
return statNames;
}
/** Returns the statistic enum constant, otherwise throws exception (param: statName, case insensitive) */
public static Statistic getStatEnum(@NotNull String statName) throws IllegalArgumentException {
try {
return Statistic.valueOf(statName.toUpperCase());
@ -111,7 +121,7 @@ public class EnumHandler {
}
}
//gets the type of the statistic from the string, otherwise throws exception (param: statName, case insensitive)
/** Gets the type of the statistic from the string, otherwise throws exception (param: statName, case insensitive) */
public static Statistic.Type getStatType(@NotNull String statName) throws IllegalArgumentException {
try {
return Statistic.valueOf(statName.toUpperCase()).getType();
@ -121,36 +131,26 @@ public class EnumHandler {
}
}
//checks if string is a valid statistic (param: statName, not case sensitive)
public static boolean isStatistic(String statName) {
return statNames.contains(statName.toLowerCase());
}
//returns the names of all general statistics in lowercase
public static List<String> getStatNames() {
return statNames;
}
//returns all statistics that have type entities, in lowercase
public static List<String> getEntityStatNames() {
return entityStatNames;
}
//checks if this statistic is a subStatEntry, meaning it is a block, item or entity (param: statName, not case sensitive)
/** Checks if this statistic is a subStatEntry, meaning it is a block, item or entity (param: statName, not case sensitive) */
public static boolean isSubStatEntry(String statName) {
return subStatEntryNames.contains(statName.toLowerCase());
return subStatNames.contains(statName.toLowerCase());
}
//checks whether a subStatEntry is of the type that the statistic requires
/** Returns all statistics that have type entities, in lowercase */
public static List<String> getEntitySubStatNames() {
return entitySubStatNames;
}
/** Checks whether a subStatEntry is of the type that the statistic requires */
public static boolean isValidStatEntry(Statistic.Type statType, String subStatEntry) {
return (statType != null) && isMatchingSubStatEntry(statType, subStatEntry);
}
//returns true if subStatEntry matches the type the stat requires, or if stat is untyped and subStatEntry is null
/** Returns true if subStatEntry matches the type the stat requires, or if stat is untyped and subStatEntry is null */
private static boolean isMatchingSubStatEntry(@NotNull Statistic.Type statType, String subStatEntry) {
switch (statType) {
case ENTITY -> {
return subStatEntry != null && isEntityType(subStatEntry);
return subStatEntry != null && isEntity(subStatEntry);
}
case ITEM -> {
return subStatEntry != null && isItem(subStatEntry);

View File

@ -3,8 +3,8 @@ package com.gmail.artemis.the.gr8.playerstats.utils;
public class 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)
/** 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). */
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,14 +1,12 @@
# ------------------------------------------------------------------------------------------------------ #
# PlayerStats Configuration #
# ------------------------------------------------------------------------------------------------------ #
config-version: 2.1
config-version: 3
# ------------------------------- #
# General #
# ------------------------------- #
# Send OP players a message if the config-version is outdated when they join the server
outdated-config-notifications: true
# # ------------------------------- # #
# # General # #
# # ------------------------------- # #
# Filtering options to control which players should be included in statistic calculations
include-whitelist-only: false
@ -19,10 +17,13 @@ exclude-banned-players: false
number-of-days-since-last-joined: 0
# ------------------------------- #
# Format & Display #
# ------------------------------- #
# For the duration of certain holidays or festivals, PlayerStats will use special themed formatting
# # ------------------------------- # #
# # Format & Display # #
# # ------------------------------- # #
# Whether to use special themed formatting for the duration of certain holidays or festivals
# The festive formatting automatically stops when the holiday/event is over
# Changing this setting requires a server restart to take effect!
enable-festive-formatting: true
rainbow-phase:
@ -44,22 +45,24 @@ total-server-stat-title: 'Total on'
your-server-name: 'this server'
# ------------------------------- #
# Color & Style #
# ------------------------------- #
# # ------------------------------- # #
# # Color & Style # #
# # ------------------------------- # #
# The colors below can be Chat Colors or hex codes (format: '#xxxxxx' <-- including quotation marks!)
# -------- Styles --------- # # -------- Chat Colors --------- #
# # # #
# bold # # red dark_red #
# italic # # yellow gold #
# underlined # # green dark_green #
# magic # # aqua dark_aqua #
# strikethrough # # blue dark_blue #
# ------------------------- # # light_purple dark_purple #
# gray dark_gray #
# black white #
top-list: # ------------------------------ #
# # -------- Styles --------- # # -------- Chat Colors --------- # #
# # # # # #
# # bold # # red dark_red # #
# # italic # # yellow gold # #
# # underlined # # green dark_green # #
# # magic # # aqua dark_aqua # #
# # strikethrough # # blue dark_blue # #
# # ------------------------- # # light_purple dark_purple # #
# # gray dark_gray # #
# # black white # #
# # ------------------------------ # #
top-list:
title: yellow
title-style: none

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -1,7 +1,7 @@
main: com.gmail.artemis.the.gr8.playerstats.Main
name: PlayerStats
version: 1.2
api-version: 1.18
version: 1.3
api-version: 1.19
description: adds commands to view player statistics in chat
author: Artemis_the_gr8
commands:
@ -20,8 +20,8 @@ commands:
permission: playerstats.reload
permissions:
playerstats.stat:
description: lowest permission level
description: allows usage of the /statistic command
default: true
playerstats.reload:
description: allows config and scoreboard related things?
description: allows usage of /statreload
default: op