+ [Blocking] Added a new check to prevent players from running/attacking

while blocking
+ [Critical] Added a new check to prevent players from only making
criticals hits
= [NoFall] Fixed the false positive when falling into unclimbable vines
= [NoPwnage] Fixed an exception when getting message's parameters
= [Unpushable] Fixed the issues when two players are colliding
= [Running] Fixed players being able to move normally into cobweb
- [Unpushable] Disabled the check by default (consider it as
experimental)
This commit is contained in:
NeatMonster 2012-04-21 00:03:39 +02:00
parent 4a3d4d4cac
commit ef738e3b11
17 changed files with 657 additions and 459 deletions

File diff suppressed because it is too large Load Diff

View File

@ -47,6 +47,10 @@ permissions:
description: Allow a player to move through water without slowdown description: Allow a player to move through water without slowdown
nocheatplus.checks.moving.sneaking: nocheatplus.checks.moving.sneaking:
description: Allow a player to sneak without slowdown description: Allow a player to sneak without slowdown
nocheatplus.checks.moving.blocking:
description: Allow a player to block without slowdown
nocheatplus.checks.moving.cobweb:
description: Allow a player to move without slowdown while being into cobweb
nocheatplus.checks.moving.nofall: nocheatplus.checks.moving.nofall:
description: Allow a player to cheat and not take fall damage at all description: Allow a player to cheat and not take fall damage at all
nocheatplus.checks.moving.morepackets: nocheatplus.checks.moving.morepackets:
@ -111,6 +115,8 @@ permissions:
description: Allow a player to artificially speed up his health regeneration description: Allow a player to artificially speed up his health regeneration
nocheatplus.checks.fight.knockback: nocheatplus.checks.fight.knockback:
description: Allow a player to do knockbacks when it's not technically possible description: Allow a player to do knockbacks when it's not technically possible
nocheatplus.checks.fight.critical:
description: Allow a player to do criticals when it's not technically possible
nocheatplus.checks.inventory: nocheatplus.checks.inventory:
description: Allow the player to bypass all inventory checks description: Allow the player to bypass all inventory checks
children: children:

View File

@ -4,7 +4,7 @@
<!-- Informations --> <!-- Informations -->
<name>NoCheatPlus</name> <name>NoCheatPlus</name>
<version>3.5.7_1</version> <version>3.5.8</version>
<description>Detect and fight the exploitation of various flaws/bugs in Minecraft.</description> <description>Detect and fight the exploitation of various flaws/bugs in Minecraft.</description>
<url>http://dev.bukkit.org/server-mods/nocheatplus</url> <url>http://dev.bukkit.org/server-mods/nocheatplus</url>

View File

@ -18,9 +18,9 @@ import org.bukkit.util.Vector;
*/ */
public class CheckUtil { public class CheckUtil {
private final static double magic = 0.45D; private static final double magic = 0.45D;
private final static double magic2 = 0.55D; private static final double magic2 = 0.55D;
private static final int NONSOLID = 1; // 0x00000001 private static final int NONSOLID = 1; // 0x00000001
private static final int SOLID = 2; // 0x00000010 private static final int SOLID = 2; // 0x00000010
@ -32,7 +32,14 @@ public class CheckUtil {
// All fences are solid - fences are treated specially due // All fences are solid - fences are treated specially due
// to being 1.5 blocks high // to being 1.5 blocks high
private static final int FENCE = 16 | SOLID | NONSOLID; // 0x00010011 private static final int FENCE = 16 | NONSOLID | SOLID; // 0x00010011
// Webs slow players down so they must also be treated specially
private static final int WEB = 32 | NONSOLID | SOLID;
// We also treat unclimbable vines specially because players
// can't climb them but they slow players down
private static final int VINE = 64 | NONSOLID;
private static final int INGROUND = 128; private static final int INGROUND = 128;
@ -68,19 +75,18 @@ public class CheckUtil {
// du'h // du'h
types[Material.AIR.getId()] = NONSOLID; types[Material.AIR.getId()] = NONSOLID;
// Webs slow down a players fall extremely, so it makes
// sense to treat them as optionally solid
types[Material.WEB.getId()] = SOLID | NONSOLID;
// Obvious // Obvious
types[Material.LADDER.getId()] = LADDER; types[Material.LADDER.getId()] = LADDER;
types[Material.WATER_LILY.getId()] = LADDER; types[Material.WATER_LILY.getId()] = LADDER;
// The type VINE is only for unclimbable vines
types[Material.VINE.getId()] = LADDER; types[Material.VINE.getId()] = LADDER;
types[Material.FENCE.getId()] = FENCE; types[Material.FENCE.getId()] = FENCE;
types[Material.FENCE_GATE.getId()] = FENCE; types[Material.FENCE_GATE.getId()] = FENCE;
types[Material.NETHER_FENCE.getId()] = FENCE; types[Material.NETHER_FENCE.getId()] = FENCE;
types[Material.WEB.getId()] = WEB;
// These are sometimes solid, sometimes not // These are sometimes solid, sometimes not
types[Material.IRON_FENCE.getId()] = SOLID | NONSOLID; types[Material.IRON_FENCE.getId()] = SOLID | NONSOLID;
types[Material.THIN_GLASS.getId()] = SOLID | NONSOLID; types[Material.THIN_GLASS.getId()] = SOLID | NONSOLID;
@ -214,9 +220,15 @@ public class CheckUtil {
else if (isSolid(base)) else if (isSolid(base))
type = INGROUND; type = INGROUND;
// (In every case, check for water) // (In every case, check for water...)
if (isLiquid(base) || isLiquid(top)) if (isLiquid(base) || isLiquid(top))
type |= LIQUID | INGROUND; type |= LIQUID | INGROUND;
// (...and for web...)
if (isWeb(base) || isWeb(top))
type |= WEB;
// (...and for vine)
if (isVine(base))
type |= VINE;
return type; return type;
} }
@ -226,8 +238,9 @@ public class CheckUtil {
} }
private static int getType(final World world, final int x, final int y, final int z) { private static int getType(final World world, final int x, final int y, final int z) {
return types[world.getBlockAt(x, y, z).getType() == Material.VINE && !isClimbable(world, x, y, z) ? 0 : world if (world.getBlockAt(x, y, z).getType() == Material.VINE && !isClimbable(world, x, y, z))
.getBlockTypeIdAt(x, y, z)]; return VINE;
return types[world.getBlockTypeIdAt(x, y, z)];
} }
public static boolean isClimbable(final World world, final int x, final int y, final int z) { public static boolean isClimbable(final World world, final int x, final int y, final int z) {
@ -242,9 +255,7 @@ public class CheckUtil {
attachedFace = BlockFace.SOUTH; attachedFace = BlockFace.SOUTH;
if (attachedFace == null) if (attachedFace == null)
return true; return true;
return isSolid(getType(world, world.getBlockAt(x, y, z).getRelative(attachedFace).getX(), return isSolid(getType(world.getBlockAt(x, y, z).getRelative(attachedFace).getTypeId()));
world.getBlockAt(x, y, z).getRelative(attachedFace).getY(),
world.getBlockAt(x, y, z).getRelative(attachedFace).getZ()));
} }
public static boolean isFood(final ItemStack item) { public static boolean isFood(final ItemStack item) {
@ -277,6 +288,14 @@ public class CheckUtil {
return (value & SOLID) == SOLID; return (value & SOLID) == SOLID;
} }
public static boolean isVine(final int value) {
return (value & VINE) == VINE;
}
public static boolean isWeb(final int value) {
return (value & WEB) == WEB;
}
/** /**
* Personal Rounding function to determine if a player is still touching a * Personal Rounding function to determine if a player is still touching a
* block or not * block or not

View File

@ -1,6 +1,5 @@
package me.neatmonster.nocheatplus.checks.chat; package me.neatmonster.nocheatplus.checks.chat;
import java.util.Locale;
import java.util.Random; import java.util.Random;
import me.neatmonster.nocheatplus.NoCheatPlus; import me.neatmonster.nocheatplus.NoCheatPlus;
@ -189,9 +188,9 @@ public class NoPwnageCheck extends ChatCheck {
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) { public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
if (wildcard == ParameterName.REASON) if (wildcard == ParameterName.REASON)
return String.format(Locale.US, "%d", getData(player).reason); return getData(player).reason;
else if (wildcard == ParameterName.IP) else if (wildcard == ParameterName.IP)
return String.format(Locale.US, "%d", getData(player).ip); return getData(player).ip;
else else
return super.getParameter(wildcard, player); return super.getParameter(wildcard, player);
} }

View File

@ -0,0 +1,92 @@
package me.neatmonster.nocheatplus.checks.fight;
import java.util.Locale;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.checks.CheckUtil;
import me.neatmonster.nocheatplus.config.Permissions;
import me.neatmonster.nocheatplus.data.PreciseLocation;
import me.neatmonster.nocheatplus.data.Statistics.Id;
import net.minecraft.server.EntityPlayer;
import net.minecraft.server.MobEffectList;
import org.bukkit.Material;
import org.bukkit.craftbukkit.entity.CraftPlayer;
public class CriticalCheck extends FightCheck {
public CriticalCheck(final NoCheatPlus plugin) {
super(plugin, "fight.critical", Permissions.FIGHT_CRITICAL);
}
@Override
public boolean check(final NoCheatPlusPlayer player, final FightData data, final FightConfig cc) {
boolean cancel = false;
// We'll need the entity to do all the important stuff
final EntityPlayer entity = ((CraftPlayer) data.damager).getHandle();
// First we're going to check if the entity is on ladder
// Get the type of the block the entity is currently on
final int type = data.damager.getWorld().getBlockTypeIdAt((int) Math.floor(entity.locX),
(int) Math.floor(entity.locY), (int) Math.floor(entity.locZ));
// Check if this block if a ladder/vine or not
final boolean isOnLadder = type == Material.LADDER.getId() || type == Material.VINE.getId();
// Then we're going to check if the entity is in water
// Get the entity's precise location
final PreciseLocation location = new PreciseLocation();
location.x = entity.locX;
location.y = entity.locY;
location.z = entity.locZ;
// Check if the entity is in water
final boolean isInWater = CheckUtil.isLiquid(CheckUtil.evaluateLocation(data.damager.getWorld(), location));
// Check the hit was a critical hit or not (fallDistance > 0, entity in
// the air, not on ladder, not in water and no blindness effect)
if (entity.fallDistance > 0.0F && !entity.onGround && !isOnLadder && !isInWater
&& !entity.hasEffect(MobEffectList.BLINDNESS))
// That was a critical hit, now check if the player has jumped and not
// just a sent a packet to mislead the server
if (data.damager.getFallDistance() < cc.criticalFallDistance
|| Math.abs(data.damager.getVelocity().getY()) < cc.criticalVelocity) {
final double deltaFallDistance = cc.criticalFallDistance - data.damager.getFallDistance()
/ cc.criticalFallDistance;
final double deltaVelocity = cc.criticalVelocity - Math.abs(data.damager.getVelocity().getY())
/ cc.criticalVelocity;
final double delta = deltaFallDistance > 0D ? deltaFallDistance
: 0D + deltaVelocity > 0D ? deltaVelocity : 0D;
// Player failed the check, but this is influenced by lag,
// so don't do it if there was lag
if (!plugin.skipCheck()) {
// Increment the violation level
data.criticalVL += delta;
// Increment the statisctics of the player
incrementStatistics(player, Id.FI_CRITICAL, delta);
}
// Execute whatever actions are associated with this check and the
// violation level and find out if we should cancel the event
cancel = executeActions(player, cc.criticalActions, data.criticalVL);
}
return cancel;
}
@Override
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
if (wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", getData(player).criticalVL);
else
return super.getParameter(wildcard, player);
}
@Override
public boolean isEnabled(final FightConfig cc) {
return cc.criticalCheck;
}
}

View File

@ -7,6 +7,8 @@ import java.util.List;
import me.neatmonster.nocheatplus.EventManager; import me.neatmonster.nocheatplus.EventManager;
import me.neatmonster.nocheatplus.NoCheatPlus; import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer; import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.checks.moving.MovingCheck;
import me.neatmonster.nocheatplus.checks.moving.MovingConfig;
import me.neatmonster.nocheatplus.config.ConfigurationCacheStore; import me.neatmonster.nocheatplus.config.ConfigurationCacheStore;
import me.neatmonster.nocheatplus.config.Permissions; import me.neatmonster.nocheatplus.config.Permissions;
@ -47,6 +49,7 @@ public class FightCheckListener implements Listener, EventManager {
checks.add(new DirectionCheck(plugin)); checks.add(new DirectionCheck(plugin));
checks.add(new ReachCheck(plugin)); checks.add(new ReachCheck(plugin));
checks.add(new KnockbackCheck(plugin)); checks.add(new KnockbackCheck(plugin));
checks.add(new CriticalCheck(plugin));
godmodeCheck = new GodmodeCheck(plugin); godmodeCheck = new GodmodeCheck(plugin);
instanthealCheck = new InstanthealCheck(plugin); instanthealCheck = new InstanthealCheck(plugin);
@ -182,6 +185,8 @@ public class FightCheckListener implements Listener, EventManager {
s.add("fight.instantHeal"); s.add("fight.instantHeal");
if (f.knockbackCheck) if (f.knockbackCheck)
s.add("fight.knockback"); s.add("fight.knockback");
if (f.criticalCheck)
s.add("fight.critical");
return s; return s;
} }
@ -211,15 +216,25 @@ public class FightCheckListener implements Listener, EventManager {
// Get the attacked entity and remember it // Get the attacked entity and remember it
data.damagee = ((CraftEntity) event.getEntity()).getHandle(); data.damagee = ((CraftEntity) event.getEntity()).getHandle();
// Remember the attacker
data.damager = damager;
// Run through the four main checks // Run through the four main checks
for (final FightCheck check : checks) for (final FightCheck check : checks)
// If it should be executed, do it // If it should be executed, do it
if (!cancelled && check.isEnabled(cc) && !player.hasPermission(check.permission)) if (!cancelled && check.isEnabled(cc) && !player.hasPermission(check.permission))
cancelled = check.check(player, data, cc); cancelled = check.check(player, data, cc);
// Forget the attacked entity (to allow garbage collecting etc. final MovingConfig movingCc = MovingCheck.getConfig(player);
if (!cancelled && movingCc.blockingCheck && player.getPlayer().isBlocking())
cancelled = true;
// Forget the attacked entity (to allow garbage collecting, etc.)
data.damagee = null; data.damagee = null;
// Forget the attacker (to allow garbage collecting, etc.)
data.damager = null;
// One of the checks requested the event to be cancelled, so do it // One of the checks requested the event to be cancelled, so do it
if (cancelled) if (cancelled)
event.setCancelled(cancelled); event.setCancelled(cancelled);

View File

@ -41,18 +41,26 @@ public class FightConfig implements ConfigItem {
public final long knockbackInterval; public final long knockbackInterval;
public final ActionList knockbackActions; public final ActionList knockbackActions;
public final boolean criticalCheck;
public final double criticalFallDistance;
public final double criticalVelocity;
public final ActionList criticalActions;
public FightConfig(final NoCheatPlusConfiguration data) { public FightConfig(final NoCheatPlusConfiguration data) {
directionCheck = data.getBoolean(ConfPaths.FIGHT_DIRECTION_CHECK); directionCheck = data.getBoolean(ConfPaths.FIGHT_DIRECTION_CHECK);
directionPrecision = data.getInt(ConfPaths.FIGHT_DIRECTION_PRECISION) / 100D; directionPrecision = data.getInt(ConfPaths.FIGHT_DIRECTION_PRECISION) / 100D;
directionPenaltyTime = data.getInt(ConfPaths.FIGHT_DIRECTION_PENALTYTIME); directionPenaltyTime = data.getInt(ConfPaths.FIGHT_DIRECTION_PENALTYTIME);
directionActions = data.getActionList(ConfPaths.FIGHT_DIRECTION_ACTIONS, Permissions.FIGHT_DIRECTION); directionActions = data.getActionList(ConfPaths.FIGHT_DIRECTION_ACTIONS, Permissions.FIGHT_DIRECTION);
noswingCheck = data.getBoolean(ConfPaths.FIGHT_NOSWING_CHECK); noswingCheck = data.getBoolean(ConfPaths.FIGHT_NOSWING_CHECK);
noswingActions = data.getActionList(ConfPaths.FIGHT_NOSWING_ACTIONS, Permissions.FIGHT_NOSWING); noswingActions = data.getActionList(ConfPaths.FIGHT_NOSWING_ACTIONS, Permissions.FIGHT_NOSWING);
reachCheck = data.getBoolean(ConfPaths.FIGHT_REACH_CHECK); reachCheck = data.getBoolean(ConfPaths.FIGHT_REACH_CHECK);
reachLimit = data.getInt(ConfPaths.FIGHT_REACH_LIMIT) / 100D; reachLimit = data.getInt(ConfPaths.FIGHT_REACH_LIMIT) / 100D;
reachPenaltyTime = data.getInt(ConfPaths.FIGHT_REACH_PENALTYTIME); reachPenaltyTime = data.getInt(ConfPaths.FIGHT_REACH_PENALTYTIME);
reachActions = data.getActionList(ConfPaths.FIGHT_REACH_ACTIONS, Permissions.FIGHT_REACH); reachActions = data.getActionList(ConfPaths.FIGHT_REACH_ACTIONS, Permissions.FIGHT_REACH);
speedCheck = data.getBoolean(ConfPaths.FIGHT_SPEED_CHECK); speedCheck = data.getBoolean(ConfPaths.FIGHT_SPEED_CHECK);
speedActions = data.getActionList(ConfPaths.FIGHT_SPEED_ACTIONS, Permissions.FIGHT_SPEED); speedActions = data.getActionList(ConfPaths.FIGHT_SPEED_ACTIONS, Permissions.FIGHT_SPEED);
speedAttackLimit = data.getInt(ConfPaths.FIGHT_SPEED_ATTACKLIMIT); speedAttackLimit = data.getInt(ConfPaths.FIGHT_SPEED_ATTACKLIMIT);
@ -66,5 +74,10 @@ public class FightConfig implements ConfigItem {
knockbackCheck = data.getBoolean(ConfPaths.FIGHT_KNOCKBACK_CHECK); knockbackCheck = data.getBoolean(ConfPaths.FIGHT_KNOCKBACK_CHECK);
knockbackInterval = data.getLong(ConfPaths.FIGHT_KNOCKBACK_INTERVAL); knockbackInterval = data.getLong(ConfPaths.FIGHT_KNOCKBACK_INTERVAL);
knockbackActions = data.getActionList(ConfPaths.FIGHT_KNOCKBACK_ACTIONS, Permissions.FIGHT_KNOCKBACK); knockbackActions = data.getActionList(ConfPaths.FIGHT_KNOCKBACK_ACTIONS, Permissions.FIGHT_KNOCKBACK);
criticalCheck = data.getBoolean(ConfPaths.FIGHT_CRITICAL_CHECK);
criticalFallDistance = data.getDouble(ConfPaths.FIGHT_CRITICAL_FALLDISTANCE);
criticalVelocity = data.getDouble(ConfPaths.FIGHT_CRITICAL_VELOCITY);
criticalActions = data.getActionList(ConfPaths.FIGHT_CRITICAL_ACTIONS, Permissions.FIGHT_CRITICAL);
} }
} }

View File

@ -3,6 +3,8 @@ package me.neatmonster.nocheatplus.checks.fight;
import me.neatmonster.nocheatplus.DataItem; import me.neatmonster.nocheatplus.DataItem;
import net.minecraft.server.Entity; import net.minecraft.server.Entity;
import org.bukkit.entity.Player;
/** /**
* Player specific data for the fight checks * Player specific data for the fight checks
* *
@ -17,6 +19,7 @@ public class FightData implements DataItem {
public double godmodeVL; public double godmodeVL;
public double instanthealVL; public double instanthealVL;
public double knockbackVL; public double knockbackVL;
public double criticalVL;
// For checks that have penalty time // For checks that have penalty time
public long directionLastViolationTime; public long directionLastViolationTime;
@ -36,6 +39,9 @@ public class FightData implements DataItem {
// While handling an event, use this to keep the attacked entity // While handling an event, use this to keep the attacked entity
public Entity damagee; public Entity damagee;
// Remember the player who attacked the entity
public Player damager;
// The player swung his arm // The player swung his arm
public boolean armswung = true; public boolean armswung = true;

View File

@ -136,14 +136,14 @@ public class MovingCheckListener implements Listener, EventManager {
event.setCancelled(true); event.setCancelled(true);
} }
private PreciseLocation collide(final PreciseLocation to, final Player collider, final Player collided) { private Location collide(final Player collider, final Player collided, final PreciseLocation to) {
// Calculate some distances // Calculate some distances
double moveX = collider.getLocation().getX() - collided.getLocation().getX(); double moveX = collider.getLocation().getX() - collided.getLocation().getX();
double moveZ = collider.getLocation().getZ() - collided.getLocation().getZ(); double moveZ = collider.getLocation().getZ() - collided.getLocation().getZ();
double move = Math.max(Math.abs(moveX), Math.abs(moveZ)); double move = Math.max(Math.abs(moveX), Math.abs(moveZ));
// If the two players are close enough // If the two players are close enough
if (move >= 0.009999999776482582D) { if (move >= 0.0099999997764825821D) {
// Calculate the move // Calculate the move
move = Math.sqrt(move); move = Math.sqrt(move);
@ -161,14 +161,16 @@ public class MovingCheckListener implements Listener, EventManager {
// Teleport the collided player to his new location // Teleport the collided player to his new location
// if he hasn't the required permission // if he hasn't the required permission
if (!collided.hasPermission(Permissions.MOVING_UNPUSHABLE)) if (!collided.hasPermission(Permissions.MOVING_UNPUSHABLE))
collided.teleport(collided.getLocation().add(-moveX, 0, -moveZ)); ((CraftPlayer) collided).getHandle().move(-moveX, 0, -moveZ);
// Same for the collider, check his permissions // Same for the collider, check his permissions
to.x = to.x + moveX; if (!collider.hasPermission(Permissions.MOVING_UNPUSHABLE)) {
to.z = to.z + moveZ; final Entity entity = ((CraftPlayer) collider).getHandle();
entity.setPosition(to.x, to.y, to.z);
if (!collider.hasPermission(Permissions.MOVING_UNPUSHABLE)) entity.move(moveX, 0, moveZ);
return to; return new Location(collider.getWorld(), entity.locX, entity.locY, entity.locZ, entity.yaw,
entity.pitch);
}
} }
return null; return null;
} }
@ -184,6 +186,8 @@ public class MovingCheckListener implements Listener, EventManager {
s.add("moving.runfly"); s.add("moving.runfly");
if (m.sneakingCheck) if (m.sneakingCheck)
s.add("moving.sneaking"); s.add("moving.sneaking");
if (m.blockingCheck)
s.add("moving.blocking");
if (m.nofallCheck) if (m.nofallCheck)
s.add("moving.nofall"); s.add("moving.nofall");
if (m.waterWalkCheck) if (m.waterWalkCheck)
@ -313,10 +317,10 @@ public class MovingCheckListener implements Listener, EventManager {
// Check if the entity is a player // Check if the entity is a player
if (collidedEntity.getBukkitEntity() instanceof Player) { if (collidedEntity.getBukkitEntity() instanceof Player) {
final Player collidedPlayer = (Player) collidedEntity.getBukkitEntity(); final Location toLoc = collide(event.getPlayer(), (Player) collidedEntity.getBukkitEntity(),
data.to);
// Collide the two players if (toLoc != null)
newTo = collide(data.to, event.getPlayer(), collidedPlayer); event.setTo(toLoc);
} }
} }
} }

View File

@ -14,14 +14,19 @@ import me.neatmonster.nocheatplus.config.Permissions;
public class MovingConfig implements ConfigItem { public class MovingConfig implements ConfigItem {
public final boolean runflyCheck; public final boolean runflyCheck;
public final double jumpheight;
public final int maxCooldown;
public final boolean identifyCreativeMode; public final boolean identifyCreativeMode;
public final double walkingSpeedLimit; public final double walkingSpeedLimit;
public final double sprintingSpeedLimit; public final double sprintingSpeedLimit;
public final double jumpheight;
public final double swimmingSpeedLimit; public final double swimmingSpeedLimit;
public final boolean sneakingCheck; public final boolean sneakingCheck;
public final double sneakingSpeedLimit; public final double sneakingSpeedLimit;
public final int maxCooldown; public final boolean blockingCheck;
public final double blockingSpeedLimit;
public final double cobWebHoriSpeedLimit;
public final double cobWebVertSpeedLimit;
public final ActionList actions; public final ActionList actions;
public final boolean allowFlying; public final boolean allowFlying;
@ -57,13 +62,19 @@ public class MovingConfig implements ConfigItem {
final int sprintspeed = data.getInt(ConfPaths.MOVING_RUNFLY_SPRINTSPEED, 100); final int sprintspeed = data.getInt(ConfPaths.MOVING_RUNFLY_SPRINTSPEED, 100);
final int swimspeed = data.getInt(ConfPaths.MOVING_RUNFLY_SWIMSPEED, 100); final int swimspeed = data.getInt(ConfPaths.MOVING_RUNFLY_SWIMSPEED, 100);
final int sneakspeed = data.getInt(ConfPaths.MOVING_RUNFLY_SNEAKSPEED, 100); final int sneakspeed = data.getInt(ConfPaths.MOVING_RUNFLY_SNEAKSPEED, 100);
final int blockspeed = data.getInt(ConfPaths.MOVING_RUNFLY_BLOCKSPEED, 100);
final int cobWebSpeed = data.getInt(ConfPaths.MOVING_RUNFLY_COBWEBSPEED, 100);
walkingSpeedLimit = 0.22 * walkspeed / 100D; walkingSpeedLimit = 0.22 * walkspeed / 100D;
sprintingSpeedLimit = 0.35 * sprintspeed / 100D; sprintingSpeedLimit = 0.35 * sprintspeed / 100D;
swimmingSpeedLimit = 0.18 * swimspeed / 100D; swimmingSpeedLimit = 0.18 * swimspeed / 100D;
sneakingSpeedLimit = 0.14 * sneakspeed / 100D; sneakingSpeedLimit = 0.14 * sneakspeed / 100D;
blockingSpeedLimit = 0.16 * blockspeed / 100D;
cobWebHoriSpeedLimit = 0.08 * cobWebSpeed / 100D;
cobWebVertSpeedLimit = 0.07 * cobWebSpeed / 100D;
jumpheight = 135 / 100D; jumpheight = 135 / 100D;
sneakingCheck = !data.getBoolean(ConfPaths.MOVING_RUNFLY_ALLOWFASTSNEAKING); sneakingCheck = !data.getBoolean(ConfPaths.MOVING_RUNFLY_ALLOWFASTSNEAKING);
blockingCheck = !data.getBoolean(ConfPaths.MOVING_RUNFLY_ALLOWFASTBLOCKING);
maxCooldown = data.getInt(ConfPaths.MOVING_RUNFLY_MAXCOOLDOWN); maxCooldown = data.getInt(ConfPaths.MOVING_RUNFLY_MAXCOOLDOWN);
actions = data.getActionList(ConfPaths.MOVING_RUNFLY_ACTIONS, Permissions.MOVING_RUNFLY); actions = data.getActionList(ConfPaths.MOVING_RUNFLY_ACTIONS, Permissions.MOVING_RUNFLY);

View File

@ -5,6 +5,7 @@ import java.util.Locale;
import me.neatmonster.nocheatplus.NoCheatPlus; import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer; import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName; import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.checks.CheckUtil;
import me.neatmonster.nocheatplus.data.Statistics.Id; import me.neatmonster.nocheatplus.data.Statistics.Id;
/** /**
@ -32,6 +33,14 @@ public class NoFallCheck extends MovingCheck {
return; return;
} }
// If the player is in unclimbable vines, do not do the check
if (CheckUtil.isVine(CheckUtil.evaluateLocation(player.getPlayer().getWorld(), data.from))
|| CheckUtil.isVine(CheckUtil.evaluateLocation(player.getPlayer().getWorld(), data.to))) {
data.fallDistance = 0F;
data.lastAddedFallDistance = 0F;
return;
}
// This check is pretty much always a step behind for technical reasons. // This check is pretty much always a step behind for technical reasons.
if (data.fromOnOrInGround) if (data.fromOnOrInGround)
// Start with zero fall distance // Start with zero fall distance

View File

@ -11,6 +11,7 @@ import me.neatmonster.nocheatplus.data.PreciseLocation;
import me.neatmonster.nocheatplus.data.Statistics.Id; import me.neatmonster.nocheatplus.data.Statistics.Id;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
/** /**
@ -148,7 +149,14 @@ public class RunningCheck extends MovingCheck {
else if (data.onIce > 0) else if (data.onIce > 0)
data.onIce--; data.onIce--;
if (cc.sneakingCheck && player.getPlayer().isSneaking() && !player.hasPermission(Permissions.MOVING_SNEAKING)) { if (cc.blockingCheck && player.getPlayer().isBlocking() && !player.hasPermission(Permissions.MOVING_BLOCKING)) {
limit = cc.blockingSpeedLimit;
statisticsCategory = Id.MOV_BLOCKING;
if (cc.sneakingCheck && player.getPlayer().isSneaking()
&& !player.hasPermission(Permissions.MOVING_SNEAKING))
limit = Math.min(cc.sneakingSpeedLimit, cc.blockingSpeedLimit);
} else if (cc.sneakingCheck && player.getPlayer().isSneaking()
&& !player.hasPermission(Permissions.MOVING_SNEAKING)) {
limit = cc.sneakingSpeedLimit; limit = cc.sneakingSpeedLimit;
statisticsCategory = Id.MOV_SNEAKING; statisticsCategory = Id.MOV_SNEAKING;
} else if (isSwimming && !player.hasPermission(Permissions.MOVING_SWIMMING)) { } else if (isSwimming && !player.hasPermission(Permissions.MOVING_SWIMMING)) {
@ -163,7 +171,16 @@ public class RunningCheck extends MovingCheck {
} }
if (data.onIce > 0) if (data.onIce > 0)
limit *= 2.5; limit *= 2.5D;
// If the player is in web, we need a fixed limit
final World world = player.getPlayer().getWorld();
if (CheckUtil.isWeb(CheckUtil.evaluateLocation(world, data.from))
&& CheckUtil.isWeb(CheckUtil.evaluateLocation(world, data.to))
&& !player.hasPermission(Permissions.MOVING_COBWEB)) {
limit = cc.cobWebHoriSpeedLimit;
statisticsCategory = Id.MOV_COBWEB;
}
// Taken directly from Minecraft code, should work // Taken directly from Minecraft code, should work
limit *= player.getSpeedAmplifier(); limit *= player.getSpeedAmplifier();
@ -219,7 +236,15 @@ public class RunningCheck extends MovingCheck {
if (data.jumpPhase > jumpingLimit + data.lastJumpAmplifier) if (data.jumpPhase > jumpingLimit + data.lastJumpAmplifier)
limit -= (data.jumpPhase - jumpingLimit) * 0.15D; limit -= (data.jumpPhase - jumpingLimit) * 0.15D;
distanceAboveLimit = data.to.y - data.runflySetBackPoint.y - limit; // Check if the player is in web and check his move
final World world = player.getPlayer().getWorld();
if (CheckUtil.isWeb(CheckUtil.evaluateLocation(world, data.from))
&& CheckUtil.isWeb(CheckUtil.evaluateLocation(world, data.to))
&& Math.abs(data.to.y - data.from.y) > cc.cobWebVertSpeedLimit)
distanceAboveLimit = Math.abs(data.to.y - data.from.y - cc.cobWebVertSpeedLimit);
else
distanceAboveLimit = data.to.y - data.runflySetBackPoint.y - limit;
if (distanceAboveLimit > 0) if (distanceAboveLimit > 0)
data.statisticCategory = Id.MOV_FLYING; data.statisticCategory = Id.MOV_FLYING;

View File

@ -46,13 +46,16 @@ public abstract class ConfPaths {
private static final String MOVING_RUNFLY = MOVING + "runfly."; private static final String MOVING_RUNFLY = MOVING + "runfly.";
public static final String MOVING_RUNFLY_CHECK = MOVING_RUNFLY + "active"; public static final String MOVING_RUNFLY_CHECK = MOVING_RUNFLY + "active";
// These four are not automatically shown in the config // These sixth are not automatically shown in the config
public static final String MOVING_RUNFLY_WALKSPEED = MOVING_RUNFLY + "walkspeed"; public static final String MOVING_RUNFLY_WALKSPEED = MOVING_RUNFLY + "walkspeed";
public static final String MOVING_RUNFLY_SNEAKSPEED = MOVING_RUNFLY + "sneakspeed"; public static final String MOVING_RUNFLY_SNEAKSPEED = MOVING_RUNFLY + "sneakspeed";
public static final String MOVING_RUNFLY_BLOCKSPEED = MOVING_RUNFLY + "blockspeed";
public static final String MOVING_RUNFLY_SWIMSPEED = MOVING_RUNFLY + "swimspeed"; public static final String MOVING_RUNFLY_SWIMSPEED = MOVING_RUNFLY + "swimspeed";
public static final String MOVING_RUNFLY_SPRINTSPEED = MOVING_RUNFLY + "sprintspeed"; public static final String MOVING_RUNFLY_SPRINTSPEED = MOVING_RUNFLY + "sprintspeed";
public static final String MOVING_RUNFLY_COBWEBSPEED = MOVING_RUNFLY + "cobwebspeed";
public static final String MOVING_RUNFLY_ALLOWFASTSNEAKING = MOVING_RUNFLY + "allowfastsneaking"; public static final String MOVING_RUNFLY_ALLOWFASTSNEAKING = MOVING_RUNFLY + "allowfastsneaking";
public static final String MOVING_RUNFLY_ALLOWFASTBLOCKING = MOVING_RUNFLY + "allowfastblocking";
public static final String MOVING_RUNFLY_MAXCOOLDOWN = MOVING_RUNFLY + "maxcooldown"; public static final String MOVING_RUNFLY_MAXCOOLDOWN = MOVING_RUNFLY + "maxcooldown";
public static final String MOVING_RUNFLY_ACTIONS = MOVING_RUNFLY + "actions"; public static final String MOVING_RUNFLY_ACTIONS = MOVING_RUNFLY + "actions";
@ -233,6 +236,12 @@ public abstract class ConfPaths {
public static final String FIGHT_KNOCKBACK_INTERVAL = FIGHT_KNOCKBACK + "interval"; public static final String FIGHT_KNOCKBACK_INTERVAL = FIGHT_KNOCKBACK + "interval";
public static final String FIGHT_KNOCKBACK_ACTIONS = FIGHT_KNOCKBACK + "actions"; public static final String FIGHT_KNOCKBACK_ACTIONS = FIGHT_KNOCKBACK + "actions";
private static final String FIGHT_CRITICAL = FIGHT + "critical.";
public static final String FIGHT_CRITICAL_CHECK = FIGHT_CRITICAL + "active";
public static final String FIGHT_CRITICAL_FALLDISTANCE = FIGHT_CRITICAL + "falldistance";
public static final String FIGHT_CRITICAL_VELOCITY = FIGHT_CRITICAL + "velocity";
public static final String FIGHT_CRITICAL_ACTIONS = FIGHT_CRITICAL + "actions";
public static final String STRINGS = "strings"; public static final String STRINGS = "strings";
} }

View File

@ -48,6 +48,7 @@ public class DefaultConfiguration extends NoCheatPlusConfiguration {
set(ConfPaths.MOVING_RUNFLY_CHECK, true); set(ConfPaths.MOVING_RUNFLY_CHECK, true);
set(ConfPaths.MOVING_RUNFLY_ALLOWFASTSNEAKING, false); set(ConfPaths.MOVING_RUNFLY_ALLOWFASTSNEAKING, false);
set(ConfPaths.MOVING_RUNFLY_ALLOWFASTBLOCKING, false);
set(ConfPaths.MOVING_RUNFLY_MAXCOOLDOWN, 10000); set(ConfPaths.MOVING_RUNFLY_MAXCOOLDOWN, 10000);
set(ConfPaths.MOVING_RUNFLY_ACTIONS, set(ConfPaths.MOVING_RUNFLY_ACTIONS,
"log:moveshort:3:5:f cancel vl>100 log:moveshort:0:5:if cancel vl>400 log:movelong:0:5:cif cancel"); "log:moveshort:3:5:f cancel vl>100 log:moveshort:0:5:if cancel vl>400 log:movelong:0:5:cif cancel");
@ -74,7 +75,7 @@ public class DefaultConfiguration extends NoCheatPlusConfiguration {
set(ConfPaths.MOVING_WATERWALK_ACTIONS, set(ConfPaths.MOVING_WATERWALK_ACTIONS,
"log:waterwalk:3:5:f cancel vl>100 log:waterwalk:0:5:if cancel vl>400 log:waterwalk:0:5:cif cancel"); "log:waterwalk:3:5:f cancel vl>100 log:waterwalk:0:5:if cancel vl>400 log:waterwalk:0:5:cif cancel");
set(ConfPaths.MOVING_UNPUSHABLE_CHECK, true); set(ConfPaths.MOVING_UNPUSHABLE_CHECK, false);
/*** BLOCKBREAK ***/ /*** BLOCKBREAK ***/
@ -202,6 +203,11 @@ public class DefaultConfiguration extends NoCheatPlusConfiguration {
set(ConfPaths.FIGHT_KNOCKBACK_INTERVAL, 50); set(ConfPaths.FIGHT_KNOCKBACK_INTERVAL, 50);
set(ConfPaths.FIGHT_KNOCKBACK_ACTIONS, "cancel vl>50 log:fknock:0:5:cif cancel"); set(ConfPaths.FIGHT_KNOCKBACK_ACTIONS, "cancel vl>50 log:fknock:0:5:cif cancel");
set(ConfPaths.FIGHT_CRITICAL_CHECK, true);
set(ConfPaths.FIGHT_CRITICAL_FALLDISTANCE, 0.01D);
set(ConfPaths.FIGHT_CRITICAL_VELOCITY, 0.1D);
set(ConfPaths.FIGHT_CRITICAL_ACTIONS, "cancel vl>50 log:fcritical:0:5:cif cancel");
set(ConfPaths.STRINGS + ".drop", set(ConfPaths.STRINGS + ".drop",
"[player] failed [check]: Tried to drop more items than allowed. VL [violations]"); "[player] failed [check]: Tried to drop more items than allowed. VL [violations]");
set(ConfPaths.STRINGS + ".moveshort", "[player] failed [check]. VL [violations]"); set(ConfPaths.STRINGS + ".moveshort", "[player] failed [check]. VL [violations]");
@ -242,7 +248,9 @@ public class DefaultConfiguration extends NoCheatPlusConfiguration {
set(ConfPaths.STRINGS + ".fheal", set(ConfPaths.STRINGS + ".fheal",
"[player] failed [check]: Tried to regenerate health faster than normal. VL [violations]"); "[player] failed [check]: Tried to regenerate health faster than normal. VL [violations]");
set(ConfPaths.STRINGS + ".fknock", set(ConfPaths.STRINGS + ".fknock",
"[player] failed [check]: Tried to do a knockback but wasn't really sprinting. VL [violations]"); "[player] failed [check]: Tried to do a knockback but wasn't technically sprinting. VL [violations]");
set(ConfPaths.STRINGS + ".fcritical",
"[player] failed [check]: Tried to do a critical hit but wasn't technically jumping. VL [violations]");
set(ConfPaths.STRINGS + ".ibow", "[player] failed [check]: Fires bow to fast. VL [violations]"); set(ConfPaths.STRINGS + ".ibow", "[player] failed [check]: Fires bow to fast. VL [violations]");
set(ConfPaths.STRINGS + ".ieat", "[player] failed [check]: Eats food [food] too fast. VL [violations]"); set(ConfPaths.STRINGS + ".ieat", "[player] failed [check]: Eats food [food] too fast. VL [violations]");
set(ConfPaths.STRINGS + ".kick", "kick [player]"); set(ConfPaths.STRINGS + ".kick", "kick [player]");

View File

@ -44,6 +44,7 @@ public class Permissions {
public static final String FIGHT_GODMODE = FIGHT + ".godmode"; public static final String FIGHT_GODMODE = FIGHT + ".godmode";
public static final String FIGHT_INSTANTHEAL = FIGHT + ".instantheal"; public static final String FIGHT_INSTANTHEAL = FIGHT + ".instantheal";
public static final String FIGHT_KNOCKBACK = FIGHT + ".knockback"; public static final String FIGHT_KNOCKBACK = FIGHT + ".knockback";
public static final String FIGHT_CRITICAL = FIGHT + ".critical";
private static final String INVENTORY = CHECKS + ".inventory"; private static final String INVENTORY = CHECKS + ".inventory";
public static final String INVENTORY_DROP = INVENTORY + ".drop"; public static final String INVENTORY_DROP = INVENTORY + ".drop";
@ -54,7 +55,9 @@ public class Permissions {
public static final String MOVING_RUNFLY = MOVING + ".runfly"; public static final String MOVING_RUNFLY = MOVING + ".runfly";
public static final String MOVING_SWIMMING = MOVING + ".swimming"; public static final String MOVING_SWIMMING = MOVING + ".swimming";
public static final String MOVING_SNEAKING = MOVING + ".sneaking"; public static final String MOVING_SNEAKING = MOVING + ".sneaking";
public static final String MOVING_BLOCKING = MOVING + ".blocking";
public static final String MOVING_FLYING = MOVING + ".flying"; public static final String MOVING_FLYING = MOVING + ".flying";
public static final String MOVING_COBWEB = MOVING + ".cobweb";
public static final String MOVING_NOFALL = MOVING + ".nofall"; public static final String MOVING_NOFALL = MOVING + ".nofall";
public static final String MOVING_MOREPACKETS = MOVING + ".morepackets"; public static final String MOVING_MOREPACKETS = MOVING + ".morepackets";
public static final String MOVING_MOREPACKETSVEHICLE = MOVING + ".morepacketsvehicle"; public static final String MOVING_MOREPACKETSVEHICLE = MOVING + ".morepacketsvehicle";

View File

@ -23,6 +23,7 @@ public class Statistics {
FI_REACH("fight.reach"), FI_REACH("fight.reach"),
FI_SPEED("fight.speed"), FI_SPEED("fight.speed"),
FI_KNOCKBACK("fight.knockback"), FI_KNOCKBACK("fight.knockback"),
FI_CRITICAL("fight.critical"),
INV_DROP("inventory.drop"), INV_DROP("inventory.drop"),
INV_BOW("inventory.instantbow"), INV_BOW("inventory.instantbow"),
INV_EAT("inventory.instanteat"), INV_EAT("inventory.instanteat"),
@ -32,7 +33,9 @@ public class Statistics {
MOV_MOREPACKETSVEHICLE("moving.morepacketsvehicle"), MOV_MOREPACKETSVEHICLE("moving.morepacketsvehicle"),
MOV_NOFALL("moving.nofall"), MOV_NOFALL("moving.nofall"),
MOV_SNEAKING("moving.sneaking"), MOV_SNEAKING("moving.sneaking"),
MOV_BLOCKING("moving.blocking"),
MOV_SWIMMING("moving.swimming"), MOV_SWIMMING("moving.swimming"),
MOV_COBWEB("moving.cobweb"),
FI_GODMODE("fight.godmode"), FI_GODMODE("fight.godmode"),
FI_INSTANTHEAL("fight.instantheal"); FI_INSTANTHEAL("fight.instantheal");