MixinProbe
What Mixin merges into its targets, read off Mixin's own model — the prepared configs and the MixinInfos under them — rather than by applying anything to a class.
Game-loader side: the ClassNode Mixin hands back belongs to the host's ASM, and the masking loader has its own copy of that class, so only Decls crosses the seam.
Why so little is carried
Mixin renames a merged member exactly when nothing outside could name it: an injector handler becomes handler$<uid>$…, a non-public @Unique becomes md<session>$…, and a static @Accessor lands on the target as …_$md$<session>$<n> — where session is a fresh UUID per launch, so a name recorded today is wrong tomorrow. The converse is what this rests on: what Mixin does not rename is exactly what source is allowed to write, because renaming it would break the callers.
So the overlay carries two things:
the INTERFACES a mixin adds. Their members are already declared on the interface's own class file, which is an ordinary classpath entry, so the target needs the
implementsentry and nothing more — and an interface name is never renamed.PUBLIC merged members, for a mixin that adds them with no interface to reach them through.
and nothing else. Handlers are modifications, not additions. Static @Accessor/@Invoker are called as Iface.foo(), so the interface alone already compiles. Anything below public is out of a snippet's reach regardless — it is neither in the package nor a subclass.
Every touch is reflective and none of it is API. Any failure degrades to "no overlay", which costs a snippet a cast.
Types
A class's declarations. Declared here, in a package the masking loader delegates, so both sides see one type and nothing has to be flattened to cross.
Properties
Functions
name's own declarations, read straight off its class file. No Mixin involved: this is asked about an added INTERFACE, which is an ordinary classpath class. Null when it cannot be read.
Annotation descriptors that mark a member as something other than a plain addition.