package com.vanhal.progressiveautomation.entities.farmer;
import java.util.List;
import com.vanhal.progressiveautomation.ProgressiveAutomation;
import com.vanhal.progressiveautomation.entities.UpgradeableTileEntity;
import com.vanhal.progressiveautomation.ref.ToolHelper;
import com.vanhal.progressiveautomation.upgrades.UpgradeType;
import com.vanhal.progressiveautomation.util.PlayerFake;
import com.vanhal.progressiveautomation.util.Point2I;
import com.vanhal.progressiveautomation.util.Point3I;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.item.EntityXPOrb;
import net.minecraft.entity.passive.EntityAnimal;
import net.minecraft.entity.passive.EntityCow;
import net.minecraft.init.Items;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.IShearable;
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
public class TileFarmer extends UpgradeableTileEntity {
public int SLOT_FOOD;
public int SLOT_SHEARS;
public int SLOT_BUCKETS;
//time between actions
public int waitTime = 80;
public int currentTime = 0;
protected int searchBlock = -1;
protected PlayerFake faker;
protected int currentAction = 0;
protected AxisAlignedBB boundCheck = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
public TileFarmer() {
super(13);
setUpgradeLevel(ToolHelper.LEVEL_WOOD);
setAllowedUpgrades(UpgradeType.WOODEN, UpgradeType.WITHER, UpgradeType.MILKER, UpgradeType.SHEARING);
//slots
SLOT_UPGRADE = 1;
SLOT_FOOD = 2;
SLOT_SHEARS = 3;
SLOT_BUCKETS = 4;
}
public void setWaitTime(int time) {
this.waitTime = time;
}
public int getCurrentAction() {
return currentAction;
}
@Override
protected void writeSyncOnlyNBT(NBTTagCompound nbt) {
super.writeSyncOnlyNBT(nbt);
nbt.setInteger("currentAction", currentAction);
}
@Override
public void readSyncOnlyNBT(NBTTagCompound nbt) {
super.readSyncOnlyNBT(nbt);
if (nbt.hasKey("currentAction")) currentAction = nbt.getInteger("currentAction");
}
@Override
public void writeCommonNBT(NBTTagCompound nbt) {
super.writeCommonNBT(nbt);
//save the current action time
nbt.setInteger("currentTime", currentTime);
nbt.setInteger("currentBlock", searchBlock);
}
@Override
public void readCommonNBT(NBTTagCompound nbt) {
super.readCommonNBT(nbt);
//load the current action time
if (nbt.hasKey("currentTime")) currentTime = nbt.getInteger("currentTime");
if (nbt.hasKey("currentBlock")) searchBlock = nbt.getInteger("currentBlock");
}
public boolean doSearch() {
if (searchBlock>=0) return true;
//search for any animals that can be fed
if (slots[SLOT_FOOD]!=null) {
for (int i = 0; i < this.getRange(); i++) {
if (findAnimalToFeed(i)!=null) {
searchBlock = i;
addPartialUpdate("currentBlock", searchBlock);
currentAction = 1;
addPartialUpdate("currentAction", currentAction);
return true;
}
}
}
//if we as able to shear then search for animal to shear
if (hasUpgrade(UpgradeType.SHEARING)) {
if (slots[SLOT_SHEARS]!=null) {
for (int i = 0; i < this.getRange(); i++) {
if (findAnimalToShear(i)!=null) {
searchBlock = i;
addPartialUpdate("currentBlock", searchBlock);
currentAction = 2;
addPartialUpdate("currentAction", currentAction);
return true;
}
}
}
}
//if we are able to milk, and have empty containers then see if there is an animal to milk
if (hasUpgrade(UpgradeType.MILKER)) {
if ( (slots[SLOT_BUCKETS]!=null) && (slots[SLOT_BUCKETS].stackSize>0) ) {
for (int i = 0; i < this.getRange(); i++) {
if (findAnimalToMilk(i)!=null) {
searchBlock = i;
addPartialUpdate("currentBlock", searchBlock);
currentAction = 3;
addPartialUpdate("currentAction", currentAction);
return true;
}
}
}
}
currentAction = 0;
addPartialUpdate("currentAction", currentAction);
return false;
}
protected EntityAnimal findAnimalToFeed(int n) {
Point3I point = getPoint(n);
boundCheck = new AxisAlignedBB(point.getX(), point.getY()-1, point.getZ(),
point.getX()+1, point.getY()+2, point.getZ()+1);
List<EntityAnimal> entities = worldObj.getEntitiesWithinAABB(EntityAnimal.class, boundCheck);
if (!entities.isEmpty()) {
for (EntityAnimal animal: entities) {
if ( (slots[SLOT_FOOD]!=null) && (animal.isBreedingItem(slots[SLOT_FOOD])) ) {
if (animal.getGrowingAge() == 0 && !animal.isInLove()) {
return animal;
}
}
}
}
return null;
}
protected EntityAnimal findAnimalToShear(int n) {
if (!hasUpgrade(UpgradeType.SHEARING)) return null;
Point3I point = getPoint(n);
boundCheck = new AxisAlignedBB(point.getX(), point.getY()-1, point.getZ(),
point.getX()+1, point.getY()+2, point.getZ()+1);
List<EntityAnimal> entities = worldObj.getEntitiesWithinAABB(EntityAnimal.class, boundCheck);
if (!entities.isEmpty()) {
for (EntityAnimal animal: entities) {
if ( slots[SLOT_SHEARS]!=null ) {
if (animal instanceof IShearable) {
if (((IShearable)animal).isShearable(slots[SLOT_SHEARS], worldObj, point.toPosition())) {
return animal;
}
}
}
}
}
return null;
}
protected EntityAnimal findAnimalToMilk(int n) {
if (!hasUpgrade(UpgradeType.MILKER)) return null;
Point3I point = getPoint(n);
boundCheck = new AxisAlignedBB(point.getX(), point.getY()-1, point.getZ(),
point.getX()+1, point.getY()+2, point.getZ()+1);
List<EntityAnimal> entities = worldObj.getEntitiesWithinAABB(EntityAnimal.class, boundCheck);
if (!entities.isEmpty()) {
for (EntityAnimal animal: entities) {
if ( (slots[SLOT_BUCKETS]!=null) && (slots[SLOT_BUCKETS].stackSize>0) ) {
if (animal instanceof EntityCow) {
NBTTagCompound cowTag = new NBTTagCompound();
animal.writeEntityToNBT(cowTag);
if (cowTag.hasKey("CurrentUseCooldown")) {
int coolDown = cowTag.getInteger("CurrentUseCooldown");
if (coolDown <= 0) {
return animal;
}
} else if (cowTag.hasKey("NextUseCooldown")) {
int coolDown = cowTag.getInteger("NextUseCooldown");
if (coolDown <= 0) {
return animal;
}
} else {
initFaker();
faker.setItemInHand(slots[SLOT_BUCKETS].copy());
if (animal.processInteract(faker, EnumHand.MAIN_HAND, faker.getHeldItemMainhand())) {
return animal;
}
}
}
}
}
}
return null;
}
public void pickup(int n) {
Point3I point = getPoint(n);
boundCheck = new AxisAlignedBB(point.getX(), point.getY(), point.getZ(),
point.getX()+1, point.getY()+2, point.getZ()+1);
//pick up the drops
List<Entity> entities = worldObj.getEntitiesWithinAABB(Entity.class, boundCheck);
if (!entities.isEmpty()) {
for (Entity item: entities) {
if (item instanceof EntityXPOrb) {
worldObj.removeEntity(item);
} else if (item instanceof EntityItem) {
if (((EntityItem)item).getEntityItem().getItem() == Items.EGG) {
if (roomInInventory(((EntityItem)item).getEntityItem())) {
if (!worldObj.isRemote) addToInventory(((EntityItem)item).getEntityItem());
worldObj.removeEntity(item);
}
}
}
}
}
}
public void doPickup() {
for (int i = 0; i < this.getRange(); i++) {
pickup(i);
}
}
protected Point3I getPoint(int n) {
Point2I p1 = spiral(n+2, pos.getX(), pos.getZ());
return new Point3I(p1.getX(), pos.getY(), p1.getY());
}
@Override
public boolean readyToBurn() {
if (doSearch()) {
return true;
}
return false;
}
protected void initFaker() {
if (faker == null) {
faker = new PlayerFake((WorldServer)worldObj, worldObj.getBlockState(pos).getBlock().getLocalizedName());
faker.setPosition(0, 0, 0);
}
faker.inventory.clear();
}
@Override
public void update() {
super.update();
if (!worldObj.isRemote) {
doPickup();
checkInventory();
// Pause if we're full and told to
if (isFull()) return;
if (isBurning()) {
if (currentTime>0) {
currentTime--;
} else {
if (searchBlock > -1) {
initFaker();
EntityAnimal animal = findAnimalToFeed(searchBlock);
if (animal!=null) feedAnimal(animal);
else {
animal = findAnimalToShear(searchBlock);
if (animal!=null) shearAnimal(animal);
else {
animal = findAnimalToMilk(searchBlock);
if (animal!=null) milkAnimal(animal);
else {
searchBlock = -1;
addPartialUpdate("currentBlock", searchBlock);
}
}
}
} else {
doSearch();
}
}
}
}
}
protected void feedAnimal(EntityAnimal animal) {
if (slots[SLOT_FOOD]!=null) {
animal.setInLove(faker);
slots[SLOT_FOOD].stackSize--;
if (slots[SLOT_FOOD].stackSize==0) slots[SLOT_FOOD] = null;
currentTime = waitTime;
addPartialUpdate("currentTime", currentTime);
}
}
protected void shearAnimal(EntityAnimal animal) {
if ( (slots[SLOT_SHEARS]!=null) && (hasUpgrade(UpgradeType.SHEARING)) ) {
if (animal instanceof IShearable) {
int fortuneLevel = EnchantmentHelper.getEnchantmentLevel(Enchantment.getEnchantmentByLocation("fortune"), slots[SLOT_SHEARS]);
List<ItemStack> items = ((IShearable)animal).onSheared(slots[SLOT_SHEARS], worldObj, pos, fortuneLevel);
//get the drops
for (ItemStack item : items) {
addToInventory(item);
}
if (ToolHelper.damageTool(slots[SLOT_SHEARS], worldObj, pos.getX(), pos.getY(), pos.getZ())) {
destroyTool(SLOT_SHEARS);
}
currentTime = waitTime;
addPartialUpdate("currentTime", currentTime);
}
}
}
protected void milkAnimal(EntityAnimal animal) {
if ( (slots[SLOT_BUCKETS]!=null) && (hasUpgrade(UpgradeType.MILKER)) ) {
initFaker();
ItemStack item = slots[SLOT_BUCKETS].copy();
item.stackSize = 1;
faker.setItemInHand(item);
if (animal.processInteract(faker, EnumHand.MAIN_HAND, faker.getHeldItemMainhand())) {
IInventory inv = faker.inventory;
for (int i = 0; i < inv.getSizeInventory(); i++){
if (inv.getStackInSlot(i)!=null) {
addToInventory(inv.getStackInSlot(i));
inv.setInventorySlotContents(i, null);
}
}
slots[SLOT_BUCKETS].stackSize--;
if (slots[SLOT_BUCKETS].stackSize==0) slots[SLOT_BUCKETS] = null;
currentTime = waitTime;
addPartialUpdate("currentTime", currentTime);
}
}
}
public static boolean isFeed(ItemStack itemStack) {
if (itemStack==null) return false;
if (itemStack.getItem()==null) return false;
if (itemStack.getItem() == Items.WHEAT) return true;
if (itemStack.getItem() == Items.WHEAT_SEEDS) return true;
if (itemStack.getItem() == Items.CARROT) return true;
return false;
}
@Override
public boolean isItemValidForSlot(int slot, ItemStack stack) {
if (stack == null) return false;
if ( (slot == this.SLOT_FOOD) && (this.isFeed(stack)) ) {
return true;
}
if ( (slot == this.SLOT_SHEARS) && (stack.getItem() == Items.SHEARS) && (hasUpgrade(UpgradeType.SHEARING)) ) {
return true;
} else if ( (slot == this.SLOT_BUCKETS) && (stack.getItem() == Items.BUCKET) && (hasUpgrade(UpgradeType.MILKER)) ) {
return true;
}
return super.isItemValidForSlot(slot, stack);
}
@Override
protected Point3I adjustedSpiral(int n) {
Point3I point = super.adjustedSpiral(n + 1);
return point;
}
}