Commit a1377b8d403baf8188f23daf54ea5ff2d5146f25

Authored by Mumfrey
1 parent 70fa603a

LiteLoader 1.6.2 - replaced version.txt functionality with litemod.json, added v…

…ersion ordering and filtering for mods
.classpath
@@ -6,5 +6,6 @@ @@ -6,5 +6,6 @@
6 <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> 6 <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
7 <classpathentry kind="lib" path="/Client/jars/libraries/org/lwjgl/lwjgl/lwjgl/2.9.0/lwjgl-2.9.0.jar"/> 7 <classpathentry kind="lib" path="/Client/jars/libraries/org/lwjgl/lwjgl/lwjgl/2.9.0/lwjgl-2.9.0.jar"/>
8 <classpathentry kind="lib" path="/Client/jars/versions/1.6.2/1.6.2.jar"/> 8 <classpathentry kind="lib" path="/Client/jars/versions/1.6.2/1.6.2.jar"/>
  9 + <classpathentry kind="lib" path="/Client/jars/libraries/com/google/code/gson/gson/2.2.2/gson-2.2.2.jar"/>
9 <classpathentry kind="output" path="bin"/> 10 <classpathentry kind="output" path="bin"/>
10 </classpath> 11 </classpath>
java/com/mumfrey/liteloader/core/HookChat.java
@@ -136,39 +136,39 @@ public class HookChat extends Packet3Chat @@ -136,39 +136,39 @@ public class HookChat extends Packet3Chat
136 /** 136 /**
137 * Register this packet as the new packet for packet ID 3 137 * Register this packet as the new packet for packet ID 3
138 */ 138 */
139 - public static void register()  
140 - {  
141 - register(false);  
142 - }  
143 -  
144 - /**  
145 - * Register this packet as the new packet for packet ID 3 and optionally force re-registration even  
146 - * if registration was performed already.  
147 - *  
148 - * @param force Force registration even if registration was already performed previously.  
149 - */  
150 - @SuppressWarnings({ "unchecked", "rawtypes" }) 139 + public static void register()
  140 + {
  141 + register(false);
  142 + }
  143 +
  144 + /**
  145 + * Register this packet as the new packet for packet ID 3 and optionally force re-registration even
  146 + * if registration was performed already.
  147 + *
  148 + * @param force Force registration even if registration was already performed previously.
  149 + */
  150 + @SuppressWarnings({ "unchecked", "rawtypes" })
151 public static void register(boolean force) 151 public static void register(boolean force)
152 { 152 {
153 if (!registered || force) 153 if (!registered || force)
154 { 154 {
155 try 155 try
156 { 156 {
157 - IntHashMap packetIdToClassMap = Packet.packetIdToClassMap;  
158 - proxyClass = (Class<? extends Packet>)packetIdToClassMap.lookup(3);  
159 -  
160 - if (proxyClass.equals(Packet3Chat.class))  
161 - {  
162 - proxyClass = null;  
163 - }  
164 -  
165 - packetIdToClassMap.removeObject(3);  
166 - packetIdToClassMap.addKey(3, HookChat.class);  
167 -  
168 - Map packetClassToIdMap = PrivateFields.StaticFields.packetClassToIdMap.get();  
169 - packetClassToIdMap.put(HookChat.class, Integer.valueOf(3));  
170 -  
171 - registered = true; 157 + IntHashMap packetIdToClassMap = Packet.packetIdToClassMap;
  158 + proxyClass = (Class<? extends Packet>)packetIdToClassMap.lookup(3);
  159 +
  160 + if (proxyClass.equals(Packet3Chat.class))
  161 + {
  162 + proxyClass = null;
  163 + }
  164 +
  165 + packetIdToClassMap.removeObject(3);
  166 + packetIdToClassMap.addKey(3, HookChat.class);
  167 +
  168 + Map packetClassToIdMap = PrivateFields.StaticFields.packetClassToIdMap.get();
  169 + packetClassToIdMap.put(HookChat.class, Integer.valueOf(3));
  170 +
  171 + registered = true;
172 } 172 }
173 catch (Exception ex) 173 catch (Exception ex)
174 { 174 {
java/com/mumfrey/liteloader/core/HookPluginChannels.java
@@ -128,39 +128,39 @@ public class HookPluginChannels extends Packet250CustomPayload @@ -128,39 +128,39 @@ public class HookPluginChannels extends Packet250CustomPayload
128 /** 128 /**
129 * Register this packet as the new packet for packet ID 250 129 * Register this packet as the new packet for packet ID 250
130 */ 130 */
131 - public static void register()  
132 - {  
133 - register(false);  
134 - }  
135 -  
136 - /**  
137 - * Register this packet as the new packet for packet ID 250 and optionally force re-registration even  
138 - * if registration was performed already.  
139 - *  
140 - * @param force Force registration even if registration was already performed previously.  
141 - */  
142 - @SuppressWarnings({ "unchecked", "rawtypes" }) 131 + public static void register()
  132 + {
  133 + register(false);
  134 + }
  135 +
  136 + /**
  137 + * Register this packet as the new packet for packet ID 250 and optionally force re-registration even
  138 + * if registration was performed already.
  139 + *
  140 + * @param force Force registration even if registration was already performed previously.
  141 + */
  142 + @SuppressWarnings({ "unchecked", "rawtypes" })
143 public static void register(boolean force) 143 public static void register(boolean force)
144 { 144 {
145 if (!registered || force) 145 if (!registered || force)
146 { 146 {
147 try 147 try
148 { 148 {
149 - IntHashMap packetIdToClassMap = Packet.packetIdToClassMap;  
150 - proxyClass = (Class<? extends Packet>)packetIdToClassMap.lookup(250);  
151 -  
152 - if (proxyClass.equals(Packet250CustomPayload.class))  
153 - {  
154 - proxyClass = null;  
155 - }  
156 -  
157 - packetIdToClassMap.removeObject(250);  
158 - packetIdToClassMap.addKey(250, HookPluginChannels.class);  
159 -  
160 - Map packetClassToIdMap = PrivateFields.StaticFields.packetClassToIdMap.get();  
161 - packetClassToIdMap.put(HookPluginChannels.class, Integer.valueOf(250));  
162 -  
163 - registered = true; 149 + IntHashMap packetIdToClassMap = Packet.packetIdToClassMap;
  150 + proxyClass = (Class<? extends Packet>)packetIdToClassMap.lookup(250);
  151 +
  152 + if (proxyClass.equals(Packet250CustomPayload.class))
  153 + {
  154 + proxyClass = null;
  155 + }
  156 +
  157 + packetIdToClassMap.removeObject(250);
  158 + packetIdToClassMap.addKey(250, HookPluginChannels.class);
  159 +
  160 + Map packetClassToIdMap = PrivateFields.StaticFields.packetClassToIdMap.get();
  161 + packetClassToIdMap.put(HookPluginChannels.class, Integer.valueOf(250));
  162 +
  163 + registered = true;
164 } 164 }
165 catch (Exception ex) 165 catch (Exception ex)
166 { 166 {
java/com/mumfrey/liteloader/core/LiteLoader.java
@@ -10,16 +10,23 @@ import java.io.IOException; @@ -10,16 +10,23 @@ import java.io.IOException;
10 import java.io.InputStream; 10 import java.io.InputStream;
11 import java.io.InputStreamReader; 11 import java.io.InputStreamReader;
12 import java.io.PrintStream; 12 import java.io.PrintStream;
  13 +import java.io.UnsupportedEncodingException;
13 import java.lang.reflect.Method; 14 import java.lang.reflect.Method;
  15 +import java.net.MalformedURLException;
  16 +import java.net.URISyntaxException;
14 import java.net.URL; 17 import java.net.URL;
15 import java.net.URLClassLoader; 18 import java.net.URLClassLoader;
16 import java.net.URLDecoder; 19 import java.net.URLDecoder;
17 import java.nio.charset.Charset; 20 import java.nio.charset.Charset;
  21 +import java.util.ArrayList;
18 import java.util.HashMap; 22 import java.util.HashMap;
19 import java.util.Iterator; 23 import java.util.Iterator;
20 import java.util.LinkedList; 24 import java.util.LinkedList;
21 import java.util.List; 25 import java.util.List;
  26 +import java.util.Map;
  27 +import java.util.Map.Entry;
22 import java.util.Properties; 28 import java.util.Properties;
  29 +import java.util.TreeSet;
23 import java.util.logging.FileHandler; 30 import java.util.logging.FileHandler;
24 import java.util.logging.Formatter; 31 import java.util.logging.Formatter;
25 import java.util.logging.Level; 32 import java.util.logging.Level;
@@ -71,7 +78,6 @@ import com.mumfrey.liteloader.util.PrivateFields; @@ -71,7 +78,6 @@ import com.mumfrey.liteloader.util.PrivateFields;
71 * @author Adam Mummery-Smith 78 * @author Adam Mummery-Smith
72 * @version 1.6.2 79 * @version 1.6.2
73 */ 80 */
74 -@SuppressWarnings("rawtypes")  
75 public final class LiteLoader implements FilenameFilter, IPlayerUsage 81 public final class LiteLoader implements FilenameFilter, IPlayerUsage
76 { 82 {
77 /** 83 /**
@@ -115,6 +121,11 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -115,6 +121,11 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
115 private static String profile = ""; 121 private static String profile = "";
116 122
117 /** 123 /**
  124 + * List of mods passed into the command line
  125 + */
  126 + private static List<String> modNameFilter = null;
  127 +
  128 + /**
118 * Mods folder which contains mods and legacy config files 129 * Mods folder which contains mods and legacy config files
119 */ 130 */
120 private File modsFolder; 131 private File modsFolder;
@@ -173,6 +184,16 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -173,6 +184,16 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
173 private Timer minecraftTimer; 184 private Timer minecraftTimer;
174 185
175 /** 186 /**
  187 + * Classes to load, mapped by class name
  188 + */
  189 + private Map<String, Class<? extends LiteMod>> modsToLoad = new HashMap<String, Class<? extends LiteMod>>();
  190 +
  191 + /**
  192 + * Mod metadata from version file
  193 + */
  194 + private Map<String, ModFile> modFiles = new HashMap<String, ModFile>();
  195 +
  196 + /**
176 * List of loaded mods, for crash reporting 197 * List of loaded mods, for crash reporting
177 */ 198 */
178 private String loadedModsList = "none"; 199 private String loadedModsList = "none";
@@ -280,8 +301,8 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -280,8 +301,8 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
280 * Permission Manager 301 * Permission Manager
281 */ 302 */
282 private static PermissionsManagerClient permissionsManager = PermissionsManagerClient.getInstance(); 303 private static PermissionsManagerClient permissionsManager = PermissionsManagerClient.getInstance();
283 -  
284 - public static final void init(File gameDirectory, File assetsDirectory, String profile) 304 +
  305 + public static final void init(File gameDirectory, File assetsDirectory, String profile, List<String> modNameFilter)
285 { 306 {
286 if (instance == null) 307 if (instance == null)
287 { 308 {
@@ -289,6 +310,22 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -289,6 +310,22 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
289 LiteLoader.assetsDirectory = assetsDirectory; 310 LiteLoader.assetsDirectory = assetsDirectory;
290 LiteLoader.profile = profile; 311 LiteLoader.profile = profile;
291 312
  313 + try
  314 + {
  315 + if (modNameFilter != null)
  316 + {
  317 + LiteLoader.modNameFilter = new ArrayList<String>();
  318 + for (String filterEntry : modNameFilter)
  319 + {
  320 + LiteLoader.modNameFilter.add(filterEntry.toLowerCase().trim());
  321 + }
  322 + }
  323 + }
  324 + catch (Exception ex)
  325 + {
  326 + LiteLoader.modNameFilter = null;
  327 + }
  328 +
292 instance = new LiteLoader(); 329 instance = new LiteLoader();
293 instance.initLoader(); 330 instance.initLoader();
294 } 331 }
@@ -371,14 +408,10 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -371,14 +408,10 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
371 this.commonConfigFolder = new File(this.configBaseFolder, "common"); 408 this.commonConfigFolder = new File(this.configBaseFolder, "common");
372 this.versionConfigFolder = this.inflectVersionedConfigPath(LiteLoader.VERSION); 409 this.versionConfigFolder = this.inflectVersionedConfigPath(LiteLoader.VERSION);
373 410
374 - if (!this.modsFolder.exists())  
375 - this.modsFolder.mkdirs();  
376 - if (!this.configBaseFolder.exists())  
377 - this.configBaseFolder.mkdirs();  
378 - if (!this.commonConfigFolder.exists())  
379 - this.commonConfigFolder.mkdirs();  
380 - if (!this.versionConfigFolder.exists())  
381 - this.versionConfigFolder.mkdirs(); 411 + if (!this.modsFolder.exists()) this.modsFolder.mkdirs();
  412 + if (!this.configBaseFolder.exists()) this.configBaseFolder.mkdirs();
  413 + if (!this.commonConfigFolder.exists()) this.commonConfigFolder.mkdirs();
  414 + if (!this.versionConfigFolder.exists()) this.versionConfigFolder.mkdirs();
382 415
383 this.propertiesFile = new File(this.configBaseFolder, "liteloader.properties"); 416 this.propertiesFile = new File(this.configBaseFolder, "liteloader.properties");
384 } 417 }
@@ -402,8 +435,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -402,8 +435,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
402 */ 435 */
403 private void initLoader() 436 private void initLoader()
404 { 437 {
405 - if (this.loaderStartupDone)  
406 - return; 438 + if (this.loaderStartupDone) return;
407 this.loaderStartupDone = true; 439 this.loaderStartupDone = true;
408 440
409 // Set up loader, initialises any reflection methods needed 441 // Set up loader, initialises any reflection methods needed
@@ -700,8 +732,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -700,8 +732,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
700 /** 732 /**
701 * Get a reference to a loaded mod, if the mod exists 733 * Get a reference to a loaded mod, if the mod exists
702 * 734 *
703 - * @param modName  
704 - * Mod's name or class name 735 + * @param modName Mod's name or class name
705 * @return 736 * @return
706 * @throws InvalidActivityException 737 * @throws InvalidActivityException
707 */ 738 */
@@ -728,13 +759,65 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -728,13 +759,65 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
728 } 759 }
729 760
730 /** 761 /**
  762 + * Get whether the specified mod is installed
  763 + *
  764 + * @param modName
  765 + * @return
  766 + */
  767 + public boolean isModInstalled(String modName)
  768 + {
  769 + if (!this.loaderStartupComplete || modName == null) return false;
  770 +
  771 + for (LiteMod mod : this.mods)
  772 + {
  773 + if (modName.equalsIgnoreCase(mod.getName()) || modName.equalsIgnoreCase(mod.getClass().getSimpleName())) return true;
  774 + }
  775 +
  776 + return true;
  777 + }
  778 +
  779 + /**
  780 + * Get metadata for the specified mod, attempts to retrieve the mod by name first
  781 + *
  782 + * @param mod
  783 + * @param metaDataKey
  784 + * @param defaultValue
  785 + * @return
  786 + * @throws InvalidActivityException
  787 + * @throws IllegalArgumentException
  788 + */
  789 + public String getModMetaData(String mod, String metaDataKey, String defaultValue) throws InvalidActivityException, IllegalArgumentException
  790 + {
  791 + return this.getModMetaData(this.getMod(mod), metaDataKey, defaultValue);
  792 + }
  793 +
  794 + /**
  795 + * Get a metadata value for the specified mod
  796 + *
  797 + * @param mod
  798 + * @param metaDataKey
  799 + * @param defaultValue
  800 + * @return
  801 + */
  802 + public String getModMetaData(LiteMod mod, String metaDataKey, String defaultValue)
  803 + {
  804 + if (mod == null || metaDataKey == null) return defaultValue;
  805 +
  806 + String modClassName = mod.getClass().getSimpleName();
  807 + if (!this.modFiles.containsKey(modClassName)) return defaultValue;
  808 +
  809 + ModFile modFile = this.modFiles.get(modClassName);
  810 + return modFile.getMetaValue(metaDataKey, defaultValue);
  811 + }
  812 +
  813 + /**
731 * Enumerate the java class path and "mods" folder to find mod classes, then 814 * Enumerate the java class path and "mods" folder to find mod classes, then
732 * load the classes 815 * load the classes
733 */ 816 */
734 private void prepareMods(boolean searchMods, boolean searchProtectionDomain, boolean searchClassPath) 817 private void prepareMods(boolean searchMods, boolean searchProtectionDomain, boolean searchClassPath)
735 { 818 {
736 // List of mod files in the "mods" folder 819 // List of mod files in the "mods" folder
737 - LinkedList<File> modFiles = new LinkedList<File>(); 820 + List<ModFile> modFiles = new LinkedList<ModFile>();
738 821
739 if (searchMods) 822 if (searchMods)
740 { 823 {
@@ -748,8 +831,6 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -748,8 +831,6 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
748 } 831 }
749 } 832 }
750 833
751 - // Find and enumerate classes on the class path  
752 - HashMap<String, Class> modsToLoad = null;  
753 try 834 try
754 { 835 {
755 logger.info("Enumerating class path..."); 836 logger.info("Enumerating class path...");
@@ -763,7 +844,8 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -763,7 +844,8 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
763 844
764 if (searchProtectionDomain || searchClassPath) 845 if (searchProtectionDomain || searchClassPath)
765 logger.info("Discovering mods on class path..."); 846 logger.info("Discovering mods on class path...");
766 - modsToLoad = this.findModClasses(classPathEntries, modFiles, searchProtectionDomain, searchClassPath); 847 +
  848 + this.findModClasses(classPathEntries, modFiles, searchProtectionDomain, searchClassPath);
767 849
768 logger.info("Mod class discovery completed"); 850 logger.info("Mod class discovery completed");
769 } 851 }
@@ -773,44 +855,87 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -773,44 +855,87 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
773 return; 855 return;
774 } 856 }
775 857
776 - this.loadMods(modsToLoad); 858 + this.loadMods();
777 } 859 }
778 860
779 /** 861 /**
780 * Find mod files in the "mods" folder 862 * Find mod files in the "mods" folder
781 * 863 *
782 - * @param modFolder  
783 - * Folder to search  
784 - * @param modFiles  
785 - * List of mod files to load 864 + * @param modFolder Folder to search
  865 + * @param modFiles List of mod files to load
786 */ 866 */
787 - protected void findModFiles(File modFolder, LinkedList<File> modFiles) 867 + protected void findModFiles(File modFolder, List<ModFile> modFiles)
788 { 868 {
  869 + Map<String, TreeSet<ModFile>> versionOrderingSets = new HashMap<String, TreeSet<ModFile>>();
  870 +
789 for (File modFile : modFolder.listFiles(this)) 871 for (File modFile : modFolder.listFiles(this))
790 { 872 {
791 try 873 try
792 { 874 {
  875 + String strVersion = null;
  876 +
793 // Check for a version file 877 // Check for a version file
794 ZipFile modZip = new ZipFile(modFile); 878 ZipFile modZip = new ZipFile(modFile);
795 - ZipEntry version = modZip.getEntry("version.txt"); 879 + ZipEntry version = modZip.getEntry("litemod.json");
  880 +
  881 + if (version == null)
  882 + {
  883 + version = modZip.getEntry("version.txt");
  884 + }
796 885
797 if (version != null) 886 if (version != null)
798 { 887 {
799 - // Read the version string  
800 - InputStream versionStream = modZip.getInputStream(version);  
801 - BufferedReader versionReader = new BufferedReader(new InputStreamReader(versionStream));  
802 - String strVersion = versionReader.readLine();  
803 - versionReader.close(); 888 + BufferedReader versionReader = null;
  889 + StringBuilder versionBuilder = new StringBuilder();
804 890
805 - // Only add the mod if the version matches and we were able  
806 - // to successfully add it to the class path  
807 - if (LiteLoader.VERSION.isVersionSupported(strVersion) && this.addURLToClassPath(modFile.toURI().toURL())) 891 + try
808 { 892 {
809 - modFiles.add(modFile); 893 + // Read the version string
  894 + InputStream versionStream = modZip.getInputStream(version);
  895 + versionReader = new BufferedReader(new InputStreamReader(versionStream));
  896 +
  897 + String versionFileLine;
  898 + while ((versionFileLine = versionReader.readLine()) != null)
  899 + versionBuilder.append(versionFileLine);
  900 +
  901 + strVersion = versionBuilder.toString();
810 } 902 }
811 - else 903 + catch (Exception ex)
  904 + {
  905 + logger.warning("Error reading version data from " + modFile.getName());
  906 + }
  907 + finally
812 { 908 {
813 - logger.info("Not adding invalid or outdated mod file: " + modFile.getAbsolutePath()); 909 + if (versionReader != null) versionReader.close();
  910 + }
  911 +
  912 + if (strVersion != null)
  913 + {
  914 + ModFile modFileInfo = new ModFile(modFile, strVersion);
  915 +
  916 + if (modFileInfo.isValid())
  917 + {
  918 + // Only add the mod if the version matches and we were able
  919 + // to successfully add it to the class path
  920 + if (LiteLoader.VERSION.isVersionSupported(modFileInfo.getVersion()))
  921 + {
  922 + if (!modFileInfo.isJson())
  923 + {
  924 + logger.warning("Missing or invalid litemod.json reading mod file: " + modFile.getAbsolutePath());
  925 + }
  926 +
  927 + if (!versionOrderingSets.containsKey(modFileInfo.getName()))
  928 + {
  929 + versionOrderingSets.put(modFileInfo.getName(), new TreeSet<ModFile>());
  930 + }
  931 +
  932 + versionOrderingSets.get(modFileInfo.getName()).add(modFileInfo);
  933 + }
  934 + else
  935 + {
  936 + logger.info("Not adding invalid or outdated mod file: " + modFile.getAbsolutePath());
  937 + }
  938 + }
814 } 939 }
815 } 940 }
816 941
@@ -818,9 +943,28 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -818,9 +943,28 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
818 } 943 }
819 catch (Exception ex) 944 catch (Exception ex)
820 { 945 {
  946 + ex.printStackTrace(System.err);
821 logger.warning("Error enumerating '" + modFile.getAbsolutePath() + "': Invalid zip file or error reading file"); 947 logger.warning("Error enumerating '" + modFile.getAbsolutePath() + "': Invalid zip file or error reading file");
822 } 948 }
823 } 949 }
  950 +
  951 + // Copy the first entry in every version set into the modfiles list
  952 + for (Entry<String, TreeSet<ModFile>> modFileEntry : versionOrderingSets.entrySet())
  953 + {
  954 + ModFile newestVersion = modFileEntry.getValue().iterator().next();
  955 +
  956 + try
  957 + {
  958 + if (this.addURLToClassPath(newestVersion.toURI().toURL()))
  959 + {
  960 + modFiles.add(newestVersion);
  961 + }
  962 + }
  963 + catch (Exception ex)
  964 + {
  965 + logger.warning("Error injecting '" + newestVersion.getAbsolutePath() + "' into classPath. The mod will not be loaded");
  966 + }
  967 + }
824 } 968 }
825 969
826 /* 970 /*
@@ -837,66 +981,15 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -837,66 +981,15 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
837 /** 981 /**
838 * Find mod classes in the class path and enumerated mod files list 982 * Find mod classes in the class path and enumerated mod files list
839 * 983 *
840 - * @param classPathEntries  
841 - * Java class path split into string entries  
842 - * @return map of classes to load 984 + * @param classPathEntries Java class path split into string entries
843 */ 985 */
844 - private HashMap<String, Class> findModClasses(String[] classPathEntries, LinkedList<File> modFiles, boolean searchProtectionDomain, boolean searchClassPath) 986 + private void findModClasses(String[] classPathEntries, List<ModFile> modFiles, boolean searchProtectionDomain, boolean searchClassPath)
845 { 987 {
846 - // To try to avoid loading the same mod multiple times if it appears in  
847 - // more than one entry in the class path, we index  
848 - // the mods by name and hopefully match only a single instance of a  
849 - // particular mod  
850 - HashMap<String, Class> modsToLoad = new HashMap<String, Class>();  
851 -  
852 if (searchProtectionDomain) 988 if (searchProtectionDomain)
853 { 989 {
854 try 990 try
855 { 991 {
856 - logger.info("Searching protection domain code source...");  
857 -  
858 - File packagePath = null;  
859 -  
860 - URL protectionDomainLocation = LiteLoader.class.getProtectionDomain().getCodeSource().getLocation();  
861 - if (protectionDomainLocation != null)  
862 - {  
863 - if (protectionDomainLocation.toString().indexOf('!') > -1 && protectionDomainLocation.toString().startsWith("jar:"))  
864 - {  
865 - protectionDomainLocation = new URL(protectionDomainLocation.toString().substring(4, protectionDomainLocation.toString().indexOf('!')));  
866 - }  
867 -  
868 - packagePath = new File(protectionDomainLocation.toURI());  
869 - }  
870 - else  
871 - {  
872 - // Fix (?) for forge and other mods which screw up the  
873 - // protection domain  
874 - String reflectionClassPath = LiteLoader.class.getResource("/com/mumfrey/liteloader/core/LiteLoader.class").getPath();  
875 -  
876 - if (reflectionClassPath.indexOf('!') > -1)  
877 - {  
878 - reflectionClassPath = URLDecoder.decode(reflectionClassPath, "UTF-8");  
879 - packagePath = new File(reflectionClassPath.substring(5, reflectionClassPath.indexOf('!')));  
880 - }  
881 - }  
882 -  
883 - if (packagePath != null)  
884 - {  
885 - LinkedList<Class> modClasses = getSubclassesFor(packagePath, Minecraft.class.getClassLoader(), LiteMod.class, "LiteMod");  
886 -  
887 - for (Class mod : modClasses)  
888 - {  
889 - if (modsToLoad.containsKey(mod.getSimpleName()))  
890 - {  
891 - logger.warning("Mod name collision for mod with class '" + mod.getSimpleName() + "', maybe you have more than one copy?");  
892 - }  
893 -  
894 - modsToLoad.put(mod.getSimpleName(), mod);  
895 - }  
896 -  
897 - if (modClasses.size() > 0)  
898 - logger.info(String.format("Found %s potential matches", modClasses.size()));  
899 - } 992 + this.searchProtectionDomain();
900 } 993 }
901 catch (Throwable th) 994 catch (Throwable th)
902 { 995 {
@@ -907,78 +1000,158 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -907,78 +1000,158 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
907 if (searchClassPath) 1000 if (searchClassPath)
908 { 1001 {
909 // Search through the class path and find mod classes 1002 // Search through the class path and find mod classes
910 - for (String classPathPart : classPathEntries) 1003 + this.searchClassPath(classPathEntries);
  1004 + }
  1005 +
  1006 + // Search through mod files and find mod classes
  1007 + this.searchModFiles(modFiles);
  1008 + }
  1009 +
  1010 + /**
  1011 + * @param modsToLoad
  1012 + * @throws MalformedURLException
  1013 + * @throws URISyntaxException
  1014 + * @throws UnsupportedEncodingException
  1015 + */
  1016 + @SuppressWarnings("unchecked")
  1017 + private void searchProtectionDomain() throws MalformedURLException, URISyntaxException, UnsupportedEncodingException
  1018 + {
  1019 + logger.info("Searching protection domain code source...");
  1020 +
  1021 + File packagePath = null;
  1022 +
  1023 + URL protectionDomainLocation = LiteLoader.class.getProtectionDomain().getCodeSource().getLocation();
  1024 + if (protectionDomainLocation != null)
  1025 + {
  1026 + if (protectionDomainLocation.toString().indexOf('!') > -1 && protectionDomainLocation.toString().startsWith("jar:"))
911 { 1027 {
912 - logger.info(String.format("Searching %s...", classPathPart));  
913 -  
914 - File packagePath = new File(classPathPart);  
915 - LinkedList<Class> modClasses = getSubclassesFor(packagePath, Minecraft.class.getClassLoader(), LiteMod.class, "LiteMod"); 1028 + protectionDomainLocation = new URL(protectionDomainLocation.toString().substring(4, protectionDomainLocation.toString().indexOf('!')));
  1029 + }
  1030 +
  1031 + packagePath = new File(protectionDomainLocation.toURI());
  1032 + }
  1033 + else
  1034 + {
  1035 + // Fix (?) for forge and other mods which screw up the
  1036 + // protection domain
  1037 + String reflectionClassPath = LiteLoader.class.getResource("/com/mumfrey/liteloader/core/LiteLoader.class").getPath();
  1038 +
  1039 + if (reflectionClassPath.indexOf('!') > -1)
  1040 + {
  1041 + reflectionClassPath = URLDecoder.decode(reflectionClassPath, "UTF-8");
  1042 + packagePath = new File(reflectionClassPath.substring(5, reflectionClassPath.indexOf('!')));
  1043 + }
  1044 + }
  1045 +
  1046 + if (packagePath != null)
  1047 + {
  1048 + LinkedList<Class<?>> modClasses = getSubclassesFor(packagePath, Minecraft.class.getClassLoader(), LiteMod.class, "LiteMod");
  1049 +
  1050 + for (Class<?> mod : modClasses)
  1051 + {
  1052 + if (this.modsToLoad.containsKey(mod.getSimpleName()))
  1053 + {
  1054 + logger.warning("Mod name collision for mod with class '" + mod.getSimpleName() + "', maybe you have more than one copy?");
  1055 + }
916 1056
917 - for (Class mod : modClasses) 1057 + this.modsToLoad.put(mod.getSimpleName(), (Class<? extends LiteMod>)mod);
  1058 + }
  1059 +
  1060 + if (modClasses.size() > 0)
  1061 + logger.info(String.format("Found %s potential matches", modClasses.size()));
  1062 + }
  1063 + }
  1064 +
  1065 + /**
  1066 + * @param classPathEntries
  1067 + * @param modsToLoad
  1068 + */
  1069 + @SuppressWarnings("unchecked")
  1070 + private void searchClassPath(String[] classPathEntries)
  1071 + {
  1072 + for (String classPathPart : classPathEntries)
  1073 + {
  1074 + logger.info(String.format("Searching %s...", classPathPart));
  1075 +
  1076 + File packagePath = new File(classPathPart);
  1077 + LinkedList<Class<?>> modClasses = getSubclassesFor(packagePath, Minecraft.class.getClassLoader(), LiteMod.class, "LiteMod");
  1078 +
  1079 + for (Class<?> mod : modClasses)
  1080 + {
  1081 + if (this.modsToLoad.containsKey(mod.getSimpleName()))
918 { 1082 {
919 - if (modsToLoad.containsKey(mod.getSimpleName()))  
920 - {  
921 - logger.warning("Mod name collision for mod with class '" + mod.getSimpleName() + "', maybe you have more than one copy?");  
922 - }  
923 -  
924 - modsToLoad.put(mod.getSimpleName(), mod); 1083 + logger.warning("Mod name collision for mod with class '" + mod.getSimpleName() + "', maybe you have more than one copy?");
925 } 1084 }
926 1085
927 - if (modClasses.size() > 0)  
928 - logger.info(String.format("Found %s potential matches", modClasses.size())); 1086 + this.modsToLoad.put(mod.getSimpleName(), (Class<? extends LiteMod>)mod);
929 } 1087 }
  1088 +
  1089 + if (modClasses.size() > 0)
  1090 + logger.info(String.format("Found %s potential matches", modClasses.size()));
930 } 1091 }
931 -  
932 - // Search through mod files and find mod classes  
933 - for (File modFile : modFiles) 1092 + }
  1093 +
  1094 + /**
  1095 + * @param modFiles
  1096 + * @param modsToLoad
  1097 + */
  1098 + @SuppressWarnings("unchecked")
  1099 + private void searchModFiles(List<ModFile> modFiles)
  1100 + {
  1101 + for (ModFile modFile : modFiles)
934 { 1102 {
935 logger.info(String.format("Searching %s...", modFile.getAbsolutePath())); 1103 logger.info(String.format("Searching %s...", modFile.getAbsolutePath()));
936 1104
937 - LinkedList<Class> modClasses = getSubclassesFor(modFile, Minecraft.class.getClassLoader(), LiteMod.class, "LiteMod"); 1105 + LinkedList<Class<?>> modClasses = getSubclassesFor(modFile, Minecraft.class.getClassLoader(), LiteMod.class, "LiteMod");
938 1106
939 - for (Class mod : modClasses) 1107 + for (Class<?> mod : modClasses)
940 { 1108 {
941 - if (modsToLoad.containsKey(mod.getSimpleName())) 1109 + if (this.modsToLoad.containsKey(mod.getSimpleName()))
942 { 1110 {
943 logger.warning("Mod name collision for mod with class '" + mod.getSimpleName() + "', maybe you have more than one copy?"); 1111 logger.warning("Mod name collision for mod with class '" + mod.getSimpleName() + "', maybe you have more than one copy?");
944 } 1112 }
945 1113
946 - modsToLoad.put(mod.getSimpleName(), mod); 1114 + this.modsToLoad.put(mod.getSimpleName(), (Class<? extends LiteMod>)mod);
  1115 + this.modFiles.put(mod.getSimpleName(), modFile);
947 } 1116 }
948 1117
949 if (modClasses.size() > 0) 1118 if (modClasses.size() > 0)
950 logger.info(String.format("Found %s potential matches", modClasses.size())); 1119 logger.info(String.format("Found %s potential matches", modClasses.size()));
951 } 1120 }
952 -  
953 - return modsToLoad;  
954 } 1121 }
955 1122
956 /** 1123 /**
957 * Create mod instances from the enumerated classes 1124 * Create mod instances from the enumerated classes
958 * 1125 *
959 - * @param modsToLoad  
960 - * List of mods to load 1126 + * @param modsToLoad List of mods to load
961 */ 1127 */
962 - private void loadMods(HashMap<String, Class> modsToLoad) 1128 + private void loadMods()
963 { 1129 {
964 - if (modsToLoad == null) 1130 + if (this.modsToLoad == null)
965 { 1131 {
966 logger.info("Mod class discovery failed. Not loading any mods!"); 1132 logger.info("Mod class discovery failed. Not loading any mods!");
967 return; 1133 return;
968 } 1134 }
969 1135
970 - logger.info("Discovered " + modsToLoad.size() + " total mod(s)"); 1136 + logger.info("Discovered " + this.modsToLoad.size() + " total mod(s)");
971 1137
972 - for (Class mod : modsToLoad.values()) 1138 + for (Class<? extends LiteMod> mod : this.modsToLoad.values())
973 { 1139 {
974 try 1140 try
975 { 1141 {
976 logger.info("Loading mod from " + mod.getName()); 1142 logger.info("Loading mod from " + mod.getName());
977 1143
978 - LiteMod newMod = (LiteMod)mod.newInstance();  
979 - this.mods.add(newMod); 1144 + LiteMod newMod = mod.newInstance();
980 1145
981 - logger.info("Successfully added mod " + newMod.getName() + " version " + newMod.getVersion()); 1146 + if (this.shouldAddMod(newMod))
  1147 + {
  1148 + this.mods.add(newMod);
  1149 + logger.info("Successfully added mod " + newMod.getName() + " version " + newMod.getVersion());
  1150 + }
  1151 + else
  1152 + {
  1153 + logger.info("Not loading mod " + newMod.getName() + ", excluded by filter");
  1154 + }
982 } 1155 }
983 catch (Throwable th) 1156 catch (Throwable th)
984 { 1157 {
@@ -989,6 +1162,26 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -989,6 +1162,26 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
989 } 1162 }
990 1163
991 /** 1164 /**
  1165 + * @param name
  1166 + * @return
  1167 + */
  1168 + private boolean shouldAddMod(LiteMod mod)
  1169 + {
  1170 + if (this.modNameFilter == null) return true;
  1171 +
  1172 + String modClassName = mod.getClass().getSimpleName();
  1173 + if (!this.modFiles.containsKey(modClassName)) return true;
  1174 +
  1175 + String metaName = this.modFiles.get(modClassName).getModName().toLowerCase();
  1176 + if (this.modNameFilter.contains(metaName))
  1177 + {
  1178 + return true;
  1179 + }
  1180 +
  1181 + return false;
  1182 + }
  1183 +
  1184 + /**
992 * Initialise the mods which were loaded 1185 * Initialise the mods which were loaded
993 */ 1186 */
994 private void initMods() 1187 private void initMods()
@@ -999,28 +1192,29 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -999,28 +1192,29 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
999 for (Iterator<LiteMod> iter = this.mods.iterator(); iter.hasNext();) 1192 for (Iterator<LiteMod> iter = this.mods.iterator(); iter.hasNext();)
1000 { 1193 {
1001 LiteMod mod = iter.next(); 1194 LiteMod mod = iter.next();
  1195 + String modName = mod.getName();
1002 1196
1003 try 1197 try
1004 { 1198 {
1005 - logger.info("Initialising mod " + mod.getName() + " version " + mod.getVersion()); 1199 + logger.info("Initialising mod " + modName + " version " + mod.getVersion());
1006 1200
1007 try 1201 try
1008 { 1202 {
1009 - String modKey = this.getModNameForConfig(mod.getClass(), mod.getName()); 1203 + String modKey = this.getModNameForConfig(mod.getClass(), modName);
1010 LiteLoaderVersion lastModVersion = LiteLoaderVersion.getVersionFromRevision(this.getLastKnownModRevision(modKey)); 1204 LiteLoaderVersion lastModVersion = LiteLoaderVersion.getVersionFromRevision(this.getLastKnownModRevision(modKey));
1011 1205
1012 if (LiteLoader.VERSION.getLoaderRevision() > lastModVersion.getLoaderRevision()) 1206 if (LiteLoader.VERSION.getLoaderRevision() > lastModVersion.getLoaderRevision())
1013 { 1207 {
1014 - logger.info("Performing config upgrade for mod " + mod.getName() + ". Upgrading " + lastModVersion + " to " + LiteLoader.VERSION + "..."); 1208 + logger.info("Performing config upgrade for mod " + modName + ". Upgrading " + lastModVersion + " to " + LiteLoader.VERSION + "...");
1015 mod.upgradeSettings(LiteLoader.getVersion(), this.versionConfigFolder, this.inflectVersionedConfigPath(lastModVersion)); 1209 mod.upgradeSettings(LiteLoader.getVersion(), this.versionConfigFolder, this.inflectVersionedConfigPath(lastModVersion));
1016 1210
1017 this.storeLastKnownModRevision(modKey); 1211 this.storeLastKnownModRevision(modKey);
1018 - logger.info("Config upgrade succeeded for mod " + mod.getName()); 1212 + logger.info("Config upgrade succeeded for mod " + modName);
1019 } 1213 }
1020 } 1214 }
1021 catch (Throwable th) 1215 catch (Throwable th)
1022 { 1216 {
1023 - logger.warning("Error performing settings upgrade for " + mod.getName() + ". Settings may not be properly migrated"); 1217 + logger.warning("Error performing settings upgrade for " + modName + ". Settings may not be properly migrated");
1024 } 1218 }
1025 1219
1026 mod.init(this.modsFolder); 1220 mod.init(this.modsFolder);
@@ -1059,7 +1253,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -1059,7 +1253,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
1059 { 1253 {
1060 if (mod instanceof ChatFilter) 1254 if (mod instanceof ChatFilter)
1061 { 1255 {
1062 - this.logger.warning(String.format("Interface error initialising mod '%1s'. A mod implementing ChatFilter and ChatListener is not supported! Remove one of these interfaces", mod.getName())); 1256 + this.logger.warning(String.format("Interface error initialising mod '%1s'. A mod implementing ChatFilter and ChatListener is not supported! Remove one of these interfaces", modName));
1063 } 1257 }
1064 else 1258 else
1065 { 1259 {
@@ -1092,12 +1286,12 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -1092,12 +1286,12 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
1092 permissionsManager.registerPermissible((Permissible)mod); 1286 permissionsManager.registerPermissible((Permissible)mod);
1093 } 1287 }
1094 1288
1095 - this.loadedModsList += String.format("\n - %s version %s", mod.getName(), mod.getVersion()); 1289 + this.loadedModsList += String.format("\n - %s version %s", modName, mod.getVersion());
1096 loadedModsCount++; 1290 loadedModsCount++;
1097 } 1291 }
1098 catch (Throwable th) 1292 catch (Throwable th)
1099 { 1293 {
1100 - logger.log(Level.WARNING, "Error initialising mod '" + mod.getName(), th); 1294 + logger.log(Level.WARNING, "Error initialising mod '" + modName, th);
1101 iter.remove(); 1295 iter.remove();
1102 } 1296 }
1103 } 1297 }
@@ -1304,9 +1498,9 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -1304,9 +1498,9 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
1304 * @param superClass 1498 * @param superClass
1305 * @return 1499 * @return
1306 */ 1500 */
1307 - private static LinkedList<Class> getSubclassesFor(File packagePath, ClassLoader classloader, Class superClass, String prefix) 1501 + private static LinkedList<Class<?>> getSubclassesFor(File packagePath, ClassLoader classloader, Class<?> superClass, String prefix)
1308 { 1502 {
1309 - LinkedList<Class> classes = new LinkedList<Class>(); 1503 + LinkedList<Class<?>> classes = new LinkedList<Class<?>>();
1310 1504
1311 try 1505 try
1312 { 1506 {
@@ -1335,7 +1529,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -1335,7 +1529,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
1335 * @throws FileNotFoundException 1529 * @throws FileNotFoundException
1336 * @throws IOException 1530 * @throws IOException
1337 */ 1531 */
1338 - private static void enumerateCompressedPackage(String prefix, Class superClass, ClassLoader classloader, LinkedList<Class> classes, File packagePath) throws FileNotFoundException, IOException 1532 + private static void enumerateCompressedPackage(String prefix, Class<?> superClass, ClassLoader classloader, LinkedList<Class<?>> classes, File packagePath) throws FileNotFoundException, IOException
1339 { 1533 {
1340 FileInputStream fileinputstream = new FileInputStream(packagePath); 1534 FileInputStream fileinputstream = new FileInputStream(packagePath);
1341 ZipInputStream zipinputstream = new ZipInputStream(fileinputstream); 1535 ZipInputStream zipinputstream = new ZipInputStream(fileinputstream);
@@ -1377,7 +1571,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -1377,7 +1571,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
1377 * @param packagePath 1571 * @param packagePath
1378 * @param packageName 1572 * @param packageName
1379 */ 1573 */
1380 - private static void enumerateDirectory(String prefix, Class superClass, ClassLoader classloader, LinkedList<Class> classes, File packagePath) 1574 + private static void enumerateDirectory(String prefix, Class<?> superClass, ClassLoader classloader, LinkedList<Class<?>> classes, File packagePath)
1381 { 1575 {
1382 enumerateDirectory(prefix, superClass, classloader, classes, packagePath, "", 0); 1576 enumerateDirectory(prefix, superClass, classloader, classes, packagePath, "", 0);
1383 } 1577 }
@@ -1391,7 +1585,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -1391,7 +1585,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
1391 * @param packagePath 1585 * @param packagePath
1392 * @param packageName 1586 * @param packageName
1393 */ 1587 */
1394 - private static void enumerateDirectory(String prefix, Class superClass, ClassLoader classloader, LinkedList<Class> classes, File packagePath, String packageName, int depth) 1588 + private static void enumerateDirectory(String prefix, Class<?> superClass, ClassLoader classloader, LinkedList<Class<?>> classes, File packagePath, String packageName, int depth)
1395 { 1589 {
1396 // Prevent crash due to broken recursion 1590 // Prevent crash due to broken recursion
1397 if (depth > MAX_DISCOVERY_DEPTH) 1591 if (depth > MAX_DISCOVERY_DEPTH)
@@ -1423,15 +1617,14 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -1423,15 +1617,14 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
1423 * @param classes 1617 * @param classes
1424 * @param className 1618 * @param className
1425 */ 1619 */
1426 - @SuppressWarnings("unchecked")  
1427 - private static void checkAndAddClass(ClassLoader classloader, Class superClass, LinkedList<Class> classes, String className) 1620 + private static void checkAndAddClass(ClassLoader classloader, Class<?> superClass, LinkedList<Class<?>> classes, String className)
1428 { 1621 {
1429 if (className.indexOf('$') > -1) 1622 if (className.indexOf('$') > -1)
1430 return; 1623 return;
1431 1624
1432 try 1625 try
1433 { 1626 {
1434 - Class subClass = classloader.loadClass(className); 1627 + Class<?> subClass = classloader.loadClass(className);
1435 1628
1436 if (subClass != null && !superClass.equals(subClass) && superClass.isAssignableFrom(subClass) && !subClass.isInterface() && !classes.contains(subClass)) 1629 if (subClass != null && !superClass.equals(subClass) && superClass.isAssignableFrom(subClass) && !subClass.isInterface() && !classes.contains(subClass))
1437 { 1630 {
@@ -1447,8 +1640,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -1447,8 +1640,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
1447 /** 1640 /**
1448 * Add a URL to the Minecraft classloader class path 1641 * Add a URL to the Minecraft classloader class path
1449 * 1642 *
1450 - * @param classUrl  
1451 - * URL of the resource to add 1643 + * @param classUrl URL of the resource to add
1452 */ 1644 */
1453 private boolean addURLToClassPath(URL classUrl) 1645 private boolean addURLToClassPath(URL classUrl)
1454 { 1646 {
@@ -1596,8 +1788,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -1596,8 +1788,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
1596 /** 1788 /**
1597 * Callback from the tick hook, ticks all tickable mods 1789 * Callback from the tick hook, ticks all tickable mods
1598 * 1790 *
1599 - * @param tick  
1600 - * True if this is a new tick (otherwise it's just a new frame) 1791 + * @param tick True if this is a new tick (otherwise it's just a new frame)
1601 */ 1792 */
1602 public void onTick(Profiler profiler, boolean tick) 1793 public void onTick(Profiler profiler, boolean tick)
1603 { 1794 {
@@ -1728,10 +1919,8 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage @@ -1728,10 +1919,8 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
1728 /** 1919 /**
1729 * Delegate to ModUtilities.sendPluginChannelMessage 1920 * Delegate to ModUtilities.sendPluginChannelMessage
1730 * 1921 *
1731 - * @param channel  
1732 - * Channel to send data to  
1733 - * @param data  
1734 - * Data to send 1922 + * @param channel Channel to send data to
  1923 + * @param data Data to send
1735 */ 1924 */
1736 public void sendPluginChannelMessage(String channel, byte[] data) 1925 public void sendPluginChannelMessage(String channel, byte[] data)
1737 { 1926 {
java/com/mumfrey/liteloader/core/LiteLoaderVersion.java
@@ -12,6 +12,8 @@ import java.util.Set; @@ -12,6 +12,8 @@ import java.util.Set;
12 public enum LiteLoaderVersion 12 public enum LiteLoaderVersion
13 { 13 {
14 LEGACY(0, "-", "-", "-"), 14 LEGACY(0, "-", "-", "-"),
  15 + MC_1_5_2_R1(9, "1.5.2", "1.5.2", "1.5.2"),
  16 + MC_1_5_2_R2(10, "1.5.2", "1.5.2", "1.5.2"),
15 MC_1_6_1_R0(11, "1.6.1", "1.6.1", "1.6.1", "1.6.r1"), 17 MC_1_6_1_R0(11, "1.6.1", "1.6.1", "1.6.1", "1.6.r1"),
16 MC_1_6_2_R0(12, "1.6.2", "1.6.2", "1.6.2", "1.6.r2"); 18 MC_1_6_2_R0(12, "1.6.2", "1.6.2", "1.6.2", "1.6.r2");
17 19
java/com/mumfrey/liteloader/core/ModFile.java 0 → 100644
  1 +package com.mumfrey.liteloader.core;
  2 +
  3 +import java.io.File;
  4 +import java.util.HashMap;
  5 +import java.util.Map;
  6 +
  7 +import com.google.gson.Gson;
  8 +import com.google.gson.JsonSyntaxException;
  9 +
  10 +/**
  11 + * Wrapper for file which represents a mod file to load with associated version information and
  12 + * metadata. Retrieve this from litemod.xml at enumeration time. We also override comparable to
  13 + * provide our own custom sorting logic based on version info.
  14 + *
  15 + * @author Adam Mummery-Smith
  16 + */
  17 +public class ModFile extends File
  18 +{
  19 + private static final long serialVersionUID = -7952147161905688459L;
  20 +
  21 + /**
  22 + * Gson parser for JSON
  23 + */
  24 + private static Gson gson = new Gson();
  25 +
  26 + /**
  27 + * True if the metadata information is parsed successfully, the mod will be added
  28 + */
  29 + private boolean valid = false;
  30 +
  31 + /**
  32 + * True if parsed from JSON, false if fallback mode using legacy version.txt
  33 + */
  34 + private boolean json = false;
  35 +
  36 + /**
  37 + * Name of the mod specified in the JSON file, this can be any string but should be the same between mod versions
  38 + */
  39 + private String modName;
  40 +
  41 + /**
  42 + * Loader version
  43 + */
  44 + private String version;
  45 +
  46 + /**
  47 + * File time stamp, used as sorting criteria when no revision information is found
  48 + */
  49 + private long timeStamp;
  50 +
  51 + /**
  52 + * Revision number from the json file
  53 + */
  54 + private float revision = 0.0F;
  55 +
  56 + /**
  57 + * True if the revision number was successfully read, used as a semaphore so that we know when revision is a valid number
  58 + */
  59 + private boolean hasRevision = false;
  60 +
  61 + /**
  62 + * ALL of the parsed metadata from the file, associated with the mod later on for retrieval via the loader
  63 + */
  64 + private HashMap<String, String> metaData = new HashMap<String, String>();
  65 +
  66 + /**
  67 + * @param file
  68 + * @param strVersion
  69 + */
  70 + public ModFile(File file, String strVersion)
  71 + {
  72 + super(file.getAbsolutePath());
  73 +
  74 + this.timeStamp = this.lastModified();
  75 +
  76 + this.parseVersionFile(strVersion);
  77 + }
  78 +
  79 + @SuppressWarnings("unchecked")
  80 + private void parseVersionFile(String strVersionData)
  81 + {
  82 + // Assume that it's json if the file starts with a brace
  83 + if (strVersionData.trim().startsWith("{"))
  84 + {
  85 + try
  86 + {
  87 + this.metaData = ModFile.gson.fromJson(strVersionData, HashMap.class);
  88 + }
  89 + catch (JsonSyntaxException jsx)
  90 + {
  91 + LiteLoader.getLogger().warning("Error reading litemod.json in " + this.getName() + ", JSON syntax exception: " + jsx.getMessage());
  92 + return;
  93 + }
  94 +
  95 + this.modName = this.metaData.get("name");
  96 +
  97 + this.version = this.metaData.get("mcversion");
  98 + if (this.version == null)
  99 + {
  100 + LiteLoader.getLogger().warning("Mod in " + this.getName() + " has no loader version number reading litemod.json");
  101 + return;
  102 + }
  103 +
  104 + try
  105 + {
  106 + this.revision = Float.parseFloat(this.metaData.get("revision"));
  107 + this.hasRevision = true;
  108 + }
  109 + catch (Exception ex)
  110 + {
  111 + LiteLoader.getLogger().warning("Mod in " + this.getName() + " has an invalid revision number reading litemod.json");
  112 + }
  113 +
  114 + this.valid = true;
  115 + this.json = true;
  116 + }
  117 + else
  118 + {
  119 + // Legacy version.txt file
  120 + this.version = strVersionData;
  121 + this.valid = true;
  122 + }
  123 +
  124 + if (this.modName == null)
  125 + {
  126 + this.modName = this.getName().replaceAll("[^a-zA-Z]", "");
  127 + }
  128 + }
  129 +
  130 + public String getModName()
  131 + {
  132 + return this.modName;
  133 + }
  134 +
  135 + public boolean isValid()
  136 + {
  137 + return this.valid;
  138 + }
  139 +
  140 + public boolean isJson()
  141 + {
  142 + return this.json;
  143 + }
  144 +
  145 + public String getVersion()
  146 + {
  147 + return this.version;
  148 + }
  149 +
  150 + public float getRevision()
  151 + {
  152 + return this.revision;
  153 + }
  154 +
  155 + public String getMetaValue(String metaKey, String defaultValue)
  156 + {
  157 + return this.metaData.containsKey(metaKey) ? this.metaData.get(metaKey) : defaultValue;
  158 + }
  159 +
  160 + public Map<String, String> getMetaData()
  161 + {
  162 + return this.metaData;
  163 + }
  164 +
  165 + @Override
  166 + public int compareTo(File other)
  167 + {
  168 + if (other == null || !(other instanceof ModFile)) return -1;
  169 +
  170 + ModFile otherMod = (ModFile)other;
  171 +
  172 + // If the other object has a revision, compare revisions
  173 + if (otherMod.hasRevision)
  174 + {
  175 + return this.hasRevision && this.revision - otherMod.revision > 0 ? -1 : 1;
  176 + }
  177 +
  178 + // If we have a revision and the other object doesn't, then we are higher
  179 + if (this.hasRevision)
  180 + {
  181 + return -1;
  182 + }
  183 +
  184 + // Give up and use timestamp
  185 + return (int)(otherMod.timeStamp - this.timeStamp);
  186 + }
  187 +}
java/com/mumfrey/liteloader/gui/GuiControlsPaginated.java
@@ -20,58 +20,58 @@ public class GuiControlsPaginated extends GuiScreen @@ -20,58 +20,58 @@ public class GuiControlsPaginated extends GuiScreen
20 * Pagination variables 20 * Pagination variables
21 */ 21 */
22 protected int controlsPerPage, startIndex, endIndex; 22 protected int controlsPerPage, startIndex, endIndex;
23 - 23 +
24 /** 24 /**
25 * Parent screen which will be displayed when this screen is closed 25 * Parent screen which will be displayed when this screen is closed
26 */ 26 */
27 protected GuiScreen parentScreen; 27 protected GuiScreen parentScreen;
28 -  
29 - /**  
30 - * Game settings  
31 - */ 28 +
  29 + /**
  30 + * Game settings
  31 + */
32 protected GameSettings gameSettings; 32 protected GameSettings gameSettings;
33 -  
34 - /**  
35 - * Additional buttons  
36 - */ 33 +
  34 + /**
  35 + * Additional buttons
  36 + */
37 protected GuiButton btnNext, btnPrevious; 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") 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() 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 - 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() 75 public GuiScreen getParentScreen()
76 { 76 {
77 return this.parentScreen; 77 return this.parentScreen;
@@ -84,40 +84,40 @@ public class GuiControlsPaginated extends GuiScreen @@ -84,40 +84,40 @@ public class GuiControlsPaginated extends GuiScreen
84 public void initGui() 84 public void initGui()
85 { 85 {
86 this.getLegacyControlList().clear(); 86 this.getLegacyControlList().clear();
87 - 87 +
88 int oldControlsPerPage = this.controlsPerPage; 88 int oldControlsPerPage = this.controlsPerPage;
89 this.controlsPerPage = ((this.getHeight() - 70) / 24) * 2; 89 this.controlsPerPage = ((this.getHeight() - 70) / 24) * 2;
90 - this.endIndex = this.gameSettings.keyBindings.length - (this.gameSettings.keyBindings.length % this.controlsPerPage == 0 ? this.controlsPerPage : this.gameSettings.keyBindings.length % this.controlsPerPage);  
91 - if (oldControlsPerPage != this.controlsPerPage) this.startIndex = 0;  
92 -  
93 - for (int controlId = 0; controlId < this.gameSettings.keyBindings.length; controlId++)  
94 - {  
95 - boolean buttonVisible = controlId >= this.startIndex && controlId < this.startIndex + this.controlsPerPage; 90 + this.endIndex = this.gameSettings.keyBindings.length - (this.gameSettings.keyBindings.length % this.controlsPerPage == 0 ? this.controlsPerPage : this.gameSettings.keyBindings.length % this.controlsPerPage);
  91 + if (oldControlsPerPage != this.controlsPerPage) this.startIndex = 0;
  92 +
  93 + for (int controlId = 0; controlId < this.gameSettings.keyBindings.length; controlId++)
  94 + {
  95 + boolean buttonVisible = controlId >= this.startIndex && controlId < this.startIndex + this.controlsPerPage;
96 int left = buttonVisible ? this.getWidth() / 2 - 155 : this.getWidth() + 10000; 96 int left = buttonVisible ? this.getWidth() / 2 - 155 : this.getWidth() + 10000;
97 - int top = this.getHeight() / 6 + 24 * ((controlId - this.startIndex) >> 1); 97 + int top = this.getHeight() / 6 + 24 * ((controlId - this.startIndex) >> 1);
98 this.getLegacyControlList().add(new GuiSmallButton(controlId, left + ((controlId - this.startIndex) % 2) * 160, top, 70, 20, this.gameSettings.getOptionDisplayString(controlId))); 98 this.getLegacyControlList().add(new GuiSmallButton(controlId, left + ((controlId - this.startIndex) % 2) * 160, top, 70, 20, this.gameSettings.getOptionDisplayString(controlId)));
99 - }  
100 -  
101 - int buttonY = this.getHeight() / 6 + (this.controlsPerPage >> 1) * 24;  
102 -  
103 - // Only bother paginating if there are too many controls to display 99 + }
  100 +
  101 + int buttonY = this.getHeight() / 6 + (this.controlsPerPage >> 1) * 24;
  102 +
  103 + // Only bother paginating if there are too many controls to display
104 if (this.gameSettings.keyBindings.length > this.controlsPerPage) 104 if (this.gameSettings.keyBindings.length > this.controlsPerPage)
105 - {  
106 - this.getLegacyControlList().add(this.btnNext = new GuiButton(201, this.getWidth() / 2 - 51, buttonY, 50, 20, ">>"));  
107 - this.getLegacyControlList().add(this.btnPrevious = new GuiButton(202, this.getWidth() / 2 - 103, buttonY, 50, 20, "<<"));  
108 - this.getLegacyControlList().add(new GuiButton(200, this.getWidth() / 2 + 1, buttonY, 100, 20, I18n.func_135053_a("gui.done")));  
109 -  
110 - this.btnNext.enabled = this.startIndex < this.endIndex;  
111 - this.btnPrevious.enabled = this.startIndex > 0;  
112 - }  
113 - else  
114 - {  
115 - this.getLegacyControlList().add(new GuiButton(200, this.getWidth() / 2 - 100, buttonY, I18n.func_135053_a("gui.done")));  
116 - }  
117 -  
118 - this.screenTitle = I18n.func_135053_a("controls.title"); 105 + {
  106 + this.getLegacyControlList().add(this.btnNext = new GuiButton(201, this.getWidth() / 2 - 51, buttonY, 50, 20, ">>"));
  107 + this.getLegacyControlList().add(this.btnPrevious = new GuiButton(202, this.getWidth() / 2 - 103, buttonY, 50, 20, "<<"));
  108 + this.getLegacyControlList().add(new GuiButton(200, this.getWidth() / 2 + 1, buttonY, 100, 20, I18n.func_135053_a("gui.done")));
  109 +
  110 + this.btnNext.enabled = this.startIndex < this.endIndex;
  111 + this.btnPrevious.enabled = this.startIndex > 0;
  112 + }
  113 + else
  114 + {
  115 + this.getLegacyControlList().add(new GuiButton(200, this.getWidth() / 2 - 100, buttonY, I18n.func_135053_a("gui.done")));
  116 + }
  117 +
  118 + this.screenTitle = I18n.func_135053_a("controls.title");
119 } 119 }
120 - 120 +
121 /** 121 /**
122 * @param controlId 122 * @param controlId
123 * @return 123 * @return
@@ -136,103 +136,103 @@ public class GuiControlsPaginated extends GuiScreen @@ -136,103 +136,103 @@ public class GuiControlsPaginated extends GuiScreen
136 protected void actionPerformed(GuiButton guibutton) 136 protected void actionPerformed(GuiButton guibutton)
137 { 137 {
138 // Update the button labels with the appropriate key names 138 // Update the button labels with the appropriate key names
139 - for(int i = 0; i < this.gameSettings.keyBindings.length; i++)  
140 - {  
141 - this.getLegacyControlList().get(i).displayString = this.gameSettings.getOptionDisplayString(i);  
142 - }  
143 -  
144 - if (guibutton.id == 200) // Done button  
145 - {  
146 - this.mc.displayGuiScreen(this.parentScreen);  
147 - }  
148 - else if (guibutton.id == 201) // Next button  
149 - {  
150 - this.startIndex += this.controlsPerPage;  
151 - this.startIndex = Math.min(this.endIndex, this.startIndex);  
152 - this.initGui();  
153 - }  
154 - else if (guibutton.id == 202) // Previous button  
155 - {  
156 - this.startIndex -= this.controlsPerPage;  
157 - this.startIndex = Math.max(0, this.startIndex);  
158 - this.initGui();  
159 - }  
160 - else  
161 - {  
162 - this.activeButtonId = guibutton.id;  
163 - guibutton.displayString = String.format("> %s <", this.gameSettings.getOptionDisplayString(guibutton.id));  
164 - } 139 + for(int i = 0; i < this.gameSettings.keyBindings.length; i++)
  140 + {
  141 + this.getLegacyControlList().get(i).displayString = this.gameSettings.getOptionDisplayString(i);
  142 + }
  143 +
  144 + if (guibutton.id == 200) // Done button
  145 + {
  146 + this.mc.displayGuiScreen(this.parentScreen);
  147 + }
  148 + else if (guibutton.id == 201) // Next button
  149 + {
  150 + this.startIndex += this.controlsPerPage;
  151 + this.startIndex = Math.min(this.endIndex, this.startIndex);
  152 + this.initGui();
  153 + }
  154 + else if (guibutton.id == 202) // Previous button
  155 + {
  156 + this.startIndex -= this.controlsPerPage;
  157 + this.startIndex = Math.max(0, this.startIndex);
  158 + this.initGui();
  159 + }
  160 + else
  161 + {
  162 + this.activeButtonId = guibutton.id;
  163 + guibutton.displayString = String.format("> %s <", this.gameSettings.getOptionDisplayString(guibutton.id));
  164 + }
165 } 165 }
166 - 166 +
167 @Override 167 @Override
168 - protected void mouseClicked(int mouseX, int mouseY, int mouseButton)  
169 - {  
170 - if (this.activeButtonId >= 0)  
171 - {  
172 - this.gameSettings.setKeyBinding(this.activeButtonId, -100 + mouseButton);  
173 - this.getLegacyControlList().get(this.activeButtonId).displayString = this.gameSettings.getOptionDisplayString(this.activeButtonId);  
174 - this.activeButtonId = -1;  
175 - KeyBinding.resetKeyBindingArrayAndHash();  
176 - }  
177 - else  
178 - {  
179 - super.mouseClicked(mouseX, mouseY, mouseButton);  
180 - }  
181 - }  
182 - 168 + protected void mouseClicked(int mouseX, int mouseY, int mouseButton)
  169 + {
  170 + if (this.activeButtonId >= 0)
  171 + {
  172 + this.gameSettings.setKeyBinding(this.activeButtonId, -100 + mouseButton);
  173 + this.getLegacyControlList().get(this.activeButtonId).displayString = this.gameSettings.getOptionDisplayString(this.activeButtonId);
  174 + this.activeButtonId = -1;
  175 + KeyBinding.resetKeyBindingArrayAndHash();
  176 + }
  177 + else
  178 + {
  179 + super.mouseClicked(mouseX, mouseY, mouseButton);
  180 + }
  181 + }
  182 +
183 @Override 183 @Override
184 - protected void keyTyped(char keyChar, int keyCode)  
185 - {  
186 - if (this.activeButtonId >= 0)  
187 - {  
188 - this.gameSettings.setKeyBinding(this.activeButtonId, keyCode);  
189 - this.getLegacyControlList().get(this.activeButtonId).displayString = this.gameSettings.getOptionDisplayString(this.activeButtonId);  
190 - this.activeButtonId = -1;  
191 - KeyBinding.resetKeyBindingArrayAndHash();  
192 - }  
193 - else  
194 - {  
195 - super.keyTyped(keyChar, keyCode);  
196 - }  
197 - }  
198 - 184 + protected void keyTyped(char keyChar, int keyCode)
  185 + {
  186 + if (this.activeButtonId >= 0)
  187 + {
  188 + this.gameSettings.setKeyBinding(this.activeButtonId, keyCode);
  189 + this.getLegacyControlList().get(this.activeButtonId).displayString = this.gameSettings.getOptionDisplayString(this.activeButtonId);
  190 + this.activeButtonId = -1;
  191 + KeyBinding.resetKeyBindingArrayAndHash();
  192 + }
  193 + else
  194 + {
  195 + super.keyTyped(keyChar, keyCode);
  196 + }
  197 + }
  198 +
199 @Override 199 @Override
200 - public void drawScreen(int mouseX, int mouseY, float partialTick)  
201 - {  
202 - this.drawDefaultBackground();  
203 - this.drawCenteredString(this.fontRenderer, this.screenTitle, this.width / 2, 20, 0xffffff);  
204 -  
205 - // Draw key labels  
206 - for (int controlId = 0; controlId < this.gameSettings.keyBindings.length; controlId++)  
207 - {  
208 - boolean conflict = false;  
209 -  
210 - for (int id = 0; id < this.gameSettings.keyBindings.length; id++)  
211 - {  
212 - if (id != controlId && this.gameSettings.keyBindings[controlId].keyCode == this.gameSettings.keyBindings[id].keyCode)  
213 - {  
214 - conflict = true;  
215 - break;  
216 - }  
217 - }  
218 -  
219 - if (this.activeButtonId == controlId)  
220 - {  
221 - this.getLegacyControlList().get(controlId).displayString = "\247f> \247e??? \247f<";  
222 - }  
223 - else if (conflict)  
224 - {  
225 - this.getLegacyControlList().get(controlId).displayString = "\247c" + this.gameSettings.getOptionDisplayString(controlId);  
226 - }  
227 - else  
228 - {  
229 - this.getLegacyControlList().get(controlId).displayString = this.gameSettings.getOptionDisplayString(controlId);  
230 - }  
231 -  
232 - int left = (controlId >= this.startIndex && controlId < this.startIndex + this.controlsPerPage) ? this.getWidth() / 2 - 155 : this.getWidth() + 10000;  
233 - 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);  
234 - }  
235 -  
236 - super.drawScreen(mouseX, mouseY, partialTick);  
237 - } 200 + public void drawScreen(int mouseX, int mouseY, float partialTick)
  201 + {
  202 + this.drawDefaultBackground();
  203 + this.drawCenteredString(this.fontRenderer, this.screenTitle, this.width / 2, 20, 0xffffff);
  204 +
  205 + // Draw key labels
  206 + for (int controlId = 0; controlId < this.gameSettings.keyBindings.length; controlId++)
  207 + {
  208 + boolean conflict = false;
  209 +
  210 + for (int id = 0; id < this.gameSettings.keyBindings.length; id++)
  211 + {
  212 + if (id != controlId && this.gameSettings.keyBindings[controlId].keyCode == this.gameSettings.keyBindings[id].keyCode)
  213 + {
  214 + conflict = true;
  215 + break;
  216 + }
  217 + }
  218 +
  219 + if (this.activeButtonId == controlId)
  220 + {
  221 + this.getLegacyControlList().get(controlId).displayString = "\247f> \247e??? \247f<";
  222 + }
  223 + else if (conflict)
  224 + {
  225 + this.getLegacyControlList().get(controlId).displayString = "\247c" + this.gameSettings.getOptionDisplayString(controlId);
  226 + }
  227 + else
  228 + {
  229 + this.getLegacyControlList().get(controlId).displayString = this.gameSettings.getOptionDisplayString(controlId);
  230 + }
  231 +
  232 + int left = (controlId >= this.startIndex && controlId < this.startIndex + this.controlsPerPage) ? this.getWidth() / 2 - 155 : this.getWidth() + 10000;
  233 + 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);
  234 + }
  235 +
  236 + super.drawScreen(mouseX, mouseY, partialTick);
  237 + }
238 } 238 }
239 \ No newline at end of file 239 \ No newline at end of file
java/com/mumfrey/liteloader/permissions/PermissionsManager.java
@@ -58,13 +58,13 @@ public interface PermissionsManager @@ -58,13 +58,13 @@ public interface PermissionsManager
58 */ 58 */
59 public abstract void onCustomPayload(String channel, int length, byte[] data); 59 public abstract void onCustomPayload(String channel, int length, byte[] data);
60 60
61 - /**  
62 - * LiteLoader support, gets the list of plugin channels to listen on  
63 - *  
64 - * @return  
65 - */  
66 - public abstract List<String> getChannels();  
67 - 61 + /**
  62 + * LiteLoader support, gets the list of plugin channels to listen on
  63 + *
  64 + * @return
  65 + */
  66 + public abstract List<String> getChannels();
  67 +
68 /** 68 /**
69 * Register a new event listener, the registered object will receive callbacks for permissions events 69 * Register a new event listener, the registered object will receive callbacks for permissions events
70 * 70 *
java/com/mumfrey/liteloader/util/ModUtilities.java
@@ -36,47 +36,47 @@ public abstract class ModUtilities @@ -36,47 +36,47 @@ public abstract class ModUtilities
36 * @param entityClass 36 * @param entityClass
37 * @param renderer 37 * @param renderer
38 */ 38 */
39 - @SuppressWarnings("unchecked") 39 + @SuppressWarnings("unchecked")
40 public static void addRenderer(Class<? extends Entity> entityClass, Render renderer) 40 public static void addRenderer(Class<? extends Entity> entityClass, Render renderer)
41 - {  
42 - Map<Class<? extends Entity>, Render> entityRenderMap = PrivateFields.entityRenderMap.get(RenderManager.instance);  
43 - entityRenderMap.put(entityClass, renderer);  
44 - renderer.setRenderManager(RenderManager.instance);  
45 - }  
46 -  
47 - /**  
48 - * Register a packet override  
49 - *  
50 - * @param packetId  
51 - * @param newPacket  
52 - */  
53 - @SuppressWarnings("unchecked")  
54 - public static boolean registerPacketOverride(int packetId, Class<? extends Packet> newPacket)  
55 - {  
56 - if (overriddenPackets.contains(Integer.valueOf(packetId)))  
57 - {  
58 - LiteLoader.getLogger().warning(String.format("Packet with ID %s was already overridden by another mod, one or mods may not function correctly", packetId));  
59 - }  
60 -  
61 - try  
62 - {  
63 - IntHashMap packetIdToClassMap = Packet.packetIdToClassMap;  
64 - PrivateFields.StaticFields.packetClassToIdMap.get();  
65 - Map<Class<? extends Packet>, Integer> packetClassToIdMap = PrivateFields.StaticFields.packetClassToIdMap.get();  
66 -  
67 - packetIdToClassMap.removeObject(packetId);  
68 - packetIdToClassMap.addKey(packetId, newPacket);  
69 - packetClassToIdMap.put(newPacket, Integer.valueOf(packetId));  
70 -  
71 - return true;  
72 - }  
73 - catch (Exception ex)  
74 - {  
75 - LiteLoader.logger.warning("Error registering packet override for packet id " + packetId + ": " + ex.getMessage());  
76 - return false;  
77 - }  
78 - }  
79 - 41 + {
  42 + Map<Class<? extends Entity>, Render> entityRenderMap = PrivateFields.entityRenderMap.get(RenderManager.instance);
  43 + entityRenderMap.put(entityClass, renderer);
  44 + renderer.setRenderManager(RenderManager.instance);
  45 + }
  46 +
  47 + /**
  48 + * Register a packet override
  49 + *
  50 + * @param packetId
  51 + * @param newPacket
  52 + */
  53 + @SuppressWarnings("unchecked")
  54 + public static boolean registerPacketOverride(int packetId, Class<? extends Packet> newPacket)
  55 + {
  56 + if (overriddenPackets.contains(Integer.valueOf(packetId)))
  57 + {
  58 + LiteLoader.getLogger().warning(String.format("Packet with ID %s was already overridden by another mod, one or mods may not function correctly", packetId));
  59 + }
  60 +
  61 + try
  62 + {
  63 + IntHashMap packetIdToClassMap = Packet.packetIdToClassMap;
  64 + PrivateFields.StaticFields.packetClassToIdMap.get();
  65 + Map<Class<? extends Packet>, Integer> packetClassToIdMap = PrivateFields.StaticFields.packetClassToIdMap.get();
  66 +
  67 + packetIdToClassMap.removeObject(packetId);
  68 + packetIdToClassMap.addKey(packetId, newPacket);
  69 + packetClassToIdMap.put(newPacket, Integer.valueOf(packetId));
  70 +
  71 + return true;
  72 + }
  73 + catch (Exception ex)
  74 + {
  75 + LiteLoader.logger.warning("Error registering packet override for packet id " + packetId + ": " + ex.getMessage());
  76 + return false;
  77 + }
  78 + }
  79 +
80 /** 80 /**
81 * Send a plugin channel (custom payload) packet to the server 81 * Send a plugin channel (custom payload) packet to the server
82 * 82 *