Commit 4e3e54ae64c23c62d860514b105283e96c61d780
1 parent
95b3fc7d
LiteLoader 1.5.2
+ Added paginated "Controls" GUI based on the Macros one + Added new interfaces GameLoopListener and ChatRenderListener + Added sanity check for profiler hook + Added more descriptive exception for when mods screw up the profiler stack so that it's clearer that it's not LiteLoader's fault
Showing
8 changed files
with
542 additions
and
50 deletions
java/com/mumfrey/liteloader/ChatRenderListener.java
0 → 100644
1 | +package com.mumfrey.liteloader; | |
2 | + | |
3 | +import net.minecraft.src.GuiNewChat; | |
4 | + | |
5 | +/** | |
6 | + * Interface for mods which want to alter the chat display | |
7 | + * | |
8 | + * @author Adam Mummery-Smith | |
9 | + */ | |
10 | +public interface ChatRenderListener extends LiteMod | |
11 | +{ | |
12 | + public abstract void onPreRenderChat(int screenWidth, int screenHeight, GuiNewChat chat); | |
13 | + | |
14 | + public abstract void onPostRenderChat(int screenWidth, int screenHeight, GuiNewChat chat); | |
15 | +} | ... | ... |
java/com/mumfrey/liteloader/GameLoopListener.java
0 → 100644
1 | +package com.mumfrey.liteloader; | |
2 | + | |
3 | +import net.minecraft.client.Minecraft; | |
4 | + | |
5 | +/** | |
6 | + * Interface for mods which want a frame notification every single game loop | |
7 | + * | |
8 | + * @author Adam Mummery-Smith | |
9 | + */ | |
10 | +public interface GameLoopListener | |
11 | +{ | |
12 | + /** | |
13 | + * Called every frame, before the world is ticked | |
14 | + * | |
15 | + * @param minecraft | |
16 | + */ | |
17 | + public abstract void onRunGameLoop(Minecraft minecraft); | |
18 | +} | ... | ... |
java/com/mumfrey/liteloader/core/HookProfiler.java
... | ... | @@ -3,6 +3,7 @@ package com.mumfrey.liteloader.core; |
3 | 3 | import java.lang.reflect.Field; |
4 | 4 | import java.lang.reflect.Method; |
5 | 5 | import java.util.LinkedList; |
6 | +import java.util.NoSuchElementException; | |
6 | 7 | import java.util.logging.Logger; |
7 | 8 | |
8 | 9 | import net.minecraft.client.Minecraft; |
... | ... | @@ -65,7 +66,7 @@ public class HookProfiler extends Profiler |
65 | 66 | this.logger = logger; |
66 | 67 | |
67 | 68 | // Detect optifine (duh!) |
68 | - detectOptifine(); | |
69 | + this.detectOptifine(); | |
69 | 70 | } |
70 | 71 | |
71 | 72 | /** |
... | ... | @@ -77,18 +78,18 @@ public class HookProfiler extends Profiler |
77 | 78 | { |
78 | 79 | try |
79 | 80 | { |
80 | - ofProfiler = GameSettings.class.getDeclaredField("ofProfiler"); | |
81 | + this.ofProfiler = GameSettings.class.getDeclaredField("ofProfiler"); | |
81 | 82 | } |
82 | 83 | catch (SecurityException ex) {} |
83 | 84 | catch (NoSuchFieldException ex) |
84 | 85 | { |
85 | - logger.info("Optifine not detected"); | |
86 | + this.logger.info("Optifine not detected"); | |
86 | 87 | } |
87 | 88 | finally |
88 | 89 | { |
89 | - if (ofProfiler != null) | |
90 | + if (this.ofProfiler != null) | |
90 | 91 | { |
91 | - logger.info(String.format("Optifine version %s detected, enabling compatibility check", getOptifineVersion())); | |
92 | + this.logger.info(String.format("Optifine version %s detected, enabling compatibility check", this.getOptifineVersion())); | |
92 | 93 | } |
93 | 94 | } |
94 | 95 | } |
... | ... | @@ -125,44 +126,54 @@ public class HookProfiler extends Profiler |
125 | 126 | @Override |
126 | 127 | public void startSection(String sectionName) |
127 | 128 | { |
128 | - if (!initDone) | |
129 | + if (!this.initDone) | |
129 | 130 | { |
130 | - initDone = true; | |
131 | - loader.onInit(); | |
131 | + this.initDone = true; | |
132 | + this.loader.onInit(); | |
132 | 133 | } |
133 | 134 | |
134 | - if ("gameRenderer".equals(sectionName) && "root".equals(sectionStack.getLast())) | |
135 | + if ("gameRenderer".equals(sectionName) && "root".equals(this.sectionStack.getLast())) | |
135 | 136 | { |
136 | - loader.onRender(); | |
137 | + this.loader.onRender(); | |
137 | 138 | } |
138 | 139 | |
139 | - if ("frustrum".equals(sectionName) && "level".equals(sectionStack.getLast())) | |
140 | + if ("frustrum".equals(sectionName) && "level".equals(this.sectionStack.getLast())) | |
140 | 141 | { |
141 | - loader.onSetupCameraTransform(); | |
142 | + this.loader.onSetupCameraTransform(); | |
142 | 143 | } |
143 | 144 | |
144 | 145 | if ("litParticles".equals(sectionName)) |
145 | 146 | { |
146 | - loader.postRenderEntities(); | |
147 | + this.loader.postRenderEntities(); | |
147 | 148 | } |
148 | 149 | |
149 | - if ("animateTick".equals(sectionName)) tick = true; | |
150 | - sectionStack.add(sectionName); | |
150 | + if ("tick".equals(sectionName) && "root".equals(this.sectionStack.getLast())) | |
151 | + { | |
152 | + this.loader.onTimerUpdate(); | |
153 | + } | |
154 | + | |
155 | + if ("chat".equals(sectionName)) | |
156 | + { | |
157 | + this.loader.onBeforeChatRender(); | |
158 | + } | |
159 | + | |
160 | + if ("animateTick".equals(sectionName)) this.tick = true; | |
161 | + this.sectionStack.add(sectionName); | |
151 | 162 | super.startSection(sectionName); |
152 | 163 | |
153 | - if (ofProfiler != null) | |
164 | + if (this.ofProfiler != null) | |
154 | 165 | { |
155 | 166 | try |
156 | 167 | { |
157 | - ofProfiler.set(mc.gameSettings, true); | |
168 | + this.ofProfiler.set(this.mc.gameSettings, true); | |
158 | 169 | } |
159 | 170 | catch (IllegalArgumentException ex) |
160 | 171 | { |
161 | - ofProfiler = null; | |
172 | + this.ofProfiler = null; | |
162 | 173 | } |
163 | 174 | catch (IllegalAccessException ex) |
164 | 175 | { |
165 | - ofProfiler = null; | |
176 | + this.ofProfiler = null; | |
166 | 177 | } |
167 | 178 | } |
168 | 179 | } |
... | ... | @@ -175,25 +186,37 @@ public class HookProfiler extends Profiler |
175 | 186 | { |
176 | 187 | super.endSection(); |
177 | 188 | |
178 | - String endingSection = sectionStack.size() > 0 ? sectionStack.removeLast() : null; | |
179 | - String nextSection = sectionStack.size() > 0 ? sectionStack.getLast() : null; | |
180 | - | |
181 | - if ("gameRenderer".equals(endingSection) && "root".equals(sectionStack.getLast())) | |
189 | + try | |
182 | 190 | { |
183 | - super.startSection("litetick"); | |
184 | - | |
185 | - loader.onTick(this, tick); | |
186 | - tick = false; | |
191 | + String endingSection = this.sectionStack.size() > 0 ? this.sectionStack.removeLast() : null; | |
192 | + String nextSection = this.sectionStack.size() > 0 ? this.sectionStack.getLast() : null; | |
187 | 193 | |
188 | - super.endSection(); | |
189 | - } | |
190 | - else if (("mouse".equals(endingSection) && "gameRenderer".equals(nextSection) && (mc.skipRenderWorld || mc.theWorld == null)) || ("gui".equals(endingSection) && "gameRenderer".equals(nextSection) && mc.theWorld != null)) | |
191 | - { | |
192 | - loader.onBeforeGuiRender(); | |
194 | + if ("gameRenderer".equals(endingSection) && "root".equals(this.sectionStack.getLast())) | |
195 | + { | |
196 | + super.startSection("litetick"); | |
197 | + | |
198 | + this.loader.onTick(this, this.tick); | |
199 | + this.tick = false; | |
200 | + | |
201 | + super.endSection(); | |
202 | + } | |
203 | + else if (("mouse".equals(endingSection) && "gameRenderer".equals(nextSection) && (this.mc.skipRenderWorld || this.mc.theWorld == null)) || ("gui".equals(endingSection) && "gameRenderer".equals(nextSection) && this.mc.theWorld != null)) | |
204 | + { | |
205 | + this.loader.onBeforeGuiRender(); | |
206 | + } | |
207 | + else if ("hand".equals(endingSection) && "level".equals(this.sectionStack.getLast())) | |
208 | + { | |
209 | + this.loader.postRender(); | |
210 | + } | |
211 | + else if ("chat".equals(endingSection)) | |
212 | + { | |
213 | + this.loader.onAfterChatRender(); | |
214 | + } | |
193 | 215 | } |
194 | - else if ("hand".equals(endingSection) && "level".equals(sectionStack.getLast())) | |
216 | + catch (NoSuchElementException ex) | |
195 | 217 | { |
196 | - loader.postRender(); | |
218 | + this.logger.severe("Corrupted Profiler stack detected, this indicates an error with one of your mods."); | |
219 | + throw new ProfilerStackCorruptionException("Corrupted Profiler stack detected"); | |
197 | 220 | } |
198 | 221 | } |
199 | 222 | } | ... | ... |
java/com/mumfrey/liteloader/core/LiteLoader.java
... | ... | @@ -34,14 +34,23 @@ import java.util.zip.ZipInputStream; |
34 | 34 | import javax.activity.InvalidActivityException; |
35 | 35 | |
36 | 36 | import net.minecraft.client.Minecraft; |
37 | +import net.minecraft.src.GuiControls; | |
38 | +import net.minecraft.src.GuiNewChat; | |
39 | +import net.minecraft.src.GuiScreen; | |
40 | +import net.minecraft.src.ILogAgent; | |
41 | +import net.minecraft.src.IPlayerUsage; | |
37 | 42 | import net.minecraft.src.NetHandler; |
38 | 43 | import net.minecraft.src.Packet1Login; |
39 | 44 | import net.minecraft.src.Packet3Chat; |
45 | +import net.minecraft.src.PlayerUsageSnooper; | |
40 | 46 | import net.minecraft.src.Profiler; |
47 | +import net.minecraft.src.ScaledResolution; | |
41 | 48 | import net.minecraft.src.Timer; |
42 | 49 | |
43 | 50 | import com.mumfrey.liteloader.ChatFilter; |
44 | 51 | import com.mumfrey.liteloader.ChatListener; |
52 | +import com.mumfrey.liteloader.ChatRenderListener; | |
53 | +import com.mumfrey.liteloader.GameLoopListener; | |
45 | 54 | import com.mumfrey.liteloader.InitCompleteListener; |
46 | 55 | import com.mumfrey.liteloader.LiteMod; |
47 | 56 | import com.mumfrey.liteloader.LoginListener; |
... | ... | @@ -50,34 +59,35 @@ import com.mumfrey.liteloader.PostRenderListener; |
50 | 59 | import com.mumfrey.liteloader.PreLoginListener; |
51 | 60 | import com.mumfrey.liteloader.RenderListener; |
52 | 61 | import com.mumfrey.liteloader.Tickable; |
62 | +import com.mumfrey.liteloader.gui.GuiControlsPaginated; | |
53 | 63 | import com.mumfrey.liteloader.util.ModUtilities; |
54 | 64 | import com.mumfrey.liteloader.util.PrivateFields; |
55 | 65 | |
56 | 66 | /** |
57 | - * LiteLoader is a simple loader which provides tick events to loaded mods | |
67 | + * LiteLoader is a simple loader which loads and provides useful callbacks to lightweight mods | |
58 | 68 | * |
59 | 69 | * @author Adam Mummery-Smith |
60 | - * @version 1.5.1 | |
70 | + * @version 1.5.2 | |
61 | 71 | */ |
62 | 72 | @SuppressWarnings("rawtypes") |
63 | -public final class LiteLoader implements FilenameFilter | |
73 | +public final class LiteLoader implements FilenameFilter, IPlayerUsage | |
64 | 74 | { |
65 | 75 | /** |
66 | 76 | * Liteloader version |
67 | 77 | */ |
68 | - private static final String LOADER_VERSION = "1.5.1"; | |
78 | + private static final String LOADER_VERSION = "1.5.2"; | |
69 | 79 | |
70 | 80 | /** |
71 | 81 | * Loader revision, can be used by mods to determine whether the loader is sufficiently up-to-date |
72 | 82 | */ |
73 | - private static final int LOADER_REVISION = 8; | |
83 | + private static final int LOADER_REVISION = 9; | |
74 | 84 | |
75 | 85 | /** |
76 | 86 | * Minecraft versions that we will load mods for, this will be compared |
77 | 87 | * against the version.txt value in mod files to prevent outdated mods being |
78 | 88 | * loaded!!! |
79 | 89 | */ |
80 | - private static final String[] SUPPORTED_VERSIONS = { "1.5.1", "1.5.r2" }; | |
90 | + private static final String[] SUPPORTED_VERSIONS = { "1.5.2", "1.5.r1" }; | |
81 | 91 | |
82 | 92 | /** |
83 | 93 | * Maximum recursion depth for mod discovery |
... | ... | @@ -130,6 +140,11 @@ public final class LiteLoader implements FilenameFilter |
130 | 140 | private String branding = null; |
131 | 141 | |
132 | 142 | /** |
143 | + * Setting value, if true we will swap out the MC "Controls" GUI for our custom, paginated one | |
144 | + */ | |
145 | + private boolean paginateControls = true; | |
146 | + | |
147 | + /** | |
133 | 148 | * Reference to the minecraft timer |
134 | 149 | */ |
135 | 150 | private Timer minecraftTimer; |
... | ... | @@ -151,6 +166,11 @@ public final class LiteLoader implements FilenameFilter |
151 | 166 | private LinkedList<Tickable> tickListeners = new LinkedList<Tickable>(); |
152 | 167 | |
153 | 168 | /** |
169 | + * List of mods which implement the GameLoopListener interface and will receive loop events | |
170 | + */ | |
171 | + private LinkedList<GameLoopListener> loopListeners = new LinkedList<GameLoopListener>(); | |
172 | + | |
173 | + /** | |
154 | 174 | * |
155 | 175 | */ |
156 | 176 | private LinkedList<InitCompleteListener> initListeners = new LinkedList<InitCompleteListener>(); |
... | ... | @@ -167,6 +187,11 @@ public final class LiteLoader implements FilenameFilter |
167 | 187 | private LinkedList<PostRenderListener> postRenderListeners = new LinkedList<PostRenderListener>(); |
168 | 188 | |
169 | 189 | /** |
190 | + * List of mods which implement ChatRenderListener and want to know when chat is rendered | |
191 | + */ | |
192 | + private LinkedList<ChatRenderListener> chatRenderListeners = new LinkedList<ChatRenderListener>(); | |
193 | + | |
194 | + /** | |
170 | 195 | * List of mods which implement ChatListener interface and will receive chat |
171 | 196 | * events |
172 | 197 | */ |
... | ... | @@ -212,6 +237,16 @@ public final class LiteLoader implements FilenameFilter |
212 | 237 | * Flags which keep track of whether hooks have been applied |
213 | 238 | */ |
214 | 239 | private boolean chatHooked, loginHooked, pluginChannelHooked, tickHooked; |
240 | + | |
241 | + /** | |
242 | + * Profiler hook objects | |
243 | + */ | |
244 | + private HookProfiler profilerHook = new HookProfiler(this, logger); | |
245 | + | |
246 | + /** | |
247 | + * ScaledResolution used by the pre-chat and post-chat render callbacks | |
248 | + */ | |
249 | + private ScaledResolution currentResolution; | |
215 | 250 | |
216 | 251 | /** |
217 | 252 | * Get the singleton instance of LiteLoader, initialises the loader if necessary |
... | ... | @@ -399,6 +434,9 @@ public final class LiteLoader implements FilenameFilter |
399 | 434 | // Prepare the log writer |
400 | 435 | this.prepareLogger(); |
401 | 436 | |
437 | + this.paginateControls = this.localProperties.getProperty("controls.pages", "true").equalsIgnoreCase("true"); | |
438 | + this.localProperties.setProperty("controls.pages", String.valueOf(this.paginateControls)); | |
439 | + | |
402 | 440 | this.branding = this.internalProperties.getProperty("brand", null); |
403 | 441 | if (this.branding != null && this.branding.length() < 1) this.branding = null; |
404 | 442 | |
... | ... | @@ -652,7 +690,7 @@ public final class LiteLoader implements FilenameFilter |
652 | 690 | versionReader.close(); |
653 | 691 | |
654 | 692 | // Only add the mod if the version matches and we were able to successfully add it to the class path |
655 | - if (supportedVerions.contains(strVersion) && addURLToClassPath(modFile.toURI().toURL())) | |
693 | + if (supportedVerions.contains(strVersion) && this.addURLToClassPath(modFile.toURI().toURL())) | |
656 | 694 | { |
657 | 695 | modFiles.add(modFile); |
658 | 696 | } |
... | ... | @@ -834,7 +872,7 @@ public final class LiteLoader implements FilenameFilter |
834 | 872 | this.loadedModsList = ""; |
835 | 873 | int loadedModsCount = 0; |
836 | 874 | |
837 | - for (Iterator<LiteMod> iter = mods.iterator(); iter.hasNext();) | |
875 | + for (Iterator<LiteMod> iter = this.mods.iterator(); iter.hasNext();) | |
838 | 876 | { |
839 | 877 | LiteMod mod = iter.next(); |
840 | 878 | |
... | ... | @@ -848,6 +886,11 @@ public final class LiteLoader implements FilenameFilter |
848 | 886 | { |
849 | 887 | this.addTickListener((Tickable)mod); |
850 | 888 | } |
889 | + | |
890 | + if (mod instanceof GameLoopListener) | |
891 | + { | |
892 | + this.addLoopListener((GameLoopListener)mod); | |
893 | + } | |
851 | 894 | |
852 | 895 | if (mod instanceof InitCompleteListener) |
853 | 896 | { |
... | ... | @@ -881,6 +924,11 @@ public final class LiteLoader implements FilenameFilter |
881 | 924 | } |
882 | 925 | } |
883 | 926 | |
927 | + if (mod instanceof ChatRenderListener) | |
928 | + { | |
929 | + this.addChatRenderListener((ChatRenderListener)mod); | |
930 | + } | |
931 | + | |
884 | 932 | if (mod instanceof PreLoginListener) |
885 | 933 | { |
886 | 934 | this.addPreLoginListener((PreLoginListener)mod); |
... | ... | @@ -944,8 +992,12 @@ public final class LiteLoader implements FilenameFilter |
944 | 992 | if (!this.tickHooked) |
945 | 993 | { |
946 | 994 | this.tickHooked = true; |
947 | - PrivateFields.minecraftProfiler.setFinal(this.minecraft, new HookProfiler(this, logger)); | |
995 | + PrivateFields.minecraftProfiler.setFinal(this.minecraft, this.profilerHook); | |
948 | 996 | } |
997 | + | |
998 | + // Sanity hook | |
999 | + PlayerUsageSnooper snooper = this.minecraft.getPlayerUsageSnooper(); | |
1000 | + PrivateFields.playerStatsCollector.setFinal(snooper, this); | |
949 | 1001 | } |
950 | 1002 | catch (Exception ex) |
951 | 1003 | { |
... | ... | @@ -967,6 +1019,18 @@ public final class LiteLoader implements FilenameFilter |
967 | 1019 | } |
968 | 1020 | |
969 | 1021 | /** |
1022 | + * @param loopListener | |
1023 | + */ | |
1024 | + public void addLoopListener(GameLoopListener loopListener) | |
1025 | + { | |
1026 | + if (!this.loopListeners.contains(loopListener)) | |
1027 | + { | |
1028 | + this.loopListeners.add(loopListener); | |
1029 | + if (this.loaderStartupComplete) this.initHooks(); | |
1030 | + } | |
1031 | + } | |
1032 | + | |
1033 | + /** | |
970 | 1034 | * @param initCompleteListener |
971 | 1035 | */ |
972 | 1036 | public void addInitListener(InitCompleteListener initCompleteListener) |
... | ... | @@ -1025,6 +1089,18 @@ public final class LiteLoader implements FilenameFilter |
1025 | 1089 | if (this.loaderStartupComplete) this.initHooks(); |
1026 | 1090 | } |
1027 | 1091 | } |
1092 | + | |
1093 | + /** | |
1094 | + * @param chatRenderListener | |
1095 | + */ | |
1096 | + public void addChatRenderListener(ChatRenderListener chatRenderListener) | |
1097 | + { | |
1098 | + if (!this.chatRenderListeners.contains(chatRenderListener)) | |
1099 | + { | |
1100 | + this.chatRenderListeners.add(chatRenderListener); | |
1101 | + if (this.loaderStartupComplete) this.initHooks(); | |
1102 | + } | |
1103 | + } | |
1028 | 1104 | |
1029 | 1105 | /** |
1030 | 1106 | * @param loginListener |
... | ... | @@ -1261,6 +1337,17 @@ public final class LiteLoader implements FilenameFilter |
1261 | 1337 | */ |
1262 | 1338 | public void onRender() |
1263 | 1339 | { |
1340 | + if (this.paginateControls && this.minecraft.currentScreen != null && this.minecraft.currentScreen.getClass().equals(GuiControls.class)) | |
1341 | + { | |
1342 | + try | |
1343 | + { | |
1344 | + // Try to get the parent screen entry from the existing screen | |
1345 | + GuiScreen parentScreen = PrivateFields.guiControlsParentScreen.get((GuiControls)this.minecraft.currentScreen); | |
1346 | + this.minecraft.displayGuiScreen(new GuiControlsPaginated(parentScreen, this.minecraft.gameSettings)); | |
1347 | + } | |
1348 | + catch (Exception ex) { } | |
1349 | + } | |
1350 | + | |
1264 | 1351 | for (RenderListener renderListener : this.renderListeners) |
1265 | 1352 | renderListener.onRender(); |
1266 | 1353 | } |
... | ... | @@ -1304,6 +1391,44 @@ public final class LiteLoader implements FilenameFilter |
1304 | 1391 | for (RenderListener renderListener : this.renderListeners) |
1305 | 1392 | renderListener.onSetupCameraTransform(); |
1306 | 1393 | } |
1394 | + | |
1395 | + /** | |
1396 | + * Called immediately before the chat log is rendered | |
1397 | + */ | |
1398 | + public void onBeforeChatRender() | |
1399 | + { | |
1400 | + this.currentResolution = new ScaledResolution(this.minecraft.gameSettings, this.minecraft.displayWidth, this.minecraft.displayHeight); | |
1401 | + int screenWidth = this.currentResolution.getScaledWidth(); | |
1402 | + int screenHeight = this.currentResolution.getScaledHeight(); | |
1403 | + | |
1404 | + GuiNewChat chat = this.minecraft.ingameGUI.getChatGUI(); | |
1405 | + | |
1406 | + for (ChatRenderListener chatRenderListener : this.chatRenderListeners) | |
1407 | + chatRenderListener.onPreRenderChat(screenWidth, screenHeight, chat); | |
1408 | + } | |
1409 | + | |
1410 | + /** | |
1411 | + * Called immediately after the chat log is rendered | |
1412 | + */ | |
1413 | + public void onAfterChatRender() | |
1414 | + { | |
1415 | + int screenWidth = this.currentResolution.getScaledWidth(); | |
1416 | + int screenHeight = this.currentResolution.getScaledHeight(); | |
1417 | + | |
1418 | + GuiNewChat chat = this.minecraft.ingameGUI.getChatGUI(); | |
1419 | + | |
1420 | + for (ChatRenderListener chatRenderListener : this.chatRenderListeners) | |
1421 | + chatRenderListener.onPostRenderChat(screenWidth, screenHeight, chat); | |
1422 | + } | |
1423 | + | |
1424 | + /** | |
1425 | + * Callback from the tick hook, called every frame when the timer is updated | |
1426 | + */ | |
1427 | + public void onTimerUpdate() | |
1428 | + { | |
1429 | + for (GameLoopListener loopListener : this.loopListeners) | |
1430 | + loopListener.onRunGameLoop(this.minecraft); | |
1431 | + } | |
1307 | 1432 | |
1308 | 1433 | /** |
1309 | 1434 | * Callback from the tick hook, ticks all tickable mods |
... | ... | @@ -1323,7 +1448,7 @@ public final class LiteLoader implements FilenameFilter |
1323 | 1448 | // Hooray, we got the timer reference |
1324 | 1449 | if (this.minecraftTimer != null) |
1325 | 1450 | { |
1326 | - partialTicks = this.minecraftTimer.elapsedPartialTicks; | |
1451 | + partialTicks = this.minecraftTimer.renderPartialTicks; | |
1327 | 1452 | tick = this.minecraftTimer.elapsedTicks > 0; |
1328 | 1453 | } |
1329 | 1454 | |
... | ... | @@ -1389,7 +1514,7 @@ public final class LiteLoader implements FilenameFilter |
1389 | 1514 | for (LoginListener loginListener : this.loginListeners) |
1390 | 1515 | loginListener.onLogin(netHandler, loginPacket); |
1391 | 1516 | |
1392 | - setupPluginChannels(); | |
1517 | + this.setupPluginChannels(); | |
1393 | 1518 | } |
1394 | 1519 | |
1395 | 1520 | /** |
... | ... | @@ -1468,7 +1593,55 @@ public final class LiteLoader implements FilenameFilter |
1468 | 1593 | |
1469 | 1594 | byte[] registrationData = channelList.toString().getBytes(Charset.forName("UTF8")); |
1470 | 1595 | |
1471 | - sendPluginChannelMessage("REGISTER", registrationData); | |
1596 | + this.sendPluginChannelMessage("REGISTER", registrationData); | |
1597 | + } | |
1598 | + } | |
1599 | + | |
1600 | + /* (non-Javadoc) | |
1601 | + * @see net.minecraft.src.IPlayerUsage#addServerStatsToSnooper(net.minecraft.src.PlayerUsageSnooper) | |
1602 | + */ | |
1603 | + @Override | |
1604 | + public void addServerStatsToSnooper(PlayerUsageSnooper var1) | |
1605 | + { | |
1606 | + this.minecraft.addServerStatsToSnooper(var1); | |
1607 | + } | |
1608 | + | |
1609 | + /* (non-Javadoc) | |
1610 | + * @see net.minecraft.src.IPlayerUsage#addServerTypeToSnooper(net.minecraft.src.PlayerUsageSnooper) | |
1611 | + */ | |
1612 | + @Override | |
1613 | + public void addServerTypeToSnooper(PlayerUsageSnooper var1) | |
1614 | + { | |
1615 | + this.sanityCheck(); | |
1616 | + this.minecraft.addServerTypeToSnooper(var1); | |
1617 | + } | |
1618 | + | |
1619 | + /* (non-Javadoc) | |
1620 | + * @see net.minecraft.src.IPlayerUsage#isSnooperEnabled() | |
1621 | + */ | |
1622 | + @Override | |
1623 | + public boolean isSnooperEnabled() | |
1624 | + { | |
1625 | + return this.minecraft.isSnooperEnabled(); | |
1626 | + } | |
1627 | + | |
1628 | + /* (non-Javadoc) | |
1629 | + * @see net.minecraft.src.IPlayerUsage#getLogAgent() | |
1630 | + */ | |
1631 | + @Override | |
1632 | + public ILogAgent getLogAgent() | |
1633 | + { | |
1634 | + return this.minecraft.getLogAgent(); | |
1635 | + } | |
1636 | + | |
1637 | + /** | |
1638 | + * Check that the profiler hook hasn't been overridden by something else | |
1639 | + */ | |
1640 | + private void sanityCheck() | |
1641 | + { | |
1642 | + if (this.tickHooked && this.minecraft.mcProfiler != this.profilerHook) | |
1643 | + { | |
1644 | + PrivateFields.minecraftProfiler.setFinal(this.minecraft, this.profilerHook); | |
1472 | 1645 | } |
1473 | 1646 | } |
1474 | 1647 | } |
1475 | 1648 | \ No newline at end of file | ... | ... |
java/com/mumfrey/liteloader/core/ProfilerStackCorruptionException.java
0 → 100644
1 | +package com.mumfrey.liteloader.core; | |
2 | + | |
3 | +/** | |
4 | + * Exception to throw when a mod corrupts the profiler stack, this avoids throwing a | |
5 | + * (somewhat cryptic) NoSuchElementException inside HookProfiler | |
6 | + * | |
7 | + * @author Adam Mummery-Smith | |
8 | + */ | |
9 | +public class ProfilerStackCorruptionException extends RuntimeException | |
10 | +{ | |
11 | + /** | |
12 | + * | |
13 | + */ | |
14 | + private static final long serialVersionUID = -7745831270297368169L; | |
15 | + | |
16 | + public ProfilerStackCorruptionException(String message) | |
17 | + { | |
18 | + super(message); | |
19 | + } | |
20 | +} | ... | ... |
java/com/mumfrey/liteloader/gui/GuiControlsPaginated.java
0 → 100644
1 | +package com.mumfrey.liteloader.gui; | |
2 | + | |
3 | +import java.util.List; | |
4 | + | |
5 | +import net.minecraft.src.GameSettings; | |
6 | +import net.minecraft.src.GuiButton; | |
7 | +import net.minecraft.src.GuiScreen; | |
8 | +import net.minecraft.src.GuiSmallButton; | |
9 | +import net.minecraft.src.KeyBinding; | |
10 | +import net.minecraft.src.StringTranslate; | |
11 | + | |
12 | +/** | |
13 | + * Extended "Controls" screen with pages | |
14 | + * | |
15 | + * @author Adam Mummery-Smith | |
16 | + */ | |
17 | +public class GuiControlsPaginated extends GuiScreen | |
18 | +{ | |
19 | + /** | |
20 | + * Pagination variables | |
21 | + */ | |
22 | + protected int controlsPerPage, startIndex, endIndex; | |
23 | + | |
24 | + /** | |
25 | + * Parent screen which will be displayed when this screen is closed | |
26 | + */ | |
27 | + protected GuiScreen parentScreen; | |
28 | + | |
29 | + /** | |
30 | + * Game settings | |
31 | + */ | |
32 | + protected GameSettings gameSettings; | |
33 | + | |
34 | + /** | |
35 | + * Additional buttons | |
36 | + */ | |
37 | + protected GuiButton btnNext, btnPrevious; | |
38 | + | |
39 | + /** | |
40 | + * Title to display | |
41 | + */ | |
42 | + protected String screenTitle = "Controls"; | |
43 | + | |
44 | + /** | |
45 | + * ID of the button currently being edited | |
46 | + */ | |
47 | + protected int activeButtonId = -1; | |
48 | + | |
49 | + public GuiControlsPaginated(GuiScreen parentScreen, GameSettings gameSettings) | |
50 | + { | |
51 | + this.parentScreen = parentScreen; | |
52 | + this.gameSettings = gameSettings; | |
53 | + | |
54 | + // Pagination defaults | |
55 | + this.controlsPerPage = 14; | |
56 | + this.endIndex = this.gameSettings.keyBindings.length - (this.gameSettings.keyBindings.length % this.controlsPerPage == 0 ? this.controlsPerPage : this.gameSettings.keyBindings.length % this.controlsPerPage); | |
57 | + } | |
58 | + | |
59 | + @SuppressWarnings("unchecked") | |
60 | + protected List<GuiButton> getLegacyControlList() | |
61 | + { | |
62 | + return this.buttonList; | |
63 | + } | |
64 | + | |
65 | + protected final int getHeight() | |
66 | + { | |
67 | + return this.height; | |
68 | + } | |
69 | + | |
70 | + protected final int getWidth() | |
71 | + { | |
72 | + return this.width; | |
73 | + } | |
74 | + | |
75 | + public GuiScreen getParentScreen() | |
76 | + { | |
77 | + return this.parentScreen; | |
78 | + } | |
79 | + | |
80 | + /** | |
81 | + * Initialise this GUI, called when the GUI is created | |
82 | + */ | |
83 | + @Override | |
84 | + public void initGui() | |
85 | + { | |
86 | + StringTranslate stringtranslate = StringTranslate.getInstance(); | |
87 | + this.getLegacyControlList().clear(); | |
88 | + | |
89 | + int oldControlsPerPage = this.controlsPerPage; | |
90 | + this.controlsPerPage = ((this.getHeight() - 70) / 24) * 2; | |
91 | + this.endIndex = this.gameSettings.keyBindings.length - (this.gameSettings.keyBindings.length % this.controlsPerPage == 0 ? this.controlsPerPage : this.gameSettings.keyBindings.length % this.controlsPerPage); | |
92 | + if (oldControlsPerPage != this.controlsPerPage) this.startIndex = 0; | |
93 | + | |
94 | + for (int controlId = 0; controlId < this.gameSettings.keyBindings.length; controlId++) | |
95 | + { | |
96 | + boolean buttonVisible = controlId >= this.startIndex && controlId < this.startIndex + this.controlsPerPage; | |
97 | + int left = buttonVisible ? this.getWidth() / 2 - 155 : this.getWidth() + 10000; | |
98 | + int top = this.getHeight() / 6 + 24 * ((controlId - this.startIndex) >> 1); | |
99 | + this.getLegacyControlList().add(new GuiSmallButton(controlId, left + ((controlId - this.startIndex) % 2) * 160, top, 70, 20, this.gameSettings.getOptionDisplayString(controlId))); | |
100 | + } | |
101 | + | |
102 | + int buttonY = this.getHeight() / 6 + (this.controlsPerPage >> 1) * 24; | |
103 | + | |
104 | + // Only bother paginating if there are too many controls to display | |
105 | + if (this.gameSettings.keyBindings.length > this.controlsPerPage) | |
106 | + { | |
107 | + this.getLegacyControlList().add(this.btnNext = new GuiButton(201, this.getWidth() / 2 - 51, buttonY, 50, 20, ">>")); | |
108 | + this.getLegacyControlList().add(this.btnPrevious = new GuiButton(202, this.getWidth() / 2 - 103, buttonY, 50, 20, "<<")); | |
109 | + this.getLegacyControlList().add(new GuiButton(200, this.getWidth() / 2 + 1, buttonY, 100, 20, stringtranslate.translateKey("gui.done"))); | |
110 | + | |
111 | + this.btnNext.enabled = this.startIndex < this.endIndex; | |
112 | + this.btnPrevious.enabled = this.startIndex > 0; | |
113 | + } | |
114 | + else | |
115 | + { | |
116 | + this.getLegacyControlList().add(new GuiButton(200, this.getWidth() / 2 - 100, buttonY, stringtranslate.translateKey("gui.done"))); | |
117 | + } | |
118 | + | |
119 | + this.screenTitle = stringtranslate.translateKey("controls.title"); | |
120 | + } | |
121 | + | |
122 | + /** | |
123 | + * @param controlId | |
124 | + * @return | |
125 | + */ | |
126 | + protected String getKeybindDescription(int controlId) | |
127 | + { | |
128 | + return this.gameSettings.getKeyBindingDescription(controlId); | |
129 | + } | |
130 | + | |
131 | + /** | |
132 | + * A button was clicked, deal with it | |
133 | + * | |
134 | + * @param guibutton Button which was clicked | |
135 | + */ | |
136 | + @Override | |
137 | + protected void actionPerformed(GuiButton guibutton) | |
138 | + { | |
139 | + // Update the button labels with the appropriate key names | |
140 | + for(int i = 0; i < this.gameSettings.keyBindings.length; i++) | |
141 | + { | |
142 | + this.getLegacyControlList().get(i).displayString = this.gameSettings.getOptionDisplayString(i); | |
143 | + } | |
144 | + | |
145 | + if (guibutton.id == 200) // Done button | |
146 | + { | |
147 | + this.mc.displayGuiScreen(this.parentScreen); | |
148 | + } | |
149 | + else if (guibutton.id == 201) // Next button | |
150 | + { | |
151 | + this.startIndex += this.controlsPerPage; | |
152 | + this.startIndex = Math.min(this.endIndex, this.startIndex); | |
153 | + this.initGui(); | |
154 | + } | |
155 | + else if (guibutton.id == 202) // Previous button | |
156 | + { | |
157 | + this.startIndex -= this.controlsPerPage; | |
158 | + this.startIndex = Math.max(0, this.startIndex); | |
159 | + this.initGui(); | |
160 | + } | |
161 | + else | |
162 | + { | |
163 | + this.activeButtonId = guibutton.id; | |
164 | + guibutton.displayString = String.format("> %s <", this.gameSettings.getOptionDisplayString(guibutton.id)); | |
165 | + } | |
166 | + } | |
167 | + | |
168 | + @Override | |
169 | + protected void mouseClicked(int mouseX, int mouseY, int mouseButton) | |
170 | + { | |
171 | + if (this.activeButtonId >= 0) | |
172 | + { | |
173 | + this.gameSettings.setKeyBinding(this.activeButtonId, -100 + mouseButton); | |
174 | + this.getLegacyControlList().get(this.activeButtonId).displayString = this.gameSettings.getOptionDisplayString(this.activeButtonId); | |
175 | + this.activeButtonId = -1; | |
176 | + KeyBinding.resetKeyBindingArrayAndHash(); | |
177 | + } | |
178 | + else | |
179 | + { | |
180 | + super.mouseClicked(mouseX, mouseY, mouseButton); | |
181 | + } | |
182 | + } | |
183 | + | |
184 | + @Override | |
185 | + protected void keyTyped(char keyChar, int keyCode) | |
186 | + { | |
187 | + if (this.activeButtonId >= 0) | |
188 | + { | |
189 | + this.gameSettings.setKeyBinding(this.activeButtonId, keyCode); | |
190 | + this.getLegacyControlList().get(this.activeButtonId).displayString = this.gameSettings.getOptionDisplayString(this.activeButtonId); | |
191 | + this.activeButtonId = -1; | |
192 | + KeyBinding.resetKeyBindingArrayAndHash(); | |
193 | + } | |
194 | + else | |
195 | + { | |
196 | + super.keyTyped(keyChar, keyCode); | |
197 | + } | |
198 | + } | |
199 | + | |
200 | + @Override | |
201 | + public void drawScreen(int mouseX, int mouseY, float partialTick) | |
202 | + { | |
203 | + this.drawDefaultBackground(); | |
204 | + this.drawCenteredString(this.fontRenderer, this.screenTitle, this.width / 2, 20, 0xffffff); | |
205 | + | |
206 | + // Draw key labels | |
207 | + for (int controlId = 0; controlId < this.gameSettings.keyBindings.length; controlId++) | |
208 | + { | |
209 | + boolean conflict = false; | |
210 | + | |
211 | + for (int id = 0; id < this.gameSettings.keyBindings.length; id++) | |
212 | + { | |
213 | + if (id != controlId && this.gameSettings.keyBindings[controlId].keyCode == this.gameSettings.keyBindings[id].keyCode) | |
214 | + { | |
215 | + conflict = true; | |
216 | + break; | |
217 | + } | |
218 | + } | |
219 | + | |
220 | + if (this.activeButtonId == controlId) | |
221 | + { | |
222 | + this.getLegacyControlList().get(controlId).displayString = "\247f> \247e??? \247f<"; | |
223 | + } | |
224 | + else if (conflict) | |
225 | + { | |
226 | + this.getLegacyControlList().get(controlId).displayString = "\247c" + this.gameSettings.getOptionDisplayString(controlId); | |
227 | + } | |
228 | + else | |
229 | + { | |
230 | + this.getLegacyControlList().get(controlId).displayString = this.gameSettings.getOptionDisplayString(controlId); | |
231 | + } | |
232 | + | |
233 | + int left = (controlId >= this.startIndex && controlId < this.startIndex + this.controlsPerPage) ? this.getWidth() / 2 - 155 : this.getWidth() + 10000; | |
234 | + this.drawString(this.fontRenderer, this.getKeybindDescription(controlId), left + ((controlId - this.startIndex) % 2) * 160 + 70 + 6, this.getHeight() / 6 + 24 * ((controlId - this.startIndex) >> 1) + 7, 0xFFFFFF); | |
235 | + } | |
236 | + | |
237 | + super.drawScreen(mouseX, mouseY, partialTick); | |
238 | + } | |
239 | +} | |
0 | 240 | \ No newline at end of file | ... | ... |
java/com/mumfrey/liteloader/util/PrivateFields.java
... | ... | @@ -15,7 +15,7 @@ import net.minecraft.src.*; |
15 | 15 | * @param <P> Parent class type, the type of the class that owns the field |
16 | 16 | * @param <T> Field type, the type of the field value |
17 | 17 | * |
18 | - * TODO Obfuscation - updated 1.5.1 | |
18 | + * TODO Obfuscation - updated 1.5.2 | |
19 | 19 | */ |
20 | 20 | @SuppressWarnings("rawtypes") |
21 | 21 | public class PrivateFields<P, T> |
... | ... | @@ -132,6 +132,7 @@ public class PrivateFields<P, T> |
132 | 132 | */ |
133 | 133 | public static final class StaticFields<P, T> extends PrivateFields<P, T> |
134 | 134 | { |
135 | + @SuppressWarnings("synthetic-access") | |
135 | 136 | public StaticFields(Class<P> owner, String mcpName, String name, String fmlName) { super(owner, mcpName, name, fmlName); } |
136 | 137 | public T get() { return get(null); } |
137 | 138 | public void set(T value) { set(null, value); } |
... | ... | @@ -140,8 +141,10 @@ public class PrivateFields<P, T> |
140 | 141 | public static final StaticFields<TileEntity, Map> tileEntityNameToClassMap = new StaticFields<TileEntity, Map> (TileEntity.class, "nameToClassMap", "a", "field_70326_a"); // TileEntity/nameToClassMap |
141 | 142 | } |
142 | 143 | |
143 | - public static final PrivateFields<Minecraft, Timer> minecraftTimer = new PrivateFields<Minecraft, Timer> (Minecraft.class, "timer", "V", "field_71428_T"); // Minecraft/timer | |
144 | - public static final PrivateFields<Minecraft, Profiler> minecraftProfiler = new PrivateFields<Minecraft, Profiler> (Minecraft.class, "mcProfiler", "J", "field_71424_I"); // Minecraft/mcProfiler | |
145 | - public static final PrivateFields<RenderManager, Map> entityRenderMap = new PrivateFields<RenderManager, Map> (RenderManager.class, "entityRenderMap", "q", "field_78729_o"); // RenderManager/entityRenderMap | |
144 | + public static final PrivateFields<Minecraft, Timer> minecraftTimer = new PrivateFields<Minecraft, Timer> (Minecraft.class, "timer", "V", "field_71428_T"); // Minecraft/timer | |
145 | + public static final PrivateFields<Minecraft, Profiler> minecraftProfiler = new PrivateFields<Minecraft, Profiler> (Minecraft.class, "mcProfiler", "J", "field_71424_I"); // Minecraft/mcProfiler | |
146 | + public static final PrivateFields<RenderManager, Map> entityRenderMap = new PrivateFields<RenderManager, Map> (RenderManager.class, "entityRenderMap", "q", "field_78729_o"); // RenderManager/entityRenderMap | |
147 | + public static final PrivateFields<GuiControls, GuiScreen> guiControlsParentScreen = new PrivateFields<GuiControls, GuiScreen> (GuiControls.class, "parentScreen", "b", "field_73909_b"); // GuiControls/parentScreen | |
148 | + public static final PrivateFields<PlayerUsageSnooper, IPlayerUsage> playerStatsCollector = new PrivateFields<PlayerUsageSnooper, IPlayerUsage>(PlayerUsageSnooper.class, "playerStatsCollector", "d", "field_76478_d"); // PlayerUsageSnooper/playerStatsCollector | |
146 | 149 | } |
147 | 150 | ... | ... |