package mcjty.deepresonance.blocks.purifier;
import elec332.core.world.WorldHelper;
import mcjty.deepresonance.blocks.tank.ITankHook;
import mcjty.deepresonance.blocks.tank.TileTank;
import mcjty.deepresonance.config.ConfigMachines;
import mcjty.deepresonance.fluid.DRFluidRegistry;
import mcjty.deepresonance.fluid.LiquidCrystalFluidTagData;
import mcjty.deepresonance.items.ModItems;
import mcjty.lib.container.DefaultSidedInventory;
import mcjty.lib.container.InventoryHelper;
import mcjty.lib.container.InventoryLocator;
import mcjty.lib.entity.GenericTileEntity;
import mcjty.lib.varia.CustomSidedInvWrapper;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ITickable;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import java.util.Random;
public class PurifierTileEntity extends GenericTileEntity implements ITankHook, DefaultSidedInventory, ITickable {
private InventoryHelper inventoryHelper = new InventoryHelper(this, PurifierContainer.factory, 1);
public PurifierTileEntity() {
}
private TileTank bottomTank;
private TileTank topTank;
private int progress = 0;
// Cache for the inventory used to put the spent filter material in.
private InventoryLocator inventoryLocator = new InventoryLocator();
private static Random random = new Random();
@Override
public InventoryHelper getInventoryHelper() {
return inventoryHelper;
}
@Override
public void update() {
if (!worldObj.isRemote){
checkStateServer();
}
}
private void checkStateServer() {
if (progress > 0) {
progress--;
if (progress == 0) {
// Done. First check if we can actually insert the liquid. If not we postpone this.
progress = 1;
if (getOutputTank() != null) {
if (canWork()) {
LiquidCrystalFluidTagData fluidData = LiquidCrystalFluidTagData.fromStack(getInputTank().drain(null, ConfigMachines.Purifier.rclPerPurify, true));
if (fluidData != null) {
if (random.nextInt(doPurify(fluidData)) == 0) {
consumeFilter();
}
}
progress = 0; // Really done
}
}
}
markDirty();
} else {
if (canWork()) {
progress = ConfigMachines.Purifier.ticksPerPurify;
markDirty();
}
}
}
private static EnumFacing[] directions = new EnumFacing[] { null, EnumFacing.EAST, EnumFacing.WEST, EnumFacing.NORTH, EnumFacing.SOUTH };
private void consumeFilter() {
inventoryHelper.decrStackSize(PurifierContainer.SLOT_FILTERINPUT, 1);
ItemStack spentMaterial = new ItemStack(ModItems.spentFilterMaterialItem, 1);
inventoryLocator.ejectStack(worldObj, pos, spentMaterial, pos, directions);
}
private int doPurify(LiquidCrystalFluidTagData fluidData) {
float purity = fluidData.getPurity();
float maxPurityToAdd = ConfigMachines.Purifier.addedPurity / 100.0f;
float addedPurity = maxPurityToAdd;
float maxPurity = (ConfigMachines.Purifier.maxPurity + .1f) / 100.0f;
maxPurity *= fluidData.getQuality();
if (purity + addedPurity > maxPurity) {
addedPurity = maxPurity - purity;
if (addedPurity < 0.0001f) {
// We are already very pure. Do nothing.
// Put back the fluid we extracted.
FluidStack stack = fluidData.makeLiquidCrystalStack();
getOutputTank().fill(null, stack, true);
return 1000000;
}
}
purity += addedPurity;
fluidData.setPurity(purity);
FluidStack stack = fluidData.makeLiquidCrystalStack();
getOutputTank().fill(null, stack, true);
return (int) ((maxPurityToAdd - addedPurity) * 40 / maxPurityToAdd + 1);
}
private boolean testFillOutputTank() {
return getOutputTank().fill(null, new FluidStack(DRFluidRegistry.liquidCrystal, ConfigMachines.Purifier.rclPerPurify), false) == ConfigMachines.Purifier.rclPerPurify;
}
private TileTank getInputTank() {
if (topTank == null) {
return bottomTank;
}
return topTank;
}
private TileTank getOutputTank() {
if (bottomTank == null) {
return topTank;
}
return bottomTank;
}
private boolean canWork() {
if (bottomTank == null && topTank == null) {
return false;
}
if (getInputTank().getFluidAmount() < ConfigMachines.Purifier.rclPerPurify) {
return false;
}
if (!validSlot()) {
return false;
}
// Same tank so operation is possible.
return getInputTank().getMultiBlock().equals(getOutputTank().getMultiBlock()) || testFillOutputTank();
}
private boolean validSlot(){
return inventoryHelper.getStackInSlot(PurifierContainer.SLOT_FILTERINPUT) != null && inventoryHelper.getStackInSlot(PurifierContainer.SLOT_FILTERINPUT).getItem() == ModItems.filterMaterialItem;
}
@Override
public void writeToNBT(NBTTagCompound tagCompound) {
super.writeToNBT(tagCompound);
tagCompound.setInteger("progress", progress);
}
@Override
public void writeRestorableToNBT(NBTTagCompound tagCompound) {
super.writeRestorableToNBT(tagCompound);
writeBufferToNBT(tagCompound, inventoryHelper);
}
@Override
public void readFromNBT(NBTTagCompound tagCompound) {
super.readFromNBT(tagCompound);
progress = tagCompound.getInteger("progress");
}
@Override
public void readRestorableFromNBT(NBTTagCompound tagCompound) {
super.readRestorableFromNBT(tagCompound);
readBufferFromNBT(tagCompound, inventoryHelper);
}
@Override
public void hook(TileTank tank, EnumFacing direction) {
if (direction == EnumFacing.DOWN){
if (validRCLTank(tank)) {
bottomTank = tank;
}
} else if (topTank == null){
if (validRCLTank(tank)){
topTank = tank;
}
}
}
@Override
public void unHook(TileTank tank, EnumFacing direction) {
if (tilesEqual(bottomTank, tank)){
bottomTank = null;
notifyAndMarkDirty();
} else if (tilesEqual(topTank, tank)){
topTank = null;
notifyAndMarkDirty();
}
}
@Override
public void onContentChanged(TileTank tank, EnumFacing direction) {
if (tilesEqual(topTank, tank)){
if (!validRCLTank(tank)) {
topTank = null;
}
}
if (tilesEqual(bottomTank, tank)){
if (!validRCLTank(tank)) {
bottomTank = null;
}
}
}
private boolean validRCLTank(TileTank tank){
Fluid fluid = DRFluidRegistry.getFluidFromStack(tank.getFluid());
return fluid == null || fluid == DRFluidRegistry.liquidCrystal;
}
private boolean tilesEqual(TileTank first, TileTank second){
return first != null && second != null && first.getPos().equals(second.getPos()) && WorldHelper.getDimID(first.getWorld()) == WorldHelper.getDimID(second.getWorld());
}
@Override
public int[] getSlotsForFace(EnumFacing side) {
return new int[] { PurifierContainer.SLOT_FILTERINPUT };
}
@Override
public boolean canInsertItem(int index, ItemStack item, EnumFacing side) {
if (!isItemValidForSlot(index, item)) {
return false;
}
return PurifierContainer.factory.isInputSlot(index) || PurifierContainer.factory.isSpecificItemSlot(index);
}
@Override
public boolean canExtractItem(int index, ItemStack item, EnumFacing side) {
return PurifierContainer.factory.isOutputSlot(index);
}
@Override
public int getInventoryStackLimit() {
return 64;
}
@Override
public boolean isUseableByPlayer(EntityPlayer player) {
return canPlayerAccess(player);
}
@Override
public boolean isItemValidForSlot(int index, ItemStack stack) {
return stack.getItem() == ModItems.filterMaterialItem;
}
private IItemHandler invHandler = new CustomSidedInvWrapper(this);
@Override
public boolean hasCapability(Capability<?> capability, EnumFacing facing) {
return capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY || super.hasCapability(capability, facing);
}
@Override
@SuppressWarnings("unchecked")
public <T> T getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, net.minecraft.util.EnumFacing facing) {
if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
return (T) invHandler;
}
return super.getCapability(capability, facing);
}
protected void notifyAndMarkDirty(){
if (WorldHelper.chunkLoaded(worldObj, pos)){
this.markDirty();
this.worldObj.notifyNeighborsOfStateChange(pos, blockType);
}
}
}