package bspkrs.treecapitator; import java.util.ArrayList; import java.util.List; import net.minecraft.src.Block; import net.minecraft.src.BlockLeavesBase; import net.minecraft.src.BlockLog; import net.minecraft.src.BlockVine; import net.minecraft.src.EntityPlayer; import net.minecraft.src.ItemStack; import net.minecraft.src.World; import bspkrs.util.*; public class BlockTree extends BlockLog { private EntityPlayer player; private boolean shouldFell; private Coord startPos; private float axeDamage; private int currentAxeDamage; private ItemStack axe; private float shearDamage; private int currentShearDamage; private ItemStack shears; public BlockTree(int i) { super(i); setHardness(TreeCapitator.logHardnessNormal); setStepSound(Block.soundWoodFootstep); setBlockName("log"); setRequiresSelfNotify(); shouldFell = false; } /** * Called when the block is clicked by a player. Args: x, y, z, entityPlayer */ @Override public void onBlockClicked(World world, int x, int y, int z, EntityPlayer entityPlayer) { player = entityPlayer; shouldFell = false; if ((!TreeCapitator.needItem || isAxeItemEquipped(entityPlayer)) && !world.isRemote) { blockHardness = TreeCapitator.logHardnessModified; if(axe != null) currentAxeDamage = axe.getMaxDamage() + 1 - axe.getItemDamage(); else currentAxeDamage = 0; shouldFell = true; if(!entityPlayer.capabilities.isCreativeMode && TreeCapitator.allowItemDamage && axe != null && currentAxeDamage <= 1) shouldFell = false; } else { blockHardness = TreeCapitator.logHardnessNormal; } } /** * Called when the block is attempted to be harvested */ @Override public void onBlockHarvested(World world, int x, int y, int z, int md, EntityPlayer entityPlayer) { player = entityPlayer; startPos = new Coord(x, y, z); if(((TreeCapitator.sneakAction.equalsIgnoreCase("enable") && player.isSneaking()) || (!TreeCapitator.sneakAction.toLowerCase().contains("enable") && !player.isSneaking())) && !world.isRemote && !(player.capabilities.isCreativeMode && TreeCapitator.disableInCreative)) { Coord topLog = getTopLog(world, new Coord(x, y, z)); if (leavesAround(world, topLog) > 2 && shouldFell) { List listFinal = new ArrayList(); List logs = addLogs(world, new Coord(x, y, z)); addLogsAbove(world, new Coord(x, y, z), listFinal); destroyBlocks(world, logs); if (TreeCapitator.destroyLeaves) { for(Coord pos : listFinal) { List leaves = addLeaves(world, pos); removeLeavesWithLogsAround(world, leaves); destroyBlocksWithChance(world, leaves, 0.5F, playerHasShearsInHotbar(player)); } } } } } public Coord getTopLog(World world, Coord pos) { while(world.getBlockId(pos.x, pos.y + 1, pos.z) == blockID) pos.y++; return pos; } public int leavesAround(World world, Coord pos) { int i = 0; for (int x = -1; x <= 1; x++) { for (int y = -1; y <= 1; y++) { for (int z = -1; z <= 1; z++) { if (x != 0 || y != 0 || z != 0) { Block block = Block.blocksList[world.getBlockId(pos.x + x, pos.y + y, pos.z + z)]; if (block != null && (block instanceof BlockLeavesBase)) i++; } } } } return i; } /** * Defines whether or not a player can break the block with current tool and sets the local axe object if possible */ private boolean isAxeItemEquipped(EntityPlayer entityPlayer) { ItemStack item = entityPlayer.getCurrentEquippedItem(); if(item != null && CommonUtils.isItemInList(item.itemID, item.getItemDamage(), TreeCapitator.axeIDList)) { axe = item; return true; } else { axe = null; return false; } } /** * Defines whether or not a player has a shear-type item in the hotbar */ private boolean playerHasShearsInHotbar(EntityPlayer entityplayer) { return shearsHotbarIndex(entityplayer) != -1; } /** * Returns the index of the left-most shear-type item in the hotbar and sets the local shears object if possible */ private int shearsHotbarIndex(EntityPlayer entityPlayer) { for(int i = 0; i < 9; i++) { ItemStack item = entityPlayer.inventory.mainInventory[i]; if(item != null && CommonUtils.isItemInList(item.itemID, item.getItemDamage(), TreeCapitator.shearIDList)) { shears = item; return i; } } shears = null; return -1; } private void destroyBlocks(World world, List list) { destroyBlocksWithChance(world, list, 1.0F, false); } private void destroyBlocksWithChance(World world, List list, float f, boolean canShear) { while (list.size() > 0) { Coord pos = list.remove(0); int id = world.getBlockId(pos.x, pos.y, pos.z); if(id != 0) { Block block = Block.blocksList[id]; int metadata = world.getBlockMetadata(pos.x, pos.y, pos.z); world.setBlockWithNotify(pos.x, pos.y, pos.z, 0); if((((block instanceof BlockVine && TreeCapitator.shearVines) || (block instanceof BlockLeavesBase && TreeCapitator.shearLeaves)) && canShear) && !(player.capabilities.isCreativeMode && TreeCapitator.disableCreativeDrops)) { dropBlockAsItem_do(world, pos.x, pos.y, pos.z, new ItemStack(id, 1, metadata & 0x03)); } else if(!(player.capabilities.isCreativeMode && TreeCapitator.disableCreativeDrops)) { block.dropBlockAsItem(world, pos.x, pos.y, pos.z, metadata, 0); } } } } public List addLogs(World world, Coord pos) { int index = 0, lowY = pos.y, x, y, z; List list = new ArrayList(); Coord newPos; list.add(pos); do { Coord currentLog = list.get(index); for (x = -1; x <= 1; x++) { for (y = -1; y <= 1; y++) { for (z = -1; z <= 1; z++) { if (world.getBlockId(currentLog.x + x, currentLog.y + y, currentLog.z + z) == this.blockID) { newPos = new Coord(currentLog.x + x, currentLog.y + y, currentLog.z + z); if(TreeCapitator.maxBreakDistance == -1 || (Math.abs(newPos.x - startPos.x) <= TreeCapitator.maxBreakDistance && Math.abs(newPos.z - startPos.z) <= TreeCapitator.maxBreakDistance)) if (!list.contains(newPos) && (newPos.y >= lowY || !TreeCapitator.onlyDestroyUpwards)) list.add(newPos); } } } } } while (++index < list.size()); return list; } private void addLogsAbove(World world, Coord position, List listFinal) { List listAbove = new ArrayList(); List list; Coord newPosition; int counter, index, x, z; listAbove.add(position); do { list = listAbove; listAbove = new ArrayList(); for (Coord pos : list) { counter = 0; for (x = -1; x <= 1; x++) { for (z = -1; z <= 1; z++) { if (world.getBlockId(pos.x + x, pos.y + 1, pos.z + z) == this.blockID) { if (!listAbove.contains(newPosition = new Coord(pos.x + x, pos.y + 1, pos.z + z))) { listAbove.add(newPosition); } counter++; } } } if (counter == 0) { listFinal.add(pos.clone()); } } index = -1; while (++index < listAbove.size()) { Coord pos = listAbove.get(index); for (x = -1; x <= 1; x++) { for (z = -1; z <= 1; z++) { if (world.getBlockId(pos.x + x, pos.y, pos.z + z) == this.blockID) { if (!listAbove.contains(newPosition = new Coord(pos.x + x, pos.y, pos.z + z))) { listAbove.add(newPosition); } } } } } } while (listAbove.size() > 0); } public List addLeaves(World world, Coord pos) { int index = -1; List list = new ArrayList(); addLeavesInDistance(world, pos, 4, list); while (++index < list.size()) { Coord var5 = list.get(index); addLeavesInDistance(world, var5, 1, list); } return list; } public void addLeavesInDistance(World world, Coord pos, int range, List list) { for (int x = -range; x <= range; x++) { for (int y = -range; y <= range; y++) { for (int z = -range; z <= range; z++) { Block block = Block.blocksList[world.getBlockId(x + pos.x, y + pos.y, z + pos.z)]; if (block != null && (block instanceof BlockLeavesBase || block instanceof BlockVine)) { int metadata = world.getBlockMetadata(x + pos.x, y + pos.y, z + pos.z); if ((metadata & 8) != 0 && (metadata & 4) == 0) { Coord newPos = new Coord(x + pos.x, y + pos.y, z + pos.z); if (!list.contains(newPos)) { list.add(newPos); } } } } } } } public void removeLeavesWithLogsAround(World world, List list) { for (int i = 0; i < list.size();) if (hasLogClose(world, list.get(i), 1)) list.remove(i); else i++; } public boolean hasLogClose(World world, Coord pos, int i) { for (int x = -i; x <= i; x++) for (int y = -i; y <= i; y++) for (int z = -i; z <= i; z++) if ((x != 0 || y != 0 || z != 0) && world.getBlockId(x + pos.x, y + pos.y, z + pos.z) == this.blockID) return true; return false; } }