Commit aecc5dcf6d2d0ccb9de81de87d2eeb6a9179b529
1 parent
f2549841
cleaning up the tweaker a bit, moving logic to separate StartupEnvironment class
Showing
7 changed files
with
411 additions
and
287 deletions
java/common/com/mumfrey/liteloader/core/LiteLoaderBootstrap.java
@@ -30,6 +30,7 @@ import com.mumfrey.liteloader.interfaces.LoaderEnumerator; | @@ -30,6 +30,7 @@ import com.mumfrey.liteloader.interfaces.LoaderEnumerator; | ||
30 | import com.mumfrey.liteloader.launch.LoaderBootstrap; | 30 | import com.mumfrey.liteloader.launch.LoaderBootstrap; |
31 | import com.mumfrey.liteloader.launch.LoaderEnvironment; | 31 | import com.mumfrey.liteloader.launch.LoaderEnvironment; |
32 | import com.mumfrey.liteloader.launch.LoaderProperties; | 32 | import com.mumfrey.liteloader.launch.LoaderProperties; |
33 | +import com.mumfrey.liteloader.launch.StartupEnvironment; | ||
33 | import com.mumfrey.liteloader.util.log.LiteLoaderLogger; | 34 | import com.mumfrey.liteloader.util.log.LiteLoaderLogger; |
34 | 35 | ||
35 | /** | 36 | /** |
@@ -143,17 +144,17 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP | @@ -143,17 +144,17 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP | ||
143 | * @param assetsDirectory | 144 | * @param assetsDirectory |
144 | * @param profile | 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 | this.versionedModsFolder = new File(this.modsFolder, LiteLoaderVersion.CURRENT.getMinecraftVersion()); | 158 | this.versionedModsFolder = new File(this.modsFolder, LiteLoaderVersion.CURRENT.getMinecraftVersion()); |
158 | this.configBaseFolder = new File(this.gameDirectory, "liteconfig"); | 159 | this.configBaseFolder = new File(this.gameDirectory, "liteconfig"); |
159 | this.logFile = new File(this.configBaseFolder, "liteloader.log"); | 160 | this.logFile = new File(this.configBaseFolder, "liteloader.log"); |
@@ -169,7 +170,7 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP | @@ -169,7 +170,7 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP | ||
169 | if (!this.commonConfigFolder.exists()) this.commonConfigFolder.mkdirs(); | 170 | if (!this.commonConfigFolder.exists()) this.commonConfigFolder.mkdirs(); |
170 | if (!this.versionConfigFolder.exists()) this.versionConfigFolder.mkdirs(); | 171 | if (!this.versionConfigFolder.exists()) this.versionConfigFolder.mkdirs(); |
171 | 172 | ||
172 | - this.initAPIs(apisToLoad); | 173 | + this.initAPIs(env.getAPIsToLoad()); |
173 | this.apiProvider = this.apiRegistry.getProvider(); | 174 | this.apiProvider = this.apiRegistry.getProvider(); |
174 | this.apiAdapter = this.apiRegistry.getAdapter(); | 175 | this.apiAdapter = this.apiRegistry.getAdapter(); |
175 | } | 176 | } |
@@ -242,6 +243,18 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP | @@ -242,6 +243,18 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP | ||
242 | return this.environmentType; | 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 | /* (non-Javadoc) | 258 | /* (non-Javadoc) |
246 | * @see com.mumfrey.liteloader.launch.ILoaderBootstrap#preInit(net.minecraft.launchwrapper.LaunchClassLoader, boolean) | 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,7 +320,7 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP | ||
307 | // PreInit failed | 320 | // PreInit failed |
308 | if (this.enumerator == null) return; | 321 | if (this.enumerator == null) return; |
309 | 322 | ||
310 | - LiteLoader.createInstance(this, this, classLoader); | 323 | + LiteLoader.createInstance(this.getEnvironment(), this.getProperties(), classLoader); |
311 | LiteLoader.invokeInit(); | 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,19 +5,11 @@ import java.lang.reflect.Constructor; | ||
5 | import java.lang.reflect.Method; | 5 | import java.lang.reflect.Method; |
6 | import java.net.URL; | 6 | import java.net.URL; |
7 | import java.net.URLClassLoader; | 7 | import java.net.URLClassLoader; |
8 | -import java.util.ArrayList; | ||
9 | -import java.util.HashMap; | ||
10 | import java.util.HashSet; | 8 | import java.util.HashSet; |
11 | import java.util.List; | 9 | import java.util.List; |
12 | -import java.util.Map; | ||
13 | -import java.util.Map.Entry; | ||
14 | import java.util.Set; | 10 | import java.util.Set; |
15 | import java.util.TreeSet; | 11 | import java.util.TreeSet; |
16 | 12 | ||
17 | -import joptsimple.ArgumentAcceptingOptionSpec; | ||
18 | -import joptsimple.NonOptionArgumentSpec; | ||
19 | -import joptsimple.OptionParser; | ||
20 | -import joptsimple.OptionSet; | ||
21 | import net.minecraft.launchwrapper.ITweaker; | 13 | import net.minecraft.launchwrapper.ITweaker; |
22 | import net.minecraft.launchwrapper.Launch; | 14 | import net.minecraft.launchwrapper.Launch; |
23 | import net.minecraft.launchwrapper.LaunchClassLoader; | 15 | import net.minecraft.launchwrapper.LaunchClassLoader; |
@@ -33,11 +25,13 @@ import com.mumfrey.liteloader.util.log.LiteLoaderLogger; | @@ -33,11 +25,13 @@ import com.mumfrey.liteloader.util.log.LiteLoaderLogger; | ||
33 | */ | 25 | */ |
34 | public class LiteLoaderTweaker implements ITweaker | 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 | * Loader startup state | 37 | * Loader startup state |
@@ -170,172 +164,159 @@ public class LiteLoaderTweaker implements ITweaker | @@ -170,172 +164,159 @@ public class LiteLoaderTweaker implements ITweaker | ||
170 | 164 | ||
171 | private static LiteLoaderTweaker instance; | 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 | * Loader bootstrap object | 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 | * Transformer manager | 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 | @Override | 189 | @Override |
205 | public void acceptOptions(List<String> args, File gameDirectory, File assetsDirectory, String profile) | 190 | public void acceptOptions(List<String> args, File gameDirectory, File assetsDirectory, String profile) |
206 | { | 191 | { |
207 | Launch.classLoader.addClassLoaderExclusion("com.google.common."); | 192 | Launch.classLoader.addClassLoaderExclusion("com.google.common."); |
208 | - | ||
209 | LiteLoaderTweaker.instance = this; | 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 | @Override | 322 | @Override |
@@ -371,21 +352,7 @@ public class LiteLoaderTweaker implements ITweaker | @@ -371,21 +352,7 @@ public class LiteLoaderTweaker implements ITweaker | ||
371 | @Override | 352 | @Override |
372 | public String[] getLaunchArguments() | 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 | public static boolean addCascadedTweaker(String tweakClass, int priority) | 358 | public static boolean addCascadedTweaker(String tweakClass, int priority) |
@@ -485,21 +452,21 @@ public class LiteLoaderTweaker implements ITweaker | @@ -485,21 +452,21 @@ public class LiteLoaderTweaker implements ITweaker | ||
485 | return false; | 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 | if (!StartupState.PREPARE.isInState()) | 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 | try | 462 | try |
496 | { | 463 | { |
497 | @SuppressWarnings("unchecked") | 464 | @SuppressWarnings("unchecked") |
498 | Class<? extends LoaderBootstrap> bootstrapClass = (Class<? extends LoaderBootstrap>)Class.forName(bootstrapClassName, false, classLoader); | 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 | bootstrapCtor.setAccessible(true); | 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 | catch (Throwable th) | 471 | catch (Throwable th) |
505 | { | 472 | { |
@@ -508,113 +475,6 @@ public class LiteLoaderTweaker implements ITweaker | @@ -508,113 +475,6 @@ public class LiteLoaderTweaker implements ITweaker | ||
508 | 475 | ||
509 | return null; | 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 | public static URL getJarUrl() | 479 | public static URL getJarUrl() |
620 | { | 480 | { |
java/common/com/mumfrey/liteloader/launch/LiteLoaderTweakerServer.java
1 | package com.mumfrey.liteloader.launch; | 1 | package com.mumfrey.liteloader.launch; |
2 | 2 | ||
3 | +import java.io.File; | ||
4 | +import java.net.URL; | ||
3 | import java.util.List; | 5 | import java.util.List; |
4 | 6 | ||
7 | +import net.minecraft.launchwrapper.Launch; | ||
8 | + | ||
5 | public class LiteLoaderTweakerServer extends LiteLoaderTweaker | 9 | public class LiteLoaderTweakerServer extends LiteLoaderTweaker |
6 | { | 10 | { |
7 | @Override | 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 | @Override | 33 | @Override |
14 | public String getLaunchTarget() | 34 | public String getLaunchTarget() |
15 | { | 35 | { |
@@ -17,10 +37,4 @@ public class LiteLoaderTweakerServer extends LiteLoaderTweaker | @@ -17,10 +37,4 @@ public class LiteLoaderTweakerServer extends LiteLoaderTweaker | ||
17 | 37 | ||
18 | return "net.minecraft.server.MinecraftServer"; | 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,4 +42,8 @@ public interface LoaderBootstrap | ||
42 | public abstract List<String> getRequiredDownstreamTransformers(); | 42 | public abstract List<String> getRequiredDownstreamTransformers(); |
43 | 43 | ||
44 | public abstract List<String> getPacketTransformers(); | 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,7 +16,7 @@ import com.mumfrey.liteloader.interfaces.LoaderEnumerator; | ||
16 | * | 16 | * |
17 | * @author Adam Mummery-Smith | 17 | * @author Adam Mummery-Smith |
18 | */ | 18 | */ |
19 | -public interface LoaderEnvironment | 19 | +public interface LoaderEnvironment extends GameEnvironment |
20 | { | 20 | { |
21 | public enum EnvironmentType | 21 | public enum EnvironmentType |
22 | { | 22 | { |
@@ -47,26 +47,6 @@ public interface LoaderEnvironment | @@ -47,26 +47,6 @@ public interface LoaderEnvironment | ||
47 | public abstract LoaderEnumerator getEnumerator(); | 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 | * Get the version-specific mods folder | 50 | * Get the version-specific mods folder |
71 | */ | 51 | */ |
72 | public abstract File getVersionedModsFolder(); | 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 | +} |