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;