diff --git a/src/main/java/ch/njol/skript/expressions/ExprCreeperMaxFuseTicks.java b/src/main/java/ch/njol/skript/expressions/ExprCreeperMaxFuseTicks.java deleted file mode 100644 index a14766b6341..00000000000 --- a/src/main/java/ch/njol/skript/expressions/ExprCreeperMaxFuseTicks.java +++ /dev/null @@ -1,84 +0,0 @@ -package ch.njol.skript.expressions; - -import org.bukkit.entity.Creeper; -import org.bukkit.entity.LivingEntity; -import org.bukkit.event.Event; -import org.jetbrains.annotations.Nullable; - -import ch.njol.skript.Skript; -import ch.njol.skript.classes.Changer.ChangeMode; -import ch.njol.skript.doc.Description; -import ch.njol.skript.doc.Example; -import ch.njol.skript.doc.Name; -import ch.njol.skript.doc.Since; -import ch.njol.skript.expressions.base.SimplePropertyExpression; -import ch.njol.util.coll.CollectionUtils; - -@Name("Creeper Max Fuse Ticks") -@Description("The max fuse ticks that a creeper has.") -@Example("set target entity's max fuse ticks to 20 #1 second") -@Since("2.5") -public class ExprCreeperMaxFuseTicks extends SimplePropertyExpression { - - static { - if(Skript.methodExists(LivingEntity.class, "getMaxFuseTicks")) - register(ExprCreeperMaxFuseTicks.class, Long.class, "[creeper] max[imum] fuse tick[s]", "livingentities"); - } - - @Override - public Long convert(LivingEntity e) { - return e instanceof Creeper ? (long) ((Creeper) e).getMaxFuseTicks() : 0; - } - - @Override - @Nullable - public Class[] acceptChange(final ChangeMode mode) { - if (mode == ChangeMode.REMOVE_ALL) - return null; - return CollectionUtils.array(Number.class); - } - - @Override - public void change(final Event e, final @Nullable Object[] delta, final ChangeMode mode) { - int d = delta == null ? 0 : ((Number) delta[0]).intValue(); - for (LivingEntity le : getExpr().getArray(e)) { - if (le instanceof Creeper) { - Creeper c = (Creeper) le; - switch (mode) { - case ADD: - int r1 = c.getMaxFuseTicks() + d; - if (r1 < 0) r1 = 0; - c.setMaxFuseTicks(r1); - break; - case SET: - c.setMaxFuseTicks(d); - break; - case DELETE: - c.setMaxFuseTicks(0); - break; - case RESET: - c.setMaxFuseTicks(30); //Seems to be the same for powered creepers? - break; - case REMOVE: - int r2 = c.getMaxFuseTicks() - d; - if (r2 < 0) r2 = 0; - c.setMaxFuseTicks(r2); - break; - case REMOVE_ALL: - assert false; - } - } - } - } - - @Override - public Class getReturnType() { - return Long.class; - } - - @Override - protected String getPropertyName() { - return "creeper max fuse ticks"; - } - -} diff --git a/src/main/java/ch/njol/skript/expressions/ExprFuseDuration.java b/src/main/java/ch/njol/skript/expressions/ExprFuseDuration.java new file mode 100644 index 00000000000..87ac2710539 --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprFuseDuration.java @@ -0,0 +1,90 @@ +package ch.njol.skript.expressions; + +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Example; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.expressions.base.SimplePropertyExpression; +import ch.njol.skript.util.Timespan; +import ch.njol.util.Math2; +import ch.njol.util.coll.CollectionUtils; +import org.bukkit.entity.Creeper; +import org.bukkit.entity.Entity; +import org.bukkit.entity.TNTPrimed; +import org.bukkit.event.Event; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.registration.SyntaxRegistry; + +@Name("Fuse Duration") +@Description("The fuse duration of a creeper or primed TNT. For creepers, this is the total fuse duration before explosion. For primed TNT, this is the remaining time before explosion.") +@Example(""" + on spawn of a creeper: + set the fuse duration of the event-entity to 5 seconds + """) +@Example(""" + on spawn of primed tnt: + set fuse duration of event-entity to 10 seconds + """) +@Since("INSERT VERSION") +public class ExprFuseDuration extends SimplePropertyExpression { + + public static void register(SyntaxRegistry registry) { + registry.register( + SyntaxRegistry.EXPRESSION, + infoBuilder(ExprFuseDuration.class, Timespan.class, "fuse (duration|time)", "entities", false).build() + ); + } + + @Override + public @Nullable Timespan convert(Entity entity) { + if (entity instanceof Creeper creeper) + return new Timespan(Timespan.TimePeriod.TICK, creeper.getMaxFuseTicks()); + else if (entity instanceof TNTPrimed tnt) + return new Timespan(Timespan.TimePeriod.TICK, tnt.getFuseTicks()); + return null; + } + + @Override + public Class @Nullable [] acceptChange(ChangeMode mode) { + return switch (mode) { + case SET, DELETE, ADD, REMOVE -> CollectionUtils.array(Timespan.class); + default -> null; + }; + } + + @Override + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { + int ticks = delta != null && delta[0] instanceof Timespan ts + ? (int) Math2.fit(0, ts.get(Timespan.TimePeriod.TICK), Integer.MAX_VALUE) + : 0; + for (Entity entity : getExpr().getArray(event)) { + if (entity instanceof Creeper creeper) { + creeper.setMaxFuseTicks(Math2.fit(0, switch (mode) { + case SET, DELETE -> ticks; + case ADD -> creeper.getMaxFuseTicks() + ticks; + case REMOVE -> creeper.getMaxFuseTicks() - ticks; + default -> throw new IllegalArgumentException("Unexpected mode: " + mode); + }, Integer.MAX_VALUE)); + } else if (entity instanceof TNTPrimed tnt) { + tnt.setFuseTicks(Math2.fit(0, switch (mode) { + case SET, DELETE -> ticks; + case ADD -> tnt.getFuseTicks() + ticks; + case REMOVE -> tnt.getFuseTicks() - ticks; + default -> throw new IllegalArgumentException("Unexpected mode: " + mode); + }, Integer.MAX_VALUE)); + } + } + } + + @Override + public Class getReturnType() { + return Timespan.class; + } + + @Override + protected String getPropertyName() { + return "fuse duration"; + } + +} \ No newline at end of file diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java index 5e07c604ed6..e5721c2f0f1 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/EntityModule.java @@ -2,6 +2,7 @@ import ch.njol.skript.Skript; import ch.njol.skript.entity.SimpleEntityData; +import ch.njol.skript.expressions.ExprFuseDuration; import org.bukkit.entity.AbstractNautilus; import org.skriptlang.skript.addon.AddonModule; import org.skriptlang.skript.addon.HierarchicalAddonModule; @@ -38,7 +39,8 @@ protected void loadSelf(SkriptAddon addon) { } register(addon, - ExprDeathMessage::register + ExprDeathMessage::register, + ExprFuseDuration::register ); } diff --git a/src/test/skript/tests/syntaxes/expressions/ExprFuseDuration.sk b/src/test/skript/tests/syntaxes/expressions/ExprFuseDuration.sk new file mode 100644 index 00000000000..b5b101f2401 --- /dev/null +++ b/src/test/skript/tests/syntaxes/expressions/ExprFuseDuration.sk @@ -0,0 +1,25 @@ +test "creeper fuse duration": + spawn a creeper at test-location: + assert fuse duration of entity is 1.5 seconds with "fuse duration of a creeper should be 1.5 seconds by default" + set fuse duration of entity to 5 seconds + assert fuse duration of entity is 5 seconds with "fuse duration of creeper should be 5 seconds after setting to 5 seconds" + add 2.5 seconds to fuse duration of entity + assert fuse duration of entity is 7.5 seconds with "fuse duration of creeper should be 7.5 seconds after adding 2.5 seconds" + remove 10 seconds from fuse duration of entity + assert fuse duration of entity is 0 seconds with "fuse duration of creeper should be capped at 0 minimum" + delete fuse duration of entity + assert fuse duration of entity is 0 seconds with "fuse duration of creeper should be 0 seconds after deletion" + delete entity + +test "primed tnt fuse duration": + spawn a primed tnt at test-location: + assert fuse duration of entity is 4 seconds with "fuse duration of primed tnt should be 4 seconds by default" + set fuse duration of entity to 10 seconds + assert fuse duration of entity is 10 seconds with "fuse duration of primed tnt should be 10 seconds after setting to 10 seconds" + add 2.5 seconds to fuse duration of entity + assert fuse duration of entity is 12.5 seconds with "fuse duration of primed tnt should be 12.5 seconds after adding 2.5 seconds" + remove 15 seconds from fuse duration of entity + assert fuse duration of entity is 0 seconds with "fuse duration of primed tnt should be capped at 0 minimum" + delete fuse duration of entity + assert fuse duration of entity is 0 seconds with "fuse duration of primed tnt should be 0 seconds after deletion" + delete entity \ No newline at end of file