package lilypad.bukkit.connect.injector; import java.util.ArrayList; import java.util.EnumMap; import java.util.List; import lilypad.bukkit.connect.util.ReflectionUtils; import org.bukkit.event.Event; import org.bukkit.event.EventPriority; import org.bukkit.event.HandlerList; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.RegisteredListener; public class HandlerListInjector extends HandlerList { @SuppressWarnings("unchecked") public static void prioritize(Plugin plugin, Class<? extends Event> event) throws Exception { HandlerList handlerList = ReflectionUtils.getPrivateField(event, null, HandlerList.class, "handlers"); HandlerListInjector injector = new HandlerListInjector(plugin); // move the handlerslots EnumMap<EventPriority, ArrayList<RegisteredListener>> handlerListHandlerSlots = ReflectionUtils.getPrivateField(HandlerList.class, handlerList, EnumMap.class, "handlerslots"); EnumMap<EventPriority, ArrayList<RegisteredListener>> injectorHandlerSlots = ReflectionUtils.getPrivateField(HandlerList.class, injector, EnumMap.class, "handlerslots"); injectorHandlerSlots.putAll(handlerListHandlerSlots); // remove old from allLists ArrayList<HandlerList> allLists = ReflectionUtils.getPrivateField(HandlerList.class, null, ArrayList.class, "allLists"); allLists.remove(handlerList); // replace event handlers ReflectionUtils.setFinalField(event, null, "handlers", injector); } private Plugin plugin; private List<RegisteredListener> startListeners = new ArrayList<RegisteredListener>(); private List<RegisteredListener> middleListeners = new ArrayList<RegisteredListener>(); private List<RegisteredListener> endListeners = new ArrayList<RegisteredListener>(); private HandlerListInjector(Plugin plugin) { this.plugin = plugin; } @Override public synchronized void bake() { super.bake(); RegisteredListener[] handlers = super.getRegisteredListeners(); // TODO we can speed this up greatly using arrays. It's not really necessary though, as this isn't a hot function for(RegisteredListener handler : handlers) { if(handler.getPlugin().equals(plugin)) { if(handler.getPriority().equals(EventPriority.LOWEST)) { this.startListeners.add(handler); continue; } else if(handler.getPriority().equals(EventPriority.MONITOR)) { this.endListeners.add(handler); continue; } } this.middleListeners.add(handler); } List<RegisteredListener> handlerList = new ArrayList<RegisteredListener>(handlers.length); handlerList.addAll(this.startListeners); handlerList.addAll(this.middleListeners); handlerList.addAll(this.endListeners); handlerList.toArray(handlers); } }