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 b9fc82069..dfd5df626 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 @@ -2,7 +2,7 @@ package ru.dbotthepony.mc.otm.block.entity.cable import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap import it.unimi.dsi.fastutil.objects.ReferenceArraySet -import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet +import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet import net.minecraft.core.BlockPos import org.apache.logging.log4j.LogManager import ru.dbotthepony.mc.otm.SERVER_IS_LIVE @@ -133,12 +133,24 @@ class EnergyCableGraph : GraphNodeList() - private val paths = ReferenceOpenHashSet() + private var paths = ReferenceLinkedOpenHashSet() operator fun contains(node: EnergyCableBlockEntity.Node): Boolean { return node in nodes } + fun missingNodes(from: Collection): List { + val missing = ArrayList() + + this.nodes.forEach { + if (it !in from) { + missing.add(it) + } + } + + return missing + } + var throughput = Decimal.ZERO private set @@ -282,8 +294,9 @@ class EnergyCableGraph : GraphNodeList { - if (nodes.isEmpty()) { - throw IllegalStateException("Empty segment somehow?") - } else if (nodes.size == 1) { + fun split(nodes: Collection): List { + for (node in nodes) + require(node in this.nodes) { "$node does not belong to $this" } + + if (this.nodes.size == 1) { return listOf(this) } else { - lastPoweredStatus = 0 - val list = ArrayList(nodes) - val itr = list.iterator() - itr.next() val result = ArrayList() result.add(this) - for (v in itr) { - v._segment = Segment() - v.segment.nodes.add(v) + for (v in nodes) { + v.segment = Segment() v.segment.throughput = v.energyThroughput v.segment.throughputKnown = true v.segment.transferredLastTick = transferredLastTick - v.segment.paths.addAll(paths) + v.segment.lastPoweredStatus = lastPoweredStatus + v.segment.paths = paths.clone() paths.forEach { it.segments.add(v.segment) } result.add(v.segment) } - nodes.clear() - nodes.add(list[0]) - throughput = list[0].energyThroughput - throughputKnown = true - return result } } @@ -397,7 +402,7 @@ class EnergyCableGraph : GraphNodeList() + val solution = LinkedHashSet() var last = first.parent solution.add(first.node) @@ -408,10 +413,23 @@ class EnergyCableGraph : GraphNodeList() - solution.forEach { touchedSegments.addAll(it.segment.split()) } + + for (it in solution) { + if (it.segment in touchedSegments) + continue + + val diff = it.segment.missingNodes(solution) + + // segment satisfies new constraints + if (diff.isEmpty()) { + touchedSegments.add(it.segment) + } else { + touchedSegments.addAll(it.segment.split(diff)) + } + } + val path = SegmentPath(a.blockEntity.blockPos, b.blockEntity.blockPos) solution.forEach { it.segment.add(path) } - touchedSegments.forEach { it.tryCombine(touchedSegments) } return path