Prechádzať zdrojové kódy

Fix some bugs with Rupture and fix a small memory leak

nossr50 4 rokov pred
rodič
commit
a2ee4be86a

+ 3 - 1
Changelog.txt

@@ -1,5 +1,7 @@
 Version 2.1.186
     Rupture has been reworked to solve a few outstanding issues (see notes)
+    Fixed an exploit involving enchantments (thanks TheBusyBiscuit)
+    Fixed a very small memory leak that would only happen in very rare situations
     Gore no longer applies Rupture
     Gore no longer sends a message to the Wolf owner when it triggers
     Gore no longer sends a message to players that are hit by it
@@ -27,7 +29,7 @@ Version 2.1.186
     NOTES:
     The old Rupture would constantly interfere with your ability to do a Sweep Attack/Swipe with swords, the new one solves this problem
     Targets will bleed and take "pure" damage while bleeding, this never kills the target. It will reduce them to 0.01 HP.
-    After 5 seconds since your last attack on the target have transpired Rupture "explodes" dealing a large amount of damage, this damage is not pure and is affected by armor etc.
+    After 5 seconds of not applying Rupture on the target Rupture explodes dealing a large amount of damage, this damage is not pure and is affected by armor etc.
     Rupture no longer tells you that you that you applied it to the target, it should be obvious from the sounds/particle effects
     The new Rupture no longer constantly interferes with the vanilla Swipe (the AOE attack built into Minecraft)
     The new Rupture has not had a fine tuned balance pass, I will be balancing it frequently after this patch, it may be too weak or too strong in its current form

+ 0 - 1
src/main/java/com/gmail/nossr50/commands/skills/MmoInfoCommand.java

@@ -2,7 +2,6 @@ package com.gmail.nossr50.commands.skills;
 
 import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
 import com.gmail.nossr50.datatypes.skills.SubSkillType;
-import com.gmail.nossr50.datatypes.skills.subskills.AbstractSubSkill;
 import com.gmail.nossr50.listeners.InteractionManager;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.util.Permissions;

+ 1 - 2
src/main/java/com/gmail/nossr50/commands/skills/SwordsCommand.java

@@ -1,7 +1,6 @@
 package com.gmail.nossr50.commands.skills;
 
 import com.gmail.nossr50.config.AdvancedConfig;
-import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
 import com.gmail.nossr50.datatypes.skills.SubSkillType;
 import com.gmail.nossr50.locale.LocaleLoader;
@@ -56,7 +55,7 @@ public class SwordsCommand extends SkillCommand {
             ruptureExplosionDamageAgainstPlayers = String.valueOf(AdvancedConfig.getInstance().getRuptureExplosionDamage(true, ruptureRank));
             ruptureExplosionDamageAgainstMobs = String.valueOf(AdvancedConfig.getInstance().getRuptureExplosionDamage(false, ruptureRank));
 
-            ruptureChanceToApply = String.valueOf(AdvancedConfig.getInstance().getRuptureChanceToApplyOnHit(ruptureRank));
+            ruptureChanceToApply = String.valueOf(AdvancedConfig.getInstance().getRuptureChanceToApplyOnHit(ruptureRank) + "%");
             ruptureChanceToApplyLucky = String.valueOf(AdvancedConfig.getInstance().getRuptureChanceToApplyOnHit(ruptureRank) * 1.33);
         }
         

+ 0 - 3
src/main/java/com/gmail/nossr50/config/AdvancedConfig.java

@@ -5,9 +5,6 @@ import com.gmail.nossr50.datatypes.skills.SubSkillType;
 import com.gmail.nossr50.datatypes.skills.subskills.AbstractSubSkill;
 import com.gmail.nossr50.mcMMO;
 import net.md_5.bungee.api.ChatColor;
-import org.bukkit.entity.LivingEntity;
-import org.bukkit.entity.Player;
-import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
 import java.util.List;

+ 5 - 1
src/main/java/com/gmail/nossr50/listeners/EntityListener.java

@@ -489,6 +489,10 @@ public class EntityListener implements Listener {
         if(WorldBlacklist.isWorldBlacklisted(event.getEntity().getWorld()))
             return;
 
+        if(event.getEntity().hasMetadata(mcMMO.EXPLOSION_FROM_RUPTURE)) {
+            event.getEntity().removeMetadata(mcMMO.EXPLOSION_FROM_RUPTURE, mcMMO.p);
+        }
+
         if(event.getEntity() instanceof Player)
         {
             Player player = (Player) event.getEntity();
@@ -661,7 +665,7 @@ public class EntityListener implements Listener {
      */
     @EventHandler(priority = EventPriority.LOWEST)
     public void onEntityDeathLowest(EntityDeathEvent event) {
-        mcMMO.getTransientMetadataTools().cleanAllMobMetadata(event.getEntity());
+        mcMMO.getTransientMetadataTools().cleanAllLivingEntityMetadata(event.getEntity());
     }
 
     /**

+ 1 - 0
src/main/java/com/gmail/nossr50/listeners/PlayerListener.java

@@ -546,6 +546,7 @@ public class PlayerListener implements Listener {
 
         //Use a sync save if the server is shutting down to avoid race conditions
         mcMMOPlayer.logout(mcMMO.isServerShutdownExecuted());
+        mcMMO.getTransientMetadataTools().cleanAllLivingEntityMetadata(event.getPlayer());
     }
 
     /**

+ 1 - 0
src/main/java/com/gmail/nossr50/mcMMO.java

@@ -125,6 +125,7 @@ public class mcMMO extends JavaPlugin {
 
     /* Metadata Values */
     public static final String REPLANT_META_KEY      = "mcMMO: Recently Replanted";
+    public static final String EXPLOSION_FROM_RUPTURE = "mcMMO: Rupture Explosion";
     public static final String RUPTURE_META_KEY      = "mcMMO: RuptureTask";
     public static final String FISH_HOOK_REF_METAKEY = "mcMMO: Fish Hook Tracker";
     public static final String DODGE_TRACKER         = "mcMMO: Dodge Tracker";

+ 11 - 17
src/main/java/com/gmail/nossr50/runnables/skills/RuptureTask.java

@@ -8,6 +8,7 @@ import com.gmail.nossr50.util.skills.ParticleEffectUtils;
 import com.google.common.base.Objects;
 import org.bukkit.entity.LivingEntity;
 import org.bukkit.entity.Player;
+import org.bukkit.metadata.FixedMetadataValue;
 import org.bukkit.scheduler.BukkitRunnable;
 import org.jetbrains.annotations.NotNull;
 
@@ -27,7 +28,7 @@ public class RuptureTask extends BukkitRunnable {
     public RuptureTask(@NotNull McMMOPlayer ruptureSource, @NotNull LivingEntity targetEntity, double pureTickDamage, double explosionDamage) {
         this.ruptureSource = ruptureSource;
         this.targetEntity = targetEntity;
-        this.expireTick = AdvancedConfig.getInstance().getRuptureDurationSeconds(targetEntity instanceof Player);
+        this.expireTick = AdvancedConfig.getInstance().getRuptureDurationSeconds(targetEntity instanceof Player) * 20;
 
         this.ruptureTick = 0;
         this.damageTickTracker = 0;
@@ -44,12 +45,10 @@ public class RuptureTask extends BukkitRunnable {
 
             //Rupture hasn't ended yet
             if(ruptureTick < expireTick) {
-
                 //Is it time to damage?
                 if(damageTickTracker >= DAMAGE_TICK_INTERVAL) {
                     damageTickTracker = 0; //Reset
                     ParticleEffectUtils.playBleedEffect(targetEntity); //Animate
-                    double finalDamage = 0; //Used for mob health bars and setting last damage
 
                     if(targetEntity.getHealth() > 0.01) {
                         double healthBeforeRuptureIsApplied = targetEntity.getHealth();
@@ -59,21 +58,8 @@ public class RuptureTask extends BukkitRunnable {
                             mcMMO.p.getLogger().severe("DEBUG: Miscalculating Rupture tick damage");
                         } else {
                             targetEntity.setHealth(damagedHealth); //Hurt entity without the unwanted side effects of damage()
-
-                            //TODO: Do we need to set last damage? Double check
-                            finalDamage = healthBeforeRuptureIsApplied - targetEntity.getHealth();
-
-                            if(finalDamage <= 0) {
-                                mcMMO.p.getLogger().severe("DEBUG: Miscalculating final damage for Rupture");
-                            } else {
-                                //Actually should this even be done?
-                                targetEntity.setLastDamage(finalDamage);
-                            }
                         }
                     }
-
-                    //Update Health bars
-                    MobHealthbarUtils.handleMobHealthbars(targetEntity, finalDamage, mcMMO.p);
                 }
             } else {
                 explode();
@@ -84,8 +70,15 @@ public class RuptureTask extends BukkitRunnable {
         }
     }
 
+    public void refreshRupture() {
+        damageTickTracker = DAMAGE_TICK_INTERVAL;
+        ruptureTick = 0;
+    }
+
     public void explode() {
-        ParticleEffectUtils.playBleedEffect(targetEntity); //Animate
+        targetEntity.setMetadata(mcMMO.EXPLOSION_FROM_RUPTURE, new FixedMetadataValue(mcMMO.p, "null"));
+
+        ParticleEffectUtils.playGreaterImpactEffect(targetEntity); //Animate
 
         if(ruptureSource.getPlayer() != null && ruptureSource.getPlayer().isValid()) {
             targetEntity.damage(getExplosionDamage(), ruptureSource.getPlayer());
@@ -94,6 +87,7 @@ public class RuptureTask extends BukkitRunnable {
         }
 
         targetEntity.removeMetadata(mcMMO.RUPTURE_META_KEY, mcMMO.p);
+
         this.cancel(); //Task no longer needed
     }
 

+ 7 - 6
src/main/java/com/gmail/nossr50/skills/swords/SwordsManager.java

@@ -63,19 +63,20 @@ public class SwordsManager extends SkillManager {
      *
      * @param target The defending entity
      */
-    public void processRupture(@NotNull LivingEntity target) throws IllegalStateException {
-        if(target.hasMetadata(mcMMO.REPLANT_META_KEY)) {
+    public void processRupture(@NotNull LivingEntity target) {
+        if(target.hasMetadata(mcMMO.RUPTURE_META_KEY)) {
+            RuptureTaskMeta ruptureTaskMeta = (RuptureTaskMeta) target.getMetadata(mcMMO.RUPTURE_META_KEY);
+
             if(mmoPlayer.isDebugMode()) {
                 mmoPlayer.getPlayer().sendMessage("Rupture task ongoing for target " + target.toString());
-                RuptureTaskMeta ruptureTaskMeta = (RuptureTaskMeta) target.getMetadata(mcMMO.RUPTURE_META_KEY);
-                RuptureTask ruptureTask = (RuptureTask) target.getMetadata(mcMMO.RUPTURE_META_KEY);
-                mmoPlayer.getPlayer().sendMessage(ruptureTask.toString());
+                mmoPlayer.getPlayer().sendMessage(ruptureTaskMeta.getRuptureTimerTask().toString());
             }
 
+            ruptureTaskMeta.getRuptureTimerTask().refreshRupture();
             return; //Don't apply bleed
         }
 
-        if (RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.SWORDS_RUPTURE, getPlayer())) {
+        if (RandomChanceUtil.rollDice(AdvancedConfig.getInstance().getRuptureChanceToApplyOnHit(getRuptureRank()), 100)) {
 
             if (target instanceof Player) {
                 Player defender = (Player) target;

+ 1 - 1
src/main/java/com/gmail/nossr50/util/MobHealthbarUtils.java

@@ -131,7 +131,7 @@ public final class MobHealthbarUtils {
                 return null;
         }
 
-        int coloredDisplay = (int) Math.ceil(fullDisplay * (healthPercentage / 100.0D));
+        int coloredDisplay = (int) Math.max(Math.ceil(fullDisplay * (healthPercentage / 100.0D)), 0.5);
         int grayDisplay = fullDisplay - coloredDisplay;
 
         StringBuilder healthbar = new StringBuilder(color + "");

+ 8 - 4
src/main/java/com/gmail/nossr50/util/TransientMetadataTools.java

@@ -2,16 +2,17 @@ package com.gmail.nossr50.util;
 
 import com.gmail.nossr50.mcMMO;
 import org.bukkit.entity.LivingEntity;
+import org.jetbrains.annotations.NotNull;
 
 public class TransientMetadataTools {
     public static final String OLD_NAME_METAKEY = TransientMetadataTools.OLD_NAME_METAKEY;
     private final mcMMO pluginRef;
 
-    public TransientMetadataTools(mcMMO pluginRef) {
+    public TransientMetadataTools(@NotNull mcMMO pluginRef) {
         this.pluginRef = pluginRef;
     }
 
-    public void cleanAllMobMetadata(LivingEntity livingEntity) {
+    public void cleanAllLivingEntityMetadata(@NotNull LivingEntity livingEntity) {
         //Since its not written anywhere, apparently the GC won't touch objects with metadata still present on them
         if (livingEntity.hasMetadata(mcMMO.customNameKey)) {
             livingEntity.setCustomName(livingEntity.getMetadata(mcMMO.customNameKey).get(0).asString());
@@ -33,10 +34,13 @@ public class TransientMetadataTools {
             livingEntity.removeMetadata(mcMMO.travelingBlock, pluginRef);
         }
 
-        if(livingEntity.hasMetadata(mcMMO.REPLANT_META_KEY)) {
-            livingEntity.removeMetadata(mcMMO.REPLANT_META_KEY, pluginRef);
+        if(livingEntity.hasMetadata(mcMMO.RUPTURE_META_KEY)) {
+            livingEntity.removeMetadata(mcMMO.RUPTURE_META_KEY, pluginRef);
         }
 
+        if(livingEntity.hasMetadata(mcMMO.EXPLOSION_FROM_RUPTURE)) {
+            livingEntity.removeMetadata(mcMMO.EXPLOSION_FROM_RUPTURE, pluginRef);
+        }
 
         //Cleanup mob metadata
         mcMMO.getCompatibilityManager().getPersistentDataLayer().removeMobFlags(livingEntity);

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

@@ -12,6 +12,7 @@ import com.gmail.nossr50.events.fake.FakeEntityDamageByEntityEvent;
 import com.gmail.nossr50.events.fake.FakeEntityDamageEvent;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.party.PartyManager;
+import com.gmail.nossr50.runnables.skills.AwardCombatXpTask;
 import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager;
 import com.gmail.nossr50.skills.archery.ArcheryManager;
 import com.gmail.nossr50.skills.axes.AxesManager;
@@ -40,7 +41,6 @@ import org.bukkit.potion.PotionEffectType;
 import org.bukkit.projectiles.ProjectileSource;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
-import com.gmail.nossr50.runnables.skills.AwardCombatXpTask;
 
 import java.util.EnumMap;
 import java.util.HashMap;
@@ -93,8 +93,7 @@ public final class CombatUtils {
             mcMMOPlayer.checkAbilityActivation(PrimarySkillType.SWORDS);
         }
 
-        if(target.getHealth() - event.getFinalDamage() >= 1)
-        {
+        if(target.getHealth() - event.getFinalDamage() > 0) {
             if (swordsManager.canUseRupture()) {
                 swordsManager.processRupture(target);
             }

+ 4 - 5
src/main/java/com/gmail/nossr50/util/skills/ParticleEffectUtils.java

@@ -1,19 +1,18 @@
 package com.gmail.nossr50.util.skills;
 
 import com.gmail.nossr50.config.Config;
-import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.util.sounds.SoundManager;
 import com.gmail.nossr50.util.sounds.SoundType;
 import org.apache.commons.lang.math.RandomUtils;
-import org.bukkit.*;
+import org.bukkit.Effect;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.World;
 import org.bukkit.block.Block;
 import org.bukkit.block.BlockFace;
 import org.bukkit.entity.LivingEntity;
 import org.bukkit.entity.Player;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-
 public final class ParticleEffectUtils {
 
     private ParticleEffectUtils() {}