many changes

This commit is contained in:
Rohan Sircar 2020-11-22 22:05:52 +05:30
parent a2a328d078
commit c93d0704b5
48 changed files with 859 additions and 965 deletions

View File

@ -74,7 +74,8 @@ lazy val root = (project in file(".")).settings(
"org.typelevel" %% "cats-core" % "2.1.1", "org.typelevel" %% "cats-core" % "2.1.1",
"org.typelevel" %% "cats-effect" % "2.1.4", "org.typelevel" %% "cats-effect" % "2.1.4",
"io.monix" %% "monix" % "3.2.2", "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-core" % "0.13.0",
"io.circe" %% "circe-generic" % "0.13.0", "io.circe" %% "circe-generic" % "0.13.0",
"com.softwaremill.sttp.client" %% "core" % "2.2.5", "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", "org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.0-RC1",
"com.typesafe.scala-logging" %% "scala-logging" % "3.9.2", "com.typesafe.scala-logging" %% "scala-logging" % "3.9.2",
"io.circe" %% "circe-config" % "0.8.0", "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 // Determine OS version of JavaFX binaries
@ -104,12 +106,20 @@ lazy val root = (project in file(".")).settings(
"UTF-8", "UTF-8",
"-deprecation", "-deprecation",
"-feature", "-feature",
"-language:existentials",
"-language:experimental.macros",
"-language:higherKinds",
"-language:implicitConversions",
"-unchecked", "-unchecked",
"-Xlint", "-Xlint",
"-Ywarn-numeric-widen", "-Ywarn-numeric-widen",
"-Ymacro-annotations", "-Ymacro-annotations",
"-Xlint:byname-implicit", // "-Xlint:byname-implicit",
// "utf-8", // Specify character encoding used by source files. // "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. "-explaintypes" // Explain type errors in more detail.
), ),
javacOptions ++= Seq("-source", "11", "-target", "11"), 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 // To learn more about multi-project builds, head over to the official sbt
// documentation at http://www.scala-sbt.org/documentation.html // documentation at http://www.scala-sbt.org/documentation.html
addCompilerPlugin("com.olegpy" %% "better-monadic-for" % "0.3.1") addCompilerPlugin("com.olegpy" %% "better-monadic-for" % "0.3.1")
ThisBuild / scalafixDependencies += "com.github.liancheng" %% "organize-imports" % "0.4.3"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,7 @@
package com.jme3 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. * Created by Brandon Barker on 6/21/17.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,41 +1,13 @@
package wow.doge.mygame 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.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._
import akka.actor.typed.SpawnProtocol import akka.actor.typed.SpawnProtocol
import akka.actor.typed.Scheduler import cats.effect.Resource
import wow.doge.mygame.utils.AkkaUtils import io.odin.Logger
import scala.concurrent.duration._ import monix.bio.Task
import akka.actor.typed.ActorRef import wow.doge.mygame.executors.ExecutorsModule
import wow.doge.mygame.implicits._ import wow.doge.mygame.game.GameModule
trait MainModule extends GameModule with ExecutorsModule { 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( def actorSystemResource2(
logger: Logger[Task] logger: Logger[Task]
@ -43,93 +15,11 @@ trait MainModule extends GameModule with ExecutorsModule {
Resource.make(logger.info("Creating Actor System") >> Task { Resource.make(logger.info("Creating Actor System") >> Task {
ActorSystem( ActorSystem(
SpawnProtocol(), SpawnProtocol(),
name = "GameActorSystem2" name = "GameActorSystem"
) )
})(sys => })(sys =>
logger.info("Shutting down actor system") >> Task( logger.info("Shutting down actor system") >> Task(
sys.terminate() 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
}
)
} }

View File

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

View File

@ -1,23 +1,21 @@
package wow.doge.mygame.executors 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.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 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 javafx.application.Platform
import monix.execution.Scheduler import monix.execution.Scheduler
import scala.concurrent.ExecutionContext
import java.util.concurrent.Executor
// First we wrap invokeLater/runLater as an ExecutorService // First we wrap invokeLater/runLater as an ExecutorService
trait GUIExecutorService extends AbstractExecutorService { trait GUIExecutorService extends AbstractExecutorService {

View File

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

View File

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

View File

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

View File

@ -1,27 +1,15 @@
package wow.doge.mygame.game 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.ActorRef
import akka.actor.typed.Scheduler
import akka.actor.typed.SpawnProtocol
import akka.actor.typed.scaladsl.Behaviors
import io.odin.Logger import io.odin.Logger
import monix.bio.Task import monix.bio.Task
import akka.actor.typed.Scheduler import wow.doge.mygame.events.Events
import scala.util.Failure import wow.doge.mygame.executors.Schedulers
import scala.util.Success
import com.jme3.app.StatsAppState
object GameAppActor { object GameAppActor {
import Methods._
sealed trait Command sealed trait Command
case object ApplicationStarted extends Command case object ApplicationStarted extends Command
@ -39,22 +27,6 @@ object GameAppActor {
Behaviors.setup[Command] { ctx => Behaviors.setup[Command] { ctx =>
ctx.log.info("Hello from GameAppActor") 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 => Behaviors.receiveMessage { msg =>
msg match { msg match {
case Stop => case Stop =>

View File

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

View File

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

View File

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

View File

@ -2,18 +2,16 @@ package wow.doge.mygame.state
import scala.concurrent.duration.DurationInt 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.InputManager
import com.jme3.input.KeyInput import com.jme3.input.KeyInput
import com.jme3.input.controls.KeyTrigger import com.jme3.input.controls.KeyTrigger
import com.jme3.math.Vector3f 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 com.jme3.scene.Geometry
import akka.actor.typed.scaladsl.TimerScheduler
import wow.doge.mygame.implicits._ import wow.doge.mygame.implicits._
import wow.doge.mygame.subsystems.movement.ImMovementActor import wow.doge.mygame.subsystems.movement.ImMovementActor

View File

@ -1,17 +1,18 @@
package wow.doge.mygame.state package wow.doge.mygame.state
import ammonite.runtime.Storage.Folder
import ammonite.main.Defaults
import ammonite.Main
import javax.script.ScriptEngine 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.AbstractBehavior
import akka.actor.typed.scaladsl.ActorContext 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.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( class ScriptingEngineState(
sse: ScalaScriptingEngine, sse: ScalaScriptingEngine,

View File

@ -1,13 +1,13 @@
package wow.doge.mygame.state package wow.doge.mygame.state
import wow.doge.mygame.implicits._ import com.jme3.asset.AssetManager
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.material.Material
import com.jme3.math.ColorRGBA import com.jme3.math.ColorRGBA
import com.jme3.asset.AssetManager
import com.jme3.math.Vector3f 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( class TestAppState(
// private var _entity: Option[EntityData] = Some(new DefaultEntityData()) // private var _entity: Option[EntityData] = Some(new DefaultEntityData())
) extends MyBaseState { ) extends MyBaseState {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,36 +1,20 @@
package wow.doge.mygame.game.subsystems.level package wow.doge.mygame.game.subsystems.level
import com.jme3.bullet.BulletAppState import com.jme3.asset.AssetManager
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape
import com.jme3.bullet.control.CharacterControl
import com.jme3.bullet.control.RigidBodyControl import com.jme3.bullet.control.RigidBodyControl
import com.jme3.bullet.util.CollisionShapeFactory 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.DirectionalLight
import com.jme3.math.Vector3f
import com.jme3.light.AmbientLight import com.jme3.light.AmbientLight
import com.jme3.light.DirectionalLight
import com.jme3.math.ColorRGBA
import com.jme3.math.Vector3f
import com.jme3.renderer.ViewPort
import com.jme3.scene.Spatial
object DefaultGameLevel { object DefaultGameLevel {
// lazy valbulletAppState: BulletAppState def apply(
// bulletAppState.setThreadingType(ThreadingType.SEQUENTIAL) assetManager: AssetManager,
viewPort: ViewPort
// We set up collision detection for the scene by creating a ) = {
// compound collision shape and a static RigidBodyControl with mass zero. lazy val sceneModel: Spatial = assetManager.loadModel("main.scene")
// 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")
lazy val sceneShape = CollisionShapeFactory.createMeshShape( lazy val sceneShape = CollisionShapeFactory.createMeshShape(
sceneModel.toNode match { sceneModel.toNode match {
case util.Right(node) => node case util.Right(node) => node
@ -41,23 +25,26 @@ object DefaultGameLevel {
lazy val landscape: RigidBodyControl = lazy val landscape: RigidBodyControl =
new RigidBodyControl(sceneShape, 0) new RigidBodyControl(sceneShape, 0)
// // discard { app.stateManager.attach(bulletAppState) } viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f))
app.viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f))
sceneModel.setLocalScale(2f) sceneModel.setLocalScale(2f)
sceneModel.addControl(landscape) sceneModel.addControl(landscape)
discard { app.rootNode.attachChild(sceneModel) } // discard { rootNode.attachChild(sceneModel) }
bulletAppState.getPhysicsSpace.add(landscape) // bulletAppState.getPhysicsSpace.add(landscape)
bulletAppState.getPhysicsSpace.add(player) // bulletAppState.getPhysicsSpace.add(player)
val al = new AmbientLight(); val al = new AmbientLight();
al.setColor(ColorRGBA.White.mult(1.3f)); al.setColor(ColorRGBA.White.mult(1.3f));
app.rootNode.addLight(al); // app.rootNode.addLight(al);
val dl = new DirectionalLight(); val dl = new DirectionalLight();
dl.setColor(ColorRGBA.White); dl.setColor(ColorRGBA.White);
dl.setDirection(new Vector3f(2.8f, -2.8f, -2.8f).normalizeLocal()); 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
)
} }
} }

View File

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

View File

@ -4,11 +4,11 @@ import com.jme3.bullet.control.BetterCharacterControl
import com.jme3.math.FastMath import com.jme3.math.FastMath
import com.jme3.math.Quaternion import com.jme3.math.Quaternion
import com.jme3.math.Vector3f 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.jme3.scene.Spatial
import com.typesafe.scalalogging.LazyLogging 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] { trait CanMove[-A] {
// def getDirection(cam: Camera, cardinalDir: CardinalDirection): ImVector3f // def getDirection(cam: Camera, cardinalDir: CardinalDirection): ImVector3f

View File

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

View File

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

View File

@ -1,52 +1,54 @@
package wow.doge.mygame package wow.doge.mygame
import com.jme3.app.SimpleApplication
import com.jme3.app.state.AppStateManager
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 com.jme3.input.InputManager
import com.jme3.input.controls.Trigger
import com.jme3.input.controls.InputListener
import com.jme3.math.Vector3f
import wow.doge.mygame.math.ImVector3f
import com.jme3.scene.Geometry
import scala.jdk.CollectionConverters._ import scala.jdk.CollectionConverters._
import scala.reflect.ClassTag
import akka.actor.typed.ActorRef
import akka.actor.typed.Scheduler
import akka.util.Timeout
import cats.effect.concurrent.Ref
import com.jme3.app.Application import com.jme3.app.Application
import com.jme3.scene.SceneGraphVisitor import com.jme3.app.SimpleApplication
import monix.reactive.Observable import com.jme3.app.state.AppState
import com.jme3.asset.AssetManager import com.jme3.app.state.AppStateManager
import com.jme3.asset.AssetLocator import com.jme3.asset.AssetLocator
import com.jme3.input.controls.ActionListener import com.jme3.asset.AssetManager
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
import com.jme3.bullet.BulletAppState import com.jme3.bullet.BulletAppState
import wow.doge.mygame.state.MyBaseState import com.jme3.bullet.PhysicsSpace
import monix.bio.UIO 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.bullet.control.BetterCharacterControl
import com.jme3.input.Action
import com.jme3.input.InputManager
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 com.jme3.scene.CameraNode import com.jme3.scene.CameraNode
import com.jme3.scene.Geometry
import com.jme3.scene.Node
import com.jme3.scene.SceneGraphVisitor
import com.jme3.scene.Spatial
import com.jme3.scene.control.CameraControl.ControlDirection import com.jme3.scene.control.CameraControl.ControlDirection
import com.jme3.scene.control.Control import com.jme3.scene.control.Control
import com.jme3.input.controls.AnalogListener import com.simsilica.es.EntityComponent
import com.simsilica.es.EntityData
import com.simsilica.es.EntityId
import enumeratum._ 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 monix.reactive.Observable
import monix.reactive.OverflowStrategy
import monix.reactive.observers.Subscriber
import wow.doge.mygame.math.ImVector3f
import wow.doge.mygame.state.MyBaseState
case class ActionEvent(binding: Action, value: Boolean, tpf: Float) case class ActionEvent(binding: Action, value: Boolean, tpf: Float)
case class EnumActionEvent[T <: EnumEntry]( 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 { extends AnyVal {
def state[S <: AppState]()(implicit c: ClassTag[S]): S = 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 { implicit class NodeExt[T <: Node](private val n: T) extends AnyVal {
/** /**
@ -139,6 +175,11 @@ package object implicits {
def observableChildren = def observableChildren =
Observable.fromIterable(n.getChildren().asScala) 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) def children = LazyList.from(n.getChildren().asScala)
/** /**
@ -147,12 +188,24 @@ package object implicits {
* @param lst * @param lst
*/ */
def withChildren(lst: Spatial*): Node = { def withChildren(lst: Spatial*): Node = {
for (c <- lst) n.withChild(c) for (c <- lst) n.attachChild(c)
n n
} }
def +=(spatial: Spatial) = n.attachChild(spatial) 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) = def depthFirst(cb: Spatial => Unit) =
n.depthFirstTraversal(new SceneGraphVisitor() { n.depthFirstTraversal(new SceneGraphVisitor() {
override def visit(s: Spatial) = cb(s) override def visit(s: Spatial) = cb(s)
@ -333,6 +386,16 @@ package object implicits {
inputManager 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] = { def observableAction(mappingNames: String*): Observable[ActionEvent] = {
Observable.create(OverflowStrategy.DropOld(10)) { sub => 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] = { def analogObservable(mappingNames: String*): Observable[AnalogEvent] = {
Observable.create(OverflowStrategy.DropOld(50)) { sub => Observable.create(OverflowStrategy.DropOld(50)) { sub =>
@ -509,60 +566,60 @@ package object implicits {
//TODO Create a typeclass for this //TODO Create a typeclass for this
def +=(anyObject: Any) = space.add(anyObject) def +=(anyObject: Any) = space.add(anyObject)
def :+(anyObject: Any) = {
space.add(anyObject)
space
}
def :-(anyObject: Any) = {
space.remove(anyObject)
space
}
def +=(spatial: Spatial) = space.addAll(spatial) def +=(spatial: Spatial) = space.addAll(spatial)
def :+(spatial: Spatial) = {
space.addAll(spatial)
space
} }
implicit class AssetManagerExt(private val am: AssetManager) extends AnyVal { def :-(spatial: Spatial) = {
def registerLocator( space.removeAll(spatial)
assetPath: os.RelPath, space
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 Vector3fExt(private val v: Vector3f) extends AnyVal { implicit class Vector3fExt(private val v: Vector3f) extends AnyVal {
//TODO add more operations //TODO add more operations
def +=(that: Vector3f) = v.addLocal(that) 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.addLocal(that.x, that.y, that.z)
def +=:(that: ImVector3f) = v += that def +=:(that: ImVector3f) = v += that
def *=(that: Vector3f) = v.multLocal(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: 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: Vector3f) = v.divideLocal(that)
def /=(that: ImVector3f) = v.divideLocal(that.mutable)
def /=:(that: ImVector3f) = v *= that
def unary_- = v.negateLocal() def unary_- = v.negateLocal()
def immutable = ImVector3f(v.x, v.y, v.z) def immutable = ImVector3f(v.x, v.y, v.z)
} }
implicit class ImVector3fExt(private val v: ImVector3f) extends AnyVal { 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 +(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 *(that: ImVector3f) = v.copy(v.x * that.x, v.y * that.y, v.z * that.z)
def *(f: Float): ImVector3f = def *(f: Float): ImVector3f =
v.copy(v.x * f, v.y * f, v.z * f) v.copy(v.x * f, v.y * f, v.z * f)
// v * ImVector3f(f, f, f) // v * ImVector3f(f, f, f)
def -(that: ImVector3f) = v.copy(v.x - that.x, v.y - that.y, v.z - that.z) 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 /(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_- = 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) 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,19 +1,20 @@
package wow.doge.mygame.scriptsystem 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.Behaviors
import akka.actor.typed.scaladsl.PoolRouter import akka.actor.typed.scaladsl.PoolRouter
import akka.actor.typed.scaladsl.Routers 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 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 com.typesafe.scalalogging.Logger
import org.slf4j.event.Level
import wow.doge.mygame.state.ScriptActor
object ScriptCachingActor { object ScriptCachingActor {

View File

@ -1,23 +1,65 @@
package wow.doge.mygame.subsystems.scriptsystem 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.ActorRef
import akka.actor.typed.Scheduler
import akka.actor.typed.SpawnProtocol import akka.actor.typed.SpawnProtocol
import akka.util.Timeout 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( class ScriptSystemResource(
path: os.Path, path: os.Path,
spawnProtocol: ActorRef[SpawnProtocol.Command] spawnProtocol: ActorRef[SpawnProtocol.Command],
mode: ScriptInitMode = ScriptInitMode.Lazy
)(implicit timeout: Timeout, scheduler: Scheduler) { )(implicit timeout: Timeout, scheduler: Scheduler) {
def make = val make = {
Resource.liftF( // throw new Exception("boom")
AkkaUtils.spawnActorL( findScriptFiles(os.pwd / "assets" / "scripts")
lazy val scriptCacheActor = AkkaUtils.spawnActorL(
spawnProtocol, spawnProtocol,
"scriptCachingActor", "scriptCachingActor",
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

View File

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

View File

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