diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/Jobs.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/Jobs.kt index 434b79133..c9df0f764 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/Jobs.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/Jobs.kt @@ -18,6 +18,7 @@ import ru.dbotthepony.mc.otm.util.math.weakGreaterThan import ru.dbotthepony.mc.otm.util.math.weakLessThan import ru.dbotthepony.mc.otm.util.set import ru.dbotthepony.mc.otm.data.codec.DecimalCodec +import ru.dbotthepony.mc.otm.data.codec.EnhancedItemStackCodecs private fun isReason(status: Any?, reason: Any) = status == null || status == reason private val LOGGER = LogManager.getLogger() @@ -67,7 +68,7 @@ open class ItemJob( ) : Job(ticks, power, experience) { companion object { fun itemCodec(builder: RecordCodecBuilder.Instance): Products.P4, ItemStack, Double, Decimal, Float> { - return builder.group(ItemStack.CODEC.fieldOf("Item").forGetter(ItemJob::itemStack)).and(basicCodec(builder)) + return builder.group(EnhancedItemStackCodecs.CODEC.fieldOf("Item").forGetter(ItemJob::itemStack)).and(basicCodec(builder)) } val CODEC: Codec by lazy { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterEntanglerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterEntanglerBlockEntity.kt index 4b9ba0cc0..79e9bb716 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterEntanglerBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterEntanglerBlockEntity.kt @@ -38,6 +38,7 @@ import ru.dbotthepony.mc.otm.util.math.Decimal import ru.dbotthepony.mc.otm.container.ItemStackKey import ru.dbotthepony.mc.otm.container.asKey import ru.dbotthepony.mc.otm.data.codec.DecimalCodec +import ru.dbotthepony.mc.otm.data.codec.EnhancedItemStackCodecs import ru.dbotthepony.mc.otm.data.codec.minRange import ru.dbotthepony.mc.otm.graph.matter.MatterNode import ru.dbotthepony.mc.otm.menu.matter.MatterEntanglerMenu @@ -53,7 +54,7 @@ class MatterEntanglerBlockEntity(blockPos: BlockPos, blockState: BlockState) : M companion object { val CODEC: Codec = RecordCodecBuilder.create { it.group( - ItemStack.CODEC.fieldOf("itemStack").forGetter(ItemJob::itemStack), + EnhancedItemStackCodecs.CODEC.fieldOf("itemStack").forGetter(ItemJob::itemStack), DecimalCodec.minRange(Decimal.ZERO).fieldOf("matter").forGetter(Job::matter), Codec.DOUBLE.minRange(0.0).fieldOf("ticks").forGetter(ItemJob::ticks), Codec.FLOAT.minRange(0f).optionalFieldOf("experience", 0f).forGetter(Job::experience) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReplicatorBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReplicatorBlockEntity.kt index 0d99da45b..0e362dd67 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReplicatorBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReplicatorBlockEntity.kt @@ -30,6 +30,7 @@ import ru.dbotthepony.mc.otm.container.slotted.SlottedContainer import ru.dbotthepony.mc.otm.util.math.Decimal import ru.dbotthepony.mc.otm.util.otmRandom import ru.dbotthepony.mc.otm.data.codec.DecimalCodec +import ru.dbotthepony.mc.otm.data.codec.EnhancedItemStackCodecs import ru.dbotthepony.mc.otm.data.codec.minRange import ru.dbotthepony.mc.otm.graph.matter.MatterNode import ru.dbotthepony.mc.otm.matter.MatterManager @@ -55,7 +56,7 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : val CODEC: Codec by lazy { RecordCodecBuilder.create { it.group( - ItemStack.CODEC.fieldOf("Item").forGetter(ReplicatorJob::itemStack), + EnhancedItemStackCodecs.CODEC.fieldOf("Item").forGetter(ReplicatorJob::itemStack), DecimalCodec.minRange(Decimal.ZERO).fieldOf("matterPerTick").forGetter(ReplicatorJob::matterPerTick), UUIDUtil.CODEC.fieldOf("task").forGetter(ReplicatorJob::task), DecimalCodec.minRange(Decimal.ZERO).fieldOf("matterValue").forGetter(ReplicatorJob::matterValue), diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/EnhancedContainer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/EnhancedContainer.kt index 9fafb973b..3301ad261 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/EnhancedContainer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/EnhancedContainer.kt @@ -13,6 +13,7 @@ import net.minecraft.world.item.ItemStack import net.neoforged.neoforge.common.util.INBTSerializable import org.apache.logging.log4j.LogManager import ru.dbotthepony.mc.otm.container.slotted.SlottedContainer +import ru.dbotthepony.mc.otm.data.codec.EnhancedItemStackCodecs import ru.dbotthepony.mc.otm.util.isNotEmpty import ru.dbotthepony.mc.otm.util.set @@ -133,7 +134,7 @@ abstract class EnhancedContainer(private val size: Int) if (items[i].isNotEmpty) { attached = true - tag["item"] = ItemStack.OPTIONAL_CODEC.encodeStart(ops, items[i]) + tag["item"] = EnhancedItemStackCodecs.OPTIONAL_CODEC.encodeStart(ops, items[i]) .getOrThrow { RuntimeException("Unable to serialize item ${items[i]} at slot $i: $it") } } @@ -165,7 +166,7 @@ abstract class EnhancedContainer(private val size: Int) if (!seenSlots.add(slot)) continue if ("item" in element) { - ItemStack.OPTIONAL_CODEC.decode(ops, element["item"]) + EnhancedItemStackCodecs.OPTIONAL_CODEC.decode(ops, element["item"]) .map { it.first } .ifError { LOGGER.error("Failed to deserialize item stack in slot $slot: ${it.message()}") } .ifSuccess { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/slotted/ContainerSlot.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/slotted/ContainerSlot.kt index ec1139e49..6f629403c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/slotted/ContainerSlot.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/slotted/ContainerSlot.kt @@ -8,6 +8,7 @@ import net.minecraft.world.item.ItemStack import net.neoforged.neoforge.common.util.INBTSerializable import org.apache.logging.log4j.LogManager import ru.dbotthepony.mc.otm.container.IAutomatedContainerSlot +import ru.dbotthepony.mc.otm.data.codec.EnhancedItemStackCodecs import ru.dbotthepony.mc.otm.util.isNotEmpty import ru.dbotthepony.mc.otm.util.set import ru.dbotthepony.mc.otm.data.getOrNull @@ -97,13 +98,13 @@ open class ContainerSlot( override fun serializeNBT(provider: HolderLookup.Provider): CompoundTag { return CompoundTag().also { - it["item"] = ItemStack.OPTIONAL_CODEC.encodeStart(provider.createSerializationContext(NbtOps.INSTANCE), item) + it["item"] = EnhancedItemStackCodecs.OPTIONAL_CODEC.encodeStart(provider.createSerializationContext(NbtOps.INSTANCE), item) .getOrThrow { RuntimeException("Unable to serialize $item in slot $slot: $it") } } } override fun deserializeNBT(provider: HolderLookup.Provider, nbt: CompoundTag) { - _item = ItemStack.OPTIONAL_CODEC.decode(provider.createSerializationContext(NbtOps.INSTANCE), nbt["item"]) + _item = EnhancedItemStackCodecs.OPTIONAL_CODEC.decode(provider.createSerializationContext(NbtOps.INSTANCE), nbt["item"]) .ifError { LOGGER.error("Unable to deserialize item at slot $slot: ${it.message()}") } .getOrNull()?.first ?: ItemStack.EMPTY diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/slotted/SlottedContainer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/slotted/SlottedContainer.kt index e1561b3b9..bad20a22b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/slotted/SlottedContainer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/slotted/SlottedContainer.kt @@ -23,6 +23,7 @@ import ru.dbotthepony.mc.otm.container.IAutomatedContainer import ru.dbotthepony.mc.otm.container.IFilteredContainerSlot import ru.dbotthepony.mc.otm.container.ItemFilter import ru.dbotthepony.mc.otm.container.balance +import ru.dbotthepony.mc.otm.data.codec.EnhancedItemStackCodecs import ru.dbotthepony.mc.otm.util.isNotEmpty import ru.dbotthepony.mc.otm.util.set import ru.dbotthepony.mc.otm.data.codec.minRange @@ -183,7 +184,7 @@ class SlottedContainer( companion object { val CODEC: Codec = RecordCodecBuilder.create { it.group( - ItemStack.OPTIONAL_CODEC.fieldOf("item").forGetter { it.item }, + EnhancedItemStackCodecs.OPTIONAL_CODEC.fieldOf("item").forGetter { it.item }, Codec.INT.minRange(0).fieldOf("slot").forGetter { it.slot }, ).apply(it, SlottedContainer::LegacySerializedItem) } @@ -227,7 +228,7 @@ class SlottedContainer( for (entry in lostItems) { if ("item" in entry) { - ItemStack.OPTIONAL_CODEC.decode(provider, entry["item"]) + EnhancedItemStackCodecs.OPTIONAL_CODEC.decode(provider, entry["item"]) .ifError { LOGGER.warn("Unable to deserialize 'lost' item: ${it.message()}") } .ifSuccess { if (it.first.isNotEmpty) result.add(it.first) } } @@ -275,7 +276,7 @@ class SlottedContainer( slots[slot].item = item bitmap[slot] = item.isNotEmpty } else if (item.isNotEmpty) { - ItemStack.CODEC.encodeStart(provider.createSerializationContext(NbtOps.INSTANCE), item) + EnhancedItemStackCodecs.CODEC.encodeStart(provider.createSerializationContext(NbtOps.INSTANCE), item) .ifError { LOGGER.warn("Unable to serialize 'lost' item: ${it.message()}") } .ifSuccess { s -> this.provider = provider diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/data/codec/EnhancedItemStackCodecs.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/data/codec/EnhancedItemStackCodecs.kt new file mode 100644 index 000000000..a8bc96564 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/data/codec/EnhancedItemStackCodecs.kt @@ -0,0 +1,26 @@ +package ru.dbotthepony.mc.otm.data.codec + +import com.mojang.serialization.Codec +import com.mojang.serialization.codecs.RecordCodecBuilder +import net.minecraft.core.component.DataComponentPatch +import net.minecraft.util.ExtraCodecs +import net.minecraft.world.item.ItemStack +import java.util.* +import kotlin.jvm.optionals.getOrElse + +object EnhancedItemStackCodecs { + val CODEC: Codec by lazy { + RecordCodecBuilder.create { + it.group( + ItemStack.ITEM_NON_AIR_CODEC.fieldOf("id").forGetter(ItemStack::getItemHolder), + Codec.INT.minRange(1).fieldOf("count").orElse(1).forGetter(ItemStack::getCount), + DataComponentPatch.CODEC.optionalFieldOf("components", DataComponentPatch.EMPTY).forGetter(ItemStack::getComponentsPatch) + ).apply(it, ::ItemStack) + } + } + + val OPTIONAL_CODEC: Codec by lazy { + ExtraCodecs.optionalEmptyMap(CODEC) + .xmap({ it.getOrElse { ItemStack.EMPTY } }, { if (it.isEmpty) Optional.empty() else Optional.of(it) }) + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/data/condition/ItemInInventoryCondition.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/data/condition/ItemInInventoryCondition.kt index 5f9c68dde..a18ce2413 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/data/condition/ItemInInventoryCondition.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/data/condition/ItemInInventoryCondition.kt @@ -10,6 +10,7 @@ import net.minecraft.world.level.storage.loot.predicates.LootItemCondition import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType import ru.dbotthepony.mc.otm.capability.items import ru.dbotthepony.kommons.collect.filter +import ru.dbotthepony.mc.otm.data.codec.EnhancedItemStackCodecs import ru.dbotthepony.mc.otm.data.get import ru.dbotthepony.mc.otm.registry.data.MLootItemConditions @@ -48,7 +49,7 @@ data class ItemInInventoryCondition( val CODEC: MapCodec by lazy { RecordCodecBuilder.mapCodec { it.group( - ItemStack.CODEC.fieldOf("item").forGetter(ItemInInventoryCondition::item), + EnhancedItemStackCodecs.CODEC.fieldOf("item").forGetter(ItemInInventoryCondition::item), Codec.BOOL.optionalFieldOf("matchComponents", false).forGetter(ItemInInventoryCondition::matchComponents), Codec.BOOL.optionalFieldOf("matchCosmetics", false).forGetter(ItemInInventoryCondition::matchCosmetics), ).apply(it, ::ItemInInventoryCondition) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/recipe/MatterEntanglerRecipe.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/recipe/MatterEntanglerRecipe.kt index 0e3cd3295..4001d6454 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/recipe/MatterEntanglerRecipe.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/recipe/MatterEntanglerRecipe.kt @@ -22,6 +22,7 @@ import ru.dbotthepony.kommons.collect.filterNotNull import ru.dbotthepony.kommons.collect.map import ru.dbotthepony.mc.otm.util.math.Decimal import ru.dbotthepony.mc.otm.data.codec.DecimalCodec +import ru.dbotthepony.mc.otm.data.codec.EnhancedItemStackCodecs import ru.dbotthepony.mc.otm.data.codec.minRange import ru.dbotthepony.mc.otm.network.StreamCodecs import ru.dbotthepony.mc.otm.network.optional @@ -168,7 +169,7 @@ open class MatterEntanglerRecipe( ShapedRecipePattern.MAP_CODEC.fieldOf("ingredients").forGetter(MatterEntanglerRecipe::ingredients), DecimalCodec.minRange(Decimal.ZERO).fieldOf("matter").forGetter(MatterEntanglerRecipe::matter), Codec.DOUBLE.minRange(0.0).fieldOf("ticks").forGetter(MatterEntanglerRecipe::ticks), - ItemStack.CODEC.fieldOf("result").forGetter(MatterEntanglerRecipe::result), + EnhancedItemStackCodecs.CODEC.fieldOf("result").forGetter(MatterEntanglerRecipe::result), Codec.FLOAT.minRange(0f).optionalFieldOf("experience", 0f).forGetter(MatterEntanglerRecipe::experience), (DataComponentType.CODEC as Codec>).optionalFieldOf("uuidKey").forGetter(MatterEntanglerRecipe::uuidKey), UUIDUtil.STRING_CODEC.optionalFieldOf("fixedUuid").forGetter(MatterEntanglerRecipe::fixedUuid)