*and cause the mixin to be applied to a method that they don't (probably shouldn't) match.
The result of this is having mixins that work in development but generate unnecessary headaches further down the line when they fail the build condition, or that might make their way into production since testing them normally doesn't produce any sort of error.
What I expected to happen: The game should have crashed with an exception saying it did not find the target method.
What actually happened: The game did not crash, and the mixin was applied to a method that it should not have been able to match given the incorrect descriptor.
Below is a more detailed description of my setup and how exactly I managed to encounter this weird... bug?
The method I'm injecting into looks like this (located in net.minecraft.client.render.GameRenderer):
public static float getNightVisionStrength(LivingEntity livingEntity, float f)
And it has a target descriptor that should look like this when used in a mixin:
getNightVisionStrength(Lnet/minecraft/entity/LivingEntity;F)F
Now I wrote my mixin like this (details omitted):
@Mixin(GameRenderer.class)
abstract class MixinGameRenderer {
@Inject(method = "getNightVisionStrength(FJLnet/minecraft/entity/LivingEntity;F)F",
at = @At("HEAD"),
cancellable = true)
private static void onGetNightVisionStrengthHead(LivingEntity entity, float tickDelta, CallbackInfoReturnable<Float> info) {
}
}
You will notice it has an ever so slightly, hard to notice typo. Do you see it? There's an additional "FJ" - float and long that snuck in there when copying from another method.
What this means is that the target descriptor does not match any known (or existing) methods in that class, and indeed it doesn't, as when doing a build through gradle it fails and produces the following two errors, as expected:
warning: Cannot find target method for @Inject in net.minecraft.client.render.GameRenderer
@Inject(method = "getNightVisionStrength(FJLnet/minecraft/entity/LivingEntity;F)F",
^
error: No obfuscation mapping for @Inject target getNightVisionStrength
@Inject(method = "getNightVisionStrength(FJLnet/minecraft/entity/LivingEntity;F)F",
^
This is correct.
Based on these I wouldn't expect the game to even run when there are mixins that cannot find their target methods,
however, the problem arises when I do run the project in my IDE (as I normally do to test my code - building with gradle is usually the last step to obtain a jar I cna distribute):
When I run the game it "works", and I don't mean it "prints a warning and keeps running with my callback never being executed" I mean it works. The mixin is applied to the intended method, and the callback is executed as desired, somehow despite the descriptor not actually being correct!
I would understand it behaving like this when I specify only he method name in the @Inject annotation, however I've given it a full explicit method descriptor. Not only that, but it also doesn't even match the callback method I've given! Either one of those two things should be enough to make the annotation processor panic.
*and cause the mixin to be applied to a method that they don't (probably shouldn't) match.
The result of this is having mixins that work in development but generate unnecessary headaches further down the line when they fail the build condition, or that might make their way into production since testing them normally doesn't produce any sort of error.
What I expected to happen: The game should have crashed with an exception saying it did not find the target method.
What actually happened: The game did not crash, and the mixin was applied to a method that it should not have been able to match given the incorrect descriptor.
Below is a more detailed description of my setup and how exactly I managed to encounter this weird... bug?
The method I'm injecting into looks like this (located in net.minecraft.client.render.GameRenderer):
And it has a target descriptor that should look like this when used in a mixin:
Now I wrote my mixin like this (details omitted):
You will notice it has an ever so slightly, hard to notice typo. Do you see it? There's an additional "FJ" - float and long that snuck in there when copying from another method.
What this means is that the target descriptor does not match any known (or existing) methods in that class, and indeed it doesn't, as when doing a build through gradle it fails and produces the following two errors, as expected:
This is correct.
Based on these I wouldn't expect the game to even run when there are mixins that cannot find their target methods,
however, the problem arises when I do run the project in my IDE (as I normally do to test my code - building with gradle is usually the last step to obtain a jar I cna distribute):
When I run the game it "works", and I don't mean it "prints a warning and keeps running with my callback never being executed" I mean it works. The mixin is applied to the intended method, and the callback is executed as desired, somehow despite the descriptor not actually being correct!
I would understand it behaving like this when I specify only he method name in the @Inject annotation, however I've given it a full explicit method descriptor. Not only that, but it also doesn't even match the callback method I've given! Either one of those two things should be enough to make the annotation processor panic.