Package appeng.me.cache

Source Code of appeng.me.cache.CraftingGridCache$ActiveCpuIterator

package appeng.me.cache;

import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;

import com.google.common.collect.*;
import net.minecraft.world.World;
import appeng.api.config.AccessRestriction;
import appeng.api.config.Actionable;
import appeng.api.networking.IGrid;
import appeng.api.networking.IGridHost;
import appeng.api.networking.IGridNode;
import appeng.api.networking.IGridStorage;
import appeng.api.networking.crafting.ICraftingCPU;
import appeng.api.networking.crafting.ICraftingCallback;
import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.networking.crafting.ICraftingJob;
import appeng.api.networking.crafting.ICraftingLink;
import appeng.api.networking.crafting.ICraftingMedium;
import appeng.api.networking.crafting.ICraftingPatternDetails;
import appeng.api.networking.crafting.ICraftingProvider;
import appeng.api.networking.crafting.ICraftingProviderHelper;
import appeng.api.networking.crafting.ICraftingRequester;
import appeng.api.networking.crafting.ICraftingWatcher;
import appeng.api.networking.crafting.ICraftingWatcherHost;
import appeng.api.networking.energy.IEnergyGrid;
import appeng.api.networking.events.MENetworkCraftingCpuChange;
import appeng.api.networking.events.MENetworkCraftingPatternChange;
import appeng.api.networking.events.MENetworkEventSubscribe;
import appeng.api.networking.events.MENetworkPostCacheConstruction;
import appeng.api.networking.security.BaseActionSource;
import appeng.api.networking.storage.IStorageGrid;
import appeng.api.storage.ICellProvider;
import appeng.api.storage.IMEInventoryHandler;
import appeng.api.storage.StorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IAEStack;
import appeng.api.storage.data.IItemList;
import appeng.crafting.CraftingJob;
import appeng.crafting.CraftingLink;
import appeng.crafting.CraftingLinkNexus;
import appeng.crafting.CraftingWatcher;
import appeng.me.cluster.implementations.CraftingCPUCluster;
import appeng.me.helpers.GenericInterestManager;
import appeng.tile.crafting.TileCraftingStorageTile;
import appeng.tile.crafting.TileCraftingTile;
import appeng.util.ItemSorters;

public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper, ICellProvider, IMEInventoryHandler<IAEStack>
{

  private final Set<CraftingCPUCluster> craftingCPUClusters = new HashSet<CraftingCPUCluster>();
  private final Set<ICraftingProvider> craftingProviders = new HashSet<ICraftingProvider>();

  private final Map<IGridNode, ICraftingWatcher> craftingWatchers = new HashMap<IGridNode, ICraftingWatcher>();

  private final IGrid grid;
  private IStorageGrid storageGrid;
  private IEnergyGrid energyGrid;

  private final Map<ICraftingPatternDetails, List<ICraftingMedium>> craftingMethods = new HashMap<ICraftingPatternDetails, List<ICraftingMedium>>();
  private final Map<IAEItemStack, ImmutableList<ICraftingPatternDetails>> craftableItems = new HashMap<IAEItemStack, ImmutableList<ICraftingPatternDetails>>();
  private final Set<IAEItemStack> emitableItems = new HashSet<IAEItemStack>();
  private final Map<String, CraftingLinkNexus> craftingLinks = new HashMap<String, CraftingLinkNexus>();

  private boolean updateList = false;
  private final Multimap<IAEStack, CraftingWatcher> interests = HashMultimap.create();
  public final GenericInterestManager<CraftingWatcher> interestManager = new GenericInterestManager<CraftingWatcher>( this.interests );

  static class ActiveCpuIterator implements Iterator<ICraftingCPU>
  {

    private final Iterator<CraftingCPUCluster> iterator;
    private CraftingCPUCluster cpuCluster;

    public ActiveCpuIterator(Collection<CraftingCPUCluster> o)
    {
      this.iterator = o.iterator();
      this.cpuCluster = null;
    }

    @Override
    public boolean hasNext()
    {
      findNext();

      return this.cpuCluster != null;
    }

    private void findNext()
    {
      while (this.iterator.hasNext() && this.cpuCluster == null)
      {
        this.cpuCluster = this.iterator.next();
        if ( !this.cpuCluster.isActive() || this.cpuCluster.isDestroyed )
        {
          this.cpuCluster = null;
        }
      }
    }

    @Override
    public ICraftingCPU next()
    {
      final ICraftingCPU o = this.cpuCluster;
      this.cpuCluster = null;

      return o;
    }

    @Override
    public void remove()
    {
      // no..
    }

  }

  @Override
  public ImmutableSet<ICraftingCPU> getCpus()
  {
    return ImmutableSet.copyOf( new ActiveCpuIterator( this.craftingCPUClusters ) );
  }

  public CraftingGridCache(IGrid grid)
  {
    this.grid = grid;
  }

  @MENetworkEventSubscribe
  public void afterCacheConstruction(MENetworkPostCacheConstruction cacheConstruction)
  {
    this.storageGrid = this.grid.getCache( IStorageGrid.class );
    this.energyGrid = this.grid.getCache( IEnergyGrid.class );

    this.storageGrid.registerCellProvider( this );
  }

  public void addLink(CraftingLink link)
  {
    if ( link.isStandalone() )
    {
      return;
    }

    CraftingLinkNexus nexus = this.craftingLinks.get( link.getCraftingID() );
    if ( nexus == null )
    {
      this.craftingLinks.put( link.getCraftingID(), nexus = new CraftingLinkNexus( link.getCraftingID() ) );
    }

    link.setNexus( nexus );
  }

  @Override
  public void onUpdateTick()
  {
    if ( this.updateList )
    {
      this.updateList = false;
      this.updateCPUClusters();
    }

    Iterator<CraftingLinkNexus> craftingLinkIterator = this.craftingLinks.values().iterator();
    while (craftingLinkIterator.hasNext())
    {
      if ( craftingLinkIterator.next().isDead( this.grid, this ) )
      {
        craftingLinkIterator.remove();
      }
    }

    for (CraftingCPUCluster cpu : this.craftingCPUClusters)
    {
      cpu.updateCraftingLogic( this.grid, this.energyGrid, this );
    }
  }

  @MENetworkEventSubscribe
  public void updateCPUClusters(MENetworkCraftingCpuChange c)
  {
    this.updateList = true;
  }

  @MENetworkEventSubscribe
  public void updateCPUClusters(MENetworkCraftingPatternChange c)
  {
    updatePatterns();
  }

  @Override
  public void removeNode(IGridNode gridNode, IGridHost machine)
  {
    if ( machine instanceof ICraftingWatcherHost )
    {
      ICraftingWatcher craftingWatcher = this.craftingWatchers.get( machine );
      if ( craftingWatcher != null )
      {
        craftingWatcher.clear();
        this.craftingWatchers.remove( machine );
      }
    }

    if ( machine instanceof ICraftingRequester )
    {
      for (CraftingLinkNexus link : this.craftingLinks.values())
      {
        if ( link.isMachine( machine ) )
        {
          link.removeNode();
        }
      }
    }

    if ( machine instanceof TileCraftingTile )
    {
      this.updateList = true;
    }

    if ( machine instanceof ICraftingProvider )
    {
      this.craftingProviders.remove( machine );
      this.updatePatterns();
    }
  }

  @Override
  public void addNode(IGridNode gridNode, IGridHost machine)
  {
    if ( machine instanceof ICraftingWatcherHost )
    {
      ICraftingWatcherHost watcherHost = (ICraftingWatcherHost) machine;
      CraftingWatcher watcher = new CraftingWatcher( this, watcherHost );
      craftingWatchers.put( gridNode, watcher );
      watcherHost.updateWatcher( watcher );
    }

    if ( machine instanceof ICraftingRequester )
    {
      for (ICraftingLink link : ((ICraftingRequester) machine).getRequestedJobs())
      {
        if ( link instanceof CraftingLink )
        {
          this.addLink( (CraftingLink) link );
        }
      }
    }

    if ( machine instanceof TileCraftingTile )
    {
      this.updateList = true;
    }

    if ( machine instanceof ICraftingProvider )
    {
      this.craftingProviders.add( (ICraftingProvider) machine );
      this.updatePatterns();
    }
  }

  private void updateCPUClusters()
  {
    this.craftingCPUClusters.clear();

    for (IGridNode cst : this.grid.getMachines( TileCraftingStorageTile.class ))
    {
      TileCraftingStorageTile tile = (TileCraftingStorageTile) cst.getMachine();
      CraftingCPUCluster cluster = (CraftingCPUCluster) tile.getCluster();
      if ( cluster != null )
      {
        this.craftingCPUClusters.add( cluster );

        if ( cluster.myLastLink != null )
        {
          addLink( (CraftingLink) cluster.myLastLink );
        }
      }
    }
  }

  @Override
  public void addCraftingOption(ICraftingMedium medium, ICraftingPatternDetails api)
  {
    List<ICraftingMedium> details = this.craftingMethods.get( api );
    if ( details == null )
    {
      details = new ArrayList<ICraftingMedium>();
      details.add( medium );
      this.craftingMethods.put( api, details );
    }
    else
    {
      details.add( medium );
    }
  }

  static final Comparator<ICraftingPatternDetails> comp = new Comparator<ICraftingPatternDetails>()
  {
    @Override
    public int compare(ICraftingPatternDetails firstDetail, ICraftingPatternDetails nextDetail)
    {
      return nextDetail.getPriority() - firstDetail.getPriority();
    }
  };

  private void updatePatterns()
  {
    Map<IAEItemStack, ImmutableList<ICraftingPatternDetails>> oldItems = this.craftableItems;

    // erase list.
    this.craftingMethods.clear();
    this.craftableItems.clear();
    this.emitableItems.clear();

    // update the stuff that was in the list...
    this.storageGrid.postAlterationOfStoredItems( StorageChannel.ITEMS, oldItems.keySet(), new BaseActionSource() );

    // re-create list..
    for (ICraftingProvider provider : this.craftingProviders)
    {
      provider.provideCrafting( this );
    }

    Map<IAEItemStack, Set<ICraftingPatternDetails>> tmpCraft = new HashMap<IAEItemStack, Set<ICraftingPatternDetails>>();

    // new craftables!
    for (ICraftingPatternDetails details : this.craftingMethods.keySet())
    {
      for (IAEItemStack out : details.getOutputs())
      {
        out = out.copy();
        out.reset();
        out.setCraftable( true );

        Set<ICraftingPatternDetails> methods = tmpCraft.get( out );

        if ( methods == null )
        {
          tmpCraft.put( out, methods = new TreeSet<ICraftingPatternDetails>( comp ) );
        }

        methods.add( details );
      }
    }

    // make them immutable
    for (Entry<IAEItemStack, Set<ICraftingPatternDetails>> e : tmpCraft.entrySet())
    {
      this.craftableItems.put( e.getKey(), ImmutableList.copyOf( e.getValue() ) );
    }

    this.storageGrid.postAlterationOfStoredItems( StorageChannel.ITEMS, this.craftableItems.keySet(), new BaseActionSource() );
  }

  @Override
  public void onSplit(IGridStorage destinationStorage)
  { // nothing!
  }

  @Override
  public void onJoin(IGridStorage sourceStorage)
  {
    // nothing!
  }

  @Override
  public void populateGridStorage(IGridStorage destinationStorage)
  {
    // nothing!
  }

  @Override
  public List<IMEInventoryHandler> getCellArray(StorageChannel channel)
  {
    List<IMEInventoryHandler> list = new ArrayList<IMEInventoryHandler>( 1 );

    if ( channel == StorageChannel.ITEMS )
    {
      list.add( this );
    }

    return list;
  }

  @Override
  public int getPriority()
  {
    return Integer.MAX_VALUE;
  }

  @Override
  public IAEStack extractItems(IAEStack request, Actionable mode, BaseActionSource src)
  {
    return null;
  }

  @Override
  public IItemList<IAEStack> getAvailableItems(IItemList<IAEStack> out)
  {
    // add craftable items!
    for (IAEItemStack stack : this.craftableItems.keySet())
    {
      out.addCrafting( stack );
    }

    for (IAEItemStack st : this.emitableItems)
    {
      out.addCrafting( st );
    }

    return out;
  }

  @Override
  public StorageChannel getChannel()
  {
    return StorageChannel.ITEMS;
  }

  @Override
  public AccessRestriction getAccess()
  {
    return AccessRestriction.WRITE;
  }

  @Override
  public boolean isPrioritized(IAEStack input)
  {
    return true;
  }

  @Override
  public IAEStack injectItems(IAEStack input, Actionable type, BaseActionSource src)
  {
    for (CraftingCPUCluster cpu : this.craftingCPUClusters)
    {
      input = cpu.injectItems( input, type, src );
    }

    return input;
  }

  @Override
  public boolean canAccept(IAEStack input)
  {
    for (CraftingCPUCluster cpu : this.craftingCPUClusters)
    {
      if ( cpu.canAccept( input ) )
      {
        return true;
      }
    }

    return false;
  }

  @Override
  public ICraftingLink submitJob(ICraftingJob job, ICraftingRequester requestingMachine, ICraftingCPU target, final boolean prioritizePower, BaseActionSource src)
  {
    if ( job.isSimulation() )
    {
      return null;
    }

    CraftingCPUCluster cpuCluster = null;

    if ( target instanceof CraftingCPUCluster )
    {
      cpuCluster = (CraftingCPUCluster) target;
    }

    if ( target == null )
    {
      List<CraftingCPUCluster> validCpusClusters = new ArrayList<CraftingCPUCluster>();
      for (CraftingCPUCluster cpu : this.craftingCPUClusters)
      {
        if ( cpu.isActive() && !cpu.isBusy() && cpu.getAvailableStorage() >= job.getByteTotal() )
        {
          validCpusClusters.add( cpu );
        }
      }

      Collections.sort( validCpusClusters, new Comparator<CraftingCPUCluster>()
      {
        @Override
        public int compare(CraftingCPUCluster firstCluster, CraftingCPUCluster nextCluster)
        {
          if ( prioritizePower )
          {
            int comparison = ItemSorters.compareLong( nextCluster.getCoProcessors(), firstCluster.getCoProcessors() );
            if ( comparison != 0 )
              return comparison;
            return ItemSorters.compareLong( nextCluster.getAvailableStorage(), firstCluster.getAvailableStorage() );
          }

          int comparison = ItemSorters.compareLong( firstCluster.getCoProcessors(), nextCluster.getCoProcessors() );
          if ( comparison != 0 )
            return comparison;
          return ItemSorters.compareLong( firstCluster.getAvailableStorage(), nextCluster.getAvailableStorage() );
        }

      } );

      if ( !validCpusClusters.isEmpty() )
      {
        cpuCluster = validCpusClusters.get( 0 );
      }
    }

    if ( cpuCluster != null )
    {
      return cpuCluster.submitJob( grid, job, src, requestingMachine );
    }

    return null;
  }

  @Override
  public int getSlot()
  {
    return 0;
  }

  @Override
  public ImmutableCollection<ICraftingPatternDetails> getCraftingFor(IAEItemStack whatToCraft, ICraftingPatternDetails details, int slotIndex, World world)
  {
    ImmutableList<ICraftingPatternDetails> res = this.craftableItems.get( whatToCraft );

    if ( res == null )
    {
      if ( details != null && details.isCraftable() )
      {
        for (IAEItemStack ais : this.craftableItems.keySet())
        {
          if ( ais.getItem() == whatToCraft.getItem() && (!ais.getItem().getHasSubtypes() || ais.getItemDamage() == whatToCraft.getItemDamage()) )
          {
            if ( details.isValidItemForSlot( slotIndex, ais.getItemStack(), world ) )
            {
              return this.craftableItems.get( ais );
            }
          }
        }
      }

      return ImmutableSet.of();
    }

    return res;
  }

  public List<ICraftingMedium> getMediums(ICraftingPatternDetails key)
  {
    List<ICraftingMedium> mediums = craftingMethods.get( key );

    if ( mediums == null )
    {
      mediums = ImmutableList.of();
    }

    return mediums;
  }

  @Override
  public boolean validForPass(int i)
  {
    return i == 1;
  }

  final public static ExecutorService craftingPool;

  static
  {
    ThreadFactory factory = new ThreadFactory() {

      @Override
      public Thread newThread(Runnable ar)
      {
        return new Thread( ar, "AE Crafting Calculator" );
      }

    };

    craftingPool = Executors.newCachedThreadPool( factory );
  }

  @Override
  public Future<ICraftingJob> beginCraftingJob(World world, IGrid grid, BaseActionSource actionSrc, IAEItemStack slotItem, ICraftingCallback cb)
  {
    if ( world == null || grid == null || actionSrc == null || slotItem == null )
    {
      throw new RuntimeException( "Invalid Crafting Job Request" );
    }

    CraftingJob job = new CraftingJob( world, grid, actionSrc, slotItem, cb );

    return craftingPool.submit( job, (ICraftingJob) job );
  }

  public boolean hasCpu(ICraftingCPU cpu)
  {
    return this.craftingCPUClusters.contains( cpu );
  }

  @Override
  public boolean isRequesting(IAEItemStack what)
  {
    for (CraftingCPUCluster cluster : this.craftingCPUClusters)
    {
      if ( cluster.isMaking( what ) )
      {
        return true;
      }
    }

    return false;
  }

  @Override
  public boolean canEmitFor(IAEItemStack someItem)
  {
    return this.emitableItems.contains( someItem );
  }

  @Override
  public void setEmitable(IAEItemStack someItem)
  {
    this.emitableItems.add( someItem.copy() );
  }

}
TOP

Related Classes of appeng.me.cache.CraftingGridCache$ActiveCpuIterator

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.