summaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
authorTravis Watkins <amaranth@ubuntu.com>2014-07-09 16:19:27 -0500
committerTravis Watkins <amaranth@ubuntu.com>2014-07-09 19:00:16 -0500
commitf9e3bf24a8104f070b3fc4d57e7bbd3d7532be75 (patch)
tree7a02ba2ce97283340c45772405a8c15ba3e21fd5 /src/main
parent9b7b142ad0534452325bb997d8d55e8beb4b3d99 (diff)
downloadbukkit-f9e3bf24a8104f070b3fc4d57e7bbd3d7532be75.tar
bukkit-f9e3bf24a8104f070b3fc4d57e7bbd3d7532be75.tar.gz
bukkit-f9e3bf24a8104f070b3fc4d57e7bbd3d7532be75.tar.lz
bukkit-f9e3bf24a8104f070b3fc4d57e7bbd3d7532be75.tar.xz
bukkit-f9e3bf24a8104f070b3fc4d57e7bbd3d7532be75.zip
Recalculate damage modifiers in event for old method. Fixes BUKKIT-5681
When we added the new API in EntityDamageEvent to give control over the various things that modify the final damage done we caused a change in behavior for users of the old #setDamage(double) method. Before changing the damage would happen before the modifiers were calculated so they would be based on the final damage value from the event. Now they are calculated at the beginning so changing the damage does not change the modifiers. To allow the old style and the new to coexist we now expose the vanilla modifer calculations to the event in the form of Function objects. These are used in #setDamage(double) to calculate the difference in the modifier between the old damage and the new and apply this difference to the current modifier. The difference is between the vanilla values for both damage values and is applied on top of the event's modifier value as this should make old and new API usage work together in a way that isn't surprising.
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/org/bukkit/event/entity/EntityDamageByBlockEvent.java5
-rw-r--r--src/main/java/org/bukkit/event/entity/EntityDamageByEntityEvent.java5
-rw-r--r--src/main/java/org/bukkit/event/entity/EntityDamageEvent.java42
3 files changed, 45 insertions, 7 deletions
diff --git a/src/main/java/org/bukkit/event/entity/EntityDamageByBlockEvent.java b/src/main/java/org/bukkit/event/entity/EntityDamageByBlockEvent.java
index 49bf2a84..2ff121e3 100644
--- a/src/main/java/org/bukkit/event/entity/EntityDamageByBlockEvent.java
+++ b/src/main/java/org/bukkit/event/entity/EntityDamageByBlockEvent.java
@@ -2,6 +2,7 @@ package org.bukkit.event.entity;
import java.util.Map;
+import com.google.common.base.Function;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
@@ -22,8 +23,8 @@ public class EntityDamageByBlockEvent extends EntityDamageEvent {
this.damager = damager;
}
- public EntityDamageByBlockEvent(final Block damager, final Entity damagee, final DamageCause cause, final Map<DamageModifier, Double> modifiers) {
- super(damagee, cause, modifiers);
+ public EntityDamageByBlockEvent(final Block damager, final Entity damagee, final DamageCause cause, final Map<DamageModifier, Double> modifiers, final Map<DamageModifier, ? extends Function<? super Double, Double>> modifierFunctions) {
+ super(damagee, cause, modifiers, modifierFunctions);
this.damager = damager;
}
diff --git a/src/main/java/org/bukkit/event/entity/EntityDamageByEntityEvent.java b/src/main/java/org/bukkit/event/entity/EntityDamageByEntityEvent.java
index e7ea32f5..49e74c30 100644
--- a/src/main/java/org/bukkit/event/entity/EntityDamageByEntityEvent.java
+++ b/src/main/java/org/bukkit/event/entity/EntityDamageByEntityEvent.java
@@ -2,6 +2,7 @@ package org.bukkit.event.entity;
import java.util.Map;
+import com.google.common.base.Function;
import org.bukkit.entity.Entity;
/**
@@ -21,8 +22,8 @@ public class EntityDamageByEntityEvent extends EntityDamageEvent {
this.damager = damager;
}
- public EntityDamageByEntityEvent(final Entity damager, final Entity damagee, final DamageCause cause, final Map<DamageModifier, Double> modifiers) {
- super(damagee, cause, modifiers);
+ public EntityDamageByEntityEvent(final Entity damager, final Entity damagee, final DamageCause cause, final Map<DamageModifier, Double> modifiers, final Map<DamageModifier, ? extends Function<? super Double, Double>> modifierFunctions) {
+ super(damagee, cause, modifiers, modifierFunctions);
this.damager = damager;
}
diff --git a/src/main/java/org/bukkit/event/entity/EntityDamageEvent.java b/src/main/java/org/bukkit/event/entity/EntityDamageEvent.java
index 17d95487..2cc07996 100644
--- a/src/main/java/org/bukkit/event/entity/EntityDamageEvent.java
+++ b/src/main/java/org/bukkit/event/entity/EntityDamageEvent.java
@@ -10,6 +10,8 @@ import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.util.NumberConversions;
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
import com.google.common.collect.ImmutableMap;
/**
@@ -18,7 +20,9 @@ import com.google.common.collect.ImmutableMap;
public class EntityDamageEvent extends EntityEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private static final DamageModifier[] MODIFIERS = DamageModifier.values();
+ private static final Function<? super Double, Double> ZERO = Functions.constant(-0.0);
private final Map<DamageModifier, Double> modifiers;
+ private final Map<DamageModifier, ? extends Function<? super Double, Double>> modifierFunctions;
private final Map<DamageModifier, Double> originals;
private boolean cancelled;
private final DamageCause cause;
@@ -30,16 +34,20 @@ public class EntityDamageEvent extends EntityEvent implements Cancellable {
@Deprecated
public EntityDamageEvent(final Entity damagee, final DamageCause cause, final double damage) {
- this(damagee, cause, new EnumMap<DamageModifier, Double>(ImmutableMap.of(DamageModifier.BASE, damage)));
+ this(damagee, cause, new EnumMap<DamageModifier, Double>(ImmutableMap.of(DamageModifier.BASE, damage)), new EnumMap<DamageModifier, Function<? super Double, Double>>(ImmutableMap.of(DamageModifier.BASE, ZERO)));
}
- public EntityDamageEvent(final Entity damagee, final DamageCause cause, final Map<DamageModifier, Double> modifiers) {
+ public EntityDamageEvent(final Entity damagee, final DamageCause cause, final Map<DamageModifier, Double> modifiers, final Map<DamageModifier, ? extends Function<? super Double, Double>> modifierFunctions) {
super(damagee);
Validate.isTrue(modifiers.containsKey(DamageModifier.BASE), "BASE DamageModifier missing");
Validate.isTrue(!modifiers.containsKey(null), "Cannot have null DamageModifier");
+ Validate.noNullElements(modifiers.values(), "Cannot have null modifier values");
+ Validate.isTrue(modifiers.keySet().equals(modifierFunctions.keySet()), "Must have a modifier function for each DamageModifier");
+ Validate.noNullElements(modifierFunctions.values(), "Cannot have null modifier function");
this.originals = new EnumMap<DamageModifier, Double>(modifiers);
this.cause = cause;
this.modifiers = modifiers;
+ this.modifierFunctions = modifierFunctions;
}
public boolean isCancelled() {
@@ -149,11 +157,39 @@ public class EntityDamageEvent extends EntityEvent implements Cancellable {
}
/**
- * Sets the raw amount of damage caused by the event
+ * Sets the raw amount of damage caused by the event.
+ * <p>
+ * For compatibility this also recalculates the modifiers and scales
+ * them by the difference between the modifier for the previous damage
+ * value and the new one.
*
* @param damage The raw amount of damage caused by the event
*/
public void setDamage(double damage) {
+ // These have to happen in the same order as the server calculates them, keep the enum sorted
+ double remaining = damage;
+ double oldRemaining = getDamage(DamageModifier.BASE);
+ for (DamageModifier modifier : MODIFIERS) {
+ if (!isApplicable(modifier)) {
+ continue;
+ }
+
+ Function<? super Double, Double> modifierFunction = modifierFunctions.get(modifier);
+ double newVanilla = modifierFunction.apply(remaining);
+ double oldVanilla = modifierFunction.apply(oldRemaining);
+ double difference = oldVanilla - newVanilla;
+
+ // Don't allow value to cross zero, assume zero values should be negative
+ double old = getDamage(modifier);
+ if (old > 0) {
+ setDamage(modifier, Math.max(0, old - difference));
+ } else {
+ setDamage(modifier, Math.min(0, old - difference));
+ }
+ remaining += newVanilla;
+ oldRemaining += oldVanilla;
+ }
+
setDamage(DamageModifier.BASE, damage);
}