Woodcutting.java 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. package com.gmail.nossr50.skills.woodcutting;
  2. import com.gmail.nossr50.config.MainConfig;
  3. import com.gmail.nossr50.config.experience.ExperienceConfig;
  4. import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
  5. import com.gmail.nossr50.mcMMO;
  6. import com.gmail.nossr50.util.BlockUtils;
  7. import com.gmail.nossr50.util.Misc;
  8. import com.gmail.nossr50.util.skills.SkillUtils;
  9. import org.bukkit.Material;
  10. import org.bukkit.block.BlockFace;
  11. import org.bukkit.block.BlockState;
  12. import org.bukkit.inventory.ItemStack;
  13. import java.util.ArrayList;
  14. import java.util.List;
  15. import java.util.Set;
  16. public final class Woodcutting {
  17. public static int treeFellerThreshold = MainConfig.getInstance().getTreeFellerThreshold();
  18. protected static boolean treeFellerReachedThreshold = false;
  19. protected enum ExperienceGainMethod {
  20. DEFAULT,
  21. TREE_FELLER,
  22. }
  23. private Woodcutting() {}
  24. /**
  25. * Retrieves the experience reward from a log
  26. *
  27. * @param blockState Log being broken
  28. * @param experienceGainMethod How the log is being broken
  29. * @return Amount of experience
  30. */
  31. protected static int getExperienceFromLog(BlockState blockState, ExperienceGainMethod experienceGainMethod) {
  32. /*if (mcMMO.getModManager().isCustomLog(blockState)) {
  33. return mcMMO.getModManager().getBlock(blockState).getXpGain();
  34. }*/
  35. return ExperienceConfig.getInstance().getXp(PrimarySkillType.WOODCUTTING, blockState.getType());
  36. }
  37. /**
  38. * Checks for double drops
  39. *
  40. * @param blockState Block being broken
  41. */
  42. protected static void checkForDoubleDrop(BlockState blockState) {
  43. /*if (mcMMO.getModManager().isCustomLog(blockState) && mcMMO.getModManager().getBlock(blockState).isDoubleDropEnabled()) {
  44. Misc.dropItems(Misc.getBlockCenter(blockState), blockState.getBlock().getDrops());
  45. }
  46. else {*/
  47. if (MainConfig.getInstance().getWoodcuttingDoubleDropsEnabled(blockState.getBlockData())) {
  48. Misc.dropItems(Misc.getBlockCenter(blockState), blockState.getBlock().getDrops());
  49. }
  50. //}
  51. }
  52. /**
  53. * The x/y differences to the blocks in a flat cylinder around the center
  54. * block, which is excluded.
  55. */
  56. private static final int[][] directions = {
  57. new int[] {-2, -1}, new int[] {-2, 0}, new int[] {-2, 1},
  58. new int[] {-1, -2}, new int[] {-1, -1}, new int[] {-1, 0}, new int[] {-1, 1}, new int[] {-1, 2},
  59. new int[] { 0, -2}, new int[] { 0, -1}, new int[] { 0, 1}, new int[] { 0, 2},
  60. new int[] { 1, -2}, new int[] { 1, -1}, new int[] { 1, 0}, new int[] { 1, 1}, new int[] { 1, 2},
  61. new int[] { 2, -1}, new int[] { 2, 0}, new int[] { 2, 1},
  62. };
  63. /**
  64. * Processes Tree Feller in a recursive manner
  65. *
  66. * @param blockState Block being checked
  67. * @param treeFellerBlocks List of blocks to be removed
  68. */
  69. /*
  70. * Algorithm: An int[][] of X/Z directions is created on static class
  71. * initialization, representing a cylinder with radius of about 2 - the
  72. * (0,0) center and all (+-2, +-2) corners are omitted.
  73. *
  74. * handleBlock() returns a boolean, which is used for the sole purpose of
  75. * switching between these two behaviors:
  76. *
  77. * (Call blockState "this log" for the below explanation.)
  78. *
  79. * [A] There is another log above this log (TRUNK)
  80. * Only the flat cylinder in the directions array is searched.
  81. * [B] There is not another log above this log (BRANCH AND TOP)
  82. * The cylinder in the directions array is extended up and down by 1
  83. * block in the Y-axis, and the block below this log is checked as
  84. * well. Due to the fact that the directions array will catch all
  85. * blocks on a red mushroom, the special method for it is eliminated.
  86. *
  87. * This algorithm has been shown to achieve a performance of 2-5
  88. * milliseconds on regular trees and 10-15 milliseconds on jungle trees
  89. * once the JIT has optimized the function (use the ability about 4 times
  90. * before taking measurements).
  91. */
  92. protected static void processTree(BlockState blockState, Set<BlockState> treeFellerBlocks) {
  93. List<BlockState> futureCenterBlocks = new ArrayList<BlockState>();
  94. // Check the block up and take different behavior (smaller search) if it's a log
  95. if (handleBlock(blockState.getBlock().getRelative(BlockFace.UP).getState(), futureCenterBlocks, treeFellerBlocks)) {
  96. for (int[] dir : directions) {
  97. handleBlock(blockState.getBlock().getRelative(dir[0], 0, dir[1]).getState(), futureCenterBlocks, treeFellerBlocks);
  98. if (treeFellerReachedThreshold) {
  99. return;
  100. }
  101. }
  102. }
  103. else {
  104. // Cover DOWN
  105. handleBlock(blockState.getBlock().getRelative(BlockFace.DOWN).getState(), futureCenterBlocks, treeFellerBlocks);
  106. // Search in a cube
  107. for (int y = -1; y <= 1; y++) {
  108. for (int[] dir : directions) {
  109. handleBlock(blockState.getBlock().getRelative(dir[0], y, dir[1]).getState(), futureCenterBlocks, treeFellerBlocks);
  110. if (treeFellerReachedThreshold) {
  111. return;
  112. }
  113. }
  114. }
  115. }
  116. // Recursive call for each log found
  117. for (BlockState futureCenterBlock : futureCenterBlocks) {
  118. if (treeFellerReachedThreshold) {
  119. return;
  120. }
  121. processTree(futureCenterBlock, treeFellerBlocks);
  122. }
  123. }
  124. /**
  125. * Handles the durability loss
  126. *
  127. * @param treeFellerBlocks List of blocks to be removed
  128. * @param inHand tool being used
  129. * @return True if the tool can sustain the durability loss
  130. */
  131. protected static boolean handleDurabilityLoss(Set<BlockState> treeFellerBlocks, ItemStack inHand) {
  132. short durabilityLoss = 0;
  133. Material type = inHand.getType();
  134. for (BlockState blockState : treeFellerBlocks) {
  135. if (BlockUtils.isLog(blockState)) {
  136. durabilityLoss += MainConfig.getInstance().getAbilityToolDamage();
  137. }
  138. }
  139. SkillUtils.handleDurabilityChange(inHand, durabilityLoss);
  140. return (inHand.getDurability() < (mcMMO.getRepairableManager().isRepairable(type) ? mcMMO.getRepairableManager().getRepairable(type).getMaximumDurability() : type.getMaxDurability()));
  141. }
  142. /**
  143. * Handle a block addition to the list of blocks to be removed and to the
  144. * list of blocks used for future recursive calls of
  145. * 'processTree()'
  146. *
  147. * @param blockState Block to be added
  148. * @param futureCenterBlocks List of blocks that will be used to call
  149. * 'processTree()'
  150. * @param treeFellerBlocks List of blocks to be removed
  151. * @return true if and only if the given blockState was a Log not already
  152. * in treeFellerBlocks.
  153. */
  154. private static boolean handleBlock(BlockState blockState, List<BlockState> futureCenterBlocks, Set<BlockState> treeFellerBlocks) {
  155. if (treeFellerBlocks.contains(blockState) || mcMMO.getPlaceStore().isTrue(blockState)) {
  156. return false;
  157. }
  158. // Without this check Tree Feller propagates through leaves until the threshold is hit
  159. if (treeFellerBlocks.size() > treeFellerThreshold) {
  160. treeFellerReachedThreshold = true;
  161. }
  162. if (BlockUtils.isLog(blockState)) {
  163. treeFellerBlocks.add(blockState);
  164. futureCenterBlocks.add(blockState);
  165. return true;
  166. }
  167. else if (BlockUtils.isLeaves(blockState)) {
  168. treeFellerBlocks.add(blockState);
  169. return false;
  170. }
  171. return false;
  172. }
  173. }