From 7fb1da6dc5354be181773a7780ea27a8cf92c5e0 Mon Sep 17 00:00:00 2001 From: asofold Date: Sat, 19 Nov 2016 14:26:03 +0100 Subject: [PATCH] FORMAT +comments +fibbity. --- .../compat/blocks/BlockChangeTracker.java | 61 ++++++++++++++++--- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/blocks/BlockChangeTracker.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/blocks/BlockChangeTracker.java index 62b06609..5d497aa5 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/blocks/BlockChangeTracker.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/blocks/BlockChangeTracker.java @@ -44,7 +44,21 @@ import fr.neatmonster.nocheatplus.utilities.ds.map.LinkedCoordHashMap; import fr.neatmonster.nocheatplus.utilities.ds.map.LinkedCoordHashMap.MoveOrder; import fr.neatmonster.nocheatplus.utilities.map.BlockProperties; - +/** + * Keep track of block changes, to allow mitigation of false positives. Think of + * pistons, falling blocks, digging, block placing, explosions, vegetables + * growing, all sorts of doors, plugins changing blocks and so on. This is + * needed not only for elevator and parkour designs, but also to prevent piston + * based trap designs, which could lead to players violating moving checks. + *
+ * In general we assume that at the time of adding a block change entry, the + * block has not yet been changed, so we access the "old state" at that point of + * time. If needed, a method allowing to specify the old state explicitly will + * be added. + * + * @author asofold + * + */ public class BlockChangeTracker { /** These blocks certainly can't be pushed nor pulled. */ public static long F_MOVABLE_IGNORE = BlockProperties.F_LIQUID; @@ -88,8 +102,19 @@ public class BlockChangeTracker { } public static class WorldNode { + // TODO: private + access methods. + /* + * TODO: A coarse rectangle or cuboid based approach, Allowing fast + * exclusion check for moves (needs access methods for everything then). + * Could merge with the per-block map, similar to WorldGuard. + */ + /* + * TODO: Consider a filter mechanism for player activity by chunks or + * chunk sections (some margin, only add if activity, let expire by + * tick). Only add blocks if players could reach the location. + */ + public final LinkedCoordHashMap> blocks = new LinkedCoordHashMap>(); - // TODO: Filter mechanism for player activity by chunks or chunk sections (some margin, only add if activity, let expire by tick). /** Tick of last change. */ public int lastChangeTick = 0; @@ -106,6 +131,7 @@ public class BlockChangeTracker { blocks.clear(); size = 0; } + } /** @@ -216,7 +242,8 @@ public class BlockChangeTracker { if (ReflectionUtil.getMethodNoArgs(BlockPistonRetractEvent.class, "getBlocks") == null) { retractHasBlocks = false; NCPAPIProvider.getNoCheatPlusAPI().getLogManager().info(Streams.STATUS, "Assume legacy piston behavior."); - } else { + } + else { retractHasBlocks = true; } } @@ -284,13 +311,15 @@ public class BlockChangeTracker { final Location retLoc = event.getRetractLocation(); if (retLoc == null) { blocks = null; - } else { + } + else { final Block retBlock = retLoc.getBlock(); final long flags = BlockProperties.getBlockFlags(retBlock.getType()); if ((flags & F_MOVABLE_IGNORE) == 0L && (flags & F_MOVABLE) != 0L) { blocks = new ArrayList(1); blocks.add(retBlock); - } else { + } + else { blocks = null; } } @@ -320,7 +349,10 @@ public class BlockChangeTracker { /** Use to avoid duplicate entries with pistons. Always empty after processing. */ private final Set processBlocks = new HashSet(); - // TODO: Consider tracking regions of player activity (chunk sections, with a margin around the player) and filter. + /* + * TODO: Consider tracking regions of player activity (chunk sections, with + * a margin around the player) and filter. + */ /** * Process the data, as given by a BlockPistonExtendEvent or @@ -334,6 +366,11 @@ public class BlockChangeTracker { * direction (!) are added. */ public void addPistonBlocks(final Block pistonBlock, final BlockFace blockFace, final List movedBlocks) { + /* + * TODO: Might need a configuration for if to also add block + * state/properties right here (or if to wait for a multi block change + * event or what not). + */ final int tick = TickTask.getTick(); final UUID worldId = pistonBlock.getWorld().getUID(); WorldNode worldNode = worldMap.get(worldId); @@ -394,7 +431,8 @@ public class BlockChangeTracker { if (entries == null) { entries = new LinkedList(); worldNode.blocks.put(x, y, z, entries, MoveOrder.END); // Add to end. - } else { + } + else { // Lazy expiration check for this block. if (!entries.isEmpty() && entries.getFirst().tick < tick - expirationAgeTicks) { worldNode.size -= expireEntries(tick - expirationAgeTicks, entries); @@ -413,7 +451,8 @@ public class BlockChangeTracker { if (it.next().tick < olderThanTick) { it.remove(); removed ++; - } else { + } + else { return removed; } } @@ -433,7 +472,8 @@ public class BlockChangeTracker { if (worldNode.lastChangeTick < olderThanTick) { worldNode.clear(); it.remove(); - } else { + } + else { // Check for expiration of individual blocks. if (worldNode.size < worldNodeSkipSize) { continue; @@ -527,7 +567,8 @@ public class BlockChangeTracker { if (entry.tick < olderThanTick) { //DebugUtil.debug("Lazy expire: " + x + "," + y + "," + z + " " + entry.id); it.remove(); - } else { + } + else { if (ref.canUpdateWith(entry) && (direction == null || entry.direction == direction)) { return entry; }