Browse Source

many changes

master
Rohan Sircar 3 years ago
parent
commit
c93d0704b5
  1. 17
      build.sbt
  2. 2
      src/main/resources/dep.sc
  3. 3
      src/main/resources/hello.groovy
  4. 36
      src/main/resources/hello.main.kts
  5. 35
      src/main/resources/hello.sc
  6. 5
      src/main/resources/hello2.main.kts
  7. 108
      src/main/resources/hello2.sc
  8. 3
      src/main/scala/com/jme3/input/package.scala
  9. 3
      src/main/scala/com/jme3/syntax/package.scala
  10. 22
      src/main/scala/org/slf4j/impl/StaticLoggerBuilder.scala
  11. 27
      src/main/scala/wow/doge/mygame/ActorSystemModule.scala
  12. 121
      src/main/scala/wow/doge/mygame/Main.scala
  13. 139
      src/main/scala/wow/doge/mygame/MainApp.scala
  14. 120
      src/main/scala/wow/doge/mygame/MainModule.scala
  15. 2
      src/main/scala/wow/doge/mygame/executors/ExecutorsModule.scala
  16. 26
      src/main/scala/wow/doge/mygame/executors/GUIExecutor.scala
  17. 2
      src/main/scala/wow/doge/mygame/executors/Schedulers.scala
  18. 14
      src/main/scala/wow/doge/mygame/game/GameApp.scala
  19. 35
      src/main/scala/wow/doge/mygame/game/GameApp2.scala
  20. 38
      src/main/scala/wow/doge/mygame/game/GameAppActor.scala
  21. 42
      src/main/scala/wow/doge/mygame/game/GameModule.scala
  22. 43
      src/main/scala/wow/doge/mygame/game/GameSystemsInitializer.scala
  23. 4
      src/main/scala/wow/doge/mygame/game/appstates/MyBaseState.scala
  24. 12
      src/main/scala/wow/doge/mygame/game/appstates/PlayerMovementState.scala
  25. 17
      src/main/scala/wow/doge/mygame/game/appstates/ScriptingEngineState.scala
  26. 10
      src/main/scala/wow/doge/mygame/game/appstates/TestAppState.scala
  27. 2
      src/main/scala/wow/doge/mygame/game/components/Position.scala
  28. 31
      src/main/scala/wow/doge/mygame/game/nodes/PlayerActorSupervisor.scala
  29. 2
      src/main/scala/wow/doge/mygame/game/nodes/PlayerCameraActor.scala
  30. 60
      src/main/scala/wow/doge/mygame/game/nodes/PlayerController.scala
  31. 12
      src/main/scala/wow/doge/mygame/game/nodes/PlayerEventListeners.scala
  32. 135
      src/main/scala/wow/doge/mygame/game/subsystems/input/GameInputHandler.scala
  33. 3
      src/main/scala/wow/doge/mygame/game/subsystems/input/InputEnums.scala
  34. 57
      src/main/scala/wow/doge/mygame/game/subsystems/level/DefaultGameLevel.scala
  35. 34
      src/main/scala/wow/doge/mygame/game/subsystems/level/Level.scala
  36. 6
      src/main/scala/wow/doge/mygame/game/subsystems/movement/CanMove.scala
  37. 32
      src/main/scala/wow/doge/mygame/game/subsystems/movement/MovementActor.scala
  38. 5
      src/main/scala/wow/doge/mygame/implicits/EntityQuery.scala
  39. 208
      src/main/scala/wow/doge/mygame/implicits/package.scala
  40. 3
      src/main/scala/wow/doge/mygame/subsystems/events/EventBus.scala
  41. 68
      src/main/scala/wow/doge/mygame/subsystems/events/EventsModule.scala
  42. 64
      src/main/scala/wow/doge/mygame/subsystems/events/EventsModule2.scala
  43. 47
      src/main/scala/wow/doge/mygame/subsystems/moddingsystem/ModdingSystem.scala
  44. 21
      src/main/scala/wow/doge/mygame/subsystems/scriptsystem/ScriptActor.scala
  45. 19
      src/main/scala/wow/doge/mygame/subsystems/scriptsystem/ScriptCachingActor.scala
  46. 66
      src/main/scala/wow/doge/mygame/subsystems/scriptsystem/ScriptSystemModule.scala
  47. 6
      src/main/scala/wow/doge/mygame/utils/AkkaUtils.scala
  48. 7
      src/main/scala/wow/doge/mygame/utils/JFXConsoleStream.scala

17
build.sbt

@ -74,7 +74,8 @@ lazy val root = (project in file(".")).settings(
"org.typelevel" %% "cats-core" % "2.1.1",
"org.typelevel" %% "cats-effect" % "2.1.4",
"io.monix" %% "monix" % "3.2.2",
"io.monix" %% "monix-bio" % "1.0.0",
// "io.monix" %% "monix-bio" % "1.0.0",
"io.monix" %% "monix-bio" % "1.1.0",
"io.circe" %% "circe-core" % "0.13.0",
"io.circe" %% "circe-generic" % "0.13.0",
"com.softwaremill.sttp.client" %% "core" % "2.2.5",
@ -91,7 +92,8 @@ lazy val root = (project in file(".")).settings(
"org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.0-RC1",
"com.typesafe.scala-logging" %% "scala-logging" % "3.9.2",
"io.circe" %% "circe-config" % "0.8.0",
"com.beachape" %% "enumeratum-circe" % "1.6.1"
"com.beachape" %% "enumeratum-circe" % "1.6.1",
"com.lihaoyi" %% "os-lib" % "0.7.1"
),
// Determine OS version of JavaFX binaries
@ -104,12 +106,20 @@ lazy val root = (project in file(".")).settings(
"UTF-8",
"-deprecation",
"-feature",
"-language:existentials",
"-language:experimental.macros",
"-language:higherKinds",
"-language:implicitConversions",
"-unchecked",
"-Xlint",
"-Ywarn-numeric-widen",
"-Ymacro-annotations",
"-Xlint:byname-implicit",
// "-Xlint:byname-implicit",
// "utf-8", // Specify character encoding used by source files.
//silence warnings for by-name implicits
"-Wconf:cat=lint-byname-implicit:s",
//give errors on non exhaustive matches
"-Wconf:msg=match may not be exhaustive:e",
"-explaintypes" // Explain type errors in more detail.
),
javacOptions ++= Seq("-source", "11", "-target", "11"),
@ -199,3 +209,4 @@ initialCommands in (console) := """ammonite.Main.main(Array.empty)"""
// 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")
ThisBuild / scalafixDependencies += "com.github.liancheng" %% "organize-imports" % "0.4.3"

2
src/main/resources/dep.sc

@ -1,2 +0,0 @@
// println("hello from dep")
class Test(x: Int)

3
src/main/resources/hello.groovy

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

36
src/main/resources/hello.main.kts

@ -1,36 +0,0 @@
// @file:Import("src/main/resources/hello2.main.kts")
@file:DependsOn("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.0-M1")
@file:DependsOn("/home/rohan/.m2/repository/wow/doge/game/1.0-SNAPSHOT/game-1.0-SNAPSHOT.jar")
@file:DependsOn("/home/rohan/.ivy2/local/wow.doge/mygame_2.13/1.0-SNAPSHOT/jars/mygame_2.13.jar")
import wow.doge.game.types.GameScript
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlin.random.Random
import wow.doge.mygame.components.Test
//println(x * 2)
println("hello from main script")
class GameScriptImpl : GameScript {
override fun start() = runBlocking {
for(x in 0 until 5) {
launch {
val del = Random.nextLong(20, 100)
delay(del)
println("hello from start $x, delay is $del")
}
}
}
override fun stop() {println("hello from stop")}
}
GameScriptImpl()
class MyTest : Test()

35
src/main/resources/hello.sc

@ -1,35 +0,0 @@
// #!/usr/bin/env amm
// import coursierapi.MavenRepository
// interp.repositories.update(
// interp.repositories() ::: List(
// MavenRepository.of("file://home/rohan/.m2/repository")
// )
// )
// @
// import $repo.`https://jcenter.bintray.com`
// // import $repo.`https://bintray.com/jmonkeyengine/com.jme3`
// import $file.dep
// import $ivy.`org.jmonkeyengine:jme3-core:3.2.4-stable`
// import $ivy.`wow.doge:game:1.0-SNAPSHOT`
// import wow.doge.game.types.GameScript
// import com.jme3.scene.control.Control
// println("hello from script")
// class Scr extends GameScript {
// def start(): Unit = println("hello from start")
// def stop(): Unit = println("hello from stop")
// }
// // class SomeClass extends Control {}
// @main
// def main(): GameScript = new Scr()
import $file.dep
import dep.Test
new Test(1)

5
src/main/resources/hello2.main.kts

@ -1,5 +0,0 @@
println("hello from dep")
class Test(val x: Int)
var x = 2

108
src/main/resources/hello2.sc

@ -1,108 +0,0 @@
#!/usr/bin/env amm
// scala 2.13.3
// import coursierapi.MavenRepository
// interp.repositories.update(
// interp.repositories() ::: List(
// MavenRepository.of("file://home/rohan/.m2/repository")
// )
// )
// @
import $repo.`https://jcenter.bintray.com`
// import $repo.`https://bintray.com/jmonkeyengine/com.jme3`
// import $file.dep
import $ivy.`org.jmonkeyengine:jme3-core:3.2.4-stable`
// import $ivy.`wow.doge:game:1.0-SNAPSHOT`
import $ivy.`wow.doge::mygame:1.0-SNAPSHOT`
// import wow.doge.game.types.GameScript
import com.jme3.scene.control.Control
// println("hello from script")
// class Scr extends GameScript {
// def start(): Unit = println("hello from start")
// def stop(): Unit = println("hello from stop")
// }
// // class SomeClass extends Control {}
// @main
// def main(): GameScript = new Scr()
import com.simsilica.es.base.DefaultEntityData
import com.simsilica.es.EntityData
import com.jme3.app.Application
import wow.doge.mygame.game.Implicits._
import wow.doge.mygame.components.TestComponent
import com.jme3.scene.shape.Box
import com.jme3.scene.Geometry
import com.jme3.material.Material
import com.jme3.math.ColorRGBA
import com.jme3.asset.AssetManager
import com.jme3.math.Vector3f
import wow.doge.mygame.state._
class TestAppState(
// private var _entity: Option[EntityData] = Some(new DefaultEntityData())
) extends MyBaseState {
protected lazy val b = new Box(1, 1, 1)
protected lazy val geom = new Geometry("Box", b)
protected lazy val mat = Material(
assetManager = assetManager,
path = "Common/MatDefs/Misc/Unshaded.j3md"
)
// def entity = _entity
// override def initialize(app: Application): Unit = {
// super.initialize(app)
// }
override def init() = {
entityData
.createEntity()
.withComponents(TestComponent())
// entityData.setComponents(x, TestComponent())
val es = entityData.getEntities(classOf[TestComponent])
println(es)
geom.setMaterial(mat)
rootNode.attachChild(geom)
// geom.foreach(e => {
// })
}
override def update(tpf: Float) = {
geom.rotate(0, 0.5f * tpf, 0)
geom.move(new Vector3f(0, 1 * tpf, 0))
}
override def cleanup(app: Application): Unit = {
// _entity.map(_.close())
// _entity = None
}
override def onEnable(): Unit = {}
override def onDisable(): Unit = {}
}
object Material {
def apply(
color: String = "Color",
colorType: com.jme3.math.ColorRGBA = ColorRGBA.Blue,
assetManager: AssetManager,
path: String
): Material = {
val mat =
new Material(assetManager, path)
mat.setColor(color, colorType)
mat
}
}
@main
def main(): MyBaseState = new TestAppState()

3
src/main/scala/com/jme3/input/package.scala

@ -1,6 +1,7 @@
package com.jme3
import com.jme3.input.controls.{InputListener, Trigger}
import com.jme3.input.controls.InputListener
import com.jme3.input.controls.Trigger
/**
* Created by Brandon Barker on 6/21/17.

3
src/main/scala/com/jme3/syntax/package.scala

@ -1,13 +1,12 @@
package com.jme3
/**
* Created by Brandon Barker on 6/21/17.
*/
package object syntax {
@specialized def discard[A](evaluateForSideEffectOnly: A): Unit = {
val _: A = evaluateForSideEffectOnly
val _ = evaluateForSideEffectOnly
() //Return unit to prevent warning due to discarding value
}

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

@ -1,18 +1,22 @@
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.collection.immutable.ArraySeq
import scala.concurrent.ExecutionContext
import scala.concurrent.duration._
import _root_.monix.execution.Scheduler
import cats.arrow.FunctionK
import _root_.monix.execution.Scheduler.Implicits.global
import io.odin.syntax._
import scala.concurrent.duration._
import scala.collection.immutable.ArraySeq
import cats.arrow.FunctionK
import cats.effect.Clock
import cats.effect.ContextShift
import cats.effect.Effect
import cats.effect.IO
import cats.effect.Timer
import cats.implicits._
import io.odin._
import io.odin.json.Formatter
import io.odin.slf4j.OdinLoggerBinder
import io.odin.syntax._
//effect type should be specified inbefore
//log line will be recorded right after the call with no suspension

27
src/main/scala/wow/doge/mygame/ActorSystemModule.scala

@ -1,27 +0,0 @@
package wow.doge.mygame
import akka.actor.typed.ActorSystem
import cats.effect.Resource
import monix.bio.Task
import io.odin.Logger
import wow.doge.mygame.game.GameApp
import wow.doge.mygame.executors.Schedulers
trait ActorSystemModule {
def logger: Logger[Task]
def app: GameApp
def schedulers: Schedulers
lazy val actorsResource =
Resource.make(logger.info("Creating Actor System") >> Task {
ActorSystem(
RootActor(app, schedulers, logger = logger),
name = "GameActorSystem"
)
})(sys =>
logger.info("Shutting down actor system") >> Task(
sys.terminate()
)
)
}

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

@ -1,24 +1,21 @@
package wow.doge.mygame
import cats.effect.Resource
import io.odin.syntax._
import scala.concurrent.duration._
import _root_.monix.bio.Task
import akka.util.Timeout
import cats.effect.ExitCode
import cats.implicits._
import com.softwaremill.macwire._
import scala.concurrent.duration._
import monix.bio.BIOApp
import monix.bio.UIO
import io.odin._
import wow.doge.mygame.game.GameAppResource
import io.odin.json.Formatter
import wow.doge.mygame.game.GameSystemsInitializer
import wow.doge.mygame.subsystems.events.EventsModule2
import wow.doge.mygame.implicits._
import com.jme3.bullet.BulletAppState
import akka.util.Timeout
import io.odin.syntax._
import wow.doge.mygame.game.GameAppResource
import wow.doge.mygame.subsystems.scriptsystem.ScriptSystemResource
import ammonite.runtime.tools.time
import _root_.monix.bio.BIOApp
import _root_.monix.bio.UIO
import cats.effect.Resource
object Main extends BIOApp with MainModule {
import java.util.logging.{Logger => JLogger, Level}
JLogger.getLogger("").setLevel(Level.SEVERE)
@ -41,19 +38,36 @@ object Main extends BIOApp with MainModule {
// akkaScheduler = actorSystemResource2.scheduler
// consoleTextArea <- Resource.liftF(Task(new TextArea()))
// consoleStream <- wireWith(JFXConsoleStream.textAreaStream _)
(gameApp, gameAppFib) <- {
(gameApp) <- {
// new BulletAppState()
// bas.setThreadingType(Thr)
// gameAppResource(new StatsAppState())
wire[GameAppResource].get
wire[GameAppResource].get2
}
app = gameApp
inputManager = gameApp.inputManager
assetManager = gameApp.assetManager
bulletAppState = new BulletAppState()
(playerMovementEventBus, playerCameraEventBus) <- new EventsModule2(
actorSystem
).resource
_ <- Resource.liftF(
new MainApp(logger, gameApp, actorSystem, jmeScheduler)(
timeout,
actorSystem.scheduler
).gameInit
)
// fib <- Resource.liftF(
// gameApp
// .enqueueL(() =>
// new MainApp(logger, gameApp, actorSystem, jmeScheduler)(
// timeout,
// actorSystem.scheduler
// )
// )
// .start
// )
// _ <- Resource.liftF(fib.join.flatMap(_.gameInit)
// app = gameApp
// inputManager = gameApp.inputManager
// assetManager = gameApp.assetManager
// bulletAppState = new BulletAppState()
// (playerMovementEventBus, playerCameraEventBus) <- new EventsModule2(
// actorSystem
// ).resource
// b1 = playerMovementEventBus
// b2 = playerCameraEventBus
@ -67,62 +81,15 @@ object Main extends BIOApp with MainModule {
// )
// }
// _ <- Resource.liftF(IO(JMERunner.runner = gameApp))
// _ <- Resource.liftF(IO {
// new ActorSystemModule {}
// })
// actorSystem <- wireWith(actorSystemResource _)
// rootActor <- rootActorResource(logger, gameApp, schedulers, as2)
// _ <- Resource.liftF(
// gameApp.enqueueT(actorSystem ! RootActor.Start(actorSystem.scheduler))
// )
// gameSystemsInitializer = new GameSystemsInitializer(
// actorSystem,
// logger,
// playerMovementEventBus,
// playerCameraEventBus
// )(gameApp)
gameSystemsInitializerFib <- Resource.make(
logger.info("creating game systems initializer") >>
gameApp
.enqueueL(() => wire[GameSystemsInitializer])
.start
)(c => logger.info("destroying game systems initializer") >> c.cancel)
_ <- Resource.liftF(gameSystemsInitializerFib.join.flatMap(_.init))
// .runAsync {
// case Left(err) => println(err)
// case _ =>
// }(schedulers.async)
// gameSystemsInitializerFib <- Resource.make(
// logger.info("creating game systems initializer") >>
// gameApp
// .enqueueL(() => wire[GameSystemsInitializer])
// .start
// )(c => logger.info("destroying game systems initializer") >> c.cancel)
// _ <- Resource.liftF(gameSystemsInitializerFib.join.flatMap(_.init))
// _ <- Resource.liftF {
// Task {
// implicit val sched = actorSystem.scheduler
// implicit val timeout = Timeout(2.seconds)
// // val module = new EventsModule {}
// }
// }
// actorSystem <- wireWith(actorSystemResource2 _)
// (tickEventBus, playerMovementEventBus) <- wireWith(eventBusesResource _)
// rootActor <- wireWith(rootActorResource _)
// inputSystemHandler <- {
// inputHandlerSystemResource(
// GameInputHandler.Props(gameApp.inputManager, playerMovementEventBus)
// )
// }
// gameSystemsInitializer <-
// gameSystemsResource(actorSystem, inputSystemHandler)
// _ <- Resource.liftF(
// gameApp.enqueueT(rootActor ! RootActor.Start(actorSystem.scheduler))
// )
// _ <- Resource.liftF {
// IO(gameApp.start())
// .executeOn(jmeScheduler)
// }
// (_ => IO(gameApp.stop(() => actorSystem ! RootActor.Stop)))
} yield (gameAppFib)
} yield ()
// def createPlayerController(
// playerMovementEventBus: ActorRef[
@ -145,7 +112,7 @@ object Main extends BIOApp with MainModule {
// )
// )(())
appResource
.use(_.join)
.use(_ => Task.unit)
.onErrorHandle(_.printStackTrace())
.as(ExitCode.Success)
}

139
src/main/scala/wow/doge/mygame/MainApp.scala

@ -0,0 +1,139 @@
package wow.doge.mygame
import akka.actor.typed.ActorRef
import akka.actor.typed.ActorSystem
import akka.actor.typed.Scheduler
import akka.actor.typed.SpawnProtocol
import akka.util.Timeout
import cats.effect.concurrent.Ref
import com.jme3.app.state.AppStateManager
import com.jme3.asset.AssetManager
import com.jme3.asset.plugins.ZipLocator
import com.jme3.bullet.BulletAppState
import com.jme3.input.InputManager
import com.jme3.renderer.Camera
import com.jme3.scene.Node
import com.softwaremill.macwire._
import com.softwaremill.tagging._
import io.odin.Logger
import monix.bio.IO
import monix.bio.Task
import wow.doge.mygame.events.EventBus
import wow.doge.mygame.game.GameApp2
import wow.doge.mygame.game.nodes.Player
import wow.doge.mygame.game.nodes.PlayerController
import wow.doge.mygame.game.subsystems.input.GameInputHandler
import wow.doge.mygame.implicits._
import wow.doge.mygame.math.ImVector3f
import wow.doge.mygame.subsystems.events.EntityMovementEvent
import wow.doge.mygame.subsystems.events.EventsModule2
import wow.doge.mygame.subsystems.events.PlayerCameraEvent
import wow.doge.mygame.game.subsystems.level.DefaultGameLevel
import com.jme3.renderer.ViewPort
import wow.doge.mygame.subsystems.scriptsystem.ScriptSystemResource
import wow.doge.mygame.subsystems.scriptsystem.ScriptInitMode
class MainApp(
logger: Logger[Task],
gameApp: GameApp2,
spawnProtocol: ActorSystem[SpawnProtocol.Command],
jmeThread: monix.execution.Scheduler
)(implicit
@annotation.unused timeout: Timeout,
@annotation.unused scheduler: Scheduler
) {
lazy val scriptSystemInit =
new ScriptSystemResource(os.pwd, spawnProtocol, ScriptInitMode.Eager).init
lazy val gameInit: Task[Unit] = for {
eventsModule <- Task(new EventsModule2(spawnProtocol))
playerMovementEventBus <- eventsModule.playerMovementEventBusTask
playerCameraEventBus <- eventsModule.playerCameraEventBusTask
gameAppFib <- gameApp.start.executeOn(jmeThread).start
/**
* schedule a fiber to run on the JME thread and wait for it's completion
* before proceeding forward, as a signal that JME thread has been
* initialized, otherwise we'll get NPEs trying to access the fields
* of the game app
*/
initFib <- gameApp.enqueueL(() => Task("done")).start
_ <- initFib.join
inputManager <- gameApp.inputManager
assetManager <- gameApp.assetManager
stateManager <- gameApp.stateManager
camera <- gameApp.camera
rootNode <- gameApp.rootNode
enqueueR <- Task(gameApp.enqueue _)
viewPort <- gameApp.viewPort
bulletAppState <- Task(new BulletAppState())
appScheduler <- Task(gameApp.scheduler)
// enqueueL <- Task(gameApp.enqueueL _)
_ <- wire[MainAppDelegate].init(gameApp.scheduler)
_ <- gameAppFib.join
} yield ()
lazy val program = for {
scriptSystem <- scriptSystemInit
game <- gameInit
} yield ()
}
class MainAppDelegate(
gameApp: GameApp2,
spawnProtocol: ActorSystem[SpawnProtocol.Command],
loggerL: Logger[Task],
// eventBuses: EventsModule2
playerMovementEventBus: ActorRef[
EventBus.Command[EntityMovementEvent.PlayerMovementEvent]
],
playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]],
inputManager: InputManager,
assetManager: AssetManager,
stateManager: AppStateManager,
camera: Camera,
viewPort: ViewPort,
enqueueR: Function1[() => Unit, Unit],
rootNode: Ref[Task, Node],
bulletAppState: BulletAppState
)(implicit
@annotation.unused timeout: Timeout,
@annotation.unused scheduler: Scheduler
) {
def init(appScheduler: monix.execution.Scheduler) =
for {
_ <- loggerL.info("Initializing Systems")
_ <- Task(stateManager.attach(bulletAppState))
_ <- Task(
assetManager.registerLocator(
(os.rel / "assets" / "town.zip"),
classOf[ZipLocator]
)
)
_ <- DefaultGameLevel(assetManager, viewPort)
.addToGame(
rootNode,
bulletAppState.physicsSpace
)
.executeOn(appScheduler)
_ <- createPlayerController(appScheduler).startAndForget.onErrorRestart(3)
_ <- wire[GameInputHandler.Props].begin.onErrorRestart(3)
} yield ()
def createPlayerController(
appScheduler: monix.execution.Scheduler
// playerMovementEventBus: ActorRef[
// EventBus.Command[PlayerMovementEvent]
// ],
// playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]]
): IO[PlayerController.Error, Unit] = {
@annotation.unused
val playerPos = ImVector3f.ZERO
@annotation.unused
val playerNode = None.taggedWith[Player]
@annotation.unused
val modelPath = os.rel / "Models" / "Jaime" / "Jaime.j3o"
wire[PlayerController.Props].create
}
}

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

@ -1,41 +1,13 @@
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 akka.actor.typed.SpawnProtocol
import cats.effect.Resource
import io.odin.Logger
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._
import akka.actor.typed.SpawnProtocol
import akka.actor.typed.Scheduler
import wow.doge.mygame.utils.AkkaUtils
import scala.concurrent.duration._
import akka.actor.typed.ActorRef
import wow.doge.mygame.implicits._
import wow.doge.mygame.game.GameModule
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(
wire[RootActor.Props].create(RootActor.State.empty),
name = "GameActorSystem"
)
})(sys =>
logger.info("Shutting down actor system") >> Task(
sys.terminate()
)
)
def actorSystemResource2(
logger: Logger[Task]
@ -43,93 +15,11 @@ trait MainModule extends GameModule with ExecutorsModule {
Resource.make(logger.info("Creating Actor System") >> Task {
ActorSystem(
SpawnProtocol(),
name = "GameActorSystem2"
name = "GameActorSystem"
)
})(sys =>
logger.info("Shutting down actor system") >> Task(
sys.terminate()
)
)
def rootActorResource(
loggerL: Logger[Task],
app: GameApp,
schedulers: Schedulers,
spawnProtocol: ActorSystem[SpawnProtocol.Command]
): Resource[Task, ActorRef[RootActor.Command]] =
Resource.make(
loggerL.info("Creating Root Actor") >>
AkkaUtils.spawnActorL(
behavior = RootActor(app, schedulers, logger = loggerL),
actorName = "RootActor",
spawnProtocol = spawnProtocol
)(1.seconds, spawnProtocol.scheduler)
)(actor =>
loggerL.info("Shutting down root actor") >> (actor !! RootActor.Stop)
)
}
object RootActor {
sealed trait Command
final case class Start(akkaScheduler: Scheduler) extends Command
final case object Stop extends Command
final case class Props(
app: GameApp,
schedulers: Schedulers,
logger: Logger[Task]
) {
def create(state: State): Behavior[Command] =
Behaviors.setup { ctx =>
ctx.log.info("Hello from root actor")
wire[RootActor].receive(State.empty)
}
}
final case class State(initialized: Boolean = false)
object State {
val empty = State()
}
def apply(
app: GameApp,
schedulers: Schedulers,
state: State = State.empty,
logger: Logger[Task]
): 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,
logger: Logger[Task]
) {
import RootActor._
def receive(state: State): Behavior[Command] =
Behaviors.receiveMessage(msg =>
msg match {
case Start(akkaScheduler) =>
if (!state.initialized) {
ctx.log.info("Starting GameAppActor")
val spawnProtocol = ctx.spawn(SpawnProtocol(), "spawnProtocol")
val _ = ctx.spawn(
wire[GameAppActor.Props].create,
"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
}
)
}

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

@ -1,7 +1,7 @@
package wow.doge.mygame.executors
import monix.bio.Task
import cats.effect.Resource
import monix.bio.Task
import monix.execution.Scheduler
trait ExecutorsModule {

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

@ -1,23 +1,21 @@
package wow.doge.mygame.executors
import akka.dispatch.{
DispatcherPrerequisites,
ExecutorServiceFactory,
ExecutorServiceConfigurator
}
import com.typesafe.config.Config
import java.util.concurrent.{
ExecutorService,
AbstractExecutorService,
ThreadFactory,
TimeUnit
}
import java.util.Collections
import java.util.concurrent.AbstractExecutorService
import java.util.concurrent.Executor
import java.util.concurrent.ExecutorService
import java.util.concurrent.ThreadFactory
import java.util.concurrent.TimeUnit
import javax.swing.SwingUtilities
import scala.concurrent.ExecutionContext
import akka.dispatch.DispatcherPrerequisites
import akka.dispatch.ExecutorServiceConfigurator
import akka.dispatch.ExecutorServiceFactory
import com.typesafe.config.Config
import javafx.application.Platform
import monix.execution.Scheduler
import scala.concurrent.ExecutionContext
import java.util.concurrent.Executor
// First we wrap invokeLater/runLater as an ExecutorService
trait GUIExecutorService extends AbstractExecutorService {

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

@ -1,8 +1,8 @@
package wow.doge.mygame.executors
import com.typesafe.scalalogging.Logger
import monix.execution.Scheduler
import monix.execution.UncaughtExceptionReporter
import com.typesafe.scalalogging.Logger
final case class Schedulers(
blockingIO: Scheduler = Scheduler

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

@ -1,18 +1,18 @@
package wow.doge.mygame.game
import com.jme3.app.SimpleApplication
import scala.collection.immutable.Queue
import com.jme3.app.SimpleApplication
import com.jme3.app.state.AppState
import monix.execution.{CancelablePromise => Promise}
import monix.execution.CancelableFuture
import monix.bio.Task
import monix.execution.CancelableFuture
import monix.execution.Scheduler
import wow.doge.mygame.executors.GUIExecutorService
import monix.reactive.subjects.ConcurrentSubject
import monix.execution.atomic.Atomic
import monix.execution.{CancelablePromise => Promise}
import monix.reactive.MulticastStrategy
import monix.reactive.Observable
import monix.execution.atomic.Atomic
import scala.collection.immutable.Queue
import monix.reactive.subjects.ConcurrentSubject
import wow.doge.mygame.executors.GUIExecutorService
import wow.doge.mygame.executors.Schedulers
class GameApp(

35
src/main/scala/wow/doge/mygame/game/GameApp2.scala

@ -0,0 +1,35 @@
package wow.doge.mygame.game
import cats.effect.concurrent.Ref
import com.jme3.app.state.AppStateManager
import com.jme3.asset.AssetManager
import com.jme3.input.InputManager
import monix.bio.IO
import monix.bio.Task
sealed trait Error
case object FlyCamNotExists extends Error
class GameApp2(app: GameApp) {
def stateManager: Task[AppStateManager] = Task(app.getStateManager())
def inputManager: Task[InputManager] = Task(app.getInputManager())
def assetManager: Task[AssetManager] = Task(app.getAssetManager())
def guiNode = Ref[Task].of(app.getGuiNode())
def flyCam =
IO(app.getFlyByCamera()).onErrorHandleWith(_ =>
IO.raiseError(FlyCamNotExists)
)
def camera = Task(app.getCamera())
def viewPort = Task(app.getViewPort())
def rootNode = Ref[Task].of(app.getRootNode())
def enqueue(cb: () => Unit) =
app.enqueue(new Runnable {
override def run() = cb()
})
def enqueueL[T](cb: () => T): Task[T] = app.enqueueL(cb)
def start = Task(app.start())
def stop = Task(app.stop())
def scheduler = app.scheduler
}

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

@ -1,27 +1,15 @@
package wow.doge.mygame.game
import akka.actor.typed.scaladsl.Behaviors
import com.jme3.scene.Geometry
import wow.doge.mygame.events.Events
import com.jme3.scene.CameraNode
import com.jme3.scene.Node
import com.jme3.renderer.Camera
import wow.doge.mygame.executors.Schedulers
import com.softwaremill.macwire._
import wow.doge.mygame.implicits._
import akka.actor.typed.SpawnProtocol
import akka.actor.typed.ActorRef
import akka.actor.typed.Scheduler
import akka.actor.typed.SpawnProtocol
import akka.actor.typed.scaladsl.Behaviors
import io.odin.Logger
import monix.bio.Task
import akka.actor.typed.Scheduler
import scala.util.Failure
import scala.util.Success
import com.jme3.app.StatsAppState
import wow.doge.mygame.events.Events
import wow.doge.mygame.executors.Schedulers
object GameAppActor {
import Methods._
sealed trait Command
case object ApplicationStarted extends Command
@ -39,22 +27,6 @@ object GameAppActor {
Behaviors.setup[Command] { ctx =>
ctx.log.info("Hello from GameAppActor")
// {
// implicit val s = schedulers.async
// val initializer: GameSystemsInitializer = wire[GameSystemsInitializer]
// schedulers.async.execute(() => initializer.init.runAsyncAndForget)
// // ctx.pipeToSelf(application.timed.runToFuture) {
// // case Failure(exception) =>
// // ApplicationStartFailed(exception.getMessage())
// // case Success(value) =>
// // println("here applications started")
// // ApplicationStarted
// // }
// }
Behaviors.receiveMessage { msg =>
msg match {
case Stop =>

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

@ -1,28 +1,28 @@
package wow.doge.mygame.game
import akka.actor.typed.ActorRef
import akka.actor.typed.SpawnProtocol
import cats.effect.Resource
import com.jme3.app.StatsAppState
import com.jme3.system.AppSettings
import monix.bio.Task
import io.odin.Logger
import akka.actor.typed.ActorRef
import akka.actor.typed.SpawnProtocol
import wow.doge.mygame.game.subsystems.input.GameInputHandler
import monix.bio.IO
import monix.bio.Fiber
import monix.bio.IO
import monix.bio.Task
import monix.execution.Scheduler
import com.jme3.app.StatsAppState
import wow.doge.mygame.executors.Schedulers
import wow.doge.mygame.game.subsystems.input.GameInputHandler
class GameAppResource(
logger: Logger[Task],
jmeScheduler: Scheduler,
schedulers: Schedulers
) {
def get: Resource[Task, (GameApp, Fiber[Throwable, Unit])] =
def get: Resource[Task, (GameApp2, Fiber[Throwable, Unit])] =
Resource.make(
for {
_ <- logger.info("Creating game app")
app <- Task(new GameApp(schedulers, new StatsAppState()))
_ <- Task {
app2 <- Task {
val settings = new AppSettings(true)
settings.setVSync(true)
settings.setUseInput(true)
@ -30,11 +30,31 @@ class GameAppResource(
// settings.setFrameRate(250)
app.setSettings(settings)
// JMERunner.runner = app
app
// app
new GameApp2(app)
}
fib <- Task(app.start()).executeOn(jmeScheduler).start
} yield (app -> fib)
fib <- app2.start.executeOn(jmeScheduler).start
} yield (app2 -> fib)
)(logger.info("Closing game app") >> _._2.cancel)
def get2: Resource[Task, GameApp2] =
Resource.make(
for {
_ <- logger.info("Creating game app")
app <- Task(new GameApp(schedulers, new StatsAppState()))
app2 <- Task {
val settings = new AppSettings(true)
settings.setVSync(true)
settings.setUseInput(true)
// new FlyCamAppState
// settings.setFrameRate(250)
app.setSettings(settings)
// JMERunner.runner = app
new GameApp2(app)
}
// fib <- app2.start.executeOn(jmeScheduler).start
} yield (app2)
)(_ => logger.info("Closing game app"))
}
trait GameModule {

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

@ -3,30 +3,34 @@ package wow.doge.mygame.game
import scala.concurrent.duration._
import akka.actor.typed.ActorRef
import akka.actor.typed.ActorSystem
import akka.actor.typed.Scheduler
import akka.actor.typed.SpawnProtocol
import akka.util.Timeout
import cats.effect.concurrent.Ref
import com.jme3.app.state.AppStateManager
import com.jme3.asset.AssetManager
import com.jme3.asset.plugins.ZipLocator
import com.jme3.bullet.BulletAppState
import com.jme3.input.InputManager
import com.jme3.renderer.Camera
import com.jme3.scene.Node
import com.softwaremill.macwire._
import com.softwaremill.tagging._
import io.odin.Logger
import monix.bio.IO
import monix.bio.Task
import monix.reactive.Consumer
import wow.doge.mygame.events.EventBus
import wow.doge.mygame.game.nodes.Player
import wow.doge.mygame.game.nodes.PlayerController
import wow.doge.mygame.game.subsystems.input.GameInputHandler
import wow.doge.mygame.game.subsystems.level.DefaultGameLevel
import wow.doge.mygame.implicits._
import wow.doge.mygame.subsystems.events.EntityMovementEvent.PlayerMovementEvent
import wow.doge.mygame.subsystems.movement.ImMovementActor
import wow.doge.mygame.utils.IOUtils
import wow.doge.mygame.math.ImVector3f
import monix.bio.IO
import wow.doge.mygame.subsystems.events.EntityMovementEvent
import akka.actor.typed.ActorSystem
import wow.doge.mygame.subsystems.events.PlayerCameraEvent
import wow.doge.mygame.subsystems.movement.ImMovementActor
import wow.doge.mygame.utils.IOUtils
class GameSystemsInitializer(
spawnProtocol: ActorSystem[SpawnProtocol.Command],
@ -35,15 +39,22 @@ class GameSystemsInitializer(
playerMovementEventBus: ActorRef[
EventBus.Command[EntityMovementEvent.PlayerMovementEvent]
],
playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]]
)(app: GameApp) {
playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]],
inputManager: InputManager,
assetManager: AssetManager,
stateManager: AppStateManager,
camera: Camera,
enqueueR: Function1[() => Unit, Unit],
appScheduler: monix.execution.Scheduler,
rootNode: Ref[Task, Node]
) {
implicit val timeout: Timeout = Timeout(1.second)
import GameSystemsInitializer._
implicit val akkaScheduler: Scheduler = spawnProtocol.scheduler
lazy val inputManager = app.inputManager
lazy val assetManager = app.assetManager
// lazy val inputManager = app.inputManager
// lazy val assetManager = app.assetManager
lazy val bulletAppState = new BulletAppState()
// lazy val playerMovementEventBus = eventBuses.playerMovementEventBusTask
@ -51,15 +62,16 @@ class GameSystemsInitializer(
for {
_ <- loggerL.info("Initializing Systems")
// playerMovementEventBus <- playerMovementEventBusTask
_ <- Task(app.stateManager.attach(bulletAppState))
_ <- Task(stateManager.attach(bulletAppState))
_ <- Task(
app.assetManager.registerLocator(
assetManager.registerLocator(
// "src/main/resources/assets/town.zip",
(os.rel / "src" / "main" / "resources" / "assets" / "town.zip"),
(os.rel / "assets" / "town.zip"),
classOf[ZipLocator]
)
)
_ <- app.enqueueL(() => DefaultGameLevel(app, bulletAppState))
// _ <- app.enqueueL(() => DefaultGameLevel(app, bulletAppState))
_ <- wireWith(createPlayerController _).startAndForget
_ <- wire[GameInputHandler.Props].begin
@ -71,8 +83,11 @@ class GameSystemsInitializer(
// ],
// playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]]
): IO[PlayerController.Error, Unit] = {
@annotation.unused
val playerPos = ImVector3f.ZERO
@annotation.unused
val playerNode = None.taggedWith[Player]
@annotation.unused
val modelPath = os.rel / "Models" / "Jaime" / "Jaime.j3o"
wire[PlayerController.Props].create
}

4
src/main/scala/wow/doge/mygame/game/appstates/MyBaseState.scala

@ -3,11 +3,11 @@ package wow.doge.mygame.state
import com.jme3.app.Application
import com.jme3.app.SimpleApplication
import com.jme3.app.state.AppState
import com.jme3.scene.Node
import com.jme3.app.state.BaseAppState
import com.jme3.scene.Node
import com.jme3.scene.Spatial
import com.simsilica.es.EntityData
import com.simsilica.es.base.DefaultEntityData
import com.jme3.scene.Spatial
trait MyBaseState extends BaseAppState {

12
src/main/scala/wow/doge/mygame/game/appstates/PlayerMovementState.scala

@ -2,18 +2,16 @@ package wow.doge.mygame.state
import scala.concurrent.duration.DurationInt
import akka.actor.typed.ActorRef
import akka.actor.typed.Behavior
import akka.actor.typed.scaladsl.ActorContext
import akka.actor.typed.scaladsl.Behaviors
import akka.actor.typed.scaladsl.TimerScheduler
import com.jme3.input.InputManager
import com.jme3.input.KeyInput
import com.jme3.input.controls.KeyTrigger
import com.jme3.math.Vector3f
import akka.actor.typed.scaladsl.ActorContext
import akka.actor.typed.scaladsl.Behaviors
import akka.actor.typed.Behavior
import akka.actor.typed.ActorRef
import com.jme3.scene.Geometry
import akka.actor.typed.scaladsl.TimerScheduler
import wow.doge.mygame.implicits._
import wow.doge.mygame.subsystems.movement.ImMovementActor

17
src/main/scala/wow/doge/mygame/game/appstates/ScriptingEngineState.scala

@ -1,17 +1,18 @@
package wow.doge.mygame.state
import ammonite.runtime.Storage.Folder
import ammonite.main.Defaults
import ammonite.Main
import javax.script.ScriptEngine
import com.jme3.app.state.AppState
import akka.actor.typed.ActorRef
import akka.actor.typed.Behavior
import akka.actor.typed.SpawnProtocol
import akka.actor.typed.scaladsl.AbstractBehavior
import akka.actor.typed.scaladsl.ActorContext
import akka.actor.typed.Behavior
import akka.actor.typed.ActorRef
import ammonite.util.Res.Success
import akka.actor.typed.scaladsl.Behaviors
import akka.actor.typed.SpawnProtocol
import ammonite.Main
import ammonite.main.Defaults
import ammonite.runtime.Storage.Folder
import ammonite.util.Res.Success
import com.jme3.app.state.AppState
class ScriptingEngineState(
sse: ScalaScriptingEngine,

10
src/main/scala/wow/doge/mygame/game/appstates/TestAppState.scala

@ -1,13 +1,13 @@
package wow.doge.mygame.state
import wow.doge.mygame.implicits._
import wow.doge.mygame.components.TestComponent
import com.jme3.scene.shape.Box
import com.jme3.scene.Geometry
import com.jme3.asset.AssetManager
import com.jme3.material.Material
import com.jme3.math.ColorRGBA
import com.jme3.asset.AssetManager
import com.jme3.math.Vector3f
import com.jme3.scene.Geometry
import com.jme3.scene.shape.Box
import wow.doge.mygame.components.TestComponent
import wow.doge.mygame.implicits._
class TestAppState(
// private var _entity: Option[EntityData] = Some(new DefaultEntityData())
) extends MyBaseState {

2
src/main/scala/wow/doge/mygame/game/components/Position.scala

@ -1,6 +1,6 @@
package wow.doge.mygame.components
import com.simsilica.es.EntityComponent;
import com.simsilica.es.EntityComponent
import wow.doge.mygame.math.ImVector3f
final case class Position(location: ImVector3f) extends EntityComponent

31
src/main/scala/wow/doge/mygame/game/nodes/PlayerActorSupervisor.scala

@ -1,30 +1,29 @@
package wow.doge.mygame.game.nodes
import akka.actor.typed.scaladsl.Behaviors
import akka.actor.typed.scaladsl.ActorContext
import wow.doge.mygame.subsystems.movement.ImMovementActor
import wow.doge.mygame.game.GameApp
import scala.concurrent.duration._
import akka.actor.typed.ActorRef
import wow.doge.mygame.events.EventBus
import wow.doge.mygame.subsystems.events.EntityMovementEvent.PlayerMovementEvent
import wow.doge.mygame.subsystems.events.EntityMovementEvent
import akka.actor.typed.scaladsl.TimerScheduler
import akka.actor.typed.Behavior
import scala.concurrent.duration._
import akka.actor.typed.LogOptions
import org.slf4j.event.Level
import com.typesafe.scalalogging.Logger
import akka.actor.typed.SupervisorStrategy
import akka.actor.typed.scaladsl.ActorContext
import akka.actor.typed.scaladsl.Behaviors
import akka.actor.typed.scaladsl.TimerScheduler
import com.jme3.scene.CameraNode
import wow.doge.mygame.subsystems.events.PlayerCameraEvent
import com.typesafe.scalalogging.Logger
import org.slf4j.event.Level
import wow.doge.mygame.events.EventBus
import wow.doge.mygame.game.subsystems.movement.CanMove
import wow.doge.mygame.implicits._
import wow.doge.mygame.subsystems.events.EntityMovementEvent
import wow.doge.mygame.subsystems.events.EntityMovementEvent.PlayerMovementEvent
import wow.doge.mygame.subsystems.events.PlayerCameraEvent
import wow.doge.mygame.subsystems.movement.ImMovementActor
object PlayerActorSupervisor {
sealed trait Command
final case class Props(
app: GameApp,
enqueueR: Function1[() => Unit, Unit],
camNode: CameraNode,
playerMovementEventBus: ActorRef[
EventBus.Command[PlayerMovementEvent]
@ -47,7 +46,7 @@ object PlayerActorSupervisor {
Behaviors
.supervise(
ImMovementActor
.Props(app, movable, playerMovementEventBus)
.Props(enqueueR, movable, playerMovementEventBus)
.create
)
.onFailure[Exception](SupervisorStrategy.restart),
@ -70,7 +69,7 @@ object PlayerActorSupervisor {
ctx.spawn(
Behaviors
.supervise(
PlayerCameraEventListener(camNode, app.enqueueR)
PlayerCameraEventListener(camNode, enqueueR)
)
.onFailure[Exception](SupervisorStrategy.restart),
"playerCameraHandler"

2
src/main/scala/wow/doge/mygame/game/nodes/PlayerCameraActor.scala

@ -1,7 +1,7 @@
package wow.doge.mygame.game.nodes
import akka.actor.typed.scaladsl.Behaviors
import akka.actor.typed.scaladsl.ActorContext
import akka.actor.typed.scaladsl.Behaviors
object PlayerCameraActor {
sealed trait Command

60
src/main/scala/wow/doge/mygame/game/nodes/PlayerController.scala

@ -1,33 +1,34 @@
package wow.doge.mygame.game.nodes
import com.jme3.scene.Node
import akka.actor.typed.ActorRef
import akka.actor.typed.Props
import akka.actor.typed.Scheduler
import akka.actor.typed.SpawnProtocol
import akka.util.Timeout
import cats.effect.concurrent.Ref
import cats.implicits._
import com.jme3.asset.AssetManager
import com.jme3.bullet.BulletAppState
import com.jme3.bullet.control.BetterCharacterControl
import com.jme3.math.FastMath
import com.jme3.renderer.Camera
import com.jme3.scene.CameraNode
import com.jme3.scene.Geometry
import com.jme3.renderer.Camera
import com.jme3.asset.AssetManager
import wow.doge.mygame.state.MyMaterial
import com.jme3.scene.Node
import com.jme3.scene.control.CameraControl.ControlDirection
import com.jme3.scene.shape.Box
import com.jme3.bullet.control.BetterCharacterControl
import com.jme3.bullet.BulletAppState
import com.softwaremill.tagging._
import io.odin.Logger
import monix.bio.IO
import monix.bio.Task
import wow.doge.mygame.events.EventBus
import wow.doge.mygame.game.GameApp
import wow.doge.mygame.implicits._
import wow.doge.mygame.math.ImVector3f
import com.jme3.math.FastMath
import monix.bio.IO
import cats.implicits._
import akka.actor.typed.ActorRef
import wow.doge.mygame.events.EventBus
import akka.actor.typed.SpawnProtocol
import wow.doge.mygame.state.MyMaterial
import wow.doge.mygame.subsystems.events.EntityMovementEvent.PlayerMovementEvent
import wow.doge.mygame.subsystems.movement.ImMovementActor
import io.odin.Logger
import akka.util.Timeout
import monix.bio.Task
import akka.actor.typed.Scheduler
import akka.actor.typed.Props
import com.softwaremill.tagging._
import wow.doge.mygame.subsystems.events.PlayerCameraEvent
import wow.doge.mygame.subsystems.movement.ImMovementActor
import wow.doge.mygame.utils.AkkaUtils
// class PlayerNode(val name: String) extends Node(name) {}
@ -39,7 +40,9 @@ object PlayerController {
case class GenericError(reason: String) extends Error
class Props(
app: GameApp,
enqueueR: Function1[() => Unit, Unit],
rootNode: Ref[Task, Node],
camera: Camera,
loggerL: Logger[Task],
assetManager: AssetManager,
bulletAppState: BulletAppState,
@ -52,15 +55,15 @@ object PlayerController {
playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]],
_playerPhysicsControl: Option[BetterCharacterControl],
_playerNode: Option[Node with Player] = None,
_cameraNode: Option[CameraNode with PlayerCameraNode] = None
_cameraNode: Option[CameraNode with PlayerCameraNode] = None,
appScheduler: monix.execution.Scheduler
)(implicit timeout: Timeout, scheduler: Scheduler) {
import Defaults._
import Methods._
val create: IO[Error, Unit] =
// IO.raiseError(GenericError("not implemented yet"))
(for {
camNode <- IO(
_cameraNode.getOrElse(defaultCamerNode(app.camera, initialPlayerPos))
_cameraNode.getOrElse(defaultCamerNode(camera, initialPlayerPos))
)
playerPhysicsControl <- IO(
_playerPhysicsControl
@ -82,7 +85,7 @@ object PlayerController {
spawnProtocol,
"playerActorSupervisor",
new PlayerActorSupervisor.Props(
app,
enqueueR,
camNode,
playerMovementEventBus,
playerCameraEventBus
@ -92,11 +95,10 @@ object PlayerController {
bulletAppState.physicsSpace += playerNode
bulletAppState.physicsSpace += playerPhysicsControl
}
_ <- IO(app.rootNode += playerNode)
_ <- rootNode.update(_ :+ playerNode)
} yield ())
.onErrorHandleWith(e => IO.raiseError(GenericError(e.getMessage())))
.executeOn(app.scheduler)
.executeOn(appScheduler)
}
def apply(
@ -175,7 +177,7 @@ object Defaults {
object Methods {
def spawnMovementActor(
app: GameApp,
enqueueR: Function1[() => Unit, Unit],
spawnProtocol: ActorRef[SpawnProtocol.Command],
movable: BetterCharacterControl @@ Player,
playerMovementEventBus: ActorRef[
@ -185,7 +187,7 @@ object Methods {
)(implicit timeout: Timeout, scheduler: Scheduler) =
spawnProtocol.askL[ActorRef[ImMovementActor.Command]](
SpawnProtocol.Spawn(
ImMovementActor.Props(app, movable, playerMovementEventBus).create,
ImMovementActor.Props(enqueueR, movable, playerMovementEventBus).create,
"imMovementActor",
Props.empty,
_

12
src/main/scala/wow/doge/mygame/game/nodes/PlayerEventListeners.scala

@ -1,18 +1,16 @@
package wow.doge.mygame.game.nodes
import akka.actor.typed.ActorRef
import akka.actor.typed.LogOptions
import akka.actor.typed.scaladsl.Behaviors
import wow.doge.mygame.subsystems.movement.ImMovementActor
import com.jme3.scene.CameraNode
import com.typesafe.scalalogging.Logger
import org.slf4j.event.Level
import akka.actor.typed.LogOptions
import wow.doge.mygame.subsystems.events.EntityMovementEvent.PlayerMovementEvent
import com.typesafe.scalalogging.Logger
import wow.doge.mygame.subsystems.events.PlayerCameraEvent
import wow.doge.mygame.subsystems.events.PlayerCameraEvent.CameraMovedUp
import wow.doge.mygame.subsystems.events.PlayerCameraEvent.CameraMovedDown
import com.jme3.scene.CameraNode
import wow.doge.mygame.game.GameApp
import wow.doge.mygame.implicits._
import wow.doge.mygame.subsystems.events.PlayerCameraEvent.CameraMovedUp
import wow.doge.mygame.subsystems.movement.ImMovementActor
object PlayerMovementEventListener {
import PlayerMovementEvent._

135
src/main/scala/wow/doge/mygame/game/subsystems/input/GameInputHandler.scala

@ -1,23 +1,19 @@
package wow.doge.mygame.game.subsystems.input
import com.jme3.input.InputManager
import wow.doge.mygame.implicits._
import scala.concurrent.duration._
import akka.actor.typed.ActorRef
import wow.doge.mygame.events.EventBus
import com.jme3.input.InputManager
import com.jme3.input.KeyInput
import com.jme3.input.MouseInput
import com.jme3.input.controls.KeyTrigger
import com.jme3.input.controls.MouseAxisTrigger
import monix.bio.UIO
import wow.doge.mygame.utils.IOUtils._
import wow.doge.mygame.events.EventBus
import wow.doge.mygame.implicits._
import wow.doge.mygame.subsystems.events.EntityMovementEvent.PlayerMovementEvent
import scala.concurrent.duration._
import com.jme3.input.controls.MouseAxisTrigger
import com.jme3.input.MouseInput
import wow.doge.mygame.subsystems.events.PlayerCameraEvent
// class GameInputHandler(
// inputManager: InputManager
// // inputEventBus: InputEventBus
// ) {}
import wow.doge.mygame.utils.IOUtils._
object GameInputHandler {
@ -30,6 +26,7 @@ object GameInputHandler {
) {
def begin =
for {
_ <- UIO(setupMovementKeys(inputManager))
_ <- UIO(setupKeys(inputManager))
_ <- toIO(
generateMovementInputEvents(
@ -49,40 +46,49 @@ object GameInputHandler {
playerCameraEventBus
).completedL.startAndForget
)
_ <- toIO(
myTest(
inputManager
).completedL.startAndForget
)
} yield ()
}
def setupMovementKeys(inputManager: InputManager) =
inputManager.withEnumMappings(PlayerMovementInput) {
case PlayerMovementInput.WalkRight =>
Seq(new KeyTrigger(KeyInput.KEY_D))
case PlayerMovementInput.WalkLeft =>
Seq(new KeyTrigger(KeyInput.KEY_A))
case PlayerMovementInput.WalkForward =>
Seq(new KeyTrigger(KeyInput.KEY_W))
case PlayerMovementInput.WalkBackward =>
Seq(new KeyTrigger(KeyInput.KEY_S))
case PlayerMovementInput.Jump =>
Seq(new KeyTrigger(KeyInput.KEY_SPACE))
}
def setupKeys(inputManager: InputManager) =
inputManager
.withMapping(
PlayerMovementInput.WalkLeft.entryName,
new KeyTrigger(KeyInput.KEY_A)
// new KeyTrigger(KeyInput.KEY_LEFT)
)
.withMapping(
PlayerMovementInput.WalkRight.entryName,
new KeyTrigger(KeyInput.KEY_D)
// new KeyTrigger(KeyInput.KEY_RIGHT)
)
.withMapping(
PlayerMovementInput.WalkForward.entryName,
new KeyTrigger(KeyInput.KEY_W)
// new KeyTrigger(KeyInput.KEY_UP)
)
.withMapping(
PlayerMovementInput.WalkBackward.entryName,
new KeyTrigger(KeyInput.KEY_S)
// new KeyTrigger(KeyInput.KEY_DOWN)
)
.withMapping(
"Jump",
new KeyTrigger(KeyInput.KEY_SPACE)
)
// .withMapping(
// PlayerMovementInput.WalkLeft.entryName,
// new KeyTrigger(KeyInput.KEY_A)
// // new KeyTrigger(KeyInput.KEY_LEFT)
// )
// .withMapping(
// PlayerMovementInput.WalkRight.entryName,
// new KeyTrigger(KeyInput.KEY_D)
// // new KeyTrigger(KeyInput.KEY_RIGHT)
// )
// .withMapping(
// PlayerMovementInput.WalkForward.entryName,
// new KeyTrigger(KeyInput.KEY_W)
// // new KeyTrigger(KeyInput.KEY_UP)
// )
// .withMapping(
// PlayerMovementInput.WalkBackward.entryName,
// new KeyTrigger(KeyInput.KEY_S)
// // new KeyTrigger(KeyInput.KEY_DOWN)
// )
// .withMapping(
// PlayerMovementInput.Jump.entryName,
// new KeyTrigger(KeyInput.KEY_SPACE)
// )
.withMapping(
PlayerAnalogInput.TurnRight.entryName,
new KeyTrigger(KeyInput.KEY_RIGHT),
@ -145,33 +151,19 @@ object GameInputHandler {
name
)
)
// case "Jump" if action.value =>
// toTask(
// playerMovementEventBus !! EventBus.Publish(
// PlayerMovementEvent.PlayerJumped,
// name
// )
// )
// case _ => monix.eval.Task.unit
case PlayerMovementInput.Jump =>
if (action.value) {
toTask(
playerMovementEventBus !! EventBus.Publish(
PlayerMovementEvent.PlayerJumped,
name
)
)
} else monix.eval.Task.unit
}
}
}
def myTest(inputManager: InputManager) = {
inputManager
.enumObservableAction(PlayerMovementEnum)
.sample(1.millis)
.mapEval(action =>
action.binding match {
case PlayerMovementEnum.MOVE_RIGHT =>
monix.eval.Task(println("move right")) >> monix.eval.Task.unit
case PlayerMovementEnum.MOVE_LEFT =>
monix.eval.Task(println("move left"))
}
)
}
def generateRotateEvents(
inputManager: InputManager,
playerMovementEventBus: ActorRef[
@ -182,7 +174,7 @@ object GameInputHandler {
inputManager
.enumAnalogObservable(PlayerAnalogInput)
.sample(1.millis)
.map(e => e)
// .map(e => e)
.doOnNext(analogEvent =>
analogEvent.binding match {
case PlayerAnalogInput.TurnRight =>
@ -231,17 +223,4 @@ object GameInputHandler {
}
)
}
// def bindMappings(inputManager: InputManager, mappings: ActionMapping*) = {
// inputManager
// .observableAction(mappings.map(_.name): _*)
// .doOnNext(action =>
// mappings.map(m =>
// if (action.binding.name == m.name) toTask(m.cb(action))
// else monix.eval.Task.unit
// )
// )
// }
}
// case class ActionMapping(name: String, cb: ActionEvent => Task[Unit])

3
src/main/scala/wow/doge/mygame/game/subsystems/input/InputEnums.scala

@ -1,6 +1,6 @@
package wow.doge.mygame.game.subsystems.input
import enumeratum._
import enumeratum.EnumEntry._
import enumeratum._
sealed trait PlayerMovementInput extends EnumEntry with UpperSnakecase
object PlayerMovementInput extends Enum[PlayerMovementInput] {
@ -9,6 +9,7 @@ object PlayerMovementInput extends Enum[PlayerMovementInput] {
case object WalkRight extends PlayerMovementInput
case object WalkLeft extends PlayerMovementInput
case object WalkBackward extends PlayerMovementInput
case object Jump extends PlayerMovementInput
}
sealed trait PlayerAnalogInput extends EnumEntry with UpperSnakecase

57
src/main/scala/wow/doge/mygame/game/subsystems/level/DefaultGameLevel.scala

@ -1,36 +1,20 @@
package wow.doge.mygame.game.subsystems.level
import com.jme3.bullet.BulletAppState
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape
import com.jme3.bullet.control.CharacterControl
import com.jme3.asset.AssetManager
import com.jme3.bullet.control.RigidBodyControl
import com.jme3.bullet.util.CollisionShapeFactory
import com.jme3.scene.Spatial
import wow.doge.mygame.implicits._
import wow.doge.mygame.game.GameApp
import com.jme3.syntax._
import com.jme3.math.ColorRGBA
import com.jme3.light.AmbientLight
import com.jme3.light.DirectionalLight
import com.jme3.math.ColorRGBA
import com.jme3.math.Vector3f
import com.jme3.light.AmbientLight
import com.jme3.renderer.ViewPort
import com.jme3.scene.Spatial
object DefaultGameLevel {
// lazy valbulletAppState: 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.
// 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.
lazy val capsuleShape = new CapsuleCollisionShape(1.5f, 6f, 1)
lazy val player: CharacterControl =
new CharacterControl(capsuleShape, 0.05f)
def apply(app: GameApp, bulletAppState: BulletAppState) = {
lazy val sceneModel: Spatial = app.assetManager.loadModel("main.scene")
def apply(
assetManager: AssetManager,
viewPort: ViewPort
) = {
lazy val sceneModel: Spatial = assetManager.loadModel("main.scene")
lazy val sceneShape = CollisionShapeFactory.createMeshShape(
sceneModel.toNode match {
case util.Right(node) => node
@ -41,23 +25,26 @@ object DefaultGameLevel {
lazy val landscape: RigidBodyControl =
new RigidBodyControl(sceneShape, 0)
// // discard { app.stateManager.attach(bulletAppState) }
app.viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f))
viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f))
sceneModel.setLocalScale(2f)
sceneModel.addControl(landscape)
discard { app.rootNode.attachChild(sceneModel) }
bulletAppState.getPhysicsSpace.add(landscape)
bulletAppState.getPhysicsSpace.add(player)
// discard { rootNode.attachChild(sceneModel) }
// bulletAppState.getPhysicsSpace.add(landscape)
// bulletAppState.getPhysicsSpace.add(player)
val al = new AmbientLight();
al.setColor(ColorRGBA.White.mult(1.3f));
app.rootNode.addLight(al);
// app.rootNode.addLight(al);
val dl = new DirectionalLight();
dl.setColor(ColorRGBA.White);
dl.setDirection(new Vector3f(2.8f, -2.8f, -2.8f).normalizeLocal());
app.rootNode.addLight(dl);
// app.rootNode.addLight(dl);
new Level(
model = sceneModel,
physicsControl = landscape,
ambientLight = al,
directionalLight = dl
)
}
}

34
src/main/scala/wow/doge/mygame/game/subsystems/level/Level.scala

@ -0,0 +1,34 @@
package wow.doge.mygame.game.subsystems.level
import com.jme3.bullet.control.RigidBodyControl
import com.jme3.light.AmbientLight
import com.jme3.light.DirectionalLight
import com.jme3.scene.Spatial
import com.jme3.bullet.PhysicsSpace
import cats.effect.concurrent.Ref
import monix.bio.Task
import com.jme3.scene.Node
import wow.doge.mygame.implicits._
class Level(
model: Spatial,
physicsControl: RigidBodyControl,
ambientLight: AmbientLight,
directionalLight: DirectionalLight
) {
def addToGame(rootNode: Ref[Task, Node], physicsSpace: PhysicsSpace) = {
for {
_ <- rootNode.update(_ :+ model)
_ <- rootNode.update { r =>
r.addLight(ambientLight)
r
}
_ <- rootNode.update { r =>
r.addLight(directionalLight)
r
}
_ <- Task(physicsSpace += model)
_ <- Task(physicsSpace += physicsControl)
} yield ()
}
}

6
src/main/scala/wow/doge/mygame/game/subsystems/movement/CanMove.scala

@ -4,11 +4,11 @@ import com.jme3.bullet.control.BetterCharacterControl
import com.jme3.math.FastMath
import com.jme3.math.Quaternion
import com.jme3.math.Vector3f
import wow.doge.mygame.math.ImVector3f
import wow.doge.mygame.subsystems.movement.RotateDir
import wow.doge.mygame.implicits._
import com.jme3.scene.Spatial
import com.typesafe.scalalogging.LazyLogging
import wow.doge.mygame.implicits._
import wow.doge.mygame.math.ImVector3f
import wow.doge.mygame.subsystems.movement.RotateDir
trait CanMove[-A] {
// def getDirection(cam: Camera, cardinalDir: CardinalDirection): ImVector3f

32
src/main/scala/wow/doge/mygame/game/subsystems/movement/MovementActor.scala

@ -1,19 +1,17 @@
package wow.doge.mygame.subsystems.movement
import akka.actor.typed.scaladsl.ActorContext
import akka.actor.typed.ActorRef
import akka.actor.typed.Behavior
import akka.actor.typed.scaladsl.ActorContext
import akka.actor.typed.scaladsl.Behaviors
import com.jme3.math.Vector3f
import com.softwaremill.quicklens._
import wow.doge.mygame.events.EventBus
import wow.doge.mygame.game.subsystems.movement.CanMove
import wow.doge.mygame.implicits._
import wow.doge.mygame.math.ImVector3f
import wow.doge.mygame.game.GameApp
import akka.actor.typed.ActorRef
import wow.doge.mygame.events.EventBus
import com.jme3.math.Vector3f
import wow.doge.mygame.state.CardinalDirection
import wow.doge.mygame.subsystems.events.EntityMovementEvent.PlayerMovementEvent
import wow.doge.mygame.game.subsystems.movement.CanMove
import com.softwaremill.quicklens._
sealed trait RotateDir
object RotateDir {
@ -36,7 +34,7 @@ object ImMovementActor {
final case object RotateLeft extends Movement
final case class Props[T: CanMove](
app: GameApp,
enqueueR: Function1[() => Unit, Unit],
movable: T,
playerMovementEventBus: ActorRef[
EventBus.Command[PlayerMovementEvent]
@ -90,25 +88,25 @@ class ImMovementActor[T](
case m: Movement =>
m match {
case MovedLeft(pressed) =>
props.app.enqueueR(() => stopIfNotPressed(pressed, props.movable))
props.enqueueR(() => stopIfNotPressed(pressed, props.movable))
receive(state = state.modify(_.cardinalDir.left).setTo(pressed))
case MovedUp(pressed) =>
props.app.enqueueR(() => stopIfNotPressed(pressed, props.movable))
props.enqueueR(() => stopIfNotPressed(pressed, props.movable))
receive(state = state.modify(_.cardinalDir.up).setTo(pressed))
case MovedRight(pressed) =>
props.app.enqueueR(() => stopIfNotPressed(pressed, props.movable))
props.enqueueR(() => stopIfNotPressed(pressed, props.movable))
receive(state = state.modify(_.cardinalDir.right).setTo(pressed))
case MovedDown(pressed) =>
props.app.enqueueR(() => stopIfNotPressed(pressed, props.movable))
props.enqueueR(() => stopIfNotPressed(pressed, props.movable))
receive(state = state.modify(_.cardinalDir.down).setTo(pressed))
case Jump =>
props.app.enqueueR(() => cm.jump(props.movable))
props.enqueueR(() => cm.jump(props.movable))
Behaviors.same
case RotateLeft =>
props.app.enqueueR(() => cm.rotate(props.movable, RotateDir.Left))
props.enqueueR(() => cm.rotate(props.movable, RotateDir.Left))
Behaviors.same
case RotateRight =>
props.app.enqueueR(() => cm.rotate(props.movable, RotateDir.Right))
props.enqueueR(() => cm.rotate(props.movable, RotateDir.Right))
Behaviors.same
}
@ -117,7 +115,7 @@ class ImMovementActor[T](
getDirection(state.cardinalDir, ctx.log.trace)
if (walkDir != ImVector3f.ZERO) {
val tmp = walkDir * 25f * (1f / 144)
props.app.enqueueR { () =>
props.enqueueR { () =>
cm.move(props.movable, tmp)
}
}

5
src/main/scala/wow/doge/mygame/implicits/EntityQuery.scala

@ -1,12 +1,13 @@
package wow.doge.mygame.implicits
import scala.reflect.ClassTag
import scala.util.Try
import com.simsilica.es.ComponentFilter
import com.simsilica.es.EntityComponent
import com.simsilica.es.EntityData
import com.simsilica.es.EntitySet
import com.simsilica.es.Filters
import scala.reflect.ClassTag
import scala.util.Try
class EntityQuery(ed: EntityData) {
private var cfilter: Option[ComponentFilter[_ <: EntityComponent]] = None

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

@ -1,52 +1,54 @@
package wow.doge.mygame
import com.jme3.app.SimpleApplication
import com.jme3.app.state.AppStateManager
import scala.jdk.CollectionConverters._
import scala.reflect.ClassTag
import com.jme3.app.state.AppState
import com.jme3.scene.Node
import com.jme3.scene.Spatial
import com.simsilica.es.EntityData
import com.simsilica.es.EntityComponent
import com.simsilica.es.EntityId
import akka.actor.typed.ActorRef
import akka.util.Timeout
import akka.actor.typed.Scheduler
import monix.bio.Task
import akka.util.Timeout
import cats.effect.concurrent.Ref
import com.jme3.app.Application
import com.jme3.app.SimpleApplication
import com.jme3.app.state.AppState
import com.jme3.app.state.AppStateManager
import com.jme3.asset.AssetLocator
import com.jme3.asset.AssetManager
import com.jme3.bullet.BulletAppState
import com.jme3.bullet.PhysicsSpace
import com.jme3.bullet.PhysicsTickListener
import com.jme3.bullet.collision.PhysicsCollisionEvent
import com.jme3.bullet.collision.PhysicsCollisionListener
import com.jme3.bullet.control.BetterCharacterControl
import com.jme3.input.Action
import com.jme3.input.InputManager
import com.jme3.input.controls.Trigger
import com.jme3.input.controls.ActionListener
import com.jme3.input.controls.AnalogListener
import com.jme3.input.controls.InputListener
import com.jme3.input.controls.Trigger
import com.jme3.math.Vector3f
import wow.doge.mygame.math.ImVector3f
import com.jme3.scene.CameraNode
import com.jme3.scene.Geometry
import scala.jdk.CollectionConverters._
import com.jme3.app.Application
import com.jme3.scene.Node
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 com.jme3.scene.Spatial
import com.jme3.scene.control.CameraControl.ControlDirection
import com.jme3.scene.control.Control
import com.simsilica.es.EntityComponent
import com.simsilica.es.EntityData
import com.simsilica.es.EntityId
import enumeratum._
import monix.bio.Task
import monix.bio.UIO
import monix.execution.Ack
import monix.execution.Ack.Continue
import monix.execution.Ack.Stop
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.Observable
import monix.reactive.OverflowStrategy
import monix.reactive.observers.Subscriber
import monix.execution.Ack.Continue
import monix.execution.Ack.Stop
import com.jme3.bullet.BulletAppState
import wow.doge.mygame.math.ImVector3f
import wow.doge.mygame.state.MyBaseState
import monix.bio.UIO
import com.jme3.bullet.control.BetterCharacterControl
import com.jme3.scene.CameraNode
import com.jme3.scene.control.CameraControl.ControlDirection
import com.jme3.scene.control.Control
import com.jme3.input.controls.AnalogListener
import enumeratum._
case class ActionEvent(binding: Action, value: Boolean, tpf: Float)
case class EnumActionEvent[T <: EnumEntry](
@ -76,10 +78,12 @@ package object implicits {
})
}
implicit class StateManagerExt(private val sm: AppStateManager)
implicit class StateManagerExt(private val asm: AppStateManager)
extends AnyVal {
def state[S <: AppState]()(implicit c: ClassTag[S]): S =
sm.getState(c.runtimeClass.asInstanceOf[Class[S]])
asm.getState(c.runtimeClass.asInstanceOf[Class[S]])
// def appStates = asm.getStates()
}
@ -117,6 +121,38 @@ package object implicits {
}
}
implicit class AssetManagerExt(private val am: AssetManager) extends AnyVal {
def registerLocator(
assetPath: os.RelPath,
locator: Class[_ <: AssetLocator]
): Unit = {
am.registerLocator(assetPath.toString(), locator)
}
def loadModel(assetPath: os.RelPath): Spatial = {
am.loadModel(assetPath.toString())
}
}
implicit class BulletAppStateExt(private val bas: BulletAppState)
extends AnyVal {
def physicsSpace = bas.getPhysicsSpace()
def speed = bas.getSpeed()
}
implicit class BetterCharacterControlExt(
private val bcc: BetterCharacterControl
) {
def withJumpForce(force: ImVector3f) = {
bcc.setJumpForce(force.mutable)
bcc
}
}
implicit class SpatialExt[T <: Spatial](private val spat: T) extends AnyVal {
def asRef = Ref[Task].of(spat)
}
implicit class NodeExt[T <: Node](private val n: T) extends AnyVal {
/**
@ -139,6 +175,11 @@ package object implicits {
def observableChildren =
Observable.fromIterable(n.getChildren().asScala)
/**
* A copy of the list of children of this node as a lazy list
*
* @return
*/
def children = LazyList.from(n.getChildren().asScala)
/**
@ -147,12 +188,24 @@ package object implicits {
* @param lst
*/
def withChildren(lst: Spatial*): Node = {
for (c <- lst) n.withChild(c)
for (c <- lst) n.attachChild(c)
n
}
def +=(spatial: Spatial) = n.attachChild(spatial)
def :+(spatial: Spatial) = {
n += spatial
n
}
def -=(spatial: Spatial) = n.detachChild(spatial)
def :-(spatial: Spatial) = {
n -= spatial
n
}
def depthFirst(cb: Spatial => Unit) =
n.depthFirstTraversal(new SceneGraphVisitor() {
override def visit(s: Spatial) = cb(s)
@ -333,6 +386,16 @@ package object implicits {
inputManager
}
def withEnumMappings[T <: EnumEntry](
mappingEnum: Enum[T]
)(mappingFn: T => Seq[Trigger]): InputManager = {
for (entry <- mappingEnum.values) {
val mappings = mappingFn(entry)
inputManager.addMapping(entry.entryName, mappings: _*)
}
inputManager
}
def observableAction(mappingNames: String*): Observable[ActionEvent] = {
Observable.create(OverflowStrategy.DropOld(10)) { sub =>
@ -388,12 +451,6 @@ package object implicits {
}
}
// def enumObservableAction[T <: enumeratum.EnumEntry](
// mappingNames: Enum[T]
// ): Observable[ActionEvent] = {
// observableAction2(mappingNames).doOnNext()
// }
def analogObservable(mappingNames: String*): Observable[AnalogEvent] = {
Observable.create(OverflowStrategy.DropOld(50)) { sub =>
@ -509,60 +566,60 @@ package object implicits {
//TODO Create a typeclass for this
def +=(anyObject: Any) = space.add(anyObject)
def +=(spatial: Spatial) = space.addAll(spatial)
def :+(anyObject: Any) = {
space.add(anyObject)
space
}
def :-(anyObject: Any) = {
space.remove(anyObject)
space
}
}
def +=(spatial: Spatial) = space.addAll(spatial)
implicit class AssetManagerExt(private val am: AssetManager) extends AnyVal {
def registerLocator(
assetPath: os.RelPath,
locator: Class[_ <: AssetLocator]
): Unit = {
am.registerLocator(assetPath.toString(), locator)
def :+(spatial: Spatial) = {
space.addAll(spatial)
space
}
def loadModel(assetPath: os.RelPath): Spatial = {
am.loadModel(assetPath.toString())
def :-(spatial: Spatial) = {
space.removeAll(spatial)
space
}
}
implicit class BulletAppStateExt(private val bas: BulletAppState)
extends AnyVal {
def physicsSpace = bas.getPhysicsSpace()
def speed = bas.getSpeed()
}
implicit class BetterCharacterControlExt(
private val bcc: BetterCharacterControl
) {
def withJumpForce(force: ImVector3f) = {
bcc.setJumpForce(force.mutable)
bcc
}
}
implicit class Vector3fExt(private val v: Vector3f) extends AnyVal {
//TODO add more operations
def +=(that: Vector3f) = v.addLocal(that)
def +=(f: Float) = v.addLocal(f, f, f)
def +=(that: ImVector3f) = v.addLocal(that.x, that.y, that.z)
def +=:(that: ImVector3f) = v += that
def *=(that: Vector3f) = v.multLocal(that)
def *=(that: ImVector3f) = v.multLocal(that.x, that.y, that.z)
def *=:(that: ImVector3f) = v *= that
def -=(that: Vector3f) = v.subtractLocal(that)
def -=(that: ImVector3f) = v.subtractLocal(that.x, that.y, that.z)
def -=:(that: ImVector3f) = v *= that
def /=(that: Vector3f) = v.divideLocal(that)
def /=(that: ImVector3f) = v.divideLocal(that.mutable)
def /=:(that: ImVector3f) = v *= that
def unary_- = v.negateLocal()
def immutable = ImVector3f(v.x, v.y, v.z)
}
implicit class ImVector3fExt(private val v: ImVector3f) extends AnyVal {
def +(that: ImVector3f) = v.copy(v.x + that.x, v.y + that.y, v.z + that.z)
def +(f: Float): ImVector3f = v.copy(v.x + f, v.y + f, v.z + f)
def *(that: ImVector3f) = v.copy(v.x * that.x, v.y * that.y, v.z * that.z)
def *(f: Float): ImVector3f =
v.copy(v.x * f, v.y * f, v.z * f)
// v * ImVector3f(f, f, f)
def -(that: ImVector3f) = v.copy(v.x - that.x, v.y - that.y, v.z - that.z)
def -(f: Float): ImVector3f = v.copy(v.x - f, v.y - f, v.z - f)
def /(that: ImVector3f) = v.copy(v.x / that.x, v.y / that.y, v.z / that.z)
def /(f: Float): ImVector3f = v.copy(v.x / f, v.y / f, v.z / f)
def unary_- = v.copy(-v.x, -v.y, -v.z)
// def unary_-(that: ImVector3f) = this.copy(this.x, this.y, this.z)
def mutable = new Vector3f(v.x, v.y, v.z)
}
@ -572,18 +629,3 @@ package object implicits {
// }
}
// Observable.create(OverflowStrategy.Unbounded) { sub =>
// // val c = SingleAssignCancelable()
// val visitor = new SceneGraphVisitor {
// override def visit(s: Spatial): Unit = {
// sub.onNext(s)
// // if (sub.onNext(s) == Ack.Stop)
// // c.cancel()
// }
// }
// n.depthFirstTraversal(visitor)
// // c := Cancelable(() => ???)
// // c
// Cancelable.empty

3
src/main/scala/wow/doge/mygame/subsystems/events/EventBus.scala

@ -1,9 +1,10 @@
package wow.doge.mygame.events
import scala.reflect.ClassTag
import akka.actor.typed.ActorRef
import akka.actor.typed.Behavior
import akka.actor.typed.scaladsl.Behaviors
import scala.reflect.ClassTag
import akka.event.EventStream
/**

68
src/main/scala/wow/doge/mygame/subsystems/events/EventsModule.scala

@ -1,35 +1,45 @@
package wow.doge.mygame.events
package wow.doge.mygame.subsystems.events
import scala.concurrent.duration._
import akka.actor.typed.ActorRef
import akka.actor.typed.SpawnProtocol
import wow.doge.mygame.implicits._
import akka.actor.typed.scaladsl.AskPattern._
import akka.actor.typed.ActorSystem
import akka.actor.typed.LogOptions
import akka.actor.typed.Props
import akka.actor.typed.SpawnProtocol
import akka.actor.typed.SupervisorStrategy
import akka.actor.typed.scaladsl.Behaviors
import akka.util.Timeout
import akka.actor.typed.Scheduler
import akka.actor.typed.LogOptions
import cats.effect.Resource
import com.typesafe.scalalogging.{Logger => SLLogger}
import monix.bio.Task
import org.slf4j.event.Level
import wow.doge.mygame.events.EventBus
import akka.actor.typed.scaladsl.Behaviors
import wow.doge.mygame.implicits._
import wow.doge.mygame.subsystems.events.EntityMovementEvent.PlayerMovementEvent
import akka.actor.typed.SupervisorStrategy
trait EventsModule {
def spawnProtocol: ActorRef[SpawnProtocol.Command]
implicit def akkaScheduler: Scheduler
implicit def timeout: Timeout
def eventBusLogger = SLLogger[EventBus[_]]
class EventsModule2(
spawnProtocol: ActorSystem[SpawnProtocol.Command]
) {
implicit lazy val s = spawnProtocol.scheduler
lazy val tickEventBusTask = createEventBus[Events.Tick]("tickEventBus")
implicit lazy val timeout = Timeout(1.second)
lazy val eventBusLogger = SLLogger[EventBus[_]]
lazy val playerMovementEventBusTask =
createEventBus[PlayerMovementEvent]("movementEventBus")
def createEventBus[T](busName: String) =
lazy val playerCameraEventBusTask =
createEventBus[PlayerCameraEvent]("playerCameraEventBus", Level.DEBUG)
def createEventBus[T](busName: String, logLevel: Level = Level.DEBUG) =
spawnProtocol.askL(
SpawnProtocol.Spawn[EventBus.Command[T]](
Behaviors.logMessages(
logOptions = LogOptions().withLogger(eventBusLogger.underlying),
logOptions = LogOptions()
.withLevel(logLevel)
.withLogger(eventBusLogger.underlying),
Behaviors
.supervise(EventBus[T]())
.onFailure[Exception](SupervisorStrategy.restart)
@ -39,17 +49,17 @@ trait EventsModule {
_
)
)
}
object EventTypes {
type EventBus[T] = ActorRef[EventBus.Command[T]]
}
// val subscribingActor =
// spawnProtocol.askT(
// SpawnProtocol.Spawn[Events.PhysicsTick.type](
// SubscribingActor(),
// "subscriber-1",
// Props.empty,
// _
// )
// )
type EventBuses = (
ActorRef[
EventBus.Command[EntityMovementEvent.PlayerMovementEvent],
],
ActorRef[EventBus.Command[PlayerCameraEvent]]
)
val resource: Resource[Task, EventBuses] =
Resource.liftF(for {
playerMovementEventBus <- playerMovementEventBusTask
playerCameraEventBus <- playerCameraEventBusTask
} yield (playerMovementEventBus, playerCameraEventBus))
}

64
src/main/scala/wow/doge/mygame/subsystems/events/EventsModule2.scala

@ -1,64 +0,0 @@
package wow.doge.mygame.subsystems.events
import akka.actor.typed.ActorRef
import akka.actor.typed.SpawnProtocol
import wow.doge.mygame.implicits._
import akka.actor.typed.Props
import akka.actor.typed.LogOptions
import com.typesafe.scalalogging.{Logger => SLLogger}
import wow.doge.mygame.events.EventBus
import akka.actor.typed.scaladsl.Behaviors
import scala.concurrent.duration._
import akka.util.Timeout
import akka.actor.typed.SupervisorStrategy
import cats.effect.Resource
import akka.actor.typed.ActorSystem
import monix.bio.Task
import org.slf4j.event.Level
import wow.doge.mygame.subsystems.events.EntityMovementEvent.PlayerMovementEvent
class EventsModule2(
spawnProtocol: ActorSystem[SpawnProtocol.Command]
) {
private implicit lazy val s = spawnProtocol.scheduler
private implicit lazy val timeout = Timeout(1.second)
private lazy val eventBusLogger = SLLogger[EventBus[_]]
private lazy val playerMovementEventBusTask =
createEventBus[PlayerMovementEvent]("movementEventBus")
private lazy val playerCameraEventBusTask =
createEventBus[PlayerCameraEvent]("playerCameraEventBus", Level.DEBUG)
def createEventBus[T](busName: String, logLevel: Level = Level.DEBUG) =
spawnProtocol.askL(
SpawnProtocol.Spawn[EventBus.Command[T]](
Behaviors.logMessages(
logOptions = LogOptions()
.withLevel(logLevel)
.withLogger(eventBusLogger.underlying),
Behaviors
.supervise(EventBus[T]())
.onFailure[Exception](SupervisorStrategy.restart)
),
busName,
Props.empty,
_
)
)
type EventBuses = (
ActorRef[
EventBus.Command[EntityMovementEvent.PlayerMovementEvent],
],
ActorRef[EventBus.Command[PlayerCameraEvent]]
)
val resource: Resource[Task, EventBuses] =
Resource.liftF(for {
playerMovementEventBus <- playerMovementEventBusTask
playerCameraEventBus <- playerCameraEventBusTask
} yield (playerMovementEventBus, playerCameraEventBus))
}

47
src/main/scala/wow/doge/mygame/subsystems/moddingsystem/ModdingSystem.scala

@ -1,5 +1,6 @@
package wow.doge.mygame.subsystems.moddingsystem
import java.io.FileNotFoundException
import java.nio.file.NoSuchFileException
import scala.collection.View
import scala.collection.immutable.ArraySeq
@ -11,7 +12,9 @@ import io.circe.generic.semiauto._
import io.circe.parser._
import monix.bio.IO
import monix.bio.UIO
import java.nio.file.NoSuchFileException
import monix.reactive.Consumer
import monix.reactive.Observable
import wow.doge.mygame.utils.IOUtils
import io.circe.generic.JsonCodec
@JsonCodec
@ -20,6 +23,9 @@ final case class Test1(hello1: String, hello2: String)
final case class Test2(hello1: String)
final case class Plugin(name: String, priority: Int)
object Plugin {
// @annotation.nowarn(
// "msg=Block result was adapted via implicit conversion"
// )
implicit val pluginFormat: Decoder[Plugin] = deriveDecoder
}
@ -90,16 +96,29 @@ object ModdingSystem {
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 foldMerge(iterable: Iterable[Json]) =
iterable.foldLeft(Json.fromString("empty")) {
case (json, io.circe.Json.Null) => json //ignore null values
case (json, value) => json.deepMerge(value)
}
def mergePluginData(plugins: View[(Plugin, Json)]) = {
foldMerge(plugins.map {
case (p, json) => json
})
}
def mergePluginDataConsumer =
Consumer.foldLeft[Json, Json](Json.fromString("empty")) {
case (json, io.circe.Json.Null) => json
case (json, that) => json.deepMerge(that)
}
def loadBalancedPluginDataMerger =
Consumer
.loadBalance(parallelism = 2, mergePluginDataConsumer)
.map(foldMerge)
// def test =
// for {
// filePaths <- Task(findPluginFiles(os.pwd))
@ -118,7 +137,16 @@ object ModdingSystem {
plugins <- IO.fromTryEither(readPluginsList(wd))
(readFailures, readSuccesses) <- UIO(findAndReadPluginFiles(wd, plugins))
(parseFailures, parseSuccesses) <- UIO(parsePluginFiles(readSuccesses))
res <- UIO(mergePluginData(parseSuccesses))
// res <- UIO(mergePluginData(parseSuccesses))
res <-
IOUtils
.toIO(
Observable
.fromIterable(parseSuccesses)
.map { case (p, json) => json }
.consumeWith(loadBalancedPluginDataMerger)
)
.onErrorHandle(e => GenericError)
_ <- UIO {
println(s"Read Successes = ${readSuccesses.to(Seq)}")
println(s"Read Failures = ${readFailures.to(Seq)}")
@ -138,5 +166,4 @@ object ModdingSystem {
// def test3(wd: os.Path = os.pwd) = {
// (readPluginsList(os.pwd).toValidatedNec)
// }
;
}

21
src/main/scala/wow/doge/mygame/subsystems/scriptsystem/ScriptActor.scala

@ -1,21 +1,22 @@
package wow.doge.mygame.state
import akka.actor.typed.scaladsl.Behaviors
import ammonite.Main
import javax.script.ScriptEngine
import javax.script.ScriptEngineManager
import akka.actor.typed.ActorRef
import ammonite.runtime.Storage.Folder
import ammonite.main.Defaults
import akka.actor.typed.Behavior
import akka.actor.typed.LogOptions
import akka.actor.typed.scaladsl.ActorContext
import akka.actor.typed.scaladsl.Behaviors
import ammonite.Main
import ammonite.main.Defaults
import ammonite.runtime.Storage.Folder
import ammonite.util.Res.Success
import javax.script.ScriptEngine
import javax.script.ScriptEngineManager
import groovy.util.GroovyScriptEngine
import cats.implicits._
import akka.actor.typed.LogOptions
import org.slf4j.event.Level
import com.typesafe.scalalogging.Logger
import com.softwaremill.tagging._
import com.typesafe.scalalogging.Logger
import groovy.util.GroovyScriptEngine
import org.slf4j.event.Level
object ScriptActor {
trait Kotlin

19
src/main/scala/wow/doge/mygame/subsystems/scriptsystem/ScriptCachingActor.scala

@ -1,19 +1,20 @@
package wow.doge.mygame.scriptsystem
import scala.util.Failure
import scala.util.Success
import akka.actor.typed.ActorRef
import akka.actor.typed.Behavior
import akka.actor.typed.LogOptions
import akka.actor.typed.SupervisorStrategy
import akka.actor.typed.scaladsl.ActorContext
import akka.actor.typed.scaladsl.Behaviors
import akka.actor.typed.scaladsl.PoolRouter
import akka.actor.typed.scaladsl.Routers
import wow.doge.mygame.state.ScriptActor
import akka.actor.typed.ActorRef
import akka.actor.typed.scaladsl.ActorContext
import akka.actor.typed.Behavior
import akka.util.Timeout
import scala.util.Success
import scala.util.Failure
import akka.actor.typed.SupervisorStrategy
import akka.actor.typed.LogOptions
import org.slf4j.event.Level
import com.typesafe.scalalogging.Logger
import org.slf4j.event.Level
import wow.doge.mygame.state.ScriptActor
object ScriptCachingActor {

66
src/main/scala/wow/doge/mygame/subsystems/scriptsystem/ScriptSystemModule.scala

@ -1,23 +1,65 @@
package wow.doge.mygame.subsystems.scriptsystem
import wow.doge.mygame.utils.AkkaUtils
import cats.effect.Resource
import wow.doge.mygame.scriptsystem.ScriptCachingActor
import akka.actor.typed.ActorRef
import akka.actor.typed.Scheduler
import akka.actor.typed.SpawnProtocol
import akka.util.Timeout
import akka.actor.typed.Scheduler
import cats.effect.Resource
import wow.doge.mygame.scriptsystem.ScriptCachingActor
import wow.doge.mygame.utils.AkkaUtils
import monix.bio.Task
/**
* Scripts can either be searched and compiled at startup (Eager mode)
* or compiled on demand (Lazy mode)
*/
sealed trait ScriptInitMode
object ScriptInitMode {
case object Eager extends ScriptInitMode
case object Lazy extends ScriptInitMode
}
class ScriptSystemResource(
path: os.Path,
spawnProtocol: ActorRef[SpawnProtocol.Command]
spawnProtocol: ActorRef[SpawnProtocol.Command],
mode: ScriptInitMode = ScriptInitMode.Lazy
)(implicit timeout: Timeout, scheduler: Scheduler) {
def make =
Resource.liftF(
AkkaUtils.spawnActorL(
spawnProtocol,
"scriptCachingActor",
ScriptCachingActor()
)
val make = {
// throw new Exception("boom")
findScriptFiles(os.pwd / "assets" / "scripts")
lazy val scriptCacheActor = AkkaUtils.spawnActorL(
spawnProtocol,
"scriptCachingActor",
ScriptCachingActor()
)
Resource.liftF(scriptCacheActor)
}
val init = for {
scriptFiles <- Task(findScriptFiles(os.pwd / "assets" / "scripts"))
scriptCacheActor <- AkkaUtils.spawnActorL(
spawnProtocol,
"scriptCachingActor",
ScriptCachingActor()
)
} yield (scriptCacheActor)
def findScriptFiles(wd: os.Path) =
os.walk
.stream(wd)
.filter(p =>
os.isFile(p) &&
(p.ext == "sc" || (p.baseName + "." + p.ext)
.contains(".main.kts") || p.ext == "groovy")
)
.toList
// def findExternalScriptFiles =
// findScriptFiles(os.pwd / "assets" / "scripts")
// def findInternalScriptFiles =
// findScriptFiles((os.resource / "assets" / "scripts"))
// def finalInternalScriptFiles =
}
// pwd / 'src / 'main / 'resources / 'assets / 'scripts

6
src/main/scala/wow/doge/mygame/utils/AkkaUtils.scala

@ -1,11 +1,11 @@
package wow.doge.mygame.utils
import akka.actor.typed.ActorRef
import akka.actor.typed.Behavior
import akka.actor.typed.Props
import akka.util.Timeout
import akka.actor.typed.Scheduler
import akka.actor.typed.ActorRef
import akka.actor.typed.SpawnProtocol
import akka.actor.typed.Behavior
import akka.util.Timeout
import wow.doge.mygame.implicits._
object AkkaUtils {

7
src/main/scala/wow/doge/mygame/utils/JFXConsoleStream.scala

@ -1,11 +1,12 @@
package wow.doge.mygame.utils
import java.io.PrintStream
import java.io.OutputStream
import java.io.ByteArrayOutputStream
import scalafx.scene.control.TextArea
import java.io.OutputStream
import java.io.PrintStream
import cats.effect.Resource
import monix.bio.Task
import scalafx.scene.control.TextArea
trait JFXConsoleStreamable[T] {
def println(inst: T, text: String): Unit

Loading…
Cancel
Save