104 lines
2.5 KiB
Kotlin
104 lines
2.5 KiB
Kotlin
package ru.dbotthepony.kstarbound.lua
|
|
|
|
import org.classdump.luna.LuaRuntimeException
|
|
import org.classdump.luna.Table
|
|
import org.classdump.luna.runtime.Dispatch
|
|
import org.classdump.luna.runtime.ExecutionContext
|
|
import org.classdump.luna.runtime.Resumable
|
|
import org.classdump.luna.runtime.UnresolvedControlThrowable
|
|
import ru.dbotthepony.kommons.util.KOptional
|
|
import ru.dbotthepony.kommons.vector.Vector2i
|
|
import java.util.function.Supplier
|
|
|
|
class StateMachine : Resumable {
|
|
private val states = ArrayDeque<(ExecutionContext) -> Unit>()
|
|
|
|
fun add(state: (ExecutionContext) -> Unit): StateMachine {
|
|
states.add(state)
|
|
return this
|
|
}
|
|
|
|
fun mergeInto(other: StateMachine): StateMachine {
|
|
states.addAll(other.states)
|
|
return other
|
|
}
|
|
|
|
fun mergeFrom(other: StateMachine): StateMachine {
|
|
other.mergeInto(this)
|
|
return this
|
|
}
|
|
|
|
override fun resume(context: ExecutionContext, suspendedState: Any) {
|
|
run(context, this, this)
|
|
}
|
|
|
|
fun run(context: ExecutionContext): Boolean = run(context, this, this)
|
|
|
|
fun run(context: ExecutionContext, resumable: Resumable, suspendState: Any): Boolean {
|
|
if (states.isEmpty())
|
|
return false
|
|
|
|
while (states.isNotEmpty()) {
|
|
val next = states.removeFirst()
|
|
|
|
try {
|
|
next.invoke(context)
|
|
} catch (err: UnresolvedControlThrowable) {
|
|
throw err.resolve(resumable, suspendState)
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
fun index(table: Table, vararg indexes: Any): Supplier<Any> {
|
|
var value: KOptional<Any> = KOptional.empty()
|
|
|
|
for (index in indexes) {
|
|
add {
|
|
if (!value.isPresent) {
|
|
value = KOptional.ofNullable(Dispatch.index(it, table, index))
|
|
}
|
|
}
|
|
}
|
|
|
|
return Supplier {
|
|
if (!value.isPresent) {
|
|
throw LuaRuntimeException("Unable to locate value in table using following keys: ${indexes.joinToString()}")
|
|
}
|
|
}
|
|
}
|
|
|
|
fun optionalIndex(table: Table, vararg indexes: Any): Supplier<KOptional<Any>> {
|
|
var value: KOptional<Any> = KOptional.empty()
|
|
|
|
for (index in indexes) {
|
|
add {
|
|
if (!value.isPresent) {
|
|
value = KOptional.ofNullable(Dispatch.index(it, table, index))
|
|
}
|
|
}
|
|
}
|
|
|
|
return Supplier { value }
|
|
}
|
|
|
|
fun loadVector2i(table: Table): Supplier<Vector2i> {
|
|
val x = index(table, 1, "x")
|
|
val y = index(table, 2, "y")
|
|
var value = KOptional.empty<Vector2i>()
|
|
|
|
add {
|
|
val ix = x.get()
|
|
val iy = y.get()
|
|
|
|
if (ix !is Number) throw LuaRuntimeException("Invalid 'x' value for vector: ${x.get()}")
|
|
if (iy !is Number) throw LuaRuntimeException("Invalid 'y' value for vector: ${x.get()}")
|
|
|
|
value = KOptional(Vector2i(ix.toInt(), iy.toInt()))
|
|
}
|
|
|
|
return Supplier { value.value }
|
|
}
|
|
}
|