浏览代码

Prevent IllegalArgumentException with Rupture and provide more detailed logging when Rupture cannot activate from illegal state Fixes #5063

nossr50 11 月之前
父节点
当前提交
c7409a8f9b

+ 22 - 3
src/main/java/com/gmail/nossr50/runnables/skills/RuptureTask.java

@@ -8,10 +8,13 @@ import com.gmail.nossr50.util.MetadataConstants;
 import com.gmail.nossr50.util.MobHealthbarUtils;
 import com.gmail.nossr50.util.skills.ParticleEffectUtils;
 import com.google.common.base.Objects;
+import org.bukkit.attribute.AttributeInstance;
 import org.bukkit.entity.LivingEntity;
 import org.bukkit.entity.Player;
 import org.jetbrains.annotations.NotNull;
 
+import static org.bukkit.attribute.Attribute.GENERIC_MAX_HEALTH;
+
 public class RuptureTask extends CancellableRunnable {
 
     public static final int DAMAGE_TICK_INTERVAL = 10;
@@ -82,20 +85,36 @@ public class RuptureTask extends CancellableRunnable {
     private boolean applyRupture() {
         double healthBeforeRuptureIsApplied = targetEntity.getHealth();
 
-        //Ensure victim has health
+        // Ensure victim has health
         if (healthBeforeRuptureIsApplied > 0.01) {
             //Send a fake damage event
             McMMOEntityDamageByRuptureEvent event =
                     new McMMOEntityDamageByRuptureEvent(ruptureSource, targetEntity, calculateAdjustedTickDamage());
             mcMMO.p.getServer().getPluginManager().callEvent(event);
 
-            //Ensure the event wasn't cancelled and damage is still greater than 0
+            //Ensure the event wasn't canceled and damage is still greater than 0
             double damage = event.getDamage(); //Use raw damage for Rupture
 
             if (event.isCancelled() || damage <= 0 || healthBeforeRuptureIsApplied - damage <= 0)
                 return true;
 
-            double damagedHealth = healthBeforeRuptureIsApplied - damage;
+            final double damagedHealth = healthBeforeRuptureIsApplied - damage;
+
+            final AttributeInstance maxHealthAttribute = targetEntity.getAttribute(GENERIC_MAX_HEALTH);
+            if (maxHealthAttribute == null) {
+                // Can't remove health if max health is null
+                mcMMO.p.getLogger().info("RuptureTask: Target entity has an illegal state for its health." +
+                        " Cancelling Rupture. Target has null " + GENERIC_MAX_HEALTH + " attribute.");
+                return true;
+            }
+
+            if (damagedHealth > maxHealthAttribute.getValue()) {
+                // Something went very wrong here, target has an illegal state for its health
+                mcMMO.p.getLogger().info("RuptureTask: Target entity has an illegal state for its health." +
+                        " Cancelling Rupture. Target has " + targetEntity.getHealth() + " health," +
+                        " but max health is " + maxHealthAttribute.getValue());
+                return true;
+            }
 
             targetEntity.setHealth(damagedHealth); //Hurt entity without the unwanted side effects of damage()}
             MobHealthbarUtils.handleMobHealthbars(targetEntity, damage, mcMMO.p);

+ 2 - 1
src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java

@@ -38,6 +38,7 @@ import org.jetbrains.annotations.Nullable;
 
 import java.util.List;
 
+import static com.gmail.nossr50.datatypes.experience.XPGainReason.PVP;
 import static com.gmail.nossr50.util.MobMetadataUtils.hasMobFlag;
 
 public final class CombatUtils {
@@ -891,7 +892,7 @@ public final class CombatUtils {
                 return;
             }
 
-            xpGainReason = XPGainReason.PVP;
+            xpGainReason = PVP;
 
             if (defender.isOnline()
                     && SkillUtils.cooldownExpired(mcMMOPlayer.getRespawnATS(), Misc.PLAYER_RESPAWN_COOLDOWN_SECONDS)) {