[Bleeding] Add blockinteract.visible check.

This check performs somewhat heuristic ray-tracing to see if a block
interacted with can actually be "seen", in terms of not reaching
through fully solid blocks. [Still needs for performance: more refined
conditions when to use + interact-speed check].
This commit is contained in:
asofold 2013-02-17 17:49:50 +01:00
parent 3f7e2d44f1
commit 48ffb2f09f
10 changed files with 105 additions and 5 deletions

View File

@ -50,6 +50,7 @@ public enum CheckType {
BLOCKINTERACT(BlockInteractConfig.factory, BlockInteractData.factory, Permissions.BLOCKINTERACT), BLOCKINTERACT(BlockInteractConfig.factory, BlockInteractData.factory, Permissions.BLOCKINTERACT),
BLOCKINTERACT_DIRECTION(BLOCKINTERACT, Permissions.BLOCKINTERACT_DIRECTION), BLOCKINTERACT_DIRECTION(BLOCKINTERACT, Permissions.BLOCKINTERACT_DIRECTION),
BLOCKINTERACT_REACH(BLOCKINTERACT, Permissions.BLOCKINTERACT_REACH), BLOCKINTERACT_REACH(BLOCKINTERACT, Permissions.BLOCKINTERACT_REACH),
BLOCKINTERACT_VISIBLE(BLOCKINTERACT, Permissions.BLOCKINTERACT_VISIBLE),
BLOCKPLACE(BlockPlaceConfig.factory, BlockPlaceData.factory, Permissions.BLOCKPLACE), BLOCKPLACE(BlockPlaceConfig.factory, BlockPlaceData.factory, Permissions.BLOCKPLACE),
BLOCKPLACE_DIRECTION(BLOCKPLACE, Permissions.BLOCKPLACE_DIRECTION), BLOCKPLACE_DIRECTION(BLOCKPLACE, Permissions.BLOCKPLACE_DIRECTION),

View File

@ -76,6 +76,9 @@ public class BlockInteractConfig extends ACheckConfig {
public final boolean reachCheck; public final boolean reachCheck;
public final ActionList reachActions; public final ActionList reachActions;
public final boolean visibleCheck;
public final ActionList visibleActions;
/** /**
* Instantiates a new block interact configuration. * Instantiates a new block interact configuration.
@ -91,6 +94,9 @@ public class BlockInteractConfig extends ACheckConfig {
reachCheck = data.getBoolean(ConfPaths.BLOCKINTERACT_REACH_CHECK); reachCheck = data.getBoolean(ConfPaths.BLOCKINTERACT_REACH_CHECK);
reachActions = data.getOptimizedActionList(ConfPaths.BLOCKINTERACT_REACH_ACTIONS, Permissions.BLOCKINTERACT_REACH); reachActions = data.getOptimizedActionList(ConfPaths.BLOCKINTERACT_REACH_ACTIONS, Permissions.BLOCKINTERACT_REACH);
visibleCheck = data.getBoolean(ConfPaths.BLOCKINTERACT_VISIBLE_CHECK);
visibleActions = data.getOptimizedActionList(ConfPaths.BLOCKINTERACT_VISIBLE_ACTIONS, Permissions.BLOCKINTERACT_VISIBLE);
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -103,6 +109,8 @@ public class BlockInteractConfig extends ACheckConfig {
return directionCheck; return directionCheck;
case BLOCKINTERACT_REACH: case BLOCKINTERACT_REACH:
return reachCheck; return reachCheck;
case BLOCKINTERACT_VISIBLE:
return visibleCheck;
default: default:
return true; return true;
} }

View File

@ -74,8 +74,9 @@ public class BlockInteractData extends ACheckData {
} }
// Violation levels. // Violation levels.
public double directionVL; public double directionVL = 0;
public double reachVL; public double reachVL = 0;
public double visibleVL = 0;
// Data of the reach check. // Data of the reach check.
public double reachDistance; public double reachDistance;

View File

@ -2,6 +2,7 @@ package fr.neatmonster.nocheatplus.checks.blockinteract;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Event.Result; import org.bukkit.event.Event.Result;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@ -42,6 +43,9 @@ public class BlockInteractListener extends CheckListener {
/** The reach check. */ /** The reach check. */
private final Reach reach = addCheck(new Reach()); private final Reach reach = addCheck(new Reach());
/** The Visible check. */
private final Visible visible = addCheck(new Visible());
public BlockInteractListener(){ public BlockInteractListener(){
super(CheckType.BLOCKINTERACT); super(CheckType.BLOCKINTERACT);
} }
@ -85,6 +89,7 @@ public class BlockInteractListener extends CheckListener {
boolean cancelled = false; boolean cancelled = false;
final BlockFace face = event.getBlockFace();
final Location loc = player.getLocation(); final Location loc = player.getLocation();
// TODO: fast-interact ! // TODO: fast-interact !
@ -99,6 +104,11 @@ public class BlockInteractListener extends CheckListener {
cancelled = true; cancelled = true;
} }
// Ray tracing for freecam use etc.
if (!cancelled && visible.isEnabled(player) && visible.check(player, loc, block, face, action, data, cc)){
cancelled = true;
}
// If one of the checks requested to cancel the event, do so. // If one of the checks requested to cancel the event, do so.
if (cancelled) { if (cancelled) {
event.setUseInteractedBlock(Result.DENY); event.setUseInteractedBlock(Result.DENY);

View File

@ -0,0 +1,68 @@
package fr.neatmonster.nocheatplus.checks.blockinteract;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import org.bukkit.event.block.Action;
import fr.neatmonster.nocheatplus.checks.Check;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.compat.MCAccess;
import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.utilities.BlockCache;
import fr.neatmonster.nocheatplus.utilities.InteractRayTracing;
public class Visible extends Check {
private BlockCache blockCache;
private final InteractRayTracing rayTracing = new InteractRayTracing(false);
public Visible() {
super(CheckType.BLOCKINTERACT_VISIBLE);
blockCache = mcAccess.getBlockCache(null);
}
/* (non-Javadoc)
* @see fr.neatmonster.nocheatplus.checks.Check#setMCAccess(fr.neatmonster.nocheatplus.compat.MCAccess)
*/
@Override
public void setMCAccess(MCAccess mcAccess) {
super.setMCAccess(mcAccess);
// Renew the BlockCache instance.
blockCache = mcAccess.getBlockCache(null);
}
public boolean check(final Player player, final Location loc, final Block block, final BlockFace face, final Action action, final BlockInteractData data, final BlockInteractConfig cc) {
// TODO: Might confine what to check for (left/right, target blocks depending on item in hand, container blocks).
blockCache.setAccess(loc.getWorld());
rayTracing.setBlockCache(blockCache);
rayTracing.set(loc.getX(), loc.getY() + player.getEyeHeight(), loc.getZ(), 0.5 + block.getX() + 0.6 * face.getModX(), 0.5 + block.getY() + 0.6 * face.getModY(), 0.5 + block.getZ() + 0.6 * face.getModZ());
rayTracing.loop();
final boolean collides = rayTracing.collides();
blockCache.cleanup();
rayTracing.cleanup();
if (cc.debug && player.hasPermission(Permissions.ADMINISTRATION_DEBUG)){
player.sendMessage("Interact: " + (action == Action.RIGHT_CLICK_BLOCK ? "right" : "left") + " collide=" + rayTracing.collides());
}
// Actions ?
boolean cancel = false;
if (collides){
data.visibleVL += 1;
if (executeActions(player, data.visibleVL, 1, cc.visibleActions)){
cancel = true;
}
}
else{
data.visibleVL *= 0.99;
}
return cancel;
}
}

View File

@ -141,6 +141,10 @@ public abstract class ConfPaths {
private static final String BLOCKINTERACT_REACH = BLOCKINTERACT + "reach."; private static final String BLOCKINTERACT_REACH = BLOCKINTERACT + "reach.";
public static final String BLOCKINTERACT_REACH_CHECK = BLOCKINTERACT_REACH + "active"; public static final String BLOCKINTERACT_REACH_CHECK = BLOCKINTERACT_REACH + "active";
public static final String BLOCKINTERACT_REACH_ACTIONS = BLOCKINTERACT_REACH + "actions"; public static final String BLOCKINTERACT_REACH_ACTIONS = BLOCKINTERACT_REACH + "actions";
private static final String BLOCKINTERACT_VISIBLE = BLOCKINTERACT + "visible.";
public static final String BLOCKINTERACT_VISIBLE_CHECK = BLOCKINTERACT_VISIBLE + "active";
public static final String BLOCKINTERACT_VISIBLE_ACTIONS = BLOCKINTERACT_VISIBLE + "actions";
/* /*
* 888 88b, 888 888 888 88e 888 * 888 88b, 888 888 888 88e 888

View File

@ -123,7 +123,10 @@ public class DefaultConfig extends ConfigFile {
set(ConfPaths.BLOCKINTERACT_REACH_CHECK, true); set(ConfPaths.BLOCKINTERACT_REACH_CHECK, true);
set(ConfPaths.BLOCKINTERACT_REACH_ACTIONS, "cancel vl>5 log:breach:0:2:if cancel"); set(ConfPaths.BLOCKINTERACT_REACH_ACTIONS, "cancel vl>5 log:breach:0:2:if cancel");
set(ConfPaths.BLOCKINTERACT_VISIBLE_CHECK, true);
set(ConfPaths.BLOCKINTERACT_VISIBLE_ACTIONS, "cancel vl>5 log:bvisible:0:2:if cancel");
/* /*
* 888 88b, 888 888 888 88e 888 * 888 88b, 888 888 888 88e 888
* 888 88P' 888 e88 88e e88'888 888 ee 888 888D 888 ,"Y88b e88'888 ,e e, * 888 88P' 888 e88 88e e88'888 888 ee 888 888D 888 ,"Y88b e88'888 ,e e,
@ -425,9 +428,9 @@ public class DefaultConfig extends ConfigFile {
set(ConfPaths.STRINGS + ".bdirection", start + "tried to interact with a block out of his line of sight" + end); set(ConfPaths.STRINGS + ".bdirection", start + "tried to interact with a block out of his line of sight" + end);
set(ConfPaths.STRINGS + ".bedleave", start + "sends bed leave packets (was not in bed)" + end); set(ConfPaths.STRINGS + ".bedleave", start + "sends bed leave packets (was not in bed)" + end);
set(ConfPaths.STRINGS + ".bpspeed", start + "tried to throw projectiles too quickly" + end); set(ConfPaths.STRINGS + ".bpspeed", start + "tried to throw projectiles too quickly" + end);
set(ConfPaths.STRINGS + ".breach", start set(ConfPaths.STRINGS + ".breach", start + "exceeds block-interact distance ([reachdistance])" + end);
+ "tried to interact with a block over distance [reachdistance] block(s)" + end);
set(ConfPaths.STRINGS + ".bwrong", start + "broke another block than clicked" + end); set(ConfPaths.STRINGS + ".bwrong", start + "broke another block than clicked" + end);
set(ConfPaths.STRINGS + ".bvisible", start + "interacts with a block out of sight" + end);
set(ConfPaths.STRINGS + ".captcha", "[player] failed captcha repeatedly" + end); set(ConfPaths.STRINGS + ".captcha", "[player] failed captcha repeatedly" + end);
set(ConfPaths.STRINGS + ".color", start + "sent colored chat message" + end); set(ConfPaths.STRINGS + ".color", start + "sent colored chat message" + end);
set(ConfPaths.STRINGS + ".commands", start + "issued too many commands" + end); set(ConfPaths.STRINGS + ".commands", start + "issued too many commands" + end);

View File

@ -83,6 +83,7 @@ public class Permissions {
public static final String BLOCKINTERACT = CHECKS + ".blockinteract"; public static final String BLOCKINTERACT = CHECKS + ".blockinteract";
public static final String BLOCKINTERACT_DIRECTION = BLOCKINTERACT + ".direction"; public static final String BLOCKINTERACT_DIRECTION = BLOCKINTERACT + ".direction";
public static final String BLOCKINTERACT_REACH = BLOCKINTERACT + ".reach"; public static final String BLOCKINTERACT_REACH = BLOCKINTERACT + ".reach";
public static final String BLOCKINTERACT_VISIBLE = BLOCKINTERACT + ".visible";
/* /*
* 888 88b, 888 888 888 88e 888 * 888 88b, 888 888 888 88e 888

View File

@ -42,6 +42,8 @@ public class CheckUtils {
*/ */
public static double directionCheck(final Player player, final double targetX, final double targetY, final double targetZ, final double targetWidth, final double targetHeight, final double precision) public static double directionCheck(final Player player, final double targetX, final double targetY, final double targetZ, final double targetWidth, final double targetHeight, final double precision)
{ {
// TODO: optimize !
// Get the eye location of the player. // Get the eye location of the player.
final Location eyes = player.getEyeLocation(); final Location eyes = player.getEyeLocation();

View File

@ -103,6 +103,8 @@ permissions:
description: Allow the player to bypass to Direction check. description: Allow the player to bypass to Direction check.
nocheatplus.checks.blockinteract.reach: nocheatplus.checks.blockinteract.reach:
description: Allow the player to bypass the Reach check. description: Allow the player to bypass the Reach check.
nocheatplus.checks.blockinteract.visible:
description: Allow the player to bypass the Visible check.
nocheatplus.checks.blockplace: nocheatplus.checks.blockplace:
description: Allow the player to bypass all BlockPlace checks. description: Allow the player to bypass all BlockPlace checks.
children: children: