Package mekanism.common.tank

Source Code of mekanism.common.tank.TankUpdateProtocol

package mekanism.common.tank;

import java.util.HashSet;
import java.util.Set;

import mekanism.api.Coord4D;
import mekanism.common.Mekanism;
import mekanism.common.tank.SynchronizedTankData.ValveData;
import mekanism.common.tile.TileEntityDynamicTank;
import mekanism.common.tile.TileEntityDynamicValve;
import mekanism.common.util.MekanismUtils;

import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;

public class TankUpdateProtocol
{
  public static final int FLUID_PER_TANK = 16000;

  /** The dynamic tank nodes that have already been iterated over. */
  public Set<TileEntityDynamicTank> iteratedNodes = new HashSet<TileEntityDynamicTank>();

  /** The structures found, all connected by some nodes to the pointer. */
  public SynchronizedTankData structureFound = null;

  /** The original block the calculation is getting run from. */
  public TileEntity pointer;

  public TankUpdateProtocol(TileEntity tileEntity)
  {
    pointer = tileEntity;
  }

  /**
   * Recursively loops through each node connected to the given TileEntity.
   * @param tile - the TileEntity to loop over
   */
  public void loopThrough(TileEntity tile)
  {
    World worldObj = tile.getWorldObj();

    int origX = tile.xCoord, origY = tile.yCoord, origZ = tile.zCoord;

    boolean isCorner = true;
    boolean isHollow = true;
    boolean rightBlocks = true;
    boolean rightFrame = true;

    Set<Coord4D> locations = new HashSet<Coord4D>();

    int xmin = 0, xmax = 0, ymin = 0, ymax = 0, zmin = 0, zmax = 0;

    int x = 0, y = 0, z = 0;

    int volume = 0;

    if((isViableNode(origX + 1, origY, origZ) && isViableNode(origX - 1, origY, origZ)) ||
        (isViableNode(origX, origY + 1, origZ) && isViableNode(origX, origY - 1, origZ)) ||
        (isViableNode(origX, origY, origZ + 1) && isViableNode(origX, origY, origZ - 1)))
    {
      isCorner = false;
    }

    if(isCorner)
    {
      if(isViableNode(origX+1, origY, origZ))
      {
        xmin = 0;

        while(isViableNode(origX+x+1, origY, origZ))
        {
          x++;
        }

        xmax = x;
      }
      else {
        xmax = 0;

        while(isViableNode(origX+x-1, origY, origZ))
        {
          x--;
        }

        xmin = x;
      }

      if(isViableNode(origX, origY+1, origZ))
      {
        ymin = 0;

        while(isViableNode(origX, origY+y+1, origZ))
        {
          y++;
        }

        ymax = y;
      }
      else {
        ymax = 0;

        while(isViableNode(origX, origY+y-1 ,origZ))
        {
          y--;
        }

        ymin = y;
      }

      if(isViableNode(origX, origY, origZ+1))
      {
        zmin = 0;

        while(isViableNode(origX, origY, origZ+z+1))
        {
          z++;
        }

        zmax = z;
      }
      else {
        zmax = 0;

        while(isViableNode(origX, origY, origZ+z-1))
        {
          z--;
        }

        zmin = z;
      }

      for(x = xmin; x <= xmax; x++)
      {
        for(y = ymin; y <= ymax; y++)
        {
          for(z = zmin; z <= zmax; z++)
          {
            if(x == xmin || x == xmax || y == ymin || y == ymax || z == zmin || z == zmax)
            {
              if(!isViableNode(origX+x, origY+y, origZ+z))
              {
                rightBlocks = false;
                break;
              }
              else if(isFrame(Coord4D.get(tile).translate(x, y, z), origX+xmin, origX+xmax, origY+ymin, origY+ymax, origZ+zmin, origZ+zmax) && !isValidFrame(origX+x, origY+y, origZ+z))
              {
                rightFrame = false;
                break;
              }
              else {
                locations.add(Coord4D.get(tile).translate(x, y, z));
              }
            }
            else {
              if(!isAir(origX+x, origY+y, origZ+z))
              {
                isHollow = false;
                break;
              }

              volume++;
            }
          }
          if(!isHollow || !rightBlocks || !rightFrame)
          {
            break;
          }
        }
        if(!isHollow || !rightBlocks || !rightFrame)
        {
          break;
        }
      }
    }

    volume += locations.size();

    if(volume >= 27 && volume <= 5832 && locations.size() >= 26)
    {
      if(rightBlocks && rightFrame && isHollow && isCorner)
      {
        SynchronizedTankData structure = new SynchronizedTankData();
        structure.locations = locations;
        structure.volLength = Math.abs(xmax-xmin)+1;
        structure.volHeight = Math.abs(ymax-ymin)+1;
        structure.volWidth = Math.abs(zmax-zmin)+1;
        structure.volume = volume;
        structure.renderLocation = Coord4D.get(tile).translate(0, 1, 0);

        for(Coord4D obj : structure.locations)
        {
          if(obj.getTileEntity(pointer.getWorldObj()) instanceof TileEntityDynamicValve)
          {
            ValveData data = new ValveData();
            data.location = obj;
            data.side = getSide(obj, origX+xmin, origX+xmax, origY+ymin, origY+ymax, origZ+zmin, origZ+zmax);

            structure.valves.add(data);
          }
        }

        if(structure.locations.contains(Coord4D.get(pointer)) && isCorrectCorner(Coord4D.get(tile), origX+xmin, origY+ymin, origZ+zmin))
        {
          structureFound = structure;
          return;
        }
      }
    }

    iteratedNodes.add((TileEntityDynamicTank)tile);

    for(ForgeDirection side : ForgeDirection.VALID_DIRECTIONS)
    {
      TileEntity tileEntity = Coord4D.get(tile).getFromSide(side).getTileEntity(tile.getWorldObj());

      if(tileEntity instanceof TileEntityDynamicTank)
      {
        if(!iteratedNodes.contains(tileEntity))
        {
          loopThrough(tileEntity);
        }
      }
    }
  }

  public ForgeDirection getSide(Coord4D obj, int xmin, int xmax, int ymin, int ymax, int zmin, int zmax)
  {
    if(obj.xCoord == xmin)
    {
      return ForgeDirection.WEST;
    }
    else if(obj.xCoord == xmax)
    {
      return ForgeDirection.EAST;
    }
    else if(obj.yCoord == ymin)
    {
      return ForgeDirection.DOWN;
    }
    else if(obj.yCoord == ymax)
    {
      return ForgeDirection.UP;
    }
    else if(obj.zCoord == zmin)
    {
      return ForgeDirection.NORTH;
    }
    else if(obj.zCoord == zmax)
    {
      return ForgeDirection.SOUTH;
    }

    return ForgeDirection.UNKNOWN;
  }

  /**
   * Whether or not the block at the specified location is an air block.
   * @param x - x coordinate
   * @param y - y coordinate
   * @param z - z coordinate
   * @return
   */
  private boolean isAir(int x, int y, int z)
  {
    return pointer.getWorldObj().isAirBlock(x, y, z);
  }

  /**
   * Whether or not the block at the specified location is a viable node for a dynamic tank.
   * @param x - x coordinate
   * @param y - y coordinate
   * @param z - z coordinate
   * @return
   */
  private boolean isViableNode(int x, int y, int z)
  {
    if(pointer.getWorldObj().getTileEntity(x, y, z) instanceof TileEntityDynamicTank)
    {
      return true;
    }

    return false;
  }

  /**
   * If the block at the specified location is on the minimum of all angles of this dynamic tank, and the one to use for the
   * actual calculation.
   * @param obj - location to check
   * @param xmin - minimum x value
   * @param ymin - minimum y value
   * @param zmin - minimum z value
   * @return
   */
  private boolean isCorrectCorner(Coord4D obj, int xmin, int ymin, int zmin)
  {
    if(obj.xCoord == xmin && obj.yCoord == ymin && obj.zCoord == zmin)
    {
      return true;
    }

    return false;
  }

  /**
   * Whether or not the block at the specified location is considered a frame on the dynamic tank.
   * @param obj - location to check
   * @param xmin - minimum x value
   * @param xmax - maximum x value
   * @param ymin - minimum y value
   * @param ymax - maximum y value
   * @param zmin - minimum z value
   * @param zmax - maximum z value
   * @return
   */
  private boolean isFrame(Coord4D obj, int xmin, int xmax, int ymin, int ymax, int zmin, int zmax)
  {
    if(obj.xCoord == xmin && obj.yCoord == ymin)
      return true;
    if(obj.xCoord == xmax && obj.yCoord == ymin)
      return true;
    if(obj.xCoord == xmin && obj.yCoord == ymax)
      return true;
    if(obj.xCoord == xmax && obj.yCoord == ymax)
      return true;

    if(obj.xCoord == xmin && obj.zCoord == zmin)
      return true;
    if(obj.xCoord == xmax && obj.zCoord == zmin)
      return true;
    if(obj.xCoord == xmin && obj.zCoord == zmax)
      return true;
    if(obj.xCoord == xmax && obj.zCoord == zmax)
      return true;

    if(obj.yCoord == ymin && obj.zCoord == zmin)
      return true;
    if(obj.yCoord == ymax && obj.zCoord == zmin)
      return true;
    if(obj.yCoord == ymin && obj.zCoord == zmax)
      return true;
    if(obj.yCoord == ymax && obj.zCoord == zmax)
      return true;

    return false;
  }

  /**
   * Whether or not the block at the specified location serves as a frame for a dynamic tank.
   * @param x - x coordinate
   * @param y - y coordinate
   * @param z - z coordinate
   * @return
   */
  private boolean isValidFrame(int x, int y, int z)
  {
    return pointer.getWorldObj().getBlock(x, y, z) == Mekanism.BasicBlock && pointer.getWorldObj().getBlockMetadata(x, y, z) == 9;
  }

  /**
   * Runs the protocol and updates all tanks that make a part of the dynamic tank.
   */
  public void updateTanks()
  {
    loopThrough(pointer);

    if(structureFound != null)
    {
      for(TileEntityDynamicTank tileEntity : iteratedNodes)
      {
        if(!structureFound.locations.contains(Coord4D.get(tileEntity)))
        {
          for(TileEntity tile : iteratedNodes)
          {
            ((TileEntityDynamicTank)tileEntity).structure = null;
          }

          return;
        }
      }

      int idFound = -1;

      for(Coord4D obj : structureFound.locations)
      {
        TileEntityDynamicTank tileEntity = (TileEntityDynamicTank)obj.getTileEntity(pointer.getWorldObj());

        if(tileEntity.inventoryID != -1)
        {
          idFound = tileEntity.inventoryID;
          break;
        }
      }

      DynamicTankCache cache = new DynamicTankCache();

      if(idFound != -1)
      {
        if(Mekanism.dynamicInventories.get(idFound) != null)
        {
          cache = MekanismUtils.pullInventory(pointer.getWorldObj(), idFound);
        }
      }
      else {
        idFound = MekanismUtils.getUniqueInventoryID();
      }

      cache.apply(structureFound);

      if(structureFound.fluidStored != null)
      {
        structureFound.fluidStored.amount = Math.min(structureFound.fluidStored.amount, structureFound.volume*FLUID_PER_TANK);
      }

      for(Coord4D obj : structureFound.locations)
      {
        TileEntityDynamicTank tileEntity = (TileEntityDynamicTank)obj.getTileEntity(pointer.getWorldObj());

        tileEntity.inventoryID = idFound;
        tileEntity.structure = structureFound;
       
        tileEntity.cachedData.sync(structureFound);
      }
    }
    else {
      for(TileEntity tileEntity : iteratedNodes)
      {
        ((TileEntityDynamicTank)tileEntity).structure = null;
      }
    }
  }
}
TOP

Related Classes of mekanism.common.tank.TankUpdateProtocol

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.