Update painter recipe

This commit is contained in:
DBotThePony 2024-08-21 17:55:56 +07:00
parent a751cebf2d
commit 64ba95e305
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -8,27 +8,46 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap
import it.unimi.dsi.fastutil.objects.Object2IntMaps import it.unimi.dsi.fastutil.objects.Object2IntMaps
import net.minecraft.core.HolderLookup import net.minecraft.core.HolderLookup
import net.minecraft.core.NonNullList import net.minecraft.core.NonNullList
import net.minecraft.data.recipes.FinishedRecipe import net.minecraft.core.component.DataComponents
import net.minecraft.resources.ResourceLocation 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.util.StringRepresentable
import net.minecraft.world.Container import net.minecraft.world.item.DyeColor
import net.minecraft.world.item.* 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.Ingredient
import net.minecraft.world.item.crafting.RecipeInput import net.minecraft.world.item.crafting.RecipeInput
import net.minecraft.world.item.crafting.RecipeSerializer import net.minecraft.world.item.crafting.RecipeSerializer
import net.minecraft.world.item.crafting.RecipeType import net.minecraft.world.item.crafting.RecipeType
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import ru.dbotthepony.mc.otm.block.entity.decorative.PainterBlockEntity 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.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.PredicatedCodecList
import ru.dbotthepony.mc.otm.data.minRange 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.MItems
import ru.dbotthepony.mc.otm.registry.MRecipes import ru.dbotthepony.mc.otm.registry.MRecipes
import java.util.function.Predicate 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( abstract class AbstractPainterRecipe(
dyes: Map<out DyeColor?, Int> dyes: Map<out DyeColor?, Int>
@ -63,7 +82,7 @@ abstract class AbstractPainterRecipe(
override fun isSpecial(): Boolean = true override fun isSpecial(): Boolean = true
open fun getOutput(container: Container): ItemStack { open fun getOutput(container: RecipeInput): ItemStack {
if (container.isEmpty) return ItemStack.EMPTY if (container.isEmpty) return ItemStack.EMPTY
return container[0].copy() return container[0].copy()
@ -96,6 +115,12 @@ abstract class AbstractPainterRecipe(
companion object { companion object {
private val wrapperCodec: Codec<DyeColorWrapper> = StringRepresentable.fromEnum(DyeColorWrapper::values) private val wrapperCodec: Codec<DyeColorWrapper> = StringRepresentable.fromEnum(DyeColorWrapper::values)
@JvmStatic
protected val dyesFieldStreamCodec: StreamCodec<FriendlyByteBuf, Map<DyeColor?, Int>> = ByteBufCodecs.map(
{ Object2IntArrayMap(it) },
MatteryStreamCodec.Enum<FriendlyByteBuf, DyeColor>(DyeColor::class.java).nullable(),
ByteBufCodecs.INT)
@JvmStatic @JvmStatic
protected val dyesFieldCodec: MapCodec<Map<DyeColor?, Int>> = PredicatedCodecList<Map<DyeColorWrapper, Int>>( protected val dyesFieldCodec: MapCodec<Map<DyeColor?, Int>> = PredicatedCodecList<Map<DyeColorWrapper, Int>>(
wrapperCodec.xmap({ mapOf(it to 1) }, { it.keys.first() }) to Predicate { it.keys.size == 1 && it.values.first() == 1 }, 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 { override fun isIncomplete(): Boolean {
return input.isActuallyEmpty || output.isEmpty return input.hasNoItems() || output.isEmpty
} }
override fun getIngredients(): NonNullList<Ingredient> { override fun getIngredients(): NonNullList<Ingredient> {
return NonNullList.of(Ingredient.EMPTY, input) 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 -> return output.copy().also { o ->
p_44001_[0].tag?.let { o.applyComponentsAndValidate(input[0].componentsPatch)
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()
}
}
} }
} }
@ -147,30 +164,39 @@ class PainterRecipe(
} }
override fun getSerializer(): RecipeSerializer<*> { override fun getSerializer(): RecipeSerializer<*> {
return SERIALIZER return Companion
} }
override fun getType(): RecipeType<*> { override fun getType(): RecipeType<*> {
return MRecipes.PAINTER return MRecipes.PAINTER
} }
fun toFinished(id: ResourceLocation): FinishedRecipe { override fun getOutput(container: RecipeInput): ItemStack {
return SERIALIZER.toFinished(this, id)
}
override fun getOutput(container: Container): ItemStack {
return output.copy() return output.copy()
} }
companion object { companion object : RecipeSerializer<PainterRecipe> {
val SERIALIZER = Codec2RecipeSerializer<PainterRecipe> { context -> private val codec = RecordCodecBuilder.mapCodec {
RecordCodecBuilder.create {
it.group( it.group(
context.ingredients.fieldOf("input").forGetter(PainterRecipe::input), Ingredient.CODEC_NONEMPTY.fieldOf("input").forGetter(PainterRecipe::input),
ItemStack.CODEC.fieldOf("output").forGetter(PainterRecipe::output), ItemStack.CODEC.fieldOf("output").forGetter(PainterRecipe::output),
dyesFieldCodec.forGetter(AbstractPainterRecipe::dyes), dyesFieldCodec.forGetter(AbstractPainterRecipe::dyes),
).apply(it, ::PainterRecipe) ).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<PainterRecipe> {
return codec
}
override fun streamCodec(): StreamCodec<RegistryFriendlyByteBuf, PainterRecipe> {
return streamCodec
} }
} }
} }
@ -182,58 +208,56 @@ class PainterArmorDyeRecipe(
) : this(Object2IntArrayMap<DyeColor?>().also { map -> dyes.forEach { map[it] = 1 } }) ) : this(Object2IntArrayMap<DyeColor?>().also { map -> dyes.forEach { map[it] = 1 } })
override fun matches(value: ItemStack): Boolean { 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 { private fun assemble(value: ItemStack): ItemStack {
var output = container[0].copy() var output = value.copy()
dyes.forEach { entry -> if (dyes.size == 1 && dyes.keys.first() == null) {
if (entry.key == null) { output[DataComponents.DYED_COLOR] = null
(output.item as DyeableLeatherItem).clearColor(output)
} else { } else {
output = DyeableLeatherItem.dyeArmor(output.copy(), listOf(DyeItem.byColor(entry.key!!))) output = DyedItemColor.applyDyes(output, dyes.keys.map { DyeItem.byColor(it!!) })
}
} }
return output 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 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 getType(): RecipeType<*> = MRecipes.PAINTER
override fun isIncomplete(): Boolean = dyes.isEmpty() override fun isIncomplete(): Boolean = dyes.isEmpty()
fun toFinished(id: ResourceLocation): FinishedRecipe { override fun getOutput(container: RecipeInput): ItemStack {
return SERIALIZER.toFinished(this, id)
}
override fun getOutput(container: Container): ItemStack {
if (container.isEmpty) return ItemStack.EMPTY if (container.isEmpty) return ItemStack.EMPTY
return assemble(container[0])
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 companion object : RecipeSerializer<PainterArmorDyeRecipe> {
} private val codec by lazy {
RecordCodecBuilder.mapCodec {
companion object {
val SERIALIZER = Codec2RecipeSerializer<PainterArmorDyeRecipe> { _ ->
RecordCodecBuilder.create {
it.group( it.group(
dyesFieldCodec.forGetter(AbstractPainterRecipe::dyes), dyesFieldCodec.forGetter(AbstractPainterRecipe::dyes),
).apply(it, ::PainterArmorDyeRecipe) ).apply(it, ::PainterArmorDyeRecipe)
} }
} }
private val streamCodec = dyesFieldStreamCodec.map(::PainterArmorDyeRecipe, AbstractPainterRecipe::dyes)
override fun codec(): MapCodec<PainterArmorDyeRecipe> {
return codec
}
override fun streamCodec(): StreamCodec<RegistryFriendlyByteBuf, PainterArmorDyeRecipe> {
return streamCodec as StreamCodec<RegistryFriendlyByteBuf, PainterArmorDyeRecipe>
}
} }
} }