undo partially pattern cache rebuild optimization

enabled pattern substitution now can use substitute patterned items
This commit is contained in:
PrototypeTrousers
2022-03-03 22:24:41 -03:00
parent 71ffcfb839
commit 49b3dc8b60
9 changed files with 293 additions and 293 deletions
+15 -5
View File
@@ -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<IAEItemStack> crafting = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
private final IItemList<IAEItemStack> missing = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
private final IItemList<IAEItemStack> usedWhileBuilding = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
private final IItemList<IAEItemStack> uniques = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
private final HashMap<String, TwoIntegers> 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<IAEItemStack> 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();
@@ -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<IAEItemStack> inventoryList = inv.getItemList();
final List<IAEItemStack> thingsUsed = new ArrayList<>();
this.what.setStackSize( l );
if( this.getSlot() >= 0 && this.parent != null && this.parent.details.isCraftable() )
{
final Collection<IAEItemStack> itemList;
final IItemList<IAEItemStack> inventoryList = inv.getItemList();
Collection<IAEItemStack> 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<IAEItemStack> 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 )
@@ -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<CraftingTreeNode> nodes = new Object2LongArrayMap<>();
private final int depth;
boolean possible = true;
private World world;
private long crafts = 0;
private boolean containerItems;
private IItemList<IAEItemStack> 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<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 );
}
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<IAEItemStack> 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<CraftingTreeNode, Long> 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<CraftingTreeNode, Long> 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<CraftingTreeNode, Long> 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 )
@@ -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<IAEItemStack>
{
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;