From f4e0b3cd0f895df7fdafb874ccf1ddbf4bfa29a0 Mon Sep 17 00:00:00 2001 From: mezz Date: Mon, 12 Aug 2024 22:09:39 +0900 Subject: [PATCH] Optimize adding ingredients to recipes for lookups --- .../library/gui/ingredients/RecipeSlot.java | 6 +- .../RecipeLayoutIngredientSupplier.java | 45 ++---- .../layout/builder/RecipeLayoutBuilder.java | 8 +- .../layout/builder/RecipeSlotBuilder.java | 8 +- .../layout/builder/RecipeSlotIngredients.java | 15 -- .../builder/IngredientSlotBuilder.java | 21 +-- .../builder/IngredientSupplierBuilder.java | 23 ++- ...or.java => DisplayIngredientAcceptor.java} | 45 ++---- .../ingredients/IIngredientSupplier.java | 9 +- .../ingredients/SimpleIngredientAcceptor.java | 141 ++++++++++++++++++ .../library/recipes/collect/RecipeMap.java | 11 +- .../jei/library/util/RecipeErrorUtil.java | 15 +- 12 files changed, 211 insertions(+), 136 deletions(-) delete mode 100644 Library/src/main/java/mezz/jei/library/gui/recipes/layout/builder/RecipeSlotIngredients.java rename Library/src/main/java/mezz/jei/library/ingredients/{IngredientAcceptor.java => DisplayIngredientAcceptor.java} (76%) create mode 100644 Library/src/main/java/mezz/jei/library/ingredients/SimpleIngredientAcceptor.java diff --git a/Library/src/main/java/mezz/jei/library/gui/ingredients/RecipeSlot.java b/Library/src/main/java/mezz/jei/library/gui/ingredients/RecipeSlot.java index a61c91dea..3baeb3885 100644 --- a/Library/src/main/java/mezz/jei/library/gui/ingredients/RecipeSlot.java +++ b/Library/src/main/java/mezz/jei/library/gui/ingredients/RecipeSlot.java @@ -22,7 +22,7 @@ import mezz.jei.common.platform.Services; import mezz.jei.common.util.ImmutableRect2i; import mezz.jei.common.util.SafeIngredientUtil; -import mezz.jei.library.ingredients.IngredientAcceptor; +import mezz.jei.library.ingredients.DisplayIngredientAcceptor; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.renderer.Rect2i; @@ -64,7 +64,7 @@ public class RecipeSlot implements IRecipeSlotView, IRecipeSlotDrawable { private List>> displayIngredients; @Nullable - private IngredientAcceptor displayOverrides; + private DisplayIngredientAcceptor displayOverrides; public RecipeSlot( RecipeIngredientRole role, @@ -342,7 +342,7 @@ public void clearDisplayOverrides() { public IIngredientConsumer createDisplayOverrides() { if (displayOverrides == null) { IIngredientManager ingredientManager = Internal.getJeiRuntime().getIngredientManager(); - displayOverrides = new IngredientAcceptor(ingredientManager); + displayOverrides = new DisplayIngredientAcceptor(ingredientManager); } return displayOverrides; } diff --git a/Library/src/main/java/mezz/jei/library/gui/recipes/RecipeLayoutIngredientSupplier.java b/Library/src/main/java/mezz/jei/library/gui/recipes/RecipeLayoutIngredientSupplier.java index 43cbbd39e..a8990c001 100644 --- a/Library/src/main/java/mezz/jei/library/gui/recipes/RecipeLayoutIngredientSupplier.java +++ b/Library/src/main/java/mezz/jei/library/gui/recipes/RecipeLayoutIngredientSupplier.java @@ -1,52 +1,27 @@ package mezz.jei.library.gui.recipes; -import mezz.jei.api.ingredients.IIngredientType; import mezz.jei.api.ingredients.ITypedIngredient; import mezz.jei.api.recipe.RecipeIngredientRole; -import mezz.jei.library.gui.recipes.layout.builder.RecipeSlotIngredients; +import mezz.jei.library.gui.recipes.supplier.builder.IngredientSlotBuilder; import mezz.jei.library.ingredients.IIngredientSupplier; -import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.Optional; -import java.util.stream.Stream; +import java.util.Map; public class RecipeLayoutIngredientSupplier implements IIngredientSupplier { - private final List slots; + private final Map ingredientSlotBuilders; - public RecipeLayoutIngredientSupplier(List slots) { - this.slots = slots; + public RecipeLayoutIngredientSupplier(Map ingredientSlotBuilders) { + this.ingredientSlotBuilders = ingredientSlotBuilders; } @Override - public Stream> getIngredientTypes(RecipeIngredientRole role) { - return slots.stream() - .filter(slot -> slot.role() == role) - .map(RecipeSlotIngredients::types) - .flatMap(Collection::stream) - .distinct(); - } - - @Override - public Stream getIngredientStream(IIngredientType ingredientType, RecipeIngredientRole role) { - return slots.stream() - .filter(slot -> slot.role() == role) - .flatMap(slot -> slot.ingredients().stream()) - .map(ingredientType::castIngredient) - .flatMap(Optional::stream); - } - - @Override - public Collection>> getIngredients(RecipeIngredientRole role) { - List>> ingredients = new ArrayList<>(); - - for (RecipeSlotIngredients slot : slots) { - if (slot.role() == role) { - ingredients.addAll(slot.ingredients()); - } + public Collection> getIngredients(RecipeIngredientRole role) { + IngredientSlotBuilder ingredientSlotBuilder = ingredientSlotBuilders.get(role); + if (ingredientSlotBuilder == null) { + return List.of(); } - - return ingredients; + return ingredientSlotBuilder.getAllIngredients(); } } diff --git a/Library/src/main/java/mezz/jei/library/gui/recipes/layout/builder/RecipeLayoutBuilder.java b/Library/src/main/java/mezz/jei/library/gui/recipes/layout/builder/RecipeLayoutBuilder.java index 65dfd9af7..64cb3d9a4 100644 --- a/Library/src/main/java/mezz/jei/library/gui/recipes/layout/builder/RecipeLayoutBuilder.java +++ b/Library/src/main/java/mezz/jei/library/gui/recipes/layout/builder/RecipeLayoutBuilder.java @@ -28,7 +28,7 @@ import mezz.jei.library.gui.recipes.OutputSlotTooltipCallback; import mezz.jei.library.gui.recipes.RecipeLayout; import mezz.jei.library.gui.recipes.ShapelessIcon; -import mezz.jei.library.ingredients.IngredientAcceptor; +import mezz.jei.library.ingredients.DisplayIngredientAcceptor; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.Nullable; @@ -152,8 +152,8 @@ public void createFocusLink(IIngredientAcceptor... slots) { RecipeSlotBuilder builder = (RecipeSlotBuilder) slot; builders.add(builder); - IngredientAcceptor ingredientAcceptor = builder.getIngredientAcceptor(); - List>> allIngredients = ingredientAcceptor.getAllIngredients(); + DisplayIngredientAcceptor displayIngredientAcceptor = builder.getIngredientAcceptor(); + List>> allIngredients = displayIngredientAcceptor.getAllIngredients(); int ingredientCount = allIngredients.size(); if (count == -1) { count = ingredientCount; @@ -161,7 +161,7 @@ public void createFocusLink(IIngredientAcceptor... slots) { IntSummaryStatistics stats = Arrays.stream(slots) .map(RecipeSlotBuilder.class::cast) .map(RecipeSlotBuilder::getIngredientAcceptor) - .map(IngredientAcceptor::getAllIngredients) + .map(DisplayIngredientAcceptor::getAllIngredients) .mapToInt(Collection::size) .summaryStatistics(); throw new IllegalArgumentException( diff --git a/Library/src/main/java/mezz/jei/library/gui/recipes/layout/builder/RecipeSlotBuilder.java b/Library/src/main/java/mezz/jei/library/gui/recipes/layout/builder/RecipeSlotBuilder.java index 0e5f461de..76bea9643 100644 --- a/Library/src/main/java/mezz/jei/library/gui/recipes/layout/builder/RecipeSlotBuilder.java +++ b/Library/src/main/java/mezz/jei/library/gui/recipes/layout/builder/RecipeSlotBuilder.java @@ -19,7 +19,7 @@ import mezz.jei.library.gui.ingredients.ICycler; import mezz.jei.library.gui.ingredients.RecipeSlot; import mezz.jei.library.gui.ingredients.RendererOverrides; -import mezz.jei.library.ingredients.IngredientAcceptor; +import mezz.jei.library.ingredients.DisplayIngredientAcceptor; import mezz.jei.common.platform.IPlatformFluidHelperInternal; import mezz.jei.common.platform.Services; import mezz.jei.common.util.ErrorUtil; @@ -33,7 +33,7 @@ import java.util.Set; public class RecipeSlotBuilder implements IRecipeSlotBuilder { - private final IngredientAcceptor ingredients; + private final DisplayIngredientAcceptor ingredients; private final RecipeIngredientRole role; private final List tooltipCallbacks = new ArrayList<>(); private ImmutableRect2i rect; @@ -44,7 +44,7 @@ public class RecipeSlotBuilder implements IRecipeSlotBuilder { private @Nullable ISlottedWidgetFactory assignedWidgetFactory; public RecipeSlotBuilder(IIngredientManager ingredientManager, RecipeIngredientRole role, int x, int y) { - this.ingredients = new IngredientAcceptor(ingredientManager); + this.ingredients = new DisplayIngredientAcceptor(ingredientManager); this.rect = new ImmutableRect2i(x, y, 16, 16); this.role = role; } @@ -200,7 +200,7 @@ public IntSet getMatches(IFocusGroup focuses) { return this.ingredients.getMatches(focuses, role); } - public IngredientAcceptor getIngredientAcceptor() { + public DisplayIngredientAcceptor getIngredientAcceptor() { return ingredients; } diff --git a/Library/src/main/java/mezz/jei/library/gui/recipes/layout/builder/RecipeSlotIngredients.java b/Library/src/main/java/mezz/jei/library/gui/recipes/layout/builder/RecipeSlotIngredients.java deleted file mode 100644 index 7524b5b48..000000000 --- a/Library/src/main/java/mezz/jei/library/gui/recipes/layout/builder/RecipeSlotIngredients.java +++ /dev/null @@ -1,15 +0,0 @@ -package mezz.jei.library.gui.recipes.layout.builder; - -import mezz.jei.api.ingredients.IIngredientType; -import mezz.jei.api.ingredients.ITypedIngredient; -import mezz.jei.api.recipe.RecipeIngredientRole; - -import java.util.Collection; -import java.util.Optional; -import java.util.Set; - -public record RecipeSlotIngredients( - RecipeIngredientRole role, - Collection>> ingredients, - Set> types -) {} diff --git a/Library/src/main/java/mezz/jei/library/gui/recipes/supplier/builder/IngredientSlotBuilder.java b/Library/src/main/java/mezz/jei/library/gui/recipes/supplier/builder/IngredientSlotBuilder.java index 4634acee2..17b9e2a16 100644 --- a/Library/src/main/java/mezz/jei/library/gui/recipes/supplier/builder/IngredientSlotBuilder.java +++ b/Library/src/main/java/mezz/jei/library/gui/recipes/supplier/builder/IngredientSlotBuilder.java @@ -6,15 +6,14 @@ import mezz.jei.api.ingredients.IIngredientRenderer; import mezz.jei.api.ingredients.IIngredientType; import mezz.jei.api.ingredients.ITypedIngredient; -import mezz.jei.api.recipe.RecipeIngredientRole; import mezz.jei.api.runtime.IIngredientManager; import mezz.jei.library.gui.recipes.layout.builder.RecipeSlotBuilder; -import mezz.jei.library.gui.recipes.layout.builder.RecipeSlotIngredients; -import mezz.jei.library.ingredients.IngredientAcceptor; +import mezz.jei.library.ingredients.SimpleIngredientAcceptor; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.material.Fluid; import org.jetbrains.annotations.Nullable; +import java.util.Collection; import java.util.List; import java.util.Optional; @@ -23,12 +22,10 @@ * but doesn't bother building anything for drawing on screen. */ public class IngredientSlotBuilder implements IRecipeSlotBuilder { - private final IngredientAcceptor ingredients; - private final RecipeIngredientRole role; + private final SimpleIngredientAcceptor ingredients; - public IngredientSlotBuilder(IIngredientManager ingredientManager, RecipeIngredientRole role) { - this.ingredients = new IngredientAcceptor(ingredientManager); - this.role = role; + public IngredientSlotBuilder(IIngredientManager ingredientManager) { + this.ingredients = new SimpleIngredientAcceptor(ingredientManager); } @Override @@ -103,11 +100,7 @@ public IRecipeSlotBuilder setSlotName(String slotName) { return this; } - public RecipeSlotIngredients getRecipeSlotIngredients() { - return new RecipeSlotIngredients( - this.role, - this.ingredients.getAllIngredients(), - this.ingredients.getIngredientTypes() - ); + public Collection> getAllIngredients() { + return this.ingredients.getAllIngredients(); } } diff --git a/Library/src/main/java/mezz/jei/library/gui/recipes/supplier/builder/IngredientSupplierBuilder.java b/Library/src/main/java/mezz/jei/library/gui/recipes/supplier/builder/IngredientSupplierBuilder.java index 869fc7dd8..fba8f1780 100644 --- a/Library/src/main/java/mezz/jei/library/gui/recipes/supplier/builder/IngredientSupplierBuilder.java +++ b/Library/src/main/java/mezz/jei/library/gui/recipes/supplier/builder/IngredientSupplierBuilder.java @@ -7,28 +7,31 @@ import mezz.jei.api.recipe.RecipeIngredientRole; import mezz.jei.api.runtime.IIngredientManager; import mezz.jei.library.gui.recipes.RecipeLayoutIngredientSupplier; -import mezz.jei.library.gui.recipes.layout.builder.RecipeSlotIngredients; import mezz.jei.library.ingredients.IIngredientSupplier; -import java.util.ArrayList; -import java.util.List; +import java.util.EnumMap; +import java.util.Map; /** * Minimal version of {@link IRecipeLayoutBuilder} that can only return the ingredients, - * but doesn't bother building anything for drawing on screen. + * but doesn't bother building real slots or anything else for drawing on screen. */ public class IngredientSupplierBuilder implements IRecipeLayoutBuilder { - private final List slots = new ArrayList<>(); private final IIngredientManager ingredientManager; + private final Map ingredientSlotBuilders; public IngredientSupplierBuilder(IIngredientManager ingredientManager) { this.ingredientManager = ingredientManager; + this.ingredientSlotBuilders = new EnumMap<>(RecipeIngredientRole.class); } @Override public IRecipeSlotBuilder addSlot(RecipeIngredientRole role, int x, int y) { - IngredientSlotBuilder slot = new IngredientSlotBuilder(ingredientManager, role); - this.slots.add(slot); + IngredientSlotBuilder slot = ingredientSlotBuilders.get(role); + if (slot == null) { + slot = new IngredientSlotBuilder(ingredientManager); + ingredientSlotBuilders.put(role, slot); + } return slot; } @@ -63,10 +66,6 @@ public void createFocusLink(IIngredientAcceptor... slots) { } public IIngredientSupplier buildIngredientSupplier() { - List ingredients = new ArrayList<>(); - for (IngredientSlotBuilder slot : this.slots) { - ingredients.add(slot.getRecipeSlotIngredients()); - } - return new RecipeLayoutIngredientSupplier(ingredients); + return new RecipeLayoutIngredientSupplier(this.ingredientSlotBuilders); } } diff --git a/Library/src/main/java/mezz/jei/library/ingredients/IngredientAcceptor.java b/Library/src/main/java/mezz/jei/library/ingredients/DisplayIngredientAcceptor.java similarity index 76% rename from Library/src/main/java/mezz/jei/library/ingredients/IngredientAcceptor.java rename to Library/src/main/java/mezz/jei/library/ingredients/DisplayIngredientAcceptor.java index a74e38a38..77f5a65bb 100644 --- a/Library/src/main/java/mezz/jei/library/ingredients/IngredientAcceptor.java +++ b/Library/src/main/java/mezz/jei/library/ingredients/DisplayIngredientAcceptor.java @@ -23,33 +23,28 @@ import java.util.ArrayList; import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Optional; -import java.util.Set; import java.util.function.Function; -public class IngredientAcceptor implements IIngredientAcceptor { +public class DisplayIngredientAcceptor implements IIngredientAcceptor { private final IIngredientManager ingredientManager; /** * A list of ingredients, including "blank" ingredients represented by {@link Optional#empty()}. * Blank ingredients are drawn as "nothing" in a rotation of ingredients, but aren't considered in lookups. */ private final List>> ingredients = new ArrayList<>(); - private final Set> types = new HashSet<>(); - public IngredientAcceptor(IIngredientManager ingredientManager) { + public DisplayIngredientAcceptor(IIngredientManager ingredientManager) { this.ingredientManager = ingredientManager; } @Override - public IngredientAcceptor addIngredientsUnsafe(List ingredients) { + public DisplayIngredientAcceptor addIngredientsUnsafe(List ingredients) { Preconditions.checkNotNull(ingredients, "ingredients"); for (Object ingredient : ingredients) { Optional> typedIngredient = TypedIngredient.createAndFilterInvalid(ingredientManager, ingredient, false); - typedIngredient.ifPresent(i -> this.types.add(i.getType())); - this.ingredients.add(typedIngredient); } @@ -57,22 +52,15 @@ public IngredientAcceptor addIngredientsUnsafe(List ingredients) { } @Override - public IngredientAcceptor addIngredients(IIngredientType ingredientType, List<@Nullable T> ingredients) { + public DisplayIngredientAcceptor addIngredients(IIngredientType ingredientType, List<@Nullable T> ingredients) { ErrorUtil.checkNotNull(ingredientType, "ingredientType"); Preconditions.checkNotNull(ingredients, "ingredients"); List>> typedIngredients = TypedIngredient.createAndFilterInvalidList(this.ingredientManager, ingredientType, ingredients, false); if (!typedIngredients.isEmpty()) { - boolean anyPresent = false; for (Optional> typedIngredientOptional : typedIngredients) { this.ingredients.add(typedIngredientOptional.map(Function.identity())); - if (!anyPresent && typedIngredientOptional.isPresent()) { - anyPresent = true; - } - } - if (anyPresent) { - this.types.add(ingredientType); } } @@ -80,7 +68,7 @@ public IngredientAcceptor addIngredients(IIngredientType ingredientType, } @Override - public IngredientAcceptor addIngredient(IIngredientType ingredientType, T ingredient) { + public DisplayIngredientAcceptor addIngredient(IIngredientType ingredientType, T ingredient) { ErrorUtil.checkNotNull(ingredientType, "ingredientType"); ErrorUtil.checkNotNull(ingredient, "ingredient"); @@ -89,29 +77,28 @@ public IngredientAcceptor addIngredient(IIngredientType ingredientType, T } @Override - public IngredientAcceptor addTypedIngredient(ITypedIngredient typedIngredient) { + public DisplayIngredientAcceptor addTypedIngredient(ITypedIngredient typedIngredient) { ErrorUtil.checkNotNull(typedIngredient, "typedIngredient"); Optional> copy = TypedIngredient.deepCopy(ingredientManager, typedIngredient); - copy.ifPresent(i -> this.types.add(i.getType())); this.ingredients.add(copy.map(Function.identity())); return this; } @Override - public IngredientAcceptor addFluidStack(Fluid fluid, long amount) { + public DisplayIngredientAcceptor addFluidStack(Fluid fluid, long amount) { IPlatformFluidHelperInternal fluidHelper = Services.PLATFORM.getFluidHelper(); return addFluidInternal(fluidHelper, fluid, amount, null); } @Override - public IngredientAcceptor addFluidStack(Fluid fluid, long amount, CompoundTag tag) { + public DisplayIngredientAcceptor addFluidStack(Fluid fluid, long amount, CompoundTag tag) { IPlatformFluidHelperInternal fluidHelper = Services.PLATFORM.getFluidHelper(); return addFluidInternal(fluidHelper, fluid, amount, tag); } - private IngredientAcceptor addFluidInternal(IPlatformFluidHelperInternal fluidHelper, Fluid fluid, long amount, @Nullable CompoundTag tag) { + private DisplayIngredientAcceptor addFluidInternal(IPlatformFluidHelperInternal fluidHelper, Fluid fluid, long amount, @Nullable CompoundTag tag) { T fluidStack = fluidHelper.create(fluid, amount, tag); IIngredientTypeWithSubtypes fluidIngredientType = fluidHelper.getFluidIngredientType(); addIngredientInternal(fluidIngredientType, fluidStack); @@ -119,7 +106,7 @@ private IngredientAcceptor addFluidInternal(IPlatformFluidHelperInternal } @Override - public IngredientAcceptor addTypedIngredients(List> ingredients) { + public DisplayIngredientAcceptor addTypedIngredients(List> ingredients) { ErrorUtil.checkNotNull(ingredients, "ingredients"); for (ITypedIngredient typedIngredient : ingredients) { @@ -129,7 +116,7 @@ public IngredientAcceptor addTypedIngredients(List> ingredie } @Override - public IngredientAcceptor addOptionalTypedIngredients(List>> ingredients) { + public DisplayIngredientAcceptor addOptionalTypedIngredients(List>> ingredients) { ErrorUtil.checkNotNull(ingredients, "ingredients"); this.ingredients.addAll(ingredients); @@ -138,24 +125,14 @@ public IngredientAcceptor addOptionalTypedIngredients(List void addIngredientInternal(IIngredientType ingredientType, @Nullable T ingredient) { Optional> typedIngredient = TypedIngredient.createAndFilterInvalid(this.ingredientManager, ingredientType, ingredient, false); - typedIngredient.ifPresent(i -> this.types.add(i.getType())); this.ingredients.add(typedIngredient.map(Function.identity())); } - public Set> getIngredientTypes() { - return Collections.unmodifiableSet(this.types); - } - @UnmodifiableView public List>> getAllIngredients() { return Collections.unmodifiableList(this.ingredients); } - public void clear() { - this.ingredients.clear(); - this.types.clear(); - } - public IntSet getMatches(IFocusGroup focusGroup, RecipeIngredientRole role) { List> focuses = focusGroup.getFocuses(role).toList(); IntSet results = new IntOpenHashSet(); diff --git a/Library/src/main/java/mezz/jei/library/ingredients/IIngredientSupplier.java b/Library/src/main/java/mezz/jei/library/ingredients/IIngredientSupplier.java index 07e18e349..d4482c0af 100644 --- a/Library/src/main/java/mezz/jei/library/ingredients/IIngredientSupplier.java +++ b/Library/src/main/java/mezz/jei/library/ingredients/IIngredientSupplier.java @@ -1,15 +1,12 @@ package mezz.jei.library.ingredients; -import mezz.jei.api.ingredients.IIngredientType; import mezz.jei.api.ingredients.ITypedIngredient; import mezz.jei.api.recipe.RecipeIngredientRole; +import org.jetbrains.annotations.Unmodifiable; import java.util.Collection; -import java.util.Optional; -import java.util.stream.Stream; public interface IIngredientSupplier { - Stream> getIngredientTypes(RecipeIngredientRole role); - Stream getIngredientStream(IIngredientType ingredientType, RecipeIngredientRole role); - Collection>> getIngredients(RecipeIngredientRole role); + @Unmodifiable + Collection> getIngredients(RecipeIngredientRole role); } diff --git a/Library/src/main/java/mezz/jei/library/ingredients/SimpleIngredientAcceptor.java b/Library/src/main/java/mezz/jei/library/ingredients/SimpleIngredientAcceptor.java new file mode 100644 index 000000000..629cc0b1c --- /dev/null +++ b/Library/src/main/java/mezz/jei/library/ingredients/SimpleIngredientAcceptor.java @@ -0,0 +1,141 @@ +package mezz.jei.library.ingredients; + +import com.google.common.base.Preconditions; +import mezz.jei.api.gui.builder.IIngredientAcceptor; +import mezz.jei.api.ingredients.IIngredientType; +import mezz.jei.api.ingredients.IIngredientTypeWithSubtypes; +import mezz.jei.api.ingredients.ITypedIngredient; +import mezz.jei.api.runtime.IIngredientManager; +import mezz.jei.common.platform.IPlatformFluidHelperInternal; +import mezz.jei.common.platform.Services; +import mezz.jei.common.util.ErrorUtil; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.material.Fluid; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnmodifiableView; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +/** + * Minimal version of {@link DisplayIngredientAcceptor} that can only return the ingredients, + * but doesn't bother building anything for drawing on screen. + */ +@SuppressWarnings("OptionalIsPresent") +public class SimpleIngredientAcceptor implements IIngredientAcceptor { + private final IIngredientManager ingredientManager; + private final List> ingredients = new ArrayList<>(); + + public SimpleIngredientAcceptor(IIngredientManager ingredientManager) { + this.ingredientManager = ingredientManager; + } + + @Override + public SimpleIngredientAcceptor addIngredientsUnsafe(List ingredients) { + Preconditions.checkNotNull(ingredients, "ingredients"); + + for (Object ingredient : ingredients) { + Optional> typedIngredient = TypedIngredient.createAndFilterInvalid(ingredientManager, ingredient, false); + if (typedIngredient.isPresent()) { + this.ingredients.add(typedIngredient.get()); + } + } + + return this; + } + + @Override + public SimpleIngredientAcceptor addIngredients(IIngredientType ingredientType, List<@Nullable T> ingredients) { + ErrorUtil.checkNotNull(ingredientType, "ingredientType"); + Preconditions.checkNotNull(ingredients, "ingredients"); + + List>> typedIngredients = TypedIngredient.createAndFilterInvalidList(this.ingredientManager, ingredientType, ingredients, false); + + for (Optional> typedIngredientOptional : typedIngredients) { + if (typedIngredientOptional.isPresent()) { + this.ingredients.add(typedIngredientOptional.get()); + } + } + + return this; + } + + @Override + public SimpleIngredientAcceptor addIngredient(IIngredientType ingredientType, T ingredient) { + ErrorUtil.checkNotNull(ingredientType, "ingredientType"); + ErrorUtil.checkNotNull(ingredient, "ingredient"); + + addIngredientInternal(ingredientType, ingredient); + return this; + } + + @Override + public SimpleIngredientAcceptor addTypedIngredient(ITypedIngredient typedIngredient) { + ErrorUtil.checkNotNull(typedIngredient, "typedIngredient"); + + Optional> copy = TypedIngredient.deepCopy(ingredientManager, typedIngredient); + if (copy.isPresent()) { + this.ingredients.add(copy.get()); + } + + return this; + } + + @Override + public SimpleIngredientAcceptor addFluidStack(Fluid fluid, long amount) { + IPlatformFluidHelperInternal fluidHelper = Services.PLATFORM.getFluidHelper(); + return addFluidInternal(fluidHelper, fluid, amount, null); + } + + @Override + public SimpleIngredientAcceptor addFluidStack(Fluid fluid, long amount, CompoundTag tag) { + IPlatformFluidHelperInternal fluidHelper = Services.PLATFORM.getFluidHelper(); + return addFluidInternal(fluidHelper, fluid, amount, tag); + } + + private SimpleIngredientAcceptor addFluidInternal(IPlatformFluidHelperInternal fluidHelper, Fluid fluid, long amount, @Nullable CompoundTag tag) { + T fluidStack = fluidHelper.create(fluid, amount, tag); + IIngredientTypeWithSubtypes fluidIngredientType = fluidHelper.getFluidIngredientType(); + addIngredientInternal(fluidIngredientType, fluidStack); + return this; + } + + @Override + public SimpleIngredientAcceptor addTypedIngredients(List> ingredients) { + ErrorUtil.checkNotNull(ingredients, "ingredients"); + + for (ITypedIngredient typedIngredient : ingredients) { + this.addTypedIngredient(typedIngredient); + } + return this; + } + + @Override + public SimpleIngredientAcceptor addOptionalTypedIngredients(List>> ingredients) { + ErrorUtil.checkNotNull(ingredients, "ingredients"); + + for (Optional> optionalTypedIngredient : ingredients) { + if (optionalTypedIngredient.isPresent()) { + this.ingredients.add(optionalTypedIngredient.get()); + } + } + return this; + } + + private void addIngredientInternal(IIngredientType ingredientType, @Nullable T ingredient) { + if (ingredient == null) { + return; + } + Optional> typedIngredient = TypedIngredient.createAndFilterInvalid(this.ingredientManager, ingredientType, ingredient, false); + if (typedIngredient.isPresent()) { + this.ingredients.add(typedIngredient.get()); + } + } + + @UnmodifiableView + public List> getAllIngredients() { + return Collections.unmodifiableList(this.ingredients); + } +} diff --git a/Library/src/main/java/mezz/jei/library/recipes/collect/RecipeMap.java b/Library/src/main/java/mezz/jei/library/recipes/collect/RecipeMap.java index bdee7d91d..f4b098d63 100644 --- a/Library/src/main/java/mezz/jei/library/recipes/collect/RecipeMap.java +++ b/Library/src/main/java/mezz/jei/library/recipes/collect/RecipeMap.java @@ -19,7 +19,6 @@ import java.util.Comparator; import java.util.HashSet; import java.util.List; -import java.util.Optional; import java.util.Set; import java.util.stream.Stream; @@ -67,12 +66,10 @@ public boolean isCatalystForRecipeCategory(RecipeType recipeType, ITypedI public void addRecipe(RecipeType recipeType, T recipe, IIngredientSupplier ingredientSupplier) { Set ingredientUids = new HashSet<>(); - Collection>> ingredients = ingredientSupplier.getIngredients(this.role); - for (Optional> ingredient : ingredients) { - if (ingredient.isPresent()) { - Object ingredientUid = getIngredientUid(ingredient.get()); - ingredientUids.add(ingredientUid); - } + Collection> ingredients = ingredientSupplier.getIngredients(this.role); + for (ITypedIngredient ingredient : ingredients) { + Object ingredientUid = getIngredientUid(ingredient); + ingredientUids.add(ingredientUid); } if (!ingredientUids.isEmpty()) { diff --git a/Library/src/main/java/mezz/jei/library/util/RecipeErrorUtil.java b/Library/src/main/java/mezz/jei/library/util/RecipeErrorUtil.java index 85e3a2bf4..99ff7a72f 100644 --- a/Library/src/main/java/mezz/jei/library/util/RecipeErrorUtil.java +++ b/Library/src/main/java/mezz/jei/library/util/RecipeErrorUtil.java @@ -2,6 +2,7 @@ import mezz.jei.api.ingredients.IIngredientHelper; import mezz.jei.api.ingredients.IIngredientType; +import mezz.jei.api.ingredients.ITypedIngredient; import mezz.jei.api.recipe.RecipeIngredientRole; import mezz.jei.api.recipe.category.IRecipeCategory; import mezz.jei.api.runtime.IIngredientManager; @@ -13,6 +14,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.stream.Stream; @@ -50,7 +52,10 @@ public static String getInfoFromRecipe(T recipe, IRecipeCategory recipeCa } private static void appendRoleData(IIngredientSupplier ingredientSupplier, RecipeIngredientRole role, StringBuilder recipeInfoBuilder, IIngredientManager ingredientManager) { - ingredientSupplier.getIngredientTypes(role) + ingredientSupplier.getIngredients(role) + .stream() + .map(ITypedIngredient::getType) + .distinct() .forEach(ingredientType -> { String ingredientOutputInfo = getIngredientInfo(ingredientType, role, ingredientSupplier, ingredientManager); recipeInfoBuilder @@ -62,7 +67,13 @@ private static void appendRoleData(IIngredientSupplier ingredientSupplier, Recip } private static String getIngredientInfo(IIngredientType ingredientType, RecipeIngredientRole role, IIngredientSupplier ingredients, IIngredientManager ingredientManager) { - List ingredientList = ingredients.getIngredientStream(ingredientType, role).toList(); + List ingredientList = new ArrayList<>(); + + for (ITypedIngredient ingredient : ingredients.getIngredients(role)) { + ingredient.getIngredient(ingredientType) + .ifPresent(ingredientList::add); + } + IIngredientHelper ingredientHelper = ingredientManager.getIngredientHelper(ingredientType); Stream stringStream = ingredientList.stream()