diff --git a/forge/gradle.properties b/forge/gradle.properties index 1867ebeceef..23637da245d 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -2,7 +2,7 @@ name=SpongeForge implementation=Forge description=The SpongeAPI implementation for MinecraftForge -forgeVersion=51.0.17 +forgeVersion=51.0.22 loom.platform=forge fabric.loom.dontRemap=true mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.core.json,mixins.spongeforge.tracker.json \ No newline at end of file diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index a100742eae7..e4a48490f43 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1530,6 +1530,14 @@ + + + + + + + + @@ -1886,6 +1894,14 @@ + + + + + + + + @@ -2521,6 +2537,14 @@ + + + + + + + + @@ -2553,6 +2577,14 @@ + + + + + + + + @@ -2585,6 +2617,14 @@ + + + + + + + + @@ -2617,6 +2657,14 @@ + + + + + + + + @@ -2673,6 +2721,20 @@ + + + + + + + + + + + + + + @@ -2729,6 +2791,14 @@ + + + + + + + + @@ -2761,6 +2831,14 @@ + + + + + + + + @@ -2793,6 +2871,14 @@ + + + + + + + + diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java index e51e4c7fc78..41cb3f77bb1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java @@ -28,6 +28,7 @@ import net.minecraft.sounds.SoundEvent; import net.minecraft.stats.Stats; import net.minecraft.tags.DamageTypeTags; +import net.minecraft.world.InteractionHand; import net.minecraft.world.damagesource.CombatRules; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; @@ -36,6 +37,7 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import org.apache.logging.log4j.Level; +import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -56,8 +58,6 @@ import java.util.ArrayList; -import javax.annotation.Nonnull; - @Mixin(value = LivingEntity.class, priority = 900) public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin implements LivingEntityBridge, PlatformLivingEntityBridge { @@ -69,14 +69,15 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin @Shadow protected abstract void shadow$blockUsingShield(final LivingEntity $$0); @Shadow protected abstract void shadow$hurtArmor(DamageSource source, float damage); @Shadow protected abstract float shadow$getKnockback(final Entity $$0, final DamageSource $$1); + @Shadow public abstract ItemStack shadow$getItemInHand(final InteractionHand $$0); @Shadow public abstract float shadow$getAbsorptionAmount(); + @Shadow public abstract @NonNull ItemStack shadow$getWeaponItem(); @Shadow public abstract void setAbsorptionAmount(final float $$0); - @Shadow @Nonnull public abstract ItemStack shadow$getWeaponItem(); - @Shadow protected int attackStrengthTicker; @Shadow protected float lastHurt; - // @formatter:on + + // @formatter:on private float attackImpl$lastHurt; private int attackImpl$InvulnerableTime; @@ -86,6 +87,7 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin protected float attackImpl$actuallyHurtFinalDamage; protected boolean attackImpl$actuallyHurtCancelled; protected float attackImpl$actuallyHurtBlockedDamage; + protected boolean attackImpl$wasInInvulnerableTime; /** * Forge onLivingAttack Hook @@ -155,6 +157,7 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin /** * Capture the old values to reset if we end up cancelling or blocking. + * Also reset {@link #attackImpl$wasInInvulnerableTime} */ @Inject(method = "hurt", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/LivingEntity;walkAnimation:Lnet/minecraft/world/entity/WalkAnimationState;")) @@ -163,15 +166,17 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin this.attackImpl$lastHurt = this.lastHurt; this.attackImpl$InvulnerableTime = this.invulnerableTime; this.attackImpl$actuallyHurtCancelled = false; + this.attackImpl$wasInInvulnerableTime = false; } /** - * Fake {@link #lastHurt} to be 0 so that we go to #actuallyHurt even if we are invulnerable. + * Fake {@link #lastHurt} to be 0 so that we go to #actuallyHurt even if we are invulnerable and remember that we did */ @Redirect(method = "hurt", at = @At(value = "FIELD", ordinal = 0, target = "Lnet/minecraft/world/entity/LivingEntity;lastHurt:F")) private float attackImpl$afterActuallyHurt(final LivingEntity instance) { + this.attackImpl$wasInInvulnerableTime = true; return 0; } @@ -257,8 +262,13 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin if (instance.isInvulnerableTo(damageSource)) { return true; } + var realOriginalDamage = originalDamage; + if (this.attackImpl$wasInInvulnerableTime) { + realOriginalDamage = Math.max(0, realOriginalDamage); // No negative damage because of invulnerableTime + } + // Call platform hook for adjusting damage - final var modAdjustedDamage = this.bridge$applyModDamage(instance, damageSource, originalDamage); + final var modAdjustedDamage = this.bridge$applyModDamage(instance, damageSource, realOriginalDamage); // TODO check for direct call? this.attackImpl$actuallyHurt = new DamageEventUtil.ActuallyHurt(instance, new ArrayList<>(), damageSource, modAdjustedDamage); return false; @@ -344,9 +354,12 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin /** * Set final damage after calling {@link LivingEntity#setAbsorptionAmount} in which we called the event + * !!NOTE that var9 is actually decompiled incorrectly!! + * It is NOT the final damage value instead the method parameter is mutated */ - @ModifyVariable(method = "actuallyHurt", ordinal = 1, - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;setAbsorptionAmount(F)V", ordinal = 0, shift = At.Shift.AFTER)) + @ModifyVariable(method = "actuallyHurt", ordinal = 0, + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;setAbsorptionAmount(F)V", + ordinal = 0, shift = At.Shift.AFTER), argsOnly = true) public float attackImpl$setFinalDamage(final float value) { if (this.attackImpl$actuallyHurtResult.event().isCancelled()) { return 0;