magneticflux- / fabric-mumblelink-mod

A Fabric mod that connects to the MumbleLink plugin.
GNU Lesser General Public License v3.0
52 stars 13 forks source link

Crash Upon Loading Singleplayer World #58

Open TreyRuffy opened 3 years ago

TreyRuffy commented 3 years ago

Describe The Bug Whenever I start a singleplayer world (newly created or old world), my game crashes because "Desktop API is not supported on the current platform"

To Reproduce Steps

Version Information

My Mods

Additional Context All of my mods work together when MumbleLink is not loaded. I can go through each mod to see if I can find the problem, but that will take quite a bit of time, which I do not have at the time of writing this issue. The outputted error link is: https://paste.ee/p/Ncttt

magneticflux- commented 3 years ago

The issue is with Optifine, the logged message just before the crash gives a hint:

[13:42:51] [Netty Local Client IO #0/INFO]: [STDERR]: Unable to unset headless earlier (are you using OptiFine?), doing it with nasty reflection now!
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.skaggsm.mumblelinkmod.ClientMumbleLinkMod (file:/C:/Users/Treyr/AppData/Roaming/MultiMC/instances/1.16.4%20-%20Fabric/.minecraft/mods/fabric-mumblelink-mod-0.7.5.jar) to field java.awt.GraphicsEnvironment.headless
WARNING: Please consider reporting this to the maintainers of com.skaggsm.mumblelinkmod.ClientMumbleLinkMod
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
[13:42:51] [Netty Local Client IO #0/ERROR]: Encountered exception while handling in channel with name "fabric-mumblelink-mod:broadcast_mumble_url"
java.lang.UnsupportedOperationException: Desktop API is not supported on the current platform
    at java.awt.Desktop.getDesktop(Desktop.java:303) ~[?:?]

I'll need to test with Optifine again and figure out what hacky nonsense it's doing now, and how to work around it.

TreyRuffy commented 3 years ago

The issue is with Optifine, the logged message just before the crash gives a hint:

[13:42:51] [Netty Local Client IO #0/INFO]: [STDERR]: Unable to unset headless earlier (are you using OptiFine?), doing it with nasty reflection now!
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.skaggsm.mumblelinkmod.ClientMumbleLinkMod (file:/C:/Users/Treyr/AppData/Roaming/MultiMC/instances/1.16.4%20-%20Fabric/.minecraft/mods/fabric-mumblelink-mod-0.7.5.jar) to field java.awt.GraphicsEnvironment.headless
WARNING: Please consider reporting this to the maintainers of com.skaggsm.mumblelinkmod.ClientMumbleLinkMod
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
[13:42:51] [Netty Local Client IO #0/ERROR]: Encountered exception while handling in channel with name "fabric-mumblelink-mod:broadcast_mumble_url"
java.lang.UnsupportedOperationException: Desktop API is not supported on the current platform
  at java.awt.Desktop.getDesktop(Desktop.java:303) ~[?:?]

I'll need to test with Optifine again and figure out what hacky nonsense it's doing now, and how to work around it.

While that warning does occur, even with Optifine disabled the error is sent. Here is the log file without Optifine enabled. https://paste.ee/p/Zoy47

EDIT: The mod causing the problem is 5zig Reborn.

magneticflux- commented 3 years ago

It's strange that 5zig would be causing the issue, as it uses Desktop.getDesktop().browse(...) as well. They wrote some cursed fallback code here though: https://github.com/5zig-reborn/The-5zig-Mod/blob/master/mod/src/main/java/eu/the5zig/util/BrowseUrl.java

magneticflux- commented 3 years ago

Can you try using AdoptOpenJDK Hotspot instead of OpenJ9? It shouldn't make a difference... but it might?

TreyRuffy commented 3 years ago

That did not work either. Here is the log: https://paste.ee/p/1RrNh

TreyRuffy commented 3 years ago

Okay, I think I have found the culprit. Through a bit of trial and error, it looks like ViaFabric and 5zig Reborn together cause the error.

Logs:

magneticflux- commented 3 years ago

Thanks so much for narrowing it down to those two mods! I'll read through the code of each of them and see if I can understand how they would interact to cause this issue.

magneticflux- commented 3 years ago

Here's my preliminary guess as to what might be happening:

The specific combination of mods you're using causes Fabric to load them in a certain order (5zip Reborn first, then MumbleLink).

Loading 5zip Reborn before MumbleLink is an issue because when MumbleLink is initialized, it sets the java.awt.headless property to false. If this isn't done yet, any calls to Desktop.getDesktop() will create and return the "headless" variant of the object, which disables a lot of functionality. This object is cached, so even if MumbleLink sets the property later, it won't do anything.

magneticflux- commented 3 years ago

I've tracked down where it's being called in 5zip Reborn.

  1. The5zigMod.init() is being called somewhere early. I don't know exactly where because the mod uses a bunch of bytecode manipulation to call methods, but it's definitely before Fabric initializes fully or even has a chance to run pre-launch entrypoints.

  2. This is bad because it causes the TrayManager class to be initialized.

  3. This is bad because it schedules a new thread to call its run method.

  4. This is bad because it (indirectly) calls Toolkit.getDefaultToolkit() (the method that Desktop.getDesktop() indirectly calls)!

My new theory is using even more reflection hacks to "reset" the initialized Toolkit after setting the headless property false.

The real question is: why is headless mode even enabled by default for you?

As a quick workaround, you can add the flag -Djava.awt.headless=false when you start Minecraft. That should clear up any issues.

magneticflux- commented 3 years ago

Here's a test build (in a zip) that has the more aggressive reflection hacks: fabric-mumblelink-mod-0.7.6.zip

Can you test it out and see if it fixes your issue? It seems like it works in my dev environment.

magneticflux- commented 3 years ago

Here's another test build that might work better in some cases! fabric-mumblelink-mod-0.7.6.zip

I'm fairly confident that this build will work, so I'm preparing a full release as soon as you have a chance to test the fix.

TreyRuffy commented 3 years ago

Here's a test build (in a zip) that has the more aggressive reflection hacks: fabric-mumblelink-mod-0.7.6.zip

Can you test it out and see if it fixes your issue? It seems like it works in my dev environment.

I tested and this works well. I do not see any problems.


Here's another test build that might work better in some cases! fabric-mumblelink-mod-0.7.6.zip

I'm fairly confident that this build will work, so I'm preparing a full release as soon as you have a chance to test the fix.

This one also works but I am getting a warning which does not appear in the first test build. Here is the error I am getting when starting Minecraft:

[20:34:14] [Tray/WARN]: Could not load Minecraft Icon!
java.lang.IllegalArgumentException: input == null!
    at javax.imageio.ImageIO.read(ImageIO.java:1356) ~[?:?]
    at eu.the5zig.mod.manager.TrayManager.loadMinecraftIcon(TrayManager.java:68) [5zig-Reborn-1.16.1-b251.jar:?]
    at eu.the5zig.mod.manager.TrayManager.run(TrayManager.java:57) [5zig-Reborn-1.16.1-b251.jar:?]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
    at java.lang.Thread.run(Thread.java:836) [?:?]

https://paste.ee/p/C7wKz

magneticflux- commented 3 years ago

I think that's being caused by the TrayManager feature working for the first time. Without the fixed version of MumbleLink, it would check for java.awt.headless and disable itself if it was true. Now that it's being set to false much sooner (before TrayManager can even check), it can actually initialize and try to load a tray icon.

The value is null because in the 1.16 version-specific code, the Variables.getMinecraftIcon() method just returns null. It's been that way since 1.14; 1.12 has code to use the default resource pack icon.