770 lines
34 KiB
Java
770 lines
34 KiB
Java
package com.artemis.the.gr8.playerstats.core.msg;
|
|
|
|
import com.artemis.the.gr8.playerstats.api.StatTextFormatter;
|
|
import com.artemis.the.gr8.playerstats.core.msg.components.*;
|
|
import com.artemis.the.gr8.playerstats.core.msg.msgutils.*;
|
|
import com.artemis.the.gr8.playerstats.api.StatRequest;
|
|
import com.artemis.the.gr8.playerstats.core.utils.EnumHandler;
|
|
import com.artemis.the.gr8.playerstats.core.utils.MyLogger;
|
|
import com.artemis.the.gr8.playerstats.api.enums.Target;
|
|
import com.artemis.the.gr8.playerstats.core.config.ConfigHandler;
|
|
import com.artemis.the.gr8.playerstats.api.enums.Unit;
|
|
|
|
import net.kyori.adventure.text.Component;
|
|
import net.kyori.adventure.text.TextComponent;
|
|
import org.bukkit.Statistic;
|
|
import org.bukkit.command.CommandSender;
|
|
import org.bukkit.entity.Player;
|
|
import org.jetbrains.annotations.Contract;
|
|
import org.jetbrains.annotations.NotNull;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
import java.util.*;
|
|
import java.util.function.BiFunction;
|
|
|
|
import static net.kyori.adventure.text.Component.*;
|
|
|
|
/**
|
|
* Composes messages to send to a Player or Console. This class is responsible
|
|
* for constructing a final {@link TextComponent} with the text content of the
|
|
* desired message. The component parts (with appropriate formatting) are supplied
|
|
* by a {@link ComponentFactory}. By default, this class works with the standard
|
|
* ComponentFactory, but you can give it a different ComponentFactory upon creation.
|
|
*
|
|
* @see PrideComponentFactory
|
|
* @see BukkitConsoleComponentFactory
|
|
*/
|
|
public final class MessageBuilder implements StatTextFormatter {
|
|
|
|
private final ConfigHandler config;
|
|
private final boolean useHoverText;
|
|
|
|
private final ComponentFactory componentFactory;
|
|
private final LanguageKeyHandler languageKeyHandler;
|
|
private final NumberFormatter formatter;
|
|
private final ComponentSerializer serializer;
|
|
|
|
private MessageBuilder(ComponentFactory factory) {
|
|
config = ConfigHandler.getInstance();
|
|
languageKeyHandler = LanguageKeyHandler.getInstance();
|
|
componentFactory = factory;
|
|
|
|
if (componentFactory.isConsoleFactory()) {
|
|
useHoverText = false;
|
|
} else {
|
|
useHoverText = config.useHoverText();
|
|
}
|
|
formatter = new NumberFormatter();
|
|
serializer = new ComponentSerializer();
|
|
}
|
|
|
|
@Contract(" -> new")
|
|
public static @NotNull MessageBuilder defaultBuilder() {
|
|
return new MessageBuilder(new ComponentFactory());
|
|
}
|
|
|
|
@Contract("_ -> new")
|
|
public static @NotNull MessageBuilder fromComponentFactory(ComponentFactory factory) {
|
|
return new MessageBuilder(factory);
|
|
}
|
|
|
|
@Override
|
|
public @NotNull String textComponentToString(TextComponent component) {
|
|
return serializer.getTranslatableComponentSerializer().serialize(component);
|
|
}
|
|
|
|
@Override
|
|
public TextComponent getPluginPrefix() {
|
|
return componentFactory.pluginPrefix();
|
|
}
|
|
|
|
@Override
|
|
public @NotNull TextComponent getRainbowPluginPrefix() {
|
|
PrideComponentFactory pride = new PrideComponentFactory();
|
|
return pride.pluginPrefix();
|
|
}
|
|
|
|
@Override
|
|
public TextComponent getPluginPrefixAsTitle() {
|
|
return componentFactory.pluginPrefixAsTitle();
|
|
}
|
|
|
|
@Override
|
|
public @NotNull TextComponent getRainbowPluginPrefixAsTitle() {
|
|
PrideComponentFactory pride = new PrideComponentFactory();
|
|
return pride.pluginPrefixAsTitle();
|
|
}
|
|
|
|
public @NotNull TextComponent reloadedConfig() {
|
|
return composePluginMessage("Config reloaded!");
|
|
}
|
|
|
|
public @NotNull TextComponent stillReloading() {
|
|
return composePluginMessage("The plugin is (re)loading, your request will be processed when it is done!");
|
|
}
|
|
|
|
public @NotNull TextComponent excludeSuccess(String playerName) {
|
|
return componentFactory.pluginPrefix()
|
|
.append(space())
|
|
.append(componentFactory.message().content("Excluded ")
|
|
.append(componentFactory.messageAccent().content(playerName))
|
|
.append(text("!")));
|
|
}
|
|
|
|
public @NotNull TextComponent excludeFailed() {
|
|
return composePluginMessage("This player is already hidden from /stat results!");
|
|
}
|
|
|
|
public @NotNull TextComponent includeSuccess(String playerName) {
|
|
return componentFactory.pluginPrefix()
|
|
.append(space())
|
|
.append(componentFactory.message().content("Removed ")
|
|
.append(componentFactory.messageAccent().content(playerName))
|
|
.append(text(" from the exclude-list!")));
|
|
}
|
|
|
|
public @NotNull TextComponent includeFailed() {
|
|
return composePluginMessage("This is not a player that has been excluded with the /statexclude command!");
|
|
}
|
|
|
|
public @NotNull TextComponent waitAMinute() {
|
|
return composePluginMessage("Calculating statistics, this may take a minute...");
|
|
}
|
|
|
|
public @NotNull TextComponent waitAMoment() {
|
|
return composePluginMessage("Calculating statistics, this may take a few moments...");
|
|
}
|
|
|
|
public @NotNull TextComponent missingStatName() {
|
|
return composePluginMessage("Please provide a valid statistic name!");
|
|
}
|
|
|
|
public @NotNull TextComponent missingSubStatName(String statType) {
|
|
return composePluginMessage("Please add a valid " + statType + " to look up this statistic!");
|
|
}
|
|
|
|
public @NotNull TextComponent missingPlayerName() {
|
|
return composePluginMessage("Please specify a valid player-name!");
|
|
}
|
|
|
|
public @NotNull TextComponent wrongSubStatType(String statType, String subStatName) {
|
|
return componentFactory.pluginPrefix()
|
|
.append(space())
|
|
.append(componentFactory.messageAccent().content("\"" + subStatName + "\""))
|
|
.append(space())
|
|
.append(componentFactory.message().content(
|
|
"is not a valid " + statType + "!"));
|
|
}
|
|
|
|
public @NotNull TextComponent requestAlreadyRunning() {
|
|
return composePluginMessage("Please wait for your previous lookup to finish!");
|
|
}
|
|
|
|
public @NotNull TextComponent stillOnShareCoolDown() {
|
|
int waitTime = config.getStatShareWaitingTime();
|
|
String minutes = waitTime == 1 ? " minute" : " minutes";
|
|
|
|
return componentFactory.pluginPrefix()
|
|
.append(space())
|
|
.append(componentFactory.message().content("You need to wait")
|
|
.append(space())
|
|
.append(componentFactory.messageAccent()
|
|
.content(waitTime + minutes))
|
|
.append(space())
|
|
.append(text("between sharing!")));
|
|
}
|
|
|
|
public @NotNull TextComponent resultsAlreadyShared() {
|
|
return composePluginMessage("You already shared these results!");
|
|
}
|
|
|
|
public @NotNull TextComponent statResultsTooOld() {
|
|
return composePluginMessage("It has been too long since you looked up " +
|
|
"this statistic, please repeat the original command!");
|
|
}
|
|
|
|
public @NotNull TextComponent unknownError() {
|
|
return composePluginMessage("Something went wrong with your request, " +
|
|
"please try again or see /statistic for a usage explanation!");
|
|
}
|
|
|
|
private @NotNull TextComponent composePluginMessage(String content) {
|
|
return getPluginPrefix()
|
|
.append(space())
|
|
.append(componentFactory.message().content(content));
|
|
}
|
|
|
|
@Contract(" -> new")
|
|
public @NotNull TextComponent usageExamples() {
|
|
return ExampleMessage.construct(componentFactory);
|
|
}
|
|
|
|
public TextComponent helpMsg() {
|
|
int listSize = config.getTopListMaxSize();
|
|
if (useHoverText) {
|
|
return HelpMessage.constructHoverMsg(componentFactory, listSize);
|
|
} else {
|
|
return HelpMessage.constructPlainMsg(componentFactory, listSize);
|
|
}
|
|
}
|
|
|
|
public @NotNull TextComponent excludeInfoMsg() {
|
|
return ExcludeInfoMessage.construct(componentFactory);
|
|
}
|
|
|
|
public @NotNull TextComponent excludedList(@NotNull ArrayList<String> excludedPlayerNames) {
|
|
TextComponent.Builder excludedList = text()
|
|
.append(newline())
|
|
.append(getPluginPrefixAsTitle()
|
|
.append(newline())
|
|
.append(componentFactory.subTitle("All players that are currently excluded: ")));
|
|
|
|
excludedPlayerNames.forEach(playerName -> excludedList
|
|
.append(newline())
|
|
.append(componentFactory.arrow()
|
|
.append(space())
|
|
.append(componentFactory.infoMessageAccent().content(playerName))));
|
|
|
|
return excludedList.build();
|
|
}
|
|
|
|
@Override
|
|
public @NotNull TextComponent getStatTitle(Statistic statistic, @Nullable String subStatName) {
|
|
return getTopStatTitleComponent(0, statistic, subStatName, null);
|
|
}
|
|
|
|
@Override
|
|
public @NotNull TextComponent getStatTitle(Statistic statistic, Unit unit) {
|
|
return getTopStatTitleComponent(0, statistic, null, unit);
|
|
}
|
|
|
|
@Override
|
|
public @NotNull TextComponent getTopStatTitle(int topListSize, Statistic statistic, @Nullable String subStatName) {
|
|
return getTopStatTitleComponent(topListSize, statistic, subStatName, null);
|
|
}
|
|
|
|
@Override
|
|
public @NotNull TextComponent getTopStatTitle(int topStatSize, Statistic statistic, Unit unit) {
|
|
return getTopStatTitleComponent(topStatSize, statistic, null, unit);
|
|
}
|
|
|
|
@Override
|
|
public @NotNull TextComponent formatTopStatLine(int positionInTopList, String playerName, long statNumber, Statistic statistic) {
|
|
TextComponent statNumberComponent = getStatNumberComponent(statNumber, Target.TOP, statistic);
|
|
return getTopStatLineComponent(positionInTopList, playerName, statNumberComponent);
|
|
}
|
|
|
|
@Override
|
|
public @NotNull TextComponent formatTopStatLine(int positionInTopList, String playerName, long statNumber, Unit unit) {
|
|
TextComponent statNumberComponent = getStatNumberComponent(statNumber, Target.TOP, unit);
|
|
return getTopStatLineComponent(positionInTopList, playerName, statNumberComponent);
|
|
}
|
|
|
|
/**
|
|
* Time-number does not hover
|
|
*/
|
|
@Override
|
|
public @NotNull TextComponent formatTopStatLineForTypeTime(int positionInTopList, String playerName, long statNumber, Unit bigUnit, Unit smallUnit) {
|
|
TextComponent statNumberComponent = getBasicTimeNumberComponent(statNumber, Target.TOP, bigUnit, smallUnit);
|
|
return getTopStatLineComponent(positionInTopList, playerName, statNumberComponent);
|
|
}
|
|
|
|
@Override
|
|
public @NotNull TextComponent formatServerStat(long statNumber, Statistic statistic) {
|
|
TextComponent statNumberComponent = getStatNumberComponent(statNumber, Target.SERVER, statistic);
|
|
return getServerStatComponent(statNumberComponent, statistic, null, null);
|
|
}
|
|
|
|
@Override
|
|
public @NotNull TextComponent formatServerStat(long statNumber, Statistic statistic, String subStatName) {
|
|
TextComponent statNumberComponent = getStatNumberComponent(statNumber, Target.SERVER, statistic);
|
|
return getServerStatComponent(statNumberComponent, statistic, subStatName, null);
|
|
}
|
|
|
|
@Override
|
|
public @NotNull TextComponent formatServerStat(long statNumber, Statistic statistic, Unit unit) {
|
|
TextComponent statNumberComponent = getStatNumberComponent(statNumber, Target.SERVER, unit);
|
|
return getServerStatComponent(statNumberComponent, statistic, null, unit);
|
|
}
|
|
|
|
@Override
|
|
public @NotNull TextComponent formatServerStatForTypeTime(long statNumber, Statistic statistic, Unit bigUnit, Unit smallUnit) {
|
|
TextComponent statNumberComponent = getBasicTimeNumberComponent(statNumber, Target.SERVER, bigUnit, smallUnit);
|
|
return getServerStatComponent(statNumberComponent, statistic, null, null);
|
|
}
|
|
|
|
@Override
|
|
public @NotNull TextComponent formatPlayerStat(String playerName, int statNumber, Statistic statistic) {
|
|
TextComponent statNumberComponent = getStatNumberComponent(statNumber, Target.PLAYER, statistic);
|
|
return getPlayerStatComponent(playerName, statNumberComponent, statistic, null, null);
|
|
}
|
|
|
|
@Override
|
|
public @NotNull TextComponent formatPlayerStat(String playerName, int statNumber, Statistic statistic, Unit unit) {
|
|
TextComponent statNumberComponent = getStatNumberComponent(statNumber, Target.PLAYER, unit);
|
|
return getPlayerStatComponent(playerName, statNumberComponent, statistic, null, unit);
|
|
}
|
|
|
|
@Override
|
|
public @NotNull TextComponent formatPlayerStat(String playerName, int statNumber, Statistic statistic, String subStatName) {
|
|
TextComponent statNumberComponent = getStatNumberComponent(statNumber, Target.PLAYER, statistic);
|
|
return getPlayerStatComponent(playerName, statNumberComponent, statistic, subStatName, null);
|
|
}
|
|
|
|
@Override
|
|
public @NotNull TextComponent formatPlayerStatForTypeTime(String playerName, int statNumber, Statistic statistic, Unit bigUnit, Unit smallUnit) {
|
|
TextComponent statNumberComponent = getBasicTimeNumberComponent(statNumber, Target.PLAYER, bigUnit, smallUnit);
|
|
return getPlayerStatComponent(playerName, statNumberComponent, statistic, null, null);
|
|
}
|
|
|
|
/**
|
|
* Returns a BiFunction for a player statistic. This BiFunction will return
|
|
* a formattedComponent, the shape of which is determined by the 2 parameters
|
|
* the BiFunction gets.
|
|
* <p>- Integer shareCode: if a shareCode is provided, a clickable "share"
|
|
* button will be added.
|
|
* <br>- CommandSender sender: if a sender is provided, a signature with
|
|
* "shared by sender-name" will be added.
|
|
* <br>- If both parameters are null, the formattedComponent will be returned
|
|
* as is.
|
|
*/
|
|
public @NotNull FormattingFunction formattedPlayerStatFunction(int stat, @NotNull StatRequest.Settings request) {
|
|
TextComponent playerStat = formatPlayerStat(request.getPlayerName(), stat, request.getStatistic(), request.getSubStatEntryName());
|
|
return getFormattingFunction(playerStat, Target.PLAYER);
|
|
}
|
|
|
|
/**
|
|
* Returns a BiFunction for a server statistic. This BiFunction will return
|
|
* a formattedComponent, the shape of which is determined by the 2 parameters
|
|
* the BiFunction gets.
|
|
* <p>- Integer shareCode: if a shareCode is provided, a clickable "share"
|
|
* button will be added.
|
|
* <br>- CommandSender sender: if a sender is provided, a signature with
|
|
* "shared by sender-name" will be added.
|
|
* <br>- If both parameters are null, the formattedComponent will be returned
|
|
* as is.
|
|
*/
|
|
public @NotNull FormattingFunction formattedServerStatFunction(long stat, @NotNull StatRequest.Settings request) {
|
|
TextComponent serverStat = formatServerStat(stat, request.getStatistic(), request.getSubStatEntryName());
|
|
return getFormattingFunction(serverStat, Target.SERVER);
|
|
}
|
|
|
|
/**
|
|
* Returns a BiFunction for a top statistic. This BiFunction will return
|
|
* a formattedComponent, the shape of which is determined by the 2 parameters
|
|
* the BiFunction gets.
|
|
* <p>- Integer shareCode: if a shareCode is provided, a clickable "share"
|
|
* button will be added.
|
|
* <br>- CommandSender sender: if a sender is provided, a signature with
|
|
* "shared by sender-name" will be added.
|
|
* <br>- If both parameters are null, the formattedComponent will be returned
|
|
* as is.
|
|
*/
|
|
public @NotNull FormattingFunction formattedTopStatFunction(@NotNull LinkedHashMap<String, Integer> topStats, @NotNull StatRequest.Settings request) {
|
|
final TextComponent title = getTopStatTitle(topStats.size(), request.getStatistic(), request.getSubStatEntryName());
|
|
final TextComponent list = getTopStatListComponent(topStats, request.getStatistic());
|
|
final boolean useEnters = config.useEnters(Target.TOP, false);
|
|
final boolean useEntersForShared = config.useEnters(Target.TOP, true);
|
|
|
|
BiFunction<Integer, CommandSender, TextComponent> biFunction = (shareCode, sender) -> {
|
|
TextComponent.Builder topBuilder = text();
|
|
|
|
//if we're adding a share-button
|
|
if (shareCode != null) {
|
|
if (useEnters) {
|
|
topBuilder.append(newline());
|
|
}
|
|
topBuilder.append(componentFactory.pluginPrefix())
|
|
.append(space())
|
|
.append(title)
|
|
.append(space())
|
|
.append(componentFactory.shareButton(shareCode))
|
|
.append(list);
|
|
}
|
|
//if we're adding a "shared by" component
|
|
else if (sender != null) {
|
|
if (useEntersForShared) {
|
|
topBuilder.append(newline());
|
|
}
|
|
topBuilder.append(title)
|
|
.append(space())
|
|
.append(componentFactory.statResultInHoverText(text()
|
|
.append(componentFactory.pluginPrefix())
|
|
.append(space())
|
|
.append(title)
|
|
.append(list)
|
|
.build()))
|
|
.append(newline())
|
|
.append(componentFactory.sharedByMessage(
|
|
getSharerNameComponent(sender)));
|
|
}
|
|
//if we're not adding a share-button or a "shared by" component
|
|
else {
|
|
if (useEnters) {
|
|
topBuilder.append(newline());
|
|
}
|
|
topBuilder.append(componentFactory.pluginPrefix())
|
|
.append(space())
|
|
.append(title)
|
|
.append(list);
|
|
}
|
|
return topBuilder.build();
|
|
};
|
|
return new FormattingFunction(biFunction);
|
|
}
|
|
|
|
private @NotNull TextComponent getPlayerStatComponent(String playerName, TextComponent statNumberComponent, Statistic statistic, @Nullable String subStatName, @Nullable Unit unit) {
|
|
TextComponent statUnit = (unit == null) ?
|
|
getStatUnitComponent(statistic, Target.PLAYER) :
|
|
getStatUnitComponent(unit, Target.PLAYER);
|
|
|
|
return Component.text()
|
|
.append(componentFactory.playerName(playerName, Target.PLAYER)
|
|
.append(text(":"))
|
|
.append(space()))
|
|
.append(statNumberComponent)
|
|
.append(space())
|
|
.append(getStatAndSubStatNameComponent(statistic, subStatName, Target.PLAYER))
|
|
.append(statUnit) //space is provided by statUnitComponent
|
|
.build();
|
|
}
|
|
|
|
private @NotNull TextComponent getServerStatComponent(TextComponent statNumber, Statistic statistic, @Nullable String subStatName, @Nullable Unit unit) {
|
|
String serverTitle = config.getServerTitle();
|
|
String serverName = config.getServerName();
|
|
TextComponent statUnit = (unit == null) ?
|
|
getStatUnitComponent(statistic, Target.SERVER) :
|
|
getStatUnitComponent(unit, Target.SERVER);
|
|
|
|
return Component.text()
|
|
.append(componentFactory.title(serverTitle, Target.SERVER))
|
|
.append(space())
|
|
.append(componentFactory.serverName(serverName))
|
|
.append(space())
|
|
.append(statNumber)
|
|
.append(space())
|
|
.append(getStatAndSubStatNameComponent(statistic, subStatName, Target.SERVER))
|
|
.append(statUnit) //space is provided by statUnit
|
|
.build();
|
|
}
|
|
|
|
private @NotNull TextComponent getTopStatTitleComponent(int topListSize, Statistic statistic, @Nullable String subStatName, @Nullable Unit unit) {
|
|
TextComponent statUnit = (unit == null) ?
|
|
getStatUnitComponent(statistic, Target.TOP) :
|
|
getStatUnitComponent(unit, Target.TOP);
|
|
|
|
if (topListSize == 0) {
|
|
return Component.text()
|
|
.append(getStatAndSubStatNameComponent(statistic, subStatName, Target.TOP))
|
|
.append(statUnit) //space is provided by statUnitComponent
|
|
.build();
|
|
} else {
|
|
return Component.text()
|
|
.append(componentFactory.title(config.getTopStatsTitle(), Target.TOP))
|
|
.append(space())
|
|
.append(componentFactory.titleNumber(topListSize))
|
|
.append(space())
|
|
.append(getStatAndSubStatNameComponent(statistic, subStatName, Target.TOP))
|
|
.append(statUnit) //space is provided by statUnitComponent
|
|
.build();
|
|
}
|
|
}
|
|
|
|
private @NotNull TextComponent getTopStatListComponent(@NotNull LinkedHashMap<String, Integer> topStats, Statistic statistic) {
|
|
TextComponent.Builder topList = Component.text();
|
|
Set<String> playerNames = topStats.keySet();
|
|
boolean useDots = config.useDots();
|
|
|
|
int count = 0;
|
|
for (String playerName : playerNames) {
|
|
topList.append(newline());
|
|
if (useDots) {
|
|
topList.append(getTopStatLineComponent(
|
|
++count, playerName, getStatNumberComponent(topStats.get(playerName), Target.TOP, statistic)));
|
|
} else {
|
|
topList.append(space())
|
|
.append(componentFactory.rankNumber(++count))
|
|
.append(space())
|
|
.append(componentFactory.playerName(playerName + ":", Target.TOP))
|
|
.append(space()).append(getStatNumberComponent(topStats.get(playerName), Target.TOP, statistic));
|
|
}
|
|
}
|
|
return topList.build();
|
|
}
|
|
|
|
private @NotNull TextComponent getTopStatLineComponent(int positionInTopList, String playerName, TextComponent statNumberComponent) {
|
|
boolean useDots = config.useDots();
|
|
String fullPlayerName = useDots ? playerName : playerName + ":";
|
|
|
|
TextComponent.Builder topStatLineBuilder = Component.text()
|
|
.append(space())
|
|
.append(componentFactory.rankNumber(positionInTopList))
|
|
.append(space())
|
|
.append(componentFactory.playerName(fullPlayerName, Target.TOP));
|
|
|
|
if (config.useDots()) {
|
|
int dots = getNumberOfDotsToAlign(positionInTopList + ". " + playerName);
|
|
if (dots >= 1) {
|
|
topStatLineBuilder
|
|
.append(space())
|
|
.append(componentFactory.dots(".".repeat(dots)));
|
|
}
|
|
}
|
|
|
|
return topStatLineBuilder
|
|
.append(space())
|
|
.append(statNumberComponent)
|
|
.build();
|
|
}
|
|
|
|
private TextComponent getStatAndSubStatNameComponent(Statistic statistic, @Nullable String subStatName, Target target) {
|
|
EnumHandler enumHandler = EnumHandler.getInstance();
|
|
|
|
String statKey = languageKeyHandler.getStatKey(statistic);
|
|
String subStatKey = switch (statistic.getType()) {
|
|
case UNTYPED -> null;
|
|
case ENTITY -> languageKeyHandler.getEntityKey(enumHandler.getEntityEnum(subStatName));
|
|
case BLOCK -> languageKeyHandler.getBlockKey(enumHandler.getBlockEnum(subStatName));
|
|
case ITEM -> languageKeyHandler.getItemKey(enumHandler.getItemEnum(subStatName));
|
|
};
|
|
if (subStatKey == null) {
|
|
subStatKey = StringUtils.prettify(subStatName);
|
|
}
|
|
|
|
if (config.useTranslatableComponents()) {
|
|
return componentFactory.statAndSubStatNameTranslatable(statKey, subStatKey, target);
|
|
}
|
|
|
|
String prettyStatName = languageKeyHandler.convertLanguageKeyToDisplayName(statKey);
|
|
String prettySubStatName = languageKeyHandler.convertLanguageKeyToDisplayName(subStatKey);
|
|
return componentFactory.statAndSubStatName(prettyStatName, prettySubStatName, target);
|
|
}
|
|
|
|
private TextComponent getStatNumberComponent(long statNumber, Target target, @NotNull Unit unit) {
|
|
return switch (unit.getType()) {
|
|
case TIME -> getBasicTimeNumberComponent(statNumber, target, unit, null);
|
|
case DAMAGE -> getDamageNumberComponent(statNumber, target, unit);
|
|
case DISTANCE -> getDistanceNumberComponent(statNumber, target, unit);
|
|
default -> getDefaultNumberComponent(statNumber, target);
|
|
};
|
|
}
|
|
|
|
private TextComponent getStatNumberComponent(long statNumber, Target target, Statistic statistic) {
|
|
Unit.Type unitType = Unit.getTypeFromStatistic(statistic);
|
|
return switch (unitType) {
|
|
case DISTANCE -> getDistanceNumberComponent(statNumber, target);
|
|
case DAMAGE -> getDamageNumberComponent(statNumber, target);
|
|
case TIME -> getTimeNumberComponent(statNumber, target);
|
|
default -> getDefaultNumberComponent(statNumber, target);
|
|
};
|
|
}
|
|
|
|
private TextComponent getDistanceNumberComponent(long statNumber, Target target) {
|
|
Unit statUnit = Unit.fromString(config.getDistanceUnit(false));
|
|
return getDistanceNumberComponent(statNumber, target, statUnit);
|
|
}
|
|
|
|
private TextComponent getDistanceNumberComponent(long statNumber, Target target, Unit unit) {
|
|
String prettyNumber = formatter.formatDistanceNumber(statNumber, unit);
|
|
if (!useHoverText) {
|
|
return componentFactory.distanceNumber(prettyNumber, target);
|
|
}
|
|
|
|
Unit hoverUnit = Unit.fromString(config.getDistanceUnit(true));
|
|
String hoverNumber = formatter.formatDistanceNumber(statNumber, hoverUnit);
|
|
if (config.useTranslatableComponents()) {
|
|
String unitKey = languageKeyHandler.getUnitKey(hoverUnit);
|
|
if (unitKey != null) {
|
|
return componentFactory.distanceNumberWithTranslatableHoverText(prettyNumber, hoverNumber, unitKey, target);
|
|
}
|
|
}
|
|
return componentFactory.distanceNumberWithHoverText(prettyNumber, hoverNumber, hoverUnit.getLabel(), target);
|
|
}
|
|
|
|
private TextComponent getDamageNumberComponent(long statNumber, Target target) {
|
|
Unit statUnit = Unit.fromString(config.getDamageUnit(false));
|
|
return getDamageNumberComponent(statNumber, target, statUnit);
|
|
}
|
|
|
|
private TextComponent getDamageNumberComponent(long statNumber, Target target, Unit unit) {
|
|
String prettyNumber = formatter.formatDamageNumber(statNumber, unit);
|
|
if (!useHoverText) {
|
|
return componentFactory.damageNumber(prettyNumber, target);
|
|
}
|
|
|
|
Unit hoverUnit = Unit.fromString(config.getDamageUnit(true));
|
|
String prettyHoverNumber = formatter.formatDamageNumber(statNumber, hoverUnit);
|
|
if (hoverUnit == Unit.HEART) {
|
|
return componentFactory.damageNumberWithHeartUnitInHoverText(prettyNumber, prettyHoverNumber, target);
|
|
}
|
|
return componentFactory.damageNumberWithHoverText(prettyNumber, prettyHoverNumber, hoverUnit.getLabel(), target);
|
|
}
|
|
|
|
private TextComponent getTimeNumberComponent(long statNumber, Target target) {
|
|
ArrayList<Unit> unitRange = getTimeUnitRange(statNumber);
|
|
if (unitRange.size() <= 1 || (useHoverText && unitRange.size() <= 3)) {
|
|
MyLogger.logWarning("There is something wrong with the time-units you specified, please check your config!");
|
|
return componentFactory.timeNumber(formatter.formatDefaultNumber(statNumber), target);
|
|
}
|
|
else {
|
|
String mainNumber = formatter.formatTimeNumber(statNumber, unitRange.get(0), unitRange.get(1));
|
|
if (!useHoverText) {
|
|
return componentFactory.timeNumber(mainNumber, target);
|
|
} else {
|
|
String hoverNumber = formatter.formatTimeNumber(statNumber, unitRange.get(2), unitRange.get(3));
|
|
MyLogger.logHighLevelMsg("mainNumber: " + mainNumber + ", hoverNumber: " + hoverNumber);
|
|
return componentFactory.timeNumberWithHoverText(mainNumber, hoverNumber, target);
|
|
}
|
|
}
|
|
}
|
|
|
|
private TextComponent getBasicTimeNumberComponent(long statNumber, Target target, Unit bigUnit, @Nullable Unit smallUnit) {
|
|
if (smallUnit == null) {
|
|
smallUnit = bigUnit.getSmallerUnit(1);
|
|
}
|
|
return componentFactory.timeNumber(formatter.formatTimeNumber(statNumber, bigUnit, smallUnit), target);
|
|
}
|
|
|
|
private TextComponent getDefaultNumberComponent(long statNumber, Target target) {
|
|
return componentFactory.statNumber(formatter.formatDefaultNumber(statNumber), target);
|
|
}
|
|
|
|
/**
|
|
* Provides its own space in front of it!
|
|
*/
|
|
private TextComponent getStatUnitComponent(Statistic statistic, Target target) {
|
|
Unit unit = switch (Unit.getTypeFromStatistic(statistic)) {
|
|
case DAMAGE -> Unit.fromString(config.getDamageUnit(false));
|
|
case DISTANCE -> Unit.fromString(config.getDistanceUnit(false));
|
|
default -> Unit.NUMBER;
|
|
};
|
|
return getStatUnitComponent(unit, target);
|
|
}
|
|
|
|
private TextComponent getStatUnitComponent(@NotNull Unit unit, Target target) {
|
|
return switch (unit.getType()) {
|
|
case DAMAGE -> getDamageUnitComponent(unit, target);
|
|
case DISTANCE -> getDistanceUnitComponent(unit, target);
|
|
default -> Component.empty();
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Provides its own space in front of it!
|
|
*/
|
|
private @NotNull TextComponent getDistanceUnitComponent(Unit unit, Target target) {
|
|
if (config.useTranslatableComponents()) {
|
|
String unitKey = languageKeyHandler.getUnitKey(unit);
|
|
if (unitKey != null) {
|
|
return Component.space()
|
|
.append(componentFactory.statUnitTranslatable(unitKey, target));
|
|
}
|
|
}
|
|
return Component.space()
|
|
.append(componentFactory.statUnit(unit.getLabel(), target));
|
|
}
|
|
|
|
/**
|
|
* Provides its own space in front of it!
|
|
*/
|
|
private @NotNull TextComponent getDamageUnitComponent(Unit unit, Target target) {
|
|
if (unit == Unit.HEART) {
|
|
TextComponent heartUnit = useHoverText ?
|
|
componentFactory.heartBetweenBracketsWithHoverText() :
|
|
componentFactory.heartBetweenBrackets();
|
|
return Component.space().append(heartUnit);
|
|
}
|
|
return Component.space()
|
|
.append(componentFactory.statUnit(unit.getLabel(), target));
|
|
}
|
|
|
|
private Component getSharerNameComponent(CommandSender sender) {
|
|
if (sender instanceof Player player) {
|
|
Component senderName = EasterEggProvider.getPlayerName(player);
|
|
if (senderName != null) {
|
|
return senderName;
|
|
}
|
|
}
|
|
return componentFactory.sharerName(sender.getName());
|
|
}
|
|
|
|
private @NotNull FormattingFunction getFormattingFunction(@NotNull TextComponent statResult, Target target) {
|
|
boolean useEnters = config.useEnters(target, false);
|
|
boolean useEntersForShared = config.useEnters(target, true);
|
|
|
|
BiFunction<Integer, CommandSender, TextComponent> biFunction = (shareCode, sender) -> {
|
|
TextComponent.Builder statBuilder = text();
|
|
|
|
//if we're adding a share-button
|
|
if (shareCode != null) {
|
|
if (useEnters) {
|
|
statBuilder.append(newline());
|
|
}
|
|
statBuilder.append(statResult)
|
|
.append(space())
|
|
.append(componentFactory.shareButton(shareCode));
|
|
}
|
|
//if we're adding a "shared by" component
|
|
else if (sender != null) {
|
|
if (useEntersForShared) {
|
|
statBuilder.append(newline());
|
|
}
|
|
statBuilder.append(statResult)
|
|
.append(newline())
|
|
.append(componentFactory.sharedByMessage(
|
|
getSharerNameComponent(sender)));
|
|
}
|
|
//if we're not adding a share-button or a "shared by" component
|
|
else {
|
|
if (useEnters) {
|
|
statBuilder.append(newline());
|
|
}
|
|
statBuilder.append(statResult);
|
|
}
|
|
return statBuilder.build();
|
|
};
|
|
return new FormattingFunction(biFunction);
|
|
}
|
|
|
|
private int getNumberOfDotsToAlign(String displayText) {
|
|
if (componentFactory.isConsoleFactory()) {
|
|
return FontUtils.getNumberOfDotsToAlignForConsole(displayText);
|
|
} else if (config.playerNameIsBold()) {
|
|
return FontUtils.getNumberOfDotsToAlignForBoldText(displayText);
|
|
} else {
|
|
return FontUtils.getNumberOfDotsToAlign(displayText);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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 @NotNull 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 (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)));
|
|
}
|
|
}
|
|
return unitRange;
|
|
}
|
|
} |