mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2024-11-24 14:16:45 +01:00
Merge branch 'master' of github.com:mcMMO-Dev/mcMMO into tridentsxbows
This commit is contained in:
commit
8a91791d2d
@ -102,6 +102,7 @@ Version 2.2.000
|
||||
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
|
||||
|
@ -45,6 +45,6 @@ public class AddlevelsCommand extends ExperienceCommand {
|
||||
if(isSilent)
|
||||
return;
|
||||
|
||||
player.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardSkill.1", value, rootSkill.getName()));
|
||||
player.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardSkill.1", value, rootSkill.getLocalizedName()));
|
||||
}
|
||||
}
|
||||
|
@ -46,6 +46,6 @@ public class AddxpCommand extends ExperienceCommand {
|
||||
if(isSilent)
|
||||
return;
|
||||
|
||||
player.sendMessage(LocaleLoader.getString("Commands.addxp.AwardSkill", value, rootSkill.getName()));
|
||||
player.sendMessage(LocaleLoader.getString("Commands.addxp.AwardSkill", value, rootSkill.getLocalizedName()));
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +161,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", rootSkill.getName(), playerName));
|
||||
sender.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardSkill.2", rootSkill.getLocalizedName(), playerName));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,6 @@ public class MmoeditCommand extends ExperienceCommand {
|
||||
if(isSilent)
|
||||
return;
|
||||
|
||||
player.sendMessage(LocaleLoader.getString("Commands.mmoedit.Modified.1", rootSkill.getName(), value));
|
||||
player.sendMessage(LocaleLoader.getString("Commands.mmoedit.Modified.1", rootSkill.getLocalizedName(), value));
|
||||
}
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ public class SkillresetCommand implements TabExecutor {
|
||||
}
|
||||
|
||||
protected void handlePlayerMessageSkill(Player player, RootSkill rootSkill) {
|
||||
player.sendMessage(LocaleLoader.getString("Commands.Reset.Single", rootSkill.getName()));
|
||||
player.sendMessage(LocaleLoader.getString("Commands.Reset.Single", rootSkill.getLocalizedName()));
|
||||
}
|
||||
|
||||
private boolean validateArguments(CommandSender sender, String skillName) {
|
||||
@ -154,7 +154,7 @@ public class SkillresetCommand implements TabExecutor {
|
||||
sender.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardAll.2", playerName));
|
||||
}
|
||||
else {
|
||||
sender.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardSkill.2", rootSkill.getName(), playerName));
|
||||
sender.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardSkill.2", rootSkill.getLocalizedName(), playerName));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,6 @@ public class HardcoreCommand extends HardcoreModeCommand {
|
||||
rootSkill.setHardcoreStatLossEnabled(enable);
|
||||
}
|
||||
|
||||
mcMMO.p.getServer().broadcastMessage(LocaleLoader.getString("Hardcore.Mode." + (enable ? "Enabled" : "Disabled"), LocaleLoader.getString("Hardcore.DeathStatLoss.Name"), (rootSkill == null ? "all skills" : rootSkill.getName())));
|
||||
mcMMO.p.getServer().broadcastMessage(LocaleLoader.getString("Hardcore.Mode." + (enable ? "Enabled" : "Disabled"), LocaleLoader.getString("Hardcore.DeathStatLoss.Name"), (rootSkill == null ? "all skills" : rootSkill.getLocalizedName())));
|
||||
}
|
||||
}
|
@ -49,7 +49,7 @@ public abstract class SkillCommand implements TabExecutor {
|
||||
public SkillCommand(@NotNull RootSkill rootSkill) {
|
||||
this.rootSkill = CoreSkills.getSkill(primarySkillType);
|
||||
this.primarySkillType = primarySkillType;
|
||||
skillName = rootSkill.getSkillName();
|
||||
skillName = rootSkill.getLocalizedName();
|
||||
skillGuideCommand = new SkillGuideCommand(rootSkill);
|
||||
}
|
||||
|
||||
@ -177,10 +177,10 @@ public abstract class SkillCommand implements TabExecutor {
|
||||
{
|
||||
if(i+1 < parentList.size())
|
||||
{
|
||||
parentMessage.append(LocaleLoader.getString("Effects.Child.ParentList", parentList.get(i).getSkillName(), mmoPlayer.getExperienceHandler().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).getSkillName(), mmoPlayer.getExperienceHandler().getSkillLevel(parentList.get(i))));
|
||||
parentMessage.append(LocaleLoader.getString("Effects.Child.ParentList", parentList.get(i).getLocalizedName(), mcMMOPlayer.getSkillLevel(parentList.get(i))));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,8 +21,8 @@ public class SkillGuideCommand implements CommandExecutor {
|
||||
private final String invalidPage = LocaleLoader.getString("Guides.Page.Invalid");
|
||||
|
||||
public SkillGuideCommand(@NotNull RootSkill rootSkill) {
|
||||
rootSkill = CoreSkills.getSkill(rootSkill);
|
||||
header = LocaleLoader.getString("Guides.Header", rootSkill.getName());
|
||||
this.rootSkill = rootSkill;
|
||||
header = LocaleLoader.getString("Guides.Header", rootSkill.getLocalizedName());
|
||||
guide = getGuide(rootSkill);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -0,0 +1,41 @@
|
||||
package com.gmail.nossr50.datatypes;
|
||||
|
||||
import com.google.common.collect.HashMultiset;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* This class works with the assumption that you only pass in Block Locations. If locations have differing pitch/yaw, the logic breaks
|
||||
*/
|
||||
public class BlockLocationHistory {
|
||||
private final LinkedList<Location> limitedSizeOrderedList = new LinkedList<>();
|
||||
private final HashMultiset<Location> lookup = HashMultiset.create();
|
||||
private final int maxSize;
|
||||
|
||||
public BlockLocationHistory(int maxSize) {
|
||||
this.maxSize = maxSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a block location to the history. If the history memory would exceed the max size, it will remove the least recently added block location
|
||||
*
|
||||
* @param newItem
|
||||
*/
|
||||
public void add(Location newItem) {
|
||||
limitedSizeOrderedList.addFirst(newItem);
|
||||
lookup.add(newItem);
|
||||
if (limitedSizeOrderedList.size() > maxSize)
|
||||
lookup.remove(limitedSizeOrderedList.removeLast());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the block location is in the recorded history
|
||||
*
|
||||
* @param targetLoc the block location to search for
|
||||
* @return true if the block location is in the recorded history
|
||||
*/
|
||||
public boolean contains(Location targetLoc) {
|
||||
return lookup.contains(targetLoc);
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
package com.gmail.nossr50.datatypes;
|
||||
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
public class LimitedSizeList {
|
||||
public Location[] limitedSizeOrderedList;
|
||||
private final int size;
|
||||
|
||||
|
||||
public LimitedSizeList(int size)
|
||||
{
|
||||
this.size = size;
|
||||
limitedSizeOrderedList = new Location[size];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds objects to our limited size ordered list
|
||||
* New objects are added to the front
|
||||
* @param newItem
|
||||
*/
|
||||
public void add(Location newItem)
|
||||
{
|
||||
Location[] newList = new Location[size];
|
||||
|
||||
for(int i = 0; i < size-1; i++)
|
||||
{
|
||||
if(i != 0)
|
||||
newList[i] = limitedSizeOrderedList[i-1];
|
||||
else
|
||||
newList[i] = newItem;
|
||||
}
|
||||
|
||||
limitedSizeOrderedList = newList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the object is anywhere in our list
|
||||
* @param targetLoc the object to check for
|
||||
* @return true if the object is in our list
|
||||
*/
|
||||
public boolean contains(Location targetLoc)
|
||||
{
|
||||
for(Location iter : limitedSizeOrderedList)
|
||||
{
|
||||
if(iter == null)
|
||||
continue;
|
||||
|
||||
if(iter.getX() == targetLoc.getX()
|
||||
&& iter.getY() == targetLoc.getY()
|
||||
&& iter.getZ() == targetLoc.getZ())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -839,7 +839,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));
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -63,10 +63,10 @@ public class MctopCommandDisplayTask extends BukkitRunnable {
|
||||
}
|
||||
else {
|
||||
if(sender instanceof Player) {
|
||||
sender.sendMessage(LocaleLoader.getString("Commands.Skill.Leaderboard", rootSkill.getSkillName()));
|
||||
sender.sendMessage(LocaleLoader.getString("Commands.Skill.Leaderboard", skill.getLocalizedName()));
|
||||
}
|
||||
else {
|
||||
sender.sendMessage(ChatColor.stripColor(LocaleLoader.getString("Commands.Skill.Leaderboard", rootSkill.getSkillName())));
|
||||
sender.sendMessage(ChatColor.stripColor(LocaleLoader.getString("Commands.Skill.Leaderboard", skill.getLocalizedName())));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
package com.gmail.nossr50.skills.acrobatics;
|
||||
|
||||
import com.gmail.nossr50.config.experience.ExperienceConfig;
|
||||
import com.gmail.nossr50.datatypes.LimitedSizeList;
|
||||
import com.gmail.nossr50.datatypes.BlockLocationHistory;
|
||||
import com.gmail.nossr50.datatypes.experience.XPGainReason;
|
||||
import com.gmail.nossr50.datatypes.interactions.NotificationType;
|
||||
import com.neetgames.mcmmo.player.OnlineMMOPlayer;
|
||||
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
||||
@ -27,13 +28,13 @@ public class AcrobaticsManager extends SkillManager {
|
||||
|
||||
public AcrobaticsManager(OnlineMMOPlayer mmoPlayer) {
|
||||
super(mmoPlayer, PrimarySkillType.ACROBATICS);
|
||||
fallLocationMap = new LimitedSizeList(50);
|
||||
fallLocationMap = new BlockLocationHistory(50);
|
||||
}
|
||||
|
||||
private long rollXPCooldown = 0;
|
||||
private final long rollXPInterval = (1000 * 3); //1 Minute
|
||||
private long rollXPIntervalLengthen = (1000 * 10); //10 Seconds
|
||||
private final LimitedSizeList fallLocationMap;
|
||||
private final BlockLocationHistory fallLocationMap;
|
||||
|
||||
public boolean hasFallenInLocationBefore(Location location)
|
||||
{
|
||||
|
@ -17,6 +17,7 @@ import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.EntityDamageEvent.DamageModifier;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@ -32,28 +33,28 @@ public class AxesManager extends SkillManager {
|
||||
return Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.AXES_AXE_MASTERY);
|
||||
}
|
||||
|
||||
public boolean canCriticalHit(LivingEntity target) {
|
||||
public boolean canCriticalHit(@NotNull LivingEntity target) {
|
||||
if(!RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.AXES_CRITICAL_STRIKES))
|
||||
return false;
|
||||
|
||||
return target.isValid() && Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.AXES_CRITICAL_STRIKES);
|
||||
}
|
||||
|
||||
public boolean canImpact(LivingEntity target) {
|
||||
public boolean canImpact(@NotNull LivingEntity target) {
|
||||
if(!RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.AXES_ARMOR_IMPACT))
|
||||
return false;
|
||||
|
||||
return target.isValid() && Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.AXES_ARMOR_IMPACT) && Axes.hasArmor(target);
|
||||
}
|
||||
|
||||
public boolean canGreaterImpact(LivingEntity target) {
|
||||
public boolean canGreaterImpact(@NotNull LivingEntity target) {
|
||||
if(!RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.AXES_GREATER_IMPACT))
|
||||
return false;
|
||||
|
||||
return target.isValid() && Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.AXES_GREATER_IMPACT) && !Axes.hasArmor(target);
|
||||
}
|
||||
|
||||
public boolean canUseSkullSplitter(LivingEntity target) {
|
||||
public boolean canUseSkullSplitter(@NotNull LivingEntity target) {
|
||||
if(!RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.AXES_SKULL_SPLITTER))
|
||||
return false;
|
||||
|
||||
@ -68,7 +69,7 @@ public class AxesManager extends SkillManager {
|
||||
* Handle the effects of the Axe Mastery ability
|
||||
*/
|
||||
public double axeMastery() {
|
||||
if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.ALWAYS_FIRES, SubSkillType.AXES_AXE_MASTERY, getPlayer(), mmoPlayer.getAttackStrength())) {
|
||||
if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.ALWAYS_FIRES, SubSkillType.AXES_AXE_MASTERY, getPlayer())) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -82,7 +83,7 @@ public class AxesManager extends SkillManager {
|
||||
* @param damage The amount of damage initially dealt by the event
|
||||
*/
|
||||
public double criticalHit(LivingEntity target, double damage) {
|
||||
if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.AXES_CRITICAL_STRIKES, getPlayer(), mmoPlayer.getAttackStrength())) {
|
||||
if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.AXES_CRITICAL_STRIKES, getPlayer())) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -113,12 +114,12 @@ public class AxesManager extends SkillManager {
|
||||
*
|
||||
* @param target The {@link LivingEntity} being affected by Impact
|
||||
*/
|
||||
public void impactCheck(LivingEntity target) {
|
||||
public void impactCheck(@NotNull LivingEntity target) {
|
||||
double durabilityDamage = getImpactDurabilityDamage();
|
||||
|
||||
for (ItemStack armor : target.getEquipment().getArmorContents()) {
|
||||
if (armor != null && ItemUtils.isArmor(armor)) {
|
||||
if (RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_STATIC_CHANCE, SubSkillType.AXES_ARMOR_IMPACT, getPlayer(), mmoPlayer.getAttackStrength())) {
|
||||
if (RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_STATIC_CHANCE, SubSkillType.AXES_ARMOR_IMPACT, getPlayer())) {
|
||||
SkillUtils.handleDurabilityChange(armor, durabilityDamage, 1);
|
||||
}
|
||||
}
|
||||
@ -134,9 +135,9 @@ public class AxesManager extends SkillManager {
|
||||
*
|
||||
* @param target The {@link LivingEntity} being affected by the ability
|
||||
*/
|
||||
public double greaterImpact(LivingEntity target) {
|
||||
public double greaterImpact(@NotNull LivingEntity target) {
|
||||
//static chance (3rd param)
|
||||
if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_STATIC_CHANCE, SubSkillType.AXES_GREATER_IMPACT, getPlayer(), mmoPlayer.getAttackStrength())) {
|
||||
if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_STATIC_CHANCE, SubSkillType.AXES_GREATER_IMPACT, getPlayer())) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -166,7 +167,7 @@ public class AxesManager extends SkillManager {
|
||||
* @param target The {@link LivingEntity} being affected by the ability
|
||||
* @param damage The amount of damage initially dealt by the event
|
||||
*/
|
||||
public void skullSplitterCheck(LivingEntity target, double damage, Map<DamageModifier, Double> modifiers) {
|
||||
public void skullSplitterCheck(@NotNull LivingEntity target, double damage, Map<DamageModifier, Double> modifiers) {
|
||||
CombatUtils.applyAbilityAoE(getPlayer(), target, damage / Axes.skullSplitterModifier, modifiers, skill);
|
||||
}
|
||||
}
|
||||
|
@ -738,7 +738,6 @@ public class HerbalismManager extends SkillManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!playerInventory.containsAtLeast(seedStack, 1)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ public class SwordsManager extends SkillManager {
|
||||
*/
|
||||
public void ruptureCheck(@NotNull LivingEntity target) throws IllegalStateException {
|
||||
if(BleedTimerTask.isBleedOperationAllowed()) {
|
||||
if (RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.SWORDS_RUPTURE, getPlayer(), this.mmoPlayer.getAttackStrength())) {
|
||||
if (RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.SWORDS_RUPTURE, getPlayer())) {
|
||||
|
||||
if (target instanceof Player) {
|
||||
Player defender = (Player) target;
|
||||
@ -98,7 +98,7 @@ public class SwordsManager extends SkillManager {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getToolTier(ItemStack itemStack)
|
||||
public int getToolTier(@NotNull ItemStack itemStack)
|
||||
{
|
||||
if(ItemUtils.isNetheriteTool(itemStack))
|
||||
return 5;
|
||||
@ -128,7 +128,7 @@ public class SwordsManager extends SkillManager {
|
||||
* @param attacker The {@link LivingEntity} being affected by the ability
|
||||
* @param damage The amount of damage initially dealt by the event
|
||||
*/
|
||||
public void counterAttackChecks(LivingEntity attacker, double damage) {
|
||||
public void counterAttackChecks(@NotNull LivingEntity attacker, double damage) {
|
||||
if (RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.SWORDS_COUNTER_ATTACK, getPlayer())) {
|
||||
CombatUtils.dealDamage(attacker, damage / Swords.counterAttackModifier, getPlayer());
|
||||
|
||||
@ -146,7 +146,7 @@ public class SwordsManager extends SkillManager {
|
||||
* @param target The {@link LivingEntity} being affected by the ability
|
||||
* @param damage The amount of damage initially dealt by the event
|
||||
*/
|
||||
public void serratedStrikes(LivingEntity target, double damage, Map<DamageModifier, Double> modifiers) {
|
||||
public void serratedStrikes(@NotNull LivingEntity target, double damage, Map<DamageModifier, Double> modifiers) {
|
||||
CombatUtils.applyAbilityAoE(getPlayer(), target, damage / Swords.serratedStrikesModifier, modifiers, skill);
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class UnarmedManager extends SkillManager {
|
||||
|
||||
@ -69,7 +70,7 @@ public class UnarmedManager extends SkillManager {
|
||||
return Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.UNARMED_BLOCK_CRACKER);
|
||||
}
|
||||
|
||||
public boolean blockCrackerCheck(BlockState blockState) {
|
||||
public boolean blockCrackerCheck(@NotNull BlockState blockState) {
|
||||
if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.ALWAYS_FIRES, SubSkillType.UNARMED_BLOCK_CRACKER, getPlayer())) {
|
||||
return false;
|
||||
}
|
||||
@ -100,8 +101,8 @@ public class UnarmedManager extends SkillManager {
|
||||
*
|
||||
* @param defender The defending player
|
||||
*/
|
||||
public void disarmCheck(Player defender) {
|
||||
if (RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.UNARMED_DISARM, getPlayer(), mmoPlayer.getAttackStrength()) && !hasIronGrip(defender)) {
|
||||
public void disarmCheck(@NotNull Player defender) {
|
||||
if (RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.UNARMED_DISARM, getPlayer()) && !hasIronGrip(defender)) {
|
||||
if (EventUtils.callDisarmEvent(defender).isCancelled()) {
|
||||
return;
|
||||
}
|
||||
@ -178,7 +179,7 @@ public class UnarmedManager extends SkillManager {
|
||||
* @param defender The defending player
|
||||
* @return true if the defender was not disarmed, false otherwise
|
||||
*/
|
||||
private boolean hasIronGrip(Player defender) {
|
||||
private boolean hasIronGrip(@NotNull Player defender) {
|
||||
if (!Misc.isNPCEntityExcludingVillagers(defender)
|
||||
&& Permissions.isSubSkillEnabled(defender, SubSkillType.UNARMED_IRON_GRIP)
|
||||
&& RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.UNARMED_IRON_GRIP, defender)) {
|
||||
|
@ -40,7 +40,7 @@ public class HashChunkManager implements ChunkManager {
|
||||
}
|
||||
|
||||
private synchronized @Nullable ChunkStore readChunkStore(@NotNull World world, int cx, int cz) throws IOException {
|
||||
McMMOSimpleRegionFile rf = getSimpleRegionFile(world, cx, cz, false);
|
||||
McMMOSimpleRegionFile rf = getReadableSimpleRegionFile(world, cx, cz);
|
||||
if (rf == null)
|
||||
return null; // If there is no region file, there can't be a chunk
|
||||
try (DataInputStream in = rf.getInputStream(cx, cz)) { // Get input stream for chunk
|
||||
@ -54,7 +54,7 @@ public class HashChunkManager implements ChunkManager {
|
||||
if (!data.isDirty())
|
||||
return; // Don't save unchanged data
|
||||
try {
|
||||
McMMOSimpleRegionFile rf = getSimpleRegionFile(world, data.getChunkX(), data.getChunkZ(), true);
|
||||
McMMOSimpleRegionFile rf = getWriteableSimpleRegionFile(world, data.getChunkX(), data.getChunkZ());
|
||||
try (DataOutputStream out = rf.getOutputStream(data.getChunkX(), data.getChunkZ())) {
|
||||
BitSetChunkStore.Serialization.writeChunkStore(out, data);
|
||||
}
|
||||
@ -65,21 +65,33 @@ public class HashChunkManager implements ChunkManager {
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized @Nullable McMMOSimpleRegionFile getSimpleRegionFile(@NotNull World world, int cx, int cz, boolean createIfAbsent) {
|
||||
private synchronized @NotNull McMMOSimpleRegionFile getWriteableSimpleRegionFile(@NotNull World world, int cx, int cz) {
|
||||
CoordinateKey regionKey = toRegionKey(world.getUID(), cx, cz);
|
||||
|
||||
return regionMap.computeIfAbsent(regionKey, k -> {
|
||||
File worldRegionsDirectory = new File(world.getWorldFolder(), "mcmmo_regions");
|
||||
if (!createIfAbsent && !worldRegionsDirectory.isDirectory())
|
||||
return null; // Don't create the directory on read-only operations
|
||||
worldRegionsDirectory.mkdirs(); // Ensure directory exists
|
||||
File regionFile = new File(worldRegionsDirectory, "mcmmo_" + regionKey.x + "_" + regionKey.z + "_.mcm");
|
||||
if (!createIfAbsent && !regionFile.exists())
|
||||
File regionFile = getRegionFile(world, regionKey);
|
||||
regionFile.getParentFile().mkdirs();
|
||||
return new McMMOSimpleRegionFile(regionFile, regionKey.x, regionKey.z);
|
||||
});
|
||||
}
|
||||
|
||||
private synchronized @Nullable McMMOSimpleRegionFile getReadableSimpleRegionFile(@NotNull World world, int cx, int cz) {
|
||||
CoordinateKey regionKey = toRegionKey(world.getUID(), cx, cz);
|
||||
|
||||
return regionMap.computeIfAbsent(regionKey, k -> {
|
||||
File regionFile = getRegionFile(world, regionKey);
|
||||
if (!regionFile.exists())
|
||||
return null; // Don't create the file on read-only operations
|
||||
return new McMMOSimpleRegionFile(regionFile, regionKey.x, regionKey.z);
|
||||
});
|
||||
}
|
||||
|
||||
private @NotNull File getRegionFile(@NotNull World world, @NotNull CoordinateKey regionKey) {
|
||||
if (world.getUID() != regionKey.worldID)
|
||||
throw new IllegalArgumentException();
|
||||
return new File(new File(world.getWorldFolder(), "mcmmo_regions"), "mcmmo_" + regionKey.x + "_" + regionKey.z + "_.mcm");
|
||||
}
|
||||
|
||||
private @Nullable ChunkStore loadChunk(int cx, int cz, @NotNull World world) {
|
||||
try {
|
||||
return readChunkStore(world, cx, cz);
|
||||
@ -228,15 +240,15 @@ public class HashChunkManager implements ChunkManager {
|
||||
cStore.set(ix, y, iz, value);
|
||||
}
|
||||
|
||||
private CoordinateKey blockCoordinateToChunkKey(@NotNull UUID worldUid, int x, int y, int z) {
|
||||
private @NotNull CoordinateKey blockCoordinateToChunkKey(@NotNull UUID worldUid, int x, int y, int z) {
|
||||
return toChunkKey(worldUid, x >> 4, z >> 4);
|
||||
}
|
||||
|
||||
private CoordinateKey toChunkKey(@NotNull UUID worldUid, int cx, int cz){
|
||||
private @NotNull CoordinateKey toChunkKey(@NotNull UUID worldUid, int cx, int cz){
|
||||
return new CoordinateKey(worldUid, cx, cz);
|
||||
}
|
||||
|
||||
private CoordinateKey toRegionKey(@NotNull UUID worldUid, int cx, int cz) {
|
||||
private @NotNull CoordinateKey toRegionKey(@NotNull UUID worldUid, int cx, int cz) {
|
||||
// Compute region index (32x32 chunk regions)
|
||||
int rx = cx >> 5;
|
||||
int rz = cz >> 5;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -3,6 +3,7 @@ package com.gmail.nossr50.util.random;
|
||||
public interface RandomChanceExecution {
|
||||
/**
|
||||
* Gets the XPos used in the formula for success
|
||||
*
|
||||
* @return value of x for our success probability graph
|
||||
*/
|
||||
double getXPos();
|
||||
@ -10,6 +11,7 @@ public interface RandomChanceExecution {
|
||||
/**
|
||||
* The maximum odds for this RandomChanceExecution
|
||||
* For example, if this value is 10, then 10% odds would be the maximum and would be achieved only when xPos equaled the LinearCurvePeak
|
||||
*
|
||||
* @return maximum probability odds from 0.00 (no chance of ever happened) to 100.0 (probability can be guaranteed)
|
||||
*/
|
||||
double getProbabilityCap();
|
||||
|
@ -1,132 +1,114 @@
|
||||
package com.gmail.nossr50.util.random;
|
||||
|
||||
import com.gmail.nossr50.config.AdvancedConfig;
|
||||
import com.neetgames.mcmmo.player.OnlineMMOPlayer;
|
||||
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
||||
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
|
||||
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.jetbrains.annotations.Nullable;
|
||||
|
||||
public class RandomChanceSkill implements RandomChanceExecution {
|
||||
|
||||
protected final PrimarySkillType primarySkillType;
|
||||
protected final 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(Player player, SubSkillType subSkillType, double resultModifier)
|
||||
{
|
||||
this.primarySkillType = subSkillType.getParentSkill();
|
||||
this.subSkillType = subSkillType;
|
||||
public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType, double resultModifier) {
|
||||
this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR;
|
||||
|
||||
final OnlineMMOPlayer mmoPlayer = mcMMO.getUserManager().getPlayer(player);
|
||||
if (player != null && mmoPlayer != null) {
|
||||
this.skillLevel = mmoPlayer.getSkillLevel(primarySkillType);
|
||||
final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
|
||||
if (player != null && mcMMOPlayer != null) {
|
||||
this.skillLevel = mcMMOPlayer.getSkillLevel(subSkillType.getParentSkill());
|
||||
} else {
|
||||
this.skillLevel = 0;
|
||||
}
|
||||
|
||||
if(player != null)
|
||||
isLucky = Permissions.lucky(player, primarySkillType);
|
||||
if (player != null)
|
||||
isLucky = Permissions.lucky(player, subSkillType.getParentSkill());
|
||||
else
|
||||
isLucky = false;
|
||||
|
||||
this.resultModifier = resultModifier;
|
||||
this.maximumBonusLevelCap = RandomChanceUtil.getMaxBonusLevelCap(subSkillType);
|
||||
}
|
||||
|
||||
public RandomChanceSkill(Player player, SubSkillType subSkillType)
|
||||
{
|
||||
this.primarySkillType = subSkillType.getParentSkill();
|
||||
this.subSkillType = subSkillType;
|
||||
public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType) {
|
||||
this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR;
|
||||
|
||||
final OnlineMMOPlayer mmoPlayer = mcMMO.getUserManager().getPlayer(player);
|
||||
if (player != null && mmoPlayer != null) {
|
||||
this.skillLevel = mmoPlayer.getSkillLevel(primarySkillType);
|
||||
final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
|
||||
if (player != null && mcMMOPlayer != null) {
|
||||
this.skillLevel = mcMMOPlayer.getSkillLevel(subSkillType.getParentSkill());
|
||||
} else {
|
||||
this.skillLevel = 0;
|
||||
}
|
||||
|
||||
if(player != null)
|
||||
isLucky = Permissions.lucky(player, primarySkillType);
|
||||
if (player != null)
|
||||
isLucky = Permissions.lucky(player, subSkillType.getParentSkill());
|
||||
else
|
||||
isLucky = false;
|
||||
|
||||
this.resultModifier = 1.0D;
|
||||
this.maximumBonusLevelCap = RandomChanceUtil.getMaxBonusLevelCap(subSkillType);
|
||||
}
|
||||
|
||||
public RandomChanceSkill(Player player, SubSkillType subSkillType, boolean hasCap)
|
||||
{
|
||||
if(hasCap)
|
||||
this.probabilityCap = AdvancedConfig.getInstance().getMaximumProbability(subSkillType);
|
||||
public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean hasCap) {
|
||||
if (hasCap)
|
||||
this.probabilityCap = RandomChanceUtil.getMaximumProbability(subSkillType);
|
||||
else
|
||||
this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR;
|
||||
|
||||
this.primarySkillType = subSkillType.getParentSkill();
|
||||
this.subSkillType = subSkillType;
|
||||
|
||||
final OnlineMMOPlayer mmoPlayer = mcMMO.getUserManager().getPlayer(player);
|
||||
if (player != null && mmoPlayer != null) {
|
||||
this.skillLevel = mmoPlayer.getSkillLevel(primarySkillType);
|
||||
final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
|
||||
if (player != null && mcMMOPlayer != null) {
|
||||
this.skillLevel = mcMMOPlayer.getSkillLevel(subSkillType.getParentSkill());
|
||||
} else {
|
||||
this.skillLevel = 0;
|
||||
}
|
||||
|
||||
if(player != null)
|
||||
isLucky = Permissions.lucky(player, primarySkillType);
|
||||
if (player != null)
|
||||
isLucky = Permissions.lucky(player, subSkillType.getParentSkill());
|
||||
else
|
||||
isLucky = false;
|
||||
|
||||
this.resultModifier = 1.0D;
|
||||
this.maximumBonusLevelCap = RandomChanceUtil.getMaxBonusLevelCap(subSkillType);
|
||||
}
|
||||
|
||||
public RandomChanceSkill(Player player, SubSkillType subSkillType, boolean hasCap, double resultModifier)
|
||||
{
|
||||
if(hasCap)
|
||||
this.probabilityCap = AdvancedConfig.getInstance().getMaximumProbability(subSkillType);
|
||||
public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean hasCap, double resultModifier) {
|
||||
if (hasCap)
|
||||
this.probabilityCap = RandomChanceUtil.getMaximumProbability(subSkillType);
|
||||
else
|
||||
this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR;
|
||||
|
||||
this.primarySkillType = subSkillType.getParentSkill();
|
||||
this.subSkillType = subSkillType;
|
||||
|
||||
final OnlineMMOPlayer mmoPlayer = mcMMO.getUserManager().getPlayer(player);
|
||||
if (player != null && mmoPlayer != null) {
|
||||
this.skillLevel = mmoPlayer.getSkillLevel(primarySkillType);
|
||||
final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
|
||||
if (player != null && mcMMOPlayer != null) {
|
||||
this.skillLevel = mcMMOPlayer.getSkillLevel(subSkillType.getParentSkill());
|
||||
} else {
|
||||
this.skillLevel = 0;
|
||||
}
|
||||
|
||||
if(player != null)
|
||||
isLucky = Permissions.lucky(player, primarySkillType);
|
||||
if (player != null)
|
||||
isLucky = Permissions.lucky(player, subSkillType.getParentSkill());
|
||||
else
|
||||
isLucky = false;
|
||||
|
||||
this.resultModifier = resultModifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* The subskill corresponding to this RandomChanceSkill
|
||||
* @return this subskill
|
||||
*/
|
||||
public SubSkillType getSubSkill() {
|
||||
return subSkillType;
|
||||
this.maximumBonusLevelCap = RandomChanceUtil.getMaxBonusLevelCap(subSkillType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the skill level of the player who owns this RandomChanceSkill
|
||||
*
|
||||
* @return the current skill level relating to this RandomChanceSkill
|
||||
*/
|
||||
public int getSkillLevel()
|
||||
{
|
||||
public int getSkillLevel() {
|
||||
return skillLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the skill level used for this skill's RNG calculations
|
||||
*
|
||||
* @param newSkillLevel new skill level
|
||||
*/
|
||||
public void setSkillLevel(int newSkillLevel) {
|
||||
@ -141,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;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -172,8 +154,4 @@ public class RandomChanceSkill implements RandomChanceExecution {
|
||||
public double getResultModifier() {
|
||||
return resultModifier;
|
||||
}
|
||||
|
||||
public void setResultModifier(double resultModifier) {
|
||||
this.resultModifier = resultModifier;
|
||||
}
|
||||
}
|
||||
|
@ -2,19 +2,19 @@ package com.gmail.nossr50.util.random;
|
||||
|
||||
import com.gmail.nossr50.datatypes.skills.SubSkillType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class RandomChanceSkillStatic extends RandomChanceSkill {
|
||||
private final double xPos;
|
||||
|
||||
public RandomChanceSkillStatic(double xPos, Player player, SubSkillType subSkillType)
|
||||
{
|
||||
public RandomChanceSkillStatic(double xPos, @Nullable Player player, @NotNull SubSkillType subSkillType) {
|
||||
super(player, subSkillType);
|
||||
|
||||
this.xPos = xPos;
|
||||
}
|
||||
|
||||
public RandomChanceSkillStatic(double xPos, Player player, SubSkillType subSkillType, double resultModifier)
|
||||
{
|
||||
public RandomChanceSkillStatic(double xPos, @Nullable Player player, @NotNull SubSkillType subSkillType, double resultModifier) {
|
||||
super(player, subSkillType, resultModifier);
|
||||
|
||||
this.xPos = xPos;
|
||||
|
@ -5,8 +5,7 @@ public class RandomChanceStatic implements RandomChanceExecution {
|
||||
private final double probabilityCap;
|
||||
private final boolean isLucky;
|
||||
|
||||
public RandomChanceStatic(double xPos, boolean isLucky)
|
||||
{
|
||||
public RandomChanceStatic(double xPos, boolean isLucky) {
|
||||
this.xPos = xPos;
|
||||
this.probabilityCap = xPos;
|
||||
this.isLucky = isLucky;
|
||||
|
@ -1,10 +1,8 @@
|
||||
package com.gmail.nossr50.util.random;
|
||||
|
||||
import com.gmail.nossr50.config.AdvancedConfig;
|
||||
import com.neetgames.mcmmo.player.OnlineMMOPlayer;
|
||||
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;
|
||||
@ -12,15 +10,16 @@ import com.gmail.nossr50.util.Permissions;
|
||||
import com.gmail.nossr50.util.skills.SkillActivationType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class RandomChanceUtil
|
||||
{
|
||||
public static final DecimalFormat percent = new DecimalFormat("##0.00%");
|
||||
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
|
||||
@ -28,14 +27,12 @@ public class RandomChanceUtil
|
||||
* non-RNG skills just fire the cancellable event and succeed if they go uncancelled
|
||||
*
|
||||
* @param skillActivationType this value represents what kind of activation procedures this sub-skill uses
|
||||
* @param subSkillType The identifier for this specific sub-skill
|
||||
* @param player The owner of this sub-skill
|
||||
* @param subSkillType The identifier for this specific sub-skill
|
||||
* @param player The owner of this sub-skill
|
||||
* @return returns true if all conditions are met and the event is not cancelled
|
||||
*/
|
||||
public static boolean isActivationSuccessful(SkillActivationType skillActivationType, SubSkillType subSkillType, Player player)
|
||||
{
|
||||
switch(skillActivationType)
|
||||
{
|
||||
public static boolean isActivationSuccessful(@NotNull SkillActivationType skillActivationType, @NotNull SubSkillType subSkillType, @Nullable Player player) {
|
||||
switch (skillActivationType) {
|
||||
case RANDOM_LINEAR_100_SCALE_WITH_CAP:
|
||||
return checkRandomChanceExecutionSuccess(player, subSkillType, true);
|
||||
case RANDOM_STATIC_CHANCE:
|
||||
@ -48,36 +45,8 @@ public class RandomChanceUtil
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is the final step in determining if a Sub-Skill / Secondary Skill in mcMMO successfully activates either from chance or otherwise
|
||||
* Random skills check for success based on numbers and then fire a cancellable event, if that event is not cancelled they succeed
|
||||
* non-RNG skills just fire the cancellable event and succeed if they go uncancelled
|
||||
*
|
||||
* @param skillActivationType this value represents what kind of activation procedures this sub-skill uses
|
||||
* @param subSkillType The identifier for this specific sub-skill
|
||||
* @param player The owner of this sub-skill
|
||||
* @return returns true if all conditions are met and the event is not cancelled
|
||||
*/
|
||||
public static boolean isActivationSuccessful(SkillActivationType skillActivationType, SubSkillType subSkillType, Player player, double resultModifier)
|
||||
{
|
||||
switch(skillActivationType)
|
||||
{
|
||||
case RANDOM_LINEAR_100_SCALE_WITH_CAP:
|
||||
return checkRandomChanceExecutionSuccess(player, subSkillType, true);
|
||||
case RANDOM_STATIC_CHANCE:
|
||||
return checkRandomStaticChanceExecutionSuccess(player, subSkillType, resultModifier);
|
||||
case ALWAYS_FIRES:
|
||||
SubSkillEvent event = EventUtils.callSubSkillEvent(player, subSkillType);
|
||||
return !event.isCancelled();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static double getActivationChance(SkillActivationType skillActivationType, SubSkillType subSkillType, Player player)
|
||||
{
|
||||
switch(skillActivationType)
|
||||
{
|
||||
public static double getActivationChance(@NotNull SkillActivationType skillActivationType, @NotNull SubSkillType subSkillType, @Nullable Player player) {
|
||||
switch (skillActivationType) {
|
||||
case RANDOM_LINEAR_100_SCALE_WITH_CAP:
|
||||
return getRandomChanceExecutionSuccess(player, subSkillType, true);
|
||||
case RANDOM_STATIC_CHANCE:
|
||||
@ -89,10 +58,10 @@ public class RandomChanceUtil
|
||||
|
||||
/**
|
||||
* Checks whether or not the random chance succeeds
|
||||
*
|
||||
* @return true if the random chance succeeds
|
||||
*/
|
||||
public static boolean checkRandomChanceExecutionSuccess(Player player, PrimarySkillType primarySkillType, double chance)
|
||||
{
|
||||
public static boolean checkRandomChanceExecutionSuccess(@NotNull Player player, @NotNull PrimarySkillType primarySkillType, double chance) {
|
||||
//Check the odds
|
||||
chance *= 100;
|
||||
|
||||
@ -115,11 +84,11 @@ public class RandomChanceUtil
|
||||
|
||||
/**
|
||||
* Used for stuff like Excavation, Fishing, etc...
|
||||
*
|
||||
* @param randomChance
|
||||
* @return
|
||||
*/
|
||||
public static boolean checkRandomChanceExecutionSuccess(RandomChanceSkillStatic randomChance, double resultModifier)
|
||||
{
|
||||
public static boolean checkRandomChanceExecutionSuccess(@NotNull RandomChanceSkillStatic randomChance, double resultModifier) {
|
||||
double chanceOfSuccess = calculateChanceOfSuccess(randomChance);
|
||||
|
||||
//Check the odds
|
||||
@ -128,16 +97,15 @@ public class RandomChanceUtil
|
||||
|
||||
/**
|
||||
* Used for stuff like Excavation, Fishing, etc...
|
||||
*
|
||||
* @param randomChance
|
||||
* @return
|
||||
*/
|
||||
public static boolean checkRandomChanceExecutionSuccess(RandomChanceSkillStatic randomChance)
|
||||
{
|
||||
public static boolean checkRandomChanceExecutionSuccess(@NotNull RandomChanceSkillStatic randomChance) {
|
||||
return checkRandomChanceExecutionSuccess(randomChance, 1.0F);
|
||||
}
|
||||
|
||||
public static boolean checkRandomChanceExecutionSuccess(RandomChanceSkill randomChance)
|
||||
{
|
||||
public static boolean checkRandomChanceExecutionSuccess(@NotNull RandomChanceSkill randomChance) {
|
||||
double chanceOfSuccess = calculateChanceOfSuccess(randomChance);
|
||||
|
||||
//Check the odds
|
||||
@ -153,14 +121,15 @@ public class RandomChanceUtil
|
||||
|
||||
/**
|
||||
* Gets the Static Chance for something to activate
|
||||
*
|
||||
* @param randomChance
|
||||
* @return
|
||||
*/
|
||||
public static double getRandomChanceExecutionChance(RandomChanceExecution randomChance) {
|
||||
public static double getRandomChanceExecutionChance(@NotNull RandomChanceExecution randomChance) {
|
||||
return getChanceOfSuccess(randomChance.getXPos(), randomChance.getProbabilityCap(), LINEAR_CURVE_VAR);
|
||||
}
|
||||
|
||||
public static double getRandomChanceExecutionChance(RandomChanceStatic randomChance) {
|
||||
public static double getRandomChanceExecutionChance(@NotNull RandomChanceStatic randomChance) {
|
||||
double chanceOfSuccess = getChanceOfSuccess(randomChance.getXPos(), randomChance.getProbabilityCap(), LINEAR_CURVE_VAR);
|
||||
|
||||
chanceOfSuccess = addLuck(randomChance.isLucky(), chanceOfSuccess);
|
||||
@ -173,7 +142,7 @@ public class RandomChanceUtil
|
||||
return chanceOfSuccess;
|
||||
}*/
|
||||
|
||||
private static double calculateChanceOfSuccess(RandomChanceSkill randomChance) {
|
||||
public static double calculateChanceOfSuccess(@NotNull RandomChanceSkill randomChance) {
|
||||
double skillLevel = randomChance.getSkillLevel();
|
||||
double maximumProbability = randomChance.getProbabilityCap();
|
||||
double maximumBonusLevel = randomChance.getMaximumBonusLevelCap();
|
||||
@ -194,7 +163,7 @@ public class RandomChanceUtil
|
||||
return chanceOfSuccess;
|
||||
}
|
||||
|
||||
private static double calculateChanceOfSuccess(RandomChanceSkillStatic randomChance) {
|
||||
public static double calculateChanceOfSuccess(@NotNull RandomChanceSkillStatic randomChance) {
|
||||
double chanceOfSuccess = getChanceOfSuccess(randomChance.getXPos(), 100, 100);
|
||||
|
||||
//Add Luck
|
||||
@ -209,27 +178,23 @@ public class RandomChanceUtil
|
||||
*
|
||||
* @return the chance of success from 0-100 (100 = guaranteed)
|
||||
*/
|
||||
private static int getChanceOfSuccess(double skillLevel, double maxProbability, double maxLevel)
|
||||
{
|
||||
private static int getChanceOfSuccess(double skillLevel, double maxProbability, double maxLevel) {
|
||||
//return (int) (x / (y / LINEAR_CURVE_VAR));
|
||||
return (int) (maxProbability * (skillLevel/maxLevel));
|
||||
return (int) (maxProbability * (skillLevel / maxLevel));
|
||||
// max probability * (weight/maxlevel) = chance of success
|
||||
}
|
||||
|
||||
private static int getChanceOfSuccess(double x, double y)
|
||||
{
|
||||
private static int getChanceOfSuccess(double x, double y) {
|
||||
return (int) (x / (y / LINEAR_CURVE_VAR));
|
||||
// max probability * (weight/maxlevel) = chance of success
|
||||
}
|
||||
|
||||
public static double getRandomChanceExecutionSuccess(Player player, SubSkillType subSkillType, boolean hasCap)
|
||||
{
|
||||
public static double getRandomChanceExecutionSuccess(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean hasCap) {
|
||||
RandomChanceSkill rcs = new RandomChanceSkill(player, subSkillType, hasCap);
|
||||
return calculateChanceOfSuccess(rcs);
|
||||
}
|
||||
|
||||
public static double getRandomStaticChanceExecutionSuccess(Player player, SubSkillType subSkillType)
|
||||
{
|
||||
public static double getRandomStaticChanceExecutionSuccess(@Nullable Player player, @NotNull SubSkillType subSkillType) {
|
||||
try {
|
||||
return getRandomChanceExecutionChance(new RandomChanceSkillStatic(getStaticRandomChance(subSkillType), player, subSkillType));
|
||||
} catch (InvalidStaticChance invalidStaticChance) {
|
||||
@ -240,29 +205,24 @@ public class RandomChanceUtil
|
||||
return 0.1337; //Puts on shades
|
||||
}
|
||||
|
||||
public static boolean checkRandomChanceExecutionSuccess(Player player, SubSkillType subSkillType, boolean hasCap)
|
||||
{
|
||||
public static boolean checkRandomChanceExecutionSuccess(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean hasCap) {
|
||||
return checkRandomChanceExecutionSuccess(new RandomChanceSkill(player, subSkillType, hasCap));
|
||||
}
|
||||
|
||||
public static boolean checkRandomChanceExecutionSuccess(Player player, SubSkillType subSkillType)
|
||||
{
|
||||
public static boolean checkRandomChanceExecutionSuccess(@Nullable Player player, @NotNull SubSkillType subSkillType) {
|
||||
return checkRandomChanceExecutionSuccess(new RandomChanceSkill(player, subSkillType));
|
||||
}
|
||||
|
||||
public static boolean checkRandomChanceExecutionSuccess(Player player, SubSkillType subSkillType, boolean hasCap, double resultModifier)
|
||||
{
|
||||
public static boolean checkRandomChanceExecutionSuccess(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean hasCap, double resultModifier) {
|
||||
return checkRandomChanceExecutionSuccess(new RandomChanceSkill(player, subSkillType, hasCap, resultModifier));
|
||||
}
|
||||
|
||||
public static boolean checkRandomChanceExecutionSuccess(Player player, SubSkillType subSkillType, double resultModifier)
|
||||
{
|
||||
public static boolean checkRandomChanceExecutionSuccess(@Nullable Player player, @NotNull SubSkillType subSkillType, double resultModifier) {
|
||||
return checkRandomChanceExecutionSuccess(new RandomChanceSkill(player, subSkillType, resultModifier));
|
||||
}
|
||||
|
||||
|
||||
public static boolean checkRandomStaticChanceExecutionSuccess(Player player, SubSkillType subSkillType, double resultModifier)
|
||||
{
|
||||
public static boolean checkRandomStaticChanceExecutionSuccess(@Nullable Player player, @NotNull SubSkillType subSkillType) {
|
||||
try {
|
||||
return checkRandomChanceExecutionSuccess(new RandomChanceSkillStatic(getStaticRandomChance(subSkillType), player, subSkillType));
|
||||
} catch (InvalidStaticChance invalidStaticChance) {
|
||||
@ -273,21 +233,15 @@ public class RandomChanceUtil
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean checkRandomStaticChanceExecutionSuccess(Player player, SubSkillType subSkillType)
|
||||
{
|
||||
return checkRandomStaticChanceExecutionSuccess(player, subSkillType, 1.0F);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grabs static activation rolls for Secondary Abilities
|
||||
*
|
||||
* @param subSkillType The secondary ability to grab properties of
|
||||
* @throws InvalidStaticChance if the skill has no defined static chance this exception will be thrown and you should know you're a naughty boy
|
||||
* @return The static activation roll involved in the RNG calculation
|
||||
* @throws InvalidStaticChance if the skill has no defined static chance this exception will be thrown and you should know you're a naughty boy
|
||||
*/
|
||||
public static double getStaticRandomChance(SubSkillType subSkillType) throws InvalidStaticChance
|
||||
{
|
||||
switch(subSkillType)
|
||||
{
|
||||
public static double getStaticRandomChance(@NotNull SubSkillType subSkillType) throws InvalidStaticChance {
|
||||
switch (subSkillType) {
|
||||
case AXES_ARMOR_IMPACT:
|
||||
return AdvancedConfig.getInstance().getImpactChance();
|
||||
case AXES_GREATER_IMPACT:
|
||||
@ -299,24 +253,12 @@ public class RandomChanceUtil
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean sendSkillEvent(Player player, SubSkillType subSkillType, double activationChance)
|
||||
{
|
||||
public static boolean sendSkillEvent(Player player, SubSkillType subSkillType, double activationChance) {
|
||||
SubSkillRandomCheckEvent event = new SubSkillRandomCheckEvent(player, subSkillType, activationChance);
|
||||
return !event.isCancelled();
|
||||
}
|
||||
|
||||
/*public static boolean treasureDropSuccessful(Player player, double dropChance, int activationChance) {
|
||||
SubSkillRandomCheckEvent event = new SubSkillRandomCheckEvent(player, SubSkillType.EXCAVATION_ARCHAEOLOGY, dropChance / activationChance);
|
||||
mcMMO.p.getServer().getPluginManager().callEvent(event);
|
||||
return (event.getChance() * activationChance) > (Misc.getRandom().nextDouble() * activationChance) && !event.isCancelled();
|
||||
}*/
|
||||
|
||||
public static boolean isActivationSuccessful(SkillActivationType skillActivationType, AbstractSubSkill abstractSubSkill, Player player)
|
||||
{
|
||||
return isActivationSuccessful(skillActivationType, abstractSubSkill.getSubSkillType(), player);
|
||||
}
|
||||
|
||||
public static String[] calculateAbilityDisplayValues(@NotNull SkillActivationType skillActivationType, @NotNull Player player, @NotNull SubSkillType subSkillType) {
|
||||
public static String @NotNull [] calculateAbilityDisplayValues(@NotNull SkillActivationType skillActivationType, @NotNull Player player, @NotNull SubSkillType subSkillType) {
|
||||
double successChance = getActivationChance(skillActivationType, subSkillType, player);
|
||||
String[] displayValues = new String[2];
|
||||
|
||||
@ -328,7 +270,7 @@ public class RandomChanceUtil
|
||||
return displayValues;
|
||||
}
|
||||
|
||||
public static String[] calculateAbilityDisplayValuesStatic(@NotNull OnlineMMOPlayer mmoPlayer, PrimarySkillType primarySkillType, double chance) {
|
||||
public static String @NotNull [] calculateAbilityDisplayValuesStatic(@NotNull Player player, @NotNull PrimarySkillType primarySkillType, double chance) {
|
||||
RandomChanceStatic rcs = new RandomChanceStatic(chance, false);
|
||||
double successChance = getRandomChanceExecutionChance(rcs);
|
||||
|
||||
@ -337,7 +279,7 @@ public class RandomChanceUtil
|
||||
|
||||
String[] displayValues = new String[2];
|
||||
|
||||
boolean isLucky = Permissions.lucky(Misc.adaptPlayer(mmoPlayer), primarySkillType);
|
||||
boolean isLucky = Permissions.lucky(player, primarySkillType);
|
||||
|
||||
displayValues[0] = percent.format(Math.min(successChance, 100.0D) / 100.0D);
|
||||
displayValues[1] = isLucky ? percent.format(Math.min(successChance_lucky, 100.0D) / 100.0D) : null;
|
||||
@ -345,7 +287,7 @@ public class RandomChanceUtil
|
||||
return displayValues;
|
||||
}
|
||||
|
||||
public static String[] calculateAbilityDisplayValuesCustom(SkillActivationType skillActivationType, Player player, SubSkillType subSkillType, double multiplier) {
|
||||
public static String @NotNull [] calculateAbilityDisplayValuesCustom(@NotNull SkillActivationType skillActivationType, @NotNull Player player, @NotNull SubSkillType subSkillType, double multiplier) {
|
||||
double successChance = getActivationChance(skillActivationType, subSkillType, player);
|
||||
successChance *= multiplier; //Currently only used for graceful roll
|
||||
String[] displayValues = new String[2];
|
||||
@ -360,19 +302,25 @@ public class RandomChanceUtil
|
||||
return displayValues;
|
||||
}
|
||||
|
||||
public static double addLuck(Player player, PrimarySkillType primarySkillType, double chance)
|
||||
{
|
||||
if(Permissions.lucky(player, primarySkillType))
|
||||
return chance * 1.333D;
|
||||
public static double addLuck(@NotNull Player player, @NotNull PrimarySkillType primarySkillType, double chance) {
|
||||
if (Permissions.lucky(player, primarySkillType))
|
||||
return chance * LUCKY_MODIFIER;
|
||||
else
|
||||
return chance;
|
||||
}
|
||||
|
||||
public static double addLuck(boolean isLucky, double chance)
|
||||
{
|
||||
if(isLucky)
|
||||
return chance * 1.333D;
|
||||
public static double addLuck(boolean isLucky, double chance) {
|
||||
if (isLucky)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -94,7 +94,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.getSuperAbilityType() != null) {
|
||||
abilityLabelBuilder.put(type.getSuperAbilityType(), getShortenedName(colors.get(i) + type.getSuperAbilityType().getLocalizedName()));
|
||||
@ -116,7 +116,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.getSuperAbilityType() != null) {
|
||||
abilityLabelBuilder.put(type.getSuperAbilityType(), formatAbility(type.getSuperAbilityType().getLocalizedName()));
|
||||
|
@ -6,7 +6,6 @@ import com.gmail.nossr50.events.skills.SkillActivationPerkEvent;
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
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;
|
||||
|
17
src/test/java/com/gmail/nossr50/TestUtil.java
Normal file
17
src/test/java/com/gmail/nossr50/TestUtil.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package com.gmail.nossr50.datatypes;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class BlockLocationHistoryTest {
|
||||
@Test
|
||||
public void testRemovesOldestElement() {
|
||||
BlockLocationHistory history = new BlockLocationHistory(2);
|
||||
Location locationA = new Location(null, 0, 1, 2);
|
||||
Location locationB = new Location(null, 1, 2, 3);
|
||||
Location locationC = new Location(null, 2, 3, 4);
|
||||
|
||||
history.add(locationA);
|
||||
history.add(locationB);
|
||||
history.add(locationC);
|
||||
Assert.assertFalse(history.contains(locationA));
|
||||
Assert.assertTrue(history.contains(locationB));
|
||||
Assert.assertTrue(history.contains(locationC));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSupportsDuplicateElement() {
|
||||
BlockLocationHistory history = new BlockLocationHistory(2);
|
||||
Location locationA = new Location(null, 0, 1, 2);
|
||||
Location locationB = new Location(null, 1, 2, 3);
|
||||
|
||||
history.add(locationA);
|
||||
history.add(locationA);
|
||||
history.add(locationB);
|
||||
Assert.assertTrue(history.contains(locationA));
|
||||
Assert.assertTrue(history.contains(locationB));
|
||||
history.add(locationB);
|
||||
Assert.assertFalse(history.contains(locationA));
|
||||
}
|
||||
}
|
@ -1,10 +1,11 @@
|
||||
import com.gmail.nossr50.util.blockmeta.*;
|
||||
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;
|
||||
import org.bukkit.block.Block;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
@ -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)
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user