Avoid sign duplication due to a bug in CraftBukkit.

The cancelled BlockPlaceEvent will lead to an extra sign being dropped,
while the item in hand stays. Odd enough, the cactus is removed before
the BlockPlaceEvent - need to check if a ticket exists for CraftBukkit
already...
This commit is contained in:
asofold 2014-02-17 01:58:44 +01:00
parent 3361280cc7
commit 9528b15f55
3 changed files with 57 additions and 6 deletions

View File

@ -3,11 +3,15 @@ package fr.neatmonster.nocheatplus.checks.blockinteract;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.block.Action;
import fr.neatmonster.nocheatplus.checks.access.ACheckData; import fr.neatmonster.nocheatplus.checks.access.ACheckData;
import fr.neatmonster.nocheatplus.checks.access.CheckDataFactory; import fr.neatmonster.nocheatplus.checks.access.CheckDataFactory;
import fr.neatmonster.nocheatplus.checks.access.ICheckData; import fr.neatmonster.nocheatplus.checks.access.ICheckData;
import fr.neatmonster.nocheatplus.utilities.TickTask;
/* /*
* M#"""""""'M dP dP M""M dP dP * M#"""""""'M dP dP M""M dP dP
@ -79,6 +83,15 @@ public class BlockInteractData extends ACheckData {
public double speedVL = 0; public double speedVL = 0;
public double visibleVL = 0; public double visibleVL = 0;
// General data
// Last block interacted with
public int lastX = Integer.MAX_VALUE;
public int lastY, lastZ;
/** null for air */
public Material lastType = null;
public long lastTick;
public Action lastAction = null;
// Data of the reach check. // Data of the reach check.
public double reachDistance; public double reachDistance;
@ -87,4 +100,27 @@ public class BlockInteractData extends ACheckData {
/** Number of interactions since last reset-time. */ /** Number of interactions since last reset-time. */
public int speedCount = 0; public int speedCount = 0;
/**
* Last interacted block.
* @param block
*/
public void setLastBlock(Block block, Action action) {
lastX = block.getX();
lastY = block.getY();
lastZ = block.getZ();
lastType = block.getType();
if (lastType == Material.AIR) {
lastType = null;
}
lastTick = TickTask.getTick();
lastAction = action;
}
public void resetLastBlock() {
lastTick = 0;
lastAction = null;
lastX = Integer.MAX_VALUE;
lastType = null;
}
} }

View File

@ -83,7 +83,8 @@ public class BlockInteractListener extends CheckListener {
return; return;
} }
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final BlockInteractData data = BlockInteractData.getData(player);
data.setLastBlock(block, action);
switch(action){ switch(action){
case LEFT_CLICK_BLOCK: case LEFT_CLICK_BLOCK:
break; break;
@ -106,9 +107,7 @@ public class BlockInteractListener extends CheckListener {
return; return;
} }
final BlockInteractData data = BlockInteractData.getData(player);
final BlockInteractConfig cc = BlockInteractConfig.getConfig(player); final BlockInteractConfig cc = BlockInteractConfig.getConfig(player);
boolean cancelled = false; boolean cancelled = false;
final BlockFace face = event.getBlockFace(); final BlockFace face = event.getBlockFace();

View File

@ -9,7 +9,11 @@ import fr.neatmonster.nocheatplus.actions.ParameterName;
import fr.neatmonster.nocheatplus.checks.Check; import fr.neatmonster.nocheatplus.checks.Check;
import fr.neatmonster.nocheatplus.checks.CheckType; import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.ViolationData; import fr.neatmonster.nocheatplus.checks.ViolationData;
import fr.neatmonster.nocheatplus.checks.blockbreak.BlockBreakData;
import fr.neatmonster.nocheatplus.checks.blockinteract.BlockInteractData;
import fr.neatmonster.nocheatplus.utilities.BlockProperties; import fr.neatmonster.nocheatplus.utilities.BlockProperties;
import fr.neatmonster.nocheatplus.utilities.TickTask;
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
/** /**
* Check if the placing is legitimate in terms of surrounding materials. * Check if the placing is legitimate in terms of surrounding materials.
* @author mc_dev * @author mc_dev
@ -21,12 +25,24 @@ public class Against extends Check {
super(CheckType.BLOCKPLACE_AGAINST); super(CheckType.BLOCKPLACE_AGAINST);
} }
public boolean check(final Player player, final Block block, final Material mat, final Block blockAgainst, final BlockPlaceData data, final BlockPlaceConfig cc) { public boolean check(final Player player, final Block block, final Material placedMat, final Block blockAgainst, final BlockPlaceData data, final BlockPlaceConfig cc) {
boolean violation = false; boolean violation = false;
// TODO: Make more precise (workarounds like WATER_LILY, general points). // TODO: Make more precise (workarounds like WATER_LILY, general points).
// Workaround for signs on cactus and similar.
final int againstId = blockAgainst.getTypeId(); final int againstId = blockAgainst.getTypeId();
if (againstId == Material.AIR.getId()) {
// Attempt to workaround blocks like cactus.
final BlockInteractData bdata = BlockInteractData.getData(player);
if (bdata.lastType != null && bdata.lastX != Integer.MAX_VALUE && TickTask.getTick() == bdata.lastTick && TrigUtil.manhattan(bdata.lastX, bdata.lastY, bdata.lastZ, blockAgainst) == 0) {
// (Wide screen.)
// 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.
bdata.resetLastBlock();
return false;
}
}
if (BlockProperties.isLiquid(againstId)) { if (BlockProperties.isLiquid(againstId)) {
if ((mat != Material.WATER_LILY || !BlockProperties.isLiquid(block.getRelative(BlockFace.DOWN).getTypeId()))) { if ((placedMat != Material.WATER_LILY || !BlockProperties.isLiquid(block.getRelative(BlockFace.DOWN).getTypeId()))) {
violation = true; violation = true;
} }
} }
@ -37,7 +53,7 @@ public class Against extends Check {
if (violation) { if (violation) {
data.againstVL += 1.0; data.againstVL += 1.0;
final ViolationData vd = new ViolationData(this, player, data.againstVL, 1, cc.againstActions); final ViolationData vd = new ViolationData(this, player, data.againstVL, 1, cc.againstActions);
vd.setParameter(ParameterName.BLOCK_ID, Integer.toString(mat.getId())); vd.setParameter(ParameterName.BLOCK_ID, Integer.toString(placedMat.getId()));
return executeActions(vd); return executeActions(vd);
} else { } else {
data.againstVL *= 100; // Assume one false positive every 100 blocks. data.againstVL *= 100; // Assume one false positive every 100 blocks.