Commit d34ad93d56567278c29393de142716723cfb95af
1 parent
f9d96c14
support priority ordering in HandlerList
Showing
2 changed files
with
94 additions
and
1 deletions
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<T> extends LinkedList<T> implements FastIterableDeque<T | @@ -134,6 +143,16 @@ public class HandlerList<T> extends LinkedList<T> implements FastIterableDeque<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<T> extends LinkedList<T> implements FastIterableDeque<T | @@ -141,9 +160,61 @@ public class HandlerList<T> extends LinkedList<T> implements FastIterableDeque<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<T> extends LinkedList<T> implements FastIterableDeque<T | @@ -559,7 +630,7 @@ public class HandlerList<T> extends LinkedList<T> implements FastIterableDeque<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 | { |