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<Coord> listFinal = new ArrayList<Coord>();
List<Coord> 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<Coord> 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<Coord> list)
{
destroyBlocksWithChance(world, list, 1.0F, false);
}
private void destroyBlocksWithChance(World world, List<Coord> 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<Coord> list = new ArrayList<Coord>();
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<Coord> listFinal)
{
List<Coord> listAbove = new ArrayList<Coord>();
List<Coord> list;
Coord newPosition;
int counter, index, x, z;
listAbove.add(position);
do
{
list = listAbove;
listAbove = new ArrayList<Coord>();
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<Coord> addLeaves(World world, Coord pos)
{
int index = -1;
List<Coord> list = new ArrayList<Coord>();
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<Coord> 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;
}
}
Comments