From 64ba95e305c6a7ac13fee4a69704b473e20f8639 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Wed, 21 Aug 2024 17:55:56 +0700 Subject: [PATCH] Update painter recipe --- .../mc/otm/recipe/PainterRecipe.kt | 154 ++++++++++-------- 1 file changed, 89 insertions(+), 65 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/recipe/PainterRecipe.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/recipe/PainterRecipe.kt index da1f91b92..876d0847c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/recipe/PainterRecipe.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/recipe/PainterRecipe.kt @@ -8,27 +8,46 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap import it.unimi.dsi.fastutil.objects.Object2IntMaps import net.minecraft.core.HolderLookup import net.minecraft.core.NonNullList -import net.minecraft.data.recipes.FinishedRecipe -import net.minecraft.resources.ResourceLocation +import net.minecraft.core.component.DataComponents +import net.minecraft.network.FriendlyByteBuf +import net.minecraft.network.RegistryFriendlyByteBuf +import net.minecraft.network.codec.ByteBufCodecs +import net.minecraft.network.codec.StreamCodec +import net.minecraft.tags.ItemTags import net.minecraft.util.StringRepresentable -import net.minecraft.world.Container -import net.minecraft.world.item.* +import net.minecraft.world.item.DyeColor +import net.minecraft.world.item.DyeItem +import net.minecraft.world.item.ItemStack +import net.minecraft.world.item.component.DyedItemColor import net.minecraft.world.item.crafting.Ingredient import net.minecraft.world.item.crafting.RecipeInput import net.minecraft.world.item.crafting.RecipeSerializer import net.minecraft.world.item.crafting.RecipeType import net.minecraft.world.level.Level import ru.dbotthepony.mc.otm.block.entity.decorative.PainterBlockEntity -import ru.dbotthepony.mc.otm.container.get import ru.dbotthepony.mc.otm.core.get -import ru.dbotthepony.mc.otm.core.isActuallyEmpty -import ru.dbotthepony.mc.otm.core.nbt.set -import ru.dbotthepony.mc.otm.core.tagNotNull import ru.dbotthepony.mc.otm.data.PredicatedCodecList import ru.dbotthepony.mc.otm.data.minRange +import ru.dbotthepony.mc.otm.network.MatteryStreamCodec +import ru.dbotthepony.mc.otm.network.nullable import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MRecipes import java.util.function.Predicate +import kotlin.collections.ArrayList +import kotlin.collections.Map +import kotlin.collections.Set +import kotlin.collections.all +import kotlin.collections.associateWith +import kotlin.collections.component1 +import kotlin.collections.component2 +import kotlin.collections.first +import kotlin.collections.forEach +import kotlin.collections.iterator +import kotlin.collections.map +import kotlin.collections.mapKeys +import kotlin.collections.mapOf +import kotlin.collections.none +import kotlin.collections.set abstract class AbstractPainterRecipe( dyes: Map @@ -63,7 +82,7 @@ abstract class AbstractPainterRecipe( override fun isSpecial(): Boolean = true - open fun getOutput(container: Container): ItemStack { + open fun getOutput(container: RecipeInput): ItemStack { if (container.isEmpty) return ItemStack.EMPTY return container[0].copy() @@ -96,6 +115,12 @@ abstract class AbstractPainterRecipe( companion object { private val wrapperCodec: Codec = StringRepresentable.fromEnum(DyeColorWrapper::values) + @JvmStatic + protected val dyesFieldStreamCodec: StreamCodec> = ByteBufCodecs.map( + { Object2IntArrayMap(it) }, + MatteryStreamCodec.Enum(DyeColor::class.java).nullable(), + ByteBufCodecs.INT) + @JvmStatic protected val dyesFieldCodec: MapCodec> = PredicatedCodecList>( wrapperCodec.xmap({ mapOf(it to 1) }, { it.keys.first() }) to Predicate { it.keys.size == 1 && it.values.first() == 1 }, @@ -121,24 +146,16 @@ class PainterRecipe( } override fun isIncomplete(): Boolean { - return input.isActuallyEmpty || output.isEmpty + return input.hasNoItems() || output.isEmpty } override fun getIngredients(): NonNullList { return NonNullList.of(Ingredient.EMPTY, input) } - override fun assemble(p_44001_: RecipeInput, registries: HolderLookup.Provider): ItemStack { + override fun assemble(input: RecipeInput, registries: HolderLookup.Provider): ItemStack { return output.copy().also { o -> - p_44001_[0].tag?.let { - if (o.tag == null) { - o.tag = it.copy() - } else { - for (k in it.allKeys) - if (k !in o.tagNotNull) - o.tagNotNull[k] = it[k]!!.copy() - } - } + o.applyComponentsAndValidate(input[0].componentsPatch) } } @@ -147,30 +164,39 @@ class PainterRecipe( } override fun getSerializer(): RecipeSerializer<*> { - return SERIALIZER + return Companion } override fun getType(): RecipeType<*> { return MRecipes.PAINTER } - fun toFinished(id: ResourceLocation): FinishedRecipe { - return SERIALIZER.toFinished(this, id) - } - - override fun getOutput(container: Container): ItemStack { + override fun getOutput(container: RecipeInput): ItemStack { return output.copy() } - companion object { - val SERIALIZER = Codec2RecipeSerializer { context -> - RecordCodecBuilder.create { - it.group( - context.ingredients.fieldOf("input").forGetter(PainterRecipe::input), - ItemStack.CODEC.fieldOf("output").forGetter(PainterRecipe::output), - dyesFieldCodec.forGetter(AbstractPainterRecipe::dyes), - ).apply(it, ::PainterRecipe) - } + companion object : RecipeSerializer { + private val codec = RecordCodecBuilder.mapCodec { + it.group( + Ingredient.CODEC_NONEMPTY.fieldOf("input").forGetter(PainterRecipe::input), + ItemStack.CODEC.fieldOf("output").forGetter(PainterRecipe::output), + dyesFieldCodec.forGetter(AbstractPainterRecipe::dyes), + ).apply(it, ::PainterRecipe) + } + + private val streamCodec = StreamCodec.composite( + Ingredient.CONTENTS_STREAM_CODEC, PainterRecipe::input, + ItemStack.STREAM_CODEC, PainterRecipe::output, + dyesFieldStreamCodec, PainterRecipe::dyes, + ::PainterRecipe + ) + + override fun codec(): MapCodec { + return codec + } + + override fun streamCodec(): StreamCodec { + return streamCodec } } } @@ -182,58 +208,56 @@ class PainterArmorDyeRecipe( ) : this(Object2IntArrayMap().also { map -> dyes.forEach { map[it] = 1 } }) override fun matches(value: ItemStack): Boolean { - return !isIncomplete && value.item is DyeableArmorItem + return !isIncomplete && value.`is`(ItemTags.DYEABLE) } - override fun assemble(container: RecipeInput, registry: HolderLookup.Provider): ItemStack { - var output = container[0].copy() + private fun assemble(value: ItemStack): ItemStack { + var output = value.copy() - dyes.forEach { entry -> - if (entry.key == null) { - (output.item as DyeableLeatherItem).clearColor(output) - } else { - output = DyeableLeatherItem.dyeArmor(output.copy(), listOf(DyeItem.byColor(entry.key!!))) - } + if (dyes.size == 1 && dyes.keys.first() == null) { + output[DataComponents.DYED_COLOR] = null + } else { + output = DyedItemColor.applyDyes(output, dyes.keys.map { DyeItem.byColor(it!!) }) } return output } + override fun assemble(container: RecipeInput, registry: HolderLookup.Provider): ItemStack { + if (container.isEmpty) return ItemStack.EMPTY + return assemble(container[0]) + } + override fun getResultItem(registry: HolderLookup.Provider): ItemStack = ItemStack.EMPTY - override fun getSerializer(): RecipeSerializer<*> = SERIALIZER + override fun getSerializer(): RecipeSerializer<*> = Companion override fun getType(): RecipeType<*> = MRecipes.PAINTER override fun isIncomplete(): Boolean = dyes.isEmpty() - fun toFinished(id: ResourceLocation): FinishedRecipe { - return SERIALIZER.toFinished(this, id) - } - - override fun getOutput(container: Container): ItemStack { + override fun getOutput(container: RecipeInput): ItemStack { if (container.isEmpty) return ItemStack.EMPTY - - var output = container[0].copy() - - dyes.forEach { entry -> - if (entry.key == null) { - (output.item as DyeableLeatherItem).clearColor(output) - } else { - output = DyeableLeatherItem.dyeArmor(output, listOf(DyeItem.byColor(entry.key!!))) - } - } - - return output + return assemble(container[0]) } - companion object { - val SERIALIZER = Codec2RecipeSerializer { _ -> - RecordCodecBuilder.create { + companion object : RecipeSerializer { + private val codec by lazy { + RecordCodecBuilder.mapCodec { it.group( dyesFieldCodec.forGetter(AbstractPainterRecipe::dyes), ).apply(it, ::PainterArmorDyeRecipe) } } + + private val streamCodec = dyesFieldStreamCodec.map(::PainterArmorDyeRecipe, AbstractPainterRecipe::dyes) + + override fun codec(): MapCodec { + return codec + } + + override fun streamCodec(): StreamCodec { + return streamCodec as StreamCodec + } } }