forked from LogBlock/LogBlock
Log falling scaffoldings
This commit is contained in:
@@ -152,6 +152,9 @@ public class LogBlock extends JavaPlugin {
|
|||||||
if (isLogging(Logging.SNOWFADE)) {
|
if (isLogging(Logging.SNOWFADE)) {
|
||||||
pm.registerEvents(new SnowFadeLogging(this), this);
|
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)) {
|
if (isLogging(Logging.CREEPEREXPLOSION) || isLogging(Logging.TNTEXPLOSION) || isLogging(Logging.GHASTFIREBALLEXPLOSION) || isLogging(Logging.ENDERDRAGON) || isLogging(Logging.MISCEXPLOSION)) {
|
||||||
pm.registerEvents(new ExplosionLogging(this), this);
|
pm.registerEvents(new ExplosionLogging(this), this);
|
||||||
}
|
}
|
||||||
|
@@ -43,7 +43,8 @@ public enum Logging {
|
|||||||
BEDEXPLOSION(true),
|
BEDEXPLOSION(true),
|
||||||
DRAGONEGGTELEPORT(true),
|
DRAGONEGGTELEPORT(true),
|
||||||
DAYLIGHTDETECTORINTERACT,
|
DAYLIGHTDETECTORINTERACT,
|
||||||
LECTERNBOOKCHANGE(true);
|
LECTERNBOOKCHANGE(true),
|
||||||
|
SCAFFOLDING(true);
|
||||||
|
|
||||||
public static final int length = Logging.values().length;
|
public static final int length = Logging.values().length;
|
||||||
private final boolean defaultEnabled;
|
private final boolean defaultEnabled;
|
||||||
|
@@ -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<BlockFace> NEIGHBOURS_SIDES_AND_UP = EnumSet.of(BlockFace.UP, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST);
|
||||||
|
private final static EnumSet<BlockFace> NEIGHBOURS_SIDES_AND_BELOW = EnumSet.of(BlockFace.DOWN, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST);
|
||||||
|
|
||||||
|
private final ArrayDeque<ScaffoldingBreaker> scaffoldingBreakersList = new ArrayDeque<>();
|
||||||
|
private final HashMap<Location, ScaffoldingBreaker> scaffoldingBreakersByLocation = new HashMap<>();
|
||||||
|
private final HashMap<Location, Player> 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<Block> front = new ArrayDeque<>();
|
||||||
|
HashSet<Block> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user