From ce18f3df97b7bc406b4ff04638dad05f00df6df1 Mon Sep 17 00:00:00 2001 From: nossr50 Date: Sat, 2 Nov 2024 18:56:11 -0700 Subject: [PATCH] major optimizations to getting xp values for specific blocks --- Changelog.txt | 1 + .../com/gmail/nossr50/api/ExperienceAPI.java | 16 +- .../com/gmail/nossr50/chat/ChatManager.java | 1 - .../commands/skills/CrossbowsCommand.java | 1 - .../nossr50/commands/skills/MacesCommand.java | 1 - .../commands/skills/TridentsCommand.java | 1 - .../gmail/nossr50/config/GeneralConfig.java | 7 +- .../config/experience/ExperienceConfig.java | 85 +++--- .../config/party/ItemWeightConfig.java | 2 +- .../config/skills/alchemy/PotionConfig.java | 1 - .../config/skills/salvage/SalvageConfig.java | 1 - .../config/treasure/TreasureConfig.java | 28 +- .../nossr50/datatypes/player/McMMOPlayer.java | 1 - .../datatypes/skills/SuperAbilityType.java | 2 +- .../nossr50/listeners/EntityListener.java | 3 - .../skills/alchemy/AlchemyManager.java | 2 +- .../nossr50/skills/axes/AxesManager.java | 1 - .../nossr50/skills/excavation/Excavation.java | 2 +- .../skills/herbalism/HerbalismManager.java | 10 +- .../nossr50/skills/repair/RepairManager.java | 6 +- .../skills/salvage/SalvageManager.java | 8 +- .../nossr50/skills/taming/TamingManager.java | 3 +- .../gmail/nossr50/util/AttributeMapper.java | 1 - .../nossr50/util/skills/CombatUtils.java | 2 - .../gmail/nossr50/util/skills/SkillTools.java | 20 -- .../nossr50/util/sounds/SoundManager.java | 25 +- .../gmail/nossr50/util/text/StringUtils.java | 247 ++++++++++-------- .../com/gmail/nossr50/MMOTestEnvironment.java | 1 - 28 files changed, 236 insertions(+), 243 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 6e40ba6d80..31306b240c 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,4 +1,5 @@ Version 2.2.024 + Significant optimizations to the way mcMMO handles grabbing XP values for blocks Version 2.2.023 Compatibility with Minecraft 1.21.3 diff --git a/src/main/java/com/gmail/nossr50/api/ExperienceAPI.java b/src/main/java/com/gmail/nossr50/api/ExperienceAPI.java index a32873a299..98d37358a5 100644 --- a/src/main/java/com/gmail/nossr50/api/ExperienceAPI.java +++ b/src/main/java/com/gmail/nossr50/api/ExperienceAPI.java @@ -1154,15 +1154,19 @@ public static void addXpFromBlocks(ArrayList blockStates, McMMOPlaye } /** - * Will add the appropriate type of XP from the block to the player based on the material of the blocks given if it matches the given skillType + * Will add the appropriate type of XP from the block to the player based on the material of the blocks given + * if it matches the given skillType * @param blockStates the blocks to reward XP for * @param mcMMOPlayer the target player * @param skillType target primary skill */ - public static void addXpFromBlocksBySkill(ArrayList blockStates, McMMOPlayer mcMMOPlayer, PrimarySkillType skillType) { + public static void addXpFromBlocksBySkill(ArrayList blockStates, McMMOPlayer mcMMOPlayer, + PrimarySkillType skillType) { for(BlockState bs : blockStates) { if (ExperienceConfig.getInstance().getXp(skillType, bs.getType()) > 0) { - mcMMOPlayer.applyXpGain(skillType, ExperienceConfig.getInstance().getXp(skillType, bs.getType()), XPGainReason.PVE, XPGainSource.SELF); + mcMMOPlayer.applyXpGain(skillType, + ExperienceConfig.getInstance().getXp(skillType, bs.getType()), + XPGainReason.PVE, XPGainSource.SELF); } } } @@ -1175,7 +1179,8 @@ public static void addXpFromBlocksBySkill(ArrayList blockStates, McM public static void addXpFromBlock(BlockState blockState, McMMOPlayer mcMMOPlayer) { for(PrimarySkillType skillType : PrimarySkillType.values()) { if (ExperienceConfig.getInstance().getXp(skillType, blockState.getType()) > 0) { - mcMMOPlayer.applyXpGain(skillType, ExperienceConfig.getInstance().getXp(skillType, blockState.getType()), XPGainReason.PVE, XPGainSource.SELF); + mcMMOPlayer.applyXpGain(skillType, ExperienceConfig.getInstance().getXp( + skillType, blockState.getType()), XPGainReason.PVE, XPGainSource.SELF); } } } @@ -1188,7 +1193,8 @@ public static void addXpFromBlock(BlockState blockState, McMMOPlayer mcMMOPlayer */ public static void addXpFromBlockBySkill(BlockState blockState, McMMOPlayer mcMMOPlayer, PrimarySkillType skillType) { if (ExperienceConfig.getInstance().getXp(skillType, blockState.getType()) > 0) { - mcMMOPlayer.applyXpGain(skillType, ExperienceConfig.getInstance().getXp(skillType, blockState.getType()), XPGainReason.PVE, XPGainSource.SELF); + mcMMOPlayer.applyXpGain(skillType, ExperienceConfig.getInstance().getXp(skillType, blockState.getType()), + XPGainReason.PVE, XPGainSource.SELF); } } diff --git a/src/main/java/com/gmail/nossr50/chat/ChatManager.java b/src/main/java/com/gmail/nossr50/chat/ChatManager.java index 101c9e6a14..0d7c21c653 100644 --- a/src/main/java/com/gmail/nossr50/chat/ChatManager.java +++ b/src/main/java/com/gmail/nossr50/chat/ChatManager.java @@ -14,7 +14,6 @@ import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.text.StringUtils; import net.kyori.adventure.audience.Audience; -import net.kyori.adventure.chat.SignedMessage; import net.kyori.adventure.text.TextComponent; import org.bukkit.command.ConsoleCommandSender; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/com/gmail/nossr50/commands/skills/CrossbowsCommand.java b/src/main/java/com/gmail/nossr50/commands/skills/CrossbowsCommand.java index 9377e595a0..309b5de27a 100644 --- a/src/main/java/com/gmail/nossr50/commands/skills/CrossbowsCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/skills/CrossbowsCommand.java @@ -6,7 +6,6 @@ import com.gmail.nossr50.util.skills.RankUtils; import com.gmail.nossr50.util.text.TextComponentFactory; import net.kyori.adventure.text.Component; -import org.bukkit.ChatColor; import org.bukkit.entity.Player; import java.util.ArrayList; diff --git a/src/main/java/com/gmail/nossr50/commands/skills/MacesCommand.java b/src/main/java/com/gmail/nossr50/commands/skills/MacesCommand.java index 813497dfe1..7898fabe82 100644 --- a/src/main/java/com/gmail/nossr50/commands/skills/MacesCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/skills/MacesCommand.java @@ -10,7 +10,6 @@ import com.gmail.nossr50.util.skills.SkillUtils; import com.gmail.nossr50.util.text.TextComponentFactory; import net.kyori.adventure.text.Component; -import org.bukkit.ChatColor; import org.bukkit.entity.Player; import java.util.ArrayList; diff --git a/src/main/java/com/gmail/nossr50/commands/skills/TridentsCommand.java b/src/main/java/com/gmail/nossr50/commands/skills/TridentsCommand.java index fe1130c7ad..da49fdccb9 100644 --- a/src/main/java/com/gmail/nossr50/commands/skills/TridentsCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/skills/TridentsCommand.java @@ -5,7 +5,6 @@ import com.gmail.nossr50.util.skills.SkillUtils; import com.gmail.nossr50.util.text.TextComponentFactory; import net.kyori.adventure.text.Component; -import org.bukkit.ChatColor; import org.bukkit.entity.Player; import java.util.ArrayList; diff --git a/src/main/java/com/gmail/nossr50/config/GeneralConfig.java b/src/main/java/com/gmail/nossr50/config/GeneralConfig.java index 84e57c9b29..eef8da92e5 100644 --- a/src/main/java/com/gmail/nossr50/config/GeneralConfig.java +++ b/src/main/java/com/gmail/nossr50/config/GeneralConfig.java @@ -711,7 +711,7 @@ public boolean getDoubleDropsEnabled(PrimarySkillType skill, Material material) if (material.toString().equalsIgnoreCase("LILY_PAD")) return false; - return config.getBoolean("Bonus_Drops." + StringUtils.getCapitalized(skill.toString()) + "." + StringUtils.getPrettyItemString(material).replace(" ", "_")); + return config.getBoolean("Bonus_Drops." + StringUtils.getCapitalized(skill.toString()) + "." + StringUtils.getFormattedMaterialString(material).replace(" ", "_")); } public boolean getDoubleDropsDisabled(PrimarySkillType skill) { @@ -890,8 +890,9 @@ public int getTamingCOTWMaxAmount(String cotwEntity) { } /* Woodcutting */ - public boolean getWoodcuttingDoubleDropsEnabled(BlockData material) { - return config.getBoolean("Bonus_Drops.Woodcutting." + StringUtils.getFriendlyConfigBlockDataString(material)); + public boolean getWoodcuttingDoubleDropsEnabled(BlockData blockData) { + return config.getBoolean("Bonus_Drops.Woodcutting." + + StringUtils.getFormattedMaterialString(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 cd9e5a768c..bd1462d4cd 100644 --- a/src/main/java/com/gmail/nossr50/config/experience/ExperienceConfig.java +++ b/src/main/java/com/gmail/nossr50/config/experience/ExperienceConfig.java @@ -15,10 +15,15 @@ import org.bukkit.entity.EntityType; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; + +import static com.gmail.nossr50.util.skills.SkillTools.isChildSkill; public class ExperienceConfig extends BukkitConfig { private static ExperienceConfig instance; + final private Map> blockExperienceMap = new HashMap<>(); private ExperienceConfig() { super("experience.yml"); @@ -30,6 +35,23 @@ public static ExperienceConfig getInstance() { instance = new ExperienceConfig(); } + for (PrimarySkillType skill : PrimarySkillType.values()) { + // Skip child skills + if (isChildSkill(skill)) { + continue; + } + + final Map experienceMap = new HashMap<>(); + for (Material material : Material.values()) { + int xp = instance.getConfigXp(skill, material); + + if (xp > 0) { + experienceMap.put(material, xp); + } + } + instance.blockExperienceMap.put(skill, experienceMap); + } + return instance; } @@ -321,15 +343,22 @@ public boolean hasCombatXP(EntityType entity) { } /* Materials */ + private int getConfigXp(PrimarySkillType skill, Material material) { + // prevents exploit + if (material == Material.LILY_PAD) + return 0; + + final String baseString = "Experience_Values." + StringUtils.getCapitalized(skill.toString()) + "."; + final String configPath = baseString + StringUtils.getFormattedMaterialString(material); + return config.getInt(configPath, 0); + } + public int getXp(PrimarySkillType skill, Material material) { - return getXpHelper(skill, StringUtils.getExplicitConfigMaterialString(material), - StringUtils.getFriendlyConfigMaterialString(material), - StringUtils.getWildcardConfigMaterialString(material)); + return blockExperienceMap.get(skill).getOrDefault(material, 0); } public int getXp(PrimarySkillType skill, BlockState blockState) { - Material material = blockState.getType(); - return getXp(skill, material); + return getXp(skill, blockState.getType()); } public int getXp(PrimarySkillType skill, Block block) { @@ -338,57 +367,17 @@ public int getXp(PrimarySkillType skill, Block block) { } public int getXp(PrimarySkillType skill, BlockData data) { - return getXpHelper(skill, StringUtils.getExplicitConfigBlockDataString(data), - StringUtils.getFriendlyConfigBlockDataString(data), - StringUtils.getWildcardConfigBlockDataString(data)); + return getXp(skill, data.getMaterial()); } - private int getXpHelper(PrimarySkillType skill, String explicitString, String friendlyString, String wildcardString) { - if (explicitString.equalsIgnoreCase("LILY_PAD")) { - return 0; - } - - String baseString = "Experience_Values." + StringUtils.getCapitalized(skill.toString()) + "."; - String[] configStrings = {explicitString, friendlyString, wildcardString}; - - for (String configString : configStrings) { - String fullPath = baseString + configString; - if (config.contains(fullPath)) { - return config.getInt(fullPath); - } - } - - return 0; - } - - public boolean doesBlockGiveSkillXP(PrimarySkillType skill, Material material) { - return doesBlockGiveSkillXPHelper(skill, StringUtils.getExplicitConfigMaterialString(material), - StringUtils.getFriendlyConfigMaterialString(material), - StringUtils.getWildcardConfigMaterialString(material)); + return getXp(skill, material) > 0; } public boolean doesBlockGiveSkillXP(PrimarySkillType skill, BlockData data) { - return doesBlockGiveSkillXPHelper(skill, StringUtils.getExplicitConfigBlockDataString(data), - StringUtils.getFriendlyConfigBlockDataString(data), - StringUtils.getWildcardConfigBlockDataString(data)); + return getXp(skill, data) > 0; } - private boolean doesBlockGiveSkillXPHelper(PrimarySkillType skill, String explicitString, String friendlyString, String wildcardString) { - String baseString = "Experience_Values." + StringUtils.getCapitalized(skill.toString()) + "."; - String[] configStrings = {explicitString, friendlyString, wildcardString}; - - for (String configString : configStrings) { - String fullPath = baseString + configString; - if (config.contains(fullPath)) { - return true; - } - } - - return false; - } - - /* * Experience Bar Stuff */ 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 f36a9d24bd..b5ee1ebbb5 100644 --- a/src/main/java/com/gmail/nossr50/config/party/ItemWeightConfig.java +++ b/src/main/java/com/gmail/nossr50/config/party/ItemWeightConfig.java @@ -23,7 +23,7 @@ public static ItemWeightConfig getInstance() { } public int getItemWeight(Material material) { - return config.getInt("Item_Weights." + StringUtils.getPrettyItemString(material).replace(" ", "_"), config.getInt("Item_Weights.Default")); + return config.getInt("Item_Weights." + StringUtils.getFormattedMaterialString(material).replace(" ", "_"), config.getInt("Item_Weights.Default")); } public HashSet getMiscItems() { diff --git a/src/main/java/com/gmail/nossr50/config/skills/alchemy/PotionConfig.java b/src/main/java/com/gmail/nossr50/config/skills/alchemy/PotionConfig.java index cfd06649f0..14780abcc6 100644 --- a/src/main/java/com/gmail/nossr50/config/skills/alchemy/PotionConfig.java +++ b/src/main/java/com/gmail/nossr50/config/skills/alchemy/PotionConfig.java @@ -21,7 +21,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import static com.gmail.nossr50.util.ItemUtils.setItemName; import static com.gmail.nossr50.util.PotionUtil.*; diff --git a/src/main/java/com/gmail/nossr50/config/skills/salvage/SalvageConfig.java b/src/main/java/com/gmail/nossr50/config/skills/salvage/SalvageConfig.java index dfafa23581..7f68b6121e 100644 --- a/src/main/java/com/gmail/nossr50/config/skills/salvage/SalvageConfig.java +++ b/src/main/java/com/gmail/nossr50/config/skills/salvage/SalvageConfig.java @@ -9,7 +9,6 @@ import com.gmail.nossr50.skills.salvage.salvageables.SalvageableFactory; import com.gmail.nossr50.util.ItemUtils; import com.gmail.nossr50.util.LogUtils; -import com.gmail.nossr50.util.skills.SkillUtils; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.inventory.ItemStack; 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 bed8ed0598..4ad54d0f32 100755 --- a/src/main/java/com/gmail/nossr50/config/treasure/TreasureConfig.java +++ b/src/main/java/com/gmail/nossr50/config/treasure/TreasureConfig.java @@ -239,29 +239,29 @@ private void loadTreasures(String type) { for (String dropper : dropList) { if (dropper.equals("Bushes")) { - AddHylianTreasure(StringUtils.getFriendlyConfigMaterialString(Material.FERN), hylianTreasure); - AddHylianTreasure(StringUtils.getFriendlyConfigMaterialString(BlockUtils.getShortGrass()), hylianTreasure); + AddHylianTreasure(StringUtils.getFormattedMaterialString(Material.FERN), hylianTreasure); + AddHylianTreasure(StringUtils.getFormattedMaterialString(BlockUtils.getShortGrass()), hylianTreasure); for (Material species : Tag.SAPLINGS.getValues()) - AddHylianTreasure(StringUtils.getFriendlyConfigMaterialString(species), hylianTreasure); + AddHylianTreasure(StringUtils.getFormattedMaterialString(species), hylianTreasure); - AddHylianTreasure(StringUtils.getFriendlyConfigMaterialString(Material.DEAD_BUSH), hylianTreasure); + AddHylianTreasure(StringUtils.getFormattedMaterialString(Material.DEAD_BUSH), hylianTreasure); continue; } if (dropper.equals("Flowers")) { - AddHylianTreasure(StringUtils.getFriendlyConfigMaterialString(Material.POPPY), hylianTreasure); - AddHylianTreasure(StringUtils.getFriendlyConfigMaterialString(Material.DANDELION), hylianTreasure); - AddHylianTreasure(StringUtils.getFriendlyConfigMaterialString(Material.BLUE_ORCHID), hylianTreasure); - AddHylianTreasure(StringUtils.getFriendlyConfigMaterialString(Material.ALLIUM), hylianTreasure); - AddHylianTreasure(StringUtils.getFriendlyConfigMaterialString(Material.AZURE_BLUET), hylianTreasure); - AddHylianTreasure(StringUtils.getFriendlyConfigMaterialString(Material.ORANGE_TULIP), hylianTreasure); - AddHylianTreasure(StringUtils.getFriendlyConfigMaterialString(Material.PINK_TULIP), hylianTreasure); - AddHylianTreasure(StringUtils.getFriendlyConfigMaterialString(Material.RED_TULIP), hylianTreasure); - AddHylianTreasure(StringUtils.getFriendlyConfigMaterialString(Material.WHITE_TULIP), hylianTreasure); + 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); continue; } if (dropper.equals("Pots")) { for (Material species : Tag.FLOWER_POTS.getValues()) - AddHylianTreasure(StringUtils.getFriendlyConfigMaterialString(species), hylianTreasure); + AddHylianTreasure(StringUtils.getFormattedMaterialString(species), hylianTreasure); continue; } AddHylianTreasure(dropper, hylianTreasure); diff --git a/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java b/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java index cbf96352fa..7f67699cf2 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java +++ b/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java @@ -2,7 +2,6 @@ import com.gmail.nossr50.api.exceptions.InvalidSkillException; import com.gmail.nossr50.chat.author.PlayerAuthor; -import com.gmail.nossr50.config.AdvancedConfig; import com.gmail.nossr50.config.ChatConfig; import com.gmail.nossr50.config.WorldBlacklist; import com.gmail.nossr50.config.experience.ExperienceConfig; diff --git a/src/main/java/com/gmail/nossr50/datatypes/skills/SuperAbilityType.java b/src/main/java/com/gmail/nossr50/datatypes/skills/SuperAbilityType.java index 3fcf2992c6..4f982cba88 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/skills/SuperAbilityType.java +++ b/src/main/java/com/gmail/nossr50/datatypes/skills/SuperAbilityType.java @@ -167,7 +167,7 @@ public String getAbilityRefresh() { } public String getName() { - return StringUtils.getPrettyAbilityString(this); + return StringUtils.getPrettySuperAbilityString(this); } public String getLocalizedName() { diff --git a/src/main/java/com/gmail/nossr50/listeners/EntityListener.java b/src/main/java/com/gmail/nossr50/listeners/EntityListener.java index 101388891a..d5a2e5e3d6 100644 --- a/src/main/java/com/gmail/nossr50/listeners/EntityListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/EntityListener.java @@ -27,7 +27,6 @@ import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.OfflinePlayer; -import org.bukkit.attribute.Attribute; import org.bukkit.block.Block; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.*; @@ -45,8 +44,6 @@ import org.bukkit.potion.PotionEffectType; import org.bukkit.projectiles.ProjectileSource; -import java.util.Arrays; -import java.util.List; import java.util.Set; import static com.gmail.nossr50.util.AttributeMapper.MAPPED_MAX_HEALTH; 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 8cc53bc5ba..ddf94870a2 100644 --- a/src/main/java/com/gmail/nossr50/skills/alchemy/AlchemyManager.java +++ b/src/main/java/com/gmail/nossr50/skills/alchemy/AlchemyManager.java @@ -34,7 +34,7 @@ public String getIngredientList() { StringBuilder list = new StringBuilder(); for (ItemStack ingredient : getIngredients()) { - String string = StringUtils.getPrettyItemString(ingredient.getType()); + String string = StringUtils.getFormattedMaterialString(ingredient.getType()); list.append(", ").append(string); } diff --git a/src/main/java/com/gmail/nossr50/skills/axes/AxesManager.java b/src/main/java/com/gmail/nossr50/skills/axes/AxesManager.java index 1ce677e185..7f6827acf2 100644 --- a/src/main/java/com/gmail/nossr50/skills/axes/AxesManager.java +++ b/src/main/java/com/gmail/nossr50/skills/axes/AxesManager.java @@ -15,7 +15,6 @@ import com.gmail.nossr50.util.skills.CombatUtils; import com.gmail.nossr50.util.skills.ParticleEffectUtils; import com.gmail.nossr50.util.skills.RankUtils; -import com.gmail.nossr50.util.skills.SkillUtils; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.inventory.EntityEquipment; 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 aa6209e80f..7a3c376ea7 100644 --- a/src/main/java/com/gmail/nossr50/skills/excavation/Excavation.java +++ b/src/main/java/com/gmail/nossr50/skills/excavation/Excavation.java @@ -19,7 +19,7 @@ public class Excavation { * @return the list of treasures that could be found */ protected static List getTreasures(BlockState blockState) { - String friendly = StringUtils.getFriendlyConfigBlockDataString(blockState.getBlockData()); + String friendly = StringUtils.getFormattedMaterialString(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 a5f1bf17a2..0fe348fdc2 100644 --- a/src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java +++ b/src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java @@ -113,7 +113,8 @@ public void processBerryBushHarvesting(@NotNull BlockState blockState) { mmoPlayer.getPlayer().sendMessage("Bush Reward Multiplier: " + rewardByAge); } - int xpReward = ExperienceConfig.getInstance().getXp(PrimarySkillType.HERBALISM, blockState) * rewardByAge; + int xpReward = ExperienceConfig.getInstance().getXp(PrimarySkillType.HERBALISM, blockState.getType()) + * rewardByAge; if (mmoPlayer.isDebugMode()) { mmoPlayer.getPlayer().sendMessage("Bush XP: " + xpReward); @@ -713,12 +714,11 @@ public boolean processHylianLuck(BlockState blockState) { return false; } - String friendly = StringUtils.getFriendlyConfigBlockDataString(blockState.getBlockData()); + final String friendly = StringUtils.getFormattedMaterialString(blockState.getBlockData().getMaterial()); if (!TreasureConfig.getInstance().hylianMap.containsKey(friendly)) return false; List treasures = TreasureConfig.getInstance().hylianMap.get(friendly); - if (treasures.isEmpty()) { return false; } @@ -750,12 +750,12 @@ public boolean processShroomThumb(BlockState blockState) { PlayerInventory playerInventory = getPlayer().getInventory(); if (!playerInventory.contains(Material.BROWN_MUSHROOM, 1)) { - NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.REQUIREMENTS_NOT_MET, "Skills.NeedMore", StringUtils.getPrettyItemString(Material.BROWN_MUSHROOM)); + NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.REQUIREMENTS_NOT_MET, "Skills.NeedMore", StringUtils.getFormattedMaterialString(Material.BROWN_MUSHROOM)); return false; } if (!playerInventory.contains(Material.RED_MUSHROOM, 1)) { - NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.REQUIREMENTS_NOT_MET, "Skills.NeedMore", StringUtils.getPrettyItemString(Material.RED_MUSHROOM)); + NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.REQUIREMENTS_NOT_MET, "Skills.NeedMore", StringUtils.getFormattedMaterialString(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 0e022ec860..8518271bc1 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 void handleRepair(ItemStack item) { // Level check if (skillLevel < minimumRepairableLevel) { - NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Repair.Skills.Adept", String.valueOf(minimumRepairableLevel), StringUtils.getPrettyItemString(item.getType())); + NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Repair.Skills.Adept", String.valueOf(minimumRepairableLevel), StringUtils.getFormattedMaterialString(item.getType())); return; } @@ -115,7 +115,7 @@ public void handleRepair(ItemStack item) { // Check if they have the proper material to repair with if (!inventory.contains(repairMaterial)) { - String prettyName = repairable.getRepairMaterialPrettyName() == null ? StringUtils.getPrettyItemString(repairMaterial) : repairable.getRepairMaterialPrettyName(); + String prettyName = repairable.getRepairMaterialPrettyName() == null ? StringUtils.getFormattedMaterialString(repairMaterial) : repairable.getRepairMaterialPrettyName(); String materialsNeeded = ""; @@ -156,7 +156,7 @@ public void handleRepair(ItemStack item) { // Fail out with "you need material" if we don't find a suitable alternative. if (possibleMaterial.isEmpty()) { - String prettyName = repairable.getRepairMaterialPrettyName() == null ? StringUtils.getPrettyItemString(repairMaterial) : repairable.getRepairMaterialPrettyName(); + String prettyName = repairable.getRepairMaterialPrettyName() == null ? StringUtils.getFormattedMaterialString(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 e1bf40e08d..a0df8d8991 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 void handleSalvage(Location location, ItemStack item) { if (getSkillLevel() < minimumSalvageableLevel) { NotificationManager.sendPlayerInformation(player, NotificationType.REQUIREMENTS_NOT_MET, "Salvage.Skills.Adept.Level", - String.valueOf(minimumSalvageableLevel), StringUtils.getPrettyItemString(item.getType())); + String.valueOf(minimumSalvageableLevel), StringUtils.getFormattedMaterialString(item.getType())); return; } @@ -143,11 +143,11 @@ public void handleSalvage(Location location, ItemStack item) { // 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.getPrettyItemString(item.getType())); + NotificationManager.sendPlayerInformationChatOnly(player, "Salvage.Skills.Lottery.Perfect", String.valueOf(lotteryResults), StringUtils.getFormattedMaterialString(item.getType())); } else if (salvageable.getMaximumQuantity() == 1 || getSalvageLimit() >= salvageable.getMaximumQuantity()) { - NotificationManager.sendPlayerInformationChatOnly(player, "Salvage.Skills.Lottery.Normal", String.valueOf(lotteryResults), StringUtils.getPrettyItemString(item.getType())); + NotificationManager.sendPlayerInformationChatOnly(player, "Salvage.Skills.Lottery.Normal", String.valueOf(lotteryResults), StringUtils.getFormattedMaterialString(item.getType())); } else { - NotificationManager.sendPlayerInformationChatOnly(player, "Salvage.Skills.Lottery.Untrained", String.valueOf(lotteryResults), StringUtils.getPrettyItemString(item.getType())); + NotificationManager.sendPlayerInformationChatOnly(player, "Salvage.Skills.Lottery.Untrained", String.valueOf(lotteryResults), StringUtils.getFormattedMaterialString(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 46b6ffc20d..859ceab9dc 100644 --- a/src/main/java/com/gmail/nossr50/skills/taming/TamingManager.java +++ b/src/main/java/com/gmail/nossr50/skills/taming/TamingManager.java @@ -23,7 +23,6 @@ import com.gmail.nossr50.util.text.StringUtils; import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeInstance; import org.bukkit.entity.*; import org.bukkit.inventory.ItemStack; @@ -371,7 +370,7 @@ private void processCallOfTheWild() { } 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.getPrettyItemString(itemInMainHand.getType())); + NotificationManager.sendPlayerInformationChatOnly(player, "Taming.Summon.COTW.NeedMoreItems", String.valueOf(difference), StringUtils.getFormattedMaterialString(itemInMainHand.getType())); } } } diff --git a/src/main/java/com/gmail/nossr50/util/AttributeMapper.java b/src/main/java/com/gmail/nossr50/util/AttributeMapper.java index c80dadc527..c9b115b56e 100644 --- a/src/main/java/com/gmail/nossr50/util/AttributeMapper.java +++ b/src/main/java/com/gmail/nossr50/util/AttributeMapper.java @@ -1,7 +1,6 @@ package com.gmail.nossr50.util; import com.gmail.nossr50.mcMMO; -import org.bukkit.Registry; import org.bukkit.attribute.Attribute; import java.lang.reflect.Field; diff --git a/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java b/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java index b7b94bb4c6..38f5aca2ce 100644 --- a/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java +++ b/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java @@ -21,10 +21,8 @@ import com.gmail.nossr50.util.*; import com.gmail.nossr50.util.player.NotificationManager; import com.gmail.nossr50.util.player.UserManager; -import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Material; -import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeInstance; import org.bukkit.entity.*; import org.bukkit.event.entity.EntityDamageByEntityEvent; diff --git a/src/main/java/com/gmail/nossr50/util/skills/SkillTools.java b/src/main/java/com/gmail/nossr50/util/skills/SkillTools.java index 8afb055945..d2da0aac80 100644 --- a/src/main/java/com/gmail/nossr50/util/skills/SkillTools.java +++ b/src/main/java/com/gmail/nossr50/util/skills/SkillTools.java @@ -387,26 +387,6 @@ public int getSuperAbilityMaxLength(SuperAbilityType superAbilityType) { return pluginRef.getGeneralConfig().getMaxLength(superAbilityType); } - public String getSuperAbilityOnLocaleKey(SuperAbilityType superAbilityType) { - return "SuperAbility." + StringUtils.getPrettyCamelCaseName(superAbilityType) + ".On"; - } - - public String getSuperAbilityOffLocaleKey(SuperAbilityType superAbilityType) { - return "SuperAbility." + StringUtils.getPrettyCamelCaseName(superAbilityType) + ".Off"; - } - - public String getSuperAbilityOtherPlayerActivationLocaleKey(SuperAbilityType superAbilityType) { - return "SuperAbility." + StringUtils.getPrettyCamelCaseName(superAbilityType) + ".Other.On"; - } - - public String getSuperAbilityOtherPlayerDeactivationLocaleKey(SuperAbilityType superAbilityType) { - return "SuperAbility." + StringUtils.getPrettyCamelCaseName(superAbilityType) + "Other.Off"; - } - - public String getSuperAbilityRefreshedLocaleKey(SuperAbilityType superAbilityType) { - return "SuperAbility." + StringUtils.getPrettyCamelCaseName(superAbilityType) + ".Refresh"; - } - public int getLevelCap(@NotNull PrimarySkillType primarySkillType) { return mcMMO.p.getGeneralConfig().getLevelCap(primarySkillType); } diff --git a/src/main/java/com/gmail/nossr50/util/sounds/SoundManager.java b/src/main/java/com/gmail/nossr50/util/sounds/SoundManager.java index c89bf86e7b..169f0f1638 100644 --- a/src/main/java/com/gmail/nossr50/util/sounds/SoundManager.java +++ b/src/main/java/com/gmail/nossr50/util/sounds/SoundManager.java @@ -9,14 +9,7 @@ import org.bukkit.entity.Player; public class SoundManager { - public static Sound CRIPPLE_SOUND; - static { - try { - CRIPPLE_SOUND = Sound.valueOf("ITEM_MACE_SMASH_GROUND"); - } catch (IllegalArgumentException e) { - CRIPPLE_SOUND = Sound.BLOCK_ANVIL_PLACE; - } - } + private static Sound CRIPPLE_SOUND; /** * Sends a sound to the player @@ -107,10 +100,24 @@ private static Sound getSound(SoundType soundType) { case DEFLECT_ARROWS, BLEED -> Sound.ENTITY_ENDER_EYE_DEATH; case GLASS -> Sound.BLOCK_GLASS_BREAK; case ITEM_CONSUMED -> Sound.ITEM_BOTTLE_EMPTY; - case CRIPPLE -> CRIPPLE_SOUND; + case CRIPPLE -> getCrippleSound(); }; } + private static Sound getCrippleSound() { + if (CRIPPLE_SOUND != null) { + return CRIPPLE_SOUND; + } + + try { + CRIPPLE_SOUND = Sound.valueOf("ITEM_MACE_SMASH_GROUND"); + return CRIPPLE_SOUND; + } catch (IllegalArgumentException e) { + CRIPPLE_SOUND = Sound.BLOCK_ANVIL_PLACE; + return CRIPPLE_SOUND; + } + } + public static float getFizzPitch() { return 2.6F + (Misc.getRandom().nextFloat() - Misc.getRandom().nextFloat()) * 0.8F; } 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 b906058fa0..02aba7eef2 100644 --- a/src/main/java/com/gmail/nossr50/util/text/StringUtils.java +++ b/src/main/java/com/gmail/nossr50/util/text/StringUtils.java @@ -3,192 +3,217 @@ import com.gmail.nossr50.datatypes.party.PartyFeature; import com.gmail.nossr50.datatypes.skills.SuperAbilityType; import org.bukkit.Material; -import org.bukkit.block.data.Ageable; 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.function.Function; +import static java.util.Objects.requireNonNull; + +/** + * Utility class for String operations, including formatting and caching deterministic results to improve performance. + */ public class StringUtils { - protected static DecimalFormat percent = new DecimalFormat("##0.00%"); - protected static DecimalFormat shortDecimal = new DecimalFormat("##0.0"); + protected static final DecimalFormat percent = new DecimalFormat("##0.00%"); + 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<>(); /** * Gets a capitalized version of the target string. + * Results are cached to improve performance. * - * @param target - * String to capitalize + * @param target String to capitalize * @return the capitalized string */ public static String getCapitalized(String target) { - return target.substring(0, 1).toUpperCase() + target.substring(1).toLowerCase(Locale.ENGLISH); + if (target == null || target.isEmpty()) { + return target; + } + return target.substring(0, 1).toUpperCase(Locale.ENGLISH) + target.substring(1).toLowerCase(Locale.ENGLISH); } + /** + * Converts ticks to seconds, formatted to one decimal place. + * + * @param ticks Number of ticks + * @return String representation of seconds + */ public static String ticksToSeconds(double ticks) { return shortDecimal.format(ticks / 20); } - public static String convertToCamelCaseString(String baseString, String splitBy) { - String[] substrings = baseString.split(splitBy); - String prettyString = ""; - int size = 1; - - for (String string : substrings) { - prettyString = prettyString.concat(getCapitalized(string)); - - if (size < substrings.length) { - prettyString = prettyString.concat(""); - } - - size++; - } - - return prettyString; - } - - public static String getPrettyCamelCaseName(Object o) { - return StringUtils.convertToCamelCaseString(o.toString(), "_"); - } - - public static String getPrettySuperAbilityName(SuperAbilityType superAbilityType) { - return StringUtils.getPrettySuperAbilityString(superAbilityType); - } - - public static String getPrettySuperAbilityString(SuperAbilityType ability) { - return createPrettyString(ability.toString()); + /** + * Gets a pretty string representation of a SuperAbilityType. + * Results are cached to improve performance. + * + * @param superAbilityType SuperAbilityType to convert + * @return Pretty string representation of the SuperAbilityType + */ + public static String getPrettySuperAbilityString(SuperAbilityType superAbilityType) { + requireNonNull(superAbilityType, "superAbilityType cannot be null"); + return formattedSuperAbilityStrings.computeIfAbsent(superAbilityType, StringUtils::createPrettyString); } /** - * Creates a string from an array skipping the first n elements - * @param args the array to iterate over when forming the string - * @param index the amount of elements to skip over - * @return the "trimmed" string + * Creates a string from an array skipping the first n elements. + * + * @param args The array to iterate over when forming the string + * @param index The number of elements to skip over + * @return The "trimmed" string */ - public static String buildStringAfterNthElement(@NotNull String @NotNull []args, int index) { + public static String buildStringAfterNthElement(@NotNull String @NotNull [] args, int index) { StringBuilder trimMessage = new StringBuilder(); for (int i = index; i < args.length; i++) { - if (i + 1 >= args.length) - trimMessage.append(args[i]); - else - trimMessage.append(args[i]).append(" "); + if (i > index) { + trimMessage.append(' '); + } + trimMessage.append(args[i]); } return trimMessage.toString(); } - public static String getPrettyItemString(Material material) { - return createPrettyString(material.toString()); - } - - public static String getPrettyEntityTypeString(EntityType entity) { - return createPrettyString(entity.toString()); - } - - public static String getPrettyAbilityString(SuperAbilityType ability) { - return createPrettyString(ability.toString()); - } - - public static String getWildcardConfigBlockDataString(BlockData data) { - return getWildcardConfigMaterialString(data.getMaterial()); - } - - public static String getWildcardConfigMaterialString(Material data) { - return StringUtils.getPrettyItemString(data).replace(" ", "_") + "|*"; + /** + * Gets a pretty string representation of a Material. + * Results are cached to improve performance. + * + * @param material Material to convert + * @return Pretty string representation of the Material + */ + public static String getFormattedMaterialString(Material material) { + return formattedMaterialStrings.computeIfAbsent(material, StringUtils::createPrettyString); } - public static String getFriendlyConfigBlockDataString(BlockData data) { - switch(data.getMaterial()){ - case CHORUS_FLOWER: - case COCOA: - case WHEAT: - case BEETROOTS: - case CARROTS: - case POTATOES: - case NETHER_WART: { - if (data instanceof Ageable ageData) { - if (ageData.getAge() == ageData.getMaximumAge()) { - return getPrettyItemString(data.getMaterial()).replace(" ", "_") + "_Ripe"; - } - } - return getPrettyItemString(data.getMaterial()).replace(" ", "_") + "_Ungrown"; - } - } - return getPrettyItemString(data.getMaterial()).replace(" ", "_"); + /** + * Gets a pretty string representation of an EntityType. + * Results are cached to improve performance. + * + * @param entityType EntityType to convert + * @return Pretty string representation of the EntityType + */ + public static String getPrettyEntityTypeString(EntityType entityType) { + return formattedEntityStrings.computeIfAbsent(entityType, StringUtils::createPrettyString); } - public static String getFriendlyConfigMaterialString(Material data) { - return getPrettyItemString(data).replace(" ", "_"); + /** + * 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 getExplicitConfigMaterialString(data.getMaterial()); - } - - public static String getExplicitConfigMaterialString(Material data) { - return StringUtils.getPrettyItemString(data).replace(" ", "_"); + 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 createPrettyString(partyFeature.toString()); + return prettyPartyFeatureStringCache.computeIfAbsent(partyFeature, StringUtils::createPrettyString); } + /** + * Creates a pretty string from a base string by splitting underscores and capitalizing words. + * + * @param baseString String to convert + * @return Pretty string + */ private static String createPrettyString(String baseString) { - String[] substrings = baseString.split("_"); - String prettyString = ""; - int size = 1; - - for (String string : substrings) { - prettyString = prettyString.concat(getCapitalized(string)); + return PRETTY_STRING_FUNC.apply(baseString); + } - if (size < substrings.length) { - prettyString = prettyString.concat(" "); + /** + * Function to create a pretty string from a base string. + */ + private static final Function PRETTY_STRING_FUNC = baseString -> { + if (baseString.contains("_") && !baseString.contains(" ")) { + return prettify(baseString.split("_")); + } else { + if(baseString.contains(" ")) { + return prettify(baseString.split(" ")); + } else{ + return getCapitalized(baseString); } + } + }; - size++; + private static @NotNull String prettify(String[] substrings) { + final StringBuilder prettyString = new StringBuilder(); + + for (int i = 0; i < substrings.length; i++) { + prettyString.append(getCapitalized(substrings[i])); + if (i < substrings.length - 1) { + prettyString.append(' '); + } } - return prettyString; + return prettyString.toString(); + } + + /** + * Creates a pretty string from an object. + * @param object Object to convert + * @return Pretty string representation of the object + */ + private static String createPrettyString(Object object) { + return createPrettyString(object.toString()); } /** - * Determine if a string represents an Integer + * Determine if a string represents an Integer. * - * @param string - * String to check + * @param string String to check * @return true if the string is an Integer, false otherwise */ public static boolean isInt(String string) { try { Integer.parseInt(string); return true; - } catch (NumberFormatException nFE) { + } catch (NumberFormatException ignored) { return false; } } /** - * Determine if a string represents a Double + * Determine if a string represents a Double. * - * @param string - * String to check + * @param string String to check * @return true if the string is a Double, false otherwise */ public static boolean isDouble(String string) { try { Double.parseDouble(string); return true; - } catch (NumberFormatException nFE) { + } catch (NumberFormatException ignored) { return false; } } - - public static String convertKeyToName(@NotNull String key) { - // used when no display name is given for a potion - final String noUnderscores = key.replace("_", " ").toLowerCase(Locale.ENGLISH); - return org.codehaus.plexus.util.StringUtils.capitalise(noUnderscores); - } } diff --git a/src/test/java/com/gmail/nossr50/MMOTestEnvironment.java b/src/test/java/com/gmail/nossr50/MMOTestEnvironment.java index 72f883a681..d362bd93a7 100644 --- a/src/test/java/com/gmail/nossr50/MMOTestEnvironment.java +++ b/src/test/java/com/gmail/nossr50/MMOTestEnvironment.java @@ -21,7 +21,6 @@ import com.gmail.nossr50.util.skills.SkillTools; import com.gmail.nossr50.util.sounds.SoundManager; import org.bukkit.*; -import org.bukkit.attribute.Attribute; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.Event;