TreeFeller.java 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. package com.gmail.nossr50.skills.woodcutting;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import org.bukkit.Location;
  5. import org.bukkit.Material;
  6. import org.bukkit.World;
  7. import org.bukkit.block.Block;
  8. import org.bukkit.enchantments.Enchantment;
  9. import org.bukkit.entity.Player;
  10. import org.bukkit.inventory.ItemStack;
  11. import com.gmail.nossr50.mcMMO;
  12. import com.gmail.nossr50.datatypes.McMMOPlayer;
  13. import com.gmail.nossr50.locale.LocaleLoader;
  14. import com.gmail.nossr50.mods.ModChecks;
  15. import com.gmail.nossr50.mods.datatypes.CustomBlock;
  16. import com.gmail.nossr50.skills.utilities.CombatTools;
  17. import com.gmail.nossr50.skills.utilities.SkillType;
  18. import com.gmail.nossr50.skills.woodcutting.Woodcutting.ExperienceGainMethod;
  19. import com.gmail.nossr50.util.BlockChecks;
  20. import com.gmail.nossr50.util.Misc;
  21. public final class TreeFeller {
  22. private static boolean treeFellerReachedThreshold = false;
  23. private TreeFeller() {}
  24. /**
  25. * Begins Tree Feller
  26. *
  27. * @param mcMMOPlayer Player using Tree Feller
  28. * @param block Block being broken
  29. */
  30. public static void process(McMMOPlayer mcMMOPlayer, Block block) {
  31. List<Block> treeFellerBlocks = new ArrayList<Block>();
  32. processRecursively(block, treeFellerBlocks);
  33. // If the player is trying to break to many block
  34. if (treeFellerReachedThreshold) {
  35. treeFellerReachedThreshold = false;
  36. mcMMOPlayer.getPlayer().sendMessage(LocaleLoader.getString("Woodcutting.Skills.TreeFellerThreshold"));
  37. return;
  38. }
  39. Player player = mcMMOPlayer.getPlayer();
  40. // If the tool can't sustain the durability loss
  41. if (!handleDurabilityLoss(treeFellerBlocks, player.getItemInHand())) {
  42. mcMMOPlayer.getPlayer().sendMessage(LocaleLoader.getString("Woodcutting.Skills.TreeFeller.Splinter"));
  43. int health = player.getHealth();
  44. if (health > 1) {
  45. CombatTools.dealDamage(player, Misc.getRandom().nextInt(health - 1));
  46. }
  47. return;
  48. }
  49. dropBlocks(treeFellerBlocks, mcMMOPlayer);
  50. }
  51. /**
  52. * Processes Tree Feller
  53. *
  54. * @param block Block being checked
  55. * @param treeFellerBlocks List of blocks to be removed
  56. */
  57. private static void processRecursively(Block block, List<Block> treeFellerBlocks) {
  58. if (!BlockChecks.isLog(block)) {
  59. return;
  60. }
  61. List<Block> futureCenterBlocks = new ArrayList<Block>();
  62. World world = block.getWorld();
  63. // Handle the blocks around 'block'
  64. for (int y = 0 ; y <= 1 ; y++) {
  65. for (int x = -1 ; x <= 1 ; x++) {
  66. for (int z = -1 ; z <= 1 ; z++) {
  67. Block nextBlock = world.getBlockAt(block.getLocation().add(x, y, z));
  68. handleBlock(nextBlock, futureCenterBlocks, treeFellerBlocks);
  69. if (treeFellerReachedThreshold) {
  70. return;
  71. }
  72. }
  73. }
  74. }
  75. // Recursive call for each log found
  76. for (Block futurCenterBlock : futureCenterBlocks) {
  77. if (treeFellerReachedThreshold) {
  78. return;
  79. }
  80. processRecursively(futurCenterBlock, treeFellerBlocks);
  81. }
  82. }
  83. /**
  84. * Handle a block addition to the list of blocks to be removed
  85. * and to the list of blocks used for future recursive calls of 'processRecursively()'
  86. *
  87. * @param block Block to be added
  88. * @param futureCenterBlocks List of blocks that will be used to call 'processRecursively()'
  89. * @param treeFellerBlocks List of blocks to be removed
  90. */
  91. private static void handleBlock(Block block, List<Block> futureCenterBlocks, List<Block> treeFellerBlocks) {
  92. if (!BlockChecks.treeFellerCompatible(block) || mcMMO.placeStore.isTrue(block) || treeFellerBlocks.contains(block)) {
  93. return;
  94. }
  95. treeFellerBlocks.add(block);
  96. if (treeFellerBlocks.size() > Woodcutting.CONFIG.getTreeFellerThreshold()) {
  97. treeFellerReachedThreshold = true;
  98. return;
  99. }
  100. futureCenterBlocks.add(block);
  101. }
  102. /**
  103. * Handles the durability loss
  104. *
  105. * @param treeFellerBlocks List of blocks to be removed
  106. * @param inHand tool being used
  107. * @return True if the tool can sustain the durability loss
  108. */
  109. private static boolean handleDurabilityLoss(List<Block> treeFellerBlocks, ItemStack inHand) {
  110. Material inHandMaterial = inHand.getType();
  111. if (inHandMaterial != Material.AIR) {
  112. short durabilityLoss = 0;
  113. int unbreakingLevel = inHand.getEnchantmentLevel(Enchantment.DURABILITY);
  114. for (Block block : treeFellerBlocks) {
  115. if (BlockChecks.isLog(block) && Misc.getRandom().nextInt(unbreakingLevel + 1) == 0) {
  116. durabilityLoss += Misc.toolDurabilityLoss;
  117. }
  118. }
  119. short finalDurability = (short) (inHand.getDurability() + durabilityLoss);
  120. short maxDurability = ModChecks.isCustomTool(inHand) ? ModChecks.getToolFromItemStack(inHand).getDurability() : inHandMaterial.getMaxDurability();
  121. if (finalDurability >= maxDurability) {
  122. inHand.setDurability(maxDurability);
  123. return false;
  124. }
  125. inHand.setDurability(finalDurability);
  126. }
  127. return true;
  128. }
  129. /**
  130. * Handles the dropping of blocks
  131. *
  132. * @param treeFellerBlocks List of blocks to be dropped
  133. * @param mcMMOPlayer Player using the ability
  134. */
  135. private static void dropBlocks(List<Block> treeFellerBlocks, McMMOPlayer mcMMOPlayer) {
  136. int xp = 0;
  137. for (Block block : treeFellerBlocks) {
  138. if (!Misc.blockBreakSimulate(block, mcMMOPlayer.getPlayer(), true)) {
  139. break; // TODO: Shouldn't we use continue instead?
  140. }
  141. Material material = block.getType();
  142. switch (material) {
  143. case HUGE_MUSHROOM_1:
  144. case HUGE_MUSHROOM_2:
  145. try {
  146. xp += Woodcutting.getExperienceFromLog(block, ExperienceGainMethod.TREE_FELLER);
  147. }
  148. catch (IllegalArgumentException exception) {
  149. break;
  150. }
  151. // Stems have a block data value of 15 and should not drop mushrooms
  152. // 0-2 mushrooms drop when you break a block
  153. if (block.getData() == (byte) 15) {
  154. break;
  155. }
  156. if (material == Material.HUGE_MUSHROOM_1) {
  157. Misc.randomDropItems(block.getLocation(), new ItemStack(Material.BROWN_MUSHROOM), 50, 2);
  158. }
  159. else {
  160. Misc.randomDropItems(block.getLocation(), new ItemStack(Material.RED_MUSHROOM), 50, 2);
  161. }
  162. break;
  163. case LOG:
  164. Woodcutting.checkForDoubleDrop(mcMMOPlayer, block);
  165. try {
  166. xp += Woodcutting.getExperienceFromLog(block, ExperienceGainMethod.TREE_FELLER);
  167. }
  168. catch (IllegalArgumentException exception) {
  169. break;
  170. }
  171. Misc.dropItem(block.getLocation(), new ItemStack(Material.LOG, 1, Woodcutting.extractLogItemData(block.getData())));
  172. break;
  173. case LEAVES:
  174. Misc.randomDropItem(block.getLocation(), new ItemStack(Material.SAPLING, 1, Woodcutting.extractLogItemData(block.getData())), 10);
  175. break;
  176. default:
  177. if (ModChecks.isCustomLogBlock(block)) {
  178. Woodcutting.checkForDoubleDrop(mcMMOPlayer, block);
  179. CustomBlock customBlock = ModChecks.getCustomBlock(block);
  180. xp = customBlock.getXpGain();
  181. int minimumDropAmount = customBlock.getMinimumDropAmount();
  182. int maximumDropAmount = customBlock.getMaximumDropAmount();
  183. Location location = block.getLocation();
  184. ItemStack item = customBlock.getItemDrop();;
  185. Misc.dropItems(location, item, minimumDropAmount);
  186. if (minimumDropAmount < maximumDropAmount) {
  187. Misc.randomDropItems(location, item, 50, maximumDropAmount - minimumDropAmount);
  188. }
  189. }
  190. else if (ModChecks.isCustomLeafBlock(block)) {
  191. CustomBlock customBlock = ModChecks.getCustomBlock(block);
  192. Misc.randomDropItem(block.getLocation(), customBlock.getItemDrop(), 10);
  193. }
  194. break;
  195. }
  196. block.setData((byte) 0);
  197. block.setType(Material.AIR);
  198. }
  199. mcMMOPlayer.beginXpGain(SkillType.WOODCUTTING, xp);
  200. }
  201. }