From bfa231f7e469fb93ec6bf7e442f79b4230364346 Mon Sep 17 00:00:00 2001 From: Alexandra-Myers Date: Sat, 4 Oct 2025 21:02:11 -0400 Subject: [PATCH 1/2] Fix Combatify --- .../dynfix/DynFixArbitraryInjectionPoint.java | 3 ++- .../patch/test/mixin/DynamicMixinPatchTest.java | 5 +++++ .../adapter/test/mixin/LivingEntityMixin.java | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/definition/src/main/java/org/sinytra/adapter/patch/transformer/dynfix/DynFixArbitraryInjectionPoint.java b/definition/src/main/java/org/sinytra/adapter/patch/transformer/dynfix/DynFixArbitraryInjectionPoint.java index 0764a6c..ef8d899 100644 --- a/definition/src/main/java/org/sinytra/adapter/patch/transformer/dynfix/DynFixArbitraryInjectionPoint.java +++ b/definition/src/main/java/org/sinytra/adapter/patch/transformer/dynfix/DynFixArbitraryInjectionPoint.java @@ -12,6 +12,7 @@ import org.sinytra.adapter.patch.transformer.operation.unit.ModifyInjectionPoint; import org.sinytra.adapter.patch.transformer.operation.unit.ModifyInjectionTarget; import org.sinytra.adapter.patch.util.AdapterUtil; +import org.sinytra.adapter.patch.util.MethodQualifier; import java.util.ArrayList; import java.util.List; @@ -110,7 +111,7 @@ private static AbstractInsnNode findCandidates(InstructionMatcher cleanMatcher, private static MethodInsnNode findReplacementInjectionPoint(AbstractInsnNode lastInsn, UnaryOperator flow, MethodContext methodContext) { // Require matching return types for ModifyExpressionValue mixins if (methodContext.methodAnnotation().matchesDesc(MixinConstants.MODIFY_EXPR_VAL)) { - Type desiredReturnType = Type.getReturnType(methodContext.getInjectionPointMethodQualifier().desc()); + Type desiredReturnType = Type.getReturnType(methodContext.getMixinMethod().desc); return (MethodInsnNode) AdapterUtil.iterateInsns(lastInsn, flow, v -> v instanceof MethodInsnNode minsn && Type.getReturnType(minsn.desc).equals(desiredReturnType)); } else { return (MethodInsnNode) AdapterUtil.iterateInsns(lastInsn, flow, v -> v instanceof MethodInsnNode); diff --git a/test/src/test/java/org/sinytra/adapter/patch/test/mixin/DynamicMixinPatchTest.java b/test/src/test/java/org/sinytra/adapter/patch/test/mixin/DynamicMixinPatchTest.java index e65f83f..a8b6f61 100644 --- a/test/src/test/java/org/sinytra/adapter/patch/test/mixin/DynamicMixinPatchTest.java +++ b/test/src/test/java/org/sinytra/adapter/patch/test/mixin/DynamicMixinPatchTest.java @@ -204,6 +204,11 @@ void testUpdatedInjectionPointModifyExprVal() throws Exception { "isFarmlandNearWater", assertInjectionPoint() ); + assertSameCode( + "org/sinytra/adapter/test/mixin/LivingEntityMixin", + "changeIFrames", + assertInjectionPoint() + ); } @Test diff --git a/test/src/testClasses/java/org/sinytra/adapter/test/mixin/LivingEntityMixin.java b/test/src/testClasses/java/org/sinytra/adapter/test/mixin/LivingEntityMixin.java index 966a171..293059d 100644 --- a/test/src/testClasses/java/org/sinytra/adapter/test/mixin/LivingEntityMixin.java +++ b/test/src/testClasses/java/org/sinytra/adapter/test/mixin/LivingEntityMixin.java @@ -1,5 +1,8 @@ package org.sinytra.adapter.test.mixin; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.sugar.Local; +import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.LivingEntity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -11,6 +14,17 @@ @Mixin(LivingEntity.class) public class LivingEntityMixin { + // https://github.com/Alexandra-Myers/Combatify/blob/1.21.1/src/main/java/net/atlas/combatify/mixin/InvulnerabilityMixin.java#L16 + @ModifyExpressionValue(method = "hurt", at = @At(value = "CONSTANT", args = "intValue=20", ordinal = 0)) + public int changeIFrames(int original, @Local(ordinal = 0, argsOnly = true) final DamageSource source, @Local(ordinal = 0, argsOnly = true) final float amount) { + return original; + } + + @ModifyExpressionValue(method = "hurt", at = @At(value = "INVOKE", target = "Lnet/neoforged/neoforge/common/damagesource/DamageContainer;getPostAttackInvulnerabilityTicks()I")) + public int changeIFramesExpected(int original, @Local(ordinal = 0, argsOnly = true) final DamageSource source, @Local(ordinal = 0, argsOnly = true) final float amount) { + return original; + } + // https://github.com/TheDeathlyCow/frostiful/blob/5f0a696400de2ae49b21ff42af5116f058cf13ae/src/main/java/com/github/thedeathlycow/frostiful/mixins/entity/ice_skating/LivingEntityMovementMixin.java#L141 @ModifyVariable( method = "travel", From 93c71c40df1cc0eeda7960be2d3589b022f22914 Mon Sep 17 00:00:00 2001 From: Alexandra-Myers Date: Sat, 4 Oct 2025 21:02:11 -0400 Subject: [PATCH 2/2] Fix NPE when ModifyExpressionValue does not use value "INVOKE" for its @At --- .../dynfix/DynFixArbitraryInjectionPoint.java | 3 ++- .../patch/test/mixin/DynamicMixinPatchTest.java | 5 +++++ .../adapter/test/mixin/LivingEntityMixin.java | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/definition/src/main/java/org/sinytra/adapter/patch/transformer/dynfix/DynFixArbitraryInjectionPoint.java b/definition/src/main/java/org/sinytra/adapter/patch/transformer/dynfix/DynFixArbitraryInjectionPoint.java index 0764a6c..ef8d899 100644 --- a/definition/src/main/java/org/sinytra/adapter/patch/transformer/dynfix/DynFixArbitraryInjectionPoint.java +++ b/definition/src/main/java/org/sinytra/adapter/patch/transformer/dynfix/DynFixArbitraryInjectionPoint.java @@ -12,6 +12,7 @@ import org.sinytra.adapter.patch.transformer.operation.unit.ModifyInjectionPoint; import org.sinytra.adapter.patch.transformer.operation.unit.ModifyInjectionTarget; import org.sinytra.adapter.patch.util.AdapterUtil; +import org.sinytra.adapter.patch.util.MethodQualifier; import java.util.ArrayList; import java.util.List; @@ -110,7 +111,7 @@ private static AbstractInsnNode findCandidates(InstructionMatcher cleanMatcher, private static MethodInsnNode findReplacementInjectionPoint(AbstractInsnNode lastInsn, UnaryOperator flow, MethodContext methodContext) { // Require matching return types for ModifyExpressionValue mixins if (methodContext.methodAnnotation().matchesDesc(MixinConstants.MODIFY_EXPR_VAL)) { - Type desiredReturnType = Type.getReturnType(methodContext.getInjectionPointMethodQualifier().desc()); + Type desiredReturnType = Type.getReturnType(methodContext.getMixinMethod().desc); return (MethodInsnNode) AdapterUtil.iterateInsns(lastInsn, flow, v -> v instanceof MethodInsnNode minsn && Type.getReturnType(minsn.desc).equals(desiredReturnType)); } else { return (MethodInsnNode) AdapterUtil.iterateInsns(lastInsn, flow, v -> v instanceof MethodInsnNode); diff --git a/test/src/test/java/org/sinytra/adapter/patch/test/mixin/DynamicMixinPatchTest.java b/test/src/test/java/org/sinytra/adapter/patch/test/mixin/DynamicMixinPatchTest.java index e65f83f..a8b6f61 100644 --- a/test/src/test/java/org/sinytra/adapter/patch/test/mixin/DynamicMixinPatchTest.java +++ b/test/src/test/java/org/sinytra/adapter/patch/test/mixin/DynamicMixinPatchTest.java @@ -204,6 +204,11 @@ void testUpdatedInjectionPointModifyExprVal() throws Exception { "isFarmlandNearWater", assertInjectionPoint() ); + assertSameCode( + "org/sinytra/adapter/test/mixin/LivingEntityMixin", + "changeIFrames", + assertInjectionPoint() + ); } @Test diff --git a/test/src/testClasses/java/org/sinytra/adapter/test/mixin/LivingEntityMixin.java b/test/src/testClasses/java/org/sinytra/adapter/test/mixin/LivingEntityMixin.java index 966a171..293059d 100644 --- a/test/src/testClasses/java/org/sinytra/adapter/test/mixin/LivingEntityMixin.java +++ b/test/src/testClasses/java/org/sinytra/adapter/test/mixin/LivingEntityMixin.java @@ -1,5 +1,8 @@ package org.sinytra.adapter.test.mixin; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.sugar.Local; +import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.LivingEntity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -11,6 +14,17 @@ @Mixin(LivingEntity.class) public class LivingEntityMixin { + // https://github.com/Alexandra-Myers/Combatify/blob/1.21.1/src/main/java/net/atlas/combatify/mixin/InvulnerabilityMixin.java#L16 + @ModifyExpressionValue(method = "hurt", at = @At(value = "CONSTANT", args = "intValue=20", ordinal = 0)) + public int changeIFrames(int original, @Local(ordinal = 0, argsOnly = true) final DamageSource source, @Local(ordinal = 0, argsOnly = true) final float amount) { + return original; + } + + @ModifyExpressionValue(method = "hurt", at = @At(value = "INVOKE", target = "Lnet/neoforged/neoforge/common/damagesource/DamageContainer;getPostAttackInvulnerabilityTicks()I")) + public int changeIFramesExpected(int original, @Local(ordinal = 0, argsOnly = true) final DamageSource source, @Local(ordinal = 0, argsOnly = true) final float amount) { + return original; + } + // https://github.com/TheDeathlyCow/frostiful/blob/5f0a696400de2ae49b21ff42af5116f058cf13ae/src/main/java/com/github/thedeathlycow/frostiful/mixins/entity/ice_skating/LivingEntityMovementMixin.java#L141 @ModifyVariable( method = "travel",