Package buildcraft.factory

Source Code of buildcraft.factory.TileFloodGate

/**
* Copyright (c) 2011-2014, 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.factory;

import java.util.Deque;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
import java.util.TreeMap;

import net.minecraft.block.Block;
import net.minecraft.nbt.NBTTagCompound;

import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.BlockFluidBase;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidContainerRegistry;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidTankInfo;
import net.minecraftforge.fluids.IFluidHandler;

import buildcraft.api.core.BlockIndex;
import buildcraft.api.core.BuildCraftAPI;
import buildcraft.core.TileBuildCraft;
import buildcraft.core.fluids.FluidUtils;
import buildcraft.core.fluids.Tank;
import buildcraft.core.utils.BlockUtil;
import buildcraft.core.utils.Utils;

public class TileFloodGate extends TileBuildCraft implements IFluidHandler {

  public static final int[] REBUILD_DELAY = new int[8];
  public static final int MAX_LIQUID = FluidContainerRegistry.BUCKET_VOLUME * 2;
  private final TreeMap<Integer, Deque<BlockIndex>> pumpLayerQueues = new TreeMap<Integer, Deque<BlockIndex>>();
  private final Set<BlockIndex> visitedBlocks = new HashSet<BlockIndex>();
  private Deque<BlockIndex> fluidsFound = new LinkedList<BlockIndex>();
  private final Tank tank = new Tank("tank", MAX_LIQUID, this);
  private int rebuildDelay;
  private int tick = Utils.RANDOM.nextInt();
  private boolean powered = false;

  static {
    REBUILD_DELAY[0] = 128;
    REBUILD_DELAY[1] = 256;
    REBUILD_DELAY[2] = 512;
    REBUILD_DELAY[3] = 1024;
    REBUILD_DELAY[4] = 2048;
    REBUILD_DELAY[5] = 4096;
    REBUILD_DELAY[6] = 8192;
    REBUILD_DELAY[7] = 16384;
  }

  public TileFloodGate() {
  }

  @Override
  public void updateEntity() {
    super.updateEntity();

    if (worldObj.isRemote) {
      return;
    }

    if (powered) {
      return;
    }

    tick++;
    if (tick % 16 == 0) {
      FluidStack fluidtoFill = tank.drain(FluidContainerRegistry.BUCKET_VOLUME, false);
      if (fluidtoFill != null && fluidtoFill.amount == FluidContainerRegistry.BUCKET_VOLUME) {
        Fluid fluid = fluidtoFill.getFluid();
        if (fluid == null || !fluid.canBePlacedInWorld()) {
          return;
        }

        if (fluid == FluidRegistry.WATER && worldObj.provider.dimensionId == -1) {
          tank.drain(FluidContainerRegistry.BUCKET_VOLUME, true);
          return;
        }

        if (tick % REBUILD_DELAY[rebuildDelay] == 0) {
          rebuildDelay++;
          if (rebuildDelay >= REBUILD_DELAY.length) {
            rebuildDelay = REBUILD_DELAY.length - 1;
          }
          rebuildQueue();
        }
        BlockIndex index = getNextIndexToFill(true);

        if (index != null && placeFluid(index.x, index.y, index.z, fluid)) {
          tank.drain(FluidContainerRegistry.BUCKET_VOLUME, true);
          rebuildDelay = 0;
        }
      }
    }
  }

  private boolean placeFluid(int x, int y, int z, Fluid fluid) {
    Block block = worldObj.getBlock(x, y, z);

    if (canPlaceFluidAt(block, x, y, z)) {
      boolean placed;
      Block b = FluidUtils.getFluidBlock(fluid, true);

      if (b instanceof BlockFluidBase) {
        BlockFluidBase blockFluid = (BlockFluidBase) b;
        placed = worldObj.setBlock(x, y, z, b, blockFluid.getMaxRenderHeightMeta(), 3);
      } else {
        placed = worldObj.setBlock(x, y, z, b);
      }

      if (placed) {
        queueAdjacent(x, y, z);
        expandQueue();
      }

      return placed;
    }

    return false;
  }

  private BlockIndex getNextIndexToFill(boolean remove) {
    if (pumpLayerQueues.isEmpty()) {
      return null;
    }

    Deque<BlockIndex> bottomLayer = pumpLayerQueues.firstEntry().getValue();

    if (bottomLayer != null) {
      if (bottomLayer.isEmpty()) {
        pumpLayerQueues.pollFirstEntry();
      }
      if (remove) {
        BlockIndex index = bottomLayer.pollFirst();
        return index;
      }
      return bottomLayer.peekFirst();
    }

    return null;
  }

  private Deque<BlockIndex> getLayerQueue(int layer) {
    Deque<BlockIndex> pumpQueue = pumpLayerQueues.get(layer);
    if (pumpQueue == null) {
      pumpQueue = new LinkedList<BlockIndex>();
      pumpLayerQueues.put(layer, pumpQueue);
    }
    return pumpQueue;
  }

  /**
   * Nasty expensive function, don't call if you don't have to.
   */
  void rebuildQueue() {
    pumpLayerQueues.clear();
    visitedBlocks.clear();
    fluidsFound.clear();

    queueAdjacent(xCoord, yCoord, zCoord);

    expandQueue();
  }

  private void expandQueue() {
    if (tank.getFluidType() == null) {
      return;
    }
    while (!fluidsFound.isEmpty()) {
      Deque<BlockIndex> fluidsToExpand = fluidsFound;
      fluidsFound = new LinkedList<BlockIndex>();

      for (BlockIndex index : fluidsToExpand) {
        queueAdjacent(index.x, index.y, index.z);
      }
    }
  }

  public void queueAdjacent(int x, int y, int z) {
    if (tank.getFluidType() == null) {
      return;
    }
    queueForFilling(x, y - 1, z);
    queueForFilling(x + 1, y, z);
    queueForFilling(x - 1, y, z);
    queueForFilling(x, y, z + 1);
    queueForFilling(x, y, z - 1);
  }

  public void queueForFilling(int x, int y, int z) {
        if (y < 0 || y > 255) {
            return;
        }
    BlockIndex index = new BlockIndex(x, y, z);
    if (visitedBlocks.add(index)) {
      if ((x - xCoord) * (x - xCoord) + (z - zCoord) * (z - zCoord) > 64 * 64) {
        return;
      }

      Block block = worldObj.getBlock(x, y, z);
      if (BlockUtil.getFluid(block) == tank.getFluidType()) {
        fluidsFound.add(index);
      }
      if (canPlaceFluidAt(block, x, y, z)) {
        getLayerQueue(y).addLast(index);
      }
    }
  }

  private boolean canPlaceFluidAt(Block block, int x, int y, int z) {
    return BuildCraftAPI.isSoftBlock(worldObj, x, y, z) && !BlockUtil.isFullFluidBlock(block, worldObj, x, y, z);
  }

  public void onNeighborBlockChange(Block block) {
    boolean p = worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord);
    if (powered != p) {
      powered = p;
      if (!p) {
        rebuildQueue();
      }
    }
  }

  @Override
  public void readFromNBT(NBTTagCompound data) {
    super.readFromNBT(data);
    tank.readFromNBT(data);
    rebuildDelay = data.getByte("rebuildDelay");
    powered = data.getBoolean("powered");
  }

  @Override
  public void writeToNBT(NBTTagCompound data) {
    super.writeToNBT(data);
    tank.writeToNBT(data);
    data.setByte("rebuildDelay", (byte) rebuildDelay);
    data.setBoolean("powered", powered);
  }

  @Override
  public void invalidate() {
    super.invalidate();
    destroy();
  }

  @Override
  public void destroy() {
    pumpLayerQueues.clear();
  }

  // IFluidHandler implementation.
  @Override
  public int fill(ForgeDirection from, FluidStack resource, boolean doFill) {
    return tank.fill(resource, doFill);
  }

  @Override
  public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) {
    return null;
  }

  @Override
  public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) {
    return null;
  }

  @Override
  public boolean canFill(ForgeDirection from, Fluid fluid) {
    return true;
  }

  @Override
  public boolean canDrain(ForgeDirection from, Fluid fluid) {
    return false;
  }

  @Override
  public FluidTankInfo[] getTankInfo(ForgeDirection from) {
    return new FluidTankInfo[]{tank.getInfo()};
  }
}
TOP

Related Classes of buildcraft.factory.TileFloodGate

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.