diff --git a/src/main/java/ch/njol/skript/command/ScriptCommandEvent.java b/src/main/java/ch/njol/skript/command/ScriptCommandEvent.java index deed6c35be0..16e1b9df2cc 100644 --- a/src/main/java/ch/njol/skript/command/ScriptCommandEvent.java +++ b/src/main/java/ch/njol/skript/command/ScriptCommandEvent.java @@ -56,15 +56,26 @@ public boolean isCooldownCancelled() { return cooldownCancelled; } + /** + * @deprecated Use {@link #setCooldownCancelled(boolean, boolean)} instead. + */ + @Deprecated(since = "INSERT VERSION", forRemoval = true) public void setCooldownCancelled(boolean cooldownCancelled) { - if (Delay.isDelayed(this)) { - CommandSender sender = getSender(); - if (sender instanceof Player) { - Date date = cooldownCancelled ? null : executionDate; - scriptCommand.setLastUsage(((Player) sender).getUniqueId(), this, date); - } - } else { - this.cooldownCancelled = cooldownCancelled; + //noinspection removal + setCooldownCancelled(cooldownCancelled, Delay.isDelayed(this)); + } + + /** + * Sets whether the cooldown should be cancelled. + * + * @param cooldownCancelled Whether the cooldown should be cancelled. + * @param delayed Whether this event is delayed. If true, the sender's cooldown will be retroactively set. + */ + public void setCooldownCancelled(boolean cooldownCancelled, boolean delayed) { + this.cooldownCancelled = cooldownCancelled; + if (delayed && getSender() instanceof Player player) { + Date date = cooldownCancelled ? null : executionDate; + scriptCommand.setLastUsage(player.getUniqueId(), this, date); } } diff --git a/src/main/java/ch/njol/skript/effects/Delay.java b/src/main/java/ch/njol/skript/effects/Delay.java index 72e1a0dd786..72bdcdf5f45 100644 --- a/src/main/java/ch/njol/skript/effects/Delay.java +++ b/src/main/java/ch/njol/skript/effects/Delay.java @@ -5,12 +5,8 @@ import ch.njol.skript.doc.Examples; import ch.njol.skript.doc.Name; import ch.njol.skript.doc.Since; -import ch.njol.skript.lang.Effect; -import ch.njol.skript.lang.Expression; -import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.*; import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.lang.Trigger; -import ch.njol.skript.lang.TriggerItem; import ch.njol.skript.timings.SkriptTimings; import ch.njol.skript.util.Timespan; import ch.njol.skript.variables.Variables; @@ -112,7 +108,9 @@ public String toString(@Nullable Event event, boolean debug) { * The main method for checking if the execution of {@link TriggerItem}s has been delayed. * @param event The event to check for a delay. * @return Whether {@link TriggerItem} execution has been delayed. + * @deprecated Use {@link Trigger#isExecutionDelayed(Event)} or {@link TriggerItem#isExecutionDelayed(Event)} instead. */ + @Deprecated(since = "INSERT VERSION", forRemoval = true) public static boolean isDelayed(Event event) { return DELAYED.contains(event); } @@ -120,7 +118,9 @@ public static boolean isDelayed(Event event) { /** * The main method for marking the execution of {@link TriggerItem}s as delayed. * @param event The event to mark as delayed. + * @deprecated Use {@link Trigger#markExecutionAsDelayed(Event)} or {@link TriggerItem#markExecutionAsDelayed(Event)} instead. */ + @Deprecated(since = "INSERT VERSION", forRemoval = true) public static void addDelayedEvent(Event event) { DELAYED.add(event); } diff --git a/src/main/java/ch/njol/skript/effects/EffCancelCooldown.java b/src/main/java/ch/njol/skript/effects/EffCancelCooldown.java index a8706029d00..5bcc21f583d 100644 --- a/src/main/java/ch/njol/skript/effects/EffCancelCooldown.java +++ b/src/main/java/ch/njol/skript/effects/EffCancelCooldown.java @@ -1,12 +1,9 @@ package ch.njol.skript.effects; -import org.bukkit.event.Event; -import org.jetbrains.annotations.Nullable; - import ch.njol.skript.Skript; import ch.njol.skript.command.ScriptCommandEvent; import ch.njol.skript.doc.Description; -import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Example; import ch.njol.skript.doc.Name; import ch.njol.skript.doc.Since; import ch.njol.skript.lang.Effect; @@ -14,20 +11,23 @@ import ch.njol.skript.lang.SkriptParser; import ch.njol.skript.log.ErrorQuality; import ch.njol.util.Kleenean; +import org.bukkit.event.Event; +import org.jetbrains.annotations.Nullable; @Name("Cancel Command Cooldown") @Description({"Only usable in commands. Makes it so the current command usage isn't counted towards the cooldown."}) -@Examples({ - "command /nick <text>:", - "\texecutable by: players", - "\tcooldown: 10 seconds", - "\ttrigger:", - "\t\tif length of arg-1 is more than 16:", - "\t\t\t# Makes it so that invalid arguments don't make you wait for the cooldown again", - "\t\t\tcancel the cooldown", - "\t\t\tsend \"Your nickname may be at most 16 characters.\"", - "\t\t\tstop", - "\t\tset the player's display name to arg-1"}) +@Example(""" + command /nick <text>: + executable by: players + cooldown: 10 seconds + trigger: + if length of arg-1 is more than 16: + # Makes it so that invalid arguments don't make you wait for the cooldown again + cancel the cooldown + send "Your nickname may be at most 16 characters." + stop + set the player's display name to arg-1 + """) @Since("2.2-dev34") public class EffCancelCooldown extends Effect { @@ -50,15 +50,15 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye } @Override - protected void execute(Event e) { - if (!(e instanceof ScriptCommandEvent)) + protected void execute(Event event) { + if (!(event instanceof ScriptCommandEvent scriptCommandEvent)) return; - ((ScriptCommandEvent) e).setCooldownCancelled(cancel); + scriptCommandEvent.setCooldownCancelled(cancel, isExecutionDelayed(event)); } @Override - public String toString(@Nullable Event e, boolean debug) { + public String toString(@Nullable Event event, boolean debug) { return (cancel ? "" : "un") + "cancel the command cooldown"; } diff --git a/src/main/java/ch/njol/skript/effects/EffIgnite.java b/src/main/java/ch/njol/skript/effects/EffIgnite.java index 20392f897d3..6a9ee0cd13c 100644 --- a/src/main/java/ch/njol/skript/effects/EffIgnite.java +++ b/src/main/java/ch/njol/skript/effects/EffIgnite.java @@ -63,16 +63,11 @@ protected void execute(Event event) { duration = (int) timespan.getAs(Timespan.TimePeriod.TICK); } for (Entity entity : entities.getArray(event)) { - if (event instanceof EntityDamageEvent && ((EntityDamageEvent) event).getEntity() == entity && !Delay.isDelayed(event)) { - Bukkit.getScheduler().scheduleSyncDelayedTask(Skript.getInstance(), new Runnable() { - @Override - public void run() { - entity.setFireTicks(duration); - } - }); + if (event instanceof EntityDamageEvent entityDamageEvent && entityDamageEvent.getEntity() == entity && !isExecutionDelayed(event)) { + Bukkit.getScheduler().scheduleSyncDelayedTask(Skript.getInstance(), () -> entity.setFireTicks(duration)); } else { - if (event instanceof EntityCombustEvent && ((EntityCombustEvent) event).getEntity() == entity && !Delay.isDelayed(event)) - ((EntityCombustEvent) event).setCancelled(true);// can't change the duration, thus simply cancel the event (and create a new one) + if (event instanceof EntityCombustEvent entityCombustEvent && entityCombustEvent.getEntity() == entity && !isExecutionDelayed(event)) + entityCombustEvent.setCancelled(true);// can't change the duration, thus simply cancel the event (and create a new one) entity.setFireTicks(duration); } } diff --git a/src/main/java/ch/njol/skript/effects/EffKick.java b/src/main/java/ch/njol/skript/effects/EffKick.java index ef89ad297ea..6a4da32d033 100644 --- a/src/main/java/ch/njol/skript/effects/EffKick.java +++ b/src/main/java/ch/njol/skript/effects/EffKick.java @@ -1,68 +1,65 @@ package ch.njol.skript.effects; -import org.bukkit.entity.Player; -import org.bukkit.event.Event; -import org.bukkit.event.player.PlayerKickEvent; -import org.bukkit.event.player.PlayerLoginEvent; -import org.bukkit.event.player.PlayerLoginEvent.Result; -import org.jetbrains.annotations.Nullable; - import ch.njol.skript.Skript; import ch.njol.skript.doc.Description; -import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Example; import ch.njol.skript.doc.Name; import ch.njol.skript.doc.Since; import ch.njol.skript.lang.Effect; import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.util.Kleenean; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.player.PlayerKickEvent; +import org.bukkit.event.player.PlayerLoginEvent; +import org.bukkit.event.player.PlayerLoginEvent.Result; +import org.jetbrains.annotations.Nullable; -/** - * @author Peter Güttinger - */ @Name("Kick") @Description("Kicks a player from the server.") -@Examples({"on place of TNT, lava, or obsidian:", - " kick the player due to \"You may not place %block%!\"", - " cancel the event"}) +@Example(""" + on place of TNT, lava, or obsidian: + kick the player due to "You may not place %block%!" + cancel the event + """) @Since("1.0") public class EffKick extends Effect { static { Skript.registerEffect(EffKick.class, "kick %players% [(by reason of|because [of]|on account of|due to) %-string%]"); } - - @SuppressWarnings("null") + private Expression players; - @Nullable - private Expression reason; - - @SuppressWarnings({"unchecked", "null"}) + private @Nullable Expression reason; + @Override - public boolean init(final Expression[] exprs, final int matchedPattern, final Kleenean isDelayed, final ParseResult parseResult) { + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { players = (Expression) exprs[0]; reason = (Expression) exprs[1]; return true; } - - @Override - public String toString(final @Nullable Event e, final boolean debug) { - return "kick " + players.toString(e, debug) + (reason != null ? " on account of " + reason.toString(e, debug) : ""); - } - + @Override - protected void execute(final Event e) { - final String r = reason != null ? reason.getSingle(e) : ""; - if (r == null) + protected void execute(Event event) { + final String reasonString = reason != null ? reason.getSingle(event) : ""; + if (reasonString == null) return; - for (final Player p : players.getArray(e)) { - if (e instanceof PlayerLoginEvent && p.equals(((PlayerLoginEvent) e).getPlayer()) && !Delay.isDelayed(e)) { - ((PlayerLoginEvent) e).disallow(Result.KICK_OTHER, r); - } else if (e instanceof PlayerKickEvent && p.equals(((PlayerKickEvent) e).getPlayer()) && !Delay.isDelayed(e)) { - ((PlayerKickEvent) e).setLeaveMessage(r); + for (final Player player : players.getArray(event)) { + if (event instanceof PlayerLoginEvent playerLoginEvent && player.equals(playerLoginEvent.getPlayer()) && !isExecutionDelayed(event)) { + playerLoginEvent.disallow(Result.KICK_OTHER, reasonString); + } else if (event instanceof PlayerKickEvent playerKickEvent && player.equals(playerKickEvent.getPlayer()) && !isExecutionDelayed(event)) { + playerKickEvent.setLeaveMessage(reasonString); } else { - p.kickPlayer(r); + player.kickPlayer(reasonString); } } } + @Override + public String toString(@Nullable Event event, boolean debug) { + return "kick " + players.toString(event, debug) + + (reason != null ? " on account of " + reason.toString(event, debug) : ""); + } + } diff --git a/src/main/java/ch/njol/skript/effects/EffTeleport.java b/src/main/java/ch/njol/skript/effects/EffTeleport.java index 1dc3fe781b4..64e2342028c 100644 --- a/src/main/java/ch/njol/skript/effects/EffTeleport.java +++ b/src/main/java/ch/njol/skript/effects/EffTeleport.java @@ -84,7 +84,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye debug(event, true); TriggerItem next = getNext(); - boolean delayed = Delay.isDelayed(event); + boolean delayed = isExecutionDelayed(event); Location location = this.location.getSingle(event); if (location == null) return next; diff --git a/src/main/java/ch/njol/skript/expressions/ExprFoodLevel.java b/src/main/java/ch/njol/skript/expressions/ExprFoodLevel.java index 2ac18e7acba..6b8e3dc684d 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprFoodLevel.java +++ b/src/main/java/ch/njol/skript/expressions/ExprFoodLevel.java @@ -43,7 +43,7 @@ public boolean init(final Expression[] vars, final int matchedPattern, final protected Number[] get(Event event, Player[] source) { return get(source, player -> { if (getTime() >= 0 && event instanceof FoodLevelChangeEvent foodLevelChangeEvent - && player.equals(foodLevelChangeEvent.getEntity()) && !Delay.isDelayed(event)) { + && player.equals(foodLevelChangeEvent.getEntity()) && !isExecutionDelayed(event)) { return 0.5f * foodLevelChangeEvent.getFoodLevel(); } return 0.5f * player.getFoodLevel(); diff --git a/src/main/java/ch/njol/skript/lang/Trigger.java b/src/main/java/ch/njol/skript/lang/Trigger.java index 578ee748329..eaefe6602cb 100644 --- a/src/main/java/ch/njol/skript/lang/Trigger.java +++ b/src/main/java/ch/njol/skript/lang/Trigger.java @@ -1,11 +1,15 @@ package ch.njol.skript.lang; +import ch.njol.skript.effects.Delay; import ch.njol.skript.variables.Variables; import org.bukkit.event.Event; import org.jetbrains.annotations.Nullable; import org.skriptlang.skript.lang.script.Script; +import java.util.Collections; import java.util.List; +import java.util.Set; +import java.util.WeakHashMap; public class Trigger extends TriggerSection { @@ -16,6 +20,9 @@ public class Trigger extends TriggerSection { private int line = -1; // -1 is default: it means there is no line number available private String debugLabel; + private final Set delayedEvents = + Collections.synchronizedSet(Collections.newSetFromMap(new WeakHashMap<>())); + public Trigger(@Nullable Script script, String name, SkriptEvent event, List items) { super(items); this.script = script; @@ -102,4 +109,21 @@ public String getDebugLabel() { return debugLabel; } + /** + * @return Whether the execution of this trigger for this specific event has been delayed. + */ + public boolean isExecutionDelayed(Event event) { + return delayedEvents.contains(event); + } + + /** + * Marks the execution of this trigger for this specific event as delayed. + */ + public void markExecutionAsDelayed(Event event) { + delayedEvents.add(event); + // for backwards compatibility + //noinspection removal + Delay.addDelayedEvent(event); + } + } diff --git a/src/main/java/ch/njol/skript/lang/TriggerItem.java b/src/main/java/ch/njol/skript/lang/TriggerItem.java index d8a21916709..f009937405f 100644 --- a/src/main/java/ch/njol/skript/lang/TriggerItem.java +++ b/src/main/java/ch/njol/skript/lang/TriggerItem.java @@ -174,4 +174,28 @@ public TriggerItem setNext(@Nullable TriggerItem next) { return next; } + /** + * Whether there has been a delay between the event being fired and this item being executed. + * {@link TriggerItem}s without enclosing {@link Trigger}s will always return false. + * + * @see Trigger#isExecutionDelayed(Event) + */ + public boolean isExecutionDelayed(Event event) { + Trigger trigger = getTrigger(); + if (trigger == null) + return false; + return trigger.isExecutionDelayed(event); + } + + /** + * Marks this trigger's execution for this specific event as delayed. + * + * @see Trigger#markExecutionAsDelayed(Event) + */ + public void markExecutionAsDelayed(Event event) { + Trigger trigger = getTrigger(); + if (trigger != null) + trigger.markExecutionAsDelayed(event); + } + }