forked from nova/jmonkey-test
Rohan Sircar
4 years ago
41 changed files with 1492 additions and 411 deletions
-
4.jvmopts
-
9build.sbt
-
3launch.sh
-
BINlib/jme3-testdata.jar
-
4plugins.json
-
1project/plugins.sbt
-
3src/main/resources/hello.groovy
-
1src/main/resources/hello2.sc
-
59src/main/scala/org/slf4j/impl/StaticLoggerBuilder.scala
-
198src/main/scala/wow/doge/mygame/Main.scala
-
87src/main/scala/wow/doge/mygame/MainModule.scala
-
20src/main/scala/wow/doge/mygame/executors/ExecutorsModule.scala
-
11src/main/scala/wow/doge/mygame/executors/GUIExecutor.scala
-
6src/main/scala/wow/doge/mygame/executors/Schedulers.scala
-
95src/main/scala/wow/doge/mygame/game/GameApp.scala
-
193src/main/scala/wow/doge/mygame/game/GameAppActor.scala
-
25src/main/scala/wow/doge/mygame/game/GameModule.scala
-
13src/main/scala/wow/doge/mygame/game/GameSystemsInitializer.scala
-
84src/main/scala/wow/doge/mygame/game/TestActor.scala
-
2src/main/scala/wow/doge/mygame/game/appstates/EntityDataState.java
-
20src/main/scala/wow/doge/mygame/game/appstates/MovementActor.scala
-
14src/main/scala/wow/doge/mygame/game/appstates/MyBaseState.scala
-
85src/main/scala/wow/doge/mygame/game/appstates/PlayerMovementState.scala
-
8src/main/scala/wow/doge/mygame/game/appstates/ScriptingEngineState.scala
-
16src/main/scala/wow/doge/mygame/game/appstates/TestAppState.scala
-
0src/main/scala/wow/doge/mygame/game/components/Position.scala
-
0src/main/scala/wow/doge/mygame/game/components/Tag.scala
-
0src/main/scala/wow/doge/mygame/game/components/Test.java
-
0src/main/scala/wow/doge/mygame/game/components/TestComponent.scala
-
94src/main/scala/wow/doge/mygame/game/nodes/PlayerNode.scala
-
365src/main/scala/wow/doge/mygame/implicits/package.scala
-
2src/main/scala/wow/doge/mygame/math/ImVector3f.scala
-
0src/main/scala/wow/doge/mygame/subsystems/events/EventBus.scala
-
0src/main/scala/wow/doge/mygame/subsystems/events/Events.scala
-
0src/main/scala/wow/doge/mygame/subsystems/events/EventsModule.scala
-
142src/main/scala/wow/doge/mygame/subsystems/moddingsystem/ModdingSystem.scala
-
109src/main/scala/wow/doge/mygame/subsystems/scriptsystem/ScriptActor.scala
-
123src/main/scala/wow/doge/mygame/subsystems/scriptsystem/ScriptCachingActor.scala
-
53src/main/scala/wow/doge/mygame/utils/JFXConsoleStream.scala
-
1test.plugin.json
-
1test2.plugin.json
@ -0,0 +1,4 @@ |
|||||
|
-Xms2G |
||||
|
-Xmx2G |
||||
|
-XX:+UseG1GC |
||||
|
-XX:MaxGCPauseMillis=50 |
@ -0,0 +1,3 @@ |
|||||
|
# sdk use java 20.2.0.r11-grl |
||||
|
# java -J-Xms2G -J-Xmx2G -J-XX:+UseG1GC -J-XX:MaxGCPauseMillis=50 -jar target/scala-2.13/mygame-assembly-1.0-SNAPSHOT.jar |
||||
|
java -Xms2G -Xmx2G -XX:+UseG1GC -XX:MaxGCPauseMillis=50 -jar target/scala-2.13/mygame-assembly-1.0-SNAPSHOT.jar |
@ -0,0 +1,4 @@ |
|||||
|
[ |
||||
|
{ "name": "test", "priority": 1 }, |
||||
|
{ "name": "test2", "priority": 2 } |
||||
|
] |
@ -1,2 +1,3 @@ |
|||||
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0") |
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0") |
||||
addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.23") |
addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.23") |
||||
|
addCompilerPlugin("com.olegpy" %% "better-monadic-for" % "0.3.1") |
@ -0,0 +1,3 @@ |
|||||
|
println "hello" |
||||
|
|
||||
|
this |
@ -0,0 +1,59 @@ |
|||||
|
package org.slf4j.impl |
||||
|
|
||||
|
import cats.effect.{ContextShift, Clock, Effect, IO, Timer} |
||||
|
import io.odin._ |
||||
|
import io.odin.slf4j.OdinLoggerBinder |
||||
|
import cats.implicits._ |
||||
|
|
||||
|
import scala.concurrent.ExecutionContext |
||||
|
import _root_.monix.execution.Scheduler |
||||
|
import cats.arrow.FunctionK |
||||
|
import _root_.monix.execution.Scheduler.Implicits.global |
||||
|
import io.odin.syntax._ |
||||
|
import scala.concurrent.duration._ |
||||
|
|
||||
|
//effect type should be specified inbefore |
||||
|
//log line will be recorded right after the call with no suspension |
||||
|
class StaticLoggerBinder extends OdinLoggerBinder[IO] { |
||||
|
|
||||
|
val ec: ExecutionContext = Scheduler.global |
||||
|
implicit val timer: Timer[IO] = IO.timer(ec) |
||||
|
implicit val clock: Clock[IO] = timer.clock |
||||
|
implicit val cs: ContextShift[IO] = IO.contextShift(ec) |
||||
|
implicit val F: Effect[IO] = IO.ioEffect |
||||
|
|
||||
|
val monixToCats = new FunctionK[_root_.monix.bio.Task, IO] { |
||||
|
def apply[A](fa: _root_.monix.bio.Task[A]): IO[A] = fa.to[IO] |
||||
|
} |
||||
|
|
||||
|
val (fLogger, release) = |
||||
|
// MainModule.DefaultFileLogger.mapK(monixToCats).allocated.unsafeRunSync() |
||||
|
fileLogger[IO]( |
||||
|
"log2.log" |
||||
|
).withAsync(timeWindow = 1.seconds).allocated.unsafeRunSync() |
||||
|
// Runtime |
||||
|
// .getRuntime() |
||||
|
// .addShutdownHook(new Thread { |
||||
|
// release.unsafeRunSync() |
||||
|
// }) |
||||
|
scala.sys.addShutdownHook(release.unsafeRunSync()) |
||||
|
val loggers: PartialFunction[String, Logger[IO]] = { |
||||
|
case "some.external.package.SpecificClass" => |
||||
|
consoleLogger[IO](minLevel = Level.Warn) //disable noisy external logs |
||||
|
case asyncHttpClient |
||||
|
if asyncHttpClient.startsWith("org.asynchttpclient.netty") => |
||||
|
consoleLogger[IO](minLevel = Level.Warn) |
||||
|
case s if s.startsWith("akka.actor") || s.startsWith("wow.doge.mygame") => |
||||
|
consoleLogger[IO]() |+| fLogger |
||||
|
case _ => //if wildcard case isn't provided, default logger is no-op |
||||
|
consoleLogger[IO]() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
object StaticLoggerBinder extends StaticLoggerBinder { |
||||
|
|
||||
|
var REQUESTED_API_VERSION: String = "1.7" |
||||
|
|
||||
|
def getSingleton: StaticLoggerBinder = this |
||||
|
|
||||
|
} |
@ -1,127 +1,105 @@ |
|||||
package wow.doge.mygame |
package wow.doge.mygame |
||||
|
|
||||
import game.GameApp |
|
||||
import com.jme3.app.StatsAppState |
import com.jme3.app.StatsAppState |
||||
|
|
||||
import akka.actor.typed.ActorSystem |
|
||||
import akka.actor.typed.SpawnProtocol |
|
||||
import akka.actor.typed.scaladsl.Behaviors |
|
||||
import akka.actor.typed.Behavior |
|
||||
import akka.util.Timeout |
|
||||
import com.jme3.system.AppSettings |
|
||||
import wow.doge.mygame.game.GameAppActor |
|
||||
import wow.doge.mygame.scriptsystem.ScriptCachingActor |
|
||||
object Main extends App { |
|
||||
import java.util.logging.{Logger, Level} |
|
||||
Logger.getLogger("").setLevel(Level.SEVERE) |
|
||||
|
import monix.bio.Task |
||||
|
import cats.effect.Resource |
||||
|
import io.odin.syntax._ |
||||
|
|
||||
// runner.runCode("""|println("starting scala script engine")""".stripMargin) |
|
||||
val gameApp = new GameApp( |
|
||||
// new EntityDataState(), |
|
||||
// new TestAppState(), |
|
||||
// new PlayerMovementState(), |
|
||||
// new FlyCamAppState(), |
|
||||
new StatsAppState() |
|
||||
) |
|
||||
val settings = new AppSettings(true) |
|
||||
// settings.setVSync(true) |
|
||||
settings.setFrameRate(144) |
|
||||
gameApp.setSettings(settings) |
|
||||
val actorSystem = ActorSystem(RootActor(gameApp), "rootActor") |
|
||||
// actorSystem.eventStream |
|
||||
// gameApp.start() |
|
||||
println("here 1") |
|
||||
// actorSystem.terminate() |
|
||||
// JMEExecutorService.shutdown() |
|
||||
// println("here 2") |
|
||||
//FIXME remove this |
|
||||
// System.exit(0) |
|
||||
} |
|
||||
|
|
||||
object RootActor { |
|
||||
def apply(app: GameApp): Behavior[SpawnProtocol.Command] = |
|
||||
Behaviors.setup { ctx => |
|
||||
ctx.log.debug("Starting root actor") |
|
||||
val testActor = ctx.spawn(TestActor(), "testActor") |
|
||||
val _ = ctx.spawn(GameAppActor(app), "gameAppActor") |
|
||||
|
|
||||
testActor ! TestActor.Test |
|
||||
SpawnProtocol() |
|
||||
} |
|
||||
} |
|
||||
|
// import io.odin.monix._ |
||||
|
import cats.effect.ExitCode |
||||
|
import cats.implicits._ |
||||
|
import com.softwaremill.macwire._ |
||||
|
import scala.concurrent.duration._ |
||||
|
import monix.bio.BIOApp |
||||
|
import monix.bio.UIO |
||||
|
import monix.bio.IO |
||||
|
import io.odin._ |
||||
|
import wow.doge.mygame.executors.JMERunner |
||||
|
import com.jme3.bullet.BulletAppState |
||||
|
import wow.doge.mygame.implicits._ |
||||
|
|
||||
object TestActor { |
|
||||
sealed trait Command |
|
||||
case object Test extends Command |
|
||||
private case object Done extends Command |
|
||||
// sealed trait Result |
|
||||
// case object Done extends Result |
|
||||
|
// import wow.doge.mygame.implicits._ |
||||
|
|
||||
import scala.concurrent.duration._ |
|
||||
implicit val timeout = Timeout(15.seconds) |
|
||||
// implicit val scheduler = |
|
||||
|
// object Main extends App { |
||||
|
// import java.util.logging.{Logger, Level} |
||||
|
// Logger.getLogger("").setLevel(Level.SEVERE) |
||||
|
|
||||
def apply(): Behavior[Command] = |
|
||||
Behaviors.setup { ctx => |
|
||||
ctx.spawn(ScriptCachingActor(), "scriptCacher") |
|
||||
Behaviors.receiveMessage { msg => |
|
||||
msg match { |
|
||||
case Test => |
|
||||
// ctx.ask( |
|
||||
// router, |
|
||||
// ScriptActor.Compile( |
|
||||
// // os.pwd / "some.sc", |
|
||||
// os.pwd / "src" / "main" / "resources" / "hello2.main.kts", |
|
||||
// _ |
|
||||
|
// // runner.runCode("""|println("starting scala script engine")""".stripMargin) |
||||
|
// val gameApp = new GameApp( |
||||
|
// // new EntityDataState(), |
||||
|
// // new TestAppState(), |
||||
|
// // new PlayerMovementState(), |
||||
|
// // new FlyCamAppState(), |
||||
|
// new StatsAppState() |
||||
// ) |
// ) |
||||
// ) { |
|
||||
// case Success(value) => |
|
||||
// ctx.log.debug("Received Value") |
|
||||
// ctx.log.debug(value.toString()) |
|
||||
// Done |
|
||||
// case Failure(exception) => |
|
||||
// ctx.log.debug(s"Received Error ${exception.getMessage()}") |
|
||||
// Done |
|
||||
|
// val settings = new AppSettings(true) |
||||
|
// // settings.setVSync(true) |
||||
|
// settings.setFrameRate(144) |
||||
|
// gameApp.setSettings(settings) |
||||
|
// val actorSystem = ActorSystem(RootActor(gameApp), "rootActor") |
||||
|
// // actorSystem.eventStream |
||||
|
// // gameApp.start() |
||||
|
// println("here 1") |
||||
|
// // actorSystem.terminate() |
||||
|
// // JMEExecutorService.shutdown() |
||||
|
// // println("here 2") |
||||
|
// //FIXME remove this |
||||
|
// // System.exit(0) |
||||
// } |
// } |
||||
// val x = scriptStorer |
|
||||
// .askT( |
|
||||
// ScriptStoringActor |
|
||||
// .Get(os.pwd / "src" / "main" / "resources" / "hello2.sc", _) |
|
||||
// )(timeout, ctx.system.scheduler) |
|
||||
|
|
||||
// ctx.ask( |
|
||||
// scriptStorer, |
|
||||
// ScriptStoringActor |
|
||||
// .Get(os.pwd / "src" / "main" / "resources" / "hello2.sc", _) |
|
||||
// ) { |
|
||||
// case Success(value) => { |
|
||||
// ctx.log.debug(value.toString()) |
|
||||
// ctx.ask( |
|
||||
// scriptStorer, |
|
||||
// ScriptStoringActor |
|
||||
// .Get(os.pwd / "src" / "main" / "resources" / "hello2.sc", _) |
|
||||
// ) { |
|
||||
// case Success(value) => { |
|
||||
// ctx.log.debug(value.toString()) |
|
||||
// Done |
|
||||
// } |
|
||||
// case Failure(exception) => |
|
||||
// ctx.log.debug(exception.getMessage()) |
|
||||
// Done |
|
||||
// } |
|
||||
// Done |
|
||||
// } |
|
||||
// case Failure(exception) => |
|
||||
// ctx.log.debug(exception.getMessage()) |
|
||||
// Done |
|
||||
// } |
|
||||
|
object Main extends BIOApp with MainModule { |
||||
|
import java.util.logging.{Logger => JLogger, Level} |
||||
|
JLogger.getLogger("").setLevel(Level.SEVERE) |
||||
|
|
||||
Behaviors.same |
|
||||
case Done => Behaviors.same |
|
||||
|
def run(args: List[String]): UIO[ExitCode] = { |
||||
|
|
||||
|
lazy val appResource = for { |
||||
|
logger <- |
||||
|
consoleLogger().withAsync(timeWindow = 1.seconds) |+| fileLogger( |
||||
|
"log.log" |
||||
|
).withAsync(timeWindow = 1.seconds) |
||||
|
jmeScheduler <- jMESchedulerResource |
||||
|
// consoleTextArea <- Resource.liftF(Task(new TextArea())) |
||||
|
// consoleStream <- wireWith(JFXConsoleStream.textAreaStream _) |
||||
|
gameApp <- { |
||||
|
new BulletAppState() |
||||
|
// bas.setThreadingType(Thr) |
||||
|
gameAppResource(new StatsAppState()) |
||||
} |
} |
||||
|
_ <- Resource.liftF(IO(JMERunner.runner = gameApp)) |
||||
|
actorSystem <- wireWith(actorSystemResource _) |
||||
|
// _ <- Resource.liftF( |
||||
|
// Task(gameApp.start()).asyncBoundary |
||||
|
// .executeOn(Scheduler(JMEExecutorService)) |
||||
|
// ) |
||||
|
|
||||
// SpawnProtocol() |
|
||||
// Behaviors.same |
|
||||
|
_ <- Resource.liftF(gameApp.enqueueT(actorSystem ! RootActor.Start)) |
||||
|
_ <- Resource.liftF { |
||||
|
IO(gameApp.start()) |
||||
|
.executeOn(jmeScheduler) |
||||
} |
} |
||||
|
// (_ => IO(gameApp.stop(() => actorSystem ! RootActor.Stop))) |
||||
|
} yield () |
||||
|
|
||||
|
// Console.withOut( |
||||
|
// new JFXConsoleStream( |
||||
|
// new scalafx.scene.control.TextArea(), |
||||
|
// new ByteArrayOutputStream(35) |
||||
|
// ) |
||||
|
// )(()) |
||||
|
appResource |
||||
|
.use(_ => |
||||
|
// Task(gameApp.start()) |
||||
|
// .executeOn(Scheduler(JMEExecutorService)) |
||||
|
// .asyncBoundary |
||||
|
// Task.never |
||||
|
Task.unit |
||||
|
// >> |
||||
|
|
||||
|
// .executeOn(Scheduler(JMEExecutorService)) |
||||
|
) |
||||
|
.onErrorHandle(_.printStackTrace()) |
||||
|
.as(ExitCode.Success) |
||||
} |
} |
||||
} |
} |
@ -0,0 +1,87 @@ |
|||||
|
package wow.doge.mygame |
||||
|
import akka.actor.typed.scaladsl.Behaviors |
||||
|
import wow.doge.mygame.game.GameApp |
||||
|
import akka.actor.typed.Behavior |
||||
|
import wow.doge.mygame.game.GameAppActor |
||||
|
import cats.effect.Resource |
||||
|
import akka.actor.typed.ActorSystem |
||||
|
import monix.bio.Task |
||||
|
import wow.doge.mygame.game.GameModule |
||||
|
import io.odin._ |
||||
|
import io.odin.syntax._ |
||||
|
import wow.doge.mygame.executors.ExecutorsModule |
||||
|
import akka.actor.typed.scaladsl.ActorContext |
||||
|
import wow.doge.mygame.executors.Schedulers |
||||
|
import com.softwaremill.macwire._ |
||||
|
|
||||
|
trait MainModule extends GameModule with ExecutorsModule { |
||||
|
def actorSystemResource( |
||||
|
logger: Logger[Task], |
||||
|
app: GameApp, |
||||
|
schedulers: Schedulers |
||||
|
): Resource[Task, ActorSystem[RootActor.Command]] = |
||||
|
Resource.make(logger.info("Creating Actor System") >> Task { |
||||
|
ActorSystem(RootActor(app, schedulers), name = "GameActorSystem") |
||||
|
})(sys => |
||||
|
logger.info("Shutting down actor system") >> Task( |
||||
|
sys.terminate() |
||||
|
) |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
object MainModule { |
||||
|
|
||||
|
// import cats.implicits._ |
||||
|
import scala.concurrent.duration._ |
||||
|
val DefaultFileLogger: Resource[Task, Logger[Task]] = |
||||
|
fileLogger[Task]( |
||||
|
"log.log" |
||||
|
).withAsync(timeWindow = 1.seconds) |
||||
|
} |
||||
|
|
||||
|
object RootActor { |
||||
|
sealed trait Command |
||||
|
final case object Start extends Command |
||||
|
final case object Stop extends Command |
||||
|
|
||||
|
final case class State(initialized: Boolean = false) |
||||
|
def apply( |
||||
|
app: GameApp, |
||||
|
schedulers: Schedulers, |
||||
|
state: State = State() |
||||
|
): Behavior[Command] = |
||||
|
Behaviors.setup { ctx => |
||||
|
ctx.log.info("Hello from root actor") |
||||
|
wire[RootActor].receive(state) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class RootActor( |
||||
|
ctx: ActorContext[RootActor.Command], |
||||
|
app: GameApp, |
||||
|
schedulers: Schedulers |
||||
|
) { |
||||
|
import RootActor._ |
||||
|
def receive(state: State): Behavior[Command] = |
||||
|
Behaviors.receiveMessage(msg => |
||||
|
msg match { |
||||
|
case Start => |
||||
|
if (!state.initialized) { |
||||
|
ctx.log.info("Starting GameAppActor") |
||||
|
val _ = ctx.spawn( |
||||
|
wireWith(GameAppActor.apply _), |
||||
|
"gameAppActor" |
||||
|
// DispatcherSelector.fromConfig("jme-dispatcher") |
||||
|
) |
||||
|
receive(state.copy(initialized = true)) |
||||
|
} else { |
||||
|
ctx.log.warn("Already Initialized") |
||||
|
Behaviors.same |
||||
|
} |
||||
|
case Stop => |
||||
|
ctx.log.info("Stopping") |
||||
|
Behaviors.stopped |
||||
|
|
||||
|
} |
||||
|
) |
||||
|
} |
@ -1,5 +1,23 @@ |
|||||
package wow.doge.mygame.executors |
package wow.doge.mygame.executors |
||||
|
|
||||
|
import monix.bio.Task |
||||
|
import cats.effect.Resource |
||||
|
import monix.execution.Scheduler |
||||
|
|
||||
trait ExecutorsModule { |
trait ExecutorsModule { |
||||
lazy val schedulers = new Schedulers() |
|
||||
|
lazy val schedulers = Schedulers() |
||||
|
// Resource.make( |
||||
|
// Task( |
||||
|
// new Schedulers( |
||||
|
// jme = Scheduler |
||||
|
// .singleThread(name = "JME-Application-Thread", daemonic = false) |
||||
|
// ) |
||||
|
// ) |
||||
|
// )(s => Task(s.jme.shutdown())) |
||||
|
lazy val jMESchedulerResource = Resource.make( |
||||
|
Task( |
||||
|
Scheduler |
||||
|
.singleThread(name = "JME-Application-Thread", daemonic = false) |
||||
|
) |
||||
|
)(e => Task(e.shutdown())) |
||||
} |
} |
@ -0,0 +1,25 @@ |
|||||
|
package wow.doge.mygame.game |
||||
|
|
||||
|
import cats.effect.Resource |
||||
|
import com.jme3.app.state.AppState |
||||
|
import com.jme3.system.AppSettings |
||||
|
import monix.bio.Task |
||||
|
// import wow.doge.mygame.executors.JMERunner |
||||
|
|
||||
|
trait GameModule { |
||||
|
|
||||
|
def gameAppResource(appStates: AppState*): Resource[Task, GameApp] = |
||||
|
Resource.liftF { |
||||
|
for { |
||||
|
app <- Task(new GameApp(appStates: _*)) |
||||
|
_ <- Task { |
||||
|
val settings = new AppSettings(true) |
||||
|
// settings.setVSync(true) |
||||
|
settings.setFrameRate(144) |
||||
|
app.setSettings(settings) |
||||
|
// JMERunner.runner = app |
||||
|
app |
||||
|
} |
||||
|
} yield (app) |
||||
|
} |
||||
|
} |
@ -0,0 +1,13 @@ |
|||||
|
package wow.doge.mygame.game |
||||
|
|
||||
|
import wow.doge.mygame.state.MyBaseState |
||||
|
|
||||
|
class GameSystemsInitializer extends MyBaseState { |
||||
|
|
||||
|
override protected def onEnable(): Unit = {} |
||||
|
|
||||
|
override protected def onDisable(): Unit = {} |
||||
|
|
||||
|
override protected def init(): Unit = {} |
||||
|
override def stop(): Unit = {} |
||||
|
} |
@ -0,0 +1,84 @@ |
|||||
|
package wow.doge.mygame.game |
||||
|
|
||||
|
import akka.actor.typed.Behavior |
||||
|
import akka.actor.typed.scaladsl.Behaviors |
||||
|
import akka.util.Timeout |
||||
|
import wow.doge.mygame.scriptsystem.ScriptCachingActor |
||||
|
|
||||
|
object TestActor { |
||||
|
sealed trait Command |
||||
|
case object Test extends Command |
||||
|
private case object Done extends Command |
||||
|
|
||||
|
import scala.concurrent.duration._ |
||||
|
implicit val timeout = Timeout(15.seconds) |
||||
|
|
||||
|
def apply( |
||||
|
// scriptCacheBehavior: Behavior[ScriptCachingActor.Command] |
||||
|
): Behavior[Command] = |
||||
|
Behaviors.setup { ctx => |
||||
|
ctx.spawn(ScriptCachingActor(), "scriptCacher") |
||||
|
Behaviors.receiveMessage { msg => |
||||
|
msg match { |
||||
|
case Test => |
||||
|
Behaviors.same |
||||
|
case Done => Behaviors.same |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
def testKotlinScriptCompilation() = { |
||||
|
// ctx.ask( |
||||
|
// router, |
||||
|
// ScriptActor.Compile( |
||||
|
// // os.pwd / "some.sc", |
||||
|
// os.pwd / "src" / "main" / "resources" / "hello2.main.kts", |
||||
|
// _ |
||||
|
// ) |
||||
|
// ) { |
||||
|
// case Success(value) => |
||||
|
// ctx.log.debug("Received Value") |
||||
|
// ctx.log.debug(value.toString()) |
||||
|
// Done |
||||
|
// case Failure(exception) => |
||||
|
// ctx.log.debug(s"Received Error ${exception.getMessage()}") |
||||
|
// Done |
||||
|
// } |
||||
|
} |
||||
|
|
||||
|
def testTaskWrapper() = { |
||||
|
// val x = scriptStorer |
||||
|
// .askT( |
||||
|
// ScriptStoringActor |
||||
|
// .Get(os.pwd / "src" / "main" / "resources" / "hello2.sc", _) |
||||
|
// )(timeout, ctx.system.scheduler) |
||||
|
} |
||||
|
|
||||
|
def testScriptCaching() = { |
||||
|
// ctx.ask( |
||||
|
// scriptStorer, |
||||
|
// ScriptStoringActor |
||||
|
// .Get(os.pwd / "src" / "main" / "resources" / "hello2.sc", _) |
||||
|
// ) { |
||||
|
// case Success(value) => { |
||||
|
// ctx.log.debug(value.toString()) |
||||
|
// ctx.ask( |
||||
|
// scriptStorer, |
||||
|
// ScriptStoringActor |
||||
|
// .Get(os.pwd / "src" / "main" / "resources" / "hello2.sc", _) |
||||
|
// ) { |
||||
|
// case Success(value) => { |
||||
|
// ctx.log.debug(value.toString()) |
||||
|
// Done |
||||
|
// } |
||||
|
// case Failure(exception) => |
||||
|
// ctx.log.debug(exception.getMessage()) |
||||
|
// Done |
||||
|
// } |
||||
|
// Done |
||||
|
// } |
||||
|
// case Failure(exception) => |
||||
|
// ctx.log.debug(exception.getMessage()) |
||||
|
// Done |
||||
|
// } |
||||
|
} |
||||
|
} |
@ -1,4 +1,4 @@ |
|||||
package wow.doge.mygame.state; |
|
||||
|
package wow.doge.mygame.game.appstates; |
||||
|
|
||||
import com.jme3.app.state.AbstractAppState; |
import com.jme3.app.state.AbstractAppState; |
||||
import com.simsilica.es.EntityData; |
import com.simsilica.es.EntityData; |
@ -0,0 +1,94 @@ |
|||||
|
package wow.doge.mygame.game.nodes |
||||
|
|
||||
|
import com.jme3.scene.Node |
||||
|
import com.jme3.scene.CameraNode |
||||
|
import com.jme3.scene.Geometry |
||||
|
import com.jme3.renderer.Camera |
||||
|
import wow.doge.mygame.implicits._ |
||||
|
import com.jme3.asset.AssetManager |
||||
|
import wow.doge.mygame.state.MyMaterial |
||||
|
import com.jme3.math.Vector3f |
||||
|
import com.jme3.scene.control.CameraControl.ControlDirection |
||||
|
import com.jme3.syntax._ |
||||
|
import com.jme3.scene.shape.Box |
||||
|
|
||||
|
// class PlayerNode(val name: String) extends Node(name) {} |
||||
|
object PlayerNode { |
||||
|
def defaultMesh() = { |
||||
|
lazy val b = new Box(1, 1, 1) |
||||
|
lazy val geom = new Geometry("playerMesh", b) |
||||
|
geom |
||||
|
} |
||||
|
def defaultTexture(assetManager: AssetManager) = |
||||
|
MyMaterial( |
||||
|
assetManager = assetManager, |
||||
|
path = os.rel / "Common" / "MatDefs" / "Misc" / "Unshaded.j3md" |
||||
|
) |
||||
|
|
||||
|
def apply( |
||||
|
modelPath: os.RelPath, |
||||
|
cam: Camera |
||||
|
)(assetManager: AssetManager) = { |
||||
|
lazy val playerNode = new Node("PlayerNode") |
||||
|
lazy val camNode = new CameraNode("CameraNode", cam) |
||||
|
|
||||
|
// lazy val camNode = new CameraNode("CameraNode", simpleApp.getCamera()) |
||||
|
// camNode.setCamera(simpleApp.getCamera()) |
||||
|
|
||||
|
val playerModel: Node = |
||||
|
assetManager.loadModel(modelPath).asInstanceOf[Node] |
||||
|
discard { |
||||
|
playerNode |
||||
|
.child(camNode) |
||||
|
.child(playerModel) |
||||
|
// playerNode.children(Seq(camNode, geom)) |
||||
|
} |
||||
|
|
||||
|
{ |
||||
|
camNode.setControlDir(ControlDirection.SpatialToCamera) |
||||
|
camNode.setLocalTranslation( |
||||
|
new Vector3f(0, 1.5f, 10) |
||||
|
) |
||||
|
camNode.lookAt(playerNode.getLocalTranslation(), Vector3f.UNIT_Y) |
||||
|
} |
||||
|
|
||||
|
playerNode |
||||
|
} |
||||
|
def apply( |
||||
|
mesh: Geometry = defaultMesh(), |
||||
|
texturePath: os.RelPath = |
||||
|
os.rel / "Common" / "MatDefs" / "Misc" / "Unshaded.j3md", |
||||
|
cam: Camera |
||||
|
)(assetManager: AssetManager): Node = { |
||||
|
|
||||
|
lazy val playerNode = new Node("PlayerNode") |
||||
|
lazy val camNode = new CameraNode("CameraNode", cam) |
||||
|
|
||||
|
{ |
||||
|
val mat = MyMaterial( |
||||
|
assetManager = assetManager, |
||||
|
path = texturePath |
||||
|
) |
||||
|
mesh.setMaterial(mat) |
||||
|
} |
||||
|
|
||||
|
// lazy val camNode = new CameraNode("CameraNode", simpleApp.getCamera()) |
||||
|
// camNode.setCamera(simpleApp.getCamera()) |
||||
|
discard { |
||||
|
playerNode |
||||
|
.child(camNode) |
||||
|
.child(mesh) |
||||
|
// playerNode.children(Seq(camNode, geom)) |
||||
|
} |
||||
|
|
||||
|
{ |
||||
|
camNode.setControlDir(ControlDirection.SpatialToCamera) |
||||
|
camNode.setLocalTranslation( |
||||
|
new Vector3f(0, 1.5f, 10) |
||||
|
) |
||||
|
camNode.lookAt(playerNode.getLocalTranslation(), Vector3f.UNIT_Y) |
||||
|
} |
||||
|
|
||||
|
playerNode |
||||
|
} |
||||
|
} |
@ -0,0 +1,142 @@ |
|||||
|
package wow.doge.mygame.subsystems.moddingsystem |
||||
|
import java.io.FileNotFoundException |
||||
|
|
||||
|
import scala.collection.View |
||||
|
import scala.collection.immutable.ArraySeq |
||||
|
import scala.util.Try |
||||
|
|
||||
|
import cats.implicits._ |
||||
|
import io.circe._ |
||||
|
import io.circe.generic.semiauto._ |
||||
|
import io.circe.parser._ |
||||
|
import monix.bio.IO |
||||
|
import monix.bio.UIO |
||||
|
import java.nio.file.NoSuchFileException |
||||
|
import io.circe.generic.JsonCodec |
||||
|
|
||||
|
@JsonCodec |
||||
|
case class Test1(hello1: String, hello2: String) |
||||
|
@JsonCodec |
||||
|
case class Test2(hello1: String) |
||||
|
case class Plugin(name: String, priority: Int) |
||||
|
object Plugin { |
||||
|
implicit val pluginFormat: Decoder[Plugin] = deriveDecoder |
||||
|
} |
||||
|
|
||||
|
object ModdingSystem { |
||||
|
sealed trait Error extends Serializable with Product |
||||
|
case class CouldNotDecode(cause: String) extends Error |
||||
|
case class ParseFailure(cause: String) extends Error |
||||
|
case class FileNotFound(name: String) extends Error |
||||
|
case object GenericError extends Error |
||||
|
|
||||
|
def readPluginsList(dir: os.Path): Try[Either[Error, ArraySeq[Plugin]]] = |
||||
|
Try( |
||||
|
parse(os.read(dir / "plugins.json")) |
||||
|
.map( |
||||
|
_.as[ArraySeq[Plugin]] |
||||
|
.leftMap(e => CouldNotDecode(e.getMessage())) |
||||
|
) |
||||
|
.leftMap((e: ParsingFailure) => ParseFailure(e.message)) |
||||
|
.flatten |
||||
|
) |
||||
|
// .toValidated |
||||
|
|
||||
|
def findPluginFiles(dir: os.Path): View[os.Path] = |
||||
|
os.list(dir) |
||||
|
.view |
||||
|
.filter(f => f.ext == "json" && f.baseName.endsWith("plugin")) |
||||
|
|
||||
|
def findAndReadPluginFiles( |
||||
|
dir: os.Path, |
||||
|
plugins: ArraySeq[Plugin] |
||||
|
) = |
||||
|
plugins |
||||
|
.sortBy(_.priority) |
||||
|
.view |
||||
|
.map(p => |
||||
|
p -> |
||||
|
Either |
||||
|
.catchNonFatal { |
||||
|
val path = dir / os.RelPath(p.name + ".plugin.json") |
||||
|
os.read(path) |
||||
|
} |
||||
|
.leftMap { |
||||
|
case _: FileNotFoundException => |
||||
|
FileNotFound(p.name) |
||||
|
case _: NoSuchFileException => FileNotFound(p.name) |
||||
|
case e => GenericError |
||||
|
} |
||||
|
) |
||||
|
.partitionMap { |
||||
|
case (p, either) => |
||||
|
either match { |
||||
|
case Left(value) => Left(p -> value) |
||||
|
case Right(value) => Right(p -> value) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
def readPluginFiles(filePaths: View[os.Path]) = { |
||||
|
filePaths.map(path => os.read(path)) |
||||
|
} |
||||
|
|
||||
|
def parsePluginFiles(files: View[(Plugin, String)]) = |
||||
|
files |
||||
|
.map { |
||||
|
case (p, s) => p -> parse(s) |
||||
|
} |
||||
|
.partitionMap { |
||||
|
case (p, Left(value)) => Left(p -> value) |
||||
|
case (p, Right(value)) => Right(p -> value) |
||||
|
} |
||||
|
|
||||
|
def mergePluginData(plugins: View[(Plugin, Json)]) = { |
||||
|
plugins.foldLeft(Json.fromString("empty")) { |
||||
|
case (json, that) => |
||||
|
that match { |
||||
|
case (p, io.circe.Json.Null) => json //ignore null values |
||||
|
case (p, value) => json.deepMerge(value) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// def test = |
||||
|
// for { |
||||
|
// filePaths <- Task(findPluginFiles(os.pwd)) |
||||
|
// files <- Task(readPluginFiles(filePaths)) |
||||
|
// (failures, successes) <- Task(parsePluginFiles(files)) |
||||
|
// merged <- Task(mergePluginData(successes)) |
||||
|
// _ <- Task { |
||||
|
// println(s"Successes = ${successes.to(Seq)}") |
||||
|
// println(s"Failure = ${failures.to(Seq)}") |
||||
|
// println(s"Merged = $merged") |
||||
|
// } |
||||
|
// } yield () |
||||
|
|
||||
|
def test(wd: os.Path = os.pwd) = |
||||
|
for { |
||||
|
plugins <- IO.fromTryEither(readPluginsList(wd)) |
||||
|
(readFailures, readSuccesses) <- UIO(findAndReadPluginFiles(wd, plugins)) |
||||
|
(parseFailures, parseSuccesses) <- UIO(parsePluginFiles(readSuccesses)) |
||||
|
res <- UIO(mergePluginData(parseSuccesses)) |
||||
|
f <- UIO { |
||||
|
println(s"Read Successes = ${readSuccesses.to(Seq)}") |
||||
|
println(s"Read Failures = ${readFailures.to(Seq)}") |
||||
|
println(s"Parse Successes = ${parseSuccesses.to(Seq)}") |
||||
|
println(s"Parse Failures = ${parseFailures.to(Seq)}") |
||||
|
println(s"Merged = $res") |
||||
|
} |
||||
|
} yield () |
||||
|
|
||||
|
// monix.eval.Task.deferAction(implicit s => |
||||
|
// ModdingSystem |
||||
|
// .test() |
||||
|
// .leftMap(e => new Throwable(e.toString())) |
||||
|
// .to[monix.eval.Task] |
||||
|
// ) |
||||
|
|
||||
|
// def test3(wd: os.Path = os.pwd) = { |
||||
|
// (readPluginsList(os.pwd).toValidatedNec) |
||||
|
// } |
||||
|
; |
||||
|
} |
@ -0,0 +1,53 @@ |
|||||
|
package wow.doge.mygame.utils |
||||
|
|
||||
|
import java.io.PrintStream |
||||
|
import java.io.OutputStream |
||||
|
import java.io.ByteArrayOutputStream |
||||
|
import scalafx.scene.control.TextArea |
||||
|
import wow.doge.mygame.implicits._ |
||||
|
import cats.effect.Resource |
||||
|
import monix.bio.Task |
||||
|
|
||||
|
trait JFXConsoleStreamable[T] { |
||||
|
def println(inst: T, text: String): Unit |
||||
|
def print(inst: T, text: String): Unit |
||||
|
} |
||||
|
|
||||
|
class JFXConsoleStream[T]( |
||||
|
outputStream: OutputStream, |
||||
|
val config: JFXConsoleStream.Config = JFXConsoleStream.Config.default, |
||||
|
control: T |
||||
|
)(implicit |
||||
|
jcs: JFXConsoleStreamable[T] |
||||
|
) extends PrintStream(outputStream, true) { |
||||
|
private lazy val defaultOut = System.out |
||||
|
override def println(text: String): Unit = |
||||
|
if (config.exclusive) { |
||||
|
jcs.println(control, text + "\n") |
||||
|
} else { |
||||
|
defaultOut.println(text) |
||||
|
jcs.println(control, text + "\n") |
||||
|
} |
||||
|
override def print(text: String): Unit = jcs.println(control, text) |
||||
|
} |
||||
|
|
||||
|
object JFXConsoleStream { |
||||
|
|
||||
|
/** |
||||
|
* for future use |
||||
|
*/ |
||||
|
case class Config(exclusive: Boolean = false) |
||||
|
object Config { |
||||
|
lazy val default = Config() |
||||
|
} |
||||
|
|
||||
|
def textAreaStream(ta: TextArea) = |
||||
|
Resource.make( |
||||
|
Task( |
||||
|
new JFXConsoleStream( |
||||
|
outputStream = new ByteArrayOutputStream(), |
||||
|
control = ta |
||||
|
) |
||||
|
) |
||||
|
)(s => Task(s.close())) |
||||
|
} |
@ -0,0 +1 @@ |
|||||
|
{ "hello1": "world1", "hello2": "world2" } |
@ -0,0 +1 @@ |
|||||
|
{ "hello2": "world3" } |
Write
Preview
Loading…
Cancel
Save
Reference in new issue