aboutsummaryrefslogtreecommitdiffhomepage
path: root/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting
diff options
context:
space:
mode:
Diffstat (limited to 'patch-remap/mache-spigotflower/net/minecraft/world/item/crafting')
-rw-r--r--patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/BlastingRecipe.java.patch47
-rw-r--r--patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/CampfireCookingRecipe.java.patch47
-rw-r--r--patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/CustomRecipe.java.patch46
-rw-r--r--patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/Ingredient.java.patch278
-rw-r--r--patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/Recipe.java.patch30
-rw-r--r--patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/RecipeHolder.java.patch35
-rw-r--r--patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/RecipeManager.java.patch274
-rw-r--r--patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/ShapedRecipe.java.patch235
-rw-r--r--patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/ShapelessRecipe.java.patch204
-rw-r--r--patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmeltingRecipe.java.patch47
-rw-r--r--patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmithingTransformRecipe.java.patch159
-rw-r--r--patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmithingTrimRecipe.java.patch178
-rw-r--r--patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmokingRecipe.java.patch47
-rw-r--r--patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/StonecutterRecipe.java.patch48
14 files changed, 1675 insertions, 0 deletions
diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/BlastingRecipe.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/BlastingRecipe.java.patch
new file mode 100644
index 0000000000..e459ae58c7
--- /dev/null
+++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/BlastingRecipe.java.patch
@@ -0,0 +1,47 @@
+--- a/net/minecraft/world/item/crafting/BlastingRecipe.java
++++ b/net/minecraft/world/item/crafting/BlastingRecipe.java
+@@ -3,21 +3,40 @@
+ import net.minecraft.world.item.ItemStack;
+ import net.minecraft.world.level.block.Blocks;
+
++// CraftBukkit start
++import org.bukkit.NamespacedKey;
++import org.bukkit.craftbukkit.inventory.CraftBlastingRecipe;
++import org.bukkit.craftbukkit.inventory.CraftItemStack;
++import org.bukkit.craftbukkit.inventory.CraftRecipe;
++import org.bukkit.inventory.Recipe;
++// CraftBukkit end
++
+ public class BlastingRecipe extends AbstractCookingRecipe {
+
+- public BlastingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient ingredient, ItemStack itemstack, float f, int i) {
+- super(RecipeType.BLASTING, s, cookingbookcategory, ingredient, itemstack, f, i);
++ public BlastingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient recipeitemstack, ItemStack itemstack, float f, int i) {
++ super(RecipeType.BLASTING, s, cookingbookcategory, recipeitemstack, itemstack, f, i);
+ }
+
+ @Override
+- @Override
+ public ItemStack getToastSymbol() {
+ return new ItemStack(Blocks.BLAST_FURNACE);
+ }
+
+ @Override
+- @Override
+ public RecipeSerializer<?> getSerializer() {
+ return RecipeSerializer.BLASTING_RECIPE;
+ }
++
++ // CraftBukkit start
++ @Override
++ public Recipe toBukkitRecipe(NamespacedKey id) {
++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result);
++
++ CraftBlastingRecipe recipe = new CraftBlastingRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime);
++ recipe.setGroup(this.group);
++ recipe.setCategory(CraftRecipe.getCategory(this.category()));
++
++ return recipe;
++ }
++ // CraftBukkit end
+ }
diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/CampfireCookingRecipe.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/CampfireCookingRecipe.java.patch
new file mode 100644
index 0000000000..281bcf37fa
--- /dev/null
+++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/CampfireCookingRecipe.java.patch
@@ -0,0 +1,47 @@
+--- a/net/minecraft/world/item/crafting/CampfireCookingRecipe.java
++++ b/net/minecraft/world/item/crafting/CampfireCookingRecipe.java
+@@ -3,21 +3,40 @@
+ import net.minecraft.world.item.ItemStack;
+ import net.minecraft.world.level.block.Blocks;
+
++// CraftBukkit start
++import org.bukkit.NamespacedKey;
++import org.bukkit.craftbukkit.inventory.CraftCampfireRecipe;
++import org.bukkit.craftbukkit.inventory.CraftItemStack;
++import org.bukkit.craftbukkit.inventory.CraftRecipe;
++import org.bukkit.inventory.Recipe;
++// CraftBukkit end
++
+ public class CampfireCookingRecipe extends AbstractCookingRecipe {
+
+- public CampfireCookingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient ingredient, ItemStack itemstack, float f, int i) {
+- super(RecipeType.CAMPFIRE_COOKING, s, cookingbookcategory, ingredient, itemstack, f, i);
++ public CampfireCookingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient recipeitemstack, ItemStack itemstack, float f, int i) {
++ super(RecipeType.CAMPFIRE_COOKING, s, cookingbookcategory, recipeitemstack, itemstack, f, i);
+ }
+
+ @Override
+- @Override
+ public ItemStack getToastSymbol() {
+ return new ItemStack(Blocks.CAMPFIRE);
+ }
+
+ @Override
+- @Override
+ public RecipeSerializer<?> getSerializer() {
+ return RecipeSerializer.CAMPFIRE_COOKING_RECIPE;
+ }
++
++ // CraftBukkit start
++ @Override
++ public Recipe toBukkitRecipe(NamespacedKey id) {
++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result);
++
++ CraftCampfireRecipe recipe = new CraftCampfireRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime);
++ recipe.setGroup(this.group);
++ recipe.setCategory(CraftRecipe.getCategory(this.category()));
++
++ return recipe;
++ }
++ // CraftBukkit end
+ }
diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/CustomRecipe.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/CustomRecipe.java.patch
new file mode 100644
index 0000000000..6edc4b87a8
--- /dev/null
+++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/CustomRecipe.java.patch
@@ -0,0 +1,46 @@
+--- a/net/minecraft/world/item/crafting/CustomRecipe.java
++++ b/net/minecraft/world/item/crafting/CustomRecipe.java
+@@ -3,8 +3,13 @@
+ import net.minecraft.core.RegistryAccess;
+ import net.minecraft.world.item.ItemStack;
+
+-public abstract class CustomRecipe implements CraftingRecipe {
++// CraftBukkit start
++import org.bukkit.NamespacedKey;
++import org.bukkit.inventory.Recipe;
++// CraftBukkit end
+
++public abstract class CustomRecipe implements RecipeCrafting {
++
+ private final CraftingBookCategory category;
+
+ public CustomRecipe(CraftingBookCategory craftingbookcategory) {
+@@ -12,20 +17,24 @@
+ }
+
+ @Override
+- @Override
+ public boolean isSpecial() {
+ return true;
+ }
+
+ @Override
+- @Override
+- public ItemStack getResultItem(RegistryAccess registryaccess) {
++ public ItemStack getResultItem(RegistryAccess registryAccess) {
+ return ItemStack.EMPTY;
+ }
+
+ @Override
+- @Override
+ public CraftingBookCategory category() {
+ return this.category;
+ }
++
++ // CraftBukkit start
++ @Override
++ public Recipe toBukkitRecipe(NamespacedKey id) {
++ return new org.bukkit.craftbukkit.inventory.CraftComplexRecipe(id, this);
++ }
++ // CraftBukkit end
+ }
diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/Ingredient.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/Ingredient.java.patch
new file mode 100644
index 0000000000..56822af3df
--- /dev/null
+++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/Ingredient.java.patch
@@ -0,0 +1,278 @@
+--- a/net/minecraft/world/item/crafting/Ingredient.java
++++ b/net/minecraft/world/item/crafting/Ingredient.java
+@@ -25,33 +25,34 @@
+ import net.minecraft.world.entity.player.StackedContents;
+ import net.minecraft.world.item.Item;
+ import net.minecraft.world.item.ItemStack;
+-import net.minecraft.world.level.ItemLike;
++import net.minecraft.world.level.IMaterial;
+
+ public final class Ingredient implements Predicate<ItemStack> {
+
+ public static final Ingredient EMPTY = new Ingredient(Stream.empty());
+- private final Ingredient.Value[] values;
++ private final Ingredient.Provider[] values;
+ @Nullable
+- private ItemStack[] itemStacks;
++ public ItemStack[] itemStacks;
+ @Nullable
+ private IntList stackingIds;
++ public boolean exact; // CraftBukkit
+ public static final Codec<Ingredient> CODEC = codec(true);
+ public static final Codec<Ingredient> CODEC_NONEMPTY = codec(false);
+
+- private Ingredient(Stream<? extends Ingredient.Value> stream) {
+- this.values = (Ingredient.Value[]) stream.toArray((i) -> {
+- return new Ingredient.Value[i];
++ public Ingredient(Stream<? extends Ingredient.Provider> values) {
++ this.values = (Ingredient.Provider[]) values.toArray((i) -> {
++ return new Ingredient.Provider[i];
+ });
+ }
+
+- private Ingredient(Ingredient.Value[] aingredient_value) {
+- this.values = aingredient_value;
++ private Ingredient(Ingredient.Provider[] arecipeitemstack_provider) {
++ this.values = arecipeitemstack_provider;
+ }
+
+ public ItemStack[] getItems() {
+ if (this.itemStacks == null) {
+- this.itemStacks = (ItemStack[]) Arrays.stream(this.values).flatMap((ingredient_value) -> {
+- return ingredient_value.getItems().stream();
++ this.itemStacks = (ItemStack[]) Arrays.stream(this.values).flatMap((recipeitemstack_provider) -> {
++ return recipeitemstack_provider.getItems().stream();
+ }).distinct().toArray((i) -> {
+ return new ItemStack[i];
+ });
+@@ -60,12 +61,11 @@
+ return this.itemStacks;
+ }
+
+- @Override
+- public boolean test(@Nullable ItemStack itemstack) {
+- if (itemstack == null) {
++ public boolean test(@Nullable ItemStack stack) {
++ if (stack == null) {
+ return false;
+ } else if (this.isEmpty()) {
+- return itemstack.isEmpty();
++ return stack.isEmpty();
+ } else {
+ ItemStack[] aitemstack = this.getItems();
+ int i = aitemstack.length;
+@@ -73,7 +73,16 @@
+ for (int j = 0; j < i; ++j) {
+ ItemStack itemstack1 = aitemstack[j];
+
+- if (itemstack1.is(itemstack.getItem())) {
++ // CraftBukkit start
++ if (exact) {
++ if (itemstack1.getItem() == stack.getItem() && ItemStack.isSameItemSameTags(stack, itemstack1)) {
++ return true;
++ }
++
++ continue;
++ }
++ // CraftBukkit end
++ if (itemstack1.is(stack.getItem())) {
+ return true;
+ }
+ }
+@@ -102,92 +111,91 @@
+ return this.stackingIds;
+ }
+
+- public void toNetwork(FriendlyByteBuf friendlybytebuf) {
+- friendlybytebuf.writeCollection(Arrays.asList(this.getItems()), FriendlyByteBuf::writeItem);
++ public void toNetwork(FriendlyByteBuf buffer) {
++ buffer.writeCollection(Arrays.asList(this.getItems()), FriendlyByteBuf::writeItem);
+ }
+
+ public boolean isEmpty() {
+ return this.values.length == 0;
+ }
+
+- @Override
+ public boolean equals(Object object) {
+ if (object instanceof Ingredient) {
+- Ingredient ingredient = (Ingredient) object;
++ Ingredient recipeitemstack = (Ingredient) object;
+
+- return Arrays.equals(this.values, ingredient.values);
++ return Arrays.equals(this.values, recipeitemstack.values);
+ } else {
+ return false;
+ }
+ }
+
+- private static Ingredient fromValues(Stream<? extends Ingredient.Value> stream) {
+- Ingredient ingredient = new Ingredient(stream);
++ private static Ingredient fromValues(Stream<? extends Ingredient.Provider> stream) {
++ Ingredient recipeitemstack = new Ingredient(stream);
+
+- return ingredient.isEmpty() ? Ingredient.EMPTY : ingredient;
++ return recipeitemstack.isEmpty() ? Ingredient.EMPTY : recipeitemstack;
+ }
+
+ public static Ingredient of() {
+ return Ingredient.EMPTY;
+ }
+
+- public static Ingredient of(ItemLike... aitemlike) {
+- return of(Arrays.stream(aitemlike).map(ItemStack::new));
++ public static Ingredient of(IMaterial... items) {
++ return of(Arrays.stream(items).map(ItemStack::new));
+ }
+
+- public static Ingredient of(ItemStack... aitemstack) {
+- return of(Arrays.stream(aitemstack));
++ public static Ingredient of(ItemStack... stacks) {
++ return of(Arrays.stream(stacks));
+ }
+
+- public static Ingredient of(Stream<ItemStack> stream) {
+- return fromValues(stream.filter((itemstack) -> {
++ public static Ingredient of(Stream<ItemStack> stacks) {
++ return fromValues(stacks.filter((itemstack) -> {
+ return !itemstack.isEmpty();
+ }).map(Ingredient.ItemValue::new));
+ }
+
+- public static Ingredient of(TagKey<Item> tagkey) {
+- return fromValues(Stream.of(new Ingredient.TagValue(tagkey)));
++ public static Ingredient of(TagKey<Item> tag) {
++ return fromValues(Stream.of(new Ingredient.TagValue(tag)));
+ }
+
+- public static Ingredient fromNetwork(FriendlyByteBuf friendlybytebuf) {
+- return fromValues(friendlybytebuf.readList(FriendlyByteBuf::readItem).stream().map(Ingredient.ItemValue::new));
++ public static Ingredient fromNetwork(FriendlyByteBuf buffer) {
++ return fromValues(buffer.readList(FriendlyByteBuf::readItem).stream().map(Ingredient.ItemValue::new));
+ }
+
+ private static Codec<Ingredient> codec(boolean flag) {
+- Codec<Ingredient.Value[]> codec = Codec.list(Ingredient.Value.CODEC).comapFlatMap((list) -> {
++ Codec<Ingredient.Provider[]> codec = Codec.list(Ingredient.Provider.CODEC).comapFlatMap((list) -> {
+ return !flag && list.size() < 1 ? DataResult.error(() -> {
+ return "Item array cannot be empty, at least one item must be defined";
+- }) : DataResult.success((Ingredient.Value[]) list.toArray(new Ingredient.Value[0]));
++ }) : DataResult.success((Ingredient.Provider[]) list.toArray(new Ingredient.Provider[0]));
+ }, List::of);
+
+- return ExtraCodecs.either(codec, Ingredient.Value.CODEC).flatComapMap((either) -> {
+- return (Ingredient) either.map(Ingredient::new, (ingredient_value) -> {
+- return new Ingredient(new Ingredient.Value[]{ingredient_value});
++ return ExtraCodecs.either(codec, Ingredient.Provider.CODEC).flatComapMap((either) -> {
++ return (Ingredient) either.map(Ingredient::new, (recipeitemstack_provider) -> {
++ return new Ingredient(new Ingredient.Provider[]{recipeitemstack_provider});
+ });
+- }, (ingredient) -> {
+- return ingredient.values.length == 1 ? DataResult.success(Either.right(ingredient.values[0])) : (ingredient.values.length == 0 && !flag ? DataResult.error(() -> {
++ }, (recipeitemstack) -> {
++ return recipeitemstack.values.length == 1 ? DataResult.success(Either.right(recipeitemstack.values[0])) : (recipeitemstack.values.length == 0 && !flag ? DataResult.error(() -> {
+ return "Item array cannot be empty, at least one item must be defined";
+- }) : DataResult.success(Either.left(ingredient.values)));
++ }) : DataResult.success(Either.left(recipeitemstack.values)));
+ });
+ }
+
+- private interface Value {
++ public interface Provider {
+
+- Codec<Ingredient.Value> CODEC = ExtraCodecs.xor(Ingredient.ItemValue.CODEC, Ingredient.TagValue.CODEC).xmap((either) -> {
+- return (Ingredient.Value) either.map((ingredient_itemvalue) -> {
+- return ingredient_itemvalue;
+- }, (ingredient_tagvalue) -> {
+- return ingredient_tagvalue;
++ Codec<Ingredient.Provider> CODEC = ExtraCodecs.xor(Ingredient.ItemValue.CODEC, Ingredient.TagValue.CODEC).xmap((either) -> {
++ return (Ingredient.Provider) either.map((recipeitemstack_stackprovider) -> {
++ return recipeitemstack_stackprovider;
++ }, (recipeitemstack_b) -> {
++ return recipeitemstack_b;
+ });
+- }, (ingredient_value) -> {
+- if (ingredient_value instanceof Ingredient.TagValue) {
+- Ingredient.TagValue ingredient_tagvalue = (Ingredient.TagValue) ingredient_value;
++ }, (recipeitemstack_provider) -> {
++ if (recipeitemstack_provider instanceof Ingredient.TagValue) {
++ Ingredient.TagValue recipeitemstack_b = (Ingredient.TagValue) recipeitemstack_provider;
+
+- return Either.right(ingredient_tagvalue);
+- } else if (ingredient_value instanceof Ingredient.ItemValue) {
+- Ingredient.ItemValue ingredient_itemvalue = (Ingredient.ItemValue) ingredient_value;
++ return Either.right(recipeitemstack_b);
++ } else if (recipeitemstack_provider instanceof Ingredient.ItemValue) {
++ Ingredient.ItemValue recipeitemstack_stackprovider = (Ingredient.ItemValue) recipeitemstack_provider;
+
+- return Either.left(ingredient_itemvalue);
++ return Either.left(recipeitemstack_stackprovider);
+ } else {
+ throw new UnsupportedOperationException("This is neither an item value nor a tag value.");
+ }
+@@ -196,27 +204,25 @@
+ Collection<ItemStack> getItems();
+ }
+
+- private static record TagValue(TagKey<Item> tag) implements Ingredient.Value {
++ private static record TagValue(TagKey<Item> tag) implements Ingredient.Provider {
+
+ static final Codec<Ingredient.TagValue> CODEC = RecordCodecBuilder.create((instance) -> {
+- return instance.group(TagKey.codec(Registries.ITEM).fieldOf("tag").forGetter((ingredient_tagvalue) -> {
+- return ingredient_tagvalue.tag;
++ return instance.group(TagKey.codec(Registries.ITEM).fieldOf("tag").forGetter((recipeitemstack_b) -> {
++ return recipeitemstack_b.tag;
+ })).apply(instance, Ingredient.TagValue::new);
+ });
+
+- @Override
+ public boolean equals(Object object) {
+ if (object instanceof Ingredient.TagValue) {
+- Ingredient.TagValue ingredient_tagvalue = (Ingredient.TagValue) object;
++ Ingredient.TagValue recipeitemstack_b = (Ingredient.TagValue) object;
+
+- return ingredient_tagvalue.tag.location().equals(this.tag.location());
++ return recipeitemstack_b.tag.location().equals(this.tag.location());
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+- @Override
+ public Collection<ItemStack> getItems() {
+ List<ItemStack> list = Lists.newArrayList();
+ Iterator iterator = BuiltInRegistries.ITEM.getTagOrEmpty(this.tag).iterator();
+@@ -231,27 +237,25 @@
+ }
+ }
+
+- private static record ItemValue(ItemStack item) implements Ingredient.Value {
++ public static record ItemValue(ItemStack item) implements Ingredient.Provider {
+
+ static final Codec<Ingredient.ItemValue> CODEC = RecordCodecBuilder.create((instance) -> {
+- return instance.group(ItemStack.SINGLE_ITEM_CODEC.fieldOf("item").forGetter((ingredient_itemvalue) -> {
+- return ingredient_itemvalue.item;
++ return instance.group(ItemStack.SINGLE_ITEM_CODEC.fieldOf("item").forGetter((recipeitemstack_stackprovider) -> {
++ return recipeitemstack_stackprovider.item;
+ })).apply(instance, Ingredient.ItemValue::new);
+ });
+
+- @Override
+ public boolean equals(Object object) {
+ if (!(object instanceof Ingredient.ItemValue)) {
+ return false;
+ } else {
+- Ingredient.ItemValue ingredient_itemvalue = (Ingredient.ItemValue) object;
++ Ingredient.ItemValue recipeitemstack_stackprovider = (Ingredient.ItemValue) object;
+
+- return ingredient_itemvalue.item.getItem().equals(this.item.getItem()) && ingredient_itemvalue.item.getCount() == this.item.getCount();
++ return recipeitemstack_stackprovider.item.getItem().equals(this.item.getItem()) && recipeitemstack_stackprovider.item.getCount() == this.item.getCount();
+ }
+ }
+
+ @Override
+- @Override
+ public Collection<ItemStack> getItems() {
+ return Collections.singleton(this.item);
+ }
diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/Recipe.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/Recipe.java.patch
new file mode 100644
index 0000000000..a1bd9ee38e
--- /dev/null
+++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/Recipe.java.patch
@@ -0,0 +1,30 @@
+--- a/net/minecraft/world/item/crafting/Recipe.java
++++ b/net/minecraft/world/item/crafting/Recipe.java
+@@ -22,11 +22,11 @@
+
+ ItemStack getResultItem(RegistryAccess registryAccess);
+
+- default NonNullList<ItemStack> getRemainingItems(C c0) {
+- NonNullList<ItemStack> nonnulllist = NonNullList.withSize(c0.getContainerSize(), ItemStack.EMPTY);
++ default NonNullList<ItemStack> getRemainingItems(C container) {
++ NonNullList<ItemStack> nonnulllist = NonNullList.withSize(container.getContainerSize(), ItemStack.EMPTY);
+
+ for (int i = 0; i < nonnulllist.size(); ++i) {
+- Item item = c0.getItem(i).getItem();
++ Item item = container.getItem(i).getItem();
+
+ if (item.hasCraftingRemainingItem()) {
+ nonnulllist.set(i, new ItemStack(item.getCraftingRemainingItem()));
+@@ -63,8 +63,10 @@
+ default boolean isIncomplete() {
+ NonNullList<Ingredient> nonnulllist = this.getIngredients();
+
+- return nonnulllist.isEmpty() || nonnulllist.stream().anyMatch((ingredient) -> {
+- return ingredient.getItems().length == 0;
++ return nonnulllist.isEmpty() || nonnulllist.stream().anyMatch((recipeitemstack) -> {
++ return recipeitemstack.getItems().length == 0;
+ });
+ }
++
++ org.bukkit.inventory.Recipe toBukkitRecipe(org.bukkit.NamespacedKey id); // CraftBukkit
+ }
diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/RecipeHolder.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/RecipeHolder.java.patch
new file mode 100644
index 0000000000..16a1050265
--- /dev/null
+++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/RecipeHolder.java.patch
@@ -0,0 +1,35 @@
+--- a/net/minecraft/world/item/crafting/RecipeHolder.java
++++ b/net/minecraft/world/item/crafting/RecipeHolder.java
+@@ -1,10 +1,17 @@
+ package net.minecraft.world.item.crafting;
+
+ import net.minecraft.resources.ResourceLocation;
++// CraftBukkit start
++import org.bukkit.craftbukkit.util.CraftNamespacedKey;
++import org.bukkit.inventory.Recipe;
+
+-public record RecipeHolder<T extends Recipe<?>> (ResourceLocation id, T value) {
++public record RecipeHolder<T extends net.minecraft.world.item.crafting.Recipe<?>>(ResourceLocation id, T value) {
+
+- @Override
++ public final Recipe toBukkitRecipe() {
++ return this.value.toBukkitRecipe(CraftNamespacedKey.fromMinecraft(this.id));
++ }
++ // CraftBukkit end
++
+ public boolean equals(Object object) {
+ if (this == object) {
+ return true;
+@@ -25,12 +32,10 @@
+ }
+ }
+
+- @Override
+ public int hashCode() {
+ return this.id.hashCode();
+ }
+
+- @Override
+ public String toString() {
+ return this.id.toString();
+ }
diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/RecipeManager.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/RecipeManager.java.patch
new file mode 100644
index 0000000000..ae8c6942ab
--- /dev/null
+++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/RecipeManager.java.patch
@@ -0,0 +1,274 @@
+--- a/net/minecraft/world/item/crafting/RecipeManager.java
++++ b/net/minecraft/world/item/crafting/RecipeManager.java
+@@ -24,21 +24,26 @@
+ import javax.annotation.Nullable;
+ import net.minecraft.Util;
+ import net.minecraft.core.NonNullList;
++import net.minecraft.world.Container;
++import net.minecraft.world.item.ItemStack;
++import net.minecraft.world.level.Level;
++import org.slf4j.Logger;
++
++// CraftBukkit start
++import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
++import net.minecraft.core.registries.BuiltInRegistries;
++// CraftBukkit end
+ import net.minecraft.resources.ResourceLocation;
+ import net.minecraft.server.packs.resources.ResourceManager;
+ import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener;
+ import net.minecraft.util.GsonHelper;
+ import net.minecraft.util.profiling.ProfilerFiller;
+-import net.minecraft.world.Container;
+-import net.minecraft.world.item.ItemStack;
+-import net.minecraft.world.level.Level;
+-import org.slf4j.Logger;
+
+ public class RecipeManager extends SimpleJsonResourceReloadListener {
+
+ private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().disableHtmlEscaping().create();
+ private static final Logger LOGGER = LogUtils.getLogger();
+- private Map<RecipeType<?>, Map<ResourceLocation, RecipeHolder<?>>> recipes = ImmutableMap.of();
++ public Map<RecipeType<?>, Object2ObjectLinkedOpenHashMap<ResourceLocation, RecipeHolder<?>>> recipes = ImmutableMap.of(); // CraftBukkit
+ private Map<ResourceLocation, RecipeHolder<?>> byName = ImmutableMap.of();
+ private boolean hasErrors;
+
+@@ -46,98 +51,121 @@
+ super(RecipeManager.GSON, "recipes");
+ }
+
+- @Override
+- protected void apply(Map<ResourceLocation, JsonElement> map, ResourceManager resourcemanager, ProfilerFiller profilerfiller) {
++ protected void apply(Map<ResourceLocation, JsonElement> object, ResourceManager resourceManager, ProfilerFiller profiler) {
+ this.hasErrors = false;
+- Map<RecipeType<?>, Builder<ResourceLocation, RecipeHolder<?>>> map1 = Maps.newHashMap();
++ // CraftBukkit start - SPIGOT-5667 make sure all types are populated and mutable
++ Map<RecipeType<?>, Object2ObjectLinkedOpenHashMap<ResourceLocation, RecipeHolder<?>>> map1 = Maps.newHashMap();
++ for (RecipeType<?> recipeType : BuiltInRegistries.RECIPE_TYPE) {
++ map1.put(recipeType, new Object2ObjectLinkedOpenHashMap<>());
++ }
++ // CraftBukkit end
+ Builder<ResourceLocation, RecipeHolder<?>> builder = ImmutableMap.builder();
+- Iterator iterator = map.entrySet().iterator();
++ Iterator iterator = object.entrySet().iterator();
+
+ while (iterator.hasNext()) {
+ Entry<ResourceLocation, JsonElement> entry = (Entry) iterator.next();
+- ResourceLocation resourcelocation = (ResourceLocation) entry.getKey();
++ ResourceLocation minecraftkey = (ResourceLocation) entry.getKey();
+
+ try {
+- RecipeHolder<?> recipeholder = fromJson(resourcelocation, GsonHelper.convertToJsonObject((JsonElement) entry.getValue(), "top element"));
++ RecipeHolder<?> recipeholder = fromJson(minecraftkey, GsonHelper.convertToJsonObject((JsonElement) entry.getValue(), "top element"));
+
+- ((Builder) map1.computeIfAbsent(recipeholder.value().getType(), (recipetype) -> {
+- return ImmutableMap.builder();
+- })).put(resourcelocation, recipeholder);
+- builder.put(resourcelocation, recipeholder);
++ // CraftBukkit start
++ (map1.computeIfAbsent(recipeholder.value().getType(), (recipes) -> {
++ return new Object2ObjectLinkedOpenHashMap<>();
++ // CraftBukkit end
++ })).put(minecraftkey, recipeholder);
++ builder.put(minecraftkey, recipeholder);
+ } catch (IllegalArgumentException | JsonParseException jsonparseexception) {
+- RecipeManager.LOGGER.error("Parsing error loading recipe {}", resourcelocation, jsonparseexception);
++ RecipeManager.LOGGER.error("Parsing error loading recipe {}", minecraftkey, jsonparseexception);
+ }
+ }
+
+ this.recipes = (Map) map1.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry1) -> {
+- return ((Builder) entry1.getValue()).build();
++ return (entry1.getValue()); // CraftBukkit
+ }));
+- this.byName = builder.build();
++ this.byName = Maps.newHashMap(builder.build()); // CraftBukkit
+ RecipeManager.LOGGER.info("Loaded {} recipes", map1.size());
+ }
+
++ // CraftBukkit start
++ public void addRecipe(RecipeHolder<?> irecipe) {
++ Object2ObjectLinkedOpenHashMap<ResourceLocation, RecipeHolder<?>> map = this.recipes.get(irecipe.value().getType()); // CraftBukkit
++
++ if (byName.containsKey(irecipe.id()) || map.containsKey(irecipe.id())) {
++ throw new IllegalStateException("Duplicate recipe ignored with ID " + irecipe.id());
++ } else {
++ map.putAndMoveToFirst(irecipe.id(), irecipe); // CraftBukkit - SPIGOT-4638: last recipe gets priority
++ byName.put(irecipe.id(), irecipe);
++ }
++ }
++ // CraftBukkit end
++
+ public boolean hadErrorsLoading() {
+ return this.hasErrors;
+ }
+
+- public <C extends Container, T extends Recipe<C>> Optional<RecipeHolder<T>> getRecipeFor(RecipeType<T> recipetype, C c0, Level level) {
+- return this.byType(recipetype).values().stream().filter((recipeholder) -> {
+- return recipeholder.value().matches(c0, level);
++ public <C extends Container, T extends Recipe<C>> Optional<RecipeHolder<T>> getRecipeFor(RecipeType<T> recipeType, C inventory, Level level) {
++ // CraftBukkit start
++ Optional<RecipeHolder<T>> recipe = this.byType(recipeType).values().stream().filter((recipeholder) -> {
++ return recipeholder.value().matches(inventory, level);
+ }).findFirst();
++ inventory.setCurrentRecipe(recipe.orElse(null)); // CraftBukkit - Clear recipe when no recipe is found
++ return recipe;
++ // CraftBukkit end
+ }
+
+- public <C extends Container, T extends Recipe<C>> Optional<Pair<ResourceLocation, RecipeHolder<T>>> getRecipeFor(RecipeType<T> recipetype, C c0, Level level, @Nullable ResourceLocation resourcelocation) {
+- Map<ResourceLocation, RecipeHolder<T>> map = this.byType(recipetype);
++ public <C extends Container, T extends Recipe<C>> Optional<Pair<ResourceLocation, RecipeHolder<T>>> getRecipeFor(RecipeType<T> recipeType, C inventory, Level level, @Nullable ResourceLocation lastRecipe) {
++ Map<ResourceLocation, RecipeHolder<T>> map = this.byType(recipeType);
+
+- if (resourcelocation != null) {
+- RecipeHolder<T> recipeholder = (RecipeHolder) map.get(resourcelocation);
++ if (lastRecipe != null) {
++ RecipeHolder<T> recipeholder = (RecipeHolder) map.get(lastRecipe);
+
+- if (recipeholder != null && recipeholder.value().matches(c0, level)) {
+- return Optional.of(Pair.of(resourcelocation, recipeholder));
++ if (recipeholder != null && recipeholder.value().matches(inventory, level)) {
++ return Optional.of(Pair.of(lastRecipe, recipeholder));
+ }
+ }
+
+ return map.entrySet().stream().filter((entry) -> {
+- return ((RecipeHolder) entry.getValue()).value().matches(c0, level);
++ return ((RecipeHolder) entry.getValue()).value().matches(inventory, level);
+ }).findFirst().map((entry) -> {
+ return Pair.of((ResourceLocation) entry.getKey(), (RecipeHolder) entry.getValue());
+ });
+ }
+
+- public <C extends Container, T extends Recipe<C>> List<RecipeHolder<T>> getAllRecipesFor(RecipeType<T> recipetype) {
+- return List.copyOf(this.byType(recipetype).values());
++ public <C extends Container, T extends Recipe<C>> List<RecipeHolder<T>> getAllRecipesFor(RecipeType<T> recipeType) {
++ return List.copyOf(this.byType(recipeType).values());
+ }
+
+- public <C extends Container, T extends Recipe<C>> List<RecipeHolder<T>> getRecipesFor(RecipeType<T> recipetype, C c0, Level level) {
+- return (List) this.byType(recipetype).values().stream().filter((recipeholder) -> {
+- return recipeholder.value().matches(c0, level);
++ public <C extends Container, T extends Recipe<C>> List<RecipeHolder<T>> getRecipesFor(RecipeType<T> recipeType, C inventory, Level level) {
++ return (List) this.byType(recipeType).values().stream().filter((recipeholder) -> {
++ return recipeholder.value().matches(inventory, level);
+ }).sorted(Comparator.comparing((recipeholder) -> {
+ return recipeholder.value().getResultItem(level.registryAccess()).getDescriptionId();
+ })).collect(Collectors.toList());
+ }
+
+- private <C extends Container, T extends Recipe<C>> Map<ResourceLocation, RecipeHolder<T>> byType(RecipeType<T> recipetype) {
+- return (Map) this.recipes.getOrDefault(recipetype, Collections.emptyMap());
++ private <C extends Container, T extends Recipe<C>> Map<ResourceLocation, RecipeHolder<T>> byType(RecipeType<T> recipeType) {
++ return (Map) this.recipes.getOrDefault(recipeType, new Object2ObjectLinkedOpenHashMap<>()); // CraftBukkit
+ }
+
+- public <C extends Container, T extends Recipe<C>> NonNullList<ItemStack> getRemainingItemsFor(RecipeType<T> recipetype, C c0, Level level) {
+- Optional<RecipeHolder<T>> optional = this.getRecipeFor(recipetype, c0, level);
++ public <C extends Container, T extends Recipe<C>> NonNullList<ItemStack> getRemainingItemsFor(RecipeType<T> recipeType, C inventory, Level level) {
++ Optional<RecipeHolder<T>> optional = this.getRecipeFor(recipeType, inventory, level);
+
+ if (optional.isPresent()) {
+- return ((RecipeHolder) optional.get()).value().getRemainingItems(c0);
++ return ((RecipeHolder) optional.get()).value().getRemainingItems(inventory);
+ } else {
+- NonNullList<ItemStack> nonnulllist = NonNullList.withSize(c0.getContainerSize(), ItemStack.EMPTY);
++ NonNullList<ItemStack> nonnulllist = NonNullList.withSize(inventory.getContainerSize(), ItemStack.EMPTY);
+
+ for (int i = 0; i < nonnulllist.size(); ++i) {
+- nonnulllist.set(i, c0.getItem(i));
++ nonnulllist.set(i, inventory.getItem(i));
+ }
+
+ return nonnulllist;
+ }
+ }
+
+- public Optional<RecipeHolder<?>> byKey(ResourceLocation resourcelocation) {
+- return Optional.ofNullable((RecipeHolder) this.byName.get(resourcelocation));
++ public Optional<RecipeHolder<?>> byKey(ResourceLocation recipeId) {
++ return Optional.ofNullable((RecipeHolder) this.byName.get(recipeId));
+ }
+
+ public Collection<RecipeHolder<?>> getRecipes() {
+@@ -152,43 +180,62 @@
+ });
+ }
+
+- protected static RecipeHolder<?> fromJson(ResourceLocation resourcelocation, JsonObject jsonobject) {
+- Recipe<?> recipe = (Recipe) Util.getOrThrow(Recipe.CODEC.parse(JsonOps.INSTANCE, jsonobject), JsonParseException::new);
++ protected static RecipeHolder<?> fromJson(ResourceLocation minecraftkey, JsonObject jsonobject) {
++ Recipe<?> irecipe = (Recipe) Util.getOrThrow(Recipe.CODEC.parse(JsonOps.INSTANCE, jsonobject), JsonParseException::new);
+
+- return new RecipeHolder<>(resourcelocation, recipe);
++ return new RecipeHolder<>(minecraftkey, irecipe);
+ }
+
+- public void replaceRecipes(Iterable<RecipeHolder<?>> iterable) {
++ public void replaceRecipes(Iterable<RecipeHolder<?>> recipes) {
+ this.hasErrors = false;
+- Map<RecipeType<?>, Map<ResourceLocation, RecipeHolder<?>>> map = Maps.newHashMap();
++ Map<RecipeType<?>, Object2ObjectLinkedOpenHashMap<ResourceLocation, RecipeHolder<?>>> map = Maps.newHashMap(); // CraftBukkit
+ Builder<ResourceLocation, RecipeHolder<?>> builder = ImmutableMap.builder();
+
+- iterable.forEach((recipeholder) -> {
+- Map<ResourceLocation, RecipeHolder<?>> map1 = (Map) map.computeIfAbsent(recipeholder.value().getType(), (recipetype) -> {
+- return Maps.newHashMap();
++ recipes.forEach((recipeholder) -> {
++ Map<ResourceLocation, RecipeHolder<?>> map1 = (Map) map.computeIfAbsent(recipeholder.value().getType(), (recipes) -> {
++ return new Object2ObjectLinkedOpenHashMap<>(); // CraftBukkit
+ });
+- ResourceLocation resourcelocation = recipeholder.id();
+- RecipeHolder<?> recipeholder1 = (RecipeHolder) map1.put(resourcelocation, recipeholder);
++ ResourceLocation minecraftkey = recipeholder.id();
++ RecipeHolder<?> recipeholder1 = (RecipeHolder) map1.put(minecraftkey, recipeholder);
+
+- builder.put(resourcelocation, recipeholder);
++ builder.put(minecraftkey, recipeholder);
+ if (recipeholder1 != null) {
+- throw new IllegalStateException("Duplicate recipe ignored with ID " + resourcelocation);
++ throw new IllegalStateException("Duplicate recipe ignored with ID " + minecraftkey);
+ }
+ });
+ this.recipes = ImmutableMap.copyOf(map);
+- this.byName = builder.build();
++ this.byName = Maps.newHashMap(builder.build()); // CraftBukkit
+ }
+
+- public static <C extends Container, T extends Recipe<C>> RecipeManager.CachedCheck<C, T> createCheck(final RecipeType<T> recipetype) {
++ // CraftBukkit start
++ public boolean removeRecipe(ResourceLocation mcKey) {
++ for (Object2ObjectLinkedOpenHashMap<ResourceLocation, RecipeHolder<?>> recipes : recipes.values()) {
++ recipes.remove(mcKey);
++ }
++
++ return byName.remove(mcKey) != null;
++ }
++
++ public void clearRecipes() {
++ this.recipes = Maps.newHashMap();
++
++ for (RecipeType<?> recipeType : BuiltInRegistries.RECIPE_TYPE) {
++ this.recipes.put(recipeType, new Object2ObjectLinkedOpenHashMap<>());
++ }
++
++ this.byName = Maps.newHashMap();
++ }
++ // CraftBukkit end
++
++ public static <C extends Container, T extends Recipe<C>> RecipeManager.CachedCheck<C, T> createCheck(final RecipeType<T> recipeType) {
+ return new RecipeManager.CachedCheck<C, T>() {
+ @Nullable
+ private ResourceLocation lastRecipe;
+
+ @Override
+- @Override
+- public Optional<RecipeHolder<T>> getRecipeFor(C c0, Level level) {
+- RecipeManager recipemanager = level.getRecipeManager();
+- Optional<Pair<ResourceLocation, RecipeHolder<T>>> optional = recipemanager.getRecipeFor(recipetype, c0, level, this.lastRecipe);
++ public Optional<RecipeHolder<T>> getRecipeFor(C container, Level level) {
++ RecipeManager craftingmanager = level.getRecipeManager();
++ Optional<Pair<ResourceLocation, RecipeHolder<T>>> optional = craftingmanager.getRecipeFor(recipeType, container, level, this.lastRecipe);
+
+ if (optional.isPresent()) {
+ Pair<ResourceLocation, RecipeHolder<T>> pair = (Pair) optional.get();
diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/ShapedRecipe.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/ShapedRecipe.java.patch
new file mode 100644
index 0000000000..28bf8b2493
--- /dev/null
+++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/ShapedRecipe.java.patch
@@ -0,0 +1,235 @@
+--- a/net/minecraft/world/item/crafting/ShapedRecipe.java
++++ b/net/minecraft/world/item/crafting/ShapedRecipe.java
+@@ -6,11 +6,18 @@
+ import net.minecraft.core.RegistryAccess;
+ import net.minecraft.network.FriendlyByteBuf;
+ import net.minecraft.util.ExtraCodecs;
+-import net.minecraft.world.inventory.CraftingContainer;
++import net.minecraft.world.inventory.InventoryCrafting;
+ import net.minecraft.world.item.ItemStack;
+ import net.minecraft.world.level.Level;
++// CraftBukkit start
++import org.bukkit.NamespacedKey;
++import org.bukkit.craftbukkit.inventory.CraftItemStack;
++import org.bukkit.craftbukkit.inventory.CraftRecipe;
++import org.bukkit.craftbukkit.inventory.CraftShapedRecipe;
++import org.bukkit.inventory.RecipeChoice;
++// CraftBukkit end
+
+-public class ShapedRecipe implements CraftingRecipe {
++public class ShapedRecipe implements RecipeCrafting {
+
+ final ShapedRecipePattern pattern;
+ final ItemStack result;
+@@ -30,56 +37,109 @@
+ this(s, craftingbookcategory, shapedrecipepattern, itemstack, true);
+ }
+
++ // CraftBukkit start
+ @Override
++ public org.bukkit.inventory.ShapedRecipe toBukkitRecipe(NamespacedKey id) {
++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result);
++ CraftShapedRecipe recipe = new CraftShapedRecipe(id, result, this);
++ recipe.setGroup(this.group);
++ recipe.setCategory(CraftRecipe.getCategory(this.category()));
++
++ switch (this.pattern.height()) {
++ case 1:
++ switch (this.pattern.width()) {
++ case 1:
++ recipe.shape("a");
++ break;
++ case 2:
++ recipe.shape("ab");
++ break;
++ case 3:
++ recipe.shape("abc");
++ break;
++ }
++ break;
++ case 2:
++ switch (this.pattern.width()) {
++ case 1:
++ recipe.shape("a","b");
++ break;
++ case 2:
++ recipe.shape("ab","cd");
++ break;
++ case 3:
++ recipe.shape("abc","def");
++ break;
++ }
++ break;
++ case 3:
++ switch (this.pattern.width()) {
++ case 1:
++ recipe.shape("a","b","c");
++ break;
++ case 2:
++ recipe.shape("ab","cd","ef");
++ break;
++ case 3:
++ recipe.shape("abc","def","ghi");
++ break;
++ }
++ break;
++ }
++ char c = 'a';
++ for (Ingredient list : this.pattern.ingredients()) {
++ RecipeChoice choice = CraftRecipe.toBukkit(list);
++ if (choice != null) {
++ recipe.setIngredient(c, choice);
++ }
++
++ c++;
++ }
++ return recipe;
++ }
++ // CraftBukkit end
++
+ @Override
+ public RecipeSerializer<?> getSerializer() {
+ return RecipeSerializer.SHAPED_RECIPE;
+ }
+
+ @Override
+- @Override
+ public String getGroup() {
+ return this.group;
+ }
+
+ @Override
+- @Override
+ public CraftingBookCategory category() {
+ return this.category;
+ }
+
+ @Override
+- @Override
+- public ItemStack getResultItem(RegistryAccess registryaccess) {
++ public ItemStack getResultItem(RegistryAccess registryAccess) {
+ return this.result;
+ }
+
+ @Override
+- @Override
+ public NonNullList<Ingredient> getIngredients() {
+ return this.pattern.ingredients();
+ }
+
+ @Override
+- @Override
+ public boolean showNotification() {
+ return this.showNotification;
+ }
+
+ @Override
+- @Override
+- public boolean canCraftInDimensions(int i, int j) {
+- return i >= this.pattern.width() && j >= this.pattern.height();
++ public boolean canCraftInDimensions(int width, int height) {
++ return width >= this.pattern.width() && height >= this.pattern.height();
+ }
+
+- @Override
+- public boolean matches(CraftingContainer craftingcontainer, Level level) {
+- return this.pattern.matches(craftingcontainer);
++ public boolean matches(InventoryCrafting inv, Level level) {
++ return this.pattern.matches(inv);
+ }
+
+- @Override
+- public ItemStack assemble(CraftingContainer craftingcontainer, RegistryAccess registryaccess) {
+- return this.getResultItem(registryaccess).copy();
++ public ItemStack assemble(InventoryCrafting container, RegistryAccess registryAccess) {
++ return this.getResultItem(registryAccess).copy();
+ }
+
+ public int getWidth() {
+@@ -91,60 +151,56 @@
+ }
+
+ @Override
+- @Override
+ public boolean isIncomplete() {
+ NonNullList<Ingredient> nonnulllist = this.getIngredients();
+
+- return nonnulllist.isEmpty() || nonnulllist.stream().filter((ingredient) -> {
+- return !ingredient.isEmpty();
+- }).anyMatch((ingredient) -> {
+- return ingredient.getItems().length == 0;
++ return nonnulllist.isEmpty() || nonnulllist.stream().filter((recipeitemstack) -> {
++ return !recipeitemstack.isEmpty();
++ }).anyMatch((recipeitemstack) -> {
++ return recipeitemstack.getItems().length == 0;
+ });
+ }
+
+ public static class Serializer implements RecipeSerializer<ShapedRecipe> {
+
+ public static final Codec<ShapedRecipe> CODEC = RecordCodecBuilder.create((instance) -> {
+- return instance.group(ExtraCodecs.strictOptionalField(Codec.STRING, "group", "").forGetter((shapedrecipe) -> {
+- return shapedrecipe.group;
+- }), CraftingBookCategory.CODEC.fieldOf("category").orElse(CraftingBookCategory.MISC).forGetter((shapedrecipe) -> {
+- return shapedrecipe.category;
+- }), ShapedRecipePattern.MAP_CODEC.forGetter((shapedrecipe) -> {
+- return shapedrecipe.pattern;
+- }), ItemStack.ITEM_WITH_COUNT_CODEC.fieldOf("result").forGetter((shapedrecipe) -> {
+- return shapedrecipe.result;
+- }), ExtraCodecs.strictOptionalField(Codec.BOOL, "show_notification", true).forGetter((shapedrecipe) -> {
+- return shapedrecipe.showNotification;
++ return instance.group(ExtraCodecs.strictOptionalField(Codec.STRING, "group", "").forGetter((shapedrecipes) -> {
++ return shapedrecipes.group;
++ }), CraftingBookCategory.CODEC.fieldOf("category").orElse(CraftingBookCategory.MISC).forGetter((shapedrecipes) -> {
++ return shapedrecipes.category;
++ }), ShapedRecipePattern.MAP_CODEC.forGetter((shapedrecipes) -> {
++ return shapedrecipes.pattern;
++ }), ItemStack.ITEM_WITH_COUNT_CODEC.fieldOf("result").forGetter((shapedrecipes) -> {
++ return shapedrecipes.result;
++ }), ExtraCodecs.strictOptionalField(Codec.BOOL, "show_notification", true).forGetter((shapedrecipes) -> {
++ return shapedrecipes.showNotification;
+ })).apply(instance, ShapedRecipe::new);
+ });
+
+ public Serializer() {}
+
+ @Override
+- @Override
+ public Codec<ShapedRecipe> codec() {
+ return ShapedRecipe.Serializer.CODEC;
+ }
+
+ @Override
+- @Override
+- public ShapedRecipe fromNetwork(FriendlyByteBuf friendlybytebuf) {
+- String s = friendlybytebuf.readUtf();
+- CraftingBookCategory craftingbookcategory = (CraftingBookCategory) friendlybytebuf.readEnum(CraftingBookCategory.class);
+- ShapedRecipePattern shapedrecipepattern = ShapedRecipePattern.fromNetwork(friendlybytebuf);
+- ItemStack itemstack = friendlybytebuf.readItem();
+- boolean flag = friendlybytebuf.readBoolean();
++ public ShapedRecipe fromNetwork(FriendlyByteBuf packetdataserializer) {
++ String s = packetdataserializer.readUtf();
++ CraftingBookCategory craftingbookcategory = (CraftingBookCategory) packetdataserializer.readEnum(CraftingBookCategory.class);
++ ShapedRecipePattern shapedrecipepattern = ShapedRecipePattern.fromNetwork(packetdataserializer);
++ ItemStack itemstack = packetdataserializer.readItem();
++ boolean flag = packetdataserializer.readBoolean();
+
+ return new ShapedRecipe(s, craftingbookcategory, shapedrecipepattern, itemstack, flag);
+ }
+
+- @Override
+- public void toNetwork(FriendlyByteBuf friendlybytebuf, ShapedRecipe shapedrecipe) {
+- friendlybytebuf.writeUtf(shapedrecipe.group);
+- friendlybytebuf.writeEnum(shapedrecipe.category);
+- shapedrecipe.pattern.toNetwork(friendlybytebuf);
+- friendlybytebuf.writeItem(shapedrecipe.result);
+- friendlybytebuf.writeBoolean(shapedrecipe.showNotification);
++ public void toNetwork(FriendlyByteBuf buffer, ShapedRecipe recipe) {
++ buffer.writeUtf(recipe.group);
++ buffer.writeEnum(recipe.category);
++ recipe.pattern.toNetwork(buffer);
++ buffer.writeItem(recipe.result);
++ buffer.writeBoolean(recipe.showNotification);
+ }
+ }
+ }
diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/ShapelessRecipe.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/ShapelessRecipe.java.patch
new file mode 100644
index 0000000000..c3b7af75af
--- /dev/null
+++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/ShapelessRecipe.java.patch
@@ -0,0 +1,204 @@
+--- a/net/minecraft/world/item/crafting/ShapelessRecipe.java
++++ b/net/minecraft/world/item/crafting/ShapelessRecipe.java
+@@ -10,11 +10,17 @@
+ import net.minecraft.network.FriendlyByteBuf;
+ import net.minecraft.util.ExtraCodecs;
+ import net.minecraft.world.entity.player.StackedContents;
+-import net.minecraft.world.inventory.CraftingContainer;
++import net.minecraft.world.inventory.InventoryCrafting;
+ import net.minecraft.world.item.ItemStack;
+ import net.minecraft.world.level.Level;
++// CraftBukkit start
++import org.bukkit.NamespacedKey;
++import org.bukkit.craftbukkit.inventory.CraftItemStack;
++import org.bukkit.craftbukkit.inventory.CraftRecipe;
++import org.bukkit.craftbukkit.inventory.CraftShapelessRecipe;
++// CraftBukkit end
+
+-public class ShapelessRecipe implements CraftingRecipe {
++public class ShapelessRecipe implements RecipeCrafting {
+
+ final String group;
+ final CraftingBookCategory category;
+@@ -28,129 +34,134 @@
+ this.ingredients = nonnulllist;
+ }
+
++ // CraftBukkit start
++ @SuppressWarnings("unchecked")
+ @Override
++ public org.bukkit.inventory.ShapelessRecipe toBukkitRecipe(NamespacedKey id) {
++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result);
++ CraftShapelessRecipe recipe = new CraftShapelessRecipe(id, result, this);
++ recipe.setGroup(this.group);
++ recipe.setCategory(CraftRecipe.getCategory(this.category()));
++
++ for (Ingredient list : this.ingredients) {
++ recipe.addIngredient(CraftRecipe.toBukkit(list));
++ }
++ return recipe;
++ }
++ // CraftBukkit end
++
+ @Override
+ public RecipeSerializer<?> getSerializer() {
+ return RecipeSerializer.SHAPELESS_RECIPE;
+ }
+
+ @Override
+- @Override
+ public String getGroup() {
+ return this.group;
+ }
+
+ @Override
+- @Override
+ public CraftingBookCategory category() {
+ return this.category;
+ }
+
+ @Override
+- @Override
+- public ItemStack getResultItem(RegistryAccess registryaccess) {
++ public ItemStack getResultItem(RegistryAccess registryAccess) {
+ return this.result;
+ }
+
+ @Override
+- @Override
+ public NonNullList<Ingredient> getIngredients() {
+ return this.ingredients;
+ }
+
+- @Override
+- public boolean matches(CraftingContainer craftingcontainer, Level level) {
+- StackedContents stackedcontents = new StackedContents();
++ public boolean matches(InventoryCrafting inv, Level level) {
++ StackedContents autorecipestackmanager = new StackedContents();
+ int i = 0;
+
+- for (int j = 0; j < craftingcontainer.getContainerSize(); ++j) {
+- ItemStack itemstack = craftingcontainer.getItem(j);
++ for (int j = 0; j < inv.getContainerSize(); ++j) {
++ ItemStack itemstack = inv.getItem(j);
+
+ if (!itemstack.isEmpty()) {
+ ++i;
+- stackedcontents.accountStack(itemstack, 1);
++ autorecipestackmanager.accountStack(itemstack, 1);
+ }
+ }
+
+- return i == this.ingredients.size() && stackedcontents.canCraft(this, (IntList) null);
++ return i == this.ingredients.size() && autorecipestackmanager.canCraft(this, (IntList) null);
+ }
+
+- @Override
+- public ItemStack assemble(CraftingContainer craftingcontainer, RegistryAccess registryaccess) {
++ public ItemStack assemble(InventoryCrafting container, RegistryAccess registryAccess) {
+ return this.result.copy();
+ }
+
+ @Override
+- @Override
+- public boolean canCraftInDimensions(int i, int j) {
+- return i * j >= this.ingredients.size();
++ public boolean canCraftInDimensions(int width, int height) {
++ return width * height >= this.ingredients.size();
+ }
+
+ public static class Serializer implements RecipeSerializer<ShapelessRecipe> {
+
+ private static final Codec<ShapelessRecipe> CODEC = RecordCodecBuilder.create((instance) -> {
+- return instance.group(ExtraCodecs.strictOptionalField(Codec.STRING, "group", "").forGetter((shapelessrecipe) -> {
+- return shapelessrecipe.group;
+- }), CraftingBookCategory.CODEC.fieldOf("category").orElse(CraftingBookCategory.MISC).forGetter((shapelessrecipe) -> {
+- return shapelessrecipe.category;
+- }), ItemStack.ITEM_WITH_COUNT_CODEC.fieldOf("result").forGetter((shapelessrecipe) -> {
+- return shapelessrecipe.result;
++ return instance.group(ExtraCodecs.strictOptionalField(Codec.STRING, "group", "").forGetter((shapelessrecipes) -> {
++ return shapelessrecipes.group;
++ }), CraftingBookCategory.CODEC.fieldOf("category").orElse(CraftingBookCategory.MISC).forGetter((shapelessrecipes) -> {
++ return shapelessrecipes.category;
++ }), ItemStack.ITEM_WITH_COUNT_CODEC.fieldOf("result").forGetter((shapelessrecipes) -> {
++ return shapelessrecipes.result;
+ }), Ingredient.CODEC_NONEMPTY.listOf().fieldOf("ingredients").flatXmap((list) -> {
+- Ingredient[] aingredient = (Ingredient[]) list.stream().filter((ingredient) -> {
+- return !ingredient.isEmpty();
++ Ingredient[] arecipeitemstack = (Ingredient[]) list.stream().filter((recipeitemstack) -> {
++ return !recipeitemstack.isEmpty();
+ }).toArray((i) -> {
+ return new Ingredient[i];
+ });
+
+- return aingredient.length == 0 ? DataResult.error(() -> {
++ return arecipeitemstack.length == 0 ? DataResult.error(() -> {
+ return "No ingredients for shapeless recipe";
+- }) : (aingredient.length > 9 ? DataResult.error(() -> {
++ }) : (arecipeitemstack.length > 9 ? DataResult.error(() -> {
+ return "Too many ingredients for shapeless recipe";
+- }) : DataResult.success(NonNullList.of(Ingredient.EMPTY, aingredient)));
+- }, DataResult::success).forGetter((shapelessrecipe) -> {
+- return shapelessrecipe.ingredients;
++ }) : DataResult.success(NonNullList.of(Ingredient.EMPTY, arecipeitemstack)));
++ }, DataResult::success).forGetter((shapelessrecipes) -> {
++ return shapelessrecipes.ingredients;
+ })).apply(instance, ShapelessRecipe::new);
+ });
+
+ public Serializer() {}
+
+ @Override
+- @Override
+ public Codec<ShapelessRecipe> codec() {
+ return ShapelessRecipe.Serializer.CODEC;
+ }
+
+ @Override
+- @Override
+- public ShapelessRecipe fromNetwork(FriendlyByteBuf friendlybytebuf) {
+- String s = friendlybytebuf.readUtf();
+- CraftingBookCategory craftingbookcategory = (CraftingBookCategory) friendlybytebuf.readEnum(CraftingBookCategory.class);
+- int i = friendlybytebuf.readVarInt();
++ public ShapelessRecipe fromNetwork(FriendlyByteBuf packetdataserializer) {
++ String s = packetdataserializer.readUtf();
++ CraftingBookCategory craftingbookcategory = (CraftingBookCategory) packetdataserializer.readEnum(CraftingBookCategory.class);
++ int i = packetdataserializer.readVarInt();
+ NonNullList<Ingredient> nonnulllist = NonNullList.withSize(i, Ingredient.EMPTY);
+
+ for (int j = 0; j < nonnulllist.size(); ++j) {
+- nonnulllist.set(j, Ingredient.fromNetwork(friendlybytebuf));
++ nonnulllist.set(j, Ingredient.fromNetwork(packetdataserializer));
+ }
+
+- ItemStack itemstack = friendlybytebuf.readItem();
++ ItemStack itemstack = packetdataserializer.readItem();
+
+ return new ShapelessRecipe(s, craftingbookcategory, itemstack, nonnulllist);
+ }
+
+- @Override
+- public void toNetwork(FriendlyByteBuf friendlybytebuf, ShapelessRecipe shapelessrecipe) {
+- friendlybytebuf.writeUtf(shapelessrecipe.group);
+- friendlybytebuf.writeEnum(shapelessrecipe.category);
+- friendlybytebuf.writeVarInt(shapelessrecipe.ingredients.size());
+- Iterator iterator = shapelessrecipe.ingredients.iterator();
++ public void toNetwork(FriendlyByteBuf buffer, ShapelessRecipe recipe) {
++ buffer.writeUtf(recipe.group);
++ buffer.writeEnum(recipe.category);
++ buffer.writeVarInt(recipe.ingredients.size());
++ Iterator iterator = recipe.ingredients.iterator();
+
+ while (iterator.hasNext()) {
+- Ingredient ingredient = (Ingredient) iterator.next();
++ Ingredient recipeitemstack = (Ingredient) iterator.next();
+
+- ingredient.toNetwork(friendlybytebuf);
++ recipeitemstack.toNetwork(buffer);
+ }
+
+- friendlybytebuf.writeItem(shapelessrecipe.result);
++ buffer.writeItem(recipe.result);
+ }
+ }
+ }
diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmeltingRecipe.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmeltingRecipe.java.patch
new file mode 100644
index 0000000000..6869ddcb4f
--- /dev/null
+++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmeltingRecipe.java.patch
@@ -0,0 +1,47 @@
+--- a/net/minecraft/world/item/crafting/SmeltingRecipe.java
++++ b/net/minecraft/world/item/crafting/SmeltingRecipe.java
+@@ -3,21 +3,40 @@
+ import net.minecraft.world.item.ItemStack;
+ import net.minecraft.world.level.block.Blocks;
+
++// CraftBukkit start
++import org.bukkit.NamespacedKey;
++import org.bukkit.craftbukkit.inventory.CraftFurnaceRecipe;
++import org.bukkit.craftbukkit.inventory.CraftItemStack;
++import org.bukkit.craftbukkit.inventory.CraftRecipe;
++import org.bukkit.inventory.Recipe;
++// CraftBukkit end
++
+ public class SmeltingRecipe extends AbstractCookingRecipe {
+
+- public SmeltingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient ingredient, ItemStack itemstack, float f, int i) {
+- super(RecipeType.SMELTING, s, cookingbookcategory, ingredient, itemstack, f, i);
++ public SmeltingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient recipeitemstack, ItemStack itemstack, float f, int i) {
++ super(RecipeType.SMELTING, s, cookingbookcategory, recipeitemstack, itemstack, f, i);
+ }
+
+ @Override
+- @Override
+ public ItemStack getToastSymbol() {
+ return new ItemStack(Blocks.FURNACE);
+ }
+
+ @Override
+- @Override
+ public RecipeSerializer<?> getSerializer() {
+ return RecipeSerializer.SMELTING_RECIPE;
+ }
++
++ // CraftBukkit start
++ @Override
++ public Recipe toBukkitRecipe(NamespacedKey id) {
++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result);
++
++ CraftFurnaceRecipe recipe = new CraftFurnaceRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime);
++ recipe.setGroup(this.group);
++ recipe.setCategory(CraftRecipe.getCategory(this.category()));
++
++ return recipe;
++ }
++ // CraftBukkit end
+ }
diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmithingTransformRecipe.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmithingTransformRecipe.java.patch
new file mode 100644
index 0000000000..d4f0b6a3ff
--- /dev/null
+++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmithingTransformRecipe.java.patch
@@ -0,0 +1,159 @@
+--- a/net/minecraft/world/item/crafting/SmithingTransformRecipe.java
++++ b/net/minecraft/world/item/crafting/SmithingTransformRecipe.java
+@@ -9,6 +9,13 @@
+ import net.minecraft.world.Container;
+ import net.minecraft.world.item.ItemStack;
+ import net.minecraft.world.level.Level;
++// CraftBukkit start
++import org.bukkit.NamespacedKey;
++import org.bukkit.craftbukkit.inventory.CraftItemStack;
++import org.bukkit.craftbukkit.inventory.CraftRecipe;
++import org.bukkit.craftbukkit.inventory.CraftSmithingTransformRecipe;
++import org.bukkit.inventory.Recipe;
++// CraftBukkit end
+
+ public class SmithingTransformRecipe implements SmithingRecipe {
+
+@@ -17,70 +24,73 @@
+ final Ingredient addition;
+ final ItemStack result;
+
+- public SmithingTransformRecipe(Ingredient ingredient, Ingredient ingredient1, Ingredient ingredient2, ItemStack itemstack) {
+- this.template = ingredient;
+- this.base = ingredient1;
+- this.addition = ingredient2;
++ public SmithingTransformRecipe(Ingredient recipeitemstack, Ingredient recipeitemstack1, Ingredient recipeitemstack2, ItemStack itemstack) {
++ this.template = recipeitemstack;
++ this.base = recipeitemstack1;
++ this.addition = recipeitemstack2;
+ this.result = itemstack;
+ }
+
+ @Override
+- @Override
+ public boolean matches(Container container, Level level) {
+ return this.template.test(container.getItem(0)) && this.base.test(container.getItem(1)) && this.addition.test(container.getItem(2));
+ }
+
+ @Override
+- @Override
+- public ItemStack assemble(Container container, RegistryAccess registryaccess) {
++ public ItemStack assemble(Container container, RegistryAccess registryAccess) {
+ ItemStack itemstack = this.result.copy();
+- CompoundTag compoundtag = container.getItem(1).getTag();
++ CompoundTag nbttagcompound = container.getItem(1).getTag();
+
+- if (compoundtag != null) {
+- itemstack.setTag(compoundtag.copy());
++ if (nbttagcompound != null) {
++ itemstack.setTag(nbttagcompound.copy());
+ }
+
+ return itemstack;
+ }
+
+ @Override
+- @Override
+- public ItemStack getResultItem(RegistryAccess registryaccess) {
++ public ItemStack getResultItem(RegistryAccess registryAccess) {
+ return this.result;
+ }
+
+ @Override
+- @Override
+- public boolean isTemplateIngredient(ItemStack itemstack) {
+- return this.template.test(itemstack);
++ public boolean isTemplateIngredient(ItemStack stack) {
++ return this.template.test(stack);
+ }
+
+ @Override
+- @Override
+- public boolean isBaseIngredient(ItemStack itemstack) {
+- return this.base.test(itemstack);
++ public boolean isBaseIngredient(ItemStack stack) {
++ return this.base.test(stack);
+ }
+
+ @Override
+- @Override
+- public boolean isAdditionIngredient(ItemStack itemstack) {
+- return this.addition.test(itemstack);
++ public boolean isAdditionIngredient(ItemStack stack) {
++ return this.addition.test(stack);
+ }
+
+ @Override
+- @Override
+ public RecipeSerializer<?> getSerializer() {
+ return RecipeSerializer.SMITHING_TRANSFORM;
+ }
+
+ @Override
+- @Override
+ public boolean isIncomplete() {
+ return Stream.of(this.template, this.base, this.addition).anyMatch(Ingredient::isEmpty);
+ }
+
+- public static class Serializer implements RecipeSerializer<SmithingTransformRecipe> {
++ // CraftBukkit start
++ @Override
++ public Recipe toBukkitRecipe(NamespacedKey id) {
++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result);
+
++ CraftSmithingTransformRecipe recipe = new CraftSmithingTransformRecipe(id, result, CraftRecipe.toBukkit(this.template), CraftRecipe.toBukkit(this.base), CraftRecipe.toBukkit(this.addition));
++
++ return recipe;
++ }
++ // CraftBukkit end
++
++ public static class a implements RecipeSerializer<SmithingTransformRecipe> {
++
+ private static final Codec<SmithingTransformRecipe> CODEC = RecordCodecBuilder.create((instance) -> {
+ return instance.group(Ingredient.CODEC.fieldOf("template").forGetter((smithingtransformrecipe) -> {
+ return smithingtransformrecipe.template;
+@@ -93,31 +103,28 @@
+ })).apply(instance, SmithingTransformRecipe::new);
+ });
+
+- public Serializer() {}
++ public a() {}
+
+ @Override
+- @Override
+ public Codec<SmithingTransformRecipe> codec() {
+- return SmithingTransformRecipe.Serializer.CODEC;
++ return SmithingTransformRecipe.a.CODEC;
+ }
+
+ @Override
+- @Override
+- public SmithingTransformRecipe fromNetwork(FriendlyByteBuf friendlybytebuf) {
+- Ingredient ingredient = Ingredient.fromNetwork(friendlybytebuf);
+- Ingredient ingredient1 = Ingredient.fromNetwork(friendlybytebuf);
+- Ingredient ingredient2 = Ingredient.fromNetwork(friendlybytebuf);
+- ItemStack itemstack = friendlybytebuf.readItem();
++ public SmithingTransformRecipe fromNetwork(FriendlyByteBuf packetdataserializer) {
++ Ingredient recipeitemstack = Ingredient.fromNetwork(packetdataserializer);
++ Ingredient recipeitemstack1 = Ingredient.fromNetwork(packetdataserializer);
++ Ingredient recipeitemstack2 = Ingredient.fromNetwork(packetdataserializer);
++ ItemStack itemstack = packetdataserializer.readItem();
+
+- return new SmithingTransformRecipe(ingredient, ingredient1, ingredient2, itemstack);
++ return new SmithingTransformRecipe(recipeitemstack, recipeitemstack1, recipeitemstack2, itemstack);
+ }
+
+- @Override
+- public void toNetwork(FriendlyByteBuf friendlybytebuf, SmithingTransformRecipe smithingtransformrecipe) {
+- smithingtransformrecipe.template.toNetwork(friendlybytebuf);
+- smithingtransformrecipe.base.toNetwork(friendlybytebuf);
+- smithingtransformrecipe.addition.toNetwork(friendlybytebuf);
+- friendlybytebuf.writeItem(smithingtransformrecipe.result);
++ public void toNetwork(FriendlyByteBuf packetdataserializer, SmithingTransformRecipe smithingtransformrecipe) {
++ smithingtransformrecipe.template.toNetwork(packetdataserializer);
++ smithingtransformrecipe.base.toNetwork(packetdataserializer);
++ smithingtransformrecipe.addition.toNetwork(packetdataserializer);
++ packetdataserializer.writeItem(smithingtransformrecipe.result);
+ }
+ }
+ }
diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmithingTrimRecipe.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmithingTrimRecipe.java.patch
new file mode 100644
index 0000000000..8e6da53406
--- /dev/null
+++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmithingTrimRecipe.java.patch
@@ -0,0 +1,178 @@
+--- a/net/minecraft/world/item/crafting/SmithingTrimRecipe.java
++++ b/net/minecraft/world/item/crafting/SmithingTrimRecipe.java
+@@ -17,6 +17,12 @@
+ import net.minecraft.world.item.armortrim.TrimPattern;
+ import net.minecraft.world.item.armortrim.TrimPatterns;
+ import net.minecraft.world.level.Level;
++// CraftBukkit start
++import org.bukkit.NamespacedKey;
++import org.bukkit.craftbukkit.inventory.CraftRecipe;
++import org.bukkit.craftbukkit.inventory.CraftSmithingTrimRecipe;
++import org.bukkit.inventory.Recipe;
++// CraftBukkit end
+
+ public class SmithingTrimRecipe implements SmithingRecipe {
+
+@@ -24,29 +30,27 @@
+ final Ingredient base;
+ final Ingredient addition;
+
+- public SmithingTrimRecipe(Ingredient ingredient, Ingredient ingredient1, Ingredient ingredient2) {
+- this.template = ingredient;
+- this.base = ingredient1;
+- this.addition = ingredient2;
++ public SmithingTrimRecipe(Ingredient recipeitemstack, Ingredient recipeitemstack1, Ingredient recipeitemstack2) {
++ this.template = recipeitemstack;
++ this.base = recipeitemstack1;
++ this.addition = recipeitemstack2;
+ }
+
+ @Override
+- @Override
+ public boolean matches(Container container, Level level) {
+ return this.template.test(container.getItem(0)) && this.base.test(container.getItem(1)) && this.addition.test(container.getItem(2));
+ }
+
+ @Override
+- @Override
+- public ItemStack assemble(Container container, RegistryAccess registryaccess) {
++ public ItemStack assemble(Container container, RegistryAccess registryAccess) {
+ ItemStack itemstack = container.getItem(1);
+
+ if (this.base.test(itemstack)) {
+- Optional<Holder.Reference<TrimMaterial>> optional = TrimMaterials.getFromIngredient(registryaccess, container.getItem(2));
+- Optional<Holder.Reference<TrimPattern>> optional1 = TrimPatterns.getFromTemplate(registryaccess, container.getItem(0));
++ Optional<Holder.Reference<TrimMaterial>> optional = TrimMaterials.getFromIngredient(registryAccess, container.getItem(2));
++ Optional<Holder.Reference<TrimPattern>> optional1 = TrimPatterns.getFromTemplate(registryAccess, container.getItem(0));
+
+ if (optional.isPresent() && optional1.isPresent()) {
+- Optional<ArmorTrim> optional2 = ArmorTrim.getTrim(registryaccess, itemstack, false);
++ Optional<ArmorTrim> optional2 = ArmorTrim.getTrim(registryAccess, itemstack, false);
+
+ if (optional2.isPresent() && ((ArmorTrim) optional2.get()).hasPatternAndMaterial((Holder) optional1.get(), (Holder) optional.get())) {
+ return ItemStack.EMPTY;
+@@ -57,7 +61,7 @@
+ itemstack1.setCount(1);
+ ArmorTrim armortrim = new ArmorTrim((Holder) optional.get(), (Holder) optional1.get());
+
+- if (ArmorTrim.setTrim(registryaccess, itemstack1, armortrim)) {
++ if (ArmorTrim.setTrim(registryAccess, itemstack1, armortrim)) {
+ return itemstack1;
+ }
+ }
+@@ -67,18 +71,17 @@
+ }
+
+ @Override
+- @Override
+- public ItemStack getResultItem(RegistryAccess registryaccess) {
++ public ItemStack getResultItem(RegistryAccess registryAccess) {
+ ItemStack itemstack = new ItemStack(Items.IRON_CHESTPLATE);
+- Optional<Holder.Reference<TrimPattern>> optional = registryaccess.registryOrThrow(Registries.TRIM_PATTERN).holders().findFirst();
++ Optional<Holder.Reference<TrimPattern>> optional = registryAccess.registryOrThrow(Registries.TRIM_PATTERN).holders().findFirst();
+
+ if (optional.isPresent()) {
+- Optional<Holder.Reference<TrimMaterial>> optional1 = registryaccess.registryOrThrow(Registries.TRIM_MATERIAL).getHolder(TrimMaterials.REDSTONE);
++ Optional<Holder.Reference<TrimMaterial>> optional1 = registryAccess.registryOrThrow(Registries.TRIM_MATERIAL).getHolder(TrimMaterials.REDSTONE);
+
+ if (optional1.isPresent()) {
+ ArmorTrim armortrim = new ArmorTrim((Holder) optional1.get(), (Holder) optional.get());
+
+- ArmorTrim.setTrim(registryaccess, itemstack, armortrim);
++ ArmorTrim.setTrim(registryAccess, itemstack, armortrim);
+ }
+ }
+
+@@ -86,37 +89,39 @@
+ }
+
+ @Override
+- @Override
+- public boolean isTemplateIngredient(ItemStack itemstack) {
+- return this.template.test(itemstack);
++ public boolean isTemplateIngredient(ItemStack stack) {
++ return this.template.test(stack);
+ }
+
+ @Override
+- @Override
+- public boolean isBaseIngredient(ItemStack itemstack) {
+- return this.base.test(itemstack);
++ public boolean isBaseIngredient(ItemStack stack) {
++ return this.base.test(stack);
+ }
+
+ @Override
+- @Override
+- public boolean isAdditionIngredient(ItemStack itemstack) {
+- return this.addition.test(itemstack);
++ public boolean isAdditionIngredient(ItemStack stack) {
++ return this.addition.test(stack);
+ }
+
+ @Override
+- @Override
+ public RecipeSerializer<?> getSerializer() {
+ return RecipeSerializer.SMITHING_TRIM;
+ }
+
+ @Override
+- @Override
+ public boolean isIncomplete() {
+ return Stream.of(this.template, this.base, this.addition).anyMatch(Ingredient::isEmpty);
+ }
+
+- public static class Serializer implements RecipeSerializer<SmithingTrimRecipe> {
++ // CraftBukkit start
++ @Override
++ public Recipe toBukkitRecipe(NamespacedKey id) {
++ return new CraftSmithingTrimRecipe(id, CraftRecipe.toBukkit(this.template), CraftRecipe.toBukkit(this.base), CraftRecipe.toBukkit(this.addition));
++ }
++ // CraftBukkit end
+
++ public static class a implements RecipeSerializer<SmithingTrimRecipe> {
++
+ private static final Codec<SmithingTrimRecipe> CODEC = RecordCodecBuilder.create((instance) -> {
+ return instance.group(Ingredient.CODEC.fieldOf("template").forGetter((smithingtrimrecipe) -> {
+ return smithingtrimrecipe.template;
+@@ -127,29 +132,26 @@
+ })).apply(instance, SmithingTrimRecipe::new);
+ });
+
+- public Serializer() {}
++ public a() {}
+
+ @Override
+- @Override
+ public Codec<SmithingTrimRecipe> codec() {
+- return SmithingTrimRecipe.Serializer.CODEC;
++ return SmithingTrimRecipe.a.CODEC;
+ }
+
+ @Override
+- @Override
+- public SmithingTrimRecipe fromNetwork(FriendlyByteBuf friendlybytebuf) {
+- Ingredient ingredient = Ingredient.fromNetwork(friendlybytebuf);
+- Ingredient ingredient1 = Ingredient.fromNetwork(friendlybytebuf);
+- Ingredient ingredient2 = Ingredient.fromNetwork(friendlybytebuf);
++ public SmithingTrimRecipe fromNetwork(FriendlyByteBuf packetdataserializer) {
++ Ingredient recipeitemstack = Ingredient.fromNetwork(packetdataserializer);
++ Ingredient recipeitemstack1 = Ingredient.fromNetwork(packetdataserializer);
++ Ingredient recipeitemstack2 = Ingredient.fromNetwork(packetdataserializer);
+
+- return new SmithingTrimRecipe(ingredient, ingredient1, ingredient2);
++ return new SmithingTrimRecipe(recipeitemstack, recipeitemstack1, recipeitemstack2);
+ }
+
+- @Override
+- public void toNetwork(FriendlyByteBuf friendlybytebuf, SmithingTrimRecipe smithingtrimrecipe) {
+- smithingtrimrecipe.template.toNetwork(friendlybytebuf);
+- smithingtrimrecipe.base.toNetwork(friendlybytebuf);
+- smithingtrimrecipe.addition.toNetwork(friendlybytebuf);
++ public void toNetwork(FriendlyByteBuf packetdataserializer, SmithingTrimRecipe smithingtrimrecipe) {
++ smithingtrimrecipe.template.toNetwork(packetdataserializer);
++ smithingtrimrecipe.base.toNetwork(packetdataserializer);
++ smithingtrimrecipe.addition.toNetwork(packetdataserializer);
+ }
+ }
+ }
diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmokingRecipe.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmokingRecipe.java.patch
new file mode 100644
index 0000000000..d5799e7952
--- /dev/null
+++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmokingRecipe.java.patch
@@ -0,0 +1,47 @@
+--- a/net/minecraft/world/item/crafting/SmokingRecipe.java
++++ b/net/minecraft/world/item/crafting/SmokingRecipe.java
+@@ -3,21 +3,40 @@
+ import net.minecraft.world.item.ItemStack;
+ import net.minecraft.world.level.block.Blocks;
+
++// CraftBukkit start
++import org.bukkit.NamespacedKey;
++import org.bukkit.craftbukkit.inventory.CraftItemStack;
++import org.bukkit.craftbukkit.inventory.CraftRecipe;
++import org.bukkit.craftbukkit.inventory.CraftSmokingRecipe;
++import org.bukkit.inventory.Recipe;
++// CraftBukkit end
++
+ public class SmokingRecipe extends AbstractCookingRecipe {
+
+- public SmokingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient ingredient, ItemStack itemstack, float f, int i) {
+- super(RecipeType.SMOKING, s, cookingbookcategory, ingredient, itemstack, f, i);
++ public SmokingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient recipeitemstack, ItemStack itemstack, float f, int i) {
++ super(RecipeType.SMOKING, s, cookingbookcategory, recipeitemstack, itemstack, f, i);
+ }
+
+ @Override
+- @Override
+ public ItemStack getToastSymbol() {
+ return new ItemStack(Blocks.SMOKER);
+ }
+
+ @Override
+- @Override
+ public RecipeSerializer<?> getSerializer() {
+ return RecipeSerializer.SMOKING_RECIPE;
+ }
++
++ // CraftBukkit start
++ @Override
++ public Recipe toBukkitRecipe(NamespacedKey id) {
++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result);
++
++ CraftSmokingRecipe recipe = new CraftSmokingRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime);
++ recipe.setGroup(this.group);
++ recipe.setCategory(CraftRecipe.getCategory(this.category()));
++
++ return recipe;
++ }
++ // CraftBukkit end
+ }
diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/StonecutterRecipe.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/StonecutterRecipe.java.patch
new file mode 100644
index 0000000000..0b933cd748
--- /dev/null
+++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/StonecutterRecipe.java.patch
@@ -0,0 +1,48 @@
+--- a/net/minecraft/world/item/crafting/StonecutterRecipe.java
++++ b/net/minecraft/world/item/crafting/StonecutterRecipe.java
+@@ -5,21 +5,39 @@
+ import net.minecraft.world.level.Level;
+ import net.minecraft.world.level.block.Blocks;
+
++// CraftBukkit start
++import org.bukkit.NamespacedKey;
++import org.bukkit.craftbukkit.inventory.CraftItemStack;
++import org.bukkit.craftbukkit.inventory.CraftRecipe;
++import org.bukkit.craftbukkit.inventory.CraftStonecuttingRecipe;
++import org.bukkit.inventory.Recipe;
++// CraftBukkit end
++
+ public class StonecutterRecipe extends SingleItemRecipe {
+
+- public StonecutterRecipe(String s, Ingredient ingredient, ItemStack itemstack) {
+- super(RecipeType.STONECUTTING, RecipeSerializer.STONECUTTER, s, ingredient, itemstack);
++ public StonecutterRecipe(String s, Ingredient recipeitemstack, ItemStack itemstack) {
++ super(RecipeType.STONECUTTING, RecipeSerializer.STONECUTTER, s, recipeitemstack, itemstack);
+ }
+
+ @Override
+- @Override
+- public boolean matches(Container container, Level level) {
+- return this.ingredient.test(container.getItem(0));
++ public boolean matches(Container inv, Level level) {
++ return this.ingredient.test(inv.getItem(0));
+ }
+
+ @Override
+- @Override
+ public ItemStack getToastSymbol() {
+ return new ItemStack(Blocks.STONECUTTER);
+ }
++
++ // CraftBukkit start
++ @Override
++ public Recipe toBukkitRecipe(NamespacedKey id) {
++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result);
++
++ CraftStonecuttingRecipe recipe = new CraftStonecuttingRecipe(id, result, CraftRecipe.toBukkit(this.ingredient));
++ recipe.setGroup(this.group);
++
++ return recipe;
++ }
++ // CraftBukkit end
+ }