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 | 5 | import java.lang.reflect.Constructor; |
| 6 | 6 | import java.net.URL; |
| 7 | 7 | import java.net.URLClassLoader; |
| 8 | +import java.util.ArrayList; | |
| 9 | +import java.util.Arrays; | |
| 8 | 10 | import java.util.Collection; |
| 9 | 11 | import java.util.Iterator; |
| 10 | 12 | import java.util.LinkedList; |
| ... | ... | @@ -20,8 +22,10 @@ import org.objectweb.asm.Opcodes; |
| 20 | 22 | import org.objectweb.asm.Type; |
| 21 | 23 | import org.objectweb.asm.tree.*; |
| 22 | 24 | |
| 25 | +import com.mumfrey.liteloader.Priority; | |
| 23 | 26 | import com.mumfrey.liteloader.core.runtime.Obf; |
| 24 | 27 | import com.mumfrey.liteloader.interfaces.FastIterableDeque; |
| 28 | +import com.mumfrey.liteloader.util.SortableValue; | |
| 25 | 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 | 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 | 133 | * @param type |
| 125 | 134 | */ |
| 126 | 135 | public HandlerList(Class<T> type) |
| ... | ... | @@ -134,6 +143,16 @@ public class HandlerList<T> extends LinkedList<T> implements FastIterableDeque<T |
| 134 | 143 | */ |
| 135 | 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 | 156 | if (!type.isInterface()) |
| 138 | 157 | { |
| 139 | 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 | 160 | |
| 142 | 161 | this.type = type; |
| 143 | 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 | 218 | * Returns the baked list of all listeners |
| 148 | 219 | * |
| 149 | 220 | * @return |
| ... | ... | @@ -559,7 +630,7 @@ public class HandlerList<T> extends LinkedList<T> implements FastIterableDeque<T |
| 559 | 630 | { |
| 560 | 631 | // Create an instance of the class, populate the entries from the supplied list and return it |
| 561 | 632 | BakedHandlerList<T> handlerList = this.createInstance(handlerClass); |
| 562 | - return handlerList.populate(list); | |
| 633 | + return handlerList.populate(list.getSortedList()); | |
| 563 | 634 | } |
| 564 | 635 | catch (InstantiationException ex) |
| 565 | 636 | { | ... | ... |