Commit 189931b8aae31a0b6aca5704340600fb35499d27

Authored by Mumfrey
1 parent d34ad93d

added 2 new listeners, some refactoring and minor bugfixes

Showing 29 changed files with 398 additions and 209 deletions
debug/obfuscation.properties
... ... @@ -24,4 +24,8 @@ func_147612_c=bindFramebufferTexture
24 24 func_146230_a=drawChat
25 25 func_179086_m=clear
26 26 func_175068_a=renderWorldPass
27   -func_148256_e=getProfile
28 27 \ No newline at end of file
  28 +func_148256_e=getProfile
  29 +func_148260_a=saveScreenshot
  30 +func_148822_b=isFramebufferEnabled
  31 +func_147939_a=doRenderEntity
  32 +func_76986_a=doRender
29 33 \ No newline at end of file
... ...
java/client/com/mumfrey/liteloader/ChatFilter.java
1 1 package com.mumfrey.liteloader;
2 2  
3   -import net.minecraft.network.play.server.S02PacketChat;
  3 +import com.mumfrey.liteloader.core.LiteLoaderEventBroker.ReturnValue;
  4 +
4 5 import net.minecraft.util.IChatComponent;
5 6  
6 7  
... ... @@ -14,10 +15,11 @@ public interface ChatFilter extends LiteMod
14 15 /**
15 16 * Chat filter function, return false to filter this packet, true to pass the packet
16 17 *
17   - * @param chatPacket Chat packet to examine
18 18 * @param chat ChatMessageComponent parsed from the chat packet
19 19 * @param message Chat message parsed from the chat message component
  20 + * @param newMessage If you wish to mutate the message, set the value using newMessage.set()
  21 + *
20 22 * @return True to keep the packet, false to discard
21 23 */
22   - public abstract boolean onChat(S02PacketChat chatPacket, IChatComponent chat, String message);
  24 + public abstract boolean onChat(IChatComponent chat, String message, ReturnValue<IChatComponent> newMessage);
23 25 }
... ...
java/client/com/mumfrey/liteloader/ChatListener.java
... ... @@ -13,7 +13,7 @@ public interface ChatListener extends LiteMod
13 13 /**
14 14 * Handle an inbound message
15 15 *
16   - * @param chat ChatMessageComponent parsed from the chat packet
  16 + * @param chat IChatComponent parsed from the chat packet
17 17 * @param message Chat message parsed from the chat message component
18 18 */
19 19 public abstract void onChat(IChatComponent chat, String message);
... ...
java/client/com/mumfrey/liteloader/EntityRenderListener.java 0 → 100644
  1 +package com.mumfrey.liteloader;
  2 +
  3 +import net.minecraft.client.renderer.entity.Render;
  4 +import net.minecraft.entity.Entity;
  5 +
  6 +/**
  7 + * Interface for mods which want to receive callbacks when entities are rendered into the world
  8 + *
  9 + * @author Adam Mummery-Smith
  10 + */
  11 +public interface EntityRenderListener extends LiteMod
  12 +{
  13 + /**
  14 + * Called immediately prior to an entity being rendered
  15 + *
  16 + * @param render
  17 + * @param entity
  18 + * @param xPos
  19 + * @param yPos
  20 + * @param zPos
  21 + * @param yaw
  22 + * @param partialTicks
  23 + */
  24 + public abstract void onRenderEntity(Render render, Entity entity, double xPos, double yPos, double zPos, float yaw, float partialTicks);
  25 +
  26 + /**
  27 + * Called immediately following an entity being rendered
  28 + *
  29 + * @param render
  30 + * @param entity
  31 + * @param xPos
  32 + * @param yPos
  33 + * @param zPos
  34 + * @param yaw
  35 + * @param partialTicks
  36 + */
  37 + public abstract void onPostRenderEntity(Render render, Entity entity, double xPos, double yPos, double zPos, float yaw, float partialTicks);
  38 +}
... ...
java/client/com/mumfrey/liteloader/ScreenshotListener.java 0 → 100644
  1 +package com.mumfrey.liteloader;
  2 +
  3 +import net.minecraft.client.shader.Framebuffer;
  4 +import net.minecraft.util.IChatComponent;
  5 +
  6 +import com.mumfrey.liteloader.core.LiteLoaderEventBroker.ReturnValue;
  7 +
  8 +/**
  9 + * Interface for mods which want to handle or inhibit the saving of screenshots
  10 + *
  11 + * @author Adam Mummery-Smith
  12 + */
  13 +public interface ScreenshotListener extends LiteMod
  14 +{
  15 + /**
  16 + * Called when a screenshot is taken, mods should return FALSE to suspend further processing, or TRUE to allow
  17 + * processing to continue normally
  18 + *
  19 + * @param screenshotName
  20 + * @param width
  21 + * @param height
  22 + * @param fbo
  23 + * @param message Message to return if the event is cancelled
  24 + * @return FALSE to suspend further processing, or TRUE to allow processing to continue normally
  25 + */
  26 + public boolean onSaveScreenshot(String screenshotName, int width, int height, Framebuffer fbo, ReturnValue<IChatComponent> message);
  27 +}
... ...
java/client/com/mumfrey/liteloader/client/CallbackProxyClient.java
1 1 package com.mumfrey.liteloader.client;
2 2  
  3 +import java.io.File;
3 4 import java.util.UUID;
4 5  
5 6 import net.minecraft.client.Minecraft;
... ... @@ -7,12 +8,17 @@ import net.minecraft.client.entity.EntityPlayerSP;
7 8 import net.minecraft.client.gui.GuiIngame;
8 9 import net.minecraft.client.renderer.EntityRenderer;
9 10 import net.minecraft.client.renderer.OpenGlHelper;
  11 +import net.minecraft.client.renderer.entity.Render;
  12 +import net.minecraft.client.renderer.entity.RenderManager;
10 13 import net.minecraft.client.shader.Framebuffer;
  14 +import net.minecraft.entity.Entity;
11 15 import net.minecraft.entity.player.EntityPlayer;
12 16 import net.minecraft.entity.player.EntityPlayerMP;
13 17 import net.minecraft.network.NetworkManager;
14 18 import net.minecraft.server.integrated.IntegratedServer;
15 19 import net.minecraft.server.management.ServerConfigurationManager;
  20 +import net.minecraft.util.IChatComponent;
  21 +import net.minecraft.util.ScreenShotHelper;
16 22 import net.minecraft.util.Session;
17 23 import net.minecraft.world.WorldSettings;
18 24  
... ... @@ -29,12 +35,7 @@ import com.mumfrey.liteloader.transformers.event.ReturnEventInfo;
29 35 */
30 36 public class CallbackProxyClient
31 37 {
32   - /**
33   - * Tick clock, sent as a flag to the core onTick so that mods know it's a new tick
34   - */
35   - private static boolean clock = false;
36   -
37   - private static EventsClient events;
  38 + private static LiteLoaderEventBrokerClient eventBroker;
38 39  
39 40 private static boolean fboEnabled;
40 41  
... ... @@ -42,147 +43,145 @@ public class CallbackProxyClient
42 43  
43 44 public static void onStartupComplete(EventInfo<Minecraft> e)
44 45 {
45   - CallbackProxyClient.events = EventsClient.getInstance();
  46 + CallbackProxyClient.eventBroker = LiteLoaderEventBrokerClient.getInstance();
46 47  
47   - if (CallbackProxyClient.events == null)
  48 + if (CallbackProxyClient.eventBroker == null)
48 49 {
49 50 throw new RuntimeException("LiteLoader failed to start up properly. The game is in an unstable state and must shut down now. Check the developer log for startup errors");
50 51 }
51 52  
52   - CallbackProxyClient.events.onStartupComplete();
  53 + CallbackProxyClient.eventBroker.onStartupComplete();
53 54 }
54 55  
55 56 public static void onTimerUpdate(EventInfo<Minecraft> e)
56 57 {
57   - CallbackProxyClient.events.onTimerUpdate();
  58 + CallbackProxyClient.eventBroker.onTimerUpdate();
58 59 }
59 60  
60 61 public static void newTick(EventInfo<Minecraft> e)
61 62 {
62   - CallbackProxyClient.clock = true;
63 63 }
64 64  
65 65 public static void onTick(EventInfo<Minecraft> e)
66 66 {
67   - CallbackProxyClient.events.onTick(CallbackProxyClient.clock);
68   - CallbackProxyClient.clock = false;
  67 + CallbackProxyClient.eventBroker.onTick();
69 68 }
70 69  
71 70 public static void onRender(EventInfo<Minecraft> e)
72 71 {
73   - CallbackProxyClient.events.onRender();
  72 + CallbackProxyClient.eventBroker.onRender();
74 73 }
75 74  
76 75 public static void preRenderGUI(EventInfo<EntityRenderer> e, float partialTicks)
77 76 {
78   - CallbackProxyClient.events.preRenderGUI(partialTicks);
  77 + CallbackProxyClient.eventBroker.preRenderGUI(partialTicks);
79 78 }
80 79  
81 80 public static void onSetupCameraTransform(EventInfo<EntityRenderer> e, int pass, float partialTicks, long timeSlice)
82 81 {
83   - CallbackProxyClient.events.onSetupCameraTransform(partialTicks, timeSlice);
  82 + CallbackProxyClient.eventBroker.onSetupCameraTransform(partialTicks, timeSlice);
84 83 }
85 84  
86 85 public static void postRenderEntities(EventInfo<EntityRenderer> e, int pass, float partialTicks, long timeSlice)
87 86 {
88   - CallbackProxyClient.events.postRenderEntities(partialTicks, timeSlice);
  87 + CallbackProxyClient.eventBroker.postRenderEntities(partialTicks, timeSlice);
89 88 }
90 89  
91 90 public static void postRender(EventInfo<EntityRenderer> e, float partialTicks, long timeSlice)
92 91 {
93   - CallbackProxyClient.events.postRender(partialTicks, timeSlice);
  92 + CallbackProxyClient.eventBroker.postRender(partialTicks, timeSlice);
94 93 }
95 94  
96 95 public static void onRenderHUD(EventInfo<EntityRenderer> e, float partialTicks)
97 96 {
98   - CallbackProxyClient.events.onRenderHUD(partialTicks);
  97 + CallbackProxyClient.eventBroker.onRenderHUD(partialTicks);
99 98 }
100 99  
101 100 public static void onRenderChat(EventInfo<GuiIngame> e, float partialTicks)
102 101 {
103   - CallbackProxyClient.events.onRenderChat(e.getSource().getChatGUI(), partialTicks);
  102 + CallbackProxyClient.eventBroker.onRenderChat(e.getSource().getChatGUI(), partialTicks);
104 103 }
105 104  
106 105 public static void postRenderChat(EventInfo<GuiIngame> e, float partialTicks)
107 106 {
108   - CallbackProxyClient.events.postRenderChat(e.getSource().getChatGUI(), partialTicks);
  107 + CallbackProxyClient.eventBroker.postRenderChat(e.getSource().getChatGUI(), partialTicks);
109 108 }
110 109  
111 110 public static void postRenderHUD(EventInfo<EntityRenderer> e, float partialTicks)
112 111 {
113   - CallbackProxyClient.events.postRenderHUD(partialTicks);
  112 + CallbackProxyClient.eventBroker.postRenderHUD(partialTicks);
114 113 }
115 114  
116 115 public static void IntegratedServerCtor(EventInfo<IntegratedServer> e, Minecraft minecraft, String folderName, String worldName, WorldSettings worldSettings)
117 116 {
118   - CallbackProxyClient.events.onStartServer(e.getSource(), folderName, worldName, worldSettings);
  117 + CallbackProxyClient.eventBroker.onStartServer(e.getSource(), folderName, worldName, worldSettings);
119 118 }
120 119  
121 120 public static void onInitializePlayerConnection(EventInfo<ServerConfigurationManager> e, NetworkManager netManager, EntityPlayerMP player)
122 121 {
123   - CallbackProxyClient.events.onInitializePlayerConnection(e.getSource(), netManager, player);
  122 + CallbackProxyClient.eventBroker.onInitializePlayerConnection(e.getSource(), netManager, player);
124 123 }
125 124  
126 125 public static void onPlayerLogin(EventInfo<ServerConfigurationManager> e, EntityPlayerMP player)
127 126 {
128   - CallbackProxyClient.events.onPlayerLogin(e.getSource(), player);
  127 + CallbackProxyClient.eventBroker.onPlayerLogin(e.getSource(), player);
129 128 }
130 129  
131 130 public static void onPlayerLogout(EventInfo<ServerConfigurationManager> e, EntityPlayerMP player)
132 131 {
133   - CallbackProxyClient.events.onPlayerLogout(e.getSource(), player);
  132 + CallbackProxyClient.eventBroker.onPlayerLogout(e.getSource(), player);
134 133 }
135 134  
136 135 public static void onSpawnPlayer(ReturnEventInfo<ServerConfigurationManager, EntityPlayerMP> e, GameProfile profile)
137 136 {
138   - CallbackProxyClient.events.onSpawnPlayer(e.getSource(), e.getReturnValue(), profile);
  137 + CallbackProxyClient.eventBroker.onSpawnPlayer(e.getSource(), e.getReturnValue(), profile);
139 138 }
140 139  
141 140 public static void onRespawnPlayer(ReturnEventInfo<ServerConfigurationManager, EntityPlayerMP> e, EntityPlayerMP oldPlayer, int dimension, boolean won)
142 141 {
143   - CallbackProxyClient.events.onRespawnPlayer(e.getSource(), e.getReturnValue(), oldPlayer, dimension, won);
  142 + CallbackProxyClient.eventBroker.onRespawnPlayer(e.getSource(), e.getReturnValue(), oldPlayer, dimension, won);
144 143 }
145 144  
146 145 public static void onOutboundChat(EventInfo<EntityPlayerSP> e, String message)
147 146 {
148   - CallbackProxyClient.events.onSendChatMessage(e, message);
  147 + CallbackProxyClient.eventBroker.onSendChatMessage(e, message);
149 148 }
150 149  
151 150 public static void onResize(EventInfo<Minecraft> e)
152 151 {
153   - if (CallbackProxyClient.events == null) return;
154   - CallbackProxyClient.events.onResize(e.getSource());
  152 + if (CallbackProxyClient.eventBroker == null) return;
  153 + CallbackProxyClient.eventBroker.onResize(e.getSource());
155 154 }
156 155  
157 156 public static void preRenderFBO(EventInfo<Minecraft> e)
158 157 {
159   - if (CallbackProxyClient.events == null) return;
  158 + if (CallbackProxyClient.eventBroker == null) return;
160 159 CallbackProxyClient.fboEnabled = OpenGlHelper.isFramebufferEnabled();
161 160  
162 161 if (CallbackProxyClient.fboEnabled)
163 162 {
164 163 CallbackProxyClient.renderingFBO = true;
165   - CallbackProxyClient.events.preRenderFBO(e.getSource().getFramebuffer());
  164 + CallbackProxyClient.eventBroker.preRenderFBO(e.getSource().getFramebuffer());
166 165 }
167 166 }
168 167  
169 168 public static void postRenderFBO(EventInfo<Minecraft> e)
170 169 {
171   - if (CallbackProxyClient.events == null) return;
  170 + if (CallbackProxyClient.eventBroker == null) return;
172 171 CallbackProxyClient.renderingFBO = false;
173 172  
174 173 if (CallbackProxyClient.fboEnabled)
175 174 {
176   - CallbackProxyClient.events.postRenderFBO(e.getSource().getFramebuffer());
  175 + CallbackProxyClient.eventBroker.postRenderFBO(e.getSource().getFramebuffer());
177 176 }
178 177 }
179 178  
180 179 public static void renderFBO(EventInfo<Framebuffer> e, int width, int height, boolean flag)
181 180 {
182   - if (CallbackProxyClient.events == null) return;
  181 + if (CallbackProxyClient.eventBroker == null) return;
183 182 if (CallbackProxyClient.renderingFBO)
184 183 {
185   - CallbackProxyClient.events.onRenderFBO(e.getSource(), width, height);
  184 + CallbackProxyClient.eventBroker.onRenderFBO(e.getSource(), width, height);
186 185 }
187 186  
188 187 CallbackProxyClient.renderingFBO = false;
... ... @@ -190,7 +189,22 @@ public class CallbackProxyClient
190 189  
191 190 public static void onRenderWorld(EventInfo<EntityRenderer> e, float partialTicks, long timeSlice)
192 191 {
193   - CallbackProxyClient.events.onRenderWorld(partialTicks, timeSlice);
  192 + CallbackProxyClient.eventBroker.onRenderWorld(partialTicks, timeSlice);
  193 + }
  194 +
  195 + public static void onSaveScreenshot(ReturnEventInfo<ScreenShotHelper, IChatComponent> e, File gameDir, String name, int width, int height, Framebuffer fbo)
  196 + {
  197 + CallbackProxyClient.eventBroker.onScreenshot(e, name, width, height, fbo);
  198 + }
  199 +
  200 + public static void onRenderEntity(ReturnEventInfo<RenderManager, Boolean> e, Entity entity, double xPos, double yPos, double zPos, float yaw, float partialTicks, boolean hideBoundingBox, Render render)
  201 + {
  202 + CallbackProxyClient.eventBroker.onRenderEntity(e.getSource(), entity, xPos, yPos, zPos, yaw, partialTicks, render);
  203 + }
  204 +
  205 + public static void onPostRenderEntity(ReturnEventInfo<RenderManager, Boolean> e, Entity entity, double xPos, double yPos, double zPos, float yaw, float partialTicks, boolean hideBoundingBox, Render render)
  206 + {
  207 + CallbackProxyClient.eventBroker.onPostRenderEntity(e.getSource(), entity, xPos, yPos, zPos, yaw, partialTicks, render);
194 208 }
195 209  
196 210 /**
... ...
java/client/com/mumfrey/liteloader/client/EventsClient.java renamed to java/client/com/mumfrey/liteloader/client/LiteLoaderEventBrokerClient.java
... ... @@ -4,28 +4,22 @@ import net.minecraft.client.Minecraft;
4 4 import net.minecraft.client.entity.EntityPlayerSP;
5 5 import net.minecraft.client.gui.GuiNewChat;
6 6 import net.minecraft.client.gui.ScaledResolution;
  7 +import net.minecraft.client.renderer.entity.Render;
  8 +import net.minecraft.client.renderer.entity.RenderManager;
7 9 import net.minecraft.client.shader.Framebuffer;
8 10 import net.minecraft.entity.Entity;
9 11 import net.minecraft.network.play.client.C01PacketChatMessage;
10 12 import net.minecraft.server.integrated.IntegratedServer;
  13 +import net.minecraft.util.IChatComponent;
  14 +import net.minecraft.util.ScreenShotHelper;
11 15 import net.minecraft.util.Timer;
12 16  
13 17 import org.lwjgl.input.Mouse;
14 18  
15   -import com.mumfrey.liteloader.ChatRenderListener;
16   -import com.mumfrey.liteloader.FrameBufferListener;
17   -import com.mumfrey.liteloader.GameLoopListener;
18   -import com.mumfrey.liteloader.HUDRenderListener;
19   -import com.mumfrey.liteloader.InitCompleteListener;
20   -import com.mumfrey.liteloader.OutboundChatFilter;
21   -import com.mumfrey.liteloader.OutboundChatListener;
22   -import com.mumfrey.liteloader.PostRenderListener;
23   -import com.mumfrey.liteloader.RenderListener;
24   -import com.mumfrey.liteloader.Tickable;
25   -import com.mumfrey.liteloader.ViewportListener;
  19 +import com.mumfrey.liteloader.*;
26 20 import com.mumfrey.liteloader.client.overlays.IMinecraft;
27 21 import com.mumfrey.liteloader.common.LoadingProgress;
28   -import com.mumfrey.liteloader.core.Events;
  22 +import com.mumfrey.liteloader.core.LiteLoaderEventBroker;
29 23 import com.mumfrey.liteloader.core.InterfaceRegistrationDelegate;
30 24 import com.mumfrey.liteloader.core.LiteLoader;
31 25 import com.mumfrey.liteloader.core.event.HandlerList;
... ... @@ -33,11 +27,12 @@ import com.mumfrey.liteloader.core.event.HandlerList.ReturnLogicOp;
33 27 import com.mumfrey.liteloader.interfaces.FastIterableDeque;
34 28 import com.mumfrey.liteloader.launch.LoaderProperties;
35 29 import com.mumfrey.liteloader.transformers.event.EventInfo;
  30 +import com.mumfrey.liteloader.transformers.event.ReturnEventInfo;
36 31 import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
37 32  
38   -public class EventsClient extends Events<Minecraft, IntegratedServer>
  33 +public class LiteLoaderEventBrokerClient extends LiteLoaderEventBroker<Minecraft, IntegratedServer>
39 34 {
40   - private static EventsClient instance;
  35 + private static LiteLoaderEventBrokerClient instance;
41 36  
42 37 /**
43 38 * Reference to the game
... ... @@ -45,21 +40,6 @@ public class EventsClient extends Events&lt;Minecraft, IntegratedServer&gt;
45 40 protected final GameEngineClient engineClient;
46 41  
47 42 /**
48   - * Reference to the minecraft timer
49   - */
50   - private Timer minecraftTimer;
51   -
52   - /**
53   - * Flags which keep track of whether hooks have been applied
54   - */
55   - private boolean lateInitDone;
56   -
57   - /**
58   - * ScaledResolution used by the pre-chat and post-chat render callbacks
59   - */
60   - private ScaledResolution currentResolution;
61   -
62   - /**
63 43 * Current screen width
64 44 */
65 45 private int screenWidth = 854;
... ... @@ -91,20 +71,22 @@ public class EventsClient extends Events&lt;Minecraft, IntegratedServer&gt;
91 71 private FastIterableDeque<FrameBufferListener> frameBufferListeners = new HandlerList<FrameBufferListener>(FrameBufferListener.class);
92 72 private FastIterableDeque<InitCompleteListener> initListeners = new HandlerList<InitCompleteListener>(InitCompleteListener.class);
93 73 private FastIterableDeque<OutboundChatFilter> outboundChatFilters = new HandlerList<OutboundChatFilter>(OutboundChatFilter.class, ReturnLogicOp.AND);
  74 + private FastIterableDeque<ScreenshotListener> screenshotListeners = new HandlerList<ScreenshotListener>(ScreenshotListener.class, ReturnLogicOp.AND_BREAK_ON_FALSE);
  75 + private FastIterableDeque<EntityRenderListener> entityRenderListeners = new HandlerList<EntityRenderListener>(EntityRenderListener.class);
94 76  
95 77 @SuppressWarnings("cast")
96   - public EventsClient(LiteLoader loader, GameEngineClient engine, LoaderProperties properties)
  78 + public LiteLoaderEventBrokerClient(LiteLoader loader, GameEngineClient engine, LoaderProperties properties)
97 79 {
98 80 super(loader, engine, properties);
99 81  
100   - EventsClient.instance = this;
  82 + LiteLoaderEventBrokerClient.instance = this;
101 83  
102 84 this.engineClient = (GameEngineClient)engine;
103 85 }
104 86  
105   - static EventsClient getInstance()
  87 + static LiteLoaderEventBrokerClient getInstance()
106 88 {
107   - return EventsClient.instance;
  89 + return LiteLoaderEventBrokerClient.instance;
108 90 }
109 91  
110 92 /* (non-Javadoc)
... ... @@ -126,6 +108,8 @@ public class EventsClient extends Events&lt;Minecraft, IntegratedServer&gt;
126 108 delegate.registerInterface(FrameBufferListener.class);
127 109 delegate.registerInterface(InitCompleteListener.class);
128 110 delegate.registerInterface(OutboundChatFilter.class);
  111 + delegate.registerInterface(ScreenshotListener.class);
  112 + delegate.registerInterface(EntityRenderListener.class);
129 113 }
130 114  
131 115 /* (non-Javadoc)
... ... @@ -223,6 +207,22 @@ public class EventsClient extends Events&lt;Minecraft, IntegratedServer&gt;
223 207 {
224 208 this.frameBufferListeners.add(frameBufferListener);
225 209 }
  210 +
  211 + /**
  212 + * @param screenshotListener
  213 + */
  214 + public void addScreenshotListener(ScreenshotListener screenshotListener)
  215 + {
  216 + this.screenshotListeners.add(screenshotListener);
  217 + }
  218 +
  219 + /**
  220 + * @param entityRenderListener
  221 + */
  222 + public void addEntityRenderListener(EntityRenderListener entityRenderListener)
  223 + {
  224 + this.entityRenderListeners.add(entityRenderListener);
  225 + }
226 226  
227 227 /**
228 228 * Late initialisation callback
... ... @@ -232,23 +232,18 @@ public class EventsClient extends Events&lt;Minecraft, IntegratedServer&gt;
232 232 {
233 233 this.engine.refreshResources(false);
234 234  
235   - if (!this.lateInitDone)
  235 + for (InitCompleteListener initMod : this.initListeners)
236 236 {
237   - this.lateInitDone = true;
238   -
239   - for (InitCompleteListener initMod : this.initListeners)
  237 + try
240 238 {
241   - try
242   - {
243   - LoadingProgress.setMessage("Calling late init for mod %s...", initMod.getName());
244   - LiteLoaderLogger.info("Calling late init for mod %s", initMod.getName());
245   - initMod.onInitCompleted(this.engine.getClient(), this.loader);
246   - }
247   - catch (Throwable th)
248   - {
249   - this.mods.onLateInitFailed(initMod, th);
250   - LiteLoaderLogger.warning(th, "Error calling late init for mod %s", initMod.getName());
251   - }
  239 + LoadingProgress.setMessage("Calling late init for mod %s...", initMod.getName());
  240 + LiteLoaderLogger.info("Calling late init for mod %s", initMod.getName());
  241 + initMod.onInitCompleted(this.engine.getClient(), this.loader);
  242 + }
  243 + catch (Throwable th)
  244 + {
  245 + this.mods.onLateInitFailed(initMod, th);
  246 + LiteLoaderLogger.warning(th, "Error calling late init for mod %s", initMod.getName());
252 247 }
253 248 }
254 249  
... ... @@ -259,9 +254,9 @@ public class EventsClient extends Events&lt;Minecraft, IntegratedServer&gt;
259 254  
260 255 public void onResize(Minecraft minecraft)
261 256 {
262   - this.currentResolution = this.engineClient.getScaledResolution();
263   - this.screenWidth = this.currentResolution.getScaledWidth();
264   - this.screenHeight = this.currentResolution.getScaledHeight();
  257 + ScaledResolution currentResolution = this.engineClient.getScaledResolution();
  258 + this.screenWidth = currentResolution.getScaledWidth();
  259 + this.screenHeight = currentResolution.getScaledHeight();
265 260  
266 261 if (this.wasFullScreen != minecraft.isFullScreen())
267 262 {
... ... @@ -269,7 +264,7 @@ public class EventsClient extends Events&lt;Minecraft, IntegratedServer&gt;
269 264 }
270 265  
271 266 this.wasFullScreen = minecraft.isFullScreen();
272   - this.viewportListeners.all().onViewportResized(this.currentResolution, minecraft.displayWidth, minecraft.displayHeight);
  267 + this.viewportListeners.all().onViewportResized(currentResolution, minecraft.displayWidth, minecraft.displayHeight);
273 268 }
274 269  
275 270 /**
... ... @@ -286,9 +281,8 @@ public class EventsClient extends Events&lt;Minecraft, IntegratedServer&gt;
286 281 * @param timeSlice
287 282 * @param partialTicks2
288 283 */
289   - void postRenderEntities(float partialTicks2, long timeSlice)
  284 + void postRenderEntities(float partialTicks, long timeSlice)
290 285 {
291   - float partialTicks = (this.minecraftTimer != null) ? this.minecraftTimer.elapsedPartialTicks : 0.0F;
292 286 this.postRenderListeners.all().onPostRenderEntities(partialTicks);
293 287 }
294 288  
... ... @@ -298,9 +292,8 @@ public class EventsClient extends Events&lt;Minecraft, IntegratedServer&gt;
298 292 * @param timeSlice
299 293 * @param partialTicks2
300 294 */
301   - void postRender(float partialTicks2, long timeSlice)
  295 + void postRender(float partialTicks, long timeSlice)
302 296 {
303   - float partialTicks = (this.minecraftTimer != null) ? this.minecraftTimer.elapsedPartialTicks : 0.0F;
304 297 this.postRenderListeners.all().onPostRender(partialTicks);
305 298 }
306 299  
... ... @@ -376,24 +369,13 @@ public class EventsClient extends Events&lt;Minecraft, IntegratedServer&gt;
376 369 *
377 370 * @param clock True if this is a new tick (otherwise it's just a new frame)
378 371 */
379   - void onTick(boolean clock)
  372 + void onTick()
380 373 {
381 374 this.profiler.startSection("litemods");
382   - float partialTicks = 0.0F;
383   -
384   - // Try to get the minecraft timer object and determine the value of the
385   - // partialTicks
386   - if (clock || this.minecraftTimer == null)
387   - {
388   - this.minecraftTimer = ((IMinecraft)this.engine.getClient()).getTimer();
389   - }
390 375  
391   - // Hooray, we got the timer reference
392   - if (this.minecraftTimer != null)
393   - {
394   - partialTicks = this.minecraftTimer.renderPartialTicks;
395   - clock = this.minecraftTimer.elapsedTicks > 0;
396   - }
  376 + Timer minecraftTimer = ((IMinecraft)this.engine.getClient()).getTimer();
  377 + float partialTicks = minecraftTimer.renderPartialTicks;
  378 + boolean clock = minecraftTimer.elapsedTicks > 0;
397 379  
398 380 Minecraft minecraft = this.engine.getClient();
399 381  
... ... @@ -414,18 +396,11 @@ public class EventsClient extends Events&lt;Minecraft, IntegratedServer&gt;
414 396 this.tickListeners.all().onTick(minecraft, partialTicks, inGame, clock);
415 397  
416 398 // Detected world change
417   - if (minecraft.theWorld != null)
  399 + int worldHashCode = (minecraft.theWorld != null) ? minecraft.theWorld.hashCode() : 0;
  400 + if (worldHashCode != this.worldHashCode)
418 401 {
419   - if (minecraft.theWorld.hashCode() != this.worldHashCode)
420   - {
421   - this.worldHashCode = minecraft.theWorld.hashCode();
422   - super.onWorldChanged(minecraft.theWorld);
423   - }
424   - }
425   - else
426   - {
427   - this.worldHashCode = 0;
428   - super.onWorldChanged(null);
  402 + this.worldHashCode = worldHashCode;
  403 + super.onWorldChanged(minecraft.theWorld);
429 404 }
430 405  
431 406 this.profiler.endSection();
... ... @@ -481,8 +456,55 @@ public class EventsClient extends Events&lt;Minecraft, IntegratedServer&gt;
481 456 * @param partialTicks
482 457 * @param timeSlice
483 458 */
484   - public void onRenderWorld(float partialTicks, long timeSlice)
  459 + void onRenderWorld(float partialTicks, long timeSlice)
485 460 {
486 461 this.renderListeners.all().onRenderWorld();
487 462 }
  463 +
  464 + /**
  465 + * @param e
  466 + * @param name
  467 + * @param width
  468 + * @param height
  469 + * @param fbo
  470 + */
  471 + void onScreenshot(ReturnEventInfo<ScreenShotHelper, IChatComponent> e, String name, int width, int height, Framebuffer fbo)
  472 + {
  473 + ReturnValue<IChatComponent> ret = new ReturnValue<IChatComponent>(e.getReturnValue());
  474 +
  475 + if (!this.screenshotListeners.all().onSaveScreenshot(name, width, height, fbo, ret))
  476 + {
  477 + e.setReturnValue(ret.get());
  478 + }
  479 + }
  480 +
  481 + /**
  482 + * @param source
  483 + * @param entity
  484 + * @param xPos
  485 + * @param yPos
  486 + * @param zPos
  487 + * @param yaw
  488 + * @param partialTicks
  489 + * @param render
  490 + */
  491 + public void onRenderEntity(RenderManager source, Entity entity, double xPos, double yPos, double zPos, float yaw, float partialTicks, Render render)
  492 + {
  493 + this.entityRenderListeners.all().onRenderEntity(render, entity, xPos, yPos, zPos, yaw, partialTicks);
  494 + }
  495 +
  496 + /**
  497 + * @param source
  498 + * @param entity
  499 + * @param xPos
  500 + * @param yPos
  501 + * @param zPos
  502 + * @param yaw
  503 + * @param partialTicks
  504 + * @param render
  505 + */
  506 + public void onPostRenderEntity(RenderManager source, Entity entity, double xPos, double yPos, double zPos, float yaw, float partialTicks, Render render)
  507 + {
  508 + this.entityRenderListeners.all().onPostRenderEntity(render, entity, xPos, yPos, zPos, yaw, partialTicks);
  509 + }
488 510 }
... ...
java/client/com/mumfrey/liteloader/client/PacketEventsClient.java
... ... @@ -7,6 +7,7 @@ import net.minecraft.network.login.server.S02PacketLoginSuccess;
7 7 import net.minecraft.network.play.INetHandlerPlayClient;
8 8 import net.minecraft.network.play.server.S01PacketJoinGame;
9 9 import net.minecraft.network.play.server.S02PacketChat;
  10 +import net.minecraft.util.ChatComponentText;
10 11 import net.minecraft.util.IChatComponent;
11 12  
12 13 import com.mumfrey.liteloader.ChatFilter;
... ... @@ -15,6 +16,7 @@ import com.mumfrey.liteloader.PostLoginListener;
15 16 import com.mumfrey.liteloader.PreJoinGameListener;
16 17 import com.mumfrey.liteloader.common.transformers.PacketEventInfo;
17 18 import com.mumfrey.liteloader.core.ClientPluginChannels;
  19 +import com.mumfrey.liteloader.core.LiteLoaderEventBroker.ReturnValue;
18 20 import com.mumfrey.liteloader.core.InterfaceRegistrationDelegate;
19 21 import com.mumfrey.liteloader.core.LiteLoader;
20 22 import com.mumfrey.liteloader.core.PacketEvents;
... ... @@ -146,14 +148,22 @@ public class PacketEventsClient extends PacketEvents
146 148 IChatComponent chat = packet.func_148915_c();
147 149 String message = chat.getFormattedText();
148 150  
149   - // Chat filters get a stab at the chat first, if any filter returns
150   - // false the chat is discarded
  151 + // Chat filters get a stab at the chat first, if any filter returns false the chat is discarded
151 152 for (ChatFilter chatFilter : this.chatFilters)
152 153 {
153   - if (chatFilter.onChat(packet, chat, message))
  154 + ReturnValue<IChatComponent> ret = new ReturnValue<IChatComponent>();
  155 +
  156 + if (chatFilter.onChat(chat, message, ret))
154 157 {
155   - chat = packet.func_148915_c();
156   - message = chat.getFormattedText();
  158 + if (ret.isSet())
  159 + {
  160 + chat = ret.get();
  161 + if (chat == null)
  162 + {
  163 + chat = new ChatComponentText("");
  164 + }
  165 + message = chat.getFormattedText();
  166 + }
157 167 }
158 168 else
159 169 {
... ...
java/client/com/mumfrey/liteloader/client/api/ObjectFactoryClient.java
... ... @@ -4,7 +4,7 @@ import net.minecraft.client.Minecraft;
4 4 import net.minecraft.client.gui.GuiScreen;
5 5 import net.minecraft.server.integrated.IntegratedServer;
6 6  
7   -import com.mumfrey.liteloader.client.EventsClient;
  7 +import com.mumfrey.liteloader.client.LiteLoaderEventBrokerClient;
8 8 import com.mumfrey.liteloader.client.ClientPluginChannelsClient;
9 9 import com.mumfrey.liteloader.client.GameEngineClient;
10 10 import com.mumfrey.liteloader.client.LiteLoaderPanelManager;
... ... @@ -12,7 +12,7 @@ import com.mumfrey.liteloader.client.PacketEventsClient;
12 12 import com.mumfrey.liteloader.client.gui.startup.LoadingBar;
13 13 import com.mumfrey.liteloader.common.GameEngine;
14 14 import com.mumfrey.liteloader.core.ClientPluginChannels;
15   -import com.mumfrey.liteloader.core.Events;
  15 +import com.mumfrey.liteloader.core.LiteLoaderEventBroker;
16 16 import com.mumfrey.liteloader.core.LiteLoader;
17 17 import com.mumfrey.liteloader.core.PacketEvents;
18 18 import com.mumfrey.liteloader.core.ServerPluginChannels;
... ... @@ -34,7 +34,7 @@ class ObjectFactoryClient implements ObjectFactory&lt;Minecraft, IntegratedServer&gt;
34 34  
35 35 private LoaderProperties properties;
36 36  
37   - private EventsClient clientEvents;
  37 + private LiteLoaderEventBrokerClient clientEvents;
38 38  
39 39 private PacketEventsClient clientPacketEvents;
40 40  
... ... @@ -53,11 +53,11 @@ class ObjectFactoryClient implements ObjectFactory&lt;Minecraft, IntegratedServer&gt;
53 53 }
54 54  
55 55 @Override
56   - public Events<Minecraft, IntegratedServer> getEventBroker()
  56 + public LiteLoaderEventBroker<Minecraft, IntegratedServer> getEventBroker()
57 57 {
58 58 if (this.clientEvents == null)
59 59 {
60   - this.clientEvents = new EventsClient(LiteLoader.getInstance(), (GameEngineClient)this.getGameEngine(), this.properties);
  60 + this.clientEvents = new LiteLoaderEventBrokerClient(LiteLoader.getInstance(), (GameEngineClient)this.getGameEngine(), this.properties);
61 61 }
62 62  
63 63 return this.clientEvents;
... ...
java/client/com/mumfrey/liteloader/client/gui/GuiPanel.java
... ... @@ -2,7 +2,6 @@ package com.mumfrey.liteloader.client.gui;
2 2  
3 3 import static com.mumfrey.liteloader.gl.GL.*;
4 4  
5   -import java.io.IOException;
6 5 import java.util.LinkedList;
7 6 import java.util.List;
8 7  
... ... @@ -125,7 +124,7 @@ public abstract class GuiPanel extends Gui
125 124 * @param mouseY
126 125 * @param mouseButton
127 126 */
128   - void mousePressed(int mouseX, int mouseY, int mouseButton) throws IOException
  127 + void mousePressed(int mouseX, int mouseY, int mouseButton)
129 128 {
130 129 if (mouseButton == 0)
131 130 {
... ...
java/client/com/mumfrey/liteloader/client/gui/GuiPanelAbout.java
1 1 package com.mumfrey.liteloader.client.gui;
2 2  
3   -import java.io.IOException;
4 3 import java.net.URI;
5 4 import java.util.ArrayList;
6 5 import java.util.List;
... ... @@ -216,7 +215,7 @@ class GuiPanelAbout extends GuiPanel implements ScrollPanelContent
216 215 }
217 216  
218 217 @Override
219   - void mousePressed(int mouseX, int mouseY, int mouseButton) throws IOException
  218 + void mousePressed(int mouseX, int mouseY, int mouseButton)
220 219 {
221 220 this.scrollPane.mousePressed(mouseX, mouseY, mouseButton);
222 221  
... ...
java/client/com/mumfrey/liteloader/client/gui/GuiPanelConfigContainer.java
... ... @@ -2,9 +2,6 @@ package com.mumfrey.liteloader.client.gui;
2 2  
3 3 import static com.mumfrey.liteloader.gl.GL.*;
4 4 import static com.mumfrey.liteloader.gl.GLClippingPlanes.*;
5   -
6   -import java.io.IOException;
7   -
8 5 import net.minecraft.client.Minecraft;
9 6 import net.minecraft.client.gui.GuiButton;
10 7 import net.minecraft.client.resources.I18n;
... ... @@ -218,10 +215,9 @@ class GuiPanelConfigContainer extends GuiPanel implements ConfigPanelHost
218 215 * @param mouseX
219 216 * @param mouseY
220 217 * @param mouseButton
221   - * @throws IOException
222 218 */
223 219 @Override
224   - void mousePressed(int mouseX, int mouseY, int mouseButton) throws IOException
  220 + void mousePressed(int mouseX, int mouseY, int mouseButton)
225 221 {
226 222 if (mouseButton == 0)
227 223 {
... ...
java/client/com/mumfrey/liteloader/client/gui/GuiPanelError.java
1 1 package com.mumfrey.liteloader.client.gui;
2 2  
3   -import java.io.IOException;
4 3 import java.io.PrintWriter;
5 4 import java.io.StringWriter;
6 5 import java.util.ArrayList;
... ... @@ -131,7 +130,7 @@ public class GuiPanelError extends GuiPanel implements ScrollPanelContent
131 130 }
132 131  
133 132 @Override
134   - void mousePressed(int mouseX, int mouseY, int mouseButton) throws IOException
  133 + void mousePressed(int mouseX, int mouseY, int mouseButton)
135 134 {
136 135 this.scrollPane.mousePressed(mouseX, mouseY, mouseButton);
137 136 super.mousePressed(mouseX, mouseY, mouseButton);
... ...
java/client/com/mumfrey/liteloader/client/gui/GuiPanelLiteLoaderLog.java
... ... @@ -2,7 +2,6 @@ package com.mumfrey.liteloader.client.gui;
2 2  
3 3 import static com.mumfrey.liteloader.gl.GL.*;
4 4  
5   -import java.io.IOException;
6 5 import java.net.URI;
7 6 import java.util.ArrayList;
8 7 import java.util.List;
... ... @@ -333,10 +332,9 @@ class GuiPanelLiteLoaderLog extends GuiPanel implements ScrollPanelContent
333 332 * @param mouseX
334 333 * @param mouseY
335 334 * @param mouseButton
336   - * @throws IOException
337 335 */
338 336 @Override
339   - void mousePressed(int mouseX, int mouseY, int mouseButton) throws IOException
  337 + void mousePressed(int mouseX, int mouseY, int mouseButton)
340 338 {
341 339 this.scrollPane.mousePressed(mouseX, mouseY, mouseButton);
342 340  
... ...
java/client/com/mumfrey/liteloader/client/gui/GuiPanelMods.java
... ... @@ -3,7 +3,6 @@ package com.mumfrey.liteloader.client.gui;
3 3 import static com.mumfrey.liteloader.gl.GL.*;
4 4 import static com.mumfrey.liteloader.gl.GLClippingPlanes.*;
5 5  
6   -import java.io.IOException;
7 6 import java.util.ArrayList;
8 7 import java.util.List;
9 8 import java.util.Map;
... ... @@ -164,7 +163,7 @@ public class GuiPanelMods extends GuiPanel
164 163 }
165 164  
166 165 @Override
167   - void mousePressed(int mouseX, int mouseY, int mouseButton) throws IOException
  166 + void mousePressed(int mouseX, int mouseY, int mouseButton)
168 167 {
169 168 if (mouseButton == 0)
170 169 {
... ...
java/client/com/mumfrey/liteloader/client/gui/GuiScrollPanel.java
... ... @@ -2,9 +2,6 @@ package com.mumfrey.liteloader.client.gui;
2 2  
3 3 import static com.mumfrey.liteloader.gl.GL.*;
4 4 import static com.mumfrey.liteloader.gl.GLClippingPlanes.*;
5   -
6   -import java.io.IOException;
7   -
8 5 import net.minecraft.client.Minecraft;
9 6 import net.minecraft.client.gui.GuiButton;
10 7  
... ... @@ -142,7 +139,7 @@ class GuiScrollPanel extends GuiPanel
142 139 }
143 140  
144 141 @Override
145   - public void mousePressed(int mouseX, int mouseY, int mouseButton) throws IOException
  142 + public void mousePressed(int mouseX, int mouseY, int mouseButton)
146 143 {
147 144 mouseY += this.scrollBar.getValue() - this.top;
148 145 mouseX -= this.left;
... ...
java/client/com/mumfrey/liteloader/client/transformers/LiteLoaderEventInjectionTransformer.java
... ... @@ -51,6 +51,9 @@ public class LiteLoaderEventInjectionTransformer extends EventInjectionTransform
51 51 Event onRespawnPlayer = Event.getOrCreate("onRespawnPlayer", false);
52 52 Event onStartupComplete = Event.getOrCreate("onStartupComplete", false);
53 53 Event onSessionProfileBad = Event.getOrCreate("onSessionProfileBad", true);
  54 + Event onSaveScreenshot = Event.getOrCreate("onSaveScreenshot", true);
  55 + Event onRenderEntity = Event.getOrCreate("onRenderEntity", false);
  56 + Event onPostRenderEntity = Event.getOrCreate("onPostRenderEntity", false);
54 57  
55 58 // Injection Points
56 59 InjectionPoint methodHead = new MethodHead();
... ... @@ -62,6 +65,8 @@ public class LiteLoaderEventInjectionTransformer extends EventInjectionTransform
62 65 InjectionPoint beforeRender = new BeforeInvoke(updateCameraAndRender);
63 66 InjectionPoint beforeDrawChat = new BeforeInvoke(drawChat);
64 67 InjectionPoint beforeEndProfiler = new BeforeInvoke(endSection);
  68 + InjectionPoint beforeIsFBOEnabled = new BeforeInvoke(isFramebufferEnabled);
  69 + InjectionPoint beforeRenderEntity = new BeforeInvoke(doRender).setCaptureLocals(true);
65 70 InjectionPoint beforeTickProfiler = new BeforeStringInvoke("tick", startSection);
66 71 InjectionPoint beforeCenterProfiler = new BeforeStringInvoke("center", startSection);
67 72 InjectionPoint beforeRenderProfiler = new BeforeStringInvoke("gameRenderer", endStartSection);
... ... @@ -95,6 +100,9 @@ public class LiteLoaderEventInjectionTransformer extends EventInjectionTransform
95 100 this.add(onSpawnPlayer, spawnPlayer, (methodReturn), "onSpawnPlayer");
96 101 this.add(onRespawnPlayer, respawnPlayer, (methodReturn), "onRespawnPlayer");
97 102 this.add(onStartupComplete, startGame, (methodReturn), "onStartupComplete");
  103 + this.add(onSaveScreenshot, saveScreenshot, (beforeIsFBOEnabled), "onSaveScreenshot");
  104 + this.add(onRenderEntity, doRenderEntity, (beforeRenderEntity), "onRenderEntity");
  105 + this.add(onPostRenderEntity, doRenderEntity, after(beforeRenderEntity), "onPostRenderEntity");
98 106  
99 107 // Compatibility handlers
100 108 this.add(onSessionProfileBad, getProfile, (beforeNewGameProfile), "generateOfflineUUID");
... ...
java/common/com/mumfrey/liteloader/core/LiteLoader.java
... ... @@ -143,7 +143,7 @@ public final class LiteLoader
143 143 /**
144 144 * Event manager
145 145 */
146   - private Events<?, ?> events;
  146 + private LiteLoaderEventBroker<?, ?> events;
147 147  
148 148 /**
149 149 * Plugin channel manager
... ...
java/common/com/mumfrey/liteloader/core/Events.java renamed to java/common/com/mumfrey/liteloader/core/LiteLoaderEventBroker.java
... ... @@ -33,9 +33,45 @@ import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
33 33 * @param <TClient> Type of the client runtime, "Minecraft" on client and null on the server
34 34 * @param <TServer> Type of the server runtime, "IntegratedServer" on the client, "MinecraftServer" on the server
35 35 */
36   -public abstract class Events<TClient, TServer extends MinecraftServer> implements InterfaceProvider, IResourceManagerReloadListener
  36 +public abstract class LiteLoaderEventBroker<TClient, TServer extends MinecraftServer> implements InterfaceProvider, IResourceManagerReloadListener
37 37 {
38 38 /**
  39 + * @author Adam Mummery-Smith
  40 + *
  41 + * @param <T>
  42 + */
  43 + public static class ReturnValue<T>
  44 + {
  45 + private T value;
  46 + private boolean isSet;
  47 +
  48 + public ReturnValue(T value)
  49 + {
  50 + this.value = value;
  51 + }
  52 +
  53 + public ReturnValue()
  54 + {
  55 + }
  56 +
  57 + public boolean isSet()
  58 + {
  59 + return this.isSet;
  60 + }
  61 +
  62 + public T get()
  63 + {
  64 + return this.value;
  65 + }
  66 +
  67 + public void set(T value)
  68 + {
  69 + this.isSet = true;
  70 + this.value = value;
  71 + }
  72 + }
  73 +
  74 + /**
39 75 * Reference to the loader instance
40 76 */
41 77 protected final LiteLoader loader;
... ... @@ -61,14 +97,14 @@ public abstract class Events&lt;TClient, TServer extends MinecraftServer&gt; implement
61 97 * List of mods which monitor server player events
62 98 */
63 99 private FastIterable<ServerPlayerListener> serverPlayerListeners = new HandlerList<ServerPlayerListener>(ServerPlayerListener.class);
64   -
  100 +
65 101 /**
66 102 * Package private ctor
67 103 *
68 104 * @param loader
69 105 * @param minecraft
70 106 */
71   - public Events(LiteLoader loader, GameEngine<TClient, TServer> engine, LoaderProperties properties)
  107 + public LiteLoaderEventBroker(LiteLoader loader, GameEngine<TClient, TServer> engine, LoaderProperties properties)
72 108 {
73 109 this.loader = loader;
74 110 this.engine = engine;
... ...
java/common/com/mumfrey/liteloader/core/LiteLoaderVersion.java
... ... @@ -37,7 +37,7 @@ public enum LiteLoaderVersion
37 37 MC_1_7_10_R1(28, 1404673785, "1.7.10", "1.7.10_01", "1.7.10"),
38 38 MC_1_7_10_R2(29, 1405369406, "1.7.10", "1.7.10_02", "1.7.10"),
39 39 MC_1_7_10_R3(30, 1407687918, "1.7.10", "1.7.10_03", "1.7.10", "1.7.10_03"),
40   - MC_1_7_10_R4(31, 0, "1.7.10", "1.7.10_04", "1.7.10", "1.7.10_03", "1.7.10_04"),
  40 + MC_1_7_10_R4(31, 1412718533, "1.7.10", "1.7.10_04", "1.7.10", "1.7.10_03", "1.7.10_04"),
41 41 MC_1_8_0_R0(32, 0, "1.8.0", "1.8.0", "1.8", "1.8.0");
42 42  
43 43 /**
... ...
java/common/com/mumfrey/liteloader/core/event/EventProxy.java
... ... @@ -146,7 +146,12 @@ public final class EventProxy
146 146 }
147 147 tpl.append(")\n\t {\n\t // handler code here\n\t }");
148 148  
149   - return tpl.toString();
  149 + String template = tpl.toString();
  150 + if (template.contains(", ReturnType>"))
  151 + {
  152 + template = template.replace("static void", "static <ReturnType> void");
  153 + }
  154 + return template;
150 155 }
151 156  
152 157 private static boolean appendTypeName(StringBuilder tpl, Type type, String sourceClass)
... ... @@ -160,7 +165,7 @@ public final class EventProxy
160 165 String typeName = type.getClassName();
161 166 typeName = typeName.substring(typeName.lastIndexOf('.') + 1);
162 167 tpl.append(typeName);
163   - if (typeName.endsWith("ReturnEventInfo")) tpl.append('<').append(sourceClass).append(", ?>");
  168 + if (typeName.endsWith("ReturnEventInfo")) tpl.append('<').append(sourceClass).append(", ReturnType>");
164 169 else if (typeName.endsWith("EventInfo")) tpl.append('<').append(sourceClass).append('>');
165 170 return false;
166 171 default:
... ...
java/common/com/mumfrey/liteloader/core/event/HandlerList.java
... ... @@ -25,6 +25,7 @@ import org.objectweb.asm.tree.*;
25 25 import com.mumfrey.liteloader.Priority;
26 26 import com.mumfrey.liteloader.core.runtime.Obf;
27 27 import com.mumfrey.liteloader.interfaces.FastIterableDeque;
  28 +import com.mumfrey.liteloader.transformers.ByteCodeUtilities;
28 29 import com.mumfrey.liteloader.util.SortableValue;
29 30 import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
30 31  
... ... @@ -923,7 +924,7 @@ public class HandlerList&lt;T&gt; extends LinkedList&lt;T&gt; implements FastIterableDeque&lt;T
923 924 boolean isOrOperation = this.logicOp.isOr();
924 925 boolean breakOnMatch = this.logicOp.breakOnMatch();
925 926 int initialValue = isOrOperation && (!this.logicOp.assumeTrue() || this.size > 0) ? Opcodes.ICONST_0 : Opcodes.ICONST_1;
926   - int localIndex = this.getFirstLocalIndex(args);
  927 + int localIndex = ByteCodeUtilities.getArgsSize(args);
927 928  
928 929 method.instructions.add(new InsnNode(initialValue));
929 930 method.instructions.add(new VarInsnNode(Opcodes.ISTORE, localIndex));
... ... @@ -984,13 +985,6 @@ public class HandlerList&lt;T&gt; extends LinkedList&lt;T&gt; implements FastIterableDeque&lt;T
984 985 return argNumber;
985 986 }
986 987  
987   - private int getFirstLocalIndex(Type[] args)
988   - {
989   - int argNumber = 1;
990   - for (Type type : args) argNumber += type.getSize();
991   - return argNumber;
992   - }
993   -
994 988 /**
995 989 * @param baseName
996 990 * @param typeName
... ...
java/common/com/mumfrey/liteloader/core/runtime/Methods.java
1 1 package com.mumfrey.liteloader.core.runtime;
2 2  
  3 +import java.io.File;
  4 +
3 5 import com.mumfrey.liteloader.transformers.event.MethodInfo;
4 6  
5 7 /**
... ... @@ -29,6 +31,11 @@ public abstract class Methods
29 31 public static final MethodInfo respawnPlayer = new MethodInfo(Obf.ServerConfigurationManager, Obf.respawnPlayer, Obf.EntityPlayerMP, Obf.EntityPlayerMP, Integer.TYPE, Boolean.TYPE);
30 32 public static final MethodInfo glClear = new MethodInfo(Obf.GlStateManager, Obf.clear, Void.TYPE, Integer.TYPE);
31 33 public static final MethodInfo getProfile = new MethodInfo(Obf.Session, Obf.getProfile, Obf.GameProfile);
  34 + public static final MethodInfo saveScreenshot = new MethodInfo(Obf.ScreenShotHelper, Obf.saveScreenshot, Obf.IChatComponent, File.class, String.class, Integer.TYPE, Integer.TYPE, Obf.FrameBuffer);
  35 + public static final MethodInfo isFramebufferEnabled = new MethodInfo(Obf.OpenGlHelper, Obf.isFramebufferEnabled, Boolean.TYPE);
  36 + public static final MethodInfo doRenderEntity = new MethodInfo(Obf.RenderManager, Obf.doRenderEntity, Boolean.TYPE, Obf.Entity, Double.TYPE, Double.TYPE, Double.TYPE, Float.TYPE, Float.TYPE, Boolean.TYPE);
  37 + public static final MethodInfo doRender = new MethodInfo(Obf.Render, Obf.doRender, Void.TYPE, Obf.Entity, Double.TYPE, Double.TYPE, Double.TYPE, Float.TYPE, Float.TYPE);
  38 + public static final MethodInfo doRenderShadowAndFire = new MethodInfo(Obf.Render, Obf.doRenderShadowAndFire, Void.TYPE, Obf.Entity, Double.TYPE, Double.TYPE, Double.TYPE, Float.TYPE, Float.TYPE);
32 39  
33 40 public static final MethodInfo startSection = new MethodInfo(Obf.Profiler, Obf.startSection, Void.TYPE, String.class);
34 41 public static final MethodInfo endSection = new MethodInfo(Obf.Profiler, Obf.endSection, Void.TYPE);
... ...
java/common/com/mumfrey/liteloader/core/runtime/Obf.java
... ... @@ -51,6 +51,12 @@ public class Obf
51 51 public static final Obf GuiNewChat = new Obf("net.minecraft.client.gui.GuiNewChat", "buh" );
52 52 public static final Obf GlStateManager = new Obf("net.minecraft.client.renderer.GlStateManager", "cjm" );
53 53 public static final Obf Session = new Obf("net.minecraft.util.Session", "btw" );
  54 + public static final Obf IChatComponent = new Obf("net.minecraft.util.IChatComponent", "ho" );
  55 + public static final Obf ScreenShotHelper = new Obf("net.minecraft.util.ScreenShotHelper", "btt" );
  56 + public static final Obf OpenGlHelper = new Obf("net.minecraft.client.renderer.OpenGlHelper", "dax" );
  57 + public static final Obf Entity = new Obf("net.minecraft.entity.Entity", "wv" );
  58 + public static final Obf RenderManager = new Obf("net.minecraft.client.renderer.entity.RenderManager", "cpt" );
  59 + public static final Obf Render = new Obf("net.minecraft.client.renderer.entity.Render", "cpu" );
54 60  
55 61 // Fields
56 62 // -----------------------------------------------------------------------------------------
... ... @@ -94,6 +100,11 @@ public class Obf
94 100 public static final Obf clear = new Obf("func_179086_m", "m" );
95 101 public static final Obf renderWorldPass = new Obf("func_175068_a", "a" );
96 102 public static final Obf getProfile = new Obf("func_148256_e", "a" );
  103 + public static final Obf saveScreenshot = new Obf("func_148260_a", "a" );
  104 + public static final Obf isFramebufferEnabled = new Obf("func_148822_b", "i" );
  105 + public static final Obf doRenderEntity = new Obf("func_147939_a", "a" );
  106 + public static final Obf doRender = new Obf("func_76986_a", "a" );
  107 + public static final Obf doRenderShadowAndFire = new Obf("func_76979_b", "b" );
97 108  
98 109 public static final int MCP = 0;
99 110 public static final int SRG = 1;
... ...
java/common/com/mumfrey/liteloader/interfaces/ObjectFactory.java
... ... @@ -4,7 +4,7 @@ import net.minecraft.server.MinecraftServer;
4 4  
5 5 import com.mumfrey.liteloader.common.GameEngine;
6 6 import com.mumfrey.liteloader.core.ClientPluginChannels;
7   -import com.mumfrey.liteloader.core.Events;
  7 +import com.mumfrey.liteloader.core.LiteLoaderEventBroker;
8 8 import com.mumfrey.liteloader.core.PacketEvents;
9 9 import com.mumfrey.liteloader.core.ServerPluginChannels;
10 10 import com.mumfrey.liteloader.permissions.PermissionsManagerClient;
... ... @@ -20,7 +20,7 @@ import com.mumfrey.liteloader.permissions.PermissionsManagerServer;
20 20 */
21 21 public interface ObjectFactory<TClient, TServer extends MinecraftServer>
22 22 {
23   - public abstract Events<TClient, TServer> getEventBroker();
  23 + public abstract LiteLoaderEventBroker<TClient, TServer> getEventBroker();
24 24  
25 25 public abstract PacketEvents getPacketEventBroker();
26 26  
... ...
java/common/com/mumfrey/liteloader/modconfig/ConfigPanel.java
1 1 package com.mumfrey.liteloader.modconfig;
2 2  
3   -import java.io.IOException;
4 3  
5 4 /**
6 5 * Interface for mod config panels to implement
... ... @@ -61,7 +60,7 @@ public interface ConfigPanel
61 60 * @param mouseY
62 61 * @param mouseButton
63 62 */
64   - public abstract void mousePressed(ConfigPanelHost host, int mouseX, int mouseY, int mouseButton) throws IOException;
  63 + public abstract void mousePressed(ConfigPanelHost host, int mouseX, int mouseY, int mouseButton);
65 64  
66 65 /**
67 66 * Called when a mouse button is released
... ...
java/common/com/mumfrey/liteloader/transformers/ByteCodeUtilities.java
... ... @@ -74,6 +74,49 @@ public abstract class ByteCodeUtilities
74 74 }
75 75 }
76 76 }
  77 +
  78 + /**
  79 + * Get the first variable index in the supplied method which is not an argument or "this" reference, this corresponds
  80 + * to the size of the arguments passed in to the method plus an extra spot for "this" if the method is non-static
  81 + *
  82 + * @param method
  83 + * @return
  84 + */
  85 + public static int getFirstNonArgLocalIndex(MethodNode method)
  86 + {
  87 + return ByteCodeUtilities.getFirstNonArgLocalIndex(Type.getArgumentTypes(method.desc), (method.access & Opcodes.ACC_STATIC) == 0);
  88 + }
  89 +
  90 + /**
  91 + * Get the first non-arg variable index based on the supplied arg array and whether to include the "this" reference,
  92 + * this corresponds to the size of the arguments passed in to the method plus an extra spot for "this" is specified
  93 +
  94 + * @param args
  95 + * @param includeThis
  96 + * @return
  97 + */
  98 + public static int getFirstNonArgLocalIndex(Type[] args, boolean includeThis)
  99 + {
  100 + return ByteCodeUtilities.getArgsSize(args) + (includeThis ? 1 : 0);
  101 + }
  102 +
  103 + /**
  104 + * Get the size of the specified args array in local variable terms (eg. doubles and longs take two spaces)
  105 + *
  106 + * @param args
  107 + * @return
  108 + */
  109 + public static int getArgsSize(Type[] args)
  110 + {
  111 + int size = 0;
  112 +
  113 + for (Type type : args)
  114 + {
  115 + size += type.getSize();
  116 + }
  117 +
  118 + return size;
  119 + }
77 120  
78 121 /**
79 122 * Attempts to identify available locals at an arbitrary point in the bytecode specified by node.
... ... @@ -121,8 +164,7 @@ public abstract class ByteCodeUtilities
121 164 FrameNode frameNode = (FrameNode)insn;
122 165  
123 166 // localPos tracks the location in the frame node's locals list, which doesn't leave space for TOP entries
124   - int localPos = 0;
125   - for (int framePos = 0; framePos < frame.length; framePos++)
  167 + for (int localPos = 0, framePos = 0; framePos < frame.length; framePos++, localPos++)
126 168 {
127 169 // Get the local at the current position in the FrameNode's locals list
128 170 final Object localType = (localPos < frameNode.local.size()) ? frameNode.local.get(localPos) : null;
... ... @@ -163,8 +205,6 @@ public abstract class ByteCodeUtilities
163 205 {
164 206 throw new RuntimeException("Invalid value " + localType + " in locals array at position " + localPos + " in " + classNode.name + "." + method.name + method.desc);
165 207 }
166   -
167   - localPos++;
168 208 }
169 209 }
170 210 else if (insn instanceof VarInsnNode)
... ...
java/common/com/mumfrey/liteloader/transformers/event/Event.java
... ... @@ -312,11 +312,11 @@ public class Event implements Comparable&lt;Event&gt;
312 312 // Pre-flight checks
313 313 this.validate(injectionPoint, cancellable, globalEventID);
314 314  
315   - Type[] argumentTypes = Type.getArgumentTypes(this.method.desc);
316   - int initialFrameSize = argumentTypes.length + (this.methodIsStatic ? 0 : 1);
  315 + Type[] arguments = Type.getArgumentTypes(this.method.desc);
  316 + int initialFrameSize = ByteCodeUtilities.getFirstNonArgLocalIndex(arguments, !this.methodIsStatic);
317 317  
318 318 boolean doCaptureLocals = captureLocals && locals != null && locals.length > initialFrameSize;
319   - String eventDescriptor = this.generateEventDescriptor(doCaptureLocals, locals, argumentTypes, initialFrameSize);
  319 + String eventDescriptor = this.generateEventDescriptor(doCaptureLocals, locals, arguments, initialFrameSize);
320 320  
321 321 // Create the handler delegate method
322 322 MethodNode handler = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC, Event.getHandlerName(globalEventID), eventDescriptor, null, null);
... ... @@ -324,7 +324,7 @@ public class Event implements Comparable&lt;Event&gt;
324 324  
325 325 LiteLoaderLogger.debug("Event %s is spawning handler %s in class %s", this.name, handler.name, Event.getActiveProxyRef());
326 326  
327   - int ctorMAXS = 0, invokeMAXS = argumentTypes.length + (doCaptureLocals ? locals.length - initialFrameSize : 0);
  327 + int ctorMAXS = 0, invokeMAXS = arguments.length + (doCaptureLocals ? locals.length - initialFrameSize : 0);
328 328 int eventInfoVar = this.method.maxLocals++;
329 329  
330 330 InsnList insns = new InsnList();
... ... @@ -332,12 +332,12 @@ public class Event implements Comparable&lt;Event&gt;
332 332 // Instance the EventInfo for this event
333 333 insns.add(new TypeInsnNode(Opcodes.NEW, this.eventInfoClass)); ctorMAXS++;
334 334 insns.add(new InsnNode(Opcodes.DUP)); ctorMAXS++; invokeMAXS++;
335   - ctorMAXS += invokeEventInfoConstructor(insns, cancellable);
  335 + ctorMAXS += this.invokeEventInfoConstructor(insns, cancellable);
336 336 insns.add(new VarInsnNode(Opcodes.ASTORE, eventInfoVar));
337 337  
338 338 // Call the event handler method in the proxy
339 339 insns.add(new VarInsnNode(Opcodes.ALOAD, eventInfoVar));
340   - ByteCodeUtilities.loadArgs(argumentTypes, insns, this.methodIsStatic ? 0 : 1);
  340 + ByteCodeUtilities.loadArgs(arguments, insns, this.methodIsStatic ? 0 : 1);
341 341 if (doCaptureLocals)
342 342 {
343 343 ByteCodeUtilities.loadLocals(locals, insns, initialFrameSize);
... ... @@ -474,6 +474,14 @@ public class Event implements Comparable&lt;Event&gt;
474 474 }
475 475  
476 476 /**
  477 + * Get currently registered listeners for this event
  478 + */
  479 + public Set<MethodInfo> getListeners()
  480 + {
  481 + return Collections.<MethodInfo>unmodifiableSet(this.listeners);
  482 + }
  483 +
  484 + /**
477 485 * Get an event by name (case insensitive)
478 486 *
479 487 * @param eventName
... ... @@ -487,28 +495,6 @@ public class Event implements Comparable&lt;Event&gt;
487 495  
488 496 return null;
489 497 }
490   -
491   - /**
492   - * Get all of the listeners for an event by name
493   - *
494   - * @param eventName
495   - * @return
496   - */
497   - static Set<MethodInfo> getEventListeners(String eventName)
498   - {
499   - return Event.getEventListeners(Event.getEvent(eventName));
500   - }
501   -
502   - /**
503   - * Get all of an event's listeners
504   - *
505   - * @param event
506   - * @return
507   - */
508   - static Set<MethodInfo> getEventListeners(Event event)
509   - {
510   - return event == null ? null : Collections.unmodifiableSet(event.listeners);
511   - }
512 498  
513 499 /**
514 500 * Populates the event proxy class with delegating methods for all injected events
... ...
java/common/com/mumfrey/liteloader/transformers/event/EventTransformer.java
... ... @@ -10,7 +10,6 @@ import java.util.Set;
10 10 import java.util.TreeSet;
11 11  
12 12 import org.objectweb.asm.ClassWriter;
13   -import org.objectweb.asm.Opcodes;
14 13 import org.objectweb.asm.Type;
15 14 import org.objectweb.asm.tree.AbstractInsnNode;
16 15 import org.objectweb.asm.tree.ClassNode;
... ... @@ -283,7 +282,7 @@ public final class EventTransformer extends ClassTransformer
283 282 injection.setLocals(locals);
284 283 if (injectionPoint.logLocals())
285 284 {
286   - int startPos = ((method.access & Opcodes.ACC_STATIC) == 0 ? 1 : 0) + Type.getArgumentTypes(method.desc).length;
  285 + int startPos = ByteCodeUtilities.getFirstNonArgLocalIndex(method);
287 286  
288 287 LiteLoaderLogger.debug(ClassTransformer.HORIZONTAL_RULE);
289 288 LiteLoaderLogger.debug("Logging local variables for " + injectionPoint.getClass().getSimpleName());
... ...