From 92b1a2f394d414d68bf030e7c514463f9beee482 Mon Sep 17 00:00:00 2001 From: Brokkonaut Date: Wed, 1 Aug 2018 20:01:51 +0200 Subject: [PATCH] Improve logging of fallable blocks Also in this commit: Bukkit's Tags are just broken --- .../LogBlock/listeners/BlockPlaceLogging.java | 67 ++------ src/main/java/de/diddiz/util/BukkitUtils.java | 153 ++++++++++++++---- src/main/java/de/diddiz/util/LoggingUtil.java | 38 ++++- 3 files changed, 172 insertions(+), 86 deletions(-) diff --git a/src/main/java/de/diddiz/LogBlock/listeners/BlockPlaceLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/BlockPlaceLogging.java index f48aff8..a8a832a 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/BlockPlaceLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/BlockPlaceLogging.java @@ -3,20 +3,19 @@ package de.diddiz.LogBlock.listeners; import de.diddiz.LogBlock.Actor; import de.diddiz.LogBlock.LogBlock; import de.diddiz.LogBlock.Logging; -import de.diddiz.LogBlock.config.WorldConfig; -import de.diddiz.util.BukkitUtils; +import de.diddiz.LogBlock.config.Config; +import de.diddiz.util.LoggingUtil; import org.bukkit.Bukkit; -import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.player.PlayerBucketEmptyEvent; +import org.bukkit.inventory.meta.BlockStateMeta; +import org.bukkit.inventory.meta.ItemMeta; -import static de.diddiz.LogBlock.config.Config.getWorldConfig; import static de.diddiz.LogBlock.config.Config.isLogging; public class BlockPlaceLogging extends LoggingListener { @@ -26,62 +25,20 @@ public class BlockPlaceLogging extends LoggingListener { @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onBlockPlace(BlockPlaceEvent event) { - final WorldConfig wcfg = getWorldConfig(event.getBlock().getWorld()); - if (wcfg != null && wcfg.isLogging(Logging.BLOCKPLACE)) { - final Material type = event.getBlock().getType(); + if (Config.isLogging(event.getBlock().getWorld(), Logging.BLOCKPLACE)) { final BlockState before = event.getBlockReplacedState(); final BlockState after = event.getBlockPlaced().getState(); final Actor actor = Actor.actorFromEntity(event.getPlayer()); - //Handle falling blocks - if (type.hasGravity()) { - - // Catch placed blocks overwriting something - if (!BukkitUtils.isEmpty(before.getType())) { - consumer.queueBlockBreak(actor, before); + // Sign logging is handled elsewhere + if (Config.isLogging(after.getWorld(), Logging.SIGNTEXT) && (after.getType() == Material.SIGN || after.getType() == Material.WALL_SIGN)) { + ItemMeta inHandMeta = event.getItemInHand() != null ? event.getItemInHand().getItemMeta() : null; + if (!(inHandMeta instanceof BlockStateMeta) || !((BlockStateMeta) inHandMeta).hasBlockState()) { + return; } - - Location loc = event.getBlock().getLocation(); - int x = loc.getBlockX(); - int y = loc.getBlockY(); - int z = loc.getBlockZ(); - // Blocks only fall if they have a chance to start a velocity - if (BukkitUtils.isEmpty(event.getBlock().getRelative(BlockFace.DOWN).getType())) { - while (y > 0 && BukkitUtils.canFall(loc.getWorld(), x, (y - 1), z)) { - y--; - } - } - // If y is 0 then the sand block fell out of the world :( - if (y != 0) { - Location finalLoc = new Location(loc.getWorld(), x, y, z); - // Run this check to avoid false positives - if (!BukkitUtils.getFallingEntityKillers().contains(finalLoc.getBlock().getType())) { - if (BukkitUtils.isEmpty(finalLoc.getBlock().getType()) || finalLoc.equals(event.getBlock().getLocation())) { - consumer.queueBlockPlace(actor, finalLoc, event.getBlock().getBlockData()); - } else { - consumer.queueBlockReplace(actor, finalLoc, finalLoc.getBlock().getBlockData(), event.getBlock().getBlockData()); - } - } - } - return; } - - //Sign logging is handled elsewhere - if (wcfg.isLogging(Logging.SIGNTEXT) && (type == Material.SIGN || type == Material.WALL_SIGN)) { - return; - } - - //Delay queuing by one tick to allow data to be updated - LogBlock.getInstance().getServer().getScheduler().scheduleSyncDelayedTask(LogBlock.getInstance(), new Runnable() { - @Override - public void run() { - if (BukkitUtils.isEmpty(before.getType())) { - consumer.queueBlockPlace(actor, after); - } else { - consumer.queueBlockReplace(actor, before, after); - } - } - }, 1L); + + LoggingUtil.smartLogBlockPlace(consumer, actor, before, after); } } diff --git a/src/main/java/de/diddiz/util/BukkitUtils.java b/src/main/java/de/diddiz/util/BukkitUtils.java index 8b1ca9b..7cb9a8e 100644 --- a/src/main/java/de/diddiz/util/BukkitUtils.java +++ b/src/main/java/de/diddiz/util/BukkitUtils.java @@ -1,12 +1,15 @@ package de.diddiz.util; import org.bukkit.*; +import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; import org.bukkit.block.DoubleChest; import org.bukkit.block.data.Bisected; import org.bukkit.block.data.Bisected.Half; import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.type.Slab; +import org.bukkit.block.data.type.Slab.Type; import org.bukkit.block.data.type.Stairs; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Entity; @@ -42,6 +45,64 @@ public class BukkitUtils { private static final Map projectileItems; static { + EnumSet pressurePlates = EnumSet.noneOf(Material.class); + pressurePlates.add(Material.OAK_PRESSURE_PLATE); + pressurePlates.add(Material.SPRUCE_PRESSURE_PLATE); + pressurePlates.add(Material.BIRCH_PRESSURE_PLATE); + pressurePlates.add(Material.JUNGLE_PRESSURE_PLATE); + pressurePlates.add(Material.ACACIA_PRESSURE_PLATE); + pressurePlates.add(Material.DARK_OAK_PRESSURE_PLATE); + pressurePlates.add(Material.STONE_PRESSURE_PLATE); + pressurePlates.add(Material.LIGHT_WEIGHTED_PRESSURE_PLATE); + pressurePlates.add(Material.HEAVY_WEIGHTED_PRESSURE_PLATE); + + EnumSet saplings = EnumSet.noneOf(Material.class); + saplings.add(Material.OAK_SAPLING); + saplings.add(Material.SPRUCE_SAPLING); + saplings.add(Material.BIRCH_SAPLING); + saplings.add(Material.JUNGLE_SAPLING); + saplings.add(Material.ACACIA_SAPLING); + saplings.add(Material.DARK_OAK_SAPLING); + + EnumSet carpets = EnumSet.noneOf(Material.class); + carpets.add(Material.BLACK_CARPET); + carpets.add(Material.BLUE_CARPET); + carpets.add(Material.LIGHT_GRAY_CARPET); + carpets.add(Material.BROWN_CARPET); + carpets.add(Material.CYAN_CARPET); + carpets.add(Material.GRAY_CARPET); + carpets.add(Material.GREEN_CARPET); + carpets.add(Material.LIGHT_BLUE_CARPET); + carpets.add(Material.MAGENTA_CARPET); + carpets.add(Material.LIME_CARPET); + carpets.add(Material.ORANGE_CARPET); + carpets.add(Material.PINK_CARPET); + carpets.add(Material.PURPLE_CARPET); + carpets.add(Material.RED_CARPET); + carpets.add(Material.WHITE_CARPET); + carpets.add(Material.YELLOW_CARPET); + + EnumSet slabs = EnumSet.noneOf(Material.class); + slabs.add(Material.OAK_SLAB); + slabs.add(Material.SPRUCE_SLAB); + slabs.add(Material.BIRCH_SLAB); + slabs.add(Material.JUNGLE_SLAB); + slabs.add(Material.ACACIA_SLAB); + slabs.add(Material.DARK_OAK_SLAB); + slabs.add(Material.STONE_SLAB); + slabs.add(Material.STONE_BRICK_SLAB); + slabs.add(Material.COBBLESTONE_SLAB); + slabs.add(Material.PETRIFIED_OAK_SLAB); + slabs.add(Material.SANDSTONE_SLAB); + slabs.add(Material.RED_SANDSTONE_SLAB); + slabs.add(Material.NETHER_BRICK_SLAB); + slabs.add(Material.PURPUR_SLAB); + slabs.add(Material.QUARTZ_SLAB); + slabs.add(Material.BRICK_SLAB); + slabs.add(Material.PRISMARINE_SLAB); + slabs.add(Material.DARK_PRISMARINE_SLAB); + slabs.add(Material.PRISMARINE_BRICK_SLAB); + singleBlockPlants = EnumSet.noneOf(Material.class); singleBlockPlants.add(Material.GRASS); singleBlockPlants.add(Material.FERN); @@ -82,7 +143,12 @@ public class BukkitUtils { relativeBreakable.add(Material.WALL_SIGN); relativeBreakable.add(Material.LADDER); relativeBreakable.add(Material.STONE_BUTTON); - relativeBreakable.addAll(Tag.WOODEN_BUTTONS.getValues()); + relativeBreakable.add(Material.OAK_BUTTON); + relativeBreakable.add(Material.SPRUCE_BUTTON); + relativeBreakable.add(Material.BIRCH_BUTTON); + relativeBreakable.add(Material.JUNGLE_BUTTON); + relativeBreakable.add(Material.ACACIA_BUTTON); + relativeBreakable.add(Material.DARK_OAK_BUTTON); relativeBreakable.add(Material.REDSTONE_WALL_TORCH); relativeBreakable.add(Material.LEVER); relativeBreakable.add(Material.WALL_TORCH); @@ -91,7 +157,7 @@ public class BukkitUtils { // Blocks that break when they are on top of a block relativeTopBreakable = EnumSet.noneOf(Material.class); - relativeTopBreakable.addAll(Tag.SAPLINGS.getValues()); + relativeTopBreakable.addAll(saplings); relativeTopBreakable.addAll(singleBlockPlants); relativeTopBreakable.add(Material.WHEAT); relativeTopBreakable.add(Material.POTATO); @@ -106,10 +172,7 @@ public class BukkitUtils { relativeTopBreakable.add(Material.RAIL); relativeTopBreakable.add(Material.REDSTONE_WIRE); relativeTopBreakable.add(Material.SIGN); - relativeTopBreakable.add(Material.STONE_PRESSURE_PLATE); - relativeTopBreakable.addAll(Tag.WOODEN_PRESSURE_PLATES.getValues()); - relativeTopBreakable.add(Material.LIGHT_WEIGHTED_PRESSURE_PLATE); - relativeTopBreakable.add(Material.HEAVY_WEIGHTED_PRESSURE_PLATE); + relativeTopBreakable.addAll(pressurePlates); relativeTopBreakable.add(Material.SNOW); relativeTopBreakable.add(Material.REPEATER); relativeTopBreakable.add(Material.COMPARATOR); @@ -117,27 +180,42 @@ public class BukkitUtils { relativeTopBreakable.add(Material.WALL_TORCH); relativeTopBreakable.add(Material.REDSTONE_TORCH); relativeTopBreakable.add(Material.REDSTONE_WALL_TORCH); - relativeTopBreakable.addAll(Tag.WOODEN_DOORS.getValues()); + relativeTopBreakable.add(Material.OAK_DOOR); + relativeTopBreakable.add(Material.SPRUCE_DOOR); + relativeTopBreakable.add(Material.BIRCH_DOOR); + relativeTopBreakable.add(Material.JUNGLE_DOOR); + relativeTopBreakable.add(Material.ACACIA_DOOR); + relativeTopBreakable.add(Material.DARK_OAK_DOOR); relativeTopBreakable.add(Material.IRON_DOOR); - relativeTopBreakable.addAll(Tag.CARPETS.getValues()); + relativeTopBreakable.addAll(carpets); relativeTopBreakable.addAll(doublePlants); // Blocks that break falling entities fallingEntityKillers = EnumSet.noneOf(Material.class); fallingEntityKillers.add(Material.SIGN); fallingEntityKillers.add(Material.WALL_SIGN); - fallingEntityKillers.addAll(Tag.WOODEN_PRESSURE_PLATES.getValues()); - fallingEntityKillers.add(Material.STONE_PRESSURE_PLATE); - fallingEntityKillers.add(Material.LIGHT_WEIGHTED_PRESSURE_PLATE); - fallingEntityKillers.add(Material.HEAVY_WEIGHTED_PRESSURE_PLATE); - fallingEntityKillers.addAll(Tag.SAPLINGS.getValues()); - fallingEntityKillers.addAll(singleBlockPlants); + fallingEntityKillers.addAll(pressurePlates); + fallingEntityKillers.addAll(saplings); + fallingEntityKillers.add(Material.DANDELION); + fallingEntityKillers.add(Material.POPPY); + fallingEntityKillers.add(Material.BLUE_ORCHID); + fallingEntityKillers.add(Material.ALLIUM); + fallingEntityKillers.add(Material.AZURE_BLUET); + fallingEntityKillers.add(Material.ORANGE_TULIP); + fallingEntityKillers.add(Material.WHITE_TULIP); + fallingEntityKillers.add(Material.PINK_TULIP); + fallingEntityKillers.add(Material.RED_TULIP); + fallingEntityKillers.add(Material.OXEYE_DAISY); + fallingEntityKillers.add(Material.BROWN_MUSHROOM); + fallingEntityKillers.add(Material.RED_MUSHROOM); + fallingEntityKillers.addAll(doublePlants); fallingEntityKillers.add(Material.WHEAT); fallingEntityKillers.add(Material.CARROT); fallingEntityKillers.add(Material.POTATO); fallingEntityKillers.add(Material.BEETROOT); fallingEntityKillers.add(Material.NETHER_WART); - fallingEntityKillers.addAll(Tag.SLABS.getValues()); + fallingEntityKillers.add(Material.COCOA); + fallingEntityKillers.addAll(slabs); fallingEntityKillers.add(Material.TORCH); fallingEntityKillers.add(Material.WALL_TORCH); fallingEntityKillers.add(Material.FLOWER_POT); @@ -152,7 +230,19 @@ public class BukkitUtils { fallingEntityKillers.add(Material.REPEATER); fallingEntityKillers.add(Material.COMPARATOR); fallingEntityKillers.add(Material.DAYLIGHT_DETECTOR); - fallingEntityKillers.addAll(Tag.CARPETS.getValues()); + fallingEntityKillers.addAll(carpets); + fallingEntityKillers.add(Material.PLAYER_HEAD); + fallingEntityKillers.add(Material.PLAYER_WALL_HEAD); + fallingEntityKillers.add(Material.CREEPER_HEAD); + fallingEntityKillers.add(Material.CREEPER_WALL_HEAD); + fallingEntityKillers.add(Material.DRAGON_HEAD); + fallingEntityKillers.add(Material.DRAGON_WALL_HEAD); + fallingEntityKillers.add(Material.ZOMBIE_HEAD); + fallingEntityKillers.add(Material.ZOMBIE_WALL_HEAD); + fallingEntityKillers.add(Material.SKELETON_SKULL); + fallingEntityKillers.add(Material.SKELETON_WALL_SKULL); + fallingEntityKillers.add(Material.WITHER_SKELETON_SKULL); + fallingEntityKillers.add(Material.WITHER_SKELETON_WALL_SKULL); // Crop Blocks cropBlocks = EnumSet.noneOf(Material.class); @@ -214,11 +304,8 @@ public class BukkitUtils { nonFluidProofBlocks.add(Material.WALL_TORCH); nonFluidProofBlocks.add(Material.TRIPWIRE_HOOK); nonFluidProofBlocks.add(Material.COCOA); - nonFluidProofBlocks.addAll(Tag.WOODEN_PRESSURE_PLATES.getValues()); - nonFluidProofBlocks.add(Material.STONE_PRESSURE_PLATE); - nonFluidProofBlocks.add(Material.LIGHT_WEIGHTED_PRESSURE_PLATE); - nonFluidProofBlocks.add(Material.HEAVY_WEIGHTED_PRESSURE_PLATE); - nonFluidProofBlocks.addAll(Tag.SAPLINGS.getValues()); + nonFluidProofBlocks.addAll(pressurePlates); + nonFluidProofBlocks.addAll(saplings); nonFluidProofBlocks.add(Material.WHEAT); nonFluidProofBlocks.add(Material.CARROT); nonFluidProofBlocks.add(Material.POTATO); @@ -236,7 +323,7 @@ public class BukkitUtils { nonFluidProofBlocks.add(Material.REPEATER); nonFluidProofBlocks.add(Material.COMPARATOR); nonFluidProofBlocks.add(Material.DAYLIGHT_DETECTOR); - nonFluidProofBlocks.addAll(Tag.CARPETS.getValues()); + nonFluidProofBlocks.addAll(carpets); bedBlocks = EnumSet.noneOf(Material.class); bedBlocks.add(Material.BLACK_BED); @@ -462,20 +549,26 @@ public class BukkitUtils { return 0; } - public static boolean canFall(World world, int x, int y, int z) { - Material mat = world.getBlockAt(x, y, z).getType(); - - // Air - if (mat == Material.AIR) { + public static boolean canFallIn(World world, int x, int y, int z) { + Block block = world.getBlockAt(x, y, z); + Material mat = block.getType(); + if (canDirectlyFallIn(mat)) { return true; - } else if (mat == Material.WATER || mat == Material.LAVA) { // Fluids - return true; - } else if (getFallingEntityKillers().contains(mat) || mat == Material.FIRE || mat == Material.VINE || doublePlants.contains(mat) || mat == Material.DEAD_BUSH) { // Misc. + } else if (getFallingEntityKillers().contains(mat) || singleBlockPlants.contains(mat) || mat == Material.VINE) { + if (Tag.SLABS.isTagged(mat)) { + if (((Slab) block.getBlockData()).getType() != Type.BOTTOM) { + return false; + } + } return true; } return false; } + public static boolean canDirectlyFallIn(Material m) { + return isEmpty(m) || m == Material.WATER || m == Material.LAVA || m == Material.FIRE; + } + public static Material itemIDfromProjectileEntity(Entity e) { return projectileItems.get(e.getType()); } diff --git a/src/main/java/de/diddiz/util/LoggingUtil.java b/src/main/java/de/diddiz/util/LoggingUtil.java index 10e03c1..8848e3d 100644 --- a/src/main/java/de/diddiz/util/LoggingUtil.java +++ b/src/main/java/de/diddiz/util/LoggingUtil.java @@ -9,6 +9,7 @@ import org.bukkit.Material; import org.bukkit.Tag; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; import org.bukkit.block.Sign; import org.bukkit.block.data.BlockData; import org.bukkit.block.data.Directional; @@ -20,6 +21,41 @@ import static de.diddiz.LogBlock.config.Config.mb4; public class LoggingUtil { + public static void smartLogBlockPlace(Consumer consumer, Actor actor, BlockState replaced, BlockState placed) { + Location loc = replaced.getLocation(); + if (!placed.getType().hasGravity() || !BukkitUtils.canDirectlyFallIn(replaced.getBlock().getRelative(BlockFace.DOWN).getType())) { + if (BukkitUtils.isEmpty(replaced.getType())) { + consumer.queueBlockPlace(actor, placed); + } else { + consumer.queueBlockReplace(actor, replaced, placed); + } + return; + } + int x = loc.getBlockX(); + int initialy = loc.getBlockY(); + int y = initialy; + int z = loc.getBlockZ(); + while (y > 0 && BukkitUtils.canFallIn(loc.getWorld(), x, (y - 1), z)) { + y--; + } + if (initialy != y && !BukkitUtils.isEmpty(replaced.getType())) { + // this is not the final location but the block got removed (vines etc) + consumer.queueBlockBreak(actor, replaced); + } + // If y is 0 then the block fell out of the world :( + if (y != 0) { + // Run this check to avoid false positives + Location finalLoc = new Location(loc.getWorld(), x, y, z); + if (y == initialy || !BukkitUtils.getFallingEntityKillers().contains(finalLoc.getBlock().getType())) { + if (BukkitUtils.isEmpty(finalLoc.getBlock().getType())) { + consumer.queueBlockPlace(actor, finalLoc, placed.getBlockData()); + } else { + consumer.queueBlockReplace(actor, finalLoc.getBlock().getState(), placed.getBlockData()); + } + } + } + } + public static void smartLogFallables(Consumer consumer, Actor actor, Block origin) { WorldConfig wcfg = getWorldConfig(origin.getWorld()); @@ -41,7 +77,7 @@ public class LoggingUtil { int x = loc.getBlockX(); int y = loc.getBlockY(); int z = loc.getBlockZ(); - while (y > 0 && BukkitUtils.canFall(loc.getWorld(), x, (y - 1), z)) { + while (y > 0 && BukkitUtils.canFallIn(loc.getWorld(), x, (y - 1), z)) { y--; } // If y is 0 then the sand block fell out of the world :(