buildcraftAdditions.tileEntities.TileRefinery.java Source code

Java tutorial

Introduction

Here is the source code for buildcraftAdditions.tileEntities.TileRefinery.java

Source

package buildcraftAdditions.tileEntities;

import java.util.EnumSet;
import java.util.Set;

import com.google.common.collect.ImmutableSet;

import io.netty.buffer.ByteBuf;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;

import cpw.mods.fml.common.network.ByteBufUtils;

import net.minecraftforge.common.util.Constants;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidTankInfo;
import net.minecraftforge.fluids.IFluidHandler;

import cofh.api.energy.IEnergyReceiver;

import buildcraft.api.transport.IPipeConnection;
import buildcraft.api.transport.IPipeTile;

import buildcraftAdditions.BuildcraftAdditions;
import buildcraftAdditions.api.recipe.BCARecipeManager;
import buildcraftAdditions.api.recipe.refinery.IRefineryRecipe;
import buildcraftAdditions.config.ConfigurationHandler;
import buildcraftAdditions.core.Logger;
import buildcraftAdditions.multiBlocks.IMultiBlockTile;
import buildcraftAdditions.reference.Variables;
import buildcraftAdditions.reference.enums.EnumMachineUpgrades;
import buildcraftAdditions.tileEntities.Bases.TileBase;
import buildcraftAdditions.tileEntities.interfaces.IUpgradableMachine;
import buildcraftAdditions.tileEntities.varHelpers.MultiBlockData;
import buildcraftAdditions.tileEntities.varHelpers.Upgrades;
import buildcraftAdditions.utils.Location;
import buildcraftAdditions.utils.RotationUtils;
import buildcraftAdditions.utils.Utils;
import buildcraftAdditions.utils.fluids.ITankHolder;
import buildcraftAdditions.utils.fluids.RefineryRecipeTank;
import buildcraftAdditions.utils.fluids.Tank;

/**
 * Copyright (c) 2014-2015, AEnterprise
 * http://buildcraftadditions.wordpress.com/
 * Buildcraft Additions is distributed under the terms of GNU GPL v3.0
 * Please check the contents of the license located in
 * http://buildcraftadditions.wordpress.com/wiki/licensing-stuff/
 */
public class TileRefinery extends TileBase implements IMultiBlockTile, IFluidHandler, IEnergyReceiver, ITankHolder,
        IPipeConnection, IUpgradableMachine {
    public final int maxEnergy, maxTransfer;
    public final Tank input = new RefineryRecipeTank("Input", 3000, this);
    public final Tank output = new Tank(3000, this, "Output");
    protected final Upgrades upgrades = new Upgrades(0);
    private final MultiBlockData data = new MultiBlockData().setPatern(Variables.Paterns.REFINERY);
    public int energy, currentHeat, requiredHeat, energyCost, heatTimer, lastRequiredHeat;
    public boolean valve, isCooling, moved;
    public TileRefinery master;
    private boolean firstTick = true;
    private FluidStack outputFluidStack;
    private FluidStack inputFluidStack;
    private String inputFluid, outputFluid;

    public TileRefinery() {
        maxEnergy = ConfigurationHandler.capacityRefinery;
        maxTransfer = ConfigurationHandler.maxTransferRefinery;
        lastRequiredHeat = 20;
        currentHeat = 20;
        inputFluid = "";
        outputFluid = "";
    }

    public void updateEntity() {
        super.updateEntity();
        if (worldObj.isRemote)
            return;
        if (data.moved) {
            data.afterMoveCheck(worldObj);
            worldObj.scheduleBlockUpdate(xCoord, yCoord, zCoord, worldObj.getBlock(xCoord, yCoord, zCoord), 80);
        }
        if (valve && upgrades.hasUpgrade(EnumMachineUpgrades.AUTO_OUTPUT)) {
            if (master == null)
                findMaster();
            if (master == null)
                return;
            for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) {
                Location location = new Location(this).move(direction);
                TileEntity entity = location.getTileEntity();
                if (entity != null && entity instanceof IFluidHandler && !(entity instanceof TileRefinery)
                        && master.output.getFluidType() != null) {
                    IFluidHandler tank = (IFluidHandler) entity;
                    int drain = tank.fill(direction.getOpposite(), new FluidStack(master.output.getFluidType(),
                            ConfigurationHandler.refineryAutoExportMaxTransfer), false);
                    FluidStack stack = master.drain(direction, drain, true);
                    tank.fill(direction.getOpposite(), stack, true);
                }
            }
        }
        if (valve && upgrades.hasUpgrade(EnumMachineUpgrades.AUTO_IMPORT)) {
            if (master == null)
                findMaster();
            if (master == null)
                return;
            for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) {
                Location location = new Location(this).move(direction);
                TileEntity tile = location.getTileEntity();
                if (tile != null && tile instanceof IFluidHandler && !master.input.isFull()) {
                    IFluidHandler tank = (IFluidHandler) tile;
                    FluidStack drain = tank.drain(direction.getOpposite(),
                            ConfigurationHandler.refineryAutoImportMaxTransfer, false);
                    int fill = fill(ForgeDirection.UNKNOWN, drain, true);
                    if (fill > 0)
                        tank.drain(direction.getOpposite(), fill, true);
                }
            }
        }
        if (!data.isMaster)
            return;
        if (input.getFluid() != null && input.getFluid().amount <= 0)
            input.setFluid(null);
        if (output.getFluid() != null && output.getFluid().amount <= 0)
            output.setFluid(null);
        if (input.getFluid() == null)
            updateRecipe();
        updateHeat();
        if (firstTick)
            firstTick = false;
        int pEnergyCost = (int) (50 + (50 * (currentHeat / 100D)));
        energyCost = (input.getFluid() == null || isCooling || energy < pEnergyCost) ? 0 : pEnergyCost;
        if (output.isFull())
            energyCost = 0;
        double factor = 0;
        if (upgrades.hasUpgrade(EnumMachineUpgrades.EFFICIENCY_1))
            factor += ConfigurationHandler.refineryEfficiency1EnergyCostModifier;
        if (upgrades.hasUpgrade(EnumMachineUpgrades.EFFICIENCY_2))
            factor += ConfigurationHandler.refineryEfficiency2EnergyCostModifier;
        if (upgrades.hasUpgrade(EnumMachineUpgrades.EFFICIENCY_3))
            factor += ConfigurationHandler.refineryEfficiency3EnergyCostModifier;
        if (upgrades.hasUpgrade(EnumMachineUpgrades.SPEED_1))
            factor += ConfigurationHandler.refinerySpeed1EnergyCostModifier;
        if (upgrades.hasUpgrade(EnumMachineUpgrades.SPEED_2))
            factor += ConfigurationHandler.refinerySpeed2EnergyCostModifier;
        if (upgrades.hasUpgrade(EnumMachineUpgrades.SPEED_3))
            factor += ConfigurationHandler.refinerySpeed3EnergyCostModifier;
        energyCost += (energyCost * factor);
        energy -= energyCost * ConfigurationHandler.energyUseRefineryMultiplier;
        if (currentHeat < requiredHeat) {
            return;
        }
        int count = 1;
        if (upgrades.hasUpgrade(EnumMachineUpgrades.SPEED_1))
            count += ConfigurationHandler.refinerySpeed1SpeedModifier;
        if (upgrades.hasUpgrade(EnumMachineUpgrades.SPEED_2))
            count += ConfigurationHandler.refinerySpeed2SpeedModifier;
        if (upgrades.hasUpgrade(EnumMachineUpgrades.SPEED_3))
            count += ConfigurationHandler.refinerySpeed3SpeedModifier;
        for (int i = 0; i < count; i++) {
            if (energyCost == 0 || input.isEmpty() || output.isFull()
                    || !input.getFluid().isFluidEqual(inputFluidStack)
                    || input.getFluidAmount() < inputFluidStack.amount
                    || (!output.isEmpty() && !output.getFluid().isFluidEqual(outputFluidStack))
                    || output.getFreeSpace() < outputFluidStack.amount)
                return;
            input.drain(inputFluidStack.amount, true);
            output.fill(outputFluidStack, true);
        }
    }

    private void updateHeat() {
        if (worldObj.isRemote || firstTick)
            return;
        if (heatTimer == 0) {
            if (((currentHeat > requiredHeat || (energy < energyCost || energyCost == 0)) && currentHeat > 20)
                    || (output.isFull() && currentHeat > 20)) {
                currentHeat--;
                isCooling = true;
            }
            if ((currentHeat < requiredHeat && (energy >= energyCost && energyCost != 0)) && !output.isFull()) {
                currentHeat++;
                isCooling = false;
            }
            heatTimer = 10;
        }
        if (currentHeat == 20)
            isCooling = false;
        heatTimer -= 1;
    }

    private void updateRecipe() {
        if (!isPartOfMultiblock())
            return;
        if (!input.isEmpty()) {
            IRefineryRecipe recipe = BCARecipeManager.refinery.getRecipe(input.getFluid());
            if (recipe != null) {
                requiredHeat = recipe.getRequiredHeat();
                lastRequiredHeat = requiredHeat;
                outputFluidStack = recipe.getOutput();
                inputFluidStack = recipe.getInput();
                inputFluid = inputFluidStack.getLocalizedName();
                outputFluid = outputFluidStack.getLocalizedName();
            }
        } else {
            requiredHeat = 0;
        }
    }

    @Override
    public void makeMaster(int rotationIndex) {
        data.isMaster = true;
        data.partOfMultiBlock = true;
        data.rotationIndex = rotationIndex;
        upgrades.blacklistUpgrade(EnumMachineUpgrades.AUTO_OUTPUT).blacklistUpgrade(EnumMachineUpgrades.AUTO_IMPORT)
                .setMaxUpgrades(4);
    }

    public void findMaster() {
        TileEntity entity = worldObj.getTileEntity(data.masterX, data.masterY, data.masterZ);
        if (entity instanceof TileRefinery) {
            master = (TileRefinery) entity;
        }
        if (master == null || !master.data.isMaster) {
            master = null;
            invalidateMultiblock();
        }
    }

    @Override
    public void invalidateMultiblock() {
        if (isMaster())
            data.patern.destroyMultiblock(worldObj, xCoord, yCoord, zCoord, data.rotationIndex);
        else
            data.patern.destroyMultiblock(worldObj, data.masterX, data.masterY, data.masterZ, data.rotationIndex);
    }

    private void emptyTanks() {
        if (input.getFluid() == null || input.getFluid().amount < 1000 || input.getFluidType() == null)
            return;
        ForgeDirection[] directions = RotationUtils.rotateDirections(data.rotationIndex, ForgeDirection.NORTH,
                ForgeDirection.EAST, ForgeDirection.UP);
        Location location = new Location(this);
        location.move(directions);
        try {
            while (input.getFluid().amount >= 1000) {
                if (input.getFluidType().getBlock() != null)
                    location.setBlock(input.getFluidType().getBlock());
                input.drain(1000, true);
                location.move(RotationUtils.rotatateDirection(ForgeDirection.NORTH, data.rotationIndex));
            }
        } catch (Exception e) {
            Logger.error("Error while trying to empty the tank of a refinery");
        } finally {
            input.setFluid(null);
        }
        location.move(RotationUtils.rotatateDirection(ForgeDirection.NORTH, data.rotationIndex));
        if (output.getFluid() == null || output.getFluid().amount < 1000 || output.getFluidType() == null)
            return;
        try {
            while (output.getFluid().amount >= 1000) {
                location.setBlock(output.getFluidType().getBlock());
                output.drain(1000, true);
                location.move(RotationUtils.rotatateDirection(ForgeDirection.NORTH, data.rotationIndex));
            }
        } catch (Exception e) {
            Logger.error("Error while trying to empty the tank of a refinery");
        } finally {
            input.setFluid(null);
        }
    }

    @Override
    public boolean onBlockActivated(EntityPlayer player) {
        if (data.isMaster) {
            sync();
            if (!worldObj.isRemote) {
                player.openGui(BuildcraftAdditions.instance, Variables.Gui.REFINERY.ordinal(), worldObj, xCoord,
                        yCoord, zCoord);
            }
            return true;
        }
        if (data.partOfMultiBlock) {
            if (master == null)
                findMaster();
            if (master != null)
                return master.onBlockActivated(player);
        }
        return false;
    }

    @Override
    public void readFromNBT(NBTTagCompound tag) {
        super.readFromNBT(tag);
        data.readFromNBT(tag);
        valve = tag.getBoolean("valve");
        energy = tag.getInteger("energy");
        currentHeat = tag.getInteger("currentHeat");
        requiredHeat = tag.getInteger("requiredHeat");
        lastRequiredHeat = tag.getInteger("lastRequiredHeat");
        if (tag.hasKey("input", Constants.NBT.TAG_COMPOUND))
            input.readFromNBT(tag.getCompoundTag("input"));
        if (tag.hasKey("output", Constants.NBT.TAG_COMPOUND))
            output.readFromNBT(tag.getCompoundTag("output"));
        updateRecipe();
        upgrades.readFromNBT(tag);
        if (valve)
            upgrades.whitelistUpgrade(EnumMachineUpgrades.AUTO_OUTPUT)
                    .whitelistUpgrade(EnumMachineUpgrades.AUTO_IMPORT);
        if (isMaster())
            upgrades.blacklistUpgrade(EnumMachineUpgrades.AUTO_OUTPUT)
                    .blacklistUpgrade(EnumMachineUpgrades.AUTO_IMPORT);
    }

    @Override
    public void writeToNBT(NBTTagCompound tag) {
        super.writeToNBT(tag);
        tag.setBoolean("valve", valve);
        tag.setInteger("energy", energy);
        tag.setInteger("currentHeat", currentHeat);
        tag.setInteger("requiredHeat", requiredHeat);
        tag.setInteger("lastRequiredHeat", lastRequiredHeat);
        tag.setTag("input", input.writeToNBT(new NBTTagCompound()));
        tag.setTag("output", output.writeToNBT(new NBTTagCompound()));
        data.writeToNBT(tag);
        upgrades.writeToNBT(tag);
    }

    @Override
    public void formMultiblock(int masterX, int masterY, int masterZ, int rotationIndex) {
        data.formMultiBlock(masterX, masterY, masterZ, rotationIndex);
        if (valve)
            upgrades.whitelistUpgrade(EnumMachineUpgrades.AUTO_OUTPUT)
                    .whitelistUpgrade(EnumMachineUpgrades.AUTO_IMPORT).setMaxUpgrades(1);
        sync();
    }

    @Override
    public void invalidateBlock() {
        if (data.isMaster)
            emptyTanks();
        worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 0, 2);
        worldObj.scheduleBlockUpdate(xCoord, yCoord, zCoord, worldObj.getBlock(xCoord, yCoord, zCoord), 80);
        input.setFluid(null);
        output.setFluid(null);
        energy = 0;
        currentHeat = 0;
        requiredHeat = 0;
        energyCost = 0;
        heatTimer = 0;
        lastRequiredHeat = 0;
        outputFluidStack = null;
        inputFluidStack = null;
        inputFluid = "";
        outputFluid = "";
        data.invalidate();
        upgrades.invalidate();
        sync();
    }

    @Override
    public void moved(ForgeDirection direction) {
        data.onMove(direction);
        master = null;
    }

    @Override
    public int getMasterX() {
        return data.masterX;
    }

    @Override
    public void setMasterX(int masterX) {
        data.masterX = masterX;
    }

    @Override
    public int getMasterY() {
        return data.masterY;
    }

    @Override
    public void setMasterY(int masterY) {
        data.masterY = masterY;
    }

    @Override
    public int getMasterZ() {
        return data.masterZ;
    }

    @Override
    public void setMasterZ(int masterZ) {
        data.masterZ = masterZ;
    }

    @Override
    public int getRotationIndex() {
        return data.rotationIndex;
    }

    @Override
    public void setRotationIndex(int rotationIndex) {
        data.rotationIndex = rotationIndex;
    }

    @Override
    public boolean isMaster() {
        return data.isMaster;
    }

    @Override
    public boolean isPartOfMultiblock() {
        return data.partOfMultiBlock;
    }

    @Override
    public void setIsMaster(boolean isMaster) {
        data.isMaster = isMaster;
    }

    @Override
    public void setPartOfMultiBlock(boolean partOfMultiBlock) {
        data.partOfMultiBlock = partOfMultiBlock;
    }

    @Override
    public int fill(ForgeDirection from, FluidStack resource, boolean doFill) {
        if (!valve)
            return 0;
        if (master == null)
            findMaster();
        if (master != null)
            return master.realFill(resource, doFill);
        return 0;
    }

    public int realFill(FluidStack resource, boolean doFill) {
        int result = input.fill(resource, doFill);
        updateRecipe();
        return result;
    }

    @Override
    public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) {
        if (isMaster())
            return realDrain(resource, doDrain);
        if (!valve)
            return null;
        if (master == null)
            findMaster();
        if (master != null)
            return master.realDrain(resource, doDrain);
        return null;
    }

    @Override
    public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) {
        if (isMaster())
            return realDrain(maxDrain, doDrain);
        if (!valve)
            return null;
        if (master == null)
            findMaster();
        if (master != null)
            return master.realDrain(maxDrain, doDrain);
        return null;
    }

    public FluidStack realDrain(int maxDrain, boolean doDrain) {
        FluidStack result = output.drain(maxDrain, doDrain);
        updateRecipe();
        return result;
    }

    public FluidStack realDrain(FluidStack fluid, boolean doDrain) {
        FluidStack result = output.drain(fluid, doDrain);
        updateRecipe();
        return result;
    }

    @Override
    public boolean canFill(ForgeDirection from, Fluid fluid) {
        return data.partOfMultiBlock && valve;
    }

    @Override
    public boolean canDrain(ForgeDirection from, Fluid fluid) {
        return data.partOfMultiBlock && valve;
    }

    @Override
    public FluidTankInfo[] getTankInfo(ForgeDirection from) {
        if (!valve)
            return null;
        if (master == null)
            findMaster();
        if (master != null)
            return master.realGetTankInfo();
        return new FluidTankInfo[] { new FluidTankInfo(input), new FluidTankInfo(output) };
    }

    public FluidTankInfo[] realGetTankInfo() {
        return new FluidTankInfo[] { new FluidTankInfo(input), new FluidTankInfo(output) };
    }

    @Override
    public int receiveEnergy(ForgeDirection from, int maxReceive, boolean simulate) {
        if (isMaster()) {
            int energyReceived = Math.min(maxEnergy - energy, Math.min(maxTransfer, maxReceive));
            if (!simulate)
                energy += energyReceived;
            return energyReceived;
        } else {
            if (master == null)
                findMaster();
            if (master != null)
                return master.receiveEnergy(from, maxReceive, simulate);
        }
        return 0;
    }

    @Override
    public int getEnergyStored(ForgeDirection from) {
        if (data.isMaster)
            return energy;
        else {
            if (master == null)
                findMaster();
            if (master != null)
                return master.getEnergyStored(from);
        }
        return 0;
    }

    @Override
    public int getMaxEnergyStored(ForgeDirection from) {
        if (data.isMaster)
            return maxEnergy;
        else {
            if (master == null)
                findMaster();
            if (master != null)
                return master.getMaxEnergyStored(from);
        }
        return 0;
    }

    @Override
    public boolean canConnectEnergy(ForgeDirection from) {
        return true;
    }

    @Override
    public Tank[] getTanks() {
        return new Tank[] { input, output };
    }

    @Override
    public void writeToByteBuff(ByteBuf buf) {
        buf.writeBoolean(valve);
        buf.writeInt(currentHeat);
        buf.writeInt(lastRequiredHeat);
        buf.writeInt(energyCost);
        buf.writeInt(requiredHeat);
        ByteBufUtils.writeUTF8String(buf, inputFluid);
        ByteBufUtils.writeUTF8String(buf, outputFluid);
        input.writeToByteBuff(buf);
        output.writeToByteBuff(buf);
        data.writeToByteBuff(buf);
        upgrades.writeToByteBuff(buf);
    }

    @Override
    public void readFromByteBuff(ByteBuf buf) {
        valve = buf.readBoolean();
        currentHeat = buf.readInt();
        lastRequiredHeat = buf.readInt();
        energyCost = buf.readInt();
        requiredHeat = buf.readInt();
        inputFluid = ByteBufUtils.readUTF8String(buf);
        outputFluid = ByteBufUtils.readUTF8String(buf);
        input.readFromByteBuff(buf);
        output.readFromByteBuff(buf);
        data.readFromByteBuff(buf);
        upgrades.readFromByteBuff(buf);
    }

    @Override
    public ConnectOverride overridePipeConnection(IPipeTile.PipeType type, ForgeDirection with) {
        return (valve && type == IPipeTile.PipeType.FLUID) || type == IPipeTile.PipeType.POWER
                ? ConnectOverride.CONNECT
                : ConnectOverride.DISCONNECT;
    }

    @Override
    public boolean canAcceptUpgrade(EnumMachineUpgrades upgrade) {
        if (valve || isMaster()) {
            return upgrades.canInstallUpgrade(upgrade);
        } else {
            if (master == null)
                findMaster();
            return master != null && master.canAcceptUpgrade(upgrade);
        }
    }

    @Override
    public void installUpgrade(EnumMachineUpgrades upgrade) {
        if (valve || isMaster()) {
            upgrades.installUpgrade(upgrade);
        } else {
            if (master == null)
                findMaster();
            if (master == null)
                return;
            master.installUpgrade(upgrade);
        }
    }

    @Override
    public Set<EnumMachineUpgrades> getInstalledUpgrades() {
        if (isMaster()) {
            return upgrades.getUpgrades();
        } else {
            if (master == null)
                findMaster();
            if (master == null)
                return EnumSet.noneOf(EnumMachineUpgrades.class);
            Set<EnumMachineUpgrades> set = EnumSet.noneOf(EnumMachineUpgrades.class);
            set.addAll(master.getInstalledUpgrades());
            if (valve)
                set.addAll(upgrades.getUpgrades());
            return ImmutableSet.copyOf(set);
        }
    }

    @Override
    public void removeUpgrade() {
        if (valve || isMaster()) {
            EnumMachineUpgrades upgrade = upgrades.removeUpgrade();
            if (upgrade == null)
                return;
            ItemStack stack = upgrade.getItemStack();
            Utils.dropItemstack(worldObj, xCoord, yCoord, zCoord, stack);
        } else {
            if (master == null)
                findMaster();
            if (master == null)
                return;
            EnumMachineUpgrades upgrade = master.upgrades.removeUpgrade();
            if (upgrade == null)
                return;
            ItemStack stack = upgrade.getItemStack();
            Utils.dropItemstack(worldObj, xCoord, yCoord, zCoord, stack);
        }
    }

    public String getOutput() {
        return outputFluid;
    }

    public String getInput() {
        return inputFluid;
    }

}