Commit aecc5dcf6d2d0ccb9de81de87d2eeb6a9179b529

Authored by Mumfrey
1 parent f2549841

cleaning up the tweaker a bit, moving logic to separate StartupEnvironment class

java/common/com/mumfrey/liteloader/core/LiteLoaderBootstrap.java
... ... @@ -30,6 +30,7 @@ import com.mumfrey.liteloader.interfaces.LoaderEnumerator;
30 30 import com.mumfrey.liteloader.launch.LoaderBootstrap;
31 31 import com.mumfrey.liteloader.launch.LoaderEnvironment;
32 32 import com.mumfrey.liteloader.launch.LoaderProperties;
  33 +import com.mumfrey.liteloader.launch.StartupEnvironment;
33 34 import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
34 35  
35 36 /**
... ... @@ -143,17 +144,17 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
143 144 * @param assetsDirectory
144 145 * @param profile
145 146 */
146   - public LiteLoaderBootstrap(int environmentTypeId, File gameDirectory, File assetsDirectory, String profile, List<String> apisToLoad)
  147 + public LiteLoaderBootstrap(StartupEnvironment env)
147 148 {
148   - this.environmentType = EnvironmentType.values()[environmentTypeId];
  149 + this.environmentType = EnvironmentType.values()[env.getEnvironmentTypeId()];
149 150  
150   - this.apiRegistry = new APIRegistry(this, this);
  151 + this.apiRegistry = new APIRegistry(this.getEnvironment(), this.getProperties());
151 152  
152   - this.gameDirectory = gameDirectory;
153   - this.assetsDirectory = assetsDirectory;
154   - this.profile = profile;
  153 + this.gameDirectory = env.getGameDirectory();
  154 + this.assetsDirectory = env.getAssetsDirectory();
  155 + this.profile = env.getProfile();
  156 + this.modsFolder = env.getModsFolder();
155 157  
156   - this.modsFolder = new File(this.gameDirectory, "mods");
157 158 this.versionedModsFolder = new File(this.modsFolder, LiteLoaderVersion.CURRENT.getMinecraftVersion());
158 159 this.configBaseFolder = new File(this.gameDirectory, "liteconfig");
159 160 this.logFile = new File(this.configBaseFolder, "liteloader.log");
... ... @@ -169,7 +170,7 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
169 170 if (!this.commonConfigFolder.exists()) this.commonConfigFolder.mkdirs();
170 171 if (!this.versionConfigFolder.exists()) this.versionConfigFolder.mkdirs();
171 172  
172   - this.initAPIs(apisToLoad);
  173 + this.initAPIs(env.getAPIsToLoad());
173 174 this.apiProvider = this.apiRegistry.getProvider();
174 175 this.apiAdapter = this.apiRegistry.getAdapter();
175 176 }
... ... @@ -242,6 +243,18 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
242 243 return this.environmentType;
243 244 }
244 245  
  246 + @Override
  247 + public LoaderEnvironment getEnvironment()
  248 + {
  249 + return this;
  250 + }
  251 +
  252 + @Override
  253 + public LoaderProperties getProperties()
  254 + {
  255 + return this;
  256 + }
  257 +
245 258 /* (non-Javadoc)
246 259 * @see com.mumfrey.liteloader.launch.ILoaderBootstrap#preInit(net.minecraft.launchwrapper.LaunchClassLoader, boolean)
247 260 */
... ... @@ -307,7 +320,7 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
307 320 // PreInit failed
308 321 if (this.enumerator == null) return;
309 322  
310   - LiteLoader.createInstance(this, this, classLoader);
  323 + LiteLoader.createInstance(this.getEnvironment(), this.getProperties(), classLoader);
311 324 LiteLoader.invokeInit();
312 325 }
313 326  
... ...
java/common/com/mumfrey/liteloader/launch/GameEnvironment.java 0 → 100644
  1 +package com.mumfrey.liteloader.launch;
  2 +
  3 +import java.io.File;
  4 +
  5 +public interface GameEnvironment
  6 +{
  7 + /**
  8 + * Get the game directory, this is the root directory of the game profile specified by the user in the launcher
  9 + */
  10 + public abstract File getGameDirectory();
  11 +
  12 + /**
  13 + * Get the assets directory
  14 + */
  15 + public abstract File getAssetsDirectory();
  16 +
  17 + /**
  18 + * Get the active profile name
  19 + */
  20 + public abstract String getProfile();
  21 +
  22 + /**
  23 + * Get the "mods" folder, used to get the base path for enumerators and config for legacy mods
  24 + */
  25 + public abstract File getModsFolder();
  26 +}
... ...
java/common/com/mumfrey/liteloader/launch/LiteLoaderTweaker.java
... ... @@ -5,19 +5,11 @@ import java.lang.reflect.Constructor;
5 5 import java.lang.reflect.Method;
6 6 import java.net.URL;
7 7 import java.net.URLClassLoader;
8   -import java.util.ArrayList;
9   -import java.util.HashMap;
10 8 import java.util.HashSet;
11 9 import java.util.List;
12   -import java.util.Map;
13   -import java.util.Map.Entry;
14 10 import java.util.Set;
15 11 import java.util.TreeSet;
16 12  
17   -import joptsimple.ArgumentAcceptingOptionSpec;
18   -import joptsimple.NonOptionArgumentSpec;
19   -import joptsimple.OptionParser;
20   -import joptsimple.OptionSet;
21 13 import net.minecraft.launchwrapper.ITweaker;
22 14 import net.minecraft.launchwrapper.Launch;
23 15 import net.minecraft.launchwrapper.LaunchClassLoader;
... ... @@ -33,11 +25,13 @@ import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
33 25 */
34 26 public class LiteLoaderTweaker implements ITweaker
35 27 {
36   - public static final String VERSION = "1.7.10";
  28 + public static final int ENV_TYPE_CLIENT = 0;
  29 + public static final int ENV_TYPE_DEDICATEDSERVER = 1;
37 30  
38   - protected static final int ENV_TYPE_CLIENT = 0;
  31 + public static final String VERSION = "1.7.10";
39 32  
40   - protected static final int ENV_TYPE_DEDICATEDSERVER = 1;
  33 + protected static final String bootstrapClassName = "com.mumfrey.liteloader.core.LiteLoaderBootstrap";
  34 + protected static final String genTransformerClassName = "com.mumfrey.liteloader.client.gen.GenProfilerTransformer";
41 35  
42 36 /**
43 37 * Loader startup state
... ... @@ -170,172 +164,159 @@ public class LiteLoaderTweaker implements ITweaker
170 164  
171 165 private static LiteLoaderTweaker instance;
172 166  
173   - private URL jarUrl;
174   -
175   - private List<String> singularLaunchArgs = new ArrayList<String>();
176   - private Map<String, String> launchArgs;
177   -
178   - private ArgumentAcceptingOptionSpec<String> modsOption;
179   - private ArgumentAcceptingOptionSpec<String> apisOption;
180   - private OptionSet parsedOptions;
  167 + protected URL jarUrl;
181 168  
182   - private int tweakOrder = 0;
183   - private Set<String> allCascadingTweaks = new HashSet<String>();
184   - private Set<SortableValue<String>> sortedCascadingTweaks = new TreeSet<SortableValue<String>>();
  169 + protected int tweakOrder = 0;
  170 + protected Set<String> allCascadingTweaks = new HashSet<String>();
  171 + protected Set<SortableValue<String>> sortedCascadingTweaks = new TreeSet<SortableValue<String>>();
185 172  
186   - private boolean isPrimary;
  173 + protected boolean isPrimary;
  174 +
  175 + protected StartupEnvironment env;
187 176  
188 177 /**
189 178 * Loader bootstrap object
190 179 */
191   - private LoaderBootstrap bootstrap;
  180 + protected LoaderBootstrap bootstrap;
192 181  
193   - private LoaderProperties properties;
  182 + protected LoaderProperties properties;
194 183  
195 184 /**
196 185 * Transformer manager
197 186 */
198   - private ClassTransformerManager transformerManager;
199   -
200   - private static final String bootstrapClassName = "com.mumfrey.liteloader.core.LiteLoaderBootstrap";
  187 + protected ClassTransformerManager transformerManager;
201 188  
202   - private static final String genTransformerClassName = "com.mumfrey.liteloader.client.gen.GenProfilerTransformer";
203   -
204 189 @Override
205 190 public void acceptOptions(List<String> args, File gameDirectory, File assetsDirectory, String profile)
206 191 {
207 192 Launch.classLoader.addClassLoaderExclusion("com.google.common.");
208   -
209 193 LiteLoaderTweaker.instance = this;
210 194  
211   - this.initArgs(args, gameDirectory, assetsDirectory);
212   -
213   - List<String> modsToLoad = this.getModFilterList();
214   - List<String> apisToLoad = this.getAPIsToLoad();
215   -
216   - this.prepare(gameDirectory, assetsDirectory, profile, apisToLoad);
  195 + this.prepare(args, gameDirectory, assetsDirectory, profile);
217 196  
218   - this.preInit(modsToLoad);
  197 + this.preInit();
219 198 }
220 199  
221 200 /**
222   - * @return
  201 + * @param gameDirectory
  202 + * @param assetsDirectory
  203 + * @param profile
  204 + * @param apisToLoad
223 205 */
224   - private List<String> getModFilterList()
  206 + private void prepare(List<String> args, File gameDirectory, File assetsDirectory, String profile)
225 207 {
226   - return (this.parsedOptions.has(this.modsOption)) ? this.modsOption.values(this.parsedOptions) : null;
  208 + LiteLoaderLogger.info("Bootstrapping LiteLoader " + LiteLoaderTweaker.VERSION);
  209 +
  210 + try
  211 + {
  212 + this.initEnvironment(args, gameDirectory, assetsDirectory, profile);
  213 +
  214 + this.bootstrap = this.spawnBootstrap(LiteLoaderTweaker.bootstrapClassName, Launch.classLoader);
  215 + this.properties = this.bootstrap.getProperties();
  216 +
  217 + this.transformerManager = new ClassTransformerManager(this.bootstrap.getRequiredTransformers());
  218 + this.transformerManager.injectTransformers(this.bootstrap.getPacketTransformers());
  219 +
  220 + StartupState.PREPARE.completed();
  221 + }
  222 + catch (Throwable th)
  223 + {
  224 + LiteLoaderLogger.severe(th, "Error during LiteLoader PREPARE: %s %s", th.getClass().getName(), th.getMessage());
  225 + }
227 226 }
228 227  
229 228 /**
230   - * @return
  229 + * Do the first stage of loader startup, which enumerates mod sources and finds tweakers
231 230 */
232   - private List<String> getAPIsToLoad()
  231 + private void preInit()
233 232 {
234   - List<String> apisToLoad = new ArrayList<String>();
235   - this.registerCoreAPIs(apisToLoad);
236   - if (this.parsedOptions.has(this.apisOption))
  233 + StartupState.PREINIT.gotoState();
  234 +
  235 + try
  236 + {
  237 + this.bootstrap.preInit(Launch.classLoader, true, this.env.getModFilterList());
  238 +
  239 + this.injectDiscoveredTweakClasses();
  240 + StartupState.PREINIT.completed();
  241 + }
  242 + catch (Throwable th)
237 243 {
238   - apisToLoad.addAll(this.apisOption.values(this.parsedOptions));
  244 + LiteLoaderLogger.severe(th, "Error during LiteLoader PREINIT: %s %s", th.getClass().getName(), th.getMessage());
239 245 }
240   -
241   - return apisToLoad;
242 246 }
243 247  
244   - protected void registerCoreAPIs(List<String> apisToLoad)
245   - {
246   - apisToLoad.add(0, "com.mumfrey.liteloader.client.api.LiteLoaderCoreAPIClient");
247   - }
248   -
249   - private void initJar()
  248 + public static void preBeginGame()
250 249 {
251   - URL[] urls = Launch.classLoader.getURLs();
252   - this.jarUrl = urls[urls.length - 1]; // probably?
  250 + StartupState.BEGINGAME.gotoState();
  251 + try
  252 + {
  253 + LiteLoaderTweaker.instance.transformerManager.injectDownstreamTransformers(Launch.classLoader);
  254 + LiteLoaderTweaker.instance.bootstrap.preBeginGame();
  255 + StartupState.BEGINGAME.completed();
  256 + }
  257 + catch (Throwable th)
  258 + {
  259 + LiteLoaderLogger.severe(th, "Error during LiteLoader BEGINGAME: %s %s", th.getClass().getName(), th.getMessage());
  260 + }
253 261 }
254 262  
255 263 /**
256   - * @param args
257   - * @param gameDirectory
258   - * @param assetsDirectory
  264 + * Do the second stage of loader startup
259 265 */
260   - @SuppressWarnings("unchecked")
261   - public void initArgs(List<String> args, File gameDirectory, File assetsDirectory)
  266 + public static void init()
262 267 {
263   - OptionParser optionParser = new OptionParser();
264   - this.modsOption = optionParser.accepts("mods", "Comma-separated list of mods to load").withRequiredArg().ofType(String.class).withValuesSeparatedBy(',');
265   - this.apisOption = optionParser.accepts("api", "Additional API classes to load").withRequiredArg().ofType(String.class);
266   - optionParser.allowsUnrecognizedOptions();
267   - NonOptionArgumentSpec<String> nonOptions = optionParser.nonOptions();
  268 + StartupState.INIT.gotoState();
268 269  
269   - this.parsedOptions = optionParser.parse(args.toArray(new String[args.size()]));
270   - this.launchArgs = (Map<String, String>)Launch.blackboard.get("launchArgs");
271   - if (this.launchArgs == null)
  270 + try
272 271 {
273   - this.launchArgs = new HashMap<String, String>();
274   - Launch.blackboard.put("launchArgs", this.launchArgs);
  272 + LiteLoaderTweaker.instance.bootstrap.init(Launch.classLoader);
  273 + StartupState.INIT.completed();
  274 + }
  275 + catch (Throwable th)
  276 + {
  277 + LiteLoaderLogger.severe(th, "Error during LiteLoader INIT: %s %s", th.getClass().getName(), th.getMessage());
275 278 }
276   -
277   - // Parse out the arguments ourself because joptsimple doesn't really provide a good way to
278   - // add arguments to the unparsed argument list after parsing
279   - this.parseArgs(this.parsedOptions.valuesOf(nonOptions));
280   -
281   - // Put required arguments to the blackboard if they don't already exist there
282   - this.provideRequiredArgs(gameDirectory, assetsDirectory);
283 279 }
284   -
  280 +
285 281 /**
286   - * @param gameDirectory
287   - * @param assetsDirectory
  282 + * Do the second stage of loader startup
288 283 */
289   - public void provideRequiredArgs(File gameDirectory, File assetsDirectory)
  284 + public static void postInit()
290 285 {
291   - if (!this.launchArgs.containsKey("--version"))
292   - this.addClassifiedArg("--version", LiteLoaderTweaker.VERSION);
293   -
294   - if (!this.launchArgs.containsKey("--gameDir") && gameDirectory != null)
295   - this.addClassifiedArg("--gameDir", gameDirectory.getAbsolutePath());
296   -
297   - if (!this.launchArgs.containsKey("--assetsDir") && assetsDirectory != null)
298   - this.addClassifiedArg("--assetsDir", assetsDirectory.getAbsolutePath());
  286 + StartupState.POSTINIT.gotoState();
  287 +
  288 + try
  289 + {
  290 + LiteLoaderTweaker.instance.bootstrap.postInit();
  291 + StartupState.POSTINIT.completed();
  292 +
  293 + StartupState.DONE.gotoState();
  294 + }
  295 + catch (Throwable th)
  296 + {
  297 + LiteLoaderLogger.severe(th, "Error during LiteLoader POSTINIT: %s %s", th.getClass().getName(), th.getMessage());
  298 + }
299 299 }
300 300  
301   - private void parseArgs(List<String> args)
  301 + protected void initEnvironment(List<String> args, File gameDirectory, File assetsDirectory, String profile)
302 302 {
303   - String classifier = null;
304   -
305   - for (String arg : args)
  303 + this.env = new StartupEnvironment(args, gameDirectory, assetsDirectory, profile)
306 304 {
307   - if (arg.startsWith("-"))
  305 + @Override
  306 + public void registerCoreAPIs(List<String> apisToLoad)
308 307 {
309   - if (classifier != null)
310   - {
311   - this.addClassifiedArg(classifier, "");
312   - classifier = null;
313   - }
314   - else if (arg.contains("="))
315   - {
316   - this.addClassifiedArg(arg.substring(0, arg.indexOf('=')), arg.substring(arg.indexOf('=') + 1));
317   - }
318   - else
319   - {
320   - classifier = arg;
321   - }
  308 + apisToLoad.add(0, "com.mumfrey.liteloader.client.api.LiteLoaderCoreAPIClient");
322 309 }
323   - else
  310 +
  311 + @Override
  312 + public int getEnvironmentTypeId()
324 313 {
325   - if (classifier != null)
326   - {
327   - this.addClassifiedArg(classifier, arg);
328   - classifier = null;
329   - }
330   - else
331   - this.singularLaunchArgs.add(arg);
  314 + return LiteLoaderTweaker.ENV_TYPE_CLIENT;
332 315 }
333   - }
334   - }
  316 + };
335 317  
336   - private void addClassifiedArg(String classifiedArg, String arg)
337   - {
338   - this.launchArgs.put(classifiedArg, arg);
  318 + URL[] urls = Launch.classLoader.getURLs();
  319 + this.jarUrl = urls[urls.length - 1]; // probably?
339 320 }
340 321  
341 322 @Override
... ... @@ -371,21 +352,7 @@ public class LiteLoaderTweaker implements ITweaker
371 352 @Override
372 353 public String[] getLaunchArguments()
373 354 {
374   - List<String> args = new ArrayList<String>();
375   -
376   - for (String singularArg : this.singularLaunchArgs)
377   - args.add(singularArg);
378   -
379   - for (Entry<String, String> launchArg : this.launchArgs.entrySet())
380   - {
381   - args.add(launchArg.getKey().trim());
382   - args.add(launchArg.getValue().trim());
383   - }
384   -
385   - this.singularLaunchArgs.clear();
386   - this.launchArgs.clear();
387   -
388   - return args.toArray(new String[args.size()]);
  355 + return this.env.getLaunchArguments();
389 356 }
390 357  
391 358 public static boolean addCascadedTweaker(String tweakClass, int priority)
... ... @@ -485,21 +452,21 @@ public class LiteLoaderTweaker implements ITweaker
485 452 return false;
486 453 }
487 454  
488   - protected LoaderBootstrap spawnBootstrap(String bootstrapClassName, ClassLoader classLoader, File gameDirectory, File assetsDirectory, String profile, List<String> apisToLoad)
  455 + protected LoaderBootstrap spawnBootstrap(String bootstrapClassName, ClassLoader classLoader)
489 456 {
490 457 if (!StartupState.PREPARE.isInState())
491 458 {
492   - throw new IllegalStateException("spawnBootstrap is not valid outside constructor");
  459 + throw new IllegalStateException("spawnBootstrap is not valid outside PREPARE");
493 460 }
494 461  
495 462 try
496 463 {
497 464 @SuppressWarnings("unchecked")
498 465 Class<? extends LoaderBootstrap> bootstrapClass = (Class<? extends LoaderBootstrap>)Class.forName(bootstrapClassName, false, classLoader);
499   - Constructor<? extends LoaderBootstrap> bootstrapCtor = bootstrapClass.getDeclaredConstructor(Integer.TYPE, File.class, File.class, String.class, List.class);
  466 + Constructor<? extends LoaderBootstrap> bootstrapCtor = bootstrapClass.getDeclaredConstructor(StartupEnvironment.class);
500 467 bootstrapCtor.setAccessible(true);
501 468  
502   - return bootstrapCtor.newInstance(this.getEnvironmentTypeId(), gameDirectory, assetsDirectory, profile, apisToLoad);
  469 + return bootstrapCtor.newInstance(this.env);
503 470 }
504 471 catch (Throwable th)
505 472 {
... ... @@ -508,113 +475,6 @@ public class LiteLoaderTweaker implements ITweaker
508 475  
509 476 return null;
510 477 }
511   -
512   - protected int getEnvironmentTypeId()
513   - {
514   - return LiteLoaderTweaker.ENV_TYPE_CLIENT;
515   - }
516   -
517   - /**
518   - * @param gameDirectory
519   - * @param assetsDirectory
520   - * @param profile
521   - * @param apisToLoad
522   - */
523   - private void prepare(File gameDirectory, File assetsDirectory, String profile, List<String> apisToLoad)
524   - {
525   - LiteLoaderLogger.info("Bootstrapping LiteLoader " + LiteLoaderTweaker.VERSION);
526   -
527   - try
528   - {
529   - this.registerCoreAPIs(apisToLoad);
530   - this.initJar();
531   -
532   - this.bootstrap = this.spawnBootstrap(LiteLoaderTweaker.bootstrapClassName, Launch.classLoader, gameDirectory, assetsDirectory, profile, apisToLoad);
533   - this.properties = this.bootstrap instanceof LoaderProperties ? (LoaderProperties)this.bootstrap : null;
534   -
535   - this.transformerManager = new ClassTransformerManager(this.bootstrap.getRequiredTransformers());
536   - this.transformerManager.injectTransformers(this.bootstrap.getPacketTransformers());
537   -
538   - StartupState.PREPARE.completed();
539   - }
540   - catch (Throwable th)
541   - {
542   - LiteLoaderLogger.severe(th, "Error during LiteLoader PREPARE: %s %s", th.getClass().getName(), th.getMessage());
543   - }
544   - }
545   -
546   - /**
547   - * Do the first stage of loader startup, which enumerates mod sources and finds tweakers
548   - */
549   - private void preInit(List<String> modsToLoad)
550   - {
551   - StartupState.PREINIT.gotoState();
552   -
553   - try
554   - {
555   - this.bootstrap.preInit(Launch.classLoader, true, modsToLoad);
556   -
557   - this.injectDiscoveredTweakClasses();
558   - StartupState.PREINIT.completed();
559   - }
560   - catch (Throwable th)
561   - {
562   - LiteLoaderLogger.severe(th, "Error during LiteLoader PREINIT: %s %s", th.getClass().getName(), th.getMessage());
563   - }
564   - }
565   -
566   - public static void preBeginGame()
567   - {
568   - StartupState.BEGINGAME.gotoState();
569   - try
570   - {
571   - LiteLoaderTweaker.instance.transformerManager.injectDownstreamTransformers(Launch.classLoader);
572   - LiteLoaderTweaker.instance.bootstrap.preBeginGame();
573   - StartupState.BEGINGAME.completed();
574   - }
575   - catch (Throwable th)
576   - {
577   - LiteLoaderLogger.severe(th, "Error during LiteLoader BEGINGAME: %s %s", th.getClass().getName(), th.getMessage());
578   - }
579   - }
580   -
581   - /**
582   - * Do the second stage of loader startup
583   - */
584   - public static void init()
585   - {
586   - StartupState.INIT.gotoState();
587   -
588   - try
589   - {
590   - LiteLoaderTweaker.instance.bootstrap.init(Launch.classLoader);
591   - StartupState.INIT.completed();
592   - }
593   - catch (Throwable th)
594   - {
595   - LiteLoaderLogger.severe(th, "Error during LiteLoader INIT: %s %s", th.getClass().getName(), th.getMessage());
596   - }
597   - }
598   -
599   - /**
600   - * Do the second stage of loader startup
601   - */
602   - public static void postInit()
603   - {
604   - StartupState.POSTINIT.gotoState();
605   -
606   - try
607   - {
608   - LiteLoaderTweaker.instance.bootstrap.postInit();
609   - StartupState.POSTINIT.completed();
610   -
611   - StartupState.DONE.gotoState();
612   - }
613   - catch (Throwable th)
614   - {
615   - LiteLoaderLogger.severe(th, "Error during LiteLoader POSTINIT: %s %s", th.getClass().getName(), th.getMessage());
616   - }
617   - }
618 478  
619 479 public static URL getJarUrl()
620 480 {
... ...
java/common/com/mumfrey/liteloader/launch/LiteLoaderTweakerServer.java
1 1 package com.mumfrey.liteloader.launch;
2 2  
  3 +import java.io.File;
  4 +import java.net.URL;
3 5 import java.util.List;
4 6  
  7 +import net.minecraft.launchwrapper.Launch;
  8 +
5 9 public class LiteLoaderTweakerServer extends LiteLoaderTweaker
6 10 {
7 11 @Override
8   - protected void registerCoreAPIs(List<String> apisToLoad)
  12 + protected void initEnvironment(List<String> args, File gameDirectory, File assetsDirectory, String profile)
9 13 {
10   - apisToLoad.add(0, "com.mumfrey.liteloader.server.api.LiteLoaderCoreAPIServer");
  14 + this.env = new StartupEnvironment(args, gameDirectory, assetsDirectory, profile)
  15 + {
  16 + @Override
  17 + public void registerCoreAPIs(List<String> apisToLoad)
  18 + {
  19 + apisToLoad.add(0, "com.mumfrey.liteloader.server.api.LiteLoaderCoreAPIServer");
  20 + }
  21 +
  22 + @Override
  23 + public int getEnvironmentTypeId()
  24 + {
  25 + return LiteLoaderTweaker.ENV_TYPE_DEDICATEDSERVER;
  26 + }
  27 + };
  28 +
  29 + URL[] urls = Launch.classLoader.getURLs();
  30 + this.jarUrl = urls[urls.length - 1]; // probably?
11 31 }
12   -
  32 +
13 33 @Override
14 34 public String getLaunchTarget()
15 35 {
... ... @@ -17,10 +37,4 @@ public class LiteLoaderTweakerServer extends LiteLoaderTweaker
17 37  
18 38 return "net.minecraft.server.MinecraftServer";
19 39 }
20   -
21   - @Override
22   - protected int getEnvironmentTypeId()
23   - {
24   - return LiteLoaderTweaker.ENV_TYPE_DEDICATEDSERVER;
25   - }
26 40 }
... ...
java/common/com/mumfrey/liteloader/launch/LoaderBootstrap.java
... ... @@ -42,4 +42,8 @@ public interface LoaderBootstrap
42 42 public abstract List<String> getRequiredDownstreamTransformers();
43 43  
44 44 public abstract List<String> getPacketTransformers();
  45 +
  46 + public abstract LoaderEnvironment getEnvironment();
  47 +
  48 + public abstract LoaderProperties getProperties();
45 49 }
... ...
java/common/com/mumfrey/liteloader/launch/LoaderEnvironment.java
... ... @@ -16,7 +16,7 @@ import com.mumfrey.liteloader.interfaces.LoaderEnumerator;
16 16 *
17 17 * @author Adam Mummery-Smith
18 18 */
19   -public interface LoaderEnvironment
  19 +public interface LoaderEnvironment extends GameEnvironment
20 20 {
21 21 public enum EnvironmentType
22 22 {
... ... @@ -47,26 +47,6 @@ public interface LoaderEnvironment
47 47 public abstract LoaderEnumerator getEnumerator();
48 48  
49 49 /**
50   - * Get the game directory, this is the root directory of the game profile specified by the user in the launcher
51   - */
52   - public abstract File getGameDirectory();
53   -
54   - /**
55   - * Get the assets directory
56   - */
57   - public abstract File getAssetsDirectory();
58   -
59   - /**
60   - * Get the active profile name
61   - */
62   - public abstract String getProfile();
63   -
64   - /**
65   - * Get the "mods" folder, used to get the base path for enumerators and config for legacy mods
66   - */
67   - public abstract File getModsFolder();
68   -
69   - /**
70 50 * Get the version-specific mods folder
71 51 */
72 52 public abstract File getVersionedModsFolder();
... ...
java/common/com/mumfrey/liteloader/launch/StartupEnvironment.java 0 → 100644
  1 +package com.mumfrey.liteloader.launch;
  2 +
  3 +import java.io.File;
  4 +import java.util.ArrayList;
  5 +import java.util.HashMap;
  6 +import java.util.List;
  7 +import java.util.Map;
  8 +import java.util.Map.Entry;
  9 +
  10 +import net.minecraft.launchwrapper.Launch;
  11 +import joptsimple.ArgumentAcceptingOptionSpec;
  12 +import joptsimple.NonOptionArgumentSpec;
  13 +import joptsimple.OptionParser;
  14 +import joptsimple.OptionSet;
  15 +
  16 +/**
  17 + * Container for startup environment state which also parses the command line options
  18 + *
  19 + * @author Adam Mummery-Smith
  20 + */
  21 +public abstract class StartupEnvironment implements GameEnvironment
  22 +{
  23 + private List<String> singularLaunchArgs = new ArrayList<String>();
  24 + private Map<String, String> launchArgs;
  25 +
  26 + private ArgumentAcceptingOptionSpec<String> modsDirOption;
  27 + private ArgumentAcceptingOptionSpec<String> modsOption;
  28 + private ArgumentAcceptingOptionSpec<String> apisOption;
  29 + private NonOptionArgumentSpec<String> unparsedOptions;
  30 + private OptionSet parsedOptions;
  31 +
  32 + private final File gameDirectory;
  33 + private final File assetsDirectory;
  34 + private final String profile;
  35 +
  36 + public StartupEnvironment(List<String> args, File gameDirectory, File assetsDirectory, String profile)
  37 + {
  38 + this.initArgs(args);
  39 +
  40 + this.gameDirectory = gameDirectory;
  41 + this.assetsDirectory = assetsDirectory;
  42 + this.profile = profile;
  43 + }
  44 +
  45 + public abstract void registerCoreAPIs(List<String> apisToLoad);
  46 +
  47 + public abstract int getEnvironmentTypeId();
  48 +
  49 + /**
  50 + * @param args
  51 + * @param gameDirectory
  52 + * @param assetsDirectory
  53 + */
  54 + @SuppressWarnings("unchecked")
  55 + public void initArgs(List<String> args)
  56 + {
  57 + // Get the launchArgs map from the blackboard, or create it if it's not there
  58 + this.launchArgs = (Map<String, String>)Launch.blackboard.get("launchArgs");
  59 + if (this.launchArgs == null)
  60 + {
  61 + this.launchArgs = new HashMap<String, String>();
  62 + Launch.blackboard.put("launchArgs", this.launchArgs);
  63 + }
  64 +
  65 + // Parse liteloader options using joptsimple
  66 + this.parseOptions(args.toArray(new String[args.size()]));
  67 +
  68 + // Parse out the arguments ourself because joptsimple doesn't really provide a good way to
  69 + // add arguments to the unparsed argument list after parsing
  70 + this.parseArgs(this.parsedOptions.valuesOf(this.unparsedOptions));
  71 +
  72 + // Put required arguments to the blackboard if they don't already exist there
  73 + this.provideRequiredArgs();
  74 + }
  75 +
  76 + private void parseOptions(String[] args)
  77 + {
  78 + OptionParser optionParser = new OptionParser();
  79 + optionParser.allowsUnrecognizedOptions();
  80 +
  81 + this.modsOption = optionParser.accepts("mods", "Comma-separated list of mods to load").withRequiredArg().ofType(String.class).withValuesSeparatedBy(',');
  82 + this.apisOption = optionParser.accepts("api", "Additional API classes to load").withRequiredArg().ofType(String.class);
  83 + this.modsDirOption = optionParser.accepts("modsDir", "Path to 'mods' folder to use instead of default").withRequiredArg().ofType(String.class);
  84 +
  85 + this.unparsedOptions = optionParser.nonOptions();
  86 + this.parsedOptions = optionParser.parse(args);
  87 + }
  88 +
  89 + private void parseArgs(List<String> args)
  90 + {
  91 + String classifier = null;
  92 +
  93 + for (String arg : args)
  94 + {
  95 + if (arg.startsWith("-"))
  96 + {
  97 + if (classifier != null)
  98 + {
  99 + this.addClassifiedArg(classifier, "");
  100 + classifier = null;
  101 + }
  102 + else if (arg.contains("="))
  103 + {
  104 + this.addClassifiedArg(arg.substring(0, arg.indexOf('=')), arg.substring(arg.indexOf('=') + 1));
  105 + }
  106 + else
  107 + {
  108 + classifier = arg;
  109 + }
  110 + }
  111 + else
  112 + {
  113 + if (classifier != null)
  114 + {
  115 + this.addClassifiedArg(classifier, arg);
  116 + classifier = null;
  117 + }
  118 + else
  119 + this.singularLaunchArgs.add(arg);
  120 + }
  121 + }
  122 +
  123 + if (classifier != null) this.singularLaunchArgs.add(classifier);
  124 + }
  125 +
  126 + public void addClassifiedArg(String classifiedArg, String arg)
  127 + {
  128 + this.launchArgs.put(classifiedArg, arg);
  129 + }
  130 +
  131 + /**
  132 + * @param gameDirectory
  133 + * @param assetsDirectory
  134 + */
  135 + public void provideRequiredArgs()
  136 + {
  137 + if (!this.launchArgs.containsKey("--version"))
  138 + this.addClassifiedArg("--version", LiteLoaderTweaker.VERSION);
  139 +
  140 + if (!this.launchArgs.containsKey("--gameDir") && this.gameDirectory != null)
  141 + this.addClassifiedArg("--gameDir", this.gameDirectory.getAbsolutePath());
  142 +
  143 + if (!this.launchArgs.containsKey("--assetsDir") && this.assetsDirectory != null)
  144 + this.addClassifiedArg("--assetsDir", this.assetsDirectory.getAbsolutePath());
  145 + }
  146 +
  147 + public String[] getLaunchArguments()
  148 + {
  149 + List<String> args = new ArrayList<String>();
  150 +
  151 + for (String singularArg : this.singularLaunchArgs)
  152 + args.add(singularArg);
  153 +
  154 + for (Entry<String, String> launchArg : this.launchArgs.entrySet())
  155 + {
  156 + args.add(launchArg.getKey().trim());
  157 + args.add(launchArg.getValue().trim());
  158 + }
  159 +
  160 + this.singularLaunchArgs.clear();
  161 + this.launchArgs.clear();
  162 +
  163 + return args.toArray(new String[args.size()]);
  164 + }
  165 +
  166 + /**
  167 + * @return
  168 + */
  169 + public List<String> getModFilterList()
  170 + {
  171 + return (this.parsedOptions.has(this.modsOption)) ? this.modsOption.values(this.parsedOptions) : null;
  172 + }
  173 +
  174 + /**
  175 + * @return
  176 + */
  177 + public List<String> getAPIsToLoad()
  178 + {
  179 + List<String> apisToLoad = new ArrayList<String>();
  180 + this.registerCoreAPIs(apisToLoad);
  181 + if (this.parsedOptions.has(this.apisOption))
  182 + {
  183 + apisToLoad.addAll(this.apisOption.values(this.parsedOptions));
  184 + }
  185 +
  186 + return apisToLoad;
  187 + }
  188 +
  189 + public File getOptionalDirectory(File baseDirectory, ArgumentAcceptingOptionSpec<String> option, String defaultDir)
  190 + {
  191 + if (this.parsedOptions.has(option))
  192 + {
  193 + String path = option.value(this.parsedOptions);
  194 + File dir = new File(path);
  195 + if (dir.isAbsolute())
  196 + return dir;
  197 +
  198 + return new File(baseDirectory, path);
  199 + }
  200 +
  201 + return new File(baseDirectory, defaultDir);
  202 + }
  203 +
  204 + @Override
  205 + public File getGameDirectory()
  206 + {
  207 + return this.gameDirectory;
  208 + }
  209 +
  210 + @Override
  211 + public File getAssetsDirectory()
  212 + {
  213 + return this.assetsDirectory;
  214 + }
  215 +
  216 + @Override
  217 + public String getProfile()
  218 + {
  219 + return this.profile;
  220 + }
  221 +
  222 + @Override
  223 + public File getModsFolder()
  224 + {
  225 + return this.getOptionalDirectory(this.gameDirectory, this.modsDirOption, "mods");
  226 + }
  227 +}
... ...