com.builtbroken.icbm.content.crafting.station.warhead.TileWarheadStation.java Source code

Java tutorial

Introduction

Here is the source code for com.builtbroken.icbm.content.crafting.station.warhead.TileWarheadStation.java

Source

package com.builtbroken.icbm.content.crafting.station.warhead;

import com.builtbroken.icbm.ICBM;
import com.builtbroken.icbm.api.modules.IWarhead;
import com.builtbroken.icbm.api.warhead.ITrigger;
import com.builtbroken.icbm.api.warhead.ITriggerAccepter;
import com.builtbroken.icbm.api.warhead.IWarheadItem;
import com.builtbroken.mc.api.automation.IAutomatedCrafter;
import com.builtbroken.mc.api.automation.IAutomation;
import com.builtbroken.mc.api.modules.IModule;
import com.builtbroken.mc.api.modules.IModuleItem;
import com.builtbroken.mc.api.tile.IGuiTile;
import com.builtbroken.mc.core.network.IPacketIDReceiver;
import com.builtbroken.mc.core.network.packet.PacketTile;
import com.builtbroken.mc.core.network.packet.PacketType;
import com.builtbroken.mc.lib.transform.vector.Pos;
import com.builtbroken.mc.lib.world.explosive.ExplosiveRegistry;
import com.builtbroken.mc.prefab.inventory.InventoryUtility;
import com.builtbroken.mc.prefab.tile.Tile;
import com.builtbroken.mc.prefab.tile.TileModuleMachine;
import com.builtbroken.mc.prefab.tile.module.TileModuleInventory;
import io.netty.buffer.ByteBuf;
import net.minecraft.block.material.Material;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.common.util.ForgeDirection;

import java.util.ArrayList;
import java.util.List;

/**
 * Handles crafting and configuration of warheads
 *
 * @see <a href="https://github.com/BuiltBrokenModding/VoltzEngine/blob/development/license.md">License</a> for what you can and can't do with the code.
 * Created by Dark(DarkGuardsman, Robert) on 1/6/2016.
 */
public class TileWarheadStation extends TileModuleMachine
        implements IPacketIDReceiver, IGuiTile, IAutomatedCrafter {
    public static final int WARHEAD_SLOT = 0;
    public static final int EXPLOSIVE_SLOT = 1;
    public static final int OUTPUT_SLOT = 2;
    public static final int TRIGGER_SLOT = 3;
    public static final int[] INPUT_SLOTS = new int[] { WARHEAD_SLOT, EXPLOSIVE_SLOT, TRIGGER_SLOT };
    public static final int[] OUTPUT_SLOTS = new int[] { OUTPUT_SLOT };

    //TODO add pushing to next station (Saves on inserters)
    //TODO add animation for moving missile to next station
    //TODO to sync animation add a handler that chains all station into an AssemblyLine object

    /** Is the machine setup to autocraft */
    protected boolean isAutocrafting = false;
    /** Forced auto explosive to check for trigger before crafting */
    protected boolean requireExplosive = true;
    /** Forced auto crafter to check for trigger before crafting */
    protected boolean requireTrigger = false;
    /** Triggers crafting logic. */
    protected boolean checkForCraft = false;
    /** Number of explosives to craft */
    protected int explosiveStackSizeRequired = 1;

    public TileWarheadStation() {
        super("warheadStation", Material.iron);
        this.resistance = 10f;
        this.hardness = 10f;
        this.renderTileEntity = true;
        this.renderNormalBlock = false;
    }

    @Override
    public Tile newTile() {
        return new TileWarheadStation();
    }

    @Override
    public void update() {
        super.update();
        if (isServer() && ticks % 10 == 0) {
            if (checkForCraft) {
                checkForCraft = false;
                //TODO add crafting timer
                if (canCraft()) {
                    doCrafting();
                }
            }
        }
    }

    /** Called to process a crafting request */
    public void doCrafting() {
        final ItemStack warheadStack = getWarheadStack();
        final ItemStack explosiveStack = getExplosiveStack();
        final ItemStack outputStack = getOutputStack();
        ItemStack triggerStack = getTriggerStack();

        if (warheadStack != null && warheadStack.getItem() instanceof IWarheadItem
                && ExplosiveRegistry.get(explosiveStack) != null
                && (outputStack == null || outputStack.stackSize < outputStack.getMaxStackSize())) {
            final IWarhead warhead = ((IWarheadItem) warheadStack.getItem()).getModule(warheadStack);
            if (warhead != null && warhead.hasSpaceForExplosives(explosiveStack)) {
                int insert = Math.min(explosiveStackSizeRequired,
                        Math.min(explosiveStack.stackSize, warhead.getSpaceForExplosives()));
                //Update warhead's explosive stack
                if (warhead.getExplosiveStack() == null) {
                    ItemStack insertStack = explosiveStack.copy();
                    insertStack.stackSize = insert;
                    warhead.setExplosiveStack(insertStack);
                } else {
                    //Increase explosive stack
                    warhead.getExplosiveStack().stackSize += insert;
                    //Trigger any events for warhead change
                    warhead.setExplosiveStack(warhead.getExplosiveStack());
                }

                //Install trigger
                if (triggerStack != null && warhead instanceof ITriggerAccepter
                        && ((ITriggerAccepter) warhead).getTrigger() == null) {
                    triggerStack = ((ITriggerAccepter) warhead).setTrigger(triggerStack);
                }

                final ItemStack newWarhead = warhead.toStack();

                if (outputStack == null || InventoryUtility.stacksMatch(newWarhead, outputStack)) {
                    //Decrease explosive stack
                    explosiveStack.stackSize -= insert;
                    if (explosiveStack.stackSize <= 0) {
                        getInventory().setInventorySlotContents(EXPLOSIVE_SLOT, null);
                    } else {
                        //Update inventory
                        getInventory().setInventorySlotContents(EXPLOSIVE_SLOT, explosiveStack);
                    }

                    //Decrease warhead stack (INPUT)
                    warheadStack.stackSize--;
                    if (warheadStack.stackSize <= 0) {
                        getInventory().setInventorySlotContents(WARHEAD_SLOT, null);
                    } else {
                        //Update inventory
                        getInventory().setInventorySlotContents(WARHEAD_SLOT, warheadStack);
                    }
                    //Update trigger slot inventory
                    setInventorySlotContents(TRIGGER_SLOT, triggerStack);

                    //Increase output
                    if (getOutputStack() == null) {
                        getInventory().setInventorySlotContents(OUTPUT_SLOT, newWarhead);
                    } else {
                        outputStack.stackSize += 1;
                        getInventory().setInventorySlotContents(OUTPUT_SLOT, outputStack);
                    }
                }
            }
        }
    }

    /**
     * Checks if it is possible to process a crafting recipe
     *
     * @return true if possible
     */
    public boolean canCraft() {
        if (getWarheadStack() != null) {
            IWarhead result = getCraftResultAsWarhead();
            if (result != null) {
                if (isAutocrafting) {
                    if (requireTrigger && result instanceof ITriggerAccepter
                            && ((ITriggerAccepter) result).getTrigger() == null) {
                        return false;
                    }
                    if (requireExplosive) {
                        if (result.getExplosiveStack() == null) {
                            return false;
                        } else if (result.getExplosiveStack().stackSize < explosiveStackSizeRequired) {
                            return false;
                        }
                    }
                }
                //Check if we have space
                return getOutputStack() == null || InventoryUtility.stacksMatch(getCraftResult(), result.toStack())
                        && InventoryUtility.roomLeftInSlot(this, OUTPUT_SLOT) > 0;
            }
        }
        return false;
    }

    @Override
    public float getCraftingProgress() {
        return 0;
    }

    @Override
    public List<ItemStack> getRequiredItems() {
        return new ArrayList();
    }

    @Override
    public ItemStack insertRequiredItem(ItemStack stack, IAutomation entity, ForgeDirection side) {
        if (isAutocrafting && stack != null) {
            if (stack.getItem() instanceof IModuleItem) {
                final IModule module = ((IModuleItem) stack.getItem()).getModule(stack);
                if (module instanceof IWarhead) {
                    if (getWarheadStack() == null) {
                        ItemStack insert = stack.copy();
                        insert.stackSize = 1;
                        setInventorySlotContents(WARHEAD_SLOT, insert);
                        stack.stackSize -= 1;
                        checkForCraft = true;
                        return stack;
                    }
                } else if (module instanceof ITrigger) {
                    if (getTriggerStack() == null) {
                        ItemStack insert = stack.copy();
                        insert.stackSize = 1;
                        setInventorySlotContents(TRIGGER_SLOT, insert);
                        stack.stackSize -= 1;
                        checkForCraft = true;
                        return stack;
                    }
                }
            } else if (ExplosiveRegistry.get(stack) != null) {
                if (getTriggerStack() == null) {
                    ItemStack insert = stack.copy();
                    insert.stackSize = 1;
                    setInventorySlotContents(EXPLOSIVE_SLOT, insert);
                    stack.stackSize -= 1;
                    checkForCraft = true;
                    return stack;
                }
            }
        }
        return stack;
    }

    @Override
    public ItemStack insertRequiredItem(ItemStack stack, int slot, IAutomation entity, ForgeDirection side) {
        if (isAutocrafting && stack != null) {
            if ((slot == WARHEAD_SLOT || slot == TRIGGER_SLOT) && stack.getItem() instanceof IModuleItem) {
                final IModule module = ((IModuleItem) stack.getItem()).getModule(stack);
                if (slot == WARHEAD_SLOT && module instanceof IWarhead) {
                    if (getWarheadStack() == null) {
                        ItemStack insert = stack.copy();
                        insert.stackSize = 1;
                        setInventorySlotContents(WARHEAD_SLOT, insert);
                        stack.stackSize -= 1;
                        checkForCraft = true;
                        return stack.stackSize <= 0 ? null : stack;
                    }
                } else if (slot == TRIGGER_SLOT && module instanceof ITrigger) {
                    if (getTriggerStack() == null) {
                        ItemStack insert = stack.copy();
                        insert.stackSize = 1;
                        setInventorySlotContents(TRIGGER_SLOT, insert);
                        stack.stackSize -= 1;
                        checkForCraft = true;
                        return stack.stackSize <= 0 ? null : stack;
                    }
                }
            } else if (slot == EXPLOSIVE_SLOT && ExplosiveRegistry.get(stack) != null) {
                if (getExplosiveStack() == null) {
                    ItemStack insert = stack.copy();
                    insert.stackSize = 1;
                    setInventorySlotContents(EXPLOSIVE_SLOT, insert);
                    stack.stackSize -= 1;
                    checkForCraft = true;
                    return stack.stackSize <= 0 ? null : stack;
                } else if (InventoryUtility.stacksMatch(stack, getExplosiveStack())) {
                    final ItemStack explosiveStack = getExplosiveStack();
                    //Limit number of items to minimal required
                    if (explosiveStack.stackSize >= explosiveStackSizeRequired) {
                        return stack;
                    }
                    //Figure out out insert limit from space left, require items, and stack size of insert item
                    int insert = Math.min(explosiveStackSizeRequired,
                            InventoryUtility.roomLeftInSlot(this, EXPLOSIVE_SLOT));
                    insert = Math.min(stack.stackSize, insert);
                    //Increase explosive stack
                    explosiveStack.stackSize += insert;
                    //Update inventory
                    setInventorySlotContents(EXPLOSIVE_SLOT, explosiveStack);
                    //Decrease insert stack
                    stack.stackSize -= insert;
                    //Return
                    checkForCraft = true;
                    return stack.stackSize <= 0 ? null : stack;
                }
            }
        }
        return stack;
    }

    @Override
    public int[] getCraftingOutputSlots(IAutomation entity, ForgeDirection side) {
        return OUTPUT_SLOTS;
    }

    @Override
    public int[] getCraftingInputSlots(IAutomation entity, ForgeDirection side) {
        return INPUT_SLOTS;
    }

    @Override
    public boolean canStore(ItemStack stack, ForgeDirection side) {
        if (stack.getItem() instanceof IModuleItem) {
            final IModule module = ((IModuleItem) stack.getItem()).getModule(stack);
            return module instanceof IWarhead || module instanceof ITrigger;
        }
        return ExplosiveRegistry.get(stack) != null;
    }

    @Override
    public boolean canRemove(ItemStack stack, ForgeDirection side) {
        return true;
    }

    @Override
    public void onInventoryChanged(int slot, ItemStack prev, ItemStack item) {
        checkForCraft = true;
        sendDescPacket();
    }

    /**
     * Gets the expected output of a crafting recipe
     *
     * @return warhead
     */
    public IWarhead getCraftResultAsWarhead() {
        //Grab items from inventory
        final ItemStack warheadStack = getWarheadStack();
        final ItemStack explosiveStack = getExplosiveStack();
        final ItemStack triggerStack = getTriggerStack();

        //Check that the warhead stack contains a warhead
        if (warheadStack != null && warheadStack.getItem() instanceof IWarheadItem) {
            //Get warhead from stack
            final IWarhead warhead = ((IWarheadItem) warheadStack.getItem()).getModule(warheadStack);
            //Ensure it's not null
            if (warhead != null) {
                //Insert explosive
                if ((!isAutocrafting || requireExplosive) && ExplosiveRegistry.get(explosiveStack) != null
                        && warhead.hasSpaceForExplosives(explosiveStack)) {
                    //Figure out how many explosives are needed
                    int insert = Math.min(explosiveStackSizeRequired,
                            Math.min(explosiveStack.stackSize, warhead.getSpaceForExplosives()));
                    //Update warhead's explosive stack
                    if (warhead.getExplosiveStack() == null) {
                        ItemStack insertStack = explosiveStack.copy();
                        insertStack.stackSize = insert;
                        warhead.setExplosiveStack(insertStack);
                    } else {
                        //Increase explosive stack
                        warhead.getExplosiveStack().stackSize += insert;
                        //Trigger any events for warhead change
                        warhead.setExplosiveStack(warhead.getExplosiveStack());
                    }
                }

                //Insert trigger
                if ((!isAutocrafting || requireTrigger) && triggerStack != null
                        && warhead instanceof ITriggerAccepter
                        && ((ITriggerAccepter) warhead).getTrigger() == null) {
                    ((ITriggerAccepter) warhead).setTrigger(triggerStack);
                }
                return warhead;
            }
        }
        return null;
    }

    /**
     * Gets the expected output of a crafting recipe
     *
     * @return ItemStack, or null if not possible to craft
     */
    public ItemStack getCraftResult() {
        final IWarhead result = getCraftResultAsWarhead();
        return result != null ? result.toStack() : null;
    }

    @Override
    public boolean canStore(ItemStack stack, int slot, ForgeDirection side) {
        if (stack != null) {
            if (WARHEAD_SLOT == slot) {
                return stack.getItem() instanceof IModuleItem
                        && ((IModuleItem) stack.getItem()).getModule(stack) instanceof IWarhead;
            } else if (EXPLOSIVE_SLOT == slot) {
                return ExplosiveRegistry.get(stack) != null;
            } else if (TRIGGER_SLOT == slot) {
                return stack.getItem() instanceof IModuleItem
                        && ((IModuleItem) stack.getItem()).getModule(stack) instanceof ITrigger;
            }
        }
        return false;
    }

    @Override
    public boolean canRemove(ItemStack stack, int slot, ForgeDirection side) {
        return slot == OUTPUT_SLOT;
    }

    @Override
    protected boolean onPlayerRightClick(EntityPlayer player, int side, Pos hit) {
        if (isServer()) {
            openGui(player, ICBM.INSTANCE);
        }
        return true;
    }

    @Override
    public TileModuleInventory getInventory() {
        if (super.getInventory() == null) {
            //lazy init of inventory
            addInventoryModule(4);
        }
        return (TileModuleInventory) super.getInventory();
    }

    protected ItemStack getWarheadStack() {
        return getInventory().getStackInSlot(WARHEAD_SLOT);
    }

    protected ItemStack getExplosiveStack() {
        return getInventory().getStackInSlot(EXPLOSIVE_SLOT);
    }

    protected ItemStack getOutputStack() {
        return getInventory().getStackInSlot(OUTPUT_SLOT);
    }

    protected ItemStack getTriggerStack() {
        return getInventory().getStackInSlot(TRIGGER_SLOT);
    }

    @Override
    public boolean read(ByteBuf buf, int id, EntityPlayer player, PacketType type) {
        super.doUpdateGuiUsers();
        if (!super.read(buf, id, player, type)) {
            if (isServer()) {
                if (id == 1) {
                    doCrafting();
                    return true;
                } else if (id == 2) {
                    openGui(player, buf.readInt(), ICBM.INSTANCE);
                    return true;
                }
                //Gui updated some settings
                else if (id == 3) {
                    isAutocrafting = buf.readBoolean();
                    explosiveStackSizeRequired = Math.min(Math.max(1, buf.readInt()), 64);
                    requireExplosive = buf.readBoolean();
                    requireTrigger = buf.readBoolean();
                    _doUpdateGuiUsers();
                    return true;
                }
            }
            return false;
        }
        return true;
    }

    @Override
    public void writeDescPacket(ByteBuf buf) {
        super.writeDescPacket(buf);
    }

    @Override
    public void readFromNBT(NBTTagCompound nbt) {
        super.readFromNBT(nbt);
        isAutocrafting = getBoolean(nbt, "isAutocrafting", false);
        requireExplosive = getBoolean(nbt, "requireExplosive", true);
        requireTrigger = getBoolean(nbt, "requireTrigger", false);
        checkForCraft = getBoolean(nbt, "checkForCraft", false);
        if (nbt.hasKey("explosiveStackSizeRequired")) {
            explosiveStackSizeRequired = nbt.getInteger("explosiveStackSizeRequired");
        }
    }

    private boolean getBoolean(NBTTagCompound nbt, String key, boolean b) {
        return nbt.hasKey(key) ? nbt.getBoolean("isAutocrafting") : b;
    }

    @Override
    public void writeToNBT(NBTTagCompound nbt) {
        super.writeToNBT(nbt);
        nbt.setBoolean("isAutocrafting", isAutocrafting);
        nbt.setBoolean("requireExplosive", requireExplosive);
        nbt.setBoolean("requireTrigger", requireTrigger);
        nbt.setBoolean("checkForCraft", checkForCraft);
        nbt.setInteger("explosiveStackSizeRequired", explosiveStackSizeRequired);
    }

    @Override
    public void doUpdateGuiUsers() {
        if (ticks % 5 == 0) {
            _doUpdateGuiUsers();
        }
    }

    public void _doUpdateGuiUsers() {
        PacketTile packet = new PacketTile(this, 5, isAutocrafting, explosiveStackSizeRequired, requireExplosive,
                requireTrigger);
        sendPacketToGuiUsers(packet);
    }

    @Override
    public Object getServerGuiElement(int ID, EntityPlayer player) {
        return new ContainerWarheadStation(player, this, ID);
    }

    @Override
    public Object getClientGuiElement(int ID, EntityPlayer player) {
        return null;
    }
}