From 65fba3e20ebd74d350a6d11d4e8fee1c6b2bde80 Mon Sep 17 00:00:00 2001 From: nossr50 Date: Mon, 2 Nov 2020 13:51:43 -0800 Subject: [PATCH] Expanding McMMOItemSpawnEvent & Fixing a bug with Tree Feller drops --- Changelog.txt | 11 + .../gmail/nossr50/api/ItemSpawnReason.java | 17 + .../datatypes/skills/SuperAbilityType.java | 2 +- .../events/items/McMMOItemSpawnEvent.java | 26 +- .../nossr50/listeners/BlockListener.java | 22 +- .../gmail/nossr50/skills/archery/Archery.java | 6 +- .../skills/excavation/ExcavationManager.java | 3 +- .../skills/fishing/FishingManager.java | 5 +- .../skills/herbalism/HerbalismManager.java | 3 +- .../nossr50/skills/mining/MiningManager.java | 7 +- .../skills/salvage/SalvageManager.java | 5 +- .../skills/unarmed/UnarmedManager.java | 3 +- .../woodcutting/WoodcuttingManager.java | 76 ++--- .../com/gmail/nossr50/util/BlockUtils.java | 12 +- .../com/gmail/nossr50/util/EventUtils.java | 13 +- .../gmail/nossr50/util/MaterialMapStore.java | 313 ++++++++---------- .../java/com/gmail/nossr50/util/Misc.java | 74 +++-- .../com/gmail/nossr50/util/ModManager.java | 4 - 18 files changed, 318 insertions(+), 284 deletions(-) create mode 100644 src/main/java/com/gmail/nossr50/api/ItemSpawnReason.java diff --git a/Changelog.txt b/Changelog.txt index 3ded13a63..d9fc0899d 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,3 +1,14 @@ +Version 2.1.152 + Updated hu_HU locale (thanks andris) + Fixed a bug where Tree Feller would sometimes double drop blocks inappropriately + Added some code to prevent a possible NPE when spawning items in a world that got unloaded + (API) New ENUM ItemSpawnReason which gives context for why mcMMO is dropping an item + (API) McMMOItemSpawnEvent::getItemSpawnReason() was added + (API) Many instances of spawning items that didn't used to create and call an McMMOItemSpawnEvent now do + + NOTES: + I really should stop letting my OCD compel me to rewrite code all the time. + Version 2.1.151 Added new config for chat options named 'chat.yml' Added 'Chat.Channels.Party.Spies.Automatically_Enable_Spying' to chat.yml which when enabled will start users who have the chat spy permission in chat spying mode diff --git a/src/main/java/com/gmail/nossr50/api/ItemSpawnReason.java b/src/main/java/com/gmail/nossr50/api/ItemSpawnReason.java new file mode 100644 index 000000000..29fdc1d29 --- /dev/null +++ b/src/main/java/com/gmail/nossr50/api/ItemSpawnReason.java @@ -0,0 +1,17 @@ +package com.gmail.nossr50.api; + +public enum ItemSpawnReason { + ARROW_RETRIEVAL_ACTIVATED, //Players sometimes can retrieve arrows instead of losing them when hitting a mob + EXCAVATION_TREASURE, //Any drops when excavation treasures activate fall under this + FISHING_EXTRA_FISH, //A config setting allows more fish to be found when fishing, the extra fish are part of this + FISHING_SHAKE_TREASURE, //When using a fishing rod on a mob and finding a treasure via Shake + HYLIAN_LUCK_TREASURE, //When finding a treasure in grass via hylian luck + BLAST_MINING_DEBRIS_NON_ORES, //The non-ore debris that are dropped from blast mining + BLAST_MINING_ORES, //The ore(s) which may include player placed ores being dropped from blast mining + BLAST_MINING_ORES_BONUS_DROP, //Any bonus ores that drop from a result of a players Mining skills + UNARMED_DISARMED_ITEM, //When you disarm an opponent and they drop their weapon + SALVAGE_ENCHANTMENT_BOOK, //When you salvage an enchanted item and get the enchantment back in book form + SALVAGE_MATERIALS, //When you salvage an item and get materials back + TREE_FELLER_DISPLACED_BLOCK, + BONUS_DROPS, //Can be from Mining, Woodcutting, Herbalism, etc +} diff --git a/src/main/java/com/gmail/nossr50/datatypes/skills/SuperAbilityType.java b/src/main/java/com/gmail/nossr50/datatypes/skills/SuperAbilityType.java index 66c4957a9..dddb4bef5 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/skills/SuperAbilityType.java +++ b/src/main/java/com/gmail/nossr50/datatypes/skills/SuperAbilityType.java @@ -226,7 +226,7 @@ public enum SuperAbilityType { return BlockUtils.affectedBySuperBreaker(blockState); case TREE_FELLER: - return BlockUtils.isLog(blockState); + return BlockUtils.hasWoodcuttingXP(blockState); default: return false; diff --git a/src/main/java/com/gmail/nossr50/events/items/McMMOItemSpawnEvent.java b/src/main/java/com/gmail/nossr50/events/items/McMMOItemSpawnEvent.java index 3bfb95532..a626ebf00 100644 --- a/src/main/java/com/gmail/nossr50/events/items/McMMOItemSpawnEvent.java +++ b/src/main/java/com/gmail/nossr50/events/items/McMMOItemSpawnEvent.java @@ -1,5 +1,6 @@ package com.gmail.nossr50.events.items; +import com.gmail.nossr50.api.ItemSpawnReason; import org.bukkit.Location; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; @@ -14,38 +15,49 @@ public class McMMOItemSpawnEvent extends Event implements Cancellable { private Location location; private ItemStack itemStack; private boolean cancelled; + private final ItemSpawnReason itemSpawnReason; - public McMMOItemSpawnEvent(Location location, ItemStack itemStack) { + public McMMOItemSpawnEvent(@NotNull Location location, @NotNull ItemStack itemStack, @NotNull ItemSpawnReason itemSpawnReason) { this.location = location; this.itemStack = itemStack; + this.itemSpawnReason = itemSpawnReason; this.cancelled = false; } + /** + * The reason an item is being spawned by mcMMO + * @see ItemSpawnReason + * @return the item drop reason + */ + public ItemSpawnReason getItemSpawnReason() { + return itemSpawnReason; + } + /** * @return Location where the item will be dropped */ - public Location getLocation() { + public @NotNull Location getLocation() { return location; } /** * @param location Location where to drop the item */ - public void setLocation(Location location) { + public void setLocation(@NotNull Location location) { this.location = location; } /** * @return ItemStack that will be dropped */ - public ItemStack getItemStack() { + public @NotNull ItemStack getItemStack() { return itemStack; } /** * @param itemStack ItemStack to drop */ - public void setItemStack(ItemStack itemStack) { + public void setItemStack(@NotNull ItemStack itemStack) { this.itemStack = itemStack; } @@ -61,14 +73,14 @@ public class McMMOItemSpawnEvent extends Event implements Cancellable { } /** Rest of file is required boilerplate for custom events **/ - private static final HandlerList handlers = new HandlerList(); + private static final @NotNull HandlerList handlers = new HandlerList(); @Override public @NotNull HandlerList getHandlers() { return handlers; } - public static HandlerList getHandlerList() { + public static @NotNull HandlerList getHandlerList() { return handlers; } } diff --git a/src/main/java/com/gmail/nossr50/listeners/BlockListener.java b/src/main/java/com/gmail/nossr50/listeners/BlockListener.java index 94d038468..14b043e9f 100644 --- a/src/main/java/com/gmail/nossr50/listeners/BlockListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/BlockListener.java @@ -1,5 +1,6 @@ package com.gmail.nossr50.listeners; +import com.gmail.nossr50.api.ItemSpawnReason; import com.gmail.nossr50.config.Config; import com.gmail.nossr50.config.HiddenConfig; import com.gmail.nossr50.config.WorldBlacklist; @@ -19,10 +20,7 @@ import com.gmail.nossr50.skills.mining.MiningManager; import com.gmail.nossr50.skills.repair.Repair; import com.gmail.nossr50.skills.salvage.Salvage; import com.gmail.nossr50.skills.woodcutting.WoodcuttingManager; -import com.gmail.nossr50.util.BlockUtils; -import com.gmail.nossr50.util.EventUtils; -import com.gmail.nossr50.util.ItemUtils; -import com.gmail.nossr50.util.Permissions; +import com.gmail.nossr50.util.*; import com.gmail.nossr50.util.player.UserManager; import com.gmail.nossr50.util.skills.SkillUtils; import com.gmail.nossr50.util.sounds.SoundManager; @@ -98,7 +96,7 @@ public class BlockListener implements Listener { int bonusCount = bonusDropMeta.asInt(); for (int i = 0; i < bonusCount; i++) { - event.getBlock().getWorld().dropItemNaturally(event.getBlockState().getLocation(), is); + Misc.spawnItemNaturally(event.getBlockState().getLocation(), is, ItemSpawnReason.BONUS_DROPS); } } } @@ -356,13 +354,17 @@ public class BlockListener implements Listener { } /* WOOD CUTTING */ - else if (BlockUtils.isLog(blockState) && ItemUtils.isAxe(heldItem) && PrimarySkillType.WOODCUTTING.getPermissions(player) && !mcMMO.getPlaceStore().isTrue(blockState)) { + else if (BlockUtils.hasWoodcuttingXP(blockState) && ItemUtils.isAxe(heldItem) && PrimarySkillType.WOODCUTTING.getPermissions(player) && !mcMMO.getPlaceStore().isTrue(blockState)) { WoodcuttingManager woodcuttingManager = mcMMOPlayer.getWoodcuttingManager(); if (woodcuttingManager.canUseTreeFeller(heldItem)) { woodcuttingManager.processTreeFeller(blockState); } else { - woodcuttingManager.woodcuttingBlockCheck(blockState); + //Check for XP + woodcuttingManager.processWoodcuttingBlockXP(blockState); + + //Check for bonus drops + woodcuttingManager.processHarvestLumber(blockState); } } @@ -491,7 +493,7 @@ public class BlockListener implements Listener { if (mcMMOPlayer.getToolPreparationMode(ToolType.HOE) && ItemUtils.isHoe(heldItem) && (BlockUtils.affectedByGreenTerra(blockState) || BlockUtils.canMakeMossy(blockState)) && Permissions.greenTerra(player)) { mcMMOPlayer.checkAbilityActivation(PrimarySkillType.HERBALISM); } - else if (mcMMOPlayer.getToolPreparationMode(ToolType.AXE) && ItemUtils.isAxe(heldItem) && BlockUtils.isLog(blockState) && Permissions.treeFeller(player)) { + else if (mcMMOPlayer.getToolPreparationMode(ToolType.AXE) && ItemUtils.isAxe(heldItem) && BlockUtils.hasWoodcuttingXP(blockState) && Permissions.treeFeller(player)) { mcMMOPlayer.checkAbilityActivation(PrimarySkillType.WOODCUTTING); } else if (mcMMOPlayer.getToolPreparationMode(ToolType.PICKAXE) && ItemUtils.isPickaxe(heldItem) && BlockUtils.affectedBySuperBreaker(blockState) && Permissions.superBreaker(player)) { @@ -525,7 +527,7 @@ public class BlockListener implements Listener { * * We don't need to check permissions here because they've already been checked for the ability to even activate. */ - if (mcMMOPlayer.getAbilityMode(SuperAbilityType.TREE_FELLER) && BlockUtils.isLog(blockState) && Config.getInstance().getTreeFellerSoundsEnabled()) { + if (mcMMOPlayer.getAbilityMode(SuperAbilityType.TREE_FELLER) && BlockUtils.hasWoodcuttingXP(blockState) && Config.getInstance().getTreeFellerSoundsEnabled()) { SoundManager.sendSound(player, blockState.getLocation(), SoundType.FIZZ); } } @@ -596,7 +598,7 @@ public class BlockListener implements Listener { } } } - else if (mcMMOPlayer.getWoodcuttingManager().canUseLeafBlower(heldItem) && BlockUtils.isLeaves(blockState) && EventUtils.simulateBlockBreak(block, player, true)) { + else if (mcMMOPlayer.getWoodcuttingManager().canUseLeafBlower(heldItem) && BlockUtils.isNonWoodPartOfTree(blockState) && EventUtils.simulateBlockBreak(block, player, true)) { event.setInstaBreak(true); SoundManager.sendSound(player, block.getLocation(), SoundType.POP); } diff --git a/src/main/java/com/gmail/nossr50/skills/archery/Archery.java b/src/main/java/com/gmail/nossr50/skills/archery/Archery.java index 4194a2baa..a892b0a89 100644 --- a/src/main/java/com/gmail/nossr50/skills/archery/Archery.java +++ b/src/main/java/com/gmail/nossr50/skills/archery/Archery.java @@ -1,5 +1,6 @@ package com.gmail.nossr50.skills.archery; +import com.gmail.nossr50.api.ItemSpawnReason; import com.gmail.nossr50.config.AdvancedConfig; import com.gmail.nossr50.config.experience.ExperienceConfig; import com.gmail.nossr50.datatypes.skills.SubSkillType; @@ -9,6 +10,7 @@ import org.bukkit.Material; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Iterator; @@ -50,12 +52,12 @@ public class Archery { * * @param livingEntity The entity hit by the arrows */ - public static void arrowRetrievalCheck(LivingEntity livingEntity) { + public static void arrowRetrievalCheck(@NotNull LivingEntity livingEntity) { for (Iterator entityIterator = trackedEntities.iterator(); entityIterator.hasNext();) { TrackedEntity trackedEntity = entityIterator.next(); if (trackedEntity.getID() == livingEntity.getUniqueId()) { - Misc.dropItems(livingEntity.getLocation(), new ItemStack(Material.ARROW), trackedEntity.getArrowCount()); + Misc.spawnItems(livingEntity.getLocation(), new ItemStack(Material.ARROW), trackedEntity.getArrowCount(), ItemSpawnReason.ARROW_RETRIEVAL_ACTIVATED); entityIterator.remove(); return; } diff --git a/src/main/java/com/gmail/nossr50/skills/excavation/ExcavationManager.java b/src/main/java/com/gmail/nossr50/skills/excavation/ExcavationManager.java index e2d259310..b12805856 100644 --- a/src/main/java/com/gmail/nossr50/skills/excavation/ExcavationManager.java +++ b/src/main/java/com/gmail/nossr50/skills/excavation/ExcavationManager.java @@ -1,5 +1,6 @@ package com.gmail.nossr50.skills.excavation; +import com.gmail.nossr50.api.ItemSpawnReason; import com.gmail.nossr50.config.Config; import com.gmail.nossr50.datatypes.experience.XPGainReason; import com.gmail.nossr50.datatypes.player.McMMOPlayer; @@ -51,7 +52,7 @@ public class ExcavationManager extends SkillManager { } xp += treasure.getXp(); - Misc.dropItem(location, treasure.getDrop()); + Misc.spawnItem(location, treasure.getDrop(), ItemSpawnReason.EXCAVATION_TREASURE); } } } diff --git a/src/main/java/com/gmail/nossr50/skills/fishing/FishingManager.java b/src/main/java/com/gmail/nossr50/skills/fishing/FishingManager.java index 5c3de0452..9ec3c55da 100644 --- a/src/main/java/com/gmail/nossr50/skills/fishing/FishingManager.java +++ b/src/main/java/com/gmail/nossr50/skills/fishing/FishingManager.java @@ -1,5 +1,6 @@ package com.gmail.nossr50.skills.fishing; +import com.gmail.nossr50.api.ItemSpawnReason; import com.gmail.nossr50.config.AdvancedConfig; import com.gmail.nossr50.config.Config; import com.gmail.nossr50.config.experience.ExperienceConfig; @@ -318,7 +319,7 @@ public class FishingManager extends SkillManager { } if (Config.getInstance().getFishingExtraFish()) { - Misc.dropItem(player.getEyeLocation(), fishingCatch.getItemStack()); + Misc.spawnItem(player.getEyeLocation(), fishingCatch.getItemStack(), ItemSpawnReason.FISHING_EXTRA_FISH); } fishingCatch.setItemStack(treasureDrop); @@ -426,7 +427,7 @@ public class FishingManager extends SkillManager { return; } - Misc.dropItem(target.getLocation(), drop); + Misc.spawnItem(target.getLocation(), drop, ItemSpawnReason.FISHING_SHAKE_TREASURE); CombatUtils.dealDamage(target, Math.min(Math.max(target.getMaxHealth() / 4, 1), 10), EntityDamageEvent.DamageCause.CUSTOM, getPlayer()); // Make it so you can shake a mob no more than 4 times. applyXpGain(ExperienceConfig.getInstance().getFishingShakeXP(), XPGainReason.PVE); } 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 c93c2adc9..edd33d28d 100644 --- a/src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java +++ b/src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java @@ -1,5 +1,6 @@ package com.gmail.nossr50.skills.herbalism; +import com.gmail.nossr50.api.ItemSpawnReason; import com.gmail.nossr50.config.Config; import com.gmail.nossr50.config.experience.ExperienceConfig; import com.gmail.nossr50.config.treasure.TreasureConfig; @@ -626,7 +627,7 @@ public class HerbalismManager extends SkillManager { return false; } blockState.setType(Material.AIR); - Misc.dropItem(location, treasure.getDrop()); + Misc.spawnItem(location, treasure.getDrop(), ItemSpawnReason.HYLIAN_LUCK_TREASURE); NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Herbalism.HylianLuck"); return true; } diff --git a/src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java b/src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java index 116093980..29bb05d20 100644 --- a/src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java +++ b/src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java @@ -1,5 +1,6 @@ package com.gmail.nossr50.skills.mining; +import com.gmail.nossr50.api.ItemSpawnReason; import com.gmail.nossr50.config.AdvancedConfig; import com.gmail.nossr50.config.Config; import com.gmail.nossr50.config.experience.ExperienceConfig; @@ -188,7 +189,7 @@ public class MiningManager extends SkillManager { //Drop "debris" based on skill modifiers for(BlockState blockState : notOres) { if(RandomUtils.nextFloat() < debrisYield) { - Misc.dropItem(Misc.getBlockCenter(blockState), new ItemStack(blockState.getType())); // Initial block that would have been dropped + Misc.spawnItem(Misc.getBlockCenter(blockState), new ItemStack(blockState.getType()), ItemSpawnReason.BLAST_MINING_DEBRIS_NON_ORES); // Initial block that would have been dropped } } @@ -196,12 +197,12 @@ public class MiningManager extends SkillManager { if (RandomUtils.nextFloat() < (yield + oreBonus)) { xp += Mining.getBlockXp(blockState); - Misc.dropItem(Misc.getBlockCenter(blockState), new ItemStack(blockState.getType())); // Initial block that would have been dropped + Misc.spawnItem(Misc.getBlockCenter(blockState), new ItemStack(blockState.getType()), ItemSpawnReason.BLAST_MINING_ORES); // Initial block that would have been dropped if (!mcMMO.getPlaceStore().isTrue(blockState)) { for (int i = 1; i < dropMultiplier; i++) { // Bukkit.broadcastMessage("Bonus Drop on Ore: "+blockState.getType().toString()); - Misc.dropItem(Misc.getBlockCenter(blockState), new ItemStack(blockState.getType())); // Initial block that would have been dropped + Misc.spawnItem(Misc.getBlockCenter(blockState), new ItemStack(blockState.getType()), ItemSpawnReason.BLAST_MINING_ORES_BONUS_DROP); // Initial block that would have been dropped } } } diff --git a/src/main/java/com/gmail/nossr50/skills/salvage/SalvageManager.java b/src/main/java/com/gmail/nossr50/skills/salvage/SalvageManager.java index f67af3963..f71b6fbe2 100644 --- a/src/main/java/com/gmail/nossr50/skills/salvage/SalvageManager.java +++ b/src/main/java/com/gmail/nossr50/skills/salvage/SalvageManager.java @@ -1,5 +1,6 @@ package com.gmail.nossr50.skills.salvage; +import com.gmail.nossr50.api.ItemSpawnReason; import com.gmail.nossr50.config.AdvancedConfig; import com.gmail.nossr50.config.Config; import com.gmail.nossr50.config.experience.ExperienceConfig; @@ -159,10 +160,10 @@ public class SalvageManager extends SkillManager { anvilLoc.add(0, .1, 0); if (enchantBook != null) { - Misc.spawnItemTowardsLocation(anvilLoc.clone(), playerLoc.clone(), enchantBook, vectorSpeed); + Misc.spawnItemTowardsLocation(anvilLoc.clone(), playerLoc.clone(), enchantBook, vectorSpeed, ItemSpawnReason.SALVAGE_ENCHANTMENT_BOOK); } - Misc.spawnItemTowardsLocation(anvilLoc.clone(), playerLoc.clone(), salvageResults, vectorSpeed); + Misc.spawnItemTowardsLocation(anvilLoc.clone(), playerLoc.clone(), salvageResults, vectorSpeed, ItemSpawnReason.SALVAGE_MATERIALS); // BWONG BWONG BWONG - CLUNK! if (Config.getInstance().getSalvageAnvilUseSoundsEnabled()) { diff --git a/src/main/java/com/gmail/nossr50/skills/unarmed/UnarmedManager.java b/src/main/java/com/gmail/nossr50/skills/unarmed/UnarmedManager.java index ebf50f28a..2379b7c50 100644 --- a/src/main/java/com/gmail/nossr50/skills/unarmed/UnarmedManager.java +++ b/src/main/java/com/gmail/nossr50/skills/unarmed/UnarmedManager.java @@ -1,5 +1,6 @@ package com.gmail.nossr50.skills.unarmed; +import com.gmail.nossr50.api.ItemSpawnReason; import com.gmail.nossr50.config.AdvancedConfig; import com.gmail.nossr50.datatypes.interactions.NotificationType; import com.gmail.nossr50.datatypes.player.McMMOPlayer; @@ -109,7 +110,7 @@ public class UnarmedManager extends SkillManager { if(UserManager.getPlayer(defender) == null) return; - Item item = Misc.dropItem(defender.getLocation(), defender.getInventory().getItemInMainHand()); + Item item = Misc.spawnItem(defender.getLocation(), defender.getInventory().getItemInMainHand(), ItemSpawnReason.UNARMED_DISARMED_ITEM); if (item != null && AdvancedConfig.getInstance().getDisarmProtected()) { item.setMetadata(mcMMO.disarmedItemKey, UserManager.getPlayer(defender).getPlayerMetadata()); diff --git a/src/main/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingManager.java b/src/main/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingManager.java index a9eba5cdb..8b649a208 100644 --- a/src/main/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingManager.java +++ b/src/main/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingManager.java @@ -1,5 +1,6 @@ package com.gmail.nossr50.skills.woodcutting; +import com.gmail.nossr50.api.ItemSpawnReason; import com.gmail.nossr50.config.Config; import com.gmail.nossr50.config.experience.ExperienceConfig; import com.gmail.nossr50.datatypes.experience.XPGainReason; @@ -27,6 +28,7 @@ import org.bukkit.event.player.PlayerItemDamageEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.Damageable; import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashSet; @@ -65,10 +67,11 @@ public class WoodcuttingManager extends SkillManager { && ItemUtils.isAxe(heldItem); } - private boolean canGetDoubleDrops() { + private boolean checkHarvestLumberActivation(@NotNull Material material) { return Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.WOODCUTTING_HARVEST_LUMBER) && RankUtils.hasReachedRank(1, getPlayer(), SubSkillType.WOODCUTTING_HARVEST_LUMBER) - && RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.WOODCUTTING_HARVEST_LUMBER, getPlayer()); + && RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.WOODCUTTING_HARVEST_LUMBER, getPlayer()) + && Config.getInstance().getDoubleDropsEnabled(PrimarySkillType.WOODCUTTING, material); } /** @@ -76,20 +79,14 @@ public class WoodcuttingManager extends SkillManager { * * @param blockState Block being broken */ - public void woodcuttingBlockCheck(BlockState blockState) { - int xp = getExperienceFromLog(blockState); - - switch (blockState.getType()) { - case BROWN_MUSHROOM_BLOCK: - case RED_MUSHROOM_BLOCK: - break; - - default: - if (canGetDoubleDrops()) { - checkForDoubleDrop(blockState); - } + public void processHarvestLumber(@NotNull BlockState blockState) { + if (checkHarvestLumberActivation(blockState.getType())) { + spawnHarvestLumberBonusDrops(blockState); } + } + public void processWoodcuttingBlockXP(@NotNull BlockState blockState) { + int xp = getExperienceFromLog(blockState); applyXpGain(xp, XPGainReason.PVE); } @@ -206,7 +203,7 @@ public class WoodcuttingManager extends SkillManager { * @param player the player holding the item * @return True if the tool can sustain the durability loss */ - private static boolean handleDurabilityLoss(Set treeFellerBlocks, ItemStack inHand, Player player) { + private static boolean handleDurabilityLoss(@NotNull Set treeFellerBlocks, @NotNull ItemStack inHand, @NotNull Player player) { //Treat the NBT tag for unbreakable and the durability enchant differently ItemMeta meta = inHand.getItemMeta(); @@ -218,7 +215,7 @@ public class WoodcuttingManager extends SkillManager { Material type = inHand.getType(); for (BlockState blockState : treeFellerBlocks) { - if (BlockUtils.isLog(blockState)) { + if (BlockUtils.hasWoodcuttingXP(blockState)) { durabilityLoss += Config.getInstance().getAbilityToolDamage(); } } @@ -249,7 +246,7 @@ public class WoodcuttingManager extends SkillManager { * @return true if and only if the given blockState was a Log not already * in treeFellerBlocks. */ - private boolean processTreeFellerTargetBlock(BlockState blockState, List futureCenterBlocks, Set treeFellerBlocks) { + private boolean processTreeFellerTargetBlock(@NotNull BlockState blockState, @NotNull List futureCenterBlocks, @NotNull Set treeFellerBlocks) { if (treeFellerBlocks.contains(blockState) || mcMMO.getPlaceStore().isTrue(blockState)) { return false; } @@ -259,12 +256,12 @@ public class WoodcuttingManager extends SkillManager { treeFellerReachedThreshold = true; } - if (BlockUtils.isLog(blockState)) { + if (BlockUtils.hasWoodcuttingXP(blockState)) { treeFellerBlocks.add(blockState); futureCenterBlocks.add(blockState); return true; } - else if (BlockUtils.isLeaves(blockState)) { + else if (BlockUtils.isNonWoodPartOfTree(blockState)) { treeFellerBlocks.add(blockState); return false; } @@ -276,7 +273,7 @@ public class WoodcuttingManager extends SkillManager { * * @param treeFellerBlocks List of blocks to be dropped */ - private void dropTreeFellerLootFromBlocks(Set treeFellerBlocks) { + private void dropTreeFellerLootFromBlocks(@NotNull Set treeFellerBlocks) { Player player = getPlayer(); int xp = 0; int processedLogCount = 0; @@ -289,25 +286,22 @@ public class WoodcuttingManager extends SkillManager { break; // TODO: Shouldn't we use continue instead? } - Material material = blockState.getType(); + /* + * Handle Drops & XP + */ - //TODO: Update this to drop the correct items/blocks via NMS - if (material == Material.BROWN_MUSHROOM_BLOCK || material == Material.RED_MUSHROOM_BLOCK) { + if (BlockUtils.hasWoodcuttingXP(blockState)) { + //Add XP xp += processTreeFellerXPGains(blockState, processedLogCount); - Misc.dropItems(Misc.getBlockCenter(blockState), block.getDrops()); - } else if (mcMMO.getModManager().isCustomLeaf(blockState)) { - Misc.dropItems(Misc.getBlockCenter(blockState), block.getDrops()); - } else { - if (BlockUtils.isLog(blockState)) { - if (canGetDoubleDrops()) { - checkForDoubleDrop(blockState); - } - xp += processTreeFellerXPGains(blockState, processedLogCount); - Misc.dropItems(Misc.getBlockCenter(blockState), block.getDrops()); - } - if (BlockUtils.isLeaves(blockState)) { - Misc.dropItems(Misc.getBlockCenter(blockState), block.getDrops()); - } + + //Drop displaced block + Misc.spawnItemsFromCollection(Misc.getBlockCenter(blockState), block.getDrops(), ItemSpawnReason.TREE_FELLER_DISPLACED_BLOCK); + + //Bonus Drops / Harvest lumber checks + processHarvestLumber(blockState); + } else if (BlockUtils.isNonWoodPartOfTree(blockState)) { + //Drop displaced non-woodcutting XP blocks + Misc.spawnItemsFromCollection(Misc.getBlockCenter(blockState), block.getDrops(), ItemSpawnReason.TREE_FELLER_DISPLACED_BLOCK, 1); } blockState.setType(Material.AIR); @@ -367,13 +361,11 @@ public class WoodcuttingManager extends SkillManager { } /** - * Checks for double drops + * Spawns harvest lumber bonus drops * * @param blockState Block being broken */ - protected static void checkForDoubleDrop(BlockState blockState) { - if (Config.getInstance().getWoodcuttingDoubleDropsEnabled(blockState.getBlockData())) { - Misc.dropItems(Misc.getBlockCenter(blockState), blockState.getBlock().getDrops()); - } + protected static void spawnHarvestLumberBonusDrops(@NotNull BlockState blockState) { + Misc.spawnItemsFromCollection(Misc.getBlockCenter(blockState), blockState.getBlock().getDrops(), ItemSpawnReason.BONUS_DROPS); } } diff --git a/src/main/java/com/gmail/nossr50/util/BlockUtils.java b/src/main/java/com/gmail/nossr50/util/BlockUtils.java index 843c178a9..17a2d82f2 100644 --- a/src/main/java/com/gmail/nossr50/util/BlockUtils.java +++ b/src/main/java/com/gmail/nossr50/util/BlockUtils.java @@ -66,7 +66,7 @@ public final class BlockUtils { * @return true if the block awards XP, false otherwise */ public static boolean shouldBeWatched(BlockState blockState) { - return affectedByGigaDrillBreaker(blockState) || affectedByGreenTerra(blockState) || affectedBySuperBreaker(blockState) || isLog(blockState) + return affectedByGigaDrillBreaker(blockState) || affectedByGreenTerra(blockState) || affectedBySuperBreaker(blockState) || hasWoodcuttingXP(blockState) || Config.getInstance().getDoubleDropsEnabled(PrimarySkillType.MINING, blockState.getType()) || Config.getInstance().getDoubleDropsEnabled(PrimarySkillType.EXCAVATION, blockState.getType()) || Config.getInstance().getDoubleDropsEnabled(PrimarySkillType.WOODCUTTING, blockState.getType()) @@ -165,10 +165,8 @@ public final class BlockUtils { * @param blockState The {@link BlockState} of the block to check * @return true if the block is a log, false otherwise */ - public static boolean isLog(BlockState blockState) { - if (ExperienceConfig.getInstance().doesBlockGiveSkillXP(PrimarySkillType.WOODCUTTING, blockState.getBlockData())) - return true; - return mcMMO.getModManager().isCustomLog(blockState); + public static boolean hasWoodcuttingXP(BlockState blockState) { + return ExperienceConfig.getInstance().doesBlockGiveSkillXP(PrimarySkillType.WOODCUTTING, blockState.getBlockData()); } /** @@ -177,8 +175,8 @@ public final class BlockUtils { * @param blockState The {@link BlockState} of the block to check * @return true if the block is a leaf, false otherwise */ - public static boolean isLeaves(BlockState blockState) { - return mcMMO.getMaterialMapStore().isLeavesWhiteListed(blockState.getType()); + public static boolean isNonWoodPartOfTree(BlockState blockState) { + return mcMMO.getMaterialMapStore().isTreeFellerDestructible(blockState.getType()); } /** diff --git a/src/main/java/com/gmail/nossr50/util/EventUtils.java b/src/main/java/com/gmail/nossr50/util/EventUtils.java index d138c3c3d..52a2f989e 100644 --- a/src/main/java/com/gmail/nossr50/util/EventUtils.java +++ b/src/main/java/com/gmail/nossr50/util/EventUtils.java @@ -46,6 +46,7 @@ import org.bukkit.event.player.PlayerFishEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.PluginManager; +import org.jetbrains.annotations.NotNull; import java.util.HashMap; import java.util.Map; @@ -73,7 +74,7 @@ public final class EventUtils { * @param event The {@link Event} in question * @return Whether this {@link Event} has been faked by mcMMO and should not be processed normally. */ - public static boolean isFakeEvent(Event event) { + public static boolean isFakeEvent(@NotNull Event event) { return event instanceof FakeEvent; } @@ -84,7 +85,7 @@ public final class EventUtils { * @param event this event * @return true if damage is NOT from an unnatural mcMMO skill (such as bleed DOTs) */ - public static boolean isDamageFromMcMMOComplexBehaviour(Event event) { + public static boolean isDamageFromMcMMOComplexBehaviour(@NotNull Event event) { return event instanceof FakeEntityDamageEvent; } @@ -94,7 +95,7 @@ public final class EventUtils { * @param entity target entity * @return the associated McMMOPlayer for this entity */ - public static McMMOPlayer getMcMMOPlayer(Entity entity) + public static McMMOPlayer getMcMMOPlayer(@NotNull Entity entity) { return UserManager.getPlayer((Player)entity); } @@ -112,7 +113,7 @@ public final class EventUtils { * @param entityDamageEvent * @return */ - public static boolean isRealPlayerDamaged(EntityDamageEvent entityDamageEvent) + public static boolean isRealPlayerDamaged(@NotNull EntityDamageEvent entityDamageEvent) { //Make sure the damage is above 0 double damage = entityDamageEvent.getFinalDamage(); @@ -167,14 +168,14 @@ public final class EventUtils { * Others */ - public static McMMOPlayerAbilityActivateEvent callPlayerAbilityActivateEvent(Player player, PrimarySkillType skill) { + public static @NotNull McMMOPlayerAbilityActivateEvent callPlayerAbilityActivateEvent(@NotNull Player player, @NotNull PrimarySkillType skill) { McMMOPlayerAbilityActivateEvent event = new McMMOPlayerAbilityActivateEvent(player, skill); mcMMO.p.getServer().getPluginManager().callEvent(event); return event; } - public static McMMOPlayerProfileLoadEvent callPlayerProfileLoadEvent(Player player, PlayerProfile profile){ + public static @NotNull McMMOPlayerProfileLoadEvent callPlayerProfileLoadEvent(@NotNull Player player, @NotNull PlayerProfile profile){ McMMOPlayerProfileLoadEvent event = new McMMOPlayerProfileLoadEvent(player, profile); mcMMO.p.getServer().getPluginManager().callEvent(event); diff --git a/src/main/java/com/gmail/nossr50/util/MaterialMapStore.java b/src/main/java/com/gmail/nossr50/util/MaterialMapStore.java index dcdd766f2..6be54c63c 100644 --- a/src/main/java/com/gmail/nossr50/util/MaterialMapStore.java +++ b/src/main/java/com/gmail/nossr50/util/MaterialMapStore.java @@ -1,6 +1,7 @@ package com.gmail.nossr50.util; import org.bukkit.Material; +import org.jetbrains.annotations.NotNull; import java.util.HashMap; import java.util.HashSet; @@ -15,46 +16,46 @@ import java.util.Locale; */ public class MaterialMapStore { - private final HashSet abilityBlackList; - private final HashSet toolBlackList; - private final HashSet mossyWhiteList; - private final HashSet leavesWhiteList; - private final HashSet herbalismAbilityBlackList; - private final HashSet blockCrackerWhiteList; - private final HashSet canMakeShroomyWhiteList; - private final HashSet multiBlockPlant; - private final HashSet foodItemWhiteList; - private final HashSet glassBlocks; + private final @NotNull HashSet abilityBlackList; + private final @NotNull HashSet toolBlackList; + private final @NotNull HashSet mossyWhiteList; + private final @NotNull HashSet treeFellerDestructibleWhiteList; + private final @NotNull HashSet herbalismAbilityBlackList; + private final @NotNull HashSet blockCrackerWhiteList; + private final @NotNull HashSet canMakeShroomyWhiteList; + private final @NotNull HashSet multiBlockPlant; + private final @NotNull HashSet foodItemWhiteList; + private final @NotNull HashSet glassBlocks; - private final HashSet netheriteArmor; - private final HashSet netheriteTools; - private final HashSet woodTools; - private final HashSet stoneTools; - private final HashSet leatherArmor; - private final HashSet ironArmor; - private final HashSet ironTools; - private final HashSet stringTools; - private final HashSet goldArmor; - private final HashSet goldTools; - private final HashSet chainmailArmor; - private final HashSet diamondArmor; - private final HashSet diamondTools; - private final HashSet armors; + private final @NotNull HashSet netheriteArmor; + private final @NotNull HashSet netheriteTools; + private final @NotNull HashSet woodTools; + private final @NotNull HashSet stoneTools; + private final @NotNull HashSet leatherArmor; + private final @NotNull HashSet ironArmor; + private final @NotNull HashSet ironTools; + private final @NotNull HashSet stringTools; + private final @NotNull HashSet goldArmor; + private final @NotNull HashSet goldTools; + private final @NotNull HashSet chainmailArmor; + private final @NotNull HashSet diamondArmor; + private final @NotNull HashSet diamondTools; + private final @NotNull HashSet armors; - private final HashSet swords; - private final HashSet axes; - private final HashSet hoes; - private final HashSet shovels; - private final HashSet pickAxes; - private final HashSet tridents; - private final HashSet bows; - private final HashSet tools; + private final @NotNull HashSet swords; + private final @NotNull HashSet axes; + private final @NotNull HashSet hoes; + private final @NotNull HashSet shovels; + private final @NotNull HashSet pickAxes; + private final @NotNull HashSet tridents; + private final @NotNull HashSet bows; + private final @NotNull HashSet tools; - private final HashSet enchantables; + private final @NotNull HashSet enchantables; - private final HashSet ores; + private final @NotNull HashSet ores; - private final HashMap tierValue; + private final @NotNull HashMap tierValue; public MaterialMapStore() @@ -62,7 +63,7 @@ public class MaterialMapStore { abilityBlackList = new HashSet<>(); toolBlackList = new HashSet<>(); mossyWhiteList = new HashSet<>(); - leavesWhiteList = new HashSet<>(); + treeFellerDestructibleWhiteList = new HashSet<>(); herbalismAbilityBlackList = new HashSet<>(); blockCrackerWhiteList = new HashSet<>(); canMakeShroomyWhiteList = new HashSet<>(); @@ -104,52 +105,12 @@ public class MaterialMapStore { fillVanillaMaterialRegisters(); } - public boolean isMultiBlockPlant(Material material) - { - return multiBlockPlant.contains(material.getKey().getKey()); - } - - public boolean isAbilityActivationBlackListed(Material material) - { - return abilityBlackList.contains(material.getKey().getKey()); - } - - public boolean isToolActivationBlackListed(Material material) - { - return toolBlackList.contains(material.getKey().getKey()); - } - - public boolean isMossyWhiteListed(Material material) - { - return mossyWhiteList.contains(material.getKey().getKey()); - } - - public boolean isLeavesWhiteListed(Material material) - { - return leavesWhiteList.contains(material.getKey().getKey()); - } - - public boolean isHerbalismAbilityWhiteListed(Material material) - { - return herbalismAbilityBlackList.contains(material.getKey().getKey()); - } - - public boolean isBlockCrackerWhiteListed(Material material) - { - return blockCrackerWhiteList.contains(material.getKey().getKey()); - } - - public boolean isShroomyWhiteListed(Material material) - { - return canMakeShroomyWhiteList.contains(material.getKey().getKey()); - } - private void fillVanillaMaterialRegisters() { fillAbilityBlackList(); fillToolBlackList(); fillMossyWhiteList(); - fillLeavesWhiteList(); + fillTreeFellerDestructibleWhiteList(); fillHerbalismAbilityBlackList(); fillBlockCrackerWhiteList(); fillShroomyWhiteList(); @@ -164,6 +125,46 @@ public class MaterialMapStore { fillTierMap(); } + public boolean isMultiBlockPlant(@NotNull Material material) + { + return multiBlockPlant.contains(material.getKey().getKey()); + } + + public boolean isAbilityActivationBlackListed(@NotNull Material material) + { + return abilityBlackList.contains(material.getKey().getKey()); + } + + public boolean isToolActivationBlackListed(@NotNull Material material) + { + return toolBlackList.contains(material.getKey().getKey()); + } + + public boolean isMossyWhiteListed(@NotNull Material material) + { + return mossyWhiteList.contains(material.getKey().getKey()); + } + + public boolean isTreeFellerDestructible(@NotNull Material material) + { + return treeFellerDestructibleWhiteList.contains(material.getKey().getKey()); + } + + public boolean isHerbalismAbilityWhiteListed(@NotNull Material material) + { + return herbalismAbilityBlackList.contains(material.getKey().getKey()); + } + + public boolean isBlockCrackerWhiteListed(@NotNull Material material) + { + return blockCrackerWhiteList.contains(material.getKey().getKey()); + } + + public boolean isShroomyWhiteListed(@NotNull Material material) + { + return canMakeShroomyWhiteList.contains(material.getKey().getKey()); + } + private void fillTierMap() { for(String id : leatherArmor) { tierValue.put(id, 1); @@ -418,26 +419,7 @@ public class MaterialMapStore { ironTools.add("iron_shovel"); //Used for repair, remove in 2.2 - //TODO: Remove in 2.2 - //TODO: Remove in 2.2 - //TODO: Remove in 2.2 - //TODO: Remove in 2.2 - //TODO: Remove in 2.2 - //TODO: Remove in 2.2 - //TODO: Remove in 2.2 - //TODO: Remove in 2.2 - //TODO: Remove in 2.2 - //TODO: Remove in 2.2 - //TODO: Remove in 2.2 - //TODO: Remove in 2.2 - //TODO: Remove in 2.2 - //TODO: Remove in 2.2 - //TODO: Remove in 2.2 - //TODO: Remove in 2.2 - //TODO: Remove in 2.2 - //TODO: Remove in 2.2 - //TODO: Remove in 2.2 - //TODO: Remove in 2.2 + //TODO: Remove in config update ironTools.add("bucket"); ironTools.add("flint_and_steel"); ironTools.add("shears"); @@ -555,7 +537,7 @@ public class MaterialMapStore { * @param material target material * @return true if it is used for armor */ - public boolean isArmor(Material material) { + public boolean isArmor(@NotNull Material material) { return isArmor(material.getKey().getKey()); } @@ -564,207 +546,196 @@ public class MaterialMapStore { * @param id target item id * @return true if the item id matches armor */ - public boolean isArmor(String id) { + public boolean isArmor(@NotNull String id) { return armors.contains(id); } - public boolean isTool(Material material) { + public boolean isTool(@NotNull Material material) { return isTool(material.getKey().getKey()); } - public boolean isTool(String id) { + public boolean isTool(@NotNull String id) { return tools.contains(id); } - public boolean isEnchantable(Material material) { + public boolean isEnchantable(@NotNull Material material) { return isEnchantable(material.getKey().getKey()); } - public boolean isEnchantable(String id) { + public boolean isEnchantable(@NotNull String id) { return enchantables.contains(id); } - public boolean isOre(Material material) { + public boolean isOre(@NotNull Material material) { return isOre(material.getKey().getKey()); } - public boolean isOre(String id) { + public boolean isOre(@NotNull String id) { return ores.contains(id); } - public boolean isBow(Material material) { + public boolean isBow(@NotNull Material material) { return isBow(material.getKey().getKey()); } - public boolean isBow(String id) { + public boolean isBow(@NotNull String id) { return bows.contains(id); } - public boolean isLeatherArmor(Material material) { + public boolean isLeatherArmor(@NotNull Material material) { return isLeatherArmor(material.getKey().getKey()); } - public boolean isLeatherArmor(String id) { + public boolean isLeatherArmor(@NotNull String id) { return leatherArmor.contains(id); } - public boolean isIronArmor(Material material) { + public boolean isIronArmor(@NotNull Material material) { return isIronArmor(material.getKey().getKey()); } - public boolean isIronArmor(String id) { + public boolean isIronArmor(@NotNull String id) { return ironArmor.contains(id); } - public boolean isGoldArmor(Material material) { + public boolean isGoldArmor(@NotNull Material material) { return isGoldArmor(material.getKey().getKey()); } - public boolean isGoldArmor(String id) { + public boolean isGoldArmor(@NotNull String id) { return goldArmor.contains(id); } - public boolean isDiamondArmor(Material material) { + public boolean isDiamondArmor(@NotNull Material material) { return isDiamondArmor(material.getKey().getKey()); } - public boolean isDiamondArmor(String id) { + public boolean isDiamondArmor(@NotNull String id) { return diamondArmor.contains(id); } - public boolean isChainmailArmor(Material material) { + public boolean isChainmailArmor(@NotNull Material material) { return isChainmailArmor(material.getKey().getKey()); } - public boolean isChainmailArmor(String id) { + public boolean isChainmailArmor(@NotNull String id) { return chainmailArmor.contains(id); } - public boolean isNetheriteArmor(Material material) { + public boolean isNetheriteArmor(@NotNull Material material) { return isNetheriteArmor(material.getKey().getKey()); } - public boolean isNetheriteArmor(String id) { + public boolean isNetheriteArmor(@NotNull String id) { return netheriteArmor.contains(id); } - public boolean isWoodTool(Material material) { + public boolean isWoodTool(@NotNull Material material) { return isWoodTool(material.getKey().getKey()); } - public boolean isWoodTool(String id) { + public boolean isWoodTool(@NotNull String id) { return woodTools.contains(id); } - public boolean isStoneTool(Material material) { + public boolean isStoneTool(@NotNull Material material) { return isStoneTool(material.getKey().getKey()); } - public boolean isStoneTool(String id) { + public boolean isStoneTool(@NotNull String id) { return stoneTools.contains(id); } - public boolean isIronTool(Material material) { + public boolean isIronTool(@NotNull Material material) { return isIronTool(material.getKey().getKey()); } - public boolean isIronTool(String id) { + public boolean isIronTool(@NotNull String id) { return ironTools.contains(id); } - public boolean isGoldTool(Material material) { + public boolean isGoldTool(@NotNull Material material) { return isGoldTool(material.getKey().getKey()); } - public boolean isGoldTool(String id) { + public boolean isGoldTool(@NotNull String id) { return goldTools.contains(id); } - public boolean isDiamondTool(Material material) { + public boolean isDiamondTool(@NotNull Material material) { return isDiamondTool(material.getKey().getKey()); } - public boolean isDiamondTool(String id) { + public boolean isDiamondTool(@NotNull String id) { return diamondTools.contains(id); } - public boolean isSword(Material material) { + public boolean isSword(@NotNull Material material) { return isSword(material.getKey().getKey()); } - public boolean isSword(String id) { + public boolean isSword(@NotNull String id) { return swords.contains(id); } - public boolean isAxe(Material material) { + public boolean isAxe(@NotNull Material material) { return isAxe(material.getKey().getKey()); } - public boolean isAxe(String id) { + public boolean isAxe(@NotNull String id) { return axes.contains(id); } - public boolean isPickAxe(Material material) { + public boolean isPickAxe(@NotNull Material material) { return isPickAxe(material.getKey().getKey()); } - public boolean isPickAxe(String id) { + public boolean isPickAxe(@NotNull String id) { return pickAxes.contains(id); } - public boolean isShovel(Material material) { + public boolean isShovel(@NotNull Material material) { return isShovel(material.getKey().getKey()); } - public boolean isShovel(String id) { + public boolean isShovel(@NotNull String id) { return shovels.contains(id); } - public boolean isHoe(Material material) { + public boolean isHoe(@NotNull Material material) { return isHoe(material.getKey().getKey()); } - public boolean isHoe(String id) { + public boolean isHoe(@NotNull String id) { return hoes.contains(id); } - public boolean isNetheriteTool(Material material) { + public boolean isNetheriteTool(@NotNull Material material) { return isNetheriteTool(material.getKey().getKey()); } - public boolean isNetheriteTool(String id) { + public boolean isNetheriteTool(@NotNull String id) { return netheriteTools.contains(id); } - public boolean isStringTool(Material material) { + public boolean isStringTool(@NotNull Material material) { return isStringTool(material.getKey().getKey()); } - public boolean isStringTool(String id) { + public boolean isStringTool(@NotNull String id) { return stringTools.contains(id); } - public boolean isGlass(Material material) { + public boolean isGlass(@NotNull Material material) { return glassBlocks.contains(material.getKey().getKey()); } - public boolean isFood(Material material) { + public boolean isFood(@NotNull Material material) { return foodItemWhiteList.contains(material.getKey().getKey()); } private void fillMultiBlockPlantSet() { - //Single Block Plants -// plantBlockSet.add("melon"); -// plantBlockSet.add("pumpkin"); -// plantBlockSet.add("potatoes"); -// plantBlockSet.add("carrots"); -// plantBlockSet.add("beetroots"); -// plantBlockSet.add("nether_wart"); -// plantBlockSet.add("grass"); -// plantBlockSet.add("fern"); -// plantBlockSet.add("large_fern"); - //Multi-Block Plants multiBlockPlant.add("cactus"); multiBlockPlant.add("chorus_plant"); @@ -802,16 +773,18 @@ public class MaterialMapStore { herbalismAbilityBlackList.add("farmland"); } - private void fillLeavesWhiteList() + private void fillTreeFellerDestructibleWhiteList() { - leavesWhiteList.add("oak_leaves"); - leavesWhiteList.add("acacia_leaves"); - leavesWhiteList.add("birch_leaves"); - leavesWhiteList.add("dark_oak_leaves"); - leavesWhiteList.add("jungle_leaves"); - leavesWhiteList.add("spruce_leaves"); - leavesWhiteList.add("nether_wart_block"); - leavesWhiteList.add("warped_wart_block"); + treeFellerDestructibleWhiteList.add("oak_leaves"); + treeFellerDestructibleWhiteList.add("acacia_leaves"); + treeFellerDestructibleWhiteList.add("birch_leaves"); + treeFellerDestructibleWhiteList.add("dark_oak_leaves"); + treeFellerDestructibleWhiteList.add("jungle_leaves"); + treeFellerDestructibleWhiteList.add("spruce_leaves"); + treeFellerDestructibleWhiteList.add("nether_wart_block"); + treeFellerDestructibleWhiteList.add("warped_wart_block"); + treeFellerDestructibleWhiteList.add("brown_mushroom_block"); + treeFellerDestructibleWhiteList.add("red_mushroom_block"); } private void fillMossyWhiteList() @@ -1090,24 +1063,24 @@ public class MaterialMapStore { toolBlackList.add("respawn_anchor"); } - public HashSet getNetheriteArmor() { + public @NotNull HashSet getNetheriteArmor() { return netheriteArmor; } - public HashSet getNetheriteTools() { + public @NotNull HashSet getNetheriteTools() { return netheriteTools; } - public int getTier(Material material) { + public int getTier(@NotNull Material material) { return getTier(material.getKey().getKey()); } - public int getTier(String id) { + public int getTier(@NotNull String id) { return tierValue.getOrDefault(id, 1); //1 for unknown items } - private void addToHashSet(String string, HashSet stringHashSet) + private void addToHashSet(@NotNull String string, @NotNull HashSet stringHashSet) { stringHashSet.add(string.toLowerCase(Locale.ENGLISH)); } diff --git a/src/main/java/com/gmail/nossr50/util/Misc.java b/src/main/java/com/gmail/nossr50/util/Misc.java index 7346f42f1..92316d732 100644 --- a/src/main/java/com/gmail/nossr50/util/Misc.java +++ b/src/main/java/com/gmail/nossr50/util/Misc.java @@ -1,5 +1,6 @@ package com.gmail.nossr50.util; +import com.gmail.nossr50.api.ItemSpawnReason; import com.gmail.nossr50.events.items.McMMOItemSpawnEvent; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.runnables.player.PlayerProfileLoadingTask; @@ -11,6 +12,8 @@ import org.bukkit.block.BlockState; import org.bukkit.entity.*; import org.bukkit.inventory.ItemStack; import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.Locale; @@ -18,7 +21,7 @@ import java.util.Random; import java.util.Set; public final class Misc { - private static final Random random = new Random(); + private static final @NotNull Random random = new Random(); public static final int TIME_CONVERSION_FACTOR = 1000; public static final int TICK_CONVERSION_FACTOR = 20; @@ -37,7 +40,7 @@ public final class Misc { public static final float LEVELUP_PITCH = 0.5F; // Reduced to differentiate between vanilla level-up public static final float LEVELUP_VOLUME = 0.75F * Config.getInstance().getMasterVolume(); // Use max volume always*/ - public static final Set modNames = ImmutableSet.of("LOTR", "BUILDCRAFT", "ENDERIO", "ENHANCEDBIOMES", "IC2", "METALLURGY", "FORESTRY", "GALACTICRAFT", "RAILCRAFT", "TWILIGHTFOREST", "THAUMCRAFT", "GRAVESTONEMOD", "GROWTHCRAFT", "ARCTICMOBS", "DEMONMOBS", "INFERNOMOBS", "SWAMPMOBS", "MARICULTURE", "MINESTRAPPOLATION"); + public static final @NotNull Set modNames = ImmutableSet.of("LOTR", "BUILDCRAFT", "ENDERIO", "ENHANCEDBIOMES", "IC2", "METALLURGY", "FORESTRY", "GALACTICRAFT", "RAILCRAFT", "TWILIGHTFOREST", "THAUMCRAFT", "GRAVESTONEMOD", "GROWTHCRAFT", "ARCTICMOBS", "DEMONMOBS", "INFERNOMOBS", "SWAMPMOBS", "MARICULTURE", "MINESTRAPPOLATION"); private Misc() {} @@ -54,7 +57,7 @@ public final class Misc { * @param entity target entity * @return true if the entity is not a Villager and is not a "NPC" */ - public static boolean isNPCEntityExcludingVillagers(Entity entity) { + public static boolean isNPCEntityExcludingVillagers(@NotNull Entity entity) { return (!isVillager(entity) && isNPCIncludingVillagers(entity)); //Compatibility with some mod.. } @@ -73,7 +76,7 @@ public final class Misc { return entityType.equalsIgnoreCase("wandering_trader") || entity instanceof Villager; } - public static boolean isNPCIncludingVillagers(Entity entity) { + public static boolean isNPCIncludingVillagers(@Nullable Entity entity) { return (entity == null || (hasNPCMetadataTag(entity)) || (isNPCClassType(entity)) @@ -88,7 +91,7 @@ public final class Misc { * @param maxDistance The max distance apart * @return true if the distance between {@code first} and {@code second} is less than {@code maxDistance}, false otherwise */ - public static boolean isNear(Location first, Location second, double maxDistance) { + public static boolean isNear(@NotNull Location first, @NotNull Location second, double maxDistance) { return (first.getWorld() == second.getWorld()) && (first.distanceSquared(second) < (maxDistance * maxDistance) || maxDistance == 0); } @@ -102,9 +105,25 @@ public final class Misc { return blockState.getLocation().add(0.5, 0.5, 0.5); } - public static void dropItems(Location location, Collection drops) { + public static void spawnItemsFromCollection(@NotNull Location location, @NotNull Collection drops, @NotNull ItemSpawnReason itemSpawnReason) { for (ItemStack drop : drops) { - dropItem(location, drop); + spawnItem(location, drop, itemSpawnReason); + } + } + + /** + * Drops only the first n items in a collection + * Size should always be a positive integer above 0 + * + * @param location target drop location + * @param drops collection to iterate over + * @param sizeLimit the number of drops to process + */ + public static void spawnItemsFromCollection(@NotNull Location location, @NotNull Collection drops, @NotNull ItemSpawnReason itemSpawnReason, int sizeLimit) { + ItemStack[] arrayDrops = drops.toArray(new ItemStack[0]); + + for(int i = 0; i < sizeLimit-1; i++) { + spawnItem(location, arrayDrops[i], itemSpawnReason); } } @@ -115,9 +134,9 @@ public final class Misc { * @param is The items to drop * @param quantity The amount of items to drop */ - public static void dropItems(Location location, ItemStack is, int quantity) { + public static void spawnItems(@NotNull Location location, @NotNull ItemStack is, int quantity, @NotNull ItemSpawnReason itemSpawnReason) { for (int i = 0; i < quantity; i++) { - dropItem(location, is); + spawnItem(location, is, itemSpawnReason); } } @@ -126,15 +145,16 @@ public final class Misc { * * @param location The location to drop the item at * @param itemStack The item to drop + * @param itemSpawnReason the reason for the item drop * @return Dropped Item entity or null if invalid or cancelled */ - public static Item dropItem(Location location, ItemStack itemStack) { - if (itemStack.getType() == Material.AIR) { + public static @Nullable Item spawnItem(@NotNull Location location, @NotNull ItemStack itemStack, @NotNull ItemSpawnReason itemSpawnReason) { + if (itemStack.getType() == Material.AIR || location.getWorld() == null) { return null; } // We can't get the item until we spawn it and we want to make it cancellable, so we have a custom event. - McMMOItemSpawnEvent event = new McMMOItemSpawnEvent(location, itemStack); + McMMOItemSpawnEvent event = new McMMOItemSpawnEvent(location, itemStack, itemSpawnReason); mcMMO.p.getServer().getPluginManager().callEvent(event); if (event.isCancelled()) { @@ -149,22 +169,23 @@ public final class Misc { * * @param location The location to drop the item at * @param itemStack The item to drop + * @param itemSpawnReason the reason for the item drop * @return Dropped Item entity or null if invalid or cancelled */ - public static Item dropItem(Location location, ItemStack itemStack, int count) { - if (itemStack.getType() == Material.AIR) { + public static @Nullable Item spawnItemNaturally(@NotNull Location location, @NotNull ItemStack itemStack, @NotNull ItemSpawnReason itemSpawnReason) { + if (itemStack.getType() == Material.AIR || location.getWorld() == null) { return null; } // We can't get the item until we spawn it and we want to make it cancellable, so we have a custom event. - McMMOItemSpawnEvent event = new McMMOItemSpawnEvent(location, itemStack); + McMMOItemSpawnEvent event = new McMMOItemSpawnEvent(location, itemStack, itemSpawnReason); mcMMO.p.getServer().getPluginManager().callEvent(event); if (event.isCancelled()) { return null; } - return location.getWorld().dropItem(location, itemStack); + return location.getWorld().dropItemNaturally(location, itemStack); } /** @@ -175,9 +196,9 @@ public final class Misc { * @param speed the speed that the item should travel * @param quantity The amount of items to drop */ - public static void spawnItemsTowardsLocation(Location fromLocation, Location toLocation, ItemStack is, int quantity, double speed) { + public static void spawnItemsTowardsLocation(@NotNull Location fromLocation, @NotNull Location toLocation, @NotNull ItemStack is, int quantity, double speed, @NotNull ItemSpawnReason itemSpawnReason) { for (int i = 0; i < quantity; i++) { - spawnItemTowardsLocation(fromLocation, toLocation, is, speed); + spawnItemTowardsLocation(fromLocation, toLocation, is, speed, itemSpawnReason); } } @@ -191,7 +212,7 @@ public final class Misc { * @param speed the speed that the item should travel * @return Dropped Item entity or null if invalid or cancelled */ - public static Item spawnItemTowardsLocation(Location fromLocation, Location toLocation, ItemStack itemToSpawn, double speed) { + public static @Nullable Item spawnItemTowardsLocation(@NotNull Location fromLocation, @NotNull Location toLocation, @NotNull ItemStack itemToSpawn, double speed, @NotNull ItemSpawnReason itemSpawnReason) { if (itemToSpawn.getType() == Material.AIR) { return null; } @@ -201,12 +222,15 @@ public final class Misc { Location spawnLocation = fromLocation.clone(); Location targetLocation = toLocation.clone(); + if(spawnLocation.getWorld() == null) + return null; + // We can't get the item until we spawn it and we want to make it cancellable, so we have a custom event. - McMMOItemSpawnEvent event = new McMMOItemSpawnEvent(spawnLocation, clonedItem); + McMMOItemSpawnEvent event = new McMMOItemSpawnEvent(spawnLocation, clonedItem, itemSpawnReason); mcMMO.p.getServer().getPluginManager().callEvent(event); //Something cancelled the event so back out - if (event.isCancelled() || event.getItemStack() == null) { + if (event.isCancelled()) { return null; } @@ -224,7 +248,7 @@ public final class Misc { return spawnedItem; } - public static void profileCleanup(String playerName) { + public static void profileCleanup(@NotNull String playerName) { Player player = mcMMO.p.getServer().getPlayerExact(playerName); if (player != null) { @@ -239,7 +263,7 @@ public final class Misc { } } - public static String getModName(String materialName) { + public static String getModName(@NotNull String materialName) { for (String mod : modNames) { if (materialName.contains(mod)) { return mod; @@ -258,7 +282,7 @@ public final class Misc { /** * Gets a random location near the specified location */ - public static Location getLocationOffset(Location location, double strength) { + public static Location getLocationOffset(@NotNull Location location, double strength) { double blockX = location.getBlockX(); double blockZ = location.getBlockZ(); @@ -272,7 +296,7 @@ public final class Misc { return new Location(location.getWorld(), blockX, location.getY(), blockZ); } - public static Random getRandom() { + public static @NotNull Random getRandom() { return random; } } diff --git a/src/main/java/com/gmail/nossr50/util/ModManager.java b/src/main/java/com/gmail/nossr50/util/ModManager.java index b61f98048..184b571b1 100644 --- a/src/main/java/com/gmail/nossr50/util/ModManager.java +++ b/src/main/java/com/gmail/nossr50/util/ModManager.java @@ -136,10 +136,6 @@ public class ModManager { return Config.getInstance().getBlockModsEnabled() && customLogs.contains(state.getType()); } - public boolean isCustomLeaf(BlockState state) { - return Config.getInstance().getBlockModsEnabled() && customLeaves.contains(state.getType()); - } - public boolean isCustomAbilityBlock(BlockState state) { return Config.getInstance().getBlockModsEnabled() && customAbilityBlocks.contains(state.getType()); }