Package mekanism.api.transmitters

Source Code of mekanism.api.transmitters.DynamicNetwork$NetworkClientRequest

package mekanism.api.transmitters;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;

import mekanism.api.Coord4D;
import mekanism.api.IClientTicker;
import mekanism.api.Range4D;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.ForgeDirection;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.Event;

public abstract class DynamicNetwork<A, N extends DynamicNetwork<A, N>> implements ITransmitterNetwork<A, N>, IClientTicker, INetworkDataHandler
{
  public LinkedHashSet<IGridTransmitter<N>> transmitters = new LinkedHashSet<IGridTransmitter<N>>();

  public HashMap<Coord4D, A> possibleAcceptors = new HashMap<Coord4D, A>();
  public HashMap<A, ForgeDirection> acceptorDirections = new HashMap<A, ForgeDirection>();

  private List<DelayQueue> updateQueue = new ArrayList<DelayQueue>();
 
  protected Range4D packetRange = null;

  protected int ticksSinceCreate = 0;
 
  protected int capacity = 0;
  protected double meanCapacity = 0;
 
  protected boolean fixed = false;

  protected boolean needsUpdate = false;

  protected abstract ITransmitterNetwork<A, N> create(IGridTransmitter<N>... varTransmitters);

  protected abstract ITransmitterNetwork<A, N> create(Collection<IGridTransmitter<N>> collection);

  protected abstract ITransmitterNetwork<A, N> create(Set<N> networks);
 
  protected void clearAround(IGridTransmitter<N> transmitter)
  {
    for(ForgeDirection side : ForgeDirection.VALID_DIRECTIONS)
    {
      Coord4D coord = Coord4D.get(transmitter.getTile()).getFromSide(side);
     
      if(possibleAcceptors.containsKey(coord))
      {
        clearIfNecessary(coord, transmitter, side.getOpposite());
      }
    }
  }
 
  protected void clearIfNecessary(Coord4D acceptor, IGridTransmitter<N> transmitter, ForgeDirection side)
  {
    if(getWorld() == null)
    {
      return;
    }
   
    if(acceptor.getTileEntity(getWorld()) == null || acceptor.getTileEntity(getWorld()).isInvalid() || transmitter.canConnectToAcceptor(side, true))
    {
      possibleAcceptors.remove(acceptor);
      acceptorDirections.remove(acceptor.getTileEntity(getWorld()));
    }
  }

  public void addAllTransmitters(Set<IGridTransmitter<N>> newTransmitters)
  {
    transmitters.addAll(newTransmitters);
    updateCapacity();
  }

  public boolean isFirst(IGridTransmitter<N> transmitter)
  {
    return transmitters.iterator().next().equals(transmitter);
  }
 
  @Override
  public void fullRefresh()
  {
    possibleAcceptors.clear();
    acceptorDirections.clear();
   
    for(IGridTransmitter<N> transmitter : transmitters)
    {
      refresh(transmitter);
    }
   
    refresh();
  }
 
  public Range4D getPacketRange()
  {
    if(packetRange == null)
    {
      return genPacketRange();
    }
   
    return packetRange;
  }
 
  public World getWorld()
  {
    if(getSize() == 0)
    {
      return null;
    }
   
    return transmitters.iterator().next().getTile().getWorldObj();
  }
 
  protected Range4D genPacketRange()
  {
    if(getSize() == 0)
    {
      deregister();
      return null;
    }
   
    Coord4D initCoord = Coord4D.get(transmitters.iterator().next().getTile());
   
    int minX = initCoord.xCoord;
    int minY = initCoord.yCoord;
    int minZ = initCoord.zCoord;
    int maxX = initCoord.xCoord;
    int maxY = initCoord.yCoord;
    int maxZ = initCoord.zCoord;
   
    for(IGridTransmitter transmitter : transmitters)
    {
      Coord4D coord = Coord4D.get(transmitter.getTile());
     
      if(coord.xCoord < minX) minX = coord.xCoord;
      if(coord.yCoord < minY) minY = coord.yCoord;
      if(coord.zCoord < minZ) minZ = coord.zCoord;
      if(coord.xCoord > maxX) maxX = coord.xCoord;
      if(coord.yCoord > maxY) maxY = coord.yCoord;
      if(coord.zCoord > maxZ) maxZ = coord.zCoord;
    }
   
    return new Range4D(minX, minY, minZ, maxX, maxY, maxZ, getWorld().provider.dimensionId);
  }

  @Override
  public void removeTransmitter(IGridTransmitter<N> transmitter)
  {
    transmitters.remove(transmitter);
    updateCapacity();
   
    if(transmitters.size() == 0)
    {
      deregister();
    }
  }

  @Override
  public void register()
  {
    try {
      IGridTransmitter<N> aTransmitter = transmitters.iterator().next();

      if(aTransmitter instanceof TileEntity)
      {
        if(!((TileEntity)aTransmitter).getWorldObj().isRemote)
        {
          TransmitterNetworkRegistry.getInstance().registerNetwork(this);
        }
        else {
          MinecraftForge.EVENT_BUS.post(new ClientTickUpdate(this, (byte)1));
        }
      }
    } catch(NoSuchElementException e) {}
  }

  @Override
  public void deregister()
  {
    transmitters.clear();

    if(FMLCommonHandler.instance().getEffectiveSide().isServer())
    {
      TransmitterNetworkRegistry.getInstance().removeNetwork(this);
    }
    else {
      MinecraftForge.EVENT_BUS.post(new ClientTickUpdate(this, (byte)0));
    }
  }

  @Override
  public int getSize()
  {
    return transmitters.size();
  }

  @Override
  public int getAcceptorSize()
  {
    return possibleAcceptors.size();
  }

  public synchronized void updateCapacity()
  {
    updateMeanCapacity();
    capacity = (int)meanCapacity * transmitters.size();
  }

    /**
     * Override this if things can have variable capacity along the network.
     * @return An 'average' value of capacity. Calculate it how you will.
     */
  protected synchronized void updateMeanCapacity()
  {
    if(transmitters.size() > 0)
    {
      meanCapacity = transmitters.iterator().next().getCapacity();
    }
    else {
      meanCapacity = 0;
    }
  }
 
    public int getCapacity()
    {
      return capacity;
    }

    public double getMeanCapacity()
    {
      return meanCapacity;
    }
 
  @Override
  public void tick()
  {
    boolean didFix = false;

    if(!fixed)
    {
      ticksSinceCreate++;

      if(transmitters.size() == 0)
      {
        deregister();
        return;
      }

      if(ticksSinceCreate > 1200)
      {
        ticksSinceCreate = 0;
        fixMessedUpNetwork(transmitters.iterator().next());
        didFix = true;
      }
    }

    if(!didFix)
    {
      onUpdate();
    }
  }

  public void onUpdate()
  {
    if(FMLCommonHandler.instance().getEffectiveSide().isServer())
    {
      Iterator<DelayQueue> i = updateQueue.iterator();

      try {
        while(i.hasNext())
        {
          DelayQueue q = i.next();

          if(q.delay > 0)
          {
            q.delay--;
          }
          else {
            needsUpdate = true;
            i.remove();
          }
        }
      } catch(Exception e) {}
    }
  }

  @Override
  public synchronized void fixMessedUpNetwork(IGridTransmitter<N> transmitter)
  {
    if(transmitter instanceof TileEntity)
    {
      NetworkFinder finder = new NetworkFinder(((TileEntity)transmitter).getWorldObj(), getTransmissionType(), Coord4D.get((TileEntity)transmitter));
      List<Coord4D> partNetwork = finder.exploreNetwork();
      Set<IGridTransmitter<N>> newTransporters = new HashSet<IGridTransmitter<N>>();

      for(Coord4D node : partNetwork)
      {
        TileEntity nodeTile = node.getTileEntity(((TileEntity)transmitter).getWorldObj());

        if(TransmissionType.checkTransmissionType(nodeTile, getTransmissionType(), (TileEntity)transmitter))
        {
          ((IGridTransmitter<N>)nodeTile).removeFromTransmitterNetwork();
          newTransporters.add((IGridTransmitter<N>)nodeTile);
        }
      }

      ITransmitterNetwork<A, N> newNetwork = create(newTransporters);
      newNetwork.fullRefresh();
      newNetwork.setFixed(true);
      deregister();
    }
  }

  @Override
  public synchronized void split(IGridTransmitter<N> splitPoint)
  {
    if(splitPoint instanceof TileEntity)
    {
      removeTransmitter(splitPoint);

      TileEntity[] connectedBlocks = new TileEntity[6];
      boolean[] dealtWith = {false, false, false, false, false, false};
      List<ITransmitterNetwork<A, N>> newNetworks = new ArrayList<ITransmitterNetwork<A, N>>();

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

        if(sideTile != null)
        {
          connectedBlocks[side.ordinal()] = sideTile;
        }
      }

      for(int count = 0; count < connectedBlocks.length; count++)
      {
        TileEntity connectedBlockA = connectedBlocks[count];

        if(TransmissionType.checkTransmissionType(connectedBlockA, getTransmissionType()) && !dealtWith[count])
        {
          NetworkFinder finder = new NetworkFinder(((TileEntity)splitPoint).getWorldObj(), getTransmissionType(), Coord4D.get(connectedBlockA), Coord4D.get((TileEntity)splitPoint));
          List<Coord4D> partNetwork = finder.exploreNetwork();

          for(int check = count; check < connectedBlocks.length; check++)
          {
            if(check == count)
            {
              continue;
            }

            TileEntity connectedBlockB = connectedBlocks[check];

            if(TransmissionType.checkTransmissionType(connectedBlockB, getTransmissionType()) && !dealtWith[check])
            {
              if(partNetwork.contains(Coord4D.get(connectedBlockB)))
              {
                dealtWith[check] = true;
              }
            }
          }

          Set<IGridTransmitter<N>> newNetCables = new HashSet<IGridTransmitter<N>>();

          for(Coord4D node : finder.iterated)
          {
            TileEntity nodeTile = node.getTileEntity(((TileEntity)splitPoint).getWorldObj());

            if(TransmissionType.checkTransmissionType(nodeTile, getTransmissionType()))
            {
              if(nodeTile != splitPoint)
              {
                newNetCables.add((IGridTransmitter<N>)nodeTile);
              }
            }
          }

          newNetworks.add(create(newNetCables));
        }
      }

      if(newNetworks.size() > 0)
      {
        onNetworksCreated((List)newNetworks);

        for(ITransmitterNetwork<A, N> network : newNetworks)
        {
          network.fullRefresh();
        }
      }

      deregister();
    }
  }

  @Override
  public void onNetworksCreated(List<N> networks) {}

  @Override
  public void setFixed(boolean value)
  {
    fixed = value;
  }

  @Override
  public boolean needsTicks()
  {
    return getSize() > 0;
  }

  @Override
  public void clientTick()
  {
    ticksSinceCreate++;

    if(ticksSinceCreate == 5 && getSize() > 0)
    {
      TileEntity tile = (TileEntity)transmitters.iterator().next();
      MinecraftForge.EVENT_BUS.post(new NetworkClientRequest(tile));
    }
  }

  @Override
  public boolean canMerge(List<ITransmitterNetwork<?, ?>> networks)
  {
    return true;
  }

  public static class ClientTickUpdate extends Event
  {
    public DynamicNetwork network;
    public byte operation; /*0 remove, 1 add*/

    public ClientTickUpdate(DynamicNetwork net, byte b)
    {
      network = net;
      operation = b;
    }
  }

  public static class NetworkClientRequest extends Event
  {
    public TileEntity tileEntity;

    public NetworkClientRequest(TileEntity tile)
    {
      tileEntity = tile;
    }
  }

  public void addUpdate(EntityPlayer player)
  {
    updateQueue.add(new DelayQueue(player));
  }

  public static class NetworkFinder
  {
    public TransmissionType transmissionType;

    public World worldObj;
    public Coord4D start;

    public List<Coord4D> iterated = new ArrayList<Coord4D>();
    public List<Coord4D> toIgnore = new ArrayList<Coord4D>();

    public NetworkFinder(World world, TransmissionType type, Coord4D location, Coord4D... ignore)
    {
      worldObj = world;
      start = location;

      transmissionType = type;

      if(ignore != null)
      {
        for(int i = 0; i < ignore.length; i++)
        {
          toIgnore.add(ignore[i]);
        }
      }
    }

    public void loopAll(Coord4D location)
    {
      if(TransmissionType.checkTransmissionType(location.getTileEntity(worldObj), transmissionType))
      {
        iterated.add(location);
      }
      else {
        toIgnore.add(location);
      }

      for(ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS)
      {
        Coord4D obj = location.getFromSide(direction);

        if(!iterated.contains(obj) && !toIgnore.contains(obj))
        {
          TileEntity tileEntity = obj.getTileEntity(worldObj);

          if(!(tileEntity instanceof IBlockableConnection) || ((IBlockableConnection)tileEntity).canConnectMutual(direction.getOpposite()))
          {
            if(TransmissionType.checkTransmissionType(tileEntity, transmissionType, location.getTileEntity(worldObj)))
            {
              loopAll(obj);
            }
          }
        }
      }
    }

    public List<Coord4D> exploreNetwork()
    {
      loopAll(start);

      return iterated;
    }
  }

  public static class DelayQueue
  {
    public EntityPlayer player;
    public int delay;

    public DelayQueue(EntityPlayer p)
    {
      player = p;
      delay = 5;
    }
  }
}
TOP

Related Classes of mekanism.api.transmitters.DynamicNetwork$NetworkClientRequest

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.