mirror of
https://github.com/itHotL/PlayerStats.git
synced 2024-11-26 12:36:16 +01:00
commit
98d9f94544
@ -5,9 +5,7 @@ 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.config.ConfigHandler;
|
||||
import com.gmail.artemis.the.gr8.playerstats.listeners.JoinListener;
|
||||
import com.gmail.artemis.the.gr8.playerstats.msg.LanguageKeyHandler;
|
||||
import com.gmail.artemis.the.gr8.playerstats.msg.MessageWriter;
|
||||
import com.gmail.artemis.the.gr8.playerstats.msg.PrideComponentFactory;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.gmail.artemis.the.gr8.playerstats.commands;
|
||||
|
||||
import com.gmail.artemis.the.gr8.playerstats.ThreadManager;
|
||||
import com.gmail.artemis.the.gr8.playerstats.enums.PluginColor;
|
||||
import com.gmail.artemis.the.gr8.playerstats.enums.Target;
|
||||
import com.gmail.artemis.the.gr8.playerstats.utils.EnumHandler;
|
||||
import com.gmail.artemis.the.gr8.playerstats.statistic.StatRequest;
|
||||
@ -9,7 +8,6 @@ import com.gmail.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler;
|
||||
import com.gmail.artemis.the.gr8.playerstats.msg.MessageWriter;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Statistic;
|
||||
@ -22,8 +20,6 @@ import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static net.kyori.adventure.text.Component.text;
|
||||
|
||||
|
||||
public class StatCommand implements CommandExecutor {
|
||||
|
||||
@ -47,16 +43,6 @@ public class StatCommand implements CommandExecutor {
|
||||
args[0].equalsIgnoreCase("example")) { //in case of "statistic examples", show examples
|
||||
adventure.sender(sender).sendMessage(messageWriter.usageExamples(isBukkitConsole));
|
||||
}
|
||||
else if (args[0].equalsIgnoreCase("test")) {
|
||||
TextComponent msg = text("Tier 1").color(PluginColor.GOLD.getColor())
|
||||
.append(text("Tier 2").color(PluginColor.MEDIUM_GOLD.getColor())
|
||||
.append(text("Tier 3").color(TextColor.fromHexString("#FFEA40"))
|
||||
.append(text("Tier 4").color(PluginColor.LIGHT_GOLD.getColor()))
|
||||
.append(text("Tier 3?")))
|
||||
.append(text("Tier 2?")))
|
||||
.append(text("Tier 1?"));
|
||||
adventure.sender(sender).sendMessage(msg);
|
||||
}
|
||||
else {
|
||||
StatRequest request = generateRequest(sender, args);
|
||||
TextComponent issues = checkRequest(request, isBukkitConsole);
|
||||
|
@ -15,7 +15,7 @@ public class TabCompleter implements org.bukkit.command.TabCompleter {
|
||||
|
||||
private final List<String> commandOptions;
|
||||
|
||||
|
||||
//TODO add "example" to the list
|
||||
public TabCompleter() {
|
||||
commandOptions = new ArrayList<>();
|
||||
commandOptions.add("top");
|
||||
|
@ -23,7 +23,7 @@ public class ConfigHandler {
|
||||
saveDefaultConfig();
|
||||
config = YamlConfiguration.loadConfiguration(configFile);
|
||||
|
||||
configVersion = 4;
|
||||
configVersion = 5;
|
||||
checkConfigVersion();
|
||||
|
||||
MyLogger.setDebugLevel(getDebugLevel());
|
||||
@ -91,18 +91,60 @@ public class ConfigHandler {
|
||||
return config.getInt("number-of-days-since-last-joined", 0);
|
||||
}
|
||||
|
||||
/** Whether to use TranslatableComponents for statistic, block, item and entity names.
|
||||
/** Whether to use TranslatableComponents wherever possible.
|
||||
Currently supported: statistic, block, item and entity names.
|
||||
<p>Default: true</p>*/
|
||||
public boolean useTranslatableComponents() {
|
||||
return config.getBoolean("translate-to-client-language", true);
|
||||
}
|
||||
|
||||
/** Whether to use HoverComponents in the usage explanation.
|
||||
/** Whether to use HoverComponents for additional information.
|
||||
<p>Default: true</p>*/
|
||||
public boolean useHoverText() {
|
||||
return config.getBoolean("enable-hover-text", true);
|
||||
}
|
||||
|
||||
public String getDistanceUnit(boolean isHoverText) {
|
||||
return getUnitString(isHoverText, "blocks", "km", "distance-unit");
|
||||
}
|
||||
|
||||
public String getDamageUnit(boolean isHoverText) {
|
||||
return getUnitString(isHoverText, "hearts", "hp", "damage-unit");
|
||||
}
|
||||
|
||||
public boolean autoDetectTimeUnit(boolean isHoverText) {
|
||||
String path = "auto-detect-biggest-time-unit";
|
||||
if (isHoverText) {
|
||||
path = path + "-for-hover-text";
|
||||
}
|
||||
boolean defaultValue = !isHoverText;
|
||||
return config.getBoolean(path, defaultValue);
|
||||
}
|
||||
|
||||
public int getNumberOfExtraTimeUnits(boolean isHoverText) {
|
||||
String path = "number-of-extra-units";
|
||||
if (isHoverText) {
|
||||
path = path + "-for-hover-text";
|
||||
}
|
||||
int defaultValue = isHoverText ? 0 : 1;
|
||||
return config.getInt(path, defaultValue);
|
||||
}
|
||||
|
||||
/** By default, getTimeUnit will return the maxUnit. If the optional minUnit flag is specified,
|
||||
the minimum unit will be returned instead. */
|
||||
public String getTimeUnit(boolean isHoverText) {
|
||||
return getTimeUnit(isHoverText, false);
|
||||
}
|
||||
|
||||
/** By default, getTimeUnit will return the maxUnit. If the optional smallUnit flag is specified,
|
||||
the minimum unit will be returned instead. */
|
||||
public String getTimeUnit(boolean isHoverText, boolean smallUnit) {
|
||||
if (smallUnit) {
|
||||
return getUnitString(isHoverText, "hours", "seconds", "smallest-time-unit");
|
||||
}
|
||||
return getUnitString(isHoverText, "days", "hours", "biggest-time-unit");
|
||||
}
|
||||
|
||||
/** Whether to use festive formatting, such as pride colors.
|
||||
<p>Default: true</p> */
|
||||
public boolean useFestiveFormatting() {
|
||||
@ -149,7 +191,7 @@ public class ConfigHandler {
|
||||
<p>Style: "none"</p>
|
||||
<p>Color Top: "green"</p>
|
||||
<p>Color Individual/Server: "gold"</p>*/
|
||||
public String getPlayerNameFormatting(Target selection, boolean isStyle) {
|
||||
public String getPlayerNameDecoration(Target selection, boolean getStyle) {
|
||||
String def;
|
||||
if (selection == Target.TOP) {
|
||||
def = "green";
|
||||
@ -157,7 +199,7 @@ public class ConfigHandler {
|
||||
else {
|
||||
def = "gold";
|
||||
}
|
||||
return getStringFromConfig(selection, isStyle, def, "player-names");
|
||||
return getDecorationString(selection, getStyle, def, "player-names");
|
||||
}
|
||||
|
||||
/** Returns true if playerNames Style is "bold", false if it is not.
|
||||
@ -175,22 +217,22 @@ public class ConfigHandler {
|
||||
/** Returns a String that represents either a Chat Color, hex color code, or a Style. Default values are:
|
||||
<p>Style: "none"</p>
|
||||
<p>Color: "yellow"</p>*/
|
||||
public String getStatNameFormatting(Target selection, boolean isStyle) {
|
||||
return getStringFromConfig(selection, isStyle, "yellow", "stat-names");
|
||||
public String getStatNameDecoration(Target selection, boolean getStyle) {
|
||||
return getDecorationString(selection, getStyle, "yellow", "stat-names");
|
||||
}
|
||||
|
||||
/** Returns a String that represents either a Chat Color, hex color code, or a Style. Default values are:
|
||||
<p>Style: "none"</p>
|
||||
<p>Color: "#FFD52B"</p>*/
|
||||
public String getSubStatNameFormatting(Target selection, boolean isStyle) {
|
||||
return getStringFromConfig(selection, isStyle, "#FFD52B", "sub-stat-names");
|
||||
public String getSubStatNameDecoration(Target selection, boolean getStyle) {
|
||||
return getDecorationString(selection, getStyle, "#FFD52B", "sub-stat-names");
|
||||
}
|
||||
|
||||
/** Returns a String that represents either a Chat Color, hex color code, or Style. Default values are:
|
||||
<p>Style: "none"</p>
|
||||
<p>Color Top: "#55AAFF"</p>
|
||||
<p>Color Individual/Server: "#ADE7FF"</p> */
|
||||
public String getStatNumberFormatting(Target selection, boolean isStyle) {
|
||||
public String getStatNumberDecoration(Target selection, boolean getStyle) {
|
||||
String def;
|
||||
if (selection == Target.TOP) {
|
||||
def = "#55AAFF";
|
||||
@ -198,14 +240,14 @@ public class ConfigHandler {
|
||||
else {
|
||||
def = "#ADE7FF";
|
||||
}
|
||||
return getStringFromConfig(selection, isStyle, def,"stat-numbers");
|
||||
return getDecorationString(selection, getStyle, def,"stat-numbers");
|
||||
}
|
||||
|
||||
/** Returns a String that represents either a Chat Color, hex color code, or Style. Default values are:
|
||||
<p>Style: "none"</p>
|
||||
<p>Color Top: "yellow"</p>
|
||||
<p>Color Server: "gold"</p>*/
|
||||
public String getTitleFormatting(Target selection, boolean isStyle) {
|
||||
public String getTitleDecoration(Target selection, boolean getStyle) {
|
||||
String def;
|
||||
if (selection == Target.TOP) {
|
||||
def = "yellow";
|
||||
@ -213,41 +255,62 @@ public class ConfigHandler {
|
||||
else {
|
||||
def = "gold";
|
||||
}
|
||||
return getStringFromConfig(selection, isStyle, def, "title");
|
||||
return getDecorationString(selection, getStyle, def, "title");
|
||||
}
|
||||
|
||||
/** Returns a String that represents either a Chat Color, hex color code, or Style. Default values are:
|
||||
<p>Style: "none"</p>
|
||||
<p>Color: "gold"</p>*/
|
||||
public String getTitleNumberFormatting(boolean isStyle) {
|
||||
return getStringFromConfig(Target.TOP, isStyle, "gold", "title-number");
|
||||
public String getTitleNumberDecoration(boolean getStyle) {
|
||||
return getDecorationString(Target.TOP, getStyle, "gold", "title-number");
|
||||
}
|
||||
|
||||
/** Returns a String that represents either a Chat Color, hex color code, or Style. Default values are:
|
||||
<p>Style: "none"</p>
|
||||
<p>Color: "#FFB80E"</p>*/
|
||||
public String getServerNameFormatting(boolean isStyle) {
|
||||
return getStringFromConfig(Target.SERVER, isStyle, "#FFB80E", "server-name");
|
||||
public String getServerNameDecoration(boolean getStyle) {
|
||||
return getDecorationString(Target.SERVER, getStyle, "#FFB80E", "server-name");
|
||||
}
|
||||
|
||||
/** Returns a String that represents either a Chat Color, hex color code, or Style. Default values are:
|
||||
<p>Style: "none"</p>
|
||||
<p>Color: "gold"</p>*/
|
||||
public String getRankNumberFormatting(boolean isStyle) {
|
||||
return getStringFromConfig(Target.TOP, isStyle, "gold", "rank-numbers");
|
||||
public String getRankNumberDecoration(boolean getStyle) {
|
||||
return getDecorationString(Target.TOP, getStyle, "gold", "rank-numbers");
|
||||
}
|
||||
|
||||
/** Returns a String that represents either a Chat Color, hex color code, or Style. Default values are:
|
||||
<p>Style: "none"</p>
|
||||
<p>Color: "dark_gray"</p> */
|
||||
public String getDotsFormatting(boolean isStyle) {
|
||||
return getStringFromConfig(Target.TOP, isStyle, "dark_gray", "dots");
|
||||
public String getDotsDecoration(boolean getStyle) {
|
||||
return getDecorationString(Target.TOP, getStyle, "dark_gray", "dots");
|
||||
}
|
||||
|
||||
/** Returns the config value for a color or style option in string-format, the supplied default value, or null if no configSection was found. */
|
||||
private @Nullable String getStringFromConfig(Target selection, boolean isStyle, String def, String pathName){
|
||||
String path = isStyle ? pathName + "-style" : pathName;
|
||||
String defaultValue = isStyle ? "none" : def;
|
||||
/** Returns a String representing the Unit that should be used for a certain Unit.Type.
|
||||
If no String can be retrieved from the config, the supplied defaultValue will be returned.
|
||||
If the defaultValue is different for hoverText, an optional String defaultHoverValue can be supplied.
|
||||
@param isHoverText if true, the unit for hovering text is returned, otherwise the unit for plain text
|
||||
@param defaultValue the default unit for plain text
|
||||
@param defaultHoverValue the default unit for hovering text
|
||||
@param pathName the config path to retrieve the value from*/
|
||||
private String getUnitString(boolean isHoverText, String defaultValue, String defaultHoverValue, String pathName) {
|
||||
String path = isHoverText ? pathName + "-for-hover-text" : pathName;
|
||||
String def = defaultValue;
|
||||
if (isHoverText && defaultHoverValue != null) {
|
||||
def = defaultHoverValue;
|
||||
}
|
||||
return config.getString(path, def);
|
||||
}
|
||||
|
||||
/** Returns the config value for a color or style option in string-format, the supplied default value,
|
||||
or null if no configSection was found.
|
||||
@param selection the Target this decoration is meant for (Player, Server or Top)
|
||||
@param getStyle if true, the result will be a style String, otherwise a color String
|
||||
@param defaultColor the default color to return if the config value cannot be found (for style, the default is always "none")
|
||||
@param pathName the config path to retrieve the value from*/
|
||||
private @Nullable String getDecorationString(Target selection, boolean getStyle, String defaultColor, String pathName){
|
||||
String path = getStyle ? pathName + "-style" : pathName;
|
||||
String defaultValue = getStyle ? "none" : defaultColor;
|
||||
|
||||
ConfigurationSection section = getRelevantSection(selection);
|
||||
return section != null ? section.getString(path, defaultValue) : null;
|
||||
|
@ -0,0 +1,199 @@
|
||||
package com.gmail.artemis.the.gr8.playerstats.enums;
|
||||
|
||||
import org.bukkit.Statistic;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
public enum Unit {
|
||||
NUMBER (Type.UNTYPED, "Times"),
|
||||
KM (Type.DISTANCE, "km"),
|
||||
MILE (Type.DISTANCE, "Miles"),
|
||||
BLOCK (Type.DISTANCE, "Blocks"),
|
||||
CM (Type.DISTANCE, "cm"),
|
||||
HP (Type.DAMAGE, "HP"),
|
||||
HEART (Type.DAMAGE, "Hearts"),
|
||||
DAY (Type.TIME, "days"),
|
||||
HOUR (Type.TIME, "hours"),
|
||||
MINUTE (Type.TIME, "minutes"),
|
||||
SECOND (Type.TIME, "seconds"),
|
||||
TICK (Type.TIME, "ticks");
|
||||
|
||||
private final Type type;
|
||||
private final String label;
|
||||
|
||||
Unit(Type type, String label) {
|
||||
this.type = type;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
/** Returns a pretty name belonging to this enum constant. If the Unit is
|
||||
NUMBER, it will return null. */
|
||||
public String getLabel() {
|
||||
return this.label;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public Unit getSmallerUnit(int stepsSmaller) {
|
||||
switch (this) {
|
||||
case DAY -> {
|
||||
if (stepsSmaller >= 3) {
|
||||
return Unit.SECOND;
|
||||
} else if (stepsSmaller == 2) {
|
||||
return Unit.MINUTE;
|
||||
} else if (stepsSmaller == 1) {
|
||||
return Unit.HOUR;
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
case HOUR -> {
|
||||
if (stepsSmaller >= 2) {
|
||||
return Unit.SECOND;
|
||||
} else if (stepsSmaller == 1) {
|
||||
return Unit.MINUTE;
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
case MINUTE -> {
|
||||
if (stepsSmaller >= 1) {
|
||||
return Unit.SECOND;
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
case KM -> {
|
||||
if (stepsSmaller >= 2) {
|
||||
return Unit.CM;
|
||||
} else if (stepsSmaller == 1) {
|
||||
return Unit.BLOCK;
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
case BLOCK -> {
|
||||
if (stepsSmaller >= 1) {
|
||||
return Unit.CM;
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
case HEART -> {
|
||||
if (stepsSmaller >= 1) {
|
||||
return Unit.HP;
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public double getSeconds() {
|
||||
switch (this) {
|
||||
case DAY -> {
|
||||
return 86400;
|
||||
}
|
||||
case HOUR -> {
|
||||
return 3600;
|
||||
}
|
||||
case MINUTE -> {
|
||||
return 60;
|
||||
}
|
||||
case SECOND -> {
|
||||
return 1;
|
||||
}
|
||||
case TICK -> {
|
||||
return 1 / 20.0;
|
||||
}
|
||||
default -> {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the Unit corresponding to the given String. This String does NOT need to
|
||||
match exactly (it can be "day" or "days", for example), and is case-insensitive.
|
||||
@param unitName an approximation of the name belonging to the desired Unit, case-insensitive */
|
||||
public static @NotNull Unit fromString(@NotNull String unitName) {
|
||||
Unit unit;
|
||||
switch (unitName.toLowerCase()) {
|
||||
case "cm" -> unit = Unit.CM;
|
||||
case "m", "block", "blocks" -> unit = Unit.BLOCK;
|
||||
case "mile", "miles" -> unit = Unit.MILE;
|
||||
case "km" -> unit = Unit.KM;
|
||||
case "hp" -> unit = Unit.HP;
|
||||
case "heart", "hearts" -> unit = Unit.HEART;
|
||||
case "day", "days" -> unit = Unit.DAY;
|
||||
case "hour", "hours" -> unit = Unit.HOUR;
|
||||
case "minute", "minutes", "min" -> unit = Unit.MINUTE;
|
||||
case "second", "seconds", "sec" -> unit = Unit.SECOND;
|
||||
case "tick", "ticks" -> unit = Unit.TICK;
|
||||
default -> unit = Unit.NUMBER;
|
||||
}
|
||||
return unit;
|
||||
}
|
||||
|
||||
/** Returns the Unit.Type of this Statistic, which can be Untyped, Distance, Damage, or Time.
|
||||
@param statistic the Statistic enum constant*/
|
||||
public static @NotNull Type getTypeFromStatistic(Statistic statistic) {
|
||||
String name = statistic.toString().toLowerCase();
|
||||
if (name.contains("one_cm")) {
|
||||
return Type.DISTANCE;
|
||||
} else if (name.contains("damage")) {
|
||||
return Type.DAMAGE;
|
||||
} else if (name.contains("time") || name.contains("one_minute")) {
|
||||
return Type.TIME;
|
||||
} else {
|
||||
return Type.UNTYPED;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the most suitable timeUnit for this number.
|
||||
@param type the Unit.Type of the statistic this number belongs to
|
||||
@param number the statistic number as returned by Player.getStatistic()*/
|
||||
public static Unit getMostSuitableUnit(Unit.Type type, long number) {
|
||||
switch (type) {
|
||||
case TIME -> {
|
||||
long statNumber = number / 20;
|
||||
if (statNumber >= 86400) {
|
||||
return Unit.DAY;
|
||||
} else if (statNumber >= 3600) {
|
||||
return Unit.HOUR;
|
||||
} else if (statNumber >= 60) {
|
||||
return Unit.MINUTE;
|
||||
} else {
|
||||
return Unit.SECOND;
|
||||
}
|
||||
}
|
||||
case DISTANCE -> {
|
||||
if (number >= 100000) {
|
||||
return Unit.KM;
|
||||
} else {
|
||||
return Unit.BLOCK;
|
||||
}
|
||||
}
|
||||
case DAMAGE -> {
|
||||
return Unit.HEART;
|
||||
}
|
||||
default -> {
|
||||
return Unit.NUMBER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum Type{
|
||||
DAMAGE, //7 statistics
|
||||
DISTANCE, //15 statistics
|
||||
TIME, //5 statistics
|
||||
UNTYPED;
|
||||
|
||||
Type() {
|
||||
}
|
||||
}
|
||||
}
|
@ -3,9 +3,6 @@ package com.gmail.artemis.the.gr8.playerstats.msg;
|
||||
import com.gmail.artemis.the.gr8.playerstats.config.ConfigHandler;
|
||||
import com.gmail.artemis.the.gr8.playerstats.enums.PluginColor;
|
||||
import com.gmail.artemis.the.gr8.playerstats.enums.Target;
|
||||
import com.gmail.artemis.the.gr8.playerstats.statistic.StatRequest;
|
||||
import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger;
|
||||
import com.gmail.artemis.the.gr8.playerstats.utils.NumberFormatter;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.TranslatableComponent;
|
||||
@ -13,6 +10,7 @@ import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import net.kyori.adventure.util.HSVLike;
|
||||
import net.kyori.adventure.util.Index;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -32,219 +30,116 @@ public class ComponentFactory {
|
||||
config = c;
|
||||
}
|
||||
|
||||
/** Returns [PlayerStats] followed by a single space. */
|
||||
public TextComponent pluginPrefix(boolean isBukkitConsole) {
|
||||
/** Returns [PlayerStats]. */
|
||||
public TextComponent pluginPrefixComponent(boolean isBukkitConsole) {
|
||||
return text("[")
|
||||
.color(PluginColor.GRAY.getColor())
|
||||
.append(text("PlayerStats").color(PluginColor.GOLD.getColor()))
|
||||
.append(text("]"))
|
||||
.append(space());
|
||||
.append(text("]"));
|
||||
}
|
||||
|
||||
/** Returns [PlayerStats] surrounded by underscores on both sides. */
|
||||
public TextComponent prefixTitle(boolean isBukkitConsole) {
|
||||
public TextComponent prefixTitleComponent(boolean isBukkitConsole) {
|
||||
String underscores = "____________"; //12 underscores for both console and in-game
|
||||
TextColor underscoreColor = isBukkitConsole ?
|
||||
PluginColor.DARK_PURPLE.getConsoleColor() : PluginColor.DARK_PURPLE.getColor();
|
||||
|
||||
return text(underscores).color(underscoreColor)
|
||||
.append(text(" ")) //4 spaces
|
||||
.append(pluginPrefix(isBukkitConsole))
|
||||
.append(text(" ")) //3 spaces (since prefix already has one)
|
||||
.append(pluginPrefixComponent(isBukkitConsole))
|
||||
.append(text(" ")) //4 spaces
|
||||
.append(text(underscores));
|
||||
}
|
||||
|
||||
/** Returns a TextComponent with the input String as content, with color Gray and decoration Italic.*/
|
||||
public TextComponent subTitle(String content) {
|
||||
public TextComponent subTitleComponent(String content) {
|
||||
return text(content).color(PluginColor.GRAY.getColor()).decorate(TextDecoration.ITALIC);
|
||||
}
|
||||
|
||||
/** Returns a TextComponents that represents a full message, with [PlayerStats] prepended. */
|
||||
public TextComponent msg(String msg, boolean isBukkitConsole) {
|
||||
return pluginPrefix(isBukkitConsole)
|
||||
.append(text(msg)
|
||||
.color(PluginColor.MEDIUM_BLUE.getColor()));
|
||||
public TextComponent messageComponent() {
|
||||
return text().color(PluginColor.MEDIUM_BLUE.getColor()).build();
|
||||
}
|
||||
|
||||
/** Returns a plain TextComponent that represents a single message line.
|
||||
A space will be inserted after part1, part2 and part3.
|
||||
Each message part has its own designated color.
|
||||
@param part1 color DARK_GOLD
|
||||
@param part2 color MEDIUM_GOLD
|
||||
@param part3 color YELLOW
|
||||
@param part4 color GRAY
|
||||
*/
|
||||
public TextComponent msgPart(@Nullable String part1, @Nullable String part2, @Nullable String part3, @Nullable String part4) {
|
||||
return msgPart(part1, part2, part3, part4, false);
|
||||
public TextComponent.Builder playerNameBuilder(String playerName, Target selection) {
|
||||
return getComponentBuilder(playerName,
|
||||
getColorFromString(config.getPlayerNameDecoration(selection, false)),
|
||||
getStyleFromString(config.getPlayerNameDecoration(selection, true)));
|
||||
}
|
||||
|
||||
/** Returns a plain TextComponent that represents a single message line.
|
||||
A space will be inserted after part1, part2 and part3.
|
||||
Each message part has its own designated color.
|
||||
if isBukkitConsole is true, the colors will be the nearest ChatColor to the below colors.
|
||||
@param part1 color DARK_GOLD
|
||||
@param part2 color MEDIUM_GOLD
|
||||
@param part3 color YELLOW
|
||||
@param part4 color GRAY
|
||||
*/
|
||||
public TextComponent msgPart(@Nullable String part1, @Nullable String part2, @Nullable String part3, @Nullable String part4, boolean isBukkitConsole) {
|
||||
TextComponent.Builder msg = Component.text();
|
||||
if (part1 != null) {
|
||||
TextColor pluginColor = isBukkitConsole ? PluginColor.GOLD.getConsoleColor() : PluginColor.GOLD.getColor();
|
||||
msg.append(text(part1)
|
||||
.color(pluginColor))
|
||||
.append(space());
|
||||
/** @param prettyStatName a statName with underscores removed and each word capitalized
|
||||
@param prettySubStatName if present, a subStatName with underscores removed and each word capitalized*/
|
||||
public TextComponent statNameTextComponent(String prettyStatName, @Nullable String prettySubStatName, Target selection) {
|
||||
TextComponent.Builder totalStatNameBuilder = getComponentBuilder(prettyStatName,
|
||||
getColorFromString(config.getStatNameDecoration(selection, false)),
|
||||
getStyleFromString(config.getStatNameDecoration(selection, true)));
|
||||
TextComponent subStat = subStatNameTextComponent(prettySubStatName, selection);
|
||||
|
||||
if (!subStat.equals(Component.empty())) {
|
||||
totalStatNameBuilder
|
||||
.append(space().decorations(TextDecoration.NAMES.values(), false))
|
||||
.append(subStatNameTextComponent(prettySubStatName, selection));
|
||||
}
|
||||
if (part2 != null) {
|
||||
TextColor pluginColor = isBukkitConsole ? PluginColor.MEDIUM_GOLD.getConsoleColor() : PluginColor.MEDIUM_GOLD.getColor();
|
||||
msg.append(text(part2)
|
||||
.color(pluginColor))
|
||||
.append(space());
|
||||
}
|
||||
if (part3 != null) {
|
||||
TextColor pluginColor = isBukkitConsole ? PluginColor.LIGHT_GOLD.getConsoleColor() : PluginColor.LIGHT_GOLD.getColor();
|
||||
msg.append(text(part3)
|
||||
.color(pluginColor))
|
||||
.append(space());
|
||||
}
|
||||
if (part4 != null) {
|
||||
TextColor pluginColor = isBukkitConsole ? PluginColor.GRAY.getConsoleColor() : PluginColor.GRAY.getColor();
|
||||
msg.append(text(part4)
|
||||
.color(pluginColor));
|
||||
}
|
||||
return msg.build();
|
||||
return totalStatNameBuilder.build();
|
||||
}
|
||||
|
||||
/** Returns a TextComponent with a single line of hover-text in the specified color.
|
||||
@param plainText the base message
|
||||
@param hoverText the hovering text
|
||||
@param hoverColor color of the hovering text */
|
||||
public TextComponent simpleHoverPart(String plainText, String hoverText, PluginColor hoverColor) {
|
||||
return simpleHoverPart(plainText, null, hoverText, hoverColor);
|
||||
/** Returns a TextComponent for the subStatName, or an empty component.*/
|
||||
private TextComponent subStatNameTextComponent(@Nullable String prettySubStatName, Target selection) {
|
||||
if (prettySubStatName == null) {
|
||||
return Component.empty();
|
||||
} else {
|
||||
return getComponentBuilder(null,
|
||||
getColorFromString(config.getSubStatNameDecoration(selection, false)),
|
||||
getStyleFromString(config.getSubStatNameDecoration(selection, true)))
|
||||
.append(text("("))
|
||||
.append(text(prettySubStatName))
|
||||
.append(text(")"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns a TextComponent with a single line of hover-text in the specified color.
|
||||
If a PluginColor is provided for the plainText, the base color is set as well.
|
||||
@param plainText the base message
|
||||
@param plainColor color of the base message
|
||||
@param hoverText the hovering text
|
||||
@param hoverColor color of the hovering text */
|
||||
public TextComponent simpleHoverPart(String plainText, @Nullable PluginColor plainColor, String hoverText, PluginColor hoverColor) {
|
||||
TextComponent.Builder msg = Component.text()
|
||||
.append(text(plainText))
|
||||
.hoverEvent(HoverEvent.showText(
|
||||
text(hoverText)
|
||||
.color(hoverColor.getColor())));
|
||||
if (plainColor != null) {
|
||||
msg.color(plainColor.getColor());
|
||||
}
|
||||
return msg.build();
|
||||
}
|
||||
/** Returns a TextComponent with TranslatableComponent as a child.*/
|
||||
public TextComponent statNameTransComponent(String statKey, String subStatKey, Target selection) {
|
||||
TextComponent.Builder totalStatNameBuilder = getComponentBuilder(null,
|
||||
getColorFromString(config.getStatNameDecoration(selection, false)),
|
||||
getStyleFromString(config.getStatNameDecoration(selection, true)));
|
||||
|
||||
/** Returns a TextComponent with hover-text that can consist of three different parts,
|
||||
divided over two different lines. Each part has its own designated color. If all the
|
||||
input Strings are null, it will return an empty Component.
|
||||
@param plainText the non-hovering part
|
||||
@param color the color for the non-hovering part
|
||||
@param hoverLineOne text on the first line, with color LIGHT_BLUE
|
||||
@param hoverLineTwoA text on the second line, with color GOLD
|
||||
@param hoverLineTwoB text on the second part of the second line, with color LIGHT_GOLD
|
||||
*/
|
||||
public TextComponent complexHoverPart(@NotNull String plainText, @NotNull PluginColor color, String hoverLineOne, String hoverLineTwoA, String hoverLineTwoB) {
|
||||
TextComponent base = Component.text(plainText).color(color.getColor());
|
||||
TextComponent.Builder hoverText = Component.text();
|
||||
if (hoverLineOne != null) {
|
||||
hoverText.append(text(hoverLineOne)
|
||||
.color(PluginColor.LIGHT_BLUE.getColor()));
|
||||
if (hoverLineTwoA != null || hoverLineTwoB != null) {
|
||||
hoverText.append(newline());
|
||||
}
|
||||
TextComponent subStat = subStatNameTransComponent(subStatKey, selection);
|
||||
if (statKey.equalsIgnoreCase("stat_type.minecraft.killed")) {
|
||||
return totalStatNameBuilder.append(killEntityBuilder(subStat)).build();
|
||||
}
|
||||
if (hoverLineTwoA != null) {
|
||||
hoverText.append(text(hoverLineTwoA)
|
||||
.color(PluginColor.GOLD.getColor()));
|
||||
if (hoverLineTwoB != null) {
|
||||
hoverText.append(space());
|
||||
}
|
||||
}
|
||||
if (hoverLineTwoB != null) {
|
||||
hoverText.append(text(hoverLineTwoB).color(PluginColor.LIGHT_GOLD.getColor()));
|
||||
}
|
||||
return base.hoverEvent(HoverEvent.showText(hoverText.build()));
|
||||
}
|
||||
|
||||
|
||||
public TextComponent playerName(String playerName, Target selection) {
|
||||
return createComponent(playerName,
|
||||
getColorFromString(config.getPlayerNameFormatting(selection, false)),
|
||||
getStyleFromString(config.getPlayerNameFormatting(selection, true)));
|
||||
}
|
||||
|
||||
public TranslatableComponent statName(@NotNull StatRequest request) {
|
||||
String statName = request.getStatistic().name();
|
||||
String subStatName = request.getSubStatEntry();
|
||||
if (!config.useTranslatableComponents()) {
|
||||
statName = getPrettyName(statName);
|
||||
subStatName = getPrettyName(subStatName);
|
||||
else if (statKey.equalsIgnoreCase("stat_type.minecraft.killed_by")) {
|
||||
return totalStatNameBuilder.append(entityKilledByBuilder(subStat)).build();
|
||||
}
|
||||
else {
|
||||
statName = LanguageKeyHandler.getStatKey(request.getStatistic());
|
||||
switch (request.getStatistic().getType()) {
|
||||
case BLOCK -> subStatName = LanguageKeyHandler.getBlockKey(request.getBlock());
|
||||
case ENTITY -> subStatName = LanguageKeyHandler.getEntityKey(request.getEntity());
|
||||
case ITEM -> subStatName = LanguageKeyHandler.getItemKey(request.getItem());
|
||||
case UNTYPED -> {
|
||||
}
|
||||
totalStatNameBuilder.append(translatable().key(statKey));
|
||||
if (!subStat.equals(Component.empty())) {
|
||||
totalStatNameBuilder.append(
|
||||
space().decorations(TextDecoration.NAMES.values(), false)
|
||||
.append(subStat));
|
||||
}
|
||||
return totalStatNameBuilder.build();
|
||||
}
|
||||
return statName(statName, subStatName, request.getSelection());
|
||||
}
|
||||
|
||||
private TranslatableComponent statName(@NotNull String statKey, String subStatKey, @NotNull Target selection) {
|
||||
TranslatableComponent.Builder totalName;
|
||||
TextComponent subStat = subStatName(subStatKey, selection);
|
||||
TextColor statNameColor = getColorFromString(config.getStatNameFormatting(selection, false));
|
||||
TextDecoration statNameStyle = getStyleFromString(config.getStatNameFormatting(selection, true));
|
||||
|
||||
if (statKey.equalsIgnoreCase("stat_type.minecraft.killed") && subStat != null) {
|
||||
totalName = killEntity(subStat);
|
||||
}
|
||||
else if (statKey.equalsIgnoreCase("stat_type.minecraft.killed_by") && subStat != null) {
|
||||
totalName = entityKilledBy(subStat);
|
||||
}
|
||||
else {
|
||||
totalName = translatable().key(statKey);
|
||||
if (subStat != null) totalName.append(space()).append(subStat);
|
||||
}
|
||||
|
||||
if (statNameStyle != null) totalName.decoration(statNameStyle, TextDecoration.State.TRUE);
|
||||
return totalName
|
||||
.color(statNameColor)
|
||||
.build();
|
||||
}
|
||||
|
||||
private @Nullable TextComponent subStatName(@Nullable String subStatName, Target selection) {
|
||||
if (subStatName != null) {
|
||||
TextDecoration style = getStyleFromString(config.getSubStatNameFormatting(selection, true));
|
||||
TextComponent.Builder subStat = text()
|
||||
/** Returns a TranslatableComponent for the subStatName, or an empty component.*/
|
||||
private TextComponent subStatNameTransComponent(String subStatKey, Target selection) {
|
||||
if (subStatKey != null) {
|
||||
return getComponentBuilder(null,
|
||||
getColorFromString(config.getSubStatNameDecoration(selection, false)),
|
||||
getStyleFromString(config.getSubStatNameDecoration(selection, true)))
|
||||
.append(text("("))
|
||||
.append(translatable()
|
||||
.key(subStatName))
|
||||
.key(subStatKey))
|
||||
.append(text(")"))
|
||||
.color(getColorFromString(config.getSubStatNameFormatting(selection, false)));
|
||||
|
||||
subStat.decorations(TextDecoration.NAMES.values(), false);
|
||||
if (style != null) subStat.decoration(style, TextDecoration.State.TRUE);
|
||||
return subStat.build();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
.build();
|
||||
}
|
||||
return Component.empty();
|
||||
}
|
||||
|
||||
/** Construct a custom translation for kill_entity with the language key for commands.kill.success.single ("Killed %s").
|
||||
@return a TranslatableComponent Builder with the subStat Component as args.*/
|
||||
private TranslatableComponent.Builder killEntity(@NotNull TextComponent subStat) {
|
||||
private TranslatableComponent.Builder killEntityBuilder(@NotNull TextComponent subStat) {
|
||||
return translatable()
|
||||
.key("commands.kill.success.single") //"Killed %s"
|
||||
.args(subStat);
|
||||
@ -254,7 +149,7 @@ public class ComponentFactory {
|
||||
("Number of Deaths") and book.byAuthor ("by %s").
|
||||
@return a TranslatableComponent Builder with stat.minecraft.deaths as key, with a ChildComponent
|
||||
with book.byAuthor as key and the subStat Component as args.*/
|
||||
private TranslatableComponent.Builder entityKilledBy(@NotNull TextComponent subStat) {
|
||||
private TranslatableComponent.Builder entityKilledByBuilder(@NotNull TextComponent subStat) {
|
||||
return translatable()
|
||||
.key("stat.minecraft.deaths") //"Number of Deaths"
|
||||
.append(space())
|
||||
@ -263,62 +158,96 @@ public class ComponentFactory {
|
||||
.args(subStat));
|
||||
}
|
||||
|
||||
public TextComponent statNumber(long number, Target selection) {
|
||||
return createComponent(NumberFormatter.format(number),
|
||||
getColorFromString(config.getStatNumberFormatting(selection, false)),
|
||||
getStyleFromString(config.getStatNumberFormatting(selection, true)));
|
||||
//TODO Add hoverComponent with full number
|
||||
public TextComponent.Builder statNumberBuilder(String prettyNumber, Target selection) {
|
||||
return getComponentBuilder(prettyNumber,
|
||||
getColorFromString(config.getStatNumberDecoration(selection, false)),
|
||||
getStyleFromString(config.getStatNumberDecoration(selection, true)));
|
||||
}
|
||||
|
||||
public TextComponent title(String content, Target selection) {
|
||||
return createComponent(content,
|
||||
getColorFromString(config.getTitleFormatting(selection, false)),
|
||||
getStyleFromString(config.getTitleFormatting(selection, true)));
|
||||
public TextComponent statNumberHoverComponent(String mainNumber, String hoverNumber, @Nullable String hoverUnitName, @Nullable String hoverUnitKey, Target selection) {
|
||||
TextColor baseColor = getColorFromString(config.getStatNumberDecoration(selection, false));
|
||||
TextDecoration style = getStyleFromString(config.getStatNumberDecoration(selection, true));
|
||||
|
||||
TextComponent.Builder hoverText = getComponentBuilder(hoverNumber, getLighterColor(baseColor), style);
|
||||
if (hoverUnitKey != null) {
|
||||
hoverText.append(space())
|
||||
.append(translatable().key(hoverUnitKey));
|
||||
}
|
||||
else if (hoverUnitName != null) {
|
||||
hoverText.append(space())
|
||||
.append(text(hoverUnitName));
|
||||
}
|
||||
return getComponent(mainNumber, baseColor, style).hoverEvent(HoverEvent.showText(hoverText));
|
||||
}
|
||||
|
||||
public TextComponent titleNumber(int number) {
|
||||
return createComponent(number + "",
|
||||
getColorFromString(config.getTitleNumberFormatting(false)),
|
||||
getStyleFromString(config.getTitleNumberFormatting(true)));
|
||||
//TODO Make this dark gray (or at least darker than statNumber, and at least for time statistics)
|
||||
public TextComponent statUnitComponent(String unitName, String unitKey, Target selection) {
|
||||
if (!(unitName == null && unitKey == null)) {
|
||||
TextComponent.Builder statUnitBuilder = getComponentBuilder(null,
|
||||
getColorFromString(config.getSubStatNameDecoration(selection, false)),
|
||||
getStyleFromString(config.getSubStatNameDecoration(selection, true)))
|
||||
.append(text("["));
|
||||
if (unitKey != null) {
|
||||
statUnitBuilder.append(translatable()
|
||||
.key(unitKey));
|
||||
} else {
|
||||
statUnitBuilder.append(text(unitName));
|
||||
}
|
||||
return statUnitBuilder.append(text("]")).build();
|
||||
}
|
||||
else {
|
||||
return Component.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public TextComponent serverName(String serverName) {
|
||||
TextComponent colon = text(":").color(getColorFromString(config.getServerNameFormatting(false)));
|
||||
return createComponent(serverName,
|
||||
getColorFromString(config.getServerNameFormatting(false)),
|
||||
getStyleFromString(config.getServerNameFormatting(true)))
|
||||
public TextComponent titleComponent(String content, Target selection) {
|
||||
return getComponent(content,
|
||||
getColorFromString(config.getTitleDecoration(selection, false)),
|
||||
getStyleFromString(config.getTitleDecoration(selection, true)));
|
||||
}
|
||||
|
||||
public TextComponent titleNumberComponent(int number) {
|
||||
return getComponent(number + "",
|
||||
getColorFromString(config.getTitleNumberDecoration(false)),
|
||||
getStyleFromString(config.getTitleNumberDecoration(true)));
|
||||
}
|
||||
|
||||
public TextComponent serverNameComponent(String serverName) {
|
||||
TextComponent colon = text(":").color(getColorFromString(config.getServerNameDecoration(false)));
|
||||
return getComponent(serverName,
|
||||
getColorFromString(config.getServerNameDecoration(false)),
|
||||
getStyleFromString(config.getServerNameDecoration(true)))
|
||||
.append(colon);
|
||||
}
|
||||
|
||||
public TextComponent rankingNumber(String number) {
|
||||
return createComponent(number,
|
||||
getColorFromString(config.getRankNumberFormatting(false)),
|
||||
getStyleFromString(config.getRankNumberFormatting(true)));
|
||||
public TextComponent rankingNumberComponent(String number) {
|
||||
return getComponent(number,
|
||||
getColorFromString(config.getRankNumberDecoration(false)),
|
||||
getStyleFromString(config.getRankNumberDecoration(true)));
|
||||
}
|
||||
|
||||
public TextComponent dots(String dots) {
|
||||
return createComponent(dots,
|
||||
getColorFromString(config.getDotsFormatting(false)),
|
||||
getStyleFromString(config.getDotsFormatting(true)));
|
||||
public TextComponent.Builder dotsBuilder() {
|
||||
return getComponentBuilder(null,
|
||||
getColorFromString(config.getDotsDecoration(false)),
|
||||
getStyleFromString(config.getDotsDecoration(true)));
|
||||
}
|
||||
|
||||
private TextComponent createComponent(String content, TextColor color, @Nullable TextDecoration style) {
|
||||
return style == null ? text(content).color(color) : text(content).color(color).decoration(style, TextDecoration.State.TRUE);
|
||||
private TextComponent getComponent(String content, TextColor color, @Nullable TextDecoration style) {
|
||||
return getComponentBuilder(content, color, style).build();
|
||||
}
|
||||
|
||||
/** Replace "_" with " " and capitalize each first letter of the input.
|
||||
@param input String to prettify, case-insensitive*/
|
||||
private String getPrettyName(String input) {
|
||||
if (input == null) return null;
|
||||
StringBuilder capitals = new StringBuilder(input.toLowerCase());
|
||||
capitals.setCharAt(0, Character.toUpperCase(capitals.charAt(0)));
|
||||
while (capitals.indexOf("_") != -1) {
|
||||
MyLogger.replacingUnderscores();
|
||||
|
||||
int index = capitals.indexOf("_");
|
||||
capitals.setCharAt(index + 1, Character.toUpperCase(capitals.charAt(index + 1)));
|
||||
capitals.setCharAt(index, ' ');
|
||||
private TextComponent.Builder getComponentBuilder(@Nullable String content, TextColor color, @Nullable TextDecoration style) {
|
||||
TextComponent.Builder builder = text()
|
||||
.decorations(TextDecoration.NAMES.values(), false)
|
||||
.color(color);
|
||||
if (content != null) {
|
||||
builder.append(text(content));
|
||||
}
|
||||
return capitals.toString();
|
||||
if (style != null) {
|
||||
builder.decorate(style);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
private TextColor getColorFromString(String configString) {
|
||||
@ -343,6 +272,12 @@ public class ComponentFactory {
|
||||
return names.value(textColor);
|
||||
}
|
||||
|
||||
private TextColor getLighterColor(TextColor color) {
|
||||
HSVLike oldColor = HSVLike.fromRGB(color.red(), color.green(), color.blue());
|
||||
HSVLike newColor = HSVLike.hsvLike(oldColor.h(), 0.45F, oldColor.v());
|
||||
return TextColor.color(newColor);
|
||||
}
|
||||
|
||||
private @Nullable TextDecoration getStyleFromString(@NotNull String configString) {
|
||||
if (configString.equalsIgnoreCase("none")) {
|
||||
return null;
|
||||
@ -355,5 +290,4 @@ public class ComponentFactory {
|
||||
return styles.value(configString);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,13 +1,16 @@
|
||||
package com.gmail.artemis.the.gr8.playerstats.msg;
|
||||
|
||||
import com.gmail.artemis.the.gr8.playerstats.enums.PluginColor;
|
||||
import com.gmail.artemis.the.gr8.playerstats.enums.DebugLevel;
|
||||
import com.gmail.artemis.the.gr8.playerstats.enums.Target;
|
||||
import com.gmail.artemis.the.gr8.playerstats.config.ConfigHandler;
|
||||
import com.gmail.artemis.the.gr8.playerstats.enums.Unit;
|
||||
import com.gmail.artemis.the.gr8.playerstats.msg.msgutils.ExampleMessage;
|
||||
import com.gmail.artemis.the.gr8.playerstats.msg.msgutils.HelpMessage;
|
||||
import com.gmail.artemis.the.gr8.playerstats.msg.msgutils.LanguageKeyHandler;
|
||||
import com.gmail.artemis.the.gr8.playerstats.statistic.StatRequest;
|
||||
import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Statistic;
|
||||
import org.bukkit.map.MinecraftFont;
|
||||
@ -24,9 +27,13 @@ public class MessageWriter {
|
||||
|
||||
private static ConfigHandler config;
|
||||
private static ComponentFactory componentFactory;
|
||||
private final LanguageKeyHandler languageKeyHandler;
|
||||
private final NumberFormatter formatter;
|
||||
|
||||
public MessageWriter(ConfigHandler c) {
|
||||
config = c;
|
||||
formatter = new NumberFormatter();
|
||||
languageKeyHandler = new LanguageKeyHandler();
|
||||
getComponentFactory();
|
||||
}
|
||||
|
||||
@ -44,124 +51,266 @@ public class MessageWriter {
|
||||
}
|
||||
|
||||
public TextComponent reloadedConfig(boolean isBukkitConsole) {
|
||||
return componentFactory.msg(
|
||||
"Config reloaded!", isBukkitConsole);
|
||||
return componentFactory.pluginPrefixComponent(isBukkitConsole)
|
||||
.append(space())
|
||||
.append(componentFactory.messageComponent().content("Config reloaded!"));
|
||||
}
|
||||
|
||||
public TextComponent stillReloading(boolean isBukkitConsole) {
|
||||
return componentFactory.msg(
|
||||
"The plugin is (re)loading, " +
|
||||
"your request will be processed when it is done!", isBukkitConsole);
|
||||
return componentFactory.pluginPrefixComponent(isBukkitConsole)
|
||||
.append(space())
|
||||
.append(componentFactory.messageComponent().content(
|
||||
"The plugin is (re)loading, your request will be processed when it is done!"));
|
||||
}
|
||||
|
||||
public TextComponent waitAMoment(boolean longWait, boolean isBukkitConsole) {
|
||||
String msg = longWait ? "Calculating statistics, this may take a minute..." :
|
||||
"Calculating statistics, this may take a few moments...";
|
||||
return componentFactory.msg(msg, isBukkitConsole);
|
||||
return componentFactory.pluginPrefixComponent(isBukkitConsole)
|
||||
.append(space())
|
||||
.append(componentFactory.messageComponent().content(msg));
|
||||
}
|
||||
|
||||
public TextComponent missingStatName(boolean isBukkitConsole) {
|
||||
return componentFactory.msg(
|
||||
"Please provide a valid statistic name!", isBukkitConsole);
|
||||
return componentFactory.pluginPrefixComponent(isBukkitConsole)
|
||||
.append(space())
|
||||
.append(componentFactory.messageComponent().content(
|
||||
"Please provide a valid statistic name!"));
|
||||
}
|
||||
|
||||
public TextComponent missingSubStatName(Statistic.Type statType, boolean isBukkitConsole) {
|
||||
return componentFactory.msg(
|
||||
"Please add a valid " +
|
||||
getSubStatTypeName(statType) +
|
||||
" to look up this statistic!", isBukkitConsole);
|
||||
return componentFactory.pluginPrefixComponent(isBukkitConsole)
|
||||
.append(space())
|
||||
.append(componentFactory.messageComponent().content(
|
||||
"Please add a valid " + getSubStatTypeName(statType) + " to look up this statistic!"));
|
||||
}
|
||||
|
||||
public TextComponent missingPlayerName(boolean isBukkitConsole) {
|
||||
return componentFactory.msg(
|
||||
"Please specify a valid player-name!", isBukkitConsole);
|
||||
return componentFactory.pluginPrefixComponent(isBukkitConsole)
|
||||
.append(space())
|
||||
.append(componentFactory.messageComponent().content(
|
||||
"Please specify a valid player-name!"));
|
||||
}
|
||||
|
||||
public TextComponent wrongSubStatType(Statistic.Type statType, String subStatEntry, boolean isBukkitConsole) {
|
||||
return componentFactory.msg(
|
||||
"\"" + subStatEntry + "\" is not a valid " + getSubStatTypeName(statType) + "!", isBukkitConsole);
|
||||
return componentFactory.pluginPrefixComponent(isBukkitConsole)
|
||||
.append(space())
|
||||
.append(componentFactory.messageComponent().content(
|
||||
"\"" + subStatEntry + "\" is not a valid " + getSubStatTypeName(statType) + "!"));
|
||||
}
|
||||
|
||||
public TextComponent unknownError(boolean isBukkitConsole) {
|
||||
return componentFactory.msg(
|
||||
return componentFactory.pluginPrefixComponent(isBukkitConsole)
|
||||
.append(space())
|
||||
.append(componentFactory.messageComponent().content(
|
||||
"Something went wrong with your request, " +
|
||||
"please try again or see /statistic for a usage explanation!", isBukkitConsole);
|
||||
"please try again or see /statistic for a usage explanation!"));
|
||||
}
|
||||
|
||||
|
||||
public TextComponent formatPlayerStat(int stat, @NotNull StatRequest request) {
|
||||
if (!request.isValid()) return unknownError(request.isBukkitConsoleSender());
|
||||
return Component.text()
|
||||
.append(componentFactory.playerName( request.getPlayerName() + ": ", Target.PLAYER))
|
||||
.append(componentFactory.statNumber(stat, Target.PLAYER))
|
||||
.append(space())
|
||||
.append(componentFactory.statName(request))
|
||||
.append(componentFactory.playerNameBuilder(request.getPlayerName(), Target.PLAYER)
|
||||
.append(text(":"))
|
||||
.append(space()))
|
||||
.append(getStatNumberComponent(request.getStatistic(), stat, Target.PLAYER))
|
||||
.append(space())
|
||||
.append(getStatNameComponent(request))
|
||||
.append(getStatUnitComponent(request.getStatistic(), request.getSelection()))
|
||||
.build();
|
||||
}
|
||||
|
||||
public TextComponent formatTopStats(@NotNull LinkedHashMap<String, Integer> topStats, @NotNull StatRequest request) {
|
||||
if (!request.isValid()) return unknownError(request.isBukkitConsoleSender());
|
||||
|
||||
TextComponent.Builder topList = Component.text()
|
||||
.append(newline())
|
||||
.append(componentFactory.pluginPrefix(request.isBukkitConsoleSender()))
|
||||
.append(componentFactory.title(config.getTopStatsTitle(), Target.TOP))
|
||||
.append(space())
|
||||
.append(componentFactory.titleNumber(topStats.size()))
|
||||
.append(space())
|
||||
.append(componentFactory.statName(request));
|
||||
.append(componentFactory.pluginPrefixComponent(request.isBukkitConsoleSender())).append(space())
|
||||
.append(componentFactory.titleComponent(config.getTopStatsTitle(), Target.TOP)).append(space())
|
||||
.append(componentFactory.titleNumberComponent(topStats.size())).append(space())
|
||||
.append(getStatNameComponent(request))
|
||||
.append(getStatUnitComponent(request.getStatistic(), request.getSelection()));
|
||||
|
||||
ArrayList<Unit> timeUnits = null;
|
||||
if (Unit.getTypeFromStatistic(request.getStatistic()) == Unit.Type.TIME) {
|
||||
timeUnits = getTimeUnitRange(topStats.values().iterator().next());
|
||||
}
|
||||
boolean useDots = config.useDots();
|
||||
boolean boldNames = config.playerNameIsBold();
|
||||
|
||||
Set<String> playerNames = topStats.keySet();
|
||||
MinecraftFont font = new MinecraftFont();
|
||||
Set<String> playerNames = topStats.keySet();
|
||||
|
||||
int count = 0;
|
||||
for (String playerName : playerNames) {
|
||||
count = count+1;
|
||||
|
||||
TextComponent.Builder playerNameBuilder = componentFactory.playerNameBuilder(playerName, Target.TOP);
|
||||
count++;
|
||||
topList.append(newline())
|
||||
.append(componentFactory.rankingNumber(count + ". "))
|
||||
.append(componentFactory.playerName(playerName, Target.TOP));
|
||||
|
||||
.append(componentFactory.rankingNumberComponent(count + ". "))
|
||||
.append(playerNameBuilder);
|
||||
if (useDots) {
|
||||
topList.append(space());
|
||||
|
||||
int dots = (int) Math.round((130.0 - font.getWidth(count + ". " + playerName))/2);
|
||||
TextComponent.Builder dotsBuilder = componentFactory.dotsBuilder();
|
||||
int dots;
|
||||
if (request.isConsoleSender()) {
|
||||
dots = (int) Math.round((130.0 - font.getWidth(count + ". " + playerName))/6) + 7;
|
||||
}
|
||||
else if (boldNames) {
|
||||
} else if (!boldNames) {
|
||||
dots = (int) Math.round((130.0 - font.getWidth(count + ". " + playerName))/2);
|
||||
} else {
|
||||
dots = (int) Math.round((130.0 - font.getWidth(count + ". ") - (font.getWidth(playerName) * 1.19))/2);
|
||||
}
|
||||
if (dots >= 1) {
|
||||
topList.append(componentFactory.dots(".".repeat(dots)));
|
||||
topList.append(dotsBuilder.append(text((".".repeat(dots)))));
|
||||
}
|
||||
} else {
|
||||
topList.append(playerNameBuilder.append(text(":")));
|
||||
}
|
||||
else {
|
||||
topList.append(componentFactory.playerName(":", Target.TOP));
|
||||
if (timeUnits != null) {
|
||||
topList.append(space()).append(getTimeNumberComponent(topStats.get(playerName), request.getSelection(), timeUnits));
|
||||
} else {
|
||||
topList.append(space()).append(getStatNumberComponent(request.getStatistic(), topStats.get(playerName), Target.TOP));
|
||||
}
|
||||
topList.append(space()).append(componentFactory.statNumber(topStats.get(playerName), Target.TOP));
|
||||
}
|
||||
return topList.build();
|
||||
}
|
||||
|
||||
public TextComponent formatServerStat(long stat, @NotNull StatRequest request) {
|
||||
if (!request.isValid()) return unknownError(request.isBukkitConsoleSender());
|
||||
return Component.text()
|
||||
.append(componentFactory.title(config.getServerTitle(), Target.SERVER))
|
||||
.append(componentFactory.titleComponent(config.getServerTitle(), Target.SERVER))
|
||||
.append(space())
|
||||
.append(componentFactory.serverName(config.getServerName()))
|
||||
.append(componentFactory.serverNameComponent(config.getServerName()))
|
||||
.append(space())
|
||||
.append(componentFactory.statNumber(stat, Target.SERVER))
|
||||
.append(space())
|
||||
.append(componentFactory.statName(request))
|
||||
.append(getStatNumberComponent(request.getStatistic(), stat, Target.SERVER))
|
||||
.append(space())
|
||||
.append(getStatNameComponent(request))
|
||||
.append(getStatUnitComponent(request.getStatistic(), request.getSelection())) //space is provided by statUnit
|
||||
.build();
|
||||
}
|
||||
|
||||
/** Depending on the config settings, return either a TranslatableComponent representing
|
||||
the statName (and potential subStatName), or a TextComponent with capitalized English names.*/
|
||||
private TextComponent getStatNameComponent(StatRequest request) {
|
||||
if (config.useTranslatableComponents()) {
|
||||
String statKey = languageKeyHandler.getStatKey(request.getStatistic());
|
||||
String subStatKey = request.getSubStatEntry();
|
||||
if (subStatKey != null) {
|
||||
switch (request.getStatistic().getType()) {
|
||||
case BLOCK -> subStatKey = languageKeyHandler.getBlockKey(request.getBlock());
|
||||
case ENTITY -> subStatKey = languageKeyHandler.getEntityKey(request.getEntity());
|
||||
case ITEM -> subStatKey = languageKeyHandler.getItemKey(request.getItem());
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
return componentFactory.statNameTransComponent(statKey, subStatKey, request.getSelection());
|
||||
}
|
||||
else {
|
||||
return componentFactory.statNameTextComponent(
|
||||
getPrettyName(request.getStatistic().toString()),
|
||||
getPrettyName(request.getSubStatEntry()),
|
||||
request.getSelection());
|
||||
}
|
||||
}
|
||||
|
||||
private TextComponent getStatNumberComponent(Statistic statistic, long statNumber, Target selection) {
|
||||
Unit.Type type = Unit.getTypeFromStatistic(statistic);
|
||||
Unit statUnit;
|
||||
switch (type) {
|
||||
case DISTANCE -> statUnit = Unit.fromString(config.getDistanceUnit(false));
|
||||
case DAMAGE -> statUnit = Unit.fromString(config.getDamageUnit(false));
|
||||
case TIME -> {
|
||||
return getTimeNumberComponent(statNumber, selection, getTimeUnitRange(statNumber));
|
||||
}
|
||||
default -> statUnit = Unit.NUMBER;
|
||||
}
|
||||
String prettyNumber = formatter.format(statNumber, statUnit);
|
||||
if (!config.useHoverText() || statUnit == Unit.NUMBER) {
|
||||
return componentFactory.statNumberBuilder(prettyNumber, selection).build();
|
||||
}
|
||||
Unit hoverUnit = type == Unit.Type.DISTANCE ? Unit.fromString(config.getDistanceUnit(true)) :
|
||||
Unit.fromString(config.getDamageUnit(true));
|
||||
String prettyHoverNumber = formatter.format(statNumber, hoverUnit);
|
||||
MyLogger.logMsg("mainNumber: " + prettyNumber + "\n" + "hoverNumber: " + prettyHoverNumber, DebugLevel.HIGH);
|
||||
if (config.useTranslatableComponents()) {
|
||||
String unitKey = languageKeyHandler.getUnitKey(hoverUnit);
|
||||
if (unitKey == null) {
|
||||
unitKey = hoverUnit.getLabel();
|
||||
}
|
||||
return componentFactory.statNumberHoverComponent(prettyNumber, prettyHoverNumber, null, unitKey, selection);
|
||||
}
|
||||
else {
|
||||
return componentFactory.statNumberHoverComponent(prettyNumber, prettyHoverNumber, hoverUnit.getLabel(), null, selection);
|
||||
}
|
||||
}
|
||||
|
||||
private TextComponent getTimeNumberComponent(long statNumber, Target selection, ArrayList<Unit> unitRange) {
|
||||
if (unitRange.size() <= 1 || (config.useHoverText() && unitRange.size() <= 3)) {
|
||||
MyLogger.logMsg(
|
||||
"There is something wrong with the time-units you specified, please check your config!",
|
||||
true);
|
||||
return componentFactory.statNumberBuilder("-", selection).build();
|
||||
}
|
||||
else {
|
||||
String mainNumber = formatter.format(statNumber, unitRange.get(0), unitRange.get(1));
|
||||
if (!config.useHoverText()) {
|
||||
return componentFactory.statNumberBuilder(mainNumber, selection).build();
|
||||
} else {
|
||||
String hoverNumber = formatter.format(statNumber, unitRange.get(2), unitRange.get(3));
|
||||
MyLogger.logMsg("mainNumber: " + mainNumber + ", hoverNumber: " + hoverNumber, DebugLevel.HIGH);
|
||||
return componentFactory.statNumberHoverComponent(mainNumber, hoverNumber,
|
||||
null, null, selection); //Time does not support translatable text,
|
||||
} //because the unit and number are so tightly interwoven.
|
||||
}
|
||||
}
|
||||
|
||||
/** Get an ArrayList consisting of 2 or 4 timeUnits. The order of items is:
|
||||
<p>0. maxUnit</p>
|
||||
<p>1. minUnit</p>
|
||||
<p>2. maxHoverUnit</p>
|
||||
<p>3. minHoverUnit</p>*/
|
||||
private ArrayList<Unit> getTimeUnitRange(long statNumber) {
|
||||
ArrayList<Unit> unitRange = new ArrayList<>();
|
||||
if (!config.autoDetectTimeUnit(false)) {
|
||||
unitRange.add(Unit.fromString(config.getTimeUnit(false)));
|
||||
unitRange.add(Unit.fromString(config.getTimeUnit(false, true)));
|
||||
}
|
||||
else {
|
||||
Unit bigUnit = Unit.getMostSuitableUnit(Unit.Type.TIME, statNumber);
|
||||
unitRange.add(bigUnit);
|
||||
unitRange.add(bigUnit.getSmallerUnit(config.getNumberOfExtraTimeUnits(false)));
|
||||
}
|
||||
if (config.useHoverText()) {
|
||||
if (!config.autoDetectTimeUnit(true)) {
|
||||
unitRange.add(Unit.fromString(config.getTimeUnit(true)));
|
||||
unitRange.add(Unit.fromString(config.getTimeUnit(true, true)));
|
||||
}
|
||||
else {
|
||||
Unit bigHoverUnit = Unit.getMostSuitableUnit(Unit.Type.TIME, statNumber);
|
||||
unitRange.add(bigHoverUnit);
|
||||
unitRange.add(bigHoverUnit.getSmallerUnit(config.getNumberOfExtraTimeUnits(true)));
|
||||
}
|
||||
}
|
||||
MyLogger.logMsg("total selected unitRange for this statistic: " + unitRange, DebugLevel.MEDIUM);
|
||||
return unitRange;
|
||||
}
|
||||
|
||||
private TextComponent getStatUnitComponent(Statistic statistic, Target selection) {
|
||||
Unit statUnit;
|
||||
switch (Unit.getTypeFromStatistic(statistic)) {
|
||||
case DAMAGE -> statUnit = Unit.fromString(config.getDamageUnit(false));
|
||||
case DISTANCE -> statUnit = Unit.fromString(config.getDistanceUnit(false));
|
||||
default -> {
|
||||
return Component.empty();
|
||||
}
|
||||
}
|
||||
if (config.useTranslatableComponents()) {
|
||||
String unitKey = languageKeyHandler.getUnitKey(statUnit);
|
||||
if (unitKey != null) {
|
||||
return Component.space()
|
||||
.append(componentFactory.statUnitComponent(null, unitKey, selection));
|
||||
}
|
||||
}
|
||||
return Component.space()
|
||||
.append(componentFactory.statUnitComponent(statUnit.getLabel(), null, selection));
|
||||
}
|
||||
|
||||
/** Returns "block", "entity", "item", or "sub-statistic" if the provided Type is null. */
|
||||
private String getSubStatTypeName(Statistic.Type statType) {
|
||||
String subStat = "sub-statistic";
|
||||
@ -174,120 +323,30 @@ public class MessageWriter {
|
||||
return subStat;
|
||||
}
|
||||
|
||||
public TextComponent usageExamples(boolean isBukkitConsole) {
|
||||
TextColor mainColor = isBukkitConsole ? PluginColor.GOLD.getConsoleColor() : PluginColor.GOLD.getColor();
|
||||
TextColor accentColor1 = isBukkitConsole ? PluginColor.MEDIUM_GOLD.getConsoleColor() : PluginColor.MEDIUM_GOLD.getColor();
|
||||
TextColor accentColor3 = isBukkitConsole ? PluginColor.LIGHT_YELLOW.getConsoleColor() : PluginColor.LIGHT_YELLOW.getColor();
|
||||
String arrow = isBukkitConsole ? " -> " : " → "; //4 spaces, alt + 26, 1 space
|
||||
/** Replace "_" with " " and capitalize each first letter of the input.
|
||||
@param input String to prettify, case-insensitive*/
|
||||
private String getPrettyName(String input) {
|
||||
if (input == null) return null;
|
||||
StringBuilder capitals = new StringBuilder(input.toLowerCase());
|
||||
capitals.setCharAt(0, Character.toUpperCase(capitals.charAt(0)));
|
||||
while (capitals.indexOf("_") != -1) {
|
||||
MyLogger.replacingUnderscores();
|
||||
|
||||
return Component.newline()
|
||||
.append(componentFactory.prefixTitle(isBukkitConsole))
|
||||
.append(newline())
|
||||
.append(text("Examples: ").color(mainColor))
|
||||
.append(newline())
|
||||
.append(text(arrow).color(mainColor)
|
||||
.append(text("/statistic ")
|
||||
.append(text("animals_bred ").color(accentColor1)
|
||||
.append(text("top").color(accentColor3)))))
|
||||
.append(newline())
|
||||
.append(text(arrow).color(mainColor)
|
||||
.append(text("/statistic ")
|
||||
.append(text("mine_block diorite ").color(accentColor1)
|
||||
.append(text("me").color(accentColor3)))))
|
||||
.append(newline())
|
||||
.append(text(arrow).color(mainColor)
|
||||
.append(text("/statistic ")
|
||||
.append(text("deaths ").color(accentColor1)
|
||||
.append(text("player ").color(accentColor3)
|
||||
.append(text("Artemis_the_gr8"))))));
|
||||
int index = capitals.indexOf("_");
|
||||
capitals.setCharAt(index + 1, Character.toUpperCase(capitals.charAt(index + 1)));
|
||||
capitals.setCharAt(index, ' ');
|
||||
}
|
||||
return capitals.toString();
|
||||
}
|
||||
|
||||
public TextComponent usageExamples(boolean isBukkitConsole) {
|
||||
return new ExampleMessage(componentFactory, isBukkitConsole);
|
||||
}
|
||||
|
||||
public TextComponent helpMsg(boolean isConsoleSender) {
|
||||
if (isConsoleSender || !config.useHoverText()) {
|
||||
return helpMsgPlain(isConsoleSender && Bukkit.getName().equalsIgnoreCase("CraftBukkit"));
|
||||
}
|
||||
else {
|
||||
return helpMsgHover();
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the usage-explanation with hovering text */
|
||||
private TextComponent helpMsgHover() {
|
||||
String arrow = " →"; //4 spaces, alt + 26
|
||||
return Component.newline()
|
||||
.append(componentFactory.prefixTitle(false))
|
||||
.append(newline())
|
||||
.append(componentFactory.subTitle("Hover over the arguments for more information!"))
|
||||
.append(newline())
|
||||
.append(componentFactory.msgPart("Usage:", null, "/statistic", null))
|
||||
.append(newline())
|
||||
.append(componentFactory.msgPart(arrow, null, null, null)
|
||||
.append(componentFactory.complexHoverPart("name", PluginColor.LIGHT_GOLD,
|
||||
"The name that describes the statistic",
|
||||
"Example:",
|
||||
"\"animals_bred\"")))
|
||||
.append(newline())
|
||||
.append(componentFactory.msgPart(arrow, null, null, null)
|
||||
.append(componentFactory.complexHoverPart("sub-statistic", PluginColor.LIGHT_GOLD,
|
||||
"Some statistics need an item, block or entity as extra input",
|
||||
"Example:",
|
||||
"\"mine_block diorite\"")))
|
||||
.append(newline())
|
||||
.append(text(" ").color(PluginColor.LIGHT_GOLD.getColor())
|
||||
.append(componentFactory.simpleHoverPart(
|
||||
"→", PluginColor.GOLD,
|
||||
"Choose one", PluginColor.DARK_PURPLE))
|
||||
.append(space())
|
||||
.append(componentFactory.simpleHoverPart(
|
||||
"me",
|
||||
"See your own statistic", PluginColor.LIGHT_BLUE))
|
||||
.append(text(" | "))
|
||||
.append(componentFactory.simpleHoverPart(
|
||||
"player",
|
||||
"Choose any player that has played on your server", PluginColor.LIGHT_BLUE))
|
||||
.append(text(" | "))
|
||||
.append(componentFactory.simpleHoverPart(
|
||||
"server",
|
||||
"See the combined total for everyone on your server", PluginColor.LIGHT_BLUE))
|
||||
.append(text(" | "))
|
||||
.append(componentFactory.simpleHoverPart(
|
||||
"top",
|
||||
"See the top " + config.getTopListMaxSize(), PluginColor.LIGHT_BLUE)))
|
||||
.append(newline())
|
||||
.append(componentFactory.msgPart(arrow, null, null, null)
|
||||
.append(text("player-name").color(PluginColor.LIGHT_GOLD.getColor())
|
||||
.hoverEvent(HoverEvent.showText(
|
||||
text("In case you typed ").color(PluginColor.LIGHT_BLUE.getColor())
|
||||
.append(text("\"player\"").color(PluginColor.MEDIUM_GOLD.getColor()))
|
||||
.append(text(", add the player's name"))))));
|
||||
}
|
||||
|
||||
/** Returns the usage-explanation without any hovering text.
|
||||
If BukkitVersion is CraftBukkit, this doesn't use unicode symbols or hex colors */
|
||||
private TextComponent helpMsgPlain(boolean isBukkitConsole) {
|
||||
String arrow = isBukkitConsole ? " ->" : " →"; //4 spaces, alt + 26
|
||||
String bullet = isBukkitConsole ? " *" : " •"; //8 spaces, alt + 7
|
||||
return Component.newline()
|
||||
.append(componentFactory.prefixTitle(isBukkitConsole))
|
||||
.append(newline())
|
||||
.append(componentFactory.subTitle("Type \"statistic examples\" to see examples!"))
|
||||
.append(newline())
|
||||
.append(componentFactory.msgPart("Usage:", null, "/statistic", null, isBukkitConsole))
|
||||
.append(newline())
|
||||
.append(componentFactory.msgPart(arrow, null, "name", null, isBukkitConsole))
|
||||
.append(newline())
|
||||
.append(componentFactory.msgPart(arrow, null, "{sub-statistic}", "(a block, item or entity)", isBukkitConsole))
|
||||
.append(newline())
|
||||
.append(componentFactory.msgPart(arrow, null, "me | player | server | top", null, isBukkitConsole))
|
||||
.append(newline())
|
||||
.append(componentFactory.msgPart(bullet, "me:", null, "your own statistic", isBukkitConsole))
|
||||
.append(newline())
|
||||
.append(componentFactory.msgPart(bullet, "player:", null, "choose a player", isBukkitConsole))
|
||||
.append(newline())
|
||||
.append(componentFactory.msgPart(bullet, "server:", null, "everyone on the server combined", isBukkitConsole))
|
||||
.append(newline())
|
||||
.append(componentFactory.msgPart(bullet, "top:", null, "the top " + config.getTopListMaxSize(), isBukkitConsole))
|
||||
.append(newline())
|
||||
.append(componentFactory.msgPart(arrow, null, "{player-name}", null, isBukkitConsole));
|
||||
return new HelpMessage(componentFactory,
|
||||
config.useHoverText() && !isConsoleSender,
|
||||
isConsoleSender && Bukkit.getName().equalsIgnoreCase("CraftBukkit"),
|
||||
config.getTopListMaxSize());
|
||||
}
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
package com.gmail.artemis.the.gr8.playerstats.msg;
|
||||
|
||||
import com.gmail.artemis.the.gr8.playerstats.enums.Unit;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
public class NumberFormatter {
|
||||
|
||||
private final DecimalFormat format;
|
||||
|
||||
public NumberFormatter() {
|
||||
format = new DecimalFormat();
|
||||
format.setGroupingUsed(true);
|
||||
format.setGroupingSize(3);
|
||||
}
|
||||
|
||||
/** Turns the input number into a more readable format depending on its type
|
||||
(number-of-times, time-, damage- or distance-based) according to the
|
||||
corresponding config settings, and adds commas in groups of 3.*/
|
||||
public String format(long number, Unit statUnit) {
|
||||
return format(number, statUnit, null);
|
||||
}
|
||||
|
||||
public String format(long number, Unit statUnit, Unit smallTimeUnit) {
|
||||
if (smallTimeUnit == null) {
|
||||
switch (statUnit.getType()) {
|
||||
case DISTANCE -> {
|
||||
return formatDistance(number, statUnit);
|
||||
}
|
||||
case DAMAGE -> {
|
||||
return formatDamage(number, statUnit);
|
||||
}
|
||||
default -> {
|
||||
return format.format(number);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return formatTime(number, statUnit, smallTimeUnit);
|
||||
}
|
||||
}
|
||||
|
||||
/** The unit of damage-based statistics is half a heart by default.
|
||||
This method turns the number into hearts. */
|
||||
private String formatDamage(long number, Unit statUnit) { //7 statistics
|
||||
if (statUnit == Unit.HEART) {
|
||||
return format.format(Math.round(number / 2.0));
|
||||
} else {
|
||||
return format.format(number);
|
||||
}
|
||||
}
|
||||
|
||||
/** The unit of distance-based statistics is cm by default. This method turns it into blocks by default,
|
||||
and turns it into km or leaves it as cm otherwise, depending on the config settings. */
|
||||
private String formatDistance(long number, Unit statUnit) { //15 statistics
|
||||
switch (statUnit) {
|
||||
case CM -> {
|
||||
return format.format(number);
|
||||
}
|
||||
case MILE -> {
|
||||
return format.format(Math.round(number / 160934.4)); //to get from CM to Miles
|
||||
}
|
||||
case KM -> {
|
||||
return format.format(Math.round(number / 100000.0)); //divide by 100 to get M, divide by 1000 to get KM
|
||||
}
|
||||
default -> {
|
||||
return format.format(Math.round(number / 100.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** The unit of time-based statistics is ticks by default.*/
|
||||
private String formatTime(long number, Unit bigUnit, Unit smallUnit) { //5 statistics
|
||||
if (number == 0) {
|
||||
return "-";
|
||||
}
|
||||
if (bigUnit == Unit.TICK && smallUnit == Unit.TICK || bigUnit == Unit.NUMBER || smallUnit == Unit.NUMBER) {
|
||||
return format.format(number);
|
||||
}
|
||||
|
||||
StringBuilder output = new StringBuilder();
|
||||
double max = bigUnit.getSeconds();
|
||||
double min = smallUnit.getSeconds();
|
||||
double leftover = number / 20.0;
|
||||
|
||||
if (isInRange(max, min, 86400) && leftover >= 86400) {
|
||||
double days = leftover / 60 / 60 / 24;
|
||||
leftover = leftover % (60 * 60 * 24);
|
||||
if (smallUnit == Unit.DAY && leftover >= 43200) {
|
||||
days++;
|
||||
return output.append(format.format(Math.round(days)))
|
||||
.append("d").toString();
|
||||
}
|
||||
output.append(format.format(Math.round(days)))
|
||||
.append("d ");
|
||||
}
|
||||
if (isInRange(max, min, 3600) && leftover >= 3600) {
|
||||
double hours = leftover / 60 / 60;
|
||||
leftover = leftover % (60 * 60);
|
||||
if (smallUnit == Unit.HOUR && leftover >= 1800) {
|
||||
hours++;
|
||||
return output.append(format.format(Math.round(hours)))
|
||||
.append("h").toString();
|
||||
}
|
||||
output.append(format.format(Math.round(hours)))
|
||||
.append("h ");
|
||||
}
|
||||
if (isInRange(max, min, 60) && leftover >= 60) {
|
||||
double minutes = leftover / 60;
|
||||
leftover = leftover % 60;
|
||||
if (smallUnit == Unit.MINUTE && leftover >= 30) {
|
||||
minutes++;
|
||||
return output.append(format.format(Math.round(minutes)))
|
||||
.append("m").toString();
|
||||
}
|
||||
output.append(format.format(Math.round(minutes)))
|
||||
.append("m ");
|
||||
}
|
||||
if (isInRange(max, min, 1) && leftover > 0) {
|
||||
output.append(format.format(Math.round(leftover)))
|
||||
.append("s");
|
||||
}
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
private boolean isInRange(double bigUnit, double smallUnit, double unitToEvaluate) {
|
||||
return bigUnit >= unitToEvaluate && unitToEvaluate >= smallUnit;
|
||||
}
|
||||
}
|
@ -22,9 +22,9 @@ public class PrideComponentFactory extends ComponentFactory {
|
||||
|
||||
|
||||
@Override
|
||||
public TextComponent prefixTitle(boolean isBukkitConsole) {
|
||||
public TextComponent prefixTitleComponent(boolean isBukkitConsole) {
|
||||
if (cancelRainbow(isBukkitConsole)) {
|
||||
return super.prefixTitle(isBukkitConsole);
|
||||
return super.prefixTitleComponent(isBukkitConsole);
|
||||
}
|
||||
else {
|
||||
String title = "<rainbow:16>____________ [PlayerStats] ____________</rainbow>"; //12 underscores
|
||||
@ -35,9 +35,9 @@ public class PrideComponentFactory extends ComponentFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextComponent pluginPrefix(boolean isConsoleSender) {
|
||||
public TextComponent pluginPrefixComponent(boolean isConsoleSender) {
|
||||
if (cancelRainbow(isConsoleSender)) {
|
||||
return super.pluginPrefix(isConsoleSender);
|
||||
return super.pluginPrefixComponent(isConsoleSender);
|
||||
}
|
||||
return text()
|
||||
.append(MiniMessage.miniMessage()
|
||||
@ -53,7 +53,7 @@ public class PrideComponentFactory extends ComponentFactory {
|
||||
"<#01c1a7>a</#01c1a7>" +
|
||||
"<#0690d4>t</#0690d4>" +
|
||||
"<#205bf3>s</#205bf3>" +
|
||||
"<#6c15fa>] </#6c15fa>"))
|
||||
"<#6c15fa>]</#6c15fa>"))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,89 @@
|
||||
package com.gmail.artemis.the.gr8.playerstats.msg.msgutils;
|
||||
|
||||
import com.gmail.artemis.the.gr8.playerstats.enums.PluginColor;
|
||||
import com.gmail.artemis.the.gr8.playerstats.msg.ComponentFactory;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.ComponentLike;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static net.kyori.adventure.text.Component.text;
|
||||
|
||||
public class ExampleMessage implements TextComponent {
|
||||
|
||||
private final TextComponent exampleMessage;
|
||||
private final ComponentFactory componentFactory;
|
||||
|
||||
public ExampleMessage(ComponentFactory componentFactory, boolean isBukkitConsole) {
|
||||
this.componentFactory = componentFactory;
|
||||
exampleMessage = getExampleMessage(isBukkitConsole);
|
||||
}
|
||||
|
||||
public TextComponent getExampleMessage(boolean isBukkitConsole) {
|
||||
TextColor mainColor = isBukkitConsole ? PluginColor.GOLD.getConsoleColor() : PluginColor.GOLD.getColor();
|
||||
TextColor accentColor1 = isBukkitConsole ? PluginColor.MEDIUM_GOLD.getConsoleColor() : PluginColor.MEDIUM_GOLD.getColor();
|
||||
TextColor accentColor3 = isBukkitConsole ? PluginColor.LIGHT_YELLOW.getConsoleColor() : PluginColor.LIGHT_YELLOW.getColor();
|
||||
String arrow = isBukkitConsole ? " -> " : " → "; //4 spaces, alt + 26, 1 space
|
||||
|
||||
return Component.newline()
|
||||
.append(componentFactory.prefixTitleComponent(isBukkitConsole))
|
||||
.append(Component.newline())
|
||||
.append(text("Examples: ").color(mainColor))
|
||||
.append(Component.newline())
|
||||
.append(text(arrow).color(mainColor)
|
||||
.append(text("/statistic ")
|
||||
.append(text("animals_bred ").color(accentColor1)
|
||||
.append(text("top").color(accentColor3)))))
|
||||
.append(Component.newline())
|
||||
.append(text(arrow).color(mainColor)
|
||||
.append(text("/statistic ")
|
||||
.append(text("mine_block diorite ").color(accentColor1)
|
||||
.append(text("me").color(accentColor3)))))
|
||||
.append(Component.newline())
|
||||
.append(text(arrow).color(mainColor)
|
||||
.append(text("/statistic ")
|
||||
.append(text("deaths ").color(accentColor1)
|
||||
.append(text("player ").color(accentColor3)
|
||||
.append(text("Artemis_the_gr8"))))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String content() {
|
||||
return exampleMessage.content();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TextComponent content(@NotNull String content) {
|
||||
return exampleMessage.content(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TextComponent.Builder toBuilder() {
|
||||
return exampleMessage.toBuilder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Unmodifiable @NotNull List<Component> children() {
|
||||
return exampleMessage.children();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TextComponent children(@NotNull List<? extends ComponentLike> children) {
|
||||
return exampleMessage.children(children);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Style style() {
|
||||
return exampleMessage.style();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TextComponent style(@NotNull Style style) {
|
||||
return exampleMessage.style(style);
|
||||
}
|
||||
}
|
@ -0,0 +1,205 @@
|
||||
package com.gmail.artemis.the.gr8.playerstats.msg.msgutils;
|
||||
|
||||
import com.gmail.artemis.the.gr8.playerstats.enums.PluginColor;
|
||||
import com.gmail.artemis.the.gr8.playerstats.msg.ComponentFactory;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.ComponentLike;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static net.kyori.adventure.text.Component.text;
|
||||
|
||||
public class HelpMessage implements TextComponent {
|
||||
|
||||
private final ComponentFactory componentFactory;
|
||||
private final TextComponent helpMessage;
|
||||
boolean isBukkitConsole;
|
||||
TextColor GRAY;
|
||||
TextColor DARK_PURPLE;
|
||||
TextColor GOLD;
|
||||
TextColor MEDIUM_GOLD;
|
||||
TextColor LIGHT_GOLD;
|
||||
TextColor LIGHT_BLUE;
|
||||
|
||||
|
||||
public HelpMessage(ComponentFactory componentFactory, boolean useHover, boolean isBukkitConsole, int listSize) {
|
||||
this.componentFactory = componentFactory;
|
||||
this.isBukkitConsole = isBukkitConsole;
|
||||
getPluginColors(isBukkitConsole);
|
||||
|
||||
if (!useHover || isBukkitConsole) {
|
||||
helpMessage = getPlainHelpMsg(isBukkitConsole, listSize);
|
||||
} else {
|
||||
helpMessage = helpMsgHover(listSize);
|
||||
}
|
||||
}
|
||||
|
||||
private TextComponent getPlainHelpMsg(boolean isBukkitConsole, int listSize) {
|
||||
String arrowSymbol = isBukkitConsole ? "->" : "→"; //alt + 26
|
||||
String bulletSymbol = isBukkitConsole ? "*" : "•"; //alt + 7
|
||||
TextComponent spaces = text(" "); //4 spaces
|
||||
TextComponent arrow = text(arrowSymbol).color(NamedTextColor.GOLD);
|
||||
TextComponent bullet = text(bulletSymbol).color(NamedTextColor.GOLD);
|
||||
|
||||
return Component.newline()
|
||||
.append(componentFactory.prefixTitleComponent(isBukkitConsole))
|
||||
.append(newline())
|
||||
.append(text("Type \"/statistic examples\" to see examples!").color(GRAY).decorate(TextDecoration.ITALIC))
|
||||
.append(newline())
|
||||
.append(text("Usage:").color(GOLD)).append(space())
|
||||
.append(text("/statistic").color(LIGHT_GOLD))
|
||||
.append(newline())
|
||||
.append(spaces).append(arrow).append(space())
|
||||
.append(text("name").color(LIGHT_GOLD))
|
||||
.append(newline())
|
||||
.append(spaces).append(arrow).append(space())
|
||||
.append(text("{sub-statistic}").color(LIGHT_GOLD)).append(space())
|
||||
.append(text("(a block, item or entity)").color(GRAY))
|
||||
.append(newline())
|
||||
.append(spaces).append(arrow).append(space())
|
||||
.append(text("me | player | server | top").color(LIGHT_GOLD))
|
||||
.append(newline())
|
||||
.append(spaces).append(spaces).append(bullet).append(space())
|
||||
.append(text("me:").color(MEDIUM_GOLD)).append(space())
|
||||
.append(text("your own statistic").color(GRAY))
|
||||
.append(newline())
|
||||
.append(spaces).append(spaces).append(bullet).append(space())
|
||||
.append(text("player:").color(MEDIUM_GOLD)).append(space())
|
||||
.append(text("choose a player").color(GRAY))
|
||||
.append(newline())
|
||||
.append(spaces).append(spaces).append(bullet).append(space())
|
||||
.append(text("server:").color(MEDIUM_GOLD)).append(space())
|
||||
.append(text("everyone on the server combined").color(GRAY))
|
||||
.append(newline())
|
||||
.append(spaces).append(spaces).append(bullet).append(space())
|
||||
.append(text("top:").color(MEDIUM_GOLD)).append(space())
|
||||
.append(text("the top").color(GRAY).append(space()).append(text(listSize)))
|
||||
.append(newline())
|
||||
.append(spaces).append(arrow).append(space())
|
||||
.append(text("{player-name}").color(LIGHT_GOLD));
|
||||
}
|
||||
|
||||
private TextComponent helpMsgHover(int listSize) {
|
||||
TextComponent spaces = text(" ");
|
||||
TextComponent arrow = text("→").color(GOLD);
|
||||
|
||||
return Component.newline()
|
||||
.append(componentFactory.prefixTitleComponent(false))
|
||||
.append(newline())
|
||||
.append(componentFactory.subTitleComponent("Hover over the arguments for more information!"))
|
||||
.append(newline())
|
||||
.append(text("Usage:").color(GOLD)).append(space())
|
||||
.append(text("/statistic").color(LIGHT_GOLD))
|
||||
.append(newline())
|
||||
.append(spaces).append(arrow).append(space())
|
||||
.append(text("name").color(LIGHT_GOLD)
|
||||
.hoverEvent(HoverEvent.showText(text("The name that describes the statistic").color(LIGHT_BLUE)
|
||||
.append(newline())
|
||||
.append(text("Example: ").color(GOLD))
|
||||
.append(text("\"animals_bred\"").color(LIGHT_GOLD)))))
|
||||
.append(newline())
|
||||
.append(spaces).append(arrow).append(space())
|
||||
.append(text("sub-statistic").color(LIGHT_GOLD)
|
||||
.hoverEvent(HoverEvent.showText(
|
||||
text("Some statistics need an item, block or entity as extra input").color(LIGHT_BLUE)
|
||||
.append(newline())
|
||||
.append(text("Example: ").color(GOLD)
|
||||
.append(text("\"mine_block diorite\"").color(LIGHT_GOLD))))))
|
||||
.append(newline())
|
||||
.append(spaces).append(arrow
|
||||
.hoverEvent(HoverEvent.showText(
|
||||
text("Choose one").color(DARK_PURPLE)))).append(space())
|
||||
.append(text("me").color(LIGHT_GOLD)
|
||||
.hoverEvent(HoverEvent.showText(
|
||||
text("See your own statistic").color(LIGHT_BLUE))))
|
||||
.append(text(" | ").color(LIGHT_GOLD))
|
||||
.append(text("player").color(LIGHT_GOLD)
|
||||
.hoverEvent(HoverEvent.showText(
|
||||
text("Choose any player that has played on your server").color(LIGHT_BLUE))))
|
||||
.append(text(" | ").color(LIGHT_GOLD))
|
||||
.append(text("server").color(LIGHT_GOLD)
|
||||
.hoverEvent(HoverEvent.showText(
|
||||
text("See the combined total for everyone on your server").color(LIGHT_BLUE))))
|
||||
.append(text(" | ").color(LIGHT_GOLD))
|
||||
.append(text("top").color(LIGHT_GOLD)
|
||||
.hoverEvent(HoverEvent.showText(
|
||||
text("See the top").color(LIGHT_BLUE).append(space())
|
||||
.append(text(listSize)))))
|
||||
.append(newline())
|
||||
.append(spaces).append(arrow).append(space())
|
||||
.append(text("player-name").color(LIGHT_GOLD)
|
||||
.hoverEvent(HoverEvent.showText(
|
||||
text("In case you typed").color(LIGHT_BLUE).append(space())
|
||||
.append(text("\"player\"").color(LIGHT_GOLD))
|
||||
.append(text(", add the player's name")))));
|
||||
}
|
||||
|
||||
private void getPluginColors(boolean isBukkitConsole) {
|
||||
if (isBukkitConsole) {
|
||||
GRAY = PluginColor.GRAY.getConsoleColor();
|
||||
DARK_PURPLE = PluginColor.DARK_PURPLE.getConsoleColor();
|
||||
GOLD = PluginColor.GOLD.getConsoleColor();
|
||||
MEDIUM_GOLD = PluginColor.MEDIUM_GOLD.getConsoleColor();
|
||||
LIGHT_GOLD = PluginColor.LIGHT_GOLD.getConsoleColor();
|
||||
LIGHT_BLUE = PluginColor.LIGHT_BLUE.getConsoleColor();
|
||||
} else {
|
||||
GRAY = PluginColor.GRAY.getColor();
|
||||
DARK_PURPLE = PluginColor.DARK_PURPLE.getColor();
|
||||
GOLD = PluginColor.GOLD.getColor();
|
||||
MEDIUM_GOLD = PluginColor.MEDIUM_GOLD.getColor();
|
||||
LIGHT_GOLD = PluginColor.LIGHT_GOLD.getColor();
|
||||
LIGHT_BLUE = PluginColor.LIGHT_BLUE.getColor();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String content() {
|
||||
return helpMessage.content();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TextComponent content(@NotNull String content) {
|
||||
return helpMessage.content(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Builder toBuilder() {
|
||||
return helpMessage.toBuilder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Unmodifiable @NotNull List<Component> children() {
|
||||
return helpMessage.children();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TextComponent children(@NotNull List<? extends ComponentLike> children) {
|
||||
return helpMessage.children(children);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Style style() {
|
||||
return helpMessage.style();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TextComponent style(@NotNull Style style) {
|
||||
return helpMessage.style(style);
|
||||
}
|
||||
|
||||
private TextComponent space() {
|
||||
return Component.space();
|
||||
}
|
||||
|
||||
private TextComponent newline() {
|
||||
return Component.newline();
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.gmail.artemis.the.gr8.playerstats.msg;
|
||||
package com.gmail.artemis.the.gr8.playerstats.msg.msgutils;
|
||||
|
||||
import com.gmail.artemis.the.gr8.playerstats.enums.Unit;
|
||||
import com.gmail.artemis.the.gr8.playerstats.utils.EnumHandler;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Statistic;
|
||||
@ -12,17 +13,14 @@ import java.util.HashMap;
|
||||
|
||||
public class LanguageKeyHandler {
|
||||
|
||||
private final static HashMap<Statistic, String> statNameKeys;
|
||||
private final HashMap<Statistic, String> statNameKeys;
|
||||
|
||||
static {
|
||||
public LanguageKeyHandler() {
|
||||
statNameKeys = new HashMap<>();
|
||||
generateStatNameKeys();
|
||||
}
|
||||
|
||||
private LanguageKeyHandler() {
|
||||
}
|
||||
|
||||
public static String getStatKey(@NotNull Statistic statistic) {
|
||||
public String getStatKey(@NotNull Statistic statistic) {
|
||||
if (statistic.getType() == Statistic.Type.UNTYPED) {
|
||||
return "stat.minecraft." + statNameKeys.get(statistic);
|
||||
}
|
||||
@ -33,7 +31,7 @@ public class LanguageKeyHandler {
|
||||
|
||||
/** Get the official Key from the NameSpacedKey for this entityType,
|
||||
or return null if no enum constant can be retrieved or entityType is UNKNOWN.*/
|
||||
public static @Nullable String getEntityKey(EntityType entity) {
|
||||
public @Nullable String getEntityKey(EntityType entity) {
|
||||
if (entity == null || entity == EntityType.UNKNOWN) return null;
|
||||
else {
|
||||
return "entity.minecraft." + entity.getKey().getKey();
|
||||
@ -42,7 +40,7 @@ public class LanguageKeyHandler {
|
||||
|
||||
/** Get the official Key from the NameSpacedKey for this item Material,
|
||||
or return null if no enum constant can be retrieved.*/
|
||||
public static @Nullable String getItemKey(Material item) {
|
||||
public @Nullable String getItemKey(Material item) {
|
||||
if (item == null) return null;
|
||||
else if (item.isBlock()) {
|
||||
return getBlockKey(item);
|
||||
@ -54,7 +52,7 @@ public class LanguageKeyHandler {
|
||||
|
||||
/** Returns the official Key from the NameSpacedKey for the block Material provided,
|
||||
or return null if no enum constant can be retrieved.*/
|
||||
public static @Nullable String getBlockKey(Material block) {
|
||||
public @Nullable String getBlockKey(Material block) {
|
||||
if (block == null) return null;
|
||||
else if (block.toString().toLowerCase().contains("wall_banner")) { //replace wall_banner with regular banner, since there is no key for wall banners
|
||||
String blockName = block.toString().toLowerCase().replace("wall_", "");
|
||||
@ -66,11 +64,19 @@ public class LanguageKeyHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private static void generateDefaultKeys() {
|
||||
public @Nullable String getUnitKey(Unit unit) {
|
||||
if (unit == Unit.BLOCK) {
|
||||
return "soundCategory.block";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void generateDefaultKeys() {
|
||||
Arrays.stream(Statistic.values()).forEach(statistic -> statNameKeys.put(statistic, statistic.toString().toLowerCase()));
|
||||
}
|
||||
|
||||
private static void generateStatNameKeys() {
|
||||
private void generateStatNameKeys() {
|
||||
//get the enum names for all statistics first
|
||||
generateDefaultKeys();
|
||||
|
@ -111,9 +111,9 @@ public class ReloadThread extends Thread {
|
||||
MyLogger.actionCreated((offlinePlayers != null) ? offlinePlayers.length : 0);
|
||||
ForkJoinPool.commonPool().invoke(task);
|
||||
MyLogger.actionFinished(1);
|
||||
MyLogger.logTimeTaken("ReloadThread",
|
||||
("loaded " + OfflinePlayerHandler.getOfflinePlayerCount() + " offline players"), time);
|
||||
|
||||
OfflinePlayerHandler.updateOfflinePlayerList(playerMap);
|
||||
MyLogger.logTimeTaken("ReloadThread",
|
||||
("loaded " + OfflinePlayerHandler.getOfflinePlayerCount() + " offline players"), time);
|
||||
}
|
||||
}
|
@ -30,26 +30,6 @@ public class StatRequest {
|
||||
playerFlag = false;
|
||||
}
|
||||
|
||||
/** Returns true if this StatRequest has all the information needed for a Statistic lookup to succeed.*/
|
||||
public boolean isValid() {
|
||||
if (statistic == null) return false;
|
||||
switch (statistic.getType()) {
|
||||
case BLOCK -> {
|
||||
if (block == null) return false;
|
||||
}
|
||||
case ENTITY -> {
|
||||
if (entity == null) return false;
|
||||
}
|
||||
case ITEM -> {
|
||||
if (item == null) return false;
|
||||
}
|
||||
case UNTYPED -> {
|
||||
if (subStatEntry != null) return false;
|
||||
}
|
||||
} //if target = PLAYER and playerName = null, return false, otherwise return true
|
||||
return selection != Target.PLAYER || playerName != null;
|
||||
}
|
||||
|
||||
public @NotNull CommandSender getCommandSender() {
|
||||
return sender;
|
||||
}
|
||||
|
@ -112,6 +112,18 @@ public class EnumHandler {
|
||||
return statNames.contains(statName.toLowerCase());
|
||||
}
|
||||
|
||||
public static boolean isDistanceStatistic(@NotNull String statName) {
|
||||
return statName.toLowerCase().contains("one_cm");
|
||||
}
|
||||
|
||||
public static boolean isDamageStatistic(@NotNull String statName) {
|
||||
return statName.toLowerCase().contains("damage");
|
||||
}
|
||||
|
||||
public static boolean isTimeStatistic(@NotNull String statName) {
|
||||
return statName.toLowerCase().contains("time") || statName.toLowerCase().contains("one_minute");
|
||||
}
|
||||
|
||||
/** Returns the names of all general statistics in lowercase */
|
||||
public static List<String> getStatNames() {
|
||||
return statNames;
|
||||
|
@ -52,6 +52,10 @@ public class MyLogger {
|
||||
}
|
||||
}
|
||||
|
||||
public static void logMsg(String content) {
|
||||
logMsg(content, DebugLevel.LOW, false);
|
||||
}
|
||||
|
||||
public static void logMsg(String content, boolean logAsWarning) {
|
||||
logMsg(content, DebugLevel.LOW, logAsWarning);
|
||||
}
|
||||
@ -129,7 +133,7 @@ public class MyLogger {
|
||||
if (debugLevel != DebugLevel.LOW) {
|
||||
threadNames = new ConcurrentHashMap<>();
|
||||
playersIndex.set(0);
|
||||
logger.info("Initial Action created for " + taskLength + " Players. Start Index is " + playersIndex.get() + ". Processing...");
|
||||
logger.info("Initial Action created for " + taskLength + " Players. Processing...");
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,7 +165,7 @@ public class MyLogger {
|
||||
}
|
||||
processedPlayers[nextPlayersIndex() % 10] = playerName;
|
||||
}
|
||||
else if (debugLevel == DebugLevel.MEDIUM) {
|
||||
else if (debugLevel == DebugLevel.MEDIUM || debugLevel == DebugLevel.HIGH && thread == 2) {
|
||||
nextPlayersIndex();
|
||||
}
|
||||
}
|
||||
@ -179,8 +183,10 @@ public class MyLogger {
|
||||
if (debugLevel != DebugLevel.LOW) {
|
||||
logger.info("Finished Recursive Action! In total " +
|
||||
threadNames.size() + " Threads were used to process " +
|
||||
playersIndex.get() + " Players: " +
|
||||
Collections.list(threadNames.keys()));
|
||||
playersIndex.get() + " Players.");
|
||||
}
|
||||
if (debugLevel == DebugLevel.HIGH) {
|
||||
logger.info(Collections.list(threadNames.keys()).toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,20 +0,0 @@
|
||||
package com.gmail.artemis.the.gr8.playerstats.utils;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
public class NumberFormatter {
|
||||
|
||||
private static final DecimalFormat format;
|
||||
|
||||
static{
|
||||
format = new DecimalFormat();
|
||||
format.setGroupingUsed(true);
|
||||
format.setGroupingSize(3);
|
||||
}
|
||||
private NumberFormatter(){
|
||||
}
|
||||
|
||||
public static String format(long number) {
|
||||
return format.format(number);
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
# ------------------------------------------------------------------------------------------------------ #
|
||||
# PlayerStats Configuration #
|
||||
# ------------------------------------------------------------------------------------------------------ #
|
||||
config-version: 4
|
||||
config-version: 5
|
||||
|
||||
|
||||
# # ------------------------------- # #
|
||||
@ -10,7 +10,7 @@ config-version: 4
|
||||
|
||||
# How much output you'll get in the server console while PlayerStats is processing
|
||||
# 1 = low (only show unexpected errors)
|
||||
# 2 = medium (detail all encountered exceptions, log main tasks and show time taken)
|
||||
# 2 = medium (log main tasks and time taken)
|
||||
# 3 = high (log all tasks and time taken)
|
||||
debug-level: 1
|
||||
|
||||
@ -31,9 +31,34 @@ number-of-days-since-last-joined: 0
|
||||
# The actual translation is handled by the Minecraft language files and happens automatically
|
||||
translate-to-client-language: true
|
||||
|
||||
# Use hover-text for additional info in the usage explanation
|
||||
# Use hover-text for additional info about statistic numbers
|
||||
enable-hover-text: true
|
||||
|
||||
# The unit to display certain statistics in.
|
||||
# Minecraft measures distance in cm. PlayerStats supports: blocks, cm, m (= blocks), miles, km
|
||||
distance-unit: blocks
|
||||
distance-unit-for-hover-text: km
|
||||
|
||||
# Minecraft measures damage in 0.5 hearts (1HP). PlayerStats supports: hp, hearts
|
||||
damage-unit: hearts
|
||||
damage-unit-for-hover-text: hp
|
||||
|
||||
# Minecraft measures time in ticks. With the below settings, PlayerStats will:
|
||||
# Auto-detect the best maximum unit to use (weeks/days/hours/minutes/seconds) for your players' statistics
|
||||
# Show a specified amount of additional smaller units (example: "x days" would become "x days, y hours, z minutes")
|
||||
auto-detect-biggest-time-unit: true
|
||||
number-of-extra-units: 1
|
||||
auto-detect-biggest-time-unit-for-hover-text: false
|
||||
number-of-extra-units-for-hover-text: 0
|
||||
|
||||
# If you don't want the unit to be auto-detected, set the auto-detect settings to false and specify your own range here
|
||||
# If the max and min are the same, only that unit will be displayed
|
||||
# PlayerStats supports: days, hours, minutes, seconds (and ticks if you want the original number)
|
||||
biggest-time-unit: days
|
||||
smallest-time-unit: hours
|
||||
biggest-time-unit-for-hover-text: hours
|
||||
smallest-time-unit-for-hover-text: seconds
|
||||
|
||||
# Automatically use themed formatting for the duration of certain holidays or festivals
|
||||
enable-festive-formatting: true
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user