package crazypants.enderio.machine.farm.farmers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import scala.actors.threadpool.Arrays;
import net.minecraft.block.Block;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import net.minecraftforge.common.IPlantable;
import net.minecraftforge.common.IShearable;
import net.minecraftforge.common.util.ForgeDirection;
import com.enderio.core.common.util.BlockCoord;
import crazypants.enderio.config.Config;
import crazypants.enderio.machine.farm.FarmStationContainer;
import crazypants.enderio.machine.farm.TileFarmStation;
public class TreeFarmer implements IFarmerJoe {
private static final HeightComparator comp = new HeightComparator();
protected Block sapling;
protected ItemStack saplingItem;
protected Block[] woods;
protected TreeHarvestUtil harvester = new TreeHarvestUtil();
private boolean ignoreMeta;
public TreeFarmer(Block sapling, Block... wood) {
this.sapling = sapling;
if(sapling != null) {
saplingItem = new ItemStack(sapling);
FarmStationContainer.slotItemsSeeds.add(saplingItem);
}
woods = wood;
for (Block awood : woods) {
FarmStationContainer.slotItemsProduce.add(new ItemStack(awood));
}
}
public TreeFarmer(boolean ignoreMeta, Block sapling, Block... wood) {
this(sapling,wood);
this.ignoreMeta = ignoreMeta;
}
@Override
public boolean canHarvest(TileFarmStation farm, BlockCoord bc, Block block, int meta) {
return isWood(block);
}
protected boolean isWood(Block block) {
for(Block wood : woods) {
if(block == wood) {
return true;
}
}
return false;
}
@Override
public boolean canPlant(ItemStack stack) {
return stack != null && stack.getItem() == saplingItem.getItem();
}
@Override
public boolean prepareBlock(TileFarmStation farm, BlockCoord bc, Block block, int meta) {
if(block == sapling) {
return true;
}
return plantFromInventory(farm, bc, block, meta);
}
protected boolean plantFromInventory(TileFarmStation farm, BlockCoord bc, Block block, int meta) {
World worldObj = farm.getWorldObj();
if(canPlant(worldObj, bc)) {
ItemStack seed = farm.takeSeedFromSupplies(saplingItem, bc, false);
if(seed != null) {
return plant(farm, worldObj, bc, seed);
}
}
return false;
}
protected boolean canPlant(World worldObj, BlockCoord bc) {
Block ground = worldObj.getBlock(bc.x, bc.y - 1, bc.z);
IPlantable plantable = (IPlantable) sapling;
if(sapling.canPlaceBlockAt(worldObj, bc.x, bc.y, bc.z) &&
sapling.canBlockStay(worldObj, bc.x, bc.y, bc.z) &&
ground.canSustainPlant(worldObj, bc.x, bc.y - 1, bc.z, ForgeDirection.UP, plantable)) {
return true;
}
return false;
}
protected boolean plant(TileFarmStation farm, World worldObj, BlockCoord bc, ItemStack seed) {
worldObj.setBlock(bc.x, bc.y, bc.z, Blocks.air, 0, 1 | 2);
if(canPlant(worldObj, bc)) {
worldObj.setBlock(bc.x, bc.y, bc.z, sapling, seed.getItemDamage(), 1 | 2);
farm.actionPerformed(false);
return true;
}
return false;
}
@Override
public IHarvestResult harvestBlock(TileFarmStation farm, BlockCoord bc, Block block, int meta) {
boolean hasAxe = farm.hasAxe();
if(!hasAxe) {
return null;
}
HarvestResult res = new HarvestResult();
harvester.harvest(farm, this, bc, res);
Collections.sort(res.harvestedBlocks, comp);
List<BlockCoord> actualHarvests = new ArrayList<BlockCoord>();
// avoid calling this in a loop
boolean hasShears = farm.hasShears();
int noShearingPercentage = farm.isLowOnSaplings(bc);
int shearCount = 0;
for (int i = 0; i < res.harvestedBlocks.size() && hasAxe; i++) {
BlockCoord coord = res.harvestedBlocks.get(i);
Block blk = farm.getBlock(coord);
ArrayList<ItemStack> drops;
boolean wasSheared = false;
boolean wasAxed = false;
boolean wasWood = isWood(blk);
if (blk instanceof IShearable && hasShears && ((shearCount / res.harvestedBlocks.size() + noShearingPercentage) < 100)) {
drops = ((IShearable)blk).onSheared(null, farm.getWorldObj(), coord.x, coord.y, coord.z, 0);
wasSheared = true;
shearCount += 100;
} else {
drops = blk.getDrops(farm.getWorldObj(), coord.x, coord.y, coord.z, farm.getBlockMeta(coord), farm.getAxeLootingValue());
wasAxed = true;
}
if(drops != null) {
for (ItemStack drop : drops) {
res.drops.add(new EntityItem(farm.getWorldObj(), bc.x + 0.5, bc.y + 0.5, bc.z + 0.5, drop.copy()));
}
}
if (wasAxed && !wasWood) {
wasAxed = Config.farmAxeDamageOnLeafBreak;
int leaveMeta = farm.getBlockMeta(coord);
if(TreeHarvestUtil.canDropApples(blk, leaveMeta)) {
if(farm.getWorldObj().rand.nextInt(200) == 0) {
res.drops.add(new EntityItem(farm.getWorldObj(), bc.x + 0.5, bc.y + 0.5, bc.z + 0.5, new ItemStack(Items.apple)));
}
}
}
farm.actionPerformed(wasWood || wasSheared);
if(wasAxed) {
farm.damageAxe(blk, coord);
hasAxe = farm.hasAxe();
} else if (wasSheared) {
farm.damageShears(blk, coord);
hasShears = farm.hasShears();
}
farm.getWorldObj().setBlockToAir(coord.x, coord.y, coord.z);
actualHarvests.add(coord);
}
if (!hasAxe) {
farm.setNotification(TileFarmStation.NOTIFICATION_NO_AXE);
}
res.harvestedBlocks.clear();
res.harvestedBlocks.addAll(actualHarvests);
return res;
}
public boolean getIgnoreMeta()
{
return ignoreMeta;
}
private static class HeightComparator implements Comparator<BlockCoord> {
@Override
public int compare(BlockCoord o1, BlockCoord o2) {
return compare(o2.y, o1.y); //reverse order
}
//same as 1.7 Integer.compare
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
}
}