com.teambrmodding.neotech.common.tiles.machines.processors.TileSolidifier.java Source code

Java tutorial

Introduction

Here is the source code for com.teambrmodding.neotech.common.tiles.machines.processors.TileSolidifier.java

Source

package com.teambrmodding.neotech.common.tiles.machines.processors;

import com.teambr.bookshelf.client.gui.GuiColor;
import com.teambr.bookshelf.client.gui.GuiTextFormat;
import com.teambr.bookshelf.util.ClientUtils;
import com.teambr.bookshelf.util.InventoryUtils;
import com.teambrmodding.neotech.client.gui.machines.processors.GuiSolidifier;
import com.teambrmodding.neotech.collections.EnumInputOutputMode;
import com.teambrmodding.neotech.collections.SolidifierMode;
import com.teambrmodding.neotech.common.container.machines.processors.ContainerSolidifier;
import com.teambrmodding.neotech.common.tiles.MachineProcessor;
import com.teambrmodding.neotech.common.tiles.traits.IUpgradeItem;
import com.teambrmodding.neotech.managers.MetalManager;
import com.teambrmodding.neotech.managers.RecipeManager;
import com.teambrmodding.neotech.registries.SolidifierRecipeHandler;
import com.teambrmodding.neotech.registries.recipes.AbstractRecipe;
import com.teambrmodding.neotech.registries.recipes.SolidifierRecipe;
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.EnumParticleTypes;
import net.minecraft.world.World;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidTank;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.items.IItemHandler;
import org.apache.commons.lang3.tuple.Pair;

import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;

/**
 * This file was created for NeoTech
 *
 * NeoTech is licensed under the
 * Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License:
 * http://creativecommons.org/licenses/by-nc-sa/4.0/
 *
 * @author Paul Davis - pauljoda
 * @since 2/16/2017
 */
public class TileSolidifier extends MachineProcessor<FluidStack, ItemStack> {
    // Class Variables
    public static final int OUTPUT_SLOT = 0;
    public static final int TANK = 0;

    public static final int BASE_ENERGY_TICK = 300;

    public static final int UPDATE_MODE_NBT = 4;

    // The current mode for the machine
    public SolidifierMode currentMode = SolidifierMode.BLOCK_MODE;

    /**
     * The initial size of the inventory
     */
    @Override
    public int getInventorySize() {
        return 1;
    }

    /**
     * Add all modes you want, in order, here
     */
    @Override
    public void addValidModes() {
        validModes.add(EnumInputOutputMode.INPUT_ALL);
        validModes.add(EnumInputOutputMode.OUTPUT_ALL);
        validModes.add(EnumInputOutputMode.ALL_MODES);
    }

    /**
     * Return the list of upgrades by their id that are allowed in this machine
     *
     * @return A list of valid upgrades
     */
    @Override
    public List<String> getAcceptableUpgrades() {
        List<String> list = new ArrayList<>();
        list.add(IUpgradeItem.CPU_SINGLE_CORE);
        list.add(IUpgradeItem.CPU_DUAL_CORE);
        list.add(IUpgradeItem.CPU_QUAD_CORE);
        list.add(IUpgradeItem.CPU_OCT_CORE);
        list.add(IUpgradeItem.MEMORY_DDR1);
        list.add(IUpgradeItem.MEMORY_DDR2);
        list.add(IUpgradeItem.MEMORY_DDR3);
        list.add(IUpgradeItem.MEMORY_DDR4);
        list.add(IUpgradeItem.PSU_250W);
        list.add(IUpgradeItem.PSU_500W);
        list.add(IUpgradeItem.PSU_750W);
        list.add(IUpgradeItem.PSU_960W);
        list.add(IUpgradeItem.TRANSFORMER);
        list.add(IUpgradeItem.REDSTONE_CIRCUIT);
        list.add(IUpgradeItem.NETWORK_CARD);
        return list;
    }

    /**
     * Used to get how much energy to drain per tick, you should check for upgrades at this point
     *
     * @return How much energy to drain per tick
     */
    @Override
    public int getEnergyCostPerTick() {
        return BASE_ENERGY_TICK * getModifierForCategory(IUpgradeItem.ENUM_UPGRADE_CATEGORY.MEMORY)
                + ((getModifierForCategory(IUpgradeItem.ENUM_UPGRADE_CATEGORY.CPU) - 1) * 62);
    }

    /**
     * Used to get how long it takes to cook things, you should check for upgrades at this point
     *
     * @return The time it takes in ticks to cook the current item
     */
    @Override
    public int getCookTime() {
        return Math.max(500 - (((500 / 16) * getModifierForCategory(IUpgradeItem.ENUM_UPGRADE_CATEGORY.CPU) - 1)),
                5);
    }

    /**
     * Used to tell if this tile is able to process
     *
     * @return True if you are able to process
     */
    @Override
    public boolean canProcess() {
        if (energyStorage.getEnergyStored() > getEnergyCostPerTick() && tanks[TANK].getFluid() != null) {
            if (getStackInSlot(OUTPUT_SLOT) == null) {
                SolidifierRecipe recipe = ((SolidifierRecipeHandler) RecipeManager
                        .getHandler(RecipeManager.RecipeType.SOLIDIFIER))
                                .getRecipe(Pair.of(currentMode, tanks[TANK].getFluid()));
                if (recipe != null && tanks[TANK]
                        .getFluidAmount() >= AbstractRecipe.getFluidStackFromString(recipe.inputFluidStack).amount)
                    return true;
            } else {
                SolidifierRecipe recipe = ((SolidifierRecipeHandler) RecipeManager
                        .getHandler(RecipeManager.RecipeType.SOLIDIFIER))
                                .getRecipe(Pair.of(currentMode, tanks[TANK].getFluid()));
                if (recipe != null) {
                    ItemStack output = AbstractRecipe.getItemStackFromString(recipe.outputItemStack);
                    if (tanks[TANK].getFluidAmount() >= AbstractRecipe
                            .getFluidStackFromString(recipe.inputFluidStack).amount) {
                        ItemStack ourStack = getStackInSlot(OUTPUT_SLOT);
                        if (output.getItem() == ourStack.getItem()
                                && output.getItemDamage() == ourStack.getItemDamage()
                                && ourStack.getCount() + output.getCount() <= ourStack.getMaxStackSize())
                            return true;
                    }
                }
                return false;
            }
        }
        failCoolDown = 40;
        return false;
    }

    /**
     * Used to actually cook the item
     */
    @Override
    protected void cook() {
        cookTime++;
    }

    /**
     * Called when the tile has completed the cook process
     */
    @Override
    protected void completeCook() {
        for (int x = 0; x < getModifierForCategory(IUpgradeItem.ENUM_UPGRADE_CATEGORY.MEMORY); x++) {
            if (canProcess()) {
                if (tanks[TANK].getFluid() != null) {
                    SolidifierRecipe recipe = ((SolidifierRecipeHandler) RecipeManager
                            .getHandler(RecipeManager.RecipeType.SOLIDIFIER))
                                    .getRecipe(Pair.of(currentMode, tanks[TANK].getFluid()));
                    ItemStack output = AbstractRecipe.getItemStackFromString(recipe.outputItemStack);
                    FluidStack drainedStack = drain(
                            AbstractRecipe.getFluidStackFromString(recipe.inputFluidStack).amount, false);
                    if (drainedStack != null
                            && drainedStack.amount == AbstractRecipe
                                    .getFluidStackFromString(recipe.inputFluidStack).amount
                            && output != null
                            && (getStackInSlot(OUTPUT_SLOT) == null || getStackInSlot(OUTPUT_SLOT).getCount()
                                    + output.getCount() <= getStackInSlot(OUTPUT_SLOT).getMaxStackSize())) {
                        // Drain
                        drain(AbstractRecipe.getFluidStackFromString(recipe.inputFluidStack).amount, true);
                        if (!getStackInSlot(OUTPUT_SLOT).isEmpty())
                            getStackInSlot(OUTPUT_SLOT).grow(output.getCount());
                        else
                            setStackInSlot(OUTPUT_SLOT, output);
                    }
                }
            } else
                break;
        }
        markForUpdate(6);
    }

    /**
     * Get the output of the recipe
     *
     * @param input The input
     * @return The output
     */
    @Override
    public ItemStack getOutput(FluidStack input) {
        return ((SolidifierRecipeHandler) RecipeManager.getHandler(RecipeManager.RecipeType.SOLIDIFIER))
                .getOutput(Pair.of(currentMode, input));
    }

    /**
     * Get the output of the recipe (used in insert options)
     *
     * @param input The input
     * @return The output
     */
    @Override
    public ItemStack getOutputForStack(ItemStack input) {
        return ItemStack.EMPTY;
    }

    /*******************************************************************************************************************
     * Tile Methods                                                                                                    *
     *******************************************************************************************************************/

    /**
     * This will try to take things from other inventories and put it into ours
     */
    @Override
    public void tryInput() {
        for (EnumFacing dir : EnumFacing.values()) {
            if (canInputFromSide(dir, true)) {
                if (world.getTileEntity(pos.offset(dir)) != null && world.getTileEntity(pos.offset(dir))
                        .hasCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, dir.getOpposite())) {
                    IFluidHandler otherTank = world.getTileEntity(pos.offset(dir))
                            .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, dir.getOpposite());

                    // Try and match us
                    if (tanks[TANK].getFluid() != null && otherTank.drain(tanks[TANK].getFluid(), false) != null) {
                        int amount = fill(otherTank.drain(tanks[TANK].getFluid(), false), false);
                        if (amount > 0) {
                            fill(otherTank.drain(amount, true), true);
                            markForUpdate(6);
                        }
                    }

                    // Can we accept
                    else if (tanks[TANK].getFluid() == null && otherTank.drain(1000, false) != null) {
                        int amount = fill(otherTank.drain(1000, false), false);
                        if (amount > 0) {
                            fill(otherTank.drain(amount, true), true);
                            markForUpdate(6);
                        }
                    }
                }
            }
        }
    }

    /**
     * This will try to take things from our inventory and try to place them in others
     */
    @Override
    public void tryOutput() {
        for (EnumFacing dir : EnumFacing.values()) {
            if (canOutputFromSide(dir, true))
                InventoryUtils.moveItemInto(this, OUTPUT_SLOT, world.getTileEntity(pos.offset(dir)), -1, 64,
                        dir.getOpposite(), true, false, true);
        }
    }

    @Override
    public NBTTagCompound writeToNBT(NBTTagCompound compound) {
        super.writeToNBT(compound);
        compound.setInteger("ProcessMode", currentMode.ordinal());
        return compound;
    }

    @Override
    public void readFromNBT(NBTTagCompound compound) {
        super.readFromNBT(compound);
        currentMode = SolidifierMode.values()[compound.getInteger("ProcessMode")];
    }

    /**
     * Used to expose the item handler capability, in child classes, manage input and output based on this
     *
     * @param dir The direction
     * @return The item handler
     */
    @Nullable
    @Override
    protected IItemHandler getItemHandlerCapability(EnumFacing dir) {
        return getModeForSide(dir) == EnumInputOutputMode.DEFAULT || canOutputFromSide(dir, true)
                ? super.getItemHandlerCapability(dir)
                : null;
    }

    /**
     * Used to get the fluid handler for exposing
     *
     * @param dir The direction
     * @return The fluid handler
     */
    @Nullable
    @Override
    protected IFluidHandler getFluidHandlerCapability(EnumFacing dir) {
        return getModeForSide(dir) == EnumInputOutputMode.DEFAULT || canInputFromSide(dir, true)
                ? super.getFluidHandlerCapability(dir)
                : null;
    }

    /**
     * Used to set the variable for this tile, the Syncable will use this when you send a value to the server
     *
     * @param id    The ID of the variable to send
     * @param value The new value to set to (you can use this however you want, eg using the ordinal of EnumFacing)
     */
    @Override
    public void setVariable(int id, double value) {
        if (id == UPDATE_MODE_NBT)
            toggleMode();
        super.setVariable(id, value);
    }

    /**
     * Toggles what mode we are in
     */
    public void toggleMode() {
        currentMode = currentMode.getNextMode();
    }

    /*******************************************************************************************************************
     * Inventory Methods                                                                                               *
     *******************************************************************************************************************/

    /**
     * Used to get what slots are allowed to be output
     *
     * @param mode
     * @return The slots to output from
     */
    @Override
    public int[] getOutputSlots(EnumInputOutputMode mode) {
        return new int[] { OUTPUT_SLOT };
    }

    /**
     * Used to get what slots are allowed to be input
     *
     * @param mode
     * @return The slots to input from
     */
    @Override
    public int[] getInputSlots(EnumInputOutputMode mode) {
        return new int[0];
    }

    /*******************************************************************************************************************
     * FluidHandler Methods                                                                                            *
     *******************************************************************************************************************/

    /**
     * Method to define if this tile is a fluid handler
     *
     * @return False by default, override in child classes to enable fluid handling
     */
    @Override
    public boolean isFluidHandler() {
        return true;
    }

    /**
     * Used to set up the tanks needed. You can insert any number of tanks
     *
     * MUST OVERRIDE IN CHILD CLASSES IF isFluidHandler RETURNS TRUE
     */
    @Override
    protected void setupTanks() {
        tanks = new FluidTank[1];
        tanks[0] = new FluidTank(10 * MetalManager.BLOCK_MB);
    }

    /**
     * Which tanks can input
     *
     * MUST OVERRIDE IN CHILD CLASSES IF isFluidHandler RETURNS TRUE
     *
     * @return An array with the indexes of the input tanks
     */
    @Override
    protected int[] getInputTanks() {
        return new int[] { TANK };
    }

    /**
     * Which tanks can output
     *
     * MUST OVERRIDE IN CHILD CLASSES IF isFluidHandler RETURNS TRUE
     *
     * @return An array with the indexes of the output tanks
     */
    @Override
    protected int[] getOutputTanks() {
        return new int[] { TANK };
    }

    /**
     * Returns true if the given fluid can be inserted
     *
     * More formally, this should return true if fluid is able to enter
     *
     * @param fluid
     */
    @Override
    protected boolean canFill(Fluid fluid) {
        return fluid != null
                && ((tanks[TANK].getFluid() == null && RecipeManager.getHandler(RecipeManager.RecipeType.SOLIDIFIER)
                        .isValidInput(Pair.of(currentMode, new FluidStack(fluid, currentMode.getRequiredAmount()))))
                        || (tanks[TANK].getFluid() != null && fluid == tanks[TANK].getFluid().getFluid()));
    }

    /*******************************************************************************************************************
     * Misc Methods                                                                                                    *
     *******************************************************************************************************************/

    /**
     * Return the container for this tile
     *
     * @param id       Id, probably not needed but could be used for multiple guis
     * @param player   The player that is opening the gui
     * @param world The world
     * @param x        X Pos
     * @param y        Y Pos
     * @param z        Z Pos
     * @return The container to open
     */
    @Override
    public Object getServerGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) {
        return new ContainerSolidifier(player.inventory, this);
    }

    /**
     * Return the gui for this tile
     *
     * @param id       Id, probably not needed but could be used for multiple guis
     * @param player   The player that is opening the gui
     * @param world The world
     * @param x        X Pos
     * @param y        Y Pos
     * @param z        Z Pos
     * @return The gui to open
     */
    @Override
    public Object getClientGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) {
        return new GuiSolidifier(player, this);
    }

    /**
     * Used to get the description to display on the tab
     *
     * @return The long string with the description
     */
    @Override
    public String getDescription() {
        return "" + GuiColor.GREEN + GuiTextFormat.BOLD + GuiTextFormat.UNDERLINE
                + ClientUtils.translate("neotech.text.stats") + ":\n" + GuiColor.YELLOW + GuiTextFormat.BOLD
                + ClientUtils.translate("neotech.text.energyUsage") + ":\n" + GuiColor.WHITE + "  "
                + ClientUtils.formatNumber(getEnergyCostPerTick()) + " RF/tick\n" + GuiColor.YELLOW
                + GuiTextFormat.BOLD + ClientUtils.translate("neotech.text.processTime") + ":\n" + GuiColor.WHITE
                + "  " + getCookTime() + " ticks\n" + GuiColor.YELLOW + GuiTextFormat.BOLD
                + ClientUtils.translate("neotech.text.operations") + ":\n" + GuiColor.WHITE + "  "
                + getModifierForCategory(IUpgradeItem.ENUM_UPGRADE_CATEGORY.MEMORY) + "\n\n" + GuiColor.WHITE
                + ClientUtils.translate("neotech.electricSolidifier.desc") + "\n\n" + GuiColor.GREEN
                + GuiTextFormat.BOLD + GuiTextFormat.UNDERLINE + ClientUtils.translate("neotech.text.upgrade")
                + ":\n" + GuiTextFormat.RESET + GuiColor.YELLOW + GuiTextFormat.BOLD
                + ClientUtils.translate("neotech.text.processors") + ":\n" + GuiColor.WHITE
                + ClientUtils.translate("neotech.electricFurnace.processorUpgrade.desc") + "\n\n" + GuiColor.YELLOW
                + GuiTextFormat.BOLD + ClientUtils.translate("neotech.text.memory") + ":\n" + GuiColor.WHITE
                + ClientUtils.translate("neotech.electricFurnace.memoryUpgrade.desc") + "\n\n" + GuiColor.YELLOW
                + GuiTextFormat.BOLD + ClientUtils.translate("neotech.text.psu") + ":\n" + GuiColor.WHITE
                + ClientUtils.translate("neotech.electricFurnace.psuUpgrade.desc") + "\n\n" + GuiColor.YELLOW
                + GuiTextFormat.BOLD + ClientUtils.translate("neotech.text.control") + ":\n" + GuiColor.WHITE
                + ClientUtils.translate("neotech.electricFurnace.controlUpgrade.desc") + "\n\n" + GuiColor.YELLOW
                + GuiTextFormat.BOLD + ClientUtils.translate("neotech.text.network") + ":\n" + GuiColor.WHITE
                + ClientUtils.translate("neotech.electricFurnace.networkUpgrade.desc");
    }

    /**
     * Used to output the redstone single from this structure
     *
     * Use a range from 0 - 16.
     *
     * 0 Usually means that there is nothing in the tile, so take that for lowest level. Like the generator has no energy while
     * 16 is usually the flip side of that. Output 16 when it is totally full and not less
     *
     * @return int range 0 - 16
     */
    @Override
    public int getRedstoneOutput() {
        return isActive() ? 16 : 0;
    }

    /**
     * Used to get what particles to spawn. This will be called when the tile is active
     *
     * @param xPos
     * @param yPos
     * @param zPos
     */
    @Override
    public void spawnActiveParticles(double xPos, double yPos, double zPos) {
        world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, xPos, yPos, zPos, 0, 0, 0);
        world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, xPos, yPos, zPos, 0, 0, 0);
        world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, xPos, yPos, zPos, 0, 0, 0);
    }
}