Cable segment merging
This commit is contained in:
parent
90dc125b1b
commit
b4e37fbd1f
@ -99,7 +99,8 @@ abstract class EnergyCableBlockEntity(type: BlockEntityType<*>, blockPos: BlockP
|
||||
}
|
||||
|
||||
inner class Node : GraphNode<Node, EnergyCableGraph>(::EnergyCableGraph) {
|
||||
private var _segment = EnergyCableGraph.Segment(this)
|
||||
@Deprecated("internal property")
|
||||
var _segment = EnergyCableGraph.Segment(this)
|
||||
|
||||
var segment: EnergyCableGraph.Segment
|
||||
get() { return _segment }
|
||||
|
@ -3,6 +3,7 @@ package ru.dbotthepony.mc.otm.block.entity.cable
|
||||
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap
|
||||
import it.unimi.dsi.fastutil.objects.ReferenceArraySet
|
||||
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet
|
||||
import net.minecraft.core.BlockPos
|
||||
import org.apache.logging.log4j.LogManager
|
||||
@ -118,7 +119,6 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Actual segment logic (merging segments)
|
||||
class Segment() {
|
||||
constructor(node: EnergyCableBlockEntity.Node) : this() {
|
||||
nodes.add(node)
|
||||
@ -136,7 +136,7 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
||||
|
||||
private fun checkThroughput() {
|
||||
if (!throughputKnown) {
|
||||
throughput = nodes.maxOf { it.energyThroughput }
|
||||
throughput = nodes.maxOfOrNull { it.energyThroughput } ?: Decimal.ZERO
|
||||
throughputKnown = true
|
||||
}
|
||||
}
|
||||
@ -154,6 +154,8 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
||||
private var lastPoweredStatus = 0
|
||||
|
||||
private fun updateBlockstates(): Boolean {
|
||||
if (nodes.isEmpty()) return false
|
||||
|
||||
if (lastTick + 2 < UNIVERSE_TICKS) {
|
||||
transferredLastTick = Decimal.ZERO
|
||||
lastTick = UNIVERSE_TICKS
|
||||
@ -199,6 +201,7 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
||||
lastTick = UNIVERSE_TICKS
|
||||
}
|
||||
|
||||
checkThroughput()
|
||||
val currentTransferred = instantSnapshot[this] ?: transferredLastTick
|
||||
|
||||
if (currentTransferred >= throughput || !amount.isPositive) {
|
||||
@ -217,6 +220,7 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
||||
lastTick = UNIVERSE_TICKS
|
||||
}
|
||||
|
||||
checkThroughput()
|
||||
if (transferredLastTick >= throughput || !amount.isPositive) {
|
||||
return Decimal.ZERO
|
||||
}
|
||||
@ -238,33 +242,30 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
||||
instantSnapshot[this] = maxOf(instantSnapshot[this]!! - amount, Decimal.ZERO)
|
||||
}
|
||||
} else {
|
||||
transferredLastTick = maxOf(transferredLastTick, Decimal.ZERO)
|
||||
transferredLastTick = maxOf(transferredLastTick - amount, Decimal.ZERO)
|
||||
}
|
||||
}
|
||||
|
||||
fun remove(node: EnergyCableBlockEntity.Node) {
|
||||
check(nodes.remove(node)) { "Tried to remove node $node from segment $this, but that node does not belong to this segment" }
|
||||
|
||||
if (nodes.isEmpty())
|
||||
throughput = Decimal.ZERO
|
||||
else
|
||||
throughput = nodes.maxOf { it.energyThroughput }
|
||||
throughputKnown = false
|
||||
}
|
||||
|
||||
fun add(node: EnergyCableBlockEntity.Node) {
|
||||
check(nodes.add(node)) { "Tried to add node $node to segment $this, but we already have that node added" }
|
||||
throughput = maxOf(throughput, node.energyThroughput)
|
||||
|
||||
if (throughputKnown)
|
||||
throughput = maxOf(throughput, node.energyThroughput)
|
||||
}
|
||||
|
||||
fun add(path: SegmentPath) {
|
||||
check(paths.add(path)) { "Path $path should already contain $this" }
|
||||
check(paths.add(path)) { "Path $path shouldn't contain $this" }
|
||||
check(path.segments.add(this)) { "Path set and Segment disagree whenever $this is absent from $path" }
|
||||
|
||||
checkThroughput()
|
||||
}
|
||||
|
||||
fun remove(path: SegmentPath) {
|
||||
check(paths.remove(path)) { "Path $path shouldn't contain $this" }
|
||||
check(paths.remove(path)) { "Path $path should already contain $this" }
|
||||
check(path.segments.remove(this)) { "Path set and Segment disagree whenever $this is present in $path" }
|
||||
}
|
||||
|
||||
@ -285,6 +286,7 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
||||
|
||||
for (v in itr) {
|
||||
v.segment = Segment()
|
||||
v.segment.transferredLastTick = transferredLastTick
|
||||
v.segment.paths.addAll(paths)
|
||||
paths.forEach { it.segments.add(v.segment) }
|
||||
result.add(v.segment)
|
||||
@ -293,6 +295,52 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
private fun combineInto(segment: Segment) {
|
||||
nodes.forEach { it._segment = segment }
|
||||
segment.nodes.addAll(nodes)
|
||||
// this should match on both segments
|
||||
// segment.transferredLastTick = maxOf(segment.transferredLastTick, transferredLastTick)
|
||||
paths.forEach { it.segments.remove(this) }
|
||||
segment.throughputKnown = false
|
||||
nodes.clear() // mark segment as dead
|
||||
}
|
||||
|
||||
private fun tryCombineWith(segment: Segment): Boolean {
|
||||
if (segment === this || segment.nodes.isEmpty()) return false
|
||||
|
||||
// if nodes have same set of paths then it is safe to combine this with target segment
|
||||
if (segment.paths == paths) {
|
||||
if (nodes.size >= segment.nodes.size) {
|
||||
segment.combineInto(this)
|
||||
} else {
|
||||
combineInto(segment)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
fun tryCombine() {
|
||||
if (nodes.isEmpty()) return
|
||||
|
||||
// TODO: This is inefficient as fk
|
||||
for (path in paths) {
|
||||
for (segment in path.segments) {
|
||||
if (tryCombineWith(segment)) return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun tryCombine(with: Collection<Segment>) {
|
||||
if (nodes.isEmpty()) return
|
||||
|
||||
for (segment in with) {
|
||||
if (tryCombineWith(segment)) return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun invalidatePathCache() {
|
||||
@ -329,11 +377,13 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
||||
last = last.parent
|
||||
}
|
||||
|
||||
val touchedSegments = ArrayList<Segment>()
|
||||
val touchedSegments = ReferenceArraySet<Segment>()
|
||||
solution.forEach { touchedSegments.addAll(it.segment.split()) }
|
||||
val path = SegmentPath(a.blockEntity.blockPos, b.blockEntity.blockPos)
|
||||
touchedSegments.forEach { it.add(path) }
|
||||
|
||||
touchedSegments.forEach { it.tryCombine(touchedSegments) }
|
||||
|
||||
return path
|
||||
} else {
|
||||
for (neighbour in first.node.neighboursView.values) {
|
||||
|
Loading…
Reference in New Issue
Block a user