From fbaf92105e6803e7263aaabbb6e56b0c881f3af0 Mon Sep 17 00:00:00 2001 From: Sara Freimer Date: Fri, 8 Apr 2022 17:37:43 -0500 Subject: [PATCH] Fix issues with custom forge ingredients causing sub ingredients to be prematurely and invalidly cached (#8550) Add config option and skip checking for empty ingredients in shapeless recipe deserialization --- .../world/item/crafting/ShapelessRecipe.java.patch | 9 +++++++++ src/main/java/net/minecraftforge/common/ForgeConfig.java | 6 ++++++ .../common/crafting/CompoundIngredient.java | 2 +- .../common/crafting/DifferenceIngredient.java | 2 +- .../common/crafting/IntersectionIngredient.java | 2 +- src/main/resources/assets/forge/lang/en_us.json | 2 ++ 6 files changed, 20 insertions(+), 3 deletions(-) diff --git a/patches/minecraft/net/minecraft/world/item/crafting/ShapelessRecipe.java.patch b/patches/minecraft/net/minecraft/world/item/crafting/ShapelessRecipe.java.patch index 4b7977e78a..bda562abfa 100644 --- a/patches/minecraft/net/minecraft/world/item/crafting/ShapelessRecipe.java.patch +++ b/patches/minecraft/net/minecraft/world/item/crafting/ShapelessRecipe.java.patch @@ -56,3 +56,12 @@ } else { ItemStack itemstack = ShapedRecipe.m_151274_(GsonHelper.m_13930_(p_44291_, "result")); return new ShapelessRecipe(p_44290_, s, itemstack, nonnulllist); +@@ -88,7 +_,7 @@ + + for(int i = 0; i < p_44276_.size(); ++i) { + Ingredient ingredient = Ingredient.m_43917_(p_44276_.get(i)); +- if (!ingredient.m_43947_()) { ++ if (net.minecraftforge.common.ForgeConfig.SERVER.skipEmptyShapelessCheck.get() || !ingredient.m_43947_()) { + nonnulllist.add(ingredient); + } + } diff --git a/src/main/java/net/minecraftforge/common/ForgeConfig.java b/src/main/java/net/minecraftforge/common/ForgeConfig.java index f258d48b41..80049a2358 100644 --- a/src/main/java/net/minecraftforge/common/ForgeConfig.java +++ b/src/main/java/net/minecraftforge/common/ForgeConfig.java @@ -27,6 +27,7 @@ public class ForgeConfig { public final DoubleValue zombieBabyChance; public final BooleanValue treatEmptyTagsAsAir; + public final BooleanValue skipEmptyShapelessCheck; public final BooleanValue fixAdvancementLoading; @@ -65,6 +66,11 @@ public class ForgeConfig { .translation("forge.configgui.treatEmptyTagsAsAir") .define("treatEmptyTagsAsAir", false); + skipEmptyShapelessCheck = builder + .comment("Skip checking if an ingredient is empty during shapeless recipe deserialization to prevent complex ingredients from caching tags too early.") + .translation("forge.configgui.skipEmptyShapelessCheck") + .define("skipEmptyShapelessCheck", true); + fixAdvancementLoading = builder .comment("Fix advancement loading to use a proper topological sort. This may have visibility side-effects and can thus be turned off if needed for data-pack compatibility.") .translation("forge.configgui.fixAdvancementLoading") diff --git a/src/main/java/net/minecraftforge/common/crafting/CompoundIngredient.java b/src/main/java/net/minecraftforge/common/crafting/CompoundIngredient.java index ef03f7cea7..f8a78358a1 100644 --- a/src/main/java/net/minecraftforge/common/crafting/CompoundIngredient.java +++ b/src/main/java/net/minecraftforge/common/crafting/CompoundIngredient.java @@ -156,7 +156,7 @@ public class CompoundIngredient extends AbstractIngredient @Override public boolean isEmpty() { - return getItems().length == 0; + return children.stream().allMatch(Ingredient::isEmpty); } public static class Serializer implements IIngredientSerializer diff --git a/src/main/java/net/minecraftforge/common/crafting/DifferenceIngredient.java b/src/main/java/net/minecraftforge/common/crafting/DifferenceIngredient.java index 49f808116a..fa14812a1c 100644 --- a/src/main/java/net/minecraftforge/common/crafting/DifferenceIngredient.java +++ b/src/main/java/net/minecraftforge/common/crafting/DifferenceIngredient.java @@ -64,7 +64,7 @@ public class DifferenceIngredient extends AbstractIngredient @Override public boolean isEmpty() { - return getItems().length == 0; + return base.isEmpty(); } @Override diff --git a/src/main/java/net/minecraftforge/common/crafting/IntersectionIngredient.java b/src/main/java/net/minecraftforge/common/crafting/IntersectionIngredient.java index 60d7fabd64..50ab157b29 100644 --- a/src/main/java/net/minecraftforge/common/crafting/IntersectionIngredient.java +++ b/src/main/java/net/minecraftforge/common/crafting/IntersectionIngredient.java @@ -91,7 +91,7 @@ public class IntersectionIngredient extends AbstractIngredient @Override public boolean isEmpty() { - return getItems().length == 0; + return children.stream().anyMatch(Ingredient::isEmpty); } @Override diff --git a/src/main/resources/assets/forge/lang/en_us.json b/src/main/resources/assets/forge/lang/en_us.json index 73b52830a8..07e5e7de41 100644 --- a/src/main/resources/assets/forge/lang/en_us.json +++ b/src/main/resources/assets/forge/lang/en_us.json @@ -153,6 +153,8 @@ "forge.configgui.clumpingThreshold": "Packet Clumping Threshold", "forge.configgui.treatEmptyTagsAsAir.tooltip": "Vanilla will treat crafting recipes using empty tags as air, and allow you to craft with nothing in that slot. This changes empty tags to use BARRIER as the item. To prevent crafting with air.", "forge.configgui.treatEmptyTagsAsAir": "Treat empty tags as air", + "forge.configgui.skipEmptyShapelessCheck.tooltip": "Skip checking if an ingredient is empty during shapeless recipe deserialization to prevent complex ingredients from caching tags too early.", + "forge.configgui.skipEmptyShapelessCheck": "Skip checking for empty ingredients in Shapeless Recipe Deserialization", "forge.configgui.forceSystemNanoTime.tooltip": "Force the use of System.nanoTime instead of glfwGetTime as the main client Time provider.", "forge.configgui.forceSystemNanoTime": "Force System.nanoTime",