Commit d34ad93d56567278c29393de142716723cfb95af

Authored by Mumfrey
1 parent f9d96c14

support priority ordering in HandlerList

java/common/com/mumfrey/liteloader/Priority.java 0 → 100644
  1 +package com.mumfrey.liteloader;
  2 +
  3 +import java.lang.annotation.ElementType;
  4 +import java.lang.annotation.Retention;
  5 +import java.lang.annotation.RetentionPolicy;
  6 +import java.lang.annotation.Target;
  7 +
  8 +/**
  9 + * Priority declaration for LiteMods, used when sorting listener lists. Default value if no Priority annotation
  10 + * is specified is 1000.
  11 + *
  12 + * @author Adam Mummery-Smith
  13 + */
  14 +@Target(ElementType.TYPE)
  15 +@Retention(RetentionPolicy.RUNTIME)
  16 +public @interface Priority
  17 +{
  18 + /**
  19 + * Priority value, default priority is 1000
  20 + */
  21 + public int value();
  22 +}
java/common/com/mumfrey/liteloader/core/event/HandlerList.java
@@ -5,6 +5,8 @@ import java.io.IOException; @@ -5,6 +5,8 @@ import java.io.IOException;
5 import java.lang.reflect.Constructor; 5 import java.lang.reflect.Constructor;
6 import java.net.URL; 6 import java.net.URL;
7 import java.net.URLClassLoader; 7 import java.net.URLClassLoader;
  8 +import java.util.ArrayList;
  9 +import java.util.Arrays;
8 import java.util.Collection; 10 import java.util.Collection;
9 import java.util.Iterator; 11 import java.util.Iterator;
10 import java.util.LinkedList; 12 import java.util.LinkedList;
@@ -20,8 +22,10 @@ import org.objectweb.asm.Opcodes; @@ -20,8 +22,10 @@ import org.objectweb.asm.Opcodes;
20 import org.objectweb.asm.Type; 22 import org.objectweb.asm.Type;
21 import org.objectweb.asm.tree.*; 23 import org.objectweb.asm.tree.*;
22 24
  25 +import com.mumfrey.liteloader.Priority;
23 import com.mumfrey.liteloader.core.runtime.Obf; 26 import com.mumfrey.liteloader.core.runtime.Obf;
24 import com.mumfrey.liteloader.interfaces.FastIterableDeque; 27 import com.mumfrey.liteloader.interfaces.FastIterableDeque;
  28 +import com.mumfrey.liteloader.util.SortableValue;
25 import com.mumfrey.liteloader.util.log.LiteLoaderLogger; 29 import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
26 30
27 /** 31 /**
@@ -121,6 +125,11 @@ public class HandlerList<T> extends LinkedList<T> implements FastIterableDeque<T @@ -121,6 +125,11 @@ public class HandlerList<T> extends LinkedList<T> implements FastIterableDeque<T
121 private BakedHandlerList<T> bakedHandler; 125 private BakedHandlerList<T> bakedHandler;
122 126
123 /** 127 /**
  128 + * True to sort the list when baking
  129 + */
  130 + private boolean sorted = true;
  131 +
  132 + /**
124 * @param type 133 * @param type
125 */ 134 */
126 public HandlerList(Class<T> type) 135 public HandlerList(Class<T> type)
@@ -134,6 +143,16 @@ public class HandlerList&lt;T&gt; extends LinkedList&lt;T&gt; implements FastIterableDeque&lt;T @@ -134,6 +143,16 @@ public class HandlerList&lt;T&gt; extends LinkedList&lt;T&gt; implements FastIterableDeque&lt;T
134 */ 143 */
135 public HandlerList(Class<T> type, ReturnLogicOp logicOp) 144 public HandlerList(Class<T> type, ReturnLogicOp logicOp)
136 { 145 {
  146 + this(type, logicOp, true);
  147 + }
  148 +
  149 + /**
  150 + * @param type
  151 + * @param logicOp Logical operation to apply to interface methods which return boolean
  152 + * @param sorted True to sort the list when baking (doesn't sort the underlying list)
  153 + */
  154 + public HandlerList(Class<T> type, ReturnLogicOp logicOp, boolean sorted)
  155 + {
137 if (!type.isInterface()) 156 if (!type.isInterface())
138 { 157 {
139 throw new IllegalArgumentException("HandlerList type argument must be an interface"); 158 throw new IllegalArgumentException("HandlerList type argument must be an interface");
@@ -141,9 +160,61 @@ public class HandlerList&lt;T&gt; extends LinkedList&lt;T&gt; implements FastIterableDeque&lt;T @@ -141,9 +160,61 @@ public class HandlerList&lt;T&gt; extends LinkedList&lt;T&gt; implements FastIterableDeque&lt;T
141 160
142 this.type = type; 161 this.type = type;
143 this.logicOp = logicOp; 162 this.logicOp = logicOp;
  163 + this.sorted = sorted;
144 } 164 }
145 165
146 /** 166 /**
  167 + * True if the list will be sorted by priority on bake
  168 + */
  169 + public boolean isSorted()
  170 + {
  171 + return this.sorted;
  172 + }
  173 +
  174 + /**
  175 + * Set whether to sort list entries before baking them
  176 + */
  177 + public void setSorted(boolean sorted)
  178 + {
  179 + this.sorted = sorted;
  180 + this.invalidate();
  181 + }
  182 +
  183 + @SuppressWarnings("unchecked")
  184 + protected List<T> getSortedList()
  185 + {
  186 + if (!this.sorted) return this;
  187 +
  188 + SortableValue<T>[] sortable = new SortableValue[this.size()];
  189 + for (int s = 0; s < this.size(); s++)
  190 + {
  191 + T value = this.get(s);
  192 + sortable[s] = new SortableValue<T>(this.getPriority(value), s, value);
  193 + }
  194 +
  195 + Arrays.sort(sortable);
  196 +
  197 + List<T> sortedList = new ArrayList<T>(this.size());
  198 + for (int s = 0; s < sortable.length; s++)
  199 + {
  200 + sortedList.add(sortable[s].getValue());
  201 + }
  202 +
  203 + return sortedList;
  204 + }
  205 +
  206 + private int getPriority(T value)
  207 + {
  208 + Priority priority = value.getClass().getAnnotation(Priority.class);
  209 + if (priority != null)
  210 + {
  211 + return priority.value();
  212 + }
  213 +
  214 + return 1000;
  215 + }
  216 +
  217 + /**
147 * Returns the baked list of all listeners 218 * Returns the baked list of all listeners
148 * 219 *
149 * @return 220 * @return
@@ -559,7 +630,7 @@ public class HandlerList&lt;T&gt; extends LinkedList&lt;T&gt; implements FastIterableDeque&lt;T @@ -559,7 +630,7 @@ public class HandlerList&lt;T&gt; extends LinkedList&lt;T&gt; implements FastIterableDeque&lt;T
559 { 630 {
560 // Create an instance of the class, populate the entries from the supplied list and return it 631 // Create an instance of the class, populate the entries from the supplied list and return it
561 BakedHandlerList<T> handlerList = this.createInstance(handlerClass); 632 BakedHandlerList<T> handlerList = this.createInstance(handlerClass);
562 - return handlerList.populate(list); 633 + return handlerList.populate(list.getSortedList());
563 } 634 }
564 catch (InstantiationException ex) 635 catch (InstantiationException ex)
565 { 636 {