Applied-Energistics-2-tiler.../me/cache/CraftingGridCache.java

527 lines
12 KiB
Java
Raw Normal View History

package appeng.me.cache;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
2014-06-06 06:26:01 +02:00
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import net.minecraft.world.World;
import appeng.api.config.AccessRestriction;
import appeng.api.config.Actionable;
2014-05-18 05:19:23 +02:00
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;
2014-05-18 05:19:23 +02:00
import appeng.api.networking.crafting.ICraftingPatternDetails;
import appeng.api.networking.crafting.ICraftingProvider;
2014-05-18 05:19:23 +02:00
import appeng.api.networking.crafting.ICraftingProviderHelper;
import appeng.api.networking.crafting.ICraftingRequester;
2014-06-28 07:20:12 +02:00
import appeng.api.networking.energy.IEnergyGrid;
2014-05-18 05:19:23 +02:00
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.me.cluster.implementations.CraftingCPUCluster;
2014-05-18 05:19:23 +02:00
import appeng.tile.crafting.TileCraftingStorageTile;
import appeng.tile.crafting.TileCraftingTile;
import appeng.util.ItemSorters;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
2014-07-18 05:38:57 +02:00
import com.google.common.collect.ImmutableSortedSet;
public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper, ICellProvider, IMEInventoryHandler
{
HashSet<CraftingCPUCluster> cpuClusters = new HashSet();
HashSet<ICraftingProvider> providers = new HashSet();
2014-06-28 07:20:12 +02:00
2014-05-18 05:19:23 +02:00
IGrid grid;
2014-06-28 07:20:12 +02:00
IStorageGrid sg;
IEnergyGrid eg;
2014-05-18 05:19:23 +02:00
HashMap<ICraftingPatternDetails, List<ICraftingMedium>> craftingMethods = new HashMap();
HashMap<IAEItemStack, ImmutableSet<ICraftingPatternDetails>> craftableItems = new HashMap();
HashMap<String, CraftingLinkNexus> links = new HashMap();
2014-05-18 05:19:23 +02:00
boolean updateList = false;
class ActiveCpuIterator implements Iterator<ICraftingCPU>
{
final Iterator<CraftingCPUCluster> i;
CraftingCPUCluster c = null;
public ActiveCpuIterator(Collection<CraftingCPUCluster> o) {
i = o.iterator();
}
@Override
public boolean hasNext()
{
findNext();
return c != null;
}
private void findNext()
{
while (i.hasNext() && c == null)
{
c = i.next();
if ( !c.isActive() || c.isDestroyed )
c = null;
}
}
@Override
public ICraftingCPU next()
{
ICraftingCPU o = c;
c = null;
return o;
}
@Override
public void remove()
{
// no..
}
};
@Override
public ImmutableSet<ICraftingCPU> getCpus()
{
return ImmutableSet.copyOf( new ActiveCpuIterator( cpuClusters ) );
}
public CraftingGridCache(IGrid g) {
2014-05-18 05:19:23 +02:00
grid = g;
}
@MENetworkEventSubscribe
public void afterCacheConstruction(MENetworkPostCacheConstruction cc)
{
2014-06-28 07:20:12 +02:00
sg = grid.getCache( IStorageGrid.class );
eg = grid.getCache( IEnergyGrid.class );
sg.registerCellProvider( this );
}
public void addLink(CraftingLink l)
{
if ( l.isStandalone() )
return;
CraftingLinkNexus n = links.get( l.getCraftingID() );
if ( n == null )
links.put( l.getCraftingID(), n = new CraftingLinkNexus( l.getCraftingID() ) );
l.setNextus( n );
}
@Override
public void onUpdateTick()
{
2014-05-18 05:19:23 +02:00
if ( updateList )
{
updateList = false;
updateCPUClusters();
}
Iterator<CraftingLinkNexus> i = links.values().iterator();
while (i.hasNext())
{
if ( i.next().isDead( grid, this ) )
i.remove();
}
for (CraftingCPUCluster cpu : cpuClusters)
2014-06-28 07:20:12 +02:00
cpu.updateCraftingLogic( grid, eg, this );
2014-05-18 05:19:23 +02:00
}
@MENetworkEventSubscribe
2014-05-18 05:19:23 +02:00
public void updateCPUClusters(MENetworkCraftingCpuChange c)
{
updateList = true;
}
@MENetworkEventSubscribe
2014-05-18 05:19:23 +02:00
public void updateCPUClusters(MENetworkCraftingPatternChange c)
{
updatePatterns();
}
@Override
public void removeNode(IGridNode gridNode, IGridHost machine)
{
if ( machine instanceof ICraftingRequester )
{
Iterator<CraftingLinkNexus> nex = links.values().iterator();
while (nex.hasNext())
{
CraftingLinkNexus n = nex.next();
if ( n.isMachine( machine ) )
n.removeNode();
}
}
2014-05-18 05:19:23 +02:00
if ( machine instanceof TileCraftingTile )
updateList = true;
if ( machine instanceof ICraftingProvider )
2014-05-18 05:19:23 +02:00
{
providers.remove( machine );
2014-05-18 05:19:23 +02:00
updatePatterns();
}
}
@Override
public void addNode(IGridNode gridNode, IGridHost machine)
{
if ( machine instanceof ICraftingRequester )
{
for (ICraftingLink l : ((ICraftingRequester) machine).getRequestedJobs())
{
if ( l instanceof CraftingLink )
addLink( (CraftingLink) l );
}
}
2014-05-18 05:19:23 +02:00
if ( machine instanceof TileCraftingTile )
updateList = true;
if ( machine instanceof ICraftingProvider )
2014-05-18 05:19:23 +02:00
{
providers.add( (ICraftingProvider) machine );
2014-05-18 05:19:23 +02:00
updatePatterns();
}
}
2014-05-18 05:19:23 +02:00
private void updateCPUClusters()
{
cpuClusters.clear();
for (IGridNode cst : grid.getMachines( TileCraftingStorageTile.class ))
{
TileCraftingStorageTile tile = (TileCraftingStorageTile) cst.getMachine();
CraftingCPUCluster clust = (CraftingCPUCluster) tile.getCluster();
if ( clust != null )
{
cpuClusters.add( clust );
if ( clust.myLastLink != null )
addLink( (CraftingLink) clust.myLastLink );
}
2014-05-18 05:19:23 +02:00
}
}
2014-05-18 05:19:23 +02:00
@Override
public void addCraftingOption(ICraftingMedium medium, ICraftingPatternDetails api)
{
List<ICraftingMedium> details = craftingMethods.get( api );
if ( details == null )
{
details = new ArrayList<ICraftingMedium>();
details.add( medium );
craftingMethods.put( api, details );
}
else
details.add( medium );
}
2014-05-18 05:19:23 +02:00
private void updatePatterns()
{
// update the stuff that was in the list...
2014-06-06 06:26:01 +02:00
for (IAEItemStack out : craftableItems.keySet())
{
out.reset();
sg.postAlterationOfStoredItems( StorageChannel.ITEMS, out, new BaseActionSource() );
}
// erase list.
craftingMethods.clear();
2014-06-06 06:26:01 +02:00
craftableItems.clear();
// re-create list..
2014-05-18 05:19:23 +02:00
for (ICraftingProvider cp : providers)
cp.provideCrafting( this );
HashMap<IAEItemStack, Set<ICraftingPatternDetails>> tmpCraft = new HashMap();
// new craftables!
for (ICraftingPatternDetails details : craftingMethods.keySet())
{
for (IAEItemStack out : details.getOutputs())
{
2014-06-20 09:10:28 +02:00
out = out.copy();
out.reset();
out.setCraftable( true );
2014-06-06 06:26:01 +02:00
Set<ICraftingPatternDetails> methods = tmpCraft.get( out );
2014-06-06 06:26:01 +02:00
if ( methods == null )
2014-07-18 05:03:42 +02:00
tmpCraft.put( out, methods = new HashSet() );
2014-06-06 06:26:01 +02:00
methods.add( details );
sg.postAlterationOfStoredItems( StorageChannel.ITEMS, out, new BaseActionSource() );
}
}
// make them immutable
for (Entry<IAEItemStack, Set<ICraftingPatternDetails>> e : tmpCraft.entrySet())
{
2014-07-18 05:38:57 +02:00
craftableItems.put( e.getKey(), ImmutableSortedSet.copyOf( e.getValue() ) );
}
2014-05-18 05:19:23 +02:00
}
@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)
{
ArrayList<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 getAvailableItems(IItemList out)
{
// add craftable items!
2014-06-06 06:26:01 +02:00
for (IAEItemStack st : craftableItems.keySet())
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 : cpuClusters)
input = cpu.injectItems( input, type, src );
return input;
}
@Override
public boolean canAccept(IAEStack input)
{
for (CraftingCPUCluster cpu : cpuClusters)
if ( cpu.canAccept( (IAEItemStack) input ) )
return true;
return false;
}
@Override
2014-08-01 03:06:37 +02:00
public ICraftingLink submitJob(ICraftingJob job, ICraftingRequester requestingMachine, ICraftingCPU target, final boolean prioritizePower,
BaseActionSource src)
{
2014-06-22 09:00:38 +02:00
if ( job.isSimulation() )
return null;
2014-06-22 09:00:38 +02:00
CraftingCPUCluster cpuClust = null;
if ( target instanceof CraftingCPUCluster )
cpuClust = (CraftingCPUCluster) target;
if ( target == null )
{
List<CraftingCPUCluster> validCpusClusters = new ArrayList<CraftingCPUCluster>();
for (CraftingCPUCluster cpu : cpuClusters)
{
if ( cpu.isActive() && !cpu.isBusy() && cpu.getAvailableStorage() >= job.getByteTotal() )
2014-06-22 09:00:38 +02:00
{
validCpusClusters.add( cpu );
2014-06-22 09:00:38 +02:00
break;
}
}
Collections.sort( validCpusClusters, new Comparator<CraftingCPUCluster>() {
@Override
public int compare(CraftingCPUCluster o1, CraftingCPUCluster o2)
{
2014-08-01 03:06:37 +02:00
if ( prioritizePower )
{
int a = ItemSorters.compareLong( o2.getCoProcessors(), o1.getCoProcessors() );
if ( a != 0 )
return a;
return ItemSorters.compareLong( o2.getAvailableStorage(), o1.getAvailableStorage() );
}
int a = ItemSorters.compareLong( o1.getCoProcessors(), o2.getCoProcessors() );
if ( a != 0 )
return a;
2014-08-01 03:06:37 +02:00
return ItemSorters.compareLong( o1.getAvailableStorage(), o2.getAvailableStorage() );
}
} );
if ( !validCpusClusters.isEmpty() )
cpuClust = validCpusClusters.get( 0 );
}
if ( cpuClust != null )
{
return cpuClust.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)
2014-06-06 06:26:01 +02:00
{
ImmutableSet<ICraftingPatternDetails> res = craftableItems.get( whatToCraft );
if ( res == null )
{
if ( details != null && details.isCraftable() )
{
for (IAEItemStack ais : craftableItems.keySet())
{
if ( ais.getItem() == whatToCraft.getItem() && (!ais.getItem().getHasSubtypes() || ais.getItemDamage() == whatToCraft.getItemDamage()) )
{
if ( details.isValidItemForSlot( slotIndex, ais.getItemStack(), world ) )
{
return craftableItems.get( ais );
}
}
}
}
return ImmutableSet.of();
}
return res;
2014-06-06 06:26:01 +02:00
}
public List<ICraftingMedium> getMediums(ICraftingPatternDetails key)
{
List<ICraftingMedium> o = craftingMethods.get( key );
if ( o == null )
o = ImmutableList.of();
return o;
}
@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 Craftinb Job Request" );
CraftingJob cj = new CraftingJob( world, grid, actionSrc, slotItem, cb );
return craftingPool.submit( cj, (ICraftingJob) cj );
}
public boolean hasCpu(ICraftingCPU cpu)
{
return cpuClusters.contains( cpu );
}
}