package net.minecraft.world.item.crafting; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import java.util.Optional; import java.util.stream.Stream; import net.minecraft.core.Holder; import net.minecraft.core.HolderLookup; import net.minecraft.core.component.DataComponents; import net.minecraft.core.registries.Registries; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.armortrim.ArmorTrim; import net.minecraft.world.item.armortrim.TrimMaterial; import net.minecraft.world.item.armortrim.TrimMaterials; import net.minecraft.world.item.armortrim.TrimPattern; import net.minecraft.world.item.armortrim.TrimPatterns; import net.minecraft.world.level.Level; public class SmithingTrimRecipe implements SmithingRecipe { final Ingredient template; final Ingredient base; final Ingredient addition; public SmithingTrimRecipe(Ingredient template, Ingredient base, Ingredient addition) { this.template = template; this.base = base; this.addition = addition; } public boolean matches(SmithingRecipeInput input, Level level) { return this.template.test(input.template()) && this.base.test(input.base()) && this.addition.test(input.addition()); } public ItemStack assemble(SmithingRecipeInput input, HolderLookup.Provider registries) { ItemStack itemStack = input.base(); if (this.base.test(itemStack)) { Optional> optional = TrimMaterials.getFromIngredient(registries, input.addition()); Optional> optional2 = TrimPatterns.getFromTemplate(registries, input.template()); if (optional.isPresent() && optional2.isPresent()) { ArmorTrim armorTrim = itemStack.get(DataComponents.TRIM); if (armorTrim != null && armorTrim.hasPatternAndMaterial((Holder)optional2.get(), (Holder)optional.get())) { return ItemStack.EMPTY; } ItemStack itemStack2 = itemStack.copyWithCount(1); itemStack2.set(DataComponents.TRIM, new ArmorTrim((Holder)optional.get(), (Holder)optional2.get())); return itemStack2; } } return ItemStack.EMPTY; } @Override public ItemStack getResultItem(HolderLookup.Provider registries) { ItemStack itemStack = new ItemStack(Items.IRON_CHESTPLATE); Optional> optional = registries.lookupOrThrow(Registries.TRIM_PATTERN).listElements().findFirst(); Optional> optional2 = registries.lookupOrThrow(Registries.TRIM_MATERIAL).get(TrimMaterials.REDSTONE); if (optional.isPresent() && optional2.isPresent()) { itemStack.set(DataComponents.TRIM, new ArmorTrim((Holder)optional2.get(), (Holder)optional.get())); } return itemStack; } @Override public boolean isTemplateIngredient(ItemStack stack) { return this.template.test(stack); } @Override public boolean isBaseIngredient(ItemStack stack) { return this.base.test(stack); } @Override public boolean isAdditionIngredient(ItemStack stack) { return this.addition.test(stack); } @Override public RecipeSerializer getSerializer() { return RecipeSerializer.SMITHING_TRIM; } @Override public boolean isIncomplete() { return Stream.of(this.template, this.base, this.addition).anyMatch(Ingredient::isEmpty); } public static class Serializer implements RecipeSerializer { private static final MapCodec CODEC = RecordCodecBuilder.mapCodec( instance -> instance.group( Ingredient.CODEC.fieldOf("template").forGetter(smithingTrimRecipe -> smithingTrimRecipe.template), Ingredient.CODEC.fieldOf("base").forGetter(smithingTrimRecipe -> smithingTrimRecipe.base), Ingredient.CODEC.fieldOf("addition").forGetter(smithingTrimRecipe -> smithingTrimRecipe.addition) ) .apply(instance, SmithingTrimRecipe::new) ); public static final StreamCodec STREAM_CODEC = StreamCodec.of( SmithingTrimRecipe.Serializer::toNetwork, SmithingTrimRecipe.Serializer::fromNetwork ); @Override public MapCodec codec() { return CODEC; } @Override public StreamCodec streamCodec() { return STREAM_CODEC; } private static SmithingTrimRecipe fromNetwork(RegistryFriendlyByteBuf buffer) { Ingredient ingredient = Ingredient.CONTENTS_STREAM_CODEC.decode(buffer); Ingredient ingredient2 = Ingredient.CONTENTS_STREAM_CODEC.decode(buffer); Ingredient ingredient3 = Ingredient.CONTENTS_STREAM_CODEC.decode(buffer); return new SmithingTrimRecipe(ingredient, ingredient2, ingredient3); } private static void toNetwork(RegistryFriendlyByteBuf buffer, SmithingTrimRecipe recipe) { Ingredient.CONTENTS_STREAM_CODEC.encode(buffer, recipe.template); Ingredient.CONTENTS_STREAM_CODEC.encode(buffer, recipe.base); Ingredient.CONTENTS_STREAM_CODEC.encode(buffer, recipe.addition); } } }