Commit 181d76f766096fff24e1872468311ca6b0953931

Authored by Mumfrey
1 parent 64ec9596

support for baking listener lists to classes

java/client/com/mumfrey/liteloader/client/ClientEvents.java
1 package com.mumfrey.liteloader.client; 1 package com.mumfrey.liteloader.client;
2 2
3 -import java.util.LinkedList;  
4 -  
5 import net.minecraft.client.Minecraft; 3 import net.minecraft.client.Minecraft;
6 import net.minecraft.client.entity.EntityClientPlayerMP; 4 import net.minecraft.client.entity.EntityClientPlayerMP;
7 import net.minecraft.client.gui.GuiNewChat; 5 import net.minecraft.client.gui.GuiNewChat;
@@ -29,6 +27,7 @@ import com.mumfrey.liteloader.core.ClientPluginChannels; @@ -29,6 +27,7 @@ import com.mumfrey.liteloader.core.ClientPluginChannels;
29 import com.mumfrey.liteloader.core.Events; 27 import com.mumfrey.liteloader.core.Events;
30 import com.mumfrey.liteloader.core.InterfaceRegistrationDelegate; 28 import com.mumfrey.liteloader.core.InterfaceRegistrationDelegate;
31 import com.mumfrey.liteloader.core.LiteLoader; 29 import com.mumfrey.liteloader.core.LiteLoader;
  30 +import com.mumfrey.liteloader.core.event.HandlerList;
32 import com.mumfrey.liteloader.launch.LoaderProperties; 31 import com.mumfrey.liteloader.launch.LoaderProperties;
33 import com.mumfrey.liteloader.transformers.event.EventInfo; 32 import com.mumfrey.liteloader.transformers.event.EventInfo;
34 import com.mumfrey.liteloader.util.log.LiteLoaderLogger; 33 import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
@@ -76,95 +75,6 @@ public class ClientEvents extends Events<Minecraft, IntegratedServer> @@ -76,95 +75,6 @@ public class ClientEvents extends Events<Minecraft, IntegratedServer>
76 * 75 *
77 */ 76 */
78 private boolean wasFullScreen = false; 77 private boolean wasFullScreen = false;
79 -  
80 - /**  
81 - * List of mods which implement Tickable interface and will receive tick  
82 - * events  
83 - */  
84 - private LinkedList<Tickable> tickListeners = new LinkedList<Tickable>();  
85 -  
86 - /**  
87 - * List of mods which implement the GameLoopListener interface and will  
88 - * receive loop events  
89 - */  
90 - private LinkedList<GameLoopListener> loopListeners = new LinkedList<GameLoopListener>();  
91 -  
92 - /**  
93 - *  
94 - */  
95 - private LinkedList<InitCompleteListener> initListeners = new LinkedList<InitCompleteListener>();  
96 -  
97 - /**  
98 - * List of mods which implement RenderListener interface and will receive  
99 - * render events events  
100 - */  
101 - private LinkedList<RenderListener> renderListeners = new LinkedList<RenderListener>();  
102 -  
103 - /**  
104 - * List of mods which implement the PostRenderListener interface and want to  
105 - * render entities  
106 - */  
107 - private LinkedList<PostRenderListener> postRenderListeners = new LinkedList<PostRenderListener>();  
108 -  
109 - /**  
110 - * List of mods which implement HUDRenderListener and want callbacks when HUD is rendered  
111 - */  
112 - private LinkedList<HUDRenderListener> hudRenderListeners = new LinkedList<HUDRenderListener>();  
113 -  
114 - /**  
115 - * List of mods which implement ChatRenderListener and want to know when  
116 - * chat is rendered  
117 - */  
118 - private LinkedList<ChatRenderListener> chatRenderListeners = new LinkedList<ChatRenderListener>();  
119 -  
120 - /**  
121 - * List of mods which implement ChatListener interface and will receive chat  
122 - * events  
123 - */  
124 - private LinkedList<ChatListener> chatListeners = new LinkedList<ChatListener>();  
125 -  
126 - /**  
127 - * List of mods which implement ChatFilter interface and will receive chat  
128 - * filter events  
129 - */  
130 - private LinkedList<ChatFilter> chatFilters = new LinkedList<ChatFilter>();  
131 -  
132 - /**  
133 - * List of mods which implement PostLoginListener and want to be notified post login  
134 - */  
135 - private LinkedList<PostLoginListener> postLoginListeners = new LinkedList<PostLoginListener>();  
136 -  
137 - /**  
138 - * List of mods which implement LoginListener interface and will receive  
139 - * client login events  
140 - */  
141 - private LinkedList<JoinGameListener> joinGameListeners = new LinkedList<JoinGameListener>();  
142 -  
143 - /**  
144 - * List of mods which implement LoginListener interface and will receive  
145 - * client login events  
146 - */  
147 - private LinkedList<PreJoinGameListener> preJoinGameListeners = new LinkedList<PreJoinGameListener>();  
148 -  
149 - /**  
150 - * List of mods which monitor outbound chat  
151 - */  
152 - private LinkedList<OutboundChatListener> outboundChatListeners = new LinkedList<OutboundChatListener>();  
153 -  
154 - /**  
155 - * List of mods which filter outbound chat  
156 - */  
157 - private LinkedList<OutboundChatFilter> outboundChatFilters = new LinkedList<OutboundChatFilter>();  
158 -  
159 - /**  
160 - * List of mods which monitor changes in the viewport  
161 - */  
162 - private LinkedList<ViewportListener> viewportListeners = new LinkedList<ViewportListener>();  
163 -  
164 - /**  
165 - * List of mods which interact with the main minecraft FBO  
166 - */  
167 - private LinkedList<FrameBufferListener> frameBufferListeners = new LinkedList<FrameBufferListener>();  
168 78
169 /** 79 /**
170 * Hash code of the current world. We don't store the world reference here because we don't want 80 * Hash code of the current world. We don't store the world reference here because we don't want
@@ -172,6 +82,23 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -172,6 +82,23 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
172 */ 82 */
173 private int worldHashCode = 0; 83 private int worldHashCode = 0;
174 84
  85 + private HandlerList<Tickable> tickListeners = new HandlerList<Tickable>(Tickable.class);
  86 + private HandlerList<GameLoopListener> loopListeners = new HandlerList<GameLoopListener>(GameLoopListener.class);
  87 + private HandlerList<RenderListener> renderListeners = new HandlerList<RenderListener>(RenderListener.class);
  88 + private HandlerList<PostRenderListener> postRenderListeners = new HandlerList<PostRenderListener>(PostRenderListener.class);
  89 + private HandlerList<HUDRenderListener> hudRenderListeners = new HandlerList<HUDRenderListener>(HUDRenderListener.class);
  90 + private HandlerList<ChatRenderListener> chatRenderListeners = new HandlerList<ChatRenderListener>(ChatRenderListener.class);
  91 + private HandlerList<ChatListener> chatListeners = new HandlerList<ChatListener>(ChatListener.class);
  92 + private HandlerList<PostLoginListener> postLoginListeners = new HandlerList<PostLoginListener>(PostLoginListener.class);
  93 + private HandlerList<JoinGameListener> joinGameListeners = new HandlerList<JoinGameListener>(JoinGameListener.class);
  94 + private HandlerList<OutboundChatListener> outboundChatListeners = new HandlerList<OutboundChatListener>(OutboundChatListener.class);
  95 + private HandlerList<ViewportListener> viewportListeners = new HandlerList<ViewportListener>(ViewportListener.class);
  96 + private HandlerList<FrameBufferListener> frameBufferListeners = new HandlerList<FrameBufferListener>(FrameBufferListener.class);
  97 + private HandlerList<InitCompleteListener> initListeners = new HandlerList<InitCompleteListener>(InitCompleteListener.class);
  98 + private HandlerList<ChatFilter> chatFilters = new HandlerList<ChatFilter>(ChatFilter.class);
  99 + private HandlerList<PreJoinGameListener> preJoinGameListeners = new HandlerList<PreJoinGameListener>(PreJoinGameListener.class);
  100 + private HandlerList<OutboundChatFilter> outboundChatFilters = new HandlerList<OutboundChatFilter>(OutboundChatFilter.class);
  101 +
175 @SuppressWarnings("cast") 102 @SuppressWarnings("cast")
176 public ClientEvents(LiteLoader loader, GameEngineClient engine, LoaderProperties properties) 103 public ClientEvents(LiteLoader loader, GameEngineClient engine, LoaderProperties properties)
177 { 104 {
@@ -208,19 +135,20 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -208,19 +135,20 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
208 135
209 delegate.registerInterface(Tickable.class); 136 delegate.registerInterface(Tickable.class);
210 delegate.registerInterface(GameLoopListener.class); 137 delegate.registerInterface(GameLoopListener.class);
211 - delegate.registerInterface(InitCompleteListener.class);  
212 delegate.registerInterface(RenderListener.class); 138 delegate.registerInterface(RenderListener.class);
213 delegate.registerInterface(PostRenderListener.class); 139 delegate.registerInterface(PostRenderListener.class);
214 - delegate.registerInterface(ChatFilter.class);  
215 - delegate.registerInterface(ChatListener.class);  
216 - delegate.registerInterface(ChatRenderListener.class);  
217 delegate.registerInterface(HUDRenderListener.class); 140 delegate.registerInterface(HUDRenderListener.class);
218 - delegate.registerInterface(PreJoinGameListener.class); 141 + delegate.registerInterface(ChatRenderListener.class);
  142 + delegate.registerInterface(ChatListener.class);
  143 + delegate.registerInterface(PostLoginListener.class);
219 delegate.registerInterface(JoinGameListener.class); 144 delegate.registerInterface(JoinGameListener.class);
220 delegate.registerInterface(OutboundChatListener.class); 145 delegate.registerInterface(OutboundChatListener.class);
221 - delegate.registerInterface(OutboundChatFilter.class);  
222 delegate.registerInterface(ViewportListener.class); 146 delegate.registerInterface(ViewportListener.class);
223 delegate.registerInterface(FrameBufferListener.class); 147 delegate.registerInterface(FrameBufferListener.class);
  148 + delegate.registerInterface(InitCompleteListener.class);
  149 + delegate.registerInterface(ChatFilter.class);
  150 + delegate.registerInterface(PreJoinGameListener.class);
  151 + delegate.registerInterface(OutboundChatFilter.class);
224 } 152 }
225 153
226 /** 154 /**
@@ -269,10 +197,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -269,10 +197,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
269 */ 197 */
270 public void addTickListener(Tickable tickable) 198 public void addTickListener(Tickable tickable)
271 { 199 {
272 - if (!this.tickListeners.contains(tickable))  
273 - {  
274 - this.tickListeners.add(tickable);  
275 - } 200 + this.tickListeners.add(tickable);
276 } 201 }
277 202
278 /** 203 /**
@@ -280,10 +205,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -280,10 +205,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
280 */ 205 */
281 public void addLoopListener(GameLoopListener loopListener) 206 public void addLoopListener(GameLoopListener loopListener)
282 { 207 {
283 - if (!this.loopListeners.contains(loopListener))  
284 - {  
285 - this.loopListeners.add(loopListener);  
286 - } 208 + this.loopListeners.add(loopListener);
287 } 209 }
288 210
289 /** 211 /**
@@ -291,10 +213,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -291,10 +213,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
291 */ 213 */
292 public void addInitListener(InitCompleteListener initCompleteListener) 214 public void addInitListener(InitCompleteListener initCompleteListener)
293 { 215 {
294 - if (!this.initListeners.contains(initCompleteListener))  
295 - {  
296 - this.initListeners.add(initCompleteListener);  
297 - } 216 + this.initListeners.add(initCompleteListener);
298 } 217 }
299 218
300 /** 219 /**
@@ -302,10 +221,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -302,10 +221,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
302 */ 221 */
303 public void addRenderListener(RenderListener renderListener) 222 public void addRenderListener(RenderListener renderListener)
304 { 223 {
305 - if (!this.renderListeners.contains(renderListener))  
306 - {  
307 - this.renderListeners.add(renderListener);  
308 - } 224 + this.renderListeners.add(renderListener);
309 } 225 }
310 226
311 /** 227 /**
@@ -313,10 +229,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -313,10 +229,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
313 */ 229 */
314 public void addPostRenderListener(PostRenderListener postRenderListener) 230 public void addPostRenderListener(PostRenderListener postRenderListener)
315 { 231 {
316 - if (!this.postRenderListeners.contains(postRenderListener))  
317 - {  
318 - this.postRenderListeners.add(postRenderListener);  
319 - } 232 + this.postRenderListeners.add(postRenderListener);
320 } 233 }
321 234
322 /** 235 /**
@@ -353,7 +266,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -353,7 +266,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
353 { 266 {
354 LiteLoaderLogger.warning("Interface error initialising mod '%1s'. A mod implementing ChatFilter and ChatListener is not supported! Remove one of these interfaces", chatListener.getName()); 267 LiteLoaderLogger.warning("Interface error initialising mod '%1s'. A mod implementing ChatFilter and ChatListener is not supported! Remove one of these interfaces", chatListener.getName());
355 } 268 }
356 - else if (!this.chatListeners.contains(chatListener)) 269 + else
357 { 270 {
358 this.chatListeners.add(chatListener); 271 this.chatListeners.add(chatListener);
359 } 272 }
@@ -364,10 +277,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -364,10 +277,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
364 */ 277 */
365 public void addChatRenderListener(ChatRenderListener chatRenderListener) 278 public void addChatRenderListener(ChatRenderListener chatRenderListener)
366 { 279 {
367 - if (!this.chatRenderListeners.contains(chatRenderListener))  
368 - {  
369 - this.chatRenderListeners.add(chatRenderListener);  
370 - } 280 + this.chatRenderListeners.add(chatRenderListener);
371 } 281 }
372 282
373 /** 283 /**
@@ -375,10 +285,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -375,10 +285,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
375 */ 285 */
376 public void addHUDRenderListener(HUDRenderListener hudRenderListener) 286 public void addHUDRenderListener(HUDRenderListener hudRenderListener)
377 { 287 {
378 - if (!this.hudRenderListeners.contains(hudRenderListener))  
379 - {  
380 - this.hudRenderListeners.add(hudRenderListener);  
381 - } 288 + this.hudRenderListeners.add(hudRenderListener);
382 } 289 }
383 290
384 /** 291 /**
@@ -386,10 +293,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -386,10 +293,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
386 */ 293 */
387 public void addPreJoinGameListener(PostLoginListener postLoginListener) 294 public void addPreJoinGameListener(PostLoginListener postLoginListener)
388 { 295 {
389 - if (!this.postLoginListeners.contains(postLoginListener))  
390 - {  
391 - this.postLoginListeners.add(postLoginListener);  
392 - } 296 + this.postLoginListeners.add(postLoginListener);
393 } 297 }
394 298
395 /** 299 /**
@@ -397,10 +301,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -397,10 +301,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
397 */ 301 */
398 public void addPreJoinGameListener(PreJoinGameListener joinGameListener) 302 public void addPreJoinGameListener(PreJoinGameListener joinGameListener)
399 { 303 {
400 - if (!this.preJoinGameListeners.contains(joinGameListener))  
401 - {  
402 - this.preJoinGameListeners.add(joinGameListener);  
403 - } 304 + this.preJoinGameListeners.add(joinGameListener);
404 } 305 }
405 306
406 /** 307 /**
@@ -408,10 +309,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -408,10 +309,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
408 */ 309 */
409 public void addJoinGameListener(JoinGameListener joinGameListener) 310 public void addJoinGameListener(JoinGameListener joinGameListener)
410 { 311 {
411 - if (!this.joinGameListeners.contains(joinGameListener))  
412 - {  
413 - this.joinGameListeners.add(joinGameListener);  
414 - } 312 + this.joinGameListeners.add(joinGameListener);
415 } 313 }
416 314
417 /** 315 /**
@@ -419,10 +317,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -419,10 +317,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
419 */ 317 */
420 public void addOutboundChatListener(OutboundChatListener outboundChatListener) 318 public void addOutboundChatListener(OutboundChatListener outboundChatListener)
421 { 319 {
422 - if (!this.outboundChatListeners.contains(outboundChatListener))  
423 - {  
424 - this.outboundChatListeners.add(outboundChatListener);  
425 - } 320 + this.outboundChatListeners.add(outboundChatListener);
426 } 321 }
427 322
428 /** 323 /**
@@ -430,10 +325,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -430,10 +325,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
430 */ 325 */
431 public void addOutboundChatFiler(OutboundChatFilter outboundChatFilter) 326 public void addOutboundChatFiler(OutboundChatFilter outboundChatFilter)
432 { 327 {
433 - if (!this.outboundChatFilters.contains(outboundChatFilter))  
434 - {  
435 - this.outboundChatFilters.add(outboundChatFilter);  
436 - } 328 + this.outboundChatFilters.add(outboundChatFilter);
437 } 329 }
438 330
439 /** 331 /**
@@ -441,10 +333,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -441,10 +333,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
441 */ 333 */
442 public void addViewportListener(ViewportListener viewportListener) 334 public void addViewportListener(ViewportListener viewportListener)
443 { 335 {
444 - if (!this.viewportListeners.contains(viewportListener))  
445 - {  
446 - this.viewportListeners.add(viewportListener);  
447 - } 336 + this.viewportListeners.add(viewportListener);
448 } 337 }
449 338
450 /** 339 /**
@@ -452,10 +341,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -452,10 +341,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
452 */ 341 */
453 public void addFrameBufferListener(FrameBufferListener frameBufferListener) 342 public void addFrameBufferListener(FrameBufferListener frameBufferListener)
454 { 343 {
455 - if (!this.frameBufferListeners.contains(frameBufferListener))  
456 - {  
457 - this.frameBufferListeners.add(frameBufferListener);  
458 - } 344 + this.frameBufferListeners.add(frameBufferListener);
459 } 345 }
460 346
461 /** 347 /**
@@ -499,14 +385,11 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -499,14 +385,11 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
499 385
500 if (this.wasFullScreen != minecraft.isFullScreen()) 386 if (this.wasFullScreen != minecraft.isFullScreen())
501 { 387 {
502 - for (ViewportListener viewportListener : this.viewportListeners)  
503 - viewportListener.onFullScreenToggled(minecraft.isFullScreen()); 388 + this.viewportListeners.all().onFullScreenToggled(minecraft.isFullScreen());
504 } 389 }
505 390
506 this.wasFullScreen = minecraft.isFullScreen(); 391 this.wasFullScreen = minecraft.isFullScreen();
507 -  
508 - for (ViewportListener viewportListener : this.viewportListeners)  
509 - viewportListener.onViewportResized(this.currentResolution, minecraft.displayWidth, minecraft.displayHeight); 392 + this.viewportListeners.all().onViewportResized(this.currentResolution, minecraft.displayWidth, minecraft.displayHeight);
510 } 393 }
511 394
512 /** 395 /**
@@ -514,8 +397,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -514,8 +397,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
514 */ 397 */
515 void onRender() 398 void onRender()
516 { 399 {
517 - for (RenderListener renderListener : this.renderListeners)  
518 - renderListener.onRender(); 400 + this.renderListeners.all().onRender();
519 } 401 }
520 402
521 /** 403 /**
@@ -524,9 +406,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -524,9 +406,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
524 void postRenderEntities() 406 void postRenderEntities()
525 { 407 {
526 float partialTicks = (this.minecraftTimer != null) ? this.minecraftTimer.elapsedPartialTicks : 0.0F; 408 float partialTicks = (this.minecraftTimer != null) ? this.minecraftTimer.elapsedPartialTicks : 0.0F;
527 -  
528 - for (PostRenderListener renderListener : this.postRenderListeners)  
529 - renderListener.onPostRenderEntities(partialTicks); 409 + this.postRenderListeners.all().onPostRenderEntities(partialTicks);
530 } 410 }
531 411
532 /** 412 /**
@@ -535,9 +415,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -535,9 +415,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
535 void postRender() 415 void postRender()
536 { 416 {
537 float partialTicks = (this.minecraftTimer != null) ? this.minecraftTimer.elapsedPartialTicks : 0.0F; 417 float partialTicks = (this.minecraftTimer != null) ? this.minecraftTimer.elapsedPartialTicks : 0.0F;
538 -  
539 - for (PostRenderListener renderListener : this.postRenderListeners)  
540 - renderListener.onPostRender(partialTicks); 418 + this.postRenderListeners.all().onPostRender(partialTicks);
541 } 419 }
542 420
543 /** 421 /**
@@ -549,8 +427,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -549,8 +427,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
549 427
550 if (!minecraft.skipRenderWorld && ref == (minecraft.theWorld == null ? 1 : 2)) 428 if (!minecraft.skipRenderWorld && ref == (minecraft.theWorld == null ? 1 : 2))
551 { 429 {
552 - for (RenderListener renderListener : this.renderListeners)  
553 - renderListener.onRenderGui(this.engineClient.getCurrentScreen()); 430 + this.renderListeners.all().onRenderGui(this.engineClient.getCurrentScreen());
554 } 431 }
555 } 432 }
556 433
@@ -559,8 +436,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -559,8 +436,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
559 */ 436 */
560 void onSetupCameraTransform() 437 void onSetupCameraTransform()
561 { 438 {
562 - for (RenderListener renderListener : this.renderListeners)  
563 - renderListener.onSetupCameraTransform(); 439 + this.renderListeners.all().onSetupCameraTransform();
564 } 440 }
565 441
566 /** 442 /**
@@ -569,9 +445,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -569,9 +445,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
569 void onRenderChat() 445 void onRenderChat()
570 { 446 {
571 GuiNewChat chat = this.engineClient.getChatGUI(); 447 GuiNewChat chat = this.engineClient.getChatGUI();
572 -  
573 - for (ChatRenderListener chatRenderListener : this.chatRenderListeners)  
574 - chatRenderListener.onPreRenderChat(this.screenWidth, this.screenHeight, chat); 448 + this.chatRenderListeners.all().onPreRenderChat(this.screenWidth, this.screenHeight, chat);
575 } 449 }
576 450
577 /** 451 /**
@@ -580,9 +454,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -580,9 +454,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
580 void postRenderChat() 454 void postRenderChat()
581 { 455 {
582 GuiNewChat chat = this.engineClient.getChatGUI(); 456 GuiNewChat chat = this.engineClient.getChatGUI();
583 -  
584 - for (ChatRenderListener chatRenderListener : this.chatRenderListeners)  
585 - chatRenderListener.onPostRenderChat(this.screenWidth, this.screenHeight, chat); 457 + this.chatRenderListeners.all().onPostRenderChat(this.screenWidth, this.screenHeight, chat);
586 } 458 }
587 459
588 /** 460 /**
@@ -592,8 +464,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -592,8 +464,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
592 { 464 {
593 if (!this.engineClient.hideGUI() || this.engineClient.getCurrentScreen() != null) 465 if (!this.engineClient.hideGUI() || this.engineClient.getCurrentScreen() != null)
594 { 466 {
595 - for (HUDRenderListener hudRenderListener : this.hudRenderListeners)  
596 - hudRenderListener.onPreRenderHUD(this.screenWidth, this.screenHeight); 467 + this.hudRenderListeners.all().onPreRenderHUD(this.screenWidth, this.screenHeight);
597 } 468 }
598 } 469 }
599 470
@@ -604,8 +475,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -604,8 +475,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
604 { 475 {
605 if (!this.engineClient.hideGUI() || this.engineClient.getCurrentScreen() != null) 476 if (!this.engineClient.hideGUI() || this.engineClient.getCurrentScreen() != null)
606 { 477 {
607 - for (HUDRenderListener hudRenderListener : this.hudRenderListeners)  
608 - hudRenderListener.onPostRenderHUD(this.screenWidth, this.screenHeight); 478 + this.hudRenderListeners.all().onPostRenderHUD(this.screenWidth, this.screenHeight);
609 } 479 }
610 } 480 }
611 481
@@ -615,9 +485,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -615,9 +485,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
615 void onTimerUpdate() 485 void onTimerUpdate()
616 { 486 {
617 Minecraft minecraft = this.engine.getClient(); 487 Minecraft minecraft = this.engine.getClient();
618 -  
619 - for (GameLoopListener loopListener : this.loopListeners)  
620 - loopListener.onRunGameLoop(minecraft); 488 + this.loopListeners.all().onRunGameLoop(minecraft);
621 } 489 }
622 490
623 /** 491 /**
@@ -659,12 +527,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -659,12 +527,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
659 this.profiler.endSection(); 527 this.profiler.endSection();
660 528
661 // Iterate tickable mods 529 // Iterate tickable mods
662 - for (Tickable tickable : this.tickListeners)  
663 - {  
664 - this.profiler.startSection(tickable.getClass().getSimpleName().toLowerCase());  
665 - tickable.onTick(minecraft, partialTicks, inGame, clock);  
666 - this.profiler.endSection();  
667 - } 530 + this.tickListeners.all().onTick(minecraft, partialTicks, inGame, clock);
668 531
669 // Detected world change 532 // Detected world change
670 if (minecraft.theWorld != null) 533 if (minecraft.theWorld != null)
@@ -714,8 +577,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -714,8 +577,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
714 } 577 }
715 578
716 // Chat listeners get the chat if no filter removed it 579 // Chat listeners get the chat if no filter removed it
717 - for (ChatListener chatListener : this.chatListeners)  
718 - chatListener.onChat(chat, message); 580 + this.chatListeners.all().onChat(chat, message);
719 581
720 return true; 582 return true;
721 } 583 }
@@ -726,10 +588,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -726,10 +588,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
726 */ 588 */
727 void onSendChatMessage(C01PacketChatMessage packet, String message) 589 void onSendChatMessage(C01PacketChatMessage packet, String message)
728 { 590 {
729 - for (OutboundChatListener outboundChatListener : this.outboundChatListeners)  
730 - {  
731 - outboundChatListener.onSendChatMessage(packet, message);  
732 - } 591 + this.outboundChatListeners.all().onSendChatMessage(packet, message);
733 } 592 }
734 593
735 /** 594 /**
@@ -756,8 +615,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -756,8 +615,7 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
756 ((ClientPluginChannelsClient)clientPluginChannels).onPostLogin(netHandler, loginPacket); 615 ((ClientPluginChannelsClient)clientPluginChannels).onPostLogin(netHandler, loginPacket);
757 } 616 }
758 617
759 - for (PostLoginListener loginListener : this.postLoginListeners)  
760 - loginListener.onPostLogin(netHandler, loginPacket); 618 + this.postLoginListeners.all().onPostLogin(netHandler, loginPacket);
761 } 619 }
762 620
763 /** 621 /**
@@ -796,25 +654,32 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt; @@ -796,25 +654,32 @@ public class ClientEvents extends Events&lt;Minecraft, IntegratedServer&gt;
796 ((ClientPluginChannelsClient)clientPluginChannels).onJoinGame(netHandler, loginPacket); 654 ((ClientPluginChannelsClient)clientPluginChannels).onJoinGame(netHandler, loginPacket);
797 } 655 }
798 656
799 - for (JoinGameListener joinGameListener : this.joinGameListeners)  
800 - joinGameListener.onJoinGame(netHandler, loginPacket); 657 + this.joinGameListeners.all().onJoinGame(netHandler, loginPacket);
801 } 658 }
802 659
  660 + /**
  661 + * @param framebuffer
  662 + */
803 void preRenderFBO(Framebuffer framebuffer) 663 void preRenderFBO(Framebuffer framebuffer)
804 { 664 {
805 - for (FrameBufferListener frameBufferListener : this.frameBufferListeners)  
806 - frameBufferListener.preRenderFBO(framebuffer); 665 + this.frameBufferListeners.all().preRenderFBO(framebuffer);
807 } 666 }
808 667
  668 + /**
  669 + * @param framebuffer
  670 + * @param width
  671 + * @param height
  672 + */
809 void onRenderFBO(Framebuffer framebuffer, int width, int height) 673 void onRenderFBO(Framebuffer framebuffer, int width, int height)
810 { 674 {
811 - for (FrameBufferListener frameBufferListener : this.frameBufferListeners)  
812 - frameBufferListener.onRenderFBO(framebuffer, width, height); 675 + this.frameBufferListeners.all().onRenderFBO(framebuffer, width, height);
813 } 676 }
814 677
  678 + /**
  679 + * @param framebuffer
  680 + */
815 void postRenderFBO(Framebuffer framebuffer) 681 void postRenderFBO(Framebuffer framebuffer)
816 { 682 {
817 - for (FrameBufferListener frameBufferListener : this.frameBufferListeners)  
818 - frameBufferListener.postRenderFBO(framebuffer); 683 + this.frameBufferListeners.all().postRenderFBO(framebuffer);
819 } 684 }
820 } 685 }
java/common/com/mumfrey/liteloader/core/Events.java
1 package com.mumfrey.liteloader.core; 1 package com.mumfrey.liteloader.core;
2 2
3 -import java.util.LinkedList;  
4 -  
5 import net.minecraft.client.resources.IResourceManager; 3 import net.minecraft.client.resources.IResourceManager;
6 import net.minecraft.client.resources.IResourceManagerReloadListener; 4 import net.minecraft.client.resources.IResourceManagerReloadListener;
7 import net.minecraft.command.ICommandManager; 5 import net.minecraft.command.ICommandManager;
@@ -30,6 +28,7 @@ import com.mumfrey.liteloader.api.InterfaceProvider; @@ -30,6 +28,7 @@ import com.mumfrey.liteloader.api.InterfaceProvider;
30 import com.mumfrey.liteloader.api.Listener; 28 import com.mumfrey.liteloader.api.Listener;
31 import com.mumfrey.liteloader.common.GameEngine; 29 import com.mumfrey.liteloader.common.GameEngine;
32 import com.mumfrey.liteloader.common.LoadingProgress; 30 import com.mumfrey.liteloader.common.LoadingProgress;
  31 +import com.mumfrey.liteloader.core.event.HandlerList;
33 import com.mumfrey.liteloader.launch.LoaderProperties; 32 import com.mumfrey.liteloader.launch.LoaderProperties;
34 import com.mumfrey.liteloader.util.log.LiteLoaderLogger; 33 import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
35 34
@@ -61,17 +60,17 @@ public abstract class Events&lt;TClient, TServer extends MinecraftServer&gt; implement @@ -61,17 +60,17 @@ public abstract class Events&lt;TClient, TServer extends MinecraftServer&gt; implement
61 /** 60 /**
62 * List of mods which can filter server chat 61 * List of mods which can filter server chat
63 */ 62 */
64 - private LinkedList<ServerChatFilter> serverChatFilters = new LinkedList<ServerChatFilter>(); 63 + private HandlerList<ServerChatFilter> serverChatFilters = new HandlerList<ServerChatFilter>(ServerChatFilter.class);
65 64
66 /** 65 /**
67 * List of mods which provide server commands 66 * List of mods which provide server commands
68 */ 67 */
69 - private LinkedList<ServerCommandProvider> serverCommandProviders = new LinkedList<ServerCommandProvider>(); 68 + private HandlerList<ServerCommandProvider> serverCommandProviders = new HandlerList<ServerCommandProvider>(ServerCommandProvider.class);
70 69
71 /** 70 /**
72 * List of mods which monitor server player events 71 * List of mods which monitor server player events
73 */ 72 */
74 - private LinkedList<ServerPlayerListener> serverPlayerListeners = new LinkedList<ServerPlayerListener>(); 73 + private HandlerList<ServerPlayerListener> serverPlayerListeners = new HandlerList<ServerPlayerListener>(ServerPlayerListener.class);
75 74
76 /** 75 /**
77 * Package private ctor 76 * Package private ctor
@@ -169,10 +168,7 @@ public abstract class Events&lt;TClient, TServer extends MinecraftServer&gt; implement @@ -169,10 +168,7 @@ public abstract class Events&lt;TClient, TServer extends MinecraftServer&gt; implement
169 */ 168 */
170 public void addServerCommandProvider(ServerCommandProvider serverCommandProvider) 169 public void addServerCommandProvider(ServerCommandProvider serverCommandProvider)
171 { 170 {
172 - if (!this.serverCommandProviders.contains(serverCommandProvider))  
173 - {  
174 - this.serverCommandProviders.add(serverCommandProvider);  
175 - } 171 + this.serverCommandProviders.add(serverCommandProvider);
176 } 172 }
177 173
178 /** 174 /**
@@ -180,10 +176,7 @@ public abstract class Events&lt;TClient, TServer extends MinecraftServer&gt; implement @@ -180,10 +176,7 @@ public abstract class Events&lt;TClient, TServer extends MinecraftServer&gt; implement
180 */ 176 */
181 public void addServerPlayerListener(ServerPlayerListener serverPlayerListener) 177 public void addServerPlayerListener(ServerPlayerListener serverPlayerListener)
182 { 178 {
183 - if (!this.serverPlayerListeners.contains(serverPlayerListener))  
184 - {  
185 - this.serverPlayerListeners.add(serverPlayerListener);  
186 - } 179 + this.serverPlayerListeners.add(serverPlayerListener);
187 } 180 }
188 181
189 @Override 182 @Override
@@ -227,9 +220,7 @@ public abstract class Events&lt;TClient, TServer extends MinecraftServer&gt; implement @@ -227,9 +220,7 @@ public abstract class Events&lt;TClient, TServer extends MinecraftServer&gt; implement
227 if (commandManager instanceof ServerCommandManager) 220 if (commandManager instanceof ServerCommandManager)
228 { 221 {
229 ServerCommandManager serverCommandManager = (ServerCommandManager)commandManager; 222 ServerCommandManager serverCommandManager = (ServerCommandManager)commandManager;
230 -  
231 - for (ServerCommandProvider commandProvider : this.serverCommandProviders)  
232 - commandProvider.provideCommands(serverCommandManager); 223 + this.serverCommandProviders.all().provideCommands(serverCommandManager);
233 } 224 }
234 225
235 LiteLoader.getServerPluginChannels().onServerStartup(); 226 LiteLoader.getServerPluginChannels().onServerStartup();
@@ -242,8 +233,7 @@ public abstract class Events&lt;TClient, TServer extends MinecraftServer&gt; implement @@ -242,8 +233,7 @@ public abstract class Events&lt;TClient, TServer extends MinecraftServer&gt; implement
242 */ 233 */
243 public void onSpawnPlayer(ServerConfigurationManager scm, EntityPlayerMP player, GameProfile profile) 234 public void onSpawnPlayer(ServerConfigurationManager scm, EntityPlayerMP player, GameProfile profile)
244 { 235 {
245 - for (ServerPlayerListener serverPlayerListener : this.serverPlayerListeners)  
246 - serverPlayerListener.onPlayerConnect(player, profile); 236 + this.serverPlayerListeners.all().onPlayerConnect(player, profile);
247 } 237 }
248 238
249 /** 239 /**
@@ -262,8 +252,7 @@ public abstract class Events&lt;TClient, TServer extends MinecraftServer&gt; implement @@ -262,8 +252,7 @@ public abstract class Events&lt;TClient, TServer extends MinecraftServer&gt; implement
262 */ 252 */
263 public void onInitializePlayerConnection(ServerConfigurationManager scm, NetworkManager netManager, EntityPlayerMP player) 253 public void onInitializePlayerConnection(ServerConfigurationManager scm, NetworkManager netManager, EntityPlayerMP player)
264 { 254 {
265 - for (ServerPlayerListener serverPlayerListener : this.serverPlayerListeners)  
266 - serverPlayerListener.onPlayerLoggedIn(player); 255 + this.serverPlayerListeners.all().onPlayerLoggedIn(player);
267 } 256 }
268 257
269 /** 258 /**
@@ -275,8 +264,7 @@ public abstract class Events&lt;TClient, TServer extends MinecraftServer&gt; implement @@ -275,8 +264,7 @@ public abstract class Events&lt;TClient, TServer extends MinecraftServer&gt; implement
275 */ 264 */
276 public void onRespawnPlayer(ServerConfigurationManager scm, EntityPlayerMP player, EntityPlayerMP oldPlayer, int dimension, boolean won) 265 public void onRespawnPlayer(ServerConfigurationManager scm, EntityPlayerMP player, EntityPlayerMP oldPlayer, int dimension, boolean won)
277 { 266 {
278 - for (ServerPlayerListener serverPlayerListener : this.serverPlayerListeners)  
279 - serverPlayerListener.onPlayerRespawn(player, oldPlayer, dimension, won); 267 + this.serverPlayerListeners.all().onPlayerRespawn(player, oldPlayer, dimension, won);
280 } 268 }
281 269
282 /** 270 /**
@@ -285,15 +273,24 @@ public abstract class Events&lt;TClient, TServer extends MinecraftServer&gt; implement @@ -285,15 +273,24 @@ public abstract class Events&lt;TClient, TServer extends MinecraftServer&gt; implement
285 */ 273 */
286 public void onPlayerLogout(ServerConfigurationManager scm, EntityPlayerMP player) 274 public void onPlayerLogout(ServerConfigurationManager scm, EntityPlayerMP player)
287 { 275 {
288 - for (ServerPlayerListener serverPlayerListener : this.serverPlayerListeners)  
289 - serverPlayerListener.onPlayerLogout(player); 276 + this.serverPlayerListeners.all().onPlayerLogout(player);
290 } 277 }
291 278
  279 + /**
  280 + * @param clock
  281 + * @param partialTicks
  282 + * @param inGame
  283 + */
292 protected void onTick(boolean clock, float partialTicks, boolean inGame) 284 protected void onTick(boolean clock, float partialTicks, boolean inGame)
293 { 285 {
294 this.loader.onTick(clock, partialTicks, inGame); 286 this.loader.onTick(clock, partialTicks, inGame);
295 } 287 }
296 288
  289 + /**
  290 + * @param mouseX
  291 + * @param mouseY
  292 + * @param partialTicks
  293 + */
297 protected void onPostRender(int mouseX, int mouseY, float partialTicks) 294 protected void onPostRender(int mouseX, int mouseY, float partialTicks)
298 { 295 {
299 this.loader.onPostRender(mouseX, mouseY, partialTicks); 296 this.loader.onPostRender(mouseX, mouseY, partialTicks);
java/common/com/mumfrey/liteloader/core/event/HandlerList.java 0 โ†’ 100644
  1 +package com.mumfrey.liteloader.core.event;
  2 +
  3 +import java.io.IOException;
  4 +import java.lang.reflect.Constructor;
  5 +import java.net.URL;
  6 +import java.net.URLClassLoader;
  7 +import java.util.Collection;
  8 +import java.util.Iterator;
  9 +import java.util.LinkedList;
  10 +import java.util.List;
  11 +
  12 +import net.minecraft.launchwrapper.IClassTransformer;
  13 +import net.minecraft.launchwrapper.Launch;
  14 +
  15 +import org.objectweb.asm.ClassReader;
  16 +import org.objectweb.asm.ClassWriter;
  17 +import org.objectweb.asm.Label;
  18 +import org.objectweb.asm.Type;
  19 +import org.objectweb.asm.tree.*;
  20 +
  21 +import com.mumfrey.liteloader.core.runtime.Obf;
  22 +import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
  23 +import com.sun.xml.internal.ws.org.objectweb.asm.Opcodes;
  24 +
  25 +/**
  26 + * HandlerList is a generic class which supports baking a list of event handlers into a dynamic inner
  27 + * class for invokation at runtime.
  28 + *
  29 + * @author Adam Mummery-Smith
  30 + *
  31 + * @param <T>
  32 + */
  33 +public class HandlerList<T> extends LinkedList<T>
  34 +{
  35 + private static final long serialVersionUID = 1L;
  36 +
  37 + private static final int MAX_UNCOLLECTED_CLASSES = 5000;
  38 +
  39 + private static int uncollectedHandlerLists = 0;
  40 +
  41 + /**
  42 + * Type of the interface for objects in this handler list
  43 + */
  44 + private Class<T> type;
  45 +
  46 + /**
  47 + * Current baked handler list, we cook them at gas mark 5 for 30 minutes in a disposable classloader whic
  48 + * also handles the transformation for us
  49 + */
  50 + private BakedHandlerList<T> bakedHandler;
  51 +
  52 + /**
  53 + * @param type
  54 + */
  55 + public HandlerList(Class<T> type)
  56 + {
  57 + if (!type.isInterface())
  58 + {
  59 + throw new IllegalArgumentException("HandlerList type argument must be an interface");
  60 + }
  61 +
  62 + this.type = type;
  63 + }
  64 +
  65 + /* (non-Javadoc)
  66 + * @see java.util.LinkedList#add(java.lang.Object)
  67 + */
  68 + @Override
  69 + public boolean add(T listener)
  70 + {
  71 + if (!this.contains(listener))
  72 + {
  73 + super.add(listener);
  74 + this.invalidate();
  75 + }
  76 +
  77 + return true;
  78 + }
  79 +
  80 + /**
  81 + * Invalidate current baked list
  82 + */
  83 + public void invalidate()
  84 + {
  85 + this.bakedHandler = null;
  86 + HandlerList.uncollectedHandlerLists++;
  87 + if (HandlerList.uncollectedHandlerLists > HandlerList.MAX_UNCOLLECTED_CLASSES)
  88 + {
  89 + System.gc();
  90 + HandlerList.uncollectedHandlerLists = 0;
  91 + }
  92 + }
  93 +
  94 + /**
  95 + * Returns the baked list of all listeners
  96 + *
  97 + * @return
  98 + */
  99 + public T all()
  100 + {
  101 + if (this.bakedHandler == null)
  102 + {
  103 + HandlerListClassLoader<T> classLoader = new HandlerListClassLoader<T>(this.type, this.size());
  104 + this.bakedHandler = classLoader.newHandler();
  105 + this.bakedHandler.populate(this);
  106 + }
  107 +
  108 + return this.bakedHandler.get();
  109 + }
  110 +
  111 + /* (non-Javadoc)
  112 + * @see java.util.LinkedList#remove()
  113 + */
  114 + @Override
  115 + public T remove()
  116 + {
  117 + throw new UnsupportedOperationException("'remove' is not supported for HandlerList");
  118 + }
  119 +
  120 + /* (non-Javadoc)
  121 + * @see java.util.LinkedList#remove(int)
  122 + */
  123 + @Override
  124 + public T remove(int index)
  125 + {
  126 + throw new UnsupportedOperationException("'remove' is not supported for HandlerList");
  127 + }
  128 +
  129 + /* (non-Javadoc)
  130 + * @see java.util.LinkedList#remove(java.lang.Object)
  131 + */
  132 + @Override
  133 + public boolean remove(Object o)
  134 + {
  135 + throw new UnsupportedOperationException("'remove' is not supported for HandlerList");
  136 + }
  137 +
  138 + /* (non-Javadoc)
  139 + * @see java.util.AbstractCollection#removeAll(java.util.Collection)
  140 + */
  141 + @Override
  142 + public boolean removeAll(Collection<?> c)
  143 + {
  144 + throw new UnsupportedOperationException("'removeAll' is not supported for HandlerList");
  145 + }
  146 +
  147 + /* (non-Javadoc)
  148 + * @see java.util.LinkedList#removeFirst()
  149 + */
  150 + @Override
  151 + public T removeFirst()
  152 + {
  153 + throw new UnsupportedOperationException("'removeFirst' is not supported for HandlerList");
  154 + }
  155 +
  156 + /* (non-Javadoc)
  157 + * @see java.util.LinkedList#removeFirstOccurrence(java.lang.Object)
  158 + */
  159 + @Override
  160 + public boolean removeFirstOccurrence(Object o)
  161 + {
  162 + throw new UnsupportedOperationException("'removeFirstOccurrence' is not supported for HandlerList");
  163 + }
  164 +
  165 + /* (non-Javadoc)
  166 + * @see java.util.LinkedList#removeLast()
  167 + */
  168 + @Override
  169 + public T removeLast()
  170 + {
  171 + throw new UnsupportedOperationException("'removeLast' is not supported for HandlerList");
  172 + }
  173 +
  174 + /* (non-Javadoc)
  175 + * @see java.util.LinkedList#removeLastOccurrence(java.lang.Object)
  176 + */
  177 + @Override
  178 + public boolean removeLastOccurrence(Object o)
  179 + {
  180 + throw new UnsupportedOperationException("'removeLastOccurrence' is not supported for HandlerList");
  181 + }
  182 +
  183 + /**
  184 + * Base class for baked handler lists
  185 + *
  186 + * @author Adam Mummery-Smith
  187 + *
  188 + * @param <T>
  189 + */
  190 + public static abstract class BakedHandlerList<T>
  191 + {
  192 + public abstract T get();
  193 +
  194 + public abstract void populate(List<T> listeners);
  195 + }
  196 +
  197 + /**
  198 + * ClassLoader which generates the baked handler list
  199 + *
  200 + * @author Adam Mummery-Smith
  201 + * @param <T>
  202 + */
  203 + static class HandlerListClassLoader<T> extends URLClassLoader
  204 + {
  205 + /**
  206 + * Unique index number, just to ensure no name clashes
  207 + */
  208 + private static int handlerIndex;
  209 +
  210 + private int lineNumber = 1;
  211 +
  212 + private final Class<T> type;
  213 +
  214 + private final String typeRef;
  215 +
  216 + private int size;
  217 +
  218 + /**
  219 + * @param type
  220 + * @param size
  221 + */
  222 + HandlerListClassLoader(Class<T> type, int size)
  223 + {
  224 + super(new URL[0], Launch.classLoader);
  225 + this.type = type;
  226 + this.typeRef = type.getName().replace('.', '/');
  227 + this.size = size;
  228 + }
  229 +
  230 + /**
  231 + * Create and return a new baked handler list
  232 + */
  233 + @SuppressWarnings("unchecked")
  234 + public BakedHandlerList<T> newHandler()
  235 + {
  236 + try
  237 + {
  238 + String className = this.getNextClassName();
  239 + Class<BakedHandlerList<T>> handlerClass = (Class<BakedHandlerList<T>>)this.loadClass(className);
  240 + Constructor<BakedHandlerList<T>> ctor = handlerClass.getDeclaredConstructor();
  241 + ctor.setAccessible(true);
  242 + return ctor.newInstance();
  243 + }
  244 + catch (Exception ex)
  245 + {
  246 + throw new RuntimeException(ex);
  247 + }
  248 + }
  249 +
  250 + @Override
  251 + protected Class<?> findClass(String name) throws ClassNotFoundException
  252 + {
  253 + try
  254 + {
  255 + byte[] bytes = Launch.classLoader.getClassBytes(Obf.BakedHandlerList.name);
  256 + ClassReader classReader = new ClassReader(bytes);
  257 + ClassNode classNode = new ClassNode();
  258 + classReader.accept(classNode, ClassReader.EXPAND_FRAMES);
  259 +
  260 + this.transform(name, classNode);
  261 +
  262 + ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
  263 + classNode.accept(classWriter);
  264 + bytes = classWriter.toByteArray();
  265 + return this.defineClass(name, bytes, 0, bytes.length);
  266 + }
  267 + catch (Throwable th)
  268 + {
  269 + th.printStackTrace();
  270 + return null;
  271 + }
  272 + }
  273 +
  274 + private void transform(String name, ClassNode classNode)
  275 + {
  276 + LiteLoaderLogger.info("Baking listener list for %s with %d listeners", this.type.getSimpleName(), this.size);
  277 + LiteLoaderLogger.debug("Generating: %s", name);
  278 +
  279 + this.populateClass(name, classNode);
  280 + this.transformMethods(name, classNode);
  281 + this.injectInterfaceMethods(name, classNode);
  282 + }
  283 +
  284 + private void populateClass(String name, ClassNode classNode)
  285 + {
  286 + classNode.access = classNode.access & ~Opcodes.ACC_ABSTRACT;
  287 + classNode.name = name.replace('.', '/');
  288 + classNode.superName = Obf.BakedHandlerList.ref;
  289 + classNode.interfaces.add(this.type.getName().replace('.', '/'));
  290 + classNode.sourceFile = "Dynamic";
  291 +
  292 + for (int i = 0; i < this.size; i++)
  293 + {
  294 + classNode.fields.add(new FieldNode(Opcodes.ACC_PRIVATE, "handler$" + i, "L" + this.typeRef + ";", null, null));
  295 + }
  296 + }
  297 +
  298 + private void transformMethods(String name, ClassNode classNode)
  299 + {
  300 + for (Iterator<MethodNode> methodIterator = classNode.methods.iterator(); methodIterator.hasNext();)
  301 + {
  302 + MethodNode method = methodIterator.next();
  303 + if (Obf.constructor.name.equals(method.name))
  304 + {
  305 + this.processCtor(classNode, method);
  306 + }
  307 + else if ("get".equals(method.name))
  308 + {
  309 + this.processGet(classNode, method);
  310 + }
  311 + else if ("populate".equals(method.name))
  312 + {
  313 + this.processPopulate(classNode, method);
  314 + }
  315 + }
  316 + }
  317 +
  318 + private void processCtor(ClassNode classNode, MethodNode method)
  319 + {
  320 + for (Iterator<AbstractInsnNode> iter = method.instructions.iterator(); iter.hasNext();)
  321 + {
  322 + AbstractInsnNode insn = iter.next();
  323 + if (insn instanceof MethodInsnNode)
  324 + {
  325 + MethodInsnNode methodInsn = (MethodInsnNode)insn;
  326 + if (methodInsn.owner.equals("java/lang/Object"))
  327 + {
  328 + methodInsn.owner = Obf.BakedHandlerList.ref;
  329 + }
  330 + }
  331 + }
  332 + }
  333 +
  334 + private void processGet(ClassNode classNode, MethodNode method)
  335 + {
  336 + method.access = method.access & ~Opcodes.ACC_ABSTRACT;
  337 + method.instructions.clear();
  338 +
  339 + method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
  340 + method.instructions.add(new InsnNode(Opcodes.ARETURN));
  341 + }
  342 +
  343 + private void processPopulate(ClassNode classNode, MethodNode method)
  344 + {
  345 + method.access = method.access & ~Opcodes.ACC_ABSTRACT;
  346 + method.instructions.clear();
  347 +
  348 + for (int i = 0; i < this.size; i++)
  349 + {
  350 + method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
  351 + method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 1));
  352 + method.instructions.add(new IntInsnNode(Opcodes.BIPUSH, i));
  353 + method.instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, "java/util/List", "get", "(I)Ljava/lang/Object;", true));
  354 + method.instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, this.typeRef));
  355 + method.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, classNode.name, "handler$" + i, "L" + this.typeRef + ";"));
  356 + }
  357 +
  358 + method.instructions.add(new InsnNode(Opcodes.RETURN));
  359 + }
  360 +
  361 + private void injectInterfaceMethods(String name, ClassNode classNode)
  362 + {
  363 + try
  364 + {
  365 + String interfaceName = this.type.getName();
  366 + this.injectInterfaceMethods(classNode, interfaceName);
  367 + }
  368 + catch (IOException ex)
  369 + {
  370 + ex.printStackTrace();
  371 + }
  372 + }
  373 +
  374 + private void injectInterfaceMethods(ClassNode classNode, String interfaceName) throws IOException
  375 + {
  376 + ClassReader interfaceReader = new ClassReader(this.getInterfaceBytes(interfaceName));
  377 + ClassNode interfaceNode = new ClassNode();
  378 + interfaceReader.accept(interfaceNode, 0);
  379 +
  380 + for (MethodNode interfaceMethod : interfaceNode.methods)
  381 + {
  382 + classNode.methods.add(interfaceMethod);
  383 + this.populateInterfaceMethod(classNode, interfaceMethod);
  384 + }
  385 +
  386 + for (String parentInterface : interfaceNode.interfaces)
  387 + {
  388 + this.injectInterfaceMethods(classNode, parentInterface.replace('/', '.'));
  389 + }
  390 + }
  391 +
  392 + private void populateInterfaceMethod(ClassNode classNode, MethodNode method)
  393 + {
  394 + Type returnType = Type.getReturnType(method.desc);
  395 +
  396 + if (returnType.equals(Type.VOID_TYPE))
  397 + {
  398 + Type[] args = Type.getArgumentTypes(method.desc);
  399 + method.access = Opcodes.ACC_PUBLIC;
  400 +
  401 + for (int i = 0; i < this.size; i++)
  402 + {
  403 + LabelNode lineNumberLabel = new LabelNode(new Label());
  404 + method.instructions.add(lineNumberLabel);
  405 + method.instructions.add(new LineNumberNode(++this.lineNumber, lineNumberLabel));
  406 + method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
  407 + method.instructions.add(new FieldInsnNode(Opcodes.GETFIELD, classNode.name, "handler$" + i, "L" + this.typeRef + ";"));
  408 + this.invokeInterfaceMethod(method, args);
  409 + }
  410 +
  411 + method.instructions.add(new InsnNode(Opcodes.RETURN));
  412 + }
  413 + }
  414 +
  415 + private void invokeInterfaceMethod(MethodNode method, Type[] args)
  416 + {
  417 + int argNumber = 1;
  418 + for (Type type : args)
  419 + {
  420 + method.instructions.add(new VarInsnNode(type.getOpcode(Opcodes.ILOAD), argNumber));
  421 + argNumber += type.getSize();
  422 + }
  423 +
  424 + method.instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, this.typeRef, method.name, method.desc, true));
  425 + }
  426 +
  427 + private String getNextClassName()
  428 + {
  429 + return String.format("%s$%s$%s", Obf.HandlerList.name, this.type.getSimpleName(), HandlerListClassLoader.handlerIndex++);
  430 + }
  431 +
  432 + private byte[] getInterfaceBytes(String name) throws IOException
  433 + {
  434 + byte[] bytes = Launch.classLoader.getClassBytes(name);
  435 +
  436 + final List<IClassTransformer> transformers = Launch.classLoader.getTransformers();
  437 +
  438 + for (final IClassTransformer transformer : transformers)
  439 + {
  440 + try
  441 + {
  442 + bytes = transformer.transform(name, name, bytes);
  443 + }
  444 + catch (Exception ex)
  445 + {
  446 + ex.printStackTrace();
  447 + }
  448 + }
  449 +
  450 + return bytes;
  451 + }
  452 + }
  453 +}
java/common/com/mumfrey/liteloader/core/runtime/Obf.java
@@ -17,6 +17,8 @@ public class Obf @@ -17,6 +17,8 @@ public class Obf
17 public static final Obf CallbackProxyClient = new Obf("com.mumfrey.liteloader.client.CallbackProxyClient" ); 17 public static final Obf CallbackProxyClient = new Obf("com.mumfrey.liteloader.client.CallbackProxyClient" );
18 public static final Obf CallbackProxyServer = new Obf("com.mumfrey.liteloader.server.CallbackProxyServer" ); 18 public static final Obf CallbackProxyServer = new Obf("com.mumfrey.liteloader.server.CallbackProxyServer" );
19 public static final Obf EventProxy = new Obf("com.mumfrey.liteloader.core.event.EventProxy" ); 19 public static final Obf EventProxy = new Obf("com.mumfrey.liteloader.core.event.EventProxy" );
  20 + public static final Obf HandlerList = new Obf("com.mumfrey.liteloader.core.event.HandlerList" );
  21 + public static final Obf BakedHandlerList = new Obf("com.mumfrey.liteloader.core.event.HandlerList$BakedHandlerList" );
20 public static final Obf LoadingBar = new Obf("com.mumfrey.liteloader.client.gui.startup.LoadingBar" ); 22 public static final Obf LoadingBar = new Obf("com.mumfrey.liteloader.client.gui.startup.LoadingBar" );
21 public static final Obf GameProfile = new Obf("com.mojang.authlib.GameProfile" ); 23 public static final Obf GameProfile = new Obf("com.mojang.authlib.GameProfile" );
22 public static final Obf MinecraftMain = new Obf("net.minecraft.client.main.Main" ); 24 public static final Obf MinecraftMain = new Obf("net.minecraft.client.main.Main" );