2012-01-09 20:00:13 +01:00
|
|
|
package com.gmail.nossr50.skills;
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
2012-03-26 17:04:17 +02:00
|
|
|
import java.util.Random;
|
2012-03-02 20:22:29 +01:00
|
|
|
|
2012-01-09 20:00:13 +01:00
|
|
|
import org.bukkit.Material;
|
2012-03-16 16:30:23 +01:00
|
|
|
import org.bukkit.TreeSpecies;
|
2012-01-09 20:00:13 +01:00
|
|
|
import org.bukkit.block.Block;
|
|
|
|
import org.bukkit.entity.Player;
|
|
|
|
import org.bukkit.inventory.ItemStack;
|
2012-03-16 18:33:03 +01:00
|
|
|
import org.bukkit.material.Tree;
|
2012-02-23 05:23:42 +01:00
|
|
|
import org.bukkit.event.block.BlockBreakEvent;
|
2012-03-02 20:01:09 +01:00
|
|
|
|
|
|
|
import com.gmail.nossr50.Combat;
|
2012-01-09 20:00:13 +01:00
|
|
|
import com.gmail.nossr50.Users;
|
|
|
|
import com.gmail.nossr50.m;
|
2012-04-21 20:05:39 +02:00
|
|
|
import com.gmail.nossr50.mcMMO;
|
2012-03-20 03:05:17 +01:00
|
|
|
import com.gmail.nossr50.mcPermissions;
|
2012-04-26 16:27:57 +02:00
|
|
|
import com.gmail.nossr50.config.Config;
|
2012-01-09 20:00:13 +01:00
|
|
|
import com.gmail.nossr50.datatypes.PlayerProfile;
|
|
|
|
import com.gmail.nossr50.datatypes.SkillType;
|
2012-03-27 05:01:51 +02:00
|
|
|
import com.gmail.nossr50.events.fake.FakePlayerAnimationEvent;
|
2012-01-09 20:00:13 +01:00
|
|
|
import com.gmail.nossr50.locale.mcLocale;
|
2012-03-21 03:33:58 +01:00
|
|
|
import com.gmail.nossr50.spout.SpoutSounds;
|
2012-02-23 08:12:24 +01:00
|
|
|
|
2012-02-04 07:59:31 +01:00
|
|
|
import org.getspout.spoutapi.sound.SoundEffect;
|
2012-01-09 20:00:13 +01:00
|
|
|
|
2012-03-15 22:29:27 +01:00
|
|
|
public class WoodCutting {
|
2012-01-09 20:00:13 +01:00
|
|
|
|
2012-03-26 17:04:17 +02:00
|
|
|
private static Random random = new Random();
|
|
|
|
|
2012-03-15 22:29:27 +01:00
|
|
|
/**
|
|
|
|
* Handle the Tree Feller ability.
|
|
|
|
*
|
|
|
|
* @param event Event to modify
|
|
|
|
*/
|
|
|
|
public static void treeFeller(BlockBreakEvent event) {
|
2012-02-23 05:23:42 +01:00
|
|
|
Player player = event.getPlayer();
|
|
|
|
Block firstBlock = event.getBlock();
|
|
|
|
PlayerProfile PP = Users.getProfile(player);
|
|
|
|
ArrayList<Block> toBeFelled = new ArrayList<Block>();
|
2012-03-16 16:30:23 +01:00
|
|
|
|
|
|
|
/* NOTE: Tree Feller will cut upwards like how you actually fell trees */
|
2012-03-15 22:29:27 +01:00
|
|
|
processTreeFelling(firstBlock, toBeFelled);
|
|
|
|
removeBlocks(toBeFelled, player, PP);
|
2012-02-23 05:23:42 +01:00
|
|
|
}
|
2012-03-16 16:30:23 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Handles removing & dropping the blocks from Tree Feller.
|
|
|
|
*
|
|
|
|
* @param toBeFelled List of Blocks to be removed from the tree
|
|
|
|
* @param player The player using the ability
|
|
|
|
* @param PP The PlayerProfile of the player
|
|
|
|
*/
|
|
|
|
private static void removeBlocks(ArrayList<Block> toBeFelled, Player player, PlayerProfile PP) {
|
2012-04-27 05:58:21 +02:00
|
|
|
if (toBeFelled.size() >= Config.getInstance().getTreeFellerThreshold()) {
|
2012-04-24 15:21:21 +02:00
|
|
|
player.sendMessage(mcLocale.getString("Woodcutting.Skills.TreeFellerThreshold"));
|
2012-02-24 10:46:34 +01:00
|
|
|
return;
|
|
|
|
}
|
2012-03-16 16:30:23 +01:00
|
|
|
|
2012-03-28 20:37:17 +02:00
|
|
|
int durabilityLoss = durabilityLossCalulate(toBeFelled);
|
2012-03-16 16:30:23 +01:00
|
|
|
int xp = 0;
|
|
|
|
ItemStack inHand = player.getItemInHand();
|
|
|
|
|
|
|
|
/* Damage the tool */
|
|
|
|
inHand.setDurability((short) (inHand.getDurability() + durabilityLoss));
|
|
|
|
|
|
|
|
/* This is to prevent using wood axes everytime you tree fell */
|
|
|
|
if ((inHand.getDurability() + durabilityLoss >= inHand.getType().getMaxDurability()) || inHand.getType().equals(Material.AIR)) {
|
2012-04-24 15:21:21 +02:00
|
|
|
player.sendMessage(mcLocale.getString("Woodcutting.Skills.TreeFeller.Splinter"));
|
2012-03-16 16:30:23 +01:00
|
|
|
|
|
|
|
int health = player.getHealth();
|
|
|
|
|
|
|
|
if (health >= 2) {
|
2012-03-26 17:04:17 +02:00
|
|
|
Combat.dealDamage(player, random.nextInt(health - 1));
|
2012-03-16 16:30:23 +01:00
|
|
|
}
|
2012-03-02 20:01:09 +01:00
|
|
|
return;
|
|
|
|
}
|
2012-03-16 16:30:23 +01:00
|
|
|
|
2012-02-24 10:46:34 +01:00
|
|
|
//Prepare ItemStacks
|
2012-03-16 16:30:23 +01:00
|
|
|
ItemStack item = null;
|
2012-03-16 18:45:30 +01:00
|
|
|
ItemStack oak = new ItemStack(Material.LOG, 1, (short) 0, TreeSpecies.GENERIC.getData());
|
|
|
|
ItemStack spruce = new ItemStack(Material.LOG, 1, (short) 0, TreeSpecies.REDWOOD.getData());
|
|
|
|
ItemStack birch = new ItemStack(Material.LOG, 1, (short) 0, TreeSpecies.BIRCH.getData());
|
|
|
|
ItemStack jungle = new ItemStack(Material.LOG, 1, (short) 0, TreeSpecies.JUNGLE.getData());
|
2012-02-23 08:42:03 +01:00
|
|
|
|
2012-03-16 16:30:23 +01:00
|
|
|
for (Block x : toBeFelled) {
|
|
|
|
if (m.blockBreakSimulate(x, player, true)) {
|
|
|
|
if (x.getType() == Material.LOG) {
|
2012-03-16 18:33:03 +01:00
|
|
|
Tree tree = (Tree) x.getState().getData();
|
|
|
|
TreeSpecies species = tree.getSpecies();
|
2012-03-16 16:30:23 +01:00
|
|
|
|
|
|
|
switch (species) {
|
|
|
|
case GENERIC:
|
2012-02-24 10:46:34 +01:00
|
|
|
item = oak;
|
|
|
|
break;
|
2012-03-16 16:30:23 +01:00
|
|
|
|
|
|
|
case REDWOOD:
|
2012-02-24 10:46:34 +01:00
|
|
|
item = spruce;
|
|
|
|
break;
|
2012-03-16 16:30:23 +01:00
|
|
|
|
|
|
|
case BIRCH:
|
2012-02-24 10:46:34 +01:00
|
|
|
item = birch;
|
|
|
|
break;
|
2012-03-16 16:30:23 +01:00
|
|
|
|
|
|
|
case JUNGLE:
|
2012-02-24 10:46:34 +01:00
|
|
|
item = jungle;
|
|
|
|
break;
|
2012-03-16 16:30:23 +01:00
|
|
|
|
2012-02-24 10:46:34 +01:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2012-03-16 16:30:23 +01:00
|
|
|
|
|
|
|
if (!x.hasMetadata("mcmmoPlacedBlock")) {
|
2012-02-23 10:34:34 +01:00
|
|
|
WoodCutting.woodCuttingProcCheck(player, x);
|
2012-03-16 16:30:23 +01:00
|
|
|
|
|
|
|
switch (species) {
|
|
|
|
case GENERIC:
|
2012-04-27 05:58:21 +02:00
|
|
|
xp += Config.getInstance().getWoodcuttingXPOak();
|
2012-02-23 10:34:34 +01:00
|
|
|
break;
|
2012-03-16 16:30:23 +01:00
|
|
|
|
|
|
|
case REDWOOD:
|
2012-04-27 05:58:21 +02:00
|
|
|
xp += Config.getInstance().getWoodcuttingXPSpruce();
|
2012-02-23 10:34:34 +01:00
|
|
|
break;
|
2012-03-16 16:30:23 +01:00
|
|
|
|
|
|
|
case BIRCH:
|
2012-04-27 05:58:21 +02:00
|
|
|
xp += Config.getInstance().getWoodcuttingXPBirch();
|
2012-02-23 10:34:34 +01:00
|
|
|
break;
|
2012-03-16 16:30:23 +01:00
|
|
|
|
|
|
|
case JUNGLE:
|
2012-04-27 05:58:21 +02:00
|
|
|
xp += Config.getInstance().getWoodcuttingXPJungle() / 4; //Nerf XP from Jungle Trees when using Tree Feller
|
2012-03-16 16:30:23 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2012-02-24 10:46:34 +01:00
|
|
|
break;
|
2012-02-23 05:23:42 +01:00
|
|
|
}
|
2012-02-23 10:34:34 +01:00
|
|
|
}
|
2012-03-16 16:30:23 +01:00
|
|
|
|
|
|
|
/* Remove the block */
|
|
|
|
x.setData((byte) 0x0);
|
2012-02-23 10:34:34 +01:00
|
|
|
x.setType(Material.AIR);
|
2012-03-16 16:30:23 +01:00
|
|
|
|
|
|
|
/* Drop the block */
|
|
|
|
m.mcDropItem(x.getLocation(), item);
|
|
|
|
}
|
|
|
|
else if (x.getType() == Material.LEAVES) {
|
2012-03-22 21:36:54 +01:00
|
|
|
final int SAPLING_DROP_CHANCE = 10;
|
2012-03-16 16:30:23 +01:00
|
|
|
|
2012-03-16 18:33:03 +01:00
|
|
|
item = new ItemStack(Material.SAPLING, 1, (short) 0, (byte) (x.getData() & 3)); //Drop the right type of sapling
|
|
|
|
m.mcRandomDropItem(x.getLocation(), item, SAPLING_DROP_CHANCE);
|
2012-03-16 16:30:23 +01:00
|
|
|
|
2012-02-23 10:34:34 +01:00
|
|
|
//Remove the block
|
|
|
|
x.setData((byte) 0);
|
|
|
|
x.setType(Material.AIR);
|
2012-02-23 05:23:42 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-03-16 16:30:23 +01:00
|
|
|
|
2012-03-29 20:24:41 +02:00
|
|
|
PP.addXP(SkillType.WOODCUTTING, xp); //Tree Feller gives nerf'd XP
|
2012-02-23 10:59:00 +01:00
|
|
|
Skills.XpCheckSkill(SkillType.WOODCUTTING, player);
|
2012-02-23 05:23:42 +01:00
|
|
|
}
|
2012-03-16 16:30:23 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if the block is affected by Tree Feller.
|
|
|
|
*
|
|
|
|
* @param block Block to check
|
|
|
|
* @return true if the block is affected by Tree Feller, false otherwise
|
|
|
|
*/
|
|
|
|
private static boolean treeFellerCompatible(Block block) {
|
|
|
|
switch (block.getType()) {
|
|
|
|
case LOG:
|
|
|
|
case LEAVES:
|
|
|
|
case AIR:
|
|
|
|
return true;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
2012-02-23 05:23:42 +01:00
|
|
|
}
|
2012-03-16 16:30:23 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle the calculations from Tree Feller.
|
|
|
|
*
|
|
|
|
* @param currentBlock The current block to be removed
|
|
|
|
* @param toBeFelled The list of blocks left to be removed
|
|
|
|
*/
|
|
|
|
private static void processTreeFelling(Block currentBlock, ArrayList<Block> toBeFelled) {
|
|
|
|
Material type = currentBlock.getType();
|
2012-04-18 21:53:02 +02:00
|
|
|
|
2012-04-27 05:58:21 +02:00
|
|
|
if(toBeFelled.size() >= Config.getInstance().getTreeFellerThreshold()) {
|
2012-04-18 21:53:02 +02:00
|
|
|
return;
|
|
|
|
}
|
2012-03-16 16:30:23 +01:00
|
|
|
|
|
|
|
if (type.equals(Material.LOG) || type.equals(Material.LEAVES)) {
|
2012-02-24 10:46:34 +01:00
|
|
|
toBeFelled.add(currentBlock);
|
2012-03-16 16:30:23 +01:00
|
|
|
}
|
|
|
|
|
2012-03-15 05:52:37 +01:00
|
|
|
Block xPositive = currentBlock.getRelative(1, 0, 0);
|
|
|
|
Block xNegative = currentBlock.getRelative(-1, 0, 0);
|
|
|
|
Block zPositive = currentBlock.getRelative(0, 0, 1);
|
|
|
|
Block zNegative = currentBlock.getRelative(0, 0, -1);
|
|
|
|
Block yPositive = currentBlock.getRelative(0, 1, 0);
|
2012-03-16 16:30:23 +01:00
|
|
|
|
|
|
|
if (!currentBlock.hasMetadata("mcmmoPlacedBlock")) {
|
|
|
|
if (!isTooAggressive(currentBlock, xPositive) && treeFellerCompatible(xPositive) && !toBeFelled.contains(xPositive)) {
|
|
|
|
processTreeFelling(xPositive, toBeFelled);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isTooAggressive(currentBlock, xNegative) && treeFellerCompatible(xNegative) && !toBeFelled.contains(xNegative)) {
|
|
|
|
processTreeFelling(xNegative, toBeFelled);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isTooAggressive(currentBlock, zPositive) && treeFellerCompatible(zPositive) && !toBeFelled.contains(zPositive)) {
|
|
|
|
processTreeFelling(zPositive, toBeFelled);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isTooAggressive(currentBlock, zNegative) && treeFellerCompatible(zNegative) && !toBeFelled.contains(zNegative)) {
|
|
|
|
processTreeFelling(zNegative, toBeFelled);
|
|
|
|
}
|
2012-03-28 20:37:17 +02:00
|
|
|
}
|
2012-03-16 16:30:23 +01:00
|
|
|
|
2012-03-28 20:37:17 +02:00
|
|
|
if (treeFellerCompatible(yPositive)) {
|
|
|
|
if(!currentBlock.hasMetadata("mcmmoPlacedBlock") && !toBeFelled.contains(yPositive)) {
|
2012-03-15 22:29:27 +01:00
|
|
|
processTreeFelling(yPositive, toBeFelled);
|
2012-02-23 05:23:42 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-03-16 16:30:23 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if Tree Feller is being too aggressive.
|
|
|
|
*
|
|
|
|
* @param currentBlock The current block being felled
|
|
|
|
* @param newBlock The next block to be felled
|
|
|
|
* @return true if Tree Feller is too aggressive, false otherwise
|
|
|
|
*/
|
|
|
|
private static boolean isTooAggressive(Block currentBlock, Block newBlock) {
|
|
|
|
Material currentType = currentBlock.getType();
|
|
|
|
Material newType = currentBlock.getType();
|
|
|
|
|
|
|
|
if ((currentType.equals(Material.LEAVES) || currentType.equals(Material.AIR)) && (newType.equals(Material.LEAVES) || newType.equals(Material.AIR))) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return false;
|
|
|
|
}
|
2012-02-23 05:53:20 +01:00
|
|
|
}
|
2012-03-16 16:30:23 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Check for double drops.
|
|
|
|
*
|
|
|
|
* @param player Player breaking the block
|
|
|
|
* @param block The block being broken
|
|
|
|
*/
|
|
|
|
private static void woodCuttingProcCheck(Player player, Block block) {
|
|
|
|
final int MAX_SKILL_LEVEL = 1000;
|
|
|
|
|
|
|
|
int skillLevel = Users.getProfile(player).getSkillLevel(SkillType.WOODCUTTING);
|
|
|
|
byte type = block.getData();
|
|
|
|
Material mat = Material.getMaterial(block.getTypeId());
|
|
|
|
|
2012-03-26 17:04:17 +02:00
|
|
|
if ((skillLevel > MAX_SKILL_LEVEL || random.nextInt(1000) <= skillLevel) && mcPermissions.getInstance().woodcuttingDoubleDrops(player)) {
|
2012-03-16 16:30:23 +01:00
|
|
|
ItemStack item = new ItemStack(mat, 1, (short) 0, type);
|
|
|
|
m.mcDropItem(block.getLocation(), item);
|
|
|
|
}
|
2012-01-09 20:00:13 +01:00
|
|
|
}
|
2012-03-16 16:30:23 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Check XP gain for woodcutting.
|
|
|
|
*
|
|
|
|
* @param player The player breaking the block
|
|
|
|
* @param block The block being broken
|
|
|
|
*/
|
|
|
|
public static void woodcuttingBlockCheck(Player player, Block block) {
|
|
|
|
PlayerProfile PP = Users.getProfile(player);
|
|
|
|
int xp = 0;
|
|
|
|
TreeSpecies species = TreeSpecies.getByData(block.getData());
|
|
|
|
|
2012-03-23 04:33:11 +01:00
|
|
|
if (block.hasMetadata("mcmmoPlacedBlock")) {
|
2012-03-16 16:30:23 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (species) {
|
|
|
|
case GENERIC:
|
2012-04-27 05:58:21 +02:00
|
|
|
xp += Config.getInstance().getWoodcuttingXPOak();
|
2012-03-16 16:30:23 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case REDWOOD:
|
2012-04-27 05:58:21 +02:00
|
|
|
xp += Config.getInstance().getWoodcuttingXPSpruce();
|
2012-03-16 16:30:23 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case BIRCH:
|
2012-04-27 05:58:21 +02:00
|
|
|
xp += Config.getInstance().getWoodcuttingXPBirch();
|
2012-03-16 16:30:23 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case JUNGLE:
|
2012-04-27 05:58:21 +02:00
|
|
|
xp += Config.getInstance().getWoodcuttingXPJungle();
|
2012-03-16 16:30:23 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
WoodCutting.woodCuttingProcCheck(player, block);
|
2012-03-29 20:24:41 +02:00
|
|
|
PP.addXP(SkillType.WOODCUTTING, xp);
|
2012-03-16 16:30:23 +01:00
|
|
|
Skills.XpCheckSkill(SkillType.WOODCUTTING, player);
|
2012-02-04 06:22:10 +01:00
|
|
|
}
|
2012-03-16 16:30:23 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle the Leaf Blower ability.
|
|
|
|
*
|
|
|
|
* @param player Player using the ability
|
|
|
|
* @param block Block being broken
|
|
|
|
*/
|
|
|
|
public static void leafBlower(Player player, Block block) {
|
2012-03-27 05:01:51 +02:00
|
|
|
FakePlayerAnimationEvent armswing = new FakePlayerAnimationEvent(player);
|
2012-04-21 20:05:39 +02:00
|
|
|
mcMMO.p.getServer().getPluginManager().callEvent(armswing);
|
2012-03-16 16:30:23 +01:00
|
|
|
|
2012-04-27 05:58:21 +02:00
|
|
|
if (Config.getInstance().getWoodcuttingRequiresTool()) {
|
|
|
|
Skills.abilityDurabilityLoss(player.getItemInHand(), Config.getInstance().getAbilityToolDamage());
|
2012-03-16 16:30:23 +01:00
|
|
|
}
|
|
|
|
|
2012-04-27 05:58:21 +02:00
|
|
|
if (Config.getInstance().spoutEnabled) {
|
2012-03-21 03:33:58 +01:00
|
|
|
SpoutSounds.playSoundForPlayer(SoundEffect.POP, player, block.getLocation());
|
2012-03-16 16:30:23 +01:00
|
|
|
}
|
2012-02-04 07:36:03 +01:00
|
|
|
}
|
2012-03-28 20:37:17 +02:00
|
|
|
|
|
|
|
private static int durabilityLossCalulate(ArrayList<Block> toBeFelled) {
|
|
|
|
int durabilityLoss = 0;
|
|
|
|
for (Block x : toBeFelled) {
|
|
|
|
if (x.getType().equals(Material.LOG)) {
|
|
|
|
durabilityLoss++;
|
2012-04-27 05:58:21 +02:00
|
|
|
durabilityLoss = durabilityLoss + Config.getInstance().getAbilityToolDamage();
|
2012-03-28 20:37:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return durabilityLoss;
|
|
|
|
}
|
2012-01-09 20:00:13 +01:00
|
|
|
}
|