summaryrefslogtreecommitdiff
path: root/composeApp/src/commonMain/kotlin/coffee/liz/ecs/DAGWorld.kt
diff options
context:
space:
mode:
Diffstat (limited to 'composeApp/src/commonMain/kotlin/coffee/liz/ecs/DAGWorld.kt')
-rw-r--r--composeApp/src/commonMain/kotlin/coffee/liz/ecs/DAGWorld.kt29
1 files changed, 13 insertions, 16 deletions
diff --git a/composeApp/src/commonMain/kotlin/coffee/liz/ecs/DAGWorld.kt b/composeApp/src/commonMain/kotlin/coffee/liz/ecs/DAGWorld.kt
index 77cb30b..c6303d3 100644
--- a/composeApp/src/commonMain/kotlin/coffee/liz/ecs/DAGWorld.kt
+++ b/composeApp/src/commonMain/kotlin/coffee/liz/ecs/DAGWorld.kt
@@ -7,19 +7,20 @@ import kotlin.reflect.KClass
import kotlin.time.Duration
/**
- * [World] that updates in [System.dependencies] DAG order.
+ * [World] that updates in [System.dependencies] topological order.
*/
@OptIn(ExperimentalAtomicApi::class)
-class DAGWorld<Outside>(systems: List<System<Outside>>) : World<Outside> {
+class DAGWorld<Outside>(
+ systems: List<System<Outside>>,
+) : World<Outside> {
private val entities = mutableSetOf<Entity>()
private val componentCache = mutableMapOf<KClass<out Component>, MutableSet<Entity>>()
private val systemExecutionOrder: List<System<Outside>> = buildExecutionOrder(systems)
private val nextEntityId = AtomicInt(0)
- override fun createEntity(): Entity {
- return Entity(nextEntityId.incrementAndFetch())
+ override fun createEntity(): Entity =
+ Entity(nextEntityId.incrementAndFetch())
.also { entities.add(it) }
- }
override fun removeEntity(entity: Entity) {
entity.componentTypes().forEach { componentType ->
@@ -31,17 +32,18 @@ class DAGWorld<Outside>(systems: List<System<Outside>>) : World<Outside> {
override fun query(vararg componentTypes: KClass<out Component>): Set<Entity> {
if (componentTypes.isEmpty()) return entities.toSet()
- // Start with entities that have the first component type
val firstType = componentTypes[0]
val candidates = componentCache[firstType] ?: return emptySet()
- // Filter to entities that have all component types
- return candidates.filter { entity ->
- componentTypes.all { entity.has(it) }
- }.toSet()
+ return candidates
+ .filter { entity -> componentTypes.all { entity.has(it) } }
+ .toSet()
}
- override fun update(state: Outside, deltaTime: Duration) {
+ override fun update(
+ state: Outside,
+ deltaTime: Duration,
+ ) {
refreshComponentCache()
systemExecutionOrder.forEach { system ->
system.update(this, state, deltaTime)
@@ -57,9 +59,6 @@ class DAGWorld<Outside>(systems: List<System<Outside>>) : World<Outside> {
}
}
- /**
- * Build a topologically sorted execution order from system dependencies.
- */
private fun buildExecutionOrder(systems: List<System<Outside>>): List<System<Outside>> {
if (systems.isEmpty()) return emptyList()
@@ -88,7 +87,6 @@ class DAGWorld<Outside>(systems: List<System<Outside>>) : World<Outside> {
val queue = ArrayDeque<KClass<out System<Outside>>>()
val result = mutableListOf<System<Outside>>()
- // Add all systems with no dependencies to queue
queue.addAll(inDegree.filterValues { it == 0 }.keys)
while (queue.isNotEmpty()) {
@@ -104,7 +102,6 @@ class DAGWorld<Outside>(systems: List<System<Outside>>) : World<Outside> {
}
}
- // Check for cycles
if (result.size != systems.size) {
error("Circular dependency detected in systems")
}