Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Swap to using Koin for DI, do not rely on any global context #106

Merged
merged 22 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
3d6d096
refactor: Swap to using proper dependency injection throughout in ant…
0ffz Oct 15, 2024
9ae475a
chore: Rewrite core to use koin module
0ffz Oct 16, 2024
c30d09b
refactor: Get addons compiling
0ffz Oct 16, 2024
0cd483c
chore: Bump gradlew
0ffz Oct 16, 2024
5fde1d0
refactor: Finish fixing tests for addons
0ffz Oct 18, 2024
4de4973
fix: entityOf and entityOfOrNull swapped logic
0ffz Oct 19, 2024
0852f67
chore: Add some helper methods for caching queries
0ffz Oct 22, 2024
2e5408e
chore: Some helper functions for addons
0ffz Oct 24, 2024
0a71387
fix: Actually load prefabs defined by prefab addon
0ffz Oct 25, 2024
77159f0
Merge branch 'di-rewrite'
0ffz Oct 26, 2024
9c99a31
chore: Bump version to reflect breaking changes
0ffz Oct 26, 2024
c5ee414
refactor: Swap to kotlinx.io for multiplatform paths
0ffz Oct 26, 2024
c4f6958
fix: Failed cast when initializing addons
0ffz Oct 26, 2024
7888481
fix: Inheriting an entity should not inherit its prefabs directly
0ffz Oct 27, 2024
e46fa21
fix: Use correct idofront release version
0ffz Oct 27, 2024
1100511
fix: Load resources from jar correctly
0ffz Oct 27, 2024
364b694
chore: make jar resource more generic
DevScyu Oct 28, 2024
33e9b48
fix: Don't pass world in CopyToInstances, we can get it from the enti…
0ffz Oct 28, 2024
e4f44e6
chore: fix tests
DevScyu Oct 29, 2024
9952033
refactor: Add back benchmarks module
0ffz Oct 31, 2024
0d5e7b3
chore: Update benchmarks to use new query syntax
0ffz Nov 1, 2024
d583615
chore: Add helper function for creating prefabs directly with the pre…
0ffz Nov 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Read our [Quickstart guide](https://wiki.mineinabyss.com/geary/quickstart/) to s
data class Position(var x: Double, var y: Double)
data class Velocity(var x: Double, var y: Double)

fun GearyModule.updatePositionSystem() = system(query<Position, Velocity>())
fun Geary.updatePositionSystem() = system(query<Position, Velocity>())
.every(interval = 20.milliseconds)
.exec { (position, velocity) ->
// We can access our components like regular variables!
Expand Down
7 changes: 2 additions & 5 deletions addons/geary-actions/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,16 @@ kotlin {
dependencies {
implementation(project(":geary-core"))
implementation(project(":geary-serialization"))

implementation(libs.uuid)
implementation(idofrontLibs.idofront.di)
}
}
val commonTest by getting {
val jvmTest by getting {
dependencies {
implementation(project(":geary-test"))
implementation(kotlin("test"))
implementation(idofrontLibs.kotlinx.coroutines.test)
implementation(idofrontLibs.kotlinx.serialization.kaml)
implementation(idofrontLibs.kotest.assertions)
implementation(idofrontLibs.kotest.property)
implementation(idofrontLibs.idofront.di)
implementation(project(":geary-core"))
implementation(project(":geary-serialization"))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,19 @@ import com.mineinabyss.geary.actions.actions.EmitEventAction
import com.mineinabyss.geary.actions.actions.EnsureAction
import com.mineinabyss.geary.actions.event_binds.*
import com.mineinabyss.geary.actions.expressions.Expression
import com.mineinabyss.geary.modules.geary
import com.mineinabyss.geary.modules.Geary
import com.mineinabyss.geary.serialization.getWorld
import com.mineinabyss.geary.serialization.serializers.InnerSerializer
import com.mineinabyss.geary.serialization.serializers.PolymorphicListAsMapSerializer
import com.mineinabyss.geary.serialization.serializers.SerializedComponents
import kotlinx.serialization.ContextualSerializer
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.modules.SerializersModule

class ActionEntry(
val action: Action,
Expand Down Expand Up @@ -64,14 +71,15 @@ class ActionGroup(
customKeys = mapOf(
"when" to { ActionWhen.serializer() },
"register" to { ActionRegister.serializer() },
"onFail" to { ActionOnFail.serializer() },
"onFail" to { ActionOnFail.Serializer() },
"loop" to { ActionLoop.serializer() }
)
)
)
),
inverseTransform = { TODO() },
transform = {
val world = serializersModule.getWorld()
val actions = it.mapNotNull { components ->
var action: Action? = null
var condition: List<EnsureAction>? = null
Expand All @@ -85,11 +93,11 @@ class ActionGroup(
comp is ActionRegister -> register = comp.register
comp is ActionOnFail -> onFail = comp.action
comp is ActionLoop -> loop =
Expression.parseExpression(comp.expression, serializersModule) as Expression<List<Any>>
Expression.parseExpression(world, comp.expression, serializersModule) as Expression<List<Any>>

comp is ActionEnvironment -> environment = comp.environment
action != null -> geary.logger.w { "Multiple actions defined in one block!" }
else -> action = EmitEventAction.wrapIfNotAction(comp)
action != null -> Geary.w { "Multiple actions defined in one block!" }
else -> action = EmitEventAction.wrapIfNotAction(world, comp)
}
}
if (action == null) return@mapNotNull null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,11 @@ package com.mineinabyss.geary.actions

import com.mineinabyss.geary.actions.event_binds.bindEntityObservers
import com.mineinabyss.geary.actions.event_binds.parsePassive
import com.mineinabyss.geary.addons.dsl.GearyAddonWithDefault
import com.mineinabyss.geary.modules.geary
import com.mineinabyss.geary.addons.dsl.createAddon

class GearyActions {
companion object : GearyAddonWithDefault<GearyActions> {
override fun default() = GearyActions()

override fun GearyActions.install() {
geary.run {
bindEntityObservers()
parsePassive()
}
}
val GearyActions = createAddon("Geary Actions") {
onStart {
bindEntityObservers()
parsePassive()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.mineinabyss.geary.actions.Action
import com.mineinabyss.geary.actions.ActionGroupContext
import com.mineinabyss.geary.datatypes.ComponentId
import com.mineinabyss.geary.helpers.componentId
import com.mineinabyss.geary.modules.Geary

class EmitEventAction(
val eventId: ComponentId,
Expand All @@ -14,8 +15,8 @@ class EmitEventAction(
}

companion object {
fun from(data: Any) = EmitEventAction(componentId(data::class), data)
fun from(world: Geary, data: Any) = EmitEventAction(world.componentId(data::class), data)

fun wrapIfNotAction(data: Any) = if (data is Action) data else from(data)
fun wrapIfNotAction(world: Geary, data: Any) = if (data is Action) data else from(world, data)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@ package com.mineinabyss.geary.actions.actions

import com.mineinabyss.geary.actions.*
import com.mineinabyss.geary.helpers.componentId
import com.mineinabyss.geary.modules.Geary
import com.mineinabyss.geary.serialization.getWorld
import com.mineinabyss.geary.serialization.serializers.InnerSerializer
import com.mineinabyss.geary.serialization.serializers.PolymorphicListAsMapSerializer
import com.mineinabyss.geary.serialization.serializers.SerializedComponents
import kotlinx.serialization.ContextualSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient

@Serializable(with = EnsureAction.Serializer::class)
class EnsureAction(
world: Geary,
val conditions: SerializedComponents,
) : Action {
@Transient
private val flat = conditions.map { componentId(it::class) to it }
private val flat = conditions.map { world.componentId(it::class) to it }

override fun ActionGroupContext.execute() {
flat.forEach { (id, data) ->
Expand All @@ -38,10 +42,10 @@ class EnsureAction(
return true
}

object Serializer : InnerSerializer<SerializedComponents, EnsureAction>(
class Serializer : InnerSerializer<SerializedComponents, EnsureAction>(
serialName = "geary:ensure",
inner = PolymorphicListAsMapSerializer.ofComponents(),
inverseTransform = { it.conditions },
transform = { EnsureAction(it) }
transform = { EnsureAction(serializersModule.getWorld(), it) }
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,21 @@ import com.mineinabyss.geary.actions.Action
import com.mineinabyss.geary.actions.ActionGroupContext
import com.mineinabyss.geary.actions.expressions.Expression
import com.mineinabyss.geary.actions.expressions.InlineExpressionSerializer
import com.mineinabyss.geary.modules.Geary
import com.mineinabyss.geary.serialization.serializers.InnerSerializer
import kotlinx.serialization.Serializable

@Serializable(with = EvalAction.Serializer::class)
class EvalAction(
val expression: Expression<*>,
) : Action {
override fun ActionGroupContext.execute() =
expression.evaluate(this)

object Serializer : InnerSerializer<Expression<*>, EvalAction>(
class Serializer(
world: Geary,
) : InnerSerializer<Expression<*>, EvalAction>(
serialName = "geary:eval",
inner = InlineExpressionSerializer,
inner = InlineExpressionSerializer(world),
inverseTransform = { it.expression },
transform = { EvalAction(it) }
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ package com.mineinabyss.geary.actions.event_binds
import com.mineinabyss.geary.actions.ActionGroup
import com.mineinabyss.geary.actions.actions.EnsureAction
import com.mineinabyss.geary.actions.expressions.Expression
import com.mineinabyss.geary.datatypes.ComponentId
import com.mineinabyss.geary.modules.Geary
import com.mineinabyss.geary.serialization.serializers.InnerSerializer
import com.mineinabyss.geary.serialization.serializers.SerializableComponentId
import kotlinx.serialization.Contextual
import kotlinx.serialization.ContextualSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.UseContextualSerialization
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.builtins.MapSerializer
import kotlinx.serialization.builtins.serializer
Expand All @@ -20,8 +23,8 @@ class EntityObservers(
class Serializer : InnerSerializer<Map<SerializableComponentId, ActionGroup>, EntityObservers>(
serialName = "geary:observe",
inner = MapSerializer(
SerializableComponentId.serializer(),
ActionGroup.serializer()
ContextualSerializer(ComponentId::class),
ActionGroup.Serializer()
),
inverseTransform = { TODO() },
transform = {
Expand Down Expand Up @@ -67,7 +70,7 @@ value class ActionLoop(val expression: String)
class ActionEnvironment(val environment: Map<String, Expression<@Contextual Any>>) {
object Serializer : InnerSerializer<Map<String, Expression<@Contextual Any>>, ActionEnvironment>(
serialName = "geary:with",
inner = MapSerializer(String.serializer(), Expression.serializer(ContextualSerializer(Any::class))),
inner = MapSerializer(String.serializer(), Expression.Serializer(ContextualSerializer(Any::class))),
inverseTransform = ActionEnvironment::environment,
transform = { ActionEnvironment(it) }
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ package com.mineinabyss.geary.actions.event_binds
import com.mineinabyss.geary.actions.ActionGroupContext
import com.mineinabyss.geary.actions.execute
import com.mineinabyss.geary.datatypes.EntityType
import com.mineinabyss.geary.modules.GearyModule
import com.mineinabyss.geary.modules.Geary
import com.mineinabyss.geary.modules.observe
import com.mineinabyss.geary.observers.entity.observe
import com.mineinabyss.geary.observers.events.OnSet
import com.mineinabyss.geary.systems.builders.observe
import com.mineinabyss.geary.systems.query.query

fun GearyModule.bindEntityObservers() = observe<OnSet>()
fun Geary.bindEntityObservers() = observe<OnSet>()
.involving(query<EntityObservers>())
.exec { (observers) ->
observers.observers.forEach { observer ->
val actionGroup = observer.actionGroup
entity.observe(observer.event.id).involving(EntityType(observer.involving.map { it.id })).exec {
entity.observe(observer.event).involving(EntityType(observer.involving)).exec {
val context = ActionGroupContext(entity)
actionGroup.execute(context)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ import com.mineinabyss.geary.actions.execute
import com.mineinabyss.geary.actions.serializers.DurationSerializer
import com.mineinabyss.geary.helpers.entity
import com.mineinabyss.geary.helpers.fastForEach
import com.mineinabyss.geary.modules.GearyModule
import com.mineinabyss.geary.modules.Geary
import com.mineinabyss.geary.modules.observe
import com.mineinabyss.geary.observers.events.OnSet
import com.mineinabyss.geary.serialization.serializers.InnerSerializer
import com.mineinabyss.geary.serialization.serializers.SerializableComponentId
import com.mineinabyss.geary.systems.builders.observe
import com.mineinabyss.geary.systems.builders.system
import com.mineinabyss.geary.systems.query.query
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.ListSerializer
Expand All @@ -37,15 +36,15 @@ class Passive(
)
}

fun GearyModule.parsePassive() = observe<OnSet>()
fun Geary.parsePassive() = observe<OnSet>()
.involving(query<Passive>())
.exec { (passive) ->
passive.systems.forEach { systemBind ->
val systemMatchingId = entity().id
entity.add(systemMatchingId)
system(query {
has(systemMatchingId)
has(systemBind.match.map { it.id })
has(systemBind.match)
}).every(systemBind.every).execOnAll {
entities().fastForEach { entity ->
runCatching {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.mineinabyss.geary.actions.expressions

import com.mineinabyss.geary.actions.ActionGroupContext
import com.mineinabyss.geary.modules.Geary
import com.mineinabyss.geary.serialization.getWorld
import kotlinx.serialization.ContextualSerializer
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
Expand Down Expand Up @@ -31,23 +33,25 @@ sealed interface Expression<T> {
}

companion object {
fun parseExpression(string: String, module: SerializersModule): Expression<*> {
fun parseExpression(
world: Geary,string: String, module: SerializersModule): Expression<*> {
val (name, rem) = getFunctionName(string)
val reference = Variable<Any>(name)
if(rem == "") return reference
return foldFunctions(reference, rem, module)
return foldFunctions(world, reference, rem, module)
}

tailrec fun foldFunctions(
world: Geary,
reference: Expression<*>,
remainder: String,
module: SerializersModule,
): Expression<*> {
val (name, afterName) = getFunctionName(remainder)
val (yaml, afterYaml) = getYaml(afterName)
val functionExpr = FunctionExpression.parse(reference, name, yaml, module)
val functionExpr = FunctionExpression.parse(world, reference, name, yaml, module)
if (afterYaml == "") return functionExpr
return foldFunctions(functionExpr, afterYaml, module)
return foldFunctions(world, functionExpr, afterYaml, module)
}

fun getYaml(expr: String): Pair<String, String> {
Expand Down Expand Up @@ -76,6 +80,7 @@ sealed interface Expression<T> {
override val descriptor: SerialDescriptor = ContextualSerializer(Any::class).descriptor

override fun deserialize(decoder: Decoder): Expression<T> {
val world = decoder.serializersModule.getWorld()
// Try reading string value, if serial type isn't string, this fails
runCatching {
decoder.decodeStructure(String.serializer().descriptor) {
Expand All @@ -84,6 +89,7 @@ sealed interface Expression<T> {
}.onSuccess { string ->
if (string.startsWith("{{") && string.endsWith("}}"))
return parseExpression(
world,
string.removePrefix("{{").removeSuffix("}}").trim(),
decoder.serializersModule
) as Expression<T>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
package com.mineinabyss.geary.actions.expressions

import com.mineinabyss.geary.actions.ActionGroupContext
import com.mineinabyss.geary.serialization.serializableComponents
import com.mineinabyss.geary.serialization.serializers.SerializableComponentId
import com.mineinabyss.geary.modules.Geary
import com.mineinabyss.geary.serialization.SerializableComponents
import com.mineinabyss.geary.serialization.serializers.ComponentIdSerializer
import kotlinx.serialization.modules.SerializersModule

interface FunctionExpression<I, O> {
companion object {
fun parse(
world: Geary,
ref: Expression<*>,
name: String,
yaml: String,
module: SerializersModule,
): FunctionExpressionWithInput<*, *> {
val compClass = SerializableComponentId.Serializer.getComponent(name, module)
val serializableComponents = world.getAddon(SerializableComponents)
val compClass = ComponentIdSerializer(serializableComponents.serializers, world).getComponent(name, module)
val serializer = serializableComponents.serializers.getSerializerFor(compClass)
?: error("No serializer found for component $name")
val expr =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
package com.mineinabyss.geary.actions.expressions

import com.mineinabyss.geary.modules.Geary
import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder

object InlineExpressionSerializer : KSerializer<Expression<*>> {
class InlineExpressionSerializer(
val world: Geary,
) : KSerializer<Expression<*>> {
override val descriptor: SerialDescriptor = String.serializer().descriptor

override fun deserialize(decoder: Decoder): Expression<*> {
return Expression.parseExpression(
world,
decoder.decodeString(),
decoder.serializersModule
)
Expand All @@ -19,5 +23,4 @@ object InlineExpressionSerializer : KSerializer<Expression<*>> {
override fun serialize(encoder: Encoder, value: Expression<*>) {
TODO("Not yet implemented")
}

}
Loading
Loading