158 lines
4.5 KiB
Scala
158 lines
4.5 KiB
Scala
package wow.doge.mygame.state
|
|
|
|
import akka.actor.typed.scaladsl.Behaviors
|
|
import ammonite.Main
|
|
import akka.actor.typed.ActorRef
|
|
import com.jme3.app.state.AppState
|
|
import ammonite.runtime.Storage.Folder
|
|
import ammonite.main.Defaults
|
|
import akka.actor.typed.Behavior
|
|
import akka.actor.typed.scaladsl.ActorContext
|
|
import ammonite.util.Res.Success
|
|
import javax.script.ScriptEngine
|
|
import javax.script.ScriptEngineManager
|
|
import scala.util.Try
|
|
import cats.implicits._
|
|
|
|
object ScriptActor {
|
|
sealed trait Result
|
|
final case class AppStateResult(state: AppState) extends Result
|
|
final case class Error(reason: String) extends Result
|
|
|
|
sealed trait Command
|
|
final case class Compile(path: os.Path, sender: ActorRef[Result])
|
|
extends Command
|
|
|
|
final case class CompileAny(
|
|
path: os.Path,
|
|
result: ActorRef[Either[Error, Any]]
|
|
) extends Command
|
|
|
|
def defaultScalaRunner() =
|
|
ammonite
|
|
.Main(
|
|
storageBackend = new Folder(
|
|
// os.pwd / "target"
|
|
Defaults.ammoniteHome,
|
|
isRepl = false
|
|
)
|
|
)
|
|
|
|
def defaultKotlinRunner(): ScriptEngine = {
|
|
val manager = new ScriptEngineManager()
|
|
val engine = manager.getEngineByExtension("main.kts")
|
|
engine
|
|
}
|
|
|
|
def apply(
|
|
scalaRunner: Main = defaultScalaRunner(),
|
|
kotlinRunner: ScriptEngine = defaultKotlinRunner()
|
|
// parent: ActorRef[ScriptStoringActor.Command]
|
|
): Behavior[ScriptActor.Command] =
|
|
Behaviors.setup(ctx =>
|
|
new ScriptActor(scalaRunner, kotlinRunner, ctx).receiveMessage
|
|
)
|
|
|
|
sealed trait ScriptType
|
|
case object ScalaType extends ScriptType
|
|
case object KotlinType extends ScriptType
|
|
case object GroovyType extends ScriptType
|
|
|
|
def determineScriptType(path: os.Path): Either[Error, ScriptType] =
|
|
path.toString match {
|
|
case s if s.endsWith(".sc") => Right(ScalaType)
|
|
case s if s.endsWith(".main.kts") => Right(KotlinType)
|
|
case s if s.endsWith(".groovy") => Right(GroovyType)
|
|
case _ => Left(Error("Unknown script type"))
|
|
}
|
|
|
|
def runScala(path: os.Path, scalaRunner: ammonite.Main): Either[Error, Any] =
|
|
scalaRunner
|
|
.runScript(
|
|
path,
|
|
Seq.empty
|
|
)
|
|
._1 match {
|
|
case ammonite.util.Res.Exception(t, msg) => Left(Error(msg))
|
|
|
|
case Success(obj) => Right(obj)
|
|
|
|
case _ => Left(Error("Failed to run script"))
|
|
}
|
|
|
|
def runKotlin(path: os.Path, kotlinRunner: ScriptEngine): Either[Error, Any] =
|
|
Try(kotlinRunner.eval(os.read(path))).toEither.leftMap(t =>
|
|
Error(t.getMessage())
|
|
)
|
|
|
|
def runGroovy(path: os.Path): Either[Error, Any] =
|
|
Left(Error("Not implemented yet"))
|
|
|
|
}
|
|
|
|
class ScriptActor(
|
|
val scalaRunner: Main,
|
|
val kotlinRunner: ScriptEngine,
|
|
// parent: ActorRef[ScriptStoringActor.Command],
|
|
context: ActorContext[ScriptActor.Command]
|
|
) {
|
|
import ScriptActor._
|
|
|
|
def receiveMessage: Behavior[Command] =
|
|
Behaviors.receiveMessage { msg =>
|
|
msg match {
|
|
case Compile(path, sender) =>
|
|
context.log.debug(s"Received $path")
|
|
val res = getScript(path)
|
|
sender ! res
|
|
Behaviors.same
|
|
// case CompileScripts(sender, paths) =>
|
|
case CompileAny(path, requester) =>
|
|
context.log.debug(s"Received $path")
|
|
val res = getScript2(path)
|
|
context.log.debug(s"result = $res")
|
|
requester ! res
|
|
// parent ! ScriptStoringActor.Put(path, res)
|
|
Behaviors.same
|
|
}
|
|
}
|
|
|
|
def getScript(path: os.Path) = {
|
|
val res = determineScriptType(path) match {
|
|
case Right(ScalaType) => runScala(path, scalaRunner)
|
|
case Right(KotlinType) => runKotlin(path, kotlinRunner)
|
|
case Right(GroovyType) => runGroovy(path)
|
|
case l @ Left(err) => l
|
|
}
|
|
|
|
res match {
|
|
case Left(err) => err
|
|
case Right(obj) =>
|
|
obj match {
|
|
case s: MyBaseState => AppStateResult(s)
|
|
case _ => Error("Class in script does not match known types")
|
|
}
|
|
}
|
|
}
|
|
|
|
def getScript2(path: os.Path): Either[Error, Any] = {
|
|
val res = determineScriptType(path) match {
|
|
case Right(ScalaType) => runScala(path, scalaRunner)
|
|
case Right(KotlinType) => runKotlin(path, kotlinRunner)
|
|
case Right(GroovyType) => runGroovy(path)
|
|
case l @ Left(err) => l
|
|
}
|
|
|
|
// res match {
|
|
// case Left(err) => err
|
|
// case Right(obj) =>
|
|
// obj match {
|
|
// case s: MyBaseState => AppStateResult(s)
|
|
// case _ => Error("Class in script does not match known types")
|
|
// }
|
|
// }
|
|
res
|
|
}
|
|
|
|
}
|