From c078e853ebbd0e2c0aa738cbf7e262ae021b37d1 Mon Sep 17 00:00:00 2001 From: nossr50 Date: Sun, 21 Apr 2024 14:56:57 -0700 Subject: [PATCH] Fix bug where Green Thumb did not replant if seeds were solely in the offhand Fixes #4994 --- .../secondaryabilities/SubSkillEvent.java | 4 - .../com/gmail/nossr50/party/ShareHandler.java | 4 +- .../skills/herbalism/HerbalismManager.java | 80 ++++++++----------- .../com/gmail/nossr50/util/EventUtils.java | 1 - .../com/gmail/nossr50/util/ItemUtils.java | 44 ++++++++++ 5 files changed, 80 insertions(+), 53 deletions(-) diff --git a/src/main/java/com/gmail/nossr50/events/skills/secondaryabilities/SubSkillEvent.java b/src/main/java/com/gmail/nossr50/events/skills/secondaryabilities/SubSkillEvent.java index 7aefb003e..5445bbfcd 100644 --- a/src/main/java/com/gmail/nossr50/events/skills/secondaryabilities/SubSkillEvent.java +++ b/src/main/java/com/gmail/nossr50/events/skills/secondaryabilities/SubSkillEvent.java @@ -16,9 +16,7 @@ public class SubSkillEvent extends McMMOPlayerSkillEvent implements Cancellable * Only skills using the old system will fire this event * @param player target player * @param subSkillType target subskill - * @Deprecated Skills will be using a new system stemming from the AbstractSubSkill class so make sure you check for both events, this event will be removed eventually. */ - @Deprecated public SubSkillEvent(Player player, SubSkillType subSkillType) { super(player, mcMMO.p.getSkillTools().getPrimarySkillBySubSkill(subSkillType)); this.subSkillType = subSkillType; @@ -29,9 +27,7 @@ public class SubSkillEvent extends McMMOPlayerSkillEvent implements Cancellable * @param player target player * @param subSkillType target subskill * @param resultModifier a value multiplied against the final result of the dice roll, typically between 0-1.0 - * @Deprecated Skills will be using a new system stemming from the AbstractSubSkill class so make sure you check for both events, this event will be removed eventually. */ - @Deprecated public SubSkillEvent(Player player, SubSkillType subSkillType, double resultModifier) { super(player, mcMMO.p.getSkillTools().getPrimarySkillBySubSkill(subSkillType)); this.subSkillType = subSkillType; diff --git a/src/main/java/com/gmail/nossr50/party/ShareHandler.java b/src/main/java/com/gmail/nossr50/party/ShareHandler.java index 38aa0e2c3..24392e6b1 100644 --- a/src/main/java/com/gmail/nossr50/party/ShareHandler.java +++ b/src/main/java/com/gmail/nossr50/party/ShareHandler.java @@ -44,7 +44,9 @@ public final class ShareHandler { nearMembers.add(mcMMOPlayer.getPlayer()); int partySize = nearMembers.size(); - double shareBonus = Math.min(mcMMO.p.getGeneralConfig().getPartyShareBonusBase() + (partySize * mcMMO.p.getGeneralConfig().getPartyShareBonusIncrease()), mcMMO.p.getGeneralConfig().getPartyShareBonusCap()); + double shareBonus = Math.min(mcMMO.p.getGeneralConfig().getPartyShareBonusBase() + + (partySize * mcMMO.p.getGeneralConfig().getPartyShareBonusIncrease()), + mcMMO.p.getGeneralConfig().getPartyShareBonusCap()); float splitXp = (float) (xp / partySize * shareBonus); for (Player member : nearMembers) { diff --git a/src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java b/src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java index a2eb57ae1..c75f03a1a 100644 --- a/src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java +++ b/src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java @@ -33,6 +33,7 @@ import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; import org.bukkit.block.data.Ageable; import org.bukkit.block.data.BlockData; +import org.bukkit.entity.Item; import org.bukkit.entity.Player; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.inventory.ItemStack; @@ -41,6 +42,9 @@ import org.jetbrains.annotations.NotNull; import java.util.*; +import static com.gmail.nossr50.util.ItemUtils.hasItemIncludingOffHand; +import static com.gmail.nossr50.util.ItemUtils.removeItemIncludingOffHand; + public class HerbalismManager extends SkillManager { public HerbalismManager(McMMOPlayer mcMMOPlayer) { super(mcMMOPlayer, PrimarySkillType.HERBALISM); @@ -745,13 +749,14 @@ public class HerbalismManager extends SkillManager { * @param blockState The {@link BlockState} to check ability activation for * @param greenTerra boolean to determine if greenTerra is active or not */ - private boolean processGreenThumbPlants(BlockState blockState, BlockBreakEvent blockBreakEvent, boolean greenTerra) { + private boolean processGreenThumbPlants(@NotNull BlockState blockState, @NotNull BlockBreakEvent blockBreakEvent, + boolean greenTerra) { if (!ItemUtils.isHoe(blockBreakEvent.getPlayer().getInventory().getItemInMainHand()) && !ItemUtils.isAxe(blockBreakEvent.getPlayer().getInventory().getItemInMainHand())) { return false; } - BlockData blockData = blockState.getBlockData(); + final BlockData blockData = blockState.getBlockData(); if (!(blockData instanceof Ageable ageable)) { return false; @@ -759,47 +764,28 @@ public class HerbalismManager extends SkillManager { //If the ageable is NOT mature and the player is NOT using a hoe, abort - Player player = getPlayer(); - PlayerInventory playerInventory = player.getInventory(); - Material seed; + final Player player = getPlayer(); + final Material replantMaterial; - switch (blockState.getType().getKey().getKey().toLowerCase(Locale.ROOT)) { - case "carrots": - seed = Material.matchMaterial("CARROT"); - break; - - case "wheat": - seed = Material.matchMaterial("WHEAT_SEEDS"); - break; - - case "nether_wart": - seed = Material.getMaterial("NETHER_WART"); - break; - - case "potatoes": - seed = Material.matchMaterial("POTATO"); - break; - - case "beetroots": - seed = Material.matchMaterial("BEETROOT_SEEDS"); - break; - - case "cocoa": - seed = Material.matchMaterial("COCOA_BEANS"); - break; - - case "torchflower": - seed = Material.matchMaterial("TORCHFLOWER_SEEDS"); - break; - default: + switch (blockState.getType().getKey().getKey().toLowerCase(Locale.ENGLISH)) { + case "carrots" -> replantMaterial = Material.matchMaterial("CARROT"); + case "wheat" -> replantMaterial = Material.matchMaterial("WHEAT_SEEDS"); + case "nether_wart" -> replantMaterial = Material.getMaterial("NETHER_WART"); + case "potatoes" -> replantMaterial = Material.matchMaterial("POTATO"); + case "beetroots" -> replantMaterial = Material.matchMaterial("BEETROOT_SEEDS"); + case "cocoa" -> replantMaterial = Material.matchMaterial("COCOA_BEANS"); + case "torchflower" -> replantMaterial = Material.matchMaterial("TORCHFLOWER_SEEDS"); + default -> { return false; + } } - - ItemStack seedStack = new ItemStack(seed); + if (replantMaterial == null) { + return false; + } if (ItemUtils.isAxe(blockBreakEvent.getPlayer().getInventory().getItemInMainHand()) - && blockState.getType() != Material.COCOA) { + && blockState.getType() != Material.COCOA) { return false; } @@ -807,25 +793,25 @@ public class HerbalismManager extends SkillManager { return false; } - if (!playerInventory.containsAtLeast(seedStack, 1)) { + if (!hasItemIncludingOffHand(player, replantMaterial)) { return false; } - if (!processGrowingPlants(blockState, ageable, blockBreakEvent, greenTerra)) { - return false; - } - - if(EventUtils.callSubSkillBlockEvent(player, SubSkillType.HERBALISM_GREEN_THUMB, blockState.getBlock()).isCancelled()) { + if(EventUtils.callSubSkillBlockEvent(player, SubSkillType.HERBALISM_GREEN_THUMB, blockState.getBlock()) + .isCancelled()) { return false; } else { - playerInventory.removeItem(seedStack); - player.updateInventory(); // Needed until replacement available + if (!processGrowingPlants(blockState, ageable, blockBreakEvent, greenTerra)) { + return false; + } + // remove the item from the player's inventory + removeItemIncludingOffHand(player, replantMaterial, 1); + // player.updateInventory(); // Needed until replacement available + //Play sound SoundManager.sendSound(player, player.getLocation(), SoundType.ITEM_CONSUMED); return true; } - -// new HerbalismBlockUpdaterTask(blockState).runTaskLater(mcMMO.p, 0); } private boolean processGrowingPlants(BlockState blockState, Ageable ageable, BlockBreakEvent blockBreakEvent, boolean greenTerra) { diff --git a/src/main/java/com/gmail/nossr50/util/EventUtils.java b/src/main/java/com/gmail/nossr50/util/EventUtils.java index 1bf700c04..f53fde6df 100644 --- a/src/main/java/com/gmail/nossr50/util/EventUtils.java +++ b/src/main/java/com/gmail/nossr50/util/EventUtils.java @@ -197,7 +197,6 @@ public final class EventUtils { * @param block associated block * @return the event after it has been fired */ - @Deprecated public static @NotNull SubSkillBlockEvent callSubSkillBlockEvent(@NotNull Player player, @NotNull SubSkillType subSkillType, @NotNull Block block) { SubSkillBlockEvent event = new SubSkillBlockEvent(player, subSkillType, block); mcMMO.p.getServer().getPluginManager().callEvent(event); diff --git a/src/main/java/com/gmail/nossr50/util/ItemUtils.java b/src/main/java/com/gmail/nossr50/util/ItemUtils.java index 04993eb74..6055582e3 100644 --- a/src/main/java/com/gmail/nossr50/util/ItemUtils.java +++ b/src/main/java/com/gmail/nossr50/util/ItemUtils.java @@ -41,6 +41,50 @@ public final class ItemUtils { return mcMMO.getMaterialMapStore().isBow(item.getType().getKey().getKey()); } + /** + * Checks if a player has an item in their inventory or offhand. + * + * @param player Player to check + * @param material Material to check for + * @return true if the player has the item in their inventory or offhand, false otherwise + */ + public static boolean hasItemIncludingOffHand(Player player, Material material) { + // Checks main inventory / item bar + boolean containsInMain = player.getInventory().contains(material); + + if (containsInMain) { + return true; + } + + return player.getInventory().getItemInOffHand().getType() == material; + } + + /** + * Removes an item from a player's inventory, including their offhand. + * + * @param player Player to remove the item from + * @param material Material to remove + * @param amount Amount of the material to remove + */ + public static void removeItemIncludingOffHand(@NotNull Player player, @NotNull Material material, int amount) { + // Checks main inventory / item bar + if (player.getInventory().contains(material)) { + player.getInventory().removeItem(new ItemStack(material, amount)); + return; + } + + // Check off-hand + final ItemStack offHandItem = player.getInventory().getItemInOffHand(); + if (offHandItem.getType() == material) { + int newAmount = offHandItem.getAmount() - amount; + if (newAmount > 0) { + offHandItem.setAmount(newAmount); + } else { + player.getInventory().setItemInOffHand(new ItemStack(Material.AIR)); + } + } + } + // TODO: Unit tests public static boolean isCrossbow(@NotNull ItemStack item) { return mcMMO.getMaterialMapStore().isCrossbow(item.getType().getKey().getKey());