Implemented hoverComponents with dynamic color, proper formatting and proper unit for damage and distance-based statistics!

This commit is contained in:
Artemis-the-gr8 2022-07-03 02:29:05 +02:00
parent f723a657e7
commit cde80fa9d2
5 changed files with 115 additions and 85 deletions

View File

@ -92,19 +92,33 @@ public class ConfigHandler {
return config.getInt("number-of-days-since-last-joined", 0);
}
public Unit getDistanceUnit() {
public Unit getStatUnit(Unit.Type unitType, boolean isHoverText) {
switch (unitType) {
case DISTANCE -> {
return isHoverText ? getDistanceUnitHoverText() : getDistanceUnit();
}
case DAMAGE -> {
return isHoverText ? getDamageUnitHoverText() : getDamageUnit();
}
default -> {
return Unit.NUMBER;
}
}
}
private Unit getDistanceUnit() {
return getUnitFromString(config.getString("distance-unit", "blocks"), Unit.BLOCK);
}
public Unit getDistanceUnitHoverText() {
private Unit getDistanceUnitHoverText() {
return getUnitFromString(config.getString("distance-unit-hover-text", "km"), Unit.KM);
}
public Unit getDamageUnit() {
private Unit getDamageUnit() {
return getUnitFromString(config.getString("damage-unit", "hearts"), Unit.HEART);
}
public Unit getDamageUnitHoverText() {
private Unit getDamageUnitHoverText() {
return getUnitFromString(config.getString("damage-unit-hover-text", "hp"), Unit.HP);
}

View File

@ -1,5 +1,6 @@
package com.gmail.artemis.the.gr8.playerstats.enums;
import org.bukkit.Statistic;
import org.jetbrains.annotations.NotNull;
public enum Unit {
@ -17,10 +18,26 @@ public enum Unit {
DAY (Type.TIME),
WEEK (Type.TIME);
private final Type type;
Unit(Type type) {
Unit() {
this(Type.UNTYPED);
}
Unit(Type type) {
this.type = type;
}
public Type type() {
return type;
}
public static @NotNull Type getType(Statistic statistic) {
return getType(statistic.toString());
}
/** Returns the Unit.Type of this Statistic, which can be Untyped, Distance, Damage, or Time.
@param statName the name of the Statistic enum constant in String*/
public static @NotNull Type getType(String statName) {
String name = statName.toLowerCase();
if (name.contains("one_cm")) {
@ -34,7 +51,9 @@ public enum Unit {
}
}
public @NotNull String getName() {
/** Returns a pretty name belonging to this enum constant. If the Unit is
NUMBER, it will return an empty String. */
public @NotNull String getName() throws NullPointerException {
switch (this) {
case CM -> {
return "cm";
@ -72,18 +91,21 @@ public enum Unit {
case WEEK -> {
return "weeks";
}
case NUMBER -> {
return "";
}
default ->
throw new NullPointerException("Trying to get the name of an enum constant that does not exist!");
}
}
public static enum Type{
public enum Type{
DAMAGE, //7 statistics
DISTANCE, //15 statistics
TIME, //5 statistics
UNTYPED;
private Type() {
Type() {
}
}
}

View File

@ -203,20 +203,25 @@ public class ComponentFactory {
//TODO Make this dark gray (or at least darker than statNumber, and at least for time statistics)
public TextComponent statUnitComponent(Unit statUnit, Target selection, boolean isTranslatable) {
TextComponent.Builder statUnitBuilder = getComponentBuilder(null,
getColorFromString(config.getSubStatNameFormatting(selection, false)),
getStyleFromString(config.getSubStatNameFormatting(selection, true)))
.append(text("["));
if (isTranslatable) {
String unitKey = languageKeyHandler.getUnitKey(statUnit);
if (unitKey == null) {
unitKey = statUnit.getName();
if (statUnit.type() != Unit.Type.UNTYPED) {
TextComponent.Builder statUnitBuilder = getComponentBuilder(null,
getColorFromString(config.getSubStatNameFormatting(selection, false)),
getStyleFromString(config.getSubStatNameFormatting(selection, true)))
.append(text("["));
if (isTranslatable) {
String unitKey = languageKeyHandler.getUnitKey(statUnit);
if (unitKey == null) {
unitKey = statUnit.getName();
}
statUnitBuilder.append(translatable().key(unitKey));
} else {
statUnitBuilder.append(text(statUnit.getName()));
}
statUnitBuilder.append(translatable().key(unitKey));
} else {
statUnitBuilder.append(text(statUnit.getName()));
return statUnitBuilder.append(text("]")).build();
}
else {
return Component.empty();
}
return statUnitBuilder.append(text("]")).build();
}
public TextComponent titleComponent(String content, Target selection) {

View File

@ -29,7 +29,7 @@ public class MessageWriter {
public MessageWriter(ConfigHandler c) {
config = c;
formatter = new NumberFormatter(config);
formatter = new NumberFormatter();
getComponentFactory();
}
@ -108,11 +108,14 @@ public class MessageWriter {
.append(componentFactory.playerNameBuilder(request.getPlayerName(), Target.PLAYER)
.append(text(":"))
.append(space()))
.append(componentFactory.statNumberComponent(stat, request.getStatistic().toString(), Target.PLAYER))
.append(getStatNumberComponent(request.getStatistic(), stat, Target.PLAYER))
.append(space())
.append(getStatNameComponent(request))
.append(space())
.append(componentFactory.statUnitComponent(request.getStatistic().toString(), Target.PLAYER))
.append(componentFactory.statUnitComponent(
config.getStatUnit(Unit.getType(request.getStatistic()), false),
Target.PLAYER,
config.useTranslatableComponents()))
.build();
}
@ -124,11 +127,13 @@ public class MessageWriter {
.append(componentFactory.titleNumberComponent(topStats.size())).append(space())
.append(getStatNameComponent(request))
.append(space())
.append(componentFactory.statUnitComponent(request.getStatistic().toString(), Target.TOP));
.append(componentFactory.statUnitComponent(
config.getStatUnit(Unit.getType(request.getStatistic()), false),
Target.TOP,
config.useTranslatableComponents()));
boolean useDots = config.useDots();
boolean boldNames = config.playerNameIsBold();
boolean useHover = config.useHoverText();
Set<String> playerNames = topStats.keySet();
MinecraftFont font = new MinecraftFont();
@ -155,20 +160,15 @@ public class MessageWriter {
}
if (dots >= 1) {
topList.append(dotsBuilder
.append(text((".".repeat(dots))))
.build());
.append(text((".".repeat(dots)))));
}
} else {
topList.append(playerNameBuilder
.append(text(":"))
.build());
}
topList.append(space());
if (useHover) {
topList.append(
//componentFactory.statNumberHoverComponent(
// formatter.formatMainNumber(request.getStatistic().toString(), topStats.get(playerName)), Target.TOP));
.append(text(":")));
}
topList.append(space())
.append(getStatNumberComponent(request.getStatistic(), topStats.get(playerName), Target.TOP));
}
return topList.build();
}
@ -179,17 +179,20 @@ public class MessageWriter {
.append(space())
.append(componentFactory.serverNameComponent(config.getServerName()))
.append(space())
.append(componentFactory.statNumberComponent(stat, request.getStatistic().toString(), Target.SERVER))
.append(getStatNumberComponent(request.getStatistic(), stat, Target.SERVER))
.append(space())
.append(getStatNameComponent(request))
.append(space())
.append(componentFactory.statUnitComponent(request.getStatistic().toString(), Target.SERVER))
.append(componentFactory.statUnitComponent(
config.getStatUnit(Unit.getType(request.getStatistic()), false),
Target.SERVER,
config.useTranslatableComponents()))
.build();
}
/** Depending on the config settings, return either a TranslatableComponent representing
the statName (and potential subStatName), or a TextComponent with capitalized English names.*/
private Component getStatNameComponent(StatRequest request) {
private TextComponent getStatNameComponent(StatRequest request) {
if (config.useTranslatableComponents()) {
return componentFactory.statNameTransComponent(request);
} else {
@ -200,12 +203,18 @@ public class MessageWriter {
}
}
private Component getStatNumberComponent(String statName, long statNumber) {
Unit.getType(statName);
if (config.useHoverText()) {
return componentFactory.statNumberHoverComponent(formatter.formatMainNumber(statName, statNumber),
formatter.formatHoverNumber(statName, statNumber),
//something like config.getUnit that calls a bunch of smaller specific getUnit methods)
private TextComponent getStatNumberComponent(Statistic statistic, long statNumber, Target selection) {
Unit.Type type = Unit.getType(statistic);
Unit baseUnit = config.getStatUnit(type, false);
String prettyNumber = formatter.format(statNumber, baseUnit);
if (config.useHoverText() && type != Unit.Type.UNTYPED) {
Unit hoverUnit = config.getStatUnit(type, true);
return componentFactory.statNumberHoverComponent(
prettyNumber,
formatter.format(statNumber, hoverUnit),
hoverUnit, selection, config.useTranslatableComponents());
} else {
return componentFactory.statNumberComponent(prettyNumber, selection).build();
}
}

View File

@ -1,62 +1,43 @@
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.Unit;
import com.gmail.artemis.the.gr8.playerstats.utils.EnumHandler;
import java.text.DecimalFormat;
public class NumberFormatter {
private static ConfigHandler config;
private final DecimalFormat format;
public NumberFormatter(ConfigHandler c) {
config = c;
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-or-times, time-, damage- or distance-based) according to the
(number-of-times, time-, damage- or distance-based) according to the
corresponding config settings, and adds commas in groups of 3.*/
public String formatMainNumber(String statName, long number) {
return format(statName, number, false);
}
/** Turns the input number into a more readable format depending on its type
(number-or-times, time-, damage- or distance-based) according to the
corresponding config settings, and adds commas in groups of 3.*/
public String formatHoverNumber(String statName, long number) {
return format(statName, number, true);
}
/** Formats the input based on the desired config settings from *-unit or *-unit-hover-text.
@param statName the Statistic enum name in String format
@param number the statistic number
@param isHoverText boolean that indicates whether this number will be displayed in a HoverComponent or not*/
private String format(String statName, long number, boolean isHoverText) {
if (EnumHandler.isDistanceStatistic(statName)) {
return formatDistance(number, isHoverText);
}
else if (EnumHandler.isDamageStatistic(statName)) {
return formatDamage(number, isHoverText);
}
else if (EnumHandler.isTimeStatistic(statName)) {
return formatTime(number, isHoverText);
}
else {
return format.format(number);
public String format(long number, Unit statUnit) {
switch (statUnit.type()) {
case DISTANCE -> {
return formatDistance(number, statUnit);
}
case DAMAGE -> {
return formatDamage(number, statUnit);
}
case TIME -> {
return formatTime(number, statUnit);
}
default -> {
return format.format(number);
}
}
}
/** The unit of damage-based statistics is half a heart by default.
This method turns the number into hearts. */
private String formatDamage(long number, boolean isHoverText) { //7 statistics
Unit unit = isHoverText ? config.getDamageUnitHoverText() : config.getDamageUnit();
if (unit == Unit.HEART) {
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);
@ -65,9 +46,8 @@ public class NumberFormatter {
/** The unit of distance-based statistics is cm by default. This method turns it into blocks by default,
and turns it into km or leaves it as cm otherwise, depending on the config settings. */
private String formatDistance(long number, boolean isHoverText) { //15 statistics
Unit unit = isHoverText ? config.getDistanceUnitHoverText() : config.getDistanceUnit();
switch (unit) {
private String formatDistance(long number, Unit statUnit) { //15 statistics
switch (statUnit) {
case CM -> {
return format.format(number);
}
@ -84,7 +64,7 @@ public class NumberFormatter {
}
/** The unit of time-based statistics is ticks by default.*/
private String formatTime(long number, boolean isHoverText) { //5 statistics
private String formatTime(long number, Unit statUnit) { //5 statistics
if (number == 0) {
return "-";
}