Skip to content

Commit

Permalink
Reverse system disposal order. (#130)
Browse files Browse the repository at this point in the history
  • Loading branch information
metaphore authored Dec 2, 2023
1 parent 187addd commit ed9f4d4
Show file tree
Hide file tree
Showing 2 changed files with 182 additions and 3 deletions.
13 changes: 10 additions & 3 deletions src/commonMain/kotlin/com/github/quillraven/fleks/world.kt
Original file line number Diff line number Diff line change
Expand Up @@ -234,9 +234,9 @@ class WorldConfiguration(@PublishedApi internal val world: World) {
val systemArray = systemList.toTypedArray()
family.removeHook = if (ownHook != null) { entity ->
ownHook(world, entity)
systemArray.forEach { it.onRemoveEntity(entity) }
systemArray.forEachReverse { it.onRemoveEntity(entity) }
} else { entity ->
systemArray.forEach { it.onRemoveEntity(entity) }
systemArray.forEachReverse { it.onRemoveEntity(entity) }
}
}
}
Expand Down Expand Up @@ -633,7 +633,7 @@ class World internal constructor(
*/
fun dispose() {
entityService.removeAll()
systems.forEach { it.onDispose() }
systems.forEachReverse { it.onDispose() }
}


Expand Down Expand Up @@ -669,3 +669,10 @@ class World internal constructor(
CURRENT_WORLD?.family(cfg) ?: throw FleksWrongConfigurationUsageException()
}
}

private inline fun <T> Array<T>.forEachReverse(action: (T) -> Unit) {
val lastIndex = this.lastIndex
for (i in lastIndex downTo 0) {
action(this[i])
}
}
172 changes: 172 additions & 0 deletions src/commonTest/kotlin/com/github/quillraven/fleks/SystemOrderTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
package com.github.quillraven.fleks

import com.github.quillraven.fleks.World.Companion.family
import kotlin.test.Test
import kotlin.test.assertEquals

private class TestComponent : Component<TestComponent> {
companion object : ComponentType<TestComponent>()
override fun type() = TestComponent
}

private abstract class BaseSystem(
val onInitOrder: MutableList<BaseSystem> = mutableListOf(),
val onUpdateOrder: MutableList<BaseSystem> = mutableListOf(),
val onDisposeOrder: MutableList<BaseSystem> = mutableListOf(),
val onAddEntityOrder: MutableList<BaseSystem> = mutableListOf(),
val onTickEntityOrder: MutableList<BaseSystem> = mutableListOf(),
val onRemoveEntityOrder: MutableList<BaseSystem> = mutableListOf(),
) : IteratingSystem(
family { all (TestComponent) }
), FamilyOnAdd, FamilyOnRemove {

override fun onInit() {
super.onInit()
onInitOrder += this
}

override fun onUpdate() {
super.onUpdate()
onUpdateOrder += this
}

override fun onDispose() {
super.onDispose()
onDisposeOrder += this
}

override fun onAddEntity(entity: Entity) {
onAddEntityOrder += this
}

override fun onTickEntity(entity: Entity) {
onTickEntityOrder += this
}

override fun onRemoveEntity(entity: Entity) {
onRemoveEntityOrder += this
}
}

private class FirstSystem(
onInitOrder: MutableList<BaseSystem> = mutableListOf(),
onUpdateOrder: MutableList<BaseSystem> = mutableListOf(),
onDisposeOrder: MutableList<BaseSystem> = mutableListOf(),
onAddEntityOrder: MutableList<BaseSystem> = mutableListOf(),
onTickEntityOrder: MutableList<BaseSystem> = mutableListOf(),
onRemoveEntityOrder: MutableList<BaseSystem> = mutableListOf(),
) : BaseSystem(onInitOrder, onUpdateOrder, onDisposeOrder, onAddEntityOrder, onTickEntityOrder, onRemoveEntityOrder)

private class SecondSystem(
onInitOrder: MutableList<BaseSystem> = mutableListOf(),
onUpdateOrder: MutableList<BaseSystem> = mutableListOf(),
onDisposeOrder: MutableList<BaseSystem> = mutableListOf(),
onAddEntityOrder: MutableList<BaseSystem> = mutableListOf(),
onTickEntityOrder: MutableList<BaseSystem> = mutableListOf(),
onRemoveEntityOrder: MutableList<BaseSystem> = mutableListOf(),
) : BaseSystem(onInitOrder, onUpdateOrder, onDisposeOrder, onAddEntityOrder, onTickEntityOrder, onRemoveEntityOrder)

internal class SystemOrderTest {

@Test
fun onInit() {
val systemOrder = mutableListOf<BaseSystem>()

configureWorld {
systems {
add(FirstSystem(onInitOrder = systemOrder))
add(SecondSystem(onInitOrder = systemOrder))
}
}

assertEquals(FirstSystem::class, systemOrder[0]::class)
assertEquals(SecondSystem::class, systemOrder[1]::class)
}

@Test
fun onUpdate() {
val systemOrder = mutableListOf<BaseSystem>()

val world = configureWorld {
systems {
add(FirstSystem(onUpdateOrder = systemOrder))
add(SecondSystem(onUpdateOrder = systemOrder))
}
}

world.update(0f)

assertEquals(FirstSystem::class, systemOrder[0]::class)
assertEquals(SecondSystem::class, systemOrder[1]::class)
}

@Test
fun onDispose() {
val systemOrder = mutableListOf<BaseSystem>()

val world = configureWorld {
systems {
add(FirstSystem(onDisposeOrder = systemOrder))
add(SecondSystem(onDisposeOrder = systemOrder))
}
}

world.dispose()

assertEquals(SecondSystem::class, systemOrder[0]::class)
assertEquals(FirstSystem::class, systemOrder[1]::class)
}

@Test
fun onAddEntity() {
val systemOrder = mutableListOf<BaseSystem>()

val world = configureWorld {
systems {
add(FirstSystem(onAddEntityOrder = systemOrder))
add(SecondSystem(onAddEntityOrder = systemOrder))
}
}

world.entity { it += TestComponent() }

assertEquals(FirstSystem::class, systemOrder[0]::class)
assertEquals(SecondSystem::class, systemOrder[1]::class)
}

@Test
fun onTickEntity() {
val systemOrder = mutableListOf<BaseSystem>()

val world = configureWorld {
systems {
add(FirstSystem(onTickEntityOrder = systemOrder))
add(SecondSystem(onTickEntityOrder = systemOrder))
}
}

world.entity { it += TestComponent() }
world.update(0f)

assertEquals(FirstSystem::class, systemOrder[0]::class)
assertEquals(SecondSystem::class, systemOrder[1]::class)
}

@Test
fun onRemoveEntity() {
val systemOrder = mutableListOf<BaseSystem>()

val world = configureWorld {
systems {
add(FirstSystem(onRemoveEntityOrder = systemOrder))
add(SecondSystem(onRemoveEntityOrder = systemOrder))
}
}

val entity = world.entity { it += TestComponent() }
world -= entity

assertEquals(SecondSystem::class, systemOrder[0]::class)
assertEquals(FirstSystem::class, systemOrder[1]::class)
}
}

0 comments on commit ed9f4d4

Please sign in to comment.