From 8544368ab26496b62b09257176906d3e9305db61 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Tue, 11 Feb 2025 10:48:25 +0700 Subject: [PATCH 01/11] Update cable heuristics --- .../mc/otm/block/entity/cable/EnergyCableGraph.kt | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) 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 c00d7d159..13edd418c 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 @@ -3,15 +3,12 @@ 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.ReferenceLinkedOpenHashSet -import net.minecraft.core.BlockPos import org.apache.logging.log4j.LogManager import ru.dbotthepony.mc.otm.SERVER_IS_LIVE import ru.dbotthepony.mc.otm.UNIVERSE_TICKS import ru.dbotthepony.mc.otm.capability.receiveEnergy import ru.dbotthepony.mc.otm.config.CablesConfig -import ru.dbotthepony.mc.otm.core.addAll import ru.dbotthepony.mc.otm.core.collect.map -import ru.dbotthepony.mc.otm.core.collect.max import ru.dbotthepony.mc.otm.core.collect.reduce import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.RelativeSide @@ -493,17 +490,18 @@ class EnergyCableGraph : GraphNodeList Date: Tue, 11 Feb 2025 10:51:52 +0700 Subject: [PATCH 02/11] Don't oversearch paths when target block won't accept all energy sent --- .../dbotthepony/mc/otm/block/entity/cable/EnergyCableGraph.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 13edd418c..b022c8e24 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 @@ -477,7 +477,7 @@ class EnergyCableGraph : GraphNodeList { - if (!a.canTraverse || !b.canTraverse) + if (!a.canTraverse || !b.canTraverse || energyToTransfer <= Decimal.ZERO) return listOf() if (searchedOnTick != UNIVERSE_TICKS) { @@ -558,7 +558,7 @@ class EnergyCableGraph : GraphNodeList Date: Tue, 11 Feb 2025 11:05:10 +0700 Subject: [PATCH 03/11] a --- .../mc/otm/block/entity/cable/EnergyCableGraph.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 b022c8e24..4a8297a98 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 @@ -335,10 +335,13 @@ class EnergyCableGraph : GraphNodeList Date: Tue, 11 Feb 2025 11:08:24 +0700 Subject: [PATCH 04/11] egg --- .../dbotthepony/mc/otm/block/entity/cable/EnergyCableGraph.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 4a8297a98..867599c3b 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 @@ -496,7 +496,7 @@ class EnergyCableGraph : GraphNodeList Date: Tue, 11 Feb 2025 11:12:11 +0700 Subject: [PATCH 05/11] Improve cable path search performance when there are a lot of paths existing already --- .../mc/otm/block/entity/cable/EnergyCableGraph.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 867599c3b..6ab9b9646 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 @@ -426,6 +426,9 @@ class EnergyCableGraph : GraphNodeList() + existing.forEach { existingNodes.addAll(it.nodes) } + while (openNodes.isNotEmpty()) { val first = openNodes.remove() openNodes.remove(first) @@ -466,7 +469,7 @@ class EnergyCableGraph : GraphNodeList Date: Tue, 11 Feb 2025 12:58:12 +0700 Subject: [PATCH 06/11] Further refine cable path search performance --- .../block/entity/cable/EnergyCableGraph.kt | 55 ++++++++++++++++++- 1 file changed, 52 insertions(+), 3 deletions(-) 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 6ab9b9646..2dacd80b6 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 @@ -21,6 +21,56 @@ import kotlin.collections.HashSet import kotlin.collections.LinkedHashSet import kotlin.math.ln +private class LinkedPriorityQueue> { + private class Entry(val value: T) { + var next: Entry? = null + } + + private var head: Entry? = null + + fun isNotEmpty(): Boolean { + return head != null + } + + fun add(value: T) { + if (head == null) { + head = Entry(value) + } else if (head!!.value >= value) { + val entry = Entry(value) + entry.next = head + head = entry + } else { + var current = head + var previous = current + + while (current != null) { + if (current.value >= value) { + val entry = Entry(value) + entry.next = current + previous!!.next = entry + return + } + + previous = current + current = current.next + } + + previous!!.next = Entry(value) + } + } + + fun remove(): T? { + val head = head + + if (head != null) { + this.head = head.next + return head.value + } + + return null + } +} + class EnergyCableGraph : GraphNodeList() { private val livelyNodes = HashSet() private val livelyNodesList = ArrayList() @@ -421,7 +471,7 @@ class EnergyCableGraph : GraphNodeList() + val openNodes = LinkedPriorityQueue() val seenNodes = HashSet() openNodes.add(SearchNode(a, b, null, seenTop)) @@ -430,8 +480,7 @@ class EnergyCableGraph : GraphNodeList Date: Tue, 11 Feb 2025 13:49:48 +0700 Subject: [PATCH 07/11] Don't subscribe block entity to chunk if syncher has no entries --- .../dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt | 7 ++++--- .../dbotthepony/mc/otm/network/syncher/SynchableGroup.kt | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt index 59d9efe96..40941bf09 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt @@ -413,7 +413,6 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc } private var _subCache: ChunkSubscribers? = null - private val subscription get() = _subCache ?: subscribe() private var playerListUpdated = false private fun unsubscribe() { @@ -430,7 +429,10 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc playerListUpdated = false } - private fun subscribe(): ChunkSubscribers { + private fun subscribe() { + if (!syncher.hasChildren) + return + val level = level check(level is ServerLevel) { "Invalid realm" } unsubscribe() @@ -442,7 +444,6 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc subs.subscribe(this) _subCache = subs playerListUpdated = true - return subs } private class ChunkSubscribers(level: ServerLevel, val chunkPos: Long) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/syncher/SynchableGroup.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/syncher/SynchableGroup.kt index bc3ee3c78..9b5ad3f04 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/syncher/SynchableGroup.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/syncher/SynchableGroup.kt @@ -66,6 +66,9 @@ class SynchableGroup : Observer, ISynchable, Iterable { override val hasRemotes: Boolean get() = remotes.isNotEmpty() + val hasChildren: Boolean + get() = slots.any { it != null } + override fun iterator(): Iterator { return slots.iterator().map { it?.synchable }.filterNotNull() } From be9641fc037f7db8a66c23b676d9255ef1d8cc2b Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Tue, 11 Feb 2025 13:54:23 +0700 Subject: [PATCH 08/11] Try to search for better path when cabling changes even if current path set is sufficient --- .../mc/otm/block/entity/cable/EnergyCableGraph.kt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) 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 2dacd80b6..e583c8a62 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 @@ -90,6 +90,7 @@ class EnergyCableGraph : GraphNodeList(1) var saturated = false + var forceExploreAlternatives = false } // TODO: LRU cache? @@ -548,7 +549,8 @@ class EnergyCableGraph : GraphNodeList Date: Tue, 11 Feb 2025 14:37:51 +0700 Subject: [PATCH 09/11] Fix cables getting stuck on "powered" blockstate when segments get split --- .../dbotthepony/mc/otm/block/entity/cable/EnergyCableGraph.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 e583c8a62..9949039cb 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 @@ -384,8 +384,8 @@ class EnergyCableGraph : GraphNodeList Date: Tue, 11 Feb 2025 15:55:30 +0700 Subject: [PATCH 10/11] Misc fixes regarding cable network node removals --- .../block/entity/cable/EnergyCableGraph.kt | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) 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 9949039cb..1e2053a9f 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 @@ -8,6 +8,7 @@ import ru.dbotthepony.mc.otm.SERVER_IS_LIVE import ru.dbotthepony.mc.otm.UNIVERSE_TICKS import ru.dbotthepony.mc.otm.capability.receiveEnergy import ru.dbotthepony.mc.otm.config.CablesConfig +import ru.dbotthepony.mc.otm.core.addAll import ru.dbotthepony.mc.otm.core.collect.map import ru.dbotthepony.mc.otm.core.collect.reduce import ru.dbotthepony.mc.otm.core.math.Decimal @@ -186,7 +187,7 @@ class EnergyCableGraph : GraphNodeList() + val nodes = LinkedHashSet() var paths = ReferenceLinkedOpenHashSet() operator fun contains(node: EnergyCableBlockEntity.Node): Boolean { @@ -244,7 +245,7 @@ class EnergyCableGraph : GraphNodeList) { - if (nodes.isEmpty()) return + if (nodes.isEmpty() || paths.isEmpty()) return for (segment in with) { if (tryCombineWith(segment)) return @@ -581,12 +585,23 @@ class EnergyCableGraph : GraphNodeList() + + node.segment.paths.toTypedArray().forEach { pathCache.remove(it.a to it.b) + + it.segments.forEach { s -> + touchedSegments.add(s) + s.paths.remove(it) + + // this doesn't cover 100% of cases where previously split path segments + // due to "this" path get recombined, but it should be good enough + s.paths.forEach { touchedSegments.addAll(it.segments) } + } } - node.segment.paths = ReferenceLinkedOpenHashSet() - node.segment.split() + touchedSegments.addAll(node.segment.split()) + touchedSegments.forEach { it.tryCombine(touchedSegments) } } override fun onNodeAdded(node: EnergyCableBlockEntity.Node) { From 5813a3ad65cd6ebd18e0342e46d8f17107e48d28 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Tue, 11 Feb 2025 18:13:19 +0700 Subject: [PATCH 11/11] Make "powered" cable display handle more edge cases --- .../dbotthepony/mc/otm/block/entity/cable/EnergyCableGraph.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 1e2053a9f..df421a4b4 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 @@ -233,6 +233,7 @@ class EnergyCableGraph : GraphNodeList 0) { lastPoweredStatus = numState nodes.forEach { if (it.segment === this) it.updatePoweredState(newState) } } @@ -395,6 +396,7 @@ class EnergyCableGraph : GraphNodeList