mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2024-12-27 11:07:44 +01:00
Create a WoodcuttingManager
This commit is contained in:
parent
c1161da6de
commit
44ede5c3f8
@ -34,6 +34,7 @@ import com.gmail.nossr50.skills.smelting.SmeltingManager;
|
|||||||
import com.gmail.nossr50.skills.swords.SwordsManager;
|
import com.gmail.nossr50.skills.swords.SwordsManager;
|
||||||
import com.gmail.nossr50.skills.taming.TamingManager;
|
import com.gmail.nossr50.skills.taming.TamingManager;
|
||||||
import com.gmail.nossr50.skills.unarmed.UnarmedManager;
|
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.Misc;
|
||||||
import com.gmail.nossr50.util.ModUtils;
|
import com.gmail.nossr50.util.ModUtils;
|
||||||
import com.gmail.nossr50.util.Permissions;
|
import com.gmail.nossr50.util.Permissions;
|
||||||
@ -94,12 +95,7 @@ public class McMMOPlayer {
|
|||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
for (SkillType skillType : SkillType.values()) {
|
for (SkillType skillType : SkillType.values()) {
|
||||||
Class<? extends SkillManager> skillManagerClass = skillType.getManagerClass();
|
skillManagers.put(skillType, skillType.getManagerClass().getConstructor(McMMOPlayer.class).newInstance(this));
|
||||||
|
|
||||||
// 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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
@ -166,6 +162,10 @@ public class McMMOPlayer {
|
|||||||
return (UnarmedManager) skillManagers.get(SkillType.UNARMED);
|
return (UnarmedManager) skillManagers.get(SkillType.UNARMED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WoodcuttingManager getWoodcuttingManager() {
|
||||||
|
return (WoodcuttingManager) skillManagers.get(SkillType.WOODCUTTING);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Abilities
|
* Abilities
|
||||||
*/
|
*/
|
||||||
|
@ -16,6 +16,7 @@ import com.gmail.nossr50.skills.smelting.SmeltingManager;
|
|||||||
import com.gmail.nossr50.skills.swords.SwordsManager;
|
import com.gmail.nossr50.skills.swords.SwordsManager;
|
||||||
import com.gmail.nossr50.skills.taming.TamingManager;
|
import com.gmail.nossr50.skills.taming.TamingManager;
|
||||||
import com.gmail.nossr50.skills.unarmed.UnarmedManager;
|
import com.gmail.nossr50.skills.unarmed.UnarmedManager;
|
||||||
|
import com.gmail.nossr50.skills.woodcutting.WoodcuttingManager;
|
||||||
import com.gmail.nossr50.util.StringUtils;
|
import com.gmail.nossr50.util.StringUtils;
|
||||||
|
|
||||||
public enum SkillType {
|
public enum SkillType {
|
||||||
@ -31,7 +32,7 @@ public enum SkillType {
|
|||||||
SWORDS(SwordsManager.class, AbilityType.SERRATED_STRIKES, ToolType.SWORD),
|
SWORDS(SwordsManager.class, AbilityType.SERRATED_STRIKES, ToolType.SWORD),
|
||||||
TAMING(TamingManager.class),
|
TAMING(TamingManager.class),
|
||||||
UNARMED(UnarmedManager.class, AbilityType.BERSERK, ToolType.FISTS),
|
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<? extends SkillManager> managerClass;
|
private Class<? extends SkillManager> managerClass;
|
||||||
private AbilityType ability;
|
private AbilityType ability;
|
||||||
|
@ -20,8 +20,6 @@ import org.bukkit.event.block.BlockPlaceEvent;
|
|||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import com.gmail.nossr50.mcMMO;
|
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.config.HiddenConfig;
|
||||||
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
|
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
|
||||||
import com.gmail.nossr50.datatypes.skills.AbilityType;
|
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.repair.Repair;
|
||||||
import com.gmail.nossr50.skills.smelting.SmeltingManager;
|
import com.gmail.nossr50.skills.smelting.SmeltingManager;
|
||||||
import com.gmail.nossr50.skills.unarmed.Unarmed;
|
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.BlockUtils;
|
||||||
import com.gmail.nossr50.util.ItemUtils;
|
import com.gmail.nossr50.util.ItemUtils;
|
||||||
import com.gmail.nossr50.util.Misc;
|
import com.gmail.nossr50.util.Misc;
|
||||||
@ -179,18 +177,13 @@ public class BlockListener implements Listener {
|
|||||||
|
|
||||||
/* WOOD CUTTING */
|
/* WOOD CUTTING */
|
||||||
else if (BlockUtils.isLog(blockState) && Permissions.skillEnabled(player, SkillType.WOODCUTTING) && !mcMMO.placeStore.isTrue(blockState)) {
|
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)) {
|
WoodcuttingManager woodcuttingManager = mcMMOPlayer.getWoodcuttingManager();
|
||||||
Woodcutting.beginTreeFeller(blockState, player);
|
|
||||||
|
if (woodcuttingManager.canUseTreeFeller(heldItem)) {
|
||||||
|
woodcuttingManager.processTreeFeller(blockState);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (Config.getInstance().getWoodcuttingRequiresTool()) {
|
woodcuttingManager.woodcuttingBlockCheck(blockState);
|
||||||
if (ItemUtils.isAxe(heldItem)) {
|
|
||||||
Woodcutting.beginWoodcutting(player, blockState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Woodcutting.beginWoodcutting(player, blockState);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,18 +360,10 @@ public class BlockListener implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((mcMMOPlayer.getProfile().getSkillLevel(SkillType.WOODCUTTING) >= AdvancedConfig.getInstance().getLeafBlowUnlockLevel()) && BlockUtils.isLeaves(blockState)) {
|
else if (BlockUtils.isLeaves(blockState)) {
|
||||||
if (SkillUtils.triggerCheck(player, block, AbilityType.LEAF_BLOWER)) {
|
if (UserManager.getPlayer(player).getWoodcuttingManager().canUseLeafBlower(heldItem) && SkillUtils.blockBreakSimulate(block, player, true)) {
|
||||||
if (Config.getInstance().getWoodcuttingRequiresTool()) {
|
|
||||||
if (ItemUtils.isAxe(heldItem)) {
|
|
||||||
event.setInstaBreak(true);
|
event.setInstaBreak(true);
|
||||||
Woodcutting.beginLeafBlower(player, blockState);
|
player.playSound(blockState.getLocation(), Sound.ITEM_PICKUP, Misc.POP_VOLUME, Misc.POP_PITCH);
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!(heldItem.getType() == Material.SHEARS)) {
|
|
||||||
event.setInstaBreak(true);
|
|
||||||
Woodcutting.beginLeafBlower(player, blockState);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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<BlockState> treeFellerBlocks = new ArrayList<BlockState>();
|
|
||||||
|
|
||||||
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<BlockState> treeFellerBlocks) {
|
|
||||||
if (!BlockUtils.isLog(blockState)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<BlockState> futureCenterBlocks = new ArrayList<BlockState>();
|
|
||||||
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<BlockState> treeFellerBlocks) {
|
|
||||||
if (!BlockUtils.isLog(blockState)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<BlockState> futureCenterBlocks = new ArrayList<BlockState>();
|
|
||||||
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<BlockState> futureCenterBlocks, List<BlockState> 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<BlockState> 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<BlockState> 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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +1,12 @@
|
|||||||
package com.gmail.nossr50.skills.woodcutting;
|
package com.gmail.nossr50.skills.woodcutting;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.Sound;
|
|
||||||
import org.bukkit.block.BlockState;
|
import org.bukkit.block.BlockState;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.enchantments.Enchantment;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.material.Tree;
|
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.AdvancedConfig;
|
||||||
import com.gmail.nossr50.config.Config;
|
import com.gmail.nossr50.config.Config;
|
||||||
import com.gmail.nossr50.datatypes.mods.CustomBlock;
|
import com.gmail.nossr50.datatypes.mods.CustomBlock;
|
||||||
import com.gmail.nossr50.datatypes.skills.SkillType;
|
import com.gmail.nossr50.util.BlockUtils;
|
||||||
import com.gmail.nossr50.events.fake.FakePlayerAnimationEvent;
|
|
||||||
import com.gmail.nossr50.util.Misc;
|
import com.gmail.nossr50.util.Misc;
|
||||||
import com.gmail.nossr50.util.ModUtils;
|
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 final class Woodcutting {
|
||||||
public static int doubleDropsMaxLevel = AdvancedConfig.getInstance().getWoodcuttingDoubleDropMaxLevel();
|
public static int doubleDropsMaxLevel = AdvancedConfig.getInstance().getWoodcuttingDoubleDropMaxLevel();
|
||||||
public static double doubleDropsMaxChance = AdvancedConfig.getInstance().getWoodcuttingDoubleDropChance();
|
public static double doubleDropsMaxChance = AdvancedConfig.getInstance().getWoodcuttingDoubleDropChance();
|
||||||
|
|
||||||
|
public static int leafBlowerUnlockLevel = AdvancedConfig.getInstance().getLeafBlowUnlockLevel();
|
||||||
|
public static int treeFellerThreshold = Config.getInstance().getTreeFellerThreshold();
|
||||||
|
|
||||||
protected enum ExperienceGainMethod {
|
protected enum ExperienceGainMethod {
|
||||||
DEFAULT,
|
DEFAULT,
|
||||||
TREE_FELLER,
|
TREE_FELLER,
|
||||||
@ -31,47 +32,6 @@ public final class Woodcutting {
|
|||||||
|
|
||||||
private 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
|
* Retrieves the experience reward from a log
|
||||||
*
|
*
|
||||||
@ -126,11 +86,7 @@ public final class Woodcutting {
|
|||||||
* @param mcMMOPlayer Player breaking the block
|
* @param mcMMOPlayer Player breaking the block
|
||||||
* @param blockState Block being broken
|
* @param blockState Block being broken
|
||||||
*/
|
*/
|
||||||
protected static void checkForDoubleDrop(Player player, BlockState blockState) {
|
protected static void checkForDoubleDrop(BlockState blockState) {
|
||||||
if (!SkillUtils.activationSuccessful(player, SkillType.WOODCUTTING, doubleDropsMaxChance, doubleDropsMaxLevel)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ModUtils.isCustomLogBlock(blockState)) {
|
if (ModUtils.isCustomLogBlock(blockState)) {
|
||||||
CustomBlock customBlock = ModUtils.getCustomBlock(blockState);
|
CustomBlock customBlock = ModUtils.getCustomBlock(blockState);
|
||||||
int minimumDropAmount = customBlock.getMinimumDropAmount();
|
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<BlockState> treeFellerBlocks) {
|
||||||
|
List<BlockState> futureCenterBlocks = new ArrayList<BlockState>();
|
||||||
|
|
||||||
|
// 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<BlockState> treeFellerBlocks) {
|
||||||
|
List<BlockState> futureCenterBlocks = new ArrayList<BlockState>();
|
||||||
|
|
||||||
|
// 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<BlockState> 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<BlockState> futureCenterBlocks, List<BlockState> 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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<BlockState> treeFellerBlocks = new ArrayList<BlockState>();
|
||||||
|
|
||||||
|
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<BlockState> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user