diff --git a/src/main/java/net/coreprotect/config/Config.java b/src/main/java/net/coreprotect/config/Config.java index 168489e8..7de01a4a 100644 --- a/src/main/java/net/coreprotect/config/Config.java +++ b/src/main/java/net/coreprotect/config/Config.java @@ -63,6 +63,7 @@ public class Config extends Language { public boolean PISTONS; public boolean BLOCK_BURN; public boolean BLOCK_IGNITE; + public boolean FIRE_EXTINGUISH; public boolean EXPLOSIONS; public boolean ENTITY_CHANGE; public boolean ENTITY_KILLS; @@ -118,6 +119,7 @@ public class Config extends Language { DEFAULT_VALUES.put("pistons", "true"); DEFAULT_VALUES.put("block-burn", "true"); DEFAULT_VALUES.put("block-ignite", "true"); + DEFAULT_VALUES.put("fire-extinguish", "false"); DEFAULT_VALUES.put("explosions", "true"); DEFAULT_VALUES.put("entity-change", "true"); DEFAULT_VALUES.put("entity-kills", "true"); @@ -161,6 +163,7 @@ public class Config extends Language { HEADERS.put("pistons", new String[] { "# Properly track blocks moved by pistons." }); HEADERS.put("block-burn", new String[] { "# Logs blocks that burn up in a fire." }); HEADERS.put("block-ignite", new String[] { "# Logs when a block naturally ignites, such as from fire spreading." }); + HEADERS.put("fire-extinguish", new String[] { "# Logs when fire naturally extinguishes." }); HEADERS.put("explosions", new String[] { "# Logs explosions, such as TNT and Creepers." }); HEADERS.put("entity-change", new String[] { "# Track when an entity changes a block, such as an Enderman destroying blocks." }); HEADERS.put("entity-kills", new String[] { "# Logs killed entities, such as killed cows and enderman." }); @@ -223,6 +226,7 @@ public class Config extends Language { this.PISTONS = this.getBoolean("pistons"); this.BLOCK_BURN = this.getBoolean("block-burn"); this.BLOCK_IGNITE = this.getBoolean("block-ignite"); + this.FIRE_EXTINGUISH = this.getBoolean("fire-extinguish"); this.EXPLOSIONS = this.getBoolean("explosions"); this.ENTITY_CHANGE = this.getBoolean("entity-change"); this.ENTITY_KILLS = this.getBoolean("entity-kills"); diff --git a/src/main/java/net/coreprotect/listener/ListenerHandler.java b/src/main/java/net/coreprotect/listener/ListenerHandler.java index 48529201..cbb2c575 100644 --- a/src/main/java/net/coreprotect/listener/ListenerHandler.java +++ b/src/main/java/net/coreprotect/listener/ListenerHandler.java @@ -16,6 +16,7 @@ import net.coreprotect.listener.block.BlockPistonListener; import net.coreprotect.listener.block.BlockPlaceListener; import net.coreprotect.listener.block.BlockSpreadListener; import net.coreprotect.listener.block.CampfireStartListener; +import net.coreprotect.listener.block.TNTPrimeListener; import net.coreprotect.listener.channel.PluginChannelHandshakeListener; import net.coreprotect.listener.channel.PluginChannelListener; import net.coreprotect.listener.entity.CreatureSpawnListener; @@ -57,6 +58,7 @@ import net.coreprotect.listener.world.StructureGrowListener; import net.coreprotect.paper.listener.BlockPreDispenseListener; import net.coreprotect.paper.listener.CopperGolemChestListener; import net.coreprotect.paper.listener.FlowerPotManipulateListener; +import net.coreprotect.paper.listener.LegacyTNTPrimeListener; import net.coreprotect.paper.listener.PaperChatListener; public final class ListenerHandler { @@ -102,6 +104,19 @@ public final class ListenerHandler { catch (Exception e) { CampfireStartListener.useCampfireStartEvent = false; } + try { + Class.forName("org.bukkit.event.block.TNTPrimeEvent"); // Bukkit 1.20+ + pluginManager.registerEvents(new TNTPrimeListener(), plugin); + } + catch (Exception e) { + try { + Class.forName("com.destroystokyo.paper.event.block.TNTPrimeEvent"); // Paper 1.16+ + pluginManager.registerEvents(new LegacyTNTPrimeListener(), plugin); + } + catch (Exception ignored) { + // Ignore registration failures to remain compatible with older servers. + } + } // Entity Listeners pluginManager.registerEvents(new CreatureSpawnListener(), plugin); diff --git a/src/main/java/net/coreprotect/listener/block/BlockFadeListener.java b/src/main/java/net/coreprotect/listener/block/BlockFadeListener.java index 7c96d591..080d34f8 100644 --- a/src/main/java/net/coreprotect/listener/block/BlockFadeListener.java +++ b/src/main/java/net/coreprotect/listener/block/BlockFadeListener.java @@ -3,30 +3,44 @@ package net.coreprotect.listener.block; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.Block; +import org.bukkit.block.BlockState; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockFadeEvent; import net.coreprotect.config.Config; import net.coreprotect.consumer.Queue; +import net.coreprotect.model.BlockGroup; public final class BlockFadeListener extends Queue implements Listener { @EventHandler protected void onBlockFade(BlockFadeEvent event) { - // snow/ice fading if (event.isCancelled()) { return; } Block block = event.getBlock(); - if (block.getType().equals(Material.TURTLE_EGG)) { - World world = block.getWorld(); + Material type = block.getType(); + World world = block.getWorld(); + + if (BlockGroup.FIRE.contains(type)) { + if (!Config.getConfig(world).FIRE_EXTINGUISH) { + return; + } + + BlockState newState = event.getNewState(); + Material newType = newState.getType(); + if (newType == Material.AIR || newType == Material.CAVE_AIR || newType == Material.VOID_AIR) { + Queue.queueBlockBreak("#fire", block.getState(), type, block.getBlockData().getAsString(), 0); + } + } + else if (type.equals(Material.TURTLE_EGG)) { if (!Config.getConfig(world).ENTITY_CHANGE) { return; } - Queue.queueBlockBreak("#turtle", block.getState(), block.getType(), block.getBlockData().getAsString(), 0); + Queue.queueBlockBreak("#turtle", block.getState(), type, block.getBlockData().getAsString(), 0); } } diff --git a/src/main/java/net/coreprotect/listener/block/TNTPrimeListener.java b/src/main/java/net/coreprotect/listener/block/TNTPrimeListener.java new file mode 100644 index 00000000..38f2688f --- /dev/null +++ b/src/main/java/net/coreprotect/listener/block/TNTPrimeListener.java @@ -0,0 +1,29 @@ +package net.coreprotect.listener.block; + +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.TNTPrimeEvent; + +import net.coreprotect.config.Config; +import net.coreprotect.consumer.Queue; + +public final class TNTPrimeListener extends Queue implements Listener { + + @EventHandler(priority = EventPriority.MONITOR) + protected void onTNTPrime(TNTPrimeEvent event) { + Block block = event.getBlock(); + if (event.isCancelled() || block.getType() != Material.TNT || !Config.getConfig(block.getWorld()).EXPLOSIONS || isAlreadyLogged(event.getCause())) { + return; + } + + Queue.queueBlockBreak(TNTPrimeUtil.getUser(event.getPrimingEntity()), block.getState(), Material.TNT, block.getBlockData().getAsString(), 0); + } + + private boolean isAlreadyLogged(TNTPrimeEvent.PrimeCause cause) { + return cause == TNTPrimeEvent.PrimeCause.EXPLOSION || cause == TNTPrimeEvent.PrimeCause.BLOCK_BREAK; + } + +} diff --git a/src/main/java/net/coreprotect/listener/block/TNTPrimeUtil.java b/src/main/java/net/coreprotect/listener/block/TNTPrimeUtil.java new file mode 100644 index 00000000..ceaada65 --- /dev/null +++ b/src/main/java/net/coreprotect/listener/block/TNTPrimeUtil.java @@ -0,0 +1,36 @@ +package net.coreprotect.listener.block; + +import java.util.Locale; + +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; +import org.bukkit.projectiles.ProjectileSource; + +public final class TNTPrimeUtil { + + private TNTPrimeUtil() { + } + + public static String getUser(Entity entity) { + if (entity instanceof Player) { + return ((Player) entity).getName(); + } + else if (entity instanceof Projectile) { + ProjectileSource source = ((Projectile) entity).getShooter(); + if (source instanceof Player) { + return ((Player) source).getName(); + } + else if (source instanceof LivingEntity && ((LivingEntity) source).getType() != null) { + return "#" + ((LivingEntity) source).getType().name().toLowerCase(Locale.ROOT); + } + } + else if (entity != null && entity.getType() != null) { + return "#" + entity.getType().name().toLowerCase(Locale.ROOT); + } + + return "#tnt"; + } + +} diff --git a/src/main/java/net/coreprotect/paper/listener/LegacyTNTPrimeListener.java b/src/main/java/net/coreprotect/paper/listener/LegacyTNTPrimeListener.java new file mode 100644 index 00000000..b9e21d71 --- /dev/null +++ b/src/main/java/net/coreprotect/paper/listener/LegacyTNTPrimeListener.java @@ -0,0 +1,27 @@ +package net.coreprotect.paper.listener; + +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +import com.destroystokyo.paper.event.block.TNTPrimeEvent; + +import net.coreprotect.config.Config; +import net.coreprotect.consumer.Queue; +import net.coreprotect.listener.block.TNTPrimeUtil; + +public final class LegacyTNTPrimeListener extends Queue implements Listener { + + @EventHandler(priority = EventPriority.MONITOR) + protected void onTNTPrime(TNTPrimeEvent event) { + Block block = event.getBlock(); + if (event.isCancelled() || block.getType() != Material.TNT || !Config.getConfig(block.getWorld()).EXPLOSIONS || event.getReason() == TNTPrimeEvent.PrimeReason.EXPLOSION) { + return; + } + + Queue.queueBlockBreak(TNTPrimeUtil.getUser(event.getPrimerEntity()), block.getState(), Material.TNT, block.getBlockData().getAsString(), 0); + } + +}