Make PatternState be only immutable, completely move it to codecs, write/read binary json with codec

This commit is contained in:
DBotThePony 2023-07-26 01:45:14 +07:00
parent 662801df7d
commit a673ed966e
Signed by: DBot
GPG Key ID: DCC23B5715498507
15 changed files with 95 additions and 194 deletions

View File

@ -11,7 +11,6 @@ import net.minecraft.world.inventory.AbstractContainerMenu
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag import net.minecraft.nbt.ListTag
import net.minecraft.server.level.ServerLevel
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import net.minecraftforge.common.util.INBTSerializable import net.minecraftforge.common.util.INBTSerializable
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
@ -22,9 +21,7 @@ import ru.dbotthepony.mc.otm.core.nbt.map
import ru.dbotthepony.mc.otm.core.nbt.mapString import ru.dbotthepony.mc.otm.core.nbt.mapString
import ru.dbotthepony.mc.otm.core.nbt.set import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.util.ItemSorter import ru.dbotthepony.mc.otm.core.util.ItemSorter
import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.graph.matter.MatterGraph import ru.dbotthepony.mc.otm.graph.matter.MatterGraph
import ru.dbotthepony.mc.otm.graph.matter.MatterNode
import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import java.util.* import java.util.*
@ -195,7 +192,7 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
setChanged() setChanged()
} }
fun addTask(state: IPatternState, count: Int): IReplicationTask<*> { fun addTask(state: PatternState, count: Int): IReplicationTask<*> {
val task = ReplicationTask(UUID.randomUUID(), Optional.of(state.id), state.item, 0, 0, count) val task = ReplicationTask(UUID.randomUUID(), Optional.of(state.id), state.item, 0, 0, count)
_tasks[task.id] = task _tasks[task.id] = task

View File

@ -21,7 +21,7 @@ import ru.dbotthepony.mc.otm.capability.energy.BlockEnergyStorageImpl
import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.matter.IMatterStorage import ru.dbotthepony.mc.otm.capability.matter.IMatterStorage
import ru.dbotthepony.mc.otm.capability.matter.IPatternState import ru.dbotthepony.mc.otm.capability.matter.PatternState
import ru.dbotthepony.mc.otm.capability.matter.MatterStorageImpl import ru.dbotthepony.mc.otm.capability.matter.MatterStorageImpl
import ru.dbotthepony.mc.otm.capability.matter.ProfiledMatterStorage import ru.dbotthepony.mc.otm.capability.matter.ProfiledMatterStorage
import ru.dbotthepony.mc.otm.config.EnergyBalanceValues import ru.dbotthepony.mc.otm.config.EnergyBalanceValues
@ -68,15 +68,15 @@ class MatterReconstructorBlockEntity(blockPos: BlockPos, blockState: BlockState)
return matter return matter
} }
override fun onPatternAdded(state: IPatternState) { override fun onPatternAdded(state: PatternState) {
containerChanged() containerChanged()
} }
override fun onPatternRemoved(state: IPatternState) { override fun onPatternRemoved(state: PatternState) {
containerChanged() containerChanged()
} }
override fun onPatternUpdated(newState: IPatternState, oldState: IPatternState) { override fun onPatternUpdated(newState: PatternState, oldState: PatternState) {
containerChanged() containerChanged()
} }
} }

View File

@ -91,7 +91,7 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
jobEventLoops[0].notify(MachineJobEventLoop.IdleReason.OBSERVING) jobEventLoops[0].notify(MachineJobEventLoop.IdleReason.OBSERVING)
} }
override fun onPatternAdded(state: IPatternState) { override fun onPatternAdded(state: PatternState) {
jobEventLoops[0].notify(MachineJobEventLoop.IdleReason.OBSERVING) jobEventLoops[0].notify(MachineJobEventLoop.IdleReason.OBSERVING)
} }
} }
@ -182,7 +182,7 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
matterPerTick = matter.matter / ticks, matterPerTick = matter.matter / ticks,
task = allocation.task.id, task = allocation.task.id,
matterValue = matter.matter, matterValue = matter.matter,
pattern = Optional.ofNullable(allocation.pattern?.asImmutable()), pattern = Optional.ofNullable(allocation.pattern),
asDust = (level?.random?.nextDouble() ?: 1.0) * upgrades.failureMultiplier > (allocation.pattern?.researchPercent ?: 2.0), asDust = (level?.random?.nextDouble() ?: 1.0) * upgrades.failureMultiplier > (allocation.pattern?.researchPercent ?: 2.0),
ticks = ticks, ticks = ticks,
)) ))

View File

@ -7,32 +7,22 @@ import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.ForgeConfigSpec
import ru.dbotthepony.mc.otm.block.entity.JobContainer import ru.dbotthepony.mc.otm.block.entity.JobContainer
import ru.dbotthepony.mc.otm.block.entity.JobStatus import ru.dbotthepony.mc.otm.block.entity.JobStatus
import ru.dbotthepony.mc.otm.block.entity.ItemJob import ru.dbotthepony.mc.otm.block.entity.ItemJob
import ru.dbotthepony.mc.otm.block.entity.MachineJobEventLoop import ru.dbotthepony.mc.otm.block.entity.MachineJobEventLoop
import ru.dbotthepony.mc.otm.config.EnergyBalanceValues
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
import ru.dbotthepony.mc.otm.capability.IMatteryUpgrade
import ru.dbotthepony.mc.otm.capability.energy.BlockEnergyStorageImpl
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.UpgradeType import ru.dbotthepony.mc.otm.capability.UpgradeType
import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.matter.IPatternState
import ru.dbotthepony.mc.otm.capability.matter.PatternState import ru.dbotthepony.mc.otm.capability.matter.PatternState
import ru.dbotthepony.mc.otm.config.MachinesConfig import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.HandlerFilter import ru.dbotthepony.mc.otm.container.HandlerFilter
import ru.dbotthepony.mc.otm.container.UpgradeContainer import ru.dbotthepony.mc.otm.container.UpgradeContainer
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.DecimalConfigValue
import ru.dbotthepony.mc.otm.core.math.defineDecimal
import ru.dbotthepony.mc.otm.menu.matter.MatterScannerMenu import ru.dbotthepony.mc.otm.menu.matter.MatterScannerMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.core.util.WriteOnce
import ru.dbotthepony.mc.otm.graph.matter.MatterNode import ru.dbotthepony.mc.otm.graph.matter.MatterNode
import ru.dbotthepony.mc.otm.matter.MatterManager import ru.dbotthepony.mc.otm.matter.MatterManager
import java.util.* import java.util.*
@ -58,15 +48,15 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
val energyConfig = ConfigurableEnergy(energy) val energyConfig = ConfigurableEnergy(energy)
val matterNode = object : MatterNode() { val matterNode = object : MatterNode() {
override fun onPatternAdded(state: IPatternState) { override fun onPatternAdded(state: PatternState) {
jobEventLoops[0].notify(MachineJobEventLoop.IdleReason.PATTERN) jobEventLoops[0].notify(MachineJobEventLoop.IdleReason.PATTERN)
} }
override fun onPatternRemoved(state: IPatternState) { override fun onPatternRemoved(state: PatternState) {
jobEventLoops[0].notify(MachineJobEventLoop.IdleReason.PATTERN) jobEventLoops[0].notify(MachineJobEventLoop.IdleReason.PATTERN)
} }
override fun onPatternUpdated(newState: IPatternState, oldState: IPatternState) { override fun onPatternUpdated(newState: PatternState, oldState: PatternState) {
jobEventLoops[0].notify(MachineJobEventLoop.IdleReason.PATTERN) jobEventLoops[0].notify(MachineJobEventLoop.IdleReason.PATTERN)
} }
} }
@ -96,7 +86,7 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
val stack = status.job.itemStack val stack = status.job.itemStack
if (stack.isEmpty || !MatterManager.hasMatterValue(stack)) return status.success() if (stack.isEmpty || !MatterManager.hasMatterValue(stack)) return status.success()
var findState: IPatternState? = null var findState: PatternState? = null
for (state in matterNode.graph.patterns.filter { it.item === stack.item }) { for (state in matterNode.graph.patterns.filter { it.item === stack.item }) {
if (findState == null && state.researchPercent < 1.0) { if (findState == null && state.researchPercent < 1.0) {
@ -108,7 +98,7 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
val researchAdvance = MatterManager.getResearchAdvance(stack.item) val researchAdvance = MatterManager.getResearchAdvance(stack.item)
val new: IPatternState = val new: PatternState =
if (findState != null) { if (findState != null) {
PatternState(findState.id, stack.item, (findState.researchPercent + researchAdvance).coerceAtMost(1.0)) PatternState(findState.id, stack.item, (findState.researchPercent + researchAdvance).coerceAtMost(1.0))
} else { } else {
@ -128,7 +118,7 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
val stack = container.getItem(0) val stack = container.getItem(0)
if (stack.isEmpty || !MatterManager.canDecompose(stack)) return JobContainer.noItem() if (stack.isEmpty || !MatterManager.canDecompose(stack)) return JobContainer.noItem()
var findState: IPatternState? = null var findState: PatternState? = null
for (state in matterNode.graph.patterns.filter { it.item === stack.item }) { for (state in matterNode.graph.patterns.filter { it.item === stack.item }) {
if (state.researchPercent < 1.0) { if (state.researchPercent < 1.0) {
@ -142,7 +132,7 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
val researchAdvance = MatterManager.getResearchAdvance(stack.item) val researchAdvance = MatterManager.getResearchAdvance(stack.item)
val new: IPatternState = val new: PatternState =
if (findState != null) { if (findState != null) {
PatternState(findState.id, stack.item, (findState.researchPercent + researchAdvance).coerceAtMost(1.0)) PatternState(findState.id, stack.item, (findState.researchPercent + researchAdvance).coerceAtMost(1.0))
} else { } else {

View File

@ -13,14 +13,11 @@ import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu import net.minecraft.world.inventory.AbstractContainerMenu
import ru.dbotthepony.mc.otm.menu.matter.PatternStorageMenu import ru.dbotthepony.mc.otm.menu.matter.PatternStorageMenu
import net.minecraft.MethodsReturnNonnullByDefault import net.minecraft.MethodsReturnNonnullByDefault
import net.minecraft.server.level.ServerLevel
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.Block
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.capability.matter.* import ru.dbotthepony.mc.otm.capability.matter.*
import ru.dbotthepony.mc.otm.core.collect.iterator import ru.dbotthepony.mc.otm.core.collect.iterator
import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.graph.matter.MatterGraph
import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import java.util.ArrayList import java.util.ArrayList
@ -97,8 +94,8 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
return PatternStorageMenu(containerID, inventory, this) return PatternStorageMenu(containerID, inventory, this)
} }
override val patterns: Stream<out IPatternState> get() { override val patterns: Stream<out PatternState> get() {
val streams = ArrayList<Stream<out IPatternState>>() val streams = ArrayList<Stream<out PatternState>>()
for (provider in this.container.iterator(MatteryCapability.PATTERN)) { for (provider in this.container.iterator(MatteryCapability.PATTERN)) {
streams.add(provider.second.patterns) streams.add(provider.second.patterns)
@ -130,7 +127,7 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
matterNode.isValid = false matterNode.isValid = false
} }
override fun insertPattern(pattern: IPatternState, onlyUpdate: Boolean, simulate: Boolean): PatternInsertStatus { override fun insertPattern(pattern: PatternState, onlyUpdate: Boolean, simulate: Boolean): PatternInsertStatus {
for (pair in this.container.iterator(MatteryCapability.PATTERN)) { for (pair in this.container.iterator(MatteryCapability.PATTERN)) {
val status = pair.second.insertPattern(pattern, onlyUpdate, simulate) val status = pair.second.insertPattern(pattern, onlyUpdate, simulate)

View File

@ -8,8 +8,8 @@ private enum class PatternInsertResult {
sealed class PatternInsertStatus( sealed class PatternInsertStatus(
private val status: PatternInsertResult, private val status: PatternInsertResult,
val newState: IPatternState?, val newState: PatternState?,
val oldState: IPatternState? val oldState: PatternState?
) { ) {
val isFailed get() = status == PatternInsertResult.FAIL val isFailed get() = status == PatternInsertResult.FAIL
val isUpdated get() = status == PatternInsertResult.UPDATED val isUpdated get() = status == PatternInsertResult.UPDATED
@ -17,8 +17,8 @@ sealed class PatternInsertStatus(
} }
object PatternInsertFailure : PatternInsertStatus(PatternInsertResult.FAIL, null, null) object PatternInsertFailure : PatternInsertStatus(PatternInsertResult.FAIL, null, null)
class PatternInsertUpdated(new: IPatternState, old: IPatternState) : PatternInsertStatus(PatternInsertResult.UPDATED, new, old) class PatternInsertUpdated(new: PatternState, old: PatternState) : PatternInsertStatus(PatternInsertResult.UPDATED, new, old)
class PatternInsertInserted(new: IPatternState) : PatternInsertStatus(PatternInsertResult.INSERTED, new, null) class PatternInsertInserted(new: PatternState) : PatternInsertStatus(PatternInsertResult.INSERTED, new, null)
@JvmRecord @JvmRecord
data class ReplicationTaskAllocation(val task: IReplicationTask<*>, val pattern: IPatternState?) data class ReplicationTaskAllocation(val task: IReplicationTask<*>, val pattern: PatternState?)

View File

@ -15,21 +15,21 @@ interface IPatternStorage {
/** /**
* It must return new stream each time * It must return new stream each time
*/ */
val patterns: Stream<out IPatternState> val patterns: Stream<out PatternState>
fun findPatterns(item: Item): Collection<IPatternState> { fun findPatterns(item: Item): Collection<PatternState> {
return findPatterns { item == it.item } return findPatterns { item == it.item }
} }
fun findPatterns(predicate: Predicate<IPatternState>): Collection<IPatternState> { fun findPatterns(predicate: Predicate<PatternState>): Collection<PatternState> {
return patterns.filter(predicate).collect(Collectors.toList()) return patterns.filter(predicate).collect(Collectors.toList())
} }
fun findPattern(item: Item): IPatternState? { fun findPattern(item: Item): PatternState? {
return patterns.filter { it.item == item }.findAny().orElse(null) return patterns.filter { it.item == item }.findAny().orElse(null)
} }
fun getPattern(id: UUID?): IPatternState? { fun getPattern(id: UUID?): PatternState? {
return patterns.filter { it.id == id }.findAny().orElse(null) return patterns.filter { it.id == id }.findAny().orElse(null)
} }
@ -37,7 +37,7 @@ interface IPatternStorage {
return patterns.filter { it.item == item }.findAny().isPresent return patterns.filter { it.item == item }.findAny().isPresent
} }
fun hasPattern(state: IPatternState): Boolean { fun hasPattern(state: PatternState): Boolean {
return hasPattern(state.id) return hasPattern(state.id)
} }
@ -57,13 +57,13 @@ interface IPatternStorage {
* @param simulate whenever to affect state * @param simulate whenever to affect state
* @return record of status of the operation (at status() FAIL, UPDATED, INSERTED) as well as new_state and old_state * @return record of status of the operation (at status() FAIL, UPDATED, INSERTED) as well as new_state and old_state
*/ */
fun insertPattern(pattern: IPatternState, onlyUpdate: Boolean, simulate: Boolean): PatternInsertStatus fun insertPattern(pattern: PatternState, onlyUpdate: Boolean, simulate: Boolean): PatternInsertStatus
fun insertPattern(pattern: IPatternState, simulate: Boolean): PatternInsertStatus { fun insertPattern(pattern: PatternState, simulate: Boolean): PatternInsertStatus {
return insertPattern(pattern, false, simulate) return insertPattern(pattern, false, simulate)
} }
fun updatePattern(pattern: IPatternState, simulate: Boolean): PatternInsertStatus { fun updatePattern(pattern: PatternState, simulate: Boolean): PatternInsertStatus {
return insertPattern(pattern, true, simulate) return insertPattern(pattern, true, simulate)
} }
} }

View File

@ -1,101 +1,39 @@
package ru.dbotthepony.mc.otm.capability.matter package ru.dbotthepony.mc.otm.capability.matter
import com.mojang.datafixers.Products
import com.mojang.serialization.Codec import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.NbtOps import net.minecraft.nbt.NbtOps
import net.minecraft.nbt.Tag import net.minecraft.nbt.Tag
import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.Item import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraftforge.registries.ForgeRegistries import net.minecraftforge.registries.ForgeRegistries
import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.core.util.readBinaryJsonWithCodec
import ru.dbotthepony.mc.otm.core.nbt.contains import ru.dbotthepony.mc.otm.core.util.writeBinaryJsonWithCodec
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.data.UUIDCodec import ru.dbotthepony.mc.otm.data.UUIDCodec
import java.util.* import java.util.*
sealed interface IPatternState { data class PatternState(
val id: UUID val id: UUID,
val item: Item val item: Item,
val researchPercent: Double val researchPercent: Double,
) {
fun asMutable(): MutablePatternState fun matchId(other: PatternState): Boolean {
fun asImmutable() : PatternState
fun matchId(other: IPatternState): Boolean {
return other.id == id return other.id == id
} }
fun copyAsMutable(
id: UUID = this.id,
item: Item = this.item,
researchPercent: Double = this.researchPercent,
): MutablePatternState {
return MutablePatternState(id, item, researchPercent)
}
fun copyAsImmutable(
id: UUID = this.id,
item: Item = this.item,
researchPercent: Double = this.researchPercent,
) : PatternState {
return PatternState(id, item, researchPercent)
}
fun stack(count: Int = 1): ItemStack { fun stack(count: Int = 1): ItemStack {
return ItemStack(item, count) return ItemStack(item, count)
} }
fun serializeNBT(): CompoundTag
fun write(buff: FriendlyByteBuf) { fun write(buff: FriendlyByteBuf) {
buff.writeUUID(id) buff.writeBinaryJsonWithCodec(CODEC, this)
buff.writeItemType(item)
buff.writeDouble(researchPercent)
}
}
private fun <T : IPatternState> codec(builder: RecordCodecBuilder.Instance<T>): Products.P3<RecordCodecBuilder.Mu<T>, UUID, Item, Double> {
return builder.group(
UUIDCodec.fieldOf("id").forGetter(IPatternState::id),
ForgeRegistries.ITEMS.codec.fieldOf("item").forGetter(IPatternState::item),
Codec.doubleRange(0.0, 1.0).fieldOf("researchPercent").forGetter(IPatternState::researchPercent)
)
}
private fun read(buff: FriendlyByteBuf, mutable: Boolean): IPatternState? {
val id = buff.readUUID()
val item = buff.readItemType()
val researchPercent = buff.readDouble()
item ?: return null
if (mutable) {
return MutablePatternState(id, item, researchPercent)
} else {
return PatternState(id, item, researchPercent)
}
}
data class PatternState(
override val id: UUID,
override val item: Item,
override val researchPercent: Double,
) : IPatternState {
override fun asMutable(): MutablePatternState {
return MutablePatternState(id, item, researchPercent)
} }
override fun asImmutable(): PatternState { fun serializeNBT(): CompoundTag {
return this return CODEC.encode(this, NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).get()
} .map({ it as CompoundTag }, { throw RuntimeException("Failed to serialize PatternState: ${it.message()}") })
override fun serializeNBT(): CompoundTag {
return CODEC.encode(this, NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).get().map({ it as CompoundTag }, { throw RuntimeException("Failed to serialize PatternState: ${it.message()}") })
} }
companion object { companion object {
@ -104,48 +42,17 @@ data class PatternState(
return CODEC.decode(NbtOps.INSTANCE, tag).result().map { it.first }.orElse(null) return CODEC.decode(NbtOps.INSTANCE, tag).result().map { it.first }.orElse(null)
} }
fun read(buff: FriendlyByteBuf): PatternState? { fun read(buff: FriendlyByteBuf): PatternState {
return read(buff, false) as PatternState? return buff.readBinaryJsonWithCodec(CODEC)
} }
val CODEC: Codec<PatternState> by lazy { val CODEC: Codec<PatternState> by lazy {
RecordCodecBuilder.create { RecordCodecBuilder.create {
codec(it).apply(it, ::PatternState) it.group(
} UUIDCodec.fieldOf("id").forGetter(PatternState::id),
} ForgeRegistries.ITEMS.codec.fieldOf("item").forGetter(PatternState::item),
} Codec.doubleRange(0.0, 1.0).fieldOf("researchPercent").forGetter(PatternState::researchPercent)
} ).apply(it, ::PatternState)
data class MutablePatternState(
override val id: UUID,
override val item: Item,
override var researchPercent: Double,
) : IPatternState {
override fun asMutable(): MutablePatternState {
return this
}
override fun asImmutable(): PatternState {
return PatternState(id, item, researchPercent)
}
override fun serializeNBT(): CompoundTag {
return CODEC.encode(this, NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).get().map({ it as CompoundTag }, { throw RuntimeException("Failed to serialize MutablePatternState: ${it.message()}") })
}
companion object {
fun deserializeNBT(tag: Tag?): MutablePatternState? {
tag ?: return null
return CODEC.decode(NbtOps.INSTANCE, tag).result().map { it.first }.orElse(null)
}
fun read(buff: FriendlyByteBuf): MutablePatternState? {
return read(buff, true) as MutablePatternState?
}
val CODEC: Codec<MutablePatternState> by lazy {
RecordCodecBuilder.create {
codec(it).apply(it, ::MutablePatternState)
} }
} }
} }

View File

@ -2,11 +2,10 @@ package ru.dbotthepony.mc.otm.client.screen.matter
import net.minecraft.ChatFormatting import net.minecraft.ChatFormatting
import net.minecraft.client.gui.GuiGraphics import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.gui.components.EditBox
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.capability.matter.IPatternState import ru.dbotthepony.mc.otm.capability.matter.PatternState
import ru.dbotthepony.mc.otm.capability.matter.IReplicationTask import ru.dbotthepony.mc.otm.capability.matter.IReplicationTask
import ru.dbotthepony.mc.otm.client.ShiftPressedCond import ru.dbotthepony.mc.otm.client.ShiftPressedCond
import ru.dbotthepony.mc.otm.client.render.* import ru.dbotthepony.mc.otm.client.render.*
@ -16,7 +15,6 @@ import ru.dbotthepony.mc.otm.client.screen.panels.button.ButtonPanel
import ru.dbotthepony.mc.otm.client.screen.panels.button.DeviceControls import ru.dbotthepony.mc.otm.client.screen.panels.button.DeviceControls
import ru.dbotthepony.mc.otm.client.screen.panels.button.LargeBooleanRectangleButtonPanel import ru.dbotthepony.mc.otm.client.screen.panels.button.LargeBooleanRectangleButtonPanel
import ru.dbotthepony.mc.otm.client.screen.panels.button.LargeEnumRectangleButtonPanel import ru.dbotthepony.mc.otm.client.screen.panels.button.LargeEnumRectangleButtonPanel
import ru.dbotthepony.mc.otm.client.screen.panels.input.EditBoxPanel
import ru.dbotthepony.mc.otm.client.screen.panels.input.TextInputPanel import ru.dbotthepony.mc.otm.client.screen.panels.input.TextInputPanel
import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel
import ru.dbotthepony.mc.otm.client.screen.panels.util.DiscreteScrollBarPanel import ru.dbotthepony.mc.otm.client.screen.panels.util.DiscreteScrollBarPanel
@ -299,7 +297,7 @@ class MatterPanelScreen(
return frame return frame
} }
private fun openPattern(pattern: IPatternState): FramePanel<MatterPanelScreen> { private fun openPattern(pattern: PatternState): FramePanel<MatterPanelScreen> {
val frame = FramePanel.padded(this, null, 213f, (ButtonPanel.HEIGHT + 3f) * 4f + 38f, TranslatableComponent("otm.gui.matter_panel.task")) val frame = FramePanel.padded(this, null, 213f, (ButtonPanel.HEIGHT + 3f) * 4f + 38f, TranslatableComponent("otm.gui.matter_panel.task"))
frame.behaveAsWindow() frame.behaveAsWindow()

View File

@ -7,8 +7,11 @@ import com.google.gson.JsonObject
import com.google.gson.JsonParseException import com.google.gson.JsonParseException
import com.google.gson.JsonPrimitive import com.google.gson.JsonPrimitive
import com.google.gson.JsonSyntaxException import com.google.gson.JsonSyntaxException
import com.mojang.serialization.Codec
import com.mojang.serialization.JsonOps
import io.netty.buffer.ByteBufInputStream import io.netty.buffer.ByteBufInputStream
import io.netty.buffer.ByteBufOutputStream import io.netty.buffer.ByteBufOutputStream
import io.netty.handler.codec.DecoderException
import io.netty.handler.codec.EncoderException import io.netty.handler.codec.EncoderException
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.NbtAccounter import net.minecraft.nbt.NbtAccounter
@ -273,6 +276,16 @@ fun FriendlyByteBuf.writeBinaryJson(value: JsonElement) {
ByteBufOutputStream(this).writeBinaryJson(value) ByteBufOutputStream(this).writeBinaryJson(value)
} }
fun <S> FriendlyByteBuf.writeBinaryJsonWithCodec(codec: Codec<S>, value: S) {
writeBinaryJson(codec.encode(value, JsonOps.INSTANCE, JsonOps.INSTANCE.empty())
.get().map({ it }, { throw EncoderException("Failed to encode input data: ${it.message()}") }))
}
fun <S> FriendlyByteBuf.readBinaryJsonWithCodec(codec: Codec<S>, sizeLimit: NbtAccounter = NbtAccounter(1L shl 18)): S {
return codec.decode(JsonOps.INSTANCE, readBinaryJson(sizeLimit))
.get().map({ it.first }, { throw DecoderException("Failed to decode data from network: ${it.message()}") })
}
fun FriendlyByteBuf.readBinaryComponent(): Component { fun FriendlyByteBuf.readBinaryComponent(): Component {
return Component.Serializer.fromJson(readBinaryJson()) ?: throw NullPointerException("Received null component") return Component.Serializer.fromJson(readBinaryJson()) ?: throw NullPointerException("Received null component")
} }

View File

@ -3,9 +3,9 @@ package ru.dbotthepony.mc.otm.graph.matter
import ru.dbotthepony.mc.otm.capability.matter.* import ru.dbotthepony.mc.otm.capability.matter.*
interface IMatterGraphListener { interface IMatterGraphListener {
fun onPatternAdded(state: IPatternState) {} fun onPatternAdded(state: PatternState) {}
fun onPatternRemoved(state: IPatternState) {} fun onPatternRemoved(state: PatternState) {}
fun onPatternUpdated(newState: IPatternState, oldState: IPatternState) {} fun onPatternUpdated(newState: PatternState, oldState: PatternState) {}
fun onMatterTaskCreated(task: IReplicationTask<*>) {} fun onMatterTaskCreated(task: IReplicationTask<*>) {}
fun <T : IReplicationTask<*>> onMatterTaskUpdated(newState: T, oldState: T) {} fun <T : IReplicationTask<*>> onMatterTaskUpdated(newState: T, oldState: T) {}

View File

@ -170,7 +170,7 @@ class MatterGraph : Abstract6Graph<MatterNode, MatterGraph>(), IMatterGraphListe
return received return received
} }
private fun doInsertPattern(state: IPatternState, onlyUpdate: Boolean, simulate: Boolean): PatternInsertStatus { private fun doInsertPattern(state: PatternState, onlyUpdate: Boolean, simulate: Boolean): PatternInsertStatus {
for (node in nodes) { for (node in nodes) {
val storage = node.getPatternHandler() val storage = node.getPatternHandler()
@ -186,7 +186,7 @@ class MatterGraph : Abstract6Graph<MatterNode, MatterGraph>(), IMatterGraphListe
return PatternInsertFailure return PatternInsertFailure
} }
fun insertPattern(state: IPatternState, onlyUpdate: Boolean, simulate: Boolean): PatternInsertStatus { fun insertPattern(state: PatternState, onlyUpdate: Boolean, simulate: Boolean): PatternInsertStatus {
if (onlyUpdate) return doInsertPattern(state, true, simulate) if (onlyUpdate) return doInsertPattern(state, true, simulate)
val status = doInsertPattern(state, true, simulate) val status = doInsertPattern(state, true, simulate)
if (!status.isFailed) return status if (!status.isFailed) return status
@ -201,7 +201,7 @@ class MatterGraph : Abstract6Graph<MatterNode, MatterGraph>(), IMatterGraphListe
return nodes.stream().map { it.getTaskHandler()?.allReplicationTasks }.filterNotNull().flatMap { it } return nodes.stream().map { it.getTaskHandler()?.allReplicationTasks }.filterNotNull().flatMap { it }
} }
val patterns: Stream<IPatternState> get() { val patterns: Stream<PatternState> get() {
return nodes.stream().map { it.getPatternHandler()?.patterns }.filterNotNull().flatMap { it } return nodes.stream().map { it.getPatternHandler()?.patterns }.filterNotNull().flatMap { it }
} }
@ -233,7 +233,7 @@ class MatterGraph : Abstract6Graph<MatterNode, MatterGraph>(), IMatterGraphListe
return value return value
} }
fun getPattern(id: UUID): IPatternState? { fun getPattern(id: UUID): PatternState? {
for (node in nodes) { for (node in nodes) {
val storage = node.getPatternHandler() val storage = node.getPatternHandler()
@ -253,7 +253,7 @@ class MatterGraph : Abstract6Graph<MatterNode, MatterGraph>(), IMatterGraphListe
fun hasPattern(state: PatternState) = getPattern(state.id) != null fun hasPattern(state: PatternState) = getPattern(state.id) != null
fun hasPattern(id: UUID) = getPattern(id) != null fun hasPattern(id: UUID) = getPattern(id) != null
fun findPattern(predicate: Predicate<IPatternState>): IPatternState? { fun findPattern(predicate: Predicate<PatternState>): PatternState? {
for (node in nodes) { for (node in nodes) {
val storage = node.getPatternHandler() val storage = node.getPatternHandler()
@ -271,7 +271,7 @@ class MatterGraph : Abstract6Graph<MatterNode, MatterGraph>(), IMatterGraphListe
fun findPattern(predicate: Item) = findPattern { it.item == predicate } fun findPattern(predicate: Item) = findPattern { it.item == predicate }
fun findPatterns(predicate: Predicate<IPatternState>): List<IPatternState> { fun findPatterns(predicate: Predicate<PatternState>): List<PatternState> {
return patterns.filter(predicate).toList() return patterns.filter(predicate).toList()
} }
@ -297,17 +297,17 @@ class MatterGraph : Abstract6Graph<MatterNode, MatterGraph>(), IMatterGraphListe
return nodes.any { it.getTaskHandler()?.notifyTaskCompletion(taskId) == true } return nodes.any { it.getTaskHandler()?.notifyTaskCompletion(taskId) == true }
} }
override fun onPatternAdded(state: IPatternState) { override fun onPatternAdded(state: PatternState) {
for (node in nodes) node.onPatternAdded(state) for (node in nodes) node.onPatternAdded(state)
for (node in listeners) node.onPatternAdded(state) for (node in listeners) node.onPatternAdded(state)
} }
override fun onPatternRemoved(state: IPatternState) { override fun onPatternRemoved(state: PatternState) {
for (node in nodes) node.onPatternRemoved(state) for (node in nodes) node.onPatternRemoved(state)
for (node in listeners) node.onPatternRemoved(state) for (node in listeners) node.onPatternRemoved(state)
} }
override fun onPatternUpdated(newState: IPatternState, oldState: IPatternState) { override fun onPatternUpdated(newState: PatternState, oldState: PatternState) {
for (node in nodes) node.onPatternUpdated(newState, oldState) for (node in nodes) node.onPatternUpdated(newState, oldState)
for (node in listeners) node.onPatternUpdated(newState, oldState) for (node in listeners) node.onPatternUpdated(newState, oldState)
} }

View File

@ -14,11 +14,10 @@ import net.minecraftforge.common.capabilities.ICapabilityProvider
import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.registries.ForgeRegistries import net.minecraftforge.registries.ForgeRegistries
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.matter.IPatternState import ru.dbotthepony.mc.otm.capability.matter.PatternState
import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage
import ru.dbotthepony.mc.otm.capability.matter.PatternInsertFailure import ru.dbotthepony.mc.otm.capability.matter.PatternInsertFailure
import ru.dbotthepony.mc.otm.capability.matter.PatternInsertStatus import ru.dbotthepony.mc.otm.capability.matter.PatternInsertStatus
import ru.dbotthepony.mc.otm.capability.matter.PatternState
import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.getID import ru.dbotthepony.mc.otm.core.getID
import ru.dbotthepony.mc.otm.matter.MatterManager import ru.dbotthepony.mc.otm.matter.MatterManager
@ -29,7 +28,7 @@ class CreativePatternItem : Item(Properties().rarity(Rarity.EPIC).stacksTo(1)) {
private object Patterns : IPatternStorage, ICapabilityProvider { private object Patterns : IPatternStorage, ICapabilityProvider {
private val resolver = LazyOptional.of<IPatternStorage> { this } private val resolver = LazyOptional.of<IPatternStorage> { this }
override val patterns: Stream<out IPatternState> override val patterns: Stream<out PatternState>
get() = MatterManager.map.keys.stream().map { PatternState(UUID(34783464838L, 4463458382L + ForgeRegistries.ITEMS.getID(it)), it, 1.0) } get() = MatterManager.map.keys.stream().map { PatternState(UUID(34783464838L, 4463458382L + ForgeRegistries.ITEMS.getID(it)), it, 1.0) }
override val patternCapacity: Int override val patternCapacity: Int
@ -43,7 +42,7 @@ class CreativePatternItem : Item(Properties().rarity(Rarity.EPIC).stacksTo(1)) {
} }
override fun insertPattern( override fun insertPattern(
pattern: IPatternState, pattern: PatternState,
onlyUpdate: Boolean, onlyUpdate: Boolean,
simulate: Boolean simulate: Boolean
): PatternInsertStatus { ): PatternInsertStatus {

View File

@ -108,14 +108,14 @@ class PatternStorageItem : Item {
return if (cap == MatteryCapability.PATTERN) resolver.cast() else LazyOptional.empty() return if (cap == MatteryCapability.PATTERN) resolver.cast() else LazyOptional.empty()
} }
override val patterns: Stream<out IPatternState> get() { override val patterns: Stream<out PatternState> get() {
return stack.tag?.map("otm_patterns") { it: ListTag -> return stack.tag?.map("otm_patterns") { it: ListTag ->
it.stream().map { PatternState.deserializeNBT(it) }.filter { it != null } as Stream<out IPatternState> it.stream().map { PatternState.deserializeNBT(it) }.filter { it != null } as Stream<out PatternState>
} ?: Stream.empty() } ?: Stream.empty()
} }
override fun insertPattern( override fun insertPattern(
pattern: IPatternState, pattern: PatternState,
onlyUpdate: Boolean, onlyUpdate: Boolean,
simulate: Boolean simulate: Boolean
): PatternInsertStatus { ): PatternInsertStatus {
@ -128,7 +128,7 @@ class PatternStorageItem : Item {
if (simulate) { if (simulate) {
if (patternCapacity > 0) if (patternCapacity > 0)
return PatternInsertInserted(pattern.asImmutable()) return PatternInsertInserted(pattern)
else else
return PatternInsertFailure return PatternInsertFailure
} }
@ -148,7 +148,7 @@ class PatternStorageItem : Item {
list[i] = pattern.serializeNBT() list[i] = pattern.serializeNBT()
} }
return PatternInsertUpdated(pattern.asImmutable(), state) return PatternInsertUpdated(pattern, state)
} }
} else { } else {
invalidCounter++ invalidCounter++
@ -160,7 +160,7 @@ class PatternStorageItem : Item {
if (invalidCounter > 0) { if (invalidCounter > 0) {
if (simulate) if (simulate)
return PatternInsertInserted(pattern.asImmutable()) return PatternInsertInserted(pattern)
for (i in list.indices) { for (i in list.indices) {
val state = PatternState.deserializeNBT(list.getCompound(i)) val state = PatternState.deserializeNBT(list.getCompound(i))

View File

@ -49,7 +49,7 @@ class CancelTaskPacket(val id: UUID) : MatteryPacket {
} }
} }
class PatternsChangePacket(val isUpdate: Boolean, val patterns: Collection<IPatternState>) : MatteryPacket { class PatternsChangePacket(val isUpdate: Boolean, val patterns: Collection<PatternState>) : MatteryPacket {
override fun write(buff: FriendlyByteBuf) { override fun write(buff: FriendlyByteBuf) {
buff.writeBoolean(isUpdate) buff.writeBoolean(isUpdate)
buff.writeInt(patterns.size) buff.writeInt(patterns.size)
@ -205,16 +205,16 @@ class MatterPanelMenu @JvmOverloads constructor(
val sortingGS = GetterSetter.of(::sorting, changeSorting::input) val sortingGS = GetterSetter.of(::sorting, changeSorting::input)
val isAscendingGS = GetterSetter.of(::isAscending, changeIsAscending::input) val isAscendingGS = GetterSetter.of(::isAscending, changeIsAscending::input)
private val actualComparator = Comparator<IPatternState> { o1, o2 -> sorting.comparator.compare(o1.item, o2.item) * (if (isAscending) 1 else -1) } private val actualComparator = Comparator<PatternState> { o1, o2 -> sorting.comparator.compare(o1.item, o2.item) * (if (isAscending) 1 else -1) }
private val actualTaskComparator = Comparator<IReplicationTask<*>> { o1, o2 -> sorting.comparator.compare(o1.item, o2.item) * (if (isAscending) 1 else -1) } private val actualTaskComparator = Comparator<IReplicationTask<*>> { o1, o2 -> sorting.comparator.compare(o1.item, o2.item) * (if (isAscending) 1 else -1) }
private val patterns = ArrayList<IPatternState>() private val patterns = ArrayList<PatternState>()
private val tasks = ArrayList<IReplicationTask<*>>() private val tasks = ArrayList<IReplicationTask<*>>()
val patternsFiltered = ArrayList<IPatternState>() val patternsFiltered = ArrayList<PatternState>()
val tasksFiltered = ArrayList<IReplicationTask<*>>() val tasksFiltered = ArrayList<IReplicationTask<*>>()
fun networkPatternsUpdated(patterns: Collection<IPatternState>) { fun networkPatternsUpdated(patterns: Collection<PatternState>) {
for (pattern in patterns) { for (pattern in patterns) {
val index = this.patterns.indexOfFirst(pattern::matchId) val index = this.patterns.indexOfFirst(pattern::matchId)
@ -236,7 +236,7 @@ class MatterPanelMenu @JvmOverloads constructor(
} }
} }
fun networkPatternsRemoved(patterns: Collection<IPatternState>) { fun networkPatternsRemoved(patterns: Collection<PatternState>) {
for (pattern in patterns) { for (pattern in patterns) {
this.patterns.remove(pattern) this.patterns.remove(pattern)
} }
@ -310,15 +310,15 @@ class MatterPanelMenu @JvmOverloads constructor(
MenuNetworkChannel.sendToServer(CancelTaskPacket(id)) MenuNetworkChannel.sendToServer(CancelTaskPacket(id))
} }
override fun onPatternAdded(state: IPatternState) { override fun onPatternAdded(state: PatternState) {
sendNetwork(PatternsChangePacket(true, listOf(state))) sendNetwork(PatternsChangePacket(true, listOf(state)))
} }
override fun onPatternRemoved(state: IPatternState) { override fun onPatternRemoved(state: PatternState) {
sendNetwork(PatternsChangePacket(false, listOf(state))) sendNetwork(PatternsChangePacket(false, listOf(state)))
} }
override fun onPatternUpdated(newState: IPatternState, oldState: IPatternState) { override fun onPatternUpdated(newState: PatternState, oldState: PatternState) {
sendNetwork(PatternsChangePacket(true, listOf(newState))) sendNetwork(PatternsChangePacket(true, listOf(newState)))
} }