diff --git a/src/main/java/ch/njol/skript/effects/EffExplosion.java b/src/main/java/ch/njol/skript/effects/EffExplosion.java
index 93c413aa47d..d9caf9851c5 100644
--- a/src/main/java/ch/njol/skript/effects/EffExplosion.java
+++ b/src/main/java/ch/njol/skript/effects/EffExplosion.java
@@ -1,9 +1,5 @@
package ch.njol.skript.effects;
-import org.bukkit.Location;
-import org.bukkit.event.Event;
-import org.jetbrains.annotations.Nullable;
-
import ch.njol.skript.Skript;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Examples;
@@ -12,70 +8,125 @@
import ch.njol.skript.lang.Effect;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.SkriptParser.ParseResult;
+import ch.njol.skript.registrations.EventValues;
import ch.njol.skript.util.Direction;
import ch.njol.util.Kleenean;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
-/**
- * @author Peter Güttinger
- */
@Name("Explosion")
-@Description({"Creates an explosion of a given force. The Minecraft Wiki has an article on explosions " +
- "which lists the explosion forces of TNT, creepers, etc.",
- "Hint: use a force of 0 to create a fake explosion that does no damage whatsoever, or use the explosion effect introduced in Skript 2.0.",
- "Starting with Bukkit 1.4.5 and Skript 2.0 you can use safe explosions which will damage entities but won't destroy any blocks."})
-@Examples({"create an explosion of force 10 at the player",
- "create an explosion of force 0 at the victim"})
+@Description({
+ "Creates an explosion of a given force. The Minecraft Wiki has an article on explosions " +
+ "which lists the explosion forces of TNT, creepers, etc.",
+ "Use a force of 0 to create a fake explosion that does no damage whatsoever, or use the 'fake explosion' effect.",
+ "Use safe explosions to create an explosion which damages entities but won't destroy any blocks."})
+@Examples({
+ "create an explosion of force 10 at the player with fire",
+ "create a safe explosion with force 10",
+ "create a fake explosion at the player",
+})
@Since("1.0")
public class EffExplosion extends Effect {
static {
Skript.registerEffect(EffExplosion.class,
- "[(create|make)] [an] explosion (of|with) (force|strength|power) %number% [%directions% %locations%] [(1¦with fire)]",
- "[(create|make)] [a] safe explosion (of|with) (force|strength|power) %number% [%directions% %locations%]",
- "[(create|make)] [a] fake explosion [%directions% %locations%]",
- "[(create|make)] [an] explosion[ ]effect [%directions% %locations%]");
+ "[create|make] [an] explosion (of|with) (force|strength|power) %number% [%directions% %locations%] [fire:with fire]",
+ "[create|make] [a] safe explosion (of|with) (force|strength|power) %number% [%directions% %locations%]",
+ "[create|make] [a] fake explosion [%directions% %locations%]",
+ "[create|make] [an] explosion[ ]effect [%directions% %locations%]");
+
+ EventValues.registerEventValue(ScriptExplodeEvent.class, Location.class, ScriptExplodeEvent::getLocation);
+ EventValues.registerEventValue(ScriptExplodeEvent.class, Number.class, ScriptExplodeEvent::getPower);
}
- @Nullable
private Expression force;
- @SuppressWarnings("null")
private Expression locations;
private boolean blockDamage;
-
private boolean setFire;
- @SuppressWarnings({"unchecked", "null"})
@Override
- public boolean init(final Expression>[] exprs, final int matchedPattern, final Kleenean isDelayed, final ParseResult parser) {
+ public boolean init(Expression>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parser) {
+ //noinspection unchecked
force = matchedPattern <= 1 ? (Expression) exprs[0] : null;
blockDamage = matchedPattern != 1;
- setFire = parser.mark == 1;
- locations = Direction.combine((Expression extends Direction>) exprs[exprs.length - 2], (Expression extends Location>) exprs[exprs.length - 1]);
+ setFire = parser.hasTag("fire");
+ //noinspection unchecked
+ locations = Direction.combine((Expression extends Direction>) exprs[exprs.length - 2],
+ (Expression extends Location>) exprs[exprs.length - 1]);
return true;
}
@Override
- public void execute(final Event e) {
- final Number power = force != null ? force.getSingle(e) : 0;
- if (power == null)
+ public void execute(Event event) {
+ Number optionalForce = force != null ? force.getSingle(event) : 0;
+ if (optionalForce == null)
return;
- for (Location location : locations.getArray(e)) {
+
+ float power = optionalForce.floatValue();
+
+ for (Location location : locations.getArray(event)) {
if (location.getWorld() == null)
continue;
- if (!blockDamage)
- location.getWorld().createExplosion(location.getX(), location.getY(), location.getZ(), power.floatValue(), false, false);
- else
- location.getWorld().createExplosion(location, power.floatValue(), setFire);
+
+ boolean cancelled;
+ if (!blockDamage) {
+ cancelled = location.getWorld().createExplosion(location.getX(), location.getY(), location.getZ(),
+ power, false, false);
+ } else {
+ cancelled = location.getWorld().createExplosion(location, power, setFire);
+ }
+
+ if (!cancelled)
+ Bukkit.getPluginManager().callEvent(new ScriptExplodeEvent(location, power));
}
}
@Override
- public String toString(final @Nullable Event e, final boolean debug) {
- if (force != null)
- return "create explosion of force " + force.toString(e, debug) + " " + locations.toString(e, debug);
- else
- return "create explosion effect " + locations.toString(e, debug);
+ public String toString(@Nullable Event event, boolean debug) {
+ if (force != null) {
+ return "create explosion of force " + force.toString(event, debug) + " " + locations.toString(event, debug);
+ } else {
+ return "create explosion effect " + locations.toString(event, debug);
+ }
+ }
+
+ /**
+ * Event for handling explosions created by this effect.
+ */
+ public static class ScriptExplodeEvent extends Event {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ private final Location at;
+ private final float power;
+
+ public ScriptExplodeEvent(@NotNull Location at, float power) {
+ this.at = at;
+ this.power = power;
+ }
+
+ public @NotNull Location getLocation() {
+ return at;
+ }
+
+ public float getPower() {
+ return power;
+ }
+
+ @Override
+ public @NotNull HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }
+
}
}
diff --git a/src/main/java/ch/njol/skript/events/EvtExplode.java b/src/main/java/ch/njol/skript/events/EvtExplode.java
new file mode 100644
index 00000000000..869096a8bcd
--- /dev/null
+++ b/src/main/java/ch/njol/skript/events/EvtExplode.java
@@ -0,0 +1,177 @@
+package ch.njol.skript.events;
+
+import ch.njol.skript.Skript;
+import ch.njol.skript.effects.EffExplosion;
+import ch.njol.skript.entity.EntityType;
+import ch.njol.skript.lang.Literal;
+import ch.njol.skript.lang.SkriptEvent;
+import ch.njol.skript.lang.SkriptParser.ParseResult;
+import ch.njol.skript.util.Color;
+import ch.njol.skript.util.ColorRGB;
+import ch.njol.util.coll.CollectionUtils;
+import org.bukkit.FireworkEffect;
+import org.bukkit.event.Event;
+import org.bukkit.event.entity.EntityExplodeEvent;
+import org.bukkit.event.entity.FireworkExplodeEvent;
+import org.bukkit.inventory.meta.FireworkMeta;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class EvtExplode extends SkriptEvent {
+
+ static {
+ Skript.registerEvent("Explode", EvtExplode.class,
+ CollectionUtils.array(EffExplosion.ScriptExplodeEvent.class, FireworkExplodeEvent.class, EntityExplodeEvent.class),
+ "[a] script[ed] explo(d(e|ing)|sion)",
+ "[a] firework explo(d(e|ing)|sion) [colo[u]red %-colors%]",
+ "[a] [%entitytypes%] explo(d(e|ing)|sion)"
+ )
+ .description(
+ "Called when an entity explodes, or when an explosion is created by a script.",
+ "Entity and script explosions have a power value, obtained by using `event-number`.",
+ "Fireworks have an optional specifier for the exploded color."
+ )
+ .examples(
+ "on explosion:",
+ "on script explosion:",
+ "on tnt explosion:",
+ "on firework explode:",
+ "\tif event-colors contains red:",
+ "on firework exploding colored red, light green and black:",
+ "on firework explosion colored rgb 0, 255, 0:",
+ "\tbroadcast \"A firework colored %colors% was exploded at %location%!\""
+ )
+ .since("1.0, INSERT VERSION (script)");
+ }
+
+ private State state;
+
+ @Override
+ public boolean init(Literal>[] args, int matchedPattern, ParseResult parseResult) {
+ switch (matchedPattern) {
+ case 0 -> state = State.SCRIPT;
+ case 1 -> state = State.FIREWORK;
+ default -> state = State.ENTITY;
+ }
+
+ return state.init(args, matchedPattern, parseResult);
+ }
+
+ @Override
+ public boolean check(Event event) {
+ return state.check(event);
+ }
+
+ @Override
+ public String toString(@Nullable Event event, boolean debug) {
+ return state.toString(event, debug);
+ }
+
+ private enum State {
+
+ SCRIPT {
+ @Override
+ boolean init(Literal>[] args, int matchedPattern, ParseResult parseResult) {
+ return true;
+ }
+
+ @Override
+ boolean check(Event event) {
+ return event instanceof EffExplosion.ScriptExplodeEvent;
+ }
+
+ @Override
+ String toString(@Nullable Event event, boolean debug) {
+ return "script explosion";
+ }
+ },
+ FIREWORK {
+ private @Nullable Literal colors;
+
+ @Override
+ boolean init(Literal>[] args, int matchedPattern, ParseResult parseResult) {
+ if (args[0] != null)
+ //noinspection unchecked
+ colors = (Literal) args[0];
+ return true;
+ }
+
+ @Override
+ boolean check(Event event) {
+ if (!(event instanceof FireworkExplodeEvent fireworkExplodeEvent))
+ return false;
+
+ if (colors == null)
+ return true;
+
+ Set colours = colors.stream(event)
+ .map(color -> {
+ if (color instanceof ColorRGB)
+ return color.asBukkitColor();
+ return color.asDyeColor().getFireworkColor();
+ })
+ .collect(Collectors.toSet());
+
+ FireworkMeta meta = fireworkExplodeEvent.getEntity().getFireworkMeta();
+ for (FireworkEffect effect : meta.getEffects()) {
+ if (colours.containsAll(effect.getColors()))
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ String toString(@Nullable Event event, boolean debug) {
+ return "firework explode " + (colors != null ? " with colors " + colors.toString(event, debug) : "");
+ }
+ },
+ ENTITY {
+ private @Nullable Literal extends EntityType> typesLiteral;
+ private EntityType @Nullable [] types;
+
+ @Override
+ boolean init(Literal>[] args, int matchedPattern, ParseResult parseResult) {
+ //noinspection unchecked
+ Literal extends EntityType> arg = (Literal extends EntityType>) args[0];
+ if (arg == null)
+ return false;
+
+ typesLiteral = arg;
+ types = arg.getAll();
+ return true;
+ }
+
+ @Override
+ boolean check(Event event) {
+ if (!(event instanceof EntityExplodeEvent explodeEvent))
+ return false;
+ if (types == null)
+ return true;
+
+ for (EntityType type : types) {
+ if (type.isInstance(explodeEvent.getEntity()))
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ String toString(@Nullable Event event, boolean debug) {
+ if (typesLiteral != null)
+ return typesLiteral.toString(event, debug) + " explosion";
+
+ return "explosion";
+ }
+ };
+
+ abstract boolean init(Literal>[] args, int matchedPattern, ParseResult parseResult);
+
+ abstract boolean check(Event event);
+
+ abstract String toString(@Nullable Event event, boolean debug);
+
+ }
+
+}
diff --git a/src/main/java/ch/njol/skript/events/EvtFirework.java b/src/main/java/ch/njol/skript/events/EvtFirework.java
deleted file mode 100644
index 7c64987f0de..00000000000
--- a/src/main/java/ch/njol/skript/events/EvtFirework.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package ch.njol.skript.events;
-
-import ch.njol.skript.Skript;
-import ch.njol.skript.lang.Literal;
-import ch.njol.skript.lang.SkriptEvent;
-import ch.njol.skript.lang.SkriptParser.ParseResult;
-import ch.njol.skript.util.Color;
-import java.util.Arrays;
-import java.util.List;
-
-import ch.njol.skript.util.ColorRGB;
-import org.bukkit.FireworkEffect;
-import org.bukkit.event.Event;
-import org.bukkit.event.entity.FireworkExplodeEvent;
-import org.bukkit.inventory.meta.FireworkMeta;
-import org.jetbrains.annotations.Nullable;
-
-
-public class EvtFirework extends SkriptEvent {
-
- static {
- if (Skript.classExists("org.bukkit.event.entity.FireworkExplodeEvent"))
- //Making the event argument type fireworkeffects, led to Skript having troubles parsing for some reason.
- Skript.registerEvent("Firework Explode", EvtFirework.class, FireworkExplodeEvent.class, "[a] firework explo(d(e|ing)|sion) [colo[u]red %-colors%]")
- .description("Called when a firework explodes.")
- .examples("on firework explode:",
- "\tif event-colors contains red:",
- "on firework exploding colored red, light green and black:",
- "on firework explosion colored rgb 0, 255, 0:",
- "\tbroadcast \"A firework colored %colors% was exploded at %location%!\"")
- .since("2.4");
- }
-
- private @Nullable Literal colors;
-
- @SuppressWarnings("unchecked")
- @Override
- public boolean init(Literal>[] args, int matchedPattern, ParseResult parseResult) {
- if (args[0] != null)
- colors = (Literal) args[0];
- return true;
- }
-
- @Override
- public boolean check(Event event) {
- if (!(event instanceof FireworkExplodeEvent fireworkExplodeEvent))
- return false;
-
- if (colors == null)
- return true;
-
- List colours = colors.stream(event)
- .map(color -> {
- if (color instanceof ColorRGB)
- return color.asBukkitColor();
- return color.asDyeColor().getFireworkColor();
- })
- .toList();
- FireworkMeta meta = fireworkExplodeEvent.getEntity().getFireworkMeta();
- for (FireworkEffect effect : meta.getEffects()) {
- if (colours.containsAll(effect.getColors()))
- return true;
- }
- return false;
- }
-
- @Override
- public String toString(@Nullable Event e, boolean debug) {
- return "Firework explode " + (colors != null ? " with colors " + colors.toString(e, debug) : "");
- }
-
-}
diff --git a/src/main/java/ch/njol/skript/events/SimpleEvents.java b/src/main/java/ch/njol/skript/events/SimpleEvents.java
index 9997a21405b..4c996975f17 100644
--- a/src/main/java/ch/njol/skript/events/SimpleEvents.java
+++ b/src/main/java/ch/njol/skript/events/SimpleEvents.java
@@ -111,10 +111,6 @@ public class SimpleEvents {
.description("Called when an entity is set on fire, e.g. by fire or lava, a fireball, or by standing in direct sunlight (zombies, skeletons).")
.examples("on combust:")
.since("1.0");
- Skript.registerEvent("Explode", SimpleEvent.class, EntityExplodeEvent.class, "explo(d(e|ing)|sion)")
- .description("Called when an entity (a primed TNT or a creeper) explodes.")
- .examples("on explosion:")
- .since("1.0");
// Skript.registerEvent(SimpleEvent.class, EntityInteractEvent.class, "interact");// = entity interacts with block, e.g. endermen?; player -> PlayerInteractEvent // likely tripwires, pressure plates, etc.
Skript.registerEvent("Portal Enter", SimpleEvent.class, EntityPortalEnterEvent.class, "portal enter[ing]", "entering [a] portal")
.description("Called when an entity enters a nether portal or an end portal. Please note that this event will be fired many times for a nether portal.")
diff --git a/src/test/java/org/skriptlang/skript/test/tests/syntaxes/events/EvtFireworkTest.java b/src/test/java/org/skriptlang/skript/test/tests/syntaxes/events/EvtExplodeTest.java
similarity index 71%
rename from src/test/java/org/skriptlang/skript/test/tests/syntaxes/events/EvtFireworkTest.java
rename to src/test/java/org/skriptlang/skript/test/tests/syntaxes/events/EvtExplodeTest.java
index 75941ff7de6..953327f64e2 100644
--- a/src/test/java/org/skriptlang/skript/test/tests/syntaxes/events/EvtFireworkTest.java
+++ b/src/test/java/org/skriptlang/skript/test/tests/syntaxes/events/EvtExplodeTest.java
@@ -1,13 +1,17 @@
package org.skriptlang.skript.test.tests.syntaxes.events;
import ch.njol.skript.Skript;
+import ch.njol.skript.effects.EffExplosion;
import ch.njol.skript.test.runner.SkriptJUnitTest;
import ch.njol.skript.util.SkriptColor;
import org.bukkit.Bukkit;
+import org.bukkit.ExplosionResult;
import org.bukkit.FireworkEffect;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Firework;
+import org.bukkit.entity.Pig;
import org.bukkit.event.Event;
+import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.FireworkExplodeEvent;
import org.bukkit.inventory.meta.FireworkMeta;
import org.junit.After;
@@ -17,22 +21,26 @@
import java.util.ArrayList;
import java.util.List;
-public class EvtFireworkTest extends SkriptJUnitTest {
+public class EvtExplodeTest extends SkriptJUnitTest {
+
+ private Pig pig;
private EntityType entityType;
- private List fireworkList = new ArrayList<>();
+ private final List fireworkList = new ArrayList<>();
@Before
- public void getEntity() {
+ public void before() {
if (Skript.isRunningMinecraft(1, 20, 5)) {
entityType = EntityType.FIREWORK_ROCKET;
} else {
entityType = EntityType.valueOf("FIREWORK");
}
+
+ pig = spawnTestPig();
}
@Test
- public void callEvents() {
+ public void test() {
List events = new ArrayList<>();
for (SkriptColor color : SkriptColor.values()) {
Firework firework = (Firework) getTestWorld().spawnEntity(getTestLocation(), entityType);
@@ -44,13 +52,19 @@ public void callEvents() {
events.add(new FireworkExplodeEvent(firework));
}
+ events.add(new EffExplosion.ScriptExplodeEvent(getTestLocation(), 10));
+ events.add(new EntityExplodeEvent(pig, getTestLocation(), List.of(), 10,
+ ExplosionResult.DESTROY_WITH_DECAY));
+
for (Event event : events) {
Bukkit.getPluginManager().callEvent(event);
}
}
@After
- public void cleanUp() {
+ public void after() {
+ pig.remove();
+
for (Firework firework : fireworkList) {
firework.remove();
}
diff --git a/src/test/skript/junit/EvtExplodeTest.sk b/src/test/skript/junit/EvtExplodeTest.sk
new file mode 100644
index 00000000000..6e821ce57ca
--- /dev/null
+++ b/src/test/skript/junit/EvtExplodeTest.sk
@@ -0,0 +1,32 @@
+options:
+ EvtExplodeTest: "org.skriptlang.skript.test.tests.syntaxes.events.EvtExplodeTest"
+
+test "EvtExplodeJUnit" when running JUnit:
+ set {_tests::1} to "any firework"
+ loop all colors:
+ set {_tests::%loop-iteration + 1%} to "%loop-color% firework"
+
+ add "script explode" to {_tests::*}
+ add "entity explode" to {_tests::*}
+
+ ensure junit test {@EvtExplodeTest} completes {_tests::*}
+
+on scripted explode:
+ junit test is {@EvtExplodeTest}
+
+ if event-location is set:
+ complete objective "script explode" for {@EvtExplodeTest}
+
+on pig explode:
+ junit test is {@EvtExplodeTest}
+
+ if event-entity is pig:
+ complete objective "entity explode" for {@EvtExplodeTest}
+
+on firework explode:
+ junit test is {@EvtExplodeTest}
+
+ complete objective "any firework" for {@EvtExplodeTest}
+ if event-colors is set:
+ set {_color} to first element of event-colors
+ complete objective "%{_color}% firework" for {@EvtExplodeTest}
\ No newline at end of file
diff --git a/src/test/skript/junit/EvtFireworkTest.sk b/src/test/skript/junit/EvtFireworkTest.sk
deleted file mode 100644
index 9646a81a82d..00000000000
--- a/src/test/skript/junit/EvtFireworkTest.sk
+++ /dev/null
@@ -1,16 +0,0 @@
-options:
- EvtFireworkTest: "org.skriptlang.skript.test.tests.syntaxes.events.EvtFireworkTest"
-
-test "EvtFireworkJUnit" when running JUnit:
- set {_tests::1} to "any firework"
- loop all colors:
- set {_tests::%loop-iteration + 1%} to "%loop-color% firework"
-
- ensure junit test {@EvtFireworkTest} completes {_tests::*}
-
-on firework explode:
- junit test is {@EvtFireworkTest}
- complete objective "any firework" for {@EvtFireworkTest}
- if event-colors is set:
- set {_color} to first element of event-colors
- complete objective "%{_color}% firework" for {@EvtFireworkTest}