Fixed language bugs (#123), improved LanguageKeyHandler, ComponentUtils and StringUtils

This commit is contained in:
Artemis-the-gr8 2022-10-04 16:48:09 +02:00
parent 9ac77a365b
commit 2c7717a20c
9 changed files with 208 additions and 184 deletions

View File

@ -81,18 +81,6 @@ public final class Main extends JavaPlugin {
this.getLogger().info("Disabled PlayerStats!");
}
/**
*
* @return the JavaPlugin instance associated with PlayerStats
* @throws IllegalStateException if PlayerStats is not enabled
*/
public static @NotNull JavaPlugin getPluginInstance() throws IllegalStateException {
if (pluginInstance == null) {
throw new IllegalStateException("PlayerStats is not loaded!");
}
return pluginInstance;
}
/**
* @return Adventure's BukkitAudiences object
* @throws IllegalStateException if PlayerStats is not enabled
@ -105,19 +93,44 @@ public final class Main extends JavaPlugin {
}
/**
* @return PlayerStats' ConfigHandler
*
* @return the JavaPlugin instance associated with PlayerStats
* @throws IllegalStateException if PlayerStats is not enabled
*/
public static @NotNull ConfigHandler getConfigHandler() throws IllegalStateException {
if (config == null) {
public static @NotNull JavaPlugin getPluginInstance() throws IllegalStateException {
if (pluginInstance == null) {
throw new IllegalStateException("PlayerStats is not loaded!");
}
return pluginInstance;
}
public static @NotNull PlayerStats getPlayerStatsAPI() throws IllegalStateException {
if (playerStatsAPI == null) {
throw new IllegalStateException("PlayerStats does not seem to be loaded!");
}
return playerStatsAPI;
}
public static @NotNull InternalFormatter getOutputManager() throws IllegalStateException {
if (outputManager == null) {
throw new IllegalStateException("PlayerStats does not seem to be loaded!");
}
return outputManager;
}
/**
* @return PlayerStats' ConfigHandler
*/
public static @NotNull ConfigHandler getConfigHandler() {
if (config == null) {
config = new ConfigHandler();
}
return config;
}
public static @NotNull OfflinePlayerHandler getOfflinePlayerHandler() throws IllegalStateException {
public static @NotNull OfflinePlayerHandler getOfflinePlayerHandler() {
if (offlinePlayerHandler == null) {
throw new IllegalStateException("PlayerStats does not seem to be loaded!");
offlinePlayerHandler = new OfflinePlayerHandler(getConfigHandler());
}
return offlinePlayerHandler;
}
@ -140,27 +153,13 @@ public final class Main extends JavaPlugin {
return enumHandler;
}
public static @NotNull StatCalculator getStatCalculator() throws IllegalStateException {
public static @NotNull StatCalculator getStatCalculator() {
if (statCalculator == null) {
throw new IllegalStateException("PlayerStats does not seem to be loaded!");
statCalculator = new StatCalculator(getOfflinePlayerHandler());
}
return statCalculator;
}
public static @NotNull InternalFormatter getStatFormatter() throws IllegalStateException {
if (outputManager == null) {
throw new IllegalStateException("PlayerStats does not seem to be loaded!");
}
return outputManager;
}
public static @NotNull PlayerStats getPlayerStatsAPI() throws IllegalStateException {
if (playerStatsAPI == null) {
throw new IllegalStateException("PlayerStats does not seem to be loaded!");
}
return playerStatsAPI;
}
private void initializeMainClasses() {
pluginInstance = this;
adventure = BukkitAudiences.create(this);

View File

@ -20,6 +20,7 @@ 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;
@ -61,11 +62,13 @@ public final class MessageBuilder implements ApiFormatter {
languageKeyHandler = Main.getLanguageKeyHandler();
}
public static MessageBuilder defaultBuilder(ConfigHandler config) {
@Contract("_ -> new")
public static @NotNull MessageBuilder defaultBuilder(ConfigHandler config) {
return new MessageBuilder(config);
}
public static MessageBuilder fromComponentFactory(ConfigHandler config, ComponentFactory factory) {
@Contract("_, _ -> new")
public static @NotNull MessageBuilder fromComponentFactory(ConfigHandler config, ComponentFactory factory) {
return new MessageBuilder(config, factory);
}
@ -103,20 +106,20 @@ public final class MessageBuilder implements ApiFormatter {
return pride.pluginPrefixAsTitle();
}
public TextComponent reloadedConfig() {
public @NotNull TextComponent reloadedConfig() {
return componentFactory.pluginPrefix()
.append(space())
.append(componentFactory.message().content("Config reloaded!"));
}
public TextComponent stillReloading() {
public @NotNull TextComponent stillReloading() {
return componentFactory.pluginPrefix()
.append(space())
.append(componentFactory.message().content(
"The plugin is (re)loading, your request will be processed when it is done!"));
}
public TextComponent waitAMoment(boolean longWait) {
public @NotNull TextComponent waitAMoment(boolean longWait) {
String msg = longWait ? "Calculating statistics, this may take a minute..." :
"Calculating statistics, this may take a few moments...";
return componentFactory.pluginPrefix()
@ -124,28 +127,28 @@ public final class MessageBuilder implements ApiFormatter {
.append(componentFactory.message().content(msg));
}
public TextComponent missingStatName() {
public @NotNull TextComponent missingStatName() {
return componentFactory.pluginPrefix()
.append(space())
.append(componentFactory.message().content(
"Please provide a valid statistic name!"));
}
public TextComponent missingSubStatName(Statistic.Type statType) {
public @NotNull TextComponent missingSubStatName(Statistic.Type statType) {
return componentFactory.pluginPrefix()
.append(space())
.append(componentFactory.message().content(
"Please add a valid " + EnumHandler.getSubStatTypeName(statType) + " to look up this statistic!"));
}
public TextComponent missingPlayerName() {
public @NotNull TextComponent missingPlayerName() {
return componentFactory.pluginPrefix()
.append(space())
.append(componentFactory.message().content(
"Please specify a valid player-name!"));
}
public TextComponent wrongSubStatType(Statistic.Type statType, String subStatName) {
public @NotNull TextComponent wrongSubStatType(Statistic.Type statType, String subStatName) {
return componentFactory.pluginPrefix()
.append(space())
.append(componentFactory.messageAccent().content("\"" + subStatName + "\""))
@ -154,14 +157,14 @@ public final class MessageBuilder implements ApiFormatter {
"is not a valid " + EnumHandler.getSubStatTypeName(statType) + "!"));
}
public TextComponent requestAlreadyRunning() {
public @NotNull TextComponent requestAlreadyRunning() {
return componentFactory.pluginPrefix()
.append(space())
.append(componentFactory.message().content(
"Please wait for your previous lookup to finish!"));
}
public TextComponent stillOnShareCoolDown() {
public @NotNull TextComponent stillOnShareCoolDown() {
int waitTime = config.getStatShareWaitingTime();
String minutes = waitTime == 1 ? " minute" : " minutes";
@ -175,20 +178,20 @@ public final class MessageBuilder implements ApiFormatter {
.append(text("between sharing!")));
}
public TextComponent resultsAlreadyShared() {
public @NotNull TextComponent resultsAlreadyShared() {
return componentFactory.pluginPrefix()
.append(space())
.append(componentFactory.message().content("You already shared these results!"));
}
public TextComponent statResultsTooOld() {
public @NotNull TextComponent statResultsTooOld() {
return componentFactory.pluginPrefix()
.append(space())
.append(componentFactory.message().content(
"It has been too long since you looked up this statistic, please repeat the original command!"));
}
public TextComponent unknownError() {
public @NotNull TextComponent unknownError() {
return componentFactory.pluginPrefix()
.append(space())
.append(componentFactory.message().content(
@ -196,7 +199,8 @@ public final class MessageBuilder implements ApiFormatter {
"please try again or see /statistic for a usage explanation!"));
}
public TextComponent usageExamples() {
@Contract(" -> new")
public @NotNull TextComponent usageExamples() {
return ExampleMessage.construct(componentFactory);
}
@ -210,33 +214,33 @@ public final class MessageBuilder implements ApiFormatter {
}
@Override
public TextComponent getStatTitle(Statistic statistic, @Nullable String subStatName) {
public @NotNull TextComponent getStatTitle(Statistic statistic, @Nullable String subStatName) {
return getTopStatTitleComponent(0, statistic, subStatName, null);
}
@Override
public TextComponent getStatTitle(Statistic statistic, Unit unit) {
public @NotNull TextComponent getStatTitle(Statistic statistic, Unit unit) {
return getTopStatTitleComponent(0, statistic, null, unit);
}
@Override
public TextComponent getTopStatTitle(int topListSize, Statistic statistic, @Nullable String subStatName) {
public @NotNull TextComponent getTopStatTitle(int topListSize, Statistic statistic, @Nullable String subStatName) {
return getTopStatTitleComponent(topListSize, statistic, subStatName, null);
}
@Override
public TextComponent getTopStatTitle(int topStatSize, Statistic statistic, Unit unit) {
public @NotNull TextComponent getTopStatTitle(int topStatSize, Statistic statistic, Unit unit) {
return getTopStatTitleComponent(topStatSize, statistic, null, unit);
}
@Override
public TextComponent formatTopStatLine(int positionInTopList, String playerName, long statNumber, Statistic statistic) {
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 TextComponent formatTopStatLine(int positionInTopList, String playerName, long statNumber, Unit unit) {
public @NotNull TextComponent formatTopStatLine(int positionInTopList, String playerName, long statNumber, Unit unit) {
TextComponent statNumberComponent = getStatNumberComponent(statNumber, Target.TOP, unit);
return getTopStatLineComponent(positionInTopList, playerName, statNumberComponent);
}
@ -245,55 +249,55 @@ public final class MessageBuilder implements ApiFormatter {
* Time-number does not hover
*/
@Override
public TextComponent formatTopStatLineForTypeTime(int positionInTopList, String playerName, long statNumber, Unit bigUnit, Unit smallUnit) {
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 TextComponent formatServerStat(long statNumber, Statistic statistic) {
public @NotNull TextComponent formatServerStat(long statNumber, Statistic statistic) {
TextComponent statNumberComponent = getStatNumberComponent(statNumber, Target.SERVER, statistic);
return getServerStatComponent(statNumberComponent, statistic, null, null);
}
@Override
public TextComponent formatServerStat(long statNumber, Statistic statistic, String subStatName) {
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 TextComponent formatServerStat(long statNumber, Statistic statistic, Unit unit) {
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 TextComponent formatServerStatForTypeTime(long statNumber, Statistic statistic, Unit bigUnit, Unit smallUnit) {
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 TextComponent formatPlayerStat(String playerName, int statNumber, Statistic statistic) {
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 TextComponent formatPlayerStat(String playerName, int statNumber, Statistic statistic, Unit unit) {
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 TextComponent formatPlayerStat(String playerName, int statNumber, Statistic statistic, String subStatName) {
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 TextComponent formatPlayerStatForTypeTime(String playerName, int statNumber, Statistic statistic, Unit bigUnit, Unit smallUnit) {
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);
}
@ -309,7 +313,7 @@ public final class MessageBuilder implements ApiFormatter {
* <br>- If both parameters are null, the formattedComponent will be returned
* as is.
*/
public BiFunction<Integer, CommandSender, TextComponent> formattedPlayerStatFunction(int stat, @NotNull RequestSettings request) {
public @NotNull BiFunction<Integer, CommandSender, TextComponent> formattedPlayerStatFunction(int stat, @NotNull RequestSettings request) {
TextComponent playerStat = formatPlayerStat(request.getPlayerName(), stat, request.getStatistic(), request.getSubStatEntryName());
return getFormattingFunction(playerStat, Target.PLAYER);
}
@ -325,7 +329,7 @@ public final class MessageBuilder implements ApiFormatter {
* <br>- If both parameters are null, the formattedComponent will be returned
* as is.
*/
public BiFunction<Integer, CommandSender, TextComponent> formattedServerStatFunction(long stat, @NotNull RequestSettings request) {
public @NotNull BiFunction<Integer, CommandSender, TextComponent> formattedServerStatFunction(long stat, @NotNull RequestSettings request) {
TextComponent serverStat = formatServerStat(stat, request.getStatistic(), request.getSubStatEntryName());
return getFormattingFunction(serverStat, Target.SERVER);
}
@ -341,7 +345,7 @@ public final class MessageBuilder implements ApiFormatter {
* <br>- If both parameters are null, the formattedComponent will be returned
* as is.
*/
public BiFunction<Integer, CommandSender, TextComponent> formattedTopStatFunction(@NotNull LinkedHashMap<String, Integer> topStats, @NotNull RequestSettings request) {
public @NotNull BiFunction<Integer, CommandSender, TextComponent> formattedTopStatFunction(@NotNull LinkedHashMap<String, Integer> topStats, @NotNull RequestSettings 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);
@ -393,7 +397,7 @@ public final class MessageBuilder implements ApiFormatter {
};
}
private TextComponent getPlayerStatComponent(String playerName, TextComponent statNumberComponent, Statistic statistic, @Nullable String subStatName, @Nullable Unit unit) {
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);
@ -409,7 +413,7 @@ public final class MessageBuilder implements ApiFormatter {
.build();
}
private TextComponent getServerStatComponent(TextComponent statNumber, Statistic statistic, @Nullable String subStatName, @Nullable Unit unit) {
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) ?
@ -428,7 +432,7 @@ public final class MessageBuilder implements ApiFormatter {
.build();
}
private TextComponent getTopStatTitleComponent(int topListSize, Statistic statistic, @Nullable String subStatName, @Nullable Unit unit) {
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);
@ -450,7 +454,7 @@ public final class MessageBuilder implements ApiFormatter {
}
}
private TextComponent getTopStatListComponent(LinkedHashMap<String, Integer> topStats, Statistic statistic) {
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();
@ -472,7 +476,7 @@ public final class MessageBuilder implements ApiFormatter {
return topList.build();
}
private TextComponent getTopStatLineComponent(int positionInTopList, String playerName, TextComponent statNumberComponent) {
private @NotNull TextComponent getTopStatLineComponent(int positionInTopList, String playerName, TextComponent statNumberComponent) {
boolean useDots = config.useDots();
String fullPlayerName = useDots ? playerName : playerName + ":";
@ -498,27 +502,27 @@ public final class MessageBuilder implements ApiFormatter {
}
private TextComponent getStatAndSubStatNameComponent(Statistic statistic, @Nullable String subStatName, Target target) {
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()) {
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);
}
return componentFactory.statAndSubStatNameTranslatable(statKey, subStatKey, target);
}
//TODO turn key into custom input from file
String prettyStatName = StringUtils.prettify(statistic.toString());
String prettySubStatName = StringUtils.prettify(subStatName);
String prettyStatName = languageKeyHandler.convertLanguageKeyToDisplayName(statKey);
String prettySubStatName = languageKeyHandler.convertLanguageKeyToDisplayName(subStatKey);
return componentFactory.statAndSubStatName(prettyStatName, prettySubStatName, target);
}
private TextComponent getStatNumberComponent(long statNumber, Target target, Unit unit) {
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);
@ -619,7 +623,7 @@ public final class MessageBuilder implements ApiFormatter {
return getStatUnitComponent(unit, target);
}
private TextComponent getStatUnitComponent(Unit unit, Target target) {
private TextComponent getStatUnitComponent(@NotNull Unit unit, Target target) {
return switch (unit.getType()) {
case DAMAGE -> getDamageUnitComponent(unit, target);
case DISTANCE -> getDistanceUnitComponent(unit, target);
@ -630,7 +634,7 @@ public final class MessageBuilder implements ApiFormatter {
/**
* Provides its own space in front of it!
*/
private TextComponent getDistanceUnitComponent(Unit unit, Target target) {
private @NotNull TextComponent getDistanceUnitComponent(Unit unit, Target target) {
if (config.useTranslatableComponents()) {
String unitKey = languageKeyHandler.getUnitKey(unit);
if (unitKey != null) {
@ -645,7 +649,7 @@ public final class MessageBuilder implements ApiFormatter {
/**
* Provides its own space in front of it!
*/
private TextComponent getDamageUnitComponent(Unit unit, Target target) {
private @NotNull TextComponent getDamageUnitComponent(Unit unit, Target target) {
if (unit == Unit.HEART) {
TextComponent heartUnit;
if (isConsoleBuilder) {
@ -672,7 +676,7 @@ public final class MessageBuilder implements ApiFormatter {
return componentFactory.sharerName(sender.getName());
}
private BiFunction<Integer, CommandSender, TextComponent> getFormattingFunction(@NotNull TextComponent statResult, Target target) {
private @NotNull BiFunction<Integer, CommandSender, TextComponent> getFormattingFunction(@NotNull TextComponent statResult, Target target) {
boolean useEnters = config.useEnters(target, false);
boolean useEntersForShared = config.useEnters(target, true);
@ -726,7 +730,7 @@ public final class MessageBuilder implements ApiFormatter {
* <p>2. maxHoverUnit</p>
* <p>3. minHoverUnit</p>
*/
private ArrayList<Unit> getTimeUnitRange(long statNumber) {
private @NotNull ArrayList<Unit> getTimeUnitRange(long statNumber) {
ArrayList<Unit> unitRange = new ArrayList<>();
if (!config.autoDetectTimeUnit(false)) {
unitRange.add(Unit.fromString(config.getTimeUnit(false)));

View File

@ -225,10 +225,10 @@ public class ComponentFactory {
getStyleFromString(config.getStatNameDecoration(target, true)));
TextComponent subStat = subStatNameTranslatable(subStatKey, target);
if (LanguageKeyHandler.isKeyForKillEntity(statKey)) {
if (LanguageKeyHandler.isNormalKeyForKillEntity(statKey)) {
return totalStatNameBuilder.append(killEntityBuilder(subStat)).build();
}
else if (LanguageKeyHandler.isKeyForEntityKilledBy(statKey)) {
else if (LanguageKeyHandler.isNormalKeyForEntityKilledBy(statKey)) {
return totalStatNameBuilder.append(entityKilledByBuilder(subStat)).build();
}
else {
@ -370,7 +370,7 @@ public class ComponentFactory {
*/
private TranslatableComponent.Builder killEntityBuilder(@NotNull TextComponent subStat) {
return translatable()
.key(LanguageKeyHandler.getAlternativeKeyForKillEntity()) //"Killed %s"
.key(LanguageKeyHandler.getCustomKeyForKillEntity()) //"Killed %s"
.args(subStat);
}
@ -384,10 +384,10 @@ public class ComponentFactory {
*/
private TranslatableComponent.Builder entityKilledByBuilder(@NotNull TextComponent subStat) {
return translatable()
.key(LanguageKeyHandler.getAlternativeKeyForEntityKilledBy()) //"Number of Deaths"
.key(LanguageKeyHandler.getCustomKeyForEntityKilledBy()) //"Number of Deaths"
.append(space())
.append(translatable()
.key(LanguageKeyHandler.getAlternativeKeyForEntityKilledByArg()) //"by %s"
.key(LanguageKeyHandler.getCustomKeyForEntityKilledByArg()) //"by %s"
.args(subStat));
}

View File

@ -2,10 +2,11 @@ package com.artemis.the.gr8.playerstats.msg.components;
import com.artemis.the.gr8.playerstats.Main;
import com.artemis.the.gr8.playerstats.msg.msgutils.LanguageKeyHandler;
import com.artemis.the.gr8.playerstats.msg.msgutils.StringUtils;
import net.kyori.adventure.text.*;
import net.kyori.adventure.text.flattener.ComponentFlattener;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
/**
* A small utility class for turning PlayerStats' custom Components into String.
@ -22,19 +23,20 @@ public final class ComponentUtils {
* @return the Serializer
* @see LanguageKeyHandler
*/
public static LegacyComponentSerializer getTranslatableComponentSerializer() {
public static @NotNull LegacyComponentSerializer getTranslatableComponentSerializer() {
LanguageKeyHandler languageKeyHandler = Main.getLanguageKeyHandler();
LegacyComponentSerializer serializer = getTextComponentSerializer();
ComponentFlattener flattener = ComponentFlattener.basic().toBuilder()
.mapper(TranslatableComponent.class, trans -> {
StringBuilder totalPrettyName = new StringBuilder();
if (LanguageKeyHandler.isKeyForEntityKilledByArg(trans.key())) {
if (LanguageKeyHandler.isCustomKeyForEntityKilledByArg(trans.key())) {
return "";
}
else if (LanguageKeyHandler.isKeyForEntityKilledBy(trans.key()) ||
LanguageKeyHandler.isAlternativeKeyForEntityKilledBy(trans.key()) ||
LanguageKeyHandler.isKeyForKillEntity(trans.key()) ||
LanguageKeyHandler.isAlternativeKeyForKillEntity(trans.key())) {
else if (LanguageKeyHandler.isNormalKeyForEntityKilledBy(trans.key()) ||
LanguageKeyHandler.isCustomKeyForEntityKilledBy(trans.key()) ||
LanguageKeyHandler.isNormalKeyForKillEntity(trans.key()) ||
LanguageKeyHandler.isCustomKeyForKillEntity(trans.key())) {
TextComponent.Builder temp = Component.text();
trans.iterator(ComponentIteratorType.DEPTH_FIRST, ComponentIteratorFlag.INCLUDE_TRANSLATABLE_COMPONENT_ARGUMENTS)
@ -51,28 +53,25 @@ public final class ComponentUtils {
}
//isolate the translatable component with the entity inside
else if (component instanceof TranslatableComponent translatable) {
if (translatable.key().contains("entity.")) {
if (LanguageKeyHandler.isEntityKey(translatable.key())) {
temp.append(Component.space())
.append(Component.text("(")
.append(Component.text(
StringUtils.prettify(LanguageKeyHandler.convertToName(translatable.key()))))
languageKeyHandler.convertLanguageKeyToDisplayName(translatable.key())))
.append(Component.text(")")));
totalPrettyName.append(
serializer.serialize(temp.build()));
}
else if (!LanguageKeyHandler.isKeyForEntityKilledByArg(translatable.key())) {
else if (!LanguageKeyHandler.isCustomKeyForEntityKilledByArg(translatable.key())) {
totalPrettyName.append(
Main.getLanguageKeyHandler().getStatKeyTranslation(
languageKeyHandler.convertLanguageKeyToDisplayName(
translatable.key()));
}
}
});
}
else if (trans.key().startsWith("stat")) {
return Main.getLanguageKeyHandler().getStatKeyTranslation(trans.key());
}
else {
return StringUtils.prettify(LanguageKeyHandler.convertToName(trans.key()));
return languageKeyHandler.convertLanguageKeyToDisplayName(trans.key());
}
return totalPrettyName.toString();
})
@ -81,7 +80,8 @@ public final class ComponentUtils {
return serializer.toBuilder().flattener(flattener).build();
}
private static LegacyComponentSerializer getTextComponentSerializer() {
@Contract(" -> new")
private static @NotNull LegacyComponentSerializer getTextComponentSerializer() {
return LegacyComponentSerializer
.builder()
.hexColors()

View File

@ -6,11 +6,14 @@ import com.artemis.the.gr8.playerstats.enums.Unit;
import org.bukkit.Material;
import org.bukkit.Statistic;
import org.bukkit.entity.EntityType;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
*
@ -19,7 +22,8 @@ import java.util.HashMap;
*/
public final class LanguageKeyHandler extends FileHandler {
private static HashMap<Statistic, String> statNameKeys;
private static HashMap<Statistic, String> statisticKeys;
private final Pattern subStatKey;
/**
* This class uses a file to get the English translations
@ -28,7 +32,18 @@ public final class LanguageKeyHandler extends FileHandler {
*/
public LanguageKeyHandler() {
super("language.yml");
statNameKeys = generateStatNameKeys();
statisticKeys = generateStatisticKeys();
subStatKey = Pattern.compile("(item|entity|block)\\.minecraft\\.");
}
@Contract(pure = true)
public @NotNull String getKeyForBlockUnit() {
return "soundCategory.block";
}
@Contract(pure = true)
public static boolean isEntityKey(@NotNull String key) {
return key.contains("entity.minecraft");
}
/**
@ -37,7 +52,8 @@ public final class LanguageKeyHandler extends FileHandler {
* @param statKey the Key to check
* @return true if this Key is key for kill-entity
*/
public static boolean isKeyForKillEntity(String statKey) {
@Contract(pure = true)
public static boolean isNormalKeyForKillEntity(@NotNull String statKey) {
return statKey.equalsIgnoreCase("stat_type.minecraft.killed");
}
@ -47,7 +63,8 @@ public final class LanguageKeyHandler extends FileHandler {
* @param statKey the Key to check
* @return true if this Key is key for commands.kill.success.single
*/
public static boolean isAlternativeKeyForKillEntity(String statKey) {
@Contract(pure = true)
public static boolean isCustomKeyForKillEntity(@NotNull String statKey) {
return statKey.equalsIgnoreCase("commands.kill.success.single");
}
@ -56,7 +73,8 @@ public final class LanguageKeyHandler extends FileHandler {
*
* @return the key "commands.kill.success.single", which results in "Killed %s"
*/
public static String getAlternativeKeyForKillEntity() {
@Contract(pure = true)
public static @NotNull String getCustomKeyForKillEntity() {
return "commands.kill.success.single";
}
@ -66,27 +84,19 @@ public final class LanguageKeyHandler extends FileHandler {
* @param statKey the Key to check
* @return true if this Key is a key for entity-killed-by
*/
public static boolean isKeyForEntityKilledBy(String statKey) {
@Contract(pure = true)
public static boolean isNormalKeyForEntityKilledBy(@NotNull String statKey) {
return statKey.equalsIgnoreCase("stat_type.minecraft.killed_by");
}
/**
* Checks if a given Key is the language key "stat.minecraft.deaths".
* Checks if a given Key is the language key "subtitles.entity.generic.death".
* @param statKey the Key to check
* @return true if this Key is key for stat.minecraft.deaths
* @return true if this Key is key for subtitles.entity.generic.death
*/
public static boolean isAlternativeKeyForEntityKilledBy(String statKey) {
return statKey.equalsIgnoreCase("stat.minecraft.deaths");
}
/**
* Returns a language key to replace the default stat_type.minecraft.killed_by key.
*
* @return the key "stat.minecraft.deaths", which results in "Number of Deaths"
* (meant to be followed by {@link #getAlternativeKeyForEntityKilledByArg()})
*/
public static String getAlternativeKeyForEntityKilledBy() {
return "stat.minecraft.deaths";
@Contract(pure = true)
public static boolean isCustomKeyForEntityKilledBy(@NotNull String statKey) {
return statKey.equalsIgnoreCase("subtitles.entity.generic.death");
}
/**
@ -96,70 +106,75 @@ public final class LanguageKeyHandler extends FileHandler {
* @param statKey the Key to Check
* @return true if this Key is the key for book.byAuthor
*/
public static boolean isKeyForEntityKilledByArg(String statKey) {
@Contract(pure = true)
public static boolean isCustomKeyForEntityKilledByArg(@NotNull String statKey) {
return statKey.equalsIgnoreCase("book.byAuthor");
}
/**
* Returns a language key to complete the alternative key for Statistic.Entity_Killed_By.
* Returns a language key to replace the default stat_type.minecraft.killed_by key.
*
* @return the key "book.byAuthor", which results in "by %". If used after
* {@link #getAlternativeKeyForEntityKilledBy()}, you will get "Number of Deaths" "by %s"
* @return the key "subtitles.entity.generic.death", which results in "Dying"
* (meant to be followed by {@link #getCustomKeyForEntityKilledByArg()})
*/
public static String getAlternativeKeyForEntityKilledByArg() {
return "book.byAuthor";
@Contract(pure = true)
public static @NotNull String getCustomKeyForEntityKilledBy() {
return "subtitles.entity.generic.death";
}
/**
* @param key the String to turn into a normal name
* @return a pretty name
* Returns a language key to complete the alternative key for statistic.entity_killed_by.
*
* @return the key "book.byAuthor", which results in "by %". If used after
* {@link #getCustomKeyForEntityKilledBy()}, you will get "Dying" "by %s"
*/
public static String convertToName(String key) {
if (key.equalsIgnoreCase("soundCategory.block")) {
@Contract(pure = true)
public static @NotNull String getCustomKeyForEntityKilledByArg() {
return "book.byAuthor";
}
public String convertLanguageKeyToDisplayName(String key) {
if (key == null) return null;
if (isStatKey(key)) {
return getStatKeyTranslation(key);
}
else if (key.equalsIgnoreCase(getKeyForBlockUnit())) {
return Unit.BLOCK.getLabel();
} else if (isKeyForKillEntity(key)) {
return "times_killed";
} else if (isKeyForEntityKilledBy(key)) {
return "number_of_times_killed_by";
} else if (isKeyForEntityKilledByArg(key)) { //this one returns nothing, because it's an extra key I added
return ""; //to make the TranslatableComponent work
}
String toReplace = "";
if (key.contains("stat")) {
if (key.contains("type")) {
toReplace = "stat_type";
} else {
toReplace = "stat";
}
} else if (key.contains("entity")) { //for the two entity-related ones, put brackets around it to
toReplace = "entity"; //make up for the multiple-keys/args-serializer issues
} else if (key.contains("block")) {
toReplace = "block";
} else if (key.contains("item")) {
toReplace = "item";
Matcher matcher = subStatKey.matcher(key);
if (matcher.find()) {
String rawName = matcher.replaceFirst("");
return StringUtils.prettify(rawName);
}
toReplace = toReplace + ".minecraft.";
return key.replace(toReplace, "");
return key;
}
private static @Nullable String convertToNormalStatKey(String statKey) {
if (isKeyForKillEntity(statKey)) {
return "stat_type.minecraft.killed";
} else if (isKeyForEntityKilledBy(statKey)) {
return "stat_type.minecraft.killed_by";
} else if (isKeyForEntityKilledByArg(statKey)) {
return null;
} else {
return statKey;
}
private boolean isStatKey(@NotNull String key) {
return (key.contains("stat") ||
isCustomKeyForKillEntity(key) ||
isCustomKeyForEntityKilledBy(key) ||
isCustomKeyForEntityKilledByArg(key));
}
public String getStatKeyTranslation(String statKey) {
private String getStatKeyTranslation(String statKey) {
String realKey = convertToNormalStatKey(statKey);
if (realKey == null) {
return "";
}
return super.getFileConfiguration().getString(statKey);
return super.getFileConfiguration().getString(realKey);
}
private static @Nullable String convertToNormalStatKey(String statKey) {
if (isCustomKeyForKillEntity(statKey)) {
return "stat_type.minecraft.killed";
} else if (isCustomKeyForEntityKilledBy(statKey)) {
return "stat_type.minecraft.killed_by";
} else if (isCustomKeyForEntityKilledByArg(statKey)) {
return null;
} else {
return statKey;
}
}
/**
@ -167,12 +182,12 @@ public final class LanguageKeyHandler extends FileHandler {
* @return the official Key from the NameSpacedKey for this Statistic,
* or return null if no enum constant can be retrieved.
*/
public String getStatKey(@NotNull Statistic statistic) {
public @NotNull String getStatKey(@NotNull Statistic statistic) {
if (statistic.getType() == Statistic.Type.UNTYPED) {
return "stat.minecraft." + statNameKeys.get(statistic);
return "stat.minecraft." + statisticKeys.get(statistic);
}
else {
return "stat_type.minecraft." + statNameKeys.get(statistic);
return "stat_type.minecraft." + statisticKeys.get(statistic);
}
}
@ -232,7 +247,7 @@ public final class LanguageKeyHandler extends FileHandler {
}
}
private @NotNull HashMap<Statistic, String> generateStatNameKeys() {
private @NotNull HashMap<Statistic, String> generateStatisticKeys() {
//get the enum names for all statistics first
HashMap<Statistic, String> statNames = new HashMap<>(Statistic.values().length);
Arrays.stream(Statistic.values()).forEach(statistic -> statNames.put(statistic, statistic.toString().toLowerCase()));

View File

@ -18,15 +18,21 @@ public final class StringUtils {
*/
public static String prettify(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.logHighLevelMsg("Replacing underscores and capitalizing names...");
while (capitals.indexOf("_") != -1) {
MyLogger.logHighLevelMsg("Replacing underscores...");
int index = capitals.indexOf("_");
capitals.setCharAt(index + 1, Character.toUpperCase(capitals.charAt(index + 1)));
capitals.setCharAt(index, ' ');
}
while (capitals.indexOf(" ") != -1) {
MyLogger.logHighLevelMsg("Capitalizing names...");
int index = capitals.indexOf(" ") + 1;
capitals.setCharAt(index, Character.toUpperCase(capitals.charAt(index)));
}
return capitals.toString();
}
}

View File

@ -48,7 +48,7 @@ public final class PlayerStatRequest extends StatRequest<Integer> implements Req
.getPlayerStat(completedRequest);
TextComponent prettyComponent = Main
.getStatFormatter()
.getOutputManager()
.formatAndSavePlayerStat(completedRequest, stat);
String prettyString = ComponentUtils

View File

@ -48,7 +48,7 @@ public final class ServerStatRequest extends StatRequest<Long> implements Reques
.getServerStat(completedRequest);
TextComponent prettyComponent = Main
.getStatFormatter()
.getOutputManager()
.formatAndSaveServerStat(completedRequest, stat);
String prettyString = ComponentUtils

View File

@ -50,7 +50,7 @@ public final class TopStatRequest extends StatRequest<LinkedHashMap<String, Inte
.getTopStats(completedRequest);
TextComponent prettyComponent = Main
.getStatFormatter()
.getOutputManager()
.formatAndSaveTopStat(completedRequest, stat);
String prettyString = ComponentUtils