mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-11-09 20:20:11 +01:00
Bleeding: Add "passable" check (~vclip).
This commit is contained in:
parent
791dca6048
commit
23e6d9b1be
@ -22,6 +22,7 @@ package fr.neatmonster.nocheatplus.actions;
|
||||
*/
|
||||
public enum ParameterName {
|
||||
CHECK("check"),
|
||||
BLOCK_ID("blockid"),
|
||||
DISTANCE("distance"),
|
||||
FALL_DISTANCE("falldistance"),
|
||||
FOOD("food"),
|
||||
|
@ -92,6 +92,7 @@ public enum CheckType {
|
||||
MOVING_MOREPACKETS(MOVING, Permissions.MOVING_MOREPACKETS),
|
||||
MOVING_MOREPACKETSVEHICLE(MOVING, Permissions.MOVING_MOREPACKETSVEHICLE),
|
||||
MOVING_NOFALL(MOVING, Permissions.MOVING_NOFALL),
|
||||
MOVING_PASSABLE(MOVING, Permissions.MOVING_PASSABLE),
|
||||
MOVING_SURVIVALFLY(MOVING, Permissions.MOVING_SURVIVALFLY),
|
||||
|
||||
UNKNOWN;
|
||||
|
@ -145,5 +145,9 @@ public class ViolationData {
|
||||
final String value = parameters.get(parameterName);
|
||||
return(value == null) ? ("<?" + parameterName + ">") : value;
|
||||
}
|
||||
|
||||
public void setParameter(final ParameterName parameterName, String value){
|
||||
if (parameters != null) parameters.put(parameterName, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -80,6 +80,9 @@ public class MovingConfig extends ACheckConfig {
|
||||
|
||||
public final boolean noFallCheck;
|
||||
public final ActionList noFallActions;
|
||||
|
||||
public final boolean passableCheck;
|
||||
public final ActionList passableActions;
|
||||
|
||||
public final boolean survivalFlyCheck;
|
||||
public final int survivalFlyBlockingSpeed;
|
||||
@ -121,6 +124,9 @@ public class MovingConfig extends ACheckConfig {
|
||||
|
||||
noFallCheck = data.getBoolean(ConfPaths.MOVING_NOFALL_CHECK);
|
||||
noFallActions = data.getActionList(ConfPaths.MOVING_NOFALL_ACTIONS, Permissions.MOVING_NOFALL);
|
||||
|
||||
passableCheck = data.getBoolean(ConfPaths.MOVING_PASSABLE_CHECK);
|
||||
passableActions = data.getActionList(ConfPaths.MOVING_PASSABLE_ACTIONS, Permissions.MOVING_PASSABLE);
|
||||
|
||||
survivalFlyCheck = data.getBoolean(ConfPaths.MOVING_SURVIVALFLY_CHECK);
|
||||
// Default values are specified here because this settings aren't showed by default into the configuration file.
|
||||
@ -149,6 +155,8 @@ public class MovingConfig extends ACheckConfig {
|
||||
return noFallCheck;
|
||||
case MOVING_SURVIVALFLY:
|
||||
return survivalFlyCheck;
|
||||
case MOVING_PASSABLE:
|
||||
return passableCheck;
|
||||
case MOVING_MOREPACKETS:
|
||||
return morePacketsCheck;
|
||||
case MOVING_MOREPACKETSVEHICLE:
|
||||
|
@ -95,6 +95,9 @@ public class MovingData extends ACheckData {
|
||||
public double noFallFallDistance;
|
||||
public boolean noFallOnGround;
|
||||
public boolean noFallWasOnGround;
|
||||
|
||||
// Passable check.
|
||||
public double passableVL;
|
||||
|
||||
// Data of the survival fly check.
|
||||
public int survivalFlyJumpPhase;
|
||||
|
@ -75,6 +75,8 @@ public class MovingListener implements Listener {
|
||||
|
||||
/** The survival fly check. */
|
||||
private final SurvivalFly survivalFly = new SurvivalFly();
|
||||
|
||||
private final Passable passable = new Passable();
|
||||
|
||||
/**
|
||||
* A workaround for players placing blocks below them getting pushed off the block by NoCheatPlus.
|
||||
@ -352,8 +354,11 @@ public class MovingListener implements Listener {
|
||||
|
||||
Location newTo = null;
|
||||
|
||||
if (passable.isEnabled(player)) newTo = passable.check(player, data.from, data.to, data, cc);
|
||||
|
||||
// Optimized checking, giving creativefly permission precedence over survivalfly.
|
||||
if (!player.hasPermission(Permissions.MOVING_CREATIVEFLY)){
|
||||
if (newTo != null);
|
||||
else if (!player.hasPermission(Permissions.MOVING_CREATIVEFLY)){
|
||||
// Either survivalfly or speed check.
|
||||
if ((cc.ignoreCreative || player.getGameMode() != GameMode.CREATIVE) && (cc.ignoreAllowFlight || !player.getAllowFlight())
|
||||
&& cc.survivalFlyCheck && !NCPExemptionManager.isExempted(player, CheckType.MOVING_SURVIVALFLY) && !player.hasPermission(Permissions.MOVING_SURVIVALFLY)){
|
||||
|
55
src/fr/neatmonster/nocheatplus/checks/moving/Passable.java
Normal file
55
src/fr/neatmonster/nocheatplus/checks/moving/Passable.java
Normal file
@ -0,0 +1,55 @@
|
||||
package fr.neatmonster.nocheatplus.checks.moving;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import fr.neatmonster.nocheatplus.actions.ParameterName;
|
||||
import fr.neatmonster.nocheatplus.checks.Check;
|
||||
import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||
import fr.neatmonster.nocheatplus.checks.ViolationData;
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockProperties;
|
||||
import fr.neatmonster.nocheatplus.utilities.PlayerLocation;
|
||||
|
||||
public class Passable extends Check {
|
||||
|
||||
public Passable() {
|
||||
super(CheckType.MOVING_PASSABLE);
|
||||
}
|
||||
|
||||
public Location check(final Player player, final PlayerLocation from, final PlayerLocation to, final MovingData data, final MovingConfig cc){
|
||||
// Simple check.
|
||||
final int toId = to.getTypeId();
|
||||
if (!BlockProperties.isPassable(to.getBlockAccess(), to.getX(), to.getY(), to.getZ(), toId)){
|
||||
// Allow moving into the same block.
|
||||
if (from.isSameBlock(to)){
|
||||
if (!BlockProperties.isPassable(from.getBlockAccess(), from.getX(), from.getY(), from.getZ(), from.getTypeId())) return null;
|
||||
}
|
||||
// Return the reset position.
|
||||
data.passableVL += 1d;
|
||||
final ViolationData vd = new ViolationData(this, player, data.passableVL, 1, cc.passableActions);
|
||||
vd.setParameter(ParameterName.BLOCK_ID, "" + toId);
|
||||
if (executeActions(vd)){
|
||||
final Location newTo = from.getLocation();
|
||||
newTo.setYaw(to.getYaw());
|
||||
newTo.setPitch(to.getPitch());
|
||||
return newTo;
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
data.passableVL *= 0.99;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<ParameterName, String> getParameterMap(final ViolationData violationData) {
|
||||
// TODO Auto-generated method stub
|
||||
return super.getParameterMap(violationData);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -223,7 +223,7 @@ public class SurvivalFly extends Check {
|
||||
|
||||
// Slowly reduce the level with each event.
|
||||
data.survivalFlyVL *= 0.95D;
|
||||
|
||||
// System.out.println("vertical freedom: " + data.verticalFreedom + " ("+data.verticalVelocity+"/"+data.verticalVelocityCounter+")");
|
||||
// Did the player move in unexpected ways?
|
||||
if (result > 0D) {
|
||||
// Increment violation counter.
|
||||
|
@ -450,6 +450,10 @@ public abstract class ConfPaths {
|
||||
private static final String MOVING_NOFALL = MOVING + "nofall.";
|
||||
public static final String MOVING_NOFALL_CHECK = MOVING_NOFALL + "active";
|
||||
public static final String MOVING_NOFALL_ACTIONS = MOVING_NOFALL + "actions";
|
||||
|
||||
public static final String MOVING_PASSABLE = MOVING + "passable.";
|
||||
public static final String MOVING_PASSABLE_CHECK = MOVING_PASSABLE + "active";
|
||||
public static final String MOVING_PASSABLE_ACTIONS = MOVING_PASSABLE + "actions";
|
||||
|
||||
private static final String MOVING_SURVIVALFLY = MOVING + "survivalfly.";
|
||||
public static final String MOVING_SURVIVALFLY_CHECK = MOVING_SURVIVALFLY + "active";
|
||||
|
@ -342,6 +342,9 @@ public class DefaultConfig extends ConfigFile {
|
||||
|
||||
set(ConfPaths.MOVING_NOFALL_CHECK, true);
|
||||
set(ConfPaths.MOVING_NOFALL_ACTIONS, "cancel vl>0 log:nofall:0:5:if cancel vl>6 log:nofall:0:5:icf cancel");
|
||||
|
||||
set(ConfPaths.MOVING_PASSABLE_CHECK, true);
|
||||
set(ConfPaths.MOVING_PASSABLE_ACTIONS, "cancel vl>5 log:passable:0:5:if cancel vl>50 log:passable:0:5:icf cancel");
|
||||
|
||||
set(ConfPaths.MOVING_SURVIVALFLY_CHECK, true);
|
||||
// The settings aren't enabled by default. Simply write them yourself in the configuration file.
|
||||
@ -408,6 +411,7 @@ public class DefaultConfig extends ConfigFile {
|
||||
set(ConfPaths.STRINGS + ".nofall", start + "tried to avoid fall damage for ~[falldistance] block(s)" + end);
|
||||
set(ConfPaths.STRINGS + ".nopwnage", start + "acted like spamming (IP: [ip])" + end);
|
||||
set(ConfPaths.STRINGS + ".noswing", start + "didn't swing arm" + end);
|
||||
set(ConfPaths.STRINGS + ".passable", start + "moved into a block([blockid])" + end);
|
||||
set(ConfPaths.STRINGS + ".tellglchat", tell + "&cNCP: &eChat can by annoying at times...");
|
||||
set(ConfPaths.STRINGS + ".tempkick1", "ncp tempkick [player] 1 Wait a minute!");
|
||||
set(ConfPaths.STRINGS + ".tempkick5", "ncp tempkick [player] 5 You have five minutes to think about it!");
|
||||
|
@ -164,6 +164,7 @@ public class Permissions {
|
||||
public static final String MOVING_MOREPACKETS = MOVING + ".morepackets";
|
||||
public static final String MOVING_MOREPACKETSVEHICLE = MOVING + ".morepacketsvehicle";
|
||||
public static final String MOVING_NOFALL = MOVING + ".nofall";
|
||||
public static final String MOVING_PASSABLE = MOVING + ".passable";
|
||||
public static final String MOVING_SURVIVALFLY = MOVING + ".survivalfly";
|
||||
public static final String MOVING_SURVIVALFLY_BLOCKING = MOVING_SURVIVALFLY + ".blocking";
|
||||
public static final String MOVING_SURVIVALFLY_SNEAKING = MOVING_SURVIVALFLY + ".sneaking";
|
||||
|
@ -7,6 +7,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.server.Block;
|
||||
import net.minecraft.server.IBlockAccess;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
@ -236,8 +237,10 @@ public class BlockProperties {
|
||||
protected static final long[] blockFlags = new long[maxBlocks];
|
||||
|
||||
/** Flag position for stairs. */
|
||||
public static final int F_STAIRS = 0x1;
|
||||
public static final int F_LIQUID = 0x2;
|
||||
public static final int F_STAIRS = 0x1;
|
||||
public static final int F_LIQUID = 0x2;
|
||||
public static final int F_SOLID = 0x4;
|
||||
public static final int F_IGN_SOLID = 0x8;
|
||||
|
||||
static{
|
||||
try{
|
||||
@ -283,11 +286,19 @@ public class BlockProperties {
|
||||
for (int i = 0; i <maxBlocks; i++){
|
||||
blocks[i] = null;
|
||||
blockFlags[i] = 0;
|
||||
final net.minecraft.server.Block block = net.minecraft.server.Block.byId[i];
|
||||
if (block != null){
|
||||
if (block.material != null){
|
||||
final net.minecraft.server.Material material = block.material;
|
||||
if (material.isSolid()) blockFlags[i] |= F_SOLID;
|
||||
if (material.isLiquid()) blockFlags[i] |= F_LIQUID;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Stairs.
|
||||
for (final Material mat : new Material[] {Material.WOOD_STAIRS, Material.COBBLESTONE_STAIRS,
|
||||
Material.BRICK_STAIRS, Material.SMOOTH_STAIRS, Material.NETHER_BRICK_STAIRS, Material.SANDSTONE_STAIRS,
|
||||
Material.SPRUCE_WOOD_STAIRS, Material.BIRCH_WOOD_STAIRS, Material.JUNGLE_WOOD_STAIRS}){
|
||||
for (final Material mat : new Material[] {Material.NETHER_BRICK_STAIRS,
|
||||
Material.COBBLESTONE_STAIRS, Material.SMOOTH_STAIRS, Material.BRICK_STAIRS, Material.SANDSTONE_STAIRS,
|
||||
Material.WOOD_STAIRS, Material.SPRUCE_WOOD_STAIRS, Material.BIRCH_WOOD_STAIRS, Material.JUNGLE_WOOD_STAIRS}){
|
||||
blockFlags[mat.getId()] |= F_STAIRS;
|
||||
}
|
||||
// Liquid.
|
||||
@ -295,7 +306,13 @@ public class BlockProperties {
|
||||
Material.LAVA, Material.STATIONARY_LAVA,
|
||||
Material.STATIONARY_WATER, Material.WATER,
|
||||
}) {
|
||||
blockFlags[mat.getId()] |= F_LIQUID;
|
||||
blockFlags[mat.getId()] |= F_LIQUID; // TODO: This might already be handled above now.
|
||||
}
|
||||
for (final Material mat : new Material[]{
|
||||
Material.WOOD_PLATE, Material.STONE_PLATE,
|
||||
Material.WALL_SIGN, Material.SIGN_POST,
|
||||
}){
|
||||
blockFlags[mat.getId()] |= F_IGN_SOLID;
|
||||
}
|
||||
// Instantly breakable.
|
||||
for (final Material mat : instantMat){
|
||||
@ -534,30 +551,6 @@ public class BlockProperties {
|
||||
return getBreakingDuration(blockId, itemInHand, onGround, inWater, helmet != null && helmet.containsEnchantment(Enchantment.WATER_WORKER));
|
||||
}
|
||||
|
||||
public static boolean isInWater(final int blockId) {
|
||||
if (blockId == Material.STATIONARY_WATER.getId() || blockId == Material.STATIONARY_LAVA.getId()) return true;
|
||||
// TODO: count in water height ?
|
||||
// TODO: lava ?
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Heavy but ...
|
||||
* @param world
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @return
|
||||
*/
|
||||
public static boolean isOnGround(Player player, Location location) {
|
||||
// return blockId != 0 && net.minecraft.server.Block.byId[blockId].//.c();// d();
|
||||
final PlayerLocation loc = new PlayerLocation();
|
||||
// Bit fat workaround, maybe put the object through from check listener ?
|
||||
loc.set(location, player, 0.3);
|
||||
return loc.isOnGround();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the normal breaking duration, including enchantments, and tool properties.
|
||||
@ -724,6 +717,29 @@ public class BlockProperties {
|
||||
blockProps.validate();
|
||||
BlockProperties.defaultBlockProps = blockProps;
|
||||
}
|
||||
|
||||
public static boolean isInWater(final int blockId) {
|
||||
if (blockId == Material.STATIONARY_WATER.getId() || blockId == Material.STATIONARY_LAVA.getId()) return true;
|
||||
// TODO: count in water height ?
|
||||
// TODO: lava ?
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Heavy but ...
|
||||
* @param world
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @return
|
||||
*/
|
||||
public static boolean isOnGround(Player player, Location location) {
|
||||
// return blockId != 0 && net.minecraft.server.Block.byId[blockId].//.c();// d();
|
||||
final PlayerLocation loc = new PlayerLocation();
|
||||
// Bit fat workaround, maybe put the object through from check listener ?
|
||||
loc.set(location, player, 0.3);
|
||||
return loc.isOnGround();
|
||||
}
|
||||
|
||||
/**
|
||||
* Hiding the API access here.<br>
|
||||
@ -734,14 +750,82 @@ public class BlockProperties {
|
||||
public static final boolean i(final int id) {
|
||||
return Block.i(id);
|
||||
}
|
||||
|
||||
public static final long getBLockFlags(final int id){
|
||||
return blockFlags[id];
|
||||
}
|
||||
|
||||
public static final void setBlockFlags(final int id, final long flags){
|
||||
blockFlags[id] = flags;
|
||||
}
|
||||
|
||||
public static final boolean isStairs(final int id) {
|
||||
return (blockFlags[id] & F_STAIRS) != 0;
|
||||
}
|
||||
|
||||
|
||||
public static boolean isLiquid(final int id) {
|
||||
public static final boolean isLiquid(final int id) {
|
||||
return (blockFlags[id] & F_LIQUID) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Might hold true for liquids too.
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
public static final boolean isSolid(final int id){
|
||||
return (blockFlags[id] & F_SOLID) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Just check if a position is not inside of a block that has a bounding box.<br>
|
||||
* This is an inaccurate check, it also returns false for doors etc.
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
public static final boolean isPassable(final int id){
|
||||
if ((blockFlags[id] & (F_LIQUID | F_IGN_SOLID)) != 0) return true;
|
||||
else return (blockFlags[id] & F_SOLID) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a position can be passed through.<br>
|
||||
* NOTE: This is experimental.
|
||||
* @param world
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
public static final boolean isPassable(final IBlockAccess blockAccess, final double x, final double y, final double z, final int id){
|
||||
// Simple exclusion check first.
|
||||
if (isPassable(id)) return true;
|
||||
// Check if the position is inside of a bounding box.
|
||||
final int bx = Location.locToBlock(x);
|
||||
final int by = Location.locToBlock(y);
|
||||
final int bz = Location.locToBlock(z);
|
||||
final net.minecraft.server.Block block = net.minecraft.server.Block.byId[id];
|
||||
if (block == null) return true;
|
||||
block.updateShape(blockAccess, bx, by, bz);
|
||||
final double fx = x - bx;
|
||||
final double fy = y - by;
|
||||
final double fz = z - bz;
|
||||
if (fx < block.minX || fx >= block.maxX || fy < block.minY || fy >= block.maxY || fz < block.minZ || fz >= block.maxZ) return true;
|
||||
else{
|
||||
// Workarounds.
|
||||
if (isStairs(id)){
|
||||
if ((blockAccess.getData(bx, by, bz) & 0x4) == 1){
|
||||
if (fy < 0.5) return true;
|
||||
}
|
||||
else if (fy >= 0.5) return true;
|
||||
}
|
||||
else if ((id == Material.IRON_FENCE.getId() || id == Material.THIN_GLASS.getId()) && block.maxX == 1.0){
|
||||
if (Math.abs(0.5 - fx) > 0.1 && Math.abs(0.5 - fz) > 0.1) return true;
|
||||
}
|
||||
// Nothing found.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package fr.neatmonster.nocheatplus.utilities;
|
||||
|
||||
import net.minecraft.server.AxisAlignedBB;
|
||||
import net.minecraft.server.EntityPlayer;
|
||||
import net.minecraft.server.IBlockAccess;
|
||||
import net.minecraft.server.WorldServer;
|
||||
|
||||
import org.bukkit.Location;
|
||||
@ -300,4 +301,17 @@ public class PlayerLocation {
|
||||
return typeIdBelow;
|
||||
}
|
||||
|
||||
public final boolean isSameBlock(final PlayerLocation other) {
|
||||
// Maybe make block coordinate fields later.
|
||||
return Location.locToBlock(x) == Location.locToBlock(other.getX()) && Location.locToBlock(y) == Location.locToBlock(other.getY()) && Location.locToBlock(z) == Location.locToBlock(other.getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: temp maybe
|
||||
* @return
|
||||
*/
|
||||
public final IBlockAccess getBlockAccess() {
|
||||
return world;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user