Skip to content
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

Adds ability to listen to cancelled events #5896

Closed
wants to merge 6 commits into from
Closed
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
2 changes: 1 addition & 1 deletion src/main/java/ch/njol/skript/Skript.java
Original file line number Diff line number Diff line change
Expand Up @@ -1470,7 +1470,7 @@ public static <E extends SkriptEvent> SkriptEventInfo<E> registerEvent(String na

String[] transformedPatterns = new String[patterns.length];
for (int i = 0; i < patterns.length; i++)
transformedPatterns[i] = "[on] " + SkriptEvent.fixPattern(patterns[i]) + SkriptEventInfo.EVENT_PRIORITY_SYNTAX;
transformedPatterns[i] = "[on] [:all] " + SkriptEvent.fixPattern(patterns[i]) + SkriptEventInfo.EVENT_PRIORITY_SYNTAX;

SkriptEventInfo<E> r = new SkriptEventInfo<>(name, transformedPatterns, c, originClassPath, events);
structures.add(r);
Expand Down
55 changes: 33 additions & 22 deletions src/main/java/ch/njol/skript/SkriptEventHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,35 +109,33 @@ private static List<Trigger> getTriggers(Class<? extends Event> event) {
* @param priority The priority of the Event.
*/
private static void check(Event event, EventPriority priority) {
// Get all triggers for this event, return if there are none
List<Trigger> triggers = getTriggers(event.getClass());
if (triggers.isEmpty())
return;

if (Skript.logVeryHigh()) {
boolean hasTrigger = false;
for (Trigger trigger : triggers) {
SkriptEvent triggerEvent = trigger.getEvent();
if (triggerEvent.getEventPriority() == priority && triggerEvent.check(event)) {
hasTrigger = true;
break;
}
}
if (!hasTrigger)
return;
// This handles cancelled left/right clicks on air. Left/right clicks on air are called as cancelled, making isCancelled() unreliable.
// Checking useItemInHand() is a reliable method, as it will be DENY if the event was specifically cancelled.
// Note that right clicks on air with nothing in hand aren't ever sent to the server.
boolean isResultDeny = !(event instanceof PlayerInteractEvent &&
(((PlayerInteractEvent) event).getAction() == Action.LEFT_CLICK_AIR || ((PlayerInteractEvent) event).getAction() == Action.RIGHT_CLICK_AIR) &&
((PlayerInteractEvent) event).useItemInHand() != Result.DENY);

logEventStart(event);
}

boolean isCancelled = event instanceof Cancellable && ((Cancellable) event).isCancelled() && !listenCancelled.contains(event.getClass());
boolean isResultDeny = !(event instanceof PlayerInteractEvent && (((PlayerInteractEvent) event).getAction() == Action.LEFT_CLICK_AIR || ((PlayerInteractEvent) event).getAction() == Action.RIGHT_CLICK_AIR) && ((PlayerInteractEvent) event).useItemInHand() != Result.DENY);
// Check if this event should be treated as cancelled
boolean isCancelled = event instanceof Cancellable &&
(((Cancellable) event).isCancelled() && isResultDeny) &&
!listenCancelled.contains(event.getClass());

if (isCancelled && isResultDeny) {
if (Skript.logVeryHigh())
Skript.info(" -x- was cancelled");
return;
}
// This now logs events even if there isn't a trigger that's going to run at that priority.
// However, there should only be a priority listener IF there's a trigger at that priority.
// So the only change is that the time will be logged even if no triggers pass check(),
// which is still useful information.
logEventStart(event, priority);

for (Trigger trigger : triggers) {
SkriptEvent triggerEvent = trigger.getEvent();
if (triggerEvent.getEventPriority() != priority || !triggerEvent.check(event))
// Check if the trigger should be executed (matches priority, should be called if cancelled, and passes event.check())
if (triggerEvent.getEventPriority() != priority || (isCancelled && triggerEvent.shouldIgnoreCancelled()) || !triggerEvent.check(event))
continue;

logTriggerStart(trigger);
Expand Down Expand Up @@ -167,6 +165,19 @@ public static void logEventStart(Event event) {
Skript.info("== " + event.getClass().getName() + " ==");
}

/**
* Logs that the provided Event has started with a priority.
* Requires {@link Skript#logVeryHigh()} to be true to log anything.
* @param event The Event that started.
*/
public static void logEventStart(Event event, EventPriority priority) {
startEvent = System.nanoTime();
if (!Skript.logVeryHigh())
return;
Skript.info("");
Skript.info("== " + event.getClass().getName() + " with priority " + priority + " ==");
}

/**
* Logs that the last logged Event start has ended.
* Includes the number of milliseconds execution took.
Expand Down
33 changes: 20 additions & 13 deletions src/main/java/ch/njol/skript/lang/SkriptEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,14 @@
import ch.njol.skript.config.SectionNode;
import ch.njol.skript.events.EvtClick;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import org.skriptlang.skript.lang.script.Script;
import org.skriptlang.skript.lang.entry.EntryContainer;
import org.skriptlang.skript.lang.structure.Structure;
import ch.njol.util.StringUtils;
import org.bukkit.event.Event;
import org.bukkit.event.EventPriority;
import org.eclipse.jdt.annotation.Nullable;
import org.skriptlang.skript.lang.entry.EntryContainer;
import org.skriptlang.skript.lang.script.Script;
import org.skriptlang.skript.lang.structure.Structure;

import java.util.Arrays;
import java.util.List;
import java.util.Locale;

Expand All @@ -56,6 +55,7 @@ public abstract class SkriptEvent extends Structure {
@Nullable
protected EventPriority eventPriority;
private SkriptEventInfo<?> skriptEventInfo;
protected boolean ignoreCancelled = true;

/**
* The Trigger containing this SkriptEvent's code.
Expand All @@ -64,21 +64,16 @@ public abstract class SkriptEvent extends Structure {

@Override
public final boolean init(Literal<?>[] args, int matchedPattern, ParseResult parseResult, EntryContainer entryContainer) {
String expr = parseResult.expr;
if (StringUtils.startsWithIgnoreCase(expr, "on "))
expr = expr.substring("on ".length());
ignoreCancelled = !parseResult.hasTag("all");

String[] split = expr.split(" with priority ");
if (split.length != 1) {
if (parseResult.hasTag("priority")) {
if (!isEventPrioritySupported()) {
Skript.error("This event doesn't support event priority");
return false;
}

expr = String.join(" with priority ", Arrays.copyOfRange(split, 0, split.length - 1));

String priorityString = split[split.length - 1];
try {
String priorityString = parseResult.tags.get(parseResult.tags.size() - 1);
eventPriority = EventPriority.valueOf(priorityString.toUpperCase());
} catch (IllegalArgumentException e) {
throw new IllegalStateException(e);
Expand All @@ -87,7 +82,12 @@ public final boolean init(Literal<?>[] args, int matchedPattern, ParseResult par
eventPriority = null;
}

this.expr = parseResult.expr = expr;
this.expr = parseResult.expr;

// remove "on " from the beginning of the expression for better readability in logs
if (StringUtils.startsWithIgnoreCase(expr, "on ")) {
expr = expr.substring("on ".length());
}

SyntaxElementInfo<? extends Structure> syntaxElementInfo = getParser().getData(StructureData.class).getStructureInfo();
if (!(syntaxElementInfo instanceof SkriptEventInfo))
Expand Down Expand Up @@ -216,6 +216,13 @@ public boolean isEventPrioritySupported() {
return true;
}

/**
* @return whether this SkriptEvent will ignore cancelled events
*/
public boolean shouldIgnoreCancelled() {
return ignoreCancelled;
}

/**
* Fixes patterns in event by modifying every {@link ch.njol.skript.patterns.TypePatternElement}
* to be nullable.
Expand Down
9 changes: 4 additions & 5 deletions src/main/java/ch/njol/skript/lang/SkriptEventInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,17 @@
*/
package ch.njol.skript.lang;

import java.util.Locale;

import org.skriptlang.skript.lang.structure.StructureInfo;
import ch.njol.skript.SkriptAPIException;
import org.bukkit.event.Event;
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
import org.eclipse.jdt.annotation.Nullable;
import org.skriptlang.skript.lang.structure.StructureInfo;

import ch.njol.skript.SkriptAPIException;
import java.util.Locale;

public final class SkriptEventInfo<E extends SkriptEvent> extends StructureInfo<E> {

public static final String EVENT_PRIORITY_SYNTAX = " [with priority (lowest|low|normal|high|highest|monitor)]";
public static final String EVENT_PRIORITY_SYNTAX = " [priority:with priority (:lowest|:low|:normal|:high|:highest|:monitor)]";

public Class<? extends Event>[] events;
public final String name;
Expand Down