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 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<out DyeColor?, Int>
@ -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<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
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 },
@ -121,24 +146,16 @@ class PainterRecipe(
}
override fun isIncomplete(): Boolean {
return input.isActuallyEmpty || output.isEmpty
return input.hasNoItems() || output.isEmpty
}
override fun getIngredients(): NonNullList<Ingredient> {
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<PainterRecipe> { 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<PainterRecipe> {
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<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 } })
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<PainterArmorDyeRecipe> { _ ->
RecordCodecBuilder.create {
companion object : RecipeSerializer<PainterArmorDyeRecipe> {
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<PainterArmorDyeRecipe> {
return codec
}
override fun streamCodec(): StreamCodec<RegistryFriendlyByteBuf, PainterArmorDyeRecipe> {
return streamCodec as StreamCodec<RegistryFriendlyByteBuf, PainterArmorDyeRecipe>
}
}
}