Browse Source

Fix Blast Mining Fixes #5021

nossr50 1 year ago
parent
commit
2debcbefd0

+ 3 - 0
Changelog.txt

@@ -1,4 +1,7 @@
 Version 2.2.017
+    Fixed Blast Mining being almost completely broken
+    Reworked Blast Mining to drop non-mining related blocks too
+    Reworked Blast Mining to use your pickaxe when determining drops (will apply Silk Touch)
     Fixed shift-clicking ingredients into the brewing stand not working on older versions of Minecraft
     Added a setting in advanced.yml to ignore attack cooldowns (see notes)
     Fixed a bug with Mace permissions (thanks SrBedrock)

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

@@ -48,7 +48,7 @@ public class MiningCommand extends SkillCommand {
 
             blastMiningRank = miningManager.getBlastMiningTier();
             bonusTNTDrops = miningManager.getDropMultiplier();
-            oreBonus = percent.format(miningManager.getOreBonus() / 30.0D); // Base received in TNT is 30%
+            oreBonus = percent.format(miningManager.getOreBonus()); // Base received in TNT is 30%
 //            debrisReduction = percent.format(miningManager.getDebrisReduction() / 30.0D); // Base received in TNT is 30%
             blastDamageDecrease = percent.format(miningManager.getBlastDamageModifier() / 100.0D);
             blastRadiusIncrease = miningManager.getBlastRadiusModifier();

+ 14 - 48
src/main/java/com/gmail/nossr50/datatypes/skills/subskills/acrobatics/Roll.java

@@ -75,7 +75,8 @@ public class Roll extends AcrobaticsSubSkill {
              */
             
             if (canRoll(mmoPlayer)) {
-                entityDamageEvent.setDamage(rollCheck(mmoPlayer, entityDamageEvent.getFinalDamage()));
+                entityDamageEvent.setDamage(
+                        rollCheck(mmoPlayer, entityDamageEvent.getFinalDamage(), mmoPlayer.getPlayer().isSneaking()));
 
                 if (entityDamageEvent.getFinalDamage() == 0) {
                     entityDamageEvent.setCancelled(true);
@@ -189,64 +190,24 @@ public class Roll extends AcrobaticsSubSkill {
                 && Permissions.isSubSkillEnabled(mmoPlayer.getPlayer(), SubSkillType.ACROBATICS_ROLL);
     }
 
-    /**
-     * Handle the damage reduction and XP gain from the Roll ability
-     *
-     * @param damage The amount of damage initially dealt by the event
-     * @return the modified event damage if the ability was successful, the original event damage otherwise
-     */
-    @VisibleForTesting
-    public double rollCheck(McMMOPlayer mmoPlayer, double damage) {
-        int skillLevel = mmoPlayer.getSkillLevel(getPrimarySkill());
-
-        if (mmoPlayer.getPlayer().isSneaking()) {
-            return gracefulRollCheck(mmoPlayer, damage, skillLevel);
-        }
-
-        double modifiedDamage = calculateModifiedRollDamage(damage, mcMMO.p.getAdvancedConfig().getRollDamageThreshold());
-
-        if (!isFatal(mmoPlayer, modifiedDamage)
-                && ProbabilityUtil.isSkillRNGSuccessful(SubSkillType.ACROBATICS_ROLL, mmoPlayer)) {
-            NotificationManager.sendPlayerInformation(mmoPlayer.getPlayer(), NotificationType.SUBSKILL_MESSAGE, "Acrobatics.Roll.Text");
-            SoundManager.sendCategorizedSound(mmoPlayer.getPlayer(), mmoPlayer.getPlayer().getLocation(), SoundType.ROLL_ACTIVATED, SoundCategory.PLAYERS);
-            //mmoPlayer.getPlayer().sendMessage(LocaleLoader.getString("Acrobatics.Roll.Text"));
-
-            //if (!SkillUtils.cooldownExpired((long) mcMMOmmoPlayer.getPlayer().getTeleportATS(), Config.getInstance().getXPAfterTeleportCooldown())) {
-            if (!isExploiting(mmoPlayer) && mmoPlayer.getAcrobaticsManager().canGainRollXP())
-                SkillUtils.applyXpGain(mmoPlayer, getPrimarySkill(), calculateRollXP(mmoPlayer, damage, true), XPGainReason.PVE);
-            //}
-
-            addFallLocation(mmoPlayer);
-            return modifiedDamage;
-        } else if (!isFatal(mmoPlayer, damage)) {
-            //if (!SkillUtils.cooldownExpired((long) mmoPlayer.getTeleportATS(), Config.getInstance().getXPAfterTeleportCooldown())) {
-            if (!isExploiting(mmoPlayer) && mmoPlayer.getAcrobaticsManager().canGainRollXP())
-                SkillUtils.applyXpGain(mmoPlayer, getPrimarySkill(), calculateRollXP(mmoPlayer, damage, false), XPGainReason.PVE);
-            //}
-        }
-
-        addFallLocation(mmoPlayer);
-        return damage;
-    }
-
     private int getActivationChance(McMMOPlayer mmoPlayer) {
         return PerksUtils.handleLuckyPerks(mmoPlayer, getPrimarySkill());
     }
 
     /**
-     * Handle the damage reduction and XP gain from the Graceful Roll ability
+     * Handle the damage reduction and XP gain from the Roll / Graceful Roll ability
      *
      * @param damage The amount of damage initially dealt by the event
      * @return the modified event damage if the ability was successful, the original event damage otherwise
      */
-    private double gracefulRollCheck(McMMOPlayer mmoPlayer, double damage, int skillLevel) {
-        double modifiedDamage = calculateModifiedRollDamage(damage, mcMMO.p.getAdvancedConfig().getRollDamageThreshold() * 2);
-
-        final Probability gracefulProbability = getGracefulProbability(mmoPlayer);
+    private double rollCheck(McMMOPlayer mmoPlayer, double damage, boolean isGracefulRoll) {
+        final Probability probability
+                = isGracefulRoll ? getGracefulProbability(mmoPlayer) : getNonGracefulProbability(mmoPlayer);
+        double modifiedDamage = calculateModifiedRollDamage(damage,
+                mcMMO.p.getAdvancedConfig().getRollDamageThreshold() * 2);
 
         if (!isFatal(mmoPlayer, modifiedDamage)
-                //TODO: Graceful isn't sending out an event
-                && ProbabilityUtil.isStaticSkillRNGSuccessful(PrimarySkillType.ACROBATICS, mmoPlayer, gracefulProbability)) {
+                && ProbabilityUtil.isStaticSkillRNGSuccessful(PrimarySkillType.ACROBATICS, mmoPlayer, probability)) {
             NotificationManager.sendPlayerInformation(mmoPlayer.getPlayer(), NotificationType.SUBSKILL_MESSAGE, "Acrobatics.Ability.Proc");
             SoundManager.sendCategorizedSound(mmoPlayer.getPlayer(), mmoPlayer.getPlayer().getLocation(), SoundType.ROLL_ACTIVATED, SoundCategory.PLAYERS,0.5F);
             if (!isExploiting(mmoPlayer) && mmoPlayer.getAcrobaticsManager().canGainRollXP())
@@ -270,6 +231,11 @@ public class Roll extends AcrobaticsSubSkill {
         return Probability.ofValue(gracefulOdds);
     }
 
+    public static Probability getNonGracefulProbability(McMMOPlayer mmoPlayer) {
+        double gracefulOdds = ProbabilityUtil.getSubSkillProbability(SubSkillType.ACROBATICS_ROLL, mmoPlayer).getValue();
+        return Probability.ofValue(gracefulOdds);
+    }
+
     /**
      * Check if the player is "farming" Acrobatics XP using
      * exploits in the game.

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

@@ -756,7 +756,7 @@ public class EntityListener implements Listener {
         if (WorldBlacklist.isWorldBlacklisted(event.getEntity().getWorld()))
             return;
 
-        Entity entity = event.getEntity();
+        final Entity entity = event.getEntity();
 
         if (!(entity instanceof TNTPrimed) || !entity.hasMetadata(MetadataConstants.METADATA_KEY_TRACKED_TNT)) {
             return;
@@ -764,13 +764,14 @@ public class EntityListener implements Listener {
 
         // We can make this assumption because we (should) be the only ones
         // using this exact metadata
-        Player player = pluginRef.getServer().getPlayerExact(entity.getMetadata(MetadataConstants.METADATA_KEY_TRACKED_TNT).get(0).asString());
+        final Player player = pluginRef.getServer().getPlayerExact(
+                entity.getMetadata(MetadataConstants.METADATA_KEY_TRACKED_TNT).get(0).asString());
 
         if (!UserManager.hasPlayerDataKey(player)) {
             return;
         }
 
-        //Profile not loaded
+        // Profile is not loaded
         if (UserManager.getPlayer(player) == null) {
             return;
         }
@@ -781,7 +782,7 @@ public class EntityListener implements Listener {
                 return;
         }
 
-        MiningManager miningManager = UserManager.getPlayer(player).getMiningManager();
+        final MiningManager miningManager = UserManager.getPlayer(player).getMiningManager();
 
         if (miningManager.canUseBiggerBombs()) {
             event.setRadius(miningManager.biggerBombs(event.getRadius()));

+ 1 - 51
src/main/java/com/gmail/nossr50/skills/mining/BlastMining.java

@@ -10,58 +10,17 @@ import org.bukkit.entity.TNTPrimed;
 import org.bukkit.event.entity.EntityDamageByEntityEvent;
 
 public class BlastMining {
-    // The order of the values is extremely important, a few methods depend on it to work properly
-   /* public enum Tier {
-        EIGHT(8),
-        SEVEN(7),
-        SIX(6),
-        FIVE(5),
-        FOUR(4),
-        THREE(3),
-        TWO(2),
-        ONE(1);
-
-        int numerical;
-
-        private Tier(int numerical) {
-            this.numerical = numerical;
-        }
-
-        public int toNumerical() {
-            return numerical;
-        }
-
-        protected int getLevel() {
-            return mcMMO.p.getAdvancedConfig().getBlastMiningRankLevel(this);
-        }
-
-
-    }*/
-
     public final static int MAXIMUM_REMOTE_DETONATION_DISTANCE = 100;
 
     public static double getBlastRadiusModifier(int rank) {
         return mcMMO.p.getAdvancedConfig().getBlastRadiusModifier(rank);
     }
 
-
-
     public static double getBlastDamageDecrease(int rank) {
         return mcMMO.p.getAdvancedConfig().getBlastDamageDecrease(rank);
     }
 
-
-
     public static int getDemolitionExpertUnlockLevel() {
-        /*List<Tier> tierList = Arrays.asList(Tier.values());
-        for (Tier tier : tierList) {
-            if (tier.getBlastDamageDecrease() > 0) {
-                continue;
-            }
-
-            return tier == Tier.EIGHT ? tier.getLevel() : tierList.get(tierList.indexOf(tier) - 1).getLevel();
-        }*/
-
         for(int i = 0; i < SubSkillType.MINING_BLAST_MINING.getNumRanks()-1; i++) {
             if (getBlastDamageDecrease(i+1) > 0)
                 return RankUtils.getRankUnlockLevel(SubSkillType.MINING_BLAST_MINING, i+1);
@@ -71,15 +30,6 @@ public class BlastMining {
     }
 
     public static int getBiggerBombsUnlockLevel() {
-        /*List<Tier> tierList = Arrays.asList(Tier.values());
-        for (Tier tier : tierList) {
-            if (tier.getBlastRadiusModifier() > 1.0) {
-                continue;
-            }
-
-            return tier == Tier.EIGHT ? tier.getLevel() : tierList.get(tierList.indexOf(tier) - 1).getLevel();
-        }*/
-
         for(int i = 0; i < SubSkillType.MINING_BLAST_MINING.getNumRanks()-1; i++) {
             if (getBlastRadiusModifier(i+1) > 0)
                 return RankUtils.getRankUnlockLevel(SubSkillType.MINING_BLAST_MINING, i+1);
@@ -104,7 +54,7 @@ public class BlastMining {
             return false;
         }
 
-        MiningManager miningManager =  UserManager.getPlayer(defender).getMiningManager();
+        final MiningManager miningManager =  UserManager.getPlayer(defender).getMiningManager();
 
         if (!miningManager.canUseDemolitionsExpertise()) {
             return false;

+ 45 - 35
src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java

@@ -17,7 +17,6 @@ import com.gmail.nossr50.util.random.Probability;
 import com.gmail.nossr50.util.random.ProbabilityUtil;
 import com.gmail.nossr50.util.skills.RankUtils;
 import com.gmail.nossr50.util.skills.SkillUtils;
-import org.apache.commons.lang3.RandomUtils;
 import org.bukkit.Material;
 import org.bukkit.block.Block;
 import org.bukkit.block.BlockState;
@@ -30,8 +29,11 @@ import org.bukkit.inventory.ItemStack;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
+import static com.gmail.nossr50.util.ItemUtils.isPickaxe;
+
 public class MiningManager extends SkillManager {
 
     public static final String BUDDING_AMETHYST = "budding_amethyst";
@@ -51,7 +53,7 @@ public class MiningManager extends SkillManager {
         Player player = getPlayer();
 
         return canUseBlastMining() && player.isSneaking()
-                && (ItemUtils.isPickaxe(getPlayer().getInventory().getItemInMainHand()) || player.getInventory().getItemInMainHand().getType() == mcMMO.p.getGeneralConfig().getDetonatorItem())
+                && (isPickaxe(getPlayer().getInventory().getItemInMainHand()) || player.getInventory().getItemInMainHand().getType() == mcMMO.p.getGeneralConfig().getDetonatorItem())
                 && Permissions.remoteDetonation(player);
     }
 
@@ -168,69 +170,76 @@ public class MiningManager extends SkillManager {
      * @param yield The % of blocks to drop
      * @param event The {@link EntityExplodeEvent}
      */
-    //TODO: Rewrite this garbage
     public void blastMiningDropProcessing(float yield, EntityExplodeEvent event) {
         if (yield == 0)
             return;
 
-        //Strip out only stuff that gives mining XP
+        var increasedYieldFromBonuses = yield + (yield * getOreBonus());
+        // Strip out only stuff that gives mining XP
         List<BlockState> ores = new ArrayList<>();
-
         List<BlockState> notOres = new ArrayList<>();
         for (Block targetBlock : event.blockList()) {
             BlockState blockState = targetBlock.getState();
-            //Containers usually have 0 XP unless someone edited their config in a very strange way
-            if (ExperienceConfig.getInstance().getXp(PrimarySkillType.MINING, targetBlock) != 0
-                    && !(targetBlock instanceof Container)
-                    && !mcMMO.getUserBlockTracker().isIneligible(targetBlock)) {
-                if (BlockUtils.isOre(blockState)) {
+
+            if(mcMMO.getUserBlockTracker().isIneligible(targetBlock))
+                continue;
+
+            if (ExperienceConfig.getInstance().getXp(PrimarySkillType.MINING, targetBlock) != 0) {
+                if (BlockUtils.isOre(blockState) && !(targetBlock instanceof Container)) {
                     ores.add(blockState);
-                } else {
-                    notOres.add(blockState);
                 }
+            } else {
+                notOres.add(blockState);
             }
         }
 
         int xp = 0;
-
-        float oreBonus = (float) (getOreBonus() / 100);
-        float debrisReduction = (float) (getDebrisReduction() / 100);
         int dropMultiplier = getDropMultiplier();
-        float debrisYield = yield - debrisReduction;
 
-        //Drop "debris" based on skill modifiers
         for(BlockState blockState : notOres) {
             if (isDropIllegal(blockState.getType()))
                 continue;
 
             if (Probability.ofPercent(50).evaluate()) {
-                ItemUtils.spawnItem(getPlayer(), Misc.getBlockCenter(blockState), new ItemStack(blockState.getType()), ItemSpawnReason.BLAST_MINING_DEBRIS_NON_ORES); // Initial block that would have been dropped
+                ItemUtils.spawnItem(getPlayer(),
+                        Misc.getBlockCenter(blockState),
+                        new ItemStack(blockState.getType()),
+                        ItemSpawnReason.BLAST_MINING_DEBRIS_NON_ORES); // Initial block that would have been dropped
             }
         }
-
         for (BlockState blockState : ores) {
-            if (isDropIllegal(blockState.getType()))
-                continue;
-
-            if (RandomUtils.nextFloat() < (yield + oreBonus)) {
-                xp += Mining.getBlockXp(blockState);
+            // currentOreYield only used for drop calculations for ores
+            float currentOreYield = increasedYieldFromBonuses;
 
-                ItemUtils.spawnItem(getPlayer(), Misc.getBlockCenter(blockState), new ItemStack(blockState.getType()), ItemSpawnReason.BLAST_MINING_ORES); // Initial block that would have been dropped
+            if (isDropIllegal(blockState.getType())) {
+                continue;
+            }
 
-                if (mcMMO.p.getAdvancedConfig().isBlastMiningBonusDropsEnabled() && !mcMMO.getUserBlockTracker().isIneligible(blockState)) {
-                    for (int i = 1; i < dropMultiplier; i++) {
-//                        Bukkit.broadcastMessage("Bonus Drop on Ore: "+blockState.getType().toString());
-                        ItemUtils.spawnItem(getPlayer(), Misc.getBlockCenter(blockState), new ItemStack(blockState.getType()), ItemSpawnReason.BLAST_MINING_ORES_BONUS_DROP); // Initial block that would have been dropped
+            // Always give XP for every ore destroyed
+            xp += Mining.getBlockXp(blockState);
+            while(currentOreYield > 0) {
+                if (Probability.ofValue(currentOreYield).evaluate()) {
+                    Collection<ItemStack> oreDrops = isPickaxe(mmoPlayer.getPlayer().getInventory().getItemInMainHand())
+                            ? blockState.getBlock().getDrops(mmoPlayer.getPlayer().getInventory().getItemInMainHand())
+                            : List.of(new ItemStack(blockState.getType()));
+                    ItemUtils.spawnItems(getPlayer(), Misc.getBlockCenter(blockState),
+                            oreDrops, ItemSpawnReason.BLAST_MINING_ORES);
+
+                    if (mcMMO.p.getAdvancedConfig().isBlastMiningBonusDropsEnabled()) {
+                        for (int i = 1; i < dropMultiplier; i++) {
+                            ItemUtils.spawnItems(getPlayer(),
+                                    Misc.getBlockCenter(blockState),
+                                    oreDrops,
+                                    ItemSpawnReason.BLAST_MINING_ORES_BONUS_DROP);
+                        }
                     }
                 }
+                currentOreYield = Math.max(currentOreYield - 1, 0);
             }
         }
 
-        //Replace the event blocklist with the newYield list
+        // Replace the event blocklist with the newYield list
         event.setYield(0F);
-//        event.blockList().clear();
-//        event.blockList().addAll(notOres);
-
         applyXpGain(xp, XPGainReason.PVE);
     }
 
@@ -273,10 +282,11 @@ public class MiningManager extends SkillManager {
      *
      * @return the Blast Mining tier
      */
-    public double getOreBonus() {
-        return getOreBonus(getBlastMiningTier());
+    public float getOreBonus() {
+        return (float) (mcMMO.p.getAdvancedConfig().getOreBonus(getBlastMiningTier()) / 100F);
     }
 
+    @Deprecated(since = "2.2.017", forRemoval = true)
     public static double getOreBonus(int rank) {
         return mcMMO.p.getAdvancedConfig().getOreBonus(rank);
     }

+ 15 - 0
src/main/java/com/gmail/nossr50/util/ItemUtils.java

@@ -681,6 +681,21 @@ public final class ItemUtils {
         return enchantmentWrappers.get(randomIndex);
     }
 
+    /**
+     * Drop items at a given location.
+     *
+     * @param location The location to drop the items at
+     * @param itemStacks The items to drop
+     */
+    public static void spawnItems(@Nullable Player player,
+                                  @NotNull Location location,
+                                  @NotNull Collection<ItemStack> itemStacks,
+                                  @NotNull ItemSpawnReason itemSpawnReason) {
+        for (ItemStack is : itemStacks) {
+            spawnItem(player, location, is, itemSpawnReason);
+        }
+    }
+
     /**
      * Drop items at a given location.
      *

+ 0 - 2
src/main/resources/locale/locale_en_US.properties

@@ -165,8 +165,6 @@ Alchemy.Listener=Alchemy:
 Alchemy.Ability.Locked.0=LOCKED UNTIL {0}+ SKILL (CATALYSIS)
 Alchemy.SkillName=ALCHEMY
 #ARCHERY
-
-
 Archery.SubSkill.SkillShot.Name=Skill Shot
 Archery.SubSkill.SkillShot.Description=Increases damage done with bows
 Archery.SubSkill.SkillShot.Stat=Skill Shot Bonus Damage