Skip to content

Commit

Permalink
Inline some archetype related maps
Browse files Browse the repository at this point in the history
  • Loading branch information
0ffz committed Jan 15, 2022
1 parent 58bcceb commit bc1c622
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.mineinabyss.geary.ecs.accessors.building.AccessorBuilderProvider
import com.mineinabyss.geary.ecs.api.systems.MutableAndSelector
import com.mineinabyss.geary.ecs.engine.Archetype
import com.mineinabyss.geary.ecs.query.AndSelector
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
import kotlin.reflect.KProperty


Expand All @@ -16,7 +17,7 @@ import kotlin.reflect.KProperty
public open class AccessorHolder : MutableAndSelector(), AccessorBuilderProvider {
public val family: AndSelector by lazy { build() }
internal open val accessors = mutableListOf<Accessor<*>>()
private val perArchetypeCache = mutableMapOf<Archetype, List<List<Any?>>>()
private val perArchetypeCache = Int2ObjectOpenHashMap<List<List<Any?>>>()

public operator fun <T : Accessor<*>> AccessorBuilder<T>.provideDelegate(
thisRef: Any,
Expand All @@ -32,7 +33,7 @@ public open class AccessorHolder : MutableAndSelector(), AccessorBuilderProvider
/** Calculates, or gets cached values for an [archetype] */
//TODO return inline class for type safety
public fun cacheForArchetype(archetype: Archetype): List<List<Any?>> =
perArchetypeCache.getOrPut(archetype) {
perArchetypeCache.getOrPut(archetype.id) {
val accessorCache: List<MutableList<Any?>> = accessors.map { it.cached.mapTo(mutableListOf()) { null } }
val cache = ArchetypeCacheScope(archetype, accessorCache)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ public data class Archetype(
dataHoldingType.inner.map { mutableListOf() }

/** Edges to other archetypes where a single component has been added. */
internal val componentAddEdges = Long2ObjectOpenHashMap<Archetype>()
internal val componentAddEdges = CompId2ArchetypeMap()

/** Edges to other archetypes where a single component has been removed. */
internal val componentRemoveEdges = Long2ObjectOpenHashMap<Archetype>()
internal val componentRemoveEdges = CompId2ArchetypeMap()

internal val relations = type.inner.mapNotNull { it.toULong().toRelation() }

Expand Down Expand Up @@ -133,16 +133,21 @@ public data class Archetype(

/** Returns the archetype associated with adding [componentId] to this archetype's [type]. */
public operator fun plus(componentId: GearyComponentId): Archetype =
componentAddEdges[componentId] ?: type.let {
// Ensure that when adding an ID that holds data, we remove the non-data-holding ID
if (componentId.holdsData() && !componentId.isRelation())
it.minus(componentId.withoutRole(HOLDS_DATA))
else it
}.plus(componentId).getArchetype()
if (componentId in componentAddEdges)
componentAddEdges[componentId]
else
type.let {
// Ensure that when adding an ID that holds data, we remove the non-data-holding ID
if (componentId.holdsData() && !componentId.isRelation())
it.minus(componentId.withoutRole(HOLDS_DATA))
else it
}.plus(componentId).getArchetype()

/** Returns the archetype associated with removing [componentId] to this archetype's [type]. */
public operator fun minus(componentId: GearyComponentId): Archetype =
componentRemoveEdges[componentId] ?: type.minus(componentId).getArchetype().also {
if (componentId in componentRemoveEdges)
componentRemoveEdges[componentId]
else type.minus(componentId).getArchetype().also {
componentRemoveEdges[componentId] = it
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ package com.mineinabyss.geary.ecs.engine

import com.mineinabyss.geary.ecs.api.GearyType
import com.mineinabyss.geary.ecs.api.engine.Engine
import it.unimi.dsi.fastutil.ints.IntOpenHashSet
import it.unimi.dsi.fastutil.ints.IntSet

public fun GearyType.getArchetype(): Archetype = Engine.getArchetype(this)

public fun Archetype.countChildren(vis: MutableSet<Archetype> = mutableSetOf()): Int {
componentAddEdges.values.filter { it !in vis }.forEach { it.countChildren(vis) }
vis.addAll(componentAddEdges.values)
public fun Archetype.countChildren(vis: IntSet = IntOpenHashSet()): Int {
componentAddEdges.inner.values.filter { it !in vis }
.forEach { Engine.getArchetype(it).countChildren(vis) }
vis.addAll(componentAddEdges.inner.values)
return vis.count()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.mineinabyss.geary.ecs.engine

import com.mineinabyss.geary.ecs.api.GearyComponentId
import com.mineinabyss.geary.ecs.api.engine.Engine
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap

/**
* Inlined class that acts as a map of components to archetypes. Uses archetype ids for better performance.
*/
@JvmInline
public value class CompId2ArchetypeMap(public val inner: Long2IntOpenHashMap = Long2IntOpenHashMap()) {
public operator fun get(id: GearyComponentId): Archetype = Engine.getArchetype(inner[id.toLong()])
public operator fun set(id: GearyComponentId, archetype: Archetype) {
inner[id.toLong()] = archetype.id
}
public operator fun contains(id: GearyComponentId): Boolean = inner.containsKey(id.toLong())
}
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,9 @@ public open class GearyEngine : TickingEngine() {
override fun getArchetype(type: GearyType): Archetype {
var node = rootArchetype
type.forEach { compId ->
node = node.componentAddEdges[compId] ?: createArchetype(node, compId)
node =
if (compId in node.componentAddEdges) node.componentAddEdges[compId]
else createArchetype(node, compId)
}
return node
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import org.reflections.scanners.SubTypesScanner
import org.reflections.util.ClasspathHelper
import org.reflections.util.ConfigurationBuilder
import org.reflections.util.FilterBuilder
import kotlin.reflect.KClass

/**
* DSL for configuring automatic scanning of classes to be registered into Geary's [SerializersModule].
Expand Down Expand Up @@ -58,6 +59,10 @@ public class AutoScanner(private val classLoader: ClassLoader) {
return reflections
}

public inline fun <reified T : Any> getSubclassesOf(): List<KClass<out T>> {
return getReflections()?.getSubTypesOf(T::class.java)?.map { it.kotlin } ?: listOf()
}


private companion object {
private data class CacheKey(val classLoader: ClassLoader, val path: String?, val excluded: Collection<String>)
Expand Down

0 comments on commit bc1c622

Please sign in to comment.