small optimization to crafting tree

This commit is contained in:
PrototypeTrousers
2022-02-27 23:04:29 -03:00
parent 50fd83e96b
commit 285fc6314c
6 changed files with 43 additions and 67 deletions
@@ -50,7 +50,7 @@ import appeng.hooks.TickHandler;
public class CraftingJob implements Runnable, ICraftingJob public class CraftingJob implements Runnable, ICraftingJob
{ {
private static final String LOG_CRAFTING_JOB = "CraftingJob (%s) issued by %s requesting [%s] using %s bytes took %s ms"; private static final String LOG_CRAFTING_JOB = "CraftingJob (%s) issued by %s requesting [%s] using %s bytes took %s us";
private static final String LOG_MACHINE_SOURCE_DETAILS = "Machine[object=%s, %s]"; private static final String LOG_MACHINE_SOURCE_DETAILS = "Machine[object=%s, %s]";
private final MECraftingInventory original; private final MECraftingInventory original;
@@ -86,8 +86,7 @@ public class CraftingJob implements Runnable, ICraftingJob
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 IStorageGrid sg = grid.getCache( IStorageGrid.class );
this.original = new MECraftingInventory( sg this.original = new MECraftingInventory( sg.getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ), actionSrc, false, false, false );
.getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ), actionSrc, false, false, false );
this.setTree( this.getCraftingTree( cc, what ) ); this.setTree( this.getCraftingTree( cc, what ) );
this.availableCheck = null; this.availableCheck = null;
@@ -263,7 +262,7 @@ public class CraftingJob implements Runnable, ICraftingJob
this.availableCheck = null; this.availableCheck = null;
synchronized( this.monitor ) synchronized ( this.monitor )
{ {
this.running = false; this.running = false;
this.done = true; this.done = true;
@@ -311,7 +310,7 @@ public class CraftingJob implements Runnable, ICraftingJob
/** /**
* @return true if this needs more simulation * @return true if this needs more simulation
*/ */
public boolean simulateFor(final int milli) public boolean simulateFor( final int milli )
{ {
this.time = milli; this.time = milli;
@@ -353,7 +352,7 @@ public class CraftingJob implements Runnable, ICraftingJob
if( AELog.isCraftingLogEnabled() ) if( AELog.isCraftingLogEnabled() )
{ {
final String itemToOutput = this.output.toString(); final String itemToOutput = this.output.toString();
final long elapsedTime = timer.elapsed( TimeUnit.MILLISECONDS ); final long elapsedTime = timer.elapsed( TimeUnit.MICROSECONDS );
final String actionSource; final String actionSource;
if( this.actionSrc.player().isPresent() ) if( this.actionSrc.player().isPresent() )
@@ -177,7 +177,7 @@ public class CraftingTreeNode
for( IAEItemStack fuzz : itemList ) for( IAEItemStack fuzz : itemList )
{ {
if( this.parent.details.isValidItemForSlot( this.getSlot(), fuzz.copy().setStackSize( 1 ).createItemStack(), this.world ) ) if( this.parent.details.isValidItemForSlot( this.getSlot(), fuzz.copy().getCachedItemStack( 1 ), this.world ) )
{ {
fuzz = fuzz.copy(); fuzz = fuzz.copy();
fuzz.setStackSize( l ); fuzz.setStackSize( l );
@@ -19,10 +19,12 @@
package appeng.crafting; package appeng.crafting;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import it.unimi.dsi.fastutil.objects.Object2LongArrayMap;
import net.minecraft.inventory.InventoryCrafting; import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.world.World; import net.minecraft.world.World;
@@ -40,6 +42,7 @@ import appeng.api.storage.data.IItemList;
import appeng.container.ContainerNull; import appeng.container.ContainerNull;
import appeng.me.cluster.implementations.CraftingCPUCluster; import appeng.me.cluster.implementations.CraftingCPUCluster;
import appeng.util.Platform; import appeng.util.Platform;
import org.apache.commons.lang3.tuple.Pair;
public class CraftingTreeProcess public class CraftingTreeProcess
@@ -48,7 +51,7 @@ public class CraftingTreeProcess
private final CraftingTreeNode parent; private final CraftingTreeNode parent;
final ICraftingPatternDetails details; final ICraftingPatternDetails details;
private final CraftingJob job; private final CraftingJob job;
private final Map<CraftingTreeNode, Long> nodes = new HashMap<>(); private final Object2LongArrayMap<CraftingTreeNode> nodes = new Object2LongArrayMap<>();
private final int depth; private final int depth;
boolean possible = true; boolean possible = true;
private World world; private World world;
@@ -70,32 +73,15 @@ public class CraftingTreeProcess
{ {
final IAEItemStack[] list = details.getInputs(); final IAEItemStack[] list = details.getInputs();
final InventoryCrafting ic = new InventoryCrafting( new ContainerNull(), 3, 3 );
final IAEItemStack[] is = details.getInputs();
for( int x = 0; x < ic.getSizeInventory(); x++ )
{
ic.setInventorySlotContents( x, is[x] == null ? ItemStack.EMPTY : is[x].createItemStack() );
}
for( int x = 0; x < ic.getSizeInventory(); x++ )
{
final ItemStack g = ic.getStackInSlot( x );
if( !g.isEmpty() && g.getCount() > 1 )
{
this.fullSimulation = true;
}
}
for( final IAEItemStack part : details.getCondensedInputs() ) for( final IAEItemStack part : details.getCondensedInputs() )
{ {
final ItemStack g = part.createItemStack();
boolean isAnInput = false; boolean isAnInput = false;
for( final IAEItemStack a : details.getCondensedOutputs() ) for( final IAEItemStack a : details.getCondensedOutputs() )
{ {
if( !g.isEmpty() && a != null && a.equals( g ) ) if( a != null && a.equals( part ) )
{ {
isAnInput = true; isAnInput = true;
break;
} }
} }
@@ -104,15 +90,13 @@ public class CraftingTreeProcess
this.limitQty = true; this.limitQty = true;
} }
if( g.getItem().hasContainerItem( g ) ) if( part.getItem().hasContainerItem( part.getDefinition() ) )
{ {
this.limitQty = this.containerItems = true; this.limitQty = this.containerItems = true;
} }
} }
final boolean complicated = false; if( this.containerItems )
if( this.containerItems || complicated )
{ {
for( int x = 0; x < list.length; x++ ) for( int x = 0; x < list.length; x++ )
{ {
@@ -145,14 +129,13 @@ public class CraftingTreeProcess
{ {
for( final IAEItemStack part : details.getCondensedInputs() ) for( final IAEItemStack part : details.getCondensedInputs() )
{ {
final ItemStack g = part.createItemStack();
boolean isAnInput = false; boolean isAnInput = false;
for( final IAEItemStack a : details.getCondensedOutputs() ) for( final IAEItemStack a : details.getCondensedOutputs() )
{ {
if( !g.isEmpty() && a != null && a.equals( g ) ) if( a != null && a.equals( part ) )
{ {
isAnInput = true; isAnInput = true;
break;
} }
} }
@@ -190,7 +173,7 @@ public class CraftingTreeProcess
{ {
final InventoryCrafting ic = new InventoryCrafting( new ContainerNull(), 3, 3 ); final InventoryCrafting ic = new InventoryCrafting( new ContainerNull(), 3, 3 );
for( final Entry<CraftingTreeNode, Long> entry : this.nodes.entrySet() ) for( final Entry<CraftingTreeNode, Long> entry : this.nodes.object2LongEntrySet() )
{ {
final IAEItemStack item = entry.getKey().getStack( entry.getValue() ); final IAEItemStack item = entry.getKey().getStack( entry.getValue() );
final IAEItemStack stack = entry.getKey().request( inv, item.getStackSize(), src ); final IAEItemStack stack = entry.getKey().request( inv, item.getStackSize(), src );
@@ -214,7 +197,7 @@ public class CraftingTreeProcess
else else
{ {
// request and remove inputs... // request and remove inputs...
for( final Entry<CraftingTreeNode, Long> entry : this.nodes.entrySet() ) for( final Entry<CraftingTreeNode, Long> entry : this.nodes.object2LongEntrySet() )
{ {
final IAEItemStack item = entry.getKey().getStack( entry.getValue() ); final IAEItemStack item = entry.getKey().getStack( entry.getValue() );
final IAEItemStack stack = entry.getKey().request( inv, item.getStackSize() * i, src ); final IAEItemStack stack = entry.getKey().request( inv, item.getStackSize() * i, src );
@@ -247,9 +230,9 @@ public class CraftingTreeProcess
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 );
for( final CraftingTreeNode pro : this.nodes.keySet() ) for( final Entry<CraftingTreeNode, Long> entry : this.nodes.object2LongEntrySet() )
{ {
pro.dive( job ); entry.getKey().dive( job );
} }
job.addBytes( this.crafts * 8 + this.bytes ); job.addBytes( this.crafts * 8 + this.bytes );
@@ -286,9 +269,9 @@ public class CraftingTreeProcess
this.crafts = 0; this.crafts = 0;
this.bytes = 0; this.bytes = 0;
for( final CraftingTreeNode pro : this.nodes.keySet() ) for( final Entry<CraftingTreeNode, Long> entry : this.nodes.object2LongEntrySet() )
{ {
pro.setSimulate(); entry.getKey().setSimulate();
} }
} }
@@ -296,9 +279,9 @@ public class CraftingTreeProcess
{ {
craftingCPUCluster.addCrafting( this.details, this.crafts ); craftingCPUCluster.addCrafting( this.details, this.crafts );
for( final CraftingTreeNode pro : this.nodes.keySet() ) for( final Entry<CraftingTreeNode, Long> entry : this.nodes.object2LongEntrySet() )
{ {
pro.setJob( storage, craftingCPUCluster, src ); entry.getKey().setJob( storage, craftingCPUCluster, src );
} }
} }
@@ -311,9 +294,9 @@ public class CraftingTreeProcess
plan.addRequestable( i ); plan.addRequestable( i );
} }
for( final CraftingTreeNode pro : this.nodes.keySet() ) for( final Entry<CraftingTreeNode, Long> entry : this.nodes.object2LongEntrySet() )
{ {
pro.getPlan( plan ); entry.getKey().getPlan( plan );
} }
} }
} }
@@ -97,8 +97,7 @@ public class MECraftingInventory implements IMEInventory<IAEItemStack>
this.injectedCache = null; this.injectedCache = null;
} }
this.localCache = this.target this.localCache = this.target.getAvailableItems( new ItemListIgnoreCrafting<>( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList() ) );
.getAvailableItems( new ItemListIgnoreCrafting<>( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList() ) );
this.par = parent; this.par = parent;
} }
@@ -140,7 +139,14 @@ public class MECraftingInventory implements IMEInventory<IAEItemStack>
this.localCache = new ItemListIgnoreCrafting<>( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList() ); this.localCache = new ItemListIgnoreCrafting<>( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList() );
for( final IAEItemStack is : target.getStorageList() ) for( final IAEItemStack is : target.getStorageList() )
{ {
this.localCache.add( target.extractItems( is, Actionable.SIMULATE, src ) ); if( src.player().isPresent() )
{
this.localCache.add( target.extractItems( is, Actionable.SIMULATE, src ) );
}
else
{
this.localCache.add( is );
}
} }
this.par = null; this.par = null;
@@ -321,7 +327,10 @@ public class MECraftingInventory implements IMEInventory<IAEItemStack>
} }
} }
failed = true; failed = true;
if( !src.player().isPresent() ) break; if( !src.player().isPresent() )
{
break;
}
} }
} }
} }
-16
View File
@@ -544,22 +544,6 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
if( res == null ) if( res == null )
{ {
if( details != null && details.isCraftable() )
{
for( final IAEItemStack ais : this.craftableItems.keySet() )
{
if( ais.getItem() == whatToCraft.getItem() && ( !ais.getItem().getHasSubtypes() || ais.getItemDamage() == whatToCraft.getItemDamage() ) )
{
// TODO: check if OK
// TODO: this is slightly hacky, but fine as long as we only deal with itemstacks
if( details.isValidItemForSlot( slotIndex, ais.asItemStackRepresentation(), world ) )
{
return this.craftableItems.get( ais );
}
}
}
}
return ImmutableSet.of(); return ImmutableSet.of();
} }
@@ -57,7 +57,7 @@ public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemS
private String displayName; private String displayName;
@SideOnly( Side.CLIENT ) @SideOnly( Side.CLIENT )
private List<String> tooltip; private List<String> tooltip;
private WeakReference<ItemStack> cachedItemStack; private ItemStack cachedItemStack;
private AEItemStack( final AEItemStack is ) private AEItemStack( final AEItemStack is )
{ {
@@ -66,6 +66,7 @@ public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemS
this.setCountRequestable( is.getCountRequestable() ); this.setCountRequestable( is.getCountRequestable() );
this.sharedStack = is.sharedStack; this.sharedStack = is.sharedStack;
this.oreReference = is.oreReference; this.oreReference = is.oreReference;
this.cachedItemStack = is.cachedItemStack;
} }
private AEItemStack( final AESharedItemStack is, long size ) private AEItemStack( final AESharedItemStack is, long size )
@@ -282,7 +283,7 @@ public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemS
ItemStack currentCached = null; ItemStack currentCached = null;
if( this.cachedItemStack != null ) if( this.cachedItemStack != null )
{ {
currentCached = this.cachedItemStack.get(); currentCached = this.cachedItemStack;
} }
ItemStack itemStack; ItemStack itemStack;
@@ -304,7 +305,7 @@ public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemS
@Override @Override
public void setCachedItemStack( ItemStack itemStack ) public void setCachedItemStack( ItemStack itemStack )
{ {
this.cachedItemStack = new WeakReference<>( itemStack ); this.cachedItemStack = itemStack;
} }
@Override @Override