Release v1.2!

This commit is contained in:
Artemis-the-gr8 2022-06-08 01:35:08 +02:00
parent b117c2b88a
commit aa4c53b5ba
15 changed files with 102 additions and 222 deletions

View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.gmail.artemis-the-gr8</groupId>
<artifactId>PlayerStats</artifactId>
<version>1.1</version>
<version>1.2</version>
<build>
<plugins>
<plugin>

View File

@ -6,7 +6,7 @@
<groupId>com.gmail.artemis-the-gr8</groupId>
<artifactId>PlayerStats</artifactId>
<version>1.1</version>
<version>1.2</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>

View File

@ -46,7 +46,7 @@ public class Main extends JavaPlugin {
if (reloadcmd != null) reloadcmd.setExecutor(new ReloadCommand(threadManager));
//register the listener
Bukkit.getPluginManager().registerEvents(new JoinListener(threadManager), this);
Bukkit.getPluginManager().registerEvents(new JoinListener(config, threadManager), this);
logTimeTaken("onEnable", "time taken", time);
this.getLogger().info("Enabled PlayerStats!");
}

View File

@ -1,7 +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.filehandlers.TestFileHandler;
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;
@ -17,7 +16,6 @@ public class ThreadManager {
private final Main plugin;
private final BukkitAudiences adventure;
private static ConfigHandler config;
private static TestFileHandler testFile;
private final MessageFactory messageFactory;
private ReloadThread reloadThread;
@ -30,17 +28,16 @@ public class ThreadManager {
config = c;
messageFactory = m;
testFile = new TestFileHandler(plugin);
startReloadThread(null, true);
}
public void startReloadThread(CommandSender sender, boolean firstTimeLoading) {
reloadThread = new ReloadThread(threshold, adventure, config, testFile, messageFactory, plugin, statThread, sender, firstTimeLoading);
reloadThread = new ReloadThread(threshold, adventure, config, messageFactory, plugin, statThread, sender, firstTimeLoading);
reloadThread.start();
}
public void startStatThread(StatRequest request) {
statThread = new StatThread(threshold, request, reloadThread, adventure, config, testFile, messageFactory, plugin);
statThread = new StatThread(threshold, request, reloadThread, adventure, config, messageFactory, plugin);
statThread.start();
}

View File

@ -19,7 +19,21 @@ public class ConfigHandler {
public ConfigHandler(Main p) {
plugin = p;
saveDefaultConfig();
config = YamlConfiguration.loadConfiguration(configFile);
checkConfigVersion();
}
public boolean isConfigUpdated() {
return config.contains("config-version");
}
/** Sends a message in console if the latest version of the config is not present */
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");
}
}
/** Reloads the config from file, or creates a new file with default values if there is none. */
@ -67,6 +81,11 @@ public class ConfigHandler {
return config.getString("your-server-name", "this server");
}
public String getServerTitle() {
return config.getString("total-server-stat-title", "In total on");
}
/** Returns a String that represents either a Chat Color, hex color code, or Style. Default values are "none" for Style,
and "green" or "gold" for Color (for top or individual color). */
public String getPlayerNameFormatting(Query selection, boolean isStyle) {

View File

@ -1,161 +0,0 @@
package com.gmail.artemis.the.gr8.playerstats.filehandlers;
import com.gmail.artemis.the.gr8.playerstats.Main;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
import java.io.IOException;
public class TestFileHandler {
private File testFile;
private FileConfiguration testConf;
private ConfigurationSection number;
private final Main plugin;
private String onEnable;
private String reload;
private String debugging;
private String topStat;
public TestFileHandler(Main p) {
plugin = p;
onEnable = "onEnable";
reload = "reload";
debugging = "exception-debugging";
topStat = "top-stat";
}
/**
* Creates a new config section for the given threshold. Only needs to be called once, unless threshold changes.
* @param count amount of players to calculate statistics with
* @param threshold how small the subTasks have to become
*/
public void saveThreshold(int count, int threshold) {
loadFile(count);
String path = threshold + " threshold";
try {
number = testConf.getConfigurationSection(path);
if (number == null) {
number = testConf.createSection(path);
number.createSection(onEnable);
number.createSection(reload);
number.createSection(debugging);
number.createSection(topStat);
}
else {
number = testConf.getConfigurationSection(path);
}
saveFile();
}
catch (Exception e) {
e.printStackTrace();
}
}
public void logRunCount(boolean errorEncountered) {
try {
ConfigurationSection section = number.getConfigurationSection(debugging);
if (section != null) {
int runs = section.getInt("runs");
section.set("runs", runs +1);
if (errorEncountered) {
int errors = section.getInt("errors");
section.set("errors", errors + 1);
String path = "error-" + (errors + 1) + "-during-run";
int lastError = section.getInt("error-" + errors + "-during-run");
int runsUntilError = runs - lastError;
String path2 = "until-error-" + (errors + 1);
section.set(path2, runsUntilError);
section.set(path, runs);
}
saveFile();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Logs how long a certain method took for the earlier set threshold. Always make sure saveThreshold has been
* called once before this method is called.
* @param time how long the given action took
* @param scenario describes which section to get. 1 means onEnable, 2 means reload, and 3 means top-stat
*/
public void saveTimeTaken(long time, int scenario) {
String path = "";
if (scenario == 1) path = onEnable;
else if (scenario == 2) path = reload;
else if (scenario == 3) path = topStat;
try {
ConfigurationSection section = number.getConfigurationSection(path);
if (section != null) {
saveTimeToSection(time, section);
saveFile();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
private void saveTimeToSection(long time, ConfigurationSection section) {
if (section.contains("average")) {
long average = section.getLong("average");
long newAverage = ((average * (section.getKeys(false).size() -1)) + time)/section.getKeys(false).size();
section.set(section.getKeys(false).size() + "", time);
section.set("average", newAverage);
}
else {
section.set("average", time);
section.set("1", time);
}
}
private void loadFile(int players) {
String fileName = "test_" + players + ".yml";
testFile = new File(plugin.getDataFolder(), fileName);
if (!testFile.exists()) {
plugin.getLogger().info("Attempting to create testFile...");
createFile();
}
testConf = new YamlConfiguration();
try {
testConf.load(testFile);
}
catch (IOException | InvalidConfigurationException exception) {
exception.printStackTrace();
}
saveFile();
}
private void createFile() {
testFile.getParentFile().mkdirs();
try {
testFile.createNewFile();
plugin.getLogger().info("Even though this would return false, secretly a file has been created anyway");
}
catch (IOException e) {
e.printStackTrace();
}
}
private void saveFile() {
try {
testConf.save(testFile);
}
catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -1,6 +1,9 @@
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.utils.MessageFactory;
import org.bukkit.ChatColor;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
@ -8,9 +11,11 @@ import org.bukkit.event.player.PlayerJoinEvent;
public class JoinListener implements Listener {
private static ConfigHandler config;
private final ThreadManager threadManager;
public JoinListener(ThreadManager t) {
public JoinListener(ConfigHandler c, ThreadManager t) {
config = c;
threadManager = t;
}
@ -19,5 +24,11 @@ public class JoinListener implements Listener {
if (!joinEvent.getPlayer().hasPlayedBefore()) {
threadManager.startReloadThread(null, false);
}
else if (joinEvent.getPlayer().isOp() && !config.isConfigUpdated()) {
joinEvent.getPlayer().sendMessage(MessageFactory.getPluginPrefix() + ChatColor.GRAY + ChatColor.ITALIC +
"Your config version is outdated! " +
"Please delete your current config.yml (or rename it/copy it to another folder) and do /statreload");
}
}
}

View File

@ -3,7 +3,6 @@ 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.filehandlers.TestFileHandler;
import com.gmail.artemis.the.gr8.playerstats.statistic.StatThread;
import com.gmail.artemis.the.gr8.playerstats.utils.MessageFactory;
import com.gmail.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler;
@ -24,7 +23,6 @@ public class ReloadThread extends Thread {
private final BukkitAudiences adventure;
private static ConfigHandler config;
private static TestFileHandler testFile;
private final MessageFactory messageFactory;
private final Main plugin;
@ -32,11 +30,10 @@ public class ReloadThread extends Thread {
private final CommandSender sender;
private final boolean firstTimeLoading;
public ReloadThread(int threshold, BukkitAudiences b, ConfigHandler c, TestFileHandler t, MessageFactory m, Main p, @Nullable StatThread s, @Nullable CommandSender se, boolean firstTime) {
public ReloadThread(int threshold, BukkitAudiences b, ConfigHandler c, MessageFactory m, Main p, @Nullable StatThread s, @Nullable CommandSender se, boolean firstTime) {
this.threshold = threshold;
adventure = b;
config = c;
testFile = t;
messageFactory = m;
plugin = p;
@ -73,7 +70,6 @@ public class ReloadThread extends Thread {
}
}
testFile.saveTimeTaken(System.currentTimeMillis() - time, 2);
plugin.getLogger().info("Amount of relevant players: " + OfflinePlayerHandler.getOfflinePlayerCount());
plugin.logTimeTaken("ReloadThread", "loading offline players", time);
if (sender != null) {
@ -85,8 +81,6 @@ public class ReloadThread extends Thread {
plugin.getLogger().info("Loading offline players...");
OfflinePlayerHandler.updateOfflinePlayerList(getPlayerMap(true));
testFile.saveThreshold(OfflinePlayerHandler.getOfflinePlayerCount(), threshold);
testFile.saveTimeTaken(System.currentTimeMillis() - time, 1);
plugin.getLogger().info("Amount of relevant players: " + OfflinePlayerHandler.getOfflinePlayerCount());
plugin.logTimeTaken("ReloadThread", "loading offline players", time);
ThreadManager.recordCalcTime(System.currentTimeMillis() - time);

View File

@ -2,7 +2,6 @@ package com.gmail.artemis.the.gr8.playerstats.statistic;
import com.gmail.artemis.the.gr8.playerstats.Main;
import com.gmail.artemis.the.gr8.playerstats.enums.Query;
import com.gmail.artemis.the.gr8.playerstats.filehandlers.TestFileHandler;
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;
@ -28,19 +27,17 @@ public class StatThread extends Thread {
private final BukkitAudiences adventure;
private static ConfigHandler config;
private static TestFileHandler testFile;
private final MessageFactory messageFactory;
private final Main plugin;
//constructor (called on thread creation)
public StatThread(int threshold, StatRequest s, @Nullable ReloadThread r, BukkitAudiences b, ConfigHandler c, TestFileHandler t, MessageFactory o, Main p) {
public StatThread(int threshold, StatRequest s, @Nullable ReloadThread r, BukkitAudiences b, ConfigHandler c, MessageFactory o, Main p) {
this.threshold = threshold;
request = s;
reloadThread = r;
adventure = b;
config = c;
testFile = t;
messageFactory = o;
plugin = p;
plugin.getLogger().info("StatThread created!");
@ -76,7 +73,7 @@ public class StatThread extends Thread {
if (ThreadManager.getLastRecordedCalcTime() > 20000) {
adventure.sender(sender).sendMessage(messageFactory.waitAMoment(true));
}
else if (ThreadManager.getLastRecordedCalcTime() > 1500) {
else if (ThreadManager.getLastRecordedCalcTime() > 2000) {
adventure.sender(sender).sendMessage(messageFactory.waitAMoment(false));
}
@ -91,7 +88,6 @@ public class StatThread extends Thread {
}
} catch (ConcurrentModificationException e) {
testFile.logRunCount(true);
adventure.sender(sender).sendMessage(messageFactory.unknownError());
} catch (Exception e) {
adventure.sender(sender).sendMessage(messageFactory.formatExceptions(e.toString()));
@ -141,8 +137,6 @@ public class StatThread extends Thread {
throw new ConcurrentModificationException(e.toString());
}
testFile.saveTimeTaken(System.currentTimeMillis() - time, 3);
testFile.logRunCount(false);
ThreadManager.recordCalcTime(System.currentTimeMillis() - time);
plugin.logTimeTaken("StatThread", "calculating all stats", time);

View File

@ -20,11 +20,10 @@ 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 playerNames List of playerNames of players that should be included in the stat calculations
* @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
*/
public TopStatAction(int threshold, ImmutableList<String> playerNames, StatRequest statRequest, ConcurrentHashMap<String, Integer> playerStats) {
this.threshold = threshold;
this.playerNames = playerNames;

View File

@ -10,6 +10,7 @@ import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.util.Index;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Statistic;
import org.bukkit.map.MinecraftFont;
import org.jetbrains.annotations.Nullable;
@ -22,7 +23,7 @@ public class MessageFactory {
private static ConfigHandler config;
private static final TextColor msgColor = TextColor.fromHexString("#55aaff");
private static final TextColor msgColor = TextColor.fromHexString("#55AAFF");
private static final TextColor hoverBaseColor = TextColor.fromHexString("#55C6FF");
private static final TextColor hoverAccentColor1 = TextColor.fromHexString("#FFB80E");
private static final TextColor hoverAccentColor2 = TextColor.fromHexString("#FFD52B");
@ -32,7 +33,11 @@ public class MessageFactory {
config = c;
}
private static TextComponent getPluginPrefix() {
public static String getPluginPrefix() {
return ChatColor.GRAY + "[" + ChatColor.GOLD + "PlayerStats" + ChatColor.GRAY + "] " + ChatColor.RESET;
}
private static TextComponent pluginPrefix() {
return text("[")
.append(text("PlayerStats").color(NamedTextColor.GOLD))
.append(text("]")
@ -41,34 +46,34 @@ public class MessageFactory {
}
public TextComponent reloadedConfig() {
return getPluginPrefix().append(text("Config reloaded!").color(NamedTextColor.GREEN));
return pluginPrefix().append(text("Config reloaded!").color(NamedTextColor.GREEN));
}
public TextComponent stillReloading() {
return getPluginPrefix().append(text("The plugin is still (re)loading, your request will be processed when it is done!").color(msgColor));
return pluginPrefix().append(text("The plugin is still (re)loading, your request will be processed when it is done!").color(msgColor));
}
public TextComponent partiallyReloaded() {
return getPluginPrefix().append(
return pluginPrefix().append(
text("The reload process was interrupted. If you notice unexpected behavior, please reload PlayerStats again to fix it!").color(msgColor));
}
public TextComponent waitAMoment(boolean longWait) {
return longWait ? getPluginPrefix().append(text("Calculating statistics, this may take a minute...").color(msgColor))
: getPluginPrefix().append(text("Calculating statistics, this may take a few moments...").color(msgColor));
return longWait ? pluginPrefix().append(text("Calculating statistics, this may take a minute...").color(msgColor))
: pluginPrefix().append(text("Calculating statistics, this may take a few moments...").color(msgColor));
}
public TextComponent formatExceptions(String exception) {
return getPluginPrefix().append(text(exception).color(msgColor));
return pluginPrefix().append(text(exception).color(msgColor));
}
public TextComponent missingStatName() {
return getPluginPrefix().append(text("Please provide a valid statistic name!").color(msgColor));
return pluginPrefix().append(text("Please provide a valid statistic name!").color(msgColor));
}
public TextComponent missingSubStatName(Statistic.Type statType) {
String subStat = getSubStatTypeName(statType) == null ? "sub-statistic" : getSubStatTypeName(statType);
return getPluginPrefix()
return pluginPrefix()
.append(text("Please add a valid ")
.append(text(subStat))
.append(text(" to look up this statistic!")))
@ -76,12 +81,12 @@ public class MessageFactory {
}
public TextComponent missingPlayerName() {
return getPluginPrefix().append(text("Please specify a valid player-name!").color(msgColor));
return pluginPrefix().append(text("Please specify a valid player-name!").color(msgColor));
}
public TextComponent wrongSubStatType(Statistic.Type statType, String subStatEntry) {
String subStat = getSubStatTypeName(statType) == null ? "sub-statistic for this statistic" : getSubStatTypeName(statType);
return getPluginPrefix()
return pluginPrefix()
.append(text("\"")
.append(text(subStatEntry))
.append(text("\""))
@ -91,7 +96,7 @@ public class MessageFactory {
}
public TextComponent unknownError() {
return getPluginPrefix()
return pluginPrefix()
.append(text("Something went wrong with your request, please try again or see /statistic for a usage explanation!")
.color(msgColor));
}
@ -104,7 +109,7 @@ public class MessageFactory {
return Component.newline()
.append(underscores).append(spaces).append(getPluginPrefix()).append(spaces).append(underscores)
.append(underscores).append(spaces).append(pluginPrefix()).append(spaces).append(underscores)
.append(newline())
.append(text("Hover over the arguments for more information!").color(NamedTextColor.GRAY).decorate(TextDecoration.ITALIC))
.append(newline())
@ -169,7 +174,7 @@ public class MessageFactory {
public TextComponent formatTopStats(LinkedHashMap<String, Integer> topStats, String statName, String subStatEntryName) {
TextComponent.Builder topList = Component.text();
topList.append(newline()).append(getPluginPrefix())
topList.append(newline()).append(pluginPrefix())
.append(titleComponent(Query.TOP, "Top")).append(space())
.append(titleNumberComponent(topStats.size())).append(space())
.append(statNameComponent(Query.TOP, statName)).append(space())
@ -208,7 +213,7 @@ public class MessageFactory {
public TextComponent formatServerStat(String statName, String subStatEntry, int stat) {
TextComponent.Builder serverStat = Component.text();
serverStat.append(titleComponent(Query.SERVER, "Total for"))
serverStat.append(titleComponent(Query.SERVER, config.getServerTitle()))
.append(space())
.append(serverNameComponent())
.append(space())

View File

@ -1,33 +1,58 @@
# --------------------------------
# PlayerStats Configuration
# --------------------------------
# -------------------------------------------------------------------------------------------------------- #
# PlayerStats Configuration #
# -------------------------------------------------------------------------------------------------------- #
config-version: 2
# ------------------------------- #
# General #
# ------------------------------- #
# If true, OP players will receive a message when they join the server if the config version is outdated
outdated-config-notifications: true
# ----------- General ------------
# Filtering options to control which players should be included in statistic calculations
include-whitelist-only: false
exclude-banned-players: false
# To only show statistics from players that have been online in the last x days, specify the number of days here
# To only show statistics from players that have been online in the last [x] days, set a number for x
# Leave this on 0 to include all players
number-of-days-since-last-joined: 0
# ----------- Format -------------
# The name you want displayed for a total-on-this-server statistic
your-server-name: 'this server'
# ------------------------------- #
# Format & Display #
# ------------------------------- #
# If true, the stat-numbers in the top list will be aligned with dots
use-dots: true
# The maximum number of results displayed in the top list
top-list-max-size: 10
# If true, the top list will be aligned with lines of dots so that the stat numbers are all underneath each other
use-dots: true
# The title above the top list (the x is translated to the list-max-size, by default 10)
top-list-title: 'Top [x]'
# The text you want displayed for a total-on-this-server statistic
# This will be put on the same line ('In total on this server: [x] animals bred', for example)
total-server-stat-title: 'In total on'
your-server-name: 'this server'
# -------- Color & Style ---------
# The colors below can be chat color names or hex codes (format: '#xxxxxx' <-- including quotation marks!)
# The style options include: bold, italic, underlined, strikethrough (and for some reason I decided to also include magic)
# ------------------------------- #
# Color & Style #
# ------------------------------- #
# The colors below can be Chat Colors or hex codes (format: '#xxxxxx' <-- including quotation marks!)
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
@ -72,7 +97,7 @@ total-server:
title-style: none
server-name: gold
server-name-style: italic
server-name-style: none
stat-names: yellow
stat-names-style: none
@ -82,6 +107,3 @@ total-server:
stat-numbers: '#ADE7FF'
stat-numbers-style: none

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 16 KiB