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:
parent
8b34457f8b
commit
7ef2094e79
|
@ -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" />
|
||||
|
|
|
@ -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
13
pom.xml
|
@ -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>
|
||||
|
|
|
@ -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!");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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!");
|
||||
}
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 |
|
@ -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
|
Loading…
Reference in New Issue