package net.minecraft.world.item.crafting; import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.HolderLookup; import net.minecraft.core.NonNullList; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; public class ShapelessRecipe implements CraftingRecipe { final String group; final CraftingBookCategory category; final ItemStack result; final NonNullList ingredients; public ShapelessRecipe(String group, CraftingBookCategory category, ItemStack result, NonNullList ingredients) { this.group = group; this.category = category; this.result = result; this.ingredients = ingredients; } @Override public RecipeSerializer getSerializer() { return RecipeSerializer.SHAPELESS_RECIPE; } @Override public String getGroup() { return this.group; } @Override public CraftingBookCategory category() { return this.category; } @Override public ItemStack getResultItem(HolderLookup.Provider registries) { return this.result; } @Override public NonNullList getIngredients() { return this.ingredients; } public boolean matches(CraftingInput input, Level level) { if (input.ingredientCount() != this.ingredients.size()) { return false; } else { return input.size() == 1 && this.ingredients.size() == 1 ? ((Ingredient)this.ingredients.getFirst()).test(input.getItem(0)) : input.stackedContents().canCraft(this, null); } } public ItemStack assemble(CraftingInput input, HolderLookup.Provider registries) { return this.result.copy(); } @Override public boolean canCraftInDimensions(int width, int height) { return width * height >= this.ingredients.size(); } public static class Serializer implements RecipeSerializer { private static final MapCodec CODEC = RecordCodecBuilder.mapCodec( instance -> instance.group( Codec.STRING.optionalFieldOf("group", "").forGetter(shapelessRecipe -> shapelessRecipe.group), CraftingBookCategory.CODEC.fieldOf("category").orElse(CraftingBookCategory.MISC).forGetter(shapelessRecipe -> shapelessRecipe.category), ItemStack.STRICT_CODEC.fieldOf("result").forGetter(shapelessRecipe -> shapelessRecipe.result), Ingredient.CODEC_NONEMPTY .listOf() .fieldOf("ingredients") .flatXmap( list -> { Ingredient[] ingredients = (Ingredient[])list.stream().filter(ingredient -> !ingredient.isEmpty()).toArray(Ingredient[]::new); if (ingredients.length == 0) { return DataResult.error(() -> "No ingredients for shapeless recipe"); } else { return ingredients.length > 9 ? DataResult.error(() -> "Too many ingredients for shapeless recipe") : DataResult.success(NonNullList.of(Ingredient.EMPTY, ingredients)); } }, DataResult::success ) .forGetter(shapelessRecipe -> shapelessRecipe.ingredients) ) .apply(instance, ShapelessRecipe::new) ); public static final StreamCodec STREAM_CODEC = StreamCodec.of( ShapelessRecipe.Serializer::toNetwork, ShapelessRecipe.Serializer::fromNetwork ); @Override public MapCodec codec() { return CODEC; } @Override public StreamCodec streamCodec() { return STREAM_CODEC; } private static ShapelessRecipe fromNetwork(RegistryFriendlyByteBuf buffer) { String string = buffer.readUtf(); CraftingBookCategory craftingBookCategory = buffer.readEnum(CraftingBookCategory.class); int i = buffer.readVarInt(); NonNullList nonNullList = NonNullList.withSize(i, Ingredient.EMPTY); nonNullList.replaceAll(ingredient -> Ingredient.CONTENTS_STREAM_CODEC.decode(buffer)); ItemStack itemStack = ItemStack.STREAM_CODEC.decode(buffer); return new ShapelessRecipe(string, craftingBookCategory, itemStack, nonNullList); } private static void toNetwork(RegistryFriendlyByteBuf buffer, ShapelessRecipe recipe) { buffer.writeUtf(recipe.group); buffer.writeEnum(recipe.category); buffer.writeVarInt(recipe.ingredients.size()); for (Ingredient ingredient : recipe.ingredients) { Ingredient.CONTENTS_STREAM_CODEC.encode(buffer, ingredient); } ItemStack.STREAM_CODEC.encode(buffer, recipe.result); } } }