Crafting Machine Link API, and Export bus crafting implementation.

This commit is contained in:
AlgorithmX2 2014-07-04 01:19:35 -05:00
parent eb691e1802
commit 0a470eefc2
9 changed files with 683 additions and 22 deletions

View file

@ -162,7 +162,7 @@ public class ContainerCraftConfirm extends AEBaseContainer
if ( result != null && simulation == false ) if ( result != null && simulation == false )
{ {
ICraftingGrid cc = getGrid().getCache( ICraftingGrid.class ); ICraftingGrid cc = getGrid().getCache( ICraftingGrid.class );
cc.submitJob( result, null, getActionSrc() ); cc.submitJob( result, null, null, getActionSrc() );
this.isContainerValid = false; this.isContainerValid = false;
} }
} }

View file

@ -5,7 +5,10 @@ import io.netty.buffer.ByteBuf;
import java.io.IOException; import java.io.IOException;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidStack;
import appeng.api.networking.crafting.ICraftingLink;
import appeng.api.networking.crafting.ICraftingRequester;
import appeng.api.networking.energy.IEnergySource; import appeng.api.networking.energy.IEnergySource;
import appeng.api.networking.security.BaseActionSource; import appeng.api.networking.security.BaseActionSource;
import appeng.api.storage.IMEInventory; import appeng.api.storage.IMEInventory;
@ -13,6 +16,7 @@ import appeng.api.storage.IStorageHelper;
import appeng.api.storage.data.IAEFluidStack; import appeng.api.storage.data.IAEFluidStack;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList; import appeng.api.storage.data.IItemList;
import appeng.crafting.CraftingLink;
import appeng.util.Platform; import appeng.util.Platform;
import appeng.util.item.AEFluidStack; import appeng.util.item.AEFluidStack;
import appeng.util.item.AEItemStack; import appeng.util.item.AEItemStack;
@ -36,13 +40,13 @@ public class ApiStorage implements IStorageHelper
@Override @Override
public IItemList<IAEItemStack> createItemList() public IItemList<IAEItemStack> createItemList()
{ {
return new ItemList( IAEItemStack.class); return new ItemList( IAEItemStack.class );
} }
@Override @Override
public IItemList<IAEFluidStack> createFluidList() public IItemList<IAEFluidStack> createFluidList()
{ {
return new ItemList( IAEFluidStack.class); return new ItemList( IAEFluidStack.class );
} }
@Override @Override
@ -68,4 +72,10 @@ public class ApiStorage implements IStorageHelper
{ {
return AEFluidStack.loadFluidStackFromPacket( input ); return AEFluidStack.loadFluidStackFromPacket( input );
} }
@Override
public ICraftingLink loadCraftingLink(NBTTagCompound data, ICraftingRequester req)
{
return new CraftingLink( data, req );
}
} }

146
crafting/CraftingLink.java Normal file
View file

@ -0,0 +1,146 @@
package appeng.crafting;
import net.minecraft.nbt.NBTTagCompound;
import appeng.api.networking.crafting.ICraftingCPU;
import appeng.api.networking.crafting.ICraftingLink;
import appeng.api.networking.crafting.ICraftingRequester;
import appeng.api.storage.data.IAEItemStack;
public class CraftingLink implements ICraftingLink
{
boolean canceled = false;
boolean done = false;
CraftingLinkNexus tie;
final ICraftingRequester req;
final ICraftingCPU cpu;
final String CraftID;
final boolean standalone;
public CraftingLink(NBTTagCompound data, ICraftingRequester req) {
CraftID = data.getString( "CraftID" );
canceled = data.getBoolean( "canceled" );
done = data.getBoolean( "done" );
standalone = data.getBoolean( "standalone" );
if ( !data.hasKey( "req" ) || data.getBoolean( "req" ) != true )
throw new RuntimeException( "Invalid Crafting Link for Object" );
this.req = req;
cpu = null;
}
public CraftingLink(NBTTagCompound data, ICraftingCPU cpu) {
CraftID = data.getString( "CraftID" );
canceled = data.getBoolean( "canceled" );
done = data.getBoolean( "done" );
standalone = data.getBoolean( "standalone" );
if ( !data.hasKey( "req" ) || data.getBoolean( "req" ) == true )
throw new RuntimeException( "Invalid Crafting Link for Object" );
this.cpu = cpu;
req = null;
}
@Override
public boolean isCanceled()
{
if ( canceled )
return true;
if ( done )
return false;
if ( tie == null )
return false;
return tie.isCanceled();
}
@Override
public boolean isDone()
{
if ( done )
return true;
if ( canceled )
return false;
if ( tie == null )
return false;
return tie.isDone();
}
@Override
public void cancel()
{
if ( done )
return;
canceled = true;
if ( tie != null )
tie.cancel();
tie = null;
}
@Override
public void writeToNBT(NBTTagCompound tag)
{
tag.setString( "CraftID", CraftID );
tag.setBoolean( "canceled", canceled );
tag.setBoolean( "done", done );
tag.setBoolean( "standalone", standalone );
tag.setBoolean( "req", req != null );
}
public void setNextus(CraftingLinkNexus n)
{
if ( tie != null )
tie.remove( this );
if ( canceled && n != null )
{
n.cancel();
tie = null;
return;
}
tie = n;
if ( n != null )
n.add( this );
}
@Override
public String getCraftingID()
{
return CraftID;
}
@Override
public boolean isStandalone()
{
return standalone;
}
public IAEItemStack injectItems(IAEItemStack input)
{
if ( tie == null || tie.req == null || tie.req.req == null )
return input;
return tie.req.req.injectCratedItems( tie.req, input );
}
public void markDone()
{
if ( tie != null )
tie.markDone();
}
}

View file

@ -0,0 +1,121 @@
package appeng.crafting;
import appeng.api.networking.IGrid;
import appeng.api.networking.IGridHost;
import appeng.me.cache.CraftingGridCache;
public class CraftingLinkNexus
{
public CraftingLinkNexus(String craftID) {
this.CraftID = craftID;
}
public final String CraftID;
boolean canceled = false;
boolean done = false;
int tickOfDeath = 0;
CraftingLink req;
CraftingLink cpu;
public boolean isDead(IGrid g, CraftingGridCache craftingGridCache)
{
if ( isCanceled() || isDone() )
return true;
if ( req == null || cpu == null )
tickOfDeath++;
else
{
boolean hasCpu = craftingGridCache.hasCpu( cpu.cpu );
boolean hasMachine = req.req.getActionableNode().getGrid() == g;
if ( hasCpu && hasMachine )
tickOfDeath = 0;
else
tickOfDeath += 60;
}
if ( tickOfDeath > 60 )
{
cancel();
return true;
}
return false;
}
public void remove(CraftingLink craftingLink)
{
if ( req == craftingLink )
req = null;
else if ( cpu == craftingLink )
cpu = null;
}
public void add(CraftingLink craftingLink)
{
if ( craftingLink.cpu != null )
cpu = craftingLink;
else if ( craftingLink.req != null )
req = craftingLink;
}
public boolean isCanceled()
{
return canceled;
}
public boolean isDone()
{
return done;
}
public void markDone()
{
done = true;
if ( req != null )
{
req.done = true;
if ( req.req != null )
req.req.jobStateChange( req );
}
if ( cpu != null )
cpu.done = true;
}
public void cancel()
{
canceled = true;
if ( req != null )
{
req.canceled = true;
if ( req.req != null )
req.req.jobStateChange( req );
}
if ( cpu != null )
cpu.canceled = true;
}
public boolean isMachine(IGridHost machine)
{
return req == machine;
}
public void removeNode()
{
if ( req != null )
req.setNextus( null );
req = null;
tickOfDeath = 0;
}
}

View file

@ -3,6 +3,7 @@ package appeng.me.cache;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
@ -23,10 +24,12 @@ import appeng.api.networking.crafting.ICraftingCPU;
import appeng.api.networking.crafting.ICraftingCallback; import appeng.api.networking.crafting.ICraftingCallback;
import appeng.api.networking.crafting.ICraftingGrid; import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.networking.crafting.ICraftingJob; import appeng.api.networking.crafting.ICraftingJob;
import appeng.api.networking.crafting.ICraftingLink;
import appeng.api.networking.crafting.ICraftingMedium; import appeng.api.networking.crafting.ICraftingMedium;
import appeng.api.networking.crafting.ICraftingPatternDetails; import appeng.api.networking.crafting.ICraftingPatternDetails;
import appeng.api.networking.crafting.ICraftingProvider; import appeng.api.networking.crafting.ICraftingProvider;
import appeng.api.networking.crafting.ICraftingProviderHelper; import appeng.api.networking.crafting.ICraftingProviderHelper;
import appeng.api.networking.crafting.ICraftingRequester;
import appeng.api.networking.energy.IEnergyGrid; import appeng.api.networking.energy.IEnergyGrid;
import appeng.api.networking.events.MENetworkCraftingCpuChange; import appeng.api.networking.events.MENetworkCraftingCpuChange;
import appeng.api.networking.events.MENetworkCraftingPatternChange; import appeng.api.networking.events.MENetworkCraftingPatternChange;
@ -41,6 +44,8 @@ import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IAEStack; import appeng.api.storage.data.IAEStack;
import appeng.api.storage.data.IItemList; import appeng.api.storage.data.IItemList;
import appeng.crafting.CraftingJob; import appeng.crafting.CraftingJob;
import appeng.crafting.CraftingLink;
import appeng.crafting.CraftingLinkNexus;
import appeng.me.cluster.implementations.CraftingCPUCluster; import appeng.me.cluster.implementations.CraftingCPUCluster;
import appeng.tile.crafting.TileCraftingStorageTile; import appeng.tile.crafting.TileCraftingStorageTile;
import appeng.tile.crafting.TileCraftingTile; import appeng.tile.crafting.TileCraftingTile;
@ -61,6 +66,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
HashMap<ICraftingPatternDetails, List<ICraftingMedium>> craftingMethods = new HashMap(); HashMap<ICraftingPatternDetails, List<ICraftingMedium>> craftingMethods = new HashMap();
HashMap<IAEItemStack, ImmutableSet<ICraftingPatternDetails>> craftableItems = new HashMap(); HashMap<IAEItemStack, ImmutableSet<ICraftingPatternDetails>> craftableItems = new HashMap();
HashMap<String, CraftingLinkNexus> links = new HashMap();
boolean updateList = false; boolean updateList = false;
@ -77,6 +83,18 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
sg.registerCellProvider( this ); 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 @Override
public void onUpdateTick() public void onUpdateTick()
{ {
@ -86,6 +104,13 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
updateCPUClusters(); updateCPUClusters();
} }
Iterator<CraftingLinkNexus> i = links.values().iterator();
while (i.hasNext())
{
if ( i.next().isDead( grid, this ) )
i.remove();
}
for (CraftingCPUCluster cpu : cpuClusters) for (CraftingCPUCluster cpu : cpuClusters)
cpu.updateCraftingLogic( grid, eg, this ); cpu.updateCraftingLogic( grid, eg, this );
} }
@ -105,6 +130,17 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
@Override @Override
public void removeNode(IGridNode gridNode, IGridHost machine) 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();
}
}
if ( machine instanceof TileCraftingTile ) if ( machine instanceof TileCraftingTile )
updateList = true; updateList = true;
if ( machine instanceof ICraftingProvider ) if ( machine instanceof ICraftingProvider )
@ -117,6 +153,15 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
@Override @Override
public void addNode(IGridNode gridNode, IGridHost machine) public void addNode(IGridNode gridNode, IGridHost machine)
{ {
if ( machine instanceof ICraftingRequester )
{
for (ICraftingLink l : ((ICraftingRequester) machine).getRequestedJobs())
{
if ( l instanceof CraftingLink )
addLink( (CraftingLink) l );
}
}
if ( machine instanceof TileCraftingTile ) if ( machine instanceof TileCraftingTile )
updateList = true; updateList = true;
if ( machine instanceof ICraftingProvider ) if ( machine instanceof ICraftingProvider )
@ -134,7 +179,12 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
TileCraftingStorageTile tile = (TileCraftingStorageTile) cst.getMachine(); TileCraftingStorageTile tile = (TileCraftingStorageTile) cst.getMachine();
CraftingCPUCluster clust = (CraftingCPUCluster) tile.getCluster(); CraftingCPUCluster clust = (CraftingCPUCluster) tile.getCluster();
if ( clust != null ) if ( clust != null )
{
cpuClusters.add( clust ); cpuClusters.add( clust );
if ( clust.myLastLink != null )
addLink( (CraftingLink) clust.myLastLink );
}
} }
} }
@ -283,10 +333,11 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
return false; return false;
} }
public boolean submitJob(ICraftingJob job, ICraftingCPU target, BaseActionSource src) @Override
public ICraftingLink submitJob(ICraftingJob job, ICraftingRequester requestingMachine, ICraftingCPU target, BaseActionSource src)
{ {
if ( job.isSimulation() ) if ( job.isSimulation() )
return false; return null;
CraftingCPUCluster cpuClust = null; CraftingCPUCluster cpuClust = null;
@ -306,10 +357,10 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
} }
} }
if ( cpuClust != null && cpuClust.submitJob( grid, job, src ) ) if ( cpuClust != null )
return true; return cpuClust.submitJob( grid, job, src, requestingMachine );
return false; return null;
} }
@Override @Override
@ -362,8 +413,16 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
@Override @Override
public Future<ICraftingJob> beginCraftingJob(World world, IGrid grid, BaseActionSource actionSrc, IAEItemStack slotItem, ICraftingCallback cb) 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 ); CraftingJob cj = new CraftingJob( world, grid, actionSrc, slotItem, cb );
return craftingPool.submit( cj, (ICraftingJob) cj ); return craftingPool.submit( cj, (ICraftingJob) cj );
} }
public boolean hasCpu(ICraftingCPU cpu)
{
return cpuClusters.contains( cpu );
}
} }

View file

@ -22,9 +22,12 @@ import appeng.api.networking.IGridHost;
import appeng.api.networking.IGridNode; import appeng.api.networking.IGridNode;
import appeng.api.networking.crafting.CraftingItemList; import appeng.api.networking.crafting.CraftingItemList;
import appeng.api.networking.crafting.ICraftingCPU; import appeng.api.networking.crafting.ICraftingCPU;
import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.networking.crafting.ICraftingJob; import appeng.api.networking.crafting.ICraftingJob;
import appeng.api.networking.crafting.ICraftingLink;
import appeng.api.networking.crafting.ICraftingMedium; import appeng.api.networking.crafting.ICraftingMedium;
import appeng.api.networking.crafting.ICraftingPatternDetails; import appeng.api.networking.crafting.ICraftingPatternDetails;
import appeng.api.networking.crafting.ICraftingRequester;
import appeng.api.networking.energy.IEnergyGrid; import appeng.api.networking.energy.IEnergyGrid;
import appeng.api.networking.events.MENetworkCraftingCpuChange; import appeng.api.networking.events.MENetworkCraftingCpuChange;
import appeng.api.networking.security.BaseActionSource; import appeng.api.networking.security.BaseActionSource;
@ -40,6 +43,7 @@ import appeng.container.ContainerNull;
import appeng.core.AELog; import appeng.core.AELog;
import appeng.crafting.CraftBranchFailure; import appeng.crafting.CraftBranchFailure;
import appeng.crafting.CraftingJob; import appeng.crafting.CraftingJob;
import appeng.crafting.CraftingLink;
import appeng.crafting.MECraftingInventory; import appeng.crafting.MECraftingInventory;
import appeng.me.cache.CraftingGridCache; import appeng.me.cache.CraftingGridCache;
import appeng.me.cluster.IAECluster; import appeng.me.cluster.IAECluster;
@ -75,6 +79,7 @@ public class CraftingCPUCluster implements IAECluster, ICraftingCPU
private LinkedList<TileCraftingTile> status = new LinkedList<TileCraftingTile>(); private LinkedList<TileCraftingTile> status = new LinkedList<TileCraftingTile>();
long availableStorage = 0; long availableStorage = 0;
public ICraftingLink myLastLink;
MachineSource machineSrc = null; MachineSource machineSrc = null;
@ -284,6 +289,9 @@ public class CraftingCPUCluster implements IAECluster, ICraftingCPU
if ( finalOutput.getStackSize() <= 0 ) if ( finalOutput.getStackSize() <= 0 )
completeJob(); completeJob();
if ( myLastLink != null )
return ((CraftingLink) myLastLink).injectItems( (IAEItemStack) input );
return input; // ignore it. return input; // ignore it.
} }
@ -307,6 +315,9 @@ public class CraftingCPUCluster implements IAECluster, ICraftingCPU
if ( finalOutput.getStackSize() <= 0 ) if ( finalOutput.getStackSize() <= 0 )
completeJob(); completeJob();
if ( myLastLink != null )
return ((CraftingLink) myLastLink).injectItems( (IAEItemStack) input );
return input; // ignore it. return input; // ignore it.
} }
@ -338,6 +349,9 @@ public class CraftingCPUCluster implements IAECluster, ICraftingCPU
private void completeJob() private void completeJob()
{ {
if ( myLastLink != null )
((CraftingLink) myLastLink).markDone();
AELog.info( "marking job as complete" ); AELog.info( "marking job as complete" );
isComplete = true; isComplete = true;
} }
@ -383,7 +397,11 @@ public class CraftingCPUCluster implements IAECluster, ICraftingCPU
public void cancel() public void cancel()
{ {
if ( myLastLink != null )
myLastLink.cancel();
isComplete = true; isComplete = true;
myLastLink = null;
tasks.clear(); tasks.clear();
waitingFor.resetStatus(); waitingFor.resetStatus();
storeItems(); // marks dirty storeItems(); // marks dirty
@ -391,6 +409,15 @@ public class CraftingCPUCluster implements IAECluster, ICraftingCPU
public void updateCraftingLogic(IGrid grid, IEnergyGrid eg, CraftingGridCache cc) public void updateCraftingLogic(IGrid grid, IEnergyGrid eg, CraftingGridCache cc)
{ {
if ( myLastLink != null )
{
if ( myLastLink.isCanceled() )
{
myLastLink = null;
cancel();
}
}
if ( isComplete ) if ( isComplete )
{ {
if ( inventory.getItemList().isEmpty() ) if ( inventory.getItemList().isEmpty() )
@ -579,16 +606,16 @@ public class CraftingCPUCluster implements IAECluster, ICraftingCPU
private World getWorld() private World getWorld()
{ {
return null; return getCore().getWorldObj();
} }
public boolean submitJob(IGrid g, ICraftingJob job, BaseActionSource src) public ICraftingLink submitJob(IGrid g, ICraftingJob job, BaseActionSource src, ICraftingRequester requestingMachine)
{ {
if ( !tasks.isEmpty() || !waitingFor.isEmpty() ) if ( !tasks.isEmpty() || !waitingFor.isEmpty() )
return false; return null;
if ( !(job instanceof CraftingJob) ) if ( !(job instanceof CraftingJob) )
return false; return null;
IStorageGrid sg = g.getCache( IStorageGrid.class ); IStorageGrid sg = g.getCache( IStorageGrid.class );
IMEInventory<IAEItemStack> storage = sg.getItemInventory(); IMEInventory<IAEItemStack> storage = sg.getItemInventory();
@ -603,7 +630,20 @@ public class CraftingCPUCluster implements IAECluster, ICraftingCPU
waiting = false; waiting = false;
isComplete = false; isComplete = false;
markDirty(); markDirty();
return true;
String craftID = generateCraftingID();
myLastLink = new CraftingLink( generateLinkData( craftID, requestingMachine == null, false ), this );
if ( requestingMachine == null )
return myLastLink;
ICraftingLink whatLink = new CraftingLink( generateLinkData( craftID, requestingMachine == null, true ), requestingMachine );
submitLink( myLastLink );
submitLink( whatLink );
return whatLink;
} }
catch (CraftBranchFailure e) catch (CraftBranchFailure e)
{ {
@ -612,7 +652,39 @@ public class CraftingCPUCluster implements IAECluster, ICraftingCPU
AELog.error( e ); AELog.error( e );
} }
return false; return null;
}
private void submitLink(ICraftingLink myLastLink2)
{
if ( getGrid() != null )
{
CraftingGridCache cc = getGrid().getCache( ICraftingGrid.class );
cc.addLink( (CraftingLink) myLastLink2 );
}
}
private String generateCraftingID()
{
long now = System.currentTimeMillis();
int hash = System.identityHashCode( this );
int hmm = finalOutput == null ? 0 : finalOutput.hashCode();
return Long.toString( now, Character.MAX_RADIX ) + "-" + Integer.toString( hash, Character.MAX_RADIX ) + "-"
+ Integer.toString( hmm, Character.MAX_RADIX );
}
private NBTTagCompound generateLinkData(String craftingID, boolean standalone, boolean req)
{
NBTTagCompound tag = new NBTTagCompound();
tag.setString( "CraftID", craftingID );
tag.setBoolean( "canceled", false );
tag.setBoolean( "done", false );
tag.setBoolean( "standalone", standalone );
tag.setBoolean( "req", req );
return tag;
} }
private void markDirty() private void markDirty()
@ -701,6 +773,13 @@ public class CraftingCPUCluster implements IAECluster, ICraftingCPU
waiting = data.getBoolean( "waiting" ); waiting = data.getBoolean( "waiting" );
isComplete = data.getBoolean( "isComplete" ); isComplete = data.getBoolean( "isComplete" );
if ( data.hasKey( "link" ) )
{
NBTTagCompound link = data.getCompoundTag( "link" );
myLastLink = new CraftingLink( link, this );
submitLink( myLastLink );
}
NBTTagList list = data.getTagList( "tasks", 10 ); NBTTagList list = data.getTagList( "tasks", 10 );
for (int x = 0; x < list.tagCount(); x++) for (int x = 0; x < list.tagCount(); x++)
{ {
@ -729,6 +808,13 @@ public class CraftingCPUCluster implements IAECluster, ICraftingCPU
data.setBoolean( "waiting", waiting ); data.setBoolean( "waiting", waiting );
data.setBoolean( "isComplete", isComplete ); data.setBoolean( "isComplete", isComplete );
if ( myLastLink != null )
{
NBTTagCompound link = new NBTTagCompound();
myLastLink.writeToNBT( link );
data.setTag( "link", link );
}
NBTTagList list = new NBTTagList(); NBTTagList list = new NBTTagList();
for (Entry<ICraftingPatternDetails, TaskProgress> e : tasks.entrySet()) for (Entry<ICraftingPatternDetails, TaskProgress> e : tasks.entrySet())
{ {
@ -744,6 +830,8 @@ public class CraftingCPUCluster implements IAECluster, ICraftingCPU
private IItemList<IAEItemStack> readList(NBTTagList tag) private IItemList<IAEItemStack> readList(NBTTagList tag)
{ {
IItemList<IAEItemStack> out = AEApi.instance().storage().createItemList(); IItemList<IAEItemStack> out = AEApi.instance().storage().createItemList();
if ( tag == null )
return out;
for (int x = 0; x < tag.tagCount(); x++) for (int x = 0; x < tag.tagCount(); x++)
{ {

View file

@ -13,6 +13,7 @@ import appeng.api.networking.IGrid;
import appeng.api.networking.IGridBlock; import appeng.api.networking.IGridBlock;
import appeng.api.networking.IGridHost; import appeng.api.networking.IGridHost;
import appeng.api.networking.IGridNode; import appeng.api.networking.IGridNode;
import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.networking.energy.IEnergyGrid; import appeng.api.networking.energy.IEnergyGrid;
import appeng.api.networking.events.MENetworkPowerIdleChange; import appeng.api.networking.events.MENetworkPowerIdleChange;
import appeng.api.networking.pathing.IPathingGrid; import appeng.api.networking.pathing.IPathingGrid;
@ -58,7 +59,7 @@ public class AENetworkProxy implements IGridBlock
return myRepInstance; return myRepInstance;
} }
public void setVisualRepresentation( ItemStack is ) public void setVisualRepresentation(ItemStack is)
{ {
myRepInstance = is; myRepInstance = is;
} }
@ -276,6 +277,20 @@ public class AENetworkProxy implements IGridBlock
return sg; return sg;
} }
public ICraftingGrid getCrafting() throws GridAccessException
{
IGrid grid = getGrid();
if ( grid == null )
throw new GridAccessException();
ICraftingGrid sg = grid.getCache( ICraftingGrid.class );
if ( sg == null )
throw new GridAccessException();
return sg;
}
@Override @Override
public boolean isWorldAccessable() public boolean isWorldAccessable()
{ {

View file

@ -0,0 +1,38 @@
package appeng.parts.automation;
import java.util.Iterator;
import scala.NotImplementedError;
public class NonNullArrayIterator<E> implements Iterator<E>
{
int offset = 0;
final E[] g;
public NonNullArrayIterator(E[] o) {
g = o;
}
@Override
public boolean hasNext()
{
while (offset < g.length && g[offset] == null)
offset++;
return offset != g.length;
}
@Override
public E next()
{
return g[offset++];
}
@Override
public void remove()
{
throw new NotImplementedError();
}
}

View file

@ -1,15 +1,25 @@
package appeng.parts.automation; package appeng.parts.automation;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import net.minecraft.client.renderer.RenderBlocks; import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.Vec3; import net.minecraft.util.Vec3;
import appeng.api.AEApi;
import appeng.api.config.Actionable; import appeng.api.config.Actionable;
import appeng.api.config.FuzzyMode; import appeng.api.config.FuzzyMode;
import appeng.api.config.PowerMultiplier;
import appeng.api.config.RedstoneMode; import appeng.api.config.RedstoneMode;
import appeng.api.config.Settings; import appeng.api.config.Settings;
import appeng.api.config.Upgrades; import appeng.api.config.Upgrades;
import appeng.api.networking.IGridNode; import appeng.api.networking.IGridNode;
import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.networking.crafting.ICraftingJob;
import appeng.api.networking.crafting.ICraftingLink;
import appeng.api.networking.crafting.ICraftingRequester;
import appeng.api.networking.energy.IEnergyGrid; import appeng.api.networking.energy.IEnergyGrid;
import appeng.api.networking.security.BaseActionSource; import appeng.api.networking.security.BaseActionSource;
import appeng.api.networking.security.MachineSource; import appeng.api.networking.security.MachineSource;
@ -22,22 +32,28 @@ import appeng.api.storage.IMEInventory;
import appeng.api.storage.IMEMonitor; import appeng.api.storage.IMEMonitor;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.client.texture.CableBusTextures; import appeng.client.texture.CableBusTextures;
import appeng.core.AELog;
import appeng.core.settings.TickRates; import appeng.core.settings.TickRates;
import appeng.core.sync.GuiBridge; import appeng.core.sync.GuiBridge;
import appeng.me.GridAccessException; import appeng.me.GridAccessException;
import appeng.util.InventoryAdaptor; import appeng.util.InventoryAdaptor;
import appeng.util.Platform; import appeng.util.Platform;
import appeng.util.item.AEItemStack;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly; import cpw.mods.fml.relauncher.SideOnly;
public class PartExportBus extends PartSharedItemBus implements IGridTickable public class PartExportBus extends PartSharedItemBus implements IGridTickable, ICraftingRequester
{ {
BaseActionSource mySrc; BaseActionSource mySrc;
Future<ICraftingJob> calculatingJob = null;
ICraftingLink[] links = null;
public PartExportBus(ItemStack is) { public PartExportBus(ItemStack is) {
super( PartExportBus.class, is ); super( PartExportBus.class, is );
settings.registerSetting( Settings.REDSTONE_CONTROLLED, RedstoneMode.IGNORE ); settings.registerSetting( Settings.REDSTONE_CONTROLLED, RedstoneMode.IGNORE );
@ -45,6 +61,36 @@ public class PartExportBus extends PartSharedItemBus implements IGridTickable
mySrc = new MachineSource( this ); mySrc = new MachineSource( this );
} }
@Override
public void readFromNBT(NBTTagCompound extra)
{
super.readFromNBT( extra );
for (int x = 0; x < 9; x++)
{
NBTTagCompound link = extra.getCompoundTag( "links-" + x );
if ( link != null && !link.hasNoTags() )
setLink( x, AEApi.instance().storage().loadCraftingLink( link, this ) );
}
}
@Override
public void writeToNBT(NBTTagCompound extra)
{
super.writeToNBT( extra );
for (int x = 0; x < 9; x++)
{
ICraftingLink link = getLink( x );
if ( link != null )
{
NBTTagCompound ln = new NBTTagCompound();
link.writeToNBT( ln );
extra.setTag( "links-" + x, ln );
}
}
}
@Override @Override
public boolean onPartActivate(EntityPlayer player, Vec3 pos) public boolean onPartActivate(EntityPlayer player, Vec3 pos)
{ {
@ -164,20 +210,67 @@ public class PartExportBus extends PartSharedItemBus implements IGridTickable
for (int x = 0; x < availableSlots() && itemToSend > 0; x++) for (int x = 0; x < availableSlots() && itemToSend > 0; x++)
{ {
IAEItemStack ais = config.getAEStackInSlot( x ); IAEItemStack ais = config.getAEStackInSlot( x );
if ( ais == null || itemToSend <= 0 ) if ( ais == null || itemToSend <= 0 || craftOnly() )
{
if ( isCraftingEnabled() && ais != null && d.simulateAdd( ais.getItemStack() ) == null )
{
ICraftingGrid cg = proxy.getCrafting();
if ( getLink( x ) != null )
{
continue;
}
else if ( calculatingJob != null )
{
ICraftingJob job = null;
try
{
if ( calculatingJob.isDone() )
job = calculatingJob.get();
else if ( calculatingJob.isCancelled() )
calculatingJob = null;
if ( job != null )
{
calculatingJob = null;
setLink( x, cg.submitJob( job, this, null, mySrc ) );
didSomething = true;
}
}
catch (InterruptedException e)
{
// :P
}
catch (ExecutionException e)
{
// :P
}
}
else
{
if ( getLink( x ) == null )
{
IAEItemStack aisC = ais.copy();
aisC.setStackSize( itemToSend );
calculatingJob = cg.beginCraftingJob( getTile().getWorldObj(), proxy.getGrid(), mySrc, aisC, null );
}
}
}
continue; continue;
}
if ( getInstalledUpgrades( Upgrades.FUZZY ) > 0 ) if ( getInstalledUpgrades( Upgrades.FUZZY ) > 0 )
{ {
for (IAEItemStack o : ImmutableList.copyOf( inv.getStorageList().findFuzzy( ais, fzMode ) )) for (IAEItemStack o : ImmutableList.copyOf( inv.getStorageList().findFuzzy( ais, fzMode ) ))
{ {
pushItemIntoTarget( d, energy, fzMode, inv, o ); pushItemIntoTarget( d, energy, inv, o );
if ( itemToSend <= 0 ) if ( itemToSend <= 0 )
break; break;
} }
} }
else else
pushItemIntoTarget( d, energy, fzMode, inv, ais ); pushItemIntoTarget( d, energy, inv, ais );
} }
} }
@ -190,7 +283,17 @@ public class PartExportBus extends PartSharedItemBus implements IGridTickable
return didSomething ? TickRateModulation.FASTER : TickRateModulation.SLOWER; return didSomething ? TickRateModulation.FASTER : TickRateModulation.SLOWER;
} }
private void pushItemIntoTarget(InventoryAdaptor d, IEnergyGrid energy, FuzzyMode fzMode, IMEInventory<IAEItemStack> inv, IAEItemStack ais) private boolean craftOnly()
{
return true;
}
private boolean isCraftingEnabled()
{
return getInstalledUpgrades( Upgrades.CRAFTING ) > 0;
}
private void pushItemIntoTarget(InventoryAdaptor d, IEnergyGrid energy, IMEInventory<IAEItemStack> inv, IAEItemStack ais)
{ {
ItemStack is = ais.getItemStack(); ItemStack is = ais.getItemStack();
is.stackSize = (int) itemToSend; is.stackSize = (int) itemToSend;
@ -243,4 +346,85 @@ public class PartExportBus extends PartSharedItemBus implements IGridTickable
{ {
return new TickingRequest( TickRates.ExportBus.min, TickRates.ExportBus.max, isSleeping(), false ); return new TickingRequest( TickRates.ExportBus.min, TickRates.ExportBus.max, isSleeping(), false );
} }
ICraftingLink getLink(int slot)
{
if ( links == null )
return null;
return links[slot];
}
void setLink(int slot, ICraftingLink l)
{
if ( links == null )
links = new ICraftingLink[9];
links[slot] = l;
boolean hasStuff = false;
for (int x = 0; x < links.length; x++)
{
ICraftingLink g = links[x];
if ( g == null || g.isCanceled() || g.isDone() )
links[x] = null;
else
hasStuff = true;
}
if ( hasStuff == false )
links = null;
}
@Override
public ImmutableSet<ICraftingLink> getRequestedJobs()
{
if ( links == null )
return ImmutableSet.of();
return ImmutableSet.copyOf( new NonNullArrayIterator( links ) );
}
@Override
public IAEItemStack injectCratedItems(ICraftingLink link, IAEItemStack items)
{
InventoryAdaptor d = getHandler();
try
{
if ( proxy.isActive() )
{
IEnergyGrid energy = proxy.getEnergy();
double power = items.getStackSize();
if ( energy.extractAEPower( power, Actionable.MODULATE, PowerMultiplier.CONFIG ) > power - 0.01 )
{
return AEItemStack.create( d.addItems( items.getItemStack() ) );
}
}
}
catch (GridAccessException e)
{
AELog.error( e );
}
return items;
}
@Override
public void jobStateChange(ICraftingLink link)
{
if ( links != null )
{
for (int x = 0; x < links.length; x++)
{
if ( links[x] == link )
{
setLink( x, null );
return;
}
}
}
}
} }