From 39b0e87b9a0b31fd773bcbf690fdb4d2fb0b301e Mon Sep 17 00:00:00 2001 From: nossr50 Date: Sat, 2 Nov 2024 19:39:06 -0700 Subject: [PATCH] Move logic for config format into ConfigStringUtils --- .../gmail/nossr50/config/GeneralConfig.java | 11 +- .../config/experience/ExperienceConfig.java | 12 +- .../config/party/ItemWeightConfig.java | 5 +- .../config/treasure/TreasureConfig.java | 31 +- .../nossr50/datatypes/party/PartyFeature.java | 7 +- .../skills/alchemy/AlchemyManager.java | 5 +- .../nossr50/skills/excavation/Excavation.java | 5 +- .../skills/herbalism/HerbalismManager.java | 11 +- .../nossr50/skills/repair/RepairManager.java | 6 +- .../skills/salvage/SalvageManager.java | 8 +- .../nossr50/skills/taming/TamingManager.java | 2 +- .../nossr50/util/text/ConfigStringUtils.java | 81 +++++ .../gmail/nossr50/util/text/StringUtils.java | 51 +-- .../nossr50/util/text/StringUtilsTest.java | 323 ++++++++++++++++++ 14 files changed, 470 insertions(+), 88 deletions(-) create mode 100644 src/main/java/com/gmail/nossr50/util/text/ConfigStringUtils.java create mode 100644 src/test/java/com/gmail/nossr50/util/text/StringUtilsTest.java diff --git a/src/main/java/com/gmail/nossr50/config/GeneralConfig.java b/src/main/java/com/gmail/nossr50/config/GeneralConfig.java index eef8da92e..83806a4d0 100644 --- a/src/main/java/com/gmail/nossr50/config/GeneralConfig.java +++ b/src/main/java/com/gmail/nossr50/config/GeneralConfig.java @@ -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() { diff --git a/src/main/java/com/gmail/nossr50/config/experience/ExperienceConfig.java b/src/main/java/com/gmail/nossr50/config/experience/ExperienceConfig.java index bd1462d4c..baa0ca422 100644 --- a/src/main/java/com/gmail/nossr50/config/experience/ExperienceConfig.java +++ b/src/main/java/com/gmail/nossr50/config/experience/ExperienceConfig.java @@ -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() { diff --git a/src/main/java/com/gmail/nossr50/config/party/ItemWeightConfig.java b/src/main/java/com/gmail/nossr50/config/party/ItemWeightConfig.java index b5ee1ebbb..0d23230de 100644 --- a/src/main/java/com/gmail/nossr50/config/party/ItemWeightConfig.java +++ b/src/main/java/com/gmail/nossr50/config/party/ItemWeightConfig.java @@ -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 getMiscItems() { diff --git a/src/main/java/com/gmail/nossr50/config/treasure/TreasureConfig.java b/src/main/java/com/gmail/nossr50/config/treasure/TreasureConfig.java index 4ad54d0f3..72d402f81 100755 --- a/src/main/java/com/gmail/nossr50/config/treasure/TreasureConfig.java +++ b/src/main/java/com/gmail/nossr50/config/treasure/TreasureConfig.java @@ -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); diff --git a/src/main/java/com/gmail/nossr50/datatypes/party/PartyFeature.java b/src/main/java/com/gmail/nossr50/datatypes/party/PartyFeature.java index b50bfe852..c01f17f75 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/party/PartyFeature.java +++ b/src/main/java/com/gmail/nossr50/datatypes/party/PartyFeature.java @@ -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) { diff --git a/src/main/java/com/gmail/nossr50/skills/alchemy/AlchemyManager.java b/src/main/java/com/gmail/nossr50/skills/alchemy/AlchemyManager.java index ddf94870a..50c8e0974 100644 --- a/src/main/java/com/gmail/nossr50/skills/alchemy/AlchemyManager.java +++ b/src/main/java/com/gmail/nossr50/skills/alchemy/AlchemyManager.java @@ -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); } diff --git a/src/main/java/com/gmail/nossr50/skills/excavation/Excavation.java b/src/main/java/com/gmail/nossr50/skills/excavation/Excavation.java index 7a3c376ea..5f68951cc 100644 --- a/src/main/java/com/gmail/nossr50/skills/excavation/Excavation.java +++ b/src/main/java/com/gmail/nossr50/skills/excavation/Excavation.java @@ -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 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<>(); diff --git a/src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java b/src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java index 0fe348fdc..8db8d64b1 100644 --- a/src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java +++ b/src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java @@ -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 treasures = TreasureConfig.getInstance().hylianMap.get(friendly); + List 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; } diff --git a/src/main/java/com/gmail/nossr50/skills/repair/RepairManager.java b/src/main/java/com/gmail/nossr50/skills/repair/RepairManager.java index 8518271bc..6094a7277 100644 --- a/src/main/java/com/gmail/nossr50/skills/repair/RepairManager.java +++ b/src/main/java/com/gmail/nossr50/skills/repair/RepairManager.java @@ -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 = ""; diff --git a/src/main/java/com/gmail/nossr50/skills/salvage/SalvageManager.java b/src/main/java/com/gmail/nossr50/skills/salvage/SalvageManager.java index a0df8d899..cd583e754 100644 --- a/src/main/java/com/gmail/nossr50/skills/salvage/SalvageManager.java +++ b/src/main/java/com/gmail/nossr50/skills/salvage/SalvageManager.java @@ -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)); diff --git a/src/main/java/com/gmail/nossr50/skills/taming/TamingManager.java b/src/main/java/com/gmail/nossr50/skills/taming/TamingManager.java index 859ceab9d..8ce0e1bfd 100644 --- a/src/main/java/com/gmail/nossr50/skills/taming/TamingManager.java +++ b/src/main/java/com/gmail/nossr50/skills/taming/TamingManager.java @@ -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())); } } } diff --git a/src/main/java/com/gmail/nossr50/util/text/ConfigStringUtils.java b/src/main/java/com/gmail/nossr50/util/text/ConfigStringUtils.java new file mode 100644 index 000000000..8c85c5039 --- /dev/null +++ b/src/main/java/com/gmail/nossr50/util/text/ConfigStringUtils.java @@ -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 configEntityStrings = new ConcurrentHashMap<>(); + private static final Map configSuperAbilityStrings = new ConcurrentHashMap<>(); + private static final Map configMaterialStrings = new ConcurrentHashMap<>(); + private static final Map 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 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()); + } +} diff --git a/src/main/java/com/gmail/nossr50/util/text/StringUtils.java b/src/main/java/com/gmail/nossr50/util/text/StringUtils.java index 02aba7eef..615a32eee 100644 --- a/src/main/java/com/gmail/nossr50/util/text/StringUtils.java +++ b/src/main/java/com/gmail/nossr50/util/text/StringUtils.java @@ -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 formattedEntityStrings = new HashMap<>(); - private static final Map formattedSuperAbilityStrings = new HashMap<>(); - private static final Map formattedMaterialStrings = new HashMap<>(); - private static final Map prettyPartyFeatureStringCache = new HashMap<>(); + private static final Map formattedEntityStrings = new ConcurrentHashMap<>(); + private static final Map formattedSuperAbilityStrings = new ConcurrentHashMap<>(); + private static final Map 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. * diff --git a/src/test/java/com/gmail/nossr50/util/text/StringUtilsTest.java b/src/test/java/com/gmail/nossr50/util/text/StringUtilsTest.java new file mode 100644 index 000000000..13e7b4b80 --- /dev/null +++ b/src/test/java/com/gmail/nossr50/util/text/StringUtilsTest.java @@ -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); + } +}