Move logic for config format into ConfigStringUtils

This commit is contained in:
nossr50 2024-11-02 19:39:06 -07:00
parent ce18f3df97
commit 39b0e87b9a
14 changed files with 470 additions and 88 deletions

View File

@ -18,6 +18,9 @@ import java.util.List;
import java.util.Locale;
import java.util.Set;
import static com.gmail.nossr50.util.text.ConfigStringUtils.getConfigPartyFeatureString;
import static com.gmail.nossr50.util.text.ConfigStringUtils.getMaterialConfigString;
public class GeneralConfig extends BukkitConfig {
public GeneralConfig(@NotNull File dataFolder) {
@ -122,7 +125,7 @@ public class GeneralConfig extends BukkitConfig {
for (PartyFeature partyFeature : PartyFeature.values()) {
if (getPartyFeatureUnlockLevel(partyFeature) < 0) {
reason.add("Party.Leveling." + StringUtils.getPrettyPartyFeatureString(partyFeature).replace(" ", "") + "_UnlockLevel should be at least 0!");
reason.add("Party.Leveling." + getConfigPartyFeatureString(partyFeature) + "_UnlockLevel should be at least 0!");
}
}
@ -627,7 +630,7 @@ public class GeneralConfig extends BukkitConfig {
}
public int getPartyFeatureUnlockLevel(PartyFeature partyFeature) {
return config.getInt("Party.Leveling." + StringUtils.getPrettyPartyFeatureString(partyFeature).replace(" ", "") + "_UnlockLevel", 0);
return config.getInt("Party.Leveling." + getConfigPartyFeatureString(partyFeature) + "_UnlockLevel", 0);
}
/* Party Teleport Settings */
@ -711,7 +714,7 @@ public class GeneralConfig extends BukkitConfig {
if (material.toString().equalsIgnoreCase("LILY_PAD"))
return false;
return config.getBoolean("Bonus_Drops." + StringUtils.getCapitalized(skill.toString()) + "." + StringUtils.getFormattedMaterialString(material).replace(" ", "_"));
return config.getBoolean("Bonus_Drops." + StringUtils.getCapitalized(skill.toString()) + "." + getMaterialConfigString(material).replace(" ", "_"));
}
public boolean getDoubleDropsDisabled(PrimarySkillType skill) {
@ -892,7 +895,7 @@ public class GeneralConfig extends BukkitConfig {
/* Woodcutting */
public boolean getWoodcuttingDoubleDropsEnabled(BlockData blockData) {
return config.getBoolean("Bonus_Drops.Woodcutting."
+ StringUtils.getFormattedMaterialString(blockData.getMaterial()));
+ getMaterialConfigString(blockData.getMaterial()));
}
public boolean getTreeFellerSoundsEnabled() {

View File

@ -20,6 +20,8 @@ import java.util.List;
import java.util.Map;
import static com.gmail.nossr50.util.skills.SkillTools.isChildSkill;
import static com.gmail.nossr50.util.text.ConfigStringUtils.getConfigEntityTypeString;
import static com.gmail.nossr50.util.text.ConfigStringUtils.getMaterialConfigString;
public class ExperienceConfig extends BukkitConfig {
private static ExperienceConfig instance;
@ -327,11 +329,11 @@ public class ExperienceConfig extends BukkitConfig {
}
public double getCombatXP(EntityType entity) {
return config.getDouble("Experience_Values.Combat.Multiplier." + StringUtils.getPrettyEntityTypeString(entity).replace(" ", "_"));
return config.getDouble("Experience_Values.Combat.Multiplier." + getConfigEntityTypeString(entity).replace(" ", "_"));
}
public double getAnimalsXP(EntityType entity) {
return config.getDouble("Experience_Values.Combat.Multiplier." + StringUtils.getPrettyEntityTypeString(entity).replace(" ", "_"), getAnimalsXP());
return config.getDouble("Experience_Values.Combat.Multiplier." + getConfigEntityTypeString(entity).replace(" ", "_"), getAnimalsXP());
}
public double getAnimalsXP() {
@ -339,7 +341,7 @@ public class ExperienceConfig extends BukkitConfig {
}
public boolean hasCombatXP(EntityType entity) {
return config.contains("Experience_Values.Combat.Multiplier." + StringUtils.getPrettyEntityTypeString(entity).replace(" ", "_"));
return config.contains("Experience_Values.Combat.Multiplier." + getConfigEntityTypeString(entity).replace(" ", "_"));
}
/* Materials */
@ -349,7 +351,7 @@ public class ExperienceConfig extends BukkitConfig {
return 0;
final String baseString = "Experience_Values." + StringUtils.getCapitalized(skill.toString()) + ".";
final String configPath = baseString + StringUtils.getFormattedMaterialString(material);
final String configPath = baseString + getMaterialConfigString(material);
return config.getInt(configPath, 0);
}
@ -479,7 +481,7 @@ public class ExperienceConfig extends BukkitConfig {
/* Taming */
public int getTamingXP(EntityType type) {
return config.getInt("Experience_Values.Taming.Animal_Taming." + StringUtils.getPrettyEntityTypeString(type));
return config.getInt("Experience_Values.Taming.Animal_Taming." + getConfigEntityTypeString(type));
}
public boolean preventStoneLavaFarming() {

View File

@ -1,12 +1,13 @@
package com.gmail.nossr50.config.party;
import com.gmail.nossr50.config.BukkitConfig;
import com.gmail.nossr50.util.text.StringUtils;
import org.bukkit.Material;
import java.util.HashSet;
import java.util.Locale;
import static com.gmail.nossr50.util.text.ConfigStringUtils.getMaterialConfigString;
public class ItemWeightConfig extends BukkitConfig {
private static ItemWeightConfig instance;
@ -23,7 +24,7 @@ public class ItemWeightConfig extends BukkitConfig {
}
public int getItemWeight(Material material) {
return config.getInt("Item_Weights." + StringUtils.getFormattedMaterialString(material).replace(" ", "_"), config.getInt("Item_Weights.Default"));
return config.getInt("Item_Weights." + getMaterialConfigString(material).replace(" ", "_"), config.getInt("Item_Weights.Default"));
}
public HashSet<Material> getMiscItems() {

View File

@ -7,7 +7,6 @@ import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.BlockUtils;
import com.gmail.nossr50.util.LogUtils;
import com.gmail.nossr50.util.PotionUtil;
import com.gmail.nossr50.util.text.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.Tag;
@ -22,6 +21,8 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import static com.gmail.nossr50.util.text.ConfigStringUtils.getMaterialConfigString;
public class TreasureConfig extends BukkitConfig {
public static final String FILENAME = "treasures.yml";
@ -239,29 +240,29 @@ public class TreasureConfig extends BukkitConfig {
for (String dropper : dropList) {
if (dropper.equals("Bushes")) {
AddHylianTreasure(StringUtils.getFormattedMaterialString(Material.FERN), hylianTreasure);
AddHylianTreasure(StringUtils.getFormattedMaterialString(BlockUtils.getShortGrass()), hylianTreasure);
AddHylianTreasure(getMaterialConfigString(Material.FERN), hylianTreasure);
AddHylianTreasure(getMaterialConfigString(BlockUtils.getShortGrass()), hylianTreasure);
for (Material species : Tag.SAPLINGS.getValues())
AddHylianTreasure(StringUtils.getFormattedMaterialString(species), hylianTreasure);
AddHylianTreasure(getMaterialConfigString(species), hylianTreasure);
AddHylianTreasure(StringUtils.getFormattedMaterialString(Material.DEAD_BUSH), hylianTreasure);
AddHylianTreasure(getMaterialConfigString(Material.DEAD_BUSH), hylianTreasure);
continue;
}
if (dropper.equals("Flowers")) {
AddHylianTreasure(StringUtils.getFormattedMaterialString(Material.POPPY), hylianTreasure);
AddHylianTreasure(StringUtils.getFormattedMaterialString(Material.DANDELION), hylianTreasure);
AddHylianTreasure(StringUtils.getFormattedMaterialString(Material.BLUE_ORCHID), hylianTreasure);
AddHylianTreasure(StringUtils.getFormattedMaterialString(Material.ALLIUM), hylianTreasure);
AddHylianTreasure(StringUtils.getFormattedMaterialString(Material.AZURE_BLUET), hylianTreasure);
AddHylianTreasure(StringUtils.getFormattedMaterialString(Material.ORANGE_TULIP), hylianTreasure);
AddHylianTreasure(StringUtils.getFormattedMaterialString(Material.PINK_TULIP), hylianTreasure);
AddHylianTreasure(StringUtils.getFormattedMaterialString(Material.RED_TULIP), hylianTreasure);
AddHylianTreasure(StringUtils.getFormattedMaterialString(Material.WHITE_TULIP), hylianTreasure);
AddHylianTreasure(getMaterialConfigString(Material.POPPY), hylianTreasure);
AddHylianTreasure(getMaterialConfigString(Material.DANDELION), hylianTreasure);
AddHylianTreasure(getMaterialConfigString(Material.BLUE_ORCHID), hylianTreasure);
AddHylianTreasure(getMaterialConfigString(Material.ALLIUM), hylianTreasure);
AddHylianTreasure(getMaterialConfigString(Material.AZURE_BLUET), hylianTreasure);
AddHylianTreasure(getMaterialConfigString(Material.ORANGE_TULIP), hylianTreasure);
AddHylianTreasure(getMaterialConfigString(Material.PINK_TULIP), hylianTreasure);
AddHylianTreasure(getMaterialConfigString(Material.RED_TULIP), hylianTreasure);
AddHylianTreasure(getMaterialConfigString(Material.WHITE_TULIP), hylianTreasure);
continue;
}
if (dropper.equals("Pots")) {
for (Material species : Tag.FLOWER_POTS.getValues())
AddHylianTreasure(StringUtils.getFormattedMaterialString(species), hylianTreasure);
AddHylianTreasure(getMaterialConfigString(species), hylianTreasure);
continue;
}
AddHylianTreasure(dropper, hylianTreasure);

View File

@ -4,9 +4,10 @@ import com.gmail.nossr50.commands.party.PartySubcommandType;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.text.StringUtils;
import org.bukkit.entity.Player;
import static com.gmail.nossr50.util.text.ConfigStringUtils.getConfigPartyFeatureString;
public enum PartyFeature {
CHAT,
TELEPORT,
@ -15,11 +16,11 @@ public enum PartyFeature {
XP_SHARE;
public String getLocaleString() {
return LocaleLoader.getString("Party.Feature." + StringUtils.getPrettyPartyFeatureString(this).replace(" ", ""));
return LocaleLoader.getString("Party.Feature." + getConfigPartyFeatureString(this));
}
public String getFeatureLockedLocaleString() {
return LocaleLoader.getString("Ability.Generic.Template.Lock", LocaleLoader.getString("Party.Feature.Locked." + StringUtils.getPrettyPartyFeatureString(this).replace(" ", ""), mcMMO.p.getGeneralConfig().getPartyFeatureUnlockLevel(this)));
return LocaleLoader.getString("Ability.Generic.Template.Lock", LocaleLoader.getString("Party.Feature.Locked." + getConfigPartyFeatureString(this), mcMMO.p.getGeneralConfig().getPartyFeatureUnlockLevel(this)));
}
public boolean hasPermission(Player player) {

View File

@ -10,11 +10,12 @@ import com.gmail.nossr50.datatypes.skills.alchemy.PotionStage;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.skills.SkillManager;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.text.StringUtils;
import org.bukkit.inventory.ItemStack;
import java.util.List;
import static com.gmail.nossr50.util.text.ConfigStringUtils.getMaterialConfigString;
public class AlchemyManager extends SkillManager {
private final double LUCKY_MODIFIER = 4.0 / 3.0;
@ -34,7 +35,7 @@ public class AlchemyManager extends SkillManager {
StringBuilder list = new StringBuilder();
for (ItemStack ingredient : getIngredients()) {
String string = StringUtils.getFormattedMaterialString(ingredient.getType());
String string = getMaterialConfigString(ingredient.getType());
list.append(", ").append(string);
}

View File

@ -5,12 +5,13 @@ import com.gmail.nossr50.config.treasure.TreasureConfig;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.datatypes.treasure.ExcavationTreasure;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.text.StringUtils;
import org.bukkit.block.BlockState;
import java.util.ArrayList;
import java.util.List;
import static com.gmail.nossr50.util.text.ConfigStringUtils.getMaterialConfigString;
public class Excavation {
/**
* Get the list of possible {@link ExcavationTreasure|ExcavationTreasures} obtained from a given block.
@ -19,7 +20,7 @@ public class Excavation {
* @return the list of treasures that could be found
*/
protected static List<ExcavationTreasure> getTreasures(BlockState blockState) {
String friendly = StringUtils.getFormattedMaterialString(blockState.getBlockData().getMaterial());
String friendly = getMaterialConfigString(blockState.getBlockData().getMaterial());
if (TreasureConfig.getInstance().excavationMap.containsKey(friendly))
return TreasureConfig.getInstance().excavationMap.get(friendly);
return new ArrayList<>();

View File

@ -43,6 +43,7 @@ import java.util.*;
import static com.gmail.nossr50.util.ItemUtils.hasItemIncludingOffHand;
import static com.gmail.nossr50.util.ItemUtils.removeItemIncludingOffHand;
import static com.gmail.nossr50.util.text.ConfigStringUtils.getMaterialConfigString;
import static java.util.Objects.requireNonNull;
public class HerbalismManager extends SkillManager {
@ -714,10 +715,10 @@ public class HerbalismManager extends SkillManager {
return false;
}
final String friendly = StringUtils.getFormattedMaterialString(blockState.getBlockData().getMaterial());
if (!TreasureConfig.getInstance().hylianMap.containsKey(friendly))
final String materialConfigString = getMaterialConfigString(blockState.getBlockData().getMaterial());
if (!TreasureConfig.getInstance().hylianMap.containsKey(materialConfigString))
return false;
List<HylianTreasure> treasures = TreasureConfig.getInstance().hylianMap.get(friendly);
List<HylianTreasure> treasures = TreasureConfig.getInstance().hylianMap.get(materialConfigString);
if (treasures.isEmpty()) {
return false;
@ -750,12 +751,12 @@ public class HerbalismManager extends SkillManager {
PlayerInventory playerInventory = getPlayer().getInventory();
if (!playerInventory.contains(Material.BROWN_MUSHROOM, 1)) {
NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.REQUIREMENTS_NOT_MET, "Skills.NeedMore", StringUtils.getFormattedMaterialString(Material.BROWN_MUSHROOM));
NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.REQUIREMENTS_NOT_MET, "Skills.NeedMore", StringUtils.getPrettyMaterialString(Material.BROWN_MUSHROOM));
return false;
}
if (!playerInventory.contains(Material.RED_MUSHROOM, 1)) {
NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.REQUIREMENTS_NOT_MET, "Skills.NeedMore", StringUtils.getFormattedMaterialString(Material.RED_MUSHROOM));
NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.REQUIREMENTS_NOT_MET, "Skills.NeedMore", StringUtils.getPrettyMaterialString(Material.RED_MUSHROOM));
return false;
}

View File

@ -96,7 +96,7 @@ public class RepairManager extends SkillManager {
// Level check
if (skillLevel < minimumRepairableLevel) {
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Repair.Skills.Adept", String.valueOf(minimumRepairableLevel), StringUtils.getFormattedMaterialString(item.getType()));
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Repair.Skills.Adept", String.valueOf(minimumRepairableLevel), StringUtils.getPrettyMaterialString(item.getType()));
return;
}
@ -115,7 +115,7 @@ public class RepairManager extends SkillManager {
// Check if they have the proper material to repair with
if (!inventory.contains(repairMaterial)) {
String prettyName = repairable.getRepairMaterialPrettyName() == null ? StringUtils.getFormattedMaterialString(repairMaterial) : repairable.getRepairMaterialPrettyName();
String prettyName = repairable.getRepairMaterialPrettyName() == null ? StringUtils.getPrettyMaterialString(repairMaterial) : repairable.getRepairMaterialPrettyName();
String materialsNeeded = "";
@ -156,7 +156,7 @@ public class RepairManager extends SkillManager {
// Fail out with "you need material" if we don't find a suitable alternative.
if (possibleMaterial.isEmpty()) {
String prettyName = repairable.getRepairMaterialPrettyName() == null ? StringUtils.getFormattedMaterialString(repairMaterial) : repairable.getRepairMaterialPrettyName();
String prettyName = repairable.getRepairMaterialPrettyName() == null ? StringUtils.getPrettyMaterialString(repairMaterial) : repairable.getRepairMaterialPrettyName();
String materialsNeeded = "";

View File

@ -96,7 +96,7 @@ public class SalvageManager extends SkillManager {
if (getSkillLevel() < minimumSalvageableLevel) {
NotificationManager.sendPlayerInformation(player, NotificationType.REQUIREMENTS_NOT_MET,
"Salvage.Skills.Adept.Level",
String.valueOf(minimumSalvageableLevel), StringUtils.getFormattedMaterialString(item.getType()));
String.valueOf(minimumSalvageableLevel), StringUtils.getPrettyMaterialString(item.getType()));
return;
}
@ -143,11 +143,11 @@ public class SalvageManager extends SkillManager {
// We only send a confirmation message after processing the event (fixes #4694)
if (lotteryResults == potentialSalvageYield && potentialSalvageYield != 1 && RankUtils.isPlayerMaxRankInSubSkill(player, SubSkillType.SALVAGE_ARCANE_SALVAGE)) {
NotificationManager.sendPlayerInformationChatOnly(player, "Salvage.Skills.Lottery.Perfect", String.valueOf(lotteryResults), StringUtils.getFormattedMaterialString(item.getType()));
NotificationManager.sendPlayerInformationChatOnly(player, "Salvage.Skills.Lottery.Perfect", String.valueOf(lotteryResults), StringUtils.getPrettyMaterialString(item.getType()));
} else if (salvageable.getMaximumQuantity() == 1 || getSalvageLimit() >= salvageable.getMaximumQuantity()) {
NotificationManager.sendPlayerInformationChatOnly(player, "Salvage.Skills.Lottery.Normal", String.valueOf(lotteryResults), StringUtils.getFormattedMaterialString(item.getType()));
NotificationManager.sendPlayerInformationChatOnly(player, "Salvage.Skills.Lottery.Normal", String.valueOf(lotteryResults), StringUtils.getPrettyMaterialString(item.getType()));
} else {
NotificationManager.sendPlayerInformationChatOnly(player, "Salvage.Skills.Lottery.Untrained", String.valueOf(lotteryResults), StringUtils.getFormattedMaterialString(item.getType()));
NotificationManager.sendPlayerInformationChatOnly(player, "Salvage.Skills.Lottery.Untrained", String.valueOf(lotteryResults), StringUtils.getPrettyMaterialString(item.getType()));
}
player.getInventory().setItemInMainHand(new ItemStack(Material.AIR));

View File

@ -370,7 +370,7 @@ public class TamingManager extends SkillManager {
} else {
//Player did not have enough of the item in their main hand
int difference = tamingSummon.getItemAmountRequired() - itemInMainHand.getAmount();
NotificationManager.sendPlayerInformationChatOnly(player, "Taming.Summon.COTW.NeedMoreItems", String.valueOf(difference), StringUtils.getFormattedMaterialString(itemInMainHand.getType()));
NotificationManager.sendPlayerInformationChatOnly(player, "Taming.Summon.COTW.NeedMoreItems", String.valueOf(difference), StringUtils.getPrettyMaterialString(itemInMainHand.getType()));
}
}
}

View File

@ -0,0 +1,81 @@
package com.gmail.nossr50.util.text;
import com.gmail.nossr50.datatypes.party.PartyFeature;
import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import static com.gmail.nossr50.util.text.StringUtils.getCapitalized;
import static java.util.Objects.requireNonNull;
/**
* Utility class for String operations, including formatting and caching deterministic results to improve performance.
*/
public class ConfigStringUtils {
public static final String UNDERSCORE = "_";
public static final String SPACE = " ";
// Using concurrent hash maps to avoid concurrency issues (Folia)
private static final Map<EntityType, String> configEntityStrings = new ConcurrentHashMap<>();
private static final Map<SuperAbilityType, String> configSuperAbilityStrings = new ConcurrentHashMap<>();
private static final Map<Material, String> configMaterialStrings = new ConcurrentHashMap<>();
private static final Map<PartyFeature, String> configPartyFeatureStrings = new ConcurrentHashMap<>();
public static String getConfigSuperAbilityString(SuperAbilityType superAbilityType) {
requireNonNull(superAbilityType, "superAbilityType cannot be null");
return configSuperAbilityStrings.computeIfAbsent(superAbilityType,
ConfigStringUtils::createConfigFriendlyString);
}
public static String getMaterialConfigString(Material material) {
return configMaterialStrings.computeIfAbsent(material, ConfigStringUtils::createConfigFriendlyString);
}
public static String getConfigEntityTypeString(EntityType entityType) {
return configEntityStrings.computeIfAbsent(entityType, ConfigStringUtils::createConfigFriendlyString);
}
public static String getConfigPartyFeatureString(PartyFeature partyFeature) {
return configPartyFeatureStrings.computeIfAbsent(partyFeature,
// For whatever dumb reason, party feature enums got formatted like this...
pf -> createConfigFriendlyString(pf.name()).replace(UNDERSCORE, ""));
}
private static String createConfigFriendlyString(String baseString) {
return CONFIG_FRIENDLY_STRING_FORMATTER.apply(baseString);
}
private static final Function<String, String> CONFIG_FRIENDLY_STRING_FORMATTER = baseString -> {
if (baseString.contains(UNDERSCORE) && !baseString.contains(SPACE)) {
return asConfigFormat(baseString.split(UNDERSCORE));
} else {
if(baseString.contains(SPACE)) {
return asConfigFormat(baseString.split(SPACE));
} else{
return getCapitalized(baseString);
}
}
};
private static @NotNull String asConfigFormat(String[] substrings) {
final StringBuilder configString = new StringBuilder();
for (int i = 0; i < substrings.length; i++) {
configString.append(getCapitalized(substrings[i]));
if (i < substrings.length - 1) {
configString.append(UNDERSCORE);
}
}
return configString.toString();
}
private static String createConfigFriendlyString(Object object) {
return createConfigFriendlyString(object.toString());
}
}

View File

@ -1,16 +1,14 @@
package com.gmail.nossr50.util.text;
import com.gmail.nossr50.datatypes.party.PartyFeature;
import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.EntityType;
import org.jetbrains.annotations.NotNull;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import static java.util.Objects.requireNonNull;
@ -24,10 +22,9 @@ public class StringUtils {
protected static final DecimalFormat shortDecimal = new DecimalFormat("##0.0");
// Using concurrent hash maps to avoid concurrency issues (Folia)
private static final Map<EntityType, String> formattedEntityStrings = new HashMap<>();
private static final Map<SuperAbilityType, String> formattedSuperAbilityStrings = new HashMap<>();
private static final Map<Material, String> formattedMaterialStrings = new HashMap<>();
private static final Map<PartyFeature, String> prettyPartyFeatureStringCache = new HashMap<>();
private static final Map<EntityType, String> formattedEntityStrings = new ConcurrentHashMap<>();
private static final Map<SuperAbilityType, String> formattedSuperAbilityStrings = new ConcurrentHashMap<>();
private static final Map<Material, String> formattedMaterialStrings = new ConcurrentHashMap<>();
/**
* Gets a capitalized version of the target string.
@ -73,7 +70,10 @@ public class StringUtils {
* @return The "trimmed" string
*/
public static String buildStringAfterNthElement(@NotNull String @NotNull [] args, int index) {
StringBuilder trimMessage = new StringBuilder();
if (index < 0)
throw new IllegalArgumentException("Index must be greater than or equal to 0");
final StringBuilder trimMessage = new StringBuilder();
for (int i = index; i < args.length; i++) {
if (i > index) {
@ -92,7 +92,7 @@ public class StringUtils {
* @param material Material to convert
* @return Pretty string representation of the Material
*/
public static String getFormattedMaterialString(Material material) {
public static String getPrettyMaterialString(Material material) {
return formattedMaterialStrings.computeIfAbsent(material, StringUtils::createPrettyString);
}
@ -107,39 +107,6 @@ public class StringUtils {
return formattedEntityStrings.computeIfAbsent(entityType, StringUtils::createPrettyString);
}
/**
* Gets a wildcard configuration string for BlockData.
* Results are cached to improve performance.
*
* @param blockData BlockData to convert
* @return Wildcard configuration string
*/
public static String getWildcardConfigBlockDataString(BlockData blockData) {
return getFormattedMaterialString(blockData.getMaterial());
}
/**
* Gets an explicit configuration string for BlockData.
* Results are cached to improve performance.
*
* @param data BlockData to convert
* @return Explicit configuration string
*/
public static String getExplicitConfigBlockDataString(BlockData data) {
return getFormattedMaterialString(data.getMaterial());
}
/**
* Gets a pretty string representation of a PartyFeature.
* Results are cached to improve performance.
*
* @param partyFeature PartyFeature to convert
* @return Pretty string representation
*/
public static String getPrettyPartyFeatureString(PartyFeature partyFeature) {
return prettyPartyFeatureStringCache.computeIfAbsent(partyFeature, StringUtils::createPrettyString);
}
/**
* Creates a pretty string from a base string by splitting underscores and capitalizing words.
*

View File

@ -0,0 +1,323 @@
package com.gmail.nossr50.util.text;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import com.gmail.nossr50.datatypes.party.PartyFeature;
import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
import static org.junit.jupiter.api.Assertions.*;
class StringUtilsTest {
@BeforeEach
void setUp() {
// Clear caches before each test to ensure test isolation
clearCaches();
}
/**
* Utility method to clear all caches in StringUtils.
* Reflection is used since the caches are private.
*/
private void clearCaches() {
try {
java.lang.reflect.Field entityCache = StringUtils.class.getDeclaredField("formattedEntityStrings");
entityCache.setAccessible(true);
((java.util.Map<?, ?>) entityCache.get(null)).clear();
java.lang.reflect.Field superAbilityCache = StringUtils.class.getDeclaredField("formattedSuperAbilityStrings");
superAbilityCache.setAccessible(true);
((java.util.Map<?, ?>) superAbilityCache.get(null)).clear();
java.lang.reflect.Field materialCache = StringUtils.class.getDeclaredField("formattedMaterialStrings");
materialCache.setAccessible(true);
((java.util.Map<?, ?>) materialCache.get(null)).clear();
java.lang.reflect.Field partyFeatureCache = StringUtils.class.getDeclaredField("prettyPartyFeatureStringCache");
partyFeatureCache.setAccessible(true);
((java.util.Map<?, ?>) partyFeatureCache.get(null)).clear();
} catch (NoSuchFieldException | IllegalAccessException e) {
fail("Failed to clear caches: " + e.getMessage());
}
}
// Tests for getCapitalized(String target)
@Test
void testGetCapitalized_NullInput() {
assertNull(StringUtils.getCapitalized(null));
}
@Test
void testGetCapitalized_EmptyString() {
assertEquals("", StringUtils.getCapitalized(""));
}
@Test
void testGetCapitalized_SingleCharacter() {
assertEquals("A", StringUtils.getCapitalized("a"));
assertEquals("Z", StringUtils.getCapitalized("Z"));
}
@Test
void testGetCapitalized_AllUppercase() {
assertEquals("Test", StringUtils.getCapitalized("TEST"));
}
@Test
void testGetCapitalized_AllLowercase() {
assertEquals("Test", StringUtils.getCapitalized("test"));
}
@Test
void testGetCapitalized_MixedCase() {
assertEquals("Test", StringUtils.getCapitalized("tEsT"));
}
@Test
void testGetCapitalized_NonASCII() {
assertEquals("Ñandú", StringUtils.getCapitalized("ñandú"));
}
// Tests for ticksToSeconds(double ticks)
@Test
void testTicksToSeconds_PositiveTicks() {
assertEquals("1.5", StringUtils.ticksToSeconds(30));
}
@Test
void testTicksToSeconds_ZeroTicks() {
assertEquals("0.0", StringUtils.ticksToSeconds(0));
}
@Test
void testTicksToSeconds_FractionalTicks() {
assertEquals("1.5", StringUtils.ticksToSeconds(30.0));
assertEquals("1.5", StringUtils.ticksToSeconds(30.0));
assertEquals("1.0", StringUtils.ticksToSeconds(20.0));
assertEquals("0.1", StringUtils.ticksToSeconds(2.0));
}
@Test
void testTicksToSeconds_NegativeTicks() {
assertEquals("-1.0", StringUtils.ticksToSeconds(-20));
}
// Tests for getPrettySuperAbilityString(SuperAbilityType superAbilityType)
@Test
void testGetPrettySuperAbilityString_NullInput() {
assertThrows(NullPointerException.class, () -> {
StringUtils.getPrettySuperAbilityString(null);
});
}
@Test
void testGetPrettySuperAbilityString_ValidInput() {
SuperAbilityType superAbilityType = SuperAbilityType.SUPER_BREAKER;
String expected = "Super Breaker";
String actual = StringUtils.getPrettySuperAbilityString(superAbilityType);
assertEquals(expected, actual);
}
@Test
void testGetPrettySuperAbilityString_Caching() {
SuperAbilityType superAbilityType = SuperAbilityType.SUPER_BREAKER;
// First call should compute and cache
String firstCall = StringUtils.getPrettySuperAbilityString(superAbilityType);
// Second call should retrieve from cache
String secondCall = StringUtils.getPrettySuperAbilityString(superAbilityType);
assertSame(firstCall, secondCall, "Cached value should be the same instance");
}
// Tests for getPrettyEntityTypeString(EntityType entityType)
@Test
void testGetPrettyEntityTypeString_ValidInput() {
EntityType zombie = EntityType.ZOMBIE;
String expected = "Zombie";
String actual = StringUtils.getPrettyEntityTypeString(zombie);
assertEquals(expected, actual);
}
@Test
void testGetPrettyEntityTypeString_WithUnderscores() {
EntityType entity = EntityType.SKELETON_HORSE;
String expected = "Skeleton Horse";
String actual = StringUtils.getPrettyEntityTypeString(entity);
assertEquals(expected, actual);
}
@Test
void testGetPrettyEntityTypeString_Caching() {
EntityType skeleton = EntityType.SKELETON;
// First call should compute and cache
String firstCall = StringUtils.getPrettyEntityTypeString(skeleton);
// Second call should retrieve from cache
String secondCall = StringUtils.getPrettyEntityTypeString(skeleton);
assertSame(firstCall, secondCall, "Cached value should be the same instance");
}
// Tests for getFormattedMaterialString(Material material)
@Test
void testGetPrettyMaterialString_ValidInput() {
Material diamondSword = Material.DIAMOND_SWORD;
String expected = "Diamond Sword";
String actual = StringUtils.getPrettyMaterialString(diamondSword);
assertEquals(expected, actual);
}
@Test
void testGetPrettyMaterialString_WithUnderscores() {
Material goldenApple = Material.GOLDEN_APPLE;
String expected = "Golden Apple";
String actual = StringUtils.getPrettyMaterialString(goldenApple);
assertEquals(expected, actual);
}
@Test
void testGetPrettyMaterialString_Caching() {
Material ironPickaxe = Material.IRON_PICKAXE;
// First call should compute and cache
String firstCall = StringUtils.getPrettyMaterialString(ironPickaxe);
// Second call should retrieve from cache
String secondCall = StringUtils.getPrettyMaterialString(ironPickaxe);
assertSame(firstCall, secondCall, "Cached value should be the same instance");
}
// Tests for buildStringAfterNthElement(String[] args, int index)
@Test
void testBuildStringAfterNthElement_IndexZero() {
String[] args = {"Hello", "World", "Test"};
String expected = "Hello World Test";
String actual = StringUtils.buildStringAfterNthElement(args, 0);
assertEquals(expected, actual);
}
@Test
void testBuildStringAfterNthElement_IndexMiddle() {
String[] args = {"This", "is", "a", "test"};
String expected = "a test";
String actual = StringUtils.buildStringAfterNthElement(args, 2);
assertEquals(expected, actual);
}
@Test
void testBuildStringAfterNthElement_IndexLast() {
String[] args = {"Only", "One"};
String expected = "One";
String actual = StringUtils.buildStringAfterNthElement(args, 1);
assertEquals(expected, actual);
}
@Test
void testBuildStringAfterNthElement_IndexOutOfBounds() {
String[] args = {"Too", "Short"};
String expected = "";
String actual = StringUtils.buildStringAfterNthElement(args, 5);
assertEquals(expected, actual);
}
@Test
void testBuildStringAfterNthElement_EmptyArray() {
String[] args = {};
String expected = "";
String actual = StringUtils.buildStringAfterNthElement(args, 0);
assertEquals(expected, actual);
}
@Test
void testBuildStringAfterNthElement_ArgsWithSpaces() {
String[] args = {"Multiple", " ", "Spaces"};
String expected = " Spaces";
String actual = StringUtils.buildStringAfterNthElement(args, 1);
assertEquals(expected, actual);
}
// Tests for isInt(String string)
@Test
void testIsInt_ValidIntegers() {
assertTrue(StringUtils.isInt("123"));
assertTrue(StringUtils.isInt("-456"));
assertTrue(StringUtils.isInt("0"));
}
@Test
void testIsInt_InvalidIntegers() {
assertFalse(StringUtils.isInt("123.45"));
assertFalse(StringUtils.isInt("abc"));
assertFalse(StringUtils.isInt(""));
assertFalse(StringUtils.isInt(" "));
assertFalse(StringUtils.isInt(null)); // This will throw NullPointerException
}
// Tests for isDouble(String string)
@Test
void testIsDouble_ValidDoubles() {
assertTrue(StringUtils.isDouble("123.45"));
assertTrue(StringUtils.isDouble("-456.78"));
assertTrue(StringUtils.isDouble("0.0"));
assertTrue(StringUtils.isDouble("1e10"));
}
@Test
void testIsDouble_InvalidDoubles() {
assertFalse(StringUtils.isDouble("abc"));
assertFalse(StringUtils.isDouble(""));
assertFalse(StringUtils.isDouble(" "));
assertFalse(StringUtils.isDouble("123.45.67"));
}
@Test
void testIsDouble_NullInput() {
assertThrows(NullPointerException.class, () -> {
StringUtils.isDouble(null);
});
}
@Test
void testCachingMechanism_EntityType() {
EntityType zombie = EntityType.ZOMBIE;
String firstCall = StringUtils.getPrettyEntityTypeString(zombie);
String secondCall = StringUtils.getPrettyEntityTypeString(zombie);
assertSame(firstCall, secondCall, "EntityType caching failed");
}
@Test
void testCachingMechanism_Material() {
Material diamondSword = Material.DIAMOND_SWORD;
String firstCall = StringUtils.getPrettyMaterialString(diamondSword);
String secondCall = StringUtils.getPrettyMaterialString(diamondSword);
assertSame(firstCall, secondCall, "Material caching failed");
}
// Tests for createPrettyString via public methods
@Test
void testCreatePrettyString_Spaces() {
String[] args = {"hello", "world"};
String expected = "hello world";
String actual = StringUtils.buildStringAfterNthElement(args, 0);
assertEquals(expected, actual);
}
@Test
void testPrettify_Substrings() {
Material goldenApple = Material.GOLDEN_APPLE;
String expected = "Golden Apple";
String actual = StringUtils.getPrettyMaterialString(goldenApple);
assertEquals(expected, actual);
}
}