Improve performance on cable addition and removal from cable network
This commit is contained in:
parent
614ba26da6
commit
e68f3a7996
@ -111,11 +111,6 @@ abstract class EnergyCableBlockEntity(type: BlockEntityType<*>, blockPos: BlockP
|
||||
_segment = value
|
||||
}
|
||||
|
||||
fun onInvalidate() {
|
||||
_segment = EnergyCableGraph.Segment(this)
|
||||
updatePoweredState(false)
|
||||
}
|
||||
|
||||
val sides get() = energySides
|
||||
|
||||
override fun onNeighbour(link: Link) {
|
||||
|
@ -68,7 +68,7 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
||||
}
|
||||
}
|
||||
|
||||
class SegmentPath(private val a: BlockPos, private val b: BlockPos) {
|
||||
class SegmentPath(val a: EnergyCableBlockEntity.Node, val b: EnergyCableBlockEntity.Node) {
|
||||
val segments = LinkedHashSet<Segment>()
|
||||
val nodes = HashSet<EnergyCableBlockEntity.Node>()
|
||||
var shortCircuit = false
|
||||
@ -136,7 +136,7 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
||||
}
|
||||
|
||||
private val nodes = LinkedHashSet<EnergyCableBlockEntity.Node>()
|
||||
private var paths = ReferenceLinkedOpenHashSet<SegmentPath>()
|
||||
var paths = ReferenceLinkedOpenHashSet<SegmentPath>()
|
||||
|
||||
operator fun contains(node: EnergyCableBlockEntity.Node): Boolean {
|
||||
return node in nodes
|
||||
@ -338,6 +338,26 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
||||
}
|
||||
}
|
||||
|
||||
fun split(): List<Segment> {
|
||||
val result = ArrayList<Segment>()
|
||||
result.add(this)
|
||||
|
||||
for (v in nodes) {
|
||||
val segment = Segment()
|
||||
v._segment = segment
|
||||
segment.nodes.add(v)
|
||||
segment.throughput = v.energyThroughput
|
||||
segment.throughputKnown = true
|
||||
segment.transferredLastTick = transferredLastTick
|
||||
result.add(segment)
|
||||
v.updatePoweredState(false)
|
||||
}
|
||||
|
||||
// mark this segment as dead
|
||||
this.nodes.clear()
|
||||
return result
|
||||
}
|
||||
|
||||
private fun combineInto(segment: Segment) {
|
||||
nodes.forEach { it._segment = segment }
|
||||
segment.nodes.addAll(nodes)
|
||||
@ -385,11 +405,6 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
||||
}
|
||||
}
|
||||
|
||||
fun invalidatePathCache() {
|
||||
pathCache.clear()
|
||||
nodes.forEach { it.onInvalidate() }
|
||||
}
|
||||
|
||||
// isn't exactly A*, but greedy algorithm, which searched for locally optimal solutions because they lead to globally optimal ones
|
||||
private fun findPath(a: EnergyCableBlockEntity.Node, b: EnergyCableBlockEntity.Node, existing: Collection<SegmentPath>, threshold: Decimal): SegmentPath? {
|
||||
val seenTop = existing.any { a in it }
|
||||
@ -435,7 +450,7 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
||||
}
|
||||
}
|
||||
|
||||
val path = SegmentPath(a.blockEntity.blockPos, b.blockEntity.blockPos)
|
||||
val path = SegmentPath(a, b)
|
||||
solution.forEach { it.segment.add(path) }
|
||||
touchedSegments.forEach { it.tryCombine(touchedSegments) }
|
||||
|
||||
@ -490,18 +505,29 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
||||
return list.paths
|
||||
}
|
||||
|
||||
fun notifyThroughputsChanged() {
|
||||
pathCache.values.forEach { it.saturated = false }
|
||||
}
|
||||
|
||||
override fun onNodeRemoved(node: EnergyCableBlockEntity.Node) {
|
||||
if (livelyNodes.remove(node)) {
|
||||
check(livelyNodesList.remove(node))
|
||||
}
|
||||
|
||||
invalidatePathCache()
|
||||
node.segment.paths.forEach {
|
||||
pathCache.remove(it.a to it.b)
|
||||
pathCache.remove(it.b to it.a)
|
||||
}
|
||||
|
||||
node.segment.paths = ReferenceLinkedOpenHashSet()
|
||||
node.segment.split()
|
||||
}
|
||||
|
||||
override fun onNodeAdded(node: EnergyCableBlockEntity.Node) {
|
||||
check(livelyNodes.add(node))
|
||||
livelyNodesList.add(node)
|
||||
invalidatePathCache()
|
||||
|
||||
notifyThroughputsChanged()
|
||||
}
|
||||
|
||||
fun receiveEnergy(howMuch: Decimal, simulate: Boolean, fromNode: EnergyCableBlockEntity.Node, fromSide: RelativeSide): Decimal {
|
||||
|
Loading…
Reference in New Issue
Block a user