buildcraft.silicon.TileAssemblyTable.java Source code

Java tutorial

Introduction

Here is the source code for buildcraft.silicon.TileAssemblyTable.java

Source

/**
 * Copyright (c) 2011-2015, SpaceToad and the BuildCraft Team
 * http://www.mod-buildcraft.com
 *
 * BuildCraft is distributed under the terms of the Minecraft Mod Public
 * License 1.0, or MMPL. Please check the contents of the license located in
 * http://www.mod-buildcraft.com/MMPL-1.0.txt
 */
package buildcraft.silicon;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;

import io.netty.buffer.ByteBuf;

import net.minecraft.entity.item.EntityItem;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.nbt.NBTTagString;

import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.relauncher.Side;

import net.minecraftforge.common.util.Constants;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.FluidStack;

import buildcraft.BuildCraftCore;
import buildcraft.api.recipes.CraftingResult;
import buildcraft.api.recipes.IFlexibleCrafter;
import buildcraft.api.recipes.IFlexibleRecipe;
import buildcraft.core.network.CommandWriter;
import buildcraft.core.network.ICommandReceiver;
import buildcraft.core.network.PacketCommand;
import buildcraft.core.recipes.AssemblyRecipeManager;
import buildcraft.core.utils.StringUtils;
import buildcraft.core.utils.Utils;
import buildcraft.robots.EntityRobot;
import buildcraft.robots.ResourceIdAssemblyTable;
import buildcraft.robots.RobotRegistry;

public class TileAssemblyTable extends TileLaserTableBase
        implements IInventory, IFlexibleCrafter, ICommandReceiver {
    public String currentRecipeId = "";
    public IFlexibleRecipe<ItemStack> currentRecipe;
    private HashSet<String> plannedOutput = new HashSet<String>();
    private boolean queuedNetworkUpdate = false;

    public List<CraftingResult<ItemStack>> getPotentialOutputs() {
        List<CraftingResult<ItemStack>> result = new LinkedList<CraftingResult<ItemStack>>();

        for (IFlexibleRecipe recipe : AssemblyRecipeManager.INSTANCE.getRecipes()) {
            CraftingResult<ItemStack> r = recipe.craft(this, true);

            if (r != null) {
                result.add(r);
            }
        }

        return result;
    }

    private void queueNetworkUpdate() {
        queuedNetworkUpdate = true;
    }

    @Override
    public boolean canUpdate() {
        return !FMLCommonHandler.instance().getEffectiveSide().isClient();
    }

    @Override
    public void updateEntity() { // WARNING: run only server-side, see canUpdate()
        super.updateEntity();

        if (queuedNetworkUpdate) {
            sendNetworkUpdate();
            queuedNetworkUpdate = false;
        }

        if (currentRecipe == null) {
            return;
        }

        if (!currentRecipe.canBeCrafted(this)) {
            setNextCurrentRecipe();

            if (currentRecipe == null) {
                return;
            }
        }

        if (getEnergy() >= currentRecipe.craft(this, true).energyCost) {
            setEnergy(0);

            if (currentRecipe.canBeCrafted(this)) {
                ItemStack remaining = currentRecipe.craft(this, false).crafted.copy();

                EntityRobot robot = RobotRegistry.getRegistry(worldObj)
                        .robotTaking(new ResourceIdAssemblyTable(this));

                if (robot != null) {
                    remaining = robot.receiveItem(this, remaining);
                }

                if (remaining != null && remaining.stackSize > 0) {
                    remaining.stackSize -= Utils.addToRandomInventoryAround(worldObj, xCoord, yCoord, zCoord,
                            remaining);
                }

                if (remaining != null && remaining.stackSize > 0) {
                    remaining.stackSize -= Utils.addToRandomInjectableAround(worldObj, xCoord, yCoord, zCoord,
                            ForgeDirection.UNKNOWN, remaining);
                }

                if (remaining != null && remaining.stackSize > 0) {
                    EntityItem entityitem = new EntityItem(worldObj, xCoord + 0.5, yCoord + 0.7, zCoord + 0.5,
                            remaining);

                    worldObj.spawnEntityInWorld(entityitem);
                }

                setNextCurrentRecipe();
            }
        }
    }

    /* IINVENTORY */
    @Override
    public int getSizeInventory() {
        return 12;
    }

    @Override
    public void setInventorySlotContents(int slot, ItemStack stack) {
        super.setInventorySlotContents(slot, stack);

        if (currentRecipe == null) {
            setNextCurrentRecipe();
        }
    }

    @Override
    public String getInventoryName() {
        return StringUtils.localize("tile.assemblyTableBlock.name");
    }

    @Override
    public void readData(ByteBuf stream) {
        super.readData(stream);
        currentRecipeId = Utils.readUTF(stream);
        plannedOutput.clear();
        int size = stream.readUnsignedByte();
        for (int i = 0; i < size; i++) {
            plannedOutput.add(Utils.readUTF(stream));
        }

        currentRecipe = AssemblyRecipeManager.INSTANCE.getRecipe(currentRecipeId);
    }

    @Override
    public void writeData(ByteBuf stream) {
        super.writeData(stream);
        Utils.writeUTF(stream, currentRecipeId);
        stream.writeByte(plannedOutput.size());
        for (String s : plannedOutput) {
            Utils.writeUTF(stream, s);
        }
    }

    @Override
    public void readFromNBT(NBTTagCompound nbt) {
        super.readFromNBT(nbt);

        NBTTagList list = nbt.getTagList("plannedIds", Constants.NBT.TAG_STRING);

        for (int i = 0; i < list.tagCount(); ++i) {
            IFlexibleRecipe<ItemStack> recipe = AssemblyRecipeManager.INSTANCE.getRecipe(list.getStringTagAt(i));

            if (recipe != null) {
                plannedOutput.add(recipe.getId());
            }
        }

        if (nbt.hasKey("recipeId")) {
            IFlexibleRecipe<ItemStack> recipe = AssemblyRecipeManager.INSTANCE.getRecipe(nbt.getString("recipeId"));

            if (recipe != null) {
                setCurrentRecipe(recipe);
            }
        }
    }

    @Override
    public void writeToNBT(NBTTagCompound nbt) {
        super.writeToNBT(nbt);

        NBTTagList list = new NBTTagList();

        for (String recipe : plannedOutput) {
            list.appendTag(new NBTTagString(recipe));
        }

        nbt.setTag("plannedIds", list);

        if (currentRecipe != null) {
            nbt.setString("recipeId", currentRecipe.getId());
        }
    }

    public boolean isPlanned(IFlexibleRecipe recipe) {
        if (recipe == null) {
            return false;
        }

        return plannedOutput.contains(recipe.getId());
    }

    public boolean isAssembling(IFlexibleRecipe recipe) {
        return recipe != null && recipe == currentRecipe;
    }

    private void setCurrentRecipe(IFlexibleRecipe<ItemStack> recipe) {
        currentRecipe = recipe;

        if (recipe != null) {
            currentRecipeId = recipe.getId();
        } else {
            currentRecipeId = "";
        }

        if (worldObj != null && !worldObj.isRemote) {
            queueNetworkUpdate();
        }
    }

    @Override
    public int getRequiredEnergy() {
        if (currentRecipe != null) {
            CraftingResult<ItemStack> result = currentRecipe.craft(this, true);

            if (result != null) {
                return result.energyCost;
            } else {
                return 0;
            }
        } else {
            return 0;
        }
    }

    public void planOutput(IFlexibleRecipe<ItemStack> recipe) {
        if (recipe != null && !isPlanned(recipe)) {
            plannedOutput.add(recipe.getId());

            if (!isAssembling(currentRecipe) || !isPlanned(currentRecipe)) {
                setCurrentRecipe(recipe);
            }

            queueNetworkUpdate();
        }
    }

    public void cancelPlanOutput(IFlexibleRecipe<ItemStack> recipe) {
        if (isAssembling(recipe)) {
            setCurrentRecipe(null);
        }

        plannedOutput.remove(recipe.getId());

        if (!plannedOutput.isEmpty()) {
            setCurrentRecipe(AssemblyRecipeManager.INSTANCE.getRecipe(plannedOutput.iterator().next()));
        }

        queueNetworkUpdate();
    }

    public void setNextCurrentRecipe() {
        boolean takeNext = false;

        for (String recipeId : plannedOutput) {
            IFlexibleRecipe<ItemStack> recipe = AssemblyRecipeManager.INSTANCE.getRecipe(recipeId);

            if (recipe == null) {
                continue;
            }

            if (recipe == currentRecipe) {
                takeNext = true;
            } else if (takeNext && recipe.canBeCrafted(this)) {
                setCurrentRecipe(recipe);
                return;
            }
        }

        for (String recipeId : plannedOutput) {
            IFlexibleRecipe<ItemStack> recipe = AssemblyRecipeManager.INSTANCE.getRecipe(recipeId);

            if (recipe == null) {
                continue;
            }

            if (recipe.canBeCrafted(this)) {
                setCurrentRecipe(recipe);
                return;
            }
        }

        setCurrentRecipe(null);
    }

    public void rpcSelectRecipe(final String id, final boolean select) {
        BuildCraftCore.instance.sendToServer(new PacketCommand(this, "select", new CommandWriter() {
            public void write(ByteBuf data) {
                Utils.writeUTF(data, id);
                data.writeBoolean(select);
            }
        }));
    }

    @Override
    public void receiveCommand(String command, Side side, Object sender, ByteBuf stream) {
        if (side.isServer() && "select".equals(command)) {
            String id = Utils.readUTF(stream);
            boolean select = stream.readBoolean();

            IFlexibleRecipe<ItemStack> recipe = AssemblyRecipeManager.INSTANCE.getRecipe(id);

            if (recipe != null) {
                if (select) {
                    planOutput(recipe);
                } else {
                    cancelPlanOutput(recipe);
                }
            }
        }
    }

    @Override
    public boolean hasWork() {
        return currentRecipe != null;
    }

    @Override
    public boolean canCraft() {
        return hasWork();
    }

    @Override
    public boolean isItemValidForSlot(int slot, ItemStack stack) {
        return true;
    }

    @Override
    public boolean hasCustomInventoryName() {
        return false;
    }

    @Override
    public int getCraftingItemStackSize() {
        return getSizeInventory();
    }

    @Override
    public ItemStack getCraftingItemStack(int slotid) {
        return getStackInSlot(slotid);
    }

    @Override
    public ItemStack decrCraftingItemStack(int slotid, int val) {
        return decrStackSize(slotid, val);
    }

    @Override
    public FluidStack getCraftingFluidStack(int tankid) {
        return null;
    }

    @Override
    public FluidStack decrCraftingFluidStack(int tankid, int val) {
        return null;
    }

    @Override
    public int getCraftingFluidStackSize() {
        return 0;
    }
}