Compare commits

..

6 Commits

Author SHA1 Message Date
PrototypeTrousers c532b9c839 wip 2022-03-05 00:03:29 -03:00
PrototypeTrousers 447c6debab account for interfaces priority affecting which items are extractable 2022-03-04 22:49:55 -03:00
PrototypeTrousers 50470ae3cf version 2022-03-04 21:44:58 -03:00
PrototypeTrousers 993be652c9 delay container item return when simulating crafting tree 2022-03-04 21:30:26 -03:00
PrototypeTrousers b3bfbd0b58 remove debugging log 2022-03-04 17:08:23 -03:00
PrototypeTrousers 49b3dc8b60 undo partially pattern cache rebuild optimization
enabled pattern substitution now can use substitute patterned items
2022-03-03 22:25:10 -03:00
7 changed files with 334 additions and 181 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ aebuild=7
aegroup=appeng aegroup=appeng
aebasename=appliedenergistics2 aebasename=appliedenergistics2
extended=extended_life extended=extended_life
extendedversion=v50g extendedversion=v50j
######################################################### #########################################################
# Versions # # Versions #
######################################################### #########################################################
+21 -3
View File
@@ -22,6 +22,7 @@ package appeng.crafting;
import java.util.HashMap; import java.util.HashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import appeng.me.cache.GridStorageCache;
import com.google.common.base.Stopwatch; import com.google.common.base.Stopwatch;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
@@ -66,6 +67,7 @@ public class CraftingJob implements Runnable, ICraftingJob
private final Stopwatch craftingTreeWatch = Stopwatch.createUnstarted(); private final Stopwatch craftingTreeWatch = Stopwatch.createUnstarted();
private CraftingTreeNode tree; private CraftingTreeNode tree;
private final IAEItemStack output; private final IAEItemStack output;
private long expectedOutput;
private boolean simulate = false; private boolean simulate = false;
private MECraftingInventory availableCheck; private MECraftingInventory availableCheck;
private long bytes = 0; private long bytes = 0;
@@ -88,14 +90,25 @@ public class CraftingJob implements Runnable, ICraftingJob
this.actionSrc = actionSrc; this.actionSrc = actionSrc;
this.callback = callback; this.callback = callback;
final ICraftingGrid cc = grid.getCache( ICraftingGrid.class ); final ICraftingGrid cc = grid.getCache( ICraftingGrid.class );
final IStorageGrid sg = grid.getCache( IStorageGrid.class ); final GridStorageCache sg = grid.getCache( IStorageGrid.class );
this.original = new MECraftingInventory( sg.getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ), actionSrc, false, false, false ); this.original = new MECraftingInventory( sg.getExtractableList( actionSrc ) );
this.setTree( this.getCraftingTree( cc, what ) ); this.setTree( this.getCraftingTree( cc, what ) );
this.availableCheck = null; this.availableCheck = null;
} }
public long getExpectedOutput()
{
return expectedOutput;
}
public void incExpectedOutput( long amount )
{
this.expectedOutput += amount;
}
private CraftingTreeNode getCraftingTree( final ICraftingGrid cc, final IAEItemStack what ) private CraftingTreeNode getCraftingTree( final ICraftingGrid cc, final IAEItemStack what )
{ {
return new CraftingTreeNode( cc, this, what, null, -1, 0 ); return new CraftingTreeNode( cc, this, what, null, -1, 0 );
@@ -121,6 +134,11 @@ public class CraftingJob implements Runnable, ICraftingJob
return this.availableCheck.extractItems( available, Actionable.MODULATE, this.actionSrc ); return this.availableCheck.extractItems( available, Actionable.MODULATE, this.actionSrc );
} }
IAEItemStack checkAvailable( final IAEItemStack available )
{
return this.original.extractItems( available.copy().setStackSize( Long.MAX_VALUE ), Actionable.SIMULATE, this.actionSrc );
}
public void writeToNBT( final NBTTagCompound out ) public void writeToNBT( final NBTTagCompound out )
{ {
@@ -268,7 +286,7 @@ public class CraftingJob implements Runnable, ICraftingJob
} }
} }
} }
if( Thread.interrupted() ) if( Thread.interrupted() )
{ {
throw new InterruptedException(); throw new InterruptedException();
@@ -23,14 +23,12 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import com.google.common.collect.Lists; import appeng.api.config.FuzzyMode;
import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextComponentString;
import net.minecraft.world.World; import net.minecraft.world.World;
import appeng.api.AEApi; import appeng.api.AEApi;
import appeng.api.config.Actionable; import appeng.api.config.Actionable;
import appeng.api.config.FuzzyMode;
import appeng.api.networking.crafting.ICraftingGrid; import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.networking.crafting.ICraftingPatternDetails; import appeng.api.networking.crafting.ICraftingPatternDetails;
import appeng.api.networking.security.IActionSource; import appeng.api.networking.security.IActionSource;
@@ -81,100 +79,32 @@ public class CraftingTreeNode
for( final ICraftingPatternDetails details : cc.getCraftingFor( this.what, this.parent == null ? null : this.parent.details, slot, this.world ) )// in for( final ICraftingPatternDetails details : cc.getCraftingFor( this.what, this.parent == null ? null : this.parent.details, slot, this.world ) )// in
// order. // order.
{ {
if( this.parent == null || this.parent.notRecursive() ) if( this.parent == null || job.getExpectedOutput() < job.getOutput().getStackSize() )
{ {
this.nodes.add( new CraftingTreeProcess( cc, job, details, this, depth + 1 ) ); this.nodes.add( new CraftingTreeProcess( cc, job, details, this, depth + 1 ) );
} }
} }
} }
public CraftingTreeNode( final ICraftingGrid cc, final CraftingJob job, final IAEItemStack wat, final CraftingTreeProcess par, final int slot, final int depth, boolean available )
{
this.what = wat;
this.parent = par;
this.slot = slot;
this.world = job.getWorld();
this.job = job;
this.sim = false;
this.canEmit = cc.canEmitFor( this.what );
if( this.canEmit )
{
return; // if you can emit for something, you can't make it with patterns.
}
if( !available )
{
for( final ICraftingPatternDetails details : cc.getCraftingFor( this.what, this.parent == null ? null : this.parent.details, slot, this.world ) )// in
// order.
{
if( this.parent == null || this.parent.notRecursive() )
{
this.nodes.add( new CraftingTreeProcess( cc, job, details, this, depth + 1 ) );
}
}
}
}
boolean notRecursive( final ICraftingPatternDetails details )
{
IAEItemStack[] o = details.getCondensedOutputs();
for( final IAEItemStack i : o )
{
if( i.equals( this.what ) )
{
return false;
}
}
o = details.getCondensedInputs();
for( final IAEItemStack i : o )
{
if( i.equals( this.what ) )
{
return false;
}
}
if( this.parent == null )
{
return true;
}
return this.parent.notRecursive();
}
IAEItemStack request( final MECraftingInventory inv, long l, final IActionSource src ) throws CraftBranchFailure, InterruptedException IAEItemStack request( final MECraftingInventory inv, long l, final IActionSource src ) throws CraftBranchFailure, InterruptedException
{ {
this.job.handlePausing(); this.job.handlePausing();
final IItemList<IAEItemStack> inventoryList = inv.getItemList();
final List<IAEItemStack> thingsUsed = new ArrayList<>(); final List<IAEItemStack> thingsUsed = new ArrayList<>();
this.what.setStackSize( l ); this.what.setStackSize( l );
if( this.getSlot() >= 0 && this.parent != null && this.parent.details.isCraftable() ) if( this.getSlot() >= 0 && this.parent != null && this.parent.details.isCraftable() )
{ {
final Collection<IAEItemStack> itemList; Collection<IAEItemStack> itemList = new ArrayList<>();
final IItemList<IAEItemStack> inventoryList = inv.getItemList();
if( this.parent.details.canSubstitute() ) if( this.parent.getContainerItems() != null && !this.parent.getContainerItems().findFuzzy( this.what, FuzzyMode.IGNORE_ALL ).isEmpty() )
{ {
final List<IAEItemStack> substitutes = this.parent.details.getSubstituteInputs( this.slot ); itemList = inventoryList.findFuzzy( this.what, FuzzyMode.IGNORE_ALL );
itemList = new ArrayList<>( substitutes.size() );
for( IAEItemStack stack : substitutes )
{
itemList.addAll( inventoryList.findFuzzy( stack, FuzzyMode.IGNORE_ALL ) );
}
} }
else else
{ {
itemList = Lists.newArrayList();
final IAEItemStack item = inventoryList.findPrecise( this.what ); final IAEItemStack item = inventoryList.findPrecise( this.what );
if( item != null ) if( item != null )
{ {
itemList.add( item ); itemList.add( item );
@@ -345,11 +275,6 @@ public class CraftingTreeNode
throw new CraftBranchFailure( this.what, l ); throw new CraftBranchFailure( this.what, l );
} }
boolean notRecursive()
{
return job.getUniques().findPrecise( this.what ) == null || this.parent == null;
}
void dive( final CraftingJob job ) void dive( final CraftingJob job )
{ {
if( this.missing > 0 ) if( this.missing > 0 )
@@ -19,16 +19,19 @@
package appeng.crafting; package appeng.crafting;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
import appeng.api.config.Actionable;
import appeng.api.config.FuzzyMode; import appeng.api.config.FuzzyMode;
import appeng.util.item.AEItemStack; import appeng.util.item.AEItemStack;
import com.google.common.collect.ImmutableCollection;
import it.unimi.dsi.fastutil.objects.Object2LongArrayMap; import it.unimi.dsi.fastutil.objects.Object2LongArrayMap;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.world.World; import net.minecraft.world.World;
import appeng.api.AEApi; import appeng.api.AEApi;
import appeng.api.config.Actionable;
import appeng.api.networking.crafting.ICraftingGrid; import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.networking.crafting.ICraftingPatternDetails; import appeng.api.networking.crafting.ICraftingPatternDetails;
import appeng.api.networking.security.IActionSource; import appeng.api.networking.security.IActionSource;
@@ -50,6 +53,7 @@ public class CraftingTreeProcess
private long crafts = 0; private long crafts = 0;
private IItemList<IAEItemStack> containerItems; private IItemList<IAEItemStack> containerItems;
private boolean limitQty; private boolean limitQty;
private final List<IAEItemStack> craftingResultList = new ArrayList<>();
private long bytes = 0; private long bytes = 0;
public CraftingTreeProcess( final ICraftingGrid cc, final CraftingJob job, final ICraftingPatternDetails details, final CraftingTreeNode craftingTreeNode, final int depth ) public CraftingTreeProcess( final ICraftingGrid cc, final CraftingJob job, final ICraftingPatternDetails details, final CraftingTreeNode craftingTreeNode, final int depth )
@@ -72,47 +76,215 @@ public class CraftingTreeProcess
} }
containerItems.add( part ); containerItems.add( part );
this.limitQty = true; this.limitQty = true;
} //break;
}
// this is minor different then below, this slot uses the pattern, but kinda fudges it.
for( IAEItemStack part : details.getCondensedInputs() ) {
if (part == null) {
continue;
}
for (int x = 0; x < list.length; x++) {
final IAEItemStack comparePart = list[x];
if (part.equals(comparePart)) {
if (isContainerItem(part)) {
part = list[x];
}
this.nodes.put(new CraftingTreeNode(cc, job, part.copy(), this, x, depth + 1), part.getStackSize());
if (details.canSubstitute()) {
for ()
}
break;
}
} }
} }
if(!this.limitQty) { for( final IAEItemStack part : details.getCondensedOutputs() )
for (final IAEItemStack part : details.getCondensedOutputs()) { {
for (final IAEItemStack o : details.getCondensedInputs()) { if( part.equals( job.getOutput() ) )
if (part.equals(o)) { {
this.limitQty = true; job.incExpectedOutput( part.getStackSize() );
}
}
for( final IAEItemStack part : details.getCondensedInputs() )
{
if( part.equals( job.getOutput() ) )
{
job.incExpectedOutput( -part.getStackSize() );
}
}
// this is minor different then below, this slot uses the pattern, but kinda fudges it.
for( IAEItemStack part : details.getCondensedInputs() )
{
if( part == null )
{
continue;
}
for( int x = 0; x < list.length; x++ )
{
final IAEItemStack comparePart = list[x];
if( part.equals( comparePart ) )
{
boolean isPartContainer = false;
if( containerItems != null && !containerItems.findFuzzy( list[x], FuzzyMode.IGNORE_ALL ).isEmpty() )
{
part = list[x];
isPartContainer = true;
}
long wantedSize = part.getStackSize();
if( !isPartContainer )
{
IAEItemStack found = job.checkAvailable( part );
IAEItemStack used;
long requestAmount;
long remaining = 0;
if( found != null )
{
used = job.getUsedWhileBuilding().findPrecise( part );
remaining = found.getStackSize();
if( used != null )
{
if( used.getStackSize() >= found.getStackSize() )
{
remaining = 0;
}
else
{
remaining -= used.getStackSize();
}
}
}
if( remaining > 0 )
{
if( remaining >= wantedSize )
{
requestAmount = wantedSize;
wantedSize = 0;
//we have the items
}
else
{
requestAmount = remaining;
wantedSize -= remaining;
}
part = part.copy().setStackSize( requestAmount );
job.getUsedWhileBuilding().addStorage( part );
this.nodes.put( new CraftingTreeNode( cc, job, part, this, x, depth + 1 ), requestAmount );
if( wantedSize == 0 )
{
break;
}
}
if( wantedSize > 0 )
{
if( details.canSubstitute() && cc.getCraftingFor( part, details, x, world ).isEmpty() )
{
//try to extract substitutes
for( IAEItemStack subs : details.getSubstituteInputs( x ) )
{
if( subs.equals( part ) )
{
continue;
}
found = job.checkAvailable( subs );
remaining = 0;
if( found != null )
{
used = job.getUsedWhileBuilding().findPrecise( subs );
remaining = found.getStackSize();
if( used != null )
{
if( used.getStackSize() >= found.getStackSize() )
{
remaining = 0;
}
else
{
remaining -= used.getStackSize();
}
}
}
if( remaining > 0 )
{
if( remaining >= wantedSize )
{
requestAmount = wantedSize;
wantedSize = 0;
//we have the items
}
else
{
requestAmount = remaining;
wantedSize -= remaining;
}
subs = subs.copy().setStackSize( requestAmount );
job.getUsedWhileBuilding().addStorage( subs );
this.nodes.put( new CraftingTreeNode( cc, job, subs, this, x, depth + 1 ), requestAmount );
}
if( wantedSize == 0 )
{
break;
}
}
if( wantedSize > 0 )
{
//try to order the crafting of a substitute
ICraftingPatternDetails prioritizedPattern = null;
IAEItemStack prioritizedIAE = null;
for( IAEItemStack subs : details.getSubstituteInputs( x ) )
{
if( subs.equals( part ) )
{
continue;
}
ImmutableCollection<ICraftingPatternDetails> detailCollection = cc.getCraftingFor( subs, details, x, world );
for( ICraftingPatternDetails sp : detailCollection )
{
if( prioritizedPattern == null )
{
prioritizedPattern = sp;
prioritizedIAE = subs;
}
else
{
if( sp.getPriority() > prioritizedPattern.getPriority() )
{
prioritizedPattern = sp;
prioritizedIAE = subs;
}
}
this.nodes.put( new CraftingTreeNode( cc, job, prioritizedIAE.copy(), this, x, depth + 1 ), wantedSize );
wantedSize = 0;
break;
}
}
if( wantedSize == 0 )
{
break;
}
}
}
}
}
if( wantedSize > 0 )
{
part = part.copy();
// use the first slot...
this.nodes.put( new CraftingTreeNode( cc, job, part, this, x, depth + 1 ), wantedSize );
wantedSize = 0;
}
if( !isPartContainer && wantedSize == 0 )
{
break; break;
} }
} }
} }
} }
for( final IAEItemStack part : details.getCondensedOutputs() )
{
for( final IAEItemStack o : details.getCondensedInputs() )
{
if( part.equals( o ) )
{
this.limitQty = true;
break;
}
}
}
} }
boolean isContainerItem(IAEItemStack iaeItemStack) { IItemList<IAEItemStack> getContainerItems()
return (containerItems != null && !containerItems.findFuzzy(iaeItemStack, FuzzyMode.IGNORE_ALL).isEmpty());
}
boolean notRecursive()
{ {
return this.parent == null || this.parent.notRecursive(); return this.containerItems;
} }
long getTimes( final long remaining, final long stackSize ) long getTimes( final long remaining, final long stackSize )
@@ -141,7 +313,7 @@ public class CraftingTreeProcess
if( o != null ) if( o != null )
{ {
this.bytes++; this.bytes++;
inv.injectItems( o, Actionable.MODULATE, src ); craftingResultList.add( o );
} }
} }
} }
@@ -153,11 +325,22 @@ public class CraftingTreeProcess
{ {
final IAEItemStack o = out.copy(); final IAEItemStack o = out.copy();
o.setStackSize( o.getStackSize() * amountOfTimes ); o.setStackSize( o.getStackSize() * amountOfTimes );
inv.injectItems( o, Actionable.MODULATE, src ); craftingResultList.add( o );
} }
for( IAEItemStack i : craftingResultList )
{
inv.injectItems( i, Actionable.MODULATE, src );
}
this.crafts += amountOfTimes; this.crafts += amountOfTimes;
} }
public List<IAEItemStack> getCraftingResultList()
{
return craftingResultList;
}
void dive( final CraftingJob job ) void dive( final CraftingJob job )
{ {
job.addTask( this.getAmountCrafted( this.parent.getStack( 1 ) ), this.crafts, this.details, this.depth ); job.addTask( this.getAmountCrafted( this.parent.getStack( 1 ) ), this.crafts, this.details, this.depth );
@@ -28,7 +28,6 @@ import appeng.api.storage.IStorageChannel;
import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.channels.IItemStorageChannel;
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.me.helpers.PlayerSource;
import appeng.util.inv.ItemListIgnoreCrafting; import appeng.util.inv.ItemListIgnoreCrafting;
import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextComponentString;
@@ -312,11 +311,11 @@ public class MECraftingInventory implements IMEInventory<IAEItemStack>
{ {
if( result == null ) if( result == null )
{ {
src.player().get().sendStatusMessage( new TextComponentString( "System reported " + extra.getStackSize() + " " + extra.getDefinition().getItem().getItemStackDisplayName( extra.getDefinition() ) + " available but could not extract anything" ), false ); src.player().get().sendStatusMessage( new TextComponentString( "System reported " + extra.getStackSize() + " " + extra.getDefinition().getDisplayName() + " available but could not extract anything" ), false );
} }
else else
{ {
src.player().get().sendStatusMessage( new TextComponentString( "System reported " + extra.getStackSize() + " " + extra.getDefinition().getItem().getItemStackDisplayName( extra.getDefinition() ) + " available but could only extract " + result.getStackSize() ), false ); src.player().get().sendStatusMessage( new TextComponentString( "System reported " + extra.getStackSize() + " " + extra.getDefinition().getDisplayName() + " available but could only extract " + result.getStackSize() ), false );
} }
} }
failed = true; failed = true;
+34 -8
View File
@@ -19,13 +19,12 @@
package appeng.me.cache; package appeng.me.cache;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.crafting.MECraftingInventory;
import appeng.helpers.IInterfaceHost;
import appeng.helpers.IPriorityHost;
import com.google.common.collect.HashMultimap; import com.google.common.collect.HashMultimap;
import com.google.common.collect.SetMultimap; import com.google.common.collect.SetMultimap;
@@ -55,6 +54,8 @@ import appeng.me.helpers.GenericInterestManager;
import appeng.me.helpers.MachineSource; import appeng.me.helpers.MachineSource;
import appeng.me.storage.ItemWatcher; import appeng.me.storage.ItemWatcher;
import appeng.me.storage.NetworkInventoryHandler; import appeng.me.storage.NetworkInventoryHandler;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public class GridStorageCache implements IStorageGrid public class GridStorageCache implements IStorageGrid
@@ -68,6 +69,8 @@ public class GridStorageCache implements IStorageGrid
private final HashMap<IGridNode, IStackWatcher> watchers = new HashMap<>(); private final HashMap<IGridNode, IStackWatcher> watchers = new HashMap<>();
private final Map<IStorageChannel<? extends IAEStack>, NetworkInventoryHandler<?>> storageNetworks; private final Map<IStorageChannel<? extends IAEStack>, NetworkInventoryHandler<?>> storageNetworks;
private final Map<IStorageChannel<? extends IAEStack>, NetworkMonitor<?>> storageMonitors; private final Map<IStorageChannel<? extends IAEStack>, NetworkMonitor<?>> storageMonitors;
private MECraftingInventory localCache = null;
private final Int2ObjectMap<MECraftingInventory> extractableItemPriorityMap = new Int2ObjectOpenHashMap<>();
private int localDepth; private int localDepth;
public GridStorageCache( final IGrid g ) public GridStorageCache( final IGrid g )
@@ -82,6 +85,8 @@ public class GridStorageCache implements IStorageGrid
@Override @Override
public void onUpdateTick() public void onUpdateTick()
{ {
this.localCache = null;
this.extractableItemPriorityMap.clear();
this.storageMonitors.forEach( ( channel, monitor ) -> monitor.onTick() ); this.storageMonitors.forEach( ( channel, monitor ) -> monitor.onTick() );
} }
@@ -169,6 +174,28 @@ public class GridStorageCache implements IStorageGrid
return (IMEMonitor<T>) this.storageMonitors.get( channel ); return (IMEMonitor<T>) this.storageMonitors.get( channel );
} }
public MECraftingInventory getExtractableList( IActionSource src )
{
if( src instanceof MachineSource )
{
if( src.machine().isPresent() )
{
IActionHost machine = src.machine().get();
if( machine instanceof IInterfaceHost )
{
extractableItemPriorityMap.putIfAbsent( ( (IPriorityHost) machine ).getPriority(), new MECraftingInventory( getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ), src, false, false, false ) );
return extractableItemPriorityMap.get( ( (IPriorityHost) machine ).getPriority() );
}
}
}
if( localCache == null )
{
localCache = new MECraftingInventory( getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ), src, false, false, false );
}
return localCache;
}
private CellChangeTracker addCellProvider( final ICellProvider cc, final CellChangeTracker tracker ) private CellChangeTracker addCellProvider( final ICellProvider cc, final CellChangeTracker tracker )
{ {
if( this.inactiveCellProviders.contains( cc ) ) if( this.inactiveCellProviders.contains( cc ) )
@@ -198,8 +225,7 @@ public class GridStorageCache implements IStorageGrid
final IActionSource actionSrc = cc instanceof IActionHost ? new MachineSource( (IActionHost) cc ) : new BaseActionSource(); final IActionSource actionSrc = cc instanceof IActionHost ? new MachineSource( (IActionHost) cc ) : new BaseActionSource();
this.storageMonitors.forEach( ( channel, monitor ) -> this.storageMonitors.forEach( ( channel, monitor ) -> {
{
for( final IMEInventoryHandler<IAEItemStack> h : cc.getCellArray( channel ) ) for( final IMEInventoryHandler<IAEItemStack> h : cc.getCellArray( channel ) )
{ {
tracker.postChanges( channel, -1, h, actionSrc ); tracker.postChanges( channel, -1, h, actionSrc );
@@ -239,7 +239,8 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{ {
// also stop accepting items when the job is complete, i.e. to prevent re-insertion when pushing out // also stop accepting items when the job is complete, i.e. to prevent re-insertion when pushing out
// items during storeItems // items during storeItems
if (input == null || isComplete) { if( input == null || isComplete )
{
return input; return input;
} }
@@ -375,7 +376,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{ {
final ImmutableList<IAEItemStack> single = ImmutableList.of( diff.copy() ); final ImmutableList<IAEItemStack> single = ImmutableList.of( diff.copy() );
while( i.hasNext() ) while ( i.hasNext() )
{ {
final Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object> o = i.next(); final Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object> o = i.next();
final IMEMonitorHandlerReceiver<IAEItemStack> receiver = o.getKey(); final IMEMonitorHandlerReceiver<IAEItemStack> receiver = o.getKey();
@@ -495,15 +496,14 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
return null; return null;
} }
private boolean canCraft(final ICraftingPatternDetails details, final IAEItemStack[] condensedInputs) private boolean canCraft( final ICraftingPatternDetails details, final IAEItemStack[] condensedInputs )
{ {
if( !details.isCraftable() ) if( !details.isCraftable() )
{ {
// Processing patterns are relatively easy // Processing patterns are relatively easy
for ( IAEItemStack input : condensedInputs ) for( IAEItemStack input : condensedInputs )
{ {
final IAEItemStack ais = this.inventory.extractItems( input.copy(), Actionable.SIMULATE, final IAEItemStack ais = this.inventory.extractItems( input.copy(), Actionable.SIMULATE, this.machineSrc );
this.machineSrc );
if( ais == null || ais.getStackSize() < input.getStackSize() ) if( ais == null || ais.getStackSize() < input.getStackSize() )
{ {
@@ -516,7 +516,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
// When substitutions are allowed, we have to keep track of which items we've reserved // When substitutions are allowed, we have to keep track of which items we've reserved
IAEItemStack[] inputs = details.getInputs(); IAEItemStack[] inputs = details.getInputs();
Map<IAEItemStack, Integer> consumedCount = new HashMap<>(); Map<IAEItemStack, Integer> consumedCount = new HashMap<>();
for ( int i = 0; i < inputs.length; i++ ) for( int i = 0; i < inputs.length; i++ )
{ {
List<IAEItemStack> substitutes = details.getSubstituteInputs( i ); List<IAEItemStack> substitutes = details.getSubstituteInputs( i );
if( substitutes.isEmpty() ) if( substitutes.isEmpty() )
@@ -525,9 +525,9 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
} }
boolean found = false; boolean found = false;
for ( IAEItemStack substitute : substitutes ) for( IAEItemStack substitute : substitutes )
{ {
for ( IAEItemStack fuzz : this.inventory.getItemList().findFuzzy( substitute, FuzzyMode.IGNORE_ALL ) ) for( IAEItemStack fuzz : this.inventory.getItemList().findFuzzy( substitute, FuzzyMode.IGNORE_ALL ) )
{ {
int alreadyConsumed = consumedCount.getOrDefault( fuzz, 0 ); int alreadyConsumed = consumedCount.getOrDefault( fuzz, 0 );
if( fuzz.getStackSize() - alreadyConsumed <= 0 ) if( fuzz.getStackSize() - alreadyConsumed <= 0 )
@@ -537,8 +537,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
fuzz = fuzz.copy(); fuzz = fuzz.copy();
fuzz.setStackSize( 1 ); // We're iterating over non condensed inputs which means there's 1 of each needed fuzz.setStackSize( 1 ); // We're iterating over non condensed inputs which means there's 1 of each needed
final IAEItemStack ais = this.inventory.extractItems( fuzz, Actionable.SIMULATE, final IAEItemStack ais = this.inventory.extractItems( fuzz, Actionable.SIMULATE, this.machineSrc );
this.machineSrc );
if( ais != null && ais.getStackSize() > 0 ) if( ais != null && ais.getStackSize() > 0 )
{ {
@@ -565,11 +564,11 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{ {
// When no substitutions can occur, we can simply check that all items are accounted since // When no substitutions can occur, we can simply check that all items are accounted since
// each type of item should only occur once // each type of item should only occur once
for ( IAEItemStack g : condensedInputs ) for( IAEItemStack g : condensedInputs )
{ {
boolean found = false; boolean found = false;
for ( IAEItemStack fuzz : this.inventory.getItemList().findFuzzy( g, FuzzyMode.IGNORE_ALL ) ) for( IAEItemStack fuzz : this.inventory.getItemList().findFuzzy( g, FuzzyMode.IGNORE_ALL ) )
{ {
fuzz = fuzz.copy(); fuzz = fuzz.copy();
fuzz.setStackSize( g.getStackSize() ); fuzz.setStackSize( g.getStackSize() );
@@ -675,8 +674,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{ {
this.somethingChanged = false; this.somethingChanged = false;
this.executeCrafting( eg, cc ); this.executeCrafting( eg, cc );
} } while ( this.somethingChanged && this.remainingOperations > 0 );
while( this.somethingChanged && this.remainingOperations > 0 );
} }
this.usedOps[2] = this.usedOps[1]; this.usedOps[2] = this.usedOps[1];
this.usedOps[1] = this.usedOps[0]; this.usedOps[1] = this.usedOps[0];
@@ -692,7 +690,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{ {
final Iterator<Entry<ICraftingPatternDetails, TaskProgress>> i = this.tasks.entrySet().iterator(); final Iterator<Entry<ICraftingPatternDetails, TaskProgress>> i = this.tasks.entrySet().iterator();
while( i.hasNext() ) while ( i.hasNext() )
{ {
final Entry<ICraftingPatternDetails, TaskProgress> e = i.next(); final Entry<ICraftingPatternDetails, TaskProgress> e = i.next();
@@ -708,12 +706,12 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{ {
InventoryCrafting ic = null; InventoryCrafting ic = null;
if (!visitedMediums.containsKey( details ) || visitedMediums.get( details ).isEmpty()) if( !visitedMediums.containsKey( details ) || visitedMediums.get( details ).isEmpty() )
{ {
visitedMediums.put( details, new ArrayDeque<>( cc.getMediums( details ).stream().filter( Objects::nonNull ).collect( Collectors.toList()) ) ); visitedMediums.put( details, new ArrayDeque<>( cc.getMediums( details ).stream().filter( Objects::nonNull ).collect( Collectors.toList() ) ) );
} }
while (!visitedMediums.get( details ).isEmpty()) while ( !visitedMediums.get( details ).isEmpty() )
{ {
ICraftingMedium m = visitedMediums.get( details ).poll(); ICraftingMedium m = visitedMediums.get( details ).poll();
@@ -773,52 +771,58 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{ {
itemList.addAll( this.inventory.getItemList().findFuzzy( stack, FuzzyMode.IGNORE_ALL ) ); itemList.addAll( this.inventory.getItemList().findFuzzy( stack, FuzzyMode.IGNORE_ALL ) );
} }
} else { }
itemList = new ArrayList<>(1); else
{
itemList = new ArrayList<>( 1 );
final IAEItemStack item = this.inventory.getItemList() final IAEItemStack item = this.inventory.getItemList().findPrecise( input[x] );
.findPrecise(input[x]);
if (item != null) { if( item != null )
itemList.add(item); {
itemList.add( item );
} }
} }
for (IAEItemStack fuzz : itemList) { for( IAEItemStack fuzz : itemList )
{
fuzz = fuzz.copy(); fuzz = fuzz.copy();
fuzz.setStackSize(input[x].getStackSize()); fuzz.setStackSize( input[x].getStackSize() );
if (details.isValidItemForSlot(x, fuzz.createItemStack(), if( details.isValidItemForSlot( x, fuzz.createItemStack(), this.getWorld() ) )
this.getWorld())) { {
final IAEItemStack ais = this.inventory.extractItems(fuzz, final IAEItemStack ais = this.inventory.extractItems( fuzz, Actionable.MODULATE, this.machineSrc );
Actionable.MODULATE, this.machineSrc); final ItemStack is = ais == null ? ItemStack.EMPTY : ais.createItemStack();
final ItemStack is = ais == null ? ItemStack.EMPTY
: ais.createItemStack();
if (!is.isEmpty()) { if( !is.isEmpty() )
this.postChange(AEItemStack.fromItemStack(is), this.machineSrc); {
ic.setInventorySlotContents(x, is); this.postChange( AEItemStack.fromItemStack( is ), this.machineSrc );
ic.setInventorySlotContents( x, is );
found = true; found = true;
break; break;
} }
} }
} }
} else { }
final IAEItemStack ais = this.inventory.extractItems(input[x].copy(), else
Actionable.MODULATE, this.machineSrc); {
final IAEItemStack ais = this.inventory.extractItems( input[x].copy(), Actionable.MODULATE, this.machineSrc );
final ItemStack is = ais == null ? ItemStack.EMPTY : ais.createItemStack(); final ItemStack is = ais == null ? ItemStack.EMPTY : ais.createItemStack();
if (!is.isEmpty()) { if( !is.isEmpty() )
this.postChange(input[x], this.machineSrc); {
ic.setInventorySlotContents(x, is); this.postChange( input[x], this.machineSrc );
if (is.getCount() == input[x].getStackSize()) { ic.setInventorySlotContents( x, is );
if( is.getCount() == input[x].getStackSize() )
{
found = true; found = true;
continue; continue;
} }
} }
} }
if (!found) { if( !found )
{
break; break;
} }
} }
@@ -902,7 +906,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
private void storeItems() private void storeItems()
{ {
Preconditions.checkState(isComplete, "CPU should be complete to prevent re-insertion when dumping items"); Preconditions.checkState( isComplete, "CPU should be complete to prevent re-insertion when dumping items" );
final IGrid g = this.getGrid(); final IGrid g = this.getGrid();
if( g == null ) if( g == null )
@@ -1016,8 +1020,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
public boolean isBusy() public boolean isBusy()
{ {
this.tasks.entrySet().removeIf( this.tasks.entrySet().removeIf( taskProgressEntry -> taskProgressEntry.getValue().value <= 0 );
taskProgressEntry -> taskProgressEntry.getValue().value <= 0 );
if( !this.waitingFor.isEmpty() || !this.tasks.isEmpty() ) if( !this.waitingFor.isEmpty() || !this.tasks.isEmpty() )
{ {
@@ -1075,8 +1078,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
final int hash = System.identityHashCode( this ); final int hash = System.identityHashCode( this );
final int hmm = this.finalOutput == null ? 0 : this.finalOutput.hashCode(); final int hmm = this.finalOutput == null ? 0 : this.finalOutput.hashCode();
return Long.toString( now, Character.MAX_RADIX ) + '-' + Integer.toString( hash, Character.MAX_RADIX ) + '-' + Integer.toString( hmm, return Long.toString( now, Character.MAX_RADIX ) + '-' + Integer.toString( hash, Character.MAX_RADIX ) + '-' + Integer.toString( hmm, Character.MAX_RADIX );
Character.MAX_RADIX );
} }
private NBTTagCompound generateLinkData( final String craftingID, final boolean standalone, final boolean req ) private NBTTagCompound generateLinkData( final String craftingID, final boolean standalone, final boolean req )
@@ -1103,7 +1105,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
public void getListOfItem( final IItemList<IAEItemStack> list, final CraftingItemList whichList ) public void getListOfItem( final IItemList<IAEItemStack> list, final CraftingItemList whichList )
{ {
switch( whichList ) switch ( whichList )
{ {
case ACTIVE: case ACTIVE:
for( final IAEItemStack ais : this.waitingFor ) for( final IAEItemStack ais : this.waitingFor )
@@ -1174,7 +1176,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{ {
IAEItemStack is; IAEItemStack is;
switch( storage2 ) switch ( storage2 )
{ {
case STORAGE: case STORAGE:
is = this.inventory.getItemList().findPrecise( what ); is = this.inventory.getItemList().findPrecise( what );