From b360aeb069740282bddc7c8b2ab4d9b1221dbe75 Mon Sep 17 00:00:00 2001 From: Alex 'mcmonkey' Goodwin Date: Mon, 30 Aug 2021 03:20:59 -0700 Subject: [PATCH] new event: block destroyed by explosion --- .../denizen/events/ScriptEventRegistry.java | 1 + .../block/BlockDestroyedByExplosionEvent.java | 129 ++++++++++++++++++ .../block/BlockExplodesScriptEvent.java | 25 ++-- .../vehicle/VehicleDestroyedScriptEvent.java | 3 + 4 files changed, 142 insertions(+), 16 deletions(-) create mode 100644 plugin/src/main/java/com/denizenscript/denizen/events/block/BlockDestroyedByExplosionEvent.java diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/ScriptEventRegistry.java b/plugin/src/main/java/com/denizenscript/denizen/events/ScriptEventRegistry.java index 7d51d6dd4c..c859f50ffe 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/events/ScriptEventRegistry.java +++ b/plugin/src/main/java/com/denizenscript/denizen/events/ScriptEventRegistry.java @@ -29,6 +29,7 @@ public static void registerMainEvents() { // Block events ScriptEvent.registerScriptEvent(new BlockBuiltScriptEvent()); ScriptEvent.registerScriptEvent(new BlockBurnsScriptEvent()); + ScriptEvent.registerScriptEvent(new BlockDestroyedByExplosionEvent()); ScriptEvent.registerScriptEvent(new BlockDispensesScriptEvent()); ScriptEvent.registerScriptEvent(new BlockExplodesScriptEvent()); ScriptEvent.registerScriptEvent(new BlockFadesScriptEvent()); diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/block/BlockDestroyedByExplosionEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/block/BlockDestroyedByExplosionEvent.java new file mode 100644 index 0000000000..82a1b8f8e5 --- /dev/null +++ b/plugin/src/main/java/com/denizenscript/denizen/events/block/BlockDestroyedByExplosionEvent.java @@ -0,0 +1,129 @@ +package com.denizenscript.denizen.events.block; + +import com.denizenscript.denizen.events.BukkitScriptEvent; +import com.denizenscript.denizen.objects.EntityTag; +import com.denizenscript.denizen.objects.LocationTag; +import com.denizenscript.denizencore.objects.ObjectTag; +import com.denizenscript.denizencore.objects.core.ElementTag; +import org.bukkit.block.Block; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockExplodeEvent; +import org.bukkit.event.entity.EntityExplodeEvent; + +import java.util.ArrayList; +import java.util.List; + +public class BlockDestroyedByExplosionEvent extends BukkitScriptEvent implements Listener { + + // <--[event] + // @Events + // block destroyed by explosion + // destroyed by explosion + // + // @Regex ^on [^\s]+ destroyed by explosion$ + // + // @Group Block + // + // @Location true + // + // @Cancellable true + // + // @Warning This event fires extremely rapidly. One single TNT detonation can destroy a hundred blocks. + // + // @Triggers when a block is destroyed by an explosion (caused by either an entity or a block exploding). + // + // @Switch source_entity: to only fire the event if the source is an entity that matches the given type. Note that "Primed_Tnt" is an entity, not a block. + // @Switch source_block: to only fire the event if the source is a block that matches the given type. + // + // @Context + // returns the block that exploded. + // returns the location of the source block or entity. + // returns the entity that exploded, if any. + // returns an ElementTag(Decimal) of the strength of the explosion. + // + // --> + + public BlockDestroyedByExplosionEvent() { + instance = this; + } + + public static BlockDestroyedByExplosionEvent instance; + public BlockExplodeEvent blockEvent; + public EntityExplodeEvent entityEvent; + public Block block; + public List rawList; + + @Override + public boolean couldMatch(ScriptPath path) { + if (!path.eventArgLowerAt(1).equals("destroyed") || !path.eventArgLowerAt(2).equals("by") || !path.eventArgLowerAt(3).equals("explosion")) { + return false; + } + if (!couldMatchBlock(path.eventArgLowerAt(0))) { + return false; + } + return true; + } + + @Override + public boolean matches(ScriptPath path) { + if (!tryMaterial(block.getType(), path.eventArgLowerAt(0))) { + return false; + } + if (!runInCheck(path, block.getLocation())) { + return false; + } + if (path.switches.containsKey("source_entity") && (entityEvent == null || !tryEntity(new EntityTag(entityEvent.getEntity()), path.switches.get("source_entity")))) { + return false; + } + if (path.switches.containsKey("source_block") && (blockEvent == null || !tryMaterial(blockEvent.getBlock().getType(), path.switches.get("source_block")))) { + return false; + } + return super.matches(path); + } + + @Override + public String getName() { + return "BlockDestroyedByExplosion"; + } + + @Override + public ObjectTag getContext(String name) { + switch (name) { + case "block": return new LocationTag(block.getLocation()); + case "source_location": return new LocationTag(blockEvent != null ? blockEvent.getBlock().getLocation() : entityEvent.getLocation()); + case "source_entity": return entityEvent == null ? null : new EntityTag(entityEvent.getEntity()); + case "strength": return new ElementTag(blockEvent != null ? blockEvent.getYield() : entityEvent.getYield()); + default: return super.getContext(name); + } + } + + @Override + public void cancellationChanged() { + if (cancelled) { + rawList.remove(block); + } + } + + @EventHandler + public void onBlockExplodes(BlockExplodeEvent event) { + this.blockEvent = event; + this.entityEvent = null; + this.rawList = event.blockList(); + for (Block block : new ArrayList<>(rawList)) { + this.block = block; + fire(event); + } + } + + @EventHandler + public void onEntityExplodes(EntityExplodeEvent event) { + this.entityEvent = event; + this.blockEvent = null; + this.rawList = event.blockList(); + for (Block block : new ArrayList<>(rawList)) { + this.block = block; + fire(event); + } + } +} diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/block/BlockExplodesScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/block/BlockExplodesScriptEvent.java index a72f6674dd..4a80f5e617 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/events/block/BlockExplodesScriptEvent.java +++ b/plugin/src/main/java/com/denizenscript/denizen/events/block/BlockExplodesScriptEvent.java @@ -2,7 +2,6 @@ import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.LocationTag; -import com.denizenscript.denizen.objects.MaterialTag; import com.denizenscript.denizen.utilities.debugging.Debug; import com.denizenscript.denizencore.objects.ArgumentHelper; import com.denizenscript.denizencore.objects.ObjectTag; @@ -30,10 +29,11 @@ public class BlockExplodesScriptEvent extends BukkitScriptEvent implements Liste // // @Cancellable true // - // @Triggers when a block explodes (like a bed in the nether. For TNT, refer to the "entity explodes" event instead). + // @Triggers when a block explodes (like a bed in the nether. For TNT, refer to the "entity explodes" event instead). For a block being destroyed by an explosion, refer to the "block destroyed by explosion" event instead. // // @Context - // returns a ListTag of blocks that the entity blew up. + // returns the location of the exploding block. + // returns a ListTag of blocks that blew up. // returns an ElementTag(Decimal) of the strength of the explosion. // // @Determine @@ -63,20 +63,10 @@ public boolean couldMatch(ScriptPath path) { @Override public boolean matches(ScriptPath path) { - String target = path.eventArgLowerAt(0); - if (!target.equals("block")) { - boolean matched = false; - for (Block block : blocks) { - if (tryMaterial(new MaterialTag(block.getType()), target)) { - matched = true; - break; - } - } - if (!matched) { - return false; - } + if (!tryMaterial(event.getBlock().getType(), path.eventArgAt(0))) { + return false; } - if (blocks.size() > 0 && !runInCheck(path, blocks.get(0).getLocation())) { + if (!runInCheck(path, event.getBlock().getLocation())) { return false; } return super.matches(path); @@ -112,6 +102,9 @@ public boolean applyDetermination(ScriptPath path, ObjectTag determinationObj) { @Override public ObjectTag getContext(String name) { + if (name.equals("block")) { + return new LocationTag(event.getBlock().getLocation()); + } if (name.equals("blocks")) { ListTag blocks = new ListTag(); for (Block block : this.blocks) { diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/vehicle/VehicleDestroyedScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/vehicle/VehicleDestroyedScriptEvent.java index 106f41c81a..1ac773fcd4 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/events/vehicle/VehicleDestroyedScriptEvent.java +++ b/plugin/src/main/java/com/denizenscript/denizen/events/vehicle/VehicleDestroyedScriptEvent.java @@ -64,6 +64,9 @@ else if (cmd.equals("destroyed")) { if (!exactMatchesVehicle(path.eventArgLowerAt(0))) { return false; } + if (path.eventArgLowerAt(2).equals("by")) { + return false; + } } else { return false;