From f4d357714e3146e032848cafd4e67155fcd4139f Mon Sep 17 00:00:00 2001 From: James Mitchell Date: Wed, 28 Aug 2024 18:53:13 +0900 Subject: [PATCH] Add API support for batch-rendering ingredients (#3711) Add basic batch-rendering for ItemStacks --- .../java/mezz/jei/common/util/ErrorUtil.java | 50 +++---- .../jei/common/util/SafeIngredientUtil.java | 87 +++++++++--- .../api/ingredients/IIngredientRenderer.java | 22 ++- .../rendering/BatchRenderElement.java | 15 ++ .../ingredients/rendering/package-info.java | 7 + .../mezz/jei/api/recipe/IRecipeManager.java | 1 - .../jei/test/lib/TestClientToggleState.java | 2 +- .../jei/gui/bookmarks/RecipeBookmark.java | 20 +-- .../mezz/jei/gui/config/BookmarkConfig.java | 4 +- .../serializers/RecipeBookmarkSerializer.java | 15 +- .../mezz/jei/gui/overlay/IngredientGrid.java | 33 ++++- .../gui/overlay/IngredientListRenderer.java | 118 ++++++++++++++-- .../jei/gui/overlay/IngredientListSlot.java | 43 +++--- .../overlay/bookmarks/BookmarkOverlay.java | 2 +- .../gui/overlay/elements/ElementRenderer.java | 86 ------------ .../overlay/elements/ElementRenderers.java | 20 --- .../jei/gui/overlay/elements/IElement.java | 6 +- .../overlay/elements/IElementRenderer.java | 11 -- .../elements/IngredientBookmarkElement.java | 7 +- .../overlay/elements/IngredientElement.java | 7 +- .../elements/RecipeBookmarkElement.java | 63 +++++++-- .../overlay/elements/RenderableElement.java | 27 ---- .../jei/gui/recipes/RecipeBookmarkButton.java | 8 +- .../java/mezz/jei/gui/recipes/RecipesGui.java | 8 +- .../mezz/jei/gui/startup/OverlayHelper.java | 13 +- .../jei/library/config/EditModeConfig.java | 1 - .../jei/library/render/ItemStackRenderer.java | 9 ++ .../render/batch/ElementWithModel.java | 7 + .../render/batch/ItemStackBatchRenderer.java | 129 ++++++++++++++++++ .../batch/ItemStackBatchRendererCache.java | 35 +++++ .../render/batch/LimitedQuadItemModel.java | 71 ++++++++++ .../library/render/batch/package-info.java | 7 + gradle.properties | 2 +- 33 files changed, 621 insertions(+), 315 deletions(-) create mode 100644 CommonApi/src/main/java/mezz/jei/api/ingredients/rendering/BatchRenderElement.java create mode 100644 CommonApi/src/main/java/mezz/jei/api/ingredients/rendering/package-info.java delete mode 100644 Gui/src/main/java/mezz/jei/gui/overlay/elements/ElementRenderer.java delete mode 100644 Gui/src/main/java/mezz/jei/gui/overlay/elements/ElementRenderers.java delete mode 100644 Gui/src/main/java/mezz/jei/gui/overlay/elements/IElementRenderer.java delete mode 100644 Gui/src/main/java/mezz/jei/gui/overlay/elements/RenderableElement.java create mode 100644 Library/src/main/java/mezz/jei/library/render/batch/ElementWithModel.java create mode 100644 Library/src/main/java/mezz/jei/library/render/batch/ItemStackBatchRenderer.java create mode 100644 Library/src/main/java/mezz/jei/library/render/batch/ItemStackBatchRendererCache.java create mode 100644 Library/src/main/java/mezz/jei/library/render/batch/LimitedQuadItemModel.java create mode 100644 Library/src/main/java/mezz/jei/library/render/batch/package-info.java diff --git a/Common/src/main/java/mezz/jei/common/util/ErrorUtil.java b/Common/src/main/java/mezz/jei/common/util/ErrorUtil.java index d531fc285..c1cf8932b 100644 --- a/Common/src/main/java/mezz/jei/common/util/ErrorUtil.java +++ b/Common/src/main/java/mezz/jei/common/util/ErrorUtil.java @@ -13,6 +13,7 @@ import net.minecraft.CrashReportCategory; import net.minecraft.client.Minecraft; import net.minecraft.core.NonNullList; +import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; @@ -49,17 +50,7 @@ public static String getItemStackInfo(@Nullable ItemStack itemStack) { .map(ResourceLocation::toString) .orElseGet(() -> { if (item instanceof BlockItem blockItem) { - final String blockName; - Block block = blockItem.getBlock(); - //noinspection ConstantValue - if (block == null) { - blockName = "null"; - } else { - IPlatformRegistry blockRegistry = Services.PLATFORM.getRegistry(Registries.BLOCK); - blockName = blockRegistry.getRegistryName(block) - .map(ResourceLocation::toString) - .orElseGet(() -> block.getClass().getName()); - } + final String blockName = getBlockName(blockItem); return "BlockItem(" + blockName + ")"; } else { return item.getClass().getName(); @@ -73,6 +64,21 @@ public static String getItemStackInfo(@Nullable ItemStack itemStack) { return itemStack + " " + itemName; } + @SuppressWarnings("ConstantValue") + private static String getBlockName(BlockItem blockItem) { + Block block = blockItem.getBlock(); + if (block == null) { + return "null"; + } + Registry blockRegistry = RegistryUtil.getRegistry(Registries.BLOCK); + ResourceLocation key = blockRegistry.getKey(block); + if (key != null) { + return key.toString(); + } + return block.getClass().getName(); + } + + @SuppressWarnings("ConstantConditions") public static void checkNotEmpty(ItemStack itemStack) { if (itemStack == null) { @@ -164,28 +170,24 @@ public static void validateRecipes(RecipeType recipeType, Iterable CrashReport createIngredientCrashReport(Throwable throwable, String title, IIngredientManager ingredientManager, ITypedIngredient typedIngredient) { - CrashReport crashReport = CrashReport.forThrowable(throwable, title); - - IIngredientType ingredientType = typedIngredient.getType(); - IIngredientHelper ingredientHelper = ingredientManager.getIngredientHelper(ingredientType); + return createIngredientCrashReport(throwable, title, ingredientManager, typedIngredient.getType(), typedIngredient.getIngredient()); + } + public static CrashReport createIngredientCrashReport(Throwable throwable, String title, IIngredientManager ingredientManager, IIngredientType ingredientType, T ingredient) { + CrashReport crashReport = CrashReport.forThrowable(throwable, title); CrashReportCategory category = crashReport.addCategory("Ingredient"); - setIngredientCategoryDetails(category, typedIngredient, ingredientHelper); + setIngredientCategoryDetails(category, ingredientType, ingredient, ingredientManager); return crashReport; } - public static void logIngredientCrash(Throwable throwable, String title, IIngredientManager ingredientManager, ITypedIngredient typedIngredient) { + public static void logIngredientCrash(Throwable throwable, String title, IIngredientManager ingredientManager, IIngredientType ingredientType, T ingredient) { CrashReportCategory category = new CrashReportCategory("Ingredient"); - IIngredientType ingredientType = typedIngredient.getType(); - IIngredientHelper ingredientHelper = ingredientManager.getIngredientHelper(ingredientType); - setIngredientCategoryDetails(category, typedIngredient, ingredientHelper); + setIngredientCategoryDetails(category, ingredientType, ingredient, ingredientManager); LOGGER.error(crashReportToString(throwable, title, category)); } - private static void setIngredientCategoryDetails(CrashReportCategory category, ITypedIngredient typedIngredient, IIngredientHelper ingredientHelper) { - T ingredient = typedIngredient.getIngredient(); - IIngredientType ingredientType = typedIngredient.getType(); - + private static void setIngredientCategoryDetails(CrashReportCategory category, IIngredientType ingredientType, T ingredient, IIngredientManager ingredientManager) { + IIngredientHelper ingredientHelper = ingredientManager.getIngredientHelper(ingredientType); IPlatformModHelper modHelper = Services.PLATFORM.getModHelper(); category.setDetail("Name", () -> ingredientHelper.getDisplayName(ingredient)); diff --git a/Common/src/main/java/mezz/jei/common/util/SafeIngredientUtil.java b/Common/src/main/java/mezz/jei/common/util/SafeIngredientUtil.java index 5e70e8b81..af9251fc7 100644 --- a/Common/src/main/java/mezz/jei/common/util/SafeIngredientUtil.java +++ b/Common/src/main/java/mezz/jei/common/util/SafeIngredientUtil.java @@ -1,11 +1,11 @@ package mezz.jei.common.util; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; import com.mojang.blaze3d.systems.RenderSystem; import mezz.jei.api.gui.builder.ITooltipBuilder; import mezz.jei.api.ingredients.IIngredientRenderer; +import mezz.jei.api.ingredients.IIngredientType; import mezz.jei.api.ingredients.ITypedIngredient; +import mezz.jei.api.ingredients.rendering.BatchRenderElement; import mezz.jei.api.runtime.IIngredientManager; import mezz.jei.common.Internal; import mezz.jei.common.config.IClientConfig; @@ -19,18 +19,18 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.item.TooltipFlag; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; -import java.util.concurrent.TimeUnit; +import java.util.HashSet; +import java.util.List; +import java.util.Set; public final class SafeIngredientUtil { - private static final Cache, Boolean> CRASHING_INGREDIENT_RENDER_CACHE = - CacheBuilder.newBuilder() - .expireAfterAccess(10, TimeUnit.SECONDS) - .build(); - private static final Cache, Boolean> CRASHING_INGREDIENT_TOOLTIP_CACHE = - CacheBuilder.newBuilder() - .expireAfterAccess(10, TimeUnit.SECONDS) - .build(); + private static final Logger LOGGER = LogManager.getLogger(); + private static final Set> CRASHING_INGREDIENT_BATCH_RENDERERS = new HashSet<>(); + private static final Set CRASHING_INGREDIENT_RENDERERS = new HashSet<>(); + private static final Set CRASHING_INGREDIENT_TOOLTIPS = new HashSet<>(); private SafeIngredientUtil() { } @@ -49,21 +49,22 @@ public static void getTooltip( ITypedIngredient typedIngredient, TooltipFlag.Default tooltipFlag ) { - if (CRASHING_INGREDIENT_TOOLTIP_CACHE.getIfPresent(typedIngredient) == Boolean.TRUE) { + T ingredient = typedIngredient.getIngredient(); + + if (CRASHING_INGREDIENT_TOOLTIPS.contains(ingredient)) { getTooltipErrorTooltip(tooltip); return; } tooltip.setIngredient(typedIngredient); - T ingredient = typedIngredient.getIngredient(); try { ingredientRenderer.getTooltip(tooltip, ingredient, tooltipFlag); - if (CRASHING_INGREDIENT_RENDER_CACHE.getIfPresent(typedIngredient) == Boolean.TRUE) { + if (CRASHING_INGREDIENT_RENDERERS.contains(ingredient)) { getRenderErrorTooltip(tooltip); } } catch (RuntimeException | LinkageError e) { - CRASHING_INGREDIENT_TOOLTIP_CACHE.put(typedIngredient, Boolean.TRUE); - ErrorUtil.logIngredientCrash(e, "Caught an error getting an Ingredient's tooltip", ingredientManager, typedIngredient); + CRASHING_INGREDIENT_TOOLTIPS.add(ingredient); + ErrorUtil.logIngredientCrash(e, "Caught an error getting an Ingredient's tooltip", ingredientManager, typedIngredient.getType(), ingredient); getTooltipErrorTooltip(tooltip); } } @@ -78,6 +79,31 @@ private static void getRenderErrorTooltip(ITooltipBuilder tooltip) { tooltip.add(crash.withStyle(ChatFormatting.RED)); } + public static void renderBatch( + GuiGraphics guiGraphics, + IIngredientType ingredientType, + IIngredientRenderer ingredientRenderer, + List> elements + ) { + if (CRASHING_INGREDIENT_BATCH_RENDERERS.contains(ingredientRenderer)) { + for (BatchRenderElement element : elements) { + render(guiGraphics, ingredientRenderer, ingredientType, element); + } + return; + } + + try { + ingredientRenderer.renderBatch(guiGraphics, elements); + } catch (RuntimeException | LinkageError e) { + CRASHING_INGREDIENT_BATCH_RENDERERS.add(ingredientRenderer); + LOGGER.error( + "Caught an error while rendering a batch of Ingredients with ingredient renderer: {}", + ingredientRenderer.getClass(), + e + ); + } + } + public static void render( GuiGraphics guiGraphics, IIngredientRenderer ingredientRenderer, @@ -85,23 +111,42 @@ public static void render( int x, int y ) { - if (CRASHING_INGREDIENT_RENDER_CACHE.getIfPresent(typedIngredient) == Boolean.TRUE) { + render(guiGraphics, ingredientRenderer, typedIngredient.getType(), typedIngredient.getIngredient(), x, y); + } + + public static void render( + GuiGraphics guiGraphics, + IIngredientRenderer ingredientRenderer, + IIngredientType ingredientType, + BatchRenderElement element + ) { + render(guiGraphics, ingredientRenderer, ingredientType, element.ingredient(), element.x(), element.y()); + } + + public static void render( + GuiGraphics guiGraphics, + IIngredientRenderer ingredientRenderer, + IIngredientType ingredientType, + T ingredient, + int x, + int y + ) { + if (CRASHING_INGREDIENT_RENDERERS.contains(ingredient)) { renderError(guiGraphics); return; } - T ingredient = typedIngredient.getIngredient(); try { ingredientRenderer.render(guiGraphics, ingredient, x, y); } catch (RuntimeException | LinkageError e) { - CRASHING_INGREDIENT_RENDER_CACHE.put(typedIngredient, Boolean.TRUE); + CRASHING_INGREDIENT_RENDERERS.add(ingredient); IIngredientManager ingredientManager = Internal.getJeiRuntime().getIngredientManager(); if (shouldCatchRenderErrors()) { - ErrorUtil.logIngredientCrash(e, "Caught an error rendering an Ingredient", ingredientManager, typedIngredient); + ErrorUtil.logIngredientCrash(e, "Caught an error rendering an Ingredient", ingredientManager, ingredientType, ingredient); renderError(guiGraphics); } else { - CrashReport crashReport = ErrorUtil.createIngredientCrashReport(e, "Rendering ingredient", ingredientManager, typedIngredient); + CrashReport crashReport = ErrorUtil.createIngredientCrashReport(e, "Rendering ingredient", ingredientManager, ingredientType, ingredient); throw new ReportedException(crashReport); } } diff --git a/CommonApi/src/main/java/mezz/jei/api/ingredients/IIngredientRenderer.java b/CommonApi/src/main/java/mezz/jei/api/ingredients/IIngredientRenderer.java index 0d51614b3..bb8c8a0e5 100644 --- a/CommonApi/src/main/java/mezz/jei/api/ingredients/IIngredientRenderer.java +++ b/CommonApi/src/main/java/mezz/jei/api/ingredients/IIngredientRenderer.java @@ -1,17 +1,17 @@ package mezz.jei.api.ingredients; -import java.util.Collection; -import java.util.List; - import com.mojang.blaze3d.vertex.PoseStack; import mezz.jei.api.gui.builder.ITooltipBuilder; +import mezz.jei.api.ingredients.rendering.BatchRenderElement; +import mezz.jei.api.registration.IModIngredientRegistration; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; import net.minecraft.world.item.TooltipFlag; -import mezz.jei.api.registration.IModIngredientRegistration; -import net.minecraft.network.chat.Component; +import java.util.Collection; +import java.util.List; /** * Renders a type of ingredient in JEI's item list and recipes. @@ -51,6 +51,18 @@ default void render(GuiGraphics guiGraphics, T ingredient, int posX, int posY) { poseStack.popPose(); } + /** + * Render a batch of ingredients. + * Implementing this is not necessary, but can be used to optimize rendering many ingredients at once. + * + * @since 15.16.0 + */ + default void renderBatch(GuiGraphics guiGraphics, List> elements) { + for (BatchRenderElement element : elements) { + render(guiGraphics, element.ingredient(), element.x(), element.y()); + } + } + /** * Get the tooltip text for this ingredient. JEI renders the tooltip based on this. * diff --git a/CommonApi/src/main/java/mezz/jei/api/ingredients/rendering/BatchRenderElement.java b/CommonApi/src/main/java/mezz/jei/api/ingredients/rendering/BatchRenderElement.java new file mode 100644 index 000000000..133f4e2aa --- /dev/null +++ b/CommonApi/src/main/java/mezz/jei/api/ingredients/rendering/BatchRenderElement.java @@ -0,0 +1,15 @@ +package mezz.jei.api.ingredients.rendering; + +import mezz.jei.api.ingredients.IIngredientRenderer; +import net.minecraft.client.gui.GuiGraphics; + +import java.util.List; + +/** + * A single ingredient to render in a batch render operation. + * + * @see IIngredientRenderer#renderBatch(GuiGraphics, List) + * + * @since 15.16.0 + */ +public record BatchRenderElement(T ingredient, int x, int y) {} diff --git a/CommonApi/src/main/java/mezz/jei/api/ingredients/rendering/package-info.java b/CommonApi/src/main/java/mezz/jei/api/ingredients/rendering/package-info.java new file mode 100644 index 000000000..2bd39d39c --- /dev/null +++ b/CommonApi/src/main/java/mezz/jei/api/ingredients/rendering/package-info.java @@ -0,0 +1,7 @@ +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +package mezz.jei.api.ingredients.rendering; + +import net.minecraft.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/CommonApi/src/main/java/mezz/jei/api/recipe/IRecipeManager.java b/CommonApi/src/main/java/mezz/jei/api/recipe/IRecipeManager.java index 24efd698f..9303602cf 100644 --- a/CommonApi/src/main/java/mezz/jei/api/recipe/IRecipeManager.java +++ b/CommonApi/src/main/java/mezz/jei/api/recipe/IRecipeManager.java @@ -191,7 +191,6 @@ IRecipeSlotDrawable createRecipeSlotDrawable( * * @see RecipeType#getUid() * @since 11.2.3 - * @deprecated use {@link #getRecipeType(ResourceLocation, Class)} */ Optional> getRecipeType(ResourceLocation recipeUid); } diff --git a/Forge/src/test/java/mezz/jei/test/lib/TestClientToggleState.java b/Forge/src/test/java/mezz/jei/test/lib/TestClientToggleState.java index 6dec937a9..575ac7303 100644 --- a/Forge/src/test/java/mezz/jei/test/lib/TestClientToggleState.java +++ b/Forge/src/test/java/mezz/jei/test/lib/TestClientToggleState.java @@ -55,6 +55,6 @@ public void setBookmarkEnabled(boolean value) { @Override public void addEditModeToggleListener(IEditModeListener listener) { - + } } diff --git a/Gui/src/main/java/mezz/jei/gui/bookmarks/RecipeBookmark.java b/Gui/src/main/java/mezz/jei/gui/bookmarks/RecipeBookmark.java index 60a7be1a5..a335b550e 100644 --- a/Gui/src/main/java/mezz/jei/gui/bookmarks/RecipeBookmark.java +++ b/Gui/src/main/java/mezz/jei/gui/bookmarks/RecipeBookmark.java @@ -1,18 +1,14 @@ package mezz.jei.gui.bookmarks; import mezz.jei.api.gui.IRecipeLayoutDrawable; -import mezz.jei.api.gui.drawable.IDrawable; import mezz.jei.api.gui.ingredient.IRecipeSlotView; import mezz.jei.api.gui.ingredient.IRecipeSlotsView; -import mezz.jei.api.helpers.IGuiHelper; import mezz.jei.api.ingredients.ITypedIngredient; -import mezz.jei.api.recipe.IRecipeManager; import mezz.jei.api.recipe.RecipeIngredientRole; import mezz.jei.api.recipe.category.IRecipeCategory; import mezz.jei.api.runtime.IIngredientManager; import mezz.jei.gui.overlay.elements.IElement; import mezz.jei.gui.overlay.elements.RecipeBookmarkElement; -import mezz.jei.gui.recipes.RecipeCategoryIconUtil; import net.minecraft.resources.ResourceLocation; import java.util.List; @@ -28,9 +24,7 @@ public class RecipeBookmark implements IBookmark { public static Optional> create( IRecipeLayoutDrawable recipeLayoutDrawable, - IIngredientManager ingredientManager, - IRecipeManager recipeManager, - IGuiHelper guiHelper + IIngredientManager ingredientManager ) { T recipe = recipeLayoutDrawable.getRecipe(); IRecipeCategory recipeCategory = recipeLayoutDrawable.getRecipeCategory(); @@ -47,13 +41,8 @@ public class RecipeBookmark implements IBookmark { continue; } ITypedIngredient output = outputOptional.get(); - IDrawable icon = RecipeCategoryIconUtil.create( - recipeCategory, - recipeManager, - guiHelper - ); output = ingredientManager.normalizeTypedIngredient(output); - return Optional.of(new RecipeBookmark<>(recipeCategory, recipe, recipeUid, output, icon)); + return Optional.of(new RecipeBookmark<>(recipeCategory, recipe, recipeUid, output)); } return Optional.empty(); } @@ -62,14 +51,13 @@ public RecipeBookmark( IRecipeCategory recipeCategory, R recipe, ResourceLocation recipeUid, - ITypedIngredient recipeOutput, - IDrawable icon + ITypedIngredient recipeOutput ) { this.recipeCategory = recipeCategory; this.recipe = recipe; this.recipeUid = recipeUid; this.recipeOutput = recipeOutput; - this.element = new RecipeBookmarkElement<>(this, icon); + this.element = new RecipeBookmarkElement<>(this); } public IRecipeCategory getRecipeCategory() { diff --git a/Gui/src/main/java/mezz/jei/gui/config/BookmarkConfig.java b/Gui/src/main/java/mezz/jei/gui/config/BookmarkConfig.java index a188bd6c2..dc69dfa57 100644 --- a/Gui/src/main/java/mezz/jei/gui/config/BookmarkConfig.java +++ b/Gui/src/main/java/mezz/jei/gui/config/BookmarkConfig.java @@ -73,7 +73,7 @@ public void saveBookmarks( getPath(jeiConfigurationDir) .ifPresent(path -> { TypedIngredientSerializer ingredientSerializer = new TypedIngredientSerializer(ingredientManager); - RecipeBookmarkSerializer recipeBookmarkSerializer = new RecipeBookmarkSerializer(recipeManager, focusFactory, ingredientSerializer, guiHelper); + RecipeBookmarkSerializer recipeBookmarkSerializer = new RecipeBookmarkSerializer(recipeManager, focusFactory, ingredientSerializer); List strings = new ArrayList<>(); for (IBookmark bookmark : bookmarks) { @@ -123,7 +123,7 @@ public void loadBookmarks( } TypedIngredientSerializer ingredientSerializer = new TypedIngredientSerializer(ingredientManager); - RecipeBookmarkSerializer recipeBookmarkSerializer = new RecipeBookmarkSerializer(recipeManager, focusFactory, ingredientSerializer, guiHelper); + RecipeBookmarkSerializer recipeBookmarkSerializer = new RecipeBookmarkSerializer(recipeManager, focusFactory, ingredientSerializer); Collection> otherIngredientTypes = ingredientManager.getRegisteredIngredientTypes() .stream() diff --git a/Gui/src/main/java/mezz/jei/gui/config/file/serializers/RecipeBookmarkSerializer.java b/Gui/src/main/java/mezz/jei/gui/config/file/serializers/RecipeBookmarkSerializer.java index d806ff2e4..dbc8fda13 100644 --- a/Gui/src/main/java/mezz/jei/gui/config/file/serializers/RecipeBookmarkSerializer.java +++ b/Gui/src/main/java/mezz/jei/gui/config/file/serializers/RecipeBookmarkSerializer.java @@ -1,7 +1,5 @@ package mezz.jei.gui.config.file.serializers; -import mezz.jei.api.gui.drawable.IDrawable; -import mezz.jei.api.helpers.IGuiHelper; import mezz.jei.api.ingredients.ITypedIngredient; import mezz.jei.api.recipe.IFocus; import mezz.jei.api.recipe.IFocusFactory; @@ -14,7 +12,6 @@ import mezz.jei.common.config.file.serializers.TypedIngredientSerializer; import mezz.jei.gui.bookmarks.RecipeBookmark; import mezz.jei.gui.overlay.elements.IElement; -import mezz.jei.gui.recipes.RecipeCategoryIconUtil; import net.minecraft.resources.ResourceLocation; import java.util.Collection; @@ -28,18 +25,15 @@ public class RecipeBookmarkSerializer implements IJeiConfigValueSerializer value) { } T recipe = recipeResult.get(); - IDrawable icon = RecipeCategoryIconUtil.create( - recipeCategory, - recipeManager, - guiHelper - ); - RecipeBookmark recipeBookmark = new RecipeBookmark<>(recipeCategory, recipe, recipeUid, output, icon); + RecipeBookmark recipeBookmark = new RecipeBookmark<>(recipeCategory, recipe, recipeUid, output); return new DeserializeResult<>(recipeBookmark); } diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/IngredientGrid.java b/Gui/src/main/java/mezz/jei/gui/overlay/IngredientGrid.java index a29e699ba..a20c1453e 100644 --- a/Gui/src/main/java/mezz/jei/gui/overlay/IngredientGrid.java +++ b/Gui/src/main/java/mezz/jei/gui/overlay/IngredientGrid.java @@ -2,12 +2,16 @@ import com.mojang.blaze3d.systems.RenderSystem; import mezz.jei.api.helpers.IColorHelper; +import mezz.jei.api.ingredients.IIngredientHelper; +import mezz.jei.api.ingredients.IIngredientRenderer; import mezz.jei.api.ingredients.IIngredientType; +import mezz.jei.api.ingredients.ITypedIngredient; import mezz.jei.api.runtime.IIngredientManager; import mezz.jei.common.config.IClientConfig; import mezz.jei.common.config.IClientToggleState; import mezz.jei.common.config.IIngredientFilterConfig; import mezz.jei.common.config.IIngredientGridConfig; +import mezz.jei.common.gui.JeiTooltip; import mezz.jei.common.input.IInternalKeyMappings; import mezz.jei.common.network.IConnectionToServer; import mezz.jei.common.util.ImmutablePoint2i; @@ -42,6 +46,7 @@ public class IngredientGrid implements IRecipeFocusSource, IIngredientGrid { public static final int INGREDIENT_WIDTH = GuiIngredientProperties.getWidth(INGREDIENT_PADDING); public static final int INGREDIENT_HEIGHT = GuiIngredientProperties.getHeight(INGREDIENT_PADDING); + private final IIngredientManager ingredientManager; private final IIngredientGridConfig gridConfig; private final IngredientListRenderer ingredientListRenderer; private final DeleteItemInputHandler deleteItemHandler; @@ -57,10 +62,12 @@ public IngredientGrid( IClientToggleState toggleState, IConnectionToServer serverConnection, IInternalKeyMappings keyBindings, - IColorHelper colorHelper + IColorHelper colorHelper, + boolean supportsEditMode ) { + this.ingredientManager = ingredientManager; this.gridConfig = gridConfig; - this.ingredientListRenderer = new IngredientListRenderer(); + this.ingredientListRenderer = new IngredientListRenderer(ingredientManager, supportsEditMode); this.tooltipHelper = new IngredientGridTooltipHelper(ingredientManager, ingredientFilterConfig, toggleState, keyBindings, colorHelper); this.deleteItemHandler = new DeleteItemInputHandler(this, toggleState, clientConfig, serverConnection, ingredientManager); } @@ -145,7 +152,7 @@ public void draw(Minecraft minecraft, GuiGraphics guiGraphics, int mouseX, int m if (!this.deleteItemHandler.shouldDeleteItemOnClick(minecraft, mouseX, mouseY)) { ingredientListRenderer.getSlots() .filter(s -> s.getArea().contains(mouseX, mouseY)) - .filter(s -> s.getElement().isPresent()) + .filter(s -> s.getOptionalElement().isPresent()) .findFirst() .ifPresent(s -> drawHighlight(guiGraphics, s.getArea())); } @@ -176,13 +183,27 @@ public void drawTooltips(Minecraft minecraft, GuiGraphics guiGraphics, int mouse } else { ingredientListRenderer.getSlots() .filter(s -> s.isMouseOver(mouseX, mouseY)) - .filter(s -> s.getElement().isPresent()) + .map(IngredientListSlot::getOptionalElement) + .flatMap(Optional::stream) .findFirst() - .ifPresent(s -> s.drawTooltip(guiGraphics, mouseX, mouseY, tooltipHelper)); + .ifPresent(element -> { + drawTooltip(guiGraphics, mouseX, mouseY, element); + }); } } } + private void drawTooltip(GuiGraphics guiGraphics, int mouseX, int mouseY, IElement element) { + ITypedIngredient typedIngredient = element.getTypedIngredient(); + IIngredientType ingredientType = typedIngredient.getType(); + IIngredientRenderer ingredientRenderer = ingredientManager.getIngredientRenderer(ingredientType); + IIngredientHelper ingredientHelper = ingredientManager.getIngredientHelper(ingredientType); + + JeiTooltip tooltip = new JeiTooltip(); + element.getTooltip(tooltip, tooltipHelper, ingredientRenderer, ingredientHelper); + tooltip.draw(guiGraphics, mouseX, mouseY, typedIngredient, ingredientRenderer, ingredientManager); + } + @Override public boolean isMouseOver(double mouseX, double mouseY) { return area.contains(mouseX, mouseY) && @@ -212,7 +233,7 @@ public Stream getSlots() { public Stream getVisibleIngredients(IIngredientType ingredientType) { return this.ingredientListRenderer.getSlots() - .map(IngredientListSlot::getElement) + .map(IngredientListSlot::getOptionalElement) .flatMap(Optional::stream) .map(IElement::getTypedIngredient) .map(i -> i.getIngredient(ingredientType)) diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/IngredientListRenderer.java b/Gui/src/main/java/mezz/jei/gui/overlay/IngredientListRenderer.java index f51b1ce62..c5cfc5608 100644 --- a/Gui/src/main/java/mezz/jei/gui/overlay/IngredientListRenderer.java +++ b/Gui/src/main/java/mezz/jei/gui/overlay/IngredientListRenderer.java @@ -1,30 +1,50 @@ package mezz.jei.gui.overlay; +import com.mojang.blaze3d.systems.RenderSystem; +import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.api.ingredients.IIngredientRenderer; import mezz.jei.api.ingredients.IIngredientType; import mezz.jei.api.ingredients.ITypedIngredient; -import mezz.jei.gui.overlay.elements.ElementRenderer; -import mezz.jei.gui.overlay.elements.ElementRenderers; +import mezz.jei.api.ingredients.rendering.BatchRenderElement; +import mezz.jei.api.runtime.IEditModeConfig; +import mezz.jei.api.runtime.IIngredientManager; +import mezz.jei.common.Internal; +import mezz.jei.common.gui.elements.OffsetDrawable; +import mezz.jei.common.util.ImmutableRect2i; +import mezz.jei.common.util.SafeIngredientUtil; +import mezz.jei.core.collect.ListMultiMap; import mezz.jei.gui.overlay.elements.IElement; -import mezz.jei.gui.overlay.elements.RenderableElement; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.RenderType; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; +import java.util.Map; +import java.util.Set; import java.util.stream.Stream; public class IngredientListRenderer { + private static final int BLACKLIST_COLOR = 0xDDFF0000; + private static final int WILDCARD_BLACKLIST_COLOR = 0xDDFFA500; + private final List slots = new ArrayList<>(); - private final ElementRenderers elementRenderers; + private final ListMultiMap, BatchRenderElement> renderElementsByType = new ListMultiMap<>(); + private final List renderOverlays = new ArrayList<>(); + private final IIngredientManager ingredientManager; + private final boolean supportsEditMode; private int blocked = 0; - public IngredientListRenderer() { - this.elementRenderers = new ElementRenderers(); + public IngredientListRenderer(IIngredientManager ingredientManager, boolean supportsEditMode) { + this.ingredientManager = ingredientManager; + this.supportsEditMode = supportsEditMode; } public void clear() { slots.clear(); + renderElementsByType.clear(); + renderOverlays.clear(); blocked = 0; } @@ -34,6 +54,22 @@ public int size() { public void add(IngredientListSlot ingredientListSlot) { slots.add(ingredientListSlot); + addRenderElement(ingredientListSlot); + } + + private void addRenderElement(IngredientListSlot ingredientListSlot) { + ingredientListSlot.getOptionalElement() + .ifPresent(element -> { + ITypedIngredient typedIngredient = element.getTypedIngredient(); + IIngredientType ingredientType = typedIngredient.getType(); + ImmutableRect2i renderArea = ingredientListSlot.getRenderArea(); + BatchRenderElement batchRenderElement = new BatchRenderElement<>(typedIngredient.getIngredient(), renderArea.x(), renderArea.y()); + renderElementsByType.put(ingredientType, batchRenderElement); + IDrawable renderOverlay = element.createRenderOverlay(); + if (renderOverlay != null) { + renderOverlays.add(OffsetDrawable.create(renderOverlay, renderArea.x(), renderArea.y())); + } + }); } public Stream getSlots() { @@ -43,6 +79,8 @@ public Stream getSlots() { public void set(final int startIndex, List> ingredientList) { blocked = 0; + renderElementsByType.clear(); + renderOverlays.clear(); ListIterator> elementIterator = ingredientList.listIterator(startIndex); @@ -56,8 +94,8 @@ public void set(final int startIndex, List> ingredientList) { element = elementIterator.next(); } if (element.isVisible()) { - RenderableElement renderableElement = createRenderableElement(element); - ingredientListSlot.setElement(renderableElement); + ingredientListSlot.setElement(element); + addRenderElement(ingredientListSlot); } else { ingredientListSlot.clear(); } @@ -67,16 +105,66 @@ public void set(final int startIndex, List> ingredientList) { } } - private RenderableElement createRenderableElement(IElement element) { - ITypedIngredient typedIngredient = element.getTypedIngredient(); - IIngredientType type = typedIngredient.getType(); - ElementRenderer renderer = elementRenderers.get(type); - return new RenderableElement<>(element, renderer); + public void render(GuiGraphics guiGraphics) { + if (supportsEditMode && Internal.getClientToggleState().isEditModeEnabled()) { + renderEditMode(guiGraphics); + } + + for (Map.Entry, List>> entry : renderElementsByType.entrySet()) { + renderBatch(guiGraphics, entry); + } + + for (IDrawable overlay : renderOverlays) { + overlay.draw(guiGraphics); + } + } + + private void renderBatch(GuiGraphics guiGraphics, Map.Entry, List>> entry) { + @SuppressWarnings("unchecked") + IIngredientType type = (IIngredientType) entry.getKey(); + IIngredientRenderer ingredientRenderer = ingredientManager.getIngredientRenderer(type); + @SuppressWarnings("unchecked") + List> elements = (List>) (Object) entry.getValue(); + SafeIngredientUtil.renderBatch(guiGraphics, type, ingredientRenderer, elements); } - public void render(GuiGraphics guiGraphics) { + private void renderEditMode(GuiGraphics guiGraphics) { + IEditModeConfig editModeConfig = Internal.getJeiRuntime().getEditModeConfig(); + for (IngredientListSlot slot : slots) { - slot.render(guiGraphics); + slot.getOptionalElement() + .ifPresent(element -> { + renderEditMode(guiGraphics, slot.getArea(), slot.getPadding(), element.getTypedIngredient(), editModeConfig); + }); + } + + RenderSystem.enableBlend(); + } + + private static void renderEditMode(GuiGraphics guiGraphics, ImmutableRect2i area, int padding, ITypedIngredient typedIngredient, IEditModeConfig config) { + Set hideModes = config.getIngredientHiddenUsingConfigFile(typedIngredient); + if (!hideModes.isEmpty()) { + if (hideModes.contains(IEditModeConfig.HideMode.WILDCARD)) { + guiGraphics.fill( + RenderType.guiOverlay(), + area.getX() + padding, + area.getY() + padding, + area.getX() + 16 + padding, + area.getY() + 16 + padding, + WILDCARD_BLACKLIST_COLOR + ); + } + if (hideModes.contains(IEditModeConfig.HideMode.SINGLE)) { + guiGraphics.fill( + RenderType.guiOverlay(), + area.getX() + padding, + area.getY() + padding, + area.getX() + 16 + padding, + area.getY() + 16 + padding, + BLACKLIST_COLOR + ); + } + RenderSystem.setShaderColor(1f, 1f, 1f, 1f); } } } diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/IngredientListSlot.java b/Gui/src/main/java/mezz/jei/gui/overlay/IngredientListSlot.java index 5f2a8a4e6..80eb1b2b1 100644 --- a/Gui/src/main/java/mezz/jei/gui/overlay/IngredientListSlot.java +++ b/Gui/src/main/java/mezz/jei/gui/overlay/IngredientListSlot.java @@ -6,8 +6,6 @@ import mezz.jei.gui.input.IClickableIngredientInternal; import mezz.jei.gui.input.IDraggableIngredientInternal; import mezz.jei.gui.overlay.elements.IElement; -import mezz.jei.gui.overlay.elements.RenderableElement; -import net.minecraft.client.gui.GuiGraphics; import org.jetbrains.annotations.Nullable; import java.util.Optional; @@ -17,52 +15,51 @@ public class IngredientListSlot { private final int padding; private boolean blocked = false; @Nullable - private RenderableElement renderableElement; + private IElement element; public IngredientListSlot(int xPosition, int yPosition, int width, int height, int padding) { this.area = new ImmutableRect2i(xPosition, yPosition, width, height); this.padding = padding; } - public Optional> getElement() { - return Optional.ofNullable(renderableElement) - .map(RenderableElement::getElement); + public Optional> getOptionalElement() { + return Optional.ofNullable(element); + } + + public @Nullable IElement getElement() { + return element; } public Optional> getClickableIngredient() { - return Optional.ofNullable(renderableElement) - .map(RenderableElement::getElement) + return Optional.ofNullable(element) .map(element -> new ClickableIngredientInternal<>(element, this::isMouseOver, true, true)); } public Optional> getDraggableIngredient() { - return Optional.ofNullable(renderableElement) - .map(RenderableElement::getElement) + return Optional.ofNullable(element) .map(element -> new DraggableIngredientInternal<>(element, area)); } - public void render(GuiGraphics guiGraphics) { - if (!blocked && renderableElement != null) { - renderableElement.render(guiGraphics, area, padding); - } - } - public void clear() { - this.renderableElement = null; + this.element = null; } public boolean isMouseOver(double mouseX, double mouseY) { - return (this.renderableElement != null) && area.contains(mouseX, mouseY); + return (this.element != null) && area.contains(mouseX, mouseY); } - public void setElement(RenderableElement renderableElement) { - this.renderableElement = renderableElement; + public void setElement(IElement element) { + this.element = element; } public ImmutableRect2i getArea() { return area; } + public ImmutableRect2i getRenderArea() { + return area.insetBy(padding); + } + /** * Set true if this ingredient is blocked by an extra gui area from a mod. */ @@ -74,9 +71,7 @@ public boolean isBlocked() { return blocked; } - public void drawTooltip(GuiGraphics guiGraphics, int mouseX, int mouseY, IngredientGridTooltipHelper tooltipHelper) { - if (renderableElement != null) { - renderableElement.drawTooltip(guiGraphics, mouseX, mouseY, tooltipHelper); - } + public int getPadding() { + return padding; } } diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/BookmarkOverlay.java b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/BookmarkOverlay.java index 50c4eb865..320263859 100644 --- a/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/BookmarkOverlay.java +++ b/Gui/src/main/java/mezz/jei/gui/overlay/bookmarks/BookmarkOverlay.java @@ -258,7 +258,7 @@ public List createBookmarkDragTargets() { } private Optional createDragTarget(IngredientListSlot ingredientListSlot) { - return ingredientListSlot.getElement() + return ingredientListSlot.getOptionalElement() .flatMap(IElement::getBookmark) .map(bookmark -> new DragTarget(ingredientListSlot.getArea(), bookmark, bookmarkList, 0)); } diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/elements/ElementRenderer.java b/Gui/src/main/java/mezz/jei/gui/overlay/elements/ElementRenderer.java deleted file mode 100644 index 44ba713d9..000000000 --- a/Gui/src/main/java/mezz/jei/gui/overlay/elements/ElementRenderer.java +++ /dev/null @@ -1,86 +0,0 @@ -package mezz.jei.gui.overlay.elements; - -import com.mojang.blaze3d.systems.RenderSystem; -import mezz.jei.api.ingredients.IIngredientHelper; -import mezz.jei.api.ingredients.IIngredientRenderer; -import mezz.jei.api.ingredients.IIngredientType; -import mezz.jei.api.ingredients.ITypedIngredient; -import mezz.jei.api.runtime.IEditModeConfig; -import mezz.jei.api.runtime.IIngredientManager; -import mezz.jei.common.Internal; -import mezz.jei.common.gui.JeiTooltip; -import mezz.jei.common.util.ImmutableRect2i; -import mezz.jei.common.util.SafeIngredientUtil; -import mezz.jei.gui.overlay.IngredientGridTooltipHelper; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.renderer.RenderType; - -import java.util.Set; - -public class ElementRenderer implements IElementRenderer { - private static final int BLACKLIST_COLOR = 0xDDFF0000; - private static final int WILDCARD_BLACKLIST_COLOR = 0xDDFFA500; - - private final IIngredientRenderer ingredientRenderer; - - public ElementRenderer(IIngredientType ingredientType) { - IIngredientManager ingredientManager = Internal.getJeiRuntime().getIngredientManager(); - this.ingredientRenderer = ingredientManager.getIngredientRenderer(ingredientType); - } - - @Override - public void render(GuiGraphics guiGraphics, IElement element, ImmutableRect2i area, int padding) { - ITypedIngredient typedIngredient = element.getTypedIngredient(); - if (Internal.getClientToggleState().isEditModeEnabled()) { - renderEditMode(guiGraphics, area, padding, typedIngredient); - RenderSystem.enableBlend(); - } - - int xPosition = area.getX() + padding; - int yPosition = area.getY() + padding; - SafeIngredientUtil.render(guiGraphics, ingredientRenderer, typedIngredient, xPosition, yPosition); - element.renderExtras(guiGraphics, xPosition, yPosition); - } - - private static void renderEditMode(GuiGraphics guiGraphics, ImmutableRect2i area, int padding, ITypedIngredient typedIngredient) { - IEditModeConfig editModeConfig = Internal.getJeiRuntime().getEditModeConfig(); - Set hideModes = editModeConfig.getIngredientHiddenUsingConfigFile(typedIngredient); - if (!hideModes.isEmpty()) { - if (hideModes.contains(IEditModeConfig.HideMode.WILDCARD)) { - guiGraphics.fill( - RenderType.guiOverlay(), - area.getX() + padding, - area.getY() + padding, - area.getX() + 16 + padding, - area.getY() + 16 + padding, - WILDCARD_BLACKLIST_COLOR - ); - } - if (hideModes.contains(IEditModeConfig.HideMode.SINGLE)) { - guiGraphics.fill( - RenderType.guiOverlay(), - area.getX() + padding, - area.getY() + padding, - area.getX() + 16 + padding, - area.getY() + 16 + padding, - BLACKLIST_COLOR - ); - } - RenderSystem.setShaderColor(1f, 1f, 1f, 1f); - } - } - - @Override - public void drawTooltip(GuiGraphics guiGraphics, int mouseX, int mouseY, IngredientGridTooltipHelper tooltipHelper, IElement element) { - IIngredientManager ingredientManager = Internal.getJeiRuntime().getIngredientManager(); - - ITypedIngredient typedIngredient = element.getTypedIngredient(); - IIngredientType ingredientType = typedIngredient.getType(); - IIngredientRenderer ingredientRenderer = ingredientManager.getIngredientRenderer(ingredientType); - IIngredientHelper ingredientHelper = ingredientManager.getIngredientHelper(ingredientType); - - JeiTooltip tooltip = new JeiTooltip(); - element.getTooltip(tooltip, tooltipHelper, ingredientRenderer, ingredientHelper); - tooltip.draw(guiGraphics, mouseX, mouseY, typedIngredient, ingredientRenderer, ingredientManager); - } -} diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/elements/ElementRenderers.java b/Gui/src/main/java/mezz/jei/gui/overlay/elements/ElementRenderers.java deleted file mode 100644 index 31fcde5fd..000000000 --- a/Gui/src/main/java/mezz/jei/gui/overlay/elements/ElementRenderers.java +++ /dev/null @@ -1,20 +0,0 @@ -package mezz.jei.gui.overlay.elements; - -import mezz.jei.api.ingredients.IIngredientType; - -import java.util.HashMap; -import java.util.Map; - -public class ElementRenderers { - private final Map, ElementRenderer> map = new HashMap<>(); - - public ElementRenderer get(IIngredientType ingredientType) { - @SuppressWarnings("unchecked") - ElementRenderer result = (ElementRenderer) this.map.get(ingredientType); - if (result == null) { - result = new ElementRenderer<>(ingredientType); - this.map.put(ingredientType, result); - } - return result; - } -} diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/elements/IElement.java b/Gui/src/main/java/mezz/jei/gui/overlay/elements/IElement.java index 7b2375026..a29441563 100644 --- a/Gui/src/main/java/mezz/jei/gui/overlay/elements/IElement.java +++ b/Gui/src/main/java/mezz/jei/gui/overlay/elements/IElement.java @@ -1,5 +1,6 @@ package mezz.jei.gui.overlay.elements; +import mezz.jei.api.gui.drawable.IDrawable; import mezz.jei.api.ingredients.IIngredientHelper; import mezz.jei.api.ingredients.IIngredientRenderer; import mezz.jei.api.ingredients.ITypedIngredient; @@ -11,7 +12,7 @@ import mezz.jei.gui.input.UserInput; import mezz.jei.gui.overlay.IngredientGridTooltipHelper; import mezz.jei.gui.util.FocusUtil; -import net.minecraft.client.gui.GuiGraphics; +import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.Optional; @@ -24,7 +25,8 @@ public interface IElement { */ Optional getBookmark(); - void renderExtras(GuiGraphics guiGraphics, int xPosition, int yPosition); + @Nullable + IDrawable createRenderOverlay(); void show(IRecipesGui recipesGui, FocusUtil focusUtil, List roles); diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/elements/IElementRenderer.java b/Gui/src/main/java/mezz/jei/gui/overlay/elements/IElementRenderer.java deleted file mode 100644 index 31691dd7b..000000000 --- a/Gui/src/main/java/mezz/jei/gui/overlay/elements/IElementRenderer.java +++ /dev/null @@ -1,11 +0,0 @@ -package mezz.jei.gui.overlay.elements; - -import mezz.jei.common.util.ImmutableRect2i; -import mezz.jei.gui.overlay.IngredientGridTooltipHelper; -import net.minecraft.client.gui.GuiGraphics; - -public interface IElementRenderer { - void render(GuiGraphics guiGraphics, IElement element, ImmutableRect2i area, int padding); - - void drawTooltip(GuiGraphics guiGraphics, int mouseX, int mouseY, IngredientGridTooltipHelper tooltipHelper, IElement element); -} diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/elements/IngredientBookmarkElement.java b/Gui/src/main/java/mezz/jei/gui/overlay/elements/IngredientBookmarkElement.java index 5788116e8..371741f30 100644 --- a/Gui/src/main/java/mezz/jei/gui/overlay/elements/IngredientBookmarkElement.java +++ b/Gui/src/main/java/mezz/jei/gui/overlay/elements/IngredientBookmarkElement.java @@ -1,5 +1,6 @@ package mezz.jei.gui.overlay.elements; +import mezz.jei.api.gui.drawable.IDrawable; import mezz.jei.api.ingredients.IIngredientHelper; import mezz.jei.api.ingredients.IIngredientRenderer; import mezz.jei.api.ingredients.ITypedIngredient; @@ -11,7 +12,7 @@ import mezz.jei.gui.bookmarks.IngredientBookmark; import mezz.jei.gui.overlay.IngredientGridTooltipHelper; import mezz.jei.gui.util.FocusUtil; -import net.minecraft.client.gui.GuiGraphics; +import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.Optional; @@ -34,8 +35,8 @@ public Optional getBookmark() { } @Override - public void renderExtras(GuiGraphics guiGraphics, int xPosition, int yPosition) { - + public @Nullable IDrawable createRenderOverlay() { + return null; } @Override diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/elements/IngredientElement.java b/Gui/src/main/java/mezz/jei/gui/overlay/elements/IngredientElement.java index b6c0284f1..576eeec1d 100644 --- a/Gui/src/main/java/mezz/jei/gui/overlay/elements/IngredientElement.java +++ b/Gui/src/main/java/mezz/jei/gui/overlay/elements/IngredientElement.java @@ -1,5 +1,6 @@ package mezz.jei.gui.overlay.elements; +import mezz.jei.api.gui.drawable.IDrawable; import mezz.jei.api.ingredients.IIngredientHelper; import mezz.jei.api.ingredients.IIngredientRenderer; import mezz.jei.api.ingredients.ITypedIngredient; @@ -10,7 +11,7 @@ import mezz.jei.gui.bookmarks.IBookmark; import mezz.jei.gui.overlay.IngredientGridTooltipHelper; import mezz.jei.gui.util.FocusUtil; -import net.minecraft.client.gui.GuiGraphics; +import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.Optional; @@ -33,8 +34,8 @@ public Optional getBookmark() { } @Override - public void renderExtras(GuiGraphics guiGraphics, int xPosition, int yPosition) { - + public @Nullable IDrawable createRenderOverlay() { + return null; } @Override diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/elements/RecipeBookmarkElement.java b/Gui/src/main/java/mezz/jei/gui/overlay/elements/RecipeBookmarkElement.java index 89798a3e1..cbe11e71b 100644 --- a/Gui/src/main/java/mezz/jei/gui/overlay/elements/RecipeBookmarkElement.java +++ b/Gui/src/main/java/mezz/jei/gui/overlay/elements/RecipeBookmarkElement.java @@ -3,6 +3,8 @@ import mezz.jei.api.gui.IRecipeLayoutDrawable; import mezz.jei.api.gui.drawable.IDrawable; import mezz.jei.api.gui.drawable.IScalableDrawable; +import mezz.jei.api.helpers.IGuiHelper; +import mezz.jei.api.helpers.IJeiHelpers; import mezz.jei.api.helpers.IModIdHelper; import mezz.jei.api.ingredients.IIngredientHelper; import mezz.jei.api.ingredients.IIngredientRenderer; @@ -31,6 +33,7 @@ import mezz.jei.gui.overlay.IngredientGridTooltipHelper; import mezz.jei.gui.overlay.bookmarks.IngredientsTooltipComponent; import mezz.jei.gui.overlay.bookmarks.PreviewTooltipComponent; +import mezz.jei.gui.recipes.RecipeCategoryIconUtil; import mezz.jei.gui.util.FocusUtil; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; @@ -51,15 +54,13 @@ public class RecipeBookmarkElement implements IElement { private final RecipeBookmark recipeBookmark; - private final IDrawable icon; private final IClientConfig clientConfig; private final EnumMap cache = new EnumMap<>(BookmarkTooltipFeature.class); @SuppressWarnings("OptionalUsedAsFieldOrParameterType") private @Nullable Optional> cachedLayoutDrawable; - public RecipeBookmarkElement(RecipeBookmark recipeBookmark, IDrawable icon) { + public RecipeBookmarkElement(RecipeBookmark recipeBookmark) { this.recipeBookmark = recipeBookmark; - this.icon = icon; this.clientConfig = Internal.getJeiClientConfigs().getClientConfig(); } @@ -74,18 +75,9 @@ public Optional getBookmark() { } @Override - public void renderExtras(GuiGraphics guiGraphics, int xPosition, int yPosition) { - var poseStack = guiGraphics.pose(); - poseStack.pushPose(); - { - // this z level seems to be the sweet spot so that - // 2D icons draw above the items, and - // 3D icons draw still draw under tooltips. - poseStack.translate(8 + xPosition, 8 + yPosition, 200); - poseStack.scale(0.5f, 0.5f, 0.5f); - icon.draw(guiGraphics); - } - poseStack.popPose(); + public IDrawable createRenderOverlay() { + IRecipeCategory recipeCategory = recipeBookmark.getRecipeCategory(); + return new RecipeBookmarkIcon(recipeCategory); } @Override @@ -260,4 +252,45 @@ private Optional> getRecipeLayoutDrawable() { public boolean isVisible() { return recipeBookmark.isVisible(); } + + private static class RecipeBookmarkIcon implements IDrawable { + private final IDrawable icon; + + public RecipeBookmarkIcon(IRecipeCategory recipeCategory) { + IJeiRuntime jeiRuntime = Internal.getJeiRuntime(); + IRecipeManager recipeManager = jeiRuntime.getRecipeManager(); + IJeiHelpers jeiHelpers = jeiRuntime.getJeiHelpers(); + IGuiHelper guiHelper = jeiHelpers.getGuiHelper(); + icon = RecipeCategoryIconUtil.create( + recipeCategory, + recipeManager, + guiHelper + ); + } + + @Override + public int getWidth() { + return 16; + } + + @Override + public int getHeight() { + return 16; + } + + @Override + public void draw(GuiGraphics guiGraphics, int xOffset, int yOffset) { + var poseStack = guiGraphics.pose(); + poseStack.pushPose(); + { + // this z level seems to be the sweet spot so that + // 2D icons draw above the items, and + // 3D icons draw still draw under tooltips. + poseStack.translate(8 + xOffset, 8 + yOffset, 200); + poseStack.scale(0.5f, 0.5f, 0.5f); + icon.draw(guiGraphics); + } + poseStack.popPose(); + } + } } diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/elements/RenderableElement.java b/Gui/src/main/java/mezz/jei/gui/overlay/elements/RenderableElement.java deleted file mode 100644 index 1496a76db..000000000 --- a/Gui/src/main/java/mezz/jei/gui/overlay/elements/RenderableElement.java +++ /dev/null @@ -1,27 +0,0 @@ -package mezz.jei.gui.overlay.elements; - -import mezz.jei.common.util.ImmutableRect2i; -import mezz.jei.gui.overlay.IngredientGridTooltipHelper; -import net.minecraft.client.gui.GuiGraphics; - -public class RenderableElement { - private final IElement element; - private final IElementRenderer renderer; - - public RenderableElement(IElement element, IElementRenderer renderer) { - this.element = element; - this.renderer = renderer; - } - - public void render(GuiGraphics guiGraphics, ImmutableRect2i area, int padding) { - renderer.render(guiGraphics, element, area, padding); - } - - public void drawTooltip(GuiGraphics guiGraphics, int mouseX, int mouseY, IngredientGridTooltipHelper tooltipHelper) { - renderer.drawTooltip(guiGraphics, mouseX, mouseY, tooltipHelper, element); - } - - public IElement getElement() { - return element; - } -} diff --git a/Gui/src/main/java/mezz/jei/gui/recipes/RecipeBookmarkButton.java b/Gui/src/main/java/mezz/jei/gui/recipes/RecipeBookmarkButton.java index ec4884158..4347d16e7 100644 --- a/Gui/src/main/java/mezz/jei/gui/recipes/RecipeBookmarkButton.java +++ b/Gui/src/main/java/mezz/jei/gui/recipes/RecipeBookmarkButton.java @@ -2,8 +2,6 @@ import mezz.jei.api.gui.IRecipeLayoutDrawable; import mezz.jei.api.gui.drawable.IDrawable; -import mezz.jei.api.helpers.IGuiHelper; -import mezz.jei.api.recipe.IRecipeManager; import mezz.jei.api.runtime.IIngredientManager; import mezz.jei.common.Internal; import mezz.jei.common.gui.JeiTooltip; @@ -26,11 +24,9 @@ public class RecipeBookmarkButton extends GuiIconToggleButton { public static RecipeBookmarkButton create( IRecipeLayoutDrawable recipeLayout, IIngredientManager ingredientManager, - BookmarkList bookmarks, - IRecipeManager recipeManager, - IGuiHelper guiHelper + BookmarkList bookmarks ) { - RecipeBookmark recipeBookmark = RecipeBookmark.create(recipeLayout, ingredientManager, recipeManager, guiHelper) + RecipeBookmark recipeBookmark = RecipeBookmark.create(recipeLayout, ingredientManager) .orElse(null); Textures textures = Internal.getTextures(); diff --git a/Gui/src/main/java/mezz/jei/gui/recipes/RecipesGui.java b/Gui/src/main/java/mezz/jei/gui/recipes/RecipesGui.java index 22024397e..f25bab211 100644 --- a/Gui/src/main/java/mezz/jei/gui/recipes/RecipesGui.java +++ b/Gui/src/main/java/mezz/jei/gui/recipes/RecipesGui.java @@ -65,9 +65,7 @@ public class RecipesGui extends Screen implements IRecipesGui, IRecipeFocusSourc private static final int minGuiWidth = 198; private final IInternalKeyMappings keyBindings; - private final IRecipeManager recipeManager; private final BookmarkList bookmarks; - private final IGuiHelper guiHelper; private final IFocusFactory focusFactory; private final IIngredientManager ingredientManager; @@ -120,9 +118,7 @@ public RecipesGui( IGuiHelper guiHelper ) { super(Component.literal("Recipes")); - this.recipeManager = recipeManager; this.bookmarks = bookmarks; - this.guiHelper = guiHelper; this.ingredientManager = ingredientManager; this.keyBindings = keyBindings; this.logic = new RecipeGuiLogic( @@ -561,9 +557,7 @@ private RecipeLayoutWithButtons createRecipeLayoutWithButtons(IRecipeLayo RecipeBookmarkButton bookmarkButton = RecipeBookmarkButton.create( recipeLayoutDrawable, ingredientManager, - bookmarks, - recipeManager, - guiHelper + bookmarks ); return new RecipeLayoutWithButtons<>(recipeLayoutDrawable, transferButton, bookmarkButton); diff --git a/Gui/src/main/java/mezz/jei/gui/startup/OverlayHelper.java b/Gui/src/main/java/mezz/jei/gui/startup/OverlayHelper.java index 64bd90a6e..ab268c2a1 100644 --- a/Gui/src/main/java/mezz/jei/gui/startup/OverlayHelper.java +++ b/Gui/src/main/java/mezz/jei/gui/startup/OverlayHelper.java @@ -35,7 +35,8 @@ public static IngredientGridWithNavigation createIngredientGridWithNavigation( IClientToggleState toggleState, IConnectionToServer serverConnection, IColorHelper colorHelper, - IScreenHelper screenHelper + IScreenHelper screenHelper, + boolean supportsEditMode ) { IngredientGrid ingredientListGrid = new IngredientGrid( ingredientManager, @@ -45,7 +46,8 @@ public static IngredientGridWithNavigation createIngredientGridWithNavigation( toggleState, serverConnection, keyMappings, - colorHelper + colorHelper, + supportsEditMode ); return new IngredientGridWithNavigation( @@ -90,7 +92,8 @@ public static IngredientListOverlay createIngredientListOverlay( toggleState, serverConnection, colorHelper, - screenHelper + screenHelper, + true ); return new IngredientListOverlay( @@ -130,7 +133,9 @@ public static BookmarkOverlay createBookmarkOverlay( toggleState, serverConnection, colorHelper, - screenHelper); + screenHelper, + false + ); return new BookmarkOverlay( bookmarkList, diff --git a/Library/src/main/java/mezz/jei/library/config/EditModeConfig.java b/Library/src/main/java/mezz/jei/library/config/EditModeConfig.java index 0133822b3..ca0c7a73c 100644 --- a/Library/src/main/java/mezz/jei/library/config/EditModeConfig.java +++ b/Library/src/main/java/mezz/jei/library/config/EditModeConfig.java @@ -1,7 +1,6 @@ package mezz.jei.library.config; -import com.mojang.datafixers.util.Pair; import mezz.jei.api.ingredients.IIngredientHelper; import mezz.jei.api.ingredients.IIngredientType; import mezz.jei.api.ingredients.ITypedIngredient; diff --git a/Library/src/main/java/mezz/jei/library/render/ItemStackRenderer.java b/Library/src/main/java/mezz/jei/library/render/ItemStackRenderer.java index bee21c07b..a3f1dccbf 100644 --- a/Library/src/main/java/mezz/jei/library/render/ItemStackRenderer.java +++ b/Library/src/main/java/mezz/jei/library/render/ItemStackRenderer.java @@ -3,8 +3,10 @@ import com.mojang.blaze3d.systems.RenderSystem; import mezz.jei.api.gui.builder.ITooltipBuilder; import mezz.jei.api.ingredients.IIngredientRenderer; +import mezz.jei.api.ingredients.rendering.BatchRenderElement; import mezz.jei.common.platform.IPlatformRenderHelper; import mezz.jei.common.platform.Services; +import mezz.jei.library.render.batch.ItemStackBatchRendererCache; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; @@ -17,6 +19,8 @@ import java.util.List; public class ItemStackRenderer implements IIngredientRenderer { + private final ItemStackBatchRendererCache batchRenderer = new ItemStackBatchRendererCache(); + @Override public void render(GuiGraphics guiGraphics, @Nullable ItemStack ingredient) { render(guiGraphics, ingredient, 0, 0); @@ -35,6 +39,11 @@ public void render(GuiGraphics guiGraphics, @Nullable ItemStack ingredient, int } } + @Override + public void renderBatch(GuiGraphics guiGraphics, List> batchRenderElements) { + batchRenderer.renderBatch(guiGraphics, batchRenderElements); + } + @SuppressWarnings("removal") @Override public List getTooltip(ItemStack ingredient, TooltipFlag tooltipFlag) { diff --git a/Library/src/main/java/mezz/jei/library/render/batch/ElementWithModel.java b/Library/src/main/java/mezz/jei/library/render/batch/ElementWithModel.java new file mode 100644 index 000000000..4693e8e5b --- /dev/null +++ b/Library/src/main/java/mezz/jei/library/render/batch/ElementWithModel.java @@ -0,0 +1,7 @@ +package mezz.jei.library.render.batch; + +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.world.item.ItemStack; + +public record ElementWithModel(BakedModel model, ItemStack stack, int x, int y) { +} diff --git a/Library/src/main/java/mezz/jei/library/render/batch/ItemStackBatchRenderer.java b/Library/src/main/java/mezz/jei/library/render/batch/ItemStackBatchRenderer.java new file mode 100644 index 000000000..86b52eaf5 --- /dev/null +++ b/Library/src/main/java/mezz/jei/library/render/batch/ItemStackBatchRenderer.java @@ -0,0 +1,129 @@ +package mezz.jei.library.render.batch; + +import com.mojang.blaze3d.platform.Lighting; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import mezz.jei.api.ingredients.rendering.BatchRenderElement; +import mezz.jei.common.platform.IPlatformRenderHelper; +import mezz.jei.common.platform.Services; +import net.minecraft.CrashReport; +import net.minecraft.CrashReportCategory; +import net.minecraft.ReportedException; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.world.item.ItemDisplayContext; +import net.minecraft.world.item.ItemStack; +import org.joml.Matrix4f; + +import java.util.ArrayList; +import java.util.List; + +public final class ItemStackBatchRenderer { + private final List> elements; + private final List useBlockLight; + private final List noBlockLight; + private final List customRender; + + public ItemStackBatchRenderer(Minecraft minecraft, List> elements) { + this.elements = elements; + this.useBlockLight = new ArrayList<>(); + this.noBlockLight = new ArrayList<>(); + this.customRender = new ArrayList<>(); + + ClientLevel level = minecraft.level; + ItemRenderer itemRenderer = minecraft.getItemRenderer(); + + for (BatchRenderElement element : elements) { + ItemStack itemStack = element.ingredient(); + if (!itemStack.isEmpty()) { + BakedModel bakedmodel = itemRenderer.getModel(itemStack, level, null, 0); + if (bakedmodel.isCustomRenderer()) { + ElementWithModel elementWithModel = new ElementWithModel(bakedmodel, itemStack, element.x(), element.y()); + customRender.add(elementWithModel); + } else if (bakedmodel.usesBlockLight()) { + ElementWithModel elementWithModel = new ElementWithModel(bakedmodel, itemStack, element.x(), element.y()); + useBlockLight.add(elementWithModel); + } else { + if (!bakedmodel.isGui3d()) { + bakedmodel = new LimitedQuadItemModel(bakedmodel); + } + ElementWithModel elementWithModel = new ElementWithModel(bakedmodel, itemStack, element.x(), element.y()); + noBlockLight.add(elementWithModel); + } + } + } + } + + public void render(GuiGraphics guiGraphics, Minecraft minecraft, ItemRenderer itemRenderer) { + if (!noBlockLight.isEmpty()) { + Lighting.setupForFlatItems(); + for (ElementWithModel element : noBlockLight) { + renderItem(guiGraphics, itemRenderer, element.model(), element.stack(), element.x(), element.y()); + } + guiGraphics.flush(); + Lighting.setupFor3DItems(); + } + + if (!useBlockLight.isEmpty()) { + for (ElementWithModel element : useBlockLight) { + renderItem(guiGraphics, itemRenderer, element.model(), element.stack(), element.x(), element.y()); + } + guiGraphics.flush(); + } + + for (ElementWithModel element : customRender) { + renderItem(guiGraphics, itemRenderer, element.model(), element.stack(), element.x(), element.y()); + guiGraphics.flush(); + } + + IPlatformRenderHelper renderHelper = Services.PLATFORM.getRenderHelper(); + for (BatchRenderElement element : elements) { + ItemStack ingredient = element.ingredient(); + Font font = renderHelper.getFontRenderer(minecraft, ingredient); + guiGraphics.renderItemDecorations(font, ingredient, element.x(), element.y()); + } + RenderSystem.disableBlend(); + } + + private void renderItem( + GuiGraphics guiGraphics, + ItemRenderer itemRenderer, + BakedModel bakedmodel, + ItemStack itemStack, + int x, + int y + ) { + PoseStack poseStack = guiGraphics.pose(); + poseStack.pushPose(); + poseStack.translate((float) (x + 8), (float) (y + 8), 150f); + poseStack.mulPoseMatrix((new Matrix4f()).scaling(1.0F, -1.0F, 1.0F)); + poseStack.scale(16.0F, 16.0F, 16.0F); + + try { + itemRenderer.render( + itemStack, + ItemDisplayContext.GUI, + false, + poseStack, + guiGraphics.bufferSource(), + 0xf000f0, + OverlayTexture.NO_OVERLAY, + bakedmodel + ); + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Rendering item"); + CrashReportCategory crashreportcategory = crashreport.addCategory("Item being rendered"); + crashreportcategory.setDetail("Item Type", () -> String.valueOf(itemStack.getItem())); + crashreportcategory.setDetail("Item NBT", () -> String.valueOf(itemStack.getTag())); + crashreportcategory.setDetail("Item Foil", () -> String.valueOf(itemStack.hasFoil())); + throw new ReportedException(crashreport); + } + + poseStack.popPose(); + } +} diff --git a/Library/src/main/java/mezz/jei/library/render/batch/ItemStackBatchRendererCache.java b/Library/src/main/java/mezz/jei/library/render/batch/ItemStackBatchRendererCache.java new file mode 100644 index 000000000..394ba9c86 --- /dev/null +++ b/Library/src/main/java/mezz/jei/library/render/batch/ItemStackBatchRendererCache.java @@ -0,0 +1,35 @@ +package mezz.jei.library.render.batch; + + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import mezz.jei.api.ingredients.rendering.BatchRenderElement; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.world.item.ItemStack; + +import java.util.List; + +public class ItemStackBatchRendererCache { + private final LoadingCache>, ItemStackBatchRenderer> cache = + CacheBuilder.newBuilder() + .maximumSize(6) + .build(new CacheLoader<>() { + @Override + public ItemStackBatchRenderer load(List> elements) { + Minecraft minecraft = Minecraft.getInstance(); + return new ItemStackBatchRenderer(minecraft, elements); + } + }); + + public void renderBatch(GuiGraphics guiGraphics, List> elements) { + ItemStackBatchRenderer batchData = cache.getUnchecked(elements); + + Minecraft minecraft = Minecraft.getInstance(); + ItemRenderer itemRenderer = minecraft.getItemRenderer(); + batchData.render(guiGraphics, minecraft, itemRenderer); + } + +} diff --git a/Library/src/main/java/mezz/jei/library/render/batch/LimitedQuadItemModel.java b/Library/src/main/java/mezz/jei/library/render/batch/LimitedQuadItemModel.java new file mode 100644 index 000000000..5322e89f0 --- /dev/null +++ b/Library/src/main/java/mezz/jei/library/render/batch/LimitedQuadItemModel.java @@ -0,0 +1,71 @@ +package mezz.jei.library.render.batch; + +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.block.model.ItemOverrides; +import net.minecraft.client.renderer.block.model.ItemTransforms; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class LimitedQuadItemModel implements BakedModel { + private final BakedModel bakedmodel; + private @Nullable List quads; + + public LimitedQuadItemModel(BakedModel bakedmodel) { + this.bakedmodel = bakedmodel; + } + + @Override + public List getQuads(@Nullable BlockState blockState, @Nullable Direction direction, RandomSource randomSource) { + if (direction == null) { + if (quads == null) { + quads = bakedmodel.getQuads(blockState, null, randomSource) + .stream() + .filter(q -> q.getDirection() == Direction.SOUTH) + .toList(); + } + return quads; + } + return List.of(); + } + + @Override + public boolean useAmbientOcclusion() { + return bakedmodel.useAmbientOcclusion(); + } + + @Override + public boolean isGui3d() { + return bakedmodel.isGui3d(); + } + + @Override + public boolean usesBlockLight() { + return bakedmodel.usesBlockLight(); + } + + @Override + public boolean isCustomRenderer() { + return bakedmodel.isCustomRenderer(); + } + + @Override + public TextureAtlasSprite getParticleIcon() { + return bakedmodel.getParticleIcon(); + } + + @Override + public ItemTransforms getTransforms() { + return bakedmodel.getTransforms(); + } + + @Override + public ItemOverrides getOverrides() { + return bakedmodel.getOverrides(); + } +} diff --git a/Library/src/main/java/mezz/jei/library/render/batch/package-info.java b/Library/src/main/java/mezz/jei/library/render/batch/package-info.java new file mode 100644 index 000000000..f03518506 --- /dev/null +++ b/Library/src/main/java/mezz/jei/library/render/batch/package-info.java @@ -0,0 +1,7 @@ +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +package mezz.jei.library.render.batch; + +import net.minecraft.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/gradle.properties b/gradle.properties index 1e475738a..3ac969090 100644 --- a/gradle.properties +++ b/gradle.properties @@ -42,4 +42,4 @@ curseHomepageUrl=https://www.curseforge.com/minecraft/mc-mods/jei jUnitVersion=5.8.2 # Version -specificationVersion=15.15.0 +specificationVersion=15.16.0