-
Notifications
You must be signed in to change notification settings - Fork 2
Home
Making a PR or raising an issue would be more suitable
The @TargetHandler
selector allows any injector to target a handler that was added to the mixin'd class.
The handler takes in two required and two optional arguments:
-
mixin
: The fully qualified class name for the mixin the handler originates from.- Required
-
name
: The name of the handler method. Optionally followed by the descriptor.- Required
- This must be the exact name of the handler in the target mixin, if the handler is prefixed with the modid, then the
name
argument must also. - As of
0.1.2-beta.5
thename
argument behaves the same as the default selector'starget
such that now it can accept a full descriptor.
-
prefix
: The prefix added to the front of handler methods by Mixin.- Optional, will match the first prefix if not specified.
- See the table below for the prefixes.
-
print
: Print all possible candidates for the selector- Optional
- Will disable the selector matching.
When targetting a mixin'd handler with an injector, set the method parameter to @MixinSquared:Handler
to delegate the targeting to the dynamic selector.
Let's say the following mixin exists:
@Mixin(TargetClass.class)
public abstract class TargetClassMixin {
@Redirect(
method = "targetMethod",
at = @At(
value = "INVOKE",
target = "Lpackage/to/TargetClass;damage(Lpackage/to/class/DamageSource;F)Z"
)
)
private boolean handleDamage(TargetClass instance, DamageSource source, float amount) {
if(!AnotherMod.handleDamage(source, amount)) {
LOGGER.warn("Could not handle damage");
}
}
}
You may want to stop this mixin from always giving a warning when the mod doesn't handle the damage, and instead reduce the level to debug.
This can be done like so:
@Mixin(value = TargetClass.class, priority = 1500) // priority is higher than the target mixin
public abstract class TargetClassMixinSquared {
@TargetHandler(
mixin = "com.bawnorton.mixin.TargetClassMixin",
name = "handleDamage"
)
@Redirect(
method = "@MixinSquared:Handler",
at = @At(
value = "INVOKE",
target = "org/slf4j/Logger.warn(Ljava/lang/String;)V"
)
)
private void reduceLogLevel(Logger instance, String message) {
instance.debug(message);
}
}
The target handler can target other mod's mixin squared mixins as long as the priority is higher.
Targeting a handler with a specific prefix
Target mixin:
@Mixin(TargetClass.class)
public abstract class TargetClassMixin {
@Inject(method = "targetMethod", at = @At("HEAD"))
private void targetMethod(CallbackInfo ci) {
AnotherMod.doSomething();
}
@ModifyArg(
method = "targetMethod",
at = @At(
value = "INVOKE",
target = "Lpackage/to/TargetClass;someMethod(Lpackage/to/class/SomeClass;IIF)V"
)
)
private float targetMethod(float arg) {
return arg * 2;
}
}
Targeting @Inject
handler:
@Mixin(value = TargetClass.class, priority = 1500)
public abstract class TargetClassMixinSquared {
@TargetHandler(
mixin = "com.bawnorton.mixin.TargetClassMixin",
name = "targetMethod",
prefix = "handler"
)
@Inject(method = "@MixinSquared:Handler", at = @At("HEAD"))
private void doSomething(CallbackInfo originalCi, CallbackInfo ci) {
LOGGER.info("Injecting into handler$######$modid$targetMethod");
}
}
Targeting @ModifyArg
handler:
@Mixin(value = TargetClass.class, priority = 1500)
public abstract class TargetClassMixinSquared {
@TargetHandler(
mixin = "com.bawnorton.mixin.TargetClassMixin",
name = "targetMethod",
prefix = "modify"
)
@Inject(method = "@MixinSquared:Handler", at = @At("HEAD"))
private void doSomething(float arg, CallbackInfo ci) {
LOGGER.info("Injecting into modify$######$modid$targetMethod");
}
}
Targeting handler that explicitly contains the modid
Target mixin:
@Mixin(TargetClass.class)
public abstract class TargetClassMixin {
@Inject(method = "targetMethod", at = @At("HEAD"))
private void modid$targetMethod(CallbackInfo ci) {
AnotherMod.doSomething();
}
}
Targeting the handler:
@Mixin(value = TargetClass.class, priority = 1500)
public abstract class TargetClassMixinSquared {
@TargetHandler(
mixin = "com.bawnorton.mixin.TargetClassMixin",
name = "modid$targetMethod"
)
@Inject(method = "@MixinSquared:Handler", at = @At("HEAD"))
private void doSomething(CallbackInfo originalCi, CallbackInfo ci) {
LOGGER.info("Injecting into modid$targetMethod");
}
}
Targeting and using MixinExtras injectors
Target mixin:
@Mixin(TargetClass.class)
public abstract class TargetClassMixin {
@WrapOperation(
method = "targetMethod",
at = @At(
value = "INVOKE",
target = "Lpackage/to/TargetClass;someMethod(Lpackage/to/class/SomeClass;IIF)Z"
)
)
private boolean targetMethod(TargetClass instance, SomeClass someClass, int i, int j, float f, Operation<Boolean> original) {
boolean originalResult = original.call(instance, someClass, i, j, f);
return originalResult || AnotherMod.someMethod(someClass);
}
}
Changing the returned value of the AnotherMod.someMethod
call:
@Mixin(value = TargetClass.class, priority = 1500)
public abstract class TargetClassMixinSquared {
@TargetHandler(
mixin = "com.bawnorton.mixin.TargetClassMixin",
name = "targetMethod"
)
@ModifyExpressionValue(
method = "@MixinSquared:Handler",
at = @At(
value = "INVOKE",
target = "Lpackage/to/AnotherMod;someMethod(Lpackage/to/class/SomeClass;)Z"
)
)
private boolean checkOwnMethod(boolean original) {
return original && YourMod.someMethod();
}
}
Annotation | Prefix |
---|---|
@Inject | handler |
@ModifyArg | modify |
@ModifyArgs | args |
@ModifyConstant | constant |
@ModifyVariable | localvar |
@Redirect | redirect |
Mixin Extras | |
@ModifyExpressionValue | modifyExpressionValue |
@ModifyReciever | modifyReciever |
@ModifyReturnValue | modifyReturnValue |
@WrapWithCondition | wrapWithCondition |
@WrapOperation | wrapOperation |