/* This file is part of Project-Zed. Project-Zed is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Project-Zed is
* distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along
* with Project-Zed. If not, see <http://www.gnu.org/licenses/>
*/
package com.projectzed.mod.tileentity.container;
import com.hockeyhurd.hcorelib.api.math.Vector3;
import com.hockeyhurd.hcorelib.api.util.BlockUtils;
import com.projectzed.api.tileentity.container.AbstractTileEntityFluidContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.fluids.*;
/**
* TileEntity code for liquidNode.
*
* @author hockeyhurd
* @version Feb 16, 2015
*/
public class TileEntityLiquidNode extends AbstractTileEntityFluidContainer {
private EnumFacing lastReceivedDir = null;
byte[] sides = new byte[EnumFacing.VALUES.length];
private byte cachedMeta;
public TileEntityLiquidNode() {
super("liquidNode");
this.maxFluidStorage = 1000;
if (this.internalTank == null) this.internalTank = new FluidTank(this.maxFluidStorage);
else this.internalTank.setCapacity(this.maxFluidStorage);
cachedMeta = -1;
}
@Override
public int getSizeInventory() {
return 0;
}
@Override
public int getInventoryStackLimit() {
return 0;
}
@Override
protected void initContentsArray() {
}
@Override
protected void initSlotsArray() {
}
@Override
public boolean isItemValidForSlot(int slot, ItemStack stack) {
return false;
}
@Override
public int[] getSlotsForFace(EnumFacing side) {
return null;
}
@Override
public boolean canInsertItem(int slot, ItemStack stack, EnumFacing side) {
return false;
}
@Override
public boolean canExtractItem(int slot, ItemStack stack, EnumFacing side) {
return false;
}
@Override
protected void importContents() {
if (this.worldObj == null || this.worldObj.isRemote) return;
if (this.internalTank.getFluidAmount() > this.maxFluidStorage) {
FluidStack copy = this.internalTank.getFluid();
copy.amount = this.maxFluidStorage;
this.internalTank.setFluid(copy);
}
// FluidNet.importFluidFromNeighbors(this, worldObj, xCoord, yCoord, zCoord, lastReceivedDir);
// FluidNet.tryClearDirectionalTraffic(this, worldObj, xCoord, yCoord, zCoord, lastReceivedDir);
}
protected void exportContents() {
if (this.worldObj == null || this.worldObj.isRemote) return;
if (this.internalTank.getFluidAmount() == 0) return;
if (this.internalTank.getFluid() == null || this.internalTank.getFluid().getFluid() == null) return;
// FluidNet.exportFluidToNeighbors(this, worldObj, xCoord, yCoord, zCoord);
EnumFacing exportSide = null;
for (byte i = 0; i < this.sides.length; i++) {
if (this.sides[i] == 1) {
// exportSide = ForgeDirection.getOrientation(i);
exportSide = EnumFacing.getFront(i);
break;
}
}
if (exportSide != null) {
final Vector3<Integer> vec = worldVec(); // Float?
final Vector3<Integer> addVec = new Vector3<Integer>(exportSide.getFrontOffsetX(), exportSide.getFrontOffsetY(), exportSide.getFrontOffsetZ());
vec.add(addVec);
// TileEntity te = worldObj.getTileEntity(VectorHelper.toBlockPos(vec));
TileEntity te = worldObj.getTileEntity(getPos());
if (te != null && te instanceof IFluidHandler) {
IFluidHandler tank = (IFluidHandler) te;
if (tank.canFill(exportSide.getOpposite(), this.internalTank.getFluid().getFluid())) {
FluidStack thisStack = this.getTank().getFluid();
int amount = getAmountFromTank(tank, thisStack, exportSide.getOpposite());
// if destination tank is empty set to default size.
if (amount == 0) amount = this.getMaxFluidExportRate();
amount = Math.min(amount, thisStack.amount);
amount = Math.min(amount, this.getMaxFluidExportRate());
if (amount > 0) {
FluidStack sendStack = thisStack.copy();
sendStack.amount = amount;
amount = sendStack.amount = tank.fill(exportSide.getOpposite(), sendStack, false);
this.getTank().drain(amount, true);
tank.fill(exportSide.getOpposite(), sendStack, true);
}
}
}
}
}
private int getAmountFromTank(IFluidHandler tank, FluidStack stack, EnumFacing dir) {
if (tank != null && stack != null && stack.amount > 0 && dir != null && tank.getTankInfo(dir) != null && tank.getTankInfo(dir).length > 0) {
for (int i = 0; i < tank.getTankInfo(dir).length; i++) {
if (tank.getTankInfo(dir)[i].fluid != null && tank.getTankInfo(dir)[i].fluid.amount > 0
&& tank.getTankInfo(dir)[i].fluid.isFluidEqual(stack)) return tank.getTankInfo(dir)[i].fluid.amount;
}
}
return 0;
}
@Override
public void update() {
// super.updateEntity();
exportContents();
if (!worldObj.isRemote && worldObj.getTotalWorldTime() % 20L == 0) {
// byte currentMeta = (byte) (worldObj.getBlockMetadata(worldVec().x, worldVec().y, worldVec().z) - 1);
final IBlockState blockState = BlockUtils.getBlock(worldObj, worldVec());
byte currentMeta = (byte) (blockState.getBlock().getMetaFromState(blockState));
if (currentMeta != this.cachedMeta) {
for (EnumFacing dir : EnumFacing.VALUES) {
if (dir.ordinal() == currentMeta) sides[dir.ordinal()] = 1;
else sides[dir.ordinal()] = -1;
}
this.cachedMeta = currentMeta;
this.markDirty();
// worldObj.markBlockForUpdate(worldVec().x, worldVec().y, worldVec().z);
worldObj.notifyBlockOfStateChange(pos, blockType);
worldObj.notifyNeighborsOfStateChange(pos, blockType);
}
}
}
/*@Override
public Packet getDescriptionPacket() {
return null;
}*/
@Override
public NBTTagCompound getUpdateTag() {
return getTileData();
}
@Override
public boolean canBeSourceNode() {
return true;
}
@Override
public boolean canBeMaster() {
return false;
}
// START FLUID API METHODS AND HANDLERS:
@Override
public int fill(EnumFacing from, FluidStack resource, boolean doFill) {
if (!worldObj.isRemote) {
if (from != null && sides[from.ordinal()] != -1) return 0;
int fillAmount = internalTank.fill(resource, doFill);
if (doFill) {
worldObj.notifyBlockOfStateChange(pos, blockType);
worldObj.notifyNeighborsOfStateChange(pos, blockType);
this.markDirty();
// if (this.getBlockType() != null) worldObj.notifyBlockOfNeighborChange(xCoord, yCoord, zCoord, this.getBlockType());
FluidEvent.fireEvent(new FluidEvent.FluidFillingEvent(resource, worldObj, pos, this.internalTank, fillAmount));
}
return fillAmount;
}
return 0;
}
@Override
public FluidStack drain(EnumFacing from, FluidStack resource, boolean doDrain) {
return drain(from, resource, -1, doDrain);
}
@Override
public FluidStack drain(EnumFacing from, int maxDrain, boolean doDrain) {
return drain(from, null, maxDrain, doDrain);
}
/**
* Drains fluid from this block to another.
*
* @param from direction drained from.
* @param drainFluid the fluid drained.
* @param drainAmount amount of fluid drained.
* @param doDrain whether draining should be simulated or not.
* @return type and amount of fluid drained.
*/
protected FluidStack drain(EnumFacing from, FluidStack drainFluid, int drainAmount, boolean doDrain) {
if (!worldObj.isRemote) {
if (from != null && sides[from.ordinal()] != 1) return null;
FluidStack drainedFluid = (drainFluid != null && drainFluid.isFluidEqual(internalTank.getFluid())) ? internalTank.drain(
drainFluid.amount, doDrain) : drainAmount >= 0 ? internalTank.drain(drainAmount, doDrain) : null;
if (doDrain && drainedFluid != null && drainedFluid.amount > 0) {
this.markDirty();
worldObj.notifyBlockOfStateChange(pos, blockType);
worldObj.notifyNeighborsOfStateChange(pos, blockType);
FluidEvent.fireEvent(new FluidEvent.FluidDrainingEvent(drainedFluid, worldObj, pos, this.internalTank, drainedFluid.amount));
}
return drainedFluid;
}
return null;
}
@Override
public boolean canFill(EnumFacing from, Fluid fluid) {
if (from != null && sides[from.ordinal()] != -1) return false;
if (fluid != null && !isFull()) {
FluidStack tankFluid = this.internalTank.getFluid();
return tankFluid == null || tankFluid.isFluidEqual(new FluidStack(fluid, 0));
}
return false;
}
@Override
public boolean canDrain(EnumFacing from, Fluid fluid) {
if (from != null && sides[from.ordinal()] != 1) return false;
if (fluid != null && this.internalTank.getFluidAmount() > 0) {
FluidStack tankFluid = this.internalTank.getFluid();
return tankFluid != null && tankFluid.isFluidEqual(new FluidStack(fluid, 0));
}
return false;
}
@Override
public EnumFacing getRotatedState(EnumFacing facingDir, IBlockState blockState) {
if (facingDir == EnumFacing.DOWN || facingDir == EnumFacing.UP) return frontFacing;
return (frontFacing = frontFacing.rotateY());
}
}