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