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 6 <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
7 7 <classpathentry kind="lib" path="/Client/jars/libraries/org/lwjgl/lwjgl/lwjgl/2.9.0/lwjgl-2.9.0.jar"/>
8 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 10 <classpathentry kind="output" path="bin"/>
10 11 </classpath>
... ...
java/com/mumfrey/liteloader/core/HookChat.java
... ... @@ -136,39 +136,39 @@ public class HookChat extends Packet3Chat
136 136 /**
137 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 151 public static void register(boolean force)
152 152 {
153 153 if (!registered || force)
154 154 {
155 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 173 catch (Exception ex)
174 174 {
... ...
java/com/mumfrey/liteloader/core/HookPluginChannels.java
... ... @@ -128,39 +128,39 @@ public class HookPluginChannels extends Packet250CustomPayload
128 128 /**
129 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 143 public static void register(boolean force)
144 144 {
145 145 if (!registered || force)
146 146 {
147 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 165 catch (Exception ex)
166 166 {
... ...
java/com/mumfrey/liteloader/core/LiteLoader.java
... ... @@ -10,16 +10,23 @@ import java.io.IOException;
10 10 import java.io.InputStream;
11 11 import java.io.InputStreamReader;
12 12 import java.io.PrintStream;
  13 +import java.io.UnsupportedEncodingException;
13 14 import java.lang.reflect.Method;
  15 +import java.net.MalformedURLException;
  16 +import java.net.URISyntaxException;
14 17 import java.net.URL;
15 18 import java.net.URLClassLoader;
16 19 import java.net.URLDecoder;
17 20 import java.nio.charset.Charset;
  21 +import java.util.ArrayList;
18 22 import java.util.HashMap;
19 23 import java.util.Iterator;
20 24 import java.util.LinkedList;
21 25 import java.util.List;
  26 +import java.util.Map;
  27 +import java.util.Map.Entry;
22 28 import java.util.Properties;
  29 +import java.util.TreeSet;
23 30 import java.util.logging.FileHandler;
24 31 import java.util.logging.Formatter;
25 32 import java.util.logging.Level;
... ... @@ -71,7 +78,6 @@ import com.mumfrey.liteloader.util.PrivateFields;
71 78 * @author Adam Mummery-Smith
72 79 * @version 1.6.2
73 80 */
74   -@SuppressWarnings("rawtypes")
75 81 public final class LiteLoader implements FilenameFilter, IPlayerUsage
76 82 {
77 83 /**
... ... @@ -115,6 +121,11 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
115 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 129 * Mods folder which contains mods and legacy config files
119 130 */
120 131 private File modsFolder;
... ... @@ -173,6 +184,16 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
173 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 197 * List of loaded mods, for crash reporting
177 198 */
178 199 private String loadedModsList = "none";
... ... @@ -280,8 +301,8 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
280 301 * Permission Manager
281 302 */
282 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 307 if (instance == null)
287 308 {
... ... @@ -289,6 +310,22 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
289 310 LiteLoader.assetsDirectory = assetsDirectory;
290 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 329 instance = new LiteLoader();
293 330 instance.initLoader();
294 331 }
... ... @@ -371,14 +408,10 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
371 408 this.commonConfigFolder = new File(this.configBaseFolder, "common");
372 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 416 this.propertiesFile = new File(this.configBaseFolder, "liteloader.properties");
384 417 }
... ... @@ -402,8 +435,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
402 435 */
403 436 private void initLoader()
404 437 {
405   - if (this.loaderStartupDone)
406   - return;
  438 + if (this.loaderStartupDone) return;
407 439 this.loaderStartupDone = true;
408 440  
409 441 // Set up loader, initialises any reflection methods needed
... ... @@ -700,8 +732,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
700 732 /**
701 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 736 * @return
706 737 * @throws InvalidActivityException
707 738 */
... ... @@ -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 814 * Enumerate the java class path and "mods" folder to find mod classes, then
732 815 * load the classes
733 816 */
734 817 private void prepareMods(boolean searchMods, boolean searchProtectionDomain, boolean searchClassPath)
735 818 {
736 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 822 if (searchMods)
740 823 {
... ... @@ -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 834 try
754 835 {
755 836 logger.info("Enumerating class path...");
... ... @@ -763,7 +844,8 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
763 844  
764 845 if (searchProtectionDomain || searchClassPath)
765 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 850 logger.info("Mod class discovery completed");
769 851 }
... ... @@ -773,44 +855,87 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
773 855 return;
774 856 }
775 857  
776   - this.loadMods(modsToLoad);
  858 + this.loadMods();
777 859 }
778 860  
779 861 /**
780 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 871 for (File modFile : modFolder.listFiles(this))
790 872 {
791 873 try
792 874 {
  875 + String strVersion = null;
  876 +
793 877 // Check for a version file
794 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 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 943 }
819 944 catch (Exception ex)
820 945 {
  946 + ex.printStackTrace(System.err);
821 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 981 /**
838 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 988 if (searchProtectionDomain)
853 989 {
854 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 994 catch (Throwable th)
902 995 {
... ... @@ -907,78 +1000,158 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
907 1000 if (searchClassPath)
908 1001 {
909 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 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 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 1118 if (modClasses.size() > 0)
950 1119 logger.info(String.format("Found %s potential matches", modClasses.size()));
951 1120 }
952   -
953   - return modsToLoad;
954 1121 }
955 1122  
956 1123 /**
957 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 1132 logger.info("Mod class discovery failed. Not loading any mods!");
967 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 1140 try
975 1141 {
976 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 1156 catch (Throwable th)
984 1157 {
... ... @@ -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 1185 * Initialise the mods which were loaded
993 1186 */
994 1187 private void initMods()
... ... @@ -999,28 +1192,29 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
999 1192 for (Iterator<LiteMod> iter = this.mods.iterator(); iter.hasNext();)
1000 1193 {
1001 1194 LiteMod mod = iter.next();
  1195 + String modName = mod.getName();
1002 1196  
1003 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 1201 try
1008 1202 {
1009   - String modKey = this.getModNameForConfig(mod.getClass(), mod.getName());
  1203 + String modKey = this.getModNameForConfig(mod.getClass(), modName);
1010 1204 LiteLoaderVersion lastModVersion = LiteLoaderVersion.getVersionFromRevision(this.getLastKnownModRevision(modKey));
1011 1205  
1012 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 1209 mod.upgradeSettings(LiteLoader.getVersion(), this.versionConfigFolder, this.inflectVersionedConfigPath(lastModVersion));
1016 1210  
1017 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 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 1220 mod.init(this.modsFolder);
... ... @@ -1059,7 +1253,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
1059 1253 {
1060 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 1258 else
1065 1259 {
... ... @@ -1092,12 +1286,12 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
1092 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 1290 loadedModsCount++;
1097 1291 }
1098 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 1295 iter.remove();
1102 1296 }
1103 1297 }
... ... @@ -1304,9 +1498,9 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
1304 1498 * @param superClass
1305 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 1505 try
1312 1506 {
... ... @@ -1335,7 +1529,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
1335 1529 * @throws FileNotFoundException
1336 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 1534 FileInputStream fileinputstream = new FileInputStream(packagePath);
1341 1535 ZipInputStream zipinputstream = new ZipInputStream(fileinputstream);
... ... @@ -1377,7 +1571,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
1377 1571 * @param packagePath
1378 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 1576 enumerateDirectory(prefix, superClass, classloader, classes, packagePath, "", 0);
1383 1577 }
... ... @@ -1391,7 +1585,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
1391 1585 * @param packagePath
1392 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 1590 // Prevent crash due to broken recursion
1397 1591 if (depth > MAX_DISCOVERY_DEPTH)
... ... @@ -1423,15 +1617,14 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
1423 1617 * @param classes
1424 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 1622 if (className.indexOf('$') > -1)
1430 1623 return;
1431 1624  
1432 1625 try
1433 1626 {
1434   - Class subClass = classloader.loadClass(className);
  1627 + Class<?> subClass = classloader.loadClass(className);
1435 1628  
1436 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 1640 /**
1448 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 1645 private boolean addURLToClassPath(URL classUrl)
1454 1646 {
... ... @@ -1596,8 +1788,7 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
1596 1788 /**
1597 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 1793 public void onTick(Profiler profiler, boolean tick)
1603 1794 {
... ... @@ -1728,10 +1919,8 @@ public final class LiteLoader implements FilenameFilter, IPlayerUsage
1728 1919 /**
1729 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 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 12 public enum LiteLoaderVersion
13 13 {
14 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 17 MC_1_6_1_R0(11, "1.6.1", "1.6.1", "1.6.1", "1.6.r1"),
16 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 20 * Pagination variables
21 21 */
22 22 protected int controlsPerPage, startIndex, endIndex;
23   -
  23 +
24 24 /**
25 25 * Parent screen which will be displayed when this screen is closed
26 26 */
27 27 protected GuiScreen parentScreen;
28   -
29   - /**
30   - * Game settings
31   - */
  28 +
  29 + /**
  30 + * Game settings
  31 + */
32 32 protected GameSettings gameSettings;
33   -
34   - /**
35   - * Additional buttons
36   - */
  33 +
  34 + /**
  35 + * Additional buttons
  36 + */
37 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 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 75 public GuiScreen getParentScreen()
76 76 {
77 77 return this.parentScreen;
... ... @@ -84,40 +84,40 @@ public class GuiControlsPaginated extends GuiScreen
84 84 public void initGui()
85 85 {
86 86 this.getLegacyControlList().clear();
87   -
  87 +
88 88 int oldControlsPerPage = this.controlsPerPage;
89 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 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 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 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 122 * @param controlId
123 123 * @return
... ... @@ -136,103 +136,103 @@ public class GuiControlsPaginated extends GuiScreen
136 136 protected void actionPerformed(GuiButton guibutton)
137 137 {
138 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 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 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 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 239 \ No newline at end of file
... ...
java/com/mumfrey/liteloader/permissions/PermissionsManager.java
... ... @@ -58,13 +58,13 @@ public interface PermissionsManager
58 58 */
59 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 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 36 * @param entityClass
37 37 * @param renderer
38 38 */
39   - @SuppressWarnings("unchecked")
  39 + @SuppressWarnings("unchecked")
40 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 81 * Send a plugin channel (custom payload) packet to the server
82 82 *
... ...