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 | { |