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

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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.Quaternion
import com.jme3.math.Vector3f
import wow.doge.mygame.math.ImVector3f
import wow.doge.mygame.subsystems.movement.RotateDir
import wow.doge.mygame.implicits._
import com.jme3.scene.Spatial
import com.typesafe.scalalogging.LazyLogging
import wow.doge.mygame.implicits._
import wow.doge.mygame.math.ImVector3f
import wow.doge.mygame.subsystems.movement.RotateDir
trait CanMove[-A] {
// def getDirection(cam: Camera, cardinalDir: CardinalDirection): ImVector3f

View File

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

View File

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

View File

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

View File

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

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

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

View File

@ -1,21 +1,22 @@
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.ScriptEngineManager
import groovy.util.GroovyScriptEngine
import cats.implicits._
import akka.actor.typed.ActorRef
import akka.actor.typed.Behavior
import akka.actor.typed.LogOptions
import org.slf4j.event.Level
import com.typesafe.scalalogging.Logger
import akka.actor.typed.scaladsl.ActorContext
import akka.actor.typed.scaladsl.Behaviors
import ammonite.Main
import ammonite.main.Defaults
import ammonite.runtime.Storage.Folder
import ammonite.util.Res.Success
import cats.implicits._
import com.softwaremill.tagging._
import com.typesafe.scalalogging.Logger
import groovy.util.GroovyScriptEngine
import org.slf4j.event.Level
object ScriptActor {
trait Kotlin

View File

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

View File

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

View File

@ -1,11 +1,11 @@
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.SpawnProtocol
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._
object AkkaUtils {

View File

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