package mcjty.deepresonance.blocks.crystalizer;
import elec332.core.world.WorldHelper;
import mcjty.deepresonance.DeepResonance;
import mcjty.deepresonance.blocks.ModBlocks;
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.lib.container.DefaultSidedInventory;
import mcjty.lib.container.InventoryHelper;
import mcjty.lib.entity.GenericEnergyReceiverTileEntity;
import mcjty.lib.network.Argument;
import mcjty.lib.network.PacketRequestIntegerFromServer;
import mcjty.lib.varia.CustomSidedInvWrapper;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
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.Map;
public class CrystalizerTileEntity extends GenericEnergyReceiverTileEntity implements ITankHook, DefaultSidedInventory, ITickable {
public static final String CMD_GETPROGRESS = "getProgress";
public static final String CLIENTCMD_GETPROGRESS = "getProgress";
private InventoryHelper inventoryHelper = new InventoryHelper(this, CrystalizerContainer.factory, 1);
public CrystalizerTileEntity() {
super(ConfigMachines.Crystalizer.rfMaximum, ConfigMachines.Crystalizer.rfPerTick);
}
private TileTank rclTank;
private static int totalProgress = 0;
private int progress = 0;
private LiquidCrystalFluidTagData mergedData = null;
private static int clientProgress = 0;
public static int getTotalProgress() {
if (totalProgress == 0) {
totalProgress = ConfigMachines.Crystalizer.rclPerCrystal / ConfigMachines.Crystalizer.rclPerTick;
}
return totalProgress;
}
@Override
public InventoryHelper getInventoryHelper() {
return inventoryHelper;
}
@Override
public void update() {
if (!worldObj.isRemote) {
checkStateServer();
}
}
private void checkStateServer() {
if (!canCrystalize()) {
return;
}
storage.extractEnergy(ConfigMachines.Crystalizer.rfPerRcl, false);
FluidStack fluidStack = rclTank.drain(null, ConfigMachines.Crystalizer.rclPerTick, true);
LiquidCrystalFluidTagData data = LiquidCrystalFluidTagData.fromStack(fluidStack);
if (mergedData == null) {
mergedData = data;
} else {
mergedData.merge(data);
}
handleProgress();
}
private void handleProgress() {
progress++;
if (progress == 1) {
// We just started to work. Notify client
IBlockState state = worldObj.getBlockState(getPos());
worldObj.notifyBlockUpdate(getPos(), state, state, 3);
}
if (progress >= getTotalProgress()) {
progress = 0;
makeCrystal();
markDirtyClient();
}
markDirty();
}
public int getProgress() {
return progress;
}
public static int getClientProgress() {
return clientProgress;
}
private boolean canCrystalize() {
if (rclTank == null) {
return false;
}
if (storage.getEnergyStored() < ConfigMachines.Crystalizer.rfPerRcl) {
return false;
}
if (hasCrystal()) {
return false;
}
FluidStack fluidStack = rclTank.drain(null, ConfigMachines.Crystalizer.rclPerTick, false);
return !(fluidStack == null || fluidStack.amount != ConfigMachines.Crystalizer.rclPerTick);
}
public boolean hasCrystal() {
ItemStack crystalStack = inventoryHelper.getStackInSlot(CrystalizerContainer.SLOT_CRYSTAL);
return crystalStack != null;
}
private void makeCrystal() {
ItemStack stack = new ItemStack(ModBlocks.resonatingCrystalBlock);
NBTTagCompound compound = new NBTTagCompound();
compound.setFloat("power", 100.0f);
compound.setFloat("strength", mergedData.getStrength() * 100.0f);
compound.setFloat("efficiency", mergedData.getEfficiency() * 100.0f);
compound.setFloat("purity", mergedData.getPurity() * 100.0f);
compound.setByte("version", (byte) 2); // Legacy support to support older crystals.
stack.setTagCompound(compound);
mergedData = null;
inventoryHelper.setStackInSlot(CrystalizerContainer.SLOT_CRYSTAL, stack);
}
@Override
public void writeToNBT(NBTTagCompound tagCompound) {
super.writeToNBT(tagCompound);
tagCompound.setInteger("progress", progress);
if (mergedData != null) {
NBTTagCompound dataCompound = new NBTTagCompound();
mergedData.writeDataToNBT(dataCompound);
tagCompound.setTag("data", dataCompound);
tagCompound.setInteger("amount", mergedData.getInternalTankAmount());
}
}
@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");
if (tagCompound.hasKey("data")) {
NBTTagCompound dataCompound = (NBTTagCompound) tagCompound.getTag("data");
int amount = dataCompound.getInteger("amount");
mergedData = LiquidCrystalFluidTagData.fromNBT(dataCompound, amount);
} else {
mergedData = null;
}
}
@Override
public void readRestorableFromNBT(NBTTagCompound tagCompound) {
super.readRestorableFromNBT(tagCompound);
readBufferFromNBT(tagCompound, inventoryHelper);
}
@Override
public void hook(TileTank tank, EnumFacing direction) {
if (direction == EnumFacing.DOWN && rclTank == null){
if (validRCLTank(tank)){
rclTank = tank;
}
}
}
@Override
public void unHook(TileTank tank, EnumFacing direction) {
if (tilesEqual(rclTank, tank)){
rclTank = null;
notifyAndMarkDirty();
}
}
@Override
public void onContentChanged(TileTank tank, EnumFacing direction) {
if (tilesEqual(rclTank, tank)){
if (!validRCLTank(tank)) {
rclTank = 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[] { CrystalizerContainer.SLOT_CRYSTAL };
}
@Override
public boolean canExtractItem(int index, ItemStack stack, EnumFacing direction) {
return index == CrystalizerContainer.SLOT_CRYSTAL;
}
@Override
public boolean canInsertItem(int index, ItemStack itemStackIn, EnumFacing direction) {
return false;
}
@Override
public int getInventoryStackLimit() {
return 1;
}
@Override
public boolean isUseableByPlayer(EntityPlayer player) {
return canPlayerAccess(player);
}
@Override
public boolean isItemValidForSlot(int index, ItemStack stack) {
return stack.getItem() == Item.getItemFromBlock(ModBlocks.resonatingCrystalBlock);
}
@Override
public boolean shouldRenderInPass(int pass) {
return pass == 0;
}
// Request the researching amount from the server. This has to be called on the client side.
public void requestProgressFromServer() {
DeepResonance.networkHandler.getNetworkWrapper().sendToServer(new PacketRequestIntegerFromServer(DeepResonance.MODID, pos, CMD_GETPROGRESS, CLIENTCMD_GETPROGRESS));
}
@Override
public Integer executeWithResultInteger(String command, Map<String, Argument> args) {
Integer rc = super.executeWithResultInteger(command, args);
if (rc != null) {
return rc;
}
if (CMD_GETPROGRESS.equals(command)) {
return progress * 100 / getTotalProgress();
}
return null;
}
@Override
public boolean execute(String command, Integer result) {
boolean rc = super.execute(command, result);
if (rc) {
return true;
}
if (CLIENTCMD_GETPROGRESS.equals(command)) {
clientProgress = result;
return true;
}
return false;
}
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);
}
}
}