Before someone tells me to write CoreMod: I do NOT need to use any minecraft/minecraftforge classes.
I’m trying to write a plugin that needs to load a .jar file and transform its classes before loading them.
After a few (partially successful) attempts to write my own ASM transformation code I realized that what I really need is exactly what Sponge Mixins allow to do. So even if I write my oen ASM transformation code - it would be just a more broken and more limited implementation of mixins.
Is there any way to use Mixins that way? Or do I need to use some other library? I already tried to add it as dependency the same way sponge does it but it apparently needs ForgeGradle which I don’t thing I have any reason to use.
The thing is, you’d need to be a Core mod to use ANY sort of class transformations during class load. The other issue is that plugins won’t be able to do this in SpongeVanilla since it’s simply not supported.
If you have to write your own class loader to perform your own class transformations on your own plugin, then honestly, there’s something wrong with your plugin’s design. Perhaps you could explain why you need to go to such lengths for a SpongeAPI plugin?
My first bukkit plugin was called “173generator” and allowed to generate exactly the same terrain as beta 1.7.3 minecraft but in newer versions. It actually works with latest craftbukkit.
Ths thing is that there are most likely some legal issues with doing that and it may end simillar to craftbukkit.
I want to write a plugin that would load old Minecraft jar (provided by user), and transforms terrain generator classes to use my internal API that mimics Minecraft “API” (if it can be called API) from that Minecraft version.
I sort of got it working previously, with Javassist library. But I couldn’t do runtime deobfuscation which made it mearly inpossibley to do anything useful. It was able to generate basic terrain shape (stone+caves+dirt/grass). Then my next few attempts used ASM library. And this is when I realized that I need the same functionality as Mixins provide.
Note: I created my own deobfuscation mappings, I’m not going to use MCP
I’m not going to give up simply because there is plugin that does part of what I want to do.
I planned to eventually support more than just alpha/beta worldgen.
If I can’t use the sponge mixins library, is there other library that does something simillar?
You should come and talk to me on IRC at some point, as I’ll be able to guide you better. I’m in a bit of a hurry at the moment so this will be kind of brief:
Short answer, in bullet point form:
yes you can leverage Mixin to do what you want
I strongly advise against using your own classloader for two reasons:
The classloader setup in Minecraft is pretty hairy as it is, it uses an inverted form of usual classloader delegation order and adding more classloaders into the mix without really compelling reasons to do so is a really bad idea unless you can contractually guarantee that your other classloader is utterly ring-fenced, which is damn near impossible. For example if your ring-fenced classloader even references just one guava or apache commons class then you’re going to have a bad time or create class circularity errors which will be a giant bitch to troubleshoot.
It’s not necessary anyway, since the LaunchWrapper classloader has all the functionality you need and will need if you want a quiet life, so there’s no need to segregate things anyway.
Normally @gabizou would be right, to leverage Mixin you must be a coremod because only coremods get access to the game early enough in initialisation to actually register mixin and add the class transformation info you need into it. However, because you’re talking about deploading a jar yourself you buy a ticket because:
You know mixin is already injected and initialised at this point
I’m working (currently) on multi-phase support in Mixin, and this will allow you to inject and trigger your own totally custom phase
Your custom phase can be triggered after you depload the other jar into the classpath
There’s another consideration however, which is that if you’re adding a jar to the classpath which may include items which already exist, you may want to still pursue the custom classloader route to act as a filter for your jar, and have it delegate upward (the same way the LaunchWrapper classloader does) to the LaunchWrapper classloader as its parent (to leverage transformers).
Forge’s runtime deobf may bite you here, since the classes you’re loading may have the same (obf) names as current obf classes, and will get renamed at load time to whatever their corresponding counterparts in the current version are, which will (a) prevent your mixins from working and (b) probably cause the world to explode, so you will probably want your custom classloader to pre-emptively rename (to some deterministic mapping) the classes in your custom jar as well.
You can’t just create a separate transformer chain because some stuff in LaunchWrapper (key parts at least) rely on static references to certain class instances, especially the classloader itself.
What you want to do is possible, but be aware that (for legal reasons) the classloader setup is a whole lot more delicate and a butt-load more complex than under Bukkit, a lot of complicated stuff is done at runtime (which Bukkit never did) and I urge you to tread delicately and carefully before diving in because things which seem innocent can have unforseen side-effects which will make everyone hate you (believe me, I found this out the hard way over the last 5 years)
You did the right thing coming here to ask, I urge you to jump on IRC at some point to discuss it in more detail. What you want to do is possible, but there are a bunch of classloader landmines and booby-traps you’ll need to be aware of in advance so that you can avoid them.
Thank you for reply (finally what I actually wanted to know)
I knew that not renaming classes would be a bad idea because if I load many jars they would even conflict with each other.
So I need to add some package “prefix” to each of them.
If I understand you correctly it will need to be a forge mod anyway because it needs access to Sponge mixins, right?
I initially wanted to make bukkit port of it too but now I don’t think it would be a good idea (it will probably be impossible to get Mixins working on bukkit).
I’m actually on IRC for a few hours and I’m not going anywhere anytime soon.