diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/AndroidStationBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/AndroidStationBlockEntity.kt index 6f1474119..5d0babbf2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/AndroidStationBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/AndroidStationBlockEntity.kt @@ -35,8 +35,8 @@ class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : get() = MBlocks.ANDROID_STATION.name override val energy = object : WorkerEnergyStorage(this@AndroidStationBlockEntity::setChangedLight, ::CAPACITY, ::MAX_IO, { null }) { - override fun extractEnergyInner(howMuch: Decimal, simulate: Boolean): Decimal { - return super.extractEnergyInner(howMuch, simulate).also { + override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal { + return super.extractEnergy(howMuch, simulate).also { if (!simulate && this.batteryLevel.isZero) { if (blockState.getValue(WorkerState.SEMI_WORKER_STATE) != WorkerState.IDLE) { level?.setBlock(blockPos, blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS) @@ -45,8 +45,8 @@ class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : } } - override fun receiveEnergyInner(howMuch: Decimal, simulate: Boolean): Decimal { - return super.receiveEnergyInner(howMuch, simulate).also { + override fun receiveEnergy(howMuch: Decimal, simulate: Boolean): Decimal { + return super.receiveEnergy(howMuch, simulate).also { if (!simulate && it.isPositive) { if (blockState.getValue(WorkerState.SEMI_WORKER_STATE) != WorkerState.WORKING) { level?.setBlock(blockPos, blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.WORKING), Block.UPDATE_CLIENTS) @@ -85,11 +85,11 @@ class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : val missing = it.androidEnergy.missingPower if (missing > Decimal.ZERO) { - val extract = energy.extractEnergyInner(missing, true) + val extract = energy.extractEnergy(missing, true) if (extract > Decimal.ZERO) { val received = it.androidEnergy.receiveEnergy(extract, false) - energy.extractEnergyInner(received, false) + energy.extractEnergy(received, false) } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BatteryBankBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BatteryBankBlockEntity.kt index 4d1439bec..c3092159c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BatteryBankBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BatteryBankBlockEntity.kt @@ -72,17 +72,10 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte ) private data class BatteryBankDistribution(val distribution: Array, val maxThroughput: Decimal) - private enum class BankMode { RECEIVE, EXTRACT, BIDIRECTIONAL } - - private inner class BatteryBankEnergy(private val mode: BankMode) : IMatteryEnergyStorage { - override fun canExtract() = mode != BankMode.RECEIVE - override fun canReceive() = mode != BankMode.EXTRACT + private inner class BatteryBankEnergy(override val energyFlow: FlowDirection) : IMatteryEnergyStorage { override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal { - if (mode == BankMode.RECEIVE) - return Decimal.ZERO - - return extractEnergyInner(howMuch, simulate) + return distributeEnergy(isReceiving = false, howMuch, simulate) } fun getDistribution(isReceiving: Boolean): BatteryBankDistribution { @@ -157,18 +150,7 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte return summ } - fun extractEnergyInner(howMuch: Decimal, simulate: Boolean): Decimal { - return distributeEnergy(isReceiving = false, howMuch, simulate) - } - override fun receiveEnergy(howMuch: Decimal, simulate: Boolean): Decimal { - if (mode == BankMode.EXTRACT) - return Decimal.ZERO - - return receiveEnergyInner(howMuch, simulate) - } - - fun receiveEnergyInner(howMuch: Decimal, simulate: Boolean): Decimal { return distributeEnergy(isReceiving = true, howMuch, simulate) } @@ -212,9 +194,9 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte } } - private val energyReceiver = BatteryBankEnergy(BankMode.RECEIVE) - private val energyExtractor = BatteryBankEnergy(BankMode.EXTRACT) - private val energy = BatteryBankEnergy(BankMode.BIDIRECTIONAL) + private val energyReceiver = BatteryBankEnergy(FlowDirection.INPUT) + private val energyExtractor = BatteryBankEnergy(FlowDirection.OUTPUT) + private val energy = BatteryBankEnergy(FlowDirection.BI_DIRECTIONAL) private var resolverEnergyReceiver = LazyOptional.of { energyReceiver } private var resolverEnergyExtractor = LazyOptional.of { energyExtractor } @@ -347,14 +329,14 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte val diff = it.receiveEnergy(maxThroughput, true) if (!diff.isZero) { - val newExtract = energy.extractEnergyInner(diff, true) + val newExtract = energy.extractEnergy(diff, true) val newReceive = it.receiveEnergy(newExtract, true) - val extracted = energy.extractEnergyInner(newReceive, false) + val extracted = energy.extractEnergy(newReceive, false) val received = it.receiveEnergy(extracted, false) if (received < extracted) { - energy.receiveEnergyInner(extracted - received, false) + energy.receiveEnergy(extracted - received, false) } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/ChemicalGeneratorBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/ChemicalGeneratorBlockEntity.kt index 3a492a89c..b46a5e0d9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/ChemicalGeneratorBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/ChemicalGeneratorBlockEntity.kt @@ -165,18 +165,18 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryBl private var check = true private fun workWithPower(it: IEnergyStorage) { - val extracted = energy.extractEnergyInner(THROUGHPUT, true) + val extracted = energy.extractEnergy(THROUGHPUT, true) val received = it.receiveEnergy(extracted, false) if (!received.isZero) { - energy.extractEnergyInner(received, false) + energy.extractEnergy(received, false) } } fun tick() { if (workTicks > 0) { workTicks-- - energy.receiveEnergyInner(GENERATION_SPEED, false) + energy.receiveEnergy(GENERATION_SPEED, false) if (workTicks == 0) { workTicksTotal = 0 diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/EnergyCounterBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/EnergyCounterBlockEntity.kt index 98f6e9488..07a1e3ce2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/EnergyCounterBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/EnergyCounterBlockEntity.kt @@ -126,11 +126,10 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat tickOnceServer(this::checkSurroundings) } - private inner class EnergyCounterCap(val isInput: Boolean) : IMatteryEnergyStorage { - override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal { - if (isInput) - return Decimal.ZERO + private inner class EnergyCounterCap(isInput: Boolean) : IMatteryEnergyStorage { + override val energyFlow = FlowDirection.input(isInput) + override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal { if (inputCapability.isPresent) { val it = inputCapability.resolve().get() @@ -156,9 +155,6 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat } override fun receiveEnergy(howMuch: Decimal, simulate: Boolean): Decimal { - if (!isInput) - return Decimal.ZERO - if (outputCapability.isPresent) { val it = outputCapability.resolve().get() @@ -188,7 +184,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat override var batteryLevel: Decimal get() { - if (isInput) { + if (energyFlow.input) { if (outputCapability.isPresent) { val it = outputCapability.resolve().get() @@ -218,7 +214,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat override val maxBatteryLevel: Decimal get() { - if (isInput) { + if (energyFlow.input) { if (outputCapability.isPresent) { val it = outputCapability.resolve().get() @@ -245,7 +241,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat override val missingPower: Decimal get() { - if (isInput) { + if (energyFlow.input) { if (outputCapability.isPresent) { val it = outputCapability.resolve().get() @@ -269,9 +265,6 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat return Decimal.ZERO } - - override fun canExtract() = !isInput - override fun canReceive() = isInput } private var resolverInput = LazyOptional.of { energyInput } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/EnergyServoBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/EnergyServoBlockEntity.kt index 3c71756bf..7fcebc2a6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/EnergyServoBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/EnergyServoBlockEntity.kt @@ -14,6 +14,7 @@ import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.common.util.LazyOptional import ru.dbotthepony.mc.otm.block.IDroppableContainer +import ru.dbotthepony.mc.otm.capability.FlowDirection import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.canSetBatteryMattery @@ -59,6 +60,12 @@ class EnergyServoBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matte }) val energy = object : IMatteryEnergyStorage { + override val energyFlow: FlowDirection get() { + val discharge = container[SLOT_DISCHARGE].energy + val charge = container[SLOT_CHARGE].energy + return FlowDirection.of(input = charge?.canReceive() ?: false, output = discharge?.canExtract() ?: false) + } + override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal { return container[SLOT_DISCHARGE].energy?.extractEnergy(howMuch, simulate) ?: Decimal.ZERO } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryPoweredBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryPoweredBlockEntity.kt index 28745406e..bd1485eee 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryPoweredBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryPoweredBlockEntity.kt @@ -32,18 +32,8 @@ abstract class MatteryPoweredBlockEntity(p_155228_: BlockEntityType<*>, p_155229 val batteryContainer = MatteryContainer(this::setChangedLight, 1) protected fun batteryChargeLoop() { - var hit = false - - for (stack in batteryContainer) { - if (!stack.isEmpty) { - hit = true - break - } - } - - if (!hit) { + if (!batteryContainer.any { !it.isEmpty }) return - } var demand = energy.receiveEnergy(energy.missingPower, true) if (demand.isZero) return @@ -51,15 +41,9 @@ abstract class MatteryPoweredBlockEntity(p_155228_: BlockEntityType<*>, p_155229 for (stack in batteryContainer) { if (!stack.isEmpty) { stack.getCapability(ForgeCapabilities.ENERGY).ifPresentK { - if (it is IMatteryEnergyStorage) { - val diff = it.extractEnergy(demand, false) - energy.receiveEnergyInner(diff, false) - demand -= diff - } else { - val diff = it.extractEnergy(demand, false) - energy.receiveEnergyInner(diff, false) - demand -= diff - } + val diff = it.extractEnergy(demand, false) + energy.receiveEnergy(diff, false) + demand -= diff } if (demand <= Decimal.ZERO) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryWorkerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryWorkerBlockEntity.kt index e9486f406..ed475cf53 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryWorkerBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryWorkerBlockEntity.kt @@ -303,7 +303,7 @@ abstract class MatteryWorkerBlockEntity( ticksAdvanced = availableTicks.coerceAtMost(ticksLeft) } else { requiredPower = currentJob.powerUsage * ticksLeft.coerceAtMost(availableTicks) - extractedPower = energy.extractEnergyInner(requiredPower, true) + extractedPower = energy.extractEnergy(requiredPower, true) ticksAdvanced = (extractedPower / requiredPower).toDouble().coerceAtMost(ticksLeft).coerceAtMost(availableTicks) } @@ -333,7 +333,7 @@ abstract class MatteryWorkerBlockEntity( extractedPower = status.newDrainedPower ?: extractedPower if (extractedPower != null) { - energy.extractEnergyInner(extractedPower, false) + energy.extractEnergy(extractedPower, false) } continue 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 430890983..24e02c22f 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 @@ -115,7 +115,7 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : }) val matter: MatterStorageImpl = object : MatterStorageImpl(this::setChangedLight, FlowDirection.BI_DIRECTIONAL, ::CAPACITY) { - override val matterDirection: FlowDirection get() { + override val matterFlow: FlowDirection get() { return if (this@MatterBottlerBlockEntity.isBottling) FlowDirection.INPUT else FlowDirection.OUTPUT } } @@ -241,7 +241,7 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : if (!itemStack.isEmpty) { val cap = itemStack.getCapability(MatteryCapability.MATTER).orNull() ?: continue - if (cap.matterDirection != unexpectedDirection) { + if (cap.matterFlow != unexpectedDirection) { if (this.isBottling && cap.missingMatter > Decimal.ZERO || !this.isBottling && cap.storedMatter > Decimal.ZERO) { work_stack = itemStack capability = cap @@ -280,13 +280,13 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : } if (matter.storedMatter > Decimal.ZERO) { - val energyExtracted = energy.extractEnergyInner(ENERGY_CONSUMPTION, true) + val energyExtracted = energy.extractEnergy(ENERGY_CONSUMPTION, true) if (!energyExtracted.isZero) { val matter = capability.receiveMatter(MATTER_EXCHANGE_RATE.coerceAtMost(matter.storedMatter) * energyExtracted / ENERGY_CONSUMPTION, true) if (!matter.isZero) { - energy.extractEnergyInner(ENERGY_CONSUMPTION * matter / MATTER_EXCHANGE_RATE, false) + energy.extractEnergy(ENERGY_CONSUMPTION * matter / MATTER_EXCHANGE_RATE, false) capability.receiveMatter(matter, false) this.matter.extractMatterInner(matter, false) @@ -304,13 +304,13 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : } } } else { - val energyExtracted = energy.extractEnergyInner(ENERGY_CONSUMPTION, true) + val energyExtracted = energy.extractEnergy(ENERGY_CONSUMPTION, true) if (!energyExtracted.isZero) { val matter = capability.extractMatter(MATTER_EXCHANGE_RATE.coerceAtMost(matter.missingMatter) * energyExtracted / ENERGY_CONSUMPTION, true) if (!matter.isZero) { - this.energy.extractEnergyInner(ENERGY_CONSUMPTION * matter / MATTER_EXCHANGE_RATE,false) + this.energy.extractEnergy(ENERGY_CONSUMPTION * matter / MATTER_EXCHANGE_RATE,false) capability.extractMatter(matter, false) this.matter.receiveMatterInner(matter, false) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterCapacitorBankBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterCapacitorBankBlockEntity.kt index 0027a851f..7f1502cff 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterCapacitorBankBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterCapacitorBankBlockEntity.kt @@ -128,7 +128,7 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) return summ } - override val matterDirection: FlowDirection + override val matterFlow: FlowDirection get() = FlowDirection.BI_DIRECTIONAL private var resolver = LazyOptional.of { this } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt index c6825d7f7..034c23628 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt @@ -484,7 +484,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter return stack val maxPossibleDemand = ITEM_STORAGE.energyPerOperation * stack.count - val maxExtractEnergy = energy.extractEnergyInner(maxPossibleDemand, true) + val maxExtractEnergy = energy.extractEnergy(maxPossibleDemand, true) var leftover: ItemStackWrapper = stack.copy() var additional: BigInteger = BigInteger.ZERO @@ -499,7 +499,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter leftover = ItemStackWrapper(parent.insertItem(slot, leftover.stack, simulate)) if (oldCount != leftover.count && !simulate) { - energy.extractEnergyInner(ITEM_STORAGE.energyPerOperation * (oldCount - leftover.count), false) + energy.extractEnergy(ITEM_STORAGE.energyPerOperation * (oldCount - leftover.count), false) if (scanned.size <= slot) { sizeScan() @@ -529,7 +529,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter return ItemStackWrapper.EMPTY val maxPossibleDemand = ITEM_STORAGE.energyPerOperation * amount - val maxExtractEnergy = energy.extractEnergyInner(maxPossibleDemand, true) + val maxExtractEnergy = energy.extractEnergy(maxPossibleDemand, true) @Suppress("NAME_SHADOWING") var amount = amount @@ -555,7 +555,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter totalExtracted += extracted.count if (extracted.count != 0 && !simulate) { - energy.extractEnergyInner(ITEM_STORAGE.energyPerOperation * extracted.count, false) + energy.extractEnergy(ITEM_STORAGE.energyPerOperation * extracted.count, false) } if (totalExtracted >= intAmount) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageInterfaces.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageInterfaces.kt index a5627ce0d..e9d20036c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageInterfaces.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageInterfaces.kt @@ -23,6 +23,7 @@ import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity import ru.dbotthepony.mc.otm.capability.* import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage +import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact import ru.dbotthepony.mc.otm.container.ItemFilter import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.graph.Graph6Node @@ -187,7 +188,7 @@ class StorageImporterBlockEntity(blockPos: BlockPos, blockState: BlockState) return stack val view = cell.storageGraph?.getVirtualComponent(ITEM_STORAGE) ?: return stack - val maxMove = energy.extractStepInnerBi(ITEM_STORAGE.energyPerOperation, stack.count, true) + val maxMove = energy.extractEnergyExact(ITEM_STORAGE.energyPerOperation, stack.count.toBigInteger(), true) if (maxMove == BigInteger.ZERO) return stack @@ -197,7 +198,7 @@ class StorageImporterBlockEntity(blockPos: BlockPos, blockState: BlockState) if (simulate) return leftover.stack - energy.extractStepInner(ITEM_STORAGE.energyPerOperation, maxMove - leftover.count, false) + energy.extractEnergyExact(ITEM_STORAGE.energyPerOperation, maxMove - leftover.count, false) return leftover.stack } @@ -229,7 +230,7 @@ class StorageImporterBlockEntity(blockPos: BlockPos, blockState: BlockState) lastSlot = 0 } - val maxMove = energy.extractStepInner(ITEM_STORAGE.energyPerOperation, MAX_MOVE_PER_OPERATION, true) + val maxMove = energy.extractEnergyExact(ITEM_STORAGE.energyPerOperation, MAX_MOVE_PER_OPERATION, true) var extracted = resolved.extractItem(lastSlot, maxMove, true) if (extracted.isEmpty || !filter.match(extracted)) { @@ -239,7 +240,7 @@ class StorageImporterBlockEntity(blockPos: BlockPos, blockState: BlockState) if (leftOver.count.toInt() != extracted.count) { extracted = resolved.extractItem(lastSlot, extracted.count - leftOver.count.toInt(), false) - energy.extractStepInner(ITEM_STORAGE.energyPerOperation, extracted.count, false) + energy.extractEnergyExact(ITEM_STORAGE.energyPerOperation, extracted.count, false) items.insertStack(ItemStackWrapper(extracted), false) } else { nextTick += INTERVAL * 4 @@ -353,7 +354,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) : continue } - var exportAmount = energy.extractStepInner(ITEM_STORAGE.energyPerOperation, exportAmountA, true) + var exportAmount = energy.extractEnergyExact(ITEM_STORAGE.energyPerOperation, exportAmountA, true).toIntSafe() if (exportAmount == 0) { break @@ -365,7 +366,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) : hit = true exportAmount = items.extractStack(stack.first, (exportAmount - leftover.count).toBigInteger(), false).count.toInt() resolved.insertItem(lastSlot, stack.second.stack.also { it.count = exportAmount }, false) - energy.extractStepInner(ITEM_STORAGE.energyPerOperation, exportAmount, false) + energy.extractEnergyExact(ITEM_STORAGE.energyPerOperation, exportAmount, false) break } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StoragePowerSupplierBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StoragePowerSupplierBlockEntity.kt index 3b216607b..cee292844 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StoragePowerSupplierBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StoragePowerSupplierBlockEntity.kt @@ -18,6 +18,7 @@ import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage +import ru.dbotthepony.mc.otm.capability.energy.transferChecked import ru.dbotthepony.mc.otm.core.Decimal import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph @@ -103,13 +104,13 @@ class StoragePowerSupplierBlockEntity(blockPos: BlockPos, blockState: BlockState return } else if (demand < available) { for (demanding in graph.powerDemandingNodes) { - powerPassed += energy.transferInner(demanding, available, false) + powerPassed += energy.transferChecked(demanding, available, false) } } else { val forEach = available / i for (demanding in graph.powerDemandingNodes) { - powerPassed += energy.transferInner(demanding, forEach, false) + powerPassed += energy.transferChecked(demanding, forEach, false) } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/Ext.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/Ext.kt index 85558a9a4..26871d5a0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/Ext.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/Ext.kt @@ -30,9 +30,12 @@ import java.util.stream.Stream val ICapabilityProvider.matteryPlayer: MatteryPlayerCapability? get() = getCapability(MatteryCapability.MATTERY_PLAYER).orNull() -fun IEnergyStorage.receiveEnergy(amount: Decimal, simulate: Boolean): Decimal { +/** + * Does a checked energy receive, calls [IMatteryEnergyStorage.receiveEnergyChecked] if possible + */ +internal fun IEnergyStorage.receiveEnergy(amount: Decimal, simulate: Boolean): Decimal { if (this is IMatteryEnergyStorage) - return receiveEnergy(amount, simulate) + return receiveEnergyChecked(amount, simulate) if (!amount.isPositive) return Decimal.ZERO @@ -43,9 +46,12 @@ fun IEnergyStorage.receiveEnergy(amount: Decimal, simulate: Boolean): Decimal { return Decimal.valueOf(receiveEnergy(amount.toInt(), simulate)) } -fun IEnergyStorage.extractEnergy(amount: Decimal, simulate: Boolean): Decimal { +/** + * Does a checked energy extraction, calls [IMatteryEnergyStorage.extractEnergyChecked] if possible + */ +internal fun IEnergyStorage.extractEnergy(amount: Decimal, simulate: Boolean): Decimal { if (this is IMatteryEnergyStorage) - return extractEnergy(amount, simulate) + return extractEnergyChecked(amount, simulate) if (!amount.isPositive) return Decimal.ZERO diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/FlowDirection.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/FlowDirection.kt index d84501e38..e13186bf6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/FlowDirection.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/FlowDirection.kt @@ -4,6 +4,21 @@ import java.util.function.Predicate /** * Represents possible flow direction, both for matter and for energy + * + * To dynamically get this enum by two booleans (by input and output states), use [FlowDirection.of] + * + * Also, this enum implements [Predicate], you can check incoming flow direction for "compatibility" with + * this flow direction, more precisely: + * [test] will return true and only true if [input] and [output] of incoming flow are assignable to this flow + * + * Example: + * * `INPUT.test(OUTPUT)` = `false` + * * `OUTPUT.test(INPUT)` = `false` + * * `INPUT.test(BI_DIRECTIONAL)` = `true` + * * `OUTPUT.test(BI_DIRECTIONAL)` = `true` + * * `BI_DIRECTIONAL.test(BI_DIRECTIONAL)` = `true` + * * `BI_DIRECTIONAL.test(OUTPUT)` = `false` + * * `BI_DIRECTIONAL.test(INPUT)` = `false` */ enum class FlowDirection(val input: Boolean, val output: Boolean) : Predicate { /** @@ -29,4 +44,51 @@ enum class FlowDirection(val input: Boolean, val output: Boolean) : Predicate { + override val energyFlow: FlowDirection + get() = FlowDirection.INPUT + private var battery by synchronizer.fraction(initialCharge, name = "android battery") private var maxBattery by synchronizer.fraction(maxCharge, name = "android max battery") diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/BlockEnergyStorageImpl.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/BlockEnergyStorageImpl.kt index 3f66c38b7..0da6d774e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/BlockEnergyStorageImpl.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/BlockEnergyStorageImpl.kt @@ -25,7 +25,7 @@ import ru.dbotthepony.mc.otm.core.set sealed class BlockEnergyStorageImpl( protected val listener: () -> Unit, - final override val direction: FlowDirection, + final override val energyFlow: FlowDirection, private val maxBatteryLevelProvider: () -> Decimal, private val maxInputProvider: () -> Decimal?, private val maxOutputProvider: () -> Decimal?, @@ -78,20 +78,6 @@ sealed class BlockEnergyStorageImpl( } override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal { - if (direction == FlowDirection.INPUT) - return Decimal.ZERO - - return extractEnergyInner(howMuch, simulate) - } - - override fun receiveEnergy(howMuch: Decimal, simulate: Boolean): Decimal { - if (direction == FlowDirection.OUTPUT) - return Decimal.ZERO - - return receiveEnergyInner(howMuch, simulate) - } - - override fun extractEnergyInner(howMuch: Decimal, simulate: Boolean): Decimal { if (!howMuch.isPositive) return Decimal.ZERO @@ -116,7 +102,7 @@ sealed class BlockEnergyStorageImpl( return diff } - override fun receiveEnergyInner(howMuch: Decimal, simulate: Boolean): Decimal { + override fun receiveEnergy(howMuch: Decimal, simulate: Boolean): Decimal { if (!howMuch.isPositive) return Decimal.ZERO @@ -141,14 +127,6 @@ sealed class BlockEnergyStorageImpl( return diff } - override fun canExtract(): Boolean { - return direction != FlowDirection.INPUT - } - - override fun canReceive(): Boolean { - return direction != FlowDirection.OUTPUT - } - override fun serializeNBT(): CompoundTag { val tag = CompoundTag() tag[ENERGY_STORED_KEY] = batteryLevel.serializeNBT() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/IEnergyStorageImpl.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/IEnergyStorageImpl.kt index 56f0063c6..5deb39c5f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/IEnergyStorageImpl.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/IEnergyStorageImpl.kt @@ -12,77 +12,6 @@ import java.math.BigInteger sealed interface IEnergyStorageImpl { val maxInput: Decimal? val maxOutput: Decimal? - val direction: FlowDirection - - fun extractEnergyInner(howMuch: Decimal, simulate: Boolean): Decimal - fun receiveEnergyInner(howMuch: Decimal, simulate: Boolean): Decimal - - fun extractStepInner(base: Decimal, multiplier: Int, simulate: Boolean): Int { - return (extractEnergyInner(base * multiplier, simulate) / base).toInt() - } - - fun extractStepInnerBi(base: Decimal, multiplier: Int, simulate: Boolean): BigInteger { - return (extractEnergyInner(base * multiplier, simulate) / base).whole - } - - fun extractStepInner(base: Decimal, multiplier: BigInteger, simulate: Boolean): Int { - return (extractEnergyInner(base * multiplier, simulate) / base).toInt() - } - - fun extractStepInnerBi(base: Decimal, multiplier: BigInteger, simulate: Boolean): BigInteger { - return (extractEnergyInner(base * multiplier, simulate) / base).whole - } - - fun transferInner(other: IMatteryEnergyStorage, amount: Decimal, simulate: Boolean): Decimal { - if (!amount.isPositive) - return Decimal.ZERO - - val extracted = extractEnergyInner(amount, true) - val received = other.receiveEnergy(extracted, simulate) - - if (!simulate) - extractEnergyInner(received, false) - - return received - } - - /** - * All or nothing - * - * @return energy accepted - */ - fun extractEnergyInnerExact(howMuch: Decimal, simulate: Boolean): Decimal { - val extracted = extractEnergyInner(howMuch, true) - - if (extracted != howMuch) { - return Decimal.ZERO - } - - if (!simulate) { - extractEnergyInner(howMuch, false) - } - - return extracted - } - - /** - * All or nothing - * - * @return energy accepted - */ - fun receiveEnergyInnerExact(howMuch: Decimal, simulate: Boolean): Decimal { - val extracted = receiveEnergyInner(howMuch, true) - - if (extracted != howMuch) { - return Decimal.ZERO - } - - if (!simulate) { - receiveEnergyInner(howMuch, false) - } - - return extracted - } } internal fun batteryLevel(it: IEnergyStorage, tooltips: MutableList) { @@ -103,7 +32,7 @@ internal fun batteryLevel(it: IMatteryEnergyStorage, tooltips: MutableList { if (it.maxInput != null) { tooltips.add( diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/IMatteryEnergyStorage.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/IMatteryEnergyStorage.kt index be89b76b3..2e6986c6b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/IMatteryEnergyStorage.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/IMatteryEnergyStorage.kt @@ -1,29 +1,99 @@ package ru.dbotthepony.mc.otm.capability.energy import net.minecraftforge.energy.IEnergyStorage +import ru.dbotthepony.mc.otm.capability.FlowDirection import ru.dbotthepony.mc.otm.core.Decimal import ru.dbotthepony.mc.otm.core.RGBAColor import java.math.BigInteger import kotlin.math.roundToInt /** - * Energy interface in Overdrive That Matters, which is backward compatible with [IEnergyStorage] + * Energy interface in Overdrive That Matters, which also implements backward compatible methods to implement [IEnergyStorage] + * + * Details of this energy system are as follows: + * * [extractEnergy] and [receiveEnergy] are *unchecked*, which means, they will generally work regardless of energy storage type ([energyFlow]), be it tool, battery or generator. + * What this means is that, despite making no sense to use tool as a battery in machine, [extractEnergy] will work regardless. + * To avoid such cases, [extractEnergyChecked] and [receiveEnergyChecked] are provided + * * Instead of [canReceive] and [canExtract] of [IEnergyStorage], this interface employs [energyFlow] enum property, which is cleaner and easier to use, + * see [FlowDirection] for details + * * This interface allows to set energy stored *directly*. With great power comes great responsibility though, since, sometimes it is technically + * cumbersome or straight up impossible to set stored energy value, therefore, setter of [batteryLevel] is free to throw [UnsupportedOperationException]. + * To avoid try/catch block, check [canSetBatteryLevel] property first + * * Due to limitations of setting [batteryLevel] directly, two methods are also provided: [fillBattery] and [drainBattery]. If you ever + * need to only fill or drain this energy storage, call these two methods and do not use [batteryLevel] directly. + * * Lastly, there is [missingPower]. It returns whatever it has in name. What it makes better than writing your own "[maxBatteryLevel] - [batteryLevel]" logic is that + * implementations can use different and more precise logic to determine actually missing power. **Please use [missingPower] instead of writing your own logic to determine + * whenever storage is missing energy, it will make players not experience silly bugs and make you avoid headaches**. */ interface IMatteryEnergyStorage : IEnergyStorage { /** - * Energy extraction by external interacts + * Extracts up to [howMuch] energy from this storage + * + * In general, this method *does not* obey [energyFlow] and will allow to extract energy + * even if [energyFlow] and [canExtract] say otherwise, unlike [IEnergyStorage.extractEnergy], which, in general, + * obeys return value of [IEnergyStorage.canExtract]. + * + * Therefore, if you want/need to obey [energyFlow], use [extractEnergyChecked] + * + * General contracts: + * * Negative values are not allowed, failing to comply with this contract will result in undefined behavior (worst case) or exception (best case) + * * Returned value CAN NOT be bigger than requested [howMuch], implementations failing to obey this contract will cause undefined behavior in upstream code. + * Upstream code SHOULD NOT check for this contract. * * @return energy extracted */ fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal /** - * Energy insertion by external interacts + * Extracts up to [howMuch] energy from this storage, while obeying [energyFlow]. See [extractEnergy]. * - * @return energy accepted + * Interface implementations generally do not need to override this. + * + * @return energy extracted + */ + fun extractEnergyChecked(howMuch: Decimal, simulate: Boolean): Decimal { + require(!howMuch.isNegative) { "Negative amount of energy: $howMuch" } + + if (!energyFlow.output) + return Decimal.ZERO + + return extractEnergy(howMuch, simulate) + } + + /** + * Inserts up to [howMuch] energy into this storage + * + * In general, this method *does not* obey [energyFlow] and will allow to insert energy + * even if [energyFlow] and [canReceive] say otherwise, unlike [IEnergyStorage.receiveEnergy], which, in general, + * obeys return value of [IEnergyStorage.canReceive]. + * + * Therefore, if you want/need to obey [energyFlow], use [receiveEnergyChecked] + * + * General contracts: + * * Negative values are not allowed, failing to comply with this contract will result in undefined behavior (worst case) or exception (best case) + * * Returned value CAN NOT be bigger than requested [howMuch], implementations failing to obey this contract will cause undefined behavior in upstream code. + * Upstream code SHOULD NOT check for this contract. + * + * @return energy extracted */ fun receiveEnergy(howMuch: Decimal, simulate: Boolean): Decimal + /** + * Inserts up to [howMuch] energy into this storage, while obeying [energyFlow]. See [receiveEnergy]. + * + * Interface implementations generally do not need to override this. + * + * @return energy extracted + */ + fun receiveEnergyChecked(howMuch: Decimal, simulate: Boolean): Decimal { + require(!howMuch.isNegative) { "Negative amount of energy: $howMuch" } + + if (!energyFlow.output) + return Decimal.ZERO + + return extractEnergy(howMuch, simulate) + } + /** * If this is false, then [batteryLevel] will throw [UnsupportedOperationException] when trying to set it */ @@ -55,26 +125,47 @@ interface IMatteryEnergyStorage : IEnergyStorage { /** * Empties power of this energy storage * - * @throws [UnsupportedOperationException] * @see batteryLevel + * @return whenever operation was successful */ - fun drainBattery() { - batteryLevel = Decimal.ZERO + fun drainBattery(): Boolean { + try { + batteryLevel = Decimal.ZERO + } catch(err: UnsupportedOperationException) { + return false + } + + return true } /** * Fully fills power in this energy storage * - * @throws [UnsupportedOperationException] * @see batteryLevel + * @return whenever operation was successful */ - fun fillBattery() { - batteryLevel = maxBatteryLevel + fun fillBattery(): Boolean { + try { + batteryLevel = maxBatteryLevel + } catch(err: UnsupportedOperationException) { + return false + } + + return true } + /** + * Flow direction of energy possible for this energy storage, see [FlowDirection] + */ + val energyFlow: FlowDirection + // -------- Forge Energy stuff override fun receiveEnergy(maxReceive: Int, simulate: Boolean): Int { + // follow contract of IEnergyStorage + if (!energyFlow.input) + return 0 + val received = receiveEnergy(Decimal(maxReceive), true).toInt() // Receiving only a fraction @@ -85,6 +176,10 @@ interface IMatteryEnergyStorage : IEnergyStorage { } override fun extractEnergy(maxReceive: Int, simulate: Boolean): Int { + // follow contract of IEnergyStorage + if (energyFlow.output) + return 0 + val extracted = extractEnergy(Decimal(maxReceive), true).toInt() // Extracting only a fraction @@ -103,14 +198,19 @@ interface IMatteryEnergyStorage : IEnergyStorage { } override fun canExtract(): Boolean { - return extractEnergy(Decimal.ONE, true) > Decimal.ZERO + return energyFlow.output } override fun canReceive(): Boolean { - return receiveEnergy(Decimal.ONE, true) > Decimal.ZERO + return energyFlow.input } } +/** + * Performs *unchecked* extraction of energy + * + * @return whenever can (or we did) extract exactly [howMuch] energy from this storage + */ fun IMatteryEnergyStorage.extractEnergyExact(howMuch: Decimal, simulate: Boolean): Boolean { if (extractEnergy(howMuch, true) == howMuch) { if (!simulate) { @@ -123,6 +223,11 @@ fun IMatteryEnergyStorage.extractEnergyExact(howMuch: Decimal, simulate: Boolean return false } +/** + * Performs *unchecked* insertion of energy + * + * @return whenever can (or we did) receive exactly [howMuch] energy into this storage + */ fun IMatteryEnergyStorage.receiveEnergyExact(howMuch: Decimal, simulate: Boolean): Boolean { if (receiveEnergy(howMuch, true) == howMuch) { if (!simulate) { @@ -135,23 +240,56 @@ fun IMatteryEnergyStorage.receiveEnergyExact(howMuch: Decimal, simulate: Boolean return false } +/** + * Performs *unchecked* extraction of energy + * + * @return how much times can (or we did) extract exactly [howMuch] * [times] energy from this storage + */ fun IMatteryEnergyStorage.extractEnergyExact(howMuch: Decimal, times: Int, simulate: Boolean): Int { if (times == 0) return 0 require(times >= 0) { "times $times >= 0" } require(howMuch >= Decimal.ZERO) { "howMuch $howMuch >= 0" } - return (extractEnergy(howMuch * times, simulate) / times).toInt() + + @Suppress("name_shadowing") + val times = (extractEnergy(howMuch * times, true) / times).toInt() + + if (simulate) + return times + + return (extractEnergy(howMuch * times, false) / times).toInt() } +/** + * Performs *unchecked* extraction of energy + * + * @return how much times can (or we did) extract exactly [howMuch] * [times] energy from this storage + */ +fun IMatteryEnergyStorage.extractEnergyExact(howMuch: Decimal, multiplier: BigInteger, simulate: Boolean): BigInteger { + return (extractEnergy(howMuch * multiplier, simulate) / howMuch).whole +} + +/** + * @see [IMatteryEnergyStorage.extractEnergy] + */ fun IMatteryEnergyStorage.extractEnergy(howMuch: Long, simulate: Boolean): Decimal { return extractEnergy(Decimal(howMuch), simulate) } +/** + * @see [IMatteryEnergyStorage.receiveEnergy] + */ fun IMatteryEnergyStorage.receiveEnergy(howMuch: Long, simulate: Boolean): Decimal { return receiveEnergy(Decimal(howMuch), simulate) } +/** + * Performs *unchecked* energy transfer from this storage to [other] + * + * @see IMatteryEnergyStorage.extractEnergy + * @see IMatteryEnergyStorage.receiveEnergy + */ fun IMatteryEnergyStorage.transfer(other: IMatteryEnergyStorage, amount: Decimal, simulate: Boolean): Decimal { if (!amount.isPositive) return Decimal.ZERO @@ -160,25 +298,28 @@ fun IMatteryEnergyStorage.transfer(other: IMatteryEnergyStorage, amount: Decimal val received = other.receiveEnergy(extracted, simulate) if (!simulate) - extractEnergy(received, false) + return extractEnergy(received, false) return received } -fun IMatteryEnergyStorage.extractStepOuter(base: Decimal, multiplier: BigInteger, simulate: Boolean): Int { - return (extractEnergy(base * multiplier, simulate) / base).toInt() -} +/** + * Performs checked energy transfer from this storage to [other] + * + * @see IMatteryEnergyStorage.extractEnergy + * @see IMatteryEnergyStorage.receiveEnergy + */ +fun IMatteryEnergyStorage.transferChecked(other: IMatteryEnergyStorage, amount: Decimal, simulate: Boolean): Decimal { + if (!amount.isPositive) + return Decimal.ZERO -fun IMatteryEnergyStorage.extractStepOuter(base: Decimal, multiplier: Int, simulate: Boolean): Int { - return (extractEnergy(base * multiplier, simulate) / base).toInt() -} + val extracted = extractEnergy(amount, true) + val received = other.receiveEnergyChecked(extracted, simulate) -fun IMatteryEnergyStorage.extractStepOuterBi(base: Decimal, multiplier: Int, simulate: Boolean): BigInteger { - return (extractEnergy(base * multiplier, simulate) / base).whole -} + if (!simulate) + return extractEnergy(received, false) -fun IMatteryEnergyStorage.extractStepOuterBi(base: Decimal, multiplier: BigInteger, simulate: Boolean): BigInteger { - return (extractEnergy(base * multiplier, simulate) / base).whole + return received } fun IMatteryEnergyStorage.getBarWidth(): Int { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/ItemEnergyStorageImpl.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/ItemEnergyStorageImpl.kt index f9440b14b..8e9331612 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/ItemEnergyStorageImpl.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/ItemEnergyStorageImpl.kt @@ -20,7 +20,7 @@ import ru.dbotthepony.mc.otm.core.set import ru.dbotthepony.mc.otm.core.tagNotNull sealed class ItemEnergyStorageImpl( - final override val direction: FlowDirection, + final override val energyFlow: FlowDirection, protected val itemStack: ItemStack, maxBatteryLevel: Decimal, maxInput: Decimal?, @@ -56,20 +56,6 @@ sealed class ItemEnergyStorageImpl( } override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal { - if (direction == FlowDirection.INPUT) - return Decimal.ZERO - - return extractEnergyInner(howMuch, simulate) - } - - override fun receiveEnergy(howMuch: Decimal, simulate: Boolean): Decimal { - if (direction == FlowDirection.OUTPUT) - return Decimal.ZERO - - return receiveEnergyInner(howMuch, simulate) - } - - override fun extractEnergyInner(howMuch: Decimal, simulate: Boolean): Decimal { if (!howMuch.isPositive || itemStack.count != 1) return Decimal.ZERO @@ -96,7 +82,7 @@ sealed class ItemEnergyStorageImpl( return diff } - override fun receiveEnergyInner(howMuch: Decimal, simulate: Boolean): Decimal { + override fun receiveEnergy(howMuch: Decimal, simulate: Boolean): Decimal { if (!howMuch.isPositive || itemStack.count != 1) return Decimal.ZERO @@ -123,14 +109,6 @@ sealed class ItemEnergyStorageImpl( return diff } - override fun canExtract(): Boolean { - return direction != FlowDirection.INPUT - } - - override fun canReceive(): Boolean { - return direction != FlowDirection.OUTPUT - } - companion object { const val ENERGY_KEY = "energy" diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/IMatterStorage.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/IMatterStorage.kt index ab0af90b0..dc70b2142 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/IMatterStorage.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/IMatterStorage.kt @@ -81,13 +81,13 @@ interface IMatterStorage { /** * Which direction does matter flows */ - val matterDirection: FlowDirection + val matterFlow: FlowDirection } inline val IMatterStorage.canExtractMatter: Boolean - get() = matterDirection.output + get() = matterFlow.output inline val IMatterStorage.canReceiveMatter: Boolean - get() = matterDirection.input + get() = matterFlow.input fun IMatterStorage.getBarWidth(): Int { return ((storedMatter / maxStoredMatter).toFloat().coerceAtLeast(0f).coerceAtMost(1f) * 13f).roundToInt() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/MatterStorageImpl.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/MatterStorageImpl.kt index 7bb3dcc36..420c03643 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/MatterStorageImpl.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/MatterStorageImpl.kt @@ -11,7 +11,7 @@ import ru.dbotthepony.mc.otm.core.set open class MatterStorageImpl @JvmOverloads constructor( protected val listener: Runnable?, - override val matterDirection: FlowDirection, + override val matterFlow: FlowDirection, protected val maxStoredMatterSupplier: () -> Decimal, protected val maxReceiveSupplier: () -> Decimal? = { null }, protected val maxExtractSupplier: () -> Decimal? = maxReceiveSupplier diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/mekanism/Power.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/mekanism/Power.kt index 42dacc61d..d2b6e4e66 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/mekanism/Power.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/mekanism/Power.kt @@ -10,6 +10,7 @@ import net.minecraftforge.common.capabilities.ICapabilityProvider import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.energy.IEnergyStorage import org.apache.logging.log4j.LogManager +import ru.dbotthepony.mc.otm.capability.FlowDirection import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.isMekanismLoaded @@ -70,8 +71,7 @@ private val mtj2Mekanism by DoubleLazy lazy@{ return@lazy lazyOf(Decimal.ONE) } -class Mekanism2MatteryEnergyWrapper(private val power: IStrictEnergyHandler, private val forgePower: IEnergyStorage? = null) : - IMatteryEnergyStorage { +class Mekanism2MatteryEnergyWrapper(private val power: IStrictEnergyHandler, private val forgePower: IEnergyStorage? = null) : IMatteryEnergyStorage { override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal { val action = when (simulate) { true -> Action.SIMULATE @@ -121,19 +121,8 @@ class Mekanism2MatteryEnergyWrapper(private val power: IStrictEnergyHandler, pri return sum * mekanism2MtJ } - override fun canExtract(): Boolean { - if (forgePower != null) - return forgePower.canExtract() - - return super.canExtract() - } - - override fun canReceive(): Boolean { - if (forgePower != null) - return forgePower.canReceive() - - return super.canReceive() - } + override val energyFlow: FlowDirection + get() = FlowDirection.of(output = forgePower?.canExtract() ?: power.extractEnergy(FloatingLong.MAX_VALUE, Action.SIMULATE).greaterThan(FloatingLong.ZERO), input = forgePower?.canReceive() ?: power.insertEnergy(FloatingLong.MAX_VALUE, Action.SIMULATE).greaterThan(FloatingLong.ZERO)) } class Mattery2MekanismEnergyWrapper(private val power: IMatteryEnergyStorage) : IStrictEnergyHandler { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/graph/matter/MatterNetworkGraph.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/matter/MatterNetworkGraph.kt index 163bfb788..4e7ca9b03 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/graph/matter/MatterNetworkGraph.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/matter/MatterNetworkGraph.kt @@ -80,7 +80,7 @@ class MatterNetworkGraph : Abstract6Graph(), IMatterGraphListe for (node in nodes) { val matter = node.value.getMatterHandler() - if (matter != null && matter.matterDirection == FlowDirection.BI_DIRECTIONAL) { + if (matter != null && matter.matterFlow == FlowDirection.BI_DIRECTIONAL) { level += matter.storedMatter } } @@ -94,7 +94,7 @@ class MatterNetworkGraph : Abstract6Graph(), IMatterGraphListe for (node in nodes) { val matter = node.value.getMatterHandler() - if (matter != null && matter.matterDirection == FlowDirection.BI_DIRECTIONAL) { + if (matter != null && matter.matterFlow == FlowDirection.BI_DIRECTIONAL) { level += matter.maxStoredMatter } } @@ -137,7 +137,7 @@ class MatterNetworkGraph : Abstract6Graph(), IMatterGraphListe for (node in nodes) { val matter = node.value.getMatterHandler() - if (matter != null && matter.matterDirection == FlowDirection.BI_DIRECTIONAL) { + if (matter != null && matter.matterFlow == FlowDirection.BI_DIRECTIONAL) { val value = matter.receiveMatter(howMuch, simulate) howMuch -= value received += value @@ -161,7 +161,7 @@ class MatterNetworkGraph : Abstract6Graph(), IMatterGraphListe for (node in nodes) { val matter = node.value.getMatterHandler() - if (matter != null && matter.matterDirection != FlowDirection.OUTPUT) { + if (matter != null && matter.matterFlow != FlowDirection.OUTPUT) { val value = matter.receiveMatter(howMuch, simulate) howMuch -= value received += value diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/BatteryItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/BatteryItem.kt index d5d6617df..5ae18f6a0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/BatteryItem.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/BatteryItem.kt @@ -29,14 +29,14 @@ import kotlin.math.roundToInt open class BatteryItem : Item { private inner class Power(stack: ItemStack) : EnergyCapacitorItem(stack, this@BatteryItem.capacity, this@BatteryItem.receive, this@BatteryItem.extract, initialBatteryLevel = this@BatteryItem.initialBatteryLevel) { - override fun extractEnergyInner(howMuch: Decimal, simulate: Boolean): Decimal { + override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal { if (isCreative) return howMuch - return super.extractEnergyInner(howMuch, simulate) + return super.extractEnergy(howMuch, simulate) } - override fun receiveEnergyInner(howMuch: Decimal, simulate: Boolean): Decimal { + override fun receiveEnergy(howMuch: Decimal, simulate: Boolean): Decimal { if (isCreative) return howMuch - return super.receiveEnergyInner(howMuch, simulate) + return super.receiveEnergy(howMuch, simulate) } override val missingPower: Decimal get() { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/MatterCapacitorItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/MatterCapacitorItem.kt index 4475dec6f..4eda3a7e9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/MatterCapacitorItem.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/MatterCapacitorItem.kt @@ -76,7 +76,7 @@ class MatterCapacitorItem : Item { return diff } - override val matterDirection = FlowDirection.BI_DIRECTIONAL + override val matterFlow = FlowDirection.BI_DIRECTIONAL } private val _capacity: () -> Decimal diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/QuantumBatteryItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/QuantumBatteryItem.kt index 0edcffd73..2772269ce 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/QuantumBatteryItem.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/QuantumBatteryItem.kt @@ -78,6 +78,9 @@ class QuantumBatteryItem : Item { private val resolver = LazyOptional.of { this } private val resolverMekanism = if (isMekanismLoaded) LazyOptional.of { Mattery2MekanismEnergyWrapper(this) } else null + override val energyFlow: FlowDirection + get() = FlowDirection.BI_DIRECTIONAL + var data = Data() override fun getCapability(cap: Capability, side: Direction?): LazyOptional { @@ -225,14 +228,6 @@ class QuantumBatteryItem : Item { override val missingPower: Decimal get() = if (isCreative) Decimal.LONG_MAX_VALUE else super.missingPower - override fun canExtract(): Boolean { - return true - } - - override fun canReceive(): Boolean { - return true - } - private fun determineQuantumLink() { if (data.parent == null && isServerThread()) { val existing = stack.tag?.getInt("link_id") diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/PlasmaRifleItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/PlasmaRifleItem.kt index 6ce5b81e0..4035fc729 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/PlasmaRifleItem.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/PlasmaRifleItem.kt @@ -50,7 +50,7 @@ class PlasmaRifleItem : PlasmaWeaponItem(PlasmaWeaponData ) if (!player.abilities.instabuild) - energyData(itemStack).extractEnergyInner(ENERGY_PER_SHOT, false) + energyData(itemStack).extractEnergy(ENERGY_PER_SHOT, false) return true } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/PlasmaWeaponItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/PlasmaWeaponItem.kt index 765b62947..2bd11a3ff 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/PlasmaWeaponItem.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/PlasmaWeaponItem.kt @@ -24,11 +24,13 @@ import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.registry.MSoundEvents import kotlin.reflect.KClass -class PlasmaWeaponEnergy(val itemStack: ItemStack, private val innerCapacity: Decimal) : - IMatteryEnergyStorage, ICapabilityProvider, INBTSerializable { +class PlasmaWeaponEnergy(val itemStack: ItemStack, private val innerCapacity: Decimal) : IMatteryEnergyStorage, ICapabilityProvider, INBTSerializable { private val energyResolver = LazyOptional.of { this } private var innerBatteryLevel = Decimal.ZERO + override val energyFlow: FlowDirection + get() = FlowDirection.INPUT + var battery: ItemStack = ItemStack.EMPTY override fun getCapability(cap: Capability, side: Direction?): LazyOptional { @@ -52,10 +54,6 @@ class PlasmaWeaponEnergy(val itemStack: ItemStack, private val innerCapacity: De } override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal { - return Decimal.ZERO - } - - fun extractEnergyInner(howMuch: Decimal, simulate: Boolean): Decimal { if (!howMuch.isPositive) return Decimal.ZERO @@ -129,20 +127,28 @@ class PlasmaWeaponEnergy(val itemStack: ItemStack, private val innerCapacity: De } } - override fun canExtract(): Boolean { - return false - } + override fun drainBattery(): Boolean { + innerBatteryLevel = Decimal.ZERO + + if (!battery.isEmpty) { + battery.getCapability(MatteryCapability.ENERGY).ifPresentK { + return it.drainBattery() + } + } - override fun canReceive(): Boolean { return true } - override fun drainBattery() { - innerBatteryLevel = Decimal.ZERO - } - - override fun fillBattery() { + override fun fillBattery(): Boolean { innerBatteryLevel = innerCapacity + + if (!battery.isEmpty) { + battery.getCapability(MatteryCapability.ENERGY).ifPresentK { + return it.fillBattery() + } + } + + return true } override var batteryLevel: Decimal diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/AndroidStationMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/AndroidStationMenu.kt index c1a8c141c..99e112c41 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/AndroidStationMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/AndroidStationMenu.kt @@ -56,7 +56,7 @@ class AndroidStationMenu @JvmOverloads constructor( if (p_18942_ != 0 || powerWidget.level < AndroidStationBlockEntity.ENERGY_PER_OPERATION || item.isEmpty) return ItemStack.EMPTY - (tile as AndroidStationBlockEntity).energy.extractEnergyInner(AndroidStationBlockEntity.ENERGY_PER_OPERATION, false) + (tile as AndroidStationBlockEntity).energy.extractEnergy(AndroidStationBlockEntity.ENERGY_PER_OPERATION, false) return removeItemNoUpdate(p_18942_) } @@ -73,7 +73,7 @@ class AndroidStationMenu @JvmOverloads constructor( if (p_18944_ != 0) return - (tile as AndroidStationBlockEntity).energy.extractEnergyInner(AndroidStationBlockEntity.ENERGY_PER_OPERATION, false) + (tile as AndroidStationBlockEntity).energy.extractEnergy(AndroidStationBlockEntity.ENERGY_PER_OPERATION, false) item = p_18945_ } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/Slots.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/Slots.kt index 2910de8d0..7eac16375 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/Slots.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/Slots.kt @@ -48,7 +48,7 @@ open class MatterContainerInputSlot @JvmOverloads constructor( override fun mayPlace(itemStack: ItemStack): Boolean { val handler = itemStack.getCapability(MatteryCapability.MATTER).resolve() if (handler.isEmpty) return false - return super.mayPlace(itemStack) && this.direction.test(handler.get().matterDirection) + return super.mayPlace(itemStack) && this.direction.test(handler.get().matterFlow) } }