com.bluepowermod.part.gate.ic.IntegratedCircuit.java Source code

Java tutorial

Introduction

Here is the source code for com.bluepowermod.part.gate.ic.IntegratedCircuit.java

Source

/*
 * This file is part of Blue Power. Blue Power is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Blue Power is
 * distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along
 * with Blue Power. If not, see <http://www.gnu.org/licenses/>
 */
package com.bluepowermod.part.gate.ic;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.IIcon;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.IItemRenderer.ItemRenderType;
import net.minecraftforge.common.util.ForgeDirection;

import org.lwjgl.opengl.GL11;

import uk.co.qmunity.lib.client.render.RenderHelper;
import uk.co.qmunity.lib.part.IMicroblock;
import uk.co.qmunity.lib.part.IPart;
import uk.co.qmunity.lib.part.ITilePartHolder;
import uk.co.qmunity.lib.part.PartRegistry;
import uk.co.qmunity.lib.raytrace.QMovingObjectPosition;
import uk.co.qmunity.lib.transform.Rotation;
import uk.co.qmunity.lib.util.Dir;
import uk.co.qmunity.lib.vec.Vec3d;
import uk.co.qmunity.lib.vec.Vec3dCube;
import uk.co.qmunity.lib.vec.Vec3i;

import com.bluepowermod.api.block.ISilkyRemovable;
import com.bluepowermod.api.misc.MinecraftColor;
import com.bluepowermod.item.ItemPart;
import com.bluepowermod.part.BPPart;
import com.bluepowermod.part.PartManager;
import com.bluepowermod.part.RedstoneConnection;
import com.bluepowermod.part.gate.GateBase;
import com.bluepowermod.part.gate.GateWire;
import com.bluepowermod.part.wire.redstone.PartRedwireFace;
import com.bluepowermod.part.wire.redstone.RedwireType;
import com.bluepowermod.util.Refs;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

public abstract class IntegratedCircuit extends GateBase implements ISilkyRemovable, ITilePartHolder {

    private GateBase[][] gates;
    private static double BORDER_WIDTH = 1 / 16D;
    private boolean isRenderingItem;

    @Override
    public void initializeConnections() {

        clearGateArray();
    }

    private void clearGateArray() {

        gates = new GateBase[getCircuitWidth()][];
        for (int i = 0; i < gates.length; i++) {
            gates[i] = new GateBase[gates.length];
        }
    }

    @Override
    public void addSelectionBoxes(List<Vec3dCube> boxes) {

        super.addSelectionBoxes(boxes);
        double minY = 1 / 16D;
        double maxY = 2 / 16D + 0.01;

        double gateWidth = (1.0 - 2 * BORDER_WIDTH) / getCircuitWidth();
        for (int x = 0; x < getCircuitWidth(); x++) {
            for (int y = 0; y < getCircuitWidth(); y++) {
                boxes.add(new Vec3dCube(BORDER_WIDTH + x * gateWidth, minY, BORDER_WIDTH + y * gateWidth,
                        BORDER_WIDTH + (x + 1) * gateWidth, maxY, BORDER_WIDTH + (y + 1) * gateWidth));
            }
        }
    }

    public int getGateIndex(GateBase part) {

        for (int i = 0; i < getCircuitWidth(); i++) {
            for (int j = 0; j < getCircuitWidth(); j++) {
                if (part == gates[i][j]) {
                    return i * getCircuitWidth() + j;
                }
            }
        }
        throw new IllegalArgumentException("Part not found in Integrated Circuit");
    }

    public GateBase getPartForIndex(int index) {

        return gates[index / getCircuitWidth()][index % getCircuitWidth()];
    }

    @Override
    public String getId() {

        return "integratedCircuit" + getCircuitWidth() + "x" + getCircuitWidth();
    }

    @Override
    protected String getTextureName() {

        return "integrated";
    }

    protected abstract int getCircuitWidth();

    @Override
    @SideOnly(Side.CLIENT)
    public void renderItem(ItemRenderType type, ItemStack item, Object... data) {

        isRenderingItem = true;
        super.renderItem(type, item, data);
        isRenderingItem = false;
    }

    @Override
    @SideOnly(Side.CLIENT)
    public boolean renderStatic(Vec3i translation, RenderHelper renderer, RenderBlocks renderBlocks, int pass) {

        switch (getFace()) {
        case DOWN:
            break;
        case UP:
            renderer.addTransformation(new Rotation(180, 180, 0, Vec3d.center));
            break;
        case NORTH:
            renderer.addTransformation(new Rotation(90, 0, 0, Vec3d.center));
            break;
        case SOUTH:
            renderer.addTransformation(new Rotation(-90, 0, 0, Vec3d.center));
            break;
        case WEST:
            renderer.addTransformation(new Rotation(0, 0, -90, Vec3d.center));
            break;
        case EAST:
            renderer.addTransformation(new Rotation(0, 0, 90, Vec3d.center));
            break;
        default:
            break;
        }

        int rotation = getRotation();
        renderer.addTransformation(new Rotation(0, 90 * -rotation, 0));

        if (rendering == null)
            rendering = this;

        IIcon[] icons = new IIcon[] { getIcon(ForgeDirection.DOWN), getIcon(ForgeDirection.UP),
                getIcon(ForgeDirection.WEST), getIcon(ForgeDirection.EAST), getIcon(ForgeDirection.NORTH),
                getIcon(ForgeDirection.SOUTH) };

        renderer.setRenderSide(ForgeDirection.UP, false);
        renderer.renderBox(new Vec3dCube(0, 0, 0, 1, 1 / 16D, 1), icons);
        renderer.setRenderSide(ForgeDirection.UP, true);

        renderer.renderBox(new Vec3dCube(0, 1 / 16D, 0, 1, 2 / 16D, 1 / 16D), icons);
        renderer.renderBox(new Vec3dCube(0, 1 / 16D, 15 / 16D, 1, 2 / 16D, 1), icons);
        renderer.renderBox(new Vec3dCube(0, 1 / 16D, 0, 1 / 16D, 2 / 16D, 1), icons);
        renderer.renderBox(new Vec3dCube(15 / 16D, 1 / 16D, 0, 1, 2 / 16D, 1), icons);

        rendering = null;

        renderer.resetTransformations();

        return true;
    }

    @Override
    @SideOnly(Side.CLIENT)
    protected void renderTop(float frame) {

        renderTop("front", front());
        renderTop("left", left());
        renderTop("back", back());
        renderTop("right", right());
        Vec3d loc = new Vec3d(0, 0, 0);

        RenderHelper rh = RenderHelper.instance;
        rh.reset();
        RenderBlocks rb = RenderBlocks.getInstance();

        GL11.glPushMatrix();
        {
            GL11.glTranslated(0, 2 / 16D - 1 / 16D * (1.0 / getCircuitWidth()), 0);
            GL11.glNormal3d(0, 1, 0);
            int size = getCircuitWidth();
            double textureMaxUV = 0.5 * size;

            Minecraft.getMinecraft().renderEngine.bindTexture(new ResourceLocation(
                    Refs.MODID + ":textures/blocks/gates/" + getTextureName() + "/checkerboard.png"));
            GL11.glBegin(GL11.GL_QUADS);
            {
                com.bluepowermod.client.render.RenderHelper.addVertexWithTexture(BORDER_WIDTH, 0, BORDER_WIDTH, 0,
                        0);
                com.bluepowermod.client.render.RenderHelper.addVertexWithTexture(BORDER_WIDTH, 0, 1 - BORDER_WIDTH,
                        0, textureMaxUV);
                com.bluepowermod.client.render.RenderHelper.addVertexWithTexture(1 - BORDER_WIDTH, 0,
                        1 - BORDER_WIDTH, textureMaxUV, textureMaxUV);
                com.bluepowermod.client.render.RenderHelper.addVertexWithTexture(1 - BORDER_WIDTH, 0, BORDER_WIDTH,
                        textureMaxUV, 0);
            }
            GL11.glEnd();
        }
        GL11.glPopMatrix();

        GL11.glPushMatrix();
        {
            GL11.glTranslated(BORDER_WIDTH, 2 / 16D + 0.001D, BORDER_WIDTH);
            GL11.glScaled((1 - 2 * BORDER_WIDTH) / 1, 1, (1 - 2 * BORDER_WIDTH) / 1);

            GL11.glScaled(1.0 / getCircuitWidth(), 1.0 / getCircuitWidth(), 1.0 / getCircuitWidth());
            GL11.glTranslated(0, -2 / 16D, 0);
            for (GateBase[] gateArray : gates) {
                GL11.glPushMatrix();
                for (GateBase gate : gateArray) {
                    if (gate != null) {
                        GL11.glPushMatrix();
                        gate.renderDynamic(loc, frame, 0);
                        GL11.glPopMatrix();

                        if (!isRenderingItem) {
                            // Static renderer
                            GL11.glPushMatrix();
                            {
                                Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.locationBlocksTexture);
                                Tessellator.instance.startDrawingQuads();
                                gate.renderStatic(new Vec3i(gate), rh, rb, 0);
                                Tessellator.instance.draw();
                            }
                            GL11.glPopMatrix();
                        }

                        rh.reset();
                    }
                    GL11.glTranslated(0, 0, 1);
                }
                GL11.glPopMatrix();
                GL11.glTranslated(1, 0, 0);
            }
        }
        GL11.glPopMatrix();
    }

    @Override
    public void doLogic() {

        try {
            reflectGates();
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    @Override
    public void tick() {

        super.tick();
        for (GateBase[] gateArray : gates) {
            for (GateBase gate : gateArray) {
                if (gate != null) {
                    gate.update();
                }
            }
        }
    }

    private void updateNeighborGates(int i, int j) {

        GateBase gate = gates[i][j];
        for (Dir dir : Dir.values()) {
            if (dir == Dir.TOP || dir == Dir.BOTTOM)
                continue;
            GateBase neighbor = getNeighbor(i, j, dir);
            ForgeDirection forgeDir = dir.getFD().getOpposite();

            if (neighbor != null) {

                Dir neighborDir = Dir.getDirection(ForgeDirection.UP, forgeDir, neighbor.getRotation())
                        .getOpposite();
                RedstoneConnection neighborConnection = neighbor.getConnection(neighborDir);

                if (gate != null) {
                    Dir gateDir = Dir.getDirection(ForgeDirection.UP, forgeDir, gate.getRotation());
                    RedstoneConnection gateConnection = gate.getConnection(gateDir);
                    if (neighborConnection.isEnabled() /* && !(neighbor instanceof GateWire) */) {
                        if (gateConnection.isEnabled() /* && !neighborConnection.isOutputOnly() */) {
                            // gateConnection.setInput(neighborConnection.getOutput());
                            neighborConnection.setInput(gateConnection.getOutput());
                            if (neighbor instanceof GateWire) {
                                updateWires();
                            }
                            neighbor.onUpdate();
                            reflectGates();
                            sendUpdatePacket();
                        }
                    }
                } else {
                    neighborConnection.setInput(0);
                    neighbor.onUpdate();
                    reflectGates();
                    sendUpdatePacket();
                }

            }
        }
    }

    public void updateNeighborGates(GateBase gate) {

        for (int i = 0; i < gates.length; i++) {
            for (int j = 0; j < gates[i].length; j++) {
                if (gate == gates[i][j]) {
                    updateNeighborGates(i, j);
                }
            }
        }
    }

    private GateBase getNeighbor(int x, int y, Dir faceDir) {

        if (faceDir == Dir.RIGHT && x > 0)
            return gates[x - 1][y];
        if (faceDir == Dir.LEFT && x < getCircuitWidth() - 1)
            return gates[x + 1][y];
        if (faceDir == Dir.BACK && y > 0)
            return gates[x][y - 1];
        if (faceDir == Dir.FRONT && y < getCircuitWidth() - 1)
            return gates[x][y + 1];
        return null;
    }

    private int getOffsetX(Dir faceDir) {

        return faceDir == Dir.RIGHT ? -1 : faceDir == Dir.LEFT ? 1 : 0;
    }

    private int getOffsetY(Dir faceDir) {

        return faceDir == Dir.BACK ? -1 : faceDir == Dir.FRONT ? 1 : 0;
    }

    private void updateWires() {

        List<GateWire> traversedWires = new ArrayList<GateWire>();
        for (int i = 0; i < getCircuitWidth(); i++) {
            for (int j = 0; j < getCircuitWidth(); j++) {
                if (gates[i][j] instanceof GateWire && !traversedWires.contains(gates[i][j])) {
                    int startSize = traversedWires.size();
                    int wirePowaah = traverseWire(traversedWires, i, j);// POWAHH!

                    for (int k = startSize; k < traversedWires.size(); k++) {
                        GateWire wire = traversedWires.get(k);
                        for (Dir dir : Dir.values()) {
                            wire.getConnection(dir).setOutput(wirePowaah);
                        }
                    }
                }
            }
        }
    }

    private int getStrengthFromOutside(GateWire checkingWire, int x, int y) {

        int mid = getCircuitWidth() / 2;
        if (x == 0 && y == mid) {
            RedstoneConnection connection = checkingWire.getConnection(ForgeDirection.WEST);
            if (connection.isEnabled()) {
                return right().getInput();
            }
        }
        if (x == getCircuitWidth() - 1 && y == mid) {
            RedstoneConnection connection = checkingWire.getConnection(ForgeDirection.EAST);
            if (connection.isEnabled()) {
                return left().getInput();
            }
        }
        if (x == mid && y == 0) {
            RedstoneConnection connection = checkingWire.getConnection(ForgeDirection.NORTH);
            if (connection.isEnabled()) {
                return back().getInput();
            }
        }
        if (x == mid && y == getCircuitWidth() - 1) {
            RedstoneConnection connection = checkingWire.getConnection(ForgeDirection.SOUTH);
            if (connection.isEnabled()) {
                return front().getInput();
            }
        }
        return 0;
    }

    private int traverseWire(List<GateWire> traversedWires, int x, int y) {

        if (x < 0 || y < 0 || x >= getCircuitWidth() || y >= getCircuitWidth()) {
            return 0;
        }
        int maxPowaah = 0;
        GateWire curWire = (GateWire) gates[x][y];
        traversedWires.add(curWire);
        for (Dir dir : Dir.values()) {

            GateBase neighbor = getNeighbor(x, y, dir);
            if (neighbor != null) {
                ForgeDirection forgeDir = null;
                switch (dir) {
                case FRONT:
                    forgeDir = ForgeDirection.SOUTH;
                    break;
                case BACK:
                    forgeDir = ForgeDirection.NORTH;
                    break;
                case LEFT:
                    forgeDir = ForgeDirection.EAST;
                    break;
                case RIGHT:
                    forgeDir = ForgeDirection.WEST;
                    break;
                }
                Dir neighborDir = Dir.getDirection(ForgeDirection.UP, forgeDir, neighbor.getRotation())
                        .getOpposite();
                Dir gateDir = Dir.getDirection(ForgeDirection.UP, forgeDir, curWire.getRotation());
                if (curWire.getConnection(gateDir).isEnabled()) {
                    if (neighbor instanceof GateWire) {
                        if (!traversedWires.contains(neighbor) && neighbor.getConnection(neighborDir).isEnabled()) {
                            maxPowaah = Math.max(maxPowaah,
                                    traverseWire(traversedWires, x + getOffsetX(dir), y + getOffsetY(dir)));
                        }
                    } else {
                        RedstoneConnection connection = neighbor.getConnection(neighborDir);
                        if (connection.isEnabled())
                            maxPowaah = Math.max(maxPowaah, connection.getOutput());
                    }
                }
            } else {
                // maxPowaah = Math.max(maxPowaah, getStrengthFromOutside(curWire, x, y)); //accept power from outside world. creates a loop.
            }
        }
        return maxPowaah;
    }

    private void reflectGates() {

        int mid = getCircuitWidth() / 2;
        if (gates[0][mid] != null) {
            RedstoneConnection connection = gates[0][mid].getConnection(ForgeDirection.WEST);
            if (connection.isEnabled()) {
                right().enable();
            } else {
                right().disable();
            }
            connection.setInput(right().getInput());
            right().setOutput(connection.getOutput());

            gates[0][mid].onUpdate();
        } else {
            right().setOutput(false);
            right().disable();
        }
        if (gates[getCircuitWidth() - 1][mid] != null) {
            RedstoneConnection connection = gates[getCircuitWidth() - 1][mid].getConnection(ForgeDirection.EAST);
            if (connection.isEnabled()) {
                left().enable();
            } else {
                left().disable();
            }
            connection.setInput(left().getInput());
            left().setOutput(connection.getOutput());

            gates[getCircuitWidth() - 1][mid].onUpdate();
        } else {
            left().setOutput(false);
            left().disable();
        }
        if (gates[mid][0] != null) {
            RedstoneConnection connection = gates[mid][0].getConnection(ForgeDirection.NORTH);
            if (connection.isEnabled()) {
                back().enable();
            } else {
                back().disable();
            }
            connection.setInput(back().getInput());
            back().setOutput(connection.getOutput());

            gates[mid][0].onUpdate();
        } else {
            back().setOutput(false);
            back().disable();
        }
        if (gates[mid][getCircuitWidth() - 1] != null) {
            RedstoneConnection connection = gates[mid][getCircuitWidth() - 1].getConnection(ForgeDirection.SOUTH);
            if (connection.isEnabled()) {
                front().enable();
            } else {
                front().disable();
            }
            connection.setInput(front().getInput());
            front().setOutput(connection.getOutput());

            gates[mid][getCircuitWidth() - 1].onUpdate();
        } else {
            front().setOutput(false);
            front().disable();
        }
    }

    @Override
    public void writeToNBT(NBTTagCompound tag) {

        writeUpdateToNBT(tag);
    }

    @Override
    public void readFromNBT(NBTTagCompound tag) {

        readUpdateFromNBT(tag);
    }

    @Override
    public void writeUpdateToNBT(NBTTagCompound tag) {

        super.writeUpdateToNBT(tag);
        for (int k = 0; k < gates.length; k++) {
            for (int j = 0; j < gates[k].length; j++) {
                if (gates[k][j] != null) {
                    GateBase gate = gates[k][j];
                    NBTTagCompound gateTag = new NBTTagCompound();
                    gateTag.setString("type", gate.getType());
                    gate.writeToNBT(gateTag);
                    tag.setTag("gate" + k + "" + j, gateTag);
                }
            }
        }
    }

    @Override
    public void readUpdateFromNBT(NBTTagCompound tag) {

        super.readUpdateFromNBT(tag);
        for (int k = 0; k < gates.length; k++) {
            for (int j = 0; j < gates[k].length; j++) {
                if (tag.hasKey("gate" + k + "" + j)) {
                    NBTTagCompound gateTag = tag.getCompoundTag("gate" + k + "" + j);

                    String type = gateTag.getString("type");
                    GateBase gate;
                    if (gates[k][j] != null && gates[k][j].getType().equals(type)) {
                        gate = gates[k][j];
                    } else {
                        if (type.equals(GateWire.ID)) {
                            gate = new GateWire();
                        } else {
                            gate = (GateBase) PartRegistry.createPart(type, false);
                        }
                        gates[k][j] = gate;
                        gates[k][j].parentCircuit = this;
                        gate.setParent(this);
                    }
                    gate.readFromNBT(gateTag);
                } else {
                    gates[k][j] = null;
                }
            }
        }
    }

    @Override
    public boolean onActivated(EntityPlayer player, QMovingObjectPosition hit, ItemStack item) {

        List<Vec3dCube> aabbs = getSelectionBoxes();
        int subPartHit = aabbs.indexOf(hit.getCube());

        if (subPartHit <= 0)
            return super.onActivated(player, hit, item);

        subPartHit--;
        int x = getCircuitWidth() - 1 - subPartHit / getCircuitWidth();
        int y = getCircuitWidth() - 1 - subPartHit % getCircuitWidth();
        if (gates[x][y] != null) {
            if (gates[x][y].onActivated(player, hit, item)) {
                updateNeighborGates(x, y);
                gates[x][y].onUpdate();
                sendUpdatePacket();
                return true;
            } else {
                return false;
            }
        } else {
            return tryPlaceGate(player, x, y, item, hit);
        }
    }

    @Override
    public void onClicked(EntityPlayer player, QMovingObjectPosition hit, ItemStack item) {

        List<Vec3dCube> aabbs = getSelectionBoxes();
        int subPartHit = aabbs.indexOf(hit.getCube());

        if (subPartHit <= 0)
            return;

        subPartHit--;
        int x = getCircuitWidth() - 1 - subPartHit / getCircuitWidth();
        int y = getCircuitWidth() - 1 - subPartHit % getCircuitWidth();
        if (gates[x][y] != null) {
            if (!getWorld().isRemote) {
                ItemStack partStack = PartManager.getPartInfo(gates[x][y] instanceof GateWire
                        ? new PartRedwireFace(RedwireType.BLUESTONE, MinecraftColor.NONE, false).getType()
                        : gates[x][y].getType()).getStack();
                partStack.stackSize = 1;
                getWorld().spawnEntityInWorld(
                        new EntityItem(getWorld(), getX() + 0.5, getY() + 0.5, getZ() + 0.5, partStack));
                gates[x][y] = null;
                updateNeighborGates(x, y);
                sendUpdatePacket();
            }
            gates[x][y] = null;

        }
    }

    @Override
    public List<ItemStack> getDrops() {

        List<ItemStack> drops = super.getDrops();
        for (GateBase[] gateArray : gates) {
            for (GateBase gate : gateArray) {
                if (gate != null) {
                    if (gate instanceof GateWire) {
                        drops.addAll(
                                new PartRedwireFace(RedwireType.BLUESTONE, MinecraftColor.NONE, false).getDrops());
                    } else {
                        drops.addAll(gate.getDrops());
                    }
                }
            }
        }

        return drops;
    }

    private boolean tryPlaceGate(EntityPlayer player, int x, int y, ItemStack stack, MovingObjectPosition mop) {

        if (stack != null && stack.getItem() instanceof ItemPart) {
            BPPart part = PartManager.createPart(stack);
            if (part instanceof PartRedwireFace && part.getType()
                    .equals(new PartRedwireFace(RedwireType.BLUESTONE, MinecraftColor.NONE, false).getType())) {
                part = new GateWire();
            }
            if (part instanceof GateBase && !(part instanceof IntegratedCircuit)) {
                gates[x][y] = (GateBase) part;
                ((GateBase) part).setFace(ForgeDirection.DOWN);
                ((GateBase) part).parentCircuit = this;
                part.setParent(this);
                if (!player.capabilities.isCreativeMode)
                    stack.stackSize--;
                if (!getWorld().isRemote)
                    notifyUpdate();
                updateNeighborGates(x, y);
                gates[x][y].onUpdate();
                return true;
            }
        }
        return false;
    }

    @Override
    @SideOnly(Side.CLIENT)
    public void addWAILABody(List<String> info) {

    }

    /**
     * Return true if the ItemStack that's being 'injected' with info is a stack that can be injected. This method is only called when
     * itemStack.isItemEqual(otherStack) returned true.
     *
     * @param outputStack
     * @return false to disallow copying.
     */
    @Override
    public boolean canGoInCopySlot(ItemStack stack) {

        return true;
    }

    /**
     * Items that contain items (an Integrated Circuit with gates on it) need to compare the input and output, and tell which items are required. With
     * this method you can tell the Circuit Database what items the item carries, so it can calculate which items it needs.
     *
     * @param templateStack
     * @param outputStack
     * @return null is a valid return.
     */
    @Override
    public List<ItemStack> getItemsOnStack(ItemStack stack) {

        List<ItemStack> items = getDrops();
        items.remove(0); // remove the part itself
        return items;
    }

    @Override
    public List<IPart> getParts() {

        return null;
    }

    @Override
    public boolean canAddPart(IPart part) {

        return false;
    }

    @Override
    public void addPart(IPart part) {

    }

    @Override
    public boolean removePart(IPart part) {

        return false;
    }

    // @Override
    // TODO: Check me
    public void sendPartUpdate(IPart part) {

        sendUpdatePacket();
    }

    @Override
    public void addCollisionBoxesToList(List<Vec3dCube> boxes, AxisAlignedBB bounds, Entity entity) {

    }

    @Override
    public List<IMicroblock> getMicroblocks() {

        return new ArrayList<IMicroblock>();
    }

    @Override
    public boolean isSimulated() {

        return false;
    }

    @Override
    public Map<String, IPart> getPartMap() {

        Map<String, IPart> parts = new HashMap<String, IPart>();
        for (GateBase[] gateArray : gates) {
            for (GateBase gate : gateArray) {
                if (gate != null)
                    parts.put(genIdentifier(parts), gate);
            }
        }

        return parts;
    }

    private String genIdentifier(Map<String, IPart> curParts) {

        String s = null;
        do {
            s = UUID.randomUUID().toString();
        } while (curParts.containsKey(s));

        return s;
    }

}