Mixin Annotation Adjuster - Bawnorton/MixinSquared GitHub Wiki
Making a PR or raising an issue would be more suitable
MixinSquared provides a way to manipulate the annotations used in Mixins that would normally be out of a user's control as other mod's mixins are not passed through their IMixinConfigPlugin.
To use the adjuster is you need to implement the MixinAnnotationAdjuster interface and then register it.
public class YourModMixinAnnotationAdjuster implements MixinAnnotationAdjuster {
@Override
public AdjustableAnnotationNode adjust(List<String> targetClassNames, String mixinClassName, MethodNode method, AdjustableAnnotationNode annotation) {
// To leave the annotation unchanged simply:
/* return annotation; */
// You can check if you're inside a specific mixin and targetting a specific annotation:
if(!mixinClassName.equals("com.bawnorton.sandbox.mixin.LivingEntityMixin")) return annotation;
if(!annotation.is(WrapOperation.class)) return annotation;
// You can now safely cast to the appropriate AdjustableAnnotationNode:
// Use a normal cast or the "as" helper if you wish to chain method calls instead
AdjustableWrapOperationNode wrapOpNode = annotation.as(AdjustableWrapOperationNode.class);
// If you want to narrow down the search even further, helper methods are provided for each adjustable node to query their attributes.
if(wrapOpNode.getAt() // "at = "
.get(0) // at accepts an array so "getAt" returns a list
.getTarget() // "target = "
.equals("Lnet/minecraft/entity/LivingEntity;getWorld()Lnet/minecraft/world/World;")) {
// You can remove the annotation entirely, the specified annotation will not be present when the mixin is applied and thus, will not be injected.
// The handler will still be present in the resultant mixin, it'll just be treated as a normal merged method.
return null;
} else {
// You can also modify the node directly with use of the helper methods.
return wrapOpNode.withAt(at -> {
at.get(0)
.setOrdinal(1); // "ordinal = "
return at;
});
}
}
}Available in 0.3.0-beta.1+
Since the Annotation Adjuster interacts with what Mixin uses as keys for the refmap (i.e At.target()) you may want to remap the remappable parts of the annotation first before making your changes as once a change is made to a refmap key, the remapped value will not be found, causing the mixin to fail to find its target.
By using RemappableAnnotationNode#applyRefmap, the refmap will be applied earlier in the process, allowing you to make changes to the remapped values.
Example Usage:
// compare against unobfuscated name
if(injectAnnotatioNode.getMethod().contains("someMethod(II)Z")) {
// remap to obfuscated name: someMethod(II)Z -> obfuscated_name(II)Z
injectAnnotationNode.applyRefmap();
injectAnnotationNode.withMethod(methods -> {
// would cause targetting to fail if applyRefmap was not called
methods.get(0).replace("II)Z", "IIF)Z");
return methods;
}
}This will always remap regardless of whether you are in a dev environment or not, as long as there is a refmap key value pair for the remappable elmenets they will be remapped
All AdjustableAnnotationNode classes that are provided have getAttribute, setAttribute and withAttribute helper methods for querying and adjusting the annotation they represent.
AdjustableAnnotationNode can represent an annotation that is not recognised but there will be no helper methods, instead you can use:
-
<T>get(String key)->Optional<T>to query an attribute. -
getEnum(String key, Class<T> enumClass)->Optional<T>to query an enum attribute. -
set(String key, Object value)->voidto set a value.
There are minimal checks on these methods as they interact directly with the node which allows you to set or query attributes which do not normally exist on the annotation which can cause crashes.
Inside your fabric.mod.json you will need to add the following entrypoint:
"entrypoints": {
"mixinsquared-adjuster": [
"com.example.mod.YourModMixinAnnotationAdjuster"
]
}You will need to declare a service called com.bawnorton.mixinsquared.api.MixinAnnotationAdjuster inside the META-INF/services/ directory.
The content of this file will need to be a reference to your MixinAnnotationAdjuster implementation(s):
com.example.mod.YourModMixinAnnotationAdjuster
In the onLoad method inside a IMixinConfigPlugin you can register a MixinAnnotationAdjuster directly using the MixinAnnotationAdjusterRegistrar like so:
public class YourModMixinConfigPlugin implements IMixinConfigPlugin {
@Override
public void onLoad(String mixinPackage) {
MixinAnnotationAdjusterRegistrar.register(new YourModMixinAnnotationAdjuster());
}
...
}