Browse Source

many changes

master
Rohan Sircar 11 months ago
parent
commit
b0994bcdbe
  1. 4
      .jvmopts
  2. 9
      build.sbt
  3. 3
      launch.sh
  4. BIN
      lib/jme3-testdata.jar
  5. 4
      plugins.json
  6. 1
      project/plugins.sbt
  7. 3
      src/main/resources/hello.groovy
  8. 1
      src/main/resources/hello2.sc
  9. 59
      src/main/scala/org/slf4j/impl/StaticLoggerBuilder.scala
  10. 204
      src/main/scala/wow/doge/mygame/Main.scala
  11. 87
      src/main/scala/wow/doge/mygame/MainModule.scala
  12. 20
      src/main/scala/wow/doge/mygame/executors/ExecutorsModule.scala
  13. 11
      src/main/scala/wow/doge/mygame/executors/GUIExecutor.scala
  14. 6
      src/main/scala/wow/doge/mygame/executors/Schedulers.scala
  15. 99
      src/main/scala/wow/doge/mygame/game/GameApp.scala
  16. 195
      src/main/scala/wow/doge/mygame/game/GameAppActor.scala
  17. 25
      src/main/scala/wow/doge/mygame/game/GameModule.scala
  18. 13
      src/main/scala/wow/doge/mygame/game/GameSystemsInitializer.scala
  19. 84
      src/main/scala/wow/doge/mygame/game/TestActor.scala
  20. 2
      src/main/scala/wow/doge/mygame/game/appstates/EntityDataState.java
  21. 24
      src/main/scala/wow/doge/mygame/game/appstates/MovementActor.scala
  22. 14
      src/main/scala/wow/doge/mygame/game/appstates/MyBaseState.scala
  23. 117
      src/main/scala/wow/doge/mygame/game/appstates/PlayerMovementState.scala
  24. 8
      src/main/scala/wow/doge/mygame/game/appstates/ScriptingEngineState.scala
  25. 16
      src/main/scala/wow/doge/mygame/game/appstates/TestAppState.scala
  26. 0
      src/main/scala/wow/doge/mygame/game/components/Position.scala
  27. 0
      src/main/scala/wow/doge/mygame/game/components/Tag.scala
  28. 0
      src/main/scala/wow/doge/mygame/game/components/Test.java
  29. 0
      src/main/scala/wow/doge/mygame/game/components/TestComponent.scala
  30. 94
      src/main/scala/wow/doge/mygame/game/nodes/PlayerNode.scala
  31. 367
      src/main/scala/wow/doge/mygame/implicits/package.scala
  32. 2
      src/main/scala/wow/doge/mygame/math/ImVector3f.scala
  33. 0
      src/main/scala/wow/doge/mygame/subsystems/events/EventBus.scala
  34. 0
      src/main/scala/wow/doge/mygame/subsystems/events/Events.scala
  35. 0
      src/main/scala/wow/doge/mygame/subsystems/events/EventsModule.scala
  36. 142
      src/main/scala/wow/doge/mygame/subsystems/moddingsystem/ModdingSystem.scala
  37. 111
      src/main/scala/wow/doge/mygame/subsystems/scriptsystem/ScriptActor.scala
  38. 123
      src/main/scala/wow/doge/mygame/subsystems/scriptsystem/ScriptCachingActor.scala
  39. 53
      src/main/scala/wow/doge/mygame/utils/JFXConsoleStream.scala
  40. 1
      test.plugin.json
  41. 1
      test2.plugin.json

4
.jvmopts

@ -0,0 +1,4 @@
-Xms2G
-Xmx2G
-XX:+UseG1GC
-XX:MaxGCPauseMillis=50

9
build.sbt

@ -66,10 +66,11 @@ lazy val root = (project in file(".")).settings(
"com.lihaoyi" % "ammonite" % "2.2.0" cross CrossVersion.full,
"org.jetbrains.kotlin" % "kotlin-main-kts" % "1.4.10",
"org.jetbrains.kotlin" % "kotlin-scripting-jsr223" % "1.4.10",
"org.codehaus.groovy" % "groovy-all" % "3.0.6" pomOnly (),
// "wow.doge" % "game" % "1.0-SNAPSHOT",
"org.scalafx" %% "scalafx" % "14-R19",
"com.typesafe.akka" %% "akka-actor-typed" % "2.6.10",
"ch.qos.logback" % "logback-classic" % "1.2.3",
// "ch.qos.logback" % "logback-classic" % "1.2.3",
"org.typelevel" %% "cats-core" % "2.1.1",
"org.typelevel" %% "cats-effect" % "2.1.4",
"io.monix" %% "monix" % "3.2.2",
@ -85,7 +86,8 @@ lazy val root = (project in file(".")).settings(
"com.softwaremill.macwire" %% "macros" % "2.3.6" % "provided",
"com.softwaremill.macwire" %% "macrosakka" % "2.3.6" % "provided",
"com.github.valskalla" %% "odin-slf4j" % "0.8.1",
"com.softwaremill.quicklens" %% "quicklens" % "1.6.1"
"com.softwaremill.quicklens" %% "quicklens" % "1.6.1",
"org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.0-RC1"
),
// Determine OS version of JavaFX binaries
@ -102,6 +104,7 @@ lazy val root = (project in file(".")).settings(
"-Xlint",
"-Ywarn-numeric-widen",
"-Ymacro-annotations",
"-Xlint:byname-implicit",
// "utf-8", // Specify character encoding used by source files.
"-explaintypes" // Explain type errors in more detail.
),
@ -141,6 +144,7 @@ lazy val root = (project in file(".")).settings(
// semanticdbVersion := scalafixSemanticdb.revision // use Scalafix compatible version
// semanticdbVersion := "4.3.24",
)
initialCommands in (console) := """ammonite.Main.main(Array.empty)"""
// Here, `libraryDependencies` is a set of dependencies, and by using `+=`,
// we're adding the scala-parser-combinators dependency to the set of dependencies
@ -190,3 +194,4 @@ lazy val root = (project in file(".")).settings(
// To learn more about multi-project builds, head over to the official sbt
// documentation at http://www.scala-sbt.org/documentation.html
addCompilerPlugin("com.olegpy" %% "better-monadic-for" % "0.3.1")

3
launch.sh

@ -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

BIN
lib/jme3-testdata.jar

4
plugins.json

@ -0,0 +1,4 @@
[
{ "name": "test", "priority": 1 },
{ "name": "test2", "priority": 2 }
]

1
project/plugins.sbt

@ -1,2 +1,3 @@
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0")
addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.23")
addCompilerPlugin("com.olegpy" %% "better-monadic-for" % "0.3.1")

3
src/main/resources/hello.groovy

@ -0,0 +1,3 @@
println "hello"
this

1
src/main/resources/hello2.sc

@ -1,4 +1,5 @@
#!/usr/bin/env amm
// scala 2.13.3
// import coursierapi.MavenRepository

59
src/main/scala/org/slf4j/impl/StaticLoggerBuilder.scala

@ -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
}

204
src/main/scala/wow/doge/mygame/Main.scala

@ -1,127 +1,105 @@
package wow.doge.mygame
import game.GameApp
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")
// 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._
testActor ! TestActor.Test
SpawnProtocol()
}
}
// 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
// object Main extends App {
// import java.util.logging.{Logger, Level}
// Logger.getLogger("").setLevel(Level.SEVERE)
import scala.concurrent.duration._
implicit val timeout = Timeout(15.seconds)
// implicit val scheduler =
// // 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)
// }
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",
// _
// )
// ) {
// 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 x = scriptStorer
// .askT(
// ScriptStoringActor
// .Get(os.pwd / "src" / "main" / "resources" / "hello2.sc", _)
// )(timeout, ctx.system.scheduler)
object Main extends BIOApp with MainModule {
import java.util.logging.{Logger => JLogger, Level}
JLogger.getLogger("").setLevel(Level.SEVERE)
// 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
// }
def run(args: List[String]): UIO[ExitCode] = {
Behaviors.same
case Done => Behaviors.same
}
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)
}
}

87
src/main/scala/wow/doge/mygame/MainModule.scala

@ -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
}
)
}

20
src/main/scala/wow/doge/mygame/executors/ExecutorsModule.scala

@ -1,5 +1,23 @@
package wow.doge.mygame.executors
import monix.bio.Task
import cats.effect.Resource
import monix.execution.Scheduler
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()))
}

11
src/main/scala/wow/doge/mygame/executors/GUIExecutor.scala

@ -18,7 +18,6 @@ import javafx.application.Platform
import monix.execution.Scheduler
import scala.concurrent.ExecutionContext
import java.util.concurrent.Executor
import wow.doge.mygame.Main
// First we wrap invokeLater/runLater as an ExecutorService
trait GUIExecutorService extends AbstractExecutorService {
@ -44,7 +43,15 @@ object SwingExecutorService extends GUIExecutorService {
}
object JMEExecutorService extends GUIExecutorService {
override def execute(command: Runnable) = Main.gameApp.enqueue(command)
override def execute(command: Runnable) =
JMERunner.runner.enqueue(command)
// new SingleThreadEventExecutor()
sys.addShutdownHook(JMEExecutorService.shutdown())
}
object JMERunner {
var runner: com.jme3.app.Application = null
}
class JavaFXEventThreadExecutorServiceConfigurator(

6
src/main/scala/wow/doge/mygame/executors/Schedulers.scala

@ -4,7 +4,7 @@ import monix.execution.Scheduler
final case class Schedulers(
blockingIO: Scheduler = Scheduler.io(),
cpu: Scheduler = Scheduler.global,
fx: Scheduler = JFXExecutionContexts.fxScheduler,
jme: Option[Scheduler] = None
async: Scheduler = Scheduler.global,
fx: Scheduler = JFXExecutionContexts.fxScheduler
// jme: SchedulerService
)

99
src/main/scala/wow/doge/mygame/game/GameApp.scala

@ -3,23 +3,16 @@ package wow.doge.mygame.game
import com.jme3.app.SimpleApplication
import com.jme3.app.state.AppState
import akka.actor.typed.ActorRef
import akka.actor.typed.Behavior
import akka.actor.typed.scaladsl.Behaviors
object Greeter {
final case class Greet(whom: String, replyTo: ActorRef[Greeted])
final case class Greeted(whom: String, from: ActorRef[Greet])
def apply(): Behavior[Greet] =
Behaviors.receive { (context, message) =>
// context.log.info("Hello {}!", message.whom)
//#greeter-send-messages
message.replyTo ! Greeted(message.whom, context.self)
//#greeter-send-messages
Behaviors.same
}
}
import com.jme3.bullet.BulletAppState
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape
import com.jme3.bullet.control.CharacterControl
import com.jme3.bullet.control.RigidBodyControl
import com.jme3.bullet.util.CollisionShapeFactory
import com.jme3.scene.Spatial
import com.jme3.syntax._
import com.jme3.asset.plugins.ZipLocator
import com.jme3.math.ColorRGBA
import wow.doge.mygame.implicits._
class GameApp(
// actorSystem: ActorSystem[SpawnProtocol.Command],
@ -27,8 +20,47 @@ class GameApp(
) extends SimpleApplication(appStates: _*) {
// implicit val timeout = Timeout(10.seconds)
// implicit val scheduler = actorSystem.scheduler
private lazy val sceneModel: Spatial = assetManager.loadModel("main.scene")
private lazy val bulletAppState: BulletAppState = new BulletAppState()
// bulletAppState.setThreadingType(ThreadingType.SEQUENTIAL)
// We set up collision detection for the scene by creating a
// compound collision shape and a static RigidBodyControl with mass zero.
private lazy val sceneShape = CollisionShapeFactory.createMeshShape(
sceneModel.toNode match {
case util.Right(node) => node
case util.Left(ex) =>
throw new NotImplementedError("No fallback sceneshape")
}
)
private lazy val landscape: RigidBodyControl =
new RigidBodyControl(sceneShape, 0)
// We set up collision detection for the player by creating
// a capsule collision shape and a CharacterControl.
// The CharacterControl offers extra settings for
// size, stepheight, jumping, falling, and gravity.
// We also put the player in its starting position.
protected lazy val capsuleShape = new CapsuleCollisionShape(1.5f, 6f, 1)
private lazy val player: CharacterControl =
new CharacterControl(capsuleShape, 0.05f)
override def simpleInitApp(): Unit = {
discard { stateManager.attach(bulletAppState) }
assetManager.registerLocator(
// "src/main/resources/assets/town.zip",
(os.rel / "src" / "main" / "resources" / "assets" / "town.zip"),
classOf[ZipLocator]
)
viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f))
sceneModel.setLocalScale(2f)
sceneModel.addControl(landscape)
discard { rootNode.attachChild(sceneModel) }
bulletAppState.getPhysicsSpace.add(landscape)
bulletAppState.getPhysicsSpace.add(player)
println("gameapp" + Thread.currentThread().getName())
// val ship = ed.createEntity()
// val mbState = stateManager().state[EntityDataState]().map(_.getEntityData())
@ -88,22 +120,23 @@ class GameApp(
// super.stop()
// }
}
// override def start(): Unit = {
// monix.eval.Task(super.start()).runToFuture(Scheduler(JMEExecutorService))
// }
// def start(system: ActorRef[RootActor.Command]) = {
// // system ! RootActor.Start
// super.start()
object GameApp {
// def myExec(app: SimpleApplication, command: Runnable) = {
// app.enqueue(command)
// }
// val javaFxExecutionContext: ExecutionContext =
// ExecutionContext.fromExecutor(new Executor {
// def execute(command: Runnable): Unit = {
// Platform.runLater(command)
// }
// })
// def jmeEC(app: SimpleApplication): ExecutionContext =
// ExecutionContext.fromExecutor(new Executor {
// override def execute(command: Runnable): Unit = app.enqueue(command)
// })
// def jmeScheduler(app: SimpleApplication) = Sch
// override def stop(): Unit = {
// println("stopping")
// }
def stop[T](cb: () => T): Unit = {
println("destroy")
cb()
super.stop()
}
// override def stop(): Unit = {}
}

195
src/main/scala/wow/doge/mygame/game/GameAppActor.scala

@ -1,63 +1,177 @@
package wow.doge.mygame.game
import akka.actor.typed.scaladsl.Behaviors
import wow.doge.mygame.state.MovementActor
import wow.doge.mygame.state.PlayerMovementState2
import wow.doge.mygame.state.MovementActorTimer
import com.jme3.scene.shape.Box
import wow.doge.mygame.state.PlayerMovementState
import com.jme3.scene.Geometry
import wow.doge.mygame.implicits._
import wow.doge.mygame.events.EventBus
import wow.doge.mygame.events.Events
import wow.doge.mygame.state.ImMovementActor
import com.jme3.scene.CameraNode
import com.jme3.scene.Node
import com.jme3.renderer.Camera
import wow.doge.mygame.executors.Schedulers
import wow.doge.mygame.game.nodes.PlayerNode
import com.softwaremill.macwire._
import wow.doge.mygame.implicits._
object GameAppActor {
import Methods._
sealed trait Command
def apply(app: GameApp) =
case object XD extends Command
case object Stop extends Command
def apply(app: GameApp, schedulers: Schedulers) =
Behaviors.setup[Command] { ctx =>
lazy val b = new Box(1, 1, 1)
lazy val geom = new Geometry("Box", b)
val movementActor =
ctx.spawn(
MovementActor(MovementActor.Props(app, geom)),
"movementActor"
// DispatcherSelector.fromConfig("jme-dispatcher")
)
val movementActorTimer = ctx.spawn(
MovementActorTimer(movementActor),
"movementActorTimer"
)
val imMovementActor = ctx.spawn(
ImMovementActor(ImMovementActor.Props(app, geom)),
"imMovementActor"
)
ctx.log.info("Hello from GameAppActor")
// lazy val b = new Box(1, 1, 1)
// lazy val geom = new Geometry("Box", b)
// lazy val playerNode = new Node("PlayerNode")
// lazy val camNode = new CameraNode("CameraNode", app.getCamera())
// lazy val players = createPlayer(geom, app.getCamera())
// ctx.pipeToSelf(
// app.enqueueF(() => ())(monix.execution.Scheduler.io("aege"))
// ) {
// case x =>
// println("SENDEDEEEEEd")
// XD
// }
// ctx.pipeToSelf(
// createPlayer(
// geom,
// app.getCamera(),
// schedulers.jme
// )
// ) {
// case x =>
// println(x)
// XD
// }
val subscribingActor = ctx.spawn(SubscribingActor(), "subscriber-1")
val eventBus =
val tickEventBus =
ctx.spawn(Behaviors.logMessages(EventBus[Events.Tick]()), "eventBus1")
eventBus ! EventBus.Subscribe(subscribingActor)
tickEventBus ! EventBus.Subscribe(subscribingActor)
eventBus ! EventBus.Publish(Events.PhysicsTick, ctx.self)
tickEventBus ! EventBus.Publish(Events.PhysicsTick, ctx.self)
// {
// app
// .getInputManager()
// .observableAction("Left")
// .map { action =>
// action.binding.name match {
// case "Left" => Task(println("Pressed left"))
// }
// }
// }
// binding match {
// case "Left" =>
def playerNodeFactory =
PlayerNode(
modelPath = os.rel / "Models" / "Jaime" / "Jaime.j3o",
cam = app.camera
) _
// (assetManager = app.assetManager)
{
lazy val playerNode = playerNodeFactory(app.assetManager)
lazy val actor = ctx.spawn(
ImMovementActor(ImMovementActor.Props(app, playerNode)),
"imMovementActor"
)
lazy val state = wire[PlayerMovementState]
app.stateManager.attach(state)
}
Thread.sleep(2000)
app
.getStateManager()
.attach(
new PlayerMovementState2(
movementActor,
movementActorTimer,
imMovementActor,
geom
)
.getRootNode()
.depthFirst(s =>
// s match {
// case node: Node =>
// println("node" + s.getName() + " children " + node.getChildren())
// case g: Geometry => println(s.getName())
// }
println(s.getName())
)
app.start()
Behaviors.stopped
println("----------------")
{
app
.getRootNode()
.observableDepthFirst()
.map(s => s.getName())
// .takeWhileInclusive(_.getName() != "level")
.onErrorHandle(e => e.getMessage())
.foreach(println)(schedulers.async)
}
println("----------------")
{
app
.getRootNode()
.observableBreadthFirst()
.map(s => s.getName())
// .takeWhileInclusive(_.getName() != "level")
.onErrorHandle(e => e.getMessage())
.foreach(println)(schedulers.async)
}
// app.start()
// Behaviors.same
Behaviors.receiveMessage { msg =>
msg match {
case XD =>
ctx.log.info("RECEEEEEIVED")
ctx.log.info(app.camera.toString())
Behaviors.same
case Stop =>
ctx.log.info("Received stop")
Behaviors.stopped
}
}
}
}
object Methods {
def createPlayer(
geom: Geometry,
cam: Camera
): Node = {
val playerNode = new Node("PlayerNode")
lazy val camNode = new CameraNode("CameraNode", cam)
playerNode
.child(camNode)
.child(geom)
playerNode
}
def old() = {
// val movementActor =
// ctx.spawn(
// MovementActor(MovementActor.Props(app, geom)),
// "movementActor"
// // DispatcherSelector.fromConfig("jme-dispatcher")
// )
// val movementActorTimer = ctx.spawn(
// MovementActorTimer(movementActor),
// "movementActorTimer"
// )
}
}
object SubscribingActor {
def apply() =
Behaviors.receive[Events.PhysicsTick.type] { (ctx, msg) =>
@ -65,3 +179,12 @@ object SubscribingActor {
Behaviors.same
}
}
// new PlayerMovementState(
// // movementActor,
// // movementActorTimer,
// imMovementActor,
// // geom,
// // camNode,
// playerNode
// // ctx.self
// )

25
src/main/scala/wow/doge/mygame/game/GameModule.scala

@ -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)
}
}

13
src/main/scala/wow/doge/mygame/game/GameSystemsInitializer.scala

@ -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 = {}
}

84
src/main/scala/wow/doge/mygame/game/TestActor.scala

@ -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
// }
}
}

2
src/main/scala/wow/doge/mygame/state/EntityDataState.java → src/main/scala/wow/doge/mygame/game/appstates/EntityDataState.java

@ -1,4 +1,4 @@
package wow.doge.mygame.state;
package wow.doge.mygame.game.appstates;
import com.jme3.app.state.AbstractAppState;
import com.simsilica.es.EntityData;

24
src/main/scala/wow/doge/mygame/state/MovementActor.scala → src/main/scala/wow/doge/mygame/game/appstates/MovementActor.scala

@ -8,9 +8,9 @@ import wow.doge.mygame.implicits._
import com.jme3.renderer.Camera
import wow.doge.mygame.math.ImVector3f
trait CanMove[T] {
trait CanMove[-A] {
def getDirection(cam: Camera, cardinalDir: CardinalDirection): ImVector3f
def move(inst: T, direction: ImVector3f): Unit
def move(inst: A, direction: ImVector3f): Unit
}
object ImMovementActor {
@ -40,7 +40,10 @@ object ImMovementActor {
)
def apply[T: CanMove](props: Props[T]): Behavior[Command] =
Behaviors.setup(ctx => new ImMovementActor(ctx, props).receive(State()))
Behaviors.setup(ctx => {
ctx.log.info("Hello from MovementActor")
new ImMovementActor(ctx, props).receive(State())
})
}
@ -71,12 +74,15 @@ class ImMovementActor[T](
val walkDir =
cm.getDirection(props.app.getCamera(), state.cardinalDir)
if (walkDir != ImVector3f.ZERO) {
val tmp = walkDir * 2f
props.app.enqueue(new Runnable {
override def run(): Unit = {
cm.move(props.movable, tmp)
}
})
val tmp = walkDir * 25f * tpf
// props.app.enqueue(new Runnable {
// override def run(): Unit = {
// cm.move(props.movable, tmp)
// }
// })
props.app.enqueueF {
cm.move(props.movable, tmp)
}
}
Behaviors.same
// receive(state = state.modify(_.walkDirection).setTo(walkDir))

14
src/main/scala/wow/doge/mygame/state/MyBaseState.scala → src/main/scala/wow/doge/mygame/game/appstates/MyBaseState.scala

@ -7,6 +7,7 @@ import com.jme3.scene.Node
import com.jme3.app.state.BaseAppState
import com.simsilica.es.EntityData
import com.simsilica.es.base.DefaultEntityData
import com.jme3.scene.Spatial
trait MyBaseState extends BaseAppState {
@ -26,17 +27,22 @@ trait MyBaseState extends BaseAppState {
}
protected def init(): Unit
protected def stop(): Unit
override protected def cleanup(app: Application): Unit = {
entityData.close()
// stop()
}
protected def getOrCreateNode(parent: Node, id: String) =
Option(parent.getChild(id)).fold {
val node = new Node(id)
protected def getChildOption(parent: Node, id: String) =
Option(parent.getChild(id))
protected def getOrCreateSpatial(parent: Node, id: String): Spatial =
Option(parent.getChild(id)).getOrElse {
val node: Spatial = new Node(id)
parent.attachChild(node)
node
}(node => node.asInstanceOf[Node])
}
protected def enableStates(classes: Class[_ <: AppState]*) =
setEnabledToStates(true, classes: _*)

117
src/main/scala/wow/doge/mygame/state/PlayerMovementState2.scala → src/main/scala/wow/doge/mygame/game/appstates/PlayerMovementState.scala

@ -1,6 +1,5 @@
package wow.doge.mygame.state
import scala.concurrent.duration.DurationInt
import com.jme3.input.InputManager
@ -17,55 +16,64 @@ import com.jme3.scene.Geometry
import akka.actor.typed.scaladsl.TimerScheduler
import wow.doge.mygame.implicits._
import com.jme3.scene.Node
import com.jme3.syntax._
class PlayerMovementState2(
movementActor: ActorRef[MovementActor.Command],
movementActorTimer: ActorRef[MovementActorTimer.Command],
class PlayerMovementState(
// movementActor: ActorRef[MovementActor.Command],
// movementActorTimer: ActorRef[MovementActorTimer.Command],
imMovementActor: ActorRef[ImMovementActor.Command],
geom: Geometry
// geom: Geometry,
// camNode: CameraNode,
playerNode: Node
// gameAppActor: ActorRef[GameAppActor.Command]
) extends MyBaseState
with ActionListener {
protected lazy val mat = MyMaterial(
assetManager = assetManager,
path = "Common/MatDefs/Misc/Unshaded.j3md"
path = os.rel / "Common" / "MatDefs" / "Misc" / "Unshaded.j3md"
)
override protected[state] def onEnable(): Unit = {}
override protected[state] def onDisable(): Unit = {}
override protected def init(): Unit = {
setupKeys(inputManager)
geom.setMaterial(mat)
rootNode.attachChild(geom)
println("playermovementstate " + Thread.currentThread().getName())
// geom.setMaterial(mat)
// camNode.setControlDir(ControlDirection.SpatialToCamera)
// // lazy val camNode = new CameraNode("CameraNode", simpleApp.getCamera())
// // camNode.setCamera(simpleApp.getCamera())
// discard {
// playerNode
// .child(camNode)
// .child(geom)
// // playerNode.children(Seq(camNode, geom))
// }
discard { rootNode.child(playerNode) }
// camNode.setLocalTranslation(
// new Vector3f(0, 1.5f, 10)
// )
// camNode.lookAt(playerNode.getLocalTranslation(), Vector3f.UNIT_Y)
// movementActorTimer ! MovementActorTimer.Start(geom, cam)
// movementActorTimer ! MovementActorTimer.Start
}
// def system =
// simpleApp.getStateManager.getState(classOf[ActorSystemState]).system
// def player = system.actorSelection("/user/player") //.resolveOne(1.second)
var lastDir: Vector3f = Vector3f.UNIT_X
override def update(tpf: Float) = {
// val direction = new Vector3f()
// direction.multLocal(10 * tpf)
// if (direction.length() > 0f) {
// // player ! PlayerMove(direction)
// lastDir = direction.normalize
// }
// if (shoot) {
// shoot = false
// // player ! Shoot(lastDir)
// }
// movementActor ! MovementActor.Tick(tpf, geom, cam)
imMovementActor ! ImMovementActor.Tick(tpf)
// movementActorTimer ! MovementActorTimer.Update(tpf)
}
override def stop(): Unit = {}
// override protected def cleanup(app: Application): Unit = {
// // gameAppActor ! GameAppActor.Stop
// super.cleanup(app)
// }
def setupKeys(inputManager: InputManager) = {
inputManager
@ -79,33 +87,32 @@ class PlayerMovementState2(
// new KeyTrigger(KeyInput.KEY_D),
new KeyTrigger(KeyInput.KEY_RIGHT)
)
inputManager.addMapping(
"Up",
// new KeyTrigger(KeyInput.KEY_W),
new KeyTrigger(KeyInput.KEY_UP)
)
inputManager.addMapping(
"Down",
// new KeyTrigger(KeyInput.KEY_S),
new KeyTrigger(KeyInput.KEY_DOWN)
)
inputManager.addMapping(
"Space",
new KeyTrigger(KeyInput.KEY_SPACE),
new KeyTrigger(KeyInput.KEY_H)
)
inputManager.addMapping(
"Reset",
new KeyTrigger(KeyInput.KEY_R),
new KeyTrigger(KeyInput.KEY_RETURN)
)
inputManager
.withMapping(
"Up",
// new KeyTrigger(KeyInput.KEY_W),
new KeyTrigger(KeyInput.KEY_UP)
)
.withMapping(
"Down",
// new KeyTrigger(KeyInput.KEY_S),
new KeyTrigger(KeyInput.KEY_DOWN)
)
.withMapping(
"Space",
new KeyTrigger(KeyInput.KEY_SPACE),
new KeyTrigger(KeyInput.KEY_H)
)
.withMapping(
"Reset",
new KeyTrigger(KeyInput.KEY_R),
new KeyTrigger(KeyInput.KEY_RETURN)
)
.withListener(this, "Left")
.withListener(this, "Right")
inputManager.addListener(this, "Up")
inputManager.addListener(this, "Down")
inputManager.addListener(this, "Space")
inputManager.addListener(this, "Reset")
.withListener(this, "Up")
.withListener(this, "Down")
.withListener(this, "Space")
.withListener(this, "Reset")
}
def onAction(binding: String, value: Boolean, tpf: Float) =
@ -118,6 +125,10 @@ class PlayerMovementState2(
case _ =>
}
override protected def onEnable(): Unit = {}
override protected def onDisable(): Unit = {}
}
final case class CardinalDirection(

8
src/main/scala/wow/doge/mygame/state/ScriptingEngineState.scala → src/main/scala/wow/doge/mygame/game/appstates/ScriptingEngineState.scala

@ -4,7 +4,6 @@ import ammonite.runtime.Storage.Folder
import ammonite.main.Defaults
import ammonite.Main
import javax.script.ScriptEngine
import com.jme3.app.Application
import com.jme3.app.state.AppState
import akka.actor.typed.scaladsl.AbstractBehavior
import akka.actor.typed.scaladsl.ActorContext
@ -31,10 +30,11 @@ class ScriptingEngineState(
// _
// )
// )
override def stop(): Unit = {}
override protected def cleanup(app: Application): Unit = {
// actorSystem.terminate()
}
// override protected def cleanup(app: Application): Unit = {
// // actorSystem.terminate()
// }
// override protected def initialize(app: Application): Unit = {
// super.initialize(app)

16
src/main/scala/wow/doge/mygame/state/TestAppState.scala → src/main/scala/wow/doge/mygame/game/appstates/TestAppState.scala

@ -1,6 +1,5 @@
package wow.doge.mygame.state
import com.jme3.app.Application
import wow.doge.mygame.implicits._
import wow.doge.mygame.components.TestComponent
import com.jme3.scene.shape.Box
@ -32,7 +31,7 @@ class TestAppState(
val mat = MyMaterial(
assetManager = assetManager,
path = "Common/MatDefs/Misc/Unshaded.j3md"
path = os.rel / "Common" / "MatDefs" / "Misc" / "Unshaded.j3md"
)
geom.foreach(e => {
e.setMaterial(mat)
@ -45,14 +44,15 @@ class TestAppState(
geom.foreach(_.move(new Vector3f(0, 1 * tpf, 0)))
}
override def cleanup(app: Application): Unit = {
// _entity.map(_.close())
// _entity = None
}
// override def cleanup(app: Application): Unit = {
// // _entity.map(_.close())
// // _entity = None
// }
override def onEnable(): Unit = {}
override def onDisable(): Unit = {}
override def stop(): Unit = {}
}
@ -61,10 +61,10 @@ object MyMaterial {
color: String = "Color",
colorType: com.jme3.math.ColorRGBA = ColorRGBA.Blue,
assetManager: AssetManager,
path: String
path: os.RelPath
): Material = {
val mat =
new Material(assetManager, path)
new Material(assetManager, path.toString())
mat.setColor(color, colorType)
mat
}

0
src/main/scala/wow/doge/mygame/components/Position.scala → src/main/scala/wow/doge/mygame/game/components/Position.scala

0
src/main/scala/wow/doge/mygame/components/Tag.scala → src/main/scala/wow/doge/mygame/game/components/Tag.scala

0
src/main/scala/wow/doge/mygame/components/Test.java → src/main/scala/wow/doge/mygame/game/components/Test.java

0
src/main/scala/wow/doge/mygame/components/TestComponent.scala → src/main/scala/wow/doge/mygame/game/components/TestComponent.scala

94
src/main/scala/wow/doge/mygame/game/nodes/PlayerNode.scala

@ -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
}
}

367
src/main/scala/wow/doge/mygame/implicits/package.scala

@ -12,7 +12,7 @@ import com.simsilica.es.EntityId
import akka.actor.typed.ActorRef
import akka.util.Timeout
import akka.actor.typed.Scheduler
import monix.eval.Task
import monix.bio.Task
import com.jme3.input.InputManager
import com.jme3.input.controls.Trigger
import com.jme3.input.controls.InputListener
@ -22,8 +22,76 @@ import com.jme3.scene.Geometry
import wow.doge.mygame.state.CardinalDirection
import wow.doge.mygame.state.CanMove
import com.jme3.renderer.Camera
import scala.jdk.CollectionConverters._
import wow.doge.mygame.utils.JFXConsoleStreamable
import com.jme3.app.Application
import java.util.concurrent.Callable
import scala.concurrent.Future
import scala.concurrent.ExecutionContext
import com.jme3.scene.SceneGraphVisitor
import monix.reactive.Observable
import com.jme3.asset.AssetManager
import com.jme3.asset.AssetLocator
import com.jme3.input.controls.ActionListener
import monix.reactive.OverflowStrategy
import monix.execution.Ack
import monix.execution.Cancelable
import monix.execution.cancelables.SingleAssignCancelable
import com.jme3.input.Action
import com.jme3.bullet.PhysicsSpace
import com.jme3.bullet.collision.PhysicsCollisionListener
import com.jme3.bullet.collision.PhysicsCollisionEvent
import com.jme3.bullet.PhysicsTickListener
import monix.reactive.observers.Subscriber
import monix.execution.Ack.Continue
import monix.execution.Ack.Stop
case class ActionEvent(binding: Action, value: Boolean, tpf: Float)
case class PhysicsTickEvent(space: PhysicsSpace, tpf: Float)
package object implicits {
type PrePhysicsTickEvent = PhysicsTickEvent
type PhysicsTickObservable =
Observable[Either[PrePhysicsTickEvent, PhysicsTickEvent]]
implicit class JMEAppExt(val app: Application) extends AnyVal {
/**
* Blocking task. Execute on a thread pool meant for blocking operations.
* Prefer [[wow.doge.mygame.implicits.JMEAppExt#enqueueT]] instead.
*
* @param cb
* @param ec
* @return
*/
def enqueueF[T](cb: () => T)(implicit ec: ExecutionContext): Future[T] =
Future {
app
.enqueue(new Callable[T]() {
override def call(): T = cb()
})
.get()
}
/**
* Blocking task. Execute on a thread pool meant for blocking operations.
* Same as enqueue, but returns a Monix Task instead of Future
* @param cb
* @param ec