Skip to content

Commit

Permalink
feat: Revamped action system as a new addon
Browse files Browse the repository at this point in the history
  • Loading branch information
0ffz committed Jul 25, 2024
1 parent 9e7ecb7 commit 3c7ed2a
Show file tree
Hide file tree
Showing 19 changed files with 249 additions and 155 deletions.
19 changes: 19 additions & 0 deletions addons/geary-actions/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
plugins {
id(idofrontLibs.plugins.mia.kotlin.multiplatform.get().pluginId)
id(idofrontLibs.plugins.mia.publication.get().pluginId)
alias(idofrontLibs.plugins.kotlinx.serialization)
}

kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation(project(":geary-core"))
implementation(project(":geary-serialization"))

implementation(libs.uuid)
implementation(idofrontLibs.idofront.di)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.mineinabyss.geary.actions

interface Action {
fun ActionGroupContext.execute()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.mineinabyss.geary.actions

class ActionGroup(
val actions: List<Action>,
) {
fun execute(context: ActionGroupContext) {
actions.forEach {
try {
with(it) { context.execute() }
} catch (e: ActionsCancelledException) {
return
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.mineinabyss.geary.actions

import com.mineinabyss.geary.actions.expressions.Expression
import com.mineinabyss.geary.datatypes.GearyEntity

class ActionGroupContext(
var entity: GearyEntity,
) {
fun <T> eval(expression: Expression<T>): T = expression.evaluate(this)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.mineinabyss.geary.actions

class ActionsCancelledException : Exception()
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.mineinabyss.geary.actions

interface Condition {
fun ActionGroupContext.execute(): Boolean
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.mineinabyss.geary.actions

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

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

override fun GearyActions.install() {
geary.run {
bindEntityObservers()
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.mineinabyss.geary.actions.actions

import com.mineinabyss.geary.actions.Action
import com.mineinabyss.geary.actions.ActionGroupContext
import com.mineinabyss.geary.actions.expressions.EntityExpression
import com.mineinabyss.geary.serialization.serializers.InnerSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable(with = BecomeAction.Serializer::class)
@SerialName("geary:become")
class BecomeAction(
val become: EntityExpression,
) : Action {
override fun ActionGroupContext.execute() {
entity = become.evaluate(this)
}

object Serializer : InnerSerializer<EntityExpression, BecomeAction>(
serialName = "geary:become",
inner = EntityExpression.serializer(),
inverseTransform = { it.become },
transform = ::BecomeAction
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.mineinabyss.geary.actions.actions

import com.mineinabyss.geary.actions.Action
import com.mineinabyss.geary.actions.ActionGroupContext
import com.mineinabyss.geary.datatypes.ComponentId
import com.mineinabyss.geary.helpers.componentId

class EmitEventAction(
val eventId: ComponentId,
val data: Any?,
): Action {
override fun ActionGroupContext.execute() {
entity.emit(event = eventId, data = data)
}

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

fun wrapIfNotAction(data: Any) = if(data is Action) data else from(data)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.mineinabyss.geary.actions.actions

import com.mineinabyss.geary.actions.Action
import com.mineinabyss.geary.actions.ActionsCancelledException
import com.mineinabyss.geary.actions.ActionGroupContext
import com.mineinabyss.geary.actions.event_binds.EventBind
import com.mineinabyss.geary.helpers.componentId
import com.mineinabyss.geary.serialization.serializers.InnerSerializer
import com.mineinabyss.geary.serialization.serializers.PolymorphicListAsMapSerializer
import com.mineinabyss.geary.serialization.serializers.SerializedComponents
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient

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

override fun ActionGroupContext.execute() {
flat.forEach {
when (val condition = it.data) {
is Conwdition -> with(condition) {
if(!execute()) throw ActionsCancelledException()
}
else -> entity.emit(it.componentId, it.data) //TODO use geary condition system if we get one
}
}
}

object Serializer: InnerSerializer<SerializedComponents, EnsureAction>(
serialName = "geary:ensure",
inner = PolymorphicListAsMapSerializer.ofComponents(),
inverseTransform = { it.conditions },
transform = { EnsureAction(it) }
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.mineinabyss.geary.actions.event_binds

import com.mineinabyss.geary.serialization.serializers.InnerSerializer
import com.mineinabyss.geary.serialization.serializers.PolymorphicListAsMapSerializer
import com.mineinabyss.geary.serialization.serializers.SerializableComponentId
import com.mineinabyss.geary.serialization.serializers.SerializedComponents
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.builtins.MapSerializer

@Serializable(with = EntityObservers.Serializer::class)
class EntityObservers(val observers: List<EventBind>) {
class Serializer : InnerSerializer<Map<SerializableComponentId, List<SerializedComponents>>, EntityObservers>(
serialName = "geary:observe",
inner = MapSerializer(
SerializableComponentId.serializer(),
ListSerializer(PolymorphicListAsMapSerializer.ofComponents())
),
inverseTransform = { it.observers.associate { it.event to it.emit } },
transform = { EntityObservers(it.map { (event, emit) -> EventBind(event, emit = emit) }) }
)
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.mineinabyss.geary.actions.event_binds

import com.mineinabyss.geary.serialization.serializers.SerializableComponentId
import com.mineinabyss.geary.serialization.serializers.SerializedComponents

class EventBind(
val event: SerializableComponentId,
val involving: List<SerializableComponentId> = listOf(),
val emit: List<SerializedComponents>,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.mineinabyss.geary.actions.event_binds

import com.mineinabyss.geary.actions.ActionGroup
import com.mineinabyss.geary.actions.ActionGroupContext
import com.mineinabyss.geary.actions.actions.EmitEventAction
import com.mineinabyss.geary.datatypes.EntityType
import com.mineinabyss.geary.modules.GearyModule
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>()
.involving(query<EntityObservers>())
.exec { (observers) ->
observers.observers.forEach { observer ->
val actionGroup = ActionGroup(
actions = observer.emit.flatten().map { EmitEventAction.wrapIfNotAction(it) }
)
entity.observe(observer.event.id).involving(EntityType(observer.involving.map { it.id })).exec {
val context = ActionGroupContext(entity)
actionGroup.execute(context)
}
}
entity.remove<EntityObservers>()
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.mineinabyss.geary.actions.expressions

import com.mineinabyss.geary.actions.ActionGroupContext
import com.mineinabyss.geary.datatypes.GearyEntity
import com.mineinabyss.geary.helpers.parent
import kotlinx.serialization.Serializable
import kotlin.jvm.JvmInline

@JvmInline
@Serializable
value class EntityExpression(
val expression: String,
) /*: Expression<GearyEntity>()*/ {
fun evaluate(context: ActionGroupContext): GearyEntity {
return if (expression == "parent") context.entity.parent!!
else TODO()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.mineinabyss.geary.actions.expressions

import com.mineinabyss.geary.actions.ActionGroupContext
import kotlinx.serialization.Serializable

@Serializable
abstract class Expression<T> {
abstract fun evaluate(context: ActionGroupContext): T
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.mineinabyss.geary.prefabs.configuration.components

import com.mineinabyss.geary.datatypes.ComponentId
import com.mineinabyss.geary.serialization.serializers.SerializableComponentId

data class ReEmitEvent(
val findByRelationKind: SerializableComponentId,
Expand Down
Loading

0 comments on commit 3c7ed2a

Please sign in to comment.