Improve logging of fallable blocks

Also in this commit: Bukkit's Tags are just broken
This commit is contained in:
Brokkonaut
2018-08-01 20:01:51 +02:00
parent 5a7ba77095
commit 92b1a2f394
3 changed files with 172 additions and 86 deletions

View File

@ -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);
}
}

View File

@ -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<EntityType, Material> projectileItems;
static {
EnumSet<Material> 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<Material> 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<Material> 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<Material> 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());
}

View File

@ -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 :(