package net.minecraft.world.item.crafting; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import java.util.List; import java.util.Optional; import net.minecraft.core.Holder; import net.minecraft.core.Holder.Reference; import net.minecraft.core.HolderLookup.Provider; import net.minecraft.core.component.DataComponents; 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.crafting.display.RecipeDisplay; import net.minecraft.world.item.crafting.display.SlotDisplay; import net.minecraft.world.item.crafting.display.SmithingRecipeDisplay; import net.minecraft.world.item.crafting.display.SlotDisplay.ItemSlotDisplay; import net.minecraft.world.item.crafting.display.SlotDisplay.SmithingTrimDemoSlotDisplay; import net.minecraft.world.item.equipment.trim.ArmorTrim; import net.minecraft.world.item.equipment.trim.TrimMaterial; import net.minecraft.world.item.equipment.trim.TrimMaterials; import net.minecraft.world.item.equipment.trim.TrimPattern; import net.minecraft.world.item.equipment.trim.TrimPatterns; import org.jetbrains.annotations.Nullable; public class SmithingTrimRecipe implements SmithingRecipe { final Optional template; final Optional base; final Optional addition; @Nullable private PlacementInfo placementInfo; public SmithingTrimRecipe(Optional template, Optional base, Optional addition) { this.template = template; this.base = base; this.addition = addition; } public ItemStack assemble(SmithingRecipeInput smithingRecipeInput, Provider provider) { return applyTrim(provider, smithingRecipeInput.base(), smithingRecipeInput.addition(), smithingRecipeInput.template()); } public static ItemStack applyTrim(Provider registries, ItemStack base, ItemStack addition, ItemStack template) { Optional> optional = TrimMaterials.getFromIngredient(registries, addition); Optional> optional2 = TrimPatterns.getFromTemplate(registries, template); if (optional.isPresent() && optional2.isPresent()) { ArmorTrim armorTrim = base.get(DataComponents.TRIM); if (armorTrim != null && armorTrim.hasPatternAndMaterial((Holder)optional2.get(), (Holder)optional.get())) { return ItemStack.EMPTY; } else { ItemStack itemStack = base.copyWithCount(1); itemStack.set(DataComponents.TRIM, new ArmorTrim((Holder)optional.get(), (Holder)optional2.get())); return itemStack; } } else { return ItemStack.EMPTY; } } @Override public Optional templateIngredient() { return this.template; } @Override public Optional baseIngredient() { return this.base; } @Override public Optional additionIngredient() { return this.addition; } @Override public RecipeSerializer getSerializer() { return RecipeSerializer.SMITHING_TRIM; } @Override public PlacementInfo placementInfo() { if (this.placementInfo == null) { this.placementInfo = PlacementInfo.createFromOptionals(List.of(this.template, this.base, this.addition)); } return this.placementInfo; } @Override public List display() { SlotDisplay slotDisplay = Ingredient.optionalIngredientToDisplay(this.base); SlotDisplay slotDisplay2 = Ingredient.optionalIngredientToDisplay(this.addition); SlotDisplay slotDisplay3 = Ingredient.optionalIngredientToDisplay(this.template); return List.of( new SmithingRecipeDisplay( slotDisplay3, slotDisplay, slotDisplay2, new SmithingTrimDemoSlotDisplay(slotDisplay, slotDisplay2, slotDisplay3), new ItemSlotDisplay(Items.SMITHING_TABLE) ) ); } public static class Serializer implements RecipeSerializer { private static final MapCodec CODEC = RecordCodecBuilder.mapCodec( instance -> instance.group( Ingredient.CODEC.optionalFieldOf("template").forGetter(smithingTrimRecipe -> smithingTrimRecipe.template), Ingredient.CODEC.optionalFieldOf("base").forGetter(smithingTrimRecipe -> smithingTrimRecipe.base), Ingredient.CODEC.optionalFieldOf("addition").forGetter(smithingTrimRecipe -> smithingTrimRecipe.addition) ) .apply(instance, SmithingTrimRecipe::new) ); public static final StreamCodec STREAM_CODEC = StreamCodec.composite( Ingredient.OPTIONAL_CONTENTS_STREAM_CODEC, smithingTrimRecipe -> smithingTrimRecipe.template, Ingredient.OPTIONAL_CONTENTS_STREAM_CODEC, smithingTrimRecipe -> smithingTrimRecipe.base, Ingredient.OPTIONAL_CONTENTS_STREAM_CODEC, smithingTrimRecipe -> smithingTrimRecipe.addition, SmithingTrimRecipe::new ); @Override public MapCodec codec() { return CODEC; } @Override public StreamCodec streamCodec() { return STREAM_CODEC; } } }