Commit 09ab166d80d1cd803a1ff7454f3ac2975af0d25b

Authored by Mumfrey
2 parents 434901f7 21dc1eac

Merge branch '1.11.2-backport' into 1.11.2

Showing 28 changed files with 1433 additions and 440 deletions
build.gradle
@@ -72,7 +72,7 @@ repositories { @@ -72,7 +72,7 @@ repositories {
72 } 72 }
73 73
74 dependencies { 74 dependencies {
75 - compile('org.spongepowered:mixin:0.7.1-SNAPSHOT') { 75 + compile('org.spongepowered:mixin:0.7.3-SNAPSHOT') {
76 exclude module: 'asm-commons' 76 exclude module: 'asm-commons'
77 exclude module: 'asm-tree' 77 exclude module: 'asm-tree'
78 exclude module: 'launchwrapper' 78 exclude module: 'launchwrapper'
src/client/java/com/mumfrey/liteloader/client/gui/GuiPanelLiteLoaderLog.java
@@ -290,6 +290,9 @@ class GuiPanelLiteLoaderLog extends GuiPanel implements ScrollPanelContent @@ -290,6 +290,9 @@ class GuiPanelLiteLoaderLog extends GuiPanel implements ScrollPanelContent
290 if (logLine.startsWith("tweakClass '")) return 0x5555FF; 290 if (logLine.startsWith("tweakClass '")) return 0x5555FF;
291 if (logLine.startsWith("baking listener list")) return 0x00AAAA; 291 if (logLine.startsWith("baking listener list")) return 0x00AAAA;
292 if (logLine.startsWith("generating new event handler")) return 0xFFFF55; 292 if (logLine.startsWith("generating new event handler")) return 0xFFFF55;
  293 + if (logLine.startsWith("resolving mods")) return 0xFFAA00;
  294 + if (logLine.startsWith("resolved artefact")) return 0x00AA00;
  295 + if (logLine.startsWith("evicting")) return 0xFFAA00;
293 296
294 return 0xCCCCCC; 297 return 0xCCCCCC;
295 } 298 }
src/client/java/com/mumfrey/liteloader/modconfig/AbstractConfigPanel.java
@@ -105,7 +105,7 @@ public abstract class AbstractConfigPanel implements ConfigPanel @@ -105,7 +105,7 @@ public abstract class AbstractConfigPanel implements ConfigPanel
105 /** 105 /**
106 * Base for config option handle structs 106 * Base for config option handle structs
107 */ 107 */
108 - static abstract class ConfigOption 108 + abstract static class ConfigOption
109 { 109 {
110 void onTick() 110 void onTick()
111 { 111 {
@@ -303,7 +303,7 @@ public abstract class AbstractConfigPanel implements ConfigPanel @@ -303,7 +303,7 @@ public abstract class AbstractConfigPanel implements ConfigPanel
303 @Override 303 @Override
304 public ConfigTextField setRegex(String regex, boolean force) 304 public ConfigTextField setRegex(String regex, boolean force)
305 { 305 {
306 - this.textField.setRegex(Pattern.compile(regex), force);; 306 + this.textField.setRegex(Pattern.compile(regex), force);
307 return this; 307 return this;
308 } 308 }
309 309
@@ -343,7 +343,8 @@ public abstract class AbstractConfigPanel implements ConfigPanel @@ -343,7 +343,8 @@ public abstract class AbstractConfigPanel implements ConfigPanel
343 } 343 }
344 else 344 else
345 { 345 {
346 - this.setValidator((text) -> { 346 + this.setValidator((text) ->
  347 + {
347 this.validate(text); 348 this.validate(text);
348 return true; 349 return true;
349 }); 350 });
src/main/java/com/mumfrey/liteloader/api/EnumeratorModule.java
@@ -36,10 +36,7 @@ public interface EnumeratorModule @@ -36,10 +36,7 @@ public interface EnumeratorModule
36 public abstract void writeSettings(LoaderEnvironment environment, LoaderProperties properties); 36 public abstract void writeSettings(LoaderEnvironment environment, LoaderProperties properties);
37 37
38 /** 38 /**
39 - * Find loadable mods in this enumerator's domain, the enumerator module  
40 - * should call back against the enumerator itself to register containers it  
41 - * discovers using the registerModContainer() and registerTweakContainer()  
42 - * callbacks. 39 + * Find loadable mods in this enumerator's domain.
43 * 40 *
44 * <p>This method is called during loader PREINIT phase so <b>do not use any 41 * <p>This method is called during loader PREINIT phase so <b>do not use any
45 * game classes here</b>!</p> 42 * game classes here</b>!</p>
@@ -48,6 +45,20 @@ public interface EnumeratorModule @@ -48,6 +45,20 @@ public interface EnumeratorModule
48 * @param profile 45 * @param profile
49 */ 46 */
50 public abstract void enumerate(ModularEnumerator enumerator, String profile); 47 public abstract void enumerate(ModularEnumerator enumerator, String profile);
  48 +
  49 + /**
  50 + * Register loadable mods discovered in this enumerator's domain during the
  51 + * call to {@link #enumerate}, the enumerator module should call back
  52 + * against the enumerator itself to register containers it discovers using
  53 + * the registerModContainer() and registerTweakContainer() callbacks.
  54 + *
  55 + * <p>This method is called during loader PREINIT phase so <b>do not use any
  56 + * game classes here</b>!</p>
  57 + *
  58 + * @param enumerator
  59 + * @param profile
  60 + */
  61 + public abstract void register(ModularEnumerator enumerator, String profile);
51 62
52 /** 63 /**
53 * The enumerator module should inject (as required) any discovered 64 * The enumerator module should inject (as required) any discovered
src/main/java/com/mumfrey/liteloader/core/EnabledModsList.java
@@ -8,7 +8,6 @@ package com.mumfrey.liteloader.core; @@ -8,7 +8,6 @@ package com.mumfrey.liteloader.core;
8 import java.io.File; 8 import java.io.File;
9 import java.io.FileReader; 9 import java.io.FileReader;
10 import java.io.FileWriter; 10 import java.io.FileWriter;
11 -import java.io.IOException;  
12 import java.util.List; 11 import java.util.List;
13 import java.util.Map; 12 import java.util.Map;
14 import java.util.TreeMap; 13 import java.util.TreeMap;
@@ -186,12 +185,9 @@ public final class EnabledModsList @@ -186,12 +185,9 @@ public final class EnabledModsList
186 { 185 {
187 if (file.exists()) 186 if (file.exists())
188 { 187 {
189 - FileReader reader = null;  
190 -  
191 - try 188 + try (FileReader reader = new FileReader(file))
192 { 189 {
193 - reader = new FileReader(file);  
194 - EnabledModsList instance = gson.fromJson(reader, EnabledModsList.class); 190 + EnabledModsList instance = EnabledModsList.gson.fromJson(reader, EnabledModsList.class);
195 instance.setEnabledModsFile(file); 191 instance.setEnabledModsFile(file);
196 return instance; 192 return instance;
197 } 193 }
@@ -199,20 +195,6 @@ public final class EnabledModsList @@ -199,20 +195,6 @@ public final class EnabledModsList
199 { 195 {
200 ex.printStackTrace(); 196 ex.printStackTrace();
201 } 197 }
202 - finally  
203 - {  
204 - try  
205 - {  
206 - if (reader != null)  
207 - {  
208 - reader.close();  
209 - }  
210 - }  
211 - catch (IOException ex)  
212 - {  
213 - ex.printStackTrace();  
214 - }  
215 - }  
216 } 198 }
217 199
218 EnabledModsList instance = new EnabledModsList(); 200 EnabledModsList instance = new EnabledModsList();
@@ -229,31 +211,14 @@ public final class EnabledModsList @@ -229,31 +211,14 @@ public final class EnabledModsList
229 { 211 {
230 if (!this.allowSave) return; 212 if (!this.allowSave) return;
231 213
232 - FileWriter writer = null;  
233 -  
234 - try 214 + try (FileWriter writer = new FileWriter(file))
235 { 215 {
236 - writer = new FileWriter(file);  
237 - gson.toJson(this, writer); 216 + EnabledModsList.gson.toJson(this, writer);
238 } 217 }
239 catch (Exception ex) 218 catch (Exception ex)
240 { 219 {
241 ex.printStackTrace(); 220 ex.printStackTrace();
242 } 221 }
243 - finally  
244 - {  
245 - try  
246 - {  
247 - if (writer != null)  
248 - {  
249 - writer.close();  
250 - }  
251 - }  
252 - catch (IOException ex)  
253 - {  
254 - ex.printStackTrace();  
255 - }  
256 - }  
257 } 222 }
258 223
259 /** 224 /**
src/main/java/com/mumfrey/liteloader/core/LiteLoaderBootstrap.java
@@ -29,6 +29,7 @@ import com.mumfrey.liteloader.api.manager.APIProvider; @@ -29,6 +29,7 @@ import com.mumfrey.liteloader.api.manager.APIProvider;
29 import com.mumfrey.liteloader.api.manager.APIRegistry; 29 import com.mumfrey.liteloader.api.manager.APIRegistry;
30 import com.mumfrey.liteloader.common.LoadingProgress; 30 import com.mumfrey.liteloader.common.LoadingProgress;
31 import com.mumfrey.liteloader.core.api.LiteLoaderCoreAPI; 31 import com.mumfrey.liteloader.core.api.LiteLoaderCoreAPI;
  32 +import com.mumfrey.liteloader.core.api.repository.Repository;
32 import com.mumfrey.liteloader.interfaces.LoaderEnumerator; 33 import com.mumfrey.liteloader.interfaces.LoaderEnumerator;
33 import com.mumfrey.liteloader.launch.ClassTransformerManager; 34 import com.mumfrey.liteloader.launch.ClassTransformerManager;
34 import com.mumfrey.liteloader.launch.LiteLoaderTweaker; 35 import com.mumfrey.liteloader.launch.LiteLoaderTweaker;
@@ -102,6 +103,16 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP @@ -102,6 +103,16 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
102 * Folder containing version-specific configuration 103 * Folder containing version-specific configuration
103 */ 104 */
104 private final File versionConfigFolder; 105 private final File versionConfigFolder;
  106 +
  107 + /**
  108 + * Mods repo file
  109 + */
  110 + private final String repositoryFile;
  111 +
  112 + /**
  113 + * Mod repository defined in JSON
  114 + */
  115 + private final Repository repository;
105 116
106 /** 117 /**
107 * File to write log entries to 118 * File to write log entries to
@@ -138,6 +149,8 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP @@ -138,6 +149,8 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
138 149
139 private LaunchClassLoader classLoader; 150 private LaunchClassLoader classLoader;
140 151
  152 + private final StartupEnvironment env;
  153 +
141 private final ITweaker tweaker; 154 private final ITweaker tweaker;
142 155
143 private final APIRegistry apiRegistry; 156 private final APIRegistry apiRegistry;
@@ -157,7 +170,7 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP @@ -157,7 +170,7 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
157 * List of mods passed into the command line 170 * List of mods passed into the command line
158 */ 171 */
159 private EnabledModsList enabledModsList; 172 private EnabledModsList enabledModsList;
160 - 173 +
161 /** 174 /**
162 * @param env 175 * @param env
163 * @param tweaker 176 * @param tweaker
@@ -165,6 +178,7 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP @@ -165,6 +178,7 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
165 public LiteLoaderBootstrap(StartupEnvironment env, ITweaker tweaker) 178 public LiteLoaderBootstrap(StartupEnvironment env, ITweaker tweaker)
166 { 179 {
167 this.environmentType = EnvironmentType.values()[env.getEnvironmentTypeId()]; 180 this.environmentType = EnvironmentType.values()[env.getEnvironmentTypeId()];
  181 + this.env = env;
168 this.tweaker = tweaker; 182 this.tweaker = tweaker;
169 183
170 this.apiRegistry = new APIRegistry(this.getEnvironment(), this.getProperties()); 184 this.apiRegistry = new APIRegistry(this.getEnvironment(), this.getProperties());
@@ -173,6 +187,7 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP @@ -173,6 +187,7 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
173 this.assetsDirectory = env.getAssetsDirectory(); 187 this.assetsDirectory = env.getAssetsDirectory();
174 this.profile = env.getProfile(); 188 this.profile = env.getProfile();
175 this.modsFolder = env.getModsFolder(); 189 this.modsFolder = env.getModsFolder();
  190 + this.repositoryFile = env.getModsRepoFile();
176 191
177 this.versionedModsFolder = new File(this.modsFolder, LiteLoaderVersion.CURRENT.getMinecraftVersion()); 192 this.versionedModsFolder = new File(this.modsFolder, LiteLoaderVersion.CURRENT.getMinecraftVersion());
178 this.configBaseFolder = new File(this.gameDirectory, "liteconfig"); 193 this.configBaseFolder = new File(this.gameDirectory, "liteconfig");
@@ -183,17 +198,27 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP @@ -183,17 +198,27 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
183 this.commonConfigFolder = new File(this.configBaseFolder, "common"); 198 this.commonConfigFolder = new File(this.configBaseFolder, "common");
184 this.versionConfigFolder = this.inflectVersionedConfigPath(LiteLoaderVersion.CURRENT); 199 this.versionConfigFolder = this.inflectVersionedConfigPath(LiteLoaderVersion.CURRENT);
185 200
186 - if (!this.modsFolder.exists()) this.modsFolder.mkdirs();  
187 - if (!this.versionedModsFolder.exists()) this.versionedModsFolder.mkdirs();  
188 - if (!this.configBaseFolder.exists()) this.configBaseFolder.mkdirs();  
189 - if (!this.commonConfigFolder.exists()) this.commonConfigFolder.mkdirs();  
190 - if (!this.versionConfigFolder.exists()) this.versionConfigFolder.mkdirs(); 201 + this.repository = new Repository(this.gameDirectory, this.versionedModsFolder);
  202 +
  203 + this.mkdir(this.modsFolder);
  204 + this.mkdir(this.versionedModsFolder);
  205 + this.mkdir(this.configBaseFolder);
  206 + this.mkdir(this.commonConfigFolder);
  207 + this.mkdir(this.versionConfigFolder);
191 208
192 this.initAPIs(env.getAPIsToLoad()); 209 this.initAPIs(env.getAPIsToLoad());
193 this.apiProvider = this.apiRegistry.getProvider(); 210 this.apiProvider = this.apiRegistry.getProvider();
194 this.apiAdapter = this.apiRegistry.getAdapter(); 211 this.apiAdapter = this.apiRegistry.getAdapter();
195 } 212 }
196 213
  214 + private void mkdir(File dir)
  215 + {
  216 + if (!dir.isDirectory())
  217 + {
  218 + dir.mkdirs();
  219 + }
  220 + }
  221 +
197 /** 222 /**
198 * @param version 223 * @param version
199 */ 224 */
@@ -249,6 +274,12 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP @@ -249,6 +274,12 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
249 { 274 {
250 return this.enabledModsList; 275 return this.enabledModsList;
251 } 276 }
  277 +
  278 + @Override
  279 + public Repository getModRepository()
  280 + {
  281 + return this.repository;
  282 + }
252 283
253 @Override 284 @Override
254 public LoaderEnumerator getEnumerator() 285 public LoaderEnumerator getEnumerator()
@@ -301,15 +332,20 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP @@ -301,15 +332,20 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
301 * #preInit(net.minecraft.launchwrapper.LaunchClassLoader, boolean) 332 * #preInit(net.minecraft.launchwrapper.LaunchClassLoader, boolean)
302 */ 333 */
303 @Override 334 @Override
304 - public void preInit(LaunchClassLoader classLoader, boolean loadTweaks, List<String> modsToLoad) 335 + public void preInit(LaunchClassLoader classLoader, boolean loadTweaks)
305 { 336 {
  337 + List<String> modsToLoad = this.env.getModFilterList();
  338 +
306 this.classLoader = classLoader; 339 this.classLoader = classLoader;
307 this.loadTweaks = loadTweaks; 340 this.loadTweaks = loadTweaks;
308 341
309 LiteLoaderLogger.info(Verbosity.REDUCED, "LiteLoader begin PREINIT..."); 342 LiteLoaderLogger.info(Verbosity.REDUCED, "LiteLoader begin PREINIT...");
310 343
311 // Set up the bootstrap 344 // Set up the bootstrap
312 - if (!this.prepare()) return; 345 + if (!this.prepare())
  346 + {
  347 + return;
  348 + }
313 349
314 LiteLoaderLogger.info(Verbosity.REDUCED, "LiteLoader %s starting up...", LiteLoaderVersion.CURRENT.getLoaderVersion()); 350 LiteLoaderLogger.info(Verbosity.REDUCED, "LiteLoader %s starting up...", LiteLoaderVersion.CURRENT.getLoaderVersion());
315 351
@@ -323,7 +359,7 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP @@ -323,7 +359,7 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
323 359
324 this.enabledModsList = EnabledModsList.createFrom(this.enabledModsFile); 360 this.enabledModsList = EnabledModsList.createFrom(this.enabledModsFile);
325 this.enabledModsList.processModsList(this.profile, modsToLoad); 361 this.enabledModsList.processModsList(this.profile, modsToLoad);
326 - 362 +
327 this.enumerator = this.spawnEnumerator(classLoader); 363 this.enumerator = this.spawnEnumerator(classLoader);
328 this.enumerator.onPreInit(); 364 this.enumerator.onPreInit();
329 365
@@ -599,6 +635,16 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP @@ -599,6 +635,16 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
599 { 635 {
600 return this.versionConfigFolder; 636 return this.versionConfigFolder;
601 } 637 }
  638 +
  639 + /**
  640 + * Get the path to a JSON file describing a mod repository layout, can be
  641 + * null if not defined
  642 + */
  643 + @Override
  644 + public String getModsRepoFile()
  645 + {
  646 + return this.repositoryFile;
  647 + }
602 648
603 /** 649 /**
604 * Get a boolean propery from the properties file and also write the new 650 * Get a boolean propery from the properties file and also write the new
src/main/java/com/mumfrey/liteloader/core/LiteLoaderEnumerator.java
@@ -122,7 +122,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -122,7 +122,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
122 private final FastIterableDeque<EnumerationObserver> observers = new HandlerList<EnumerationObserver>(EnumerationObserver.class); 122 private final FastIterableDeque<EnumerationObserver> observers = new HandlerList<EnumerationObserver>(EnumerationObserver.class);
123 123
124 protected EnumeratorState state = EnumeratorState.INIT; 124 protected EnumeratorState state = EnumeratorState.INIT;
125 - 125 +
126 /** 126 /**
127 * @param environment 127 * @param environment
128 * @param properties 128 * @param properties
@@ -144,7 +144,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -144,7 +144,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
144 // Initialise the shared mod list if we haven't already 144 // Initialise the shared mod list if we haven't already
145 this.getSharedModList(); 145 this.getSharedModList();
146 } 146 }
147 - 147 +
148 /** 148 /**
149 * @param environment 149 * @param environment
150 */ 150 */
@@ -397,11 +397,13 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -397,11 +397,13 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
397 { 397 {
398 this.gotoState(EnumeratorState.DISCOVER); 398 this.gotoState(EnumeratorState.DISCOVER);
399 399
  400 + String profile = this.environment.getProfile();
  401 +
400 for (EnumeratorModule module : this.modules) 402 for (EnumeratorModule module : this.modules)
401 { 403 {
402 try 404 try
403 { 405 {
404 - module.enumerate(this, this.environment.getProfile()); 406 + module.enumerate(this, profile);
405 } 407 }
406 catch (Throwable th) 408 catch (Throwable th)
407 { 409 {
@@ -409,6 +411,18 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -409,6 +411,18 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
409 } 411 }
410 } 412 }
411 413
  414 + for (EnumeratorModule module : this.modules)
  415 + {
  416 + try
  417 + {
  418 + module.register(this, profile);
  419 + }
  420 + catch (Throwable th)
  421 + {
  422 + LiteLoaderLogger.warning(th, "Enumerator Module %s encountered an error whilst enumerating", module.getClass().getName());
  423 + }
  424 + }
  425 +
412 this.checkDependencies(); 426 this.checkDependencies();
413 } 427 }
414 428
@@ -651,7 +665,15 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -651,7 +665,15 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
651 if (config.endsWith(".json")) 665 if (config.endsWith(".json"))
652 { 666 {
653 LiteLoaderLogger.info(Verbosity.REDUCED, "Registering mixin config %s for %s", config, container.getName()); 667 LiteLoaderLogger.info(Verbosity.REDUCED, "Registering mixin config %s for %s", config, container.getName());
654 - Mixins.addConfiguration(config); 668 + try
  669 + {
  670 + Mixins.addConfiguration(config);
  671 + }
  672 + catch (Throwable th)
  673 + {
  674 + LiteLoaderLogger.severe(th, "Error registering mixin config %s for %s", config, container);
  675 + container.registerMixinError(th);
  676 + }
655 } 677 }
656 else if (config.contains(".json@")) 678 else if (config.contains(".json@"))
657 { 679 {
src/main/java/com/mumfrey/liteloader/core/LiteLoaderMods.java
@@ -24,6 +24,7 @@ import com.mumfrey.liteloader.interfaces.FastIterableDeque; @@ -24,6 +24,7 @@ import com.mumfrey.liteloader.interfaces.FastIterableDeque;
24 import com.mumfrey.liteloader.interfaces.Loadable; 24 import com.mumfrey.liteloader.interfaces.Loadable;
25 import com.mumfrey.liteloader.interfaces.LoadableMod; 25 import com.mumfrey.liteloader.interfaces.LoadableMod;
26 import com.mumfrey.liteloader.interfaces.LoaderEnumerator; 26 import com.mumfrey.liteloader.interfaces.LoaderEnumerator;
  27 +import com.mumfrey.liteloader.interfaces.MixinContainer;
27 import com.mumfrey.liteloader.interfaces.TweakContainer; 28 import com.mumfrey.liteloader.interfaces.TweakContainer;
28 import com.mumfrey.liteloader.launch.ClassTransformerManager; 29 import com.mumfrey.liteloader.launch.ClassTransformerManager;
29 import com.mumfrey.liteloader.launch.LoaderEnvironment; 30 import com.mumfrey.liteloader.launch.LoaderEnvironment;
@@ -444,6 +445,12 @@ public class LiteLoaderMods @@ -444,6 +445,12 @@ public class LiteLoaderMods
444 String identifier = mod.getIdentifier(); 445 String identifier = mod.getIdentifier();
445 if (identifier == null || this.environment.getEnabledModsList().isEnabled(this.environment.getProfile(), identifier)) 446 if (identifier == null || this.environment.getEnabledModsList().isEnabled(this.environment.getProfile(), identifier))
446 { 447 {
  448 + if (!this.validateMixins(mod, container))
  449 + {
  450 + this.onModLoadFailed(container, identifier, "mixins for the specified mod encountered a startup error", null);
  451 + continue;
  452 + }
  453 +
447 if (!this.enumerator.checkDependencies(container)) 454 if (!this.enumerator.checkDependencies(container))
448 { 455 {
449 this.onModLoadFailed(container, identifier, "the mod was missing a required dependency", null); 456 this.onModLoadFailed(container, identifier, "the mod was missing a required dependency", null);
@@ -474,6 +481,23 @@ public class LiteLoaderMods @@ -474,6 +481,23 @@ public class LiteLoaderMods
474 this.observers.all().onPostModLoaded(mod); 481 this.observers.all().onPostModLoaded(mod);
475 } 482 }
476 } 483 }
  484 +
  485 + private boolean validateMixins(ModInfo<?> mod, LoadableMod<?> container)
  486 + {
  487 + if (container instanceof MixinContainer)
  488 + {
  489 + @SuppressWarnings("unchecked")
  490 + Collection<Throwable> errors = ((MixinContainer<File>)container).getMixinErrors();
  491 + for (Throwable error : errors)
  492 + {
  493 + this.registerModStartupError(mod, error, true);
  494 + }
  495 +
  496 + return errors.size() == 0;
  497 + }
  498 +
  499 + return true;
  500 + }
477 501
478 /** 502 /**
479 * @param identifier 503 * @param identifier
@@ -697,26 +721,28 @@ public class LiteLoaderMods @@ -697,26 +721,28 @@ public class LiteLoaderMods
697 721
698 for (Mod mod : this.loadedMods) 722 for (Mod mod : this.loadedMods)
699 { 723 {
700 - if (mod.hasClassTransformers()) 724 + if (!mod.hasClassTransformers())
701 { 725 {
702 - List<String> modTransformers = ((TweakContainer<?>)mod.getContainer()).getClassTransformerClassNames();  
703 - for (String modTransformer : modTransformers) 726 + continue;
  727 + }
  728 +
  729 + List<String> modTransformers = ((TweakContainer<?>)mod.getContainer()).getClassTransformerClassNames();
  730 + for (String modTransformer : modTransformers)
  731 + {
  732 + if (!injectedTransformers.contains(modTransformer))
704 { 733 {
705 - if (!injectedTransformers.contains(modTransformer)) 734 + List<Throwable> throwables = transformerManager.getTransformerStartupErrors(modTransformer);
  735 + if (throwables != null)
706 { 736 {
707 - List<Throwable> throwables = transformerManager.getTransformerStartupErrors(modTransformer);  
708 - if (throwables != null) 737 + for (Throwable th : throwables)
709 { 738 {
710 - for (Throwable th : throwables)  
711 - {  
712 - this.registerModStartupError(mod, th, true);  
713 - }  
714 - }  
715 - else  
716 - {  
717 - this.registerModStartupError(mod, new RuntimeException("Missing class transformer " + modTransformer), true); 739 + this.registerModStartupError(mod, th, true);
718 } 740 }
719 } 741 }
  742 + else
  743 + {
  744 + this.registerModStartupError(mod, new RuntimeException("Missing class transformer " + modTransformer), true);
  745 + }
720 } 746 }
721 } 747 }
722 } 748 }
@@ -765,7 +791,11 @@ public class LiteLoaderMods @@ -765,7 +791,11 @@ public class LiteLoaderMods
765 private void registerModStartupError(ModInfo<?> mod, Throwable th, boolean critical) 791 private void registerModStartupError(ModInfo<?> mod, Throwable th, boolean critical)
766 { 792 {
767 this.startupErrorCount++; 793 this.startupErrorCount++;
768 - if (critical) this.criticalErrorCount++; 794 + if (critical)
  795 + {
  796 + this.criticalErrorCount++;
  797 + }
  798 +
769 mod.registerStartupError(th); 799 mod.registerStartupError(th);
770 800
771 if (!this.loadedMods.contains(mod) && !this.disabledMods.contains(mod)) 801 if (!this.loadedMods.contains(mod) && !this.disabledMods.contains(mod))
src/main/java/com/mumfrey/liteloader/core/api/EnumeratorModuleClassPath.java
@@ -82,37 +82,43 @@ public class EnumeratorModuleClassPath implements EnumeratorModule @@ -82,37 +82,43 @@ public class EnumeratorModuleClassPath implements EnumeratorModule
82 @Override 82 @Override
83 public void enumerate(ModularEnumerator enumerator, String profile) 83 public void enumerate(ModularEnumerator enumerator, String profile)
84 { 84 {
85 - if (this.loadTweaks) 85 + }
  86 +
  87 + @Override
  88 + public void register(ModularEnumerator enumerator, String profile)
  89 + {
  90 + if (!this.loadTweaks)
86 { 91 {
87 - LiteLoaderLogger.info("Discovering tweaks on class path...");  
88 -  
89 - for (String classPathPart : this.classPathEntries) 92 + return;
  93 + }
  94 +
  95 + LiteLoaderLogger.info("Discovering tweaks on class path...");
  96 + for (String classPathPart : this.classPathEntries)
  97 + {
  98 + try
90 { 99 {
91 - try 100 + File packagePath = new File(classPathPart);
  101 + if (packagePath.exists())
92 { 102 {
93 - File packagePath = new File(classPathPart);  
94 - if (packagePath.exists()) 103 + LoadableModClassPath classPathMod = new LoadableModClassPath(packagePath);
  104 + if (enumerator.registerModContainer(classPathMod))
95 { 105 {
96 - LoadableModClassPath classPathMod = new LoadableModClassPath(packagePath);  
97 - if (enumerator.registerModContainer(classPathMod)) 106 + this.loadableMods.add(classPathMod);
  107 + if (classPathMod.requiresPreInitInjection())
98 { 108 {
99 - this.loadableMods.add(classPathMod);  
100 - if (classPathMod.requiresPreInitInjection())  
101 - {  
102 - enumerator.registerTweakContainer(classPathMod);  
103 - }  
104 - }  
105 - else  
106 - {  
107 - LiteLoaderLogger.info(Verbosity.REDUCED, "Mod %s is disabled or missing a required dependency, not injecting tranformers",  
108 - classPathMod.getIdentifier()); 109 + enumerator.registerTweakContainer(classPathMod);
109 } 110 }
110 } 111 }
  112 + else
  113 + {
  114 + LiteLoaderLogger.info(Verbosity.REDUCED, "Mod %s is disabled or missing a required dependency, not injecting tranformers",
  115 + classPathMod.getIdentifier());
  116 + }
111 } 117 }
112 - catch (Throwable th)  
113 - {  
114 - LiteLoaderLogger.warning(th, "Error encountered whilst inspecting %s", classPathPart);  
115 - } 118 + }
  119 + catch (Throwable th)
  120 + {
  121 + LiteLoaderLogger.warning(th, "Error encountered whilst inspecting %s", classPathPart);
116 } 122 }
117 } 123 }
118 } 124 }
src/main/java/com/mumfrey/liteloader/core/api/EnumeratorModuleFiles.java 0 โ†’ 100644
  1 +/*
  2 + * This file is part of LiteLoader.
  3 + * Copyright (C) 2012-16 Adam Mummery-Smith
  4 + * All Rights Reserved.
  5 + */
  6 +package com.mumfrey.liteloader.core.api;
  7 +
  8 +import java.io.File;
  9 +import java.io.FilenameFilter;
  10 +import java.net.MalformedURLException;
  11 +import java.util.ArrayList;
  12 +import java.util.Iterator;
  13 +import java.util.LinkedHashMap;
  14 +import java.util.List;
  15 +import java.util.Map;
  16 +import java.util.Set;
  17 +import java.util.TreeSet;
  18 +
  19 +import com.google.common.base.Charsets;
  20 +import com.mumfrey.liteloader.api.EnumeratorModule;
  21 +import com.mumfrey.liteloader.common.LoadingProgress;
  22 +import com.mumfrey.liteloader.core.LiteLoaderVersion;
  23 +import com.mumfrey.liteloader.core.api.EnumeratorModuleFiles.ContainerEnvironment.Candidate;
  24 +import com.mumfrey.liteloader.interfaces.LoadableFile;
  25 +import com.mumfrey.liteloader.interfaces.LoadableMod;
  26 +import com.mumfrey.liteloader.interfaces.ModularEnumerator;
  27 +import com.mumfrey.liteloader.interfaces.TweakContainer;
  28 +import com.mumfrey.liteloader.launch.LoaderEnvironment;
  29 +import com.mumfrey.liteloader.launch.LoaderProperties;
  30 +import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
  31 +import com.mumfrey.liteloader.util.log.LiteLoaderLogger.Verbosity;
  32 +
  33 +import net.minecraft.launchwrapper.LaunchClassLoader;
  34 +
  35 +public abstract class EnumeratorModuleFiles implements FilenameFilter, EnumeratorModule
  36 +{
  37 + public static class ContainerEnvironment implements Iterable<ContainerEnvironment.Candidate>
  38 + {
  39 + static class Candidate
  40 + {
  41 + private final Set<LoadableMod<File>> availableFiles = new TreeSet<LoadableMod<File>>();
  42 +
  43 + private boolean isRegistered;
  44 +
  45 + public void add(LoadableMod<File> modFile)
  46 + {
  47 + if (!this.isRegistered)
  48 + {
  49 + this.availableFiles.add(modFile);
  50 + }
  51 + }
  52 +
  53 + public LoadableMod<File> getNewestVersion()
  54 + {
  55 + return this.availableFiles.iterator().next();
  56 + }
  57 +
  58 + public boolean isRegistered()
  59 + {
  60 + return this.isRegistered;
  61 + }
  62 +
  63 + public void register()
  64 + {
  65 + this.isRegistered = true;
  66 + }
  67 + }
  68 +
  69 + /**
  70 + * Ordered sets used to sort mods by version/revision
  71 + */
  72 + private final Map<String, Candidate> orderedCandidates = new LinkedHashMap<String, Candidate>();
  73 +
  74 + public void addCandidate(LoadableMod<File> modFile)
  75 + {
  76 + if (!this.orderedCandidates.containsKey(modFile.getModName()))
  77 + {
  78 + this.orderedCandidates.put(modFile.getModName(), new Candidate());
  79 + }
  80 +
  81 + LiteLoaderLogger.info("Considering valid mod file: %s", modFile);
  82 + this.orderedCandidates.get(modFile.getModName()).add(modFile);
  83 + }
  84 +
  85 + @Override
  86 + public Iterator<Candidate> iterator()
  87 + {
  88 + return this.orderedCandidates.values().iterator();
  89 + }
  90 + }
  91 +
  92 + /**
  93 + * Ordered sets used to sort mods by version/revision
  94 + */
  95 + private final ContainerEnvironment containers;
  96 +
  97 + /**
  98 + * Mods to add once init is completed
  99 + */
  100 + private final List<LoadableMod<File>> loadableMods = new ArrayList<LoadableMod<File>>();
  101 +
  102 + protected final LiteLoaderCoreAPI api;
  103 +
  104 + public EnumeratorModuleFiles(LiteLoaderCoreAPI api, ContainerEnvironment containers)
  105 + {
  106 + this.api = api;
  107 + this.containers = containers;
  108 + }
  109 +
  110 + protected abstract boolean readJarFiles();
  111 +
  112 + protected abstract boolean loadTweakJars();
  113 +
  114 + protected abstract boolean loadTweaks();
  115 +
  116 + protected abstract boolean forceInjection();
  117 +
  118 + protected abstract File[] getFiles();
  119 +
  120 + @Override
  121 + public void init(LoaderEnvironment environment, LoaderProperties properties)
  122 + {
  123 + }
  124 +
  125 + /**
  126 + * Write settings
  127 + */
  128 + @Override
  129 + public void writeSettings(LoaderEnvironment environment, LoaderProperties properties)
  130 + {
  131 + }
  132 +
  133 + /* (non-Javadoc)
  134 + * @see com.mumfrey.liteloader.core.Enumerator#getLoadableMods()
  135 + */
  136 + public List<LoadableMod<File>> getLoadableMods()
  137 + {
  138 + return this.loadableMods;
  139 + }
  140 +
  141 + /**
  142 + * For FilenameFilter interface
  143 + *
  144 + * @see java.io.FilenameFilter#accept(java.io.File, java.lang.String)
  145 + */
  146 + @Override
  147 + public boolean accept(File dir, String fileName)
  148 + {
  149 + fileName = fileName.toLowerCase();
  150 +
  151 + if (fileName.endsWith(".litemod.zip"))
  152 + {
  153 + LiteLoaderLogger.warning("Found %s with unsupported extension .litemod.zip."
  154 + + " Please change file extension to .litemod to allow this file to be loaded!", fileName);
  155 + return true;
  156 + }
  157 +
  158 + return fileName.endsWith(".litemod") || fileName.endsWith(".jar");
  159 + }
  160 +
  161 + /**
  162 + * Search the folder for (potentially) valid files
  163 + */
  164 + protected void findValidFiles(ModularEnumerator enumerator)
  165 + {
  166 + for (File file : this.getFiles())
  167 + {
  168 + LoadableFile candidateFile = new LoadableFile(file);
  169 + candidateFile.setForceInjection(this.forceInjection());
  170 + try
  171 + {
  172 + this.inspectFile(enumerator, candidateFile);
  173 + }
  174 + catch (Exception ex)
  175 + {
  176 + LiteLoaderLogger.warning(ex, "An error occurred whilst inspecting %s", candidateFile);
  177 + }
  178 + }
  179 + }
  180 +
  181 + /**
  182 + * Check whether a particular file is valid, and add it to the candiates
  183 + * list if it appears to be acceptable.
  184 + *
  185 + * @param enumerator
  186 + * @param candidateFile
  187 + */
  188 + protected void inspectFile(ModularEnumerator enumerator, LoadableFile candidateFile)
  189 + {
  190 + if (this.isValidFile(enumerator, candidateFile))
  191 + {
  192 + String metaData = candidateFile.getFileContents(LoadableMod.METADATA_FILENAME, Charsets.UTF_8);
  193 + if (metaData != null)
  194 + {
  195 + LoadableMod<File> modFile = this.getModFile(candidateFile, metaData);
  196 + this.addModFile(enumerator, modFile);
  197 + return;
  198 + }
  199 + else if (this.isValidTweakContainer(candidateFile))
  200 + {
  201 + TweakContainer<File> container = this.getTweakFile(candidateFile);
  202 + this.addTweakFile(enumerator, container);
  203 + return;
  204 + }
  205 + else
  206 + {
  207 + LiteLoaderLogger.info("Ignoring %s", candidateFile);
  208 +// enumerator.registerBadContainer(candidateFile, "No metadata");
  209 + }
  210 + }
  211 +// else
  212 +// {
  213 +// enumerator.registerBadContainer(candidateFile, "Not a valid file");
  214 +// }
  215 + }
  216 +
  217 + /**
  218 + * Check whether the specified file is a valid mod container
  219 + *
  220 + * @param enumerator
  221 + * @param candidateFile
  222 + */
  223 + protected boolean isValidFile(ModularEnumerator enumerator, LoadableFile candidateFile)
  224 + {
  225 + String filename = candidateFile.getName().toLowerCase();
  226 + if (filename.endsWith(".litemod.zip"))
  227 + {
  228 + enumerator.registerBadContainer(candidateFile, "Invalid file extension .litemod.zip");
  229 + return false;
  230 + }
  231 + else if (filename.endsWith(".litemod"))
  232 + {
  233 + return true;
  234 + }
  235 + else if (filename.endsWith(".jar"))
  236 + {
  237 + Set<String> modSystems = candidateFile.getModSystems();
  238 + boolean hasLiteLoader = modSystems.contains("LiteLoader");
  239 + if (modSystems.size() > 0)
  240 + {
  241 + LiteLoaderLogger.info("%s supports mod systems %s", candidateFile, modSystems);
  242 + if (!hasLiteLoader) return false;
  243 + }
  244 +
  245 + return this.loadTweakJars() || this.readJarFiles() || hasLiteLoader;
  246 + }
  247 +
  248 + return false;
  249 + }
  250 +
  251 + /**
  252 + * Called only if the file is not a valid mod container (has no mod
  253 + * metadata) to check whether it could instead be a potential tweak
  254 + * container.
  255 + *
  256 + * @param candidateFile
  257 + */
  258 + protected boolean isValidTweakContainer(LoadableFile candidateFile)
  259 + {
  260 + return this.loadTweakJars() && this.loadTweaks() && candidateFile.getName().toLowerCase().endsWith(".jar");
  261 + }
  262 +
  263 + /**
  264 + * Get the {@link FilenameFilter} to use to filter candidate files
  265 + */
  266 + protected FilenameFilter getFilenameFilter()
  267 + {
  268 + return this;
  269 + }
  270 +
  271 + /**
  272 + * @param modFile
  273 + */
  274 + protected boolean isFileSupported(LoadableMod<File> modFile)
  275 + {
  276 + return LiteLoaderVersion.CURRENT.isVersionSupported(modFile.getTargetVersion());
  277 + }
  278 +
  279 + /**
  280 + * @param candidateFile
  281 + * @param metaData
  282 + */
  283 + protected LoadableMod<File> getModFile(LoadableFile candidateFile, String metaData)
  284 + {
  285 + return new LoadableModFile(candidateFile, metaData);
  286 + }
  287 +
  288 + /**
  289 + * @param candidateFile
  290 + */
  291 + protected TweakContainer<File> getTweakFile(LoadableFile candidateFile)
  292 + {
  293 + return candidateFile;
  294 + }
  295 +
  296 + /**
  297 + * @param enumerator
  298 + * @param modFile
  299 + */
  300 + protected void addModFile(ModularEnumerator enumerator, LoadableMod<File> modFile)
  301 + {
  302 + if (modFile.hasValidMetaData())
  303 + {
  304 + // Only add the mod if the version matches, we add candidates to the versionOrderingSets in
  305 + // order to determine the most recent version available.
  306 + if (this.isFileSupported(modFile))
  307 + {
  308 + this.containers.addCandidate(modFile);
  309 + }
  310 + else
  311 + {
  312 + LiteLoaderLogger.info(Verbosity.REDUCED, "Not adding invalid or version-mismatched mod file: %s", modFile);
  313 + enumerator.registerBadContainer(modFile, "Version not supported");
  314 + }
  315 + }
  316 + }
  317 +
  318 + /**
  319 + * @param enumerator
  320 + * @param container
  321 + */
  322 + protected void addTweakFile(ModularEnumerator enumerator, TweakContainer<File> container)
  323 + {
  324 + enumerator.registerTweakContainer(container);
  325 + }
  326 +
  327 + /**
  328 + * @param enumerator
  329 + */
  330 + protected void sortAndRegisterFiles(ModularEnumerator enumerator)
  331 + {
  332 + // Copy the first entry in every version set into the modfiles list
  333 + for (Candidate candidate : this.containers)
  334 + {
  335 + if (candidate.isRegistered())
  336 + {
  337 + continue;
  338 + }
  339 +
  340 + LoadableMod<File> newestVersion = candidate.getNewestVersion();
  341 + this.registerFile(enumerator, newestVersion);
  342 + candidate.register();
  343 + }
  344 + }
  345 +
  346 + /**
  347 + * @param enumerator
  348 + * @param modFile
  349 + */
  350 + @SuppressWarnings("unchecked")
  351 + protected void registerFile(ModularEnumerator enumerator, LoadableMod<File> modFile)
  352 + {
  353 + if (enumerator.registerModContainer(modFile))
  354 + {
  355 + LiteLoaderLogger.info(Verbosity.REDUCED, "Adding newest valid mod file '%s' at revision %.4f", modFile, modFile.getRevision());
  356 + this.loadableMods.add(modFile);
  357 + }
  358 + else
  359 + {
  360 + LiteLoaderLogger.info(Verbosity.REDUCED, "Not adding valid mod file '%s', the specified mod is disabled or missing a required dependency",
  361 + modFile);
  362 + }
  363 +
  364 + if (this.loadTweaks())
  365 + {
  366 + try
  367 + {
  368 + if (modFile instanceof TweakContainer)
  369 + {
  370 + this.addTweakFile(enumerator, (TweakContainer<File>)modFile);
  371 + }
  372 + }
  373 + catch (Throwable th)
  374 + {
  375 + LiteLoaderLogger.warning("Error adding tweaks from '%s'", modFile);
  376 + }
  377 + }
  378 + }
  379 +
  380 + @Override
  381 + public void injectIntoClassLoader(ModularEnumerator enumerator, LaunchClassLoader classLoader)
  382 + {
  383 + LiteLoaderLogger.info("Injecting external mods into class path...");
  384 +
  385 + for (LoadableMod<?> loadableMod : this.loadableMods)
  386 + {
  387 + try
  388 + {
  389 + if (loadableMod.injectIntoClassPath(classLoader, false))
  390 + {
  391 + LiteLoaderLogger.info("Successfully injected mod file '%s' into classpath", loadableMod);
  392 + }
  393 + }
  394 + catch (MalformedURLException ex)
  395 + {
  396 + LiteLoaderLogger.warning("Error injecting '%s' into classPath. The mod will not be loaded", loadableMod);
  397 + }
  398 + }
  399 + }
  400 +
  401 + @Override
  402 + public void registerMods(ModularEnumerator enumerator, LaunchClassLoader classLoader)
  403 + {
  404 + LiteLoaderLogger.info(Verbosity.REDUCED, "Discovering mods in valid mod files...");
  405 + LoadingProgress.incTotalLiteLoaderProgress(this.loadableMods.size());
  406 +
  407 + for (LoadableMod<?> modFile : this.loadableMods)
  408 + {
  409 + LoadingProgress.incLiteLoaderProgress("Searching for mods in " + modFile.getModName() + "...");
  410 + LiteLoaderLogger.info("Searching %s...", modFile);
  411 + try
  412 + {
  413 + enumerator.registerModsFrom(modFile, true);
  414 + }
  415 + catch (Exception ex)
  416 + {
  417 + LiteLoaderLogger.warning("Error encountered whilst searching in %s...", modFile);
  418 + }
  419 + }
  420 + }
  421 +}
src/main/java/com/mumfrey/liteloader/core/api/EnumeratorModuleFolder.java
@@ -6,50 +6,19 @@ @@ -6,50 +6,19 @@
6 package com.mumfrey.liteloader.core.api; 6 package com.mumfrey.liteloader.core.api;
7 7
8 import java.io.File; 8 import java.io.File;
9 -import java.io.FilenameFilter;  
10 -import java.net.MalformedURLException;  
11 -import java.util.ArrayList;  
12 -import java.util.HashMap;  
13 -import java.util.List;  
14 -import java.util.Map;  
15 -import java.util.Map.Entry;  
16 -import java.util.Set;  
17 -import java.util.TreeSet;  
18 9
19 -import com.google.common.base.Charsets;  
20 -import com.mumfrey.liteloader.api.EnumeratorModule;  
21 -import com.mumfrey.liteloader.common.LoadingProgress;  
22 -import com.mumfrey.liteloader.core.LiteLoaderVersion;  
23 -import com.mumfrey.liteloader.interfaces.LoadableFile;  
24 -import com.mumfrey.liteloader.interfaces.LoadableMod;  
25 import com.mumfrey.liteloader.interfaces.ModularEnumerator; 10 import com.mumfrey.liteloader.interfaces.ModularEnumerator;
26 -import com.mumfrey.liteloader.interfaces.TweakContainer;  
27 import com.mumfrey.liteloader.launch.LoaderEnvironment; 11 import com.mumfrey.liteloader.launch.LoaderEnvironment;
28 import com.mumfrey.liteloader.launch.LoaderProperties; 12 import com.mumfrey.liteloader.launch.LoaderProperties;
29 import com.mumfrey.liteloader.util.log.LiteLoaderLogger; 13 import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
30 -import com.mumfrey.liteloader.util.log.LiteLoaderLogger.Verbosity;  
31 -  
32 -import net.minecraft.launchwrapper.LaunchClassLoader;  
33 14
34 /** 15 /**
35 * Enumerator module which searches for mods and tweaks in a folder 16 * Enumerator module which searches for mods and tweaks in a folder
36 * 17 *
37 * @author Adam Mummery-Smith 18 * @author Adam Mummery-Smith
38 */ 19 */
39 -public class EnumeratorModuleFolder implements FilenameFilter, EnumeratorModule 20 +public class EnumeratorModuleFolder extends EnumeratorModuleFiles
40 { 21 {
41 - /**  
42 - * Ordered sets used to sort mods by version/revision  
43 - */  
44 - protected final Map<String, TreeSet<LoadableMod<File>>> versionOrderingSets = new HashMap<String, TreeSet<LoadableMod<File>>>();  
45 -  
46 - /**  
47 - * Mods to add once init is completed  
48 - */  
49 - protected final List<LoadableMod<File>> loadableMods = new ArrayList<LoadableMod<File>>();  
50 -  
51 - protected LiteLoaderCoreAPI coreAPI;  
52 -  
53 protected File directory; 22 protected File directory;
54 23
55 protected boolean readJarFiles; 24 protected boolean readJarFiles;
@@ -62,13 +31,13 @@ public class EnumeratorModuleFolder implements FilenameFilter, EnumeratorModule @@ -62,13 +31,13 @@ public class EnumeratorModuleFolder implements FilenameFilter, EnumeratorModule
62 */ 31 */
63 protected final boolean loadTweakJars; 32 protected final boolean loadTweakJars;
64 33
65 - public EnumeratorModuleFolder(LiteLoaderCoreAPI coreAPI, File directory, boolean loadTweakJars) 34 + public EnumeratorModuleFolder(LiteLoaderCoreAPI api, ContainerEnvironment containers, File directory, boolean loadTweakJars)
66 { 35 {
67 - this.coreAPI = coreAPI;  
68 - this.directory = directory;  
69 - this.loadTweakJars = loadTweakJars; 36 + super(api, containers);
  37 + this.directory = directory;
  38 + this.loadTweakJars = loadTweakJars;
70 } 39 }
71 - 40 +
72 @Override 41 @Override
73 public void init(LoaderEnvironment environment, LoaderProperties properties) 42 public void init(LoaderEnvironment environment, LoaderProperties properties)
74 { 43 {
@@ -76,7 +45,7 @@ public class EnumeratorModuleFolder implements FilenameFilter, EnumeratorModule @@ -76,7 +45,7 @@ public class EnumeratorModuleFolder implements FilenameFilter, EnumeratorModule
76 this.readJarFiles = properties.getAndStoreBooleanProperty(LoaderProperties.OPTION_SEARCH_JARFILES, true); 45 this.readJarFiles = properties.getAndStoreBooleanProperty(LoaderProperties.OPTION_SEARCH_JARFILES, true);
77 this.forceInjection = properties.getAndStoreBooleanProperty(LoaderProperties.OPTION_FORCE_INJECTION, false); 46 this.forceInjection = properties.getAndStoreBooleanProperty(LoaderProperties.OPTION_FORCE_INJECTION, false);
78 47
79 - this.coreAPI.writeDiscoverySettings(); 48 + this.api.writeDiscoverySettings();
80 } 49 }
81 50
82 /** 51 /**
@@ -88,6 +57,36 @@ public class EnumeratorModuleFolder implements FilenameFilter, EnumeratorModule @@ -88,6 +57,36 @@ public class EnumeratorModuleFolder implements FilenameFilter, EnumeratorModule
88 properties.setBooleanProperty(LoaderProperties.OPTION_SEARCH_JARFILES, this.readJarFiles); 57 properties.setBooleanProperty(LoaderProperties.OPTION_SEARCH_JARFILES, this.readJarFiles);
89 properties.setBooleanProperty(LoaderProperties.OPTION_FORCE_INJECTION, this.forceInjection); 58 properties.setBooleanProperty(LoaderProperties.OPTION_FORCE_INJECTION, this.forceInjection);
90 } 59 }
  60 +
  61 + @Override
  62 + protected boolean forceInjection()
  63 + {
  64 + return this.forceInjection;
  65 + }
  66 +
  67 + @Override
  68 + protected boolean loadTweakJars()
  69 + {
  70 + return this.loadTweakJars;
  71 + }
  72 +
  73 + @Override
  74 + protected boolean loadTweaks()
  75 + {
  76 + return this.loadTweaks;
  77 + }
  78 +
  79 + @Override
  80 + protected boolean readJarFiles()
  81 + {
  82 + return this.readJarFiles;
  83 + }
  84 +
  85 + @Override
  86 + protected File[] getFiles()
  87 + {
  88 + return this.directory.listFiles(this.getFilenameFilter());
  89 + }
91 90
92 /* (non-Javadoc) 91 /* (non-Javadoc)
93 * @see java.lang.Object#toString() 92 * @see java.lang.Object#toString()
@@ -107,34 +106,6 @@ public class EnumeratorModuleFolder implements FilenameFilter, EnumeratorModule @@ -107,34 +106,6 @@ public class EnumeratorModuleFolder implements FilenameFilter, EnumeratorModule
107 } 106 }
108 107
109 /* (non-Javadoc) 108 /* (non-Javadoc)
110 - * @see com.mumfrey.liteloader.core.Enumerator#getLoadableMods()  
111 - */  
112 - public List<LoadableMod<File>> getLoadableMods()  
113 - {  
114 - return this.loadableMods;  
115 - }  
116 -  
117 - /**  
118 - * For FilenameFilter interface  
119 - *  
120 - * @see java.io.FilenameFilter#accept(java.io.File, java.lang.String)  
121 - */  
122 - @Override  
123 - public boolean accept(File dir, String fileName)  
124 - {  
125 - fileName = fileName.toLowerCase();  
126 -  
127 - if (fileName.endsWith(".litemod.zip"))  
128 - {  
129 - LiteLoaderLogger.warning("Found %s with unsupported extension .litemod.zip."  
130 - + " Please change file extension to .litemod to allow this file to be loaded!", fileName);  
131 - return true;  
132 - }  
133 -  
134 - return fileName.endsWith(".litemod") || fileName.endsWith(".jar");  
135 - }  
136 -  
137 - /* (non-Javadoc)  
138 * @see com.mumfrey.liteloader.core.Enumerator 109 * @see com.mumfrey.liteloader.core.Enumerator
139 * #enumerate(com.mumfrey.liteloader.core.EnabledModsList, 110 * #enumerate(com.mumfrey.liteloader.core.EnabledModsList,
140 * java.lang.String) 111 * java.lang.String)
@@ -145,272 +116,22 @@ public class EnumeratorModuleFolder implements FilenameFilter, EnumeratorModule @@ -145,272 +116,22 @@ public class EnumeratorModuleFolder implements FilenameFilter, EnumeratorModule
145 if (this.directory.exists() && this.directory.isDirectory()) 116 if (this.directory.exists() && this.directory.isDirectory())
146 { 117 {
147 LiteLoaderLogger.info("Discovering valid mod files in folder %s", this.directory.getPath()); 118 LiteLoaderLogger.info("Discovering valid mod files in folder %s", this.directory.getPath());
148 -  
149 this.findValidFiles(enumerator); 119 this.findValidFiles(enumerator);
150 - this.sortAndRegisterFiles(enumerator);  
151 - }  
152 - }  
153 -  
154 - /**  
155 - * Search the folder for (potentially) valid files  
156 - */  
157 - private void findValidFiles(ModularEnumerator enumerator)  
158 - {  
159 - for (File file : this.directory.listFiles(this.getFilenameFilter()))  
160 - {  
161 - LoadableFile candidateFile = new LoadableFile(file);  
162 - candidateFile.setForceInjection(this.forceInjection);  
163 - try  
164 - {  
165 - this.inspectFile(enumerator, candidateFile);  
166 - }  
167 - catch (Exception ex)  
168 - {  
169 - LiteLoaderLogger.warning(ex, "An error occurred whilst inspecting %s", candidateFile);  
170 - }  
171 } 120 }
172 } 121 }
173 -  
174 - /**  
175 - * Check whether a particular file is valid, and add it to the candiates  
176 - * list if it appears to be acceptable.  
177 - *  
178 - * @param enumerator  
179 - * @param candidateFile  
180 - */  
181 - protected void inspectFile(ModularEnumerator enumerator, LoadableFile candidateFile)  
182 - {  
183 - if (this.isValidFile(enumerator, candidateFile))  
184 - {  
185 - String metaData = candidateFile.getFileContents(LoadableMod.METADATA_FILENAME, Charsets.UTF_8);  
186 - if (metaData != null)  
187 - {  
188 - LoadableMod<File> modFile = this.getModFile(candidateFile, metaData);  
189 - this.addModFile(enumerator, modFile);  
190 - return;  
191 - }  
192 - else if (this.isValidTweakContainer(candidateFile))  
193 - {  
194 - TweakContainer<File> container = this.getTweakFile(candidateFile);  
195 - this.addTweakFile(enumerator, container);  
196 - return;  
197 - }  
198 - else  
199 - {  
200 - LiteLoaderLogger.info("Ignoring %s", candidateFile);  
201 -// enumerator.registerBadContainer(candidateFile, "No metadata");  
202 - }  
203 - }  
204 -// else  
205 -// {  
206 -// enumerator.registerBadContainer(candidateFile, "Not a valid file");  
207 -// }  
208 - }  
209 -  
210 - /**  
211 - * Check whether the specified file is a valid mod container  
212 - *  
213 - * @param enumerator  
214 - * @param candidateFile  
215 - */  
216 - protected boolean isValidFile(ModularEnumerator enumerator, LoadableFile candidateFile)  
217 - {  
218 - String filename = candidateFile.getName().toLowerCase();  
219 - if (filename.endsWith(".litemod.zip"))  
220 - {  
221 - enumerator.registerBadContainer(candidateFile, "Invalid file extension .litemod.zip");  
222 - return false;  
223 - }  
224 - else if (filename.endsWith(".litemod"))  
225 - {  
226 - return true;  
227 - }  
228 - else if (filename.endsWith(".jar"))  
229 - {  
230 - Set<String> modSystems = candidateFile.getModSystems();  
231 - boolean hasLiteLoader = modSystems.contains("LiteLoader");  
232 - if (modSystems.size() > 0)  
233 - {  
234 - LiteLoaderLogger.info("%s supports mod systems %s", candidateFile, modSystems);  
235 - if (!hasLiteLoader) return false;  
236 - }  
237 -  
238 - return this.loadTweakJars || this.readJarFiles || hasLiteLoader;  
239 - }  
240 -  
241 - return false;  
242 - }  
243 -  
244 - /**  
245 - * Called only if the file is not a valid mod container (has no mod  
246 - * metadata) to check whether it could instead be a potential tweak  
247 - * container.  
248 - *  
249 - * @param candidateFile  
250 - */  
251 - protected boolean isValidTweakContainer(LoadableFile candidateFile)  
252 - {  
253 - return this.loadTweakJars && this.loadTweaks && candidateFile.getName().toLowerCase().endsWith(".jar");  
254 - }  
255 -  
256 - /**  
257 - * Get the {@link FilenameFilter} to use to filter candidate files  
258 - */  
259 - protected FilenameFilter getFilenameFilter()  
260 - {  
261 - return this;  
262 - }  
263 -  
264 - /**  
265 - * @param modFile  
266 - */  
267 - protected boolean isFileSupported(LoadableMod<File> modFile)  
268 - {  
269 - return LiteLoaderVersion.CURRENT.isVersionSupported(modFile.getTargetVersion());  
270 - }  
271 -  
272 - /**  
273 - * @param candidateFile  
274 - * @param metaData  
275 - */  
276 - protected LoadableMod<File> getModFile(LoadableFile candidateFile, String metaData)  
277 - {  
278 - return new LoadableModFile(candidateFile, metaData);  
279 - }  
280 -  
281 - /**  
282 - * @param candidateFile  
283 - */  
284 - protected TweakContainer<File> getTweakFile(LoadableFile candidateFile)  
285 - {  
286 - return candidateFile;  
287 - }  
288 -  
289 - /**  
290 - * @param enumerator  
291 - * @param modFile  
292 - */  
293 - protected void addModFile(ModularEnumerator enumerator, LoadableMod<File> modFile)  
294 - {  
295 - if (modFile.hasValidMetaData())  
296 - {  
297 - // Only add the mod if the version matches, we add candidates to the versionOrderingSets in  
298 - // order to determine the most recent version available.  
299 - if (this.isFileSupported(modFile))  
300 - {  
301 - if (!this.versionOrderingSets.containsKey(modFile.getName()))  
302 - {  
303 - this.versionOrderingSets.put(modFile.getModName(), new TreeSet<LoadableMod<File>>());  
304 - }  
305 -  
306 - LiteLoaderLogger.info("Considering valid mod file: %s", modFile);  
307 - this.versionOrderingSets.get(modFil