Commit 4e3e54ae64c23c62d860514b105283e96c61d780

Authored by Mumfrey
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
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&lt;P, T&gt;
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&lt;P, T&gt;
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  
... ...
res/liteloader.properties
... ... @@ -2,5 +2,6 @@ search.mods=true
2 2 search.jar=true
3 3 search.classpath=true
4 4 log=stderr
  5 +controls.pages=true
5 6 brand=The Voxel Modpack
6 7  
... ...