-
-
Notifications
You must be signed in to change notification settings - Fork 183
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add option to generate jars with baked in mixins #1583
Comments
I looked a bit more into the tools that exist for the neoforge build process. |
In (Neo)Forge, all the transformations (including Mixin) of class files must go through ModLauncher. Therefore, ModLauncher can be modified to export the transformed class files and load them directly if the mod list is not changed. |
That architecture makes this a lot easier. Mods can mixin/AT other mods right? In that case once any mod gets updated the whole cache has to be rebuilt, unless all transformers get indexed and hashed). |
If i am understanding this correctly, you are saying that modified classes should be built into mods so they can be used instead of mixins being applied (basically mixins being done at compile time) However this would not work in the event where multiple mods are mixing into the same classes as who's bundled class should be applied? Mod A's or Mod B's? |
No not at all. The idea is that on the first launch of the game all mods apply their transformations and all of the modified classes get cached and saved to the disk. (maybe even add a launch flag to just do this step then close the game) On the following game starts these cached class files then get used and all source transformation steps can be skipped. Every time a mod gets updated or added the whole class cache needs to be rebuilt but that is still way less often than doing it on every launch. The goal is to speed up the game load times on slower CPUs and to potentially allow graalvm native image generation for even better performance gains. This doesn't actually do something the mod loader isn't doing at the moment, this is just about reusing the intermediate output. |
There's one caveat I don't see a solution for: One of the core concepts of how modding is set up is that classes are loaded conditionally and on demand. This means that in a typical installations there may be hundreds of classes that won't classload. Trying to convert everything that's in a modded installation into class file that can be processed would run into countless classloading error---with no way of knowing which ones are real errors and which ones are classes that would never be loaded in the current setup. |
I am not that familiar with the (neo)forge mod loading structure so the assumptions in this are made based on the way fabric works. The modded game launch happens in roughly the following stages:
Correct me if I am wrong but my understanding is that at the moment all the transformations are applied every time an indexed class gets loaded. My proposal is to at the very least store all the transformed class code on disk after the transformation was applied and then let the class loaded load that transformed source instead of applying the transformations again. More ideally there should be another step in the launch:
This class transformation cache needs to be tagged with the combined information of all installed mods and their versions. If there is no change in the mod list the whole scanning for mixins and ATs can be skipped and we can just assume that the cache on disk is a complete list of all the classes after they were transformed. In the long run it might be worth considering exporting all sources to that cache. Note that none of this would require knowledge over which classes would be actually loaded or not. |
Some additional points to consider with this:
|
I'm not sure I understand what you're trying to say here. "Source" as in "the raw bytes of the class file as loaded from a jar"? That is not saved in memory. That is transformed and discarded. The result of the transformation is given to the JVM and then discarded, too. "time an indexed class gets loaded" makes it sound like that happens often. It's is at most once per game run. The JVM doesn't unload or gc code (unless you destroy a whole classloader context). |
graalvm has support for compiling java programs to the native platform in a feature called native image.
There have been several people that got this working for vanilla minecraft but so far these projects don't work for modded minecraft mainly because of mixins.
Mixins don't work in native code because most of the class information is gone as it got turned into native byte code.
This proposal is about adding a flag that generates binaries that have the mixins baked into them, so that they don't have to be reapplied on every launch again.
This might improve the game load time especially when a lot of mods are installed and it allows generating a native image using graalvm, as the runtime mixins are already applied.
It is already possible to output the patched classes using the
-Dmixin.debug.export=true
flag.This generates a
.mixin.out
dir in the.minecraft
dir with all of the mixed in java byte code classes.My idea would be to add a flag to first dump all the bytecode in that dir (excluding all mixins and mixin plugins) and then override the classes as the mixins get applied.
The mod loader should then make sure to run all the mixin plugins and apply all the mixins early, to spit out the patched bytecode.
All the assets and data dirs should be extracted as well and be turned into a giant resource and asset pack that can be loaded in one go as well.
In a second step the user can turn that output dir into a really big jar, that can be ran directly and has all the mod code in it.
This second step might need some mod loader changes to work correctly as this patched code must not try to load code from the mods dir, nor from the minecraft library dirs.
Since I am not a java dev some feedback on this is very appreciated.
In theory many parts of this can be done easily by just extracting the jars as zip into the
.mixin.out
(doing it recursively for the jar in jar files)and then ignoring the META-INF dir and removing the top level files (mixin configs and pack config).
While this process would result in a way slower first start time, following game launches could be significantly faster.
The text was updated successfully, but these errors were encountered: