diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/cable/EnergyCableGraph.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/cable/EnergyCableGraph.kt index 1be70138b..cd63f30a7 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/cable/EnergyCableGraph.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/cable/EnergyCableGraph.kt @@ -75,6 +75,14 @@ class EnergyCableGraph : GraphNodeList): Decimal { if (!amount.isPositive || shortCircuit) { return Decimal.ZERO @@ -90,16 +98,15 @@ class EnergyCableGraph : GraphNodeList): Decimal { + if (lastTick != UNIVERSE_TICKS) { + transferredLastTick = Decimal.ZERO + lastTick = UNIVERSE_TICKS + } + + checkThroughput() + val currentTransferred = instantSnapshot[this] ?: transferredLastTick + return throughput - currentTransferred + } + fun transfer(amount: Decimal, instantSnapshot: MutableMap): Decimal { if (lastTick != UNIVERSE_TICKS) { transferredLastTick = Decimal.ZERO @@ -240,10 +261,7 @@ class EnergyCableGraph : GraphNodeList { if (!a.canTraverse || !b.canTraverse) - return null + return listOf() val list = pathCache.computeIfAbsent(a to b) { CacheEntry() } @@ -343,8 +361,8 @@ class EnergyCableGraph : GraphNodeList= 2) { + // Multiple paths, a bit more complicated + // Determine how much machine is likely to accept + val potentiallyAccepted = it.receiveEnergy(residue, true) + + // Won't accept anything + if (potentiallyAccepted <= Decimal.ZERO) + continue + + // Now determine combined available throughput + // Make a copy of snapshot, so we can freely write into it + val copy = snapshot.clone() + var calcResidue = potentiallyAccepted + + // TODO: Currently, all transfers cause Braess's paradox, because of greedy selection of "fastest" cable + // Need to implement heuristics to better distribute load across different paths/segments + for (path in paths) { + val passed = path.transfer(calcResidue, true, copy) + calcResidue -= passed + if (calcResidue <= Decimal.ZERO) break + } + + if (calcResidue == potentiallyAccepted) { + // мда continue } - side.neighbour.get()?.let { - if (it !is EnergyCableBlockEntity.CableSide) { - val path = getPath(fromNode, node, residue) - hit = true + var thisReceived = it.receiveEnergy(potentiallyAccepted - calcResidue, simulate) + received += thisReceived + residue -= thisReceived - if (path != null) { - val thisReceived = it.receiveEnergy(path.transfer(residue, simulate, snapshot), simulate) - received += thisReceived - residue -= thisReceived - if (!residue.isPositive) return received - } - } + for (path in paths) { + val passed = path.transfer(thisReceived, simulate, snapshot) + thisReceived -= passed + if (thisReceived <= Decimal.ZERO) break } + + if (!residue.isPositive) return received + check(thisReceived <= Decimal.ZERO) { "Путом, алло, Путом, какого чёрта Путом? Путом почему ты заблокировал логику, а Путом?" } } } if (!hit) { itr.remove() - check(livelyNodes.remove(node)) + check(livelyNodes.remove(node)) { "Lively nodes Set does not contain $node" } } }