Revamp job event loops, move jobs to codecs
Add PatternState codecs Add ReplicationTask codecs Instead of returning job status on job tick, now downstream code directly update status of provided job status object Make Matter Replicator and Matter Recycler not do full stop when there is not enough matter/nowhere to put matter
This commit is contained in:
parent
d4fb6d0b24
commit
8a78b299c5
@ -1,114 +1,229 @@
|
|||||||
package ru.dbotthepony.mc.otm.block.entity
|
package ru.dbotthepony.mc.otm.block.entity
|
||||||
|
|
||||||
|
import com.mojang.datafixers.Products
|
||||||
|
import com.mojang.serialization.Codec
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
|
import net.minecraft.nbt.NbtOps
|
||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
import net.minecraftforge.common.util.INBTSerializable
|
import net.minecraftforge.common.util.INBTSerializable
|
||||||
|
import org.apache.logging.log4j.LogManager
|
||||||
import ru.dbotthepony.mc.otm.capability.IMatteryUpgrade
|
import ru.dbotthepony.mc.otm.capability.IMatteryUpgrade
|
||||||
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
|
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
|
||||||
import ru.dbotthepony.mc.otm.config.MachinesConfig
|
import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
import ru.dbotthepony.mc.otm.core.math.getDecimal
|
|
||||||
import ru.dbotthepony.mc.otm.core.math.set
|
|
||||||
import ru.dbotthepony.mc.otm.core.math.weakEqualDoubles
|
import ru.dbotthepony.mc.otm.core.math.weakEqualDoubles
|
||||||
import ru.dbotthepony.mc.otm.core.math.weakGreaterThan
|
import ru.dbotthepony.mc.otm.core.math.weakGreaterThan
|
||||||
import ru.dbotthepony.mc.otm.core.math.weakLessThan
|
import ru.dbotthepony.mc.otm.core.math.weakLessThan
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.map
|
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||||
|
import ru.dbotthepony.mc.otm.data.DecimalCodec
|
||||||
|
import ru.dbotthepony.mc.otm.data.minRange
|
||||||
|
|
||||||
private fun isReason(status: Any?, reason: Any) = status == null || status == reason
|
private fun isReason(status: Any?, reason: Any) = status == null || status == reason
|
||||||
|
private val LOGGER = LogManager.getLogger()
|
||||||
|
|
||||||
interface IMachineJob {
|
interface IJob {
|
||||||
val ticks: Double
|
val ticks: Double
|
||||||
val powerUsage: Decimal
|
val powerUsage: Decimal
|
||||||
val experience: Float get() = 0f
|
val experience: Float get() = 0f
|
||||||
|
|
||||||
fun serializeNBT(): CompoundTag
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open class MachineJob : IMachineJob {
|
open class Job(
|
||||||
final override val ticks: Double
|
final override val ticks: Double,
|
||||||
final override val powerUsage: Decimal
|
final override val powerUsage: Decimal = Decimal.ZERO,
|
||||||
final override val experience: Float
|
final override val experience: Float = 0f
|
||||||
|
) : IJob {
|
||||||
constructor(
|
companion object {
|
||||||
ticks: Double,
|
fun <T : Job> basicCodec(builder: RecordCodecBuilder.Instance<T>): Products.P3<RecordCodecBuilder.Mu<T>, Double, Decimal, Float> {
|
||||||
powerUsage: Decimal = Decimal.ZERO,
|
return builder.group(
|
||||||
experience: Float = 0f,
|
Codec.doubleRange(0.0, Double.MAX_VALUE).fieldOf("ticks").forGetter(Job::ticks),
|
||||||
) {
|
DecimalCodec.fieldOf("powerUsage").forGetter(Job::powerUsage), // не надо указывать минимальную энергию как 0,
|
||||||
this.ticks = ticks
|
// ибо мы можем таким образом использовать это для создания работ генератора
|
||||||
this.powerUsage = powerUsage
|
Codec.floatRange(0f, Float.MAX_VALUE).optionalFieldOf("experience", 0f).forGetter(Job::experience),
|
||||||
this.experience = experience
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
fun <T : Job> plainCodec(builder: RecordCodecBuilder.Instance<T>): Products.P2<RecordCodecBuilder.Mu<T>, Double, Decimal> {
|
||||||
tag: CompoundTag
|
return builder.group(
|
||||||
) : this(tag.getDouble("Ticks"), tag.getDecimal("EnergyUsage"), tag.getFloat("Experience"))
|
Codec.doubleRange(0.0, Double.MAX_VALUE).fieldOf("ticks").forGetter(Job::ticks),
|
||||||
|
DecimalCodec.fieldOf("powerUsage").forGetter(Job::powerUsage), // не надо указывать минимальную энергию как 0,
|
||||||
|
// ибо мы можем таким образом использовать это для создания работ генератора
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun serializeNBT(): CompoundTag {
|
val CODEC: Codec<Job> by lazy {
|
||||||
return CompoundTag().also {
|
RecordCodecBuilder.create {
|
||||||
it["Ticks"] = ticks
|
basicCodec(it).apply(it, ::Job)
|
||||||
it["EnergyUsage"] = powerUsage
|
}
|
||||||
it["Experience"] = experience
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open class MachineItemJob : MachineJob {
|
open class ItemJob(
|
||||||
val itemStack: ItemStack
|
val itemStack: ItemStack,
|
||||||
|
|
||||||
constructor(
|
|
||||||
itemStack: ItemStack,
|
|
||||||
ticks: Double,
|
ticks: Double,
|
||||||
power: Decimal = Decimal.ZERO,
|
power: Decimal = Decimal.ZERO,
|
||||||
experience: Float = 0f,
|
experience: Float = 0f
|
||||||
) : super(ticks, power, experience) {
|
) : Job(ticks, power, experience) {
|
||||||
this.itemStack = itemStack
|
companion object {
|
||||||
|
fun <T : ItemJob> itemCodec(builder: RecordCodecBuilder.Instance<T>): Products.P4<RecordCodecBuilder.Mu<T>, ItemStack, Double, Decimal, Float> {
|
||||||
|
return builder.group(ItemStack.CODEC.fieldOf("itemStack").forGetter(ItemJob::itemStack)).and(basicCodec(builder))
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
val CODEC: Codec<ItemJob> by lazy {
|
||||||
tag: CompoundTag
|
RecordCodecBuilder.create {
|
||||||
) : super(tag) {
|
itemCodec(it).apply(it, ::ItemJob)
|
||||||
this.itemStack = (tag["Item"] as? CompoundTag)?.let { ItemStack.of(it) } ?: ItemStack.EMPTY
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun serializeNBT(): CompoundTag {
|
|
||||||
return super.serializeNBT().also {
|
|
||||||
it["Item"] = itemStack.serializeNBT()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class JobStatus(
|
class JobStatus<T : IJob>(
|
||||||
val success: Boolean,
|
var requiredPower: Decimal,
|
||||||
val throttleTicks: Int = 0,
|
val extractedPower: Decimal,
|
||||||
val idleReason: MachineJobEventLoop.IdleReason? = null,
|
ticksAdvanced: Double,
|
||||||
val newDrainedPower: Decimal? = null
|
val job: T,
|
||||||
) {
|
val workTicks: Double,
|
||||||
init {
|
) : IJob by job {
|
||||||
require(throttleTicks >= 0) { "Negative amount of ticks to throttle: $throttleTicks" }
|
constructor(job: T, workTicks: Double) : this(Decimal.ZERO, Decimal.ZERO, 0.0, job, workTicks)
|
||||||
|
|
||||||
|
val workProgress: Float
|
||||||
|
get() {
|
||||||
|
return ((workTicks + workTicks) / job.ticks).coerceAtMost(1.0).toFloat()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
var success = true
|
||||||
val SUCCESS = JobStatus(true)
|
|
||||||
val FAILURE = JobStatus(false)
|
var ticksAdvanced = ticksAdvanced
|
||||||
val FAILURE_ITEM = JobStatus(false, 20, MachineJobEventLoop.IdleReason.ITEM)
|
set(value) {
|
||||||
val FAILURE_MATTER = JobStatus(false, 20, MachineJobEventLoop.IdleReason.MATTER)
|
require(value >= 0.0) { "Invalid amount of ticks to advance: $value" }
|
||||||
val FAILURE_WAIT = JobStatus(false, 100)
|
field = value
|
||||||
val FAILURE_WAIT_FAST = JobStatus(false, 20)
|
}
|
||||||
|
|
||||||
|
var throttleTicks = 0
|
||||||
|
set(value) {
|
||||||
|
require(value >= 0) { "Invalid amount of ticks to throttle: $value" }
|
||||||
|
if (value != 0) success = false
|
||||||
|
field = value
|
||||||
|
}
|
||||||
|
|
||||||
|
var idleReason: Any? = null
|
||||||
|
set(value) {
|
||||||
|
if (value != null) success = false
|
||||||
|
field = value
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You don't have to actually call this, JobStatus is in this state by default
|
||||||
|
*
|
||||||
|
* But this is handy to call this when doing early returns, to clearly state that "we are in success"
|
||||||
|
*/
|
||||||
|
fun success() {
|
||||||
|
this.success = true
|
||||||
|
this.throttleTicks = 0
|
||||||
|
this.idleReason = null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun throttle() {
|
||||||
|
this.success = false
|
||||||
|
this.throttleTicks = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
fun throttleFast() {
|
||||||
|
this.success = false
|
||||||
|
this.throttleTicks = 20
|
||||||
|
}
|
||||||
|
|
||||||
|
fun noItem(throttleTicks: Int = 20) {
|
||||||
|
this.success = false
|
||||||
|
idleReason = MachineJobEventLoop.IdleReason.ITEM
|
||||||
|
this.throttleTicks = throttleTicks
|
||||||
|
}
|
||||||
|
|
||||||
|
fun noPower(throttleTicks: Int = 20) {
|
||||||
|
this.success = false
|
||||||
|
idleReason = MachineJobEventLoop.IdleReason.POWER
|
||||||
|
this.throttleTicks = throttleTicks
|
||||||
|
}
|
||||||
|
|
||||||
|
fun noMatter(throttleTicks: Int = 20) {
|
||||||
|
this.success = false
|
||||||
|
idleReason = MachineJobEventLoop.IdleReason.MATTER
|
||||||
|
this.throttleTicks = throttleTicks
|
||||||
|
}
|
||||||
|
|
||||||
|
fun noPattern(throttleTicks: Int = 20) {
|
||||||
|
this.success = false
|
||||||
|
idleReason = MachineJobEventLoop.IdleReason.PATTERN
|
||||||
|
this.throttleTicks = throttleTicks
|
||||||
|
}
|
||||||
|
|
||||||
|
fun observe(throttleTicks: Int = 20) {
|
||||||
|
this.success = false
|
||||||
|
idleReason = MachineJobEventLoop.IdleReason.OBSERVING
|
||||||
|
this.throttleTicks = throttleTicks
|
||||||
|
}
|
||||||
|
|
||||||
|
fun failure(reason: Any) {
|
||||||
|
this.success = false
|
||||||
|
idleReason = reason
|
||||||
|
}
|
||||||
|
|
||||||
|
fun failure(throttleTicks: Int = 0) {
|
||||||
|
this.success = false
|
||||||
|
this.throttleTicks = throttleTicks
|
||||||
|
}
|
||||||
|
|
||||||
|
fun scale(value: Decimal) {
|
||||||
|
require(value >= Decimal.ZERO) { "Attempted to scale by negative value: $value" }
|
||||||
|
if (value == Decimal.ONE)
|
||||||
|
return
|
||||||
|
|
||||||
|
if (value.isZero) {
|
||||||
|
ticksAdvanced = 0.0
|
||||||
|
requiredPower = Decimal.ZERO
|
||||||
|
success = false
|
||||||
|
} else {
|
||||||
|
requiredPower *= value
|
||||||
|
ticksAdvanced *= value.toDouble()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun scale(value: Double) {
|
||||||
|
require(value >= 0.0) { "Attempted to scale by negative value: $value" }
|
||||||
|
if (value == 1.0)
|
||||||
|
return
|
||||||
|
|
||||||
|
if (value == 0.0) {
|
||||||
|
ticksAdvanced = 0.0
|
||||||
|
requiredPower = Decimal.ZERO
|
||||||
|
success = false
|
||||||
|
} else {
|
||||||
|
requiredPower *= value
|
||||||
|
ticksAdvanced *= value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class JobContainer<JobType : IMachineJob>(val job: JobType? = null, val idleReason: Any? = null, val throttleTicks: Int = 0) {
|
data class JobContainer<JobType : IJob>(val job: JobType? = null, val idleReason: Any? = null, val throttleTicks: Int = 0) {
|
||||||
init {
|
init {
|
||||||
require(throttleTicks >= 0) { "Negative amount of ticks to throttle: $throttleTicks" }
|
require(throttleTicks >= 0) { "Negative amount of ticks to throttle: $throttleTicks" }
|
||||||
|
|
||||||
|
if (job != null && idleReason != null) {
|
||||||
|
throw IllegalArgumentException("Can't have both job and idle reason specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (job != null && throttleTicks != 0) {
|
||||||
|
throw IllegalArgumentException("Can't have both job and throttle ticks specified")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun <JobType : IMachineJob> success(job: JobType): JobContainer<JobType> {
|
fun <JobType : IJob> success(job: JobType): JobContainer<JobType> {
|
||||||
return JobContainer(job, null)
|
return JobContainer(job, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <JobType : IMachineJob> failure(reason: Any?): JobContainer<JobType> {
|
fun <JobType : IJob> failure(reason: Any?): JobContainer<JobType> {
|
||||||
return JobContainer(null, reason)
|
return JobContainer(null, reason)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,41 +235,40 @@ data class JobContainer<JobType : IMachineJob>(val job: JobType? = null, val idl
|
|||||||
private val observe = JobContainer(null, MachineJobEventLoop.IdleReason.OBSERVING)
|
private val observe = JobContainer(null, MachineJobEventLoop.IdleReason.OBSERVING)
|
||||||
|
|
||||||
@Suppress("unchecked_cast")
|
@Suppress("unchecked_cast")
|
||||||
fun <JobType : IMachineJob> failure(): JobContainer<JobType> {
|
fun <JobType : IJob> failure(): JobContainer<JobType> {
|
||||||
return empty as JobContainer<JobType>
|
return empty as JobContainer<JobType>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("unchecked_cast")
|
@Suppress("unchecked_cast")
|
||||||
fun <JobType : IMachineJob> noItem(): JobContainer<JobType> {
|
fun <JobType : IJob> noItem(): JobContainer<JobType> {
|
||||||
return noItem as JobContainer<JobType>
|
return noItem as JobContainer<JobType>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("unchecked_cast")
|
@Suppress("unchecked_cast")
|
||||||
fun <JobType : IMachineJob> noEnergy(): JobContainer<JobType> {
|
fun <JobType : IJob> noEnergy(): JobContainer<JobType> {
|
||||||
return noEnergy as JobContainer<JobType>
|
return noEnergy as JobContainer<JobType>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("unchecked_cast")
|
@Suppress("unchecked_cast")
|
||||||
fun <JobType : IMachineJob> noMatter(): JobContainer<JobType> {
|
fun <JobType : IJob> noMatter(): JobContainer<JobType> {
|
||||||
return noMatter as JobContainer<JobType>
|
return noMatter as JobContainer<JobType>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("unchecked_cast")
|
@Suppress("unchecked_cast")
|
||||||
fun <JobType : IMachineJob> noPattern(): JobContainer<JobType> {
|
fun <JobType : IJob> noPattern(): JobContainer<JobType> {
|
||||||
return noPattern as JobContainer<JobType>
|
return noPattern as JobContainer<JobType>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("unchecked_cast")
|
@Suppress("unchecked_cast")
|
||||||
fun <JobType : IMachineJob> observe(): JobContainer<JobType> {
|
fun <JobType : IJob> observe(): JobContainer<JobType> {
|
||||||
return observe as JobContainer<JobType>
|
return observe as JobContainer<JobType>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class MachineJobEventLoop<JobType : IMachineJob> : INBTSerializable<CompoundTag?> {
|
abstract class MachineJobEventLoop<JobType : IJob>(val codec: Codec<JobType>) : INBTSerializable<CompoundTag?> {
|
||||||
protected abstract val energy: IMatteryEnergyStorage?
|
protected abstract val energy: IMatteryEnergyStorage?
|
||||||
protected abstract val isBlockedByRedstone: Boolean
|
protected abstract val isBlockedByRedstone: Boolean
|
||||||
protected abstract fun deserializeJob(nbt: CompoundTag): JobType?
|
|
||||||
protected abstract val upgrades: IMatteryUpgrade?
|
protected abstract val upgrades: IMatteryUpgrade?
|
||||||
|
|
||||||
var currentJob: JobType? = null
|
var currentJob: JobType? = null
|
||||||
@ -212,7 +326,17 @@ abstract class MachineJobEventLoop<JobType : IMachineJob> : INBTSerializable<Com
|
|||||||
override fun serializeNBT(): CompoundTag {
|
override fun serializeNBT(): CompoundTag {
|
||||||
return CompoundTag().also { nbt ->
|
return CompoundTag().also { nbt ->
|
||||||
nbt["WorkTicks"] = workTicks
|
nbt["WorkTicks"] = workTicks
|
||||||
currentJob?.let { nbt["Job"] = it.serializeNBT() }
|
|
||||||
|
currentJob?.let {
|
||||||
|
codec.encode(it, NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).get().map(
|
||||||
|
{
|
||||||
|
nbt["Job"] = it
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LOGGER.error("Failed to serialize job data, it will not persist", RuntimeException(it.message()))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,27 +344,36 @@ abstract class MachineJobEventLoop<JobType : IMachineJob> : INBTSerializable<Com
|
|||||||
nbt ?: return
|
nbt ?: return
|
||||||
|
|
||||||
workTicks = nbt.getDouble("WorkTicks")
|
workTicks = nbt.getDouble("WorkTicks")
|
||||||
currentJob = nbt.map("Job", ::deserializeJob)
|
currentJob = null
|
||||||
|
|
||||||
|
if ("Job" in nbt) {
|
||||||
|
codec.decode(NbtOps.INSTANCE, nbt["Job"]!!).get().map(
|
||||||
|
{
|
||||||
|
currentJob = it.first
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LOGGER.error("Failed to deserialize job data from storage", RuntimeException(it.message()))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (currentJob == null)
|
if (currentJob == null)
|
||||||
workTicks = 0.0
|
workTicks = 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun jobUpdated(new: JobType?, old: JobType?)
|
protected open fun jobUpdated(new: JobType?, old: JobType?) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called whenever reaching desired amount of ticks at job
|
* Called whenever reaching desired amount of ticks at job
|
||||||
*/
|
*/
|
||||||
protected abstract fun onJobFinish(job: JobType): JobStatus
|
protected abstract fun onJobFinish(status: JobStatus<JobType>)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when there is nothing to do and we are not idling
|
* Called when there is nothing to do and we are not idling
|
||||||
*/
|
*/
|
||||||
protected abstract fun computeNextJob(): JobContainer<JobType>
|
protected abstract fun computeNextJob(): JobContainer<JobType>
|
||||||
|
|
||||||
protected open fun onWorkTick(requiredPower: Decimal, extractedPower: Decimal, ticksAdvanced: Double, job: JobType): JobStatus {
|
protected open fun onJobTick(status: JobStatus<JobType>) {}
|
||||||
return JobStatus.SUCCESS
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Advances job loop by specified [ticks]. If machine is speed up by upgrades,
|
* Advances job loop by specified [ticks]. If machine is speed up by upgrades,
|
||||||
@ -317,8 +450,11 @@ abstract class MachineJobEventLoop<JobType : IMachineJob> : INBTSerializable<Com
|
|||||||
if (requiredPower.isPositive) {
|
if (requiredPower.isPositive) {
|
||||||
extractedPower = energy!!.extractEnergy(requiredPower, true)
|
extractedPower = energy!!.extractEnergy(requiredPower, true)
|
||||||
ticksAdvanced = (extractedPower / requiredPower).toDouble().coerceIn(0.0, 1.0) * ticksLeft
|
ticksAdvanced = (extractedPower / requiredPower).toDouble().coerceIn(0.0, 1.0) * ticksLeft
|
||||||
} else {
|
} else if (requiredPower.isZero) {
|
||||||
ticksAdvanced = ticksLeft
|
ticksAdvanced = ticksLeft
|
||||||
|
} else {
|
||||||
|
extractedPower = -energy!!.receiveEnergy(-requiredPower, true)
|
||||||
|
ticksAdvanced = (extractedPower / requiredPower).toDouble().coerceIn(0.0, 1.0) * ticksLeft
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,7 +462,8 @@ abstract class MachineJobEventLoop<JobType : IMachineJob> : INBTSerializable<Com
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
val status = onWorkTick(requiredPower ?: Decimal.ZERO, extractedPower ?: Decimal.ZERO, ticksAdvanced, currentJob)
|
val status = JobStatus(requiredPower ?: Decimal.ZERO, extractedPower ?: Decimal.ZERO, ticksAdvanced, currentJob, workTicks)
|
||||||
|
onJobTick(status)
|
||||||
|
|
||||||
if (!status.success) {
|
if (!status.success) {
|
||||||
throttleTicks += status.throttleTicks
|
throttleTicks += status.throttleTicks
|
||||||
@ -336,25 +473,31 @@ abstract class MachineJobEventLoop<JobType : IMachineJob> : INBTSerializable<Com
|
|||||||
isIdling = true
|
isIdling = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
} else if (status.requiredPower.isPositive && energy == null) {
|
||||||
|
idleReason = IdleReason.POWER
|
||||||
|
isIdling = true
|
||||||
|
idleTicksAnim++
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
workingTicksAnim++
|
workingTicksAnim++
|
||||||
errorTicksAnim = 0
|
errorTicksAnim = 0
|
||||||
|
|
||||||
workTicks += ticksAdvanced
|
workTicks += status.ticksAdvanced
|
||||||
availableTicks -= ticksAdvanced
|
availableTicks -= status.ticksAdvanced
|
||||||
|
|
||||||
extractedPower = status.newDrainedPower ?: extractedPower
|
if (energy != null && status.requiredPower.isPositive) {
|
||||||
|
energy.extractEnergy(status.requiredPower, false)
|
||||||
if (extractedPower != null) {
|
} else if (energy != null && status.requiredPower.isNegative) {
|
||||||
energy!!.extractEnergy(extractedPower, false)
|
energy.receiveEnergy(-status.requiredPower, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
val status = onJobFinish(currentJob)
|
val status = JobStatus(currentJob, workTicks)
|
||||||
|
onJobFinish(status)
|
||||||
|
|
||||||
if (status.success) {
|
if (status.success) {
|
||||||
this.currentJob = null
|
this.currentJob = null
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package ru.dbotthepony.mc.otm.block.entity
|
package ru.dbotthepony.mc.otm.block.entity
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList
|
import com.google.common.collect.ImmutableList
|
||||||
|
import com.mojang.serialization.Codec
|
||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.nbt.ListTag
|
import net.minecraft.nbt.ListTag
|
||||||
@ -11,12 +12,12 @@ import net.minecraft.world.level.BlockGetter
|
|||||||
import net.minecraft.world.level.block.Block
|
import net.minecraft.world.level.block.Block
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||||
import net.minecraft.world.level.block.state.BlockState
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
|
import org.apache.logging.log4j.LogManager
|
||||||
import ru.dbotthepony.mc.otm.capability.IMatteryUpgrade
|
import ru.dbotthepony.mc.otm.capability.IMatteryUpgrade
|
||||||
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
|
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
|
||||||
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
|
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
|
||||||
import ru.dbotthepony.mc.otm.capability.matteryEnergy
|
import ru.dbotthepony.mc.otm.capability.matteryEnergy
|
||||||
import ru.dbotthepony.mc.otm.core.immutableList
|
import ru.dbotthepony.mc.otm.core.immutableList
|
||||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.getCompoundList
|
import ru.dbotthepony.mc.otm.core.nbt.getCompoundList
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||||
|
|
||||||
@ -25,15 +26,15 @@ import ru.dbotthepony.mc.otm.core.nbt.set
|
|||||||
*
|
*
|
||||||
* From technical point, this is a specialized use case of [MachineJobEventLoop].
|
* From technical point, this is a specialized use case of [MachineJobEventLoop].
|
||||||
*/
|
*/
|
||||||
abstract class MatteryWorkerBlockEntity<JobType : IMachineJob>(
|
abstract class MatteryWorkerBlockEntity<JobType : IJob>(
|
||||||
type: BlockEntityType<*>,
|
type: BlockEntityType<*>,
|
||||||
blockPos: BlockPos,
|
blockPos: BlockPos,
|
||||||
blockState: BlockState,
|
blockState: BlockState,
|
||||||
val jobDeserializer: (tag: CompoundTag) -> JobType?,
|
jobCodec: Codec<JobType>,
|
||||||
maxJobs: Int = 1,
|
maxJobs: Int = 1,
|
||||||
) : MatteryPoweredBlockEntity(type, blockPos, blockState) {
|
) : MatteryPoweredBlockEntity(type, blockPos, blockState) {
|
||||||
val jobEventLoops: ImmutableList<MachineJobEventLoop<JobType>> = immutableList(maxJobs) { id ->
|
val jobEventLoops: ImmutableList<MachineJobEventLoop<JobType>> = immutableList(maxJobs) { id ->
|
||||||
object : MachineJobEventLoop<JobType>() {
|
object : MachineJobEventLoop<JobType>(jobCodec) {
|
||||||
override val energy: IMatteryEnergyStorage?
|
override val energy: IMatteryEnergyStorage?
|
||||||
get() = matteryEnergy
|
get() = matteryEnergy
|
||||||
override val isBlockedByRedstone: Boolean
|
override val isBlockedByRedstone: Boolean
|
||||||
@ -41,12 +42,8 @@ abstract class MatteryWorkerBlockEntity<JobType : IMachineJob>(
|
|||||||
override val upgrades: IMatteryUpgrade?
|
override val upgrades: IMatteryUpgrade?
|
||||||
get() = this@MatteryWorkerBlockEntity.upgrades
|
get() = this@MatteryWorkerBlockEntity.upgrades
|
||||||
|
|
||||||
override fun deserializeJob(nbt: CompoundTag): JobType? {
|
override fun onJobFinish(status: JobStatus<JobType>) {
|
||||||
return jobDeserializer.invoke(nbt)
|
return this@MatteryWorkerBlockEntity.onJobFinish(status, id)
|
||||||
}
|
|
||||||
|
|
||||||
override fun onJobFinish(job: JobType): JobStatus {
|
|
||||||
return this@MatteryWorkerBlockEntity.onJobFinish(job, id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun computeNextJob(): JobContainer<JobType> {
|
override fun computeNextJob(): JobContainer<JobType> {
|
||||||
@ -57,8 +54,8 @@ abstract class MatteryWorkerBlockEntity<JobType : IMachineJob>(
|
|||||||
this@MatteryWorkerBlockEntity.jobUpdated(new, old, id)
|
this@MatteryWorkerBlockEntity.jobUpdated(new, old, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onWorkTick(requiredPower: Decimal, extractedPower: Decimal, ticksAdvanced: Double, job: JobType): JobStatus {
|
override fun onJobTick(status: JobStatus<JobType>) {
|
||||||
return this@MatteryWorkerBlockEntity.onWorkTick(requiredPower, extractedPower, ticksAdvanced, job, id)
|
return this@MatteryWorkerBlockEntity.onJobTick(status, id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,12 +69,10 @@ abstract class MatteryWorkerBlockEntity<JobType : IMachineJob>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected open fun jobUpdated(new: JobType?, old: JobType?, id: Int) {}
|
protected open fun jobUpdated(new: JobType?, old: JobType?, id: Int) {}
|
||||||
protected abstract fun onJobFinish(job: JobType, id: Int): JobStatus
|
protected abstract fun onJobFinish(status: JobStatus<JobType>, id: Int)
|
||||||
protected abstract fun computeNextJob(id: Int): JobContainer<JobType>
|
protected abstract fun computeNextJob(id: Int): JobContainer<JobType>
|
||||||
|
|
||||||
protected open fun onWorkTick(requiredPower: Decimal, extractedPower: Decimal, ticksAdvanced: Double, job: JobType, id: Int): JobStatus {
|
protected open fun onJobTick(status: JobStatus<JobType>, id: Int) {}
|
||||||
return JobStatus.SUCCESS
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun saveShared(nbt: CompoundTag) {
|
override fun saveShared(nbt: CompoundTag) {
|
||||||
super.saveShared(nbt)
|
super.saveShared(nbt)
|
||||||
@ -148,6 +143,8 @@ abstract class MatteryWorkerBlockEntity<JobType : IMachineJob>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private val LOGGER = LogManager.getLogger()
|
||||||
|
|
||||||
fun appendHoverText(itemStack: ItemStack, blockGetter: BlockGetter?, tooltips: MutableList<Component>, flag: TooltipFlag) {
|
fun appendHoverText(itemStack: ItemStack, blockGetter: BlockGetter?, tooltips: MutableList<Component>, flag: TooltipFlag) {
|
||||||
itemStack.tag ?: return
|
itemStack.tag ?: return
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package ru.dbotthepony.mc.otm.block.entity.matter
|
package ru.dbotthepony.mc.otm.block.entity.matter
|
||||||
|
|
||||||
|
import com.mojang.serialization.Codec
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
@ -11,7 +13,7 @@ import net.minecraft.world.level.block.state.BlockState
|
|||||||
import net.minecraftforge.common.ForgeConfigSpec
|
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.MachineJob
|
import ru.dbotthepony.mc.otm.block.entity.Job
|
||||||
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||||
@ -30,6 +32,8 @@ import ru.dbotthepony.mc.otm.core.math.getDecimal
|
|||||||
import ru.dbotthepony.mc.otm.core.math.set
|
import ru.dbotthepony.mc.otm.core.math.set
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||||
import ru.dbotthepony.mc.otm.core.util.WriteOnce
|
import ru.dbotthepony.mc.otm.core.util.WriteOnce
|
||||||
|
import ru.dbotthepony.mc.otm.data.DecimalCodec
|
||||||
|
import ru.dbotthepony.mc.otm.data.minRange
|
||||||
import ru.dbotthepony.mc.otm.graph.matter.MatterGraph
|
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.item.matter.MatterDustItem
|
import ru.dbotthepony.mc.otm.item.matter.MatterDustItem
|
||||||
@ -93,32 +97,23 @@ fun moveMatterAsDustIntoContainer(_matterValue: Decimal, container: MatteryConta
|
|||||||
}
|
}
|
||||||
|
|
||||||
class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
|
class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
|
||||||
: MatteryWorkerBlockEntity<MatterDecomposerBlockEntity.DecomposerJob>(MBlockEntities.MATTER_DECOMPOSER, pos, state, ::DecomposerJob) {
|
: MatteryWorkerBlockEntity<MatterDecomposerBlockEntity.DecomposerJob>(MBlockEntities.MATTER_DECOMPOSER, pos, state, DecomposerJob.CODEC) {
|
||||||
|
|
||||||
class DecomposerJob : MachineJob {
|
|
||||||
val toDust: Boolean
|
|
||||||
var matterValue: Decimal
|
|
||||||
|
|
||||||
constructor(tag: CompoundTag) : super(tag) {
|
|
||||||
toDust = tag.getBoolean(TO_DUST_KEY)
|
|
||||||
matterValue = tag.getDecimal(MATTER_VALUE_KEY)
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(toDust: Boolean, matterValue: Decimal, ticks: Double) : super(ticks, BASE_CONSUMPTION) {
|
|
||||||
this.toDust = toDust
|
|
||||||
this.matterValue = matterValue
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun serializeNBT(): CompoundTag {
|
|
||||||
return super.serializeNBT().also {
|
|
||||||
it[TO_DUST_KEY] = toDust
|
|
||||||
it[MATTER_VALUE_KEY] = matterValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
class DecomposerJob(
|
||||||
|
val toDust: Boolean,
|
||||||
|
var matterValue: Decimal,
|
||||||
|
ticks: Double,
|
||||||
|
) : Job(ticks, BASE_CONSUMPTION) {
|
||||||
companion object {
|
companion object {
|
||||||
const val TO_DUST_KEY = "toDust"
|
val CODEC: Codec<DecomposerJob> by lazy {
|
||||||
const val MATTER_VALUE_KEY = "matterValue"
|
RecordCodecBuilder.create {
|
||||||
|
it.group(
|
||||||
|
Codec.BOOL.fieldOf("toDust").forGetter(DecomposerJob::toDust),
|
||||||
|
DecimalCodec.minRange(Decimal.ZERO).fieldOf("matterValue").forGetter(DecomposerJob::matterValue),
|
||||||
|
Codec.DOUBLE.minRange(0.0).fieldOf("ticks").forGetter(DecomposerJob::ticks)
|
||||||
|
).apply(it, ::DecomposerJob)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,22 +160,18 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
|
|||||||
return MatterDecomposerMenu(containerID, inventory, this)
|
return MatterDecomposerMenu(containerID, inventory, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onJobFinish(job: DecomposerJob, id: Int): JobStatus {
|
override fun onJobFinish(status: JobStatus<DecomposerJob>, id: Int) {
|
||||||
if (job.toDust) {
|
if (status.job.toDust) {
|
||||||
job.matterValue = moveMatterAsDustIntoContainer(job.matterValue, outputContainer, 0, 1)
|
status.job.matterValue = moveMatterAsDustIntoContainer(status.job.matterValue, outputContainer, 0, 1)
|
||||||
|
|
||||||
if (!job.matterValue.isZero)
|
if (!status.job.matterValue.isZero)
|
||||||
return JobStatus.FAILURE_WAIT_FAST
|
status.throttleFast()
|
||||||
|
} else {
|
||||||
|
status.job.matterValue -= matter.receiveMatter(status.job.matterValue, false)
|
||||||
|
|
||||||
return JobStatus.SUCCESS
|
if (status.job.matterValue.isPositive)
|
||||||
|
status.noMatter()
|
||||||
}
|
}
|
||||||
|
|
||||||
job.matterValue -= matter.receiveMatter(job.matterValue, false)
|
|
||||||
|
|
||||||
if (job.matterValue.isPositive)
|
|
||||||
return JobStatus.FAILURE_MATTER
|
|
||||||
|
|
||||||
return JobStatus.SUCCESS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun computeNextJob(id: Int): JobContainer<DecomposerJob> {
|
override fun computeNextJob(id: Int): JobContainer<DecomposerJob> {
|
||||||
|
@ -9,8 +9,6 @@ import net.minecraft.world.entity.player.Inventory
|
|||||||
import net.minecraft.world.entity.player.Player
|
import net.minecraft.world.entity.player.Player
|
||||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||||
import java.util.HashMap
|
|
||||||
import java.util.UUID
|
|
||||||
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.server.level.ServerLevel
|
||||||
@ -29,7 +27,7 @@ import ru.dbotthepony.mc.otm.graph.matter.MatterGraph
|
|||||||
import ru.dbotthepony.mc.otm.graph.matter.MatterNode
|
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.ArrayList
|
import java.util.*
|
||||||
import java.util.stream.Stream
|
import java.util.stream.Stream
|
||||||
|
|
||||||
class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||||
@ -100,7 +98,7 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
|||||||
|
|
||||||
for ((key, task) in _tasks) {
|
for ((key, task) in _tasks) {
|
||||||
if (task.required > 0) {
|
if (task.required > 0) {
|
||||||
val pattern = task.patternId?.let(graph::getPattern) ?: continue
|
val pattern = task.patternId.map(graph::getPattern).orElse(null) ?: continue
|
||||||
|
|
||||||
if (!simulate) {
|
if (!simulate) {
|
||||||
val new = task.allocate()
|
val new = task.allocate()
|
||||||
@ -198,7 +196,7 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun addTask(state: IPatternState, count: Int): IReplicationTask<*> {
|
fun addTask(state: IPatternState, count: Int): IReplicationTask<*> {
|
||||||
val task = ReplicationTask(UUID.randomUUID(), 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
|
||||||
|
|
||||||
matterNode.graph.onMatterTaskCreated(task)
|
matterNode.graph.onMatterTaskCreated(task)
|
||||||
|
@ -1,22 +1,19 @@
|
|||||||
package ru.dbotthepony.mc.otm.block.entity.matter
|
package ru.dbotthepony.mc.otm.block.entity.matter
|
||||||
|
|
||||||
|
import com.mojang.serialization.Codec
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.nbt.CompoundTag
|
|
||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import net.minecraft.world.entity.player.Player
|
import net.minecraft.world.entity.player.Player
|
||||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
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 net.minecraftforge.common.ForgeConfigSpec.ConfigValue
|
|
||||||
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.MachineJob
|
import ru.dbotthepony.mc.otm.block.entity.Job
|
||||||
import ru.dbotthepony.mc.otm.config.ConciseBalanceValues
|
|
||||||
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||||
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.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
|
||||||
@ -30,40 +27,20 @@ import ru.dbotthepony.mc.otm.graph.matter.MatterGraph
|
|||||||
import ru.dbotthepony.mc.otm.item.matter.MatterDustItem
|
import ru.dbotthepony.mc.otm.item.matter.MatterDustItem
|
||||||
import ru.dbotthepony.mc.otm.menu.matter.MatterRecyclerMenu
|
import ru.dbotthepony.mc.otm.menu.matter.MatterRecyclerMenu
|
||||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||||
import ru.dbotthepony.mc.otm.core.math.DecimalConfigValue
|
import ru.dbotthepony.mc.otm.data.DecimalCodec
|
||||||
import ru.dbotthepony.mc.otm.core.math.defineDecimal
|
import ru.dbotthepony.mc.otm.data.minRange
|
||||||
import ru.dbotthepony.mc.otm.registry.MNames
|
|
||||||
import ru.dbotthepony.mc.otm.core.util.WriteOnce
|
|
||||||
import ru.dbotthepony.mc.otm.core.math.getDecimal
|
|
||||||
import ru.dbotthepony.mc.otm.core.math.set
|
|
||||||
import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode
|
import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode
|
||||||
|
|
||||||
class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
||||||
: MatteryWorkerBlockEntity<MatterRecyclerBlockEntity.RecyclerJob>(MBlockEntities.MATTER_RECYCLER, blockPos, blockState, ::RecyclerJob) {
|
: MatteryWorkerBlockEntity<MatterRecyclerBlockEntity.RecyclerJob>(MBlockEntities.MATTER_RECYCLER, blockPos, blockState, RecyclerJob.CODEC) {
|
||||||
|
|
||||||
class RecyclerJob : MachineJob {
|
|
||||||
var totalMatter: Decimal
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
ticks: Double,
|
|
||||||
powerUsage: Decimal,
|
|
||||||
totalMatter: Decimal
|
|
||||||
) : super(ticks, powerUsage) {
|
|
||||||
this.totalMatter = totalMatter
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(tag: CompoundTag) : super(tag) {
|
|
||||||
this.totalMatter = tag.getDecimal(KEY)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun serializeNBT(): CompoundTag {
|
|
||||||
return super.serializeNBT().also {
|
|
||||||
it[KEY] = totalMatter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
class RecyclerJob(ticks: Double, powerUsage: Decimal, var totalMatter: Decimal) : Job(ticks, powerUsage) {
|
||||||
companion object {
|
companion object {
|
||||||
const val KEY = "totalMatter"
|
val CODEC: Codec<RecyclerJob> by lazy {
|
||||||
|
RecordCodecBuilder.create {
|
||||||
|
plainCodec(it).and(DecimalCodec.minRange(Decimal.ZERO).fieldOf("totalMatter").forGetter(RecyclerJob::totalMatter)).apply(it, ::RecyclerJob)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,18 +85,18 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
|||||||
return MatterRecyclerMenu(containerID, inventory, this)
|
return MatterRecyclerMenu(containerID, inventory, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onJobFinish(job: RecyclerJob, id: Int): JobStatus {
|
override fun onJobFinish(status: JobStatus<RecyclerJob>, id: Int) {
|
||||||
|
val job = status.job
|
||||||
|
|
||||||
if (job.totalMatter.isPositive) {
|
if (job.totalMatter.isPositive) {
|
||||||
val received = matter.receiveMatter(job.totalMatter, true)
|
val received = matter.receiveMatter(job.totalMatter, true)
|
||||||
|
|
||||||
if (job.totalMatter != received)
|
if (job.totalMatter != received)
|
||||||
return JobStatus.FAILURE_MATTER
|
return status.noMatter()
|
||||||
|
|
||||||
matter.receiveMatter(job.totalMatter, false)
|
matter.receiveMatter(job.totalMatter, false)
|
||||||
job.totalMatter -= received
|
job.totalMatter -= received
|
||||||
}
|
}
|
||||||
|
|
||||||
return JobStatus.SUCCESS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun computeNextJob(id: Int): JobContainer<RecyclerJob> {
|
override fun computeNextJob(id: Int): JobContainer<RecyclerJob> {
|
||||||
@ -147,20 +124,16 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onWorkTick(requiredPower: Decimal, extractedPower: Decimal, ticksAdvanced: Double, job: RecyclerJob, id: Int): JobStatus {
|
override fun onJobTick(status: JobStatus<RecyclerJob>, id: Int) {
|
||||||
val receive = job.totalMatter.coerceAtMost(MachinesConfig.MATTER_RECYCLER_MATTER_PER_TICK.get() * ticksAdvanced)
|
val job = status.job
|
||||||
|
val toReceive = job.totalMatter.coerceAtMost(MachinesConfig.MATTER_RECYCLER_MATTER_PER_TICK.get() * status.ticksAdvanced)
|
||||||
|
|
||||||
if (receive.isZero)
|
if (toReceive.isZero)
|
||||||
return JobStatus.SUCCESS
|
return status.success()
|
||||||
|
|
||||||
val received = matter.receiveMatter(receive, true)
|
val received = matter.receiveMatter(toReceive, false)
|
||||||
|
status.scale(received / toReceive)
|
||||||
if (receive != received)
|
|
||||||
return JobStatus.FAILURE_MATTER
|
|
||||||
|
|
||||||
matter.receiveMatter(receive, false)
|
|
||||||
job.totalMatter -= received
|
job.totalMatter -= received
|
||||||
return JobStatus.SUCCESS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun tick() {
|
override fun tick() {
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
package ru.dbotthepony.mc.otm.block.entity.matter
|
package ru.dbotthepony.mc.otm.block.entity.matter
|
||||||
|
|
||||||
|
import com.mojang.serialization.Codec
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.nbt.CompoundTag
|
|
||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import net.minecraft.world.entity.player.Player
|
import net.minecraft.world.entity.player.Player
|
||||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||||
@ -11,7 +12,7 @@ import net.minecraft.world.level.block.state.BlockState
|
|||||||
import net.minecraftforge.common.ForgeConfigSpec
|
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.MachineItemJob
|
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.block.entity.MatteryWorkerBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||||
@ -28,76 +29,43 @@ import ru.dbotthepony.mc.otm.container.UpgradeContainer
|
|||||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
import ru.dbotthepony.mc.otm.core.math.DecimalConfigValue
|
import ru.dbotthepony.mc.otm.core.math.DecimalConfigValue
|
||||||
import ru.dbotthepony.mc.otm.core.math.defineDecimal
|
import ru.dbotthepony.mc.otm.core.math.defineDecimal
|
||||||
import ru.dbotthepony.mc.otm.core.math.getDecimal
|
|
||||||
import ru.dbotthepony.mc.otm.core.math.set
|
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.map
|
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
|
||||||
import ru.dbotthepony.mc.otm.core.util.WriteOnce
|
import ru.dbotthepony.mc.otm.core.util.WriteOnce
|
||||||
|
import ru.dbotthepony.mc.otm.data.DecimalCodec
|
||||||
|
import ru.dbotthepony.mc.otm.data.UUIDCodec
|
||||||
|
import ru.dbotthepony.mc.otm.data.minRange
|
||||||
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 ru.dbotthepony.mc.otm.menu.matter.MatterReplicatorMenu
|
import ru.dbotthepony.mc.otm.menu.matter.MatterReplicatorMenu
|
||||||
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.registry.MNames
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||||
MatteryWorkerBlockEntity<MatterReplicatorBlockEntity.ReplicatorJob>(MBlockEntities.MATTER_REPLICATOR, p_155229_, p_155230_, {
|
MatteryWorkerBlockEntity<MatterReplicatorBlockEntity.ReplicatorJob>(MBlockEntities.MATTER_REPLICATOR, p_155229_, p_155230_, ReplicatorJob.CODEC) {
|
||||||
try {
|
|
||||||
ReplicatorJob(it)
|
|
||||||
} catch(err: NoSuchElementException) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
|
|
||||||
class ReplicatorJob : MachineItemJob {
|
class ReplicatorJob(
|
||||||
val matterPerTick: Decimal
|
|
||||||
val task: ReplicationTask
|
|
||||||
var matterValue: Decimal
|
|
||||||
val pattern: PatternState?
|
|
||||||
val asDust: Boolean
|
|
||||||
|
|
||||||
constructor(tag: CompoundTag) : super(tag) {
|
|
||||||
matterPerTick = tag.getDecimal(MATTER_PER_TICK_KEY)
|
|
||||||
matterValue = tag.getDecimal(MATTER_VALUE_KEY)
|
|
||||||
pattern = tag.map(PATTERN_KEY, PatternState::deserializeNBT)
|
|
||||||
asDust = tag.getBoolean(AS_DUST_KEY)
|
|
||||||
task = tag.map(TASK_KEY, ReplicationTask::deserializeNBT) ?: throw NoSuchElementException("Unable to deserialize matter task")
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
itemStack: ItemStack,
|
itemStack: ItemStack,
|
||||||
matterPerTick: Decimal,
|
val matterPerTick: Decimal,
|
||||||
task: ReplicationTask,
|
val task: UUID,
|
||||||
matterValue: Decimal,
|
var matterValue: Decimal,
|
||||||
pattern: PatternState?,
|
val pattern: Optional<PatternState>,
|
||||||
asDust: Boolean,
|
val asDust: Boolean,
|
||||||
ticks: Double,
|
ticks: Double,
|
||||||
) : super(itemStack, ticks, BASE_CONSUMPTION) {
|
) : ItemJob(itemStack, ticks, BASE_CONSUMPTION) {
|
||||||
this.matterPerTick = matterPerTick
|
|
||||||
this.task = task
|
|
||||||
this.matterValue = matterValue
|
|
||||||
this.pattern = pattern
|
|
||||||
this.asDust = asDust
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun serializeNBT(): CompoundTag {
|
|
||||||
return super.serializeNBT().also {
|
|
||||||
it[MATTER_PER_TICK_KEY] = this.matterPerTick
|
|
||||||
it[TASK_KEY] = this.task.serializeNBT()
|
|
||||||
it[MATTER_VALUE_KEY] = this.matterValue
|
|
||||||
|
|
||||||
if (this.pattern != null)
|
|
||||||
it[PATTERN_KEY] = this.pattern.serializeNBT()
|
|
||||||
|
|
||||||
it[AS_DUST_KEY] = this.asDust
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val MATTER_PER_TICK_KEY = "matterPerTick"
|
val CODEC: Codec<ReplicatorJob> by lazy {
|
||||||
const val MATTER_VALUE_KEY = "matterValue"
|
RecordCodecBuilder.create {
|
||||||
const val PATTERN_KEY = "pattern"
|
it.group(
|
||||||
const val AS_DUST_KEY = "asDust"
|
ItemStack.CODEC.fieldOf("itemStack").forGetter(ReplicatorJob::itemStack),
|
||||||
const val TASK_KEY = "task"
|
DecimalCodec.minRange(Decimal.ZERO).fieldOf("matterPerTick").forGetter(ReplicatorJob::matterPerTick),
|
||||||
|
UUIDCodec.fieldOf("task").forGetter(ReplicatorJob::task),
|
||||||
|
DecimalCodec.minRange(Decimal.ZERO).fieldOf("matterValue").forGetter(ReplicatorJob::matterValue),
|
||||||
|
PatternState.CODEC.optionalFieldOf("pattern").forGetter(ReplicatorJob::pattern),
|
||||||
|
Codec.BOOL.fieldOf("asDust").forGetter(ReplicatorJob::asDust),
|
||||||
|
Codec.doubleRange(0.0, Double.MAX_VALUE).fieldOf("ticks").forGetter(ReplicatorJob::ticks),
|
||||||
|
).apply(it, ::ReplicatorJob)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,24 +109,24 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
|||||||
return MatterReplicatorMenu(containerID, inventory, this)
|
return MatterReplicatorMenu(containerID, inventory, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onJobFinish(job: ReplicatorJob, id: Int): JobStatus {
|
override fun onJobFinish(status: JobStatus<ReplicatorJob>, id: Int) {
|
||||||
|
val job = status.job
|
||||||
|
|
||||||
if (job.asDust) {
|
if (job.asDust) {
|
||||||
job.matterValue = moveMatterAsDustIntoContainer(job.matterValue, container, OUTPUT_DUST_MAIN, OUTPUT_DUST_STACKING)
|
job.matterValue = moveMatterAsDustIntoContainer(job.matterValue, container, OUTPUT_DUST_MAIN, OUTPUT_DUST_STACKING)
|
||||||
|
|
||||||
if (!job.matterValue.isZero) {
|
if (!job.matterValue.isZero) {
|
||||||
return JobStatus.FAILURE_WAIT
|
return status.throttle()
|
||||||
}
|
|
||||||
|
|
||||||
matterNode.graph.notifyTaskCompletion(job.task.id)
|
|
||||||
return JobStatus.SUCCESS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
matterNode.graph.notifyTaskCompletion(job.task)
|
||||||
|
} else {
|
||||||
if (!container.fullyAddItem(job.itemStack, FIRST_ACTUAL_OUTPUT_SLOT .. LAST_ACTUAL_OUTPUT_SLOT)) {
|
if (!container.fullyAddItem(job.itemStack, FIRST_ACTUAL_OUTPUT_SLOT .. LAST_ACTUAL_OUTPUT_SLOT)) {
|
||||||
return JobStatus.FAILURE_ITEM
|
return status.noItem()
|
||||||
}
|
}
|
||||||
|
|
||||||
matterNode.graph.notifyTaskCompletion(job.task.id)
|
matterNode.graph.notifyTaskCompletion(job.task)
|
||||||
return JobStatus.SUCCESS
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setRemoved() {
|
override fun setRemoved() {
|
||||||
@ -211,64 +179,29 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
|||||||
return JobContainer.success(ReplicatorJob(
|
return JobContainer.success(ReplicatorJob(
|
||||||
itemStack = stack,
|
itemStack = stack,
|
||||||
matterPerTick = matter.matter / ticks,
|
matterPerTick = matter.matter / ticks,
|
||||||
task = allocation.task.asImmutable(),
|
task = allocation.task.id,
|
||||||
matterValue = matter.matter,
|
matterValue = matter.matter,
|
||||||
pattern = allocation.pattern?.asImmutable(),
|
pattern = Optional.ofNullable(allocation.pattern?.asImmutable()),
|
||||||
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,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onWorkTick(requiredPower: Decimal, extractedPower: Decimal, ticksAdvanced: Double, job: ReplicatorJob, id: Int): JobStatus {
|
override fun onJobTick(status: JobStatus<ReplicatorJob>, id: Int) {
|
||||||
val drainPerTick = job.matterPerTick * ticksAdvanced
|
val job = status.job
|
||||||
|
val drainPerTick = job.matterPerTick * status.ticksAdvanced
|
||||||
|
|
||||||
if (matter.extractMatter(drainPerTick, true) < drainPerTick) {
|
if (matter.extractMatter(drainPerTick, true) < drainPerTick) {
|
||||||
// в машине недостаточно материи
|
val toDrain = (drainPerTick * DRAIN_MULT)
|
||||||
|
.coerceAtMost(job.matterPerTick * (status.ticks - status.workTicks + status.ticksAdvanced))
|
||||||
if (drainPerTick > matter.maxStoredMatter) {
|
|
||||||
// в тик требуется больше материи, чем её может хранить репликатор
|
|
||||||
val toExtract = drainPerTick - matter.extractMatter(drainPerTick, true)
|
|
||||||
val drain = matterNode.graph.extractMatter(toExtract, true)
|
|
||||||
|
|
||||||
if (drain != toExtract) {
|
|
||||||
// недостаточно материи в сети
|
|
||||||
return JobStatus.FAILURE_MATTER
|
|
||||||
}
|
|
||||||
|
|
||||||
// достаточно материи в сети + внутри машины
|
|
||||||
matter.extractMatter(drainPerTick, false)
|
|
||||||
matterNode.graph.extractMatter(drain, false)
|
|
||||||
return JobStatus.SUCCESS
|
|
||||||
} else {
|
|
||||||
// в тик требуется меньше материи, чем её может хранить репликатор
|
|
||||||
// примем из сети недостающее количество бака материи, или 200 тиков репликации, что меньше
|
|
||||||
val drain = matterNode.graph.extractMatter((drainPerTick * DRAIN_MULT)
|
|
||||||
.coerceAtMost(job.matterPerTick * (job.ticks - jobEventLoops[0].workTicks - ticksAdvanced))
|
|
||||||
.coerceAtLeast(Decimal.ONE)
|
.coerceAtLeast(Decimal.ONE)
|
||||||
.coerceAtMost(matter.missingMatter), false)
|
.coerceAtMost(matter.missingMatter)
|
||||||
|
|
||||||
if (drain.isZero) {
|
matter.receiveMatter(matterNode.graph.extractMatter(toDrain, false), false)
|
||||||
// в сети нет материи
|
|
||||||
return JobStatus.FAILURE_MATTER
|
|
||||||
}
|
}
|
||||||
|
|
||||||
matter.receiveMatter(drain, false)
|
status.scale(matter.extractMatter(drainPerTick, false) / drainPerTick)
|
||||||
|
visualProgress = status.workProgress
|
||||||
// получили материю, проверяем возможность работы
|
|
||||||
if (matter.extractMatter(drainPerTick, true) >= drainPerTick) {
|
|
||||||
matter.extractMatter(drainPerTick, false)
|
|
||||||
return JobStatus.SUCCESS
|
|
||||||
} else {
|
|
||||||
// :(
|
|
||||||
return JobStatus.FAILURE_WAIT
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// в машине достаточно материи
|
|
||||||
matter.extractMatter(drainPerTick, false)
|
|
||||||
visualProgress = jobEventLoops[0].workProgress
|
|
||||||
return JobStatus.SUCCESS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -10,7 +10,7 @@ import net.minecraft.world.level.block.state.BlockState
|
|||||||
import net.minecraftforge.common.ForgeConfigSpec
|
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.MachineItemJob
|
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.ConciseBalanceValues
|
import ru.dbotthepony.mc.otm.config.ConciseBalanceValues
|
||||||
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
|
||||||
@ -35,7 +35,7 @@ import java.util.*
|
|||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
|
||||||
class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||||
MatteryWorkerBlockEntity<MachineItemJob>(MBlockEntities.MATTER_SCANNER, p_155229_, p_155230_, ::MachineItemJob) {
|
MatteryWorkerBlockEntity<ItemJob>(MBlockEntities.MATTER_SCANNER, p_155229_, p_155230_, ItemJob.CODEC) {
|
||||||
|
|
||||||
val container = MatteryContainer(::itemContainerUpdated, 1).also(::addDroppableContainer)
|
val container = MatteryContainer(::itemContainerUpdated, 1).also(::addDroppableContainer)
|
||||||
val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::energyLevelUpdated, ENERGY_VALUES))
|
val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::energyLevelUpdated, ENERGY_VALUES))
|
||||||
@ -87,9 +87,9 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
|||||||
return MatterScannerMenu(containerID, inventory, this)
|
return MatterScannerMenu(containerID, inventory, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onJobFinish(job: MachineItemJob, id: Int): JobStatus {
|
override fun onJobFinish(status: JobStatus<ItemJob>, id: Int) {
|
||||||
val stack = job.itemStack
|
val stack = status.job.itemStack
|
||||||
if (stack.isEmpty || !MatterManager.hasMatterValue(stack)) return JobStatus.SUCCESS
|
if (stack.isEmpty || !MatterManager.hasMatterValue(stack)) return status.success()
|
||||||
|
|
||||||
var findState: IPatternState? = null
|
var findState: IPatternState? = null
|
||||||
|
|
||||||
@ -110,14 +110,12 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
|||||||
PatternState(UUID.randomUUID(), stack.item, researchAdvance)
|
PatternState(UUID.randomUUID(), stack.item, researchAdvance)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!matterNode.graph.insertPattern(new, onlyUpdate = false, simulate = false).isFailed) {
|
if (matterNode.graph.insertPattern(new, onlyUpdate = false, simulate = false).isFailed) {
|
||||||
return JobStatus.SUCCESS
|
status.throttle()
|
||||||
} else {
|
|
||||||
return JobStatus.FAILURE_WAIT
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun computeNextJob(id: Int): JobContainer<MachineItemJob> {
|
override fun computeNextJob(id: Int): JobContainer<ItemJob> {
|
||||||
if (energy.batteryLevel.isZero) {
|
if (energy.batteryLevel.isZero) {
|
||||||
return JobContainer.noEnergy()
|
return JobContainer.noEnergy()
|
||||||
}
|
}
|
||||||
@ -151,7 +149,7 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
|||||||
stack.shrink(1)
|
stack.shrink(1)
|
||||||
container.setChanged()
|
container.setChanged()
|
||||||
val complexity = MatterManager.get(copy).complexity
|
val complexity = MatterManager.get(copy).complexity
|
||||||
return JobContainer.success(MachineItemJob(copy, (if (complexity > 1.0) complexity.pow(1.25) else complexity.pow(0.5)), BASE_CONSUMPTION))
|
return JobContainer.success(ItemJob(copy, (if (complexity > 1.0) complexity.pow(1.25) else complexity.pow(0.5)), BASE_CONSUMPTION))
|
||||||
}
|
}
|
||||||
|
|
||||||
return JobContainer.noItem()
|
return JobContainer.noItem()
|
||||||
@ -163,7 +161,7 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun jobUpdated(new: MachineItemJob?, old: MachineItemJob?, id: Int) {
|
override fun jobUpdated(new: ItemJob?, old: ItemJob?, id: Int) {
|
||||||
visualItemStack = new?.itemStack ?: ItemStack.EMPTY
|
visualItemStack = new?.itemStack ?: ItemStack.EMPTY
|
||||||
visualProgress = 0f
|
visualProgress = 0f
|
||||||
}
|
}
|
||||||
@ -174,14 +172,11 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
|||||||
var visualProgress by synchronizer.float().property
|
var visualProgress by synchronizer.float().property
|
||||||
private set
|
private set
|
||||||
|
|
||||||
override fun onWorkTick(
|
override fun onJobTick(
|
||||||
requiredPower: Decimal,
|
status: JobStatus<ItemJob>,
|
||||||
extractedPower: Decimal,
|
|
||||||
ticksAdvanced: Double,
|
|
||||||
job: MachineItemJob,
|
|
||||||
id: Int
|
id: Int
|
||||||
): JobStatus {
|
) {
|
||||||
val result = super.onWorkTick(requiredPower, extractedPower, ticksAdvanced, job, id)
|
val result = super.onJobTick(status, id)
|
||||||
|
|
||||||
visualProgress = jobEventLoops[0].workProgress
|
visualProgress = jobEventLoops[0].workProgress
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import net.minecraft.world.inventory.AbstractContainerMenu
|
|||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
import net.minecraft.world.item.Items
|
import net.minecraft.world.item.Items
|
||||||
import net.minecraft.world.level.block.state.BlockState
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
import ru.dbotthepony.mc.otm.block.entity.MachineItemJob
|
import ru.dbotthepony.mc.otm.block.entity.ItemJob
|
||||||
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.MatteryWorkerBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
|
||||||
@ -17,7 +17,7 @@ import ru.dbotthepony.mc.otm.menu.tech.CobblerMenu
|
|||||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||||
|
|
||||||
class CobblerBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
class CobblerBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
||||||
: MatteryWorkerBlockEntity<MachineItemJob>(MBlockEntities.COBBLESTONE_GENERATOR, blockPos, blockState, ::MachineItemJob) {
|
: MatteryWorkerBlockEntity<ItemJob>(MBlockEntities.COBBLESTONE_GENERATOR, blockPos, blockState, ItemJob.CODEC) {
|
||||||
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
|
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
|
||||||
return CobblerMenu(containerID, inventory, this)
|
return CobblerMenu(containerID, inventory, this)
|
||||||
}
|
}
|
||||||
@ -36,16 +36,14 @@ class CobblerBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
|||||||
savetable(::container, INVENTORY_KEY)
|
savetable(::container, INVENTORY_KEY)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onJobFinish(job: MachineItemJob, id: Int): JobStatus {
|
override fun onJobFinish(status: JobStatus<ItemJob>, id: Int) {
|
||||||
if (!container.fullyAddItem(job.itemStack)) {
|
if (!container.fullyAddItem(status.job.itemStack)) {
|
||||||
return JobStatus.FAILURE_ITEM
|
status.noItem()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return JobStatus.SUCCESS
|
override fun computeNextJob(id: Int): JobContainer<ItemJob> {
|
||||||
}
|
return JobContainer.success(ItemJob(ItemStack(Items.COBBLESTONE), 40.0))
|
||||||
|
|
||||||
override fun computeNextJob(id: Int): JobContainer<MachineItemJob> {
|
|
||||||
return JobContainer.success(MachineItemJob(ItemStack(Items.COBBLESTONE), 40.0))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -10,7 +10,7 @@ import net.minecraft.world.inventory.AbstractContainerMenu
|
|||||||
import net.minecraft.world.level.block.state.BlockState
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
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.MachineItemJob
|
import ru.dbotthepony.mc.otm.block.entity.ItemJob
|
||||||
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
|
||||||
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
|
||||||
@ -20,7 +20,6 @@ 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.container.balance
|
import ru.dbotthepony.mc.otm.container.balance
|
||||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
|
||||||
import ru.dbotthepony.mc.otm.menu.tech.PlatePressMenu
|
import ru.dbotthepony.mc.otm.menu.tech.PlatePressMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.tech.TwinPlatePressMenu
|
import ru.dbotthepony.mc.otm.menu.tech.TwinPlatePressMenu
|
||||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||||
@ -30,7 +29,7 @@ class PlatePressBlockEntity(
|
|||||||
p_155229_: BlockPos,
|
p_155229_: BlockPos,
|
||||||
p_155230_: BlockState,
|
p_155230_: BlockState,
|
||||||
val isTwin: Boolean = false,
|
val isTwin: Boolean = false,
|
||||||
) : MatteryWorkerBlockEntity<MachineItemJob>(if (isTwin) MBlockEntities.TWIN_PLATE_PRESS else MBlockEntities.PLATE_PRESS, p_155229_, p_155230_, ::MachineItemJob, if (isTwin) 2 else 1) {
|
) : MatteryWorkerBlockEntity<ItemJob>(if (isTwin) MBlockEntities.TWIN_PLATE_PRESS else MBlockEntities.PLATE_PRESS, p_155229_, p_155230_, ItemJob.CODEC, if (isTwin) 2 else 1) {
|
||||||
override val upgrades = UpgradeContainer(this::setChangedLight, if (isTwin) 4 else 3, UpgradeType.BASIC_PROCESSING)
|
override val upgrades = UpgradeContainer(this::setChangedLight, if (isTwin) 4 else 3, UpgradeType.BASIC_PROCESSING)
|
||||||
val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::energyLevelUpdated, upgrades.transform(MachinesConfig.PLATE_PRESS)))
|
val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::energyLevelUpdated, upgrades.transform(MachinesConfig.PLATE_PRESS)))
|
||||||
val inputContainer = MatteryContainer(this::itemContainerUpdated, if (isTwin) 2 else 1).also(::addDroppableContainer)
|
val inputContainer = MatteryContainer(this::itemContainerUpdated, if (isTwin) 2 else 1).also(::addDroppableContainer)
|
||||||
@ -69,18 +68,17 @@ class PlatePressBlockEntity(
|
|||||||
return PlatePressMenu(containerID, inventory, this)
|
return PlatePressMenu(containerID, inventory, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onJobFinish(job: MachineItemJob, id: Int): JobStatus {
|
override fun onJobFinish(status: JobStatus<ItemJob>, id: Int) {
|
||||||
if (job.itemStack.isEmpty)
|
if (status.job.itemStack.isEmpty)
|
||||||
return JobStatus.SUCCESS
|
return status.success()
|
||||||
|
|
||||||
if (!outputContainer.fullyAddItem(job.itemStack, start = id, end = id) && !outputContainer.fullyAddItem(job.itemStack))
|
if (!outputContainer.fullyAddItem(status.job.itemStack, start = id, end = id) && !outputContainer.fullyAddItem(status.job.itemStack))
|
||||||
return JobStatus.FAILURE_ITEM
|
return status.noItem()
|
||||||
|
|
||||||
experience = (experience + job.experience).coerceAtMost(100.0)
|
experience = (experience + status.experience).coerceAtMost(100.0)
|
||||||
return JobStatus.SUCCESS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun computeNextJob(id: Int): JobContainer<MachineItemJob> {
|
override fun computeNextJob(id: Int): JobContainer<ItemJob> {
|
||||||
if (energy.batteryLevel.isZero) {
|
if (energy.batteryLevel.isZero) {
|
||||||
return JobContainer.noEnergy()
|
return JobContainer.noEnergy()
|
||||||
}
|
}
|
||||||
@ -101,7 +99,7 @@ class PlatePressBlockEntity(
|
|||||||
inputContainer.setChanged(id)
|
inputContainer.setChanged(id)
|
||||||
|
|
||||||
return JobContainer.success(
|
return JobContainer.success(
|
||||||
MachineItemJob(
|
ItemJob(
|
||||||
recipe.getResultItem(level.registryAccess()).copyWithCount(toProcess),
|
recipe.getResultItem(level.registryAccess()).copyWithCount(toProcess),
|
||||||
recipe.workTime * MachinesConfig.PLATE_PRESS.workTimeMultiplier,
|
recipe.workTime * MachinesConfig.PLATE_PRESS.workTimeMultiplier,
|
||||||
MachinesConfig.PLATE_PRESS.powerConsumption * toProcess,
|
MachinesConfig.PLATE_PRESS.powerConsumption * toProcess,
|
||||||
|
@ -3,19 +3,17 @@ package ru.dbotthepony.mc.otm.block.entity.tech
|
|||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.server.level.ServerLevel
|
import net.minecraft.server.level.ServerLevel
|
||||||
import net.minecraft.server.level.ServerPlayer
|
import net.minecraft.server.level.ServerPlayer
|
||||||
import net.minecraft.world.Container
|
|
||||||
import net.minecraft.world.entity.ExperienceOrb
|
import net.minecraft.world.entity.ExperienceOrb
|
||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import net.minecraft.world.entity.player.Player
|
import net.minecraft.world.entity.player.Player
|
||||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||||
import net.minecraft.world.item.crafting.AbstractCookingRecipe
|
import net.minecraft.world.item.crafting.AbstractCookingRecipe
|
||||||
import net.minecraft.world.item.crafting.Recipe
|
|
||||||
import net.minecraft.world.item.crafting.RecipeType
|
import net.minecraft.world.item.crafting.RecipeType
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||||
import net.minecraft.world.level.block.state.BlockState
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
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.MachineItemJob
|
import ru.dbotthepony.mc.otm.block.entity.ItemJob
|
||||||
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.capability.CombinedItemHandler
|
import ru.dbotthepony.mc.otm.capability.CombinedItemHandler
|
||||||
import ru.dbotthepony.mc.otm.capability.UpgradeType
|
import ru.dbotthepony.mc.otm.capability.UpgradeType
|
||||||
@ -36,7 +34,7 @@ class PoweredFurnaceBlockEntity(
|
|||||||
blockState: BlockState,
|
blockState: BlockState,
|
||||||
val recipeType: RecipeType<out AbstractCookingRecipe>,
|
val recipeType: RecipeType<out AbstractCookingRecipe>,
|
||||||
val config: WorkerBalanceValues
|
val config: WorkerBalanceValues
|
||||||
) : MatteryWorkerBlockEntity<MachineItemJob>(type, blockPos, blockState, ::MachineItemJob, 2) {
|
) : MatteryWorkerBlockEntity<ItemJob>(type, blockPos, blockState, ItemJob.CODEC, 2) {
|
||||||
override val upgrades = UpgradeContainer(this::setChangedLight, 2, UpgradeType.BASIC_PROCESSING)
|
override val upgrades = UpgradeContainer(this::setChangedLight, 2, UpgradeType.BASIC_PROCESSING)
|
||||||
val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::energyLevelUpdated, upgrades.transform(config)))
|
val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::energyLevelUpdated, upgrades.transform(config)))
|
||||||
|
|
||||||
@ -86,16 +84,15 @@ class PoweredFurnaceBlockEntity(
|
|||||||
return PoweredFurnaceMenu(containerID, inventory, this)
|
return PoweredFurnaceMenu(containerID, inventory, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onJobFinish(job: MachineItemJob, id: Int): JobStatus {
|
override fun onJobFinish(status: JobStatus<ItemJob>, id: Int) {
|
||||||
if (outputs[id].fullyAddItem(job.itemStack)) {
|
if (outputs[id].fullyAddItem(status.job.itemStack)) {
|
||||||
experience += job.experience
|
experience += status.experience
|
||||||
return JobStatus.SUCCESS
|
} else {
|
||||||
|
status.noItem()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return JobStatus.FAILURE_ITEM
|
override fun computeNextJob(id: Int): JobContainer<ItemJob> {
|
||||||
}
|
|
||||||
|
|
||||||
override fun computeNextJob(id: Int): JobContainer<MachineItemJob> {
|
|
||||||
if (!energy.batteryLevel.isPositive)
|
if (!energy.batteryLevel.isPositive)
|
||||||
return JobContainer.noEnergy()
|
return JobContainer.noEnergy()
|
||||||
|
|
||||||
@ -109,7 +106,7 @@ class PoweredFurnaceBlockEntity(
|
|||||||
val toProcess = inputs[id][0].count.coerceAtMost(upgrades.processingItems + 1)
|
val toProcess = inputs[id][0].count.coerceAtMost(upgrades.processingItems + 1)
|
||||||
inputs[id][0].shrink(toProcess)
|
inputs[id][0].shrink(toProcess)
|
||||||
|
|
||||||
JobContainer.success(MachineItemJob(
|
JobContainer.success(ItemJob(
|
||||||
output.copyWithCount(toProcess), it.cookingTime * config.workTimeMultiplier, config.powerConsumption * toProcess, it.experience * toProcess
|
output.copyWithCount(toProcess), it.cookingTime * config.workTimeMultiplier, config.powerConsumption * toProcess, it.experience * toProcess
|
||||||
))
|
))
|
||||||
}.orElse(JobContainer.noItem())
|
}.orElse(JobContainer.noItem())
|
||||||
|
@ -63,7 +63,7 @@ import ru.dbotthepony.mc.otm.android.AndroidResearchManager
|
|||||||
import ru.dbotthepony.mc.otm.android.AndroidResearchType
|
import ru.dbotthepony.mc.otm.android.AndroidResearchType
|
||||||
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.MachineItemJob
|
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.capability.energy.BatteryBackedEnergyStorage
|
import ru.dbotthepony.mc.otm.capability.energy.BatteryBackedEnergyStorage
|
||||||
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
|
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
|
||||||
@ -411,33 +411,26 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
|||||||
}
|
}
|
||||||
}).property
|
}).property
|
||||||
|
|
||||||
inner class SmelterBelt(index: Int) : MachineJobEventLoop<MachineItemJob>() {
|
inner class SmelterBelt(index: Int) : MachineJobEventLoop<ItemJob>(ItemJob.CODEC) {
|
||||||
override val energy: IMatteryEnergyStorage
|
override val energy: IMatteryEnergyStorage
|
||||||
get() = exoPackEnergy
|
get() = exoPackEnergy
|
||||||
override val isBlockedByRedstone: Boolean
|
override val isBlockedByRedstone: Boolean
|
||||||
get() = false
|
get() = false
|
||||||
|
|
||||||
override fun deserializeJob(nbt: CompoundTag): MachineItemJob {
|
|
||||||
return MachineItemJob(nbt)
|
|
||||||
}
|
|
||||||
|
|
||||||
override val upgrades: IMatteryUpgrade?
|
override val upgrades: IMatteryUpgrade?
|
||||||
get() = null
|
get() = null
|
||||||
|
|
||||||
override fun jobUpdated(new: MachineItemJob?, old: MachineItemJob?) {}
|
override fun onJobFinish(status: JobStatus<ItemJob>) {
|
||||||
|
if (output.fullyAddItem(status.job.itemStack)) {
|
||||||
override fun onJobFinish(job: MachineItemJob): JobStatus {
|
exoPackSmelterExperience += status.job.experience
|
||||||
if (output.fullyAddItem(job.itemStack)) {
|
|
||||||
exoPackSmelterExperience += job.experience
|
|
||||||
return JobStatus.SUCCESS
|
|
||||||
} else {
|
} else {
|
||||||
return JobStatus.FAILURE_ITEM
|
status.noItem()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val cache = RecipeManager.createCheck(RecipeType.SMELTING)
|
private val cache = RecipeManager.createCheck(RecipeType.SMELTING)
|
||||||
|
|
||||||
override fun computeNextJob(): JobContainer<MachineItemJob> {
|
override fun computeNextJob(): JobContainer<ItemJob> {
|
||||||
if (!exoPackEnergy.batteryLevel.isPositive) return JobContainer.noEnergy()
|
if (!exoPackEnergy.batteryLevel.isPositive) return JobContainer.noEnergy()
|
||||||
val level = ply.level() as? ServerLevel ?: return JobContainer.failure()
|
val level = ply.level() as? ServerLevel ?: return JobContainer.failure()
|
||||||
val recipe = cache.getRecipeFor(input, level)
|
val recipe = cache.getRecipeFor(input, level)
|
||||||
@ -449,7 +442,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
|||||||
val item = actual.assemble(input, level.registryAccess())
|
val item = actual.assemble(input, level.registryAccess())
|
||||||
input[0].shrink(1)
|
input[0].shrink(1)
|
||||||
input.setChanged(0)
|
input.setChanged(0)
|
||||||
return JobContainer.success(MachineItemJob(item, actual.cookingTime.toDouble(), ExopackConfig.FURNACE_POWER_CONSUMPTION, actual.experience))
|
return JobContainer.success(ItemJob(item, actual.cookingTime.toDouble(), ExopackConfig.FURNACE_POWER_CONSUMPTION, actual.experience))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
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.codecs.RecordCodecBuilder
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
|
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.resources.ResourceLocation
|
||||||
@ -11,6 +15,7 @@ import net.minecraftforge.registries.ForgeRegistries
|
|||||||
import ru.dbotthepony.mc.otm.core.*
|
import ru.dbotthepony.mc.otm.core.*
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.contains
|
import ru.dbotthepony.mc.otm.core.nbt.contains
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||||
|
import ru.dbotthepony.mc.otm.data.UUIDCodec
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
sealed interface IPatternState {
|
sealed interface IPatternState {
|
||||||
@ -45,13 +50,7 @@ sealed interface IPatternState {
|
|||||||
return ItemStack(item, count)
|
return ItemStack(item, count)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun serializeNBT(): CompoundTag {
|
fun serializeNBT(): CompoundTag
|
||||||
return CompoundTag().also {
|
|
||||||
it["id"] = id
|
|
||||||
it["item"] = item.registryName!!.toString()
|
|
||||||
it["researchPercent"] = researchPercent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun write(buff: FriendlyByteBuf) {
|
fun write(buff: FriendlyByteBuf) {
|
||||||
buff.writeUUID(id)
|
buff.writeUUID(id)
|
||||||
@ -60,6 +59,14 @@ sealed interface IPatternState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 deserializeNBT(nbt: Tag?, mutable: Boolean): IPatternState? {
|
private fun deserializeNBT(nbt: Tag?, mutable: Boolean): IPatternState? {
|
||||||
if (nbt !is CompoundTag)
|
if (nbt !is CompoundTag)
|
||||||
return null
|
return null
|
||||||
@ -108,6 +115,10 @@ data class PatternState(
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
fun deserializeNBT(tag: Tag?): PatternState? {
|
fun deserializeNBT(tag: Tag?): PatternState? {
|
||||||
return deserializeNBT(tag, false) as PatternState?
|
return deserializeNBT(tag, false) as PatternState?
|
||||||
@ -116,6 +127,12 @@ data class PatternState(
|
|||||||
fun read(buff: FriendlyByteBuf): PatternState? {
|
fun read(buff: FriendlyByteBuf): PatternState? {
|
||||||
return read(buff, false) as PatternState?
|
return read(buff, false) as PatternState?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val CODEC: Codec<PatternState> by lazy {
|
||||||
|
RecordCodecBuilder.create {
|
||||||
|
codec(it).apply(it, ::PatternState)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,6 +149,10 @@ data class MutablePatternState(
|
|||||||
return PatternState(id, item, researchPercent)
|
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 {
|
companion object {
|
||||||
fun deserializeNBT(tag: Tag?): MutablePatternState? {
|
fun deserializeNBT(tag: Tag?): MutablePatternState? {
|
||||||
return deserializeNBT(tag, true) as MutablePatternState?
|
return deserializeNBT(tag, true) as MutablePatternState?
|
||||||
@ -140,6 +161,12 @@ data class MutablePatternState(
|
|||||||
fun read(buff: FriendlyByteBuf): MutablePatternState? {
|
fun read(buff: FriendlyByteBuf): MutablePatternState? {
|
||||||
return read(buff, true) as MutablePatternState?
|
return read(buff, true) as MutablePatternState?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val CODEC: Codec<MutablePatternState> by lazy {
|
||||||
|
RecordCodecBuilder.create {
|
||||||
|
codec(it).apply(it, ::MutablePatternState)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
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.codecs.RecordCodecBuilder
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
|
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.resources.ResourceLocation
|
||||||
@ -9,14 +13,14 @@ import net.minecraft.world.item.ItemStack
|
|||||||
import net.minecraft.world.item.Items
|
import net.minecraft.world.item.Items
|
||||||
import net.minecraftforge.registries.ForgeRegistries
|
import net.minecraftforge.registries.ForgeRegistries
|
||||||
import ru.dbotthepony.mc.otm.core.readItemType
|
import ru.dbotthepony.mc.otm.core.readItemType
|
||||||
import ru.dbotthepony.mc.otm.core.registryName
|
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
|
||||||
import ru.dbotthepony.mc.otm.core.writeItemType
|
import ru.dbotthepony.mc.otm.core.writeItemType
|
||||||
|
import ru.dbotthepony.mc.otm.data.UUIDCodec
|
||||||
|
import java.util.Optional
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
sealed interface IReplicationTask<S : IReplicationTask<S>> {
|
sealed interface IReplicationTask<S : IReplicationTask<S>> {
|
||||||
val id: UUID
|
val id: UUID
|
||||||
val patternId: UUID?
|
val patternId: Optional<UUID>
|
||||||
val item: Item
|
val item: Item
|
||||||
val inProgress: Int
|
val inProgress: Int
|
||||||
val finished: Int
|
val finished: Int
|
||||||
@ -29,7 +33,7 @@ sealed interface IReplicationTask<S : IReplicationTask<S>> {
|
|||||||
|
|
||||||
fun copyAsMutable(
|
fun copyAsMutable(
|
||||||
id: UUID = this.id,
|
id: UUID = this.id,
|
||||||
patternId: UUID? = this.patternId,
|
patternId: Optional<UUID> = this.patternId,
|
||||||
item: Item = this.item,
|
item: Item = this.item,
|
||||||
inProgress: Int = this.inProgress,
|
inProgress: Int = this.inProgress,
|
||||||
finished: Int = this.finished,
|
finished: Int = this.finished,
|
||||||
@ -40,7 +44,7 @@ sealed interface IReplicationTask<S : IReplicationTask<S>> {
|
|||||||
|
|
||||||
fun copyAsImmutable(
|
fun copyAsImmutable(
|
||||||
id: UUID = this.id,
|
id: UUID = this.id,
|
||||||
patternId: UUID? = this.patternId,
|
patternId: Optional<UUID> = this.patternId,
|
||||||
item: Item = this.item,
|
item: Item = this.item,
|
||||||
inProgress: Int = this.inProgress,
|
inProgress: Int = this.inProgress,
|
||||||
finished: Int = this.finished,
|
finished: Int = this.finished,
|
||||||
@ -60,25 +64,13 @@ sealed interface IReplicationTask<S : IReplicationTask<S>> {
|
|||||||
fun allocate(amount: Int = 1): S
|
fun allocate(amount: Int = 1): S
|
||||||
fun finish(amount: Int = 1): S
|
fun finish(amount: Int = 1): S
|
||||||
|
|
||||||
fun serializeNBT(): CompoundTag {
|
fun serializeNBT(): CompoundTag
|
||||||
return CompoundTag().also {
|
|
||||||
it["id"] = id
|
|
||||||
|
|
||||||
if (patternId != null)
|
|
||||||
it["patternId"] = patternId!!
|
|
||||||
|
|
||||||
it["item"] = item.registryName!!.toString()
|
|
||||||
it["inProgress"] = inProgress
|
|
||||||
it["finished"] = finished
|
|
||||||
it["required"] = required
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun write(buff: FriendlyByteBuf) {
|
fun write(buff: FriendlyByteBuf) {
|
||||||
buff.writeUUID(id)
|
buff.writeUUID(id)
|
||||||
|
|
||||||
buff.writeBoolean(patternId != null)
|
buff.writeBoolean(patternId.isPresent)
|
||||||
patternId?.let(buff::writeUUID)
|
patternId.ifPresent(buff::writeUUID)
|
||||||
|
|
||||||
buff.writeItemType(item)
|
buff.writeItemType(item)
|
||||||
|
|
||||||
@ -88,6 +80,17 @@ sealed interface IReplicationTask<S : IReplicationTask<S>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun <T : IReplicationTask<T>> codec(builder: RecordCodecBuilder.Instance<T>): Products.P6<RecordCodecBuilder.Mu<T>, UUID, Optional<UUID>, Item, Int, Int, Int> {
|
||||||
|
return builder.group(
|
||||||
|
UUIDCodec.fieldOf("id").forGetter(IReplicationTask<*>::id),
|
||||||
|
UUIDCodec.optionalFieldOf("patternId").forGetter(IReplicationTask<*>::patternId),
|
||||||
|
ForgeRegistries.ITEMS.codec.fieldOf("item").forGetter(IReplicationTask<*>::item),
|
||||||
|
Codec.intRange(0, Int.MAX_VALUE).fieldOf("inProgress").forGetter(IReplicationTask<*>::inProgress),
|
||||||
|
Codec.intRange(0, Int.MAX_VALUE).fieldOf("finished").forGetter(IReplicationTask<*>::finished),
|
||||||
|
Codec.intRange(0, Int.MAX_VALUE).fieldOf("required").forGetter(IReplicationTask<*>::required),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun deserializeNBT(nbt: Tag?, mutable: Boolean): IReplicationTask<*>? {
|
private fun deserializeNBT(nbt: Tag?, mutable: Boolean): IReplicationTask<*>? {
|
||||||
if (nbt !is CompoundTag)
|
if (nbt !is CompoundTag)
|
||||||
return null
|
return null
|
||||||
@ -108,9 +111,9 @@ private fun deserializeNBT(nbt: Tag?, mutable: Boolean): IReplicationTask<*>? {
|
|||||||
val required = nbt.getInt("required")
|
val required = nbt.getInt("required")
|
||||||
|
|
||||||
if (mutable) {
|
if (mutable) {
|
||||||
return MutableReplicationTask(id, patternId, item, inProgress, finished, required)
|
return MutableReplicationTask(id, Optional.ofNullable(patternId), item, inProgress, finished, required)
|
||||||
} else {
|
} else {
|
||||||
return ReplicationTask(id, patternId, item, inProgress, finished, required)
|
return ReplicationTask(id, Optional.ofNullable(patternId), item, inProgress, finished, required)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,15 +128,15 @@ private fun read(buff: FriendlyByteBuf, mutable: Boolean): IReplicationTask<*>?
|
|||||||
item ?: return null
|
item ?: return null
|
||||||
|
|
||||||
if (mutable) {
|
if (mutable) {
|
||||||
return MutableReplicationTask(id, patternId, item, inProgress, finished, required)
|
return MutableReplicationTask(id, Optional.ofNullable(patternId), item, inProgress, finished, required)
|
||||||
} else {
|
} else {
|
||||||
return ReplicationTask(id, patternId, item, inProgress, finished, required)
|
return ReplicationTask(id, Optional.ofNullable(patternId), item, inProgress, finished, required)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ReplicationTask(
|
data class ReplicationTask(
|
||||||
override val id: UUID,
|
override val id: UUID,
|
||||||
override val patternId: UUID?,
|
override val patternId: Optional<UUID>,
|
||||||
override val item: Item,
|
override val item: Item,
|
||||||
override val inProgress: Int,
|
override val inProgress: Int,
|
||||||
override val finished: Int,
|
override val finished: Int,
|
||||||
@ -155,6 +158,10 @@ data class ReplicationTask(
|
|||||||
return ReplicationTask(id, patternId, item, inProgress - amount, finished + amount, required)
|
return ReplicationTask(id, patternId, item, inProgress - amount, finished + amount, required)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun serializeNBT(): CompoundTag {
|
||||||
|
return CODEC.encode(this, NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).get().map({ it as CompoundTag }, { throw RuntimeException("Failed to serialize ReplicationTask: ${it.message()}") })
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun deserializeNBT(nbt: Tag?): ReplicationTask? {
|
fun deserializeNBT(nbt: Tag?): ReplicationTask? {
|
||||||
return deserializeNBT(nbt, false) as ReplicationTask?
|
return deserializeNBT(nbt, false) as ReplicationTask?
|
||||||
@ -163,12 +170,18 @@ data class ReplicationTask(
|
|||||||
fun read(buff: FriendlyByteBuf): ReplicationTask? {
|
fun read(buff: FriendlyByteBuf): ReplicationTask? {
|
||||||
return read(buff, false) as ReplicationTask?
|
return read(buff, false) as ReplicationTask?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val CODEC: Codec<ReplicationTask> by lazy {
|
||||||
|
RecordCodecBuilder.create {
|
||||||
|
codec(it).apply(it, ::ReplicationTask)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class MutableReplicationTask(
|
data class MutableReplicationTask(
|
||||||
override val id: UUID,
|
override val id: UUID,
|
||||||
override val patternId: UUID?,
|
override val patternId: Optional<UUID>,
|
||||||
override val item: Item,
|
override val item: Item,
|
||||||
override var inProgress: Int,
|
override var inProgress: Int,
|
||||||
override var finished: Int,
|
override var finished: Int,
|
||||||
@ -194,6 +207,10 @@ data class MutableReplicationTask(
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun serializeNBT(): CompoundTag {
|
||||||
|
return CODEC.encode(this, NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).get().map({ it as CompoundTag }, { throw RuntimeException("Failed to serialize MutableReplicationTask: ${it.message()}") })
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun deserializeNBT(nbt: Tag?): MutableReplicationTask? {
|
fun deserializeNBT(nbt: Tag?): MutableReplicationTask? {
|
||||||
return deserializeNBT(nbt, true) as MutableReplicationTask?
|
return deserializeNBT(nbt, true) as MutableReplicationTask?
|
||||||
@ -202,6 +219,12 @@ data class MutableReplicationTask(
|
|||||||
fun read(buff: FriendlyByteBuf): MutableReplicationTask? {
|
fun read(buff: FriendlyByteBuf): MutableReplicationTask? {
|
||||||
return read(buff, true) as MutableReplicationTask?
|
return read(buff, true) as MutableReplicationTask?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val CODEC: Codec<MutableReplicationTask> by lazy {
|
||||||
|
RecordCodecBuilder.create {
|
||||||
|
codec(it).apply(it, ::MutableReplicationTask)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ package ru.dbotthepony.mc.otm.compat.jade.providers
|
|||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.nbt.ListTag
|
import net.minecraft.nbt.ListTag
|
||||||
import net.minecraft.resources.ResourceLocation
|
import net.minecraft.resources.ResourceLocation
|
||||||
import ru.dbotthepony.mc.otm.block.entity.MachineItemJob
|
import ru.dbotthepony.mc.otm.block.entity.ItemJob
|
||||||
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.compat.jade.JadeTagKeys
|
import ru.dbotthepony.mc.otm.compat.jade.JadeTagKeys
|
||||||
import ru.dbotthepony.mc.otm.compat.jade.JadeUids
|
import ru.dbotthepony.mc.otm.compat.jade.JadeUids
|
||||||
@ -34,8 +34,8 @@ object MatteryWorkerProvider : IBlockComponentProvider, IServerDataProvider<Bloc
|
|||||||
jobData.putBoolean("isIdling", job.isIdling)
|
jobData.putBoolean("isIdling", job.isIdling)
|
||||||
jobData.putBoolean("isUnableToProcess", job.isUnableToProcess)
|
jobData.putBoolean("isUnableToProcess", job.isUnableToProcess)
|
||||||
|
|
||||||
if (job.currentJob is MachineItemJob) {
|
if (job.currentJob is ItemJob) {
|
||||||
val currentJob = job.currentJob as MachineItemJob
|
val currentJob = job.currentJob as ItemJob
|
||||||
jobData.put("itemStack", currentJob.itemStack.serializeNBT())
|
jobData.put("itemStack", currentJob.itemStack.serializeNBT())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.data
|
||||||
|
|
||||||
|
import com.mojang.datafixers.util.Pair
|
||||||
|
import com.mojang.serialization.Codec
|
||||||
|
import com.mojang.serialization.DataResult
|
||||||
|
import com.mojang.serialization.DynamicOps
|
||||||
|
|
||||||
|
class ComparableCodec<S : Comparable<S>>(val parent: Codec<S>, val min: S? = null, val max: S? = null, val minExclusive: Boolean = false, val maxExclusive: Boolean = false) : Codec<S> {
|
||||||
|
private fun <T : Any> check(input: S): DataResult<T>? {
|
||||||
|
if (min != null) {
|
||||||
|
if (minExclusive) {
|
||||||
|
if (input <= min) {
|
||||||
|
return DataResult.error { "Value $input is smaller or equal to minimal $min" }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (input < min) {
|
||||||
|
return DataResult.error { "Value $input is smaller than minimal $min" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max != null) {
|
||||||
|
if (maxExclusive) {
|
||||||
|
if (input >= max) {
|
||||||
|
return DataResult.error { "Value $input is bigger or equal to maximal $max" }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (input > max) {
|
||||||
|
return DataResult.error { "Value $input is bigger than maximal $max" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : Any> encode(input: S, ops: DynamicOps<T>, prefix: T): DataResult<T> {
|
||||||
|
check<T>(input)?.let { return it }
|
||||||
|
return parent.encode(input, ops, prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : Any> decode(ops: DynamicOps<T>, input: T): DataResult<Pair<S, T>> {
|
||||||
|
return parent.decode(ops, input).flatMap {
|
||||||
|
check<Pair<S, T>>(it.first) ?: DataResult.success(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <S : Comparable<S>> Codec<S>.minRange(min: S, exclusive: Boolean = false) = ComparableCodec(this, min = min, minExclusive = exclusive)
|
||||||
|
fun <S : Comparable<S>> Codec<S>.maxRange(max: S, exclusive: Boolean = false) = ComparableCodec(this, max = max, maxExclusive = exclusive)
|
||||||
|
fun <S : Comparable<S>> Codec<S>.inRange(min: S, minExclusive: Boolean = false, max: S, maxExclusive: Boolean = false) = ComparableCodec(this, min, max, minExclusive, maxExclusive)
|
@ -4,28 +4,63 @@ import com.mojang.datafixers.util.Pair
|
|||||||
import com.mojang.serialization.Codec
|
import com.mojang.serialization.Codec
|
||||||
import com.mojang.serialization.DataResult
|
import com.mojang.serialization.DataResult
|
||||||
import com.mojang.serialization.DynamicOps
|
import com.mojang.serialization.DynamicOps
|
||||||
|
import it.unimi.dsi.fastutil.bytes.ByteArrayList
|
||||||
|
import net.minecraft.nbt.NbtOps
|
||||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
import java.util.stream.Collector
|
||||||
|
import java.util.stream.Stream
|
||||||
|
|
||||||
object DecimalCodec : Codec<Decimal> {
|
object DecimalCodec : Codec<Decimal> {
|
||||||
override fun <T : Any> encode(input: Decimal, ops: DynamicOps<T>, prefix: T): DataResult<T> {
|
override fun <T : Any> encode(input: Decimal, ops: DynamicOps<T>, prefix: T): DataResult<T> {
|
||||||
|
if (ops === NbtOps.INSTANCE) {
|
||||||
|
return DataResult.success((ops as DynamicOps<T>).createByteList(ByteBuffer.wrap(input.toByteArray())))
|
||||||
|
}
|
||||||
|
|
||||||
return DataResult.success(ops.createString(input.toString()))
|
return DataResult.success(ops.createString(input.toString()))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T : Any> decode(ops: DynamicOps<T>, input: T): DataResult<Pair<Decimal, T>> {
|
override fun <T : Any> decode(ops: DynamicOps<T>, input: T): DataResult<Pair<Decimal, T>> {
|
||||||
val result = ops.getStringValue(input).flatMap {
|
return ops.getStringValue(input).flatMap {
|
||||||
try {
|
try {
|
||||||
DataResult.success(Pair(Decimal(it), ops.empty()))
|
DataResult.success(Pair(Decimal(it), ops.empty()))
|
||||||
} catch (err: NumberFormatException) {
|
} catch (err: NumberFormatException) {
|
||||||
DataResult.error { "Not a valid number for converting into Decimal: $it" }
|
DataResult.error { "Not a valid number for converting into Decimal: $it" }
|
||||||
}
|
}
|
||||||
|
}.get().map(
|
||||||
|
{
|
||||||
|
DataResult.success(it)
|
||||||
|
},
|
||||||
|
{ e0 ->
|
||||||
|
ops.getIntStream(input).flatMap {
|
||||||
|
try {
|
||||||
|
DataResult.success(Pair(Decimal.fromByteArray(
|
||||||
|
it.mapToObj { val v = it.toLong(); Stream.of(v and 0xFFL, (v and 0xFF00L) ushr 8, (v and 0xFF0000L) ushr 16, (v and 0xFF000000L) ushr 24) }
|
||||||
|
.flatMap { it }
|
||||||
|
.collect(::ByteArrayList, { v, a -> v.add(a.toByte()) }, ByteArrayList::addAll)
|
||||||
|
.toByteArray()
|
||||||
|
), ops.empty()))
|
||||||
|
} catch (err: NumberFormatException) {
|
||||||
|
DataResult.error { "Failed to convert array of bytes into Decimal: $it" }
|
||||||
}
|
}
|
||||||
|
}.get().map(
|
||||||
if (result.result().isPresent) {
|
{
|
||||||
return result
|
DataResult.success(it)
|
||||||
}
|
},
|
||||||
|
{ e1 ->
|
||||||
return ops.getNumberValue(input).flatMap {
|
ops.getNumberValue(input).flatMap {
|
||||||
DataResult.success(Pair(Decimal(it.toString()), ops.empty()))
|
DataResult.success(Pair(Decimal(it.toString()), ops.empty()))
|
||||||
|
}.get().map(
|
||||||
|
{
|
||||||
|
DataResult.success(it)
|
||||||
|
},
|
||||||
|
{ e2 ->
|
||||||
|
DataResult.error { "None of attempts at decoding Decimal were successful: ${e0.message()}; ${e1.message()}; ${e2.message()}" }
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,17 @@ package ru.dbotthepony.mc.otm.data
|
|||||||
import com.google.gson.JsonArray
|
import com.google.gson.JsonArray
|
||||||
import com.google.gson.JsonNull
|
import com.google.gson.JsonNull
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
|
import com.mojang.datafixers.kinds.App
|
||||||
|
import com.mojang.serialization.Codec
|
||||||
import com.mojang.serialization.DataResult
|
import com.mojang.serialization.DataResult
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||||
import it.unimi.dsi.fastutil.ints.IntAVLTreeSet
|
import it.unimi.dsi.fastutil.ints.IntAVLTreeSet
|
||||||
import net.minecraft.world.entity.player.Player
|
import net.minecraft.world.entity.player.Player
|
||||||
import net.minecraft.world.level.storage.loot.LootContext
|
import net.minecraft.world.level.storage.loot.LootContext
|
||||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParam
|
import net.minecraft.world.level.storage.loot.parameters.LootContextParam
|
||||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParams
|
import net.minecraft.world.level.storage.loot.parameters.LootContextParams
|
||||||
|
import java.util.Optional
|
||||||
|
import kotlin.reflect.KProperty1
|
||||||
|
|
||||||
fun JsonArray.getRidOfNulls(): JsonArray {
|
fun JsonArray.getRidOfNulls(): JsonArray {
|
||||||
val toRemove = IntAVLTreeSet()
|
val toRemove = IntAVLTreeSet()
|
||||||
|
26
src/main/kotlin/ru/dbotthepony/mc/otm/data/UUIDCodec.kt
Normal file
26
src/main/kotlin/ru/dbotthepony/mc/otm/data/UUIDCodec.kt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.data
|
||||||
|
|
||||||
|
import com.mojang.datafixers.util.Pair
|
||||||
|
import com.mojang.serialization.Codec
|
||||||
|
import com.mojang.serialization.DataResult
|
||||||
|
import com.mojang.serialization.DynamicOps
|
||||||
|
import java.util.UUID
|
||||||
|
import java.util.stream.LongStream
|
||||||
|
|
||||||
|
object UUIDCodec : Codec<UUID> {
|
||||||
|
override fun <T : Any> encode(input: UUID, ops: DynamicOps<T>, prefix: T): DataResult<T> {
|
||||||
|
return DataResult.success(ops.createLongList(LongStream.of(input.mostSignificantBits, input.leastSignificantBits)))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : Any> decode(ops: DynamicOps<T>, input: T): DataResult<Pair<UUID, T>> {
|
||||||
|
return ops.getLongStream(input).flatMap {
|
||||||
|
val l = it.limit(2).toArray()
|
||||||
|
|
||||||
|
if (l.size != 2) {
|
||||||
|
DataResult.error { "Can't construct UUID from ${l.size} elements" }
|
||||||
|
} else {
|
||||||
|
DataResult.success(Pair(UUID(l[0], l[1]), ops.empty()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user