From 49b3dc8b602a7d0df17a9c460bb32f5a0df3d47f Mon Sep 17 00:00:00 2001 From: PrototypeTrousers Date: Thu, 3 Mar 2022 22:24:41 -0300 Subject: [PATCH] undo partially pattern cache rebuild optimization enabled pattern substitution now can use substitute patterned items --- gradle.properties | 2 +- .../java/appeng/crafting/CraftingJob.java | 20 +- .../appeng/crafting/CraftingTreeNode.java | 88 +---- .../appeng/crafting/CraftingTreeProcess.java | 321 +++++++++++------- .../appeng/crafting/MECraftingInventory.java | 5 +- .../java/appeng/helpers/DualityInterface.java | 9 +- .../appeng/me/cache/CraftingGridCache.java | 21 -- .../appeng/me/cache/GridStorageCache.java | 16 +- .../implementations/CraftingCPUCluster.java | 104 +++--- 9 files changed, 293 insertions(+), 293 deletions(-) diff --git a/gradle.properties b/gradle.properties index d883906be..aa29944c6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ aebuild=7 aegroup=appeng aebasename=appliedenergistics2 extended=extended_life -extendedversion=v50g +extendedversion=v50h ######################################################### # Versions # ######################################################### diff --git a/src/main/java/appeng/crafting/CraftingJob.java b/src/main/java/appeng/crafting/CraftingJob.java index 1fc555aef..de236bae9 100644 --- a/src/main/java/appeng/crafting/CraftingJob.java +++ b/src/main/java/appeng/crafting/CraftingJob.java @@ -22,6 +22,7 @@ package appeng.crafting; import java.util.HashMap; import java.util.concurrent.TimeUnit; +import appeng.me.cache.GridStorageCache; import com.google.common.base.Stopwatch; import net.minecraft.entity.player.EntityPlayer; @@ -58,6 +59,7 @@ public class CraftingJob implements Runnable, ICraftingJob private final IItemList crafting = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); private final IItemList missing = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); private final IItemList usedWhileBuilding = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); + private final IItemList uniques = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); private final HashMap opsAndMultiplier = new HashMap<>(); private final Object monitor = new Object(); @@ -87,9 +89,12 @@ public class CraftingJob implements Runnable, ICraftingJob this.actionSrc = actionSrc; this.callback = callback; + final ICraftingGrid cc = grid.getCache( ICraftingGrid.class ); - final IStorageGrid sg = grid.getCache( IStorageGrid.class ); - this.original = new MECraftingInventory( sg.getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ), actionSrc, false, false, false ); + final GridStorageCache sg = grid.getCache( IStorageGrid.class ); + Stopwatch stopwatch = Stopwatch.createStarted(); + this.original = new MECraftingInventory( sg.getExtractableList() ); + AELog.info( "CraftingJob: original inventory took " + stopwatch.elapsed( TimeUnit.MICROSECONDS ) + "us" ); this.setTree( this.getCraftingTree( cc, what ) ); this.availableCheck = null; @@ -110,9 +115,9 @@ public class CraftingJob implements Runnable, ICraftingJob return usedWhileBuilding; } - public IAEItemStack getOriginal( IAEItemStack request ) + public IItemList getUniques() { - return original.getItemList().findPrecise( request ); + return uniques; } IAEItemStack checkUse( final IAEItemStack available ) @@ -120,6 +125,11 @@ public class CraftingJob implements Runnable, ICraftingJob 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 ) { @@ -267,7 +277,7 @@ public class CraftingJob implements Runnable, ICraftingJob } } } - + if( Thread.interrupted() ) { throw new InterruptedException(); diff --git a/src/main/java/appeng/crafting/CraftingTreeNode.java b/src/main/java/appeng/crafting/CraftingTreeNode.java index adbdf36f8..4cbc0433f 100644 --- a/src/main/java/appeng/crafting/CraftingTreeNode.java +++ b/src/main/java/appeng/crafting/CraftingTreeNode.java @@ -23,14 +23,13 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import appeng.api.config.FuzzyMode; import com.google.common.collect.Lists; - import net.minecraft.util.text.TextComponentString; 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.IActionSource; @@ -81,100 +80,32 @@ public class CraftingTreeNode 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( details ) ) + if( this.parent == null || this.parent.notRecursive() ) { 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( details ) ) - { - 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( details ); - } - IAEItemStack request( final MECraftingInventory inv, long l, final IActionSource src ) throws CraftBranchFailure, InterruptedException { this.job.handlePausing(); + + final IItemList inventoryList = inv.getItemList(); final List thingsUsed = new ArrayList<>(); this.what.setStackSize( l ); - if( this.getSlot() >= 0 && this.parent != null && this.parent.details.isCraftable() ) { - final Collection itemList; - final IItemList inventoryList = inv.getItemList(); + Collection itemList = new ArrayList<>(); - if( this.parent.details.canSubstitute() ) + if( this.parent.getContainerItems() != null && !this.parent.getContainerItems().findFuzzy( this.what, FuzzyMode.IGNORE_ALL ).isEmpty() ) { - final List substitutes = this.parent.details.getSubstituteInputs( this.slot ); - itemList = new ArrayList<>( substitutes.size() ); - - for( IAEItemStack stack : substitutes ) - { - itemList.addAll( inventoryList.findFuzzy( stack, FuzzyMode.IGNORE_ALL ) ); - } + itemList = inventoryList.findFuzzy( this.what, FuzzyMode.IGNORE_ALL ); } else { - itemList = Lists.newArrayList(); - final IAEItemStack item = inventoryList.findPrecise( this.what ); - if( item != null ) { itemList.add( item ); @@ -345,6 +276,11 @@ public class CraftingTreeNode throw new CraftBranchFailure( this.what, l ); } + boolean notRecursive() + { + return this.parent == null || job.getUniques().findPrecise( this.what ) == null; + } + void dive( final CraftingJob job ) { if( this.missing > 0 ) diff --git a/src/main/java/appeng/crafting/CraftingTreeProcess.java b/src/main/java/appeng/crafting/CraftingTreeProcess.java index 1b72eb3e8..e5db2e170 100644 --- a/src/main/java/appeng/crafting/CraftingTreeProcess.java +++ b/src/main/java/appeng/crafting/CraftingTreeProcess.java @@ -19,17 +19,14 @@ package appeng.crafting; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; import java.util.Map.Entry; +import appeng.api.config.FuzzyMode; +import appeng.util.item.AEItemStack; +import com.google.common.collect.ImmutableCollection; import it.unimi.dsi.fastutil.objects.Object2LongArrayMap; -import net.minecraft.inventory.InventoryCrafting; import net.minecraft.item.ItemStack; import net.minecraft.world.World; -import net.minecraft.world.WorldServer; -import net.minecraftforge.fml.common.FMLCommonHandler; import appeng.api.AEApi; import appeng.api.config.Actionable; @@ -39,26 +36,21 @@ import appeng.api.networking.security.IActionSource; import appeng.api.storage.channels.IItemStorageChannel; 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 org.apache.commons.lang3.tuple.Pair; public class CraftingTreeProcess { - private final CraftingTreeNode parent; final ICraftingPatternDetails details; private final CraftingJob job; private final Object2LongArrayMap nodes = new Object2LongArrayMap<>(); private final int depth; boolean possible = true; - private World world; private long crafts = 0; - private boolean containerItems; + private IItemList containerItems; private boolean limitQty; - private boolean fullSimulation; private long bytes = 0; public CraftingTreeProcess( final ICraftingGrid cc, final CraftingJob job, final ICraftingPatternDetails details, final CraftingTreeNode craftingTreeNode, final int depth ) @@ -69,143 +61,240 @@ public class CraftingTreeProcess this.depth = depth; final World world = job.getWorld(); - if( details.isCraftable() ) + final IAEItemStack[] list = details.getInputs(); + + for( final IAEItemStack part : details.getCondensedInputs() ) { - final IAEItemStack[] list = details.getInputs(); - - for( final IAEItemStack part : details.getCondensedInputs() ) + if( part.getItem().hasContainerItem( part.getDefinition() ) ) { - boolean isAnInput = false; - for( final IAEItemStack a : details.getCondensedOutputs() ) + if( containerItems == null ) { - if( a != null && a.equals( part ) ) - { - isAnInput = true; - break; - } - } - - if( isAnInput ) - { - this.limitQty = true; - } - - if( part.getItem().hasContainerItem( part.getDefinition() ) ) - { - this.limitQty = this.containerItems = true; - break; + containerItems = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); } + containerItems.add( part ); + this.limitQty = true; + //break; } - - if( this.containerItems ) + } + // this is minor different then below, this slot uses the pattern, but kinda fudges it. + for( IAEItemStack part : details.getCondensedInputs() ) + { + if( part == null ) { - for( int x = 0; x < list.length; x++ ) - { - final IAEItemStack part = list[x]; - if( part != null ) - { - job.getUsedWhileBuilding().addStorage( part ); - IAEItemStack used = job.getUsedWhileBuilding().findPrecise( part ); - if( job.getOriginal( part ) != null && used.getStackSize() <= job.getOriginal( part ).getStackSize() ) - { - this.nodes.put( new CraftingTreeNode( cc, job, part.copy(), this, x, depth + 1, true ), part.getStackSize() ); - } - else - { - this.nodes.put( new CraftingTreeNode( cc, job, part.copy(), this, x, depth + 1 ), part.getStackSize() ); - } - } - } + continue; } - else + for( int x = 0; x < list.length; x++ ) { - // this is minor different then below, this slot uses the pattern, but kinda fudges it. - for( final IAEItemStack part : details.getCondensedInputs() ) + final IAEItemStack comparePart = list[x]; + if( part.equals( comparePart ) ) { - for( int x = 0; x < list.length; x++ ) + boolean isPartContainer = false; + if( containerItems != null && !containerItems.findFuzzy( list[x], FuzzyMode.IGNORE_ALL ).isEmpty() ) { - final IAEItemStack comparePart = list[x]; - if( part != null && part.equals( comparePart ) ) + 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 ) { - job.getUsedWhileBuilding().addStorage( part ); - IAEItemStack used = job.getUsedWhileBuilding().findPrecise( part ); - if( job.getOriginal( part ) != null && used.getStackSize() <= job.getOriginal( part ).getStackSize() ) + used = job.getUsedWhileBuilding().findPrecise( part ); + remaining = found.getStackSize(); + if( used != null ) { - this.nodes.put( new CraftingTreeNode( cc, job, part.copy(), this, x, depth + 1, true ), part.getStackSize() ); + 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 { - // use the first slot... - this.nodes.put( new CraftingTreeNode( cc, job, part.copy(), this, x, depth + 1 ), part.getStackSize() ); + 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; } - 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 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 ); + } + if( !isPartContainer || wantedSize == 0 ) + { + break; } } } } - else - { - for( final IAEItemStack part : details.getCondensedInputs() ) - { - boolean isAnInput = false; - for( final IAEItemStack a : details.getCondensedOutputs() ) - { - if( a != null && a.equals( part ) ) - { - isAnInput = true; - break; - } - } - if( isAnInput ) + for( final IAEItemStack part : details.getCondensedOutputs() ) + { + for( final IAEItemStack o : details.getCondensedInputs() ) + { + if( part.equals( o ) ) { this.limitQty = true; + break; } } - - for( final IAEItemStack part : details.getCondensedInputs() ) - { - this.nodes.put( new CraftingTreeNode( cc, job, part.copy(), this, -1, depth + 1 ), part.getStackSize() ); - } } } - boolean notRecursive( final ICraftingPatternDetails details ) + IItemList getContainerItems() { - return this.parent == null || this.parent.notRecursive( details ); + return this.containerItems; + } + + boolean notRecursive() + { + return this.parent == null || this.parent.notRecursive(); } long getTimes( final long remaining, final long stackSize ) { - if( this.limitQty || this.fullSimulation ) + if( this.limitQty ) { return 1; } return ( remaining / stackSize ) + ( remaining % stackSize != 0 ? 1 : 0 ); } - void request( final MECraftingInventory inv, final long i, final IActionSource src ) throws CraftBranchFailure, InterruptedException + void request( final MECraftingInventory inv, final long amountOfTimes, final IActionSource src ) throws CraftBranchFailure, InterruptedException { this.job.handlePausing(); - if( this.fullSimulation ) + + // request and remove inputs... + for( final Entry entry : this.nodes.object2LongEntrySet() ) { - final InventoryCrafting ic = new InventoryCrafting( new ContainerNull(), 3, 3 ); + final IAEItemStack craftableStack = entry.getKey().getStack( entry.getValue() ); + final IAEItemStack stack = entry.getKey().request( inv, craftableStack.getStackSize() * amountOfTimes, src ); - for( final Entry entry : this.nodes.object2LongEntrySet() ) + if( containerItems != null && !this.containerItems.findFuzzy( stack, FuzzyMode.IGNORE_ALL ).isEmpty() ) { - final IAEItemStack item = entry.getKey().getStack( entry.getValue() ); - final IAEItemStack stack = entry.getKey().request( inv, item.getStackSize(), src ); - - ic.setInventorySlotContents( entry.getKey().getSlot(), stack.createItemStack() ); - } - - for( int x = 0; x < ic.getSizeInventory(); x++ ) - { - ItemStack is = ic.getStackInSlot( x ); - is = Platform.getContainerItem( is ); - - final IAEItemStack o = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( is ); + final ItemStack is = Platform.getContainerItem( stack.createItemStack() ); + final IAEItemStack o = AEItemStack.fromItemStack( is ); if( o != null ) { this.bytes++; @@ -213,26 +302,6 @@ public class CraftingTreeProcess } } } - else - { - // request and remove inputs... - for( final Entry entry : this.nodes.object2LongEntrySet() ) - { - final IAEItemStack item = entry.getKey().getStack( entry.getValue() ); - final IAEItemStack stack = entry.getKey().request( inv, item.getStackSize() * i, src ); - - if( this.containerItems ) - { - final ItemStack is = Platform.getContainerItem( stack.createItemStack() ); - final IAEItemStack o = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( is ); - if( o != null ) - { - this.bytes++; - inv.injectItems( o, Actionable.MODULATE, src ); - } - } - } - } // assume its possible. @@ -240,10 +309,10 @@ public class CraftingTreeProcess for( final IAEItemStack out : this.details.getCondensedOutputs() ) { final IAEItemStack o = out.copy(); - o.setStackSize( o.getStackSize() * i ); + o.setStackSize( o.getStackSize() * amountOfTimes ); inv.injectItems( o, Actionable.MODULATE, src ); } - this.crafts += i; + this.crafts += amountOfTimes; } void dive( final CraftingJob job ) diff --git a/src/main/java/appeng/crafting/MECraftingInventory.java b/src/main/java/appeng/crafting/MECraftingInventory.java index 3814bb702..379937498 100644 --- a/src/main/java/appeng/crafting/MECraftingInventory.java +++ b/src/main/java/appeng/crafting/MECraftingInventory.java @@ -28,7 +28,6 @@ import appeng.api.storage.IStorageChannel; import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IItemList; -import appeng.me.helpers.PlayerSource; import appeng.util.inv.ItemListIgnoreCrafting; import net.minecraft.util.text.TextComponentString; @@ -312,11 +311,11 @@ public class MECraftingInventory implements IMEInventory { 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 { - 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; diff --git a/src/main/java/appeng/helpers/DualityInterface.java b/src/main/java/appeng/helpers/DualityInterface.java index 224d463a8..8e9b7acb1 100644 --- a/src/main/java/appeng/helpers/DualityInterface.java +++ b/src/main/java/appeng/helpers/DualityInterface.java @@ -464,14 +464,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn } try { - if( removed ) - { - this.gridProxy.getGrid().postEvent( new MENetworkCraftingPatternChange( this, this.gridProxy.getNode() ) ); - } - else if( newPattern ) - { - this.provideCrafting( (ICraftingProviderHelper) this.gridProxy.getCrafting() ); - } + this.gridProxy.getGrid().postEvent( new MENetworkCraftingPatternChange( this, this.gridProxy.getNode() ) ); } catch( GridAccessException e ) { diff --git a/src/main/java/appeng/me/cache/CraftingGridCache.java b/src/main/java/appeng/me/cache/CraftingGridCache.java index b02f97001..de7374bd9 100644 --- a/src/main/java/appeng/me/cache/CraftingGridCache.java +++ b/src/main/java/appeng/me/cache/CraftingGridCache.java @@ -411,27 +411,6 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper { details.add( medium ); } - - if( !updatePatterns ) - { - List newCraftables = new ArrayList<>(); - - ObjectSet b = new ObjectRBTreeSet<>( COMPARATOR ); - ImmutableList a = this.craftableItems.get( api.getCondensedOutputs()[0] ); - if( a != null ) - { - b.addAll( this.craftableItems.get( api.getOutputs()[0] ) ); - } - b.add( api ); - - for( IAEItemStack stack : api.getCondensedOutputs() ) - { - IAEItemStack i = stack.copy().reset().setCraftable( true ); - this.craftableItems.put( i, ImmutableList.copyOf( b ) ); - newCraftables.add( i ); - } - this.storageGrid.postCraftablesChanges( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ), newCraftables, new BaseActionSource() ); - } } @Override diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index 3014a3ef0..a7ebe9b4f 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -26,6 +26,8 @@ import java.util.IdentityHashMap; import java.util.List; import java.util.Map; +import appeng.api.storage.channels.IItemStorageChannel; +import appeng.crafting.MECraftingInventory; import com.google.common.collect.HashMultimap; import com.google.common.collect.SetMultimap; @@ -68,6 +70,7 @@ public class GridStorageCache implements IStorageGrid private final HashMap watchers = new HashMap<>(); private final Map, NetworkInventoryHandler> storageNetworks; private final Map, NetworkMonitor> storageMonitors; + private MECraftingInventory localCache = null; private int localDepth; public GridStorageCache( final IGrid g ) @@ -82,6 +85,7 @@ public class GridStorageCache implements IStorageGrid @Override public void onUpdateTick() { + this.localCache = null; this.storageMonitors.forEach( ( channel, monitor ) -> monitor.onTick() ); } @@ -169,6 +173,15 @@ public class GridStorageCache implements IStorageGrid return (IMEMonitor) this.storageMonitors.get( channel ); } + public MECraftingInventory getExtractableList() + { + if( localCache == null ) + { + localCache = new MECraftingInventory( getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ), new BaseActionSource(), false, false, false ); + } + return localCache; + } + private CellChangeTracker addCellProvider( final ICellProvider cc, final CellChangeTracker tracker ) { if( this.inactiveCellProviders.contains( cc ) ) @@ -198,8 +211,7 @@ public class GridStorageCache implements IStorageGrid 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 h : cc.getCellArray( channel ) ) { tracker.postChanges( channel, -1, h, actionSrc ); diff --git a/src/main/java/appeng/me/cluster/implementations/CraftingCPUCluster.java b/src/main/java/appeng/me/cluster/implementations/CraftingCPUCluster.java index d2429aaad..fa7ccb23b 100644 --- a/src/main/java/appeng/me/cluster/implementations/CraftingCPUCluster.java +++ b/src/main/java/appeng/me/cluster/implementations/CraftingCPUCluster.java @@ -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 // items during storeItems - if (input == null || isComplete) { + if( input == null || isComplete ) + { return input; } @@ -375,7 +376,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU { final ImmutableList single = ImmutableList.of( diff.copy() ); - while( i.hasNext() ) + while ( i.hasNext() ) { final Entry, Object> o = i.next(); final IMEMonitorHandlerReceiver receiver = o.getKey(); @@ -495,15 +496,14 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU return null; } - private boolean canCraft(final ICraftingPatternDetails details, final IAEItemStack[] condensedInputs) + private boolean canCraft( final ICraftingPatternDetails details, final IAEItemStack[] condensedInputs ) { if( !details.isCraftable() ) { // Processing patterns are relatively easy - for ( IAEItemStack input : condensedInputs ) + for( IAEItemStack input : condensedInputs ) { - final IAEItemStack ais = this.inventory.extractItems( input.copy(), Actionable.SIMULATE, - this.machineSrc ); + final IAEItemStack ais = this.inventory.extractItems( input.copy(), Actionable.SIMULATE, this.machineSrc ); 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 IAEItemStack[] inputs = details.getInputs(); Map consumedCount = new HashMap<>(); - for ( int i = 0; i < inputs.length; i++ ) + for( int i = 0; i < inputs.length; i++ ) { List substitutes = details.getSubstituteInputs( i ); if( substitutes.isEmpty() ) @@ -525,9 +525,9 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU } 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 ); if( fuzz.getStackSize() - alreadyConsumed <= 0 ) @@ -537,8 +537,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU fuzz = fuzz.copy(); 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, - this.machineSrc ); + final IAEItemStack ais = this.inventory.extractItems( fuzz, Actionable.SIMULATE, this.machineSrc ); 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 // each type of item should only occur once - for ( IAEItemStack g : condensedInputs ) + for( IAEItemStack g : condensedInputs ) { 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.setStackSize( g.getStackSize() ); @@ -675,8 +674,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU { this.somethingChanged = false; this.executeCrafting( eg, cc ); - } - while( this.somethingChanged && this.remainingOperations > 0 ); + } while ( this.somethingChanged && this.remainingOperations > 0 ); } this.usedOps[2] = this.usedOps[1]; this.usedOps[1] = this.usedOps[0]; @@ -692,7 +690,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU { final Iterator> i = this.tasks.entrySet().iterator(); - while( i.hasNext() ) + while ( i.hasNext() ) { final Entry e = i.next(); @@ -708,12 +706,12 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU { 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(); @@ -773,52 +771,58 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU { 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() - .findPrecise(input[x]); + final IAEItemStack item = this.inventory.getItemList().findPrecise( input[x] ); - if (item != null) { - itemList.add(item); + if( item != null ) + { + itemList.add( item ); } } - for (IAEItemStack fuzz : itemList) { + for( IAEItemStack fuzz : itemList ) + { fuzz = fuzz.copy(); - fuzz.setStackSize(input[x].getStackSize()); + fuzz.setStackSize( input[x].getStackSize() ); - if (details.isValidItemForSlot(x, fuzz.createItemStack(), - this.getWorld())) { - final IAEItemStack ais = this.inventory.extractItems(fuzz, - Actionable.MODULATE, this.machineSrc); - final ItemStack is = ais == null ? ItemStack.EMPTY - : ais.createItemStack(); + if( details.isValidItemForSlot( x, fuzz.createItemStack(), this.getWorld() ) ) + { + final IAEItemStack ais = this.inventory.extractItems( fuzz, Actionable.MODULATE, this.machineSrc ); + final ItemStack is = ais == null ? ItemStack.EMPTY : ais.createItemStack(); - if (!is.isEmpty()) { - this.postChange(AEItemStack.fromItemStack(is), this.machineSrc); - ic.setInventorySlotContents(x, is); + if( !is.isEmpty() ) + { + this.postChange( AEItemStack.fromItemStack( is ), this.machineSrc ); + ic.setInventorySlotContents( x, is ); found = true; break; } } } - } else { - final IAEItemStack ais = this.inventory.extractItems(input[x].copy(), - Actionable.MODULATE, this.machineSrc); + } + else + { + final IAEItemStack ais = this.inventory.extractItems( input[x].copy(), Actionable.MODULATE, this.machineSrc ); final ItemStack is = ais == null ? ItemStack.EMPTY : ais.createItemStack(); - if (!is.isEmpty()) { - this.postChange(input[x], this.machineSrc); - ic.setInventorySlotContents(x, is); - if (is.getCount() == input[x].getStackSize()) { + if( !is.isEmpty() ) + { + this.postChange( input[x], this.machineSrc ); + ic.setInventorySlotContents( x, is ); + if( is.getCount() == input[x].getStackSize() ) + { found = true; continue; } } } - if (!found) { + if( !found ) + { break; } } @@ -902,7 +906,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU 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(); if( g == null ) @@ -1016,8 +1020,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU public boolean isBusy() { - this.tasks.entrySet().removeIf( - taskProgressEntry -> taskProgressEntry.getValue().value <= 0 ); + this.tasks.entrySet().removeIf( taskProgressEntry -> taskProgressEntry.getValue().value <= 0 ); 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 hmm = this.finalOutput == null ? 0 : this.finalOutput.hashCode(); - return Long.toString( now, Character.MAX_RADIX ) + '-' + Integer.toString( hash, Character.MAX_RADIX ) + '-' + Integer.toString( hmm, - Character.MAX_RADIX ); + return Long.toString( now, Character.MAX_RADIX ) + '-' + Integer.toString( hash, Character.MAX_RADIX ) + '-' + Integer.toString( hmm, Character.MAX_RADIX ); } 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 list, final CraftingItemList whichList ) { - switch( whichList ) + switch ( whichList ) { case ACTIVE: for( final IAEItemStack ais : this.waitingFor ) @@ -1174,7 +1176,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU { IAEItemStack is; - switch( storage2 ) + switch ( storage2 ) { case STORAGE: is = this.inventory.getItemList().findPrecise( what );