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 72 }
73 73  
74 74 dependencies {
75   - compile('org.spongepowered:mixin:0.7.1-SNAPSHOT') {
  75 + compile('org.spongepowered:mixin:0.7.3-SNAPSHOT') {
76 76 exclude module: 'asm-commons'
77 77 exclude module: 'asm-tree'
78 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 290 if (logLine.startsWith("tweakClass '")) return 0x5555FF;
291 291 if (logLine.startsWith("baking listener list")) return 0x00AAAA;
292 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 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 105 /**
106 106 * Base for config option handle structs
107 107 */
108   - static abstract class ConfigOption
  108 + abstract static class ConfigOption
109 109 {
110 110 void onTick()
111 111 {
... ... @@ -303,7 +303,7 @@ public abstract class AbstractConfigPanel implements ConfigPanel
303 303 @Override
304 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 307 return this;
308 308 }
309 309  
... ... @@ -343,7 +343,8 @@ public abstract class AbstractConfigPanel implements ConfigPanel
343 343 }
344 344 else
345 345 {
346   - this.setValidator((text) -> {
  346 + this.setValidator((text) ->
  347 + {
347 348 this.validate(text);
348 349 return true;
349 350 });
... ...
src/main/java/com/mumfrey/liteloader/api/EnumeratorModule.java
... ... @@ -36,10 +36,7 @@ public interface EnumeratorModule
36 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 41 * <p>This method is called during loader PREINIT phase so <b>do not use any
45 42 * game classes here</b>!</p>
... ... @@ -48,6 +45,20 @@ public interface EnumeratorModule
48 45 * @param profile
49 46 */
50 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 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 8 import java.io.File;
9 9 import java.io.FileReader;
10 10 import java.io.FileWriter;
11   -import java.io.IOException;
12 11 import java.util.List;
13 12 import java.util.Map;
14 13 import java.util.TreeMap;
... ... @@ -186,12 +185,9 @@ public final class EnabledModsList
186 185 {
187 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 191 instance.setEnabledModsFile(file);
196 192 return instance;
197 193 }
... ... @@ -199,20 +195,6 @@ public final class EnabledModsList
199 195 {
200 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 200 EnabledModsList instance = new EnabledModsList();
... ... @@ -229,31 +211,14 @@ public final class EnabledModsList
229 211 {
230 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 218 catch (Exception ex)
240 219 {
241 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 29 import com.mumfrey.liteloader.api.manager.APIRegistry;
30 30 import com.mumfrey.liteloader.common.LoadingProgress;
31 31 import com.mumfrey.liteloader.core.api.LiteLoaderCoreAPI;
  32 +import com.mumfrey.liteloader.core.api.repository.Repository;
32 33 import com.mumfrey.liteloader.interfaces.LoaderEnumerator;
33 34 import com.mumfrey.liteloader.launch.ClassTransformerManager;
34 35 import com.mumfrey.liteloader.launch.LiteLoaderTweaker;
... ... @@ -102,6 +103,16 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
102 103 * Folder containing version-specific configuration
103 104 */
104 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 118 * File to write log entries to
... ... @@ -138,6 +149,8 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
138 149  
139 150 private LaunchClassLoader classLoader;
140 151  
  152 + private final StartupEnvironment env;
  153 +
141 154 private final ITweaker tweaker;
142 155  
143 156 private final APIRegistry apiRegistry;
... ... @@ -157,7 +170,7 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
157 170 * List of mods passed into the command line
158 171 */
159 172 private EnabledModsList enabledModsList;
160   -
  173 +
161 174 /**
162 175 * @param env
163 176 * @param tweaker
... ... @@ -165,6 +178,7 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
165 178 public LiteLoaderBootstrap(StartupEnvironment env, ITweaker tweaker)
166 179 {
167 180 this.environmentType = EnvironmentType.values()[env.getEnvironmentTypeId()];
  181 + this.env = env;
168 182 this.tweaker = tweaker;
169 183  
170 184 this.apiRegistry = new APIRegistry(this.getEnvironment(), this.getProperties());
... ... @@ -173,6 +187,7 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
173 187 this.assetsDirectory = env.getAssetsDirectory();
174 188 this.profile = env.getProfile();
175 189 this.modsFolder = env.getModsFolder();
  190 + this.repositoryFile = env.getModsRepoFile();
176 191  
177 192 this.versionedModsFolder = new File(this.modsFolder, LiteLoaderVersion.CURRENT.getMinecraftVersion());
178 193 this.configBaseFolder = new File(this.gameDirectory, "liteconfig");
... ... @@ -183,17 +198,27 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
183 198 this.commonConfigFolder = new File(this.configBaseFolder, "common");
184 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 209 this.initAPIs(env.getAPIsToLoad());
193 210 this.apiProvider = this.apiRegistry.getProvider();
194 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 223 * @param version
199 224 */
... ... @@ -249,6 +274,12 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
249 274 {
250 275 return this.enabledModsList;
251 276 }
  277 +
  278 + @Override
  279 + public Repository getModRepository()
  280 + {
  281 + return this.repository;
  282 + }
252 283  
253 284 @Override
254 285 public LoaderEnumerator getEnumerator()
... ... @@ -301,15 +332,20 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
301 332 * #preInit(net.minecraft.launchwrapper.LaunchClassLoader, boolean)
302 333 */
303 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 339 this.classLoader = classLoader;
307 340 this.loadTweaks = loadTweaks;
308 341  
309 342 LiteLoaderLogger.info(Verbosity.REDUCED, "LiteLoader begin PREINIT...");
310 343  
311 344 // Set up the bootstrap
312   - if (!this.prepare()) return;
  345 + if (!this.prepare())
  346 + {
  347 + return;
  348 + }
313 349  
314 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 359  
324 360 this.enabledModsList = EnabledModsList.createFrom(this.enabledModsFile);
325 361 this.enabledModsList.processModsList(this.profile, modsToLoad);
326   -
  362 +
327 363 this.enumerator = this.spawnEnumerator(classLoader);
328 364 this.enumerator.onPreInit();
329 365  
... ... @@ -599,6 +635,16 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
599 635 {
600 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 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 122 private final FastIterableDeque<EnumerationObserver> observers = new HandlerList<EnumerationObserver>(EnumerationObserver.class);
123 123  
124 124 protected EnumeratorState state = EnumeratorState.INIT;
125   -
  125 +
126 126 /**
127 127 * @param environment
128 128 * @param properties
... ... @@ -144,7 +144,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
144 144 // Initialise the shared mod list if we haven't already
145 145 this.getSharedModList();
146 146 }
147   -
  147 +
148 148 /**
149 149 * @param environment
150 150 */
... ... @@ -397,11 +397,13 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
397 397 {
398 398 this.gotoState(EnumeratorState.DISCOVER);
399 399  
  400 + String profile = this.environment.getProfile();
  401 +
400 402 for (EnumeratorModule module : this.modules)
401 403 {
402 404 try
403 405 {
404   - module.enumerate(this, this.environment.getProfile());
  406 + module.enumerate(this, profile);
405 407 }
406 408 catch (Throwable th)
407 409 {
... ... @@ -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 426 this.checkDependencies();
413 427 }
414 428  
... ... @@ -651,7 +665,15 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
651 665 if (config.endsWith(".json"))
652 666 {
653 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 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 24 import com.mumfrey.liteloader.interfaces.Loadable;
25 25 import com.mumfrey.liteloader.interfaces.LoadableMod;
26 26 import com.mumfrey.liteloader.interfaces.LoaderEnumerator;
  27 +import com.mumfrey.liteloader.interfaces.MixinContainer;
27 28 import com.mumfrey.liteloader.interfaces.TweakContainer;
28 29 import com.mumfrey.liteloader.launch.ClassTransformerManager;
29 30 import com.mumfrey.liteloader.launch.LoaderEnvironment;
... ... @@ -444,6 +445,12 @@ public class LiteLoaderMods
444 445 String identifier = mod.getIdentifier();
445 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 454 if (!this.enumerator.checkDependencies(container))
448 455 {
449 456 this.onModLoadFailed(container, identifier, "the mod was missing a required dependency", null);
... ... @@ -474,6 +481,23 @@ public class LiteLoaderMods
474 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 503 * @param identifier
... ... @@ -697,26 +721,28 @@ public class LiteLoaderMods
697 721  
698 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 791 private void registerModStartupError(ModInfo<?> mod, Throwable th, boolean critical)
766 792 {
767 793 this.startupErrorCount++;
768   - if (critical) this.criticalErrorCount++;
  794 + if (critical)
  795 + {
  796 + this.criticalErrorCount++;
  797 + }
  798 +
769 799 mod.registerStartupError(th);
770 800  
771 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 82 @Override
83 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 6 package com.mumfrey.liteloader.core.api;
7 7  
8 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 10 import com.mumfrey.liteloader.interfaces.ModularEnumerator;
26   -import com.mumfrey.liteloader.interfaces.TweakContainer;
27 11 import com.mumfrey.liteloader.launch.LoaderEnvironment;
28 12 import com.mumfrey.liteloader.launch.LoaderProperties;
29 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 16 * Enumerator module which searches for mods and tweaks in a folder
36 17 *
37 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 22 protected File directory;
54 23  
55 24 protected boolean readJarFiles;
... ... @@ -62,13 +31,13 @@ public class EnumeratorModuleFolder implements FilenameFilter, EnumeratorModule
62 31 */
63 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 41 @Override
73 42 public void init(LoaderEnvironment environment, LoaderProperties properties)
74 43 {
... ... @@ -76,7 +45,7 @@ public class EnumeratorModuleFolder implements FilenameFilter, EnumeratorModule
76 45 this.readJarFiles = properties.getAndStoreBooleanProperty(LoaderProperties.OPTION_SEARCH_JARFILES, true);
77 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 57 properties.setBooleanProperty(LoaderProperties.OPTION_SEARCH_JARFILES, this.readJarFiles);
89 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 91 /* (non-Javadoc)
93 92 * @see java.lang.Object#toString()
... ... @@ -107,34 +106,6 @@ public class EnumeratorModuleFolder implements FilenameFilter, EnumeratorModule
107 106 }
108 107  
109 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 109 * @see com.mumfrey.liteloader.core.Enumerator
139 110 * #enumerate(com.mumfrey.liteloader.core.EnabledModsList,
140 111 * java.lang.String)
... ... @@ -145,272 +116,22 @@ public class EnumeratorModuleFolder implements FilenameFilter, EnumeratorModule
145 116 if (this.directory.exists() && this.directory.isDirectory())
146 117 {
147 118 LiteLoaderLogger.info("Discovering valid mod files in folder %s", this.directory.getPath());
148   -
149 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(modFile.getModName()).add(modFile);
308   - }
309   - else
310   - {
311   - LiteLoaderLogger.info(Verbosity.REDUCED, "Not adding invalid or version-mismatched mod file: %s", modFile);
312   - enumerator.registerBadContainer(modFile, "Version not supported");
313   - }
314   - }
315   - }
316   -
317   - /**
318   - * @param enumerator
319   - * @param container
320   - */
321   - protected void addTweakFile(ModularEnumerator enumerator, TweakContainer<File> container)
322   - {
323   - enumerator.registerTweakContainer(container);
324   - }
325   -
326   - /**
327   - * @param enumerator
328   - */
329   - protected void sortAndRegisterFiles(ModularEnumerator enumerator)
330   - {
331   - // Copy the first entry in every version set into the modfiles list
332   - for (Entry<String, TreeSet<LoadableMod<File>>> modFileEntry : this.versionOrderingSets.entrySet())
333   - {
334   - LoadableMod<File> newestVersion = modFileEntry.getValue().iterator().next();
335   - this.registerFile(enumerator, newestVersion);
336   - }
337   -
338   - this.versionOrderingSets.clear();
339   - }
340   -
341   - /**
342   - * @param enumerator
343   - * @param modFile
  122 +
  123 + /* (non-Javadoc)
  124 + * @see com.mumfrey.liteloader.api.EnumeratorModule#register(
  125 + * com.mumfrey.liteloader.interfaces.ModularEnumerator,
  126 + * java.lang.String)
344 127 */
345   - @SuppressWarnings("unchecked")
346   - protected void registerFile(ModularEnumerator enumerator, LoadableMod<File> modFile)
347   - {
348   - if (enumerator.registerModContainer(modFile))
349   - {
350   - LiteLoaderLogger.info(Verbosity.REDUCED, "Adding newest valid mod file '%s' at revision %.4f", modFile, modFile.getRevision());
351   - this.loadableMods.add(modFile);
352   - }
353   - else
354   - {
355   - LiteLoaderLogger.info(Verbosity.REDUCED, "Not adding valid mod file '%s', the specified mod is disabled or missing a required dependency",
356   - modFile);
357   - }
358   -
359   - if (this.loadTweaks)
360   - {
361   - try
362   - {
363   - if (modFile instanceof TweakContainer)
364   - {
365   - this.addTweakFile(enumerator, (TweakContainer<File>)modFile);
366   - }
367   - }
368   - catch (Throwable th)
369   - {
370   - LiteLoaderLogger.warning("Error adding tweaks from '%s'", modFile);
371   - }
372   - }
373   - }
374   -
375 128 @Override
376   - public void injectIntoClassLoader(ModularEnumerator enumerator, LaunchClassLoader classLoader)
  129 + public void register(ModularEnumerator enumerator, String profile)
377 130 {
378   - LiteLoaderLogger.info("Injecting external mods into class path...");
379   -
380   - for (LoadableMod<?> loadableMod : this.loadableMods)
381   - {
382   - try
383   - {
384   - if (loadableMod.injectIntoClassPath(classLoader, false))
385   - {
386   - LiteLoaderLogger.info("Successfully injected mod file '%s' into classpath", loadableMod);
387   - }
388   - }
389   - catch (MalformedURLException ex)
390   - {
391   - LiteLoaderLogger.warning("Error injecting '%s' into classPath. The mod will not be loaded", loadableMod);
392   - }
393   - }
394   - }
395   -
396   - @Override
397   - public void registerMods(ModularEnumerator enumerator, LaunchClassLoader classLoader)
398   - {
399   - LiteLoaderLogger.info(Verbosity.REDUCED, "Discovering mods in valid mod files...");
400   - LoadingProgress.incTotalLiteLoaderProgress(this.loadableMods.size());
401   -
402   - for (LoadableMod<?> modFile : this.loadableMods)
  131 + if (this.directory.exists() && this.directory.isDirectory())
403 132 {
404   - LoadingProgress.incLiteLoaderProgress("Searching for mods in " + modFile.getModName() + "...");
405   - LiteLoaderLogger.info("Searching %s...", modFile);
406   - try
407   - {
408   - enumerator.registerModsFrom(modFile, true);
409   - }
410   - catch (Exception ex)
411   - {
412   - LiteLoaderLogger.warning("Error encountered whilst searching in %s...", modFile);
413   - }
  133 + LiteLoaderLogger.info("Registering discovered mod files in folder %s", this.directory.getPath());
  134 + this.sortAndRegisterFiles(enumerator);
414 135 }
415 136 }
416 137 }
... ...
src/main/java/com/mumfrey/liteloader/core/api/EnumeratorModuleRepository.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.util.ArrayList;
  10 +import java.util.List;
  11 +
  12 +import com.mumfrey.liteloader.core.api.repository.Repository;
  13 +import com.mumfrey.liteloader.interfaces.ModularEnumerator;
  14 +import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
  15 +
  16 +/**
  17 + * Enumerator module which searches for mods and tweaks in a folder
  18 + *
  19 + * @author Adam Mummery-Smith
  20 + */
  21 +public class EnumeratorModuleRepository extends EnumeratorModuleFiles
  22 +{
  23 + private final File modList;
  24 +
  25 + private final Repository repo;
  26 +
  27 + private File[] files = new File[0];
  28 +
  29 + public EnumeratorModuleRepository(LiteLoaderCoreAPI api, ContainerEnvironment containers, Repository repo, File modList)
  30 + {
  31 + super(api, containers);
  32 + this.repo = repo;
  33 + this.modList = modList;
  34 + }
  35 +
  36 + /* (non-Javadoc)
  37 + * @see java.lang.Object#toString()
  38 + */
  39 + @Override
  40 + public String toString()
  41 + {
  42 + return this.modList.getAbsolutePath();
  43 + }
  44 +
  45 + public File getModList()
  46 + {
  47 + return this.modList;
  48 + }
  49 +
  50 + @Override
  51 + protected boolean readJarFiles()
  52 + {
  53 + return true;
  54 + }
  55 +
  56 + @Override
  57 + protected boolean loadTweakJars()
  58 + {
  59 + return true;
  60 + }
  61 +
  62 + @Override
  63 + protected boolean loadTweaks()
  64 + {
  65 + return true;
  66 + }
  67 +
  68 + @Override
  69 + protected boolean forceInjection()
  70 + {
  71 + return false;
  72 + }
  73 +
  74 + @Override
  75 + protected File[] getFiles()
  76 + {
  77 + return this.files;
  78 + }
  79 +
  80 + /* (non-Javadoc)
  81 + * @see com.mumfrey.liteloader.core.Enumerator
  82 + * #enumerate(com.mumfrey.liteloader.core.EnabledModsList,
  83 + * java.lang.String)
  84 + */
  85 + @Override
  86 + public void enumerate(ModularEnumerator enumerator, String profile)
  87 + {
  88 + if (this.modList.isFile())
  89 + {
  90 + LiteLoaderLogger.info("Discovering mod files defined in repository %s", this.modList.getPath());
  91 + this.resolve();
  92 +
  93 + this.findValidFiles(enumerator);
  94 + }
  95 + }
  96 +
  97 + @Override
  98 + public void register(ModularEnumerator enumerator, String profile)
  99 + {
  100 + if (this.modList.isFile())
  101 + {
  102 + LiteLoaderLogger.info("Discovering mod files defined in repository %s", this.modList.getPath());
  103 + this.resolve();
  104 +
  105 + this.findValidFiles(enumerator);
  106 + this.sortAndRegisterFiles(enumerator);
  107 + }
  108 + }
  109 +
  110 + private void resolve()
  111 + {
  112 + this.repo.resolve(this.modList);
  113 +
  114 + List<File> files = new ArrayList<File>();
  115 + files.addAll(this.repo.getFiles());
  116 + this.files = files.toArray(this.files);
  117 + }
  118 +}
... ...
src/main/java/com/mumfrey/liteloader/core/api/LiteLoaderCoreAPI.java
... ... @@ -14,6 +14,7 @@ import com.mumfrey.liteloader.api.EnumeratorModule;
14 14 import com.mumfrey.liteloader.api.LiteAPI;
15 15 import com.mumfrey.liteloader.api.MixinConfigProvider;
16 16 import com.mumfrey.liteloader.core.LiteLoaderVersion;
  17 +import com.mumfrey.liteloader.core.api.EnumeratorModuleFiles.ContainerEnvironment;
17 18 import com.mumfrey.liteloader.interfaces.ObjectFactory;
18 19 import com.mumfrey.liteloader.launch.LoaderEnvironment;
19 20 import com.mumfrey.liteloader.launch.LoaderProperties;
... ... @@ -133,17 +134,26 @@ public abstract class LiteLoaderCoreAPI implements LiteAPI, MixinConfigProvider
133 134 {
134 135 enumeratorModules.add(new EnumeratorModuleClassPath());
135 136 }
  137 +
  138 + ContainerEnvironment containers = new ContainerEnvironment();
136 139  
137 140 if (this.searchModsFolder)
138 141 {
139 142 File modsFolder = this.environment.getModsFolder();
140   - enumeratorModules.add(new EnumeratorModuleFolder(this, modsFolder, false));
  143 + enumeratorModules.add(new EnumeratorModuleFolder(this, containers, modsFolder, false));
141 144  
142 145 File versionedModsFolder = this.environment.getVersionedModsFolder();
143   - enumeratorModules.add(new EnumeratorModuleFolder(this, versionedModsFolder, true));
  146 + enumeratorModules.add(new EnumeratorModuleFolder(this, containers, versionedModsFolder, true));
  147 + }
  148 +
  149 + String modsRepoFile = this.environment.getModsRepoFile();
  150 + if (modsRepoFile != null)
  151 + {
  152 + File modList = new File(modsRepoFile);
  153 + enumeratorModules.add(new EnumeratorModuleRepository(this, containers, this.environment.getModRepository(), modList));
144 154 }
145 155  
146   - return Collections.unmodifiableList(enumeratorModules);
  156 + return Collections.<EnumeratorModule>unmodifiableList(enumeratorModules);
147 157 }
148 158  
149 159 /**
... ...
src/main/java/com/mumfrey/liteloader/core/api/repository/Artefact.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.repository;
  7 +
  8 +import java.io.File;
  9 +import java.util.regex.Matcher;
  10 +import java.util.regex.Pattern;
  11 +
  12 +/**
  13 + * Specifier for a mod in the ivy repo shorthand notation
  14 + */
  15 +public final class Artefact
  16 +{
  17 + /**
  18 + * Regex for matching valid specifiers
  19 + */
  20 + private static final Pattern PATTERN = Pattern.compile("^([^:]+):([^:]+):([^:@]+?)(:([^:@]+?))?(@(zip|jar|litemod))?$");
  21 +
  22 + /**
  23 + * Artefact group id
  24 + */
  25 + private final String group;
  26 +
  27 + /**
  28 + * Artefact name
  29 + */
  30 + private final String name;
  31 +
  32 + /**
  33 + * Artefact version
  34 + */
  35 + private final String version;
  36 +
  37 + /**
  38 + * Artefact classifier (can be null)
  39 + */
  40 + private final String classifier;
  41 +
  42 + /**
  43 + * Artefact type (can be null)
  44 + */
  45 + private final String type;
  46 +
  47 + /**
  48 + * Resolved file
  49 + */
  50 + private File file;
  51 +
  52 + public Artefact(String specifier)
  53 + {
  54 + if (specifier == null)
  55 + {
  56 + throw new IllegalArgumentException("Invalid artefact specifier: null");
  57 + }
  58 +
  59 + Matcher matcher = Artefact.PATTERN.matcher(specifier);
  60 + if (!matcher.matches())
  61 + {
  62 + throw new IllegalArgumentException("Invalid artefact specifier: " + specifier);
  63 + }
  64 +
  65 + this.group = matcher.group(1);
  66 + this.name = matcher.group(2);
  67 + this.version = matcher.group(3);
  68 + this.classifier = matcher.group(5);
  69 + this.type = matcher.group(7);
  70 + }
  71 +
  72 + /**
  73 + * Get the artefact id consisting of the group and name
  74 + *
  75 + * @return
  76 + */
  77 + public String getArtefactId()
  78 + {
  79 + return String.format("%s:%s", this.getGroup(), this.getName());
  80 + }
  81 +
  82 + /**
  83 + * Get the path portion of this artefact's resolved location
  84 + *
  85 + * @return artefact path
  86 + */
  87 + public String getPath()
  88 + {
  89 + return String.format("%s/%s/%s", this.getGroup().replace('.', '/'), this.getName(), this.getVersion());
  90 + }
  91 +
  92 + /**
  93 + * Get the file name portion of this artefact's resolved location
  94 + *
  95 + * @return arefact file name
  96 + */
  97 + public String getFileName()
  98 + {
  99 + return String.format("%s-%s%s.%s", this.getName(), this.getVersion(), this.getClassifier("-"), this.getType());
  100 + }
  101 +
  102 + /**
  103 + * Get the artefact group
  104 + */
  105 + public String getGroup()
  106 + {
  107 + return this.group;
  108 + }
  109 +
  110 + /**
  111 + * Get the artefact name
  112 + */
  113 + public String getName()
  114 + {
  115 + return this.name;
  116 + }
  117 +
  118 + /**
  119 + * Get the artefact version
  120 + */
  121 + public String getVersion()
  122 + {
  123 + return this.version;
  124 + }
  125 +
  126 + /**
  127 + * Get the artefact classifier, returns an empty string if no classifier is
  128 + * set
  129 + */
  130 + public String getClassifier()
  131 + {
  132 + return this.getClassifier("");
  133 + }
  134 +
  135 + private String getClassifier(String prefix)
  136 + {
  137 + return this.classifier != null ? prefix + this.classifier : "";
  138 + }
  139 +
  140 + /**
  141 + * Get the artefact type, defaults to "jar" if no type was specified
  142 + */
  143 + public String getType()
  144 + {
  145 + return this.type != null ? this.type : "jar";
  146 + }
  147 +
  148 + /**
  149 + * Resolve this artefact beneath the specified repository root
  150 + *
  151 + * @param repositoryRoot repository root
  152 + * @return resolved file
  153 + */
  154 + void resolve(File repositoryRoot)
  155 + {
  156 + this.file = new File(new File(repositoryRoot, this.getPath()), this.getFileName());
  157 + }
  158 +
  159 + /**
  160 + * Get whether the resolved artefact actually exists
  161 + */
  162 + public boolean exists()
  163 + {
  164