mirror of
https://github.com/PaperMC/Paper.git
synced 2025-08-15 20:23:53 -07:00
Start update, apply API patches
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bjarne Koll <git@lynxplay.dev>
|
||||
Date: Mon, 11 Nov 2024 21:35:27 +0100
|
||||
Subject: [PATCH] Fix incorrect invulnerability damage reduction
|
||||
|
||||
Fixes incorrect spigot handling of the invulnerability damage
|
||||
reduction applied when an already invulnerable entity is damaged with a
|
||||
larger damage amount than the initial damage.
|
||||
Vanilla still damages entities even if invulnerable if the damage to be
|
||||
applied is larger than the previous damage taken. In that case, vanilla
|
||||
applies the difference between the previous damage taken and the
|
||||
proposed damage.
|
||||
|
||||
Spigot's damage modifier API takes over the computation of damage
|
||||
reducing effects, however spigot invokes this handling with the initial
|
||||
damage before computing the difference to the previous damage amount.
|
||||
This leads to the reduction values to generally be larger than expected,
|
||||
as they are computed on the not-yet-reduced value.
|
||||
Spigot applies these reductions after calling the EntityDamageEvent and
|
||||
*then* subtracts the previous damage point, leading to the final damage
|
||||
amount being smaller than expected.
|
||||
|
||||
This patch cannot simply call the EntityDamageEvent with the reduced
|
||||
damage, as that would lead to EntityDamageEvent#getDamage() returning
|
||||
the already reduced damage, which breaks its method contract.
|
||||
Instead, this patch makes use of the DamageModifier API, implementing
|
||||
the last-damage-reduction as a DamageModifier.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
}
|
||||
|
||||
// Paper start - only call damage event when actuallyHurt will be called - move call logic down
|
||||
- event = this.handleEntityDamage(source, amount);
|
||||
+ event = this.handleEntityDamage(source, amount, this.lastHurt); // Paper - fix invulnerability reduction in EntityDamageEvent - pass lastDamage reduction
|
||||
amount = computeAmountFromEntityDamageEvent(event);
|
||||
// Paper end - only call damage event when actuallyHurt will be called - move call logic down
|
||||
|
||||
// CraftBukkit start
|
||||
- if (!this.actuallyHurt(world, source, (float) event.getFinalDamage() - this.lastHurt, event)) {
|
||||
+ if (!this.actuallyHurt(world, source, (float) event.getFinalDamage(), event)) { // Paper - fix invulnerability reduction in EntityDamageEvent - no longer subtract lastHurt, that is part of the damage event calc now
|
||||
return false;
|
||||
}
|
||||
if (this instanceof ServerPlayer && event.getDamage() == 0 && originalAmount == 0) return false; // Paper - revert to vanilla damage - players are not affected by damage that is 0 - skip damage if the vanilla damage is 0 and was not modified by plugins in the event.
|
||||
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
flag1 = false;
|
||||
} else {
|
||||
// Paper start - only call damage event when actuallyHurt will be called - move call logic down
|
||||
- event = this.handleEntityDamage(source, amount);
|
||||
+ event = this.handleEntityDamage(source, amount, 0); // Paper - fix invulnerability reduction in EntityDamageEvent - pass lastDamage reduction (none in this branch)
|
||||
amount = computeAmountFromEntityDamageEvent(event);
|
||||
// Paper end - only call damage event when actuallyHurt will be called - move call logic down
|
||||
// CraftBukkit start
|
||||
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
}
|
||||
|
||||
// CraftBukkit start
|
||||
- private EntityDamageEvent handleEntityDamage(final DamageSource damagesource, float f) {
|
||||
+ private EntityDamageEvent handleEntityDamage(final DamageSource damagesource, float f, final float invulnerabilityRelatedLastDamage) { // Paper - fix invulnerability reduction in EntityDamageEvent
|
||||
float originalDamage = f;
|
||||
+ // Paper start - fix invulnerability reduction in EntityDamageEvent
|
||||
+ final com.google.common.base.Function<Double, Double> invulnerabilityReductionEquation = d -> {
|
||||
+ if (invulnerabilityRelatedLastDamage == 0) return 0D; // no last damage, no reduction
|
||||
+ // last damage existed, this means the reduction *technically* is (new damage - last damage).
|
||||
+ // If the event damage was changed to something less than invul damage, hard lock it at 0.
|
||||
+ if (d < invulnerabilityRelatedLastDamage) return 0D;
|
||||
+ return (double) -invulnerabilityRelatedLastDamage;
|
||||
+ };
|
||||
+ final float originalInvulnerabilityReduction = invulnerabilityReductionEquation.apply((double) f).floatValue();
|
||||
+ f += originalInvulnerabilityReduction;
|
||||
+ // Paper end - fix invulnerability reduction in EntityDamageEvent
|
||||
|
||||
com.google.common.base.Function<Double, Double> freezing = new com.google.common.base.Function<Double, Double>() {
|
||||
@Override
|
||||
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
};
|
||||
float absorptionModifier = absorption.apply((double) f).floatValue();
|
||||
|
||||
- return CraftEventFactory.handleLivingEntityDamageEvent(this, damagesource, originalDamage, freezingModifier, hardHatModifier, blockingModifier, armorModifier, resistanceModifier, magicModifier, absorptionModifier, freezing, hardHat, blocking, armor, resistance, magic, absorption);
|
||||
+ // Paper start - fix invulnerability reduction in EntityDamageEvent
|
||||
+ return CraftEventFactory.handleLivingEntityDamageEvent(this, damagesource, originalDamage, freezingModifier, hardHatModifier, blockingModifier, armorModifier, resistanceModifier, magicModifier, absorptionModifier, freezing, hardHat, blocking, armor, resistance, magic, absorption, (damageModifierDoubleMap, damageModifierFunctionMap) -> {
|
||||
+ damageModifierFunctionMap.put(DamageModifier.INVULNERABILITY_REDUCTION, invulnerabilityReductionEquation);
|
||||
+ damageModifierDoubleMap.put(DamageModifier.INVULNERABILITY_REDUCTION, (double) originalInvulnerabilityReduction);
|
||||
+ });
|
||||
+ // Paper end - fix invulnerability reduction in EntityDamageEvent
|
||||
}
|
||||
|
||||
protected boolean actuallyHurt(ServerLevel worldserver, final DamageSource damagesource, float f, final EntityDamageEvent event) { // void -> boolean, add final
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
@@ -0,0 +0,0 @@ public class CraftEventFactory {
|
||||
private static final Function<? super Double, Double> ZERO = Functions.constant(-0.0);
|
||||
|
||||
public static EntityDamageEvent handleLivingEntityDamageEvent(Entity damagee, DamageSource source, double rawDamage, double freezingModifier, double hardHatModifier, double blockingModifier, double armorModifier, double resistanceModifier, double magicModifier, double absorptionModifier, Function<Double, Double> freezing, Function<Double, Double> hardHat, Function<Double, Double> blocking, Function<Double, Double> armor, Function<Double, Double> resistance, Function<Double, Double> magic, Function<Double, Double> absorption) {
|
||||
+ // Paper start - fix invulnerability reduction in EntityDamageEvent
|
||||
+ return handleLivingEntityDamageEvent(damagee, source, rawDamage, freezingModifier, hardHatModifier, blockingModifier, armorModifier, resistanceModifier, magicModifier, absorptionModifier, freezing, hardHat, blocking, armor, resistance, magic, absorption, null);
|
||||
+ }
|
||||
+ public static EntityDamageEvent handleLivingEntityDamageEvent(Entity damagee, DamageSource source, double rawDamage, double freezingModifier, double hardHatModifier, double blockingModifier, double armorModifier, double resistanceModifier, double magicModifier, double absorptionModifier, Function<Double, Double> freezing, Function<Double, Double> hardHat, Function<Double, Double> blocking, Function<Double, Double> armor, Function<Double, Double> resistance, Function<Double, Double> magic, Function<Double, Double> absorption, java.util.function.BiConsumer<Map<DamageModifier, Double>, Map<DamageModifier, Function<? super Double, Double>>> callback) {
|
||||
+ // Paper end - fix invulnerability reduction in EntityDamageEvent
|
||||
Map<DamageModifier, Double> modifiers = new EnumMap<>(DamageModifier.class);
|
||||
Map<DamageModifier, Function<? super Double, Double>> modifierFunctions = new EnumMap<>(DamageModifier.class);
|
||||
modifiers.put(DamageModifier.BASE, rawDamage);
|
||||
@@ -0,0 +0,0 @@ public class CraftEventFactory {
|
||||
modifierFunctions.put(DamageModifier.MAGIC, magic);
|
||||
modifiers.put(DamageModifier.ABSORPTION, absorptionModifier);
|
||||
modifierFunctions.put(DamageModifier.ABSORPTION, absorption);
|
||||
+ if (callback != null) callback.accept(modifiers, modifierFunctions); // Paper - fix invulnerability reduction in EntityDamageEvent
|
||||
return CraftEventFactory.handleEntityDamageEvent(damagee, source, modifiers, modifierFunctions);
|
||||
}
|
||||
|
Reference in New Issue
Block a user