Applied-Energistics-2-tiler.../crafting/CraftingTreeNode.java
AlgorithmX2 6cbc5aa953 Recursive crafting works.
MA's can accept pushes.
Interfaces no alter pushing behavior depending on ICraftingMachine settings.
Fixed bug where crafting would record items that don't exist as available for the initial pull.
2014-06-20 02:12:39 -05:00

221 lines
4.9 KiB
Java

package appeng.crafting;
import java.util.ArrayList;
import net.minecraft.world.World;
import appeng.api.AEApi;
import appeng.api.config.Actionable;
import appeng.api.config.FuzzyMode;
import appeng.api.networking.crafting.ICraftingPatternDetails;
import appeng.api.networking.security.BaseActionSource;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
import appeng.me.cache.CraftingCache;
import appeng.me.cluster.implementations.CraftingCPUCluster;
public class CraftingTreeNode
{
// parent node.
private CraftingTreeProcess parent;
private World world;
// what slot!
int slot;
// what item is this?
private IAEItemStack what;
// what are the crafting patterns for this?
private ArrayList<CraftingTreeProcess> nodes = new ArrayList();
boolean cannotUse = false;
long missing = 0;
CraftingJob job;
IItemList<IAEItemStack> used = AEApi.instance().storage().createItemList();
boolean exhausted = false;
boolean sim;
public CraftingTreeNode(CraftingCache cc, CraftingJob job, IAEItemStack wat, CraftingTreeProcess par, int slot, int depth) {
what = wat;
parent = par;
this.slot = slot;
this.world = job.jobHost.getWorld();
this.job = job;
sim = false;
for (ICraftingPatternDetails details : cc.getCraftingFor( what ))// in order.
{
if ( notRecurive( details ) )
nodes.add( new CraftingTreeProcess( cc, job, details, this, depth + 1, world ) );
}
}
public IAEItemStack getStack(long size)
{
IAEItemStack is = what.copy();
is.setStackSize( size );
return is;
}
boolean notRecurive(ICraftingPatternDetails details)
{
IAEItemStack[] o = details.getOutputs();
for (IAEItemStack i : o)
if ( i.equals( what ) )
return true;
if ( parent == null )
return false;
return parent.notRecurive( details );
}
public IAEItemStack request(MECraftingInventory inv, long l, BaseActionSource src) throws CraftBranchFailure, InterruptedException
{
if ( Thread.interrupted() )
throw new InterruptedException();
what.setStackSize( l );
if ( slot >= 0 && parent != null && parent.details.isCraftable() )
{
for (IAEItemStack fuzz : inv.getItemList().findFuzzy( what, FuzzyMode.IGNORE_ALL ))
{
if ( parent.details.isValidItemForSlot( slot, fuzz.getItemStack(), world ) )
{
fuzz = fuzz.copy();
fuzz.setStackSize( l );
IAEItemStack available = inv.extractItems( fuzz, Actionable.MODULATE, src );
if ( available != null )
{
if ( !exhausted )
used.add( job.checkUse( available ) );
l -= available.getStackSize();
if ( l == 0 )
return available;
}
}
}
}
else
{
IAEItemStack available = inv.extractItems( what, Actionable.MODULATE, src );
if ( available != null )
{
if ( !exhausted )
used.add( job.checkUse( available ) );
l -= available.getStackSize();
if ( l == 0 )
return available;
}
}
exhausted = true;
if ( nodes.size() == 1 )
{
CraftingTreeProcess pro = nodes.get( 0 );
while (pro.possible && l > 0)
{
pro.request( inv, pro.getTimes( l, pro.getAmountCrafted( what ).getStackSize() ), src );
what.setStackSize( l );
IAEItemStack available = inv.extractItems( what, Actionable.MODULATE, src );
if ( available != null )
{
l -= available.getStackSize();
if ( l <= 0 )
return available;
}
else
pro.possible = false; // ;P
}
}
else if ( nodes.size() > 1 )
{
for (CraftingTreeProcess pro : nodes)
{
try
{
while (pro.possible && l > 0)
{
MECraftingInventory subInv = new MECraftingInventory( inv );
pro.request( subInv, 1, src );
subInv.commit( src );
what.setStackSize( l );
IAEItemStack available = inv.extractItems( what, Actionable.MODULATE, src );
if ( available != null )
{
l -= available.getStackSize();
if ( l <= 0 )
return available;
}
else
pro.possible = false; // ;P
}
}
catch (CraftBranchFailure fail)
{
pro.possible = true;
}
}
}
if ( sim )
{
missing += l;
return what;
}
throw new CraftBranchFailure( what, l );
}
public void dive(CraftingJob job)
{
if ( missing > 0 )
job.addMissing( getStack( missing ) );
missing = 0;
for (CraftingTreeProcess pro : nodes)
pro.dive( job );
}
public void setSimulate()
{
sim = true;
missing = 0;
used.resetStatus();
exhausted = false;
for (CraftingTreeProcess pro : nodes)
pro.setSimulate();
}
public void setJob(MECraftingInventory storage, CraftingCPUCluster craftingCPUCluster, BaseActionSource src) throws CraftBranchFailure
{
for (IAEItemStack i : used)
{
IAEItemStack ex = storage.extractItems( i, Actionable.MODULATE, src );
if ( ex == null || ex.getStackSize() != i.getStackSize() )
throw new CraftBranchFailure( i, i.getStackSize() );
craftingCPUCluster.addStorage( ex );
}
for (CraftingTreeProcess pro : nodes)
pro.setJob( storage, craftingCPUCluster, src );
}
}