22
33import gregtech .api .recipes .KeySharedStack ;
44import gregtech .api .util .ItemStackKey ;
5+ import gregtech .api .util .ShapedOreEnergyTransferRecipe ;
56import gregtech .common .inventory .IItemList ;
67import gregtech .common .inventory .itemsource .ItemSources ;
8+ import it .unimi .dsi .fastutil .ints .Int2ObjectArrayMap ;
9+ import it .unimi .dsi .fastutil .objects .Object2BooleanOpenHashMap ;
710import net .minecraft .inventory .InventoryCrafting ;
811import net .minecraft .item .ItemStack ;
912import net .minecraft .item .crafting .IRecipe ;
13+ import net .minecraft .item .crafting .Ingredient ;
1014import net .minecraft .world .World ;
1115
1216import java .util .HashMap ;
@@ -17,6 +21,7 @@ public class CachedRecipeData {
1721 private final ItemSources itemSources ;
1822 private IRecipe recipe ;
1923 private final Map <ItemStackKey , Integer > requiredItems = new HashMap <>();
24+ private final Map <Integer , Map <ItemStackKey , Boolean >> replaceAttemptMap = new Int2ObjectArrayMap <>();
2025 private final InventoryCrafting inventory ;
2126
2227 public CachedRecipeData (ItemSources sourceList , IRecipe recipe , InventoryCrafting inventoryCrafting ) {
@@ -74,17 +79,48 @@ public boolean getIngredientEquivalent(int slot) {
7479 return true ;
7580 }
7681
82+ ItemStack previousStack = recipe .getCraftingResult (inventory );
83+
84+ Map <ItemStackKey , Boolean > map = replaceAttemptMap .computeIfAbsent (slot , (m ) -> new Object2BooleanOpenHashMap <>());
85+
7786 //iterate stored items to find equivalent
7887 for (ItemStackKey itemStackKey : itemSources .getStoredItems ()) {
88+ if (map .containsKey (itemStackKey )) {
89+ if (!map .get (itemStackKey )) {
90+ continue ;
91+ } else {
92+ return true ;
93+ }
94+ }
95+
7996 ItemStack itemStack = itemStackKey .getItemStack ();
97+
98+ boolean matched = false ;
99+ //Matching shapeless recipes actually is very bad for performance, as it checks the entire
100+ //recipe ingredients recursively, so we fail early here if none of the recipes ingredients can
101+ //take the stack
102+ for (Ingredient in : recipe .getIngredients ()) {
103+ if (in .apply (itemStack )) {
104+ matched = true ;
105+ break ;
106+ }
107+ }
108+ if (!matched ) {
109+ map .put (itemStackKey , false );
110+ continue ;
111+ }
112+
80113 //update item in slot, and check that recipe matches and output item is equal to the expected one
81114 inventory .setInventorySlotContents (slot , itemStack );
82- if (recipe .matches (inventory , itemSources .getWorld ())) {
115+ if (recipe .matches (inventory , itemSources .getWorld ()) &&
116+ (ItemStack .areItemStacksEqual (recipe .getCraftingResult (inventory ), previousStack ) || recipe instanceof ShapedOreEnergyTransferRecipe )) {
117+ map .put (itemStackKey , true );
83118 //ingredient matched, attempt to extract it and return if successful
84119 if (simulateExtractItem (itemStackKey )) {
85120 return true ;
86121 }
87122 }
123+ map .put (itemStackKey , false );
88124 inventory .setInventorySlotContents (slot , currentStack );
89125 }
90126 //nothing matched, so return null
@@ -110,6 +146,7 @@ public boolean matches(InventoryCrafting inventoryCrafting, World world) {
110146
111147 public void setRecipe (IRecipe newRecipe ) {
112148 this .recipe = newRecipe ;
149+ this .replaceAttemptMap .clear ();
113150 }
114151
115152 public IRecipe getRecipe () {
0 commit comments