Browse Source

Add some tests for com.gmail.nossr50.util.random classes

nossr50 4 years ago
parent
commit
7931a095fe
27 changed files with 195 additions and 87 deletions
  1. 2 0
      Changelog.txt
  2. 1 1
      src/main/java/com/gmail/nossr50/commands/experience/AddlevelsCommand.java
  3. 1 1
      src/main/java/com/gmail/nossr50/commands/experience/AddxpCommand.java
  4. 1 1
      src/main/java/com/gmail/nossr50/commands/experience/ExperienceCommand.java
  5. 1 1
      src/main/java/com/gmail/nossr50/commands/experience/MmoeditCommand.java
  6. 2 2
      src/main/java/com/gmail/nossr50/commands/experience/SkillresetCommand.java
  7. 1 1
      src/main/java/com/gmail/nossr50/commands/hardcore/HardcoreCommand.java
  8. 3 3
      src/main/java/com/gmail/nossr50/commands/skills/SkillCommand.java
  9. 1 1
      src/main/java/com/gmail/nossr50/commands/skills/SkillGuideCommand.java
  10. 0 1
      src/main/java/com/gmail/nossr50/config/treasure/TreasureConfig.java
  11. 1 1
      src/main/java/com/gmail/nossr50/database/FlatfileDatabaseManager.java
  12. 3 4
      src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java
  13. 5 1
      src/main/java/com/gmail/nossr50/datatypes/skills/PrimarySkillType.java
  14. 1 1
      src/main/java/com/gmail/nossr50/listeners/PlayerListener.java
  15. 0 4
      src/main/java/com/gmail/nossr50/listeners/WorldListener.java
  16. 1 1
      src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandDisplayTask.java
  17. 2 2
      src/main/java/com/gmail/nossr50/runnables/commands/MctopCommandDisplayTask.java
  18. 0 1
      src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java
  19. 1 1
      src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java
  20. 1 1
      src/main/java/com/gmail/nossr50/util/experience/ExperienceBarManager.java
  21. 17 40
      src/main/java/com/gmail/nossr50/util/random/RandomChanceSkill.java
  22. 13 5
      src/main/java/com/gmail/nossr50/util/random/RandomChanceUtil.java
  23. 2 2
      src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardManager.java
  24. 0 1
      src/main/java/com/gmail/nossr50/util/skills/PerksUtils.java
  25. 17 0
      src/test/java/com/gmail/nossr50/TestUtil.java
  26. 2 10
      src/test/java/com/gmail/nossr50/util/blockmeta/ChunkStoreTest.java
  27. 116 0
      src/test/java/com/gmail/nossr50/util/random/RandomChanceTest.java

+ 2 - 0
Changelog.txt

@@ -1,6 +1,8 @@
 Version 2.1.168
 Version 2.1.168
     Fixed an IndexOutOfBoundsException error when trying to access UserBlockTracker from an invalid range (thanks t00thpick1)
     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)
     (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
 Version 2.1.167
     Fixed a serious dupe bug
     Fixed a serious dupe bug

+ 1 - 1
src/main/java/com/gmail/nossr50/commands/experience/AddlevelsCommand.java

@@ -46,6 +46,6 @@ public class AddlevelsCommand extends ExperienceCommand {
         if(isSilent)
         if(isSilent)
             return;
             return;
 
 
-        player.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardSkill.1", value, skill.getName()));
+        player.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardSkill.1", value, skill.getLocalizedName()));
     }
     }
 }
 }

+ 1 - 1
src/main/java/com/gmail/nossr50/commands/experience/AddxpCommand.java

@@ -49,6 +49,6 @@ public class AddxpCommand extends ExperienceCommand {
         if(isSilent)
         if(isSilent)
             return;
             return;
 
 
-        player.sendMessage(LocaleLoader.getString("Commands.addxp.AwardSkill", value, skill.getName()));
+        player.sendMessage(LocaleLoader.getString("Commands.addxp.AwardSkill", value, skill.getLocalizedName()));
     }
     }
 }
 }

+ 1 - 1
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));
             sender.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardAll.2", playerName));
         }
         }
         else {
         else {
-            sender.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardSkill.2", skill.getName(), playerName));
+            sender.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardSkill.2", skill.getLocalizedName(), playerName));
         }
         }
     }
     }
 
 

+ 1 - 1
src/main/java/com/gmail/nossr50/commands/experience/MmoeditCommand.java

@@ -52,6 +52,6 @@ public class MmoeditCommand extends ExperienceCommand {
         if(isSilent)
         if(isSilent)
             return;
             return;
 
 
-        player.sendMessage(LocaleLoader.getString("Commands.mmoedit.Modified.1", skill.getName(), value));
+        player.sendMessage(LocaleLoader.getString("Commands.mmoedit.Modified.1", skill.getLocalizedName(), value));
     }
     }
 }
 }

+ 2 - 2
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) {
     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) {
     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));
             sender.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardAll.2", playerName));
         }
         }
         else {
         else {
-            sender.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardSkill.2", skill.getName(), playerName));
+            sender.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardSkill.2", skill.getLocalizedName(), playerName));
         }
         }
     }
     }
 
 

+ 1 - 1
src/main/java/com/gmail/nossr50/commands/hardcore/HardcoreCommand.java

@@ -59,6 +59,6 @@ public class HardcoreCommand extends HardcoreModeCommand {
             skill.setHardcoreStatLossEnabled(enable);
             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())));
     }
     }
 }
 }

+ 3 - 3
src/main/java/com/gmail/nossr50/commands/skills/SkillCommand.java

@@ -45,7 +45,7 @@ public abstract class SkillCommand implements TabExecutor {
 
 
     public SkillCommand(PrimarySkillType skill) {
     public SkillCommand(PrimarySkillType skill) {
         this.skill = skill;
         this.skill = skill;
-        skillName = skill.getName();
+        skillName = skill.getLocalizedName();
         skillGuideCommand = new SkillGuideCommand(skill);
         skillGuideCommand = new SkillGuideCommand(skill);
     }
     }
 
 
@@ -173,10 +173,10 @@ public abstract class SkillCommand implements TabExecutor {
             {
             {
                 if(i+1 < parentList.size())
                 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(", ");
                     parentMessage.append(ChatColor.GRAY).append(", ");
                 } else {
                 } 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))));
                 }
                 }
             }
             }
 
 

+ 1 - 1
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");
     private final String invalidPage = LocaleLoader.getString("Guides.Page.Invalid");
 
 
     public SkillGuideCommand(PrimarySkillType skill) {
     public SkillGuideCommand(PrimarySkillType skill) {
-        header = LocaleLoader.getString("Guides.Header", skill.getName());
+        header = LocaleLoader.getString("Guides.Header", skill.getLocalizedName());
         guide = getGuide(skill);
         guide = getGuide(skill);
     }
     }
 
 

+ 0 - 1
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.Material;
 import org.bukkit.Tag;
 import org.bukkit.Tag;
 import org.bukkit.configuration.ConfigurationSection;
 import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.entity.EntityType;
 import org.bukkit.inventory.ItemStack;
 import org.bukkit.inventory.ItemStack;
 import org.bukkit.inventory.meta.ItemMeta;
 import org.bukkit.inventory.meta.ItemMeta;
 import org.bukkit.inventory.meta.PotionMeta;
 import org.bukkit.inventory.meta.PotionMeta;

+ 1 - 1
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);
                                 int cap = Config.getInstance().getLevelCap(skill);
                                 if (Integer.parseInt(character[index]) > cap) {
                                 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 + "";
                                     character[index] = cap + "";
                                     updated = true;
                                     updated = true;
                                 }
                                 }

+ 3 - 4
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 com.gmail.nossr50.util.sounds.SoundType;
 import net.kyori.adventure.identity.Identified;
 import net.kyori.adventure.identity.Identified;
 import net.kyori.adventure.identity.Identity;
 import net.kyori.adventure.identity.Identity;
-import org.apache.commons.lang.Validate;
 import org.bukkit.Bukkit;
 import org.bukkit.Bukkit;
 import org.bukkit.GameMode;
 import org.bukkit.GameMode;
 import org.bukkit.Location;
 import org.bukkit.Location;
@@ -193,7 +192,7 @@ public class McMMOPlayer implements Identified {
         if(hasReachedPowerLevelCap()) {
         if(hasReachedPowerLevelCap()) {
             NotificationManager.sendPlayerInformationChatOnly(player, "LevelCap.PowerLevel", String.valueOf(Config.getInstance().getPowerLevelCap()));
             NotificationManager.sendPlayerInformationChatOnly(player, "LevelCap.PowerLevel", String.valueOf(Config.getInstance().getPowerLevelCap()));
         } else if(hasReachedLevelCap(primarySkillType)) {
         } 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
         //Updates from Party sources
@@ -828,7 +827,7 @@ public class McMMOPlayer implements Identified {
             int diff = RankUtils.getSuperAbilityUnlockRequirement(skill.getAbility()) - getSkillLevel(skill);
             int diff = RankUtils.getSuperAbilityUnlockRequirement(skill.getAbility()) - getSkillLevel(skill);
 
 
             //Inform the player they are not yet skilled enough
             //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;
             return;
         }
         }
 
 
@@ -984,7 +983,7 @@ public class McMMOPlayer implements Identified {
         String allCDStr = aSuperAbilityCD + ", " + bSuperAbilityCD;
         String allCDStr = aSuperAbilityCD + ", " + bSuperAbilityCD;
 
 
         NotificationManager.sendPlayerInformation(player, NotificationType.TOOL, "Skills.TooTired.Extra",
         NotificationManager.sendPlayerInformation(player, NotificationType.TOOL, "Skills.TooTired.Extra",
-                primarySkillType.getName(),
+                primarySkillType.getLocalizedName(),
                 allCDStr);
                 allCDStr);
     }
     }
 
 

+ 5 - 1
src/main/java/com/gmail/nossr50/datatypes/skills/PrimarySkillType.java

@@ -234,10 +234,14 @@ public enum PrimarySkillType {
         return null;
         return null;
     }
     }
 
 
-    public String getName() {
+    public String getLocalizedName() {
         return StringUtils.getCapitalized(LocaleLoader.getString(StringUtils.getCapitalized(this.toString()) + ".SkillName"));
         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) {
     public boolean getPermissions(Player player) {
         return Permissions.skillEnabled(player, this);
         return Permissions.skillEnabled(player, this);
     }
     }

+ 1 - 1
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?
             // Do these ACTUALLY have to be lower case to work properly?
             for (PrimarySkillType skill : PrimarySkillType.values()) {
             for (PrimarySkillType skill : PrimarySkillType.values()) {
                 String skillName = skill.toString().toLowerCase(Locale.ENGLISH);
                 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)) {
                 if (lowerCaseCommand.equals(localizedName)) {
                     event.setMessage(message.replace(command, skillName));
                     event.setMessage(message.replace(command, skillName));

+ 0 - 4
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.config.WorldBlacklist;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.mcMMO;
 import org.bukkit.Chunk;
 import org.bukkit.Chunk;
-import org.bukkit.World;
 import org.bukkit.block.BlockState;
 import org.bukkit.block.BlockState;
 import org.bukkit.event.EventHandler;
 import org.bukkit.event.EventHandler;
 import org.bukkit.event.EventPriority;
 import org.bukkit.event.EventPriority;
 import org.bukkit.event.Listener;
 import org.bukkit.event.Listener;
 import org.bukkit.event.world.ChunkUnloadEvent;
 import org.bukkit.event.world.ChunkUnloadEvent;
 import org.bukkit.event.world.StructureGrowEvent;
 import org.bukkit.event.world.StructureGrowEvent;
-import org.bukkit.event.world.WorldInitEvent;
 import org.bukkit.event.world.WorldUnloadEvent;
 import org.bukkit.event.world.WorldUnloadEvent;
 
 
-import java.io.File;
-
 public class WorldListener implements Listener {
 public class WorldListener implements Listener {
     private final mcMMO plugin;
     private final mcMMO plugin;
 
 

+ 1 - 1
src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandDisplayTask.java

@@ -53,7 +53,7 @@ public class McrankCommandDisplayTask extends BukkitRunnable {
 //            }
 //            }
 
 
             rank = skills.get(skill);
             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);
         rank = skills.get(null);

+ 2 - 2
src/main/java/com/gmail/nossr50/runnables/commands/MctopCommandDisplayTask.java

@@ -61,10 +61,10 @@ public class MctopCommandDisplayTask extends BukkitRunnable {
         }
         }
         else {
         else {
             if(sender instanceof Player) {
             if(sender instanceof Player) {
-                sender.sendMessage(LocaleLoader.getString("Commands.Skill.Leaderboard", skill.getName()));
+                sender.sendMessage(LocaleLoader.getString("Commands.Skill.Leaderboard", skill.getLocalizedName()));
             }
             }
             else {
             else {
-                sender.sendMessage(ChatColor.stripColor(LocaleLoader.getString("Commands.Skill.Leaderboard", skill.getName())));
+                sender.sendMessage(ChatColor.stripColor(LocaleLoader.getString("Commands.Skill.Leaderboard", skill.getLocalizedName())));
             }
             }
         }
         }
 
 

+ 0 - 1
src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java

@@ -740,7 +740,6 @@ public class HerbalismManager extends SkillManager {
             return false;
             return false;
         }
         }
 
 
-
         if (!playerInventory.containsAtLeast(seedStack, 1)) {
         if (!playerInventory.containsAtLeast(seedStack, 1)) {
             return false;
             return false;
         }
         }

+ 1 - 1
src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java

@@ -37,7 +37,7 @@ public final class CommandRegistrationManager {
     private static void registerSkillCommands() {
     private static void registerSkillCommands() {
         for (PrimarySkillType skill : PrimarySkillType.values()) {
         for (PrimarySkillType skill : PrimarySkillType.values()) {
             String commandName = skill.toString().toLowerCase(Locale.ENGLISH);
             String commandName = skill.toString().toLowerCase(Locale.ENGLISH);
-            String localizedName = skill.getName().toLowerCase(Locale.ENGLISH);
+            String localizedName = skill.getLocalizedName().toLowerCase(Locale.ENGLISH);
 
 
             PluginCommand command;
             PluginCommand command;
 
 

+ 1 - 1
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) {
     private void informPlayer(@NotNull ExperienceBarManager.@NotNull XPBarSettingTarget settingTarget, @Nullable PrimarySkillType skillType) {
         //Inform player of setting change
         //Inform player of setting change
         if(settingTarget != XPBarSettingTarget.RESET) {
         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 {
         } else {
             NotificationManager.sendPlayerInformationChatOnlyPrefixed(mcMMOPlayer.getPlayer(), "Commands.XPBar.Reset");
             NotificationManager.sendPlayerInformationChatOnlyPrefixed(mcMMOPlayer.getPlayer(), "Commands.XPBar.Reset");
         }
         }

+ 17 - 40
src/main/java/com/gmail/nossr50/util/random/RandomChanceSkill.java

@@ -1,8 +1,6 @@
 package com.gmail.nossr50.util.random;
 package com.gmail.nossr50.util.random;
 
 
-import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 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.datatypes.skills.SubSkillType;
 import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.player.UserManager;
 import com.gmail.nossr50.util.player.UserManager;
@@ -11,109 +9,92 @@ import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.Nullable;
 
 
 public class RandomChanceSkill implements RandomChanceExecution {
 public class RandomChanceSkill implements RandomChanceExecution {
-
-    protected final @NotNull PrimarySkillType primarySkillType;
-    protected final @NotNull SubSkillType subSkillType;
     protected final double probabilityCap;
     protected final double probabilityCap;
     protected final boolean isLucky;
     protected final boolean isLucky;
     protected int skillLevel;
     protected int skillLevel;
-    protected double resultModifier;
+    protected final double resultModifier;
+    protected final double maximumBonusLevelCap;
 
 
     public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType, double resultModifier) {
     public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType, double resultModifier) {
-        this.primarySkillType = subSkillType.getParentSkill();
-        this.subSkillType = subSkillType;
         this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR;
         this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR;
 
 
         final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
         final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
         if (player != null && mcMMOPlayer != null) {
         if (player != null && mcMMOPlayer != null) {
-            this.skillLevel = mcMMOPlayer.getSkillLevel(primarySkillType);
+            this.skillLevel = mcMMOPlayer.getSkillLevel(subSkillType.getParentSkill());
         } else {
         } else {
             this.skillLevel = 0;
             this.skillLevel = 0;
         }
         }
 
 
         if (player != null)
         if (player != null)
-            isLucky = Permissions.lucky(player, primarySkillType);
+            isLucky = Permissions.lucky(player, subSkillType.getParentSkill());
         else
         else
             isLucky = false;
             isLucky = false;
 
 
         this.resultModifier = resultModifier;
         this.resultModifier = resultModifier;
+        this.maximumBonusLevelCap = RandomChanceUtil.getMaxBonusLevelCap(subSkillType);
     }
     }
 
 
     public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType) {
     public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType) {
-        this.primarySkillType = subSkillType.getParentSkill();
-        this.subSkillType = subSkillType;
         this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR;
         this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR;
 
 
         final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
         final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
         if (player != null && mcMMOPlayer != null) {
         if (player != null && mcMMOPlayer != null) {
-            this.skillLevel = mcMMOPlayer.getSkillLevel(primarySkillType);
+            this.skillLevel = mcMMOPlayer.getSkillLevel(subSkillType.getParentSkill());
         } else {
         } else {
             this.skillLevel = 0;
             this.skillLevel = 0;
         }
         }
 
 
         if (player != null)
         if (player != null)
-            isLucky = Permissions.lucky(player, primarySkillType);
+            isLucky = Permissions.lucky(player, subSkillType.getParentSkill());
         else
         else
             isLucky = false;
             isLucky = false;
 
 
         this.resultModifier = 1.0D;
         this.resultModifier = 1.0D;
+        this.maximumBonusLevelCap = RandomChanceUtil.getMaxBonusLevelCap(subSkillType);
     }
     }
 
 
     public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean hasCap) {
     public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean hasCap) {
         if (hasCap)
         if (hasCap)
-            this.probabilityCap = AdvancedConfig.getInstance().getMaximumProbability(subSkillType);
+            this.probabilityCap = RandomChanceUtil.getMaximumProbability(subSkillType);
         else
         else
             this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR;
             this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR;
 
 
-        this.primarySkillType = subSkillType.getParentSkill();
-        this.subSkillType = subSkillType;
-
         final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
         final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
         if (player != null && mcMMOPlayer != null) {
         if (player != null && mcMMOPlayer != null) {
-            this.skillLevel = mcMMOPlayer.getSkillLevel(primarySkillType);
+            this.skillLevel = mcMMOPlayer.getSkillLevel(subSkillType.getParentSkill());
         } else {
         } else {
             this.skillLevel = 0;
             this.skillLevel = 0;
         }
         }
 
 
         if (player != null)
         if (player != null)
-            isLucky = Permissions.lucky(player, primarySkillType);
+            isLucky = Permissions.lucky(player, subSkillType.getParentSkill());
         else
         else
             isLucky = false;
             isLucky = false;
 
 
         this.resultModifier = 1.0D;
         this.resultModifier = 1.0D;
+        this.maximumBonusLevelCap = RandomChanceUtil.getMaxBonusLevelCap(subSkillType);
     }
     }
 
 
     public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean hasCap, double resultModifier) {
     public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean hasCap, double resultModifier) {
         if (hasCap)
         if (hasCap)
-            this.probabilityCap = AdvancedConfig.getInstance().getMaximumProbability(subSkillType);
+            this.probabilityCap = RandomChanceUtil.getMaximumProbability(subSkillType);
         else
         else
             this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR;
             this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR;
 
 
-        this.primarySkillType = subSkillType.getParentSkill();
-        this.subSkillType = subSkillType;
-
         final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
         final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
         if (player != null && mcMMOPlayer != null) {
         if (player != null && mcMMOPlayer != null) {
-            this.skillLevel = mcMMOPlayer.getSkillLevel(primarySkillType);
+            this.skillLevel = mcMMOPlayer.getSkillLevel(subSkillType.getParentSkill());
         } else {
         } else {
             this.skillLevel = 0;
             this.skillLevel = 0;
         }
         }
 
 
         if (player != null)
         if (player != null)
-            isLucky = Permissions.lucky(player, primarySkillType);
+            isLucky = Permissions.lucky(player, subSkillType.getParentSkill());
         else
         else
             isLucky = false;
             isLucky = false;
 
 
         this.resultModifier = resultModifier;
         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
      * @return the maximum bonus from skill level for this skill
      */
      */
     public double getMaximumBonusLevelCap() {
     public double getMaximumBonusLevelCap() {
-        return AdvancedConfig.getInstance().getMaxBonusLevel(subSkillType);
+        return maximumBonusLevelCap;
     }
     }
 
 
     /**
     /**
@@ -173,8 +154,4 @@ public class RandomChanceSkill implements RandomChanceExecution {
     public double getResultModifier() {
     public double getResultModifier() {
         return resultModifier;
         return resultModifier;
     }
     }
-
-    public void setResultModifier(double resultModifier) {
-        this.resultModifier = resultModifier;
-    }
 }
 }

+ 13 - 5
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.config.AdvancedConfig;
 import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
 import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
 import com.gmail.nossr50.datatypes.skills.SubSkillType;
 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.SubSkillEvent;
 import com.gmail.nossr50.events.skills.secondaryabilities.SubSkillRandomCheckEvent;
 import com.gmail.nossr50.events.skills.secondaryabilities.SubSkillRandomCheckEvent;
 import com.gmail.nossr50.util.EventUtils;
 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 @NotNull DecimalFormat percent = new DecimalFormat("##0.00%");
     //public static final DecimalFormat decimal = 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 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
      * 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;
         return chanceOfSuccess;
     }*/
     }*/
 
 
-    private static double calculateChanceOfSuccess(@NotNull RandomChanceSkill randomChance) {
+    public static double calculateChanceOfSuccess(@NotNull RandomChanceSkill randomChance) {
         double skillLevel = randomChance.getSkillLevel();
         double skillLevel = randomChance.getSkillLevel();
         double maximumProbability = randomChance.getProbabilityCap();
         double maximumProbability = randomChance.getProbabilityCap();
         double maximumBonusLevel = randomChance.getMaximumBonusLevelCap();
         double maximumBonusLevel = randomChance.getMaximumBonusLevelCap();
@@ -163,7 +163,7 @@ public class RandomChanceUtil {
         return chanceOfSuccess;
         return chanceOfSuccess;
     }
     }
 
 
-    private static double calculateChanceOfSuccess(@NotNull RandomChanceSkillStatic randomChance) {
+    public static double calculateChanceOfSuccess(@NotNull RandomChanceSkillStatic randomChance) {
         double chanceOfSuccess = getChanceOfSuccess(randomChance.getXPos(), 100, 100);
         double chanceOfSuccess = getChanceOfSuccess(randomChance.getXPos(), 100, 100);
 
 
         //Add Luck
         //Add Luck
@@ -304,15 +304,23 @@ public class RandomChanceUtil {
 
 
     public static double addLuck(@NotNull Player player, @NotNull PrimarySkillType primarySkillType, double chance) {
     public static double addLuck(@NotNull Player player, @NotNull PrimarySkillType primarySkillType, double chance) {
         if (Permissions.lucky(player, primarySkillType))
         if (Permissions.lucky(player, primarySkillType))
-            return chance * 1.333D;
+            return chance * LUCKY_MODIFIER;
         else
         else
             return chance;
             return chance;
     }
     }
 
 
     public static double addLuck(boolean isLucky, double chance) {
     public static double addLuck(boolean isLucky, double chance) {
         if (isLucky)
         if (isLucky)
-            return chance * 1.333D;
+            return chance * LUCKY_MODIFIER;
         else
         else
             return chance;
             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);
+    }
 }
 }

+ 2 - 2
src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardManager.java

@@ -93,7 +93,7 @@ public class ScoreboardManager {
             int i = 0;
             int i = 0;
             for (PrimarySkillType type : PrimarySkillType.values()) {
             for (PrimarySkillType type : PrimarySkillType.values()) {
                 // Include child skills
                 // 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) {
                 if (type.getAbility() != null) {
                     abilityLabelBuilder.put(type.getAbility(), getShortenedName(colors.get(i) + type.getAbility().getLocalizedName()));
                     abilityLabelBuilder.put(type.getAbility(), getShortenedName(colors.get(i) + type.getAbility().getLocalizedName()));
@@ -115,7 +115,7 @@ public class ScoreboardManager {
         else {
         else {
             for (PrimarySkillType type : PrimarySkillType.values()) {
             for (PrimarySkillType type : PrimarySkillType.values()) {
                 // Include child skills
                 // Include child skills
-                skillLabelBuilder.put(type, getShortenedName(ChatColor.GREEN + type.getName()));
+                skillLabelBuilder.put(type, getShortenedName(ChatColor.GREEN + type.getLocalizedName()));
 
 
                 if (type.getAbility() != null) {
                 if (type.getAbility() != null) {
                     abilityLabelBuilder.put(type.getAbility(), formatAbility(type.getAbility().getLocalizedName()));
                     abilityLabelBuilder.put(type.getAbility(), formatAbility(type.getAbility().getLocalizedName()));

+ 0 - 1
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.events.skills.SkillActivationPerkEvent;
 import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.player.UserManager;
 import com.gmail.nossr50.util.player.UserManager;
-
 import org.bukkit.Bukkit;
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
 import org.bukkit.ChatColor;
 import org.bukkit.entity.Player;
 import org.bukkit.entity.Player;

+ 17 - 0
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();
+    }
+}

+ 2 - 10
src/test/java/com/gmail/nossr50/util/blockmeta/ChunkStoreTest.java

@@ -1,5 +1,6 @@
 package com.gmail.nossr50.util.blockmeta;
 package com.gmail.nossr50.util.blockmeta;
 
 
+import com.gmail.nossr50.TestUtil;
 import com.google.common.io.Files;
 import com.google.common.io.Files;
 import org.bukkit.Bukkit;
 import org.bukkit.Bukkit;
 import org.bukkit.World;
 import org.bukkit.World;
@@ -31,7 +32,7 @@ public class ChunkStoreTest {
 
 
     @AfterClass
     @AfterClass
     public static void tearDownClass() {
     public static void tearDownClass() {
-        recursiveDelete(tempDir);
+        TestUtil.recursiveDelete(tempDir);
     }
     }
 
 
     private World mockWorld;
     private World mockWorld;
@@ -184,15 +185,6 @@ public class ChunkStoreTest {
                     Assert.assertTrue(expected.isTrue(x, y, z) == actual.isTrue(x, y, z));
                     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 {
     private static byte[] serializeChunkstore(@NotNull ChunkStore chunkStore) throws IOException {
         ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
         ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
         if (chunkStore instanceof BitSetChunkStore)
         if (chunkStore instanceof BitSetChunkStore)

+ 116 - 0
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);
+    }
+}