From 568fc7c4d97b04d649b909896fbf3874f9bf81ee Mon Sep 17 00:00:00 2001 From: BlayTheNinth <1933180+blay09@users.noreply.github.com> Date: Tue, 9 Jan 2024 12:55:56 +0100 Subject: [PATCH] feat: add cache of last found ingredient spots for massive performance improvements #676 --- .../ItemHandlerKitchenItemProvider.java | 26 ++++- .../ItemHandlerKitchenItemProvider.java | 101 ++++++++++++++++++ .../ItemHandlerKitchenItemProvider.java | 76 ------------- .../cookingforblockheads/api/CacheHint.java | 6 ++ .../api/KitchenItemProvider.java | 16 +-- .../block/entity/FridgeBlockEntity.java | 10 +- .../block/entity/MilkJarBlockEntity.java | 12 ++- .../block/entity/SinkBlockEntity.java | 12 ++- .../crafting/CraftingContext.java | 21 +++- .../crafting/CraftingOperation.java | 89 +++++++++------ .../kitchen/CombinedKitchenItemProvider.java | 43 +++++++- .../ConditionalKitchenItemProvider.java | 28 +++-- .../kitchen/ContainerKitchenItemProvider.java | 26 ++++- 13 files changed, 326 insertions(+), 140 deletions(-) create mode 100644 neoforge/src/main/java/net/blay09/mods/cookingforblockheads/ItemHandlerKitchenItemProvider.java delete mode 100644 neoforge/src/main/java/net/blay09/mods/cookingforblockheads/compat/ItemHandlerKitchenItemProvider.java create mode 100644 shared/src/main/java/net/blay09/mods/cookingforblockheads/api/CacheHint.java diff --git a/forge/src/main/java/net/blay09/mods/cookingforblockheads/ItemHandlerKitchenItemProvider.java b/forge/src/main/java/net/blay09/mods/cookingforblockheads/ItemHandlerKitchenItemProvider.java index 4116b182..e19b9579 100644 --- a/forge/src/main/java/net/blay09/mods/cookingforblockheads/ItemHandlerKitchenItemProvider.java +++ b/forge/src/main/java/net/blay09/mods/cookingforblockheads/ItemHandlerKitchenItemProvider.java @@ -1,5 +1,6 @@ package net.blay09.mods.cookingforblockheads; +import net.blay09.mods.cookingforblockheads.api.CacheHint; import net.blay09.mods.cookingforblockheads.api.IngredientToken; import net.blay09.mods.cookingforblockheads.api.KitchenItemProvider; import net.minecraft.world.item.ItemStack; @@ -17,7 +18,14 @@ public ItemHandlerKitchenItemProvider(IItemHandler itemHandler) { } @Override - public IngredientToken findIngredient(Ingredient ingredient, Collection ingredientTokens) { + public IngredientToken findIngredient(Ingredient ingredient, Collection ingredientTokens, CacheHint cacheHint) { + if (cacheHint instanceof ItemHandlerIngredientToken itemHandlerIngredientToken) { + final var slotStack = itemHandler.getStackInSlot(itemHandlerIngredientToken.slot); + if (ingredient.test(slotStack) && hasUsesLeft(itemHandlerIngredientToken.slot, slotStack, ingredientTokens)) { + return itemHandlerIngredientToken; + } + } + for (int i = 0; i < itemHandler.getSlots(); i++) { final var slotStack = itemHandler.getStackInSlot(i); if (ingredient.test(slotStack) && hasUsesLeft(i, slotStack, ingredientTokens)) { @@ -28,7 +36,14 @@ public IngredientToken findIngredient(Ingredient ingredient, Collection ingredientTokens) { + public IngredientToken findIngredient(ItemStack itemStack, Collection ingredientTokens, CacheHint cacheHint) { + if (cacheHint instanceof ItemHandlerIngredientToken itemHandlerIngredientToken) { + final var slotStack = itemHandler.getStackInSlot(itemHandlerIngredientToken.slot); + if (ItemStack.isSameItemSameTags(slotStack, itemStack) && hasUsesLeft(itemHandlerIngredientToken.slot, slotStack, ingredientTokens)) { + return itemHandlerIngredientToken; + } + } + for (int i = 0; i < itemHandler.getSlots(); i++) { final var slotStack = itemHandler.getStackInSlot(i); if (ItemStack.isSameItemSameTags(slotStack, itemStack) && hasUsesLeft(i, slotStack, ingredientTokens)) { @@ -51,7 +66,12 @@ private boolean hasUsesLeft(int slot, ItemStack slotStack, Collection 0; } - public class ItemHandlerIngredientToken implements IngredientToken { + @Override + public CacheHint getCacheHint(IngredientToken ingredientToken) { + return ingredientToken instanceof ItemHandlerIngredientToken itemHandlerIngredientToken ? itemHandlerIngredientToken : CacheHint.NONE; + } + + public class ItemHandlerIngredientToken implements IngredientToken, CacheHint { private final int slot; public ItemHandlerIngredientToken(int slot) { diff --git a/neoforge/src/main/java/net/blay09/mods/cookingforblockheads/ItemHandlerKitchenItemProvider.java b/neoforge/src/main/java/net/blay09/mods/cookingforblockheads/ItemHandlerKitchenItemProvider.java new file mode 100644 index 00000000..60763d2e --- /dev/null +++ b/neoforge/src/main/java/net/blay09/mods/cookingforblockheads/ItemHandlerKitchenItemProvider.java @@ -0,0 +1,101 @@ +package net.blay09.mods.cookingforblockheads; + +import net.blay09.mods.cookingforblockheads.api.CacheHint; +import net.blay09.mods.cookingforblockheads.api.IngredientToken; +import net.blay09.mods.cookingforblockheads.api.KitchenItemProvider; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.neoforged.neoforge.items.IItemHandler; +import net.neoforged.neoforge.items.ItemHandlerHelper; + +import java.util.Collection; + +public class ItemHandlerKitchenItemProvider implements KitchenItemProvider { + private final IItemHandler itemHandler; + + public ItemHandlerKitchenItemProvider(IItemHandler itemHandler) { + this.itemHandler = itemHandler; + } + + @Override + public IngredientToken findIngredient(Ingredient ingredient, Collection ingredientTokens, CacheHint cacheHint) { + if (cacheHint instanceof ItemHandlerIngredientToken itemHandlerIngredientToken) { + final var slotStack = itemHandler.getStackInSlot(itemHandlerIngredientToken.slot); + if (ingredient.test(slotStack) && hasUsesLeft(itemHandlerIngredientToken.slot, slotStack, ingredientTokens)) { + return itemHandlerIngredientToken; + } + } + + for (int i = 0; i < itemHandler.getSlots(); i++) { + final var slotStack = itemHandler.getStackInSlot(i); + if (ingredient.test(slotStack) && hasUsesLeft(i, slotStack, ingredientTokens)) { + return new ItemHandlerIngredientToken(i); + } + } + return null; + } + + @Override + public IngredientToken findIngredient(ItemStack itemStack, Collection ingredientTokens, CacheHint cacheHint) { + if (cacheHint instanceof ItemHandlerIngredientToken itemHandlerIngredientToken) { + final var slotStack = itemHandler.getStackInSlot(itemHandlerIngredientToken.slot); + if (ItemStack.isSameItemSameTags(slotStack, itemStack) && hasUsesLeft(itemHandlerIngredientToken.slot, slotStack, ingredientTokens)) { + return itemHandlerIngredientToken; + } + } + + for (int i = 0; i < itemHandler.getSlots(); i++) { + final var slotStack = itemHandler.getStackInSlot(i); + if (ItemStack.isSameItemSameTags(slotStack, itemStack) && hasUsesLeft(i, slotStack, ingredientTokens)) { + return new ItemHandlerIngredientToken(i); + } + } + return null; + } + + private boolean hasUsesLeft(int slot, ItemStack slotStack, Collection ingredientTokens) { + var uses = slotStack.getCount(); + for (IngredientToken ingredientToken : ingredientTokens) { + if (ingredientToken instanceof ItemHandlerIngredientToken itemHandlerIngredientToken) { + if (itemHandlerIngredientToken.slot == slot) { + uses--; + } + } + } + + return uses > 0; + } + + @Override + public CacheHint getCacheHint(IngredientToken ingredientToken) { + return ingredientToken instanceof ItemHandlerIngredientToken itemHandlerIngredientToken ? itemHandlerIngredientToken : CacheHint.NONE; + } + + public class ItemHandlerIngredientToken implements IngredientToken, CacheHint { + private final int slot; + + public ItemHandlerIngredientToken(int slot) { + this.slot = slot; + } + + @Override + public ItemStack peek() { + return itemHandler.getStackInSlot(slot); + } + + @Override + public ItemStack consume() { + return itemHandler.extractItem(slot, 1, false); + } + + @Override + public ItemStack restore(ItemStack itemStack) { + final var restItem = itemHandler.insertItem(slot, itemStack, false); + if (!restItem.isEmpty()) { + return ItemHandlerHelper.insertItemStacked(itemHandler, restItem, false); + } + + return ItemStack.EMPTY; + } + } +} diff --git a/neoforge/src/main/java/net/blay09/mods/cookingforblockheads/compat/ItemHandlerKitchenItemProvider.java b/neoforge/src/main/java/net/blay09/mods/cookingforblockheads/compat/ItemHandlerKitchenItemProvider.java deleted file mode 100644 index 7a34aad1..00000000 --- a/neoforge/src/main/java/net/blay09/mods/cookingforblockheads/compat/ItemHandlerKitchenItemProvider.java +++ /dev/null @@ -1,76 +0,0 @@ -package net.blay09.mods.cookingforblockheads.compat; - -import net.minecraft.world.item.ItemStack; -import net.neoforged.neoforge.items.IItemHandler; -import net.neoforged.neoforge.items.ItemHandlerHelper; - -import java.util.Arrays; -import java.util.List; - -public class ItemHandlerKitchenItemProvider extends AbstractKitchenItemProvider { - private IItemHandler itemHandler; - private int[] usedStackSize; - - public ItemHandlerKitchenItemProvider() { - } - - public ItemHandlerKitchenItemProvider(IItemHandler itemHandler) { - this.itemHandler = itemHandler; - this.usedStackSize = new int[itemHandler.getSlots()]; - } - - public void setItemHandler(IItemHandler itemHandler) { - this.itemHandler = itemHandler; - this.usedStackSize = new int[itemHandler.getSlots()]; - } - - @Override - public void resetSimulation() { - Arrays.fill(usedStackSize, 0); - } - - @Override - public int getSimulatedUseCount(int slot) { - return usedStackSize[slot]; - } - - @Override - public ItemStack useItemStack(int slot, int amount, boolean simulate, List inventories, boolean requireBucket) { - // A slot of -1 means it's being infinitely provided by this block or an upgrade. - if (slot == -1) { - return ItemStack.EMPTY; - } - - ItemStack itemStack = itemHandler.getStackInSlot(slot); - if (itemStack.getCount() - (simulate ? usedStackSize[slot] : 0) >= amount) { - ItemStack result = itemHandler.extractItem(slot, amount, simulate); - if (simulate && !result.isEmpty()) { - usedStackSize[slot] += result.getCount(); - } - - return result; - } - - return ItemStack.EMPTY; - } - - @Override - public ItemStack returnItemStack(ItemStack itemStack, SourceItem sourceItem) { - ItemStack restStack = itemHandler.insertItem(sourceItem.getSourceSlot(), itemStack, false); - if (!restStack.isEmpty()) { - restStack = ItemHandlerHelper.insertItemStacked(itemHandler, itemStack, false); - } - - return restStack; - } - - @Override - public int getSlots() { - return itemHandler.getSlots(); - } - - @Override - public ItemStack getStackInSlot(int slot) { - return itemHandler.getStackInSlot(slot); - } -} diff --git a/shared/src/main/java/net/blay09/mods/cookingforblockheads/api/CacheHint.java b/shared/src/main/java/net/blay09/mods/cookingforblockheads/api/CacheHint.java new file mode 100644 index 00000000..bfe1e2fb --- /dev/null +++ b/shared/src/main/java/net/blay09/mods/cookingforblockheads/api/CacheHint.java @@ -0,0 +1,6 @@ +package net.blay09.mods.cookingforblockheads.api; + +public interface CacheHint { + CacheHint NONE = new CacheHint() { + }; +} diff --git a/shared/src/main/java/net/blay09/mods/cookingforblockheads/api/KitchenItemProvider.java b/shared/src/main/java/net/blay09/mods/cookingforblockheads/api/KitchenItemProvider.java index 02f395e6..9936bbcb 100644 --- a/shared/src/main/java/net/blay09/mods/cookingforblockheads/api/KitchenItemProvider.java +++ b/shared/src/main/java/net/blay09/mods/cookingforblockheads/api/KitchenItemProvider.java @@ -16,16 +16,20 @@ */ public interface KitchenItemProvider { /** - * @param ingredient the ingredient to find - * @param ingredientTokens the ingredient tokens that have already been provided by this provider + * @param ingredient the ingredient to find + * @param ingredientTokens the ingredient tokens that have already been provided for this type of ingredient by this provider + * @param cacheHint a hint on where to start looking, based on {@link #getCacheHint(IngredientToken)} for the last returned token for this type of ingredient * @return an ingredient token that matches the given ingredient, or null if none was found */ - IngredientToken findIngredient(Ingredient ingredient, Collection ingredientTokens); + IngredientToken findIngredient(Ingredient ingredient, Collection ingredientTokens, CacheHint cacheHint); /** - * @param itemStack the item to find - * @param ingredientTokens the ingredient tokens that have already been provided by this provider + * @param itemStack the item to find + * @param ingredientTokens the ingredient tokens that have already been provided for this type of ingredient by this provider + * @param cacheHint a hint on where to start looking, based on {@link #getCacheHint(IngredientToken)} for the last returned token for this type of ingredient * @return an ingredient token that matches the given ingredient, or null if none was found */ - IngredientToken findIngredient(ItemStack itemStack, Collection ingredientTokens); + IngredientToken findIngredient(ItemStack itemStack, Collection ingredientTokens, CacheHint cacheHint); + + CacheHint getCacheHint(IngredientToken ingredientToken); } diff --git a/shared/src/main/java/net/blay09/mods/cookingforblockheads/block/entity/FridgeBlockEntity.java b/shared/src/main/java/net/blay09/mods/cookingforblockheads/block/entity/FridgeBlockEntity.java index cd7f4aa3..91a35b6c 100644 --- a/shared/src/main/java/net/blay09/mods/cookingforblockheads/block/entity/FridgeBlockEntity.java +++ b/shared/src/main/java/net/blay09/mods/cookingforblockheads/block/entity/FridgeBlockEntity.java @@ -8,6 +8,7 @@ import net.blay09.mods.balm.api.menu.BalmMenuProvider; import net.blay09.mods.balm.api.provider.BalmProvider; import net.blay09.mods.balm.common.BalmBlockEntity; +import net.blay09.mods.cookingforblockheads.api.CacheHint; import net.blay09.mods.cookingforblockheads.api.IngredientToken; import net.blay09.mods.cookingforblockheads.api.KitchenItemProcessor; import net.blay09.mods.cookingforblockheads.api.KitchenItemProvider; @@ -70,7 +71,7 @@ public ItemStack restore(ItemStack itemStack) { private final Set providedItems = Set.of(new ItemStack(Items.SNOWBALL), new ItemStack(Items.SNOW_BLOCK), new ItemStack(Items.ICE)); @Override - public IngredientToken findIngredient(Ingredient ingredient, Collection ingredientTokens) { + public IngredientToken findIngredient(Ingredient ingredient, Collection ingredientTokens, CacheHint cacheHint) { for (final var providedItem : providedItems) { if (ingredient.test(providedItem)) { return new IceUnitIngredientToken(providedItem); @@ -80,7 +81,7 @@ public IngredientToken findIngredient(Ingredient ingredient, Collection ingredientTokens) { + public IngredientToken findIngredient(ItemStack itemStack, Collection ingredientTokens, CacheHint cacheHint) { for (final var providedItem : providedItems) { if (ItemStack.isSameItem(providedItem, itemStack)) { return new IceUnitIngredientToken(providedItem); @@ -88,6 +89,11 @@ public IngredientToken findIngredient(ItemStack itemStack, Collection ingredientTokens) { + public IngredientToken findIngredient(Ingredient ingredient, Collection ingredientTokens, CacheHint cacheHint) { for (final var itemStack : ingredient.getItems()) { - final var found = findIngredient(itemStack, ingredientTokens); + final var found = findIngredient(itemStack, ingredientTokens, cacheHint); if (found != null) { return found; } @@ -58,7 +59,7 @@ public IngredientToken findIngredient(Ingredient ingredient, Collection ingredientTokens) { + public IngredientToken findIngredient(ItemStack itemStack, Collection ingredientTokens, CacheHint cacheHint) { if (!itemStack.is(ModItemTags.MILK)) { return null; } @@ -71,6 +72,11 @@ public IngredientToken findIngredient(ItemStack itemStack, Collection ingredientTokens) { + public IngredientToken findIngredient(Ingredient ingredient, Collection ingredientTokens, CacheHint cacheHint) { for (final var itemStack : ingredient.getItems()) { - final var found = findIngredient(itemStack, ingredientTokens); + final var found = findIngredient(itemStack, ingredientTokens, cacheHint); if (found != null) { return found; } @@ -61,7 +62,7 @@ public IngredientToken findIngredient(Ingredient ingredient, Collection ingredientTokens) { + public IngredientToken findIngredient(ItemStack itemStack, Collection ingredientTokens, CacheHint cacheHint) { if (!itemStack.is(ModItemTags.WATER)) { return null; } @@ -74,6 +75,11 @@ public IngredientToken findIngredient(ItemStack itemStack, Collection itemProviders; private final List itemProcessors; + private final Map cachedProviderIndexByIngredient = new HashMap<>(); + private final Map cacheHintsByIngredient = new HashMap<>(); public CraftingContext(final Kitchen kitchen, final @Nullable Player player) { itemProviders = kitchen.getItemProviders(player); @@ -32,4 +38,17 @@ public List getItemProviders() { public List getItemProcessors() { return itemProcessors; } + + public int getCachedItemProviderIndexFor(Ingredient ingredient) { + return cachedProviderIndexByIngredient.getOrDefault(ingredient.getStackingIds(), -1); + } + + public CacheHint getCacheHintFor(CraftingOperation.IngredientTokenKey ingredientTokenKey) { + return cacheHintsByIngredient.getOrDefault(ingredientTokenKey, CacheHint.NONE); + } + + public void cache(CraftingOperation.IngredientTokenKey ingredientTokenKey, int itemProviderIndex, CacheHint cacheHint) { + cacheHintsByIngredient.put(ingredientTokenKey, cacheHint); + cachedProviderIndexByIngredient.put(ingredientTokenKey.stackingIds(), itemProviderIndex); + } } diff --git a/shared/src/main/java/net/blay09/mods/cookingforblockheads/crafting/CraftingOperation.java b/shared/src/main/java/net/blay09/mods/cookingforblockheads/crafting/CraftingOperation.java index 00c5814f..a55784c0 100644 --- a/shared/src/main/java/net/blay09/mods/cookingforblockheads/crafting/CraftingOperation.java +++ b/shared/src/main/java/net/blay09/mods/cookingforblockheads/crafting/CraftingOperation.java @@ -3,24 +3,21 @@ import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import it.unimi.dsi.fastutil.ints.IntList; +import net.blay09.mods.cookingforblockheads.api.CacheHint; import net.blay09.mods.cookingforblockheads.api.IngredientToken; -import net.blay09.mods.cookingforblockheads.api.KitchenItemProcessor; +import net.blay09.mods.cookingforblockheads.api.KitchenItemProvider; import net.blay09.mods.cookingforblockheads.registry.CookingForBlockheadsRegistry; import net.minecraft.core.NonNullList; import net.minecraft.core.RegistryAccess; import net.minecraft.world.Container; import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.TransientCraftingContainer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeHolder; -import net.minecraft.world.item.crafting.RecipeType; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; +import java.util.*; public class CraftingOperation { @@ -74,32 +71,15 @@ public CraftingOperation prepare() { } final var lockedInput = lockedInputs != null ? lockedInputs.get(i) : ItemStack.EMPTY; - final var stackingIds = ingredient.getStackingIds(); - final var itemProviders = context.getItemProviders(); - var found = false; - for (int j = 0; j < itemProviders.size(); j++) { - final var itemProvider = itemProviders.get(j); - IngredientToken ingredientToken; - final var ingredientTokenKey = new IngredientTokenKey(j, stackingIds); - if (lockedInput.isEmpty()) { - ingredientToken = itemProvider.findIngredient(ingredient, tokensByIngredient.get(ingredientTokenKey)); - } else { - ingredientToken = itemProvider.findIngredient(lockedInput, tokensByIngredient.get(ingredientTokenKey)); - } - if (ingredientToken != null) { - tokensByIngredient.put(ingredientTokenKey, ingredientToken); - if (ingredient.getItems().length > 1) { - if (lockedInputs == null) { - lockedInputs = NonNullList.withSize(ingredients.size(), ItemStack.EMPTY); - } - lockedInputs.set(i, ingredientToken.peek()); + final var ingredientToken = accountForIngredient(ingredient, lockedInput); + if (ingredientToken != null) { + if (ingredient.getItems().length > 1) { + if (lockedInputs == null) { + lockedInputs = NonNullList.withSize(recipe.getIngredients().size(), ItemStack.EMPTY); } - ingredientTokens.add(ingredientToken); - found = true; - break; + lockedInputs.set(i, ingredientToken.peek()); } - } - if (!found) { + } else { missingIngredients.add(ingredient); missingIngredientsMask |= 1 << i; } @@ -108,6 +88,55 @@ public CraftingOperation prepare() { return this; } + @Nullable + private IngredientToken accountForIngredient(Ingredient ingredient, ItemStack lockedInput) { + final var itemProviders = context.getItemProviders(); + final var cachedProviderIndex = context.getCachedItemProviderIndexFor(ingredient); + if (cachedProviderIndex != -1) { + final var itemProvider = itemProviders.get(cachedProviderIndex); + final var ingredientToken = accountForIngredient(cachedProviderIndex, itemProvider, ingredient, lockedInput, true); + if (ingredientToken != null) { + return ingredientToken; + } + } + + for (int j = 0; j < itemProviders.size(); j++) { + final var itemProvider = itemProviders.get(j); + IngredientToken ingredientToken = accountForIngredient(j, itemProvider, ingredient, lockedInput, false); + if (ingredientToken != null) { + return ingredientToken; + } + } + + return null; + } + + @Nullable + private IngredientToken accountForIngredient(int itemProviderIndex, KitchenItemProvider itemProvider, Ingredient ingredient, ItemStack lockedInput, boolean useCache) { + final var ingredientTokenKey = new IngredientTokenKey(itemProviderIndex, ingredient.getStackingIds()); + final var scopedIngredientTokens = tokensByIngredient.get(ingredientTokenKey); + final var cacheHint = useCache ? context.getCacheHintFor(ingredientTokenKey) : CacheHint.NONE; + final var ingredientToken = findIngredient(itemProvider, ingredient, lockedInput, scopedIngredientTokens, cacheHint); + if (ingredientToken != null) { + tokensByIngredient.put(ingredientTokenKey, ingredientToken); + context.cache(ingredientTokenKey, itemProviderIndex, itemProvider.getCacheHint(ingredientToken)); + ingredientTokens.add(ingredientToken); + return ingredientToken; + } + return null; + } + + @Nullable + private IngredientToken findIngredient(KitchenItemProvider itemProvider, Ingredient ingredient, ItemStack lockedInput, Collection ingredientTokens, CacheHint cacheHint) { + IngredientToken ingredientToken; + if (lockedInput.isEmpty()) { + ingredientToken = itemProvider.findIngredient(ingredient, ingredientTokens, cacheHint); + } else { + ingredientToken = itemProvider.findIngredient(lockedInput, ingredientTokens, cacheHint); + } + return ingredientToken; + } + public boolean canCraft() { return missingIngredients.isEmpty(); } diff --git a/shared/src/main/java/net/blay09/mods/cookingforblockheads/kitchen/CombinedKitchenItemProvider.java b/shared/src/main/java/net/blay09/mods/cookingforblockheads/kitchen/CombinedKitchenItemProvider.java index b2456f3b..f76e16af 100644 --- a/shared/src/main/java/net/blay09/mods/cookingforblockheads/kitchen/CombinedKitchenItemProvider.java +++ b/shared/src/main/java/net/blay09/mods/cookingforblockheads/kitchen/CombinedKitchenItemProvider.java @@ -1,5 +1,6 @@ package net.blay09.mods.cookingforblockheads.kitchen; +import net.blay09.mods.cookingforblockheads.api.CacheHint; import net.blay09.mods.cookingforblockheads.api.IngredientToken; import net.blay09.mods.cookingforblockheads.api.KitchenItemProvider; import net.minecraft.world.item.ItemStack; @@ -27,12 +28,25 @@ public ItemStack restore(ItemStack itemStack) { } } + private record CacheHintWrapper(int providerIndex, CacheHint cacheHint) implements CacheHint { + } + @Override - public IngredientToken findIngredient(Ingredient ingredient, Collection ingredientTokens) { + public IngredientToken findIngredient(Ingredient ingredient, Collection ingredientTokens, CacheHint cacheHint) { + if (cacheHint instanceof CacheHintWrapper wrapper) { + final var provider = providers.get(wrapper.providerIndex); + final var token = provider.findIngredient(ingredient, ingredientTokens, wrapper.cacheHint); + if (token != null) { + return new IngredientTokenWrapper(wrapper.providerIndex, token); + } + return null; + } + for (int i = 0; i < providers.size(); i++) { final var provider = providers.get(i); final var filteredIngredientTokens = getFilteredIngredientTokens(ingredientTokens, i); - final var token = provider.findIngredient(ingredient, filteredIngredientTokens); + final var unwrappedCacheHint = cacheHint instanceof CacheHintWrapper wrapper ? wrapper.cacheHint : cacheHint; + final var token = provider.findIngredient(ingredient, filteredIngredientTokens, unwrappedCacheHint); if (token != null) { return new IngredientTokenWrapper(i, token); } @@ -41,11 +55,21 @@ public IngredientToken findIngredient(Ingredient ingredient, Collection ingredientTokens) { + public IngredientToken findIngredient(ItemStack itemStack, Collection ingredientTokens, CacheHint cacheHint) { + if (cacheHint instanceof CacheHintWrapper wrapper) { + final var provider = providers.get(wrapper.providerIndex); + final var token = provider.findIngredient(itemStack, ingredientTokens, wrapper.cacheHint); + if (token != null) { + return new IngredientTokenWrapper(wrapper.providerIndex, token); + } + return null; + } + for (int i = 0; i < providers.size(); i++) { final var provider = providers.get(i); final var filteredIngredientTokens = getFilteredIngredientTokens(ingredientTokens, i); - final var token = provider.findIngredient(itemStack, filteredIngredientTokens); + final var unwrappedCacheHint = cacheHint instanceof CacheHintWrapper wrapper ? wrapper.cacheHint : cacheHint; + final var token = provider.findIngredient(itemStack, filteredIngredientTokens, unwrappedCacheHint); if (token != null) { return new IngredientTokenWrapper(i, token); } @@ -53,6 +77,17 @@ public IngredientToken findIngredient(ItemStack itemStack, Collection getFilteredIngredientTokens(Collection ingredientTokens, int providerIndex) { return ingredientTokens.stream() .filter(ingredientToken -> (ingredientToken instanceof IngredientTokenWrapper wrapper && wrapper.providerIndex == providerIndex)) diff --git a/shared/src/main/java/net/blay09/mods/cookingforblockheads/kitchen/ConditionalKitchenItemProvider.java b/shared/src/main/java/net/blay09/mods/cookingforblockheads/kitchen/ConditionalKitchenItemProvider.java index 1629cb71..a2b19144 100644 --- a/shared/src/main/java/net/blay09/mods/cookingforblockheads/kitchen/ConditionalKitchenItemProvider.java +++ b/shared/src/main/java/net/blay09/mods/cookingforblockheads/kitchen/ConditionalKitchenItemProvider.java @@ -1,5 +1,6 @@ package net.blay09.mods.cookingforblockheads.kitchen; +import net.blay09.mods.cookingforblockheads.api.CacheHint; import net.blay09.mods.cookingforblockheads.api.IngredientToken; import net.blay09.mods.cookingforblockheads.api.KitchenItemProvider; import net.minecraft.world.item.ItemStack; @@ -9,28 +10,37 @@ import java.util.Collection; import java.util.function.Supplier; -public record ConditionalKitchenItemProvider(Supplier condition, KitchenItemProvider delegate, - @Nullable KitchenItemProvider fallback) implements KitchenItemProvider { +public record ConditionalKitchenItemProvider(Supplier condition, T delegate, + @Nullable T fallback) implements KitchenItemProvider { - public ConditionalKitchenItemProvider(Supplier condition, KitchenItemProvider delegate) { + public ConditionalKitchenItemProvider(Supplier condition, T delegate) { this(condition, delegate, null); } @Override - public IngredientToken findIngredient(Ingredient ingredient, Collection ingredientTokens) { + public IngredientToken findIngredient(Ingredient ingredient, Collection ingredientTokens, CacheHint cacheHint) { if (!condition.get()) { - return fallback != null ? fallback.findIngredient(ingredient, ingredientTokens) : null; + return fallback != null ? fallback.findIngredient(ingredient, ingredientTokens, cacheHint) : null; } - return delegate.findIngredient(ingredient, ingredientTokens); + return delegate.findIngredient(ingredient, ingredientTokens, cacheHint); } @Override - public IngredientToken findIngredient(ItemStack itemStack, Collection ingredientTokens) { + public IngredientToken findIngredient(ItemStack itemStack, Collection ingredientTokens, CacheHint cacheHint) { if (!condition.get()) { - return fallback != null ? fallback.findIngredient(itemStack, ingredientTokens) : null; + return fallback != null ? fallback.findIngredient(itemStack, ingredientTokens, cacheHint) : null; } - return delegate.findIngredient(itemStack, ingredientTokens); + return delegate.findIngredient(itemStack, ingredientTokens, cacheHint); + } + + @Override + public CacheHint getCacheHint(IngredientToken ingredientToken) { + if (!condition.get()) { + return fallback != null ? fallback.getCacheHint(ingredientToken) : CacheHint.NONE; + } + + return delegate.getCacheHint(ingredientToken); } } diff --git a/shared/src/main/java/net/blay09/mods/cookingforblockheads/kitchen/ContainerKitchenItemProvider.java b/shared/src/main/java/net/blay09/mods/cookingforblockheads/kitchen/ContainerKitchenItemProvider.java index f1119cde..2be5572c 100644 --- a/shared/src/main/java/net/blay09/mods/cookingforblockheads/kitchen/ContainerKitchenItemProvider.java +++ b/shared/src/main/java/net/blay09/mods/cookingforblockheads/kitchen/ContainerKitchenItemProvider.java @@ -1,6 +1,7 @@ package net.blay09.mods.cookingforblockheads.kitchen; import net.blay09.mods.balm.api.container.ContainerUtils; +import net.blay09.mods.cookingforblockheads.api.CacheHint; import net.blay09.mods.cookingforblockheads.api.IngredientToken; import net.blay09.mods.cookingforblockheads.api.KitchenItemProvider; import net.minecraft.world.Container; @@ -18,7 +19,14 @@ public ContainerKitchenItemProvider(Container container) { } @Override - public IngredientToken findIngredient(Ingredient ingredient, Collection ingredientTokens) { + public IngredientToken findIngredient(Ingredient ingredient, Collection ingredientTokens, CacheHint cacheHint) { + if (cacheHint instanceof ContainerIngredientToken containerIngredientToken) { + final var slotStack = container.getItem(containerIngredientToken.slot); + if (ingredient.test(slotStack) && hasUsesLeft(containerIngredientToken.slot, slotStack, ingredientTokens)) { + return containerIngredientToken; + } + } + for (int i = 0; i < container.getContainerSize(); i++) { final var slotStack = container.getItem(i); if (ingredient.test(slotStack) && hasUsesLeft(i, slotStack, ingredientTokens)) { @@ -29,7 +37,14 @@ public IngredientToken findIngredient(Ingredient ingredient, Collection ingredientTokens) { + public IngredientToken findIngredient(ItemStack itemStack, Collection ingredientTokens, CacheHint cacheHint) { + if (cacheHint instanceof ContainerIngredientToken containerIngredientToken) { + final var slotStack = container.getItem(containerIngredientToken.slot); + if (ItemStack.isSameItemSameTags(slotStack, itemStack) && hasUsesLeft(containerIngredientToken.slot, slotStack, ingredientTokens)) { + return containerIngredientToken; + } + } + for (int i = 0; i < container.getContainerSize(); i++) { final var slotStack = container.getItem(i); if (ItemStack.isSameItemSameTags(slotStack, itemStack) && hasUsesLeft(i, slotStack, ingredientTokens)) { @@ -52,11 +67,16 @@ protected int getUsesLeft(int slot, ItemStack slotStack, Collection ingredientTokens) { return getUsesLeft(slot, slotStack, ingredientTokens) > 0; } - public class ContainerIngredientToken implements IngredientToken { + public class ContainerIngredientToken implements IngredientToken, CacheHint { private final int slot; public ContainerIngredientToken(int slot) {