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
|
_segment = value
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onInvalidate() {
|
|
||||||
_segment = EnergyCableGraph.Segment(this)
|
|
||||||
updatePoweredState(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
val sides get() = energySides
|
val sides get() = energySides
|
||||||
|
|
||||||
override fun onNeighbour(link: Link) {
|
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 segments = LinkedHashSet<Segment>()
|
||||||
val nodes = HashSet<EnergyCableBlockEntity.Node>()
|
val nodes = HashSet<EnergyCableBlockEntity.Node>()
|
||||||
var shortCircuit = false
|
var shortCircuit = false
|
||||||
@ -136,7 +136,7 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val nodes = LinkedHashSet<EnergyCableBlockEntity.Node>()
|
private val nodes = LinkedHashSet<EnergyCableBlockEntity.Node>()
|
||||||
private var paths = ReferenceLinkedOpenHashSet<SegmentPath>()
|
var paths = ReferenceLinkedOpenHashSet<SegmentPath>()
|
||||||
|
|
||||||
operator fun contains(node: EnergyCableBlockEntity.Node): Boolean {
|
operator fun contains(node: EnergyCableBlockEntity.Node): Boolean {
|
||||||
return node in nodes
|
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) {
|
private fun combineInto(segment: Segment) {
|
||||||
nodes.forEach { it._segment = segment }
|
nodes.forEach { it._segment = segment }
|
||||||
segment.nodes.addAll(nodes)
|
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
|
// 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? {
|
private fun findPath(a: EnergyCableBlockEntity.Node, b: EnergyCableBlockEntity.Node, existing: Collection<SegmentPath>, threshold: Decimal): SegmentPath? {
|
||||||
val seenTop = existing.any { a in it }
|
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) }
|
solution.forEach { it.segment.add(path) }
|
||||||
touchedSegments.forEach { it.tryCombine(touchedSegments) }
|
touchedSegments.forEach { it.tryCombine(touchedSegments) }
|
||||||
|
|
||||||
@ -490,18 +505,29 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
|||||||
return list.paths
|
return list.paths
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun notifyThroughputsChanged() {
|
||||||
|
pathCache.values.forEach { it.saturated = false }
|
||||||
|
}
|
||||||
|
|
||||||
override fun onNodeRemoved(node: EnergyCableBlockEntity.Node) {
|
override fun onNodeRemoved(node: EnergyCableBlockEntity.Node) {
|
||||||
if (livelyNodes.remove(node)) {
|
if (livelyNodes.remove(node)) {
|
||||||
check(livelyNodesList.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) {
|
override fun onNodeAdded(node: EnergyCableBlockEntity.Node) {
|
||||||
check(livelyNodes.add(node))
|
check(livelyNodes.add(node))
|
||||||
livelyNodesList.add(node)
|
livelyNodesList.add(node)
|
||||||
invalidatePathCache()
|
|
||||||
|
notifyThroughputsChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun receiveEnergy(howMuch: Decimal, simulate: Boolean, fromNode: EnergyCableBlockEntity.Node, fromSide: RelativeSide): Decimal {
|
fun receiveEnergy(howMuch: Decimal, simulate: Boolean, fromNode: EnergyCableBlockEntity.Node, fromSide: RelativeSide): Decimal {
|
||||||
|
Loading…
Reference in New Issue
Block a user