mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-09-27 14:13:11 +02:00
More details for last block. Consumed checks. Don't skip item use.
* Store complete event result state for interact. * Store consumed checks as well. * Still run the speed check, if only using the item in hand is allowed.
This commit is contained in:
parent
51d24d1a39
commit
d8ab00dfb0
@ -23,7 +23,9 @@ import java.util.UUID;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event.Result;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
|
||||
import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||
import fr.neatmonster.nocheatplus.checks.access.ACheckData;
|
||||
@ -96,9 +98,12 @@ public class BlockInteractData extends ACheckData {
|
||||
private int lastX = Integer.MAX_VALUE;
|
||||
private int lastY, lastZ;
|
||||
/** null for air */
|
||||
public Material lastType = null;
|
||||
public int lastTick;
|
||||
public Action lastAction = null;
|
||||
private Material lastType = null;
|
||||
private int lastTick;
|
||||
private Action lastAction = null;
|
||||
private boolean lastAllowUseBlock = false;
|
||||
private boolean lastAllowUseItem = false;
|
||||
private boolean lastIsCancelled = true;
|
||||
|
||||
// Data of the reach check.
|
||||
public double reachDistance;
|
||||
@ -117,15 +122,28 @@ public class BlockInteractData extends ACheckData {
|
||||
*/
|
||||
public int rateLimitSkip = 0;
|
||||
|
||||
/**
|
||||
* Checks that have been run and passed for the block last interacted with
|
||||
* (rather complete for block-interact checks, to skip subsequent
|
||||
* block-break/place checks).
|
||||
*/
|
||||
private final Set<CheckType> passedChecks = new HashSet<CheckType>();
|
||||
/**
|
||||
* Checks that have been run and consume this event, i.e. can't be run again
|
||||
* (not complete, may contain checks from other check groups).
|
||||
*/
|
||||
private final Set<CheckType> consumedChecks = new HashSet<CheckType>();
|
||||
|
||||
public BlockInteractData(final BlockInteractConfig config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Last interacted block.
|
||||
* Set last interacted block (coordinates, type, tick). Also resets the
|
||||
* passed checks.
|
||||
*
|
||||
* @param block
|
||||
* @param action
|
||||
*/
|
||||
public void setLastBlock(final Block block, final Action action) {
|
||||
lastX = block.getX();
|
||||
@ -137,6 +155,8 @@ public class BlockInteractData extends ACheckData {
|
||||
}
|
||||
lastTick = TickTask.getTick();
|
||||
lastAction = action;
|
||||
resetPassedChecks();
|
||||
resetConsumedChecks();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -210,6 +230,36 @@ public class BlockInteractData extends ACheckData {
|
||||
block.getX(), block.getY(), block.getZ());
|
||||
}
|
||||
|
||||
public boolean getLastAllowUseItem() {
|
||||
return lastAllowUseItem;
|
||||
}
|
||||
|
||||
public boolean getLastAllowUseBlock() {
|
||||
return lastAllowUseBlock;
|
||||
}
|
||||
|
||||
public boolean getLastisCancelled() {
|
||||
return lastIsCancelled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tick of the last interaction with a block.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getLastTick() {
|
||||
return lastTick;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the action of the last interaction with a block.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Action getLastAction() {
|
||||
return lastAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the last block (and passed checks).
|
||||
*/
|
||||
@ -218,7 +268,11 @@ public class BlockInteractData extends ACheckData {
|
||||
lastAction = null;
|
||||
lastX = Integer.MAX_VALUE;
|
||||
lastType = null;
|
||||
lastAllowUseBlock = false;
|
||||
lastAllowUseItem = false;
|
||||
lastIsCancelled = true;
|
||||
resetPassedChecks();
|
||||
resetConsumedChecks();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -228,10 +282,41 @@ public class BlockInteractData extends ACheckData {
|
||||
passedChecks.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the check type to be passed for the last block.
|
||||
*
|
||||
* @param checkType
|
||||
*/
|
||||
public void addPassedCheck(final CheckType checkType) {
|
||||
passedChecks.add(checkType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the last block was set to be consumed by this check type.
|
||||
*
|
||||
* @param checkType
|
||||
* @return
|
||||
*/
|
||||
public boolean isConsumedCheck(final CheckType checkType) {
|
||||
return consumedChecks.contains(checkType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset consumed checks (concern the last block interacted with).
|
||||
*/
|
||||
public void resetConsumedChecks() {
|
||||
consumedChecks.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set last block to be consumed by the given check type.
|
||||
*
|
||||
* @param checkType
|
||||
*/
|
||||
public void addConsumedCheck(final CheckType checkType) {
|
||||
consumedChecks.add(checkType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this check type was set as passed for the last block.
|
||||
*
|
||||
@ -243,10 +328,44 @@ public class BlockInteractData extends ACheckData {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjustments, disregarding who/what cancelled the event.
|
||||
* Adjust to the results of a BlockInteractEvent - only the results, the
|
||||
* coordinates and action is not updated.
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
public void onCancelledBlockInteractEvent() {
|
||||
resetLastBlock();
|
||||
public void setPlayerInteractEventResolution(final PlayerInteractEvent event) {
|
||||
if (event.isCancelled()) {
|
||||
lastIsCancelled = true;
|
||||
lastAllowUseItem = event.useItemInHand() == Result.ALLOW;
|
||||
lastAllowUseBlock = event.useInteractedBlock() == Result.ALLOW;
|
||||
subsequentCancel ++;
|
||||
}
|
||||
else {
|
||||
lastIsCancelled = false;
|
||||
lastAllowUseItem = event.useItemInHand() != Result.DENY;
|
||||
lastAllowUseBlock = event.useInteractedBlock() != Result.DENY;
|
||||
subsequentCancel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust to the results of a BlockInteractEvent.
|
||||
*
|
||||
* @param isCancelled
|
||||
* @param allowUseItem
|
||||
* @param allowUseBlock
|
||||
*/
|
||||
public void setPlayerInteractEventResolution(final boolean isCancelled,
|
||||
final boolean allowUseItem, final boolean allowUseBlock) {
|
||||
this.lastIsCancelled = isCancelled;
|
||||
this.lastAllowUseBlock = allowUseBlock;
|
||||
this.lastAllowUseItem = allowUseItem;
|
||||
if (isCancelled) {
|
||||
resetLastBlock();
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ public class BlockInteractListener extends CheckListener {
|
||||
event.setUseInteractedBlock(Result.DENY);
|
||||
event.setUseItemInHand(Result.DENY);
|
||||
event.setCancelled(true);
|
||||
data.onCancelledBlockInteractEvent();
|
||||
data.resetLastBlock();
|
||||
if (cancelId >= 0) {
|
||||
counters.addPrimaryThread(cancelId, 1);
|
||||
}
|
||||
@ -117,10 +117,12 @@ public class BlockInteractListener extends CheckListener {
|
||||
// TODO: Re-arrange for interact spamming. (With ProtocolLib something else is in place as well.)
|
||||
final Action action = event.getAction();
|
||||
final Block block = event.getClickedBlock();
|
||||
final int previousLastTick = data.lastTick;
|
||||
final int previousLastTick = data.getLastTick();
|
||||
// TODO: Last block setting: better on monitor !?.
|
||||
boolean blockChecks = true;
|
||||
if (block == null) {
|
||||
data.resetLastBlock();
|
||||
blockChecks = false;
|
||||
}
|
||||
else {
|
||||
data.setLastBlock(block, action);
|
||||
@ -147,9 +149,14 @@ public class BlockInteractListener extends CheckListener {
|
||||
|
||||
boolean cancelled = false;
|
||||
if (event.isCancelled() && event.useInteractedBlock() != Result.ALLOW) {
|
||||
data.subsequentCancel ++;
|
||||
data.onCancelledBlockInteractEvent();
|
||||
return;
|
||||
if (event.useItemInHand() == Result.ALLOW) {
|
||||
blockChecks = false;
|
||||
// TODO: Some potential for plugin features...
|
||||
}
|
||||
else {
|
||||
// Can't do more than prevent all (could: set to prevent on highest, if desired).
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
final BlockInteractConfig cc = BlockInteractConfig.getConfig(player);
|
||||
@ -161,12 +168,13 @@ public class BlockInteractListener extends CheckListener {
|
||||
// TODO: Always run all checks, also for !isBlock ?
|
||||
|
||||
// Interaction speed.
|
||||
if (!cancelled && speed.isEnabled(player) && speed.check(player, data, cc)) {
|
||||
if (!cancelled && speed.isEnabled(player)
|
||||
&& speed.check(player, data, cc)) {
|
||||
cancelled = true;
|
||||
preventUseItem = true;
|
||||
}
|
||||
|
||||
if (block != null) {
|
||||
if (blockChecks) {
|
||||
// First the reach check.
|
||||
if (!cancelled && reach.isEnabled(player)
|
||||
&& reach.check(player, loc, block, flyingHandle, data, cc)) {
|
||||
@ -191,7 +199,6 @@ public class BlockInteractListener extends CheckListener {
|
||||
onCancelInteract(player, block, face, event, previousLastTick, preventUseItem, data, cc);
|
||||
}
|
||||
else {
|
||||
data.subsequentCancel = 0;
|
||||
if (flyingHandle.isFlyingQueueFetched()) {
|
||||
final int flyingIndex = flyingHandle.getFirstIndexWithContentIfFetched();
|
||||
final Integer cId;
|
||||
@ -256,19 +263,19 @@ public class BlockInteractListener extends CheckListener {
|
||||
}
|
||||
}
|
||||
}
|
||||
data.onCancelledBlockInteractEvent();
|
||||
data.subsequentCancel ++;
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = false, priority = EventPriority.MONITOR)
|
||||
public void onPlayerInteractMonitor(final PlayerInteractEvent event) {
|
||||
// Set event resolution.
|
||||
final Player player = event.getPlayer();
|
||||
final BlockInteractData data = BlockInteractData.getData(player);
|
||||
data.setPlayerInteractEventResolution(event);
|
||||
// Elytra boost.
|
||||
if (event.getAction() == Action.RIGHT_CLICK_AIR
|
||||
&& event.isCancelled() && event.useItemInHand() != Result.DENY) {
|
||||
final Player player = event.getPlayer();
|
||||
final ItemStack stack = Bridge1_9.getUsedItem(player, event);
|
||||
if (stack != null && BridgeMisc.maybeElytraBoost(player, stack.getType())) {
|
||||
final BlockInteractData data = BlockInteractData.getData(player);
|
||||
final int power = BridgeMisc.getFireworksPower(stack);
|
||||
final MovingData mData = MovingData.getData(player);
|
||||
final int ticks = Math.max((1 + power) * 20, 30);
|
||||
@ -304,7 +311,7 @@ public class BlockInteractListener extends CheckListener {
|
||||
final BlockInteractData data, final BlockInteractConfig cc) {
|
||||
final StringBuilder builder = new StringBuilder(512);
|
||||
// Rate limit.
|
||||
if (data.lastTick == previousLastTick && data.subsequentCancel > 0) {
|
||||
if (data.getLastTick() == previousLastTick && data.subsequentCancel > 0) {
|
||||
data.rateLimitSkip ++;
|
||||
return;
|
||||
}
|
||||
|
@ -40,28 +40,33 @@ public class Against extends Check {
|
||||
|
||||
public boolean check(final Player player, final Block block, final Material placedMat, final Block blockAgainst, final BlockPlaceData data, final BlockPlaceConfig cc) {
|
||||
boolean violation = false;
|
||||
// TODO: Make more precise (workarounds like WATER_LILY, general points).
|
||||
// TODO: Make more precise (workarounds like WATER_LILY, general points, such as action?).
|
||||
// Workaround for signs on cactus and similar.
|
||||
final BlockInteractData bdata = BlockInteractData.getData(player); // TODO: pass as argument.
|
||||
final Material againstType = blockAgainst.getType();
|
||||
if (BlockProperties.isAir(againstType)) {
|
||||
// Attempt to workaround blocks like cactus.
|
||||
final BlockInteractData bdata = BlockInteractData.getData(player);
|
||||
if (bdata.matchesLastBlock(TickTask.getTick(), blockAgainst)) {
|
||||
// Block was placed against something (e.g. cactus), allow it.
|
||||
// TODO: Later reset can conflict, though it makes sense to reset with placing blocks in general.
|
||||
// TODO: Reset on leaving the listener rather - why could it conflict?
|
||||
bdata.resetLastBlock();
|
||||
return false;
|
||||
}
|
||||
if (bdata.isConsumedCheck(this.type)) {
|
||||
violation = true;
|
||||
}
|
||||
if (BlockProperties.isLiquid(againstType)) {
|
||||
if ((placedMat != Material.WATER_LILY || !BlockProperties.isLiquid(block.getRelative(BlockFace.DOWN).getType())) && !player.hasPermission(Permissions.BLOCKPLACE_AGAINST_LIQUIDS)) {
|
||||
bdata.addConsumedCheck(this.type);
|
||||
if (!violation) {
|
||||
if (BlockProperties.isAir(againstType)) {
|
||||
// Attempt to workaround blocks like cactus.
|
||||
if (!bdata.getLastisCancelled() && bdata.matchesLastBlock(TickTask.getTick(), blockAgainst)) {
|
||||
// Block was placed against something (e.g. cactus), allow it.
|
||||
// TODO: Later reset can conflict, though it makes sense to reset with placing blocks in general.
|
||||
// TODO: Reset on leaving the listener rather - why could it conflict?
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (BlockProperties.isLiquid(againstType)) {
|
||||
if ((placedMat != Material.WATER_LILY || !BlockProperties.isLiquid(block.getRelative(BlockFace.DOWN).getType())) && !player.hasPermission(Permissions.BLOCKPLACE_AGAINST_LIQUIDS)) {
|
||||
violation = true;
|
||||
}
|
||||
}
|
||||
else if (BlockProperties.isAir(againstType) && !player.hasPermission(Permissions.BLOCKPLACE_AGAINST_AIR)) {
|
||||
violation = true;
|
||||
}
|
||||
}
|
||||
else if (BlockProperties.isAir(againstType) && !player.hasPermission(Permissions.BLOCKPLACE_AGAINST_AIR)) {
|
||||
violation = true;
|
||||
}
|
||||
// Handle violation and return.
|
||||
if (violation) {
|
||||
data.againstVL += 1.0;
|
||||
|
Loading…
Reference in New Issue
Block a user