Package buildcraft.transport

Source Code of buildcraft.transport.TileGenericPipe$SideProperties

/**
* 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.transport;

import org.apache.logging.log4j.Level;

import io.netty.buffer.ByteBuf;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.Packet;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraftforge.common.util.Constants;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidTankInfo;
import net.minecraftforge.fluids.IFluidHandler;
import cofh.api.energy.IEnergyHandler;
import buildcraft.BuildCraftCore;
import buildcraft.BuildCraftTransport;
import buildcraft.api.core.BCLog;
import buildcraft.api.core.EnumColor;
import buildcraft.api.core.IIconProvider;
import buildcraft.api.core.Position;
import buildcraft.api.gates.IGateExpansion;
import buildcraft.api.power.IPowerReceptor;
import buildcraft.api.power.PowerHandler;
import buildcraft.api.power.PowerHandler.PowerReceiver;
import buildcraft.api.transport.IPipe;
import buildcraft.api.transport.IPipeConnection;
import buildcraft.api.transport.IPipePluggable;
import buildcraft.api.transport.IPipeTile;
import buildcraft.api.transport.PipeWire;
import buildcraft.core.DefaultProps;
import buildcraft.core.IDropControlInventory;
import buildcraft.core.ITileBufferHolder;
import buildcraft.core.TileBuffer;
import buildcraft.core.inventory.InvUtils;
import buildcraft.core.network.BuildCraftPacket;
import buildcraft.core.network.IClientState;
import buildcraft.core.network.IGuiReturnHandler;
import buildcraft.core.network.ISyncedTile;
import buildcraft.core.network.PacketTileState;
import buildcraft.core.robots.DockingStation;
import buildcraft.core.utils.ColorUtils;
import buildcraft.core.utils.Utils;
import buildcraft.transport.ItemFacade.FacadeState;
import buildcraft.transport.gates.GateFactory;
import buildcraft.transport.gates.ItemGate;
import buildcraft.transport.utils.RobotStationState;

public class TileGenericPipe extends TileEntity implements IPowerReceptor, IFluidHandler,
    IPipeTile, ITileBufferHolder, IEnergyHandler, IDropControlInventory,
    ISyncedTile, ISolidSideTile, IGuiReturnHandler {

  public boolean initialized = false;
  public final PipeRenderState renderState = new PipeRenderState();
  public final CoreState coreState = new CoreState();
  public boolean[] pipeConnectionsBuffer = new boolean[6];

  public Pipe pipe;
  public int redstoneInput;
  public int[] redstoneInputSide = new int[ForgeDirection.VALID_DIRECTIONS.length];
  public int glassColor = -1;
 
  protected boolean deletePipe = false;
  protected boolean sendClientUpdate = false;
  protected boolean blockNeighborChange = false;
  protected boolean refreshRenderState = false;
  protected boolean pipeBound = false;
  protected boolean resyncGateExpansions = false;
  protected boolean attachPluggables = false;

  private TileBuffer[] tileBuffer;
 
  public static class CoreState implements IClientState {
    public int pipeId = -1;
    public ItemGate.GatePluggable[] gates = new ItemGate.GatePluggable[ForgeDirection.VALID_DIRECTIONS.length];

    @Override
    public void writeData(ByteBuf data) {
      data.writeInt(pipeId);
      for (int i = 0; i < ForgeDirection.VALID_DIRECTIONS.length; i++) {
        ItemGate.GatePluggable gate = gates[i];

        boolean gateValid = gate != null;
        data.writeBoolean(gateValid);
        if (gateValid) {
          gate.writeToByteBuf(data);
        }
      }
    }

    @Override
    public void readData(ByteBuf data) {
      pipeId = data.readInt();
      for (int i = 0; i < ForgeDirection.VALID_DIRECTIONS.length; i++) {
        if (data.readBoolean()) {
          ItemGate.GatePluggable gate = gates[i];
          if (gate == null) {
            gates[i] = gate = new ItemGate.GatePluggable();
          }
          gate.readFromByteBuf(data);
        } else {
          gates[i] = null;
        }
      }
    }
  }

  public static class SideProperties {
    IPipePluggable[] pluggables = new IPipePluggable[ForgeDirection.VALID_DIRECTIONS.length];

    public void writeToNBT(NBTTagCompound nbt) {
      for (int i = 0; i < ForgeDirection.VALID_DIRECTIONS.length; i++) {
        IPipePluggable pluggable = pluggables[i];
        final String key = "pluggable[" + i + "]";
        if (pluggable == null) {
          nbt.removeTag(key);
        } else {
          NBTTagCompound pluggableData = new NBTTagCompound();
          pluggableData.setString("pluggableClass", pluggable.getClass().getName());
          pluggable.writeToNBT(pluggableData);
          nbt.setTag(key, pluggableData);
        }
      }
    }

    public void readFromNBT(NBTTagCompound nbt) {
      for (int i = 0; i < ForgeDirection.VALID_DIRECTIONS.length; i++) {
        final String key = "pluggable[" + i + "]";
        if (!nbt.hasKey(key)) {
          continue;
        }
        try {
          NBTTagCompound pluggableData = nbt.getCompoundTag(key);
          Class<?> pluggableClass = Class.forName(pluggableData.getString("pluggableClass"));
          if (!IPipePluggable.class.isAssignableFrom(pluggableClass)) {
            BCLog.logger.warn("Wrong pluggable class: " + pluggableClass);
            continue;
          }
          IPipePluggable pluggable = (IPipePluggable) pluggableClass.newInstance();
          pluggable.readFromNBT(pluggableData);
          pluggables[i] = pluggable;
        } catch (Exception e) {
          BCLog.logger.warn("Failed to load side state");
          e.printStackTrace();
        }
      }

      // Migration code
      for (int i = 0; i < ForgeDirection.VALID_DIRECTIONS.length; i++) {
        IPipePluggable pluggable = null;
        if (nbt.hasKey("facadeState[" + i + "]")) {
          pluggable = new ItemFacade.FacadePluggable(FacadeState.readArray(nbt.getTagList("facadeState[" + i + "]", Constants.NBT.TAG_COMPOUND)));
        } else {
          // Migration support for 5.0.x and 6.0.x
          if (nbt.hasKey("facadeBlocks[" + i + "]")) {
            // 5.0.x
            Block block = (Block) Block.blockRegistry.getObjectById(nbt.getInteger("facadeBlocks[" + i + "]"));
            int blockId = nbt.getInteger("facadeBlocks[" + i + "]");

            if (blockId != 0) {
              int metadata = nbt.getInteger("facadeMeta[" + i + "]");
              pluggable = new ItemFacade.FacadePluggable(new FacadeState[]{FacadeState.create(block, metadata)});
            }
          } else if (nbt.hasKey("facadeBlocksStr[" + i + "][0]")) {
            // 6.0.x
            FacadeState mainState = FacadeState.create(
                (Block) Block.blockRegistry.getObject(nbt.getString("facadeBlocksStr[" + i + "][0]")),
                nbt.getInteger("facadeMeta[" + i + "][0]")
            );
            if (nbt.hasKey("facadeBlocksStr[" + i + "][1]")) {
              FacadeState phasedState = FacadeState.create(
                  (Block) Block.blockRegistry.getObject(nbt.getString("facadeBlocksStr[" + i + "][1]")),
                  nbt.getInteger("facadeMeta[" + i + "][1]"),
                  PipeWire.fromOrdinal(nbt.getInteger("facadeWires[" + i + "]"))
              );
              pluggable = new ItemFacade.FacadePluggable(new FacadeState[]{mainState, phasedState});
            } else {
              pluggable = new ItemFacade.FacadePluggable(new FacadeState[]{mainState});
            }
          }
        }

        if (nbt.getBoolean("plug[" + i + "]")) {
          pluggable = new ItemPlug.PlugPluggable();
        }
        if (nbt.getBoolean("robotStation[" + i + "]")) {
          pluggable = new ItemRobotStation.RobotStationPluggable();
        }

        if (pluggable != null) {
          pluggables[i] = pluggable;
        }
      }
    }

    public void rotateLeft() {
      IPipePluggable[] newPluggables = new IPipePluggable[ForgeDirection.VALID_DIRECTIONS.length];
      for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
        newPluggables[dir.getRotation(ForgeDirection.UP).ordinal()] = pluggables[dir.ordinal()];
      }
      pluggables = newPluggables;
    }

    public boolean dropItem(TileGenericPipe pipe, ForgeDirection direction) {
      boolean result = false;
      IPipePluggable pluggable = pluggables[direction.ordinal()];
      if (pluggable != null) {
        pluggable.onDetachedPipe(pipe, direction);
        ItemStack[] stacks = pluggable.getDropItems(pipe);
        if (stacks != null) {
          for (ItemStack stack : stacks) {
            InvUtils.dropItems(pipe.worldObj, stack, pipe.xCoord, pipe.yCoord, pipe.zCoord);
          }
        }
        result = true;
      }
      pluggables[direction.ordinal()] = null;
      pipe.notifyBlockChanged();
      return result;
    }

    public void invalidate() {
      for (IPipePluggable p : pluggables) {
        if (p != null) {
          p.invalidate();
        }
      }
    }

    public void validate(TileGenericPipe pipe) {
      for (ForgeDirection d : ForgeDirection.VALID_DIRECTIONS) {
        IPipePluggable p = pluggables[d.ordinal()];

        if (p != null) {
          p.validate(pipe, d);
        }
      }
    }
  }

  private SideProperties sideProperties = new SideProperties();

  public TileGenericPipe() {
  }

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

    if (glassColor >= 0) {
      nbt.setByte("stainedColor", (byte) glassColor);
    }
    for (int i = 0; i < ForgeDirection.VALID_DIRECTIONS.length; i++) {
      final String key = "redstoneInputSide[" + i + "]";
      nbt.setByte(key, (byte) redstoneInputSide[i]);
    }

    if (pipe != null) {
      nbt.setInteger("pipeId", Item.getIdFromItem(pipe.item));
      pipe.writeToNBT(nbt);
    } else {
      nbt.setInteger("pipeId", coreState.pipeId);
    }

    sideProperties.writeToNBT(nbt);
  }

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

    glassColor = nbt.hasKey("stainedColor") ? nbt.getByte("stainedColor") : -1;
   
    redstoneInput = 0;
   
    for (int i = 0; i < ForgeDirection.VALID_DIRECTIONS.length; i++) {
      final String key = "redstoneInputSide[" + i + "]";
      if (nbt.hasKey(key)) {
        redstoneInputSide[i] = nbt.getByte(key);
       
        if (redstoneInputSide[i] > redstoneInput) {
          redstoneInput = redstoneInputSide[i];
        }
      } else {
        redstoneInputSide[i] = 0;
      }
    }
   
    coreState.pipeId = nbt.getInteger("pipeId");
    pipe = BlockGenericPipe.createPipe((Item) Item.getItemById(coreState.pipeId));
    bindPipe();

    if (pipe != null) {
      pipe.readFromNBT(nbt);
    } else {
      BCLog.logger.log(Level.WARN, "Pipe failed to load from NBT at {0},{1},{2}", new Object[]{xCoord, yCoord, zCoord});
      deletePipe = true;
    }

    sideProperties.readFromNBT(nbt);
    attachPluggables = true;
  }

  @Override
  public void invalidate() {
    initialized = false;
    tileBuffer = null;

    if (pipe != null) {
      pipe.invalidate();
    }

    sideProperties.invalidate();

    super.invalidate();
  }

  @Override
  public void validate() {
    super.validate();
    initialized = false;
    tileBuffer = null;
    bindPipe();

    if (pipe != null) {
      pipe.validate();
    }

    sideProperties.validate(this);
  }

  protected void notifyBlockChanged() {
    worldObj.notifyBlockOfNeighborChange(xCoord, yCoord, zCoord, getBlock());
    scheduleRenderUpdate();
    sendUpdateToClient();
    BlockGenericPipe.updateNeighbourSignalState(pipe);
  }

  @Override
  public void updateEntity() {
    if (attachPluggables) {
      attachPluggables = false;
      // Attach callback
      for (int i = 0; i < ForgeDirection.VALID_DIRECTIONS.length; i++) {
        if (sideProperties.pluggables[i] != null) {
          sideProperties.pluggables[i].onAttachedPipe(this, ForgeDirection.getOrientation(i));
        }
      }
    }

    if (!worldObj.isRemote) {
      if (deletePipe) {
        worldObj.setBlockToAir(xCoord, yCoord, zCoord);
      }

      if (pipe == null) {
        return;
      }

      if (!initialized) {
        initialize(pipe);
      }
    }

    if (!BlockGenericPipe.isValid(pipe)) {
      return;
    }

    pipe.updateEntity();

    if (worldObj.isRemote) {
      if (resyncGateExpansions) {
        syncGateExpansions();
      }

      return;
    }

    if (blockNeighborChange) {
      computeConnections();
      pipe.onNeighborBlockChange(0);
      blockNeighborChange = false;
      refreshRenderState = true;
    }

    if (refreshRenderState) {
      refreshRenderState();
      refreshRenderState = false;
    }

    if (sendClientUpdate) {
      sendClientUpdate = false;

      if (worldObj instanceof WorldServer) {
        WorldServer world = (WorldServer) worldObj;
        BuildCraftPacket updatePacket = getBCDescriptionPacket();

        for (Object o : world.playerEntities) {
          EntityPlayerMP player = (EntityPlayerMP) o;

          if (world.getPlayerManager().isPlayerWatchingChunk (player, xCoord >> 4, zCoord >> 4)) {
            BuildCraftCore.instance.sendToPlayer(player, updatePacket);
          }
        }
      }
    }
  }

  public int getItemMetadata() {
    return 1 + (worldObj.isRemote ? renderState.glassColor : glassColor);
  }
 
  public int getStainedColorMultiplier() {
    int color;
   
    if (worldObj.isRemote) {
      color = renderState.glassColor;
    } else {
      color = this.glassColor;
    }
   
    return color >= 0 ? ColorUtils.getRGBColor(color) : -1;
  }
 
  /**
   *  PRECONDITION: worldObj must not be null
   */
  protected void refreshRenderState() {
    renderState.glassColor = (byte) glassColor;
   
    // Pipe connections;
    for (ForgeDirection o : ForgeDirection.VALID_DIRECTIONS) {
      renderState.pipeConnectionMatrix.setConnected(o, this.pipeConnectionsBuffer[o.ordinal()]);
    }

    // Pipe Textures
    for (int i = 0; i < 7; i++) {
      ForgeDirection o = ForgeDirection.getOrientation(i);
      renderState.textureMatrix.setIconIndex(o, pipe.getIconIndex(o));
    }

    // WireState
    for (PipeWire color : PipeWire.values()) {
      renderState.wireMatrix.setWire(color, pipe.wireSet[color.ordinal()]);

      for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) {
        renderState.wireMatrix.setWireConnected(color, direction, pipe.isWireConnectedTo(this.getTile(direction), color));
      }

      boolean lit = pipe.signalStrength[color.ordinal()] > 0;

      switch (color) {
        case RED:
          renderState.wireMatrix.setWireIndex(color, lit ? WireIconProvider.Texture_Red_Lit : WireIconProvider.Texture_Red_Dark);
          break;
        case BLUE:
          renderState.wireMatrix.setWireIndex(color, lit ? WireIconProvider.Texture_Blue_Lit : WireIconProvider.Texture_Blue_Dark);
          break;
        case GREEN:
          renderState.wireMatrix.setWireIndex(color, lit ? WireIconProvider.Texture_Green_Lit : WireIconProvider.Texture_Green_Dark);
          break;
        case YELLOW:
          renderState.wireMatrix.setWireIndex(color, lit ? WireIconProvider.Texture_Yellow_Lit : WireIconProvider.Texture_Yellow_Dark);
          break;
        default:
          break;

      }
    }

    // Gate Textures and movement
    for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) {
      final Gate gate = pipe.gates[direction.ordinal()];
      renderState.gateMatrix.setIsGateExists(gate != null, direction);
      renderState.gateMatrix.setIsGateLit(gate != null && gate.isGateActive(), direction);
      renderState.gateMatrix.setIsGatePulsing(gate != null && gate.isGatePulsing(), direction);
    }

    // Facades
    for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) {
      IPipePluggable pluggable = sideProperties.pluggables[direction.ordinal()];
      if (!(pluggable instanceof ItemFacade.FacadePluggable)) {
        renderState.facadeMatrix.setFacade(direction, null, 0, true);
        continue;
      }
      FacadeState[] states = ((ItemFacade.FacadePluggable) pluggable).states;
      if (states == null) {
        renderState.facadeMatrix.setFacade(direction, null, 0, true);
        continue;
      }
      // Iterate over all states and activate first proper
      FacadeState defaultState = null, activeState = null;
      for (FacadeState state : states) {
        if (state.wire == null) {
          defaultState = state;
          continue;
        }
        if (pipe != null && pipe.isWireActive(state.wire)) {
          activeState = state;
          break;
        }
      }
      if (activeState == null) {
        activeState = defaultState;
      }
      Block block = activeState != null ? activeState.block : null;
      int metadata = activeState != null ? activeState.metadata : 0;
      boolean transparent = activeState == null || block == null;
      renderState.facadeMatrix.setFacade(direction, block, metadata, transparent);
    }

    //Plugs
    for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) {
      IPipePluggable pluggable = sideProperties.pluggables[direction.ordinal()];
      renderState.plugMatrix.setConnected(direction, pluggable instanceof ItemPlug.PlugPluggable);

      if (pluggable instanceof ItemRobotStation.RobotStationPluggable) {
        DockingStation station = ((ItemRobotStation.RobotStationPluggable) pluggable).getStation();

        if (station.isTaken()) {
          if (station.isMainStation()) {
            renderState.robotStationMatrix.setState(direction,
              RobotStationState.Linked);
          } else {
            renderState.robotStationMatrix.setState(direction,
                RobotStationState.Reserved);
          }
        } else {
          renderState.robotStationMatrix.setState(direction,
              RobotStationState.Available);
        }
      } else {
        renderState.robotStationMatrix.setState(direction, RobotStationState.None);
      }

    }

    if (renderState.isDirty()) {
      renderState.clean();
      sendUpdateToClient();
    }
  }

  public void initialize(Pipe<?> pipe) {
    this.blockType = getBlockType();

    if (pipe == null) {
      BCLog.logger.log(Level.WARN, "Pipe failed to initialize at {0},{1},{2}, deleting", new Object[]{xCoord, yCoord, zCoord});
      worldObj.setBlockToAir(xCoord, yCoord, zCoord);
      return;
    }

    this.pipe = pipe;

    for (ForgeDirection o : ForgeDirection.VALID_DIRECTIONS) {
      TileEntity tile = getTile(o);

      if (tile instanceof ITileBufferHolder) {
        ((ITileBufferHolder) tile).blockCreated(o, BuildCraftTransport.genericPipeBlock, this);
      }
      if (tile instanceof TileGenericPipe) {
        ((TileGenericPipe) tile).scheduleNeighborChange();
      }
    }

    bindPipe();

    computeConnections();
    scheduleNeighborChange();
    scheduleRenderUpdate();

    if (pipe.needsInit()) {
      pipe.initialize();
    }

    initialized = true;
  }

  private void bindPipe() {
    if (!pipeBound && pipe != null) {
      pipe.setTile(this);
      coreState.pipeId = Item.getIdFromItem(pipe.item);
      pipeBound = true;
    }
  }

  public boolean isInitialized() {
    return initialized;
  }

  public void scheduleNeighborChange() {
    blockNeighborChange = true;
  }

  /* IPIPEENTRY */
  @Override
  public int injectItem(ItemStack payload, boolean doAdd, ForgeDirection from, EnumColor color) {
    if (!pipe.inputOpen(from)) {
      return 0;
    }

    if (BlockGenericPipe.isValid(pipe) && pipe.transport instanceof PipeTransportItems && isPipeConnected(from)) {
      if (doAdd) {
        Position itemPos = new Position(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5, from.getOpposite());
        itemPos.moveBackwards(0.4);

        TravelingItem pipedItem = TravelingItem.make(itemPos.x, itemPos.y, itemPos.z, payload);
        pipedItem.color = color;
        ((PipeTransportItems) pipe.transport).injectItem(pipedItem, itemPos.orientation);
      }
      return payload.stackSize;
    }

    return 0;
  }

  @Override
  public int injectItem(ItemStack payload, boolean doAdd, ForgeDirection from) {
    return injectItem(payload, doAdd, from, null);
  }

  @Override
  public PipeType getPipeType() {
    if (BlockGenericPipe.isValid(pipe)) {
      return pipe.transport.getPipeType();
    }
    return null;
  }

  /* SMP */

  public BuildCraftPacket getBCDescriptionPacket() {
    bindPipe();
    updateCoreState();

    PacketTileState packet = new PacketTileState(this.xCoord, this.yCoord, this.zCoord);

    if (pipe != null && pipe.transport != null) {
      pipe.transport.sendDescriptionPacket();
    }

    packet.addStateForSerialization((byte) 0, coreState);
    packet.addStateForSerialization((byte) 1, renderState);

    if (pipe instanceof IClientState) {
      packet.addStateForSerialization((byte) 2, (IClientState) pipe);
    }

    return packet;
  }

  @Override
  public Packet getDescriptionPacket() {
    return Utils.toPacket(getBCDescriptionPacket(), 1);
  }

  public void sendUpdateToClient() {
    sendClientUpdate = true;
  }

  @Override
  public void blockRemoved(ForgeDirection from) {

  }

  public TileBuffer[] getTileCache() {
    if (tileBuffer == null && pipe != null) {
      tileBuffer = TileBuffer.makeBuffer(worldObj, xCoord, yCoord, zCoord, pipe.transport.delveIntoUnloadedChunks());
    }
    return tileBuffer;
  }

  @Override
  public void blockCreated(ForgeDirection from, Block block, TileEntity tile) {
    TileBuffer[] cache = getTileCache();
    if (cache != null) {
      cache[from.getOpposite().ordinal()].set(block, tile);
    }
  }

  @Override
  public Block getBlock(ForgeDirection to) {
    TileBuffer[] cache = getTileCache();
    if (cache != null) {
      return cache[to.ordinal()].getBlock();
    } else {
      return null;
    }
  }

  @Override
  public TileEntity getTile(ForgeDirection to) {
    TileBuffer[] cache = getTileCache();
    if (cache != null) {
      return cache[to.ordinal()].getTile();
    } else {
      return null;
    }
  }
 
  protected boolean canPipeConnect_internal(TileEntity with, ForgeDirection side) {
    if (!(pipe instanceof IPipeConnectionForced) || !((IPipeConnectionForced) pipe).ignoreConnectionOverrides(side)) {
      if (with instanceof IPipeConnection) {
        IPipeConnection.ConnectOverride override = ((IPipeConnection) with).overridePipeConnection(pipe.transport.getPipeType(), side.getOpposite());
        if (override != IPipeConnection.ConnectOverride.DEFAULT) {
          return override == IPipeConnection.ConnectOverride.CONNECT;
        }
      }
    }

    if (with instanceof TileGenericPipe) {
      TileGenericPipe other = (TileGenericPipe) with;
     
      if (other.hasBlockingPluggable(side.getOpposite())) {
        return false;
      }
     
      if (other.glassColor >= 0 && glassColor >= 0 && other.glassColor != glassColor) {
        return false;
      }
     
      Pipe<?> otherPipe = ((TileGenericPipe) with).pipe;

      if (!BlockGenericPipe.isValid(otherPipe)) {
        return false;
      }

      if (!otherPipe.canPipeConnect(this, side.getOpposite())) {
        return false;
      }
    }

    return pipe.canPipeConnect(with, side);
  }

  /**
   * Checks if this tile can connect to another tile
   *
   * @param with - The other Tile
   * @param side - The orientation to get to the other tile ('with')
   * @return true if pipes are considered connected
   */
  protected boolean canPipeConnect(TileEntity with, ForgeDirection side) {
    if (with == null) {
      return false;
    }

    if (hasBlockingPluggable(side)) {
      return false;
    }

    if (!BlockGenericPipe.isValid(pipe)) {
      return false;
    }

    return canPipeConnect_internal(with, side);
  }

  protected boolean hasBlockingPluggable(ForgeDirection side) {
    IPipePluggable pluggable = sideProperties.pluggables[side.ordinal()];
    return pluggable != null && pluggable.blocking(this, side);
  }

  private void computeConnections() {
    TileBuffer[] cache = getTileCache();
    if (cache == null) {
      return;
    }

    for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) {
      TileBuffer t = cache[side.ordinal()];
      t.refresh();

      pipeConnectionsBuffer[side.ordinal()] = canPipeConnect(t.getTile(), side);
    }
  }

  @Override
  public boolean isPipeConnected(ForgeDirection with) {
    if (worldObj.isRemote) {
      return renderState.pipeConnectionMatrix.isConnected(with);
    }
    return pipeConnectionsBuffer[with.ordinal()];
  }

  @Override
  public boolean doDrop() {
    if (BlockGenericPipe.isValid(pipe)) {
      return pipe.doDrop();
    } else {
      return false;
    }
  }

  @Override
  public void onChunkUnload() {
    if (pipe != null) {
      pipe.onChunkUnload();
    }
  }

  /**
   * ITankContainer implementation *
   */
  @Override
  public int fill(ForgeDirection from, FluidStack resource, boolean doFill) {
    if (BlockGenericPipe.isValid(pipe) && pipe.transport instanceof IFluidHandler && !hasPlug(from) && !hasRobotStation(from)) {
      return ((IFluidHandler) pipe.transport).fill(from, resource, doFill);
    } else {
      return 0;
    }
  }

  @Override
  public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) {
    if (BlockGenericPipe.isValid(pipe) && pipe.transport instanceof IFluidHandler && !hasPlug(from) && !hasRobotStation(from)) {
      return ((IFluidHandler) pipe.transport).drain(from, maxDrain, doDrain);
    } else {
      return null;
    }
  }

  @Override
  public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) {
    if (BlockGenericPipe.isValid(pipe) && pipe.transport instanceof IFluidHandler && !hasPlug(from) && !hasRobotStation(from)) {
      return ((IFluidHandler) pipe.transport).drain(from, resource, doDrain);
    } else {
      return null;
    }
  }

  @Override
  public boolean canFill(ForgeDirection from, Fluid fluid) {
    if (BlockGenericPipe.isValid(pipe) && pipe.transport instanceof IFluidHandler && !hasPlug(from) && !hasRobotStation(from)) {
      return ((IFluidHandler) pipe.transport).canFill(from, fluid);
    } else {
      return false;
    }
  }

  @Override
  public boolean canDrain(ForgeDirection from, Fluid fluid) {
    if (BlockGenericPipe.isValid(pipe) && pipe.transport instanceof IFluidHandler && !hasPlug(from) && !hasRobotStation(from)) {
      return ((IFluidHandler) pipe.transport).canDrain(from, fluid);
    } else {
      return false;
    }
  }

  @Override
  public FluidTankInfo[] getTankInfo(ForgeDirection from) {
    return null;
  }

  public void scheduleRenderUpdate() {
    refreshRenderState = true;
  }

  public boolean addFacade(ForgeDirection direction, FacadeState[] states) {
    return setPluggable(direction, new ItemFacade.FacadePluggable(states));
  }

  public boolean addPlug(ForgeDirection direction) {
    return setPluggable(direction, new ItemPlug.PlugPluggable());
  }

  public boolean addRobotStation(ForgeDirection direction) {
    return setPluggable(direction, new ItemRobotStation.RobotStationPluggable());
  }

  public boolean addGate(ForgeDirection direction, Gate gate) {
    gate.setDirection(direction);
    pipe.gates[direction.ordinal()] = gate;
    return setPluggable(direction, new ItemGate.GatePluggable(gate));
  }

  public boolean hasFacade(ForgeDirection direction) {
    if (direction == null || direction == ForgeDirection.UNKNOWN) {
      return false;
    } else if (this.getWorldObj().isRemote) {
      return renderState.facadeMatrix.getFacadeBlock(direction) != null;
    } else {
      return sideProperties.pluggables[direction.ordinal()] instanceof ItemFacade.FacadePluggable;
    }
  }

  public boolean hasGate(ForgeDirection direction) {
    if (direction == null || direction == ForgeDirection.UNKNOWN) {
      return false;
    } else if (this.getWorldObj().isRemote) {
      return renderState.gateMatrix.isGateExists(direction);
    } else {
      return sideProperties.pluggables[direction.ordinal()] instanceof ItemGate.GatePluggable;
    }
  }

  public boolean setPluggable(ForgeDirection direction, IPipePluggable pluggable) {
    if (worldObj != null && worldObj.isRemote || pluggable == null) {
      return false;
    }
    sideProperties.dropItem(this, direction);
    sideProperties.pluggables[direction.ordinal()] = pluggable;
    pluggable.onAttachedPipe(this, direction);
    notifyBlockChanged();
    return true;
  }

  private void updateCoreState() {
    for (int i = 0; i < ForgeDirection.VALID_DIRECTIONS.length; i++) {
      IPipePluggable pluggable = sideProperties.pluggables[i];
      coreState.gates[i] = pluggable instanceof ItemGate.GatePluggable ? (ItemGate.GatePluggable) pluggable : null;
    }
  }

  public boolean hasEnabledFacade(ForgeDirection direction) {
    return hasFacade(direction) && !renderState.facadeMatrix.getFacadeTransparent(direction);
  }

  public ItemStack getFacade(ForgeDirection direction) {
    IPipePluggable pluggable = sideProperties.pluggables[direction.ordinal()];
    return pluggable instanceof ItemFacade.FacadePluggable ?
        ItemFacade.getFacade(((ItemFacade.FacadePluggable) pluggable).states) : null;
  }

  public DockingStation getStation(ForgeDirection direction) {
    IPipePluggable pluggable = sideProperties.pluggables[direction.ordinal()];
    return pluggable instanceof ItemRobotStation.RobotStationPluggable ?
        ((ItemRobotStation.RobotStationPluggable) pluggable).getStation() : null;
  }

  // Legacy
  public void setGate(Gate gate, int direction) {
    if (sideProperties.pluggables[direction] == null) {
      gate.setDirection(ForgeDirection.getOrientation(direction));
      pipe.gates[direction] = gate;
      sideProperties.pluggables[direction] = new ItemGate.GatePluggable(gate);
    }
  }

  public boolean dropSideItems(ForgeDirection direction) {
    return sideProperties.dropItem(this, direction);
  }

  @SideOnly(Side.CLIENT)
  public IIconProvider getPipeIcons() {
    if (pipe == null) {
      return null;
    }
    return pipe.getIconProvider();
  }

  @Override
  public IClientState getStateInstance(byte stateId) {
    switch (stateId) {
      case 0:
        return coreState;
      case 1:
        return renderState;
      case 2:
        return (IClientState) pipe;
    }
    throw new RuntimeException("Unknown state requested: " + stateId + " this is a bug!");
  }

  @Override
  public void afterStateUpdated(byte stateId) {
    if (!worldObj.isRemote) {
      return;
    }

    switch (stateId) {
      case 0:
        if (pipe == null && coreState.pipeId != 0) {
          initialize(BlockGenericPipe.createPipe((Item) Item.itemRegistry.getObjectById(coreState.pipeId)));
        }

        if (pipe == null) {
          break;
        }

        for (int i = 0; i < ForgeDirection.VALID_DIRECTIONS.length; i++) {
          final ItemGate.GatePluggable gatePluggable = coreState.gates[i];
          if (gatePluggable == null) {
            pipe.gates[i] = null;
            continue;
          }
          Gate gate = pipe.gates[i];
          if (gate == null || gate.logic != gatePluggable.logic || gate.material != gatePluggable.material) {
            pipe.gates[i] = GateFactory.makeGate(pipe, gatePluggable.material, gatePluggable.logic, ForgeDirection.getOrientation(i));
          }
        }

        syncGateExpansions();

        worldObj.markBlockRangeForRenderUpdate(xCoord, yCoord, zCoord, xCoord, yCoord, zCoord);
        break;

      case 1: {
        if (renderState.needsRenderUpdate()) {
          worldObj.markBlockRangeForRenderUpdate(xCoord, yCoord, zCoord, xCoord, yCoord, zCoord);
          renderState.clean();
        }
        break;
      }
    }
  }

  private void syncGateExpansions() {
    resyncGateExpansions = false;
    for (int i = 0; i < ForgeDirection.VALID_DIRECTIONS.length; i++) {
      Gate gate = pipe.gates[i];
      ItemGate.GatePluggable gatePluggable = coreState.gates[i];
      if (gate != null && gatePluggable.expansions.length > 0) {
        for (IGateExpansion expansion : gatePluggable.expansions) {
          if (expansion != null) {
            if (!gate.expansions.containsKey(expansion)) {
              gate.addGateExpansion(expansion);
            }
          } else {
            resyncGateExpansions = true;
          }
        }
      }
    }
  }

  @Override
  @SideOnly(Side.CLIENT)
  public double getMaxRenderDistanceSquared() {
    return DefaultProps.PIPE_CONTENTS_RENDER_DIST * DefaultProps.PIPE_CONTENTS_RENDER_DIST;
  }

  @Override
  public boolean shouldRefresh(Block oldBlock, Block newBlock, int oldMeta, int newMeta, World world, int x, int y, int z) {
    return oldBlock != newBlock;
  }

  @Override
  public boolean isSolidOnSide(ForgeDirection side) {
    if (hasFacade(side)) {
      return true;
    }

    if (BlockGenericPipe.isValid(pipe) && pipe instanceof ISolidSideTile) {
      if (((ISolidSideTile) pipe).isSolidOnSide(side)) {
        return true;
      }
    }
    return false;
  }

  public boolean hasPlug(ForgeDirection side) {
    if (side == null || side == ForgeDirection.UNKNOWN) {
      return false;
    }

    if (this.worldObj.isRemote) {
      return renderState.plugMatrix.isConnected(side);
    }

    return sideProperties.pluggables[side.ordinal()] instanceof ItemPlug.PlugPluggable;
  }

  public boolean hasRobotStation(ForgeDirection side) {
    if (side == null || side == ForgeDirection.UNKNOWN) {
      return false;
    }

    if (this.worldObj.isRemote) {
      return renderState.robotStationMatrix.isConnected(side);
    }

    return sideProperties.pluggables[side.ordinal()] instanceof ItemRobotStation.RobotStationPluggable;
  }

  public Block getBlock() {
    return getBlockType();
  }

  @Override
  public World getWorld() {
    return worldObj;
  }

  public boolean isUseableByPlayer(EntityPlayer player) {
    return worldObj.getTileEntity(xCoord, yCoord, zCoord) == this;
  }

  @Override
  public void writeGuiData(ByteBuf data) {
    if (BlockGenericPipe.isValid(pipe) && pipe instanceof IGuiReturnHandler) {
      ((IGuiReturnHandler) pipe).writeGuiData(data);
    }
  }

  @Override
  public void readGuiData(ByteBuf data, EntityPlayer sender) {
    if (BlockGenericPipe.isValid(pipe) && pipe instanceof IGuiReturnHandler) {
      ((IGuiReturnHandler) pipe).readGuiData(data, sender);
    }
  }

  @Override
  public PowerReceiver getPowerReceiver(ForgeDirection side) {
    if (BlockGenericPipe.isValid(pipe) && pipe instanceof IPowerReceptor) {
      return ((IPowerReceptor) pipe).getPowerReceiver(null);
    } else {
      return null;
    }
  }

  @Override
  public void doWork(PowerHandler workProvider) {
    if (BlockGenericPipe.isValid(pipe) && pipe instanceof IPowerReceptor) {
      ((IPowerReceptor) pipe).doWork(workProvider);
    }
  }

  @Override
  public boolean canConnectEnergy(ForgeDirection from) {
    if (pipe instanceof IEnergyHandler) {
      return ((IEnergyHandler) pipe).canConnectEnergy(from);
    } else {
      return false;
    }
  }

  @Override
  public int receiveEnergy(ForgeDirection from, int maxReceive,
      boolean simulate) {
    if (pipe instanceof IEnergyHandler) {
      return ((IEnergyHandler) pipe).receiveEnergy(from, maxReceive, simulate);
    } else {
      return 0;
    }
  }

  @Override
  public int extractEnergy(ForgeDirection from, int maxExtract,
      boolean simulate) {
    if (pipe instanceof IEnergyHandler) {
      return ((IEnergyHandler) pipe).extractEnergy(from, maxExtract, simulate);
    } else {
      return 0;
    }
  }

  @Override
  public int getEnergyStored(ForgeDirection from) {
    if (pipe instanceof IEnergyHandler) {
      return ((IEnergyHandler) pipe).getEnergyStored(from);
    } else {
      return 0;
    }
  }

  @Override
  public int getMaxEnergyStored(ForgeDirection from) {
    if (pipe instanceof IEnergyHandler) {
      return ((IEnergyHandler) pipe).getMaxEnergyStored(from);
    } else {
      return 0;
    }
  }

  @Override
  public TileEntity getAdjacentTile(ForgeDirection dir) {
    return getTile(dir);
  }

  @Override
  public IPipe getPipe() {
    return pipe;
  }
}
TOP

Related Classes of buildcraft.transport.TileGenericPipe$SideProperties

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.