From 7931a095fe009bfe3f4f584017ad05616449335e Mon Sep 17 00:00:00 2001 From: nossr50 Date: Sun, 3 Jan 2021 12:21:32 -0800 Subject: [PATCH] Add some tests for com.gmail.nossr50.util.random classes --- Changelog.txt | 2 + .../commands/experience/AddlevelsCommand.java | 2 +- .../commands/experience/AddxpCommand.java | 2 +- .../experience/ExperienceCommand.java | 2 +- .../commands/experience/MmoeditCommand.java | 2 +- .../experience/SkillresetCommand.java | 4 +- .../commands/hardcore/HardcoreCommand.java | 2 +- .../nossr50/commands/skills/SkillCommand.java | 6 +- .../commands/skills/SkillGuideCommand.java | 2 +- .../config/treasure/TreasureConfig.java | 1 - .../database/FlatfileDatabaseManager.java | 2 +- .../nossr50/datatypes/player/McMMOPlayer.java | 7 +- .../datatypes/skills/PrimarySkillType.java | 6 +- .../nossr50/listeners/PlayerListener.java | 2 +- .../nossr50/listeners/WorldListener.java | 4 - .../commands/McrankCommandDisplayTask.java | 2 +- .../commands/MctopCommandDisplayTask.java | 4 +- .../skills/herbalism/HerbalismManager.java | 1 - .../commands/CommandRegistrationManager.java | 2 +- .../util/experience/ExperienceBarManager.java | 2 +- .../util/random/RandomChanceSkill.java | 57 +++------ .../nossr50/util/random/RandomChanceUtil.java | 18 ++- .../util/scoreboards/ScoreboardManager.java | 4 +- .../gmail/nossr50/util/skills/PerksUtils.java | 1 - src/test/java/com/gmail/nossr50/TestUtil.java | 17 +++ .../util/blockmeta/ChunkStoreTest.java | 12 +- .../nossr50/util/random/RandomChanceTest.java | 116 ++++++++++++++++++ 27 files changed, 195 insertions(+), 87 deletions(-) create mode 100644 src/test/java/com/gmail/nossr50/TestUtil.java create mode 100644 src/test/java/com/gmail/nossr50/util/random/RandomChanceTest.java diff --git a/Changelog.txt b/Changelog.txt index 5a72330a5..e4c81a0c3 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,6 +1,8 @@ Version 2.1.168 Fixed an IndexOutOfBoundsException error when trying to access UserBlockTracker from an invalid range (thanks t00thpick1) (API) UserBlockTracker is now the interface by which our block-tracker will be known (thanks t00thpick1) + Optimized memory access for Acrobatics fall anti-exploit mechanics (thanks t00thpick1) + Version 2.1.167 Fixed a serious dupe bug diff --git a/src/main/java/com/gmail/nossr50/commands/experience/AddlevelsCommand.java b/src/main/java/com/gmail/nossr50/commands/experience/AddlevelsCommand.java index 6c736fd2c..8863ab524 100644 --- a/src/main/java/com/gmail/nossr50/commands/experience/AddlevelsCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/experience/AddlevelsCommand.java @@ -46,6 +46,6 @@ public class AddlevelsCommand extends ExperienceCommand { if(isSilent) return; - player.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardSkill.1", value, skill.getName())); + player.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardSkill.1", value, skill.getLocalizedName())); } } diff --git a/src/main/java/com/gmail/nossr50/commands/experience/AddxpCommand.java b/src/main/java/com/gmail/nossr50/commands/experience/AddxpCommand.java index 03ad449bb..7799ef9af 100644 --- a/src/main/java/com/gmail/nossr50/commands/experience/AddxpCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/experience/AddxpCommand.java @@ -49,6 +49,6 @@ public class AddxpCommand extends ExperienceCommand { if(isSilent) return; - player.sendMessage(LocaleLoader.getString("Commands.addxp.AwardSkill", value, skill.getName())); + player.sendMessage(LocaleLoader.getString("Commands.addxp.AwardSkill", value, skill.getLocalizedName())); } } diff --git a/src/main/java/com/gmail/nossr50/commands/experience/ExperienceCommand.java b/src/main/java/com/gmail/nossr50/commands/experience/ExperienceCommand.java index 2443e6d62..6ff0b93ed 100644 --- a/src/main/java/com/gmail/nossr50/commands/experience/ExperienceCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/experience/ExperienceCommand.java @@ -159,7 +159,7 @@ public abstract class ExperienceCommand implements TabExecutor { sender.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardAll.2", playerName)); } else { - sender.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardSkill.2", skill.getName(), playerName)); + sender.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardSkill.2", skill.getLocalizedName(), playerName)); } } diff --git a/src/main/java/com/gmail/nossr50/commands/experience/MmoeditCommand.java b/src/main/java/com/gmail/nossr50/commands/experience/MmoeditCommand.java index 9aa02b164..8ef5635e5 100644 --- a/src/main/java/com/gmail/nossr50/commands/experience/MmoeditCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/experience/MmoeditCommand.java @@ -52,6 +52,6 @@ public class MmoeditCommand extends ExperienceCommand { if(isSilent) return; - player.sendMessage(LocaleLoader.getString("Commands.mmoedit.Modified.1", skill.getName(), value)); + player.sendMessage(LocaleLoader.getString("Commands.mmoedit.Modified.1", skill.getLocalizedName(), value)); } } diff --git a/src/main/java/com/gmail/nossr50/commands/experience/SkillresetCommand.java b/src/main/java/com/gmail/nossr50/commands/experience/SkillresetCommand.java index 3df1976d9..091ccadca 100644 --- a/src/main/java/com/gmail/nossr50/commands/experience/SkillresetCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/experience/SkillresetCommand.java @@ -143,7 +143,7 @@ public class SkillresetCommand implements TabExecutor { } protected void handlePlayerMessageSkill(Player player, PrimarySkillType skill) { - player.sendMessage(LocaleLoader.getString("Commands.Reset.Single", skill.getName())); + player.sendMessage(LocaleLoader.getString("Commands.Reset.Single", skill.getLocalizedName())); } private boolean validateArguments(CommandSender sender, String skillName) { @@ -155,7 +155,7 @@ public class SkillresetCommand implements TabExecutor { sender.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardAll.2", playerName)); } else { - sender.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardSkill.2", skill.getName(), playerName)); + sender.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardSkill.2", skill.getLocalizedName(), playerName)); } } diff --git a/src/main/java/com/gmail/nossr50/commands/hardcore/HardcoreCommand.java b/src/main/java/com/gmail/nossr50/commands/hardcore/HardcoreCommand.java index 6375265b2..2b78c5deb 100644 --- a/src/main/java/com/gmail/nossr50/commands/hardcore/HardcoreCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/hardcore/HardcoreCommand.java @@ -59,6 +59,6 @@ public class HardcoreCommand extends HardcoreModeCommand { skill.setHardcoreStatLossEnabled(enable); } - mcMMO.p.getServer().broadcastMessage(LocaleLoader.getString("Hardcore.Mode." + (enable ? "Enabled" : "Disabled"), LocaleLoader.getString("Hardcore.DeathStatLoss.Name"), (skill == null ? "all skills" : skill.getName()))); + mcMMO.p.getServer().broadcastMessage(LocaleLoader.getString("Hardcore.Mode." + (enable ? "Enabled" : "Disabled"), LocaleLoader.getString("Hardcore.DeathStatLoss.Name"), (skill == null ? "all skills" : skill.getLocalizedName()))); } } \ No newline at end of file diff --git a/src/main/java/com/gmail/nossr50/commands/skills/SkillCommand.java b/src/main/java/com/gmail/nossr50/commands/skills/SkillCommand.java index e550913fa..d7d5bc7df 100644 --- a/src/main/java/com/gmail/nossr50/commands/skills/SkillCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/skills/SkillCommand.java @@ -45,7 +45,7 @@ public abstract class SkillCommand implements TabExecutor { public SkillCommand(PrimarySkillType skill) { this.skill = skill; - skillName = skill.getName(); + skillName = skill.getLocalizedName(); skillGuideCommand = new SkillGuideCommand(skill); } @@ -173,10 +173,10 @@ public abstract class SkillCommand implements TabExecutor { { if(i+1 < parentList.size()) { - parentMessage.append(LocaleLoader.getString("Effects.Child.ParentList", parentList.get(i).getName(), mcMMOPlayer.getSkillLevel(parentList.get(i)))); + parentMessage.append(LocaleLoader.getString("Effects.Child.ParentList", parentList.get(i).getLocalizedName(), mcMMOPlayer.getSkillLevel(parentList.get(i)))); parentMessage.append(ChatColor.GRAY).append(", "); } else { - parentMessage.append(LocaleLoader.getString("Effects.Child.ParentList", parentList.get(i).getName(), mcMMOPlayer.getSkillLevel(parentList.get(i)))); + parentMessage.append(LocaleLoader.getString("Effects.Child.ParentList", parentList.get(i).getLocalizedName(), mcMMOPlayer.getSkillLevel(parentList.get(i)))); } } diff --git a/src/main/java/com/gmail/nossr50/commands/skills/SkillGuideCommand.java b/src/main/java/com/gmail/nossr50/commands/skills/SkillGuideCommand.java index a7879bb8d..f45ceadd3 100644 --- a/src/main/java/com/gmail/nossr50/commands/skills/SkillGuideCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/skills/SkillGuideCommand.java @@ -18,7 +18,7 @@ public class SkillGuideCommand implements CommandExecutor { private final String invalidPage = LocaleLoader.getString("Guides.Page.Invalid"); public SkillGuideCommand(PrimarySkillType skill) { - header = LocaleLoader.getString("Guides.Header", skill.getName()); + header = LocaleLoader.getString("Guides.Header", skill.getLocalizedName()); guide = getGuide(skill); } 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 51e01307e..370f2baa3 100755 --- a/src/main/java/com/gmail/nossr50/config/treasure/TreasureConfig.java +++ b/src/main/java/com/gmail/nossr50/config/treasure/TreasureConfig.java @@ -8,7 +8,6 @@ import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.Tag; import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.EntityType; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.PotionMeta; diff --git a/src/main/java/com/gmail/nossr50/database/FlatfileDatabaseManager.java b/src/main/java/com/gmail/nossr50/database/FlatfileDatabaseManager.java index 4c9753373..e9b5aafed 100644 --- a/src/main/java/com/gmail/nossr50/database/FlatfileDatabaseManager.java +++ b/src/main/java/com/gmail/nossr50/database/FlatfileDatabaseManager.java @@ -919,7 +919,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager { } int cap = Config.getInstance().getLevelCap(skill); if (Integer.parseInt(character[index]) > cap) { - mcMMO.p.getLogger().warning("Truncating " + skill.getName() + " to configured max level for player " + character[USERNAME]); + mcMMO.p.getLogger().warning("Truncating " + skill.getLocalizedName() + " to configured max level for player " + character[USERNAME]); character[index] = cap + ""; updated = true; } 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 cc5aebefe..85dd12fe4 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java +++ b/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java @@ -57,7 +57,6 @@ import com.gmail.nossr50.util.sounds.SoundManager; import com.gmail.nossr50.util.sounds.SoundType; import net.kyori.adventure.identity.Identified; import net.kyori.adventure.identity.Identity; -import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Location; @@ -193,7 +192,7 @@ public class McMMOPlayer implements Identified { if(hasReachedPowerLevelCap()) { NotificationManager.sendPlayerInformationChatOnly(player, "LevelCap.PowerLevel", String.valueOf(Config.getInstance().getPowerLevelCap())); } else if(hasReachedLevelCap(primarySkillType)) { - NotificationManager.sendPlayerInformationChatOnly(player, "LevelCap.Skill", String.valueOf(Config.getInstance().getLevelCap(primarySkillType)), primarySkillType.getName()); + NotificationManager.sendPlayerInformationChatOnly(player, "LevelCap.Skill", String.valueOf(Config.getInstance().getLevelCap(primarySkillType)), primarySkillType.getLocalizedName()); } //Updates from Party sources @@ -828,7 +827,7 @@ public class McMMOPlayer implements Identified { int diff = RankUtils.getSuperAbilityUnlockRequirement(skill.getAbility()) - getSkillLevel(skill); //Inform the player they are not yet skilled enough - NotificationManager.sendPlayerInformation(player, NotificationType.ABILITY_COOLDOWN, "Skills.AbilityGateRequirementFail", String.valueOf(diff), skill.getName()); + NotificationManager.sendPlayerInformation(player, NotificationType.ABILITY_COOLDOWN, "Skills.AbilityGateRequirementFail", String.valueOf(diff), skill.getLocalizedName()); return; } @@ -984,7 +983,7 @@ public class McMMOPlayer implements Identified { String allCDStr = aSuperAbilityCD + ", " + bSuperAbilityCD; NotificationManager.sendPlayerInformation(player, NotificationType.TOOL, "Skills.TooTired.Extra", - primarySkillType.getName(), + primarySkillType.getLocalizedName(), allCDStr); } diff --git a/src/main/java/com/gmail/nossr50/datatypes/skills/PrimarySkillType.java b/src/main/java/com/gmail/nossr50/datatypes/skills/PrimarySkillType.java index 6acc8cf5d..f8e0afb5b 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/skills/PrimarySkillType.java +++ b/src/main/java/com/gmail/nossr50/datatypes/skills/PrimarySkillType.java @@ -234,10 +234,14 @@ public enum PrimarySkillType { return null; } - public String getName() { + public String getLocalizedName() { return StringUtils.getCapitalized(LocaleLoader.getString(StringUtils.getCapitalized(this.toString()) + ".SkillName")); } + public String getName() { + return StringUtils.getCapitalized(StringUtils.getCapitalized(this.toString())); + } + public boolean getPermissions(Player player) { return Permissions.skillEnabled(player, this); } diff --git a/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java b/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java index b410a330d..81496c046 100644 --- a/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java @@ -937,7 +937,7 @@ public class PlayerListener implements Listener { // Do these ACTUALLY have to be lower case to work properly? for (PrimarySkillType skill : PrimarySkillType.values()) { String skillName = skill.toString().toLowerCase(Locale.ENGLISH); - String localizedName = skill.getName().toLowerCase(Locale.ENGLISH); + String localizedName = skill.getLocalizedName().toLowerCase(Locale.ENGLISH); if (lowerCaseCommand.equals(localizedName)) { event.setMessage(message.replace(command, skillName)); diff --git a/src/main/java/com/gmail/nossr50/listeners/WorldListener.java b/src/main/java/com/gmail/nossr50/listeners/WorldListener.java index 650a0e0cc..a08071a04 100644 --- a/src/main/java/com/gmail/nossr50/listeners/WorldListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/WorldListener.java @@ -3,18 +3,14 @@ package com.gmail.nossr50.listeners; import com.gmail.nossr50.config.WorldBlacklist; import com.gmail.nossr50.mcMMO; import org.bukkit.Chunk; -import org.bukkit.World; import org.bukkit.block.BlockState; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.world.ChunkUnloadEvent; import org.bukkit.event.world.StructureGrowEvent; -import org.bukkit.event.world.WorldInitEvent; import org.bukkit.event.world.WorldUnloadEvent; -import java.io.File; - public class WorldListener implements Listener { private final mcMMO plugin; diff --git a/src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandDisplayTask.java b/src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandDisplayTask.java index 353e0ea04..a0e26d306 100644 --- a/src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandDisplayTask.java +++ b/src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandDisplayTask.java @@ -53,7 +53,7 @@ public class McrankCommandDisplayTask extends BukkitRunnable { // } rank = skills.get(skill); - sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Skill", skill.getName(), (rank == null ? LocaleLoader.getString("Commands.mcrank.Unranked") : rank))); + sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Skill", skill.getLocalizedName(), (rank == null ? LocaleLoader.getString("Commands.mcrank.Unranked") : rank))); } rank = skills.get(null); diff --git a/src/main/java/com/gmail/nossr50/runnables/commands/MctopCommandDisplayTask.java b/src/main/java/com/gmail/nossr50/runnables/commands/MctopCommandDisplayTask.java index 664a1da10..4901f6bb8 100644 --- a/src/main/java/com/gmail/nossr50/runnables/commands/MctopCommandDisplayTask.java +++ b/src/main/java/com/gmail/nossr50/runnables/commands/MctopCommandDisplayTask.java @@ -61,10 +61,10 @@ public class MctopCommandDisplayTask extends BukkitRunnable { } else { if(sender instanceof Player) { - sender.sendMessage(LocaleLoader.getString("Commands.Skill.Leaderboard", skill.getName())); + sender.sendMessage(LocaleLoader.getString("Commands.Skill.Leaderboard", skill.getLocalizedName())); } else { - sender.sendMessage(ChatColor.stripColor(LocaleLoader.getString("Commands.Skill.Leaderboard", skill.getName()))); + sender.sendMessage(ChatColor.stripColor(LocaleLoader.getString("Commands.Skill.Leaderboard", skill.getLocalizedName()))); } } 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 b997f9c89..72fc0e1bb 100644 --- a/src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java +++ b/src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java @@ -740,7 +740,6 @@ public class HerbalismManager extends SkillManager { return false; } - if (!playerInventory.containsAtLeast(seedStack, 1)) { return false; } diff --git a/src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java b/src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java index 215c160d8..f072d2440 100644 --- a/src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java +++ b/src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java @@ -37,7 +37,7 @@ public final class CommandRegistrationManager { private static void registerSkillCommands() { for (PrimarySkillType skill : PrimarySkillType.values()) { String commandName = skill.toString().toLowerCase(Locale.ENGLISH); - String localizedName = skill.getName().toLowerCase(Locale.ENGLISH); + String localizedName = skill.getLocalizedName().toLowerCase(Locale.ENGLISH); PluginCommand command; diff --git a/src/main/java/com/gmail/nossr50/util/experience/ExperienceBarManager.java b/src/main/java/com/gmail/nossr50/util/experience/ExperienceBarManager.java index 7a49a1260..22e14de09 100644 --- a/src/main/java/com/gmail/nossr50/util/experience/ExperienceBarManager.java +++ b/src/main/java/com/gmail/nossr50/util/experience/ExperienceBarManager.java @@ -149,7 +149,7 @@ public class ExperienceBarManager { private void informPlayer(@NotNull ExperienceBarManager.@NotNull XPBarSettingTarget settingTarget, @Nullable PrimarySkillType skillType) { //Inform player of setting change if(settingTarget != XPBarSettingTarget.RESET) { - NotificationManager.sendPlayerInformationChatOnlyPrefixed(mcMMOPlayer.getPlayer(), "Commands.XPBar.SettingChanged", skillType.getName(), settingTarget.toString()); + NotificationManager.sendPlayerInformationChatOnlyPrefixed(mcMMOPlayer.getPlayer(), "Commands.XPBar.SettingChanged", skillType.getLocalizedName(), settingTarget.toString()); } else { NotificationManager.sendPlayerInformationChatOnlyPrefixed(mcMMOPlayer.getPlayer(), "Commands.XPBar.Reset"); } diff --git a/src/main/java/com/gmail/nossr50/util/random/RandomChanceSkill.java b/src/main/java/com/gmail/nossr50/util/random/RandomChanceSkill.java index 67221a433..c77a9e9a1 100644 --- a/src/main/java/com/gmail/nossr50/util/random/RandomChanceSkill.java +++ b/src/main/java/com/gmail/nossr50/util/random/RandomChanceSkill.java @@ -1,8 +1,6 @@ package com.gmail.nossr50.util.random; -import com.gmail.nossr50.config.AdvancedConfig; import com.gmail.nossr50.datatypes.player.McMMOPlayer; -import com.gmail.nossr50.datatypes.skills.PrimarySkillType; import com.gmail.nossr50.datatypes.skills.SubSkillType; import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.player.UserManager; @@ -11,109 +9,92 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class RandomChanceSkill implements RandomChanceExecution { - - protected final @NotNull PrimarySkillType primarySkillType; - protected final @NotNull SubSkillType subSkillType; protected final double probabilityCap; protected final boolean isLucky; protected int skillLevel; - protected double resultModifier; + protected final double resultModifier; + protected final double maximumBonusLevelCap; public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType, double resultModifier) { - this.primarySkillType = subSkillType.getParentSkill(); - this.subSkillType = subSkillType; this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR; final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); if (player != null && mcMMOPlayer != null) { - this.skillLevel = mcMMOPlayer.getSkillLevel(primarySkillType); + this.skillLevel = mcMMOPlayer.getSkillLevel(subSkillType.getParentSkill()); } else { this.skillLevel = 0; } if (player != null) - isLucky = Permissions.lucky(player, primarySkillType); + isLucky = Permissions.lucky(player, subSkillType.getParentSkill()); else isLucky = false; this.resultModifier = resultModifier; + this.maximumBonusLevelCap = RandomChanceUtil.getMaxBonusLevelCap(subSkillType); } public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType) { - this.primarySkillType = subSkillType.getParentSkill(); - this.subSkillType = subSkillType; this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR; final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); if (player != null && mcMMOPlayer != null) { - this.skillLevel = mcMMOPlayer.getSkillLevel(primarySkillType); + this.skillLevel = mcMMOPlayer.getSkillLevel(subSkillType.getParentSkill()); } else { this.skillLevel = 0; } if (player != null) - isLucky = Permissions.lucky(player, primarySkillType); + isLucky = Permissions.lucky(player, subSkillType.getParentSkill()); else isLucky = false; this.resultModifier = 1.0D; + this.maximumBonusLevelCap = RandomChanceUtil.getMaxBonusLevelCap(subSkillType); } public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean hasCap) { if (hasCap) - this.probabilityCap = AdvancedConfig.getInstance().getMaximumProbability(subSkillType); + this.probabilityCap = RandomChanceUtil.getMaximumProbability(subSkillType); else this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR; - this.primarySkillType = subSkillType.getParentSkill(); - this.subSkillType = subSkillType; - final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); if (player != null && mcMMOPlayer != null) { - this.skillLevel = mcMMOPlayer.getSkillLevel(primarySkillType); + this.skillLevel = mcMMOPlayer.getSkillLevel(subSkillType.getParentSkill()); } else { this.skillLevel = 0; } if (player != null) - isLucky = Permissions.lucky(player, primarySkillType); + isLucky = Permissions.lucky(player, subSkillType.getParentSkill()); else isLucky = false; this.resultModifier = 1.0D; + this.maximumBonusLevelCap = RandomChanceUtil.getMaxBonusLevelCap(subSkillType); } public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean hasCap, double resultModifier) { if (hasCap) - this.probabilityCap = AdvancedConfig.getInstance().getMaximumProbability(subSkillType); + this.probabilityCap = RandomChanceUtil.getMaximumProbability(subSkillType); else this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR; - this.primarySkillType = subSkillType.getParentSkill(); - this.subSkillType = subSkillType; - final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); if (player != null && mcMMOPlayer != null) { - this.skillLevel = mcMMOPlayer.getSkillLevel(primarySkillType); + this.skillLevel = mcMMOPlayer.getSkillLevel(subSkillType.getParentSkill()); } else { this.skillLevel = 0; } if (player != null) - isLucky = Permissions.lucky(player, primarySkillType); + isLucky = Permissions.lucky(player, subSkillType.getParentSkill()); else isLucky = false; this.resultModifier = resultModifier; - } - - /** - * The subskill corresponding to this RandomChanceSkill - * - * @return this subskill - */ - public @NotNull SubSkillType getSubSkill() { - return subSkillType; + this.maximumBonusLevelCap = RandomChanceUtil.getMaxBonusLevelCap(subSkillType); } /** @@ -142,7 +123,7 @@ public class RandomChanceSkill implements RandomChanceExecution { * @return the maximum bonus from skill level for this skill */ public double getMaximumBonusLevelCap() { - return AdvancedConfig.getInstance().getMaxBonusLevel(subSkillType); + return maximumBonusLevelCap; } /** @@ -173,8 +154,4 @@ public class RandomChanceSkill implements RandomChanceExecution { public double getResultModifier() { return resultModifier; } - - public void setResultModifier(double resultModifier) { - this.resultModifier = resultModifier; - } } diff --git a/src/main/java/com/gmail/nossr50/util/random/RandomChanceUtil.java b/src/main/java/com/gmail/nossr50/util/random/RandomChanceUtil.java index 885ff3a90..a6f27ef54 100644 --- a/src/main/java/com/gmail/nossr50/util/random/RandomChanceUtil.java +++ b/src/main/java/com/gmail/nossr50/util/random/RandomChanceUtil.java @@ -3,7 +3,6 @@ package com.gmail.nossr50.util.random; import com.gmail.nossr50.config.AdvancedConfig; import com.gmail.nossr50.datatypes.skills.PrimarySkillType; import com.gmail.nossr50.datatypes.skills.SubSkillType; -import com.gmail.nossr50.datatypes.skills.subskills.AbstractSubSkill; import com.gmail.nossr50.events.skills.secondaryabilities.SubSkillEvent; import com.gmail.nossr50.events.skills.secondaryabilities.SubSkillRandomCheckEvent; import com.gmail.nossr50.util.EventUtils; @@ -20,6 +19,7 @@ public class RandomChanceUtil { public static final @NotNull DecimalFormat percent = new DecimalFormat("##0.00%"); //public static final DecimalFormat decimal = new DecimalFormat("##0.00"); public static final double LINEAR_CURVE_VAR = 100.0D; + public static final double LUCKY_MODIFIER = 1.333D; /** * This method is the final step in determining if a Sub-Skill / Secondary Skill in mcMMO successfully activates either from chance or otherwise @@ -142,7 +142,7 @@ public class RandomChanceUtil { return chanceOfSuccess; }*/ - private static double calculateChanceOfSuccess(@NotNull RandomChanceSkill randomChance) { + public static double calculateChanceOfSuccess(@NotNull RandomChanceSkill randomChance) { double skillLevel = randomChance.getSkillLevel(); double maximumProbability = randomChance.getProbabilityCap(); double maximumBonusLevel = randomChance.getMaximumBonusLevelCap(); @@ -163,7 +163,7 @@ public class RandomChanceUtil { return chanceOfSuccess; } - private static double calculateChanceOfSuccess(@NotNull RandomChanceSkillStatic randomChance) { + public static double calculateChanceOfSuccess(@NotNull RandomChanceSkillStatic randomChance) { double chanceOfSuccess = getChanceOfSuccess(randomChance.getXPos(), 100, 100); //Add Luck @@ -304,15 +304,23 @@ public class RandomChanceUtil { public static double addLuck(@NotNull Player player, @NotNull PrimarySkillType primarySkillType, double chance) { if (Permissions.lucky(player, primarySkillType)) - return chance * 1.333D; + return chance * LUCKY_MODIFIER; else return chance; } public static double addLuck(boolean isLucky, double chance) { if (isLucky) - return chance * 1.333D; + return chance * LUCKY_MODIFIER; else return chance; } + + public static double getMaximumProbability(@NotNull SubSkillType subSkillType) { + return AdvancedConfig.getInstance().getMaximumProbability(subSkillType); + } + + public static double getMaxBonusLevelCap(@NotNull SubSkillType subSkillType) { + return AdvancedConfig.getInstance().getMaxBonusLevel(subSkillType); + } } diff --git a/src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardManager.java b/src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardManager.java index ad32306ae..119138ca6 100644 --- a/src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardManager.java +++ b/src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardManager.java @@ -93,7 +93,7 @@ public class ScoreboardManager { int i = 0; for (PrimarySkillType type : PrimarySkillType.values()) { // Include child skills - skillLabelBuilder.put(type, getShortenedName(colors.get(i) + type.getName(), false)); + skillLabelBuilder.put(type, getShortenedName(colors.get(i) + type.getLocalizedName(), false)); if (type.getAbility() != null) { abilityLabelBuilder.put(type.getAbility(), getShortenedName(colors.get(i) + type.getAbility().getLocalizedName())); @@ -115,7 +115,7 @@ public class ScoreboardManager { else { for (PrimarySkillType type : PrimarySkillType.values()) { // Include child skills - skillLabelBuilder.put(type, getShortenedName(ChatColor.GREEN + type.getName())); + skillLabelBuilder.put(type, getShortenedName(ChatColor.GREEN + type.getLocalizedName())); if (type.getAbility() != null) { abilityLabelBuilder.put(type.getAbility(), formatAbility(type.getAbility().getLocalizedName())); diff --git a/src/main/java/com/gmail/nossr50/util/skills/PerksUtils.java b/src/main/java/com/gmail/nossr50/util/skills/PerksUtils.java index 588b944e1..1aa39105a 100644 --- a/src/main/java/com/gmail/nossr50/util/skills/PerksUtils.java +++ b/src/main/java/com/gmail/nossr50/util/skills/PerksUtils.java @@ -5,7 +5,6 @@ import com.gmail.nossr50.datatypes.skills.PrimarySkillType; import com.gmail.nossr50.events.skills.SkillActivationPerkEvent; import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.player.UserManager; - import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.entity.Player; diff --git a/src/test/java/com/gmail/nossr50/TestUtil.java b/src/test/java/com/gmail/nossr50/TestUtil.java new file mode 100644 index 000000000..341bf4fc0 --- /dev/null +++ b/src/test/java/com/gmail/nossr50/TestUtil.java @@ -0,0 +1,17 @@ +package com.gmail.nossr50; + +import org.jetbrains.annotations.NotNull; + +import java.io.File; + +//TODO: Move generic test stuff here +public class TestUtil { + public static void recursiveDelete(@NotNull File directoryToBeDeleted) { + if (directoryToBeDeleted.isDirectory()) { + for (File file : directoryToBeDeleted.listFiles()) { + recursiveDelete(file); + } + } + directoryToBeDeleted.delete(); + } +} diff --git a/src/test/java/com/gmail/nossr50/util/blockmeta/ChunkStoreTest.java b/src/test/java/com/gmail/nossr50/util/blockmeta/ChunkStoreTest.java index 5f1af96da..450cd7222 100644 --- a/src/test/java/com/gmail/nossr50/util/blockmeta/ChunkStoreTest.java +++ b/src/test/java/com/gmail/nossr50/util/blockmeta/ChunkStoreTest.java @@ -1,5 +1,6 @@ package com.gmail.nossr50.util.blockmeta; +import com.gmail.nossr50.TestUtil; import com.google.common.io.Files; import org.bukkit.Bukkit; import org.bukkit.World; @@ -31,7 +32,7 @@ public class ChunkStoreTest { @AfterClass public static void tearDownClass() { - recursiveDelete(tempDir); + TestUtil.recursiveDelete(tempDir); } private World mockWorld; @@ -184,15 +185,6 @@ public class ChunkStoreTest { Assert.assertTrue(expected.isTrue(x, y, z) == actual.isTrue(x, y, z)); } - private static void recursiveDelete(@NotNull File directoryToBeDeleted) { - if (directoryToBeDeleted.isDirectory()) { - for (File file : directoryToBeDeleted.listFiles()) { - recursiveDelete(file); - } - } - directoryToBeDeleted.delete(); - } - private static byte[] serializeChunkstore(@NotNull ChunkStore chunkStore) throws IOException { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); if (chunkStore instanceof BitSetChunkStore) diff --git a/src/test/java/com/gmail/nossr50/util/random/RandomChanceTest.java b/src/test/java/com/gmail/nossr50/util/random/RandomChanceTest.java new file mode 100644 index 000000000..b6e2e51f8 --- /dev/null +++ b/src/test/java/com/gmail/nossr50/util/random/RandomChanceTest.java @@ -0,0 +1,116 @@ +package com.gmail.nossr50.util.random; + +import com.gmail.nossr50.datatypes.player.McMMOPlayer; +import com.gmail.nossr50.datatypes.skills.PrimarySkillType; +import com.gmail.nossr50.datatypes.skills.SubSkillType; +import com.gmail.nossr50.util.Permissions; +import com.gmail.nossr50.util.player.UserManager; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import static org.mockito.Mockito.mock; + +//TODO: Rewrite the entire com.gmail.nossr50.util.random package, it was written in haste and it disgusts me +//TODO: Add more tests for the other types of random dice rolls +@RunWith(PowerMockRunner.class) +@PrepareForTest({RandomChanceUtil.class, UserManager.class}) +public class RandomChanceTest { + + private Player luckyPlayer; + private McMMOPlayer mmoPlayerLucky; + + private Player normalPlayer; + private McMMOPlayer mmoPlayerNormal; + + private SubSkillType subSkillType; + private PrimarySkillType primarySkillType; + + private final String testASCIIHeader = "---- mcMMO Tests ----"; + + @Before + public void setUpMock() { + primarySkillType = PrimarySkillType.HERBALISM; + subSkillType = SubSkillType.HERBALISM_GREEN_THUMB; + + //TODO: Likely needs to be changed per skill if more tests were added + PowerMockito.stub(PowerMockito.method(RandomChanceUtil.class, "getMaximumProbability", subSkillType.getClass())).toReturn(100D); + PowerMockito.stub(PowerMockito.method(RandomChanceUtil.class, "getMaxBonusLevelCap", subSkillType.getClass())).toReturn(1000D); + + normalPlayer = mock(Player.class); + luckyPlayer = mock(Player.class); + + mmoPlayerNormal = mock(McMMOPlayer.class); + mmoPlayerLucky = mock(McMMOPlayer.class); + + PowerMockito.mockStatic(UserManager.class); + Mockito.when(UserManager.getPlayer(normalPlayer)).thenReturn(mmoPlayerNormal); + Mockito.when(UserManager.getPlayer(luckyPlayer)).thenReturn(mmoPlayerLucky); + + Mockito.when(mmoPlayerNormal.getPlayer()).thenReturn(normalPlayer); + Mockito.when(mmoPlayerLucky.getPlayer()).thenReturn(luckyPlayer); + + //Lucky player has the lucky permission + //Normal player doesn't have any lucky permission + Mockito.when(Permissions.lucky(luckyPlayer, primarySkillType)).thenReturn(true); + Mockito.when(Permissions.lucky(normalPlayer, primarySkillType)).thenReturn(false); + + Mockito.when(mmoPlayerNormal.getSkillLevel(primarySkillType)).thenReturn(800); + Mockito.when(mmoPlayerLucky.getSkillLevel(primarySkillType)).thenReturn(800); + } + + @Test + public void testLuckyChance() { + System.out.println(testASCIIHeader); + System.out.println("Testing success odds to fall within expected values..."); + assertEquals(80D, getSuccessChance(mmoPlayerNormal),0D); + assertEquals(80D * RandomChanceUtil.LUCKY_MODIFIER, getSuccessChance(mmoPlayerLucky),0D); + } + + @Test + public void testNeverFailsSuccessLuckyPlayer() { + System.out.println(testASCIIHeader); + System.out.println("Test - Lucky Player with 80% base success should never fail (10,000 iterations)"); + for(int x = 0; x < 10000; x++) { + Assert.assertTrue(RandomChanceUtil.checkRandomChanceExecutionSuccess(luckyPlayer, SubSkillType.HERBALISM_GREEN_THUMB, true)); + if(x == 10000-1) + System.out.println("They never failed!"); + } + } + + @Test + public void testFailsAboutExpected() { + System.out.println(testASCIIHeader); + System.out.println("Test - Player with 800 skill should fail about 20% of the time (100,000 iterations)"); + double ratioDivisor = 1000; //1000 because we run the test 100,000 times + double expectedFailRate = 20D; + + double win = 0, loss = 0; + for(int x = 0; x < 100000; x++) { + if(RandomChanceUtil.checkRandomChanceExecutionSuccess(normalPlayer, SubSkillType.HERBALISM_GREEN_THUMB, true)) { + win++; + } else { + loss++; + } + } + + double lossRatio = (loss / ratioDivisor); + Assert.assertEquals(lossRatio, expectedFailRate, 1D); + } + + private double getSuccessChance(@NotNull McMMOPlayer mmoPlayer) { + RandomChanceSkill randomChanceSkill = new RandomChanceSkill(mmoPlayer.getPlayer(), subSkillType, true); + return RandomChanceUtil.calculateChanceOfSuccess(randomChanceSkill); + } + + private void assertEquals(double expected, double actual, double delta) { + Assert.assertEquals(expected, actual, delta); + } +}