Skip to content

Commit

Permalink
allow specifying bukkit event priority for world scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
mcmonkey4eva committed Mar 6, 2019
1 parent 626899e commit 463b8d2
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 42 deletions.
Expand Up @@ -2,6 +2,7 @@

import net.aufdemrand.denizen.objects.*;
import net.aufdemrand.denizen.tags.BukkitTagContext;
import net.aufdemrand.denizen.utilities.DenizenAPI;
import net.aufdemrand.denizen.utilities.debugging.dB;
import net.aufdemrand.denizencore.events.ScriptEvent;
import net.aufdemrand.denizencore.scripts.containers.ScriptContainer;
Expand All @@ -12,11 +13,155 @@
import org.bukkit.entity.Hanging;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.Vehicle;
import org.bukkit.event.Event;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.plugin.EventExecutor;
import org.bukkit.plugin.IllegalPluginAccessException;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredListener;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Pattern;

public abstract class BukkitScriptEvent extends ScriptEvent {

public Class<? extends Event> getRegistrationClass(Class<? extends Event> clazz) {
try {
clazz.getDeclaredMethod("getHandlerList");
return clazz;
} catch (NoSuchMethodException var3) {
if (clazz.getSuperclass() != null && !clazz.getSuperclass().equals(Event.class) && Event.class.isAssignableFrom(clazz.getSuperclass())) {
return getRegistrationClass(clazz.getSuperclass().asSubclass(Event.class));
} else {
throw new IllegalPluginAccessException("Unable to find handler list for event " + clazz.getName() + ". Static getHandlerList method required!");
}
}
}

public HandlerList getEventListeners(Class<? extends Event> type) {
try {
Method method = getRegistrationClass(type).getDeclaredMethod("getHandlerList");
method.setAccessible(true);
return (HandlerList)method.invoke(null);
} catch (Exception var3) {
throw new IllegalPluginAccessException(var3.toString());
}
}

private static Field REGISTERED_LISTENER_EXECUTOR_FIELD;

static {
try {
REGISTERED_LISTENER_EXECUTOR_FIELD = RegisteredListener.class.getDeclaredField("executor");
REGISTERED_LISTENER_EXECUTOR_FIELD.setAccessible(true);
}
catch (NoSuchFieldException ex) {
dB.echoError(ex);
}
}

public EventExecutor getExecutor(RegisteredListener listener) {
try {
return (EventExecutor) REGISTERED_LISTENER_EXECUTOR_FIELD.get(listener);
}
catch (IllegalAccessException ex) {
dB.echoError(ex);
}
return null;
}

public HashMap<EventPriority, BukkitScriptEvent> priorityHandlers;

public List<Map.Entry<RegisteredListener, HandlerList>> registeredHandlers;

// <--[language]
// @name bukkit event priority
// @description
// Script events that are backed by standard Bukkit events are able to control what underlying Bukkit event priority
// they register as.
// This can be useful, for example, if a different plugin is cancelling the event at a later priority,
// and you're writing a script that needs to un-cancel the event.
// This can be done using the "bukkit_priority" switch.
// Valid priorities, in order of execution, are: LOWEST, LOW, NORMAL, HIGH, HIGHEST, MONITOR.
// Monitor is executed last, and is intended to only be used when reading the results of an event but not changing it.
// The default priority is "normal".
// -->

@Override
public void destroy() {
if (priorityHandlers != null) {
for (BukkitScriptEvent event : priorityHandlers.values()) {
event.destroy();
}
priorityHandlers = null;
}
if (registeredHandlers != null) {
for (Map.Entry<RegisteredListener, HandlerList> handler : registeredHandlers) {
handler.getValue().unregister(handler.getKey());
}
registeredHandlers = null;
}
}

@Override
public void init() {
if (this instanceof Listener) {
initListener((Listener) this);
}
}

public void initListener(Listener listener) {
if (priorityHandlers == null) {
priorityHandlers = new HashMap<>();
}
for (ScriptPath path : new ArrayList<>(eventPaths)) {
String bukkitPriority = path.switches.get("bukkit_priority");
if (bukkitPriority != null) {
try {
EventPriority priority = EventPriority.valueOf(bukkitPriority.toUpperCase());
BukkitScriptEvent handler = priorityHandlers.get(priority);
if (handler == null) {
handler = (BukkitScriptEvent) clone();
handler.eventPaths = new ArrayList<>();
handler.priorityHandlers = null;
handler.registeredHandlers = null;
priorityHandlers.put(priority, handler);
handler.initForPriority(priority, (Listener) handler);
}
handler.eventPaths.add(path);
eventPaths.remove(path);
}
catch (IllegalArgumentException ex) {
dB.echoError("Invalid 'bukkit_priority' switch for event '" + path.event + "' in script '" + path.container.getName() + "'.");
dB.echoError(ex);
}
}
}
if (!eventPaths.isEmpty()) {
initForPriority(EventPriority.NORMAL, listener);
}
}

public void initForPriority(EventPriority priority, Listener listener) {
if (registeredHandlers == null) {
registeredHandlers = new ArrayList<>();
}
Plugin plugin = DenizenAPI.getCurrentInstance();
for (Map.Entry<Class<? extends Event>, Set<RegisteredListener>> entry :
plugin.getPluginLoader().createRegisteredListeners(listener, plugin).entrySet()) {
for (RegisteredListener registeredListener : entry.getValue()) {
RegisteredListener newListener = new RegisteredListener(listener, getExecutor(registeredListener), priority, plugin, false);
HandlerList handlers = getEventListeners(getRegistrationClass(entry.getKey()));
handlers.register(newListener);
registeredHandlers.add(new HashMap.SimpleEntry<>(newListener, handlers));
}
}
}

@Deprecated
public boolean runInCheck(ScriptContainer scriptContainer, String s, String lower, Location location) {
return runInCheck(scriptContainer, s, lower, location, "in");
Expand Down
Expand Up @@ -48,7 +48,6 @@ public boolean couldMatch(ScriptContainer scriptContainer, String s) {

@Override
public boolean matches(ScriptPath path) {
String s = path.event;
String lower = path.eventLower;
String target = CoreUtilities.getXthArg(0, lower);

Expand All @@ -72,14 +71,6 @@ public String getName() {
return "EntityDespawn";
}

@Override
public void init() {
}

@Override
public void destroy() {
}

@Override
public boolean applyDetermination(ScriptContainer container, String determination) {
return super.applyDetermination(container, determination);
Expand Down
Expand Up @@ -4,13 +4,11 @@
import net.aufdemrand.denizen.events.BukkitScriptEvent;
import net.aufdemrand.denizen.objects.dEntity;
import net.aufdemrand.denizen.objects.dLocation;
import net.aufdemrand.denizen.utilities.DenizenAPI;
import net.aufdemrand.denizencore.objects.Element;
import net.aufdemrand.denizencore.objects.dObject;
import net.aufdemrand.denizencore.scripts.ScriptEntryData;
import net.aufdemrand.denizencore.scripts.containers.ScriptContainer;
import net.aufdemrand.denizencore.utilities.CoreUtilities;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
Expand Down Expand Up @@ -67,7 +65,6 @@ public boolean couldMatch(ScriptContainer scriptContainer, String s) {

@Override
public boolean matches(ScriptPath path) {
String s = path.event;
String lower = path.eventLower;

if (!tryEntity(entity, CoreUtilities.getXthArg(0, lower))) {
Expand All @@ -86,12 +83,6 @@ public String getName() {
return "EntityTeleports";
}

@Override
public void destroy() {
EntityTeleportEvent.getHandlerList().unregister(this);
PlayerTeleportEvent.getHandlerList().unregister(this);
}

@Override
public boolean applyDetermination(ScriptContainer container, String determination) {
String dlow = CoreUtilities.toLowerCase(determination);
Expand Down
Expand Up @@ -6,7 +6,6 @@
import net.aufdemrand.denizen.objects.dEntity;
import net.aufdemrand.denizen.objects.dPlayer;
import net.aufdemrand.denizen.scripts.containers.core.FormatScriptContainer;
import net.aufdemrand.denizen.utilities.DenizenAPI;
import net.aufdemrand.denizen.utilities.debugging.dB;
import net.aufdemrand.denizencore.objects.Element;
import net.aufdemrand.denizencore.objects.dList;
Expand All @@ -15,7 +14,6 @@
import net.aufdemrand.denizencore.scripts.ScriptRegistry;
import net.aufdemrand.denizencore.scripts.containers.ScriptContainer;
import net.aufdemrand.denizencore.utilities.CoreUtilities;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
Expand Down Expand Up @@ -91,20 +89,10 @@ public String getName() {
public void init() {
async = Settings.worldScriptChatEventAsynchronous();
if (async) {
Bukkit.getServer().getPluginManager().registerEvents(asch, DenizenAPI.getCurrentInstance());
initListener(asch);
}
else {
Bukkit.getServer().getPluginManager().registerEvents(sch, DenizenAPI.getCurrentInstance());
}
}

@Override
public void destroy() {
if (async) {
AsyncPlayerChatEvent.getHandlerList().unregister(asch);
}
else {
PlayerChatEvent.getHandlerList().unregister(sch);
initListener(sch);
}
}

Expand Down
Expand Up @@ -19,7 +19,6 @@
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockDispenseEvent;
import org.bukkit.event.entity.EntityDamageEvent;
Expand Down Expand Up @@ -65,7 +64,6 @@ public boolean couldMatch(ScriptContainer scriptContainer, String s) {

@Override
public boolean matches(ScriptPath path) {
String s = path.event;
String lower = path.eventLower;
String type = CoreUtilities.getXthArg(1, lower);

Expand All @@ -88,11 +86,6 @@ public String getName() {
return "PlayerEquipsArmor";
}

@Override
public void destroy() {
HandlerList.unregisterAll(this);
}

@Override
public boolean applyDetermination(ScriptContainer container, String determination) {
return super.applyDetermination(container, determination);
Expand Down
Expand Up @@ -1523,9 +1523,9 @@ public static void adjustServer(Mechanism mechanism) {
// -->
if (mechanism.matches("reset_event_stats")) {
for (ScriptEvent se : ScriptEvent.events) {
se.fires = 0;
se.scriptFires = 0;
se.nanoTimes = 0;
se.stats.fires = 0;
se.stats.scriptFires = 0;
se.stats.nanoTimes = 0;
}
}

Expand Down

0 comments on commit 463b8d2

Please sign in to comment.