Relocate Source to proper directory.

This commit is contained in:
AlgorithmX2
2014-09-23 19:26:27 -05:00
parent fe927ce65d
commit 386d18a059
785 changed files with 35585 additions and 35580 deletions
@@ -0,0 +1,17 @@
package appeng.crafting;
import appeng.api.storage.data.IAEItemStack;
public class CraftBranchFailure extends Exception
{
private static final long serialVersionUID = 654603652836724823L;
IAEItemStack missing;
public CraftBranchFailure(IAEItemStack what, long howMany) {
super( "Failed: " + what.getItem().getUnlocalizedName() + " x " + howMany );
missing = what.copy();
missing.setStackSize( howMany );
}
}
@@ -0,0 +1,17 @@
package appeng.crafting;
import appeng.api.storage.data.IAEItemStack;
public class CraftingCalculationFailure extends RuntimeException
{
private static final long serialVersionUID = 654603652836724823L;
IAEItemStack missing;
public CraftingCalculationFailure(IAEItemStack what, long howMany) {
super( "this should have been caught!" );
missing = what.copy();
missing.setStackSize( howMany );
}
}
@@ -0,0 +1,353 @@
package appeng.crafting;
import java.util.HashMap;
import java.util.HashSet;
import java.util.concurrent.TimeUnit;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import appeng.api.AEApi;
import appeng.api.config.Actionable;
import appeng.api.networking.IGrid;
import appeng.api.networking.crafting.ICraftingCallback;
import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.networking.crafting.ICraftingJob;
import appeng.api.networking.crafting.ICraftingPatternDetails;
import appeng.api.networking.security.BaseActionSource;
import appeng.api.networking.storage.IStorageGrid;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
import appeng.core.AELog;
import appeng.hooks.TickHandler;
import com.google.common.base.Stopwatch;
public class CraftingJob implements Runnable, ICraftingJob
{
IAEItemStack output;
IItemList<IAEItemStack> storage;
HashSet<IAEItemStack> prophecies;
boolean simulate = false;
final MECraftingInventory original;
MECraftingInventory availableCheck;
public CraftingTreeNode tree;
private BaseActionSource actionSrc;
private ICraftingCallback callback;
long bytes = 0;
World world;
public IAEItemStack getOutput()
{
return output;
}
public CraftingJob(World w, NBTTagCompound data)
{
world = wrapWorld( w );
storage = AEApi.instance().storage().createItemList();
prophecies = new HashSet();
original = null;
availableCheck = null;
}
public void refund(IAEItemStack o)
{
availableCheck.injectItems( o, Actionable.MODULATE, this.actionSrc );
}
public IAEItemStack checkUse(IAEItemStack available)
{
return availableCheck.extractItems( available, Actionable.MODULATE, this.actionSrc );
}
public CraftingJob(World w, IGrid grid, BaseActionSource actionSrc, IAEItemStack what, ICraftingCallback callback)
{
world = wrapWorld( w );
output = what.copy();
storage = AEApi.instance().storage().createItemList();
prophecies = new HashSet();
this.actionSrc = actionSrc;
this.callback = callback;
ICraftingGrid cc = grid.getCache( ICraftingGrid.class );
IStorageGrid sg = grid.getCache( IStorageGrid.class );
original = new MECraftingInventory( sg.getItemInventory(), actionSrc, false, false, false );
tree = getCraftingTree( cc, what );
availableCheck = null;
}
private World wrapWorld(World w)
{
return w;
}
private CraftingTreeNode getCraftingTree(ICraftingGrid cc, IAEItemStack what)
{
return new CraftingTreeNode( cc, this, what, null, -1, 0 );
}
public long getByteTotal()
{
return bytes;
}
public void writeToNBT(NBTTagCompound out)
{
}
IItemList<IAEItemStack> crafting = AEApi.instance().storage().createItemList();
IItemList<IAEItemStack> missing = AEApi.instance().storage().createItemList();
public void addTask(IAEItemStack what, long crafts, ICraftingPatternDetails details, int depth)
{
if ( crafts > 0 )
{
what = what.copy();
what.setStackSize( what.getStackSize() * crafts );
crafting.add( what );
}
}
public void addMissing(IAEItemStack what)
{
what = what.copy();
missing.add( what );
}
class twoIntegers
{
public long perOp = 0;
public long times = 0;
};
HashMap<String, twoIntegers> opsAndMultiplier = new HashMap();
@Override
public void run()
{
try
{
try
{
TickHandler.instance.registerCraftingSimulation( world, this );
handlepausing();
Stopwatch timer = Stopwatch.createStarted();
MECraftingInventory meci = new MECraftingInventory( original, true, false, true );
meci.ignore( output );
availableCheck = new MECraftingInventory( original, false, false, false );
tree.request( meci, output.getStackSize(), actionSrc );
tree.dive( this );
for (String s : opsAndMultiplier.keySet())
{
twoIntegers ti = opsAndMultiplier.get( s );
AELog.crafting( s + " * " + ti.times + " = " + (ti.perOp * ti.times) );
}
AELog.crafting( "------------- " + getByteTotal() + "b real" + timer.elapsed( TimeUnit.MILLISECONDS ) + "ms" );
// if ( mode == Actionable.MODULATE )
// meci.moveItemsToStorage( storage );
}
catch (CraftBranchFailure e)
{
simulate = true;
try
{
Stopwatch timer = Stopwatch.createStarted();
MECraftingInventory meci = new MECraftingInventory( original, true, false, true );
meci.ignore( output );
availableCheck = new MECraftingInventory( original, false, false, false );
tree.setSimulate();
tree.request( meci, output.getStackSize(), actionSrc );
tree.dive( this );
for (String s : opsAndMultiplier.keySet())
{
twoIntegers ti = opsAndMultiplier.get( s );
AELog.crafting( s + " * " + ti.times + " = " + (ti.perOp * ti.times) );
}
AELog.crafting( "------------- " + getByteTotal() + "b simulate" + timer.elapsed( TimeUnit.MILLISECONDS ) + "ms" );
}
catch (CraftBranchFailure e1)
{
AELog.error( e1 );
}
catch (CraftingCalculationFailure f)
{
AELog.error( f );
}
catch (InterruptedException e1)
{
AELog.crafting( "Crafting calculation canceled." );
finish();
return;
}
}
catch (CraftingCalculationFailure f)
{
AELog.error( f );
}
catch (InterruptedException e1)
{
AELog.crafting( "Crafting calculation canceled." );
finish();
return;
}
log( "crafting job now done" );
}
catch (Throwable t)
{
finish();
throw new RuntimeException( t );
}
finish();
}
public void finish()
{
if ( callback != null )
callback.calculationComplete( this );
availableCheck = null;
synchronized (monitor)
{
running = false;
done = true;
monitor.notify();
}
}
public boolean isSimulation()
{
return simulate;
}
public boolean isDone()
{
return done;
}
public World getWorld()
{
return world;
}
private boolean running = false;
private boolean done = false;
private Object monitor = new Object();
private Stopwatch watch = Stopwatch.createUnstarted();
private int time = 5;
/**
* returns true if this needs more simulation.
*
* @param milli
* @return
*/
public boolean simulateFor(int milli)
{
time = milli;
synchronized (monitor)
{
if ( isDone() )
return false;
watch.reset();
watch.start();
running = true;
log( "main thread is now going to sleep" );
monitor.notify();
while (running)
{
try
{
monitor.wait();
}
catch (InterruptedException e)
{
}
}
log( "main thread is now active" );
}
return true;
}
private int incTime = Integer.MAX_VALUE;
public void handlepausing() throws InterruptedException
{
if ( incTime++ > 100 )
{
incTime = 0;
synchronized (monitor)
{
if ( watch.elapsed( TimeUnit.MICROSECONDS ) > time )
{
running = false;
watch.stop();
monitor.notify();
}
if ( !running )
{
log( "crafting job will now sleep" );
while (!running)
{
monitor.wait();
}
log( "crafting job now active" );
}
}
if ( Thread.interrupted() )
throw new InterruptedException();
}
}
private void log(String string)
{
// AELog.crafting( string );
}
public void addBytes(long crafts)
{
bytes += crafts;
}
@Override
public void populatePlan(IItemList<IAEItemStack> plan)
{
if ( tree != null )
tree.getPlan( plan );
}
}
@@ -0,0 +1,147 @@
package appeng.crafting;
import net.minecraft.nbt.NBTTagCompound;
import appeng.api.config.Actionable;
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 setNexus(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, Actionable mode)
{
if ( tie == null || tie.req == null || tie.req.req == null )
return input;
return tie.req.req.injectCraftedItems( tie.req, input, mode );
}
public void markDone()
{
if ( tie != null )
tie.markDone();
}
}
@@ -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.setNexus( null );
req = null;
tickOfDeath = 0;
}
}
@@ -0,0 +1,318 @@
package appeng.crafting;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import net.minecraft.world.World;
import appeng.api.AEApi;
import appeng.api.config.Actionable;
import appeng.api.config.FuzzyMode;
import appeng.api.networking.crafting.ICraftingGrid;
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.cluster.implementations.CraftingCPUCluster;
public class CraftingTreeNode
{
// parent node.
private CraftingTreeProcess parent;
private World world;
// what slot!
int slot;
int bytes = 0;
// what item is this?
private IAEItemStack what;
// what are the crafting patterns for this?
private ArrayList<CraftingTreeProcess> nodes = new ArrayList();
boolean canEmit = false;
boolean cannotUse = false;
long missing = 0;
long howManyEmitted = 0;
CraftingJob job;
IItemList<IAEItemStack> used = AEApi.instance().storage().createItemList();
boolean exhausted = false;
boolean sim;
public CraftingTreeNode(ICraftingGrid cc, CraftingJob job, IAEItemStack wat, CraftingTreeProcess par, int slot, int depth)
{
what = wat;
parent = par;
this.slot = slot;
this.world = job.getWorld();
this.job = job;
sim = false;
canEmit = cc.canEmitFor( what );
if ( canEmit )
return; // if you can emit for something, you can't make it with patterns.
for (ICraftingPatternDetails details : cc.getCraftingFor( what, parent == null ? null : parent.details, slot, world ))// in
// order.
{
if ( parent == null || parent.notRecursive( 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 notRecursive(ICraftingPatternDetails details)
{
IAEItemStack[] o = details.getCondensedOutputs();
for (IAEItemStack i : o)
if ( i.equals( what ) )
return false;
o = details.getCondensedInputs();
for (IAEItemStack i : o)
if ( i.equals( what ) )
return false;
if ( parent == null )
return true;
return parent.notRecursive( details );
}
public IAEItemStack request(MECraftingInventory inv, long l, BaseActionSource src) throws CraftBranchFailure, InterruptedException
{
job.handlepausing();
List<IAEItemStack> thingsUsed = new LinkedList();
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 )
{
IAEItemStack is = job.checkUse( available );
if ( is != null )
{
thingsUsed.add( is.copy() );
used.add( is );
}
}
bytes += available.getStackSize();
l -= available.getStackSize();
if ( l == 0 )
return available;
}
}
}
}
else
{
IAEItemStack available = inv.extractItems( what, Actionable.MODULATE, src );
if ( available != null )
{
if ( !exhausted )
{
IAEItemStack is = job.checkUse( available );
if ( is != null )
{
thingsUsed.add( is.copy() );
used.add( is );
}
}
bytes += available.getStackSize();
l -= available.getStackSize();
if ( l == 0 )
return available;
}
}
if ( canEmit )
{
IAEItemStack wat = what.copy();
wat.setStackSize( l );
howManyEmitted = wat.getStackSize();
bytes += wat.getStackSize();
return wat;
}
exhausted = true;
if ( nodes.size() == 1 )
{
CraftingTreeProcess pro = nodes.get( 0 );
while (pro.possible && l > 0)
{
IAEItemStack madeWhat = pro.getAmountCrafted( what );
pro.request( inv, pro.getTimes( l, madeWhat.getStackSize() ), src );
madeWhat.setStackSize( l );
IAEItemStack available = inv.extractItems( madeWhat, Actionable.MODULATE, src );
if ( available != null )
{
bytes += available.getStackSize();
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, true, true, true );
pro.request( subInv, 1, src );
what.setStackSize( l );
IAEItemStack available = subInv.extractItems( what, Actionable.MODULATE, src );
if ( available != null )
{
if ( !subInv.commit( src ) )
throw new CraftBranchFailure( what, l );
bytes += available.getStackSize();
l -= available.getStackSize();
if ( l <= 0 )
return available;
}
else
pro.possible = false; // ;P
}
}
catch (CraftBranchFailure fail)
{
pro.possible = true;
}
}
}
if ( sim )
{
missing += l;
bytes += l;
IAEItemStack rv = what.copy();
rv.setStackSize( l );
return rv;
}
for (IAEItemStack o : thingsUsed)
{
job.refund( o.copy() );
o.setStackSize( -o.getStackSize() );
used.add( o );
}
throw new CraftBranchFailure( what, l );
}
public void dive(CraftingJob job)
{
if ( missing > 0 )
job.addMissing( getStack( missing ) );
// missing = 0;
job.addBytes( 8 + bytes );
for (CraftingTreeProcess pro : nodes)
pro.dive( job );
}
public void setSimulate()
{
sim = true;
missing = 0;
bytes = 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 );
}
if ( howManyEmitted > 0 )
{
IAEItemStack i = what.copy();
i.setStackSize( howManyEmitted );
craftingCPUCluster.addEmitable( i );
}
for (CraftingTreeProcess pro : nodes)
pro.setJob( storage, craftingCPUCluster, src );
}
public void getPlan(IItemList<IAEItemStack> plan)
{
if ( missing > 0 )
{
IAEItemStack o = what.copy();
o.setStackSize( missing );
plan.add( o );
}
if ( howManyEmitted > 0 )
{
IAEItemStack i = what.copy();
i.setCountRequestable( howManyEmitted );
plan.addRequestable( i );
}
for (IAEItemStack i : used)
plan.add( i.copy() );
for (CraftingTreeProcess pro : nodes)
pro.getPlan( plan );
}
}
@@ -0,0 +1,279 @@
package appeng.crafting;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import appeng.api.AEApi;
import appeng.api.config.Actionable;
import appeng.api.networking.crafting.ICraftingGrid;
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.container.ContainerNull;
import appeng.me.cluster.implementations.CraftingCPUCluster;
import appeng.util.Platform;
import cpw.mods.fml.common.FMLCommonHandler;
public class CraftingTreeProcess
{
World world;
CraftingTreeNode parent;
ICraftingPatternDetails details;
CraftingJob job;
long crafts = 0;
boolean containerItems;
boolean limitQty;
boolean fullsimulation;
private long bytes = 0;
final private int depth;
Map<CraftingTreeNode, Long> nodes = new HashMap();
public boolean possible = true;
public CraftingTreeProcess(ICraftingGrid cc, CraftingJob job, ICraftingPatternDetails details, CraftingTreeNode craftingTreeNode, int depth, World world) {
parent = craftingTreeNode;
this.details = details;
this.job = job;
this.depth = depth;
world = job.getWorld();
if ( details.isCraftable() )
{
IAEItemStack list[] = details.getInputs();
InventoryCrafting ic = new InventoryCrafting( new ContainerNull(), 3, 3 );
IAEItemStack[] is = details.getInputs();
for (int x = 0; x < ic.getSizeInventory(); x++)
ic.setInventorySlotContents( x, is[x] == null ? null : is[x].getItemStack() );
FMLCommonHandler.instance().firePlayerCraftingEvent( Platform.getPlayer( (WorldServer) world ), details.getOutput( ic, world ), ic );
for (int x = 0; x < ic.getSizeInventory(); x++)
{
ItemStack g = ic.getStackInSlot( x );
if ( g != null && g.stackSize > 1 )
fullsimulation = true;
}
for ( IAEItemStack part : details.getCondensedInputs() )
{
ItemStack g = part.getItemStack();
boolean isAnInput = false;
for ( IAEItemStack a : details.getCondensedOutputs() )
{
if ( g != null && a != null && a.equals( g ) )
isAnInput = true;
}
if ( isAnInput )
limitQty = true;
if ( g.getItem().hasContainerItem( g ) )
limitQty = containerItems = true;
}
boolean complicated = false;
if ( containerItems || complicated )
{
for (int x = 0; x < list.length; x++)
{
IAEItemStack part = list[x];
if ( part != null )
nodes.put( new CraftingTreeNode( cc, job, part.copy(), this, x, depth + 1 ), part.getStackSize() );
}
}
else
{
// this is minorly different then below, this slot uses the pattern, but kinda fudges it.
for (IAEItemStack part : details.getCondensedInputs())
{
for (int x = 0; x < list.length; x++)
{
IAEItemStack ppart = list[x];
if ( part != null && part.equals( ppart ) )
{
// use the first slot...
nodes.put( new CraftingTreeNode( cc, job, part.copy(), this, x, depth + 1 ), part.getStackSize() );
break;
}
}
}
}
}
else
{
for ( IAEItemStack part : details.getCondensedInputs() )
{
ItemStack g = part.getItemStack();
boolean isAnInput = false;
for (IAEItemStack a : details.getCondensedOutputs())
{
if ( g != null && a != null && a.equals( g ) )
isAnInput = true;
}
if ( isAnInput )
limitQty = true;
}
for (IAEItemStack part : details.getCondensedInputs())
{
nodes.put( new CraftingTreeNode( cc, job, part.copy(), this, -1, depth + 1 ), part.getStackSize() );
}
}
}
public boolean notRecursive(ICraftingPatternDetails details)
{
return parent == null || parent.notRecursive( details );
}
long getTimes(long remaining, long stackSize)
{
if ( limitQty || fullsimulation )
return 1;
return (remaining / stackSize) + (remaining % stackSize != 0 ? 1 : 0);
}
IAEItemStack getAmountCrafted(IAEItemStack what2)
{
for (IAEItemStack is : details.getCondensedOutputs())
{
if ( is.equals( what2 ) )
{
what2 = what2.copy();
what2.setStackSize( is.getStackSize() );
return what2;
}
}
// more fuzzy!
for (IAEItemStack is : details.getCondensedOutputs())
{
if ( is.getItem() == what2.getItem() && (is.getItem().isDamageable() || is.getItemDamage() == what2.getItemDamage()) )
{
what2 = is.copy();
what2.setStackSize( is.getStackSize() );
return what2;
}
}
throw new RuntimeException( "Crafting Tree construction failed." );
}
public void request(MECraftingInventory inv, long i, BaseActionSource src) throws CraftBranchFailure, InterruptedException
{
job.handlepausing();
if ( fullsimulation )
{
InventoryCrafting ic = new InventoryCrafting( new ContainerNull(), 3, 3 );
for (Entry<CraftingTreeNode, Long> entry : nodes.entrySet())
{
IAEItemStack item = entry.getKey().getStack( entry.getValue() );
IAEItemStack stack = entry.getKey().request( inv, item.getStackSize(), src );
ic.setInventorySlotContents( entry.getKey().slot, stack.getItemStack() );
}
FMLCommonHandler.instance().firePlayerCraftingEvent( Platform.getPlayer( (WorldServer) world ), details.getOutput( ic, world ), ic );
for (int x = 0; x < ic.getSizeInventory(); x++)
{
ItemStack is = ic.getStackInSlot( x );
is = Platform.getContainerItem( is );
IAEItemStack o = AEApi.instance().storage().createItemStack( is );
if ( o != null )
{
bytes++;
inv.injectItems( o, Actionable.MODULATE, src );
}
}
}
else
{
// request and remove inputs...
for (Entry<CraftingTreeNode, Long> entry : nodes.entrySet())
{
IAEItemStack item = entry.getKey().getStack( entry.getValue() );
IAEItemStack stack = entry.getKey().request( inv, item.getStackSize() * i, src );
if ( containerItems )
{
ItemStack is = Platform.getContainerItem( stack.getItemStack() );
IAEItemStack o = AEApi.instance().storage().createItemStack( is );
if ( o != null )
{
bytes++;
inv.injectItems( o, Actionable.MODULATE, src );
}
}
}
}
// assume its possible.
// add crafting results..
for (IAEItemStack out : details.getCondensedOutputs())
{
IAEItemStack o = out.copy();
o.setStackSize( o.getStackSize() * i );
inv.injectItems( o, Actionable.MODULATE, src );
}
crafts += i;
}
public void dive(CraftingJob job)
{
job.addTask( getAmountCrafted( parent.getStack( 1 ) ), crafts, details, depth );
for (CraftingTreeNode pro : nodes.keySet())
pro.dive( job );
job.addBytes( 8 + crafts + bytes );
}
public void setSimulate()
{
crafts = 0;
bytes = 0;
for (CraftingTreeNode pro : nodes.keySet())
pro.setSimulate();
}
public void setJob(MECraftingInventory storage, CraftingCPUCluster craftingCPUCluster, BaseActionSource src) throws CraftBranchFailure
{
craftingCPUCluster.addCrafting( details, crafts );
for (CraftingTreeNode pro : nodes.keySet())
pro.setJob( storage, craftingCPUCluster, src );
}
public void getPlan(IItemList<IAEItemStack> plan)
{
for (IAEItemStack i : details.getOutputs())
{
i = i.copy();
i.setCountRequestable( i.getStackSize() * crafts );
plan.addRequestable( i );
}
for (CraftingTreeNode pro : nodes.keySet())
pro.getPlan( plan );
}
}
@@ -0,0 +1,171 @@
package appeng.crafting;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import appeng.api.networking.crafting.ICraftingWatcher;
import appeng.api.networking.crafting.ICraftingWatcherHost;
import appeng.api.storage.data.IAEStack;
import appeng.me.cache.CraftingGridCache;
/**
* Maintain my interests, and a global watch list, they should always be fully synchronized.
*/
public class CraftingWatcher implements ICraftingWatcher
{
class ItemWatcherIterator implements Iterator<IAEStack>
{
final CraftingWatcher watcher;
final Iterator<IAEStack> interestIterator;
IAEStack myLast;
public ItemWatcherIterator(CraftingWatcher parent, Iterator<IAEStack> i) {
watcher = parent;
interestIterator = i;
}
@Override
public boolean hasNext()
{
return interestIterator.hasNext();
}
@Override
public IAEStack next()
{
return myLast = interestIterator.next();
}
@Override
public void remove()
{
gsc.interestManager.remove( myLast, watcher );
interestIterator.remove();
}
};
CraftingGridCache gsc;
ICraftingWatcherHost myObject;
HashSet<IAEStack> myInterests = new HashSet();
public CraftingWatcher(CraftingGridCache cache, ICraftingWatcherHost host) {
gsc = cache;
myObject = host;
}
public ICraftingWatcherHost getHost()
{
return myObject;
}
@Override
public boolean add(IAEStack e)
{
if ( myInterests.contains( e ) )
return false;
return myInterests.add( e.copy() ) && gsc.interestManager.put( e, this );
}
@Override
public boolean addAll(Collection<? extends IAEStack> c)
{
boolean didChange = false;
for (IAEStack o : c)
didChange = add( o ) || didChange;
return didChange;
}
@Override
public void clear()
{
Iterator<IAEStack> i = myInterests.iterator();
while (i.hasNext())
{
gsc.interestManager.remove( i.next(), this );
i.remove();
}
}
@Override
public boolean contains(Object o)
{
return myInterests.contains( o );
}
@Override
public boolean containsAll(Collection<?> c)
{
return myInterests.containsAll( c );
}
@Override
public boolean isEmpty()
{
return myInterests.isEmpty();
}
@Override
public Iterator<IAEStack> iterator()
{
return new ItemWatcherIterator( this, myInterests.iterator() );
}
@Override
public boolean remove(Object o)
{
return myInterests.remove( o ) && gsc.interestManager.remove( (IAEStack) o, this );
}
@Override
public boolean removeAll(Collection<?> c)
{
boolean didSomething = false;
for (Object o : c)
didSomething = remove( o ) || didSomething;
return didSomething;
}
@Override
public boolean retainAll(Collection<?> c)
{
boolean changed = false;
Iterator<IAEStack> i = iterator();
while (i.hasNext())
{
if ( !c.contains( i.next() ) )
{
i.remove();
changed = true;
}
}
return changed;
}
@Override
public int size()
{
return myInterests.size();
}
@Override
public Object[] toArray()
{
return myInterests.toArray();
}
@Override
public <T> T[] toArray(T[] a)
{
return myInterests.toArray( a );
}
}
@@ -0,0 +1,270 @@
package appeng.crafting;
import appeng.api.AEApi;
import appeng.api.config.Actionable;
import appeng.api.networking.security.BaseActionSource;
import appeng.api.storage.IMEInventory;
import appeng.api.storage.IMEMonitor;
import appeng.api.storage.StorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
public class MECraftingInventory implements IMEInventory<IAEItemStack>
{
final MECraftingInventory par;
final IMEInventory<IAEItemStack> target;
final IItemList<IAEItemStack> localCache;
final boolean logExtracted;
final IItemList<IAEItemStack> extractedCache;
final boolean logInjections;
final IItemList<IAEItemStack> injectedCache;
final boolean logMissing;
final IItemList<IAEItemStack> missingCache;
public MECraftingInventory()
{
localCache = AEApi.instance().storage().createItemList();
extractedCache = null;
injectedCache = null;
missingCache = null;
this.logExtracted = false;
this.logInjections = false;
this.logMissing = false;
target = null;
par = null;
}
public MECraftingInventory(MECraftingInventory parent)
{
this.target = parent;
this.logExtracted = parent.logExtracted;
this.logInjections = parent.logInjections;
this.logMissing = parent.logMissing;
if ( logMissing )
missingCache = AEApi.instance().storage().createItemList();
else
missingCache = null;
if ( logExtracted )
extractedCache = AEApi.instance().storage().createItemList();
else
extractedCache = null;
if ( logInjections )
injectedCache = AEApi.instance().storage().createItemList();
else
injectedCache = null;
localCache = target.getAvailableItems( AEApi.instance().storage().createItemList() );
par = parent;
}
public MECraftingInventory(IMEMonitor<IAEItemStack> target, BaseActionSource src, boolean logExtracted, boolean logInjections, boolean logMissing)
{
this.target = target;
this.logExtracted = logExtracted;
this.logInjections = logInjections;
this.logMissing = logMissing;
if ( logMissing )
missingCache = AEApi.instance().storage().createItemList();
else
missingCache = null;
if ( logExtracted )
extractedCache = AEApi.instance().storage().createItemList();
else
extractedCache = null;
if ( logInjections )
injectedCache = AEApi.instance().storage().createItemList();
else
injectedCache = null;
localCache = AEApi.instance().storage().createItemList();
for (IAEItemStack is : target.getStorageList())
localCache.add( target.extractItems( is, Actionable.SIMULATE, src ) );
par = null;
}
public MECraftingInventory(IMEInventory<IAEItemStack> target, boolean logExtracted, boolean logInjections, boolean logMissing)
{
this.target = target;
this.logExtracted = logExtracted;
this.logInjections = logInjections;
this.logMissing = logMissing;
if ( logMissing )
missingCache = AEApi.instance().storage().createItemList();
else
missingCache = null;
if ( logExtracted )
extractedCache = AEApi.instance().storage().createItemList();
else
extractedCache = null;
if ( logInjections )
injectedCache = AEApi.instance().storage().createItemList();
else
injectedCache = null;
localCache = target.getAvailableItems( AEApi.instance().storage().createItemList() );
par = null;
}
@Override
public IAEItemStack injectItems(IAEItemStack input, Actionable mode, BaseActionSource src)
{
if ( input == null )
return null;
if ( mode == Actionable.MODULATE )
{
if ( logInjections )
injectedCache.add( input );
localCache.add( input );
}
return null;
}
@Override
public IAEItemStack extractItems(IAEItemStack request, Actionable mode, BaseActionSource src)
{
if ( request == null )
return null;
IAEItemStack list = localCache.findPrecise( request );
if ( list == null || list.getStackSize() == 0 )
return null;
if ( list.getStackSize() >= request.getStackSize() )
{
if ( mode == Actionable.MODULATE )
{
list.decStackSize( request.getStackSize() );
if ( logExtracted )
extractedCache.add( request );
}
return request;
}
IAEItemStack ret = request.copy();
ret.setStackSize( list.getStackSize() );
if ( mode == Actionable.MODULATE )
{
list.reset();
if ( logExtracted )
extractedCache.add( ret );
}
return ret;
}
@Override
public IItemList<IAEItemStack> getAvailableItems(IItemList<IAEItemStack> out)
{
for (IAEItemStack is : localCache)
out.add( is );
return out;
}
public IItemList<IAEItemStack> getItemList()
{
return localCache;
}
@Override
public StorageChannel getChannel()
{
return StorageChannel.ITEMS;
}
public boolean commit(BaseActionSource src)
{
IItemList<IAEItemStack> added = AEApi.instance().storage().createItemList();
IItemList<IAEItemStack> pulled = AEApi.instance().storage().createItemList();
boolean failed = false;
if ( logInjections )
{
for (IAEItemStack inject : injectedCache)
{
IAEItemStack result = null;
added.add( result = target.injectItems( inject, Actionable.MODULATE, src ) );
if ( result != null )
{
failed = true;
break;
}
}
}
if ( failed )
{
for (IAEItemStack is : added)
target.extractItems( is, Actionable.MODULATE, src );
return false;
}
if ( logExtracted )
{
for (IAEItemStack extra : extractedCache)
{
IAEItemStack result = null;
pulled.add( result = target.extractItems( extra, Actionable.MODULATE, src ) );
if ( result == null || result.getStackSize() != extra.getStackSize() )
{
failed = true;
break;
}
}
}
if ( failed )
{
for (IAEItemStack is : added)
target.extractItems( is, Actionable.MODULATE, src );
for (IAEItemStack is : pulled)
target.injectItems( is, Actionable.MODULATE, src );
return false;
}
if ( logMissing && par != null )
{
for (IAEItemStack extra : missingCache)
par.addMissing( extra );
}
return true;
}
public void addMissing(IAEItemStack extra)
{
missingCache.add( extra );
}
public void ignore(IAEItemStack what)
{
IAEItemStack list = localCache.findPrecise( what );
if ( list != null )
list.setStackSize( 0 );
}
}