From 44ede5c3f8a7818f69cc46f895794f74a30ad35c Mon Sep 17 00:00:00 2001 From: GJ Date: Wed, 6 Mar 2013 16:23:19 -0500 Subject: [PATCH] Create a WoodcuttingManager --- .../nossr50/datatypes/player/McMMOPlayer.java | 12 +- .../nossr50/datatypes/skills/SkillType.java | 3 +- .../nossr50/listeners/BlockListener.java | 35 +-- .../skills/woodcutting/TreeFeller.java | 276 ------------------ .../skills/woodcutting/Woodcutting.java | 187 ++++++++---- .../woodcutting/WoodcuttingManager.java | 192 ++++++++++++ 6 files changed, 344 insertions(+), 361 deletions(-) delete mode 100644 src/main/java/com/gmail/nossr50/skills/woodcutting/TreeFeller.java create mode 100644 src/main/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingManager.java diff --git a/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java b/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java index 3d8d6392a..56e84f4f9 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java +++ b/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java @@ -34,6 +34,7 @@ import com.gmail.nossr50.skills.smelting.SmeltingManager; import com.gmail.nossr50.skills.swords.SwordsManager; import com.gmail.nossr50.skills.taming.TamingManager; import com.gmail.nossr50.skills.unarmed.UnarmedManager; +import com.gmail.nossr50.skills.woodcutting.WoodcuttingManager; import com.gmail.nossr50.util.Misc; import com.gmail.nossr50.util.ModUtils; import com.gmail.nossr50.util.Permissions; @@ -94,12 +95,7 @@ public class McMMOPlayer { */ try { for (SkillType skillType : SkillType.values()) { - Class skillManagerClass = skillType.getManagerClass(); - - // TODO: The null check is needed only because currently some SkillType doesn't have a valid skillManagerClass - if (skillManagerClass != null) { - skillManagers.put(skillType, skillManagerClass.getConstructor(McMMOPlayer.class).newInstance(this)); - } + skillManagers.put(skillType, skillType.getManagerClass().getConstructor(McMMOPlayer.class).newInstance(this)); } } catch (Exception e) { @@ -166,6 +162,10 @@ public class McMMOPlayer { return (UnarmedManager) skillManagers.get(SkillType.UNARMED); } + public WoodcuttingManager getWoodcuttingManager() { + return (WoodcuttingManager) skillManagers.get(SkillType.WOODCUTTING); + } + /* * Abilities */ diff --git a/src/main/java/com/gmail/nossr50/datatypes/skills/SkillType.java b/src/main/java/com/gmail/nossr50/datatypes/skills/SkillType.java index 70673716f..9a2146aca 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/skills/SkillType.java +++ b/src/main/java/com/gmail/nossr50/datatypes/skills/SkillType.java @@ -16,6 +16,7 @@ import com.gmail.nossr50.skills.smelting.SmeltingManager; import com.gmail.nossr50.skills.swords.SwordsManager; import com.gmail.nossr50.skills.taming.TamingManager; import com.gmail.nossr50.skills.unarmed.UnarmedManager; +import com.gmail.nossr50.skills.woodcutting.WoodcuttingManager; import com.gmail.nossr50.util.StringUtils; public enum SkillType { @@ -31,7 +32,7 @@ public enum SkillType { SWORDS(SwordsManager.class, AbilityType.SERRATED_STRIKES, ToolType.SWORD), TAMING(TamingManager.class), UNARMED(UnarmedManager.class, AbilityType.BERSERK, ToolType.FISTS), - WOODCUTTING(null, AbilityType.TREE_FELLER, ToolType.AXE); // TODO: Create a proper WoodcuttingManager class + WOODCUTTING(WoodcuttingManager.class, AbilityType.TREE_FELLER, ToolType.AXE); private Class managerClass; private AbilityType ability; diff --git a/src/main/java/com/gmail/nossr50/listeners/BlockListener.java b/src/main/java/com/gmail/nossr50/listeners/BlockListener.java index 4ce6d067d..d89e6dc74 100644 --- a/src/main/java/com/gmail/nossr50/listeners/BlockListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/BlockListener.java @@ -20,8 +20,6 @@ import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.inventory.ItemStack; import com.gmail.nossr50.mcMMO; -import com.gmail.nossr50.config.AdvancedConfig; -import com.gmail.nossr50.config.Config; import com.gmail.nossr50.config.HiddenConfig; import com.gmail.nossr50.datatypes.player.McMMOPlayer; import com.gmail.nossr50.datatypes.skills.AbilityType; @@ -37,7 +35,7 @@ import com.gmail.nossr50.skills.mining.MiningManager; import com.gmail.nossr50.skills.repair.Repair; import com.gmail.nossr50.skills.smelting.SmeltingManager; import com.gmail.nossr50.skills.unarmed.Unarmed; -import com.gmail.nossr50.skills.woodcutting.Woodcutting; +import com.gmail.nossr50.skills.woodcutting.WoodcuttingManager; import com.gmail.nossr50.util.BlockUtils; import com.gmail.nossr50.util.ItemUtils; import com.gmail.nossr50.util.Misc; @@ -179,18 +177,13 @@ public class BlockListener implements Listener { /* WOOD CUTTING */ else if (BlockUtils.isLog(blockState) && Permissions.skillEnabled(player, SkillType.WOODCUTTING) && !mcMMO.placeStore.isTrue(blockState)) { - if (mcMMOPlayer.getAbilityMode(AbilityType.TREE_FELLER) && Permissions.treeFeller(player) && ItemUtils.isAxe(heldItem)) { - Woodcutting.beginTreeFeller(blockState, player); + WoodcuttingManager woodcuttingManager = mcMMOPlayer.getWoodcuttingManager(); + + if (woodcuttingManager.canUseTreeFeller(heldItem)) { + woodcuttingManager.processTreeFeller(blockState); } else { - if (Config.getInstance().getWoodcuttingRequiresTool()) { - if (ItemUtils.isAxe(heldItem)) { - Woodcutting.beginWoodcutting(player, blockState); - } - } - else { - Woodcutting.beginWoodcutting(player, blockState); - } + woodcuttingManager.woodcuttingBlockCheck(blockState); } } @@ -367,18 +360,10 @@ public class BlockListener implements Listener { } } } - else if ((mcMMOPlayer.getProfile().getSkillLevel(SkillType.WOODCUTTING) >= AdvancedConfig.getInstance().getLeafBlowUnlockLevel()) && BlockUtils.isLeaves(blockState)) { - if (SkillUtils.triggerCheck(player, block, AbilityType.LEAF_BLOWER)) { - if (Config.getInstance().getWoodcuttingRequiresTool()) { - if (ItemUtils.isAxe(heldItem)) { - event.setInstaBreak(true); - Woodcutting.beginLeafBlower(player, blockState); - } - } - else if (!(heldItem.getType() == Material.SHEARS)) { - event.setInstaBreak(true); - Woodcutting.beginLeafBlower(player, blockState); - } + else if (BlockUtils.isLeaves(blockState)) { + if (UserManager.getPlayer(player).getWoodcuttingManager().canUseLeafBlower(heldItem) && SkillUtils.blockBreakSimulate(block, player, true)) { + event.setInstaBreak(true); + player.playSound(blockState.getLocation(), Sound.ITEM_PICKUP, Misc.POP_VOLUME, Misc.POP_PITCH); } } } diff --git a/src/main/java/com/gmail/nossr50/skills/woodcutting/TreeFeller.java b/src/main/java/com/gmail/nossr50/skills/woodcutting/TreeFeller.java deleted file mode 100644 index 6e813f352..000000000 --- a/src/main/java/com/gmail/nossr50/skills/woodcutting/TreeFeller.java +++ /dev/null @@ -1,276 +0,0 @@ -package com.gmail.nossr50.skills.woodcutting; - -import java.util.ArrayList; -import java.util.List; - -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.block.BlockState; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.material.Tree; - -import com.gmail.nossr50.mcMMO; -import com.gmail.nossr50.config.Config; -import com.gmail.nossr50.datatypes.mods.CustomBlock; -import com.gmail.nossr50.datatypes.skills.SkillType; -import com.gmail.nossr50.locale.LocaleLoader; -import com.gmail.nossr50.skills.woodcutting.Woodcutting.ExperienceGainMethod; -import com.gmail.nossr50.util.BlockUtils; -import com.gmail.nossr50.util.Misc; -import com.gmail.nossr50.util.ModUtils; -import com.gmail.nossr50.util.player.UserManager; -import com.gmail.nossr50.util.skills.CombatUtils; -import com.gmail.nossr50.util.skills.SkillUtils; - -public final class TreeFeller { - private static boolean treeFellerReachedThreshold = false; - - private TreeFeller() {} - - /** - * Begins Tree Feller - * - * @param mcMMOPlayer Player using Tree Feller - * @param blockState Block being broken - */ - protected static void processTreeFeller(BlockState blockState, Player player) { - List treeFellerBlocks = new ArrayList(); - - if (blockState.getTypeId() == 17 || blockState.getTypeId() == 99) { - processRegularTrees(blockState, treeFellerBlocks); - } - else { - processRedMushroomTrees(blockState, treeFellerBlocks); - } - - // If the player is trying to break too many blocks - if (treeFellerReachedThreshold) { - treeFellerReachedThreshold = false; - - player.sendMessage(LocaleLoader.getString("Woodcutting.Skills.TreeFellerThreshold")); - return; - } - - // If the tool can't sustain the durability loss - if (!handleDurabilityLoss(treeFellerBlocks, player.getItemInHand())) { - player.sendMessage(LocaleLoader.getString("Woodcutting.Skills.TreeFeller.Splinter")); - - int health = player.getHealth(); - - if (health > 1) { - CombatUtils.dealDamage(player, Misc.getRandom().nextInt(health - 1)); - } - - return; - } - - dropBlocks(treeFellerBlocks, player); - } - - /** - * Processes Tree Feller for generic Trees - * - * @param blockState Block being checked - * @param treeFellerBlocks List of blocks to be removed - */ - private static void processRegularTrees(BlockState blockState, List treeFellerBlocks) { - if (!BlockUtils.isLog(blockState)) { - return; - } - - List futureCenterBlocks = new ArrayList(); - World world = blockState.getWorld(); - - // Handle the blocks around 'block' - for (int y = 0; y <= 1; y++) { - for (int x = -1; x <= 1; x++) { - for (int z = -1; z <= 1; z++) { - BlockState nextBlock = world.getBlockAt(blockState.getLocation().add(x, y, z)).getState(); - - handleBlock(nextBlock, futureCenterBlocks, treeFellerBlocks); - - if (treeFellerReachedThreshold) { - return; - } - } - } - } - - // Recursive call for each log found - for (BlockState futureCenterBlock : futureCenterBlocks) { - if (treeFellerReachedThreshold) { - return; - } - - processRegularTrees(futureCenterBlock, treeFellerBlocks); - } - } - - /** - * Processes Tree Feller for Red Mushrooms (Dome Shaped) - * - * @param blockState Block being checked - * @param treeFellerBlocks List of blocks to be removed - */ - private static void processRedMushroomTrees(BlockState blockState, List treeFellerBlocks) { - if (!BlockUtils.isLog(blockState)) { - return; - } - - List futureCenterBlocks = new ArrayList(); - World world = blockState.getWorld(); - - // Handle the blocks around 'block' - for (int y = 0; y <= 1; y++) { - for (int x = -1; x <= 1; x++) { - for (int z = -1; z <= 1; z++) { - BlockState nextBlock = world.getBlockAt(blockState.getLocation().add(x, y, z)).getState(); - BlockState otherNextBlock = world.getBlockAt(blockState.getLocation().add(x, y - (y * 2), z)).getState(); - - handleBlock(nextBlock, futureCenterBlocks, treeFellerBlocks); - handleBlock(otherNextBlock, futureCenterBlocks, treeFellerBlocks); - - if (treeFellerReachedThreshold) { - return; - } - } - } - } - - // Recursive call for each log found - for (BlockState futureCenterBlock : futureCenterBlocks) { - if (treeFellerReachedThreshold) { - return; - } - - processRedMushroomTrees(futureCenterBlock, treeFellerBlocks); - } - } - - /** - * Handle a block addition to the list of blocks to be removed and to the list of blocks used for future recursive calls of 'processRecursively()' - * - * @param blockState Block to be added - * @param futureCenterBlocks List of blocks that will be used to call 'processRecursively()' - * @param treeFellerBlocks List of blocks to be removed - */ - private static void handleBlock(BlockState blockState, List futureCenterBlocks, List treeFellerBlocks) { - if (!BlockUtils.affectedByTreeFeller(blockState) || mcMMO.placeStore.isTrue(blockState) || treeFellerBlocks.contains(blockState)) { - return; - } - - treeFellerBlocks.add(blockState); - - if (treeFellerBlocks.size() > Config.getInstance().getTreeFellerThreshold()) { - treeFellerReachedThreshold = true; - return; - } - - futureCenterBlocks.add(blockState); - } - - /** - * Handles the durability loss - * - * @param treeFellerBlocks List of blocks to be removed - * @param inHand tool being used - * @return True if the tool can sustain the durability loss - */ - private static boolean handleDurabilityLoss(List treeFellerBlocks, ItemStack inHand) { - Material inHandMaterial = inHand.getType(); - - if (inHandMaterial != Material.AIR) { - short durabilityLoss = 0; - int unbreakingLevel = inHand.getEnchantmentLevel(Enchantment.DURABILITY); - - for (BlockState blockState : treeFellerBlocks) { - if (BlockUtils.isLog(blockState) && Misc.getRandom().nextInt(unbreakingLevel + 1) == 0) { - durabilityLoss += Config.getInstance().getAbilityToolDamage(); - } - } - - short finalDurability = (short) (inHand.getDurability() + durabilityLoss); - short maxDurability = ModUtils.isCustomTool(inHand) ? ModUtils.getToolFromItemStack(inHand).getDurability() : inHandMaterial.getMaxDurability(); - - if (finalDurability >= maxDurability) { - inHand.setDurability(maxDurability); - return false; - } - - inHand.setDurability(finalDurability); - } - - return true; - } - - /** - * Handles the dropping of blocks - * - * @param treeFellerBlocks List of blocks to be dropped - * @param player Player using the ability - */ - private static void dropBlocks(List treeFellerBlocks, Player player) { - int xp = 0; - - for (BlockState blockState : treeFellerBlocks) { - if (!SkillUtils.blockBreakSimulate(blockState.getBlock(), player, true)) { - break; // TODO: Shouldn't we use continue instead? - } - - Material material = blockState.getType(); - - if (material == Material.HUGE_MUSHROOM_1 || material == Material.HUGE_MUSHROOM_2) { - xp += Woodcutting.getExperienceFromLog(blockState, ExperienceGainMethod.TREE_FELLER); - - for (ItemStack drop : blockState.getBlock().getDrops()) { - Misc.dropItem(blockState.getLocation(), drop); - } - } - else if (ModUtils.isCustomLogBlock(blockState)) { - Woodcutting.checkForDoubleDrop(player, blockState); - - CustomBlock customBlock = ModUtils.getCustomBlock(blockState); - xp = customBlock.getXpGain(); - int minimumDropAmount = customBlock.getMinimumDropAmount(); - int maximumDropAmount = customBlock.getMaximumDropAmount(); - Location location = blockState.getLocation(); - ItemStack item = customBlock.getItemDrop();; - - Misc.dropItems(location, item, minimumDropAmount); - - if (minimumDropAmount < maximumDropAmount) { - Misc.randomDropItems(location, item, maximumDropAmount - minimumDropAmount); - } - } - else if (ModUtils.isCustomLeafBlock(blockState)) { - Misc.randomDropItem(blockState.getLocation(), ModUtils.getCustomBlock(blockState).getItemDrop(), 10); - } - else { - Tree tree = (Tree) blockState.getData(); - switch (material) { - case LOG: - Woodcutting.checkForDoubleDrop(player, blockState); - xp += Woodcutting.getExperienceFromLog(blockState, ExperienceGainMethod.TREE_FELLER); - Misc.dropItem(blockState.getLocation(), new ItemStack(Material.LOG, 1, tree.getSpecies().getData())); - break; - - case LEAVES: - Misc.randomDropItem(blockState.getLocation(), new ItemStack(Material.SAPLING, 1, tree.getSpecies().getData()), 10); - break; - - default: - break; - } - } - - blockState.setRawData((byte) 0x0); - blockState.setType(Material.AIR); - blockState.update(true); - } - - UserManager.getPlayer(player).beginXpGain(SkillType.WOODCUTTING, xp); - } -} diff --git a/src/main/java/com/gmail/nossr50/skills/woodcutting/Woodcutting.java b/src/main/java/com/gmail/nossr50/skills/woodcutting/Woodcutting.java index 47df1d5c2..cb99beb9c 100644 --- a/src/main/java/com/gmail/nossr50/skills/woodcutting/Woodcutting.java +++ b/src/main/java/com/gmail/nossr50/skills/woodcutting/Woodcutting.java @@ -1,10 +1,12 @@ package com.gmail.nossr50.skills.woodcutting; +import java.util.ArrayList; +import java.util.List; + import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.Sound; import org.bukkit.block.BlockState; -import org.bukkit.entity.Player; +import org.bukkit.enchantments.Enchantment; import org.bukkit.inventory.ItemStack; import org.bukkit.material.Tree; @@ -12,18 +14,17 @@ import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.config.AdvancedConfig; import com.gmail.nossr50.config.Config; import com.gmail.nossr50.datatypes.mods.CustomBlock; -import com.gmail.nossr50.datatypes.skills.SkillType; -import com.gmail.nossr50.events.fake.FakePlayerAnimationEvent; +import com.gmail.nossr50.util.BlockUtils; import com.gmail.nossr50.util.Misc; import com.gmail.nossr50.util.ModUtils; -import com.gmail.nossr50.util.Permissions; -import com.gmail.nossr50.util.player.UserManager; -import com.gmail.nossr50.util.skills.SkillUtils; public final class Woodcutting { public static int doubleDropsMaxLevel = AdvancedConfig.getInstance().getWoodcuttingDoubleDropMaxLevel(); public static double doubleDropsMaxChance = AdvancedConfig.getInstance().getWoodcuttingDoubleDropChance(); + public static int leafBlowerUnlockLevel = AdvancedConfig.getInstance().getLeafBlowUnlockLevel(); + public static int treeFellerThreshold = Config.getInstance().getTreeFellerThreshold(); + protected enum ExperienceGainMethod { DEFAULT, TREE_FELLER, @@ -31,47 +32,6 @@ public final class Woodcutting { private Woodcutting() {} - /** - * Begins the Tree Feller ability - * - * @param mcMMOPlayer Player using the ability - * @param block Block being broken - */ - public static void beginTreeFeller(BlockState blockState, Player player) { - TreeFeller.processTreeFeller(blockState, player); - } - - /** - * Begins the Leaf Blower ability - * - * @param player Player using the ability - * @param block Block being broken - */ - public static void beginLeafBlower(Player player, BlockState blockState) { - mcMMO.p.getServer().getPluginManager().callEvent(new FakePlayerAnimationEvent(player)); - player.playSound(blockState.getLocation(), Sound.ITEM_PICKUP, Misc.POP_VOLUME, Misc.POP_PITCH); - } - - /** - * Begins Woodcutting - * - * @param mcMMOPlayer Player breaking the block - * @param block Block being broken - */ - public static void beginWoodcutting(Player player, BlockState blockState) { - int xp = getExperienceFromLog(blockState, ExperienceGainMethod.DEFAULT); - - if (Permissions.doubleDrops(player, SkillType.WOODCUTTING)) { - Material blockType = blockState.getType(); - - if (blockType != Material.HUGE_MUSHROOM_1 && blockType != Material.HUGE_MUSHROOM_2) { - checkForDoubleDrop(player, blockState); - } - } - - UserManager.getPlayer(player).beginXpGain(SkillType.WOODCUTTING, xp); - } - /** * Retrieves the experience reward from a log * @@ -126,11 +86,7 @@ public final class Woodcutting { * @param mcMMOPlayer Player breaking the block * @param blockState Block being broken */ - protected static void checkForDoubleDrop(Player player, BlockState blockState) { - if (!SkillUtils.activationSuccessful(player, SkillType.WOODCUTTING, doubleDropsMaxChance, doubleDropsMaxLevel)) { - return; - } - + protected static void checkForDoubleDrop(BlockState blockState) { if (ModUtils.isCustomLogBlock(blockState)) { CustomBlock customBlock = ModUtils.getCustomBlock(blockState); int minimumDropAmount = customBlock.getMinimumDropAmount(); @@ -179,4 +135,129 @@ public final class Woodcutting { } } } + + /** + * Processes Tree Feller for generic Trees + * + * @param blockState Block being checked + * @param treeFellerBlocks List of blocks to be removed + */ + protected static void processRegularTrees(BlockState blockState, List treeFellerBlocks) { + List futureCenterBlocks = new ArrayList(); + + // Handle the blocks around 'block' + for (int y = 0; y <= 1; y++) { + for (int x = -1; x <= 1; x++) { + for (int z = -1; z <= 1; z++) { + BlockState nextBlock = blockState.getBlock().getRelative(x, y, z).getState(); + handleBlock(nextBlock, futureCenterBlocks, treeFellerBlocks); + + if (WoodcuttingManager.treeFellerReachedThreshold) { + return; + } + } + } + } + + // Recursive call for each log found + for (BlockState futureCenterBlock : futureCenterBlocks) { + if (WoodcuttingManager.treeFellerReachedThreshold) { + return; + } + + processRegularTrees(futureCenterBlock, treeFellerBlocks); + } + } + + /** + * Processes Tree Feller for Red Mushrooms (Dome Shaped) + * + * @param blockState Block being checked + * @param treeFellerBlocks List of blocks to be removed + */ + protected static void processRedMushroomTrees(BlockState blockState, List treeFellerBlocks) { + List futureCenterBlocks = new ArrayList(); + + // Handle the blocks around 'block' + for (int y = 0; y <= 1; y++) { + for (int x = -1; x <= 1; x++) { + for (int z = -1; z <= 1; z++) { + BlockState nextBlock = blockState.getBlock().getRelative(x, y, z).getState(); + BlockState otherNextBlock = blockState.getBlock().getRelative(x, y - (y * 2), z).getState(); + + handleBlock(nextBlock, futureCenterBlocks, treeFellerBlocks); + handleBlock(otherNextBlock, futureCenterBlocks, treeFellerBlocks); + + if (WoodcuttingManager.treeFellerReachedThreshold) { + return; + } + } + } + } + + // Recursive call for each log found + for (BlockState futureCenterBlock : futureCenterBlocks) { + if (WoodcuttingManager.treeFellerReachedThreshold) { + return; + } + + processRedMushroomTrees(futureCenterBlock, treeFellerBlocks); + } + } + + /** + * Handles the durability loss + * + * @param treeFellerBlocks List of blocks to be removed + * @param inHand tool being used + * @return True if the tool can sustain the durability loss + */ + protected static boolean handleDurabilityLoss(List treeFellerBlocks, ItemStack inHand) { + Material inHandMaterial = inHand.getType(); + + if (inHandMaterial == Material.AIR) { + return false; + } + + short durabilityLoss = 0; + int unbreakingLevel = inHand.getEnchantmentLevel(Enchantment.DURABILITY); + + for (BlockState blockState : treeFellerBlocks) { + if (BlockUtils.isLog(blockState) && Misc.getRandom().nextInt(unbreakingLevel + 1) == 0) { + durabilityLoss += Config.getInstance().getAbilityToolDamage(); + } + } + + short finalDurability = (short) (inHand.getDurability() + durabilityLoss); + short maxDurability = ModUtils.isCustomTool(inHand) ? ModUtils.getToolFromItemStack(inHand).getDurability() : inHandMaterial.getMaxDurability(); + + if (finalDurability >= maxDurability) { + return false; + } + + inHand.setDurability(finalDurability); + return true; + } + + /** + * Handle a block addition to the list of blocks to be removed and to the list of blocks used for future recursive calls of 'processRecursively()' + * + * @param blockState Block to be added + * @param futureCenterBlocks List of blocks that will be used to call 'processRecursively()' + * @param treeFellerBlocks List of blocks to be removed + */ + private static void handleBlock(BlockState blockState, List futureCenterBlocks, List treeFellerBlocks) { + if (!BlockUtils.affectedByTreeFeller(blockState) || mcMMO.placeStore.isTrue(blockState) || treeFellerBlocks.contains(blockState)) { + return; + } + + treeFellerBlocks.add(blockState); + + if (treeFellerBlocks.size() > treeFellerThreshold) { + WoodcuttingManager.treeFellerReachedThreshold = true; + return; + } + + futureCenterBlocks.add(blockState); + } } diff --git a/src/main/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingManager.java b/src/main/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingManager.java new file mode 100644 index 000000000..e15c816b3 --- /dev/null +++ b/src/main/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingManager.java @@ -0,0 +1,192 @@ +package com.gmail.nossr50.skills.woodcutting; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.BlockState; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.material.Tree; + +import com.gmail.nossr50.datatypes.mods.CustomBlock; +import com.gmail.nossr50.datatypes.player.McMMOPlayer; +import com.gmail.nossr50.datatypes.skills.AbilityType; +import com.gmail.nossr50.datatypes.skills.SkillType; +import com.gmail.nossr50.locale.LocaleLoader; +import com.gmail.nossr50.skills.SkillManager; +import com.gmail.nossr50.skills.woodcutting.Woodcutting.ExperienceGainMethod; +import com.gmail.nossr50.util.ItemUtils; +import com.gmail.nossr50.util.Misc; +import com.gmail.nossr50.util.ModUtils; +import com.gmail.nossr50.util.Permissions; +import com.gmail.nossr50.util.skills.CombatUtils; +import com.gmail.nossr50.util.skills.SkillUtils; + +public class WoodcuttingManager extends SkillManager { + protected static boolean treeFellerReachedThreshold = false; + + public WoodcuttingManager(McMMOPlayer mcMMOPlayer) { + super(mcMMOPlayer, SkillType.WOODCUTTING); + } + + public boolean canUseLeafBlower(ItemStack heldItem) { + return getSkillLevel() >= Woodcutting.leafBlowerUnlockLevel && ItemUtils.isAxe(heldItem); + } + + public boolean canUseTreeFeller(ItemStack heldItem) { + return mcMMOPlayer.getAbilityMode(AbilityType.TREE_FELLER) && Permissions.treeFeller(getPlayer()) && ItemUtils.isAxe(heldItem); + } + + protected boolean canGetDoubleDrops() { + return Permissions.doubleDrops(getPlayer(), skill) && SkillUtils.activationSuccessful(getSkillLevel(), getActivationChance(), Woodcutting.doubleDropsMaxChance, Woodcutting.doubleDropsMaxLevel); + } + + /** + * Begins Woodcutting + * + * @param blockState Block being broken + */ + public void woodcuttingBlockCheck(BlockState blockState) { + int xp = Woodcutting.getExperienceFromLog(blockState, ExperienceGainMethod.DEFAULT); + + switch (blockState.getType()) { + case HUGE_MUSHROOM_1: + case HUGE_MUSHROOM_2: + break; + + default: + if (canGetDoubleDrops()) { + Woodcutting.checkForDoubleDrop(blockState); + } + } + + applyXpGain(xp); + } + + /** + * Begins Tree Feller + * + * @param blockState Block being broken + */ + public void processTreeFeller(BlockState blockState) { + Player player = getPlayer(); + List treeFellerBlocks = new ArrayList(); + + switch (blockState.getType()) { + case LOG: + case HUGE_MUSHROOM_1: + Woodcutting.processRegularTrees(blockState, treeFellerBlocks); + break; + + case HUGE_MUSHROOM_2: + Woodcutting.processRedMushroomTrees(blockState, treeFellerBlocks); + break; + + default: + if (ModUtils.isCustomLogBlock(blockState)) { + Woodcutting.processRegularTrees(blockState, treeFellerBlocks); + } + break; + } + + // If the player is trying to break too many blocks + if (treeFellerReachedThreshold) { + treeFellerReachedThreshold = false; + + player.sendMessage(LocaleLoader.getString("Woodcutting.Skills.TreeFellerThreshold")); + return; + } + + // If the tool can't sustain the durability loss + if (!Woodcutting.handleDurabilityLoss(treeFellerBlocks, player.getItemInHand())) { + player.sendMessage(LocaleLoader.getString("Woodcutting.Skills.TreeFeller.Splinter")); + + int health = player.getHealth(); + + if (health > 1) { + CombatUtils.dealDamage(player, Misc.getRandom().nextInt(health - 1)); + } + + return; + } + + dropBlocks(treeFellerBlocks); + treeFellerReachedThreshold = false; // Reset the value after we're done with Tree Feller each time. + } + + /** + * Handles the dropping of blocks + * + * @param treeFellerBlocks List of blocks to be dropped + * @param player Player using the ability + */ + private void dropBlocks(List treeFellerBlocks) { + Player player = getPlayer(); + int xp = 0; + + for (BlockState blockState : treeFellerBlocks) { + if (!SkillUtils.blockBreakSimulate(blockState.getBlock(), player, true)) { + break; // TODO: Shouldn't we use continue instead? + } + + Material material = blockState.getType(); + + if (material == Material.HUGE_MUSHROOM_1 || material == Material.HUGE_MUSHROOM_2) { + xp += Woodcutting.getExperienceFromLog(blockState, ExperienceGainMethod.TREE_FELLER); + + for (ItemStack drop : blockState.getBlock().getDrops()) { + Misc.dropItem(blockState.getLocation(), drop); + } + } + else if (ModUtils.isCustomLogBlock(blockState)) { + if (canGetDoubleDrops()) { + Woodcutting.checkForDoubleDrop(blockState); + } + + CustomBlock customBlock = ModUtils.getCustomBlock(blockState); + xp = customBlock.getXpGain(); + int minimumDropAmount = customBlock.getMinimumDropAmount(); + int maximumDropAmount = customBlock.getMaximumDropAmount(); + Location location = blockState.getLocation(); + ItemStack item = customBlock.getItemDrop();; + + Misc.dropItems(location, item, minimumDropAmount); + + if (minimumDropAmount < maximumDropAmount) { + Misc.randomDropItems(location, item, maximumDropAmount - minimumDropAmount); + } + } + else if (ModUtils.isCustomLeafBlock(blockState)) { + Misc.randomDropItem(blockState.getLocation(), ModUtils.getCustomBlock(blockState).getItemDrop(), 10); + } + else { + Tree tree = (Tree) blockState.getData(); + switch (material) { + case LOG: + if (canGetDoubleDrops()) { + Woodcutting.checkForDoubleDrop(blockState); + } + xp += Woodcutting.getExperienceFromLog(blockState, ExperienceGainMethod.TREE_FELLER); + Misc.dropItem(blockState.getLocation(), new ItemStack(Material.LOG, 1, tree.getSpecies().getData())); + break; + + case LEAVES: + Misc.randomDropItem(blockState.getLocation(), new ItemStack(Material.SAPLING, 1, tree.getSpecies().getData()), 10); + break; + + default: + break; + } + } + + blockState.setRawData((byte) 0x0); + blockState.setType(Material.AIR); + blockState.update(true); + } + + applyXpGain(xp); + } + +}