Package pneumaticCraft.common.tileentity

Source Code of pneumaticCraft.common.tileentity.TileEntityPressureChamberValve

package pneumaticCraft.common.tileentity;

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

import net.minecraft.block.Block;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;

import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;

import pneumaticCraft.api.recipe.IPressureChamberRecipe;
import pneumaticCraft.api.recipe.PressureChamberRecipe;
import pneumaticCraft.api.tileentity.IPneumaticMachine;
import pneumaticCraft.common.Config;
import pneumaticCraft.common.DamageSourcePneumaticCraft;
import pneumaticCraft.common.block.Blockss;
import pneumaticCraft.common.item.ItemMachineUpgrade;
import pneumaticCraft.common.item.Itemss;
import pneumaticCraft.common.util.PneumaticCraftUtils;
import pneumaticCraft.lib.PneumaticValues;

public class TileEntityPressureChamberValve extends TileEntityPneumaticBase implements IInventory, IMinWorkingPressure{
    public int multiBlockX;
    public int multiBlockY;
    public int multiBlockZ;
    public int multiBlockSize;
    public List<TileEntityPressureChamberValve> accessoryValves;
    private final List<int[]> nbtValveList;
    private boolean readNBT = false;
    public boolean isValidRecipeInChamber;
    public boolean isSufficientPressureInChamber;
    public boolean areEntitiesDoneMoving;
    public float recipePressure;

    private ItemStack[] inventory = new ItemStack[4];
    public static final int UPGRADE_SLOT_1 = 0;
    public static final int UPGRADE_SLOT_4 = 3;
    private final Random rand = new Random();

    // private float oldPressure;
    // private int pressureUpdateTimer = 60;

    public TileEntityPressureChamberValve(){
        super(PneumaticValues.DANGER_PRESSURE_PRESSURE_CHAMBER, PneumaticValues.MAX_PRESSURE_PRESSURE_CHAMBER, PneumaticValues.VOLUME_PRESSURE_CHAMBER);
        accessoryValves = new ArrayList<TileEntityPressureChamberValve>();
        nbtValveList = new ArrayList<int[]>();
        setUpgradeSlots(new int[]{UPGRADE_SLOT_1, 1, 2, UPGRADE_SLOT_4});
    }

    // pneumatic methods-------------------------------------------------------
    // used in the air dispersion methods.
    @Override
    public boolean isConnectedTo(ForgeDirection side){
        switch(ForgeDirection.getOrientation(getBlockMetadata())){
            case UP:
            case DOWN:
                return side == ForgeDirection.UP || side == ForgeDirection.DOWN;
            case NORTH:
            case SOUTH:
                return side == ForgeDirection.NORTH || side == ForgeDirection.SOUTH;
            case EAST:
            case WEST:
                return side == ForgeDirection.EAST || side == ForgeDirection.WEST;
        }
        return false;
    }

    @Override
    public List<Pair<ForgeDirection, IPneumaticMachine>> getConnectedPneumatics(){
        List<Pair<ForgeDirection, IPneumaticMachine>> teList = super.getConnectedPneumatics();
        if(accessoryValves != null) {
            for(TileEntityPressureChamberValve valve : accessoryValves) {
                if(valve != this) teList.add(new ImmutablePair(ForgeDirection.UNKNOWN, valve));
            }
        }

        return teList;
    }

    @Override
    protected int getVolumeFromUpgrades(int[] upgradeSlots){
        return super.getVolumeFromUpgrades(getUpgradeSlots()) + (multiBlockSize > 0 ? (int)Math.pow(multiBlockSize - 2, 3) * PneumaticValues.VOLUME_PRESSURE_CHAMBER_PER_EMPTY : 0);
    }

    // main update method
    @Override
    public void updateEntity(){
        if(readNBT) {// this way of doing this is needed because other TE's are
                     // loaded after the reading of the NBT of this TE.
            readNBT = false;
            accessoryValves.clear();
            for(int[] valve : nbtValveList) {
                TileEntity te = worldObj.getTileEntity(valve[0], valve[1], valve[2]);
                if(te instanceof TileEntityPressureChamberValve) {

                    accessoryValves.add((TileEntityPressureChamberValve)te);
                }
            }
            if(worldObj.isRemote) worldObj.markBlockRangeForRenderUpdate(xCoord, yCoord, zCoord, xCoord, yCoord, zCoord);
        }

        if(!worldObj.isRemote) {
            //code to check if we need to leak air.
            boolean[] connected = new boolean[]{true, true, true, true, true, true};//assume we are not leaking at any side
            switch(ForgeDirection.getOrientation(getBlockMetadata())){//take off the sides that tubes can connect to.
                case UP:
                case DOWN:
                    connected[ForgeDirection.UP.ordinal()] = false;
                    connected[ForgeDirection.DOWN.ordinal()] = false;
                    break;
                case NORTH:
                case SOUTH:
                    connected[ForgeDirection.NORTH.ordinal()] = false;
                    connected[ForgeDirection.SOUTH.ordinal()] = false;
                    break;
                case EAST:
                case WEST:
                    connected[ForgeDirection.EAST.ordinal()] = false;
                    connected[ForgeDirection.WEST.ordinal()] = false;
                    break;
            }
            List<Pair<ForgeDirection, IPneumaticMachine>> teList = super.getConnectedPneumatics();//we need the super method, as the overridden method adds the other valves.
            for(Pair<ForgeDirection, IPneumaticMachine> entry : teList) {
                connected[entry.getKey().ordinal()] = true;
            }
            //retrieve the valve that is controlling the (potential) chamber.
            TileEntityPressureChamberValve baseValve = null;
            for(TileEntityPressureChamberValve valve : accessoryValves) {
                if(valve.multiBlockSize > 0) {
                    baseValve = valve;
                    break;
                }
            }
            //if we found one, we can scratch one side to be leaking air.
            if(baseValve != null) {
                switch(ForgeDirection.getOrientation(getBlockMetadata())){
                    case UP:
                    case DOWN:
                        if(baseValve.multiBlockY == yCoord) connected[ForgeDirection.UP.ordinal()] = true;
                        else connected[ForgeDirection.DOWN.ordinal()] = true;
                        break;
                    case NORTH:
                    case SOUTH:
                        if(baseValve.multiBlockZ == zCoord) connected[ForgeDirection.SOUTH.ordinal()] = true;
                        else connected[ForgeDirection.NORTH.ordinal()] = true;
                        break;
                    case EAST:
                    case WEST:
                        if(baseValve.multiBlockX == xCoord) connected[ForgeDirection.EAST.ordinal()] = true;
                        else connected[ForgeDirection.WEST.ordinal()] = true;
                        break;
                }
            }
            for(int i = 0; i < 6; i++)
                if(!connected[i]) airLeak(ForgeDirection.getOrientation(i));
        }
        super.updateEntity();

        /*
         * FIXME pressure chamber particle effects not updating properly
         * if(!worldObj.isRemote){ pressureUpdateTimer++;
         * System.out.println("timer: " + pressureUpdateTimer);
         * if(pressureUpdateTimer > 60){ pressureUpdateTimer = 0;
         * updatePressuresToClient(); } }
         */

        if(multiBlockSize != 0 && !worldObj.isRemote) {
            ItemStack[] stacksInChamber = getStacksInChamber();
            boolean oldValidRecipes = isValidRecipeInChamber;
            boolean oldSufficientPressure = isSufficientPressureInChamber;
            isValidRecipeInChamber = false;
            isSufficientPressureInChamber = false;
            recipePressure = Float.MAX_VALUE;
            //simple recipes
            for(PressureChamberRecipe recipe : PressureChamberRecipe.chamberRecipes) {
                boolean isValidRecipeInChamberFlag = canBeCompressed(recipe, stacksInChamber);
                boolean isSufficientPressureInChamberFlag = recipe.pressure <= getPressure(ForgeDirection.UNKNOWN) && recipe.pressure > 0F || recipe.pressure >= getPressure(ForgeDirection.UNKNOWN) && recipe.pressure < 0F;
                if(isValidRecipeInChamberFlag) {
                    isValidRecipeInChamber = true;
                    if(Math.abs(recipe.pressure) < Math.abs(recipePressure)) {
                        recipePressure = recipe.pressure;
                    }
                }
                if(isSufficientPressureInChamberFlag) isSufficientPressureInChamber = true;
                if(isValidRecipeInChamberFlag && isSufficientPressureInChamberFlag && areEntitiesDoneMoving) {
                    double[] outputPosition = clearStacksInChamber(recipe.input);
                    giveOutput(recipe.output, recipe.outputAsBlock, outputPosition);
                }
            }
            //special recipes
            for(IPressureChamberRecipe recipe : PressureChamberRecipe.specialRecipes) {
                ItemStack[] removedStacks = recipe.isValidRecipe(stacksInChamber);
                boolean isValidRecipeInChamberFlag = removedStacks != null;
                boolean isSufficientPressureInChamberFlag = recipe.getCraftingPressure() <= getPressure(ForgeDirection.UNKNOWN) && recipe.getCraftingPressure() > 0F || recipe.getCraftingPressure() >= getPressure(ForgeDirection.UNKNOWN) && recipe.getCraftingPressure() < 0F;
                if(isValidRecipeInChamberFlag) {
                    isValidRecipeInChamber = true;
                    if(Math.abs(recipe.getCraftingPressure()) < Math.abs(recipePressure)) {
                        recipePressure = recipe.getCraftingPressure();
                    }
                }
                if(isSufficientPressureInChamberFlag) isSufficientPressureInChamber = true;
                if(isValidRecipeInChamberFlag && isSufficientPressureInChamberFlag && areEntitiesDoneMoving) {
                    double[] outputPosition = clearStacksInChamber(removedStacks);
                    giveOutput(recipe.craftRecipe(stacksInChamber, removedStacks), false, outputPosition);
                }
            }

            if(oldValidRecipes != isValidRecipeInChamber || oldSufficientPressure != isSufficientPressureInChamber) {
                sendDescriptionPacket();
            }

            if(getPressure(ForgeDirection.UNKNOWN) > PneumaticValues.MAX_PRESSURE_LIVING_ENTITY) {
                AxisAlignedBB bbBox = AxisAlignedBB.getBoundingBox(multiBlockX + 1, multiBlockY + 1, multiBlockZ + 1, multiBlockX + multiBlockSize - 1, multiBlockY + multiBlockSize - 1, multiBlockZ + multiBlockSize - 1);
                List<EntityLivingBase> entities = worldObj.getEntitiesWithinAABB(EntityLivingBase.class, bbBox);
                for(EntityLivingBase entity : entities) {
                    if(entity instanceof EntityVillager) {
                        EntityVillager villager = (EntityVillager)entity;
                        if(villager.getProfession() != Config.villagerMechanicID) {
                            villager.setProfession(Config.villagerMechanicID);
                            NBTTagCompound tag = new NBTTagCompound();
                            villager.writeEntityToNBT(tag);
                            if(tag.hasKey("Offers")) {//reset the trade list
                                tag.removeTag("Offers");
                                villager.readEntityFromNBT(tag);
                            }
                        }
                    }
                    entity.attackEntityFrom(DamageSourcePneumaticCraft.pressure, (int)(getPressure(ForgeDirection.UNKNOWN) * 2D));
                }
            }
        }

        // move entities to eachother.
        AxisAlignedBB bbBox = AxisAlignedBB.getBoundingBox(multiBlockX, multiBlockY, multiBlockZ, multiBlockX + multiBlockSize, multiBlockY + multiBlockSize, multiBlockZ + multiBlockSize);
        List<EntityItem> entities = worldObj.getEntitiesWithinAABB(EntityItem.class, bbBox);
        areEntitiesDoneMoving = true; // set to true, set to false when one of
                                      // the entities is moving.
        for(int i = 0; i < entities.size() - 1; i++) {
            EntityItem lastEntity = entities.get(i);
            EntityItem entity = entities.get(i + 1);
            // XP Orb code snippet
            double d0 = 8.0D;
            double d1 = (lastEntity.posX - entity.posX) / d0;
            double d3 = (lastEntity.posZ - entity.posZ) / d0;
            double d4 = Math.sqrt(d1 * d1 + d3 * d3);
            double d5 = 1.0D - d4;

            if(d5 > 0.0D && d4 > 0.02D) {
                d5 *= d5;
                entity.motionX += d1 / d4 * d5 * 0.01D;
                entity.motionZ += d3 / d4 * d5 * 0.01D;
                lastEntity.motionX -= d1 / d4 * d5 * 0.01D;
                lastEntity.motionZ -= d3 / d4 * d5 * 0.01D;
                areEntitiesDoneMoving = false;
            }
        }

        boolean lifeUpgrade = getUpgrades(ItemMachineUpgrade.UPGRADE_ITEM_LIFE, getUpgradeSlots()) > 0;
        if(lifeUpgrade && !worldObj.isRemote) {
            for(EntityItem entity : entities) {
                entity.age--;
            }
        }

        // particles
        if(worldObj.isRemote && getPressure(ForgeDirection.UNKNOWN) > 0.2D) {
            int particles = (int)Math.pow(multiBlockSize - 2, 3);
            for(int i = 0; i < particles; i++) {
                if(rand.nextInt(Math.max(1, 8 - (int)(getPressure(ForgeDirection.UNKNOWN) * 2D))) == 0) {
                    double posX = multiBlockX + 1D + rand.nextDouble() * (multiBlockSize - 2D);
                    double posY = multiBlockY + 1D + rand.nextDouble() * (multiBlockSize - 2D);
                    double posZ = multiBlockZ + 1D + rand.nextDouble() * (multiBlockSize - 2D);
                    worldObj.spawnParticle("explode", posX, posY, posZ, 0D, 0D, 0D);
                }
            }
        }

    }

    private boolean canBeCompressed(PressureChamberRecipe recipe, ItemStack[] items){
        for(ItemStack in : recipe.input) {
            if(in != null) {
                int amount = 0;
                for(ItemStack item : items) {
                    if(item != null && (in.isItemEqual(item) || PneumaticCraftUtils.isSameOreDictStack(in, item))) amount += item.stackSize;
                }
                if(amount < in.stackSize) return false;
            }
        }
        return true;
    }

    public ItemStack[] getStacksInChamber(){
        List<ItemStack> stackList = new ArrayList<ItemStack>(); // first make a
                                                                // list, convert
                                                                // it to an
                                                                // array
                                                                // afterwards.
        /*for(int i = 0; i < multiBlockSize - 2; i++) {
            for(int j = 0; j < multiBlockSize - 2; j++) {
                for(int k = 0; k < multiBlockSize - 2; k++) {
                    Block blockID = worldObj.getBlock(i + multiBlockX + 1, j + multiBlockY + 1, k + multiBlockZ + 1);
                    if(!blockID.isAir(worldObj, i + multiBlockX + 1, j + multiBlockY + 1, k + multiBlockZ + 1)) {
                        ItemStack stack = new ItemStack(blockID, 1, worldObj.getBlockMetadata(i + multiBlockX + 1, j + multiBlockY + 1, k + multiBlockZ + 1));
                        if(stack.getItem() != null) addStackToList(stackList, stack);//getItem() shouldn't ever be able to be null, but still some defence cuz https://github.com/MineMaarten/PneumaticCraft-API/issues/60
                    }
                }
            }
        }*/

        // add Item entities lying on the ground.
        AxisAlignedBB bbBox = AxisAlignedBB.getBoundingBox(multiBlockX, multiBlockY, multiBlockZ, multiBlockX + multiBlockSize, multiBlockY + multiBlockSize, multiBlockZ + multiBlockSize);
        List<EntityItem> entities = worldObj.getEntitiesWithinAABB(EntityItem.class, bbBox);
        for(EntityItem entity : entities) {
            if(entity.isDead) continue;
            stackList.add(entity.getEntityItem());
        }

        return stackList.toArray(new ItemStack[stackList.size()]); // return an
                                                                   // into an
                                                                   // array
                                                                   // converted
                                                                   // list
    }

    public double[] clearStacksInChamber(ItemStack... stacksToClear){
        int[] stackSizes = new int[stacksToClear.length];
        for(int i = 0; i < stacksToClear.length; i++) {
            stackSizes[i] = stacksToClear[i].stackSize;
        }
        // default the output position to the middle of the chamber.
        double[] outputPosition = new double[]{multiBlockX + multiBlockSize / 2D, multiBlockY + 1.2D, multiBlockZ + multiBlockSize / 2D};
        // get the in world blocks
        /* for(int i = 0; i < multiBlockSize - 2; i++) {
             for(int j = multiBlockSize - 3; j >= 0; j--) {
                 for(int k = 0; k < multiBlockSize - 2; k++) {
                     Block blockID = worldObj.getBlock(i + multiBlockX + 1, j + multiBlockY + 1, k + multiBlockZ + 1);
                     if(!blockID.isAir(worldObj, i + multiBlockX + 1, j + multiBlockY + 1, k + multiBlockZ + 1)) {
                         for(int l = 0; l < stacksToClear.length; l++) {
                             if(Block.getBlockFromItem(stacksToClear[l].getItem()) == blockID && stackSizes[l] > 0) {
                                 worldObj.func_147480_a(i + multiBlockX + 1, j + multiBlockY + 1, k + multiBlockZ + 1, false);
                                 stackSizes[l]--;
                                 outputPosition[0] = i + multiBlockX + 1.5D;
                                 outputPosition[1] = j + multiBlockY + 1.5D;
                                 outputPosition[2] = k + multiBlockZ + 1.5D;
                                 break;
                             }
                         }
                     }
                 }
             }
         }*/

        // get the in world EntityItems
        AxisAlignedBB bbBox = AxisAlignedBB.getBoundingBox(multiBlockX, multiBlockY, multiBlockZ, multiBlockX + multiBlockSize, multiBlockY + multiBlockSize, multiBlockZ + multiBlockSize);
        List<EntityItem> entities = worldObj.getEntitiesWithinAABB(EntityItem.class, bbBox);
        for(EntityItem entity : entities) {
            if(entity.isDead) continue;
            ItemStack entityStack = entity.getEntityItem();
            for(int l = 0; l < stacksToClear.length; l++) {
                if(stacksToClear[l].isItemEqual(entityStack) && stackSizes[l] > 0) {
                    outputPosition[0] = entity.posX;
                    outputPosition[1] = entity.posY;
                    outputPosition[2] = entity.posZ;
                    int removedItems = Math.min(stackSizes[l], entityStack.stackSize);
                    stackSizes[l] -= removedItems;
                    entityStack.stackSize -= removedItems;
                    if(entityStack.stackSize <= 0) entity.setDead();
                    break;
                }
            }
        }
        return outputPosition;
    }

    private void giveOutput(ItemStack[] output, boolean outputAsBlock, double[] outputPosition){
        for(ItemStack iStack : output) {

            if(outputAsBlock)// when the output is a block.
            {
                int stackSize = iStack.stackSize;
                for(int i = 0; i < multiBlockSize - 2; i++) {
                    for(int j = 0; j < multiBlockSize - 2; j++) {
                        for(int k = 0; k < multiBlockSize - 2; k++) {
                            if(stackSize <= 0) continue;
                            if(worldObj.isAirBlock(j + multiBlockX + 1, i + multiBlockY + 1, k + multiBlockZ + 1)) {
                                worldObj.setBlock(j + multiBlockX + 1, i + multiBlockY + 1, k + multiBlockZ + 1, Block.getBlockFromItem(iStack.getItem()), iStack.getItemDamage(), 3);
                                stackSize--;
                            }
                        }
                    }
                }
            } else {

                EntityItem item = new EntityItem(worldObj, outputPosition[0], outputPosition[1], outputPosition[2], iStack.copy());
                worldObj.spawnEntityInWorld(item);
            }
        }
    }

    private void addStackToList(List<ItemStack> list, ItemStack stack){
        for(ItemStack listStack : list) {
            if(canCombineStacks(listStack, stack)) {
                listStack.stackSize += stack.stackSize;
                return;
            }
        }
        list.add(stack);
    }

    private boolean canCombineStacks(ItemStack iStack1, ItemStack iStack2){
        if(iStack1.getItem() != iStack2.getItem()) {
            return false;
        } else if(iStack1.hasTagCompound() ^ iStack2.hasTagCompound()) {
            return false;
        } else if(iStack1.hasTagCompound() && !iStack1.getTagCompound().equals(iStack2.getTagCompound())) {
            return false;
        } else if(iStack1.getItem().getHasSubtypes() && iStack1.getItemDamage() != iStack2.getItemDamage()) {
            return false;
        } else if(iStack1.stackSize + iStack2.stackSize > iStack1.getMaxStackSize()) {
            return false;
        } else {
            return true;
        }
    }

    // NBT methods-----------------------------------------------
    @Override
    public void readFromNBT(NBTTagCompound tag){
        super.readFromNBT(tag);
        multiBlockX = tag.getInteger("multiBlockX");
        multiBlockY = tag.getInteger("multiBlockY");
        multiBlockZ = tag.getInteger("multiBlockZ");
        multiBlockSize = tag.getInteger("multiBlockSize");
        isSufficientPressureInChamber = tag.getBoolean("sufPressure");
        isValidRecipeInChamber = tag.getBoolean("validRecipe");
        recipePressure = tag.getFloat("recipePressure");
        // Read in the ItemStacks in the inventory from NBT
        NBTTagList tagList = tag.getTagList("Items", 10);
        inventory = new ItemStack[getSizeInventory()];
        for(int i = 0; i < tagList.tagCount(); ++i) {
            NBTTagCompound tagCompound = tagList.getCompoundTagAt(i);
            byte slot = tagCompound.getByte("Slot");
            if(slot >= 0 && slot < inventory.length) {
                inventory[slot] = ItemStack.loadItemStackFromNBT(tagCompound);
            }
        }

        // Read in the accessory valves from NBT
        NBTTagList tagList2 = tag.getTagList("Valves", 10);
        nbtValveList.clear();
        for(int i = 0; i < tagList2.tagCount(); ++i) {
            NBTTagCompound tagCompound = tagList2.getCompoundTagAt(i);
            if(tagCompound != null) {
                nbtValveList.add(new int[]{tagCompound.getInteger("xCoord"), tagCompound.getInteger("yCoord"), tagCompound.getInteger("zCoord")});
            }
        }
        readNBT = true;
    }

    @Override
    public void writeToNBT(NBTTagCompound tag){
        super.writeToNBT(tag);
        tag.setInteger("multiBlockX", multiBlockX);
        tag.setInteger("multiBlockY", multiBlockY);
        tag.setInteger("multiBlockZ", multiBlockZ);
        tag.setInteger("multiBlockSize", multiBlockSize);
        tag.setBoolean("sufPressure", isSufficientPressureInChamber);
        tag.setBoolean("validRecipe", isValidRecipeInChamber);
        tag.setFloat("recipePressure", recipePressure);
        // Write the ItemStacks in the inventory to NBT
        NBTTagList tagList = new NBTTagList();
        for(int currentIndex = 0; currentIndex < inventory.length; ++currentIndex) {
            if(inventory[currentIndex] != null) {
                NBTTagCompound tagCompound = new NBTTagCompound();
                tagCompound.setByte("Slot", (byte)currentIndex);
                inventory[currentIndex].writeToNBT(tagCompound);
                tagList.appendTag(tagCompound);
            }
        }
        tag.setTag("Items", tagList);

        // Write the accessory valve to NBT
        NBTTagList tagList2 = new NBTTagList();
        for(TileEntityPressureChamberValve valve : accessoryValves) {
            NBTTagCompound tagCompound = new NBTTagCompound();
            tagCompound.setInteger("xCoord", valve.xCoord);
            tagCompound.setInteger("yCoord", valve.yCoord);
            tagCompound.setInteger("zCoord", valve.zCoord);
            tagList2.appendTag(tagCompound);
        }

        tag.setTag("Valves", tagList2);
    }

    // Multi-block structure methods
    // --------------------------------------------------------

    public void onMultiBlockBreak(){
        dropInventory(worldObj, multiBlockX + multiBlockSize / 2D, multiBlockY + multiBlockSize / 2D, multiBlockZ + multiBlockSize / 2D);
        invalidateMultiBlock();
    }

    private void dropInventory(World world, double x, double y, double z){

        IInventory inventory = this;
        Random rand = new Random();
        for(int i = 0; i < inventory.getSizeInventory(); i++) {

            ItemStack itemStack = inventory.getStackInSlot(i);

            if(itemStack != null && itemStack.stackSize > 0) {
                float dX = rand.nextFloat() * 0.8F - 0.4F;
                float dY = rand.nextFloat() * 0.8F - 0.4F;
                float dZ = rand.nextFloat() * 0.8F - 0.4F;

                EntityItem entityItem = new EntityItem(world, x + dX, y + dY, z + dZ, new ItemStack(itemStack.getItem(), itemStack.stackSize, itemStack.getItemDamage()));

                if(itemStack.hasTagCompound()) {
                    entityItem.getEntityItem().setTagCompound((NBTTagCompound)itemStack.getTagCompound().copy());
                }

                float factor = 0.05F;
                entityItem.motionX = rand.nextGaussian() * factor;
                entityItem.motionY = rand.nextGaussian() * factor + 0.2F;
                entityItem.motionZ = rand.nextGaussian() * factor;
                world.spawnEntityInWorld(entityItem);
                // itemStack.stackSize = 0;
            }
        }
        this.inventory = new ItemStack[4];
    }

    private void invalidateMultiBlock(){
        for(int x = 0; x < multiBlockSize; x++) {
            for(int y = 0; y < multiBlockSize; y++) {
                for(int z = 0; z < multiBlockSize; z++) {
                    TileEntity te = worldObj.getTileEntity(x + multiBlockX, y + multiBlockY, z + multiBlockZ);
                    if(te instanceof TileEntityPressureChamberWall) {
                        TileEntityPressureChamberWall teWall = (TileEntityPressureChamberWall)te;
                        teWall.setCore(null); // Clear the base TE's, so that
                                              // the walls can be used in a new
                                              // MultiBlock
                    }
                }
            }
        }
        if(accessoryValves != null) {
            for(TileEntityPressureChamberValve valve : accessoryValves) {
                valve.setMultiBlockCoords(0, 0, 0, 0);
                if(valve != this) {
                    valve.accessoryValves.clear();
                    valve.sendDescriptionPacket();
                }
            }
            accessoryValves.clear();
        }
        sendDescriptionPacket();
    }

    public void setMultiBlockCoords(int size, int baseX, int baseY, int baseZ){
        multiBlockSize = size;
        multiBlockX = baseX;
        multiBlockY = baseY;
        multiBlockZ = baseZ;
    }

    public static boolean checkIfProperlyFormed(World world, int x, int y, int z){
        // ArrayList<int[]> blockList = getAccessoryTiles(new
        // ArrayList<int[]>(), world, x,y,z);

        for(int i = 3; i < 6; i++) {
            if(checkForShiftedCubeOfSize(i, world, x, y, z)) {
                return true;
            }
        }
        return false;
    }

    private static boolean checkForShiftedCubeOfSize(int size, World world, int baseX, int baseY, int baseZ){
        for(int wallX = 0; wallX < size; wallX++) {
            for(int wallY = 0; wallY < size; wallY++) {
                // check every possible configuration the block can be in.
                if(checkForCubeOfSize(size, world, baseX, baseY - wallY, baseZ - wallX)) return true;
                if(checkForCubeOfSize(size, world, baseX, baseY + wallY, baseZ + wallX)) return true;
                if(checkForCubeOfSize(size, world, baseX - wallX, baseY - wallY, baseZ)) return true;
                if(checkForCubeOfSize(size, world, baseX + wallX, baseY + wallY, baseZ)) return true;
                if(checkForCubeOfSize(size, world, baseX - wallX, baseY, baseZ - wallY)) return true;
                if(checkForCubeOfSize(size, world, baseX + wallX, baseY, baseZ + wallY)) return true;

                if(checkForCubeOfSize(size, world, baseX - size + 1, baseY - wallY, baseZ - wallX)) return true;
                if(checkForCubeOfSize(size, world, baseX - size + 1, baseY + wallY, baseZ + wallX)) return true;
                if(checkForCubeOfSize(size, world, baseX - wallX, baseY - wallY, baseZ - size + 1)) return true;
                if(checkForCubeOfSize(size, world, baseX + wallX, baseY + wallY, baseZ - size + 1)) return true;
                if(checkForCubeOfSize(size, world, baseX - wallX, baseY - size + 1, baseZ - wallY)) return true;
                if(checkForCubeOfSize(size, world, baseX + wallX, baseY - size + 1, baseZ + wallY)) return true;
            }
        }
        return false;
    }

    private static boolean checkForCubeOfSize(int size, World world, int baseX, int baseY, int baseZ){
        boolean validValveFound = false;
        for(int x = 0; x < size; x++) {
            for(int y = 0; y < size; y++) {
                for(int z = 0; z < size; z++) {
                    if(x != 0 && x != size - 1 && y != 0 && y != size - 1 && z != 0 && z != size - 1) continue;
                    if(world.getBlock(x + baseX, y + baseY, z + baseZ) != Blockss.pressureChamberWall && world.getBlock(x + baseX, y + baseY, z + baseZ) != Blockss.pressureChamberValve && world.getBlock(x + baseX, y + baseY, z + baseZ) != Blockss.pressureChamberInterface) {
                        return false;
                    } else if(world.getBlock(x + baseX, y + baseY, z + baseZ) == Blockss.pressureChamberValve) {
                        boolean xMid = x != 0 && x != size - 1;
                        boolean yMid = y != 0 && y != size - 1;
                        boolean zMid = z != 0 && z != size - 1;
                        ForgeDirection facing = ForgeDirection.getOrientation(world.getBlockMetadata(x + baseX, y + baseY, z + baseZ));
                        if(xMid && yMid && (facing == ForgeDirection.NORTH || facing == ForgeDirection.SOUTH) || xMid && zMid && (facing == ForgeDirection.UP || facing == ForgeDirection.DOWN) || yMid && zMid && (facing == ForgeDirection.EAST || facing == ForgeDirection.WEST)) {
                            validValveFound = true;
                        } else {
                            return false;
                        }
                    } else {// when blockID == wall/interface
                        TileEntity te = world.getTileEntity(x + baseX, y + baseY, z + baseZ);
                        if(te instanceof TileEntityPressureChamberWall && ((TileEntityPressureChamberWall)te).getCore() != null) {
                            return false;
                        }
                    }
                }
            }
        }

        // when the code makes it to here we've found a valid structure. it only
        // depends on whether there is a valid valve in the structure now.
        if(!validValveFound) return false;

        TileEntityPressureChamberValve teValve = null;
        List<TileEntityPressureChamberValve> valveList = new ArrayList<TileEntityPressureChamberValve>();
        for(int x = 0; x < size; x++) {
            for(int y = 0; y < size; y++) {
                for(int z = 0; z < size; z++) {
                    TileEntity te = world.getTileEntity(x + baseX, y + baseY, z + baseZ);
                    if(te instanceof TileEntityPressureChamberValve) {
                        boolean xMid = x != 0 && x != size - 1;
                        boolean yMid = y != 0 && y != size - 1;
                        boolean zMid = z != 0 && z != size - 1;
                        ForgeDirection facing = ForgeDirection.getOrientation(world.getBlockMetadata(x + baseX, y + baseY, z + baseZ));
                        if(xMid && yMid && (facing == ForgeDirection.NORTH || facing == ForgeDirection.SOUTH) || xMid && zMid && (facing == ForgeDirection.UP || facing == ForgeDirection.DOWN) || yMid && zMid && (facing == ForgeDirection.EAST || facing == ForgeDirection.WEST)) {
                            teValve = (TileEntityPressureChamberValve)te;
                            valveList.add(teValve);
                        }
                    }
                }
            }
        }
        if(teValve == null) return false;// this line shouldn't be triggered
                                         // ever.

        // put the list of all the valves in the structure in all the valve
        // TE's.
        for(TileEntityPressureChamberValve valve : valveList) {
            valve.accessoryValves = new ArrayList<TileEntityPressureChamberValve>(valveList);
            valve.sendDescriptionPacket();
        }

        // set the redirections of right clicking and breaking a wall block to
        // the valve.
        for(int x = 0; x < size; x++) {
            for(int y = 0; y < size; y++) {
                for(int z = 0; z < size; z++) {
                    TileEntity te = world.getTileEntity(x + baseX, y + baseY, z + baseZ);
                    if(te instanceof TileEntityPressureChamberWall) {
                        TileEntityPressureChamberWall teWall = (TileEntityPressureChamberWall)te;
                        teWall.setCore(teValve); // set base TE to the valve
                                                 // found.
                    }
                }
            }
        }

        // set the multi-block coords in the valve TE
        teValve.setMultiBlockCoords(size, baseX, baseY, baseZ);
        teValve.sendDescriptionPacket();
        return true;
    }

    public boolean isCoordWithinChamber(World world, int x, int y, int z){
        if(x > multiBlockX && x < multiBlockX + multiBlockSize - 1 && y > multiBlockY && y < multiBlockY + multiBlockSize - 1 && z > multiBlockZ && z < multiBlockZ + multiBlockSize - 1) {
            return true;
        }
        return false;
    }

    // INVENTORY METHODS- && NBT
    // ------------------------------------------------------------

    /**
     * Returns the number of slots in the inventory.
     */
    @Override
    public int getSizeInventory(){

        return inventory.length;
    }

    /**
     * Returns the stack in slot i
     */
    @Override
    public ItemStack getStackInSlot(int slot){

        return inventory[slot];
    }

    @Override
    public ItemStack decrStackSize(int slot, int amount){

        ItemStack itemStack = getStackInSlot(slot);
        if(itemStack != null) {
            if(itemStack.stackSize <= amount) {
                setInventorySlotContents(slot, null);
            } else {
                itemStack = itemStack.splitStack(amount);
                if(itemStack.stackSize == 0) {
                    setInventorySlotContents(slot, null);
                }
            }
        }

        return itemStack;
    }

    @Override
    public ItemStack getStackInSlotOnClosing(int slot){

        ItemStack itemStack = getStackInSlot(slot);
        if(itemStack != null) {
            setInventorySlotContents(slot, null);
        }
        return itemStack;
    }

    @Override
    public void setInventorySlotContents(int slot, ItemStack itemStack){
        // super.setInventorySlotContents(slot, itemStack);
        inventory[slot] = itemStack;
        if(itemStack != null && itemStack.stackSize > getInventoryStackLimit()) {
            itemStack.stackSize = getInventoryStackLimit();
        }
    }

    @Override
    public int getInventoryStackLimit(){

        return 64;
    }

    @Override
    public String getInventoryName(){

        return Blockss.pressureChamberValve.getUnlocalizedName();
    }

    @Override
    public boolean isItemValidForSlot(int i, ItemStack itemstack){
        return itemstack.getItem() == Itemss.machineUpgrade;
    }

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

    @Override
    public boolean isUseableByPlayer(EntityPlayer var1){
        return isGuiUseableByPlayer(var1);
    }

    @Override
    public void openInventory(){}

    @Override
    public void closeInventory(){}

    @Override
    public float getMinWorkingPressure(){
        return recipePressure;
    }

}
TOP

Related Classes of pneumaticCraft.common.tileentity.TileEntityPressureChamberValve

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.