diff --git a/Changelog.txt b/Changelog.txt index 4034fd8f0..defd5527f 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -10,6 +10,7 @@ Key: Version 2.1.1 = Fixed an issue where excavation wasn't using the correct permission node = Added protection against AFK fishing + = Acrobatics now uses much better anti-exploit detection Version 2.1.0 + mcMMO now features XP bars! Configurable in experience.yml diff --git a/src/main/java/com/gmail/nossr50/datatypes/LimitedSizeList.java b/src/main/java/com/gmail/nossr50/datatypes/LimitedSizeList.java new file mode 100644 index 000000000..c57b4996f --- /dev/null +++ b/src/main/java/com/gmail/nossr50/datatypes/LimitedSizeList.java @@ -0,0 +1,57 @@ +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; + } +} diff --git a/src/main/java/com/gmail/nossr50/datatypes/skills/subskills/acrobatics/Roll.java b/src/main/java/com/gmail/nossr50/datatypes/skills/subskills/acrobatics/Roll.java index 554c8f824..52ef3c734 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/skills/subskills/acrobatics/Roll.java +++ b/src/main/java/com/gmail/nossr50/datatypes/skills/subskills/acrobatics/Roll.java @@ -3,6 +3,7 @@ package com.gmail.nossr50.datatypes.skills.subskills.acrobatics; import com.gmail.nossr50.config.AdvancedConfig; import com.gmail.nossr50.config.Config; import com.gmail.nossr50.config.experience.ExperienceConfig; +import com.gmail.nossr50.datatypes.LimitedSizeList; import com.gmail.nossr50.datatypes.interactions.NotificationType; import com.gmail.nossr50.datatypes.player.McMMOPlayer; import com.gmail.nossr50.datatypes.player.PlayerProfile; @@ -18,6 +19,7 @@ import com.gmail.nossr50.util.player.UserManager; import com.gmail.nossr50.util.random.RandomChanceSkill; import com.gmail.nossr50.util.random.RandomChanceUtil; import com.gmail.nossr50.util.skills.PerksUtils; +import com.gmail.nossr50.util.skills.RankUtils; import com.gmail.nossr50.util.skills.SkillActivationType; import com.gmail.nossr50.util.skills.SkillUtils; import com.gmail.nossr50.util.sounds.SoundManager; @@ -33,12 +35,14 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.inventory.ItemStack; +import java.util.HashMap; + public class Roll extends AcrobaticsSubSkill { - private int fallTries = 0; - protected Location lastFallLocation; + protected HashMap fallLocationMap; public Roll() { super("Roll", EventPriority.HIGHEST, SubSkillType.ACROBATICS_ROLL); + fallLocationMap = new HashMap<>(); } /** @@ -75,7 +79,6 @@ public class Roll extends AcrobaticsSubSkill { */ Player player = (Player) ((EntityDamageEvent) event).getEntity(); if (canRoll(player)) { - if(Permissions.isSubSkillEnabled(player, SubSkillType.ACROBATICS_ROLL)) entityDamageEvent.setDamage(rollCheck(player, mcMMOPlayer, entityDamageEvent.getDamage())); if (entityDamageEvent.getFinalDamage() == 0) { @@ -182,7 +185,7 @@ public class Roll extends AcrobaticsSubSkill { } private boolean canRoll(Player player) { - return !isExploiting(player) && Permissions.isSubSkillEnabled(player, SubSkillType.ACROBATICS_ROLL); + return RankUtils.hasUnlockedSubskill(player, SubSkillType.ACROBATICS_ROLL) && Permissions.isSubSkillEnabled(player, SubSkillType.ACROBATICS_ROLL); } /** @@ -208,19 +211,21 @@ public class Roll extends AcrobaticsSubSkill { //player.sendMessage(LocaleLoader.getString("Acrobatics.Roll.Text")); //if (!SkillUtils.cooldownExpired((long) mcMMOPlayer.getTeleportATS(), Config.getInstance().getXPAfterTeleportCooldown())) { + if(!isExploiting(player)) SkillUtils.applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, true), XPGainReason.PVE); //} + addFallLocation(player); return modifiedDamage; } else if (!isFatal(player, damage)) { //if (!SkillUtils.cooldownExpired((long) mcMMOPlayer.getTeleportATS(), Config.getInstance().getXPAfterTeleportCooldown())) { + if(!isExploiting(player)) SkillUtils.applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, false), XPGainReason.PVE); //} } - lastFallLocation = player.getLocation(); - + addFallLocation(player); return damage; } @@ -245,12 +250,17 @@ public class Roll extends AcrobaticsSubSkill { { NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Acrobatics.Ability.Proc"); SoundManager.sendCategorizedSound(player, player.getLocation(), SoundType.ROLL_ACTIVATED, SoundCategory.PLAYERS,0.5F); - SkillUtils.applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, true), XPGainReason.PVE); + if(!isExploiting(player)) + SkillUtils.applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, true), XPGainReason.PVE); + addFallLocation(player); return modifiedDamage; } else if (!isFatal(player, damage)) { - SkillUtils.applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, false), XPGainReason.PVE); + if(!isExploiting(player)) + SkillUtils.applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, false), XPGainReason.PVE); + + addFallLocation(player); } return damage; @@ -271,6 +281,16 @@ public class Roll extends AcrobaticsSubSkill { return true; } + if(fallLocationMap.get(player) == null) + fallLocationMap.put(player, new LimitedSizeList(20)); + + LimitedSizeList fallLocations = fallLocationMap.get(player); + + if(fallLocations.contains(getBlockLocation(player))) + return true; + + return false; //NOT EXPLOITING +/* Location fallLocation = player.getLocation(); int maxTries = Config.getInstance().getAcrobaticsAFKMaxTries(); @@ -279,7 +299,7 @@ public class Roll extends AcrobaticsSubSkill { fallTries = sameLocation ? Math.min(fallTries + 1, maxTries) : Math.max(fallTries - 1, 0); lastFallLocation = fallLocation; - return fallTries + 1 > maxTries; + return fallTries + 1 > maxTries;*/ } private float calculateRollXP(Player player, double damage, boolean isRoll) { @@ -404,4 +424,20 @@ public class Roll extends AcrobaticsSubSkill { Double[] stats = { playerChanceRoll, playerChanceGrace }; //DEBUG return stats; } + + public void addFallLocation(Player player) + { + if(fallLocationMap.get(player) == null) + fallLocationMap.put(player, new LimitedSizeList(20)); + + LimitedSizeList fallLocations = fallLocationMap.get(player); + + Location loc = getBlockLocation(player); + fallLocations.add(loc); + } + + public Location getBlockLocation(Player player) + { + return player.getLocation().getBlock().getLocation(); + } } \ No newline at end of file