Skip to content

Conversation

@GilbertzRivi
Copy link
Contributor

Fix Advanced AE compatibility on AE2CL

Added ASM shims (via mixin plugin) to add missing method overloads and a GuiText enum constant required by AAE.
Disabled AAE's CraftingService mixin via MixinSquared due to an AE2CL signature mismatch, and re-implement the behavior in our own mixin targeting the new signature.

Added a JVM flag (-Dmonilabs.mixin.verbose=true) to toggle verbose logging for the mixin plugin.

@GilbertzRivi
Copy link
Contributor Author

Now when I think about it, I can add those required overloads using normal mixin without ASM. Thats not the case for the enum entry and the constructor unfortunately. Ill try to rewrite them like that and update the PR.

@GilbertzRivi GilbertzRivi marked this pull request as draft December 31, 2025 18:22
@GilbertzRivi
Copy link
Contributor Author

Okay sorry, you can not add a public method using a mixin.

@GilbertzRivi GilbertzRivi marked this pull request as ready for review January 1, 2026 05:32
Copy link
Owner

@NegaNote NegaNote left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of this looks fine, but I'm going to need some explanation as to how all this works with ensuring these various mixin class things exist, like the special constructors etc. Otherwise the additions seem logical. I assume this has been thoroughly tested?

@GilbertzRivi
Copy link
Contributor Author

GilbertzRivi commented Jan 3, 2026

These shims are here so that the mixin plugin runs when it encounters them, to avoid a situation where we rely on running patches for classes x, y, and z based on a mixin that is not related to them at all. When it encounters the shim, it applies it "does nothing" and all the patching happens in the post apply part where its actually patching the target class using ASM.

The changes have been tested as much as I was able to test them myself. I tested all things that I made patches for and if the crafting works, if quantum cpu works, etc.

@NegaNote
Copy link
Owner

NegaNote commented Jan 3, 2026

How do the patches work?

@GilbertzRivi
Copy link
Contributor Author

Ill take ensurePpiNoAuthorOverloadExists as an example

  • it checks if the desired method (the encode without author param) exists in the class, if yes then we don't have to do anything so we return
  • checks if the method we are going to use exists (the encode with author param) if no then the patch can not be made so we return
  • then it creates a new method in the class using new MethodNode, makes it public, names it encode, provides the descriptor, does not provide generic signature and thrown exceptions because we don't need that
  • we get the instruction list of our new method InsnList insn = m.instructions; so we can add new instructions to it
  • then we add instructions, first we load all locals to the stack using insn.add(new VarInsnNode(Opcodes.ALOAD, 0/1/2)); 0 is this, 1 is the first arg etc, then we load "", for the "author" param we gonna use when calling the original method.
  • now the stack looks like (from bottom to top)
    1. this
    2. arg1
    3. arg2
    4. ""
  • Now we add the call to the original method with insn.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, PPI_INTERNAL, "encode", PPI_ENCODE_WITH_AUTHOR, false));. INVOKEVIRTUAL calls the method, PPI_INTERNAL is the class name of the target class but with / instead of ., encode is the name of the method we want to call, PPI_ENCODE_WITH_AUTHOR is the descriptor of the method we want to call, false on the end means that the owner is not an interface. That results in taking this, both args and "" from the stack, and calling this.encode(arg1, arg2, ""). The result of that method goes on the stack.
  • Now we return the result from the stack to the caller using insn.add(new InsnNode(Opcodes.ARETURN))

Long story short we just made return this.encode(arg1, arg2, ""); but using asm :)

the rest is as follows:

  • m.maxStack = 4 sets the stack depth to 4 things max, because at most we hold this, arg1, arg2, and "" at it.
  • m.maxLocals = 3 is the number of locals

At the end we add that method to the class using cn.methods.add(m);

the result is that we added a new function that's looking like

public R encode(A a, B b) {
    return this.encode(a, b, "");
}

@NegaNote NegaNote merged commit e25ca1b into NegaNote:main Jan 4, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants