fabric-loader icon indicating copy to clipboard operation
fabric-loader copied to clipboard

AppletLoader should not assume that all "applets" are true Applets

Open PhoenixVX opened this issue 4 years ago • 1 comments

This is something that most people will not notice, but in the case of old versions such as rd-132211, the Applet is not a "true applet," but instead a Runnable like so.

public class MinecraftApplet implements Runnable {...}

AppletLoader assumes that the object that is passed in is an Applet and will fail because of invalid cast. Such as the error below:

[19:53:26] [main/INFO] (Fabric|Loader) [FabricLoader] Loading 4 mods: minecraft@132211, java@15, [email protected], [email protected]
[19:53:26] [main/INFO] (mixin) SpongePowered MIXIN Subsystem Version=0.8.2 Source=file:/C:/Users/Zer0/.gradle/caches/modules-2/files-2.1/net.fabricmc/sponge-mixin/0.8.2+build.24/e5a741445d0f425bf3cce946c6cf8c7fb8376b2/sponge-mixin-0.8.2+build.24.jar Service=Knot/Fabric Env=CLIENT
[19:53:26] [main/INFO] (Fabric|MixinBootstrap) Loaded Fabric development mappings for mixin remapper!
Hello Fabric world!
Exception in thread "main" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
	at net.fabricmc.loader.game.MinecraftGameProvider.launch(MinecraftGameProvider.java:228)
	at net.fabricmc.loader.launch.knot.Knot.init(Knot.java:139)
	at net.fabricmc.loader.launch.knot.KnotClient.main(KnotClient.java:27)
	at net.fabricmc.devlaunchinjector.Main.main(Main.java:86)
Caused by: java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at net.fabricmc.loader.game.MinecraftGameProvider.launch(MinecraftGameProvider.java:226)
	... 3 more
Caused by: java.lang.ClassCastException: class com.mojang.minecraft.MinecraftApplet cannot be cast to class java.applet.Applet (com.mojang.minecraft.MinecraftApplet is in unnamed module of loader net.fabricmc.loader.launch.knot.KnotClassLoader @46cdf8bd; java.applet.Applet is in module java.desktop of loader 'bootstrap')
	at net.fabricmc.loader.entrypoint.applet.AppletLauncher.<init>(AppletLauncher.java:64)
	at net.fabricmc.loader.entrypoint.applet.AppletFrame.launch(AppletFrame.java:91)
	at net.fabricmc.loader.entrypoint.applet.AppletMain.main(AppletMain.java:37)
	... 8 more

The lucky part about this is that the onInitialize method has a chance to call the Applet as a Runnable like so:

// This is a workaround to let loader load the class.
try {
    MinecraftApplet clazz = (MinecraftApplet) FabricLauncherBase.getLauncher().getTargetClassLoader().loadClass(EntrypointTransformer.appletMainClass).getDeclaredConstructor().newInstance();
    clazz.run();
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | ClassNotFoundException e) {
    e.printStackTrace();
}

Honestly, should not assume that it's a "true applet" or have a fallback to a generic Runnable runner.

PhoenixVX avatar Jan 23 '21 02:01 PhoenixVX

The problem with the lucky part above is that the "Applet" is called again after each closing and requires external intervention to stop the program. And it's hacky, so I don't like it.

PhoenixVX avatar Jan 23 '21 02:01 PhoenixVX