Redo mattery energy storage
This commit is contained in:
parent
9073ae1b08
commit
b9cb5db9ac
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,17 +72,10 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
|
||||
)
|
||||
|
||||
private data class BatteryBankDistribution(val distribution: Array<Decimal>, 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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<IMatteryEnergyStorage> { energyInput }
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -303,7 +303,7 @@ abstract class MatteryWorkerBlockEntity<JobType : MatteryWorkerBlockEntity.Job>(
|
||||
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<JobType : MatteryWorkerBlockEntity.Job>(
|
||||
extractedPower = status.newDrainedPower ?: extractedPower
|
||||
|
||||
if (extractedPower != null) {
|
||||
energy.extractEnergyInner(extractedPower, false)
|
||||
energy.extractEnergy(extractedPower, false)
|
||||
}
|
||||
|
||||
continue
|
||||
|
@ -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)
|
||||
|
@ -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 }
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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<FlowDirection> {
|
||||
/**
|
||||
@ -29,4 +44,51 @@ enum class FlowDirection(val input: Boolean, val output: Boolean) : Predicate<Fl
|
||||
override fun test(t: FlowDirection): Boolean {
|
||||
return t === this || (!input || t.input) && (!output || t.output)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun of(input: Boolean, output: Boolean): FlowDirection {
|
||||
if (input && output) {
|
||||
return BI_DIRECTIONAL
|
||||
} else if (input) {
|
||||
return INPUT
|
||||
} else if (output) {
|
||||
return OUTPUT
|
||||
} else {
|
||||
return NONE
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return [INPUT] if [flag] is true, [OUTPUT] otherwise
|
||||
*/
|
||||
@JvmStatic
|
||||
fun input(flag: Boolean): FlowDirection {
|
||||
return of(flag, !flag)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return [OUTPUT] if [flag] is true, [INPUT] otherwise
|
||||
*/
|
||||
@JvmStatic
|
||||
fun output(flag: Boolean): FlowDirection {
|
||||
return of(!flag, flag)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return [INPUT] if [flag] is true, [NONE] otherwise
|
||||
*/
|
||||
@JvmStatic
|
||||
fun orInput(flag: Boolean): FlowDirection {
|
||||
return of(flag, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return [OUTPUT] if [flag] is true, [NONE] otherwise
|
||||
*/
|
||||
@JvmStatic
|
||||
fun orOutput(flag: Boolean): FlowDirection {
|
||||
return of(false, flag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.minecraftforge.common.util.INBTSerializable
|
||||
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||
import ru.dbotthepony.mc.otm.capability.extractEnergy
|
||||
import ru.dbotthepony.mc.otm.capability.receiveEnergy
|
||||
import ru.dbotthepony.mc.otm.core.Decimal
|
||||
@ -23,6 +24,9 @@ class AndroidPowerSource(
|
||||
initialCharge: Decimal,
|
||||
maxCharge: Decimal
|
||||
) : IMatteryEnergyStorage, INBTSerializable<CompoundTag> {
|
||||
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")
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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<Component>) {
|
||||
@ -103,7 +32,7 @@ internal fun batteryLevel(it: IMatteryEnergyStorage, tooltips: MutableList<Compo
|
||||
).withStyle(ChatFormatting.GRAY))
|
||||
|
||||
if (it is IEnergyStorageImpl) {
|
||||
when (it.direction) {
|
||||
when (it.energyFlow) {
|
||||
FlowDirection.INPUT -> {
|
||||
if (it.maxInput != null) {
|
||||
tooltips.add(
|
||||
|
@ -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 {
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -80,7 +80,7 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), 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<IMatterGraphNode>(), 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<IMatterGraphNode>(), 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<IMatterGraphNode>(), 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
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -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 <T : Any?> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
|
||||
@ -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")
|
||||
|
@ -50,7 +50,7 @@ class PlasmaRifleItem : PlasmaWeaponItem<PlasmaWeaponDataTable>(PlasmaWeaponData
|
||||
)
|
||||
|
||||
if (!player.abilities.instabuild)
|
||||
energyData(itemStack).extractEnergyInner(ENERGY_PER_SHOT, false)
|
||||
energyData(itemStack).extractEnergy(ENERGY_PER_SHOT, false)
|
||||
|
||||
return true
|
||||
}
|
||||
|
@ -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<CompoundTag> {
|
||||
class PlasmaWeaponEnergy(val itemStack: ItemStack, private val innerCapacity: Decimal) : IMatteryEnergyStorage, ICapabilityProvider, INBTSerializable<CompoundTag> {
|
||||
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 <T : Any> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
|
||||
@ -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
|
||||
|
@ -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_
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user