diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterBottlerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterBottlerBlockEntity.kt index f7b6a186a..91e8d4d20 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterBottlerBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterBottlerBlockEntity.kt @@ -22,7 +22,6 @@ import ru.dbotthepony.mc.otm.capability.matter.MatterStorageImpl import ru.dbotthepony.mc.otm.capability.matter.ProfiledMatterStorage import ru.dbotthepony.mc.otm.config.MachinesConfig import ru.dbotthepony.mc.otm.container.UpgradeContainer -import ru.dbotthepony.mc.otm.container.slotted.ContainerSlot import ru.dbotthepony.mc.otm.container.slotted.FilteredContainerSlot import ru.dbotthepony.mc.otm.container.slotted.SlottedContainer import ru.dbotthepony.mc.otm.menu.matter.MatterBottlerMenu @@ -35,7 +34,7 @@ import java.util.function.BooleanSupplier class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.MATTER_BOTTLER, blockPos, blockState) { - val upgrades = UpgradeContainer(3, UpgradeType.BASIC_MATTER, BooleanSupplier { blockState.getValue(WorkerState.SEMI_WORKER_STATE) !== WorkerState.IDLE }, ::markDirtyFast) + val upgrades = UpgradeContainer(3, UpgradeType.BASIC_MATTER, BooleanSupplier { this.blockState.getValue(WorkerState.SEMI_WORKER_STATE) !== WorkerState.IDLE }, ::markDirtyFast) override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::markDirtyFast, upgrades.transform(MachinesConfig.MatterBottler.VALUES))) val energyConfig = ConfigurableEnergy(energy) @@ -141,7 +140,7 @@ class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) : } if (state !== blockState) { - level.setBlock(blockPos, state, Block.UPDATE_CLIENTS) + level.setBlock(blockPos, state, Block.UPDATE_ALL) } } @@ -154,18 +153,143 @@ class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) : } private val workerState by countingLazy(blockStateChangesCounter) { - blockState.getValue(WorkerState.SEMI_WORKER_STATE) + this.blockState.getValue(WorkerState.SEMI_WORKER_STATE) } private fun blockstateToWorking() { if (workerState !== WorkerState.WORKING) { - level?.setBlock(blockPos, blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.WORKING), Block.UPDATE_CLIENTS) + level?.setBlock(blockPos, blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.WORKING), Block.UPDATE_ALL) } } private fun blockstateToIdle() { if (workerState !== WorkerState.IDLE) { - level?.setBlock(blockPos, blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS) + level?.setBlock(blockPos, blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.IDLE), Block.UPDATE_ALL) + } + } + + private fun tickBottling() { + var isWorking = false + var hasCapacitors = false + + for (slot in bottling.slotIterator()) { + val item = slot.item + val capability = item.getCapability(MatteryCapability.MATTER_ITEM) ?: continue + + if (!capability.receiveMatterChecked(Decimal.LONG_MAX_VALUE, true).isPositive) { + unbottling.consumeItem(item, false) + slot.setChanged() + continue + } + + hasCapacitors = true + initialCapacity = initialCapacity ?: capability.storedMatter + val rate = MachinesConfig.MatterBottler.RATE * (1.0 + upgrades.speedBonus) + val energyRate = MachinesConfig.MatterBottler.VALUES.energyConsumption * (1.0 + upgrades.speedBonus) + + if (matter.storedMatter < rate) { + val toExtract = matter.missingMatter + .coerceAtMost(rate * 200) + .coerceAtMost(capability.missingMatter - matter.storedMatter) + + matter.receiveMatter(matterNode.graph.extractMatter(toExtract, false), false) + } + + if (matter.storedMatter.isPositive) { + val energyRatio = if (energyRate <= Decimal.ZERO) Decimal.ONE else energy.extractEnergy(energyRate, true) / energyRate + val matterRatio = matter.extractMatter(capability.receiveMatter(rate.coerceAtMost(matter.storedMatter), true), true) / rate + + val minRatio = minOf(matterRatio, energyRatio) + + if (minRatio > Decimal.ZERO) { + isWorking = true + energy.extractEnergy(energyRate * minRatio, false) + matter.extractMatter(capability.receiveMatter(rate * minRatio, false), false) + workProgress = ((capability.storedMatter - initialCapacity!!) / capability.maxStoredMatter).toFloat() + slot.setChanged() + } + } else { + if (spitItemsWhenCantWork) { + unbottling.consumeItem(item, false) + slot.setChanged() + } + } + + break + } + + if (isWorking) { + blockstateToWorking() + } else { + blockstateToIdle() + } + + if (!hasCapacitors) { + matter.extractMatter(matterNode.graph.receiveMatter(matter.storedMatter, false), false) + initialCapacity = null + workProgress = 0f + } + } + + private fun tickUnbottling() { + matter.extractMatter(matterNode.graph.receiveMatter(matter.storedMatter, false), false) + + if (!matter.missingMatter.isPositive) { + if (spitItemsWhenCantWork) { + for (slot in unbottling.slotIterator()) { + bottling.consumeItem(slot.item, false) + slot.setChanged() + } + } + + blockstateToIdle() + return + } + + var any = false + var hasCapacitors = false + + for (slot in unbottling.slotIterator()) { + val item = slot.item + val it = item.getCapability(MatteryCapability.MATTER_ITEM) ?: continue + + if (!it.extractMatterChecked(Decimal.LONG_MAX_VALUE, true).isPositive) { + bottling.consumeItem(item, false) + slot.setChanged() + continue + } + + initialCapacity = initialCapacity ?: it.storedMatter + + hasCapacitors = true + val rate = MachinesConfig.MatterBottler.RATE * (1.0 + upgrades.speedBonus) + val energyRate = MachinesConfig.MatterBottler.VALUES.energyConsumption * (1.0 + upgrades.speedBonus) + + val energyRatio = if (energyRate <= Decimal.ZERO) Decimal.ONE else energy.extractEnergy(energyRate, true) / energyRate + val matterRatio = matter.receiveMatter(it.extractMatterChecked(rate, true), true) / rate + + val minRatio = minOf(energyRatio, matterRatio) + + if (minRatio > Decimal.ZERO) { + any = true + energy.extractEnergy(energyRate * energyRatio, false) + matter.receiveMatter(it.extractMatterChecked(rate * minRatio, false), false) + + workProgress = 1f - (it.storedMatter / initialCapacity!!).toFloat() + } + + break + } + + if (any) { + blockstateToWorking() + } else { + blockstateToIdle() + } + + if (!hasCapacitors) { + initialCapacity = null + workProgress = 0f } } @@ -178,106 +302,9 @@ class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) : } if (isBottling) { - var any = false - var idle = false - - for (slot in bottling.slotIterator()) { - val item = slot.item - - item.getCapability(MatteryCapability.MATTER_ITEM)?.let { - if (!it.missingMatter.isPositive) { - unbottling.consumeItem(item, false) - slot.setChanged() - } else { - any = true - initialCapacity = initialCapacity ?: it.storedMatter - val rate = MachinesConfig.MatterBottler.RATE * (1.0 + upgrades.speedBonus) - - if (matter.storedMatter < rate) { - matter.receiveMatter(matterNode.graph.extractMatter(matter.missingMatter - .coerceAtMost(rate * 200) - .coerceAtMost(it.missingMatter - matter.storedMatter), false), false) - } - - if (matter.storedMatter.isPositive) { - matter.extractMatter(it.receiveMatter(rate.coerceAtMost(matter.storedMatter), false), false) - - if (!it.missingMatter.isPositive) { - initialCapacity = null - workProgress = 0f - } else { - workProgress = ((it.storedMatter - initialCapacity!!) / it.maxStoredMatter).toFloat() - } - } else { - idle = true - - if (spitItemsWhenCantWork) { - unbottling.consumeItem(item, false) - slot.setChanged() - } - } - } - } - - if (any) { - break - } - } - - if (any && !idle) { - blockstateToWorking() - } else { - matter.extractMatter(matterNode.graph.receiveMatter(matter.storedMatter, false), false) - blockstateToIdle() - } + tickBottling() } else { - matter.extractMatter(matterNode.graph.receiveMatter(matter.storedMatter, false), false) - - if (!matter.missingMatter.isPositive) { - if (spitItemsWhenCantWork) { - for (slot in unbottling.slotIterator()) { - bottling.consumeItem(slot.item, false) - slot.setChanged() - } - } - - blockstateToIdle() - return - } - - var any = false - - for (slot in unbottling.slotIterator()) { - val item = slot.item - - item.getCapability(MatteryCapability.MATTER_ITEM)?.let { - if (!it.storedMatter.isPositive) { - bottling.consumeItem(item, false) - slot.setChanged() - } else { - any = true - initialCapacity = initialCapacity ?: it.storedMatter - matter.receiveMatter(it.extractMatter(MachinesConfig.MatterBottler.RATE, false), false) - - if (!it.storedMatter.isPositive) { - initialCapacity = null - workProgress = 0f - } else { - workProgress = 1f - (it.storedMatter / initialCapacity!!).toFloat() - } - } - } - - if (any) { - break - } - } - - if (any) { - blockstateToWorking() - } else { - blockstateToIdle() - } + tickUnbottling() } } }