From 8214e7d177bbc7faa63c7bb0b09cd77b1f52663e Mon Sep 17 00:00:00 2001 From: Brokkonaut Date: Sun, 24 Nov 2019 05:46:51 +0100 Subject: [PATCH 1/2] Log falling scaffoldings --- .../java/de/diddiz/LogBlock/LogBlock.java | 3 + src/main/java/de/diddiz/LogBlock/Logging.java | 3 +- .../listeners/ScaffoldingLogging.java | 170 ++++++++++++++++++ 3 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 src/main/java/de/diddiz/LogBlock/listeners/ScaffoldingLogging.java diff --git a/src/main/java/de/diddiz/LogBlock/LogBlock.java b/src/main/java/de/diddiz/LogBlock/LogBlock.java index 91acee3..cb7706b 100644 --- a/src/main/java/de/diddiz/LogBlock/LogBlock.java +++ b/src/main/java/de/diddiz/LogBlock/LogBlock.java @@ -152,6 +152,9 @@ public class LogBlock extends JavaPlugin { if (isLogging(Logging.SNOWFADE)) { pm.registerEvents(new SnowFadeLogging(this), this); } + if (isLogging(Logging.SCAFFOLDING)) { + pm.registerEvents(new ScaffoldingLogging(this), this); + } if (isLogging(Logging.CREEPEREXPLOSION) || isLogging(Logging.TNTEXPLOSION) || isLogging(Logging.GHASTFIREBALLEXPLOSION) || isLogging(Logging.ENDERDRAGON) || isLogging(Logging.MISCEXPLOSION)) { pm.registerEvents(new ExplosionLogging(this), this); } diff --git a/src/main/java/de/diddiz/LogBlock/Logging.java b/src/main/java/de/diddiz/LogBlock/Logging.java index 4357201..40a4e16 100644 --- a/src/main/java/de/diddiz/LogBlock/Logging.java +++ b/src/main/java/de/diddiz/LogBlock/Logging.java @@ -43,7 +43,8 @@ public enum Logging { BEDEXPLOSION(true), DRAGONEGGTELEPORT(true), DAYLIGHTDETECTORINTERACT, - LECTERNBOOKCHANGE(true); + LECTERNBOOKCHANGE(true), + SCAFFOLDING(true); public static final int length = Logging.values().length; private final boolean defaultEnabled; diff --git a/src/main/java/de/diddiz/LogBlock/listeners/ScaffoldingLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/ScaffoldingLogging.java new file mode 100644 index 0000000..ba44e8f --- /dev/null +++ b/src/main/java/de/diddiz/LogBlock/listeners/ScaffoldingLogging.java @@ -0,0 +1,170 @@ +package de.diddiz.LogBlock.listeners; + +import de.diddiz.LogBlock.Actor; +import de.diddiz.LogBlock.LogBlock; +import de.diddiz.LogBlock.Logging; +import java.util.ArrayDeque; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockFadeEvent; +import org.bukkit.event.block.BlockPlaceEvent; + +import static de.diddiz.LogBlock.config.Config.isLogging; + +public class ScaffoldingLogging extends LoggingListener { + private final static long MAX_SCAFFOLDING_LOG_TIME_MS = 2000; + private final static EnumSet NEIGHBOURS_SIDES_AND_UP = EnumSet.of(BlockFace.UP, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST); + private final static EnumSet NEIGHBOURS_SIDES_AND_BELOW = EnumSet.of(BlockFace.DOWN, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST); + + private final ArrayDeque scaffoldingBreakersList = new ArrayDeque<>(); + private final HashMap scaffoldingBreakersByLocation = new HashMap<>(); + private final HashMap scaffoldingPlacersByLocation = new HashMap<>(); + + public ScaffoldingLogging(LogBlock lb) { + super(lb); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBlockFade(BlockFadeEvent event) { + Block block = event.getBlock(); + if (isLogging(block.getWorld(), Logging.SCAFFOLDING)) { + final Material type = block.getType(); + if (type == Material.SCAFFOLDING) { + Player placer = scaffoldingPlacersByLocation.get(block.getLocation()); + cleanupScaffoldingBreakers(); + if (placer != null) { + consumer.queueBlockReplace(Actor.actorFromEntity(placer), block.getState(), event.getNewState()); + return; + } + Player breaker = getScaffoldingBreaker(block); + if (breaker != null) { + for (BlockFace dir : NEIGHBOURS_SIDES_AND_UP) { + Block otherBlock = block.getRelative(dir); + if (otherBlock.getType() == Material.SCAFFOLDING) { + addScaffoldingBreaker(breaker, otherBlock); + } + } + } + consumer.queueBlockReplace(breaker == null ? new Actor("ScaffoldingFall") : Actor.actorFromEntity(breaker), block.getState(), event.getNewState()); + } + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBlockBreak(BlockBreakEvent event) { + Block block = event.getBlock(); + if (isLogging(block.getWorld(), Logging.SCAFFOLDING)) { + cleanupScaffoldingBreakers(); + Block otherBlock; + if (block.getType() == Material.SCAFFOLDING) { + for (BlockFace dir : NEIGHBOURS_SIDES_AND_UP) { + otherBlock = block.getRelative(dir); + if (otherBlock.getType() == Material.SCAFFOLDING) { + addScaffoldingBreaker(event.getPlayer(), otherBlock); + } + } + } else if ((otherBlock = block.getRelative(BlockFace.UP)).getType() == Material.SCAFFOLDING) { + addScaffoldingBreaker(event.getPlayer(), otherBlock); + } + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBlockPlace(BlockPlaceEvent event) { + Block block = event.getBlock(); + if (isLogging(block.getWorld(), Logging.SCAFFOLDING)) { + cleanupScaffoldingBreakers(); + if (block.getType() == Material.SCAFFOLDING) { + scaffoldingPlacersByLocation.put(block.getLocation(), event.getPlayer()); + } + } + } + + private void addScaffoldingBreaker(Player player, Block block) { + ScaffoldingBreaker breaker = new ScaffoldingBreaker(player, block.getLocation()); + scaffoldingBreakersList.addLast(breaker); + scaffoldingBreakersByLocation.put(breaker.getLocation(), breaker); + + } + + private void cleanupScaffoldingBreakers() { + if (!scaffoldingPlacersByLocation.isEmpty()) { + scaffoldingPlacersByLocation.clear(); + } + if (!scaffoldingBreakersList.isEmpty()) { + long time = System.currentTimeMillis() - MAX_SCAFFOLDING_LOG_TIME_MS; + while (!scaffoldingBreakersList.isEmpty() && scaffoldingBreakersList.getFirst().getTime() < time) { + ScaffoldingBreaker breaker = scaffoldingBreakersList.removeFirst(); + scaffoldingBreakersByLocation.remove(breaker.getLocation(), breaker); + } + } + } + + private Player getScaffoldingBreaker(Block block) { + if (scaffoldingBreakersList.isEmpty()) { + return null; + } + + ScaffoldingBreaker breaker = scaffoldingBreakersByLocation.get(block.getLocation()); + if (breaker != null) { + return breaker.getBreaker(); + } + + // Search all connected scaffoldings + ArrayDeque front = new ArrayDeque<>(); + HashSet frontAndDone = new HashSet<>(); + front.addLast(block); + frontAndDone.add(block); + while (!front.isEmpty()) { + Block current = front.removeFirst(); + Location loc = current.getLocation(); + + breaker = scaffoldingBreakersByLocation.get(loc); + if (breaker != null) { + return breaker.getBreaker(); + } + + for (BlockFace dir : NEIGHBOURS_SIDES_AND_BELOW) { + Block otherBlock = current.getRelative(dir); + if (!frontAndDone.contains(otherBlock) && otherBlock.getType() == Material.SCAFFOLDING) { + front.addLast(otherBlock); + frontAndDone.add(otherBlock); + } + } + } + return null; + } + + class ScaffoldingBreaker { + protected final Player breaker; + protected final long time; + protected final Location location; + + public ScaffoldingBreaker(Player breaker, Location location) { + this.breaker = breaker; + this.location = location; + this.time = System.currentTimeMillis(); + } + + public Player getBreaker() { + return breaker; + } + + public Location getLocation() { + return location; + } + + public long getTime() { + return time; + } + } +} From 59d0794c3daa8e884db405931a0931a125b94a35 Mon Sep 17 00:00:00 2001 From: Brokkonaut Date: Sun, 24 Nov 2019 06:16:07 +0100 Subject: [PATCH 2/2] Improve scaffolding logging with fallable blocks - Log fallable blocks above scaffoldings - Log scaffolding breaking because blocks below are falling down --- .../java/de/diddiz/LogBlock/Consumer.java | 4 ++ .../java/de/diddiz/LogBlock/LogBlock.java | 7 ++- .../listeners/ScaffoldingLogging.java | 55 ++++++++++--------- src/main/java/de/diddiz/util/LoggingUtil.java | 4 ++ 4 files changed, 42 insertions(+), 28 deletions(-) diff --git a/src/main/java/de/diddiz/LogBlock/Consumer.java b/src/main/java/de/diddiz/LogBlock/Consumer.java index c9e4551..4be454a 100644 --- a/src/main/java/de/diddiz/LogBlock/Consumer.java +++ b/src/main/java/de/diddiz/LogBlock/Consumer.java @@ -78,6 +78,10 @@ public class Consumer extends Thread { setName("Logblock-Consumer"); } + public LogBlock getLogblock() { + return logblock; + } + /** * Logs any block change. Don't try to combine broken and placed blocks. Queue two block changes or use the queueBLockReplace methods. * diff --git a/src/main/java/de/diddiz/LogBlock/LogBlock.java b/src/main/java/de/diddiz/LogBlock/LogBlock.java index cb7706b..6078aa1 100644 --- a/src/main/java/de/diddiz/LogBlock/LogBlock.java +++ b/src/main/java/de/diddiz/LogBlock/LogBlock.java @@ -36,6 +36,7 @@ public class LogBlock extends JavaPlugin { private CommandsHandler commandsHandler; private boolean noDb = false, connected = true; private PlayerInfoLogging playerInfoLogging; + private ScaffoldingLogging scaffoldingLogging; private Questioner questioner; private volatile boolean isCompletelyEnabled; @@ -153,7 +154,7 @@ public class LogBlock extends JavaPlugin { pm.registerEvents(new SnowFadeLogging(this), this); } if (isLogging(Logging.SCAFFOLDING)) { - pm.registerEvents(new ScaffoldingLogging(this), this); + pm.registerEvents(scaffoldingLogging = new ScaffoldingLogging(this), this); } if (isLogging(Logging.CREEPEREXPLOSION) || isLogging(Logging.TNTEXPLOSION) || isLogging(Logging.GHASTFIREBALLEXPLOSION) || isLogging(Logging.ENDERDRAGON) || isLogging(Logging.MISCEXPLOSION)) { pm.registerEvents(new ExplosionLogging(this), this); @@ -337,4 +338,8 @@ public class LogBlock extends JavaPlugin { public Questioner getQuestioner() { return questioner; } + + public ScaffoldingLogging getScaffoldingLogging() { + return scaffoldingLogging; + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/ScaffoldingLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/ScaffoldingLogging.java index ba44e8f..cf7e1f3 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/ScaffoldingLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/ScaffoldingLogging.java @@ -11,7 +11,6 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; -import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.block.BlockBreakEvent; @@ -19,6 +18,7 @@ import org.bukkit.event.block.BlockFadeEvent; import org.bukkit.event.block.BlockPlaceEvent; import static de.diddiz.LogBlock.config.Config.isLogging; +import static de.diddiz.util.LoggingUtil.smartLogFallables; public class ScaffoldingLogging extends LoggingListener { private final static long MAX_SCAFFOLDING_LOG_TIME_MS = 2000; @@ -27,7 +27,7 @@ public class ScaffoldingLogging extends LoggingListener { private final ArrayDeque scaffoldingBreakersList = new ArrayDeque<>(); private final HashMap scaffoldingBreakersByLocation = new HashMap<>(); - private final HashMap scaffoldingPlacersByLocation = new HashMap<>(); + private final HashMap scaffoldingPlacersByLocation = new HashMap<>(); public ScaffoldingLogging(LogBlock lb) { super(lb); @@ -39,22 +39,23 @@ public class ScaffoldingLogging extends LoggingListener { if (isLogging(block.getWorld(), Logging.SCAFFOLDING)) { final Material type = block.getType(); if (type == Material.SCAFFOLDING) { - Player placer = scaffoldingPlacersByLocation.get(block.getLocation()); + Actor actor = scaffoldingPlacersByLocation.get(block.getLocation()); // get placer before cleanupScaffoldingBreakers cleanupScaffoldingBreakers(); - if (placer != null) { - consumer.queueBlockReplace(Actor.actorFromEntity(placer), block.getState(), event.getNewState()); - return; - } - Player breaker = getScaffoldingBreaker(block); - if (breaker != null) { - for (BlockFace dir : NEIGHBOURS_SIDES_AND_UP) { - Block otherBlock = block.getRelative(dir); - if (otherBlock.getType() == Material.SCAFFOLDING) { - addScaffoldingBreaker(breaker, otherBlock); + if (actor == null) { + actor = getScaffoldingBreaker(block); + if (actor != null) { + for (BlockFace dir : NEIGHBOURS_SIDES_AND_UP) { + Block otherBlock = block.getRelative(dir); + if (otherBlock.getType() == Material.SCAFFOLDING) { + addScaffoldingBreaker(actor, otherBlock); + } } + } else { + actor = new Actor("ScaffoldingFall"); } } - consumer.queueBlockReplace(breaker == null ? new Actor("ScaffoldingFall") : Actor.actorFromEntity(breaker), block.getState(), event.getNewState()); + consumer.queueBlockReplace(actor, block.getState(), event.getNewState()); + smartLogFallables(consumer, actor, block); } } } @@ -69,11 +70,11 @@ public class ScaffoldingLogging extends LoggingListener { for (BlockFace dir : NEIGHBOURS_SIDES_AND_UP) { otherBlock = block.getRelative(dir); if (otherBlock.getType() == Material.SCAFFOLDING) { - addScaffoldingBreaker(event.getPlayer(), otherBlock); + addScaffoldingBreaker(Actor.actorFromEntity(event.getPlayer()), otherBlock); } } } else if ((otherBlock = block.getRelative(BlockFace.UP)).getType() == Material.SCAFFOLDING) { - addScaffoldingBreaker(event.getPlayer(), otherBlock); + addScaffoldingBreaker(Actor.actorFromEntity(event.getPlayer()), otherBlock); } } } @@ -84,13 +85,13 @@ public class ScaffoldingLogging extends LoggingListener { if (isLogging(block.getWorld(), Logging.SCAFFOLDING)) { cleanupScaffoldingBreakers(); if (block.getType() == Material.SCAFFOLDING) { - scaffoldingPlacersByLocation.put(block.getLocation(), event.getPlayer()); + scaffoldingPlacersByLocation.put(block.getLocation(), Actor.actorFromEntity(event.getPlayer())); } } } - private void addScaffoldingBreaker(Player player, Block block) { - ScaffoldingBreaker breaker = new ScaffoldingBreaker(player, block.getLocation()); + public void addScaffoldingBreaker(Actor actor, Block block) { + ScaffoldingBreaker breaker = new ScaffoldingBreaker(actor, block.getLocation()); scaffoldingBreakersList.addLast(breaker); scaffoldingBreakersByLocation.put(breaker.getLocation(), breaker); @@ -109,14 +110,14 @@ public class ScaffoldingLogging extends LoggingListener { } } - private Player getScaffoldingBreaker(Block block) { + private Actor getScaffoldingBreaker(Block block) { if (scaffoldingBreakersList.isEmpty()) { return null; } ScaffoldingBreaker breaker = scaffoldingBreakersByLocation.get(block.getLocation()); if (breaker != null) { - return breaker.getBreaker(); + return breaker.getActor(); } // Search all connected scaffoldings @@ -130,7 +131,7 @@ public class ScaffoldingLogging extends LoggingListener { breaker = scaffoldingBreakersByLocation.get(loc); if (breaker != null) { - return breaker.getBreaker(); + return breaker.getActor(); } for (BlockFace dir : NEIGHBOURS_SIDES_AND_BELOW) { @@ -145,18 +146,18 @@ public class ScaffoldingLogging extends LoggingListener { } class ScaffoldingBreaker { - protected final Player breaker; + protected final Actor actor; protected final long time; protected final Location location; - public ScaffoldingBreaker(Player breaker, Location location) { - this.breaker = breaker; + public ScaffoldingBreaker(Actor actor, Location location) { + this.actor = actor; this.location = location; this.time = System.currentTimeMillis(); } - public Player getBreaker() { - return breaker; + public Actor getActor() { + return actor; } public Location getLocation() { diff --git a/src/main/java/de/diddiz/util/LoggingUtil.java b/src/main/java/de/diddiz/util/LoggingUtil.java index 97bb569..477a484 100644 --- a/src/main/java/de/diddiz/util/LoggingUtil.java +++ b/src/main/java/de/diddiz/util/LoggingUtil.java @@ -2,6 +2,7 @@ package de.diddiz.util; import de.diddiz.LogBlock.Actor; import de.diddiz.LogBlock.Consumer; +import de.diddiz.LogBlock.Logging; import de.diddiz.LogBlock.config.WorldConfig; import org.bukkit.Location; import org.bukkit.Material; @@ -98,6 +99,9 @@ public class LoggingUtil { } checkBlock = checkBlock.getRelative(BlockFace.UP); } + if (wcfg.isLogging(Logging.SCAFFOLDING) && checkBlock.getType() == Material.SCAFFOLDING && consumer.getLogblock().getScaffoldingLogging() != null) { + consumer.getLogblock().getScaffoldingLogging().addScaffoldingBreaker(actor, checkBlock); + } } public static void smartLogBlockBreak(Consumer consumer, Actor actor, Block origin) {