package blusunrize.immersiveengineering.common.blocks.metal;
import blusunrize.immersiveengineering.ImmersiveEngineering;
import blusunrize.immersiveengineering.api.IEEnums.SideConfig;
import blusunrize.immersiveengineering.api.Lib;
import blusunrize.immersiveengineering.api.energy.immersiveflux.FluxStorage;
import blusunrize.immersiveengineering.api.tool.BelljarHandler;
import blusunrize.immersiveengineering.api.tool.BelljarHandler.FluidFertilizerHandler;
import blusunrize.immersiveengineering.api.tool.BelljarHandler.IPlantHandler;
import blusunrize.immersiveengineering.api.tool.BelljarHandler.ItemFertilizerHandler;
import blusunrize.immersiveengineering.client.ClientUtils;
import blusunrize.immersiveengineering.client.models.IOBJModelCallback;
import blusunrize.immersiveengineering.common.Config.IEConfig;
import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.IBlockBounds;
import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.IDirectionalTile;
import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.IGuiTile;
import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.IHasDummyBlocks;
import blusunrize.immersiveengineering.common.blocks.TileEntityIEBase;
import blusunrize.immersiveengineering.common.util.EnergyHelper.IEForgeEnergyWrapper;
import blusunrize.immersiveengineering.common.util.EnergyHelper.IIEInternalFluxHandler;
import blusunrize.immersiveengineering.common.util.Utils;
import blusunrize.immersiveengineering.common.util.inventory.IEInventoryHandler;
import blusunrize.immersiveengineering.common.util.inventory.IIEInventory;
import blusunrize.immersiveengineering.common.util.network.MessageTileSync;
import com.google.common.base.Optional;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ITickable;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.model.TRSRTransformation;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidTank;
import net.minecraftforge.fluids.FluidUtil;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fml.common.network.NetworkRegistry.TargetPoint;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class TileEntityBelljar extends TileEntityIEBase implements ITickable, IDirectionalTile, IBlockBounds, IHasDummyBlocks, IIEInventory, IIEInternalFluxHandler, IGuiTile, IOBJModelCallback<IBlockState>
{
public EnumFacing facing = EnumFacing.NORTH;
public int dummy = 0;
private ItemStack[] inventory = new ItemStack[7];
public FluidTank tank = new FluidTank(4000)
{
@Override
protected void onContentsChanged()
{
TileEntityBelljar.this.sendSyncPacket(2);
}
};
public FluxStorage energyStorage = new FluxStorage(16000,Math.max(256,IEConfig.Machines.belljar_consumption));
private IPlantHandler curPlantHandler;
public int fertilizerAmount = 0;
public float fertilizerMod = 1;
private float growth = 0;
public float renderGrowth = 0;
public boolean renderActive = false;
@Override
public void update()
{
if(dummy!=0 || worldObj.isBlockIndirectlyGettingPowered(getPos())>0)
return;
if(getWorld().isRemote)
{
if(energyStorage.getEnergyStored()>IEConfig.Machines.belljar_consumption && fertilizerAmount>0 && renderActive)
{
IPlantHandler handler = getCurrentPlantHandler();
if(handler!=null&&handler.isCorrectSoil(inventory[1], inventory[0]) && fertilizerAmount>0)
{
if(renderGrowth<1)
{
renderGrowth += handler.getGrowthStep(inventory[1], inventory[0], renderGrowth, this, fertilizerMod, true);
fertilizerAmount--;
}
else
renderGrowth = handler.resetGrowth(inventory[1], inventory[0], renderGrowth, this, true);
if(getWorld().rand.nextInt(8)==0)
{
double partX = getPos().getX()+.5;
double partY = getPos().getY()+2.6875;
double partZ = getPos().getZ()+.5;
ImmersiveEngineering.proxy.spawnRedstoneFX(getWorld(), partX, partY, partZ, .25, .25, .25, 1f, .55f, .1f, .1f);
}
}
}
}
else
{
if(inventory[1]!=null)
{
IPlantHandler handler = getCurrentPlantHandler();
if(handler!=null&&handler.isCorrectSoil(inventory[1], inventory[0]) && fertilizerAmount>0 && energyStorage.extractEnergy(IEConfig.Machines.belljar_consumption, true)==IEConfig.Machines.belljar_consumption)
{
boolean consume = false;
if(growth >= 1)
{
ItemStack[] outputs = handler.getOutput(inventory[1], inventory[0], this);
int canFit = 0;
for(int i=0; i<outputs.length; i++)
if(outputs[i]!=null)
for(int j=3;j<7;j++)
if(inventory[j]==null || (ItemHandlerHelper.canItemStacksStack(inventory[j],outputs[i]) && inventory[j].stackSize+outputs[i].stackSize<=inventory[j].getMaxStackSize()))
canFit++;
if(canFit>=outputs.length)
{
for(ItemStack output : outputs)
for(int j=3;j<7;j++)
{
if(inventory[j]==null)
{
inventory[j] = output.copy();
break;
}
else if(ItemHandlerHelper.canItemStacksStack(inventory[j], output)&&inventory[j].stackSize+output.stackSize <= inventory[j].getMaxStackSize())
{
inventory[j].stackSize += output.stackSize;
break;
}
}
growth = handler.resetGrowth(inventory[1], inventory[0], growth, this, false);
consume = true;
}
}
else if(growth < 1)
{
growth += handler.getGrowthStep(inventory[1], inventory[0], growth, this, fertilizerMod, false);
consume = true;
if(worldObj.getTotalWorldTime()%32==((getPos().getX()^getPos().getZ())&31))
sendSyncPacket(0);
}
if(consume)
{
energyStorage.extractEnergy(IEConfig.Machines.belljar_consumption, false);
fertilizerAmount--;
if(!renderActive)
{
renderActive = true;
sendSyncPacket(0);
}
}
else if(renderActive)
{
renderActive = false;
sendSyncPacket(0);
}
}
else
growth = 0;
if(fertilizerAmount<=0 && tank.getFluidAmount()>=IEConfig.Machines.belljar_fluid)
{
FluidFertilizerHandler fluidFert = BelljarHandler.getFluidFertilizerHandler(tank.getFluid());
if(fluidFert!=null)
{
fertilizerMod = fluidFert.getGrowthMultiplier(tank.getFluid(), inventory[1],inventory[0], this);
tank.drain(IEConfig.Machines.belljar_fluid, true);
if(inventory[2]!=null)
{
ItemFertilizerHandler itemFert = BelljarHandler.getItemFertilizerHandler(inventory[2]);
if(itemFert!=null)
fertilizerMod *= itemFert.getGrowthMultiplier(inventory[2], inventory[1], inventory[0], this);
inventory[2].stackSize--;
if(inventory[2].stackSize<=0)
inventory[2]=null;
}
fertilizerAmount = IEConfig.Machines.belljar_fertilizer;
sendSyncPacket(1);
}
}
}
else
growth = 0;
if(worldObj.getTotalWorldTime()%8==0)
{
BlockPos outputPos = getPos().up().offset(facing.getOpposite());
TileEntity outputTile = this.worldObj.getTileEntity(outputPos);
if(outputTile!=null)
for(int j=3; j<7; j++)
if(inventory[j]!=null)
{
int out = Math.min(inventory[j].stackSize, 16);
ItemStack stack = Utils.copyStackWithAmount(inventory[j], out);
stack = Utils.insertStackIntoInventory(outputTile, stack, facing);
if(stack != null)
out -= stack.stackSize;
if((this.inventory[j].stackSize -= out) <= 0)
this.inventory[j] = null;
}
}
}
}
public IPlantHandler getCurrentPlantHandler()
{
if(curPlantHandler==null || !curPlantHandler.isValid(inventory[1]))
curPlantHandler = BelljarHandler.getHandler(inventory[1]);
return curPlantHandler;
}
protected void sendSyncPacket(int type)
{
NBTTagCompound nbt = new NBTTagCompound();
if(type==0)
{
nbt.setFloat("growth", growth);
nbt.setInteger("energy", energyStorage.getEnergyStored());
nbt.setBoolean("renderActive", renderActive);
}
else if(type==1)
{
nbt.setInteger("fertilizerAmount", fertilizerAmount);
nbt.setFloat("fertilizerMod", fertilizerMod);
}
else if(type==2)
nbt.setTag("tank", tank.writeToNBT(new NBTTagCompound()));
ImmersiveEngineering.packetHandler.sendToAllAround(new MessageTileSync(this, nbt), new TargetPoint(worldObj.provider.getDimension(),getPos().getX(), getPos().getY(), getPos().getZ(), 128));
}
@Override
public void receiveMessageFromServer(NBTTagCompound message)
{
if(message.hasKey("growth"))
renderGrowth = message.getFloat("growth");
if(message.hasKey("renderActive"))
renderActive = message.getBoolean("renderActive");
if(message.hasKey("energy"))
energyStorage.setEnergy(message.getInteger("energy"));
if(message.hasKey("fertilizerAmount"))
fertilizerAmount = message.getInteger("fertilizerAmount");
if(message.hasKey("fertilizerMod"))
fertilizerMod = message.getFloat("fertilizerMod");
if(message.hasKey("tank"))
tank.readFromNBT(message.getCompoundTag("tank"));
}
@Override
public void readCustomNBT(NBTTagCompound nbt, boolean descPacket)
{
facing = EnumFacing.getFront(nbt.getInteger("facing"));
dummy = nbt.getInteger("dummy");
inventory = Utils.readInventory(nbt.getTagList("inventory",10),7);
energyStorage.readFromNBT(nbt);
tank.readFromNBT(nbt.getCompoundTag("tank"));
fertilizerAmount = nbt.getInteger("fertilizerAmount");
fertilizerMod = nbt.getFloat("fertilizerMod");
growth = nbt.getFloat("growth");
}
@Override
public void writeCustomNBT(NBTTagCompound nbt, boolean descPacket)
{
nbt.setInteger("facing", facing.ordinal());
nbt.setInteger("dummy", dummy);
nbt.setTag("inventory", Utils.writeInventory(inventory));
energyStorage.writeToNBT(nbt);
NBTTagCompound tankTag = tank.writeToNBT(new NBTTagCompound());
nbt.setTag("tank", tankTag);
nbt.setInteger("fertilizerAmount", fertilizerAmount);
nbt.setFloat("fertilizerMod", fertilizerMod);
nbt.setFloat("growth", growth);
}
@Override
public EnumFacing getFacing()
{
return facing;
}
@Override
public void setFacing(EnumFacing facing)
{
this.facing = facing;
}
@Override
public int getFacingLimitation()
{
return 2;
}
@Override
public boolean mirrorFacingOnPlacement(EntityLivingBase placer)
{
return false;
}
@Override
public boolean canHammerRotate(EnumFacing side, float hitX, float hitY, float hitZ, EntityLivingBase entity)
{
return true;
}
@Override
public boolean canRotate(EnumFacing axis)
{
return true;
}
@Override
public float[] getBlockBounds()
{
return null;//new float[]{facing==EnumFacing.EAST?0:.25f,facing==EnumFacing.UP?0:facing==EnumFacing.DOWN?.125f:.0625f,facing==EnumFacing.SOUTH?0:.25f, facing==EnumFacing.WEST?1:.75f,facing==EnumFacing.DOWN?1:.875f,facing==EnumFacing.NORTH?1:.75f};
}
@Override
public boolean isDummy()
{
return dummy!=0;
}
@Override
public void placeDummies(BlockPos pos, IBlockState state, EnumFacing side, float hitX, float hitY, float hitZ)
{
for(int i=1; i<=2; i++)
{
worldObj.setBlockState(pos.up(i), state);
((TileEntityBelljar)worldObj.getTileEntity(pos.up(i))).dummy = i;
((TileEntityBelljar)worldObj.getTileEntity(pos.up(i))).facing = facing;
}
}
@Override
public void breakDummies(BlockPos pos, IBlockState state)
{
for(int i=0; i<=2; i++)
{
BlockPos p = getPos().down(dummy).up(i);
if(worldObj.getTileEntity(p) instanceof TileEntityBelljar)
worldObj.setBlockToAir(p);
}
}
@Override
public ItemStack[] getInventory()
{
return inventory;
}
@Override
public boolean isStackValid(int slot, ItemStack stack)
{
return true;
}
@Override
public int getSlotLimit(int slot)
{
return slot<2?1:64;
}
@Override
public void doGraphicalUpdates(int slot)
{
if(slot==0)
{
this.markDirty();
this.markContainingBlockForUpdate(null);
}
}
@Override
public boolean hasCapability(Capability<?> capability, EnumFacing facing)
{
if(capability==CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
return dummy==0?(facing==null||facing.getAxis()!=this.facing.rotateY().getAxis()): dummy==1&&(facing==null||facing==this.facing.getOpposite());
else if(capability==CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
return dummy==0 && (facing==null||facing.getAxis()!=this.facing.rotateY().getAxis());
return super.hasCapability(capability, facing);
}
IItemHandler inputHandler = new IEInventoryHandler(1,this,2, true,false);
IItemHandler outputHandler = new IEInventoryHandler(4,this,3, false,true);
@Override
public <T> T getCapability(Capability<T> capability, EnumFacing facing)
{
if(capability==CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
{
if(dummy==0 && (facing==null||facing.getAxis()!=this.facing.rotateY().getAxis()))
return (T)inputHandler;
if(dummy==1 && (facing==null||facing==this.facing.getOpposite()))
return (T)outputHandler;
}
else if(capability==CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY && dummy==0 && (facing==null||facing.getAxis()!=this.facing.rotateY().getAxis()))
return (T)tank;
return super.getCapability(capability, facing);
}
@Override
public boolean canOpenGui()
{
return true;
}
@Override
public int getGuiID()
{
return Lib.GUIID_Belljar;
}
@Override
public TileEntity getGuiMaster()
{
if(dummy==0)
return this;
TileEntity te = worldObj.getTileEntity(getPos().down(dummy));
if(te instanceof TileEntityBelljar)
return te;
return null;
}
@Override
@SideOnly(Side.CLIENT)
public TextureAtlasSprite getTextureReplacement(IBlockState object, String material)
{
if(inventory[0]!=null && "farmland".equals(material))
{
ResourceLocation rl = getSoilTexture();
if(rl!=null)
return ClientUtils.getSprite(rl);
}
return null;
}
@Override
@SideOnly(Side.CLIENT)
public boolean shouldRenderGroup(IBlockState object, String group)
{
return !"glass".equals(group);
}
@Override
@SideOnly(Side.CLIENT)
public Optional<TRSRTransformation> applyTransformations(IBlockState object, String group, Optional<TRSRTransformation> transform)
{
return transform;
}
@Override
@SideOnly(Side.CLIENT)
public String getCacheKey(IBlockState object)
{
if(inventory[0]!=null)
{
ResourceLocation rl = getSoilTexture();
if(rl!=null)
return rl.toString();
}
return null;
}
@SideOnly(Side.CLIENT)
private ResourceLocation getSoilTexture()
{
ResourceLocation rl = curPlantHandler!=null?curPlantHandler.getSoilTexture(inventory[1], inventory[0], this):null;
if(rl==null)
rl=BelljarHandler.getSoilTexture(inventory[0]);
if(rl==null)
{
IBlockState state = Utils.getStateFromItemStack(inventory[0]);
if(state!=null)
rl = ClientUtils.getSideTexture(state, EnumFacing.UP);
}
if(rl==null && inventory[0]!=null && Utils.isFluidRelatedItemStack(inventory[0]))
{
FluidStack fs = FluidUtil.getFluidContained(inventory[0]);
if(fs!=null)
rl = fs.getFluid().getStill(fs);
}
return rl;
}
@Nonnull
@Override
public FluxStorage getFluxStorage()
{
if(dummy!=0)
{
TileEntity te = worldObj.getTileEntity(getPos().down(dummy));
if(te instanceof TileEntityBelljar)
return ((TileEntityBelljar)te).energyStorage;
}
return this.energyStorage;
}
@Nonnull
@Override
public SideConfig getEnergySideConfig(@Nullable EnumFacing facing)
{
return facing==null||(dummy==0&&facing.getAxis()==this.facing.rotateY().getAxis())||(dummy==2&&facing==EnumFacing.UP)?SideConfig.INPUT:SideConfig.NONE;
}
IEForgeEnergyWrapper energyWrapper = new IEForgeEnergyWrapper(this, EnumFacing.UP);
@Override
public IEForgeEnergyWrapper getCapabilityWrapper(EnumFacing facing)
{
if(facing==null||(dummy==0&&facing.getAxis()==this.facing.rotateY().getAxis())||(dummy==2&&facing==EnumFacing.UP))
return energyWrapper;
return null;
}
}