From 395aa7d1c312e495517701be11c21425d9a5838e Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Sun, 26 Oct 2025 17:25:13 -0700 Subject: Checkpoint --- .../commonMain/kotlin/coffee/liz/ecs/DAGWorld.kt | 61 +++++++++------------- 1 file changed, 24 insertions(+), 37 deletions(-) (limited to 'composeApp/src/commonMain/kotlin/coffee/liz/ecs/DAGWorld.kt') diff --git a/composeApp/src/commonMain/kotlin/coffee/liz/ecs/DAGWorld.kt b/composeApp/src/commonMain/kotlin/coffee/liz/ecs/DAGWorld.kt index d314065..77cb30b 100644 --- a/composeApp/src/commonMain/kotlin/coffee/liz/ecs/DAGWorld.kt +++ b/composeApp/src/commonMain/kotlin/coffee/liz/ecs/DAGWorld.kt @@ -1,28 +1,27 @@ package coffee.liz.ecs +import kotlin.concurrent.atomics.AtomicInt +import kotlin.concurrent.atomics.ExperimentalAtomicApi +import kotlin.concurrent.atomics.incrementAndFetch import kotlin.reflect.KClass +import kotlin.time.Duration /** - * World implementation that executes systems in dependency order using a DAG. + * [World] that updates in [System.dependencies] DAG order. */ -class DAGWorld(systems: List) : World { +@OptIn(ExperimentalAtomicApi::class) +class DAGWorld(systems: List>) : World { private val entities = mutableSetOf() private val componentCache = mutableMapOf, MutableSet>() - private val systemExecutionOrder: List - private var nextEntityId = 0 - - init { - systemExecutionOrder = buildExecutionOrder(systems) - } + private val systemExecutionOrder: List> = buildExecutionOrder(systems) + private val nextEntityId = AtomicInt(0) override fun createEntity(): Entity { - val entity = Entity(nextEntityId++) - entities.add(entity) - return entity + return Entity(nextEntityId.incrementAndFetch()) + .also { entities.add(it) } } - override fun destroyEntity(entity: Entity) { - // Remove from all component caches + override fun removeEntity(entity: Entity) { entity.componentTypes().forEach { componentType -> componentCache[componentType]?.remove(entity) } @@ -38,25 +37,18 @@ class DAGWorld(systems: List) : World { // Filter to entities that have all component types return candidates.filter { entity -> - entity.hasAll(*componentTypes) + componentTypes.all { entity.has(it) } }.toSet() } - override fun update(deltaTime: Float) { - // Update component cache based on current entity state - updateComponentCache() - - // Execute systems in dependency order + override fun update(state: Outside, deltaTime: Duration) { + refreshComponentCache() systemExecutionOrder.forEach { system -> - system.update(this, deltaTime) + system.update(this, state, deltaTime) } } - /** - * Rebuild the component cache based on current entity components. - * Call this after components have been added/removed from entities. - */ - private fun updateComponentCache() { + private fun refreshComponentCache() { componentCache.clear() entities.forEach { entity -> entity.componentTypes().forEach { componentType -> @@ -67,14 +59,13 @@ class DAGWorld(systems: List) : World { /** * Build a topologically sorted execution order from system dependencies. - * Uses Kahn's algorithm for topological sorting. */ - private fun buildExecutionOrder(systems: List): List { + private fun buildExecutionOrder(systems: List>): List> { if (systems.isEmpty()) return emptyList() val systemMap = systems.associateBy { it::class } - val inDegree = mutableMapOf, Int>() - val adjacencyList = mutableMapOf, MutableSet>>() + val inDegree = mutableMapOf>, Int>() + val adjacencyList = mutableMapOf>, MutableSet>>>() // Initialize graph systems.forEach { system -> @@ -94,15 +85,11 @@ class DAGWorld(systems: List) : World { } // Kahn's algorithm - val queue = ArrayDeque>() - val result = mutableListOf() + val queue = ArrayDeque>>() + val result = mutableListOf>() // Add all systems with no dependencies to queue - inDegree.forEach { (systemClass, degree) -> - if (degree == 0) { - queue.add(systemClass) - } - } + queue.addAll(inDegree.filterValues { it == 0 }.keys) while (queue.isNotEmpty()) { val currentClass = queue.removeFirst() @@ -119,7 +106,7 @@ class DAGWorld(systems: List) : World { // Check for cycles if (result.size != systems.size) { - throw IllegalArgumentException("Circular dependency detected in systems") + error("Circular dependency detected in systems") } return result -- cgit v1.2.3-70-g09d2