Add block changes via redstone events for door/gate like blocks.

This is unfinished, but gives an outlook on what we may be able to do
with this.
* Double doors are not covered (upper/lower half are).
* Interaction with levers / directly with doors is not covered.
* Only doors + gates (not sure what else there is).
* More fine grained configurability is missing (+ only register
listeners if needed).
* Possibly other things.

Tracking BlockRedstone seems to be more promising than BlockPhysics, as
long as we don't have to inspect neighbour blocks to check for door like
blocks at all.
This commit is contained in:
asofold 2016-11-29 15:18:45 +01:00
parent 26b4c7a376
commit 3a6c0a4945

View File

@ -17,6 +17,7 @@ package fr.neatmonster.nocheatplus.compat.blocks;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@ -28,6 +29,7 @@ import java.util.Set;
import java.util.UUID;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
@ -36,7 +38,9 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPistonExtendEvent;
import org.bukkit.event.block.BlockPistonRetractEvent;
import org.bukkit.event.block.BlockRedstoneEvent;
import org.bukkit.material.Directional;
import org.bukkit.material.Door;
import org.bukkit.material.MaterialData;
import fr.neatmonster.nocheatplus.NCPAPIProvider;
@ -394,6 +398,8 @@ public class BlockChangeTracker {
private final BlockChangeTracker tracker;
private final boolean retractHasBlocks;
private boolean enabled = true;
private final Set<Material> redstoneMaterials = new HashSet<Material>();
public BlockChangeListener(final BlockChangeTracker tracker) {
this.tracker = tracker;
if (ReflectionUtil.getMethodNoArgs(BlockPistonRetractEvent.class, "getBlocks") == null) {
@ -403,6 +409,15 @@ public class BlockChangeTracker {
else {
retractHasBlocks = true;
}
// TODO: Make an access method to test this/such in BlockProperties!
for (Material material : Material.values()) {
if (material.isBlock()) {
final String name = material.name().toLowerCase();
if (name.indexOf("door") >= 0 || name.indexOf("gate") >= 0) {
redstoneMaterials.add(material);
}
}
}
}
public void setEnabled(boolean enabled) {
@ -488,6 +503,56 @@ public class BlockChangeTracker {
tracker.addPistonBlocks(pistonBlock.getRelative(direction.getOppositeFace()), direction, blocks);
}
// @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
// public void onBlockPhysics (final BlockPhysicsEvent event) {
// if (!enabled) {
// return;
// }
// // TODO: Fine grained enabling state (pistons, doors, other).
// final Block block = event.getBlock();
// if (block == null || !physicsMaterials.contains(block.getType())) {
// return;
// }
// // TODO: MaterialData -> Door, upper/lower half needed ?
// tracker.addBlocks(block); // TODO: Skip too fast changing states?
// DebugUtil.debug("BlockPhysics: " + block); // TODO: REMOVE
// }
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onBlockRedstone (final BlockRedstoneEvent event) {
if (!enabled) {
return;
}
// TODO: Fine grained enabling state (pistons, doors, other).
final Block block = event.getBlock();
// TODO: Abstract method for a block and a set of materials (redstone, interact, ...).
if (block == null || !redstoneMaterials.contains(block.getType())) {
return;
}
// TODO: MaterialData -> Door, upper/lower half.
final MaterialData materialData = block.getState().getData();
if (materialData instanceof Door) {
final Door door = (Door) materialData;
final Block otherBlock = block.getRelative(door.isTopHalf() ? BlockFace.DOWN : BlockFace.UP);
/*
* TODO: Double doors... detect those too? Is it still more
* efficient than using BlockPhysics with lazy delayed updating
* (TickListener...).
*/
if (redstoneMaterials.contains(otherBlock.getType())) {
tracker.addBlocks(block, otherBlock);
// DebugUtil.debug("BlockRedstone door: " + block + " / " + otherBlock); // TODO: REMOVE
return;
}
}
// Only the single block remains.
tracker.addBlocks(block);
// DebugUtil.debug("BlockRedstone: " + block); // TODO: REMOVE
}
// TODO: Falling blocks (physics?).
}
/** Change id/count, increasing with each entry added internally. */
@ -696,6 +761,7 @@ public class BlockChangeTracker {
}
}
}
// TODO: Skip too fast changing states?
entries.add(entry); // Add latest to the end always.
activityNode.count ++;
worldNode.size ++;