Skip to content

Improve API for tracking delayed execution at runtime. #7777

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: dev/feature
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions src/main/java/ch/njol/skript/command/ScriptCommandEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
10 changes: 5 additions & 5 deletions src/main/java/ch/njol/skript/effects/Delay.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -112,15 +108,19 @@ 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);
}

/**
* 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);
}
Expand Down
38 changes: 19 additions & 19 deletions src/main/java/ch/njol/skript/effects/EffCancelCooldown.java
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
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;
import ch.njol.skript.lang.Expression;
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 {

Expand All @@ -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";
}

Expand Down
13 changes: 4 additions & 9 deletions src/main/java/ch/njol/skript/effects/EffIgnite.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
69 changes: 33 additions & 36 deletions src/main/java/ch/njol/skript/effects/EffKick.java
Original file line number Diff line number Diff line change
@@ -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<Player> players;
@Nullable
private Expression<String> reason;

@SuppressWarnings({"unchecked", "null"})
private @Nullable Expression<String> 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<Player>) exprs[0];
reason = (Expression<String>) 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) : "");
}

}
2 changes: 1 addition & 1 deletion src/main/java/ch/njol/skript/effects/EffTeleport.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/ch/njol/skript/lang/Trigger.java
Original file line number Diff line number Diff line change
@@ -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 {

Expand All @@ -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<Event> delayedEvents =
Collections.synchronizedSet(Collections.newSetFromMap(new WeakHashMap<>()));

public Trigger(@Nullable Script script, String name, SkriptEvent event, List<TriggerItem> items) {
super(items);
this.script = script;
Expand Down Expand Up @@ -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);
}

}
24 changes: 24 additions & 0 deletions src/main/java/ch/njol/skript/lang/TriggerItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

}
Loading