diff --git a/.ammonite/scala-2.12.12/amm-2.2.0-4-4bd225e/src/main/resources/dep/src/ammonite/$file/src/main/resources/dep.scala b/.ammonite/scala-2.12.12/amm-2.2.0-4-4bd225e/src/main/resources/dep/src/ammonite/$file/src/main/resources/dep.scala
deleted file mode 100644
index 319342d..0000000
--- a/.ammonite/scala-2.12.12/amm-2.2.0-4-4bd225e/src/main/resources/dep/src/ammonite/$file/src/main/resources/dep.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-
-package ammonite
-package $file.src.main.resources
-import _root_.ammonite.interp.api.InterpBridge.{
- value => interp
-}
-import _root_.ammonite.interp.api.InterpBridge.value.{
- exit
-}
-import _root_.ammonite.interp.api.IvyConstructor.{
- ArtifactIdExt,
- GroupIdExt
-}
-import _root_.ammonite.runtime.tools.{
- browse,
- grep,
- time,
- tail
-}
-import _root_.ammonite.repl.tools.{
- desugar,
- source
-}
-import _root_.ammonite.main.Router.{
- doc,
- main
-}
-import _root_.ammonite.repl.tools.Util.{
- pathScoptRead
-}
-
-
-object dep{
-/**/ /**/
-def $main() = { scala.Iterator[String]() }
- override def toString = "dep"
- /**/
-}
diff --git a/.ammonite/scala-2.12.12/amm-2.2.0-4-4bd225e/src/main/resources/hello/src/ammonite/$file/src/main/resources/hello.scala b/.ammonite/scala-2.12.12/amm-2.2.0-4-4bd225e/src/main/resources/hello/src/ammonite/$file/src/main/resources/hello.scala
deleted file mode 100644
index ae97991..0000000
--- a/.ammonite/scala-2.12.12/amm-2.2.0-4-4bd225e/src/main/resources/hello/src/ammonite/$file/src/main/resources/hello.scala
+++ /dev/null
@@ -1,45 +0,0 @@
-
-package ammonite
-package $file.src.main.resources
-import _root_.ammonite.interp.api.InterpBridge.{
- value => interp
-}
-import _root_.ammonite.interp.api.InterpBridge.value.{
- exit
-}
-import _root_.ammonite.interp.api.IvyConstructor.{
- ArtifactIdExt,
- GroupIdExt
-}
-import _root_.ammonite.runtime.tools.{
- browse,
- grep,
- time,
- tail
-}
-import _root_.ammonite.repl.tools.{
- desugar,
- source
-}
-import _root_.ammonite.main.Router.{
- doc,
- main
-}
-import _root_.ammonite.repl.tools.Util.{
- pathScoptRead
-}
-import ammonite.$file.src.main.resources.{
- dep
-}
-
-
-object hello{
-/**/ /**/
-def $main() = { scala.Iterator[String]() }
- override def toString = "hello"
- /**/
-}
diff --git a/.ammonite/scala-2.12.12/amm-2.2.0-4-4bd225e/src/main/resources/hello2/src/ammonite/$file/src/main/resources/hello2.scala b/.ammonite/scala-2.12.12/amm-2.2.0-4-4bd225e/src/main/resources/hello2/src/ammonite/$file/src/main/resources/hello2.scala
deleted file mode 100644
index 52f6a44..0000000
--- a/.ammonite/scala-2.12.12/amm-2.2.0-4-4bd225e/src/main/resources/hello2/src/ammonite/$file/src/main/resources/hello2.scala
+++ /dev/null
@@ -1,134 +0,0 @@
-
-package ammonite
-package $file.src.main.resources
-import _root_.ammonite.interp.api.InterpBridge.{
- value => interp
-}
-import _root_.ammonite.interp.api.InterpBridge.value.{
- exit
-}
-import _root_.ammonite.interp.api.IvyConstructor.{
- ArtifactIdExt,
- GroupIdExt
-}
-import _root_.ammonite.runtime.tools.{
- browse,
- grep,
- time,
- tail
-}
-import _root_.ammonite.repl.tools.{
- desugar,
- source
-}
-import _root_.ammonite.main.Router.{
- doc,
- main
-}
-import _root_.ammonite.repl.tools.Util.{
- pathScoptRead
-}
-
-
-object hello2{
-/**/ /**/
-def $main() = { scala.Iterator[String]() }
- override def toString = "hello2"
- /**/
-}
diff --git a/build.sbt b/build.sbt
index d0f09ae..3159136 100644
--- a/build.sbt
+++ b/build.sbt
@@ -91,8 +91,8 @@ lazy val root = (project in file(".")).settings(
"com.beachape" %% "enumeratum-circe" % "1.6.1",
"com.lihaoyi" %% "os-lib" % "0.7.1",
// "com.jayfella" % "jme-jfx-11" % "1.1.5",
- "com.github.goxr3plus" % "FX-BorderlessScene" % "4.4.0",
- "com.github.Oshan96" % "CustomStage" % "v1.3.1",
+ // "com.github.goxr3plus" % "FX-BorderlessScene" % "4.4.0",
+ // "com.github.Oshan96" % "CustomStage" % "v1.3.1",
"com.badlogicgames.gdx" % "gdx-ai" % "1.8.2",
"org.recast4j" % "recast" % "1.2.5",
"org.recast4j" % "detour" % "1.2.5"
diff --git a/src/main/scala/org/slf4j/impl/StaticLoggerBuilder.scala b/src/main/scala/org/slf4j/impl/StaticLoggerBuilder.scala
index 0cb63ea..24e33bb 100644
--- a/src/main/scala/org/slf4j/impl/StaticLoggerBuilder.scala
+++ b/src/main/scala/org/slf4j/impl/StaticLoggerBuilder.scala
@@ -34,7 +34,7 @@ class StaticLoggerBinder extends OdinLoggerBinder[IO] {
private lazy val (defaultConsoleLogger, release1) =
consoleLogger[IO](minLevel = Level.Debug)
- .withAsync(timeWindow = 1.milliseconds)
+ .withAsync(timeWindow = 1.milliseconds, maxBufferSize = Some(2000))
.allocated
.unsafeRunSync()
@@ -43,7 +43,7 @@ class StaticLoggerBinder extends OdinLoggerBinder[IO] {
"application-log-2.log",
Formatter.json,
minLevel = Level.Debug
- ).withAsync(timeWindow = 1.milliseconds)
+ ).withAsync(timeWindow = 1.milliseconds, maxBufferSize = Some(2000))
.allocated
.unsafeRunSync()
@@ -52,7 +52,7 @@ class StaticLoggerBinder extends OdinLoggerBinder[IO] {
"eventbus.log",
Formatter.json,
minLevel = Level.Debug
- ).withAsync(timeWindow = 1.milliseconds)
+ ).withAsync(timeWindow = 1.milliseconds, maxBufferSize = Some(2000))
.allocated
.unsafeRunSync()
@@ -77,7 +77,7 @@ class StaticLoggerBinder extends OdinLoggerBinder[IO] {
// "wow.doge.mygame.subsystems.movement.PlayerMovementEventHandler"
// ) =>
// defaultConsoleLogger.withMinimalLevel( Level.Trace) //selectively turn on trace logging for specific classes
- case s if s.startsWith("wow.doge.mygame.events.EventBus") =>
+ case s if s.startsWith("wow.doge.mygame.subsystems.events.EventBus") =>
defaultConsoleLogger.withMinimalLevel(Level.Debug) |+| eventBusFileLogger
case s if s.startsWith("akka.actor") || s.startsWith("wow.doge.mygame") =>
defaultConsoleLogger.withMinimalLevel(Level.Debug) |+| mainFileLogger
diff --git a/src/main/scala/wow/doge/mygame/Main.scala b/src/main/scala/wow/doge/mygame/Main.scala
index 4a0a3b6..6e5177f 100644
--- a/src/main/scala/wow/doge/mygame/Main.scala
+++ b/src/main/scala/wow/doge/mygame/Main.scala
@@ -2,19 +2,19 @@ package wow.doge.mygame
import scala.concurrent.duration._
+import _root_.monix.bio.BIOApp
+import _root_.monix.bio.Task
+import _root_.monix.bio.UIO
import akka.util.Timeout
import cats.effect.ExitCode
+import cats.effect.Resource
import cats.implicits._
import com.softwaremill.macwire._
import io.odin._
import io.odin.json.Formatter
import io.odin.syntax._
-import wow.doge.mygame.game.GameAppResource
-import _root_.monix.bio.BIOApp
-import _root_.monix.bio.Task
-import _root_.monix.bio.UIO
-import cats.effect.Resource
import scalafx.scene.control.TextArea
+import wow.doge.mygame.game.GameAppResource
import wow.doge.mygame.utils.GenericConsoleStream
object Main extends BIOApp with MainModule {
@@ -25,15 +25,16 @@ object Main extends BIOApp with MainModule {
def appResource(consoleStream: GenericConsoleStream[TextArea]) =
for {
logger <-
- consoleLogger().withAsync(timeWindow = 1.milliseconds) |+|
+ consoleLogger().withAsync(
+ timeWindow = 1.milliseconds,
+ maxBufferSize = Some(2000)
+ ) |+|
fileLogger(
"application-log-1.log",
Formatter.json
- ).withAsync(timeWindow = 1.milliseconds)
+ ).withAsync(timeWindow = 1.milliseconds, maxBufferSize = Some(2000))
jmeScheduler <- jMESchedulerResource
- actorSystem <- actorSystemResource2(logger)
- // consoleTextArea <- Resource.liftF(Task(new TextArea()))
- // consoleStream <- wireWith(JFXConsoleStream.textAreaStream _)
+ actorSystem <- actorSystemResource(logger)
gameApp <- {
// new BulletAppState()
// bas.setThreadingType(Thr)
@@ -61,7 +62,7 @@ object Main extends BIOApp with MainModule {
lazy val consoleStream = GenericConsoleStream.textAreaStream()
Console.withOut(consoleStream)(
appResource(consoleStream)
- .use(_ => Task.unit)
+ .use(_ => Task.unit >> Task(consoleStream.close()))
.onErrorHandle(_.printStackTrace())
.as(ExitCode.Success)
)
diff --git a/src/main/scala/wow/doge/mygame/MainApp.scala b/src/main/scala/wow/doge/mygame/MainApp.scala
index b287386..133a0d1 100644
--- a/src/main/scala/wow/doge/mygame/MainApp.scala
+++ b/src/main/scala/wow/doge/mygame/MainApp.scala
@@ -5,56 +5,54 @@ 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 cats.effect.concurrent.Deferred
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.renderer.ViewPort
import com.jme3.scene.Node
import com.softwaremill.macwire._
import com.softwaremill.tagging._
import io.odin.Logger
+import monix.bio.Fiber
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.PlayerTag
-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
-import wow.doge.mygame.launcher.Launcher
-import wow.doge.mygame.executors.Schedulers
-import scalafx.application.JFXApp.PrimaryStage
-import scalafx.geometry.Insets
-import scalafx.scene.Scene
-import scalafx.scene.control.Button
-import scalafx.scene.layout.StackPane
-import scalafx.scene.paint.Color
-import scalafx.scene.shape.Rectangle
-import scalafx.Includes._
-import scala.concurrent.duration._
-import cats.effect.concurrent.Deferred
-import monix.bio.Fiber
-import wow.doge.mygame.launcher.Launcher.LauncherResult
import scalafx.scene.control.TextArea
-import com.jayfella.jme.jfx.JavaFxUI
+import wow.doge.mygame.executors.Schedulers
+import wow.doge.mygame.game.GameApp
+import wow.doge.mygame.game.GameAppActor
+import wow.doge.mygame.game.GameAppTags
+import wow.doge.mygame.game.entities.PlayerController
+import wow.doge.mygame.game.entities.PlayerControllerTags
+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.launcher.Launcher
+import wow.doge.mygame.launcher.Launcher.LauncherResult
+import wow.doge.mygame.math.ImVector3f
+import wow.doge.mygame.subsystems.events.EventBus
+import wow.doge.mygame.subsystems.events.EventsModule
+import wow.doge.mygame.subsystems.events.PlayerCameraEvent
+import wow.doge.mygame.subsystems.events.PlayerMovementEvent
+import wow.doge.mygame.subsystems.events.TickEvent
+import wow.doge.mygame.subsystems.scriptsystem.ScriptInitMode
+import wow.doge.mygame.subsystems.scriptsystem.ScriptSystemResource
+import wow.doge.mygame.utils.AkkaUtils
import wow.doge.mygame.utils.GenericConsoleStream
-import java.io.PrintStream
+
+import EventsModule.GameEventBus
+import wow.doge.mygame.game.entities.NpcMovementActor2
+import wow.doge.mygame.game.entities.NpcActorSupervisor
+import monix.execution.exceptions.DummyException
+import com.jme3.bullet.control.BetterCharacterControl
class MainApp(
logger: Logger[Task],
- gameApp: GameApp2,
- spawnProtocol: ActorSystem[SpawnProtocol.Command],
+ gameApp: GameApp,
+ implicit val spawnProtocol: ActorSystem[SpawnProtocol.Command],
jmeThread: monix.execution.Scheduler,
schedulers: Schedulers,
consoleStream: GenericConsoleStream[TextArea]
@@ -68,19 +66,29 @@ class MainApp(
def gameInit: Task[Fiber[Throwable, Unit]] =
for {
- eventsModule <- Task(new EventsModule2(spawnProtocol))
+ eventsModule <- Task(new EventsModule(spawnProtocol))
playerMovementEventBus <- eventsModule.playerMovementEventBusTask
playerCameraEventBus <- eventsModule.playerCameraEventBusTask
+ mainEventBus <- eventsModule.mainEventBusTask
+ tickEventBus <- eventsModule.tickEventBusTask
+ gameAppActor <- AkkaUtils.spawnActorL2(
+ GameAppActor.Props(tickEventBus).create,
+ "gameAppActor"
+ )
+ _ <- gameAppActor !! GameAppActor.Start
gameAppFib <- gameApp.start.executeOn(jmeThread).start
/**
* schedule a task to run on the JME thread and wait for it's completion
- * before proceeding forward, as a signal that JME thread has been
+ * before proceeding forward, as a signal that the JME thread has been
* initialized, otherwise we'll get NPEs trying to access the fields
* of the game app
*/
- res <- gameApp.enqueueL(() => Task("done")).flatten
-
+ res <- gameApp.enqueueL(() => "done")
_ <- logger.info(s"Result = $res")
+ /**
+ * JME Thread has been initialized at this point. We can now access the
+ * field of the game application
+ */
inputManager <- gameApp.inputManager
assetManager <- gameApp.assetManager
stateManager <- gameApp.stateManager
@@ -89,41 +97,20 @@ class MainApp(
enqueueR <- Task(gameApp.enqueue _)
viewPort <- gameApp.viewPort
_ <- logger.info("before")
- // jfxUI <- Task(JavaFxUI.initialize(gameApp.app))
- // .executeOn(gameApp.scheduler) >> Task.sleep(500.millis) >> Task(
- // JavaFxUI.getInstance()
- // )
- // .start
- jfxUI <- gameApp.jfxUI
+ // jfxUI <- gameApp.jfxUI
consoleTextArea <- Task(new TextArea {
- text = "hello"
+ text = "hello \n"
editable = false
wrapText = true
// maxHeight = 150
// maxWidth = 300
})
- _ <- Task(consoleStream := consoleTextArea)
- _ <- Task(jfxUI += consoleTextArea)
- // consoleStream <- Task(
- // GenericConsoleStream.textAreaStream(consoleTextArea)
- // )
+ // _ <- Task(consoleStream := consoleTextArea)
+ // _ <- Task(jfxUI += consoleTextArea)
_ <- logger.info("after")
bulletAppState <- Task(new BulletAppState())
_ <- Task(stateManager.attach(bulletAppState))
_ <- logger.info("Initializing console stream")
- // _ <- Task(GenericConsoleStream.textAreaStream(consoleTextArea)).bracket(
- // consoleStream =>
- // Task { System.setOut(consoleStream) } >> wire[MainAppDelegate]
- // .init(gameApp.scheduler, consoleStream)
- // // consoleLogger
- // // Console.withOut(consoleStream)(
- // // wire[MainAppDelegate].init(gameApp.scheduler, consoleStream)
- // // )
- // )(stream => Task(stream.close()).onErrorHandle(_.printStackTrace()))
- // _ <- Task { System.setOut(new PrintStream(consoleStream, true)) }
- // _ <- Task {
- // Console.withOut(consoleStream)(println("hello"))
- // }
_ <- wire[MainAppDelegate].init(gameApp.scheduler)
} yield (gameAppFib)
@@ -131,7 +118,7 @@ class MainApp(
scriptSystem <- scriptSystemInit
/**
* Signal for synchronization between the JavaFX launcher and the in-game JavaFX GUI
- * Without this, we get a "Toolkit already initialized" excResult. The launch button
+ * Without this, we get a "Toolkit already initialized" exception. The launch button
* in the launcher completes the signal. The game init process which listens for this
* signal can then continue
*/
@@ -141,15 +128,16 @@ class MainApp(
launchResult <- launchSignal.get
_ <- cancelToken.cancel
_ <-
+ /**
+ * User chose to quit
+ */
if (launchResult == LauncherResult.Exit)
logger.info("Exiting")
- else gameInit.flatMap(_.join)
- // _ <- Task.sleep(2000.millis)
- // gameAppFib <- gameInit
- /**
- * Wait for game window to close
- */
- // _ <- gameAppFib.join
+ /**
+ * User chose launch. Wait for game window to close
+ */
+ else
+ gameInit.flatMap(_.join)
} yield ()
}
@@ -157,27 +145,27 @@ class MainApp(
* Class with all dependencies in one place for easy wiring
*/
class MainAppDelegate(
- gameApp: GameApp2,
- spawnProtocol: ActorSystem[SpawnProtocol.Command],
+ gameApp: GameApp,
+ implicit val spawnProtocol: ActorSystem[SpawnProtocol.Command],
loggerL: Logger[Task],
- // eventBuses: EventsModule2
playerMovementEventBus: ActorRef[
- EventBus.Command[EntityMovementEvent.PlayerMovementEvent]
+ EventBus.Command[PlayerMovementEvent]
],
playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]],
+ tickEventBus: GameEventBus[TickEvent],
inputManager: InputManager,
assetManager: AssetManager,
stateManager: AppStateManager,
camera: Camera,
viewPort: ViewPort,
enqueueR: Function1[() => Unit, Unit],
- rootNode: Ref[Task, Node],
+ rootNode: Node @@ GameAppTags.RootNode,
bulletAppState: BulletAppState
)(implicit
@annotation.unused timeout: Timeout,
@annotation.unused scheduler: Scheduler
) {
-
+ lazy val physicsSpace = bulletAppState.physicsSpace
def init(
appScheduler: monix.execution.Scheduler
// consoleStream: GenericConsoleStream[TextArea]
@@ -186,11 +174,11 @@ class MainAppDelegate(
_ <- loggerL.info("Initializing Systems")
_ <- Task(
assetManager.registerLocator(
- (os.rel / "assets" / "town.zip"),
+ os.rel / "assets" / "town.zip",
classOf[ZipLocator]
)
)
- _ <- loggerL.info("test hmm")
+ _ <- loggerL.info("test")
// _ <- Task(consoleStream.println("text"))
_ <- DefaultGameLevel(assetManager, viewPort)
.addToGame(
@@ -198,23 +186,91 @@ class MainAppDelegate(
bulletAppState.physicsSpace
)
.executeOn(appScheduler)
- _ <- createPlayerController(appScheduler).startAndForget.onErrorRestart(3)
+ _ <- createPlayerController(appScheduler)
+ .absorbWith(e => DummyException("boom"))
+ .onErrorRestart(3)
+ johnActor <- createNpc(appScheduler, "John").executeOn(appScheduler)
+ _ <- johnActor !! NpcActorSupervisor.Move(ImVector3f(0, 0, 20))
_ <- 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[PlayerTag]
- @annotation.unused
val modelPath = os.rel / "Models" / "Jaime" / "Jaime.j3o"
- wire[PlayerController.Props].create
+ val playerPhysicsControl =
+ PlayerController.Defaults.defaultPlayerPhysicsControl
+ .taggedWith[PlayerControllerTags.PlayerTag]
+ val camNode =
+ PlayerController.Defaults
+ .defaultCamerNode(camera, playerPos)
+ .taggedWith[PlayerControllerTags.PlayerCameraNode]
+ val mbPlayerNode = PlayerController.Defaults
+ .defaultPlayerNode(
+ assetManager,
+ modelPath,
+ playerPos,
+ camNode,
+ playerPhysicsControl
+ )
+
+ for {
+ playerNode <- IO.fromEither(mbPlayerNode)
+ _ <- wire[PlayerController.Props].create
+ } yield ()
}
+ def createNpc(
+ appScheduler: monix.execution.Scheduler,
+ npcName: String
+ ) =
+ // : IO[PlayerController.Error, Unit] =
+ {
+ val initialPos = ImVector3f(100, 0, 0)
+ // val modelPath = os.rel / "Models" / "Jaime" / "Jaime.j3o"
+ lazy val npcPhysicsControl =
+ new BetterCharacterControl(1f, 2.1f, 10f)
+ // .withJumpForce(ImVector3f(0, 5f, 0))
+ // val npcMovementActor = AkkaUtils.spawnActorL2(
+ // new NpcMovementActor2.Props(
+ // initialPos,
+ // tickEventBus,
+ // npcPhysicsControl
+ // ).create,
+ // s"${npcName}-npcMovementActor"
+ // )
+ lazy val mbNpcNode = PlayerController.Defaults.defaultNpcNode(
+ assetManager,
+ initialPos,
+ npcPhysicsControl,
+ "John"
+ )
+ val npcActorTask = AkkaUtils.spawnActorL2(
+ NpcActorSupervisor
+ .Props(
+ new NpcMovementActor2.Props(
+ enqueueR,
+ initialPos,
+ tickEventBus,
+ npcPhysicsControl
+ ).create,
+ npcName,
+ initialPos
+ )
+ .create,
+ s"${npcName}-npcMovementActorSupervisor"
+ )
+ // .taggedWith[PlayerControllerTags.PlayerTag]
+
+ for {
+ npcNode <- IO.fromEither(mbNpcNode)
+ npcActor <- npcActorTask
+ _ <- IO {
+ physicsSpace += npcPhysicsControl
+ physicsSpace += npcNode
+ rootNode += npcNode
+ }
+ } yield (npcActor)
+ }
+
}
diff --git a/src/main/scala/wow/doge/mygame/MainModule.scala b/src/main/scala/wow/doge/mygame/MainModule.scala
index 87f51b5..e2ad87a 100644
--- a/src/main/scala/wow/doge/mygame/MainModule.scala
+++ b/src/main/scala/wow/doge/mygame/MainModule.scala
@@ -5,11 +5,10 @@ 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 {
+trait MainModule extends ExecutorsModule {
- def actorSystemResource2(
+ def actorSystemResource(
logger: Logger[Task]
): Resource[Task, ActorSystem[SpawnProtocol.Command]] =
Resource.make(logger.info("Creating Actor System") >> Task {
@@ -18,8 +17,10 @@ trait MainModule extends GameModule with ExecutorsModule {
name = "GameActorSystem"
)
})(sys =>
- logger.info("Shutting down actor system") >> Task(
- sys.terminate()
- )
+ for {
+ _ <- Task(sys.terminate())
+ _ <- Task.fromFuture(sys.whenTerminated)
+ _ <- logger.info("Actor System Terminated")
+ } yield ()
)
}
diff --git a/src/main/scala/wow/doge/mygame/game/GameApp.scala b/src/main/scala/wow/doge/mygame/game/GameApp.scala
index fc29785..8f829c5 100644
--- a/src/main/scala/wow/doge/mygame/game/GameApp.scala
+++ b/src/main/scala/wow/doge/mygame/game/GameApp.scala
@@ -1,132 +1,191 @@
package wow.doge.mygame.game
-import scala.collection.immutable.Queue
-
-import com.jme3.app.SimpleApplication
-import com.jme3.app.state.AppState
+import cats.effect.concurrent.Deferred
+import com.jme3.app.state.AppStateManager
+import com.jme3.asset.AssetManager
+import com.jme3.input.InputManager
+import com.jme3.scene.Node
+import com.jme3.scene.Spatial
+import com.softwaremill.tagging._
+import com.typesafe.scalalogging.{Logger => SLogger}
+import io.odin.Logger
+import monix.bio.IO
import monix.bio.Task
-import monix.execution.CancelableFuture
-import monix.execution.Scheduler
-import monix.execution.atomic.Atomic
-import monix.execution.{CancelablePromise => Promise}
-import monix.reactive.MulticastStrategy
-import monix.reactive.Observable
-import monix.reactive.subjects.ConcurrentSubject
-import wow.doge.mygame.executors.GUIExecutorService
-import wow.doge.mygame.executors.Schedulers
+import monix.catnap.ConcurrentChannel
+import monix.catnap.ConsumerF
+import monix.catnap.Semaphore
+import monix.eval.Coeval
+import wow.doge.mygame.game.subsystems.ui.JFxUI
-class GameApp(
- schedulers: Schedulers,
- appStates: AppState*
-) extends SimpleApplication(appStates: _*) {
- import GameApp._
+sealed trait Error
+case object FlyCamNotExists extends Error
+
+object GameAppTags {
+ sealed trait RootNode
+ sealed trait GuiNode
+}
+
+class GameApp(logger: Logger[Task], val app: SimpleAppExt) {
+ import Ops._
+
+ def stateManager: Task[AppStateManager] = Task(app.getStateManager())
+ def inputManager: Task[InputManager] = Task(app.getInputManager())
+ def assetManager: Task[AssetManager] = Task(app.getAssetManager())
+ def guiNode = Task(app.getGuiNode().taggedWith[GameAppTags.GuiNode])
+ def addToGuiNode = guiNode.flatMap(rn => Task(new AddToNode(rn)))
+ def flyCam =
+ IO(app.getFlyByCamera()).onErrorHandleWith(_ =>
+ IO.raiseError(FlyCamNotExists)
+ )
+ def camera = Task(app.getCamera())
+ def viewPort = Task(app.getViewPort())
+ def rootNode = Task(app.getRootNode().taggedWith[GameAppTags.RootNode])
+ // def rootNode2 = SynchedObject(app.getRootNode())
+ def addToRootNode = rootNode.flatMap(rn => Task(new AddToNode(rn)))
+ 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
+ def jfxUI = JFxUI(app)
+
+}
+
+object GameApp {
+
+ class WrappedNode(node: Node, lock: Semaphore[Task]) {
+
+ def +=(spat: Spatial) = lock.withPermit(Task(node.attachChild(spat)))
+ }
/**
- * A non blocking synchronized queue using an immutable scala queue and monix's atomic class
+ * Synchronization wrapper for a mutable object
+ *
+ * @param obj the mutable object
+ * @param lock lock for synchronization
*/
- private lazy val taskQueue2 = Atomic(Queue.empty[MyTask[_]])
+ class SynchedObject[A](obj: A, lock: Semaphore[Task]) {
+ def modify(f: A => Unit): Task[Unit] =
+ lock.withPermit(Task(f(obj)))
- private val tickSubject =
- ConcurrentSubject[Float](multicast = MulticastStrategy.publish)(
- schedulers.async
- )
+ def flatModify(f: A => Task[Unit]): Task[Unit] =
+ lock.withPermit(f(obj))
- def tickObservable: Observable[Float] = tickSubject
-
- override def simpleInitApp(): Unit = {}
-
- override def simpleUpdate(tpf: Float): Unit = {
- tickSubject.onNext(tpf)
+ def get: Task[A] = lock.withPermit(Task(obj))
}
- override def stop(): Unit = {
- tickSubject.onComplete()
- super.stop()
+ object SynchedObject {
+ def apply[A](obj: A) =
+ Semaphore[Task](1).flatMap(lock => Task(new SynchedObject(obj, lock)))
}
- def enqueueScala[T](cb: () => T): CancelableFuture[T] = {
- val p = Promise[T]()
- taskQueue2.transform(_ :+ MyTask(p, cb))
- p.future
- }
+}
- def enqueueL[T](cb: () => T): Task[T] =
- Task.deferFuture(enqueueScala(cb))
+object Ops {
+ final class AddToNode[T <: Node](private val node: T) extends AnyVal {
- override protected def runQueuedTasks(): Unit = {
- taskQueue2.transform { current =>
- current.dequeueOption.fold(current) {
- case (MyTask(p, cb), updated) =>
- p.success(cb())
- updated
+ /**
+ * Pure version
+ */
+ def apply(spatial: Spatial)(implicit logger: Logger[Task]) =
+ logger.debug(
+ s"Request to add spatial with name ${spatial.getName()} to node ${node.getName()}"
+ ) >> Task(node.attachChild(spatial))
+
+ /**
+ * Impure version
+ */
+ def apply(spatial: Spatial)(implicit logger: SLogger) =
+ Coeval {
+ logger.debug(
+ s"Request to add spatial with name ${spatial.getName()} to node ${node.getName()}"
+ )
+ node.attachChild(spatial)
}
+ }
+}
+
+object SpawnSystem {
+ sealed trait Result
+ final case object Ok extends Result
+
+ sealed trait Complete
+ final case object Complete extends Complete
+
+ sealed trait SpawnRequest
+ final case class SpawnSpatial(node: Node) extends SpawnRequest
+
+ final case class SpawnRequestWrapper(
+ spawnRequest: SpawnRequest,
+ result: Deferred[Task, Result]
+ )
+
+ def apply(logger: Logger[Task]) =
+ for {
+ spawnChannel <- ConcurrentChannel[Task].of[Complete, SpawnRequestWrapper]
+ spawnSystem <- Task(new SpawnSystem(logger, spawnChannel))
+ consumer <-
+ spawnChannel.consume
+ .use(consumer => spawnSystem.receive(consumer))
+ .startAndForget
+ } yield (spawnSystem)
+}
+
+class SpawnSystem(
+ logger: Logger[Task],
+ spawnChannel: ConcurrentChannel[
+ Task,
+ SpawnSystem.Complete,
+ SpawnSystem.SpawnRequestWrapper
+ ]
+) {
+ import SpawnSystem._
+
+ for {
+ spawnSystem <- SpawnSystem(logger)
+ n <- spawnSystem.request(SpawnSpatial(new Node("Test")))
+ } yield ()
+
+ // val spawnChannel = ConcurrentChannel[Task].of[Result, SpawnRequest]
+
+ private def receive(
+ consumer: ConsumerF[Task, Complete, SpawnRequestWrapper]
+ ): Task[Unit] =
+ consumer.pull.flatMap {
+ case Right(message) =>
+ for {
+ _ <-
+ logger
+ .debug(s"Received spawn request $message")
+ _ <- handleSpawn(message)
+ } yield receive(consumer)
+ case Left(r) =>
+ logger.info("Worker $$index is done!")
}
- super.runQueuedTasks()
- }
+ private def handleSpawn(spawnRequestWrapper: SpawnRequestWrapper) =
+ spawnRequestWrapper match {
+ case SpawnRequestWrapper(spawnRequest, result) =>
+ spawnRequest match {
+ case SpawnSpatial(spatial) =>
+ logger.debug(
+ s"Spawning spatial with name ${spatial.getName()}"
+ ) >> result
+ .complete(Ok)
- object JMEExecutorService extends GUIExecutorService {
- override def execute(command: Runnable): Unit =
- enqueueScala(() => command.run())
- // enqueue(command)
- // new SingleThreadEventExecutor()
- // sys.addShutdownHook(JMEExecutorService.shutdown())
- }
+ }
+ }
- lazy val scheduler = Scheduler(JMEExecutorService)
+ def request(spawnRequest: SpawnRequest) =
+ for {
+ d <- Deferred[Task, Result]
+ _ <- spawnChannel.push(SpawnRequestWrapper(spawnRequest, d))
+ res <- d.get
+ } yield (res)
+
+ def stop = spawnChannel.halt(Complete)
}
-object GameApp {
- private[game] case class MyTask[T](p: Promise[T], cb: () => T)
-}
-
-// val ship = ed.createEntity()
-// val mbState = stateManager().state[EntityDataState]().map(_.getEntityData())
-// val mbState = Try(
-// stateManager()
-// .state[TestAppState]()
-// .entity
-// ).toOption.flatten.toRight(println("empty"))
-// // .flatMap(_.entity)
-// val x = mbState.flatMap(
-// _.query
-// .filter[TestComponent]("name", new Object())
-// // .filterOr[TestEntity](
-// // Filters
-// // .fieldEquals(classOf[TestEntity], "", null)
-// // )
-// .component[Tag]()
-// .component[TestComponent]()
-// .result
-// .toRight(println("failed"))
-// )
-
-// rootNode
-// .child(geom)
-// .child(geom)
-// .child(geom)
-// .child(geom)
-// .child(geom)
-// .child(geom)
-// .child(geom)
-// .child(geom)
-// Future(println("hello"))(jmeEC(this))
-// val wbActor: Future[ActorRef[Greeter.Greet]] = actorSystem.ask(
-// SpawnProtocol.Spawn(
-// behavior = Greeter(),
-// name = "listener",
-// DispatcherSelector.fromConfig("jme-dispatcher"),
-// _
-// )
-// )
-
-// wbActor.map(a => a.ask(Greeter.Greet("hello", _)).map(println))
-
-// Task(Promise[T]()).flatMap { p =>
-// Task(taskQueue2.transform(_ :+ MyTask(p, cb))) >>
-// Task.fromCancelablePromise(p)
-// }
-// Task.fromCancelablePromise {
-// val p = Promise[T]()
-// taskQueue2.transform(_ :+ MyTask(p, cb))
-// p
-// }
diff --git a/src/main/scala/wow/doge/mygame/game/GameApp2.scala b/src/main/scala/wow/doge/mygame/game/GameApp2.scala
deleted file mode 100644
index 54a9f28..0000000
--- a/src/main/scala/wow/doge/mygame/game/GameApp2.scala
+++ /dev/null
@@ -1,71 +0,0 @@
-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
-import com.jme3.scene.Node
-import monix.catnap.Semaphore
-import com.jme3.scene.Spatial
-import wow.doge.mygame.game.GameApp2.SynchedObject
-import wow.doge.mygame.game.subsystems.ui.JFxUI
-
-sealed trait Error
-case object FlyCamNotExists extends Error
-
-class GameApp2(val 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 rootNode2 = SynchedObject(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
- def jfxUI = JFxUI(app)
-
-}
-
-object GameApp2 {
-
- class WrappedNode(node: Node, lock: Semaphore[Task]) {
-
- def +=(spat: Spatial) = lock.withPermit(Task(node.attachChild(spat)))
- }
-
- /**
- * Synchronization wrapper for a mutable object
- *
- * @param obj the mutable object
- * @param lock lock for synchronization
- */
- class SynchedObject[A](obj: A, lock: Semaphore[Task]) {
- def modify(f: A => Unit): Task[Unit] =
- lock.withPermit(Task(f(obj)))
-
- def flatModify(f: A => Task[Unit]): Task[Unit] =
- lock.withPermit(f(obj))
-
- def get: Task[A] = lock.withPermit(Task(obj))
- }
-
- object SynchedObject {
- def apply[A](obj: A) =
- Semaphore[Task](1).flatMap(lock => Task(new SynchedObject(obj, lock)))
- }
-}
diff --git a/src/main/scala/wow/doge/mygame/game/GameAppActor.scala b/src/main/scala/wow/doge/mygame/game/GameAppActor.scala
index 89d3fbd..61ac299 100644
--- a/src/main/scala/wow/doge/mygame/game/GameAppActor.scala
+++ b/src/main/scala/wow/doge/mygame/game/GameAppActor.scala
@@ -1,53 +1,83 @@
package wow.doge.mygame.game
-import akka.actor.typed.ActorRef
-import akka.actor.typed.Scheduler
-import akka.actor.typed.SpawnProtocol
+import scala.concurrent.duration._
+
+import akka.actor.typed.SupervisorStrategy
import akka.actor.typed.scaladsl.Behaviors
-import io.odin.Logger
-import monix.bio.Task
-import wow.doge.mygame.events.Events
-import wow.doge.mygame.executors.Schedulers
+import wow.doge.mygame.game.TickGenerator.Send
+import wow.doge.mygame.game.entities.GenericTimerActor
+import wow.doge.mygame.subsystems.events.EventBus
+import wow.doge.mygame.subsystems.events.EventsModule.GameEventBus
+import wow.doge.mygame.subsystems.events.TickEvent
+import wow.doge.mygame.subsystems.events.TickEvent.PhysicsTick
object GameAppActor {
sealed trait Command
- case object ApplicationStarted extends Command
- case class ApplicationStartFailed(reason: String) extends Command
+ case object Start extends Command
+ case object Pause extends Command
case object Stop extends Command
case class Props(
- app: GameApp,
- akkaScheduler: Scheduler,
- schedulers: Schedulers,
- spawnProtocol: ActorRef[SpawnProtocol.Command],
- loggerL: Logger[Task]
+ // app: SimpleAppExt,
+ // akkaScheduler: Scheduler,
+ // schedulers: Schedulers,
+ // spawnProtocol: ActorRef[SpawnProtocol.Command],
+ // loggerL: Logger[Task]
+ tickEventBus: GameEventBus[TickEvent]
) {
def create =
Behaviors.setup[Command] { ctx =>
ctx.log.info("Hello from GameAppActor")
+ val renderTickGenerator =
+ ctx.spawn(
+ Behaviors
+ .supervise(renderTickGeneratorBehavior)
+ .onFailure[Exception](SupervisorStrategy.restart),
+ "tickGeneratorActor"
+ )
+
+ val tickGeneratorTimer = ctx.spawn(
+ GenericTimerActor
+ .Props(renderTickGenerator, TickGenerator.Send, 10.millis)
+ .create,
+ "tickGeneratorTimer"
+ )
+
+ Behaviors.receiveMessage {
+ case Start =>
+ tickGeneratorTimer ! GenericTimerActor.Start
+ Behaviors.same
+ case Pause =>
+ tickGeneratorTimer ! GenericTimerActor.Stop
+ Behaviors.same
+ case Stop =>
+ ctx.log.info("Received stop")
+ tickGeneratorTimer ! GenericTimerActor.Stop
+ Behaviors.stopped
- Behaviors.receiveMessage { msg =>
- msg match {
- case Stop =>
- ctx.log.info("Received stop")
- Behaviors.stopped
- case ApplicationStarted =>
- ctx.log.info("Application started")
- Behaviors.same
- case ApplicationStartFailed(reason) =>
- ctx.log.error(
- s"Failed to start application - $reason"
- )
- Behaviors.stopped
- }
}
}
+
+ val renderTickGeneratorBehavior =
+ Behaviors.receiveMessage[TickGenerator.Command] {
+ case Send =>
+ tickEventBus ! EventBus.Publish(
+ TickEvent.RenderTick,
+ "tickGeneratorActor"
+ )
+ Behaviors.same
+ }
}
}
+
+object TickGenerator {
+ sealed trait Command
+ case object Send extends Command
+}
object SubscribingActor {
def apply() =
- Behaviors.receive[Events.Tick.PhysicsTick.type] { (ctx, msg) =>
+ Behaviors.receive[PhysicsTick.type] { (ctx, msg) =>
ctx.log.debug(s"received event $msg")
Behaviors.same
}
diff --git a/src/main/scala/wow/doge/mygame/game/GameModule.scala b/src/main/scala/wow/doge/mygame/game/GameModule.scala
index c7378e2..d29fae7 100644
--- a/src/main/scala/wow/doge/mygame/game/GameModule.scala
+++ b/src/main/scala/wow/doge/mygame/game/GameModule.scala
@@ -1,48 +1,24 @@
package wow.doge.mygame.game
-import akka.actor.typed.ActorRef
-import akka.actor.typed.SpawnProtocol
import cats.effect.Resource
import com.jme3.app.StatsAppState
import com.jme3.system.AppSettings
import 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 get2: Resource[Task, (GameApp2, Fiber[Throwable, Unit])] =
- 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
- // app
- new GameApp2(app)
- }
- fib <- app2.start.executeOn(jmeScheduler).start
- } yield (app2 -> fib)
- )(logger.info("Closing game app") >> _._2.cancel)
- def get: Resource[Task, GameApp2] =
+ def get: Resource[Task, GameApp] =
Resource.make(
for {
_ <- logger.info("Creating game app")
- app <- Task(new GameApp(schedulers, new StatsAppState()))
- app2 <- Task {
+ appExt <- Task(new SimpleAppExt(schedulers, new StatsAppState()))
+ app <- Task {
val settings = new AppSettings(true)
settings.setVSync(true)
@@ -50,48 +26,11 @@ class GameAppResource(
* disables the launcher
* We'll be making our own launcher anyway
*/
- app.setShowSettings(false)
- app.setSettings(settings)
+ appExt.setShowSettings(false)
+ appExt.setSettings(settings)
// JMERunner.runner = app
- new GameApp2(app)
+ new GameApp(logger, appExt)
}
- // fib <- app2.start.executeOn(jmeScheduler).start
- } yield (app2)
+ } yield (app)
)(_ => logger.info("Closing game app"))
}
-
-trait GameModule {
-
- def gameAppResource(
- logger: Logger[Task],
- jmeScheduler: Scheduler,
- schedulers: Schedulers
- ): Resource[Task, (GameApp, Fiber[Throwable, Unit])] =
- Resource.make(
- (for {
- _ <- logger.info("Creating game app")
- app <- Task(new GameApp(schedulers))
- _ <- Task {
- val settings = new AppSettings(true)
- settings.setVSync(true)
- // settings.setFrameRate(250)
- app.setSettings(settings)
- // JMERunner.runner = app
- app
- }
- fib <- Task(app.start()).executeOn(jmeScheduler).start
- } yield (app -> fib))
- )(_._2.cancel)
-
- def inputHandlerSystemResource(
- props: GameInputHandler.Props
- ): Resource[Task, Task[Unit]] =
- Resource.liftF {
- Task.evalAsync(props.begin)
- }
- def gameSystemsResource(
- spawnProtocol: ActorRef[SpawnProtocol.Command],
- gameSystems: Task[Unit]*
- ): Resource[Task, List[Unit]] =
- Resource.liftF(IO.defer(Task.parSequence(gameSystems)))
-}
diff --git a/src/main/scala/wow/doge/mygame/game/GameSystemsInitializer.scala b/src/main/scala/wow/doge/mygame/game/GameSystemsInitializer.scala
deleted file mode 100644
index ead2fc0..0000000
--- a/src/main/scala/wow/doge/mygame/game/GameSystemsInitializer.scala
+++ /dev/null
@@ -1,106 +0,0 @@
-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.PlayerTag
-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.PlayerCameraEvent
-import wow.doge.mygame.subsystems.movement.ImMovementActor
-import wow.doge.mygame.utils.IOUtils
-
-class GameSystemsInitializer(
- 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,
- 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 bulletAppState = new BulletAppState()
- // lazy val playerMovementEventBus = eventBuses.playerMovementEventBusTask
-
- val init =
- for {
- _ <- loggerL.info("Initializing Systems")
- // playerMovementEventBus <- playerMovementEventBusTask
- _ <- Task(stateManager.attach(bulletAppState))
- _ <- Task(
- assetManager.registerLocator(
- // "src/main/resources/assets/town.zip",
- (os.rel / "assets" / "town.zip"),
- classOf[ZipLocator]
- )
- )
-
- // _ <- app.enqueueL(() => DefaultGameLevel(app, bulletAppState))
- _ <- wireWith(createPlayerController _).startAndForget
- _ <- wire[GameInputHandler.Props].begin
-
- } yield ()
-
- def createPlayerController(
- // 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[PlayerTag]
- @annotation.unused
- val modelPath = os.rel / "Models" / "Jaime" / "Jaime.j3o"
- wire[PlayerController.Props].create
- }
-}
-
-object GameSystemsInitializer {
-
- def playerMovementActorTickConsumer(
- playerMovementActor: ActorRef[ImMovementActor.Command]
- ) =
- Consumer
- .foreachTask[Float](tpf =>
- IOUtils.toTask(playerMovementActor !! ImMovementActor.Tick)
- )
- // .mapTask()
-}
diff --git a/src/main/scala/wow/doge/mygame/game/SimpleAppExt.scala b/src/main/scala/wow/doge/mygame/game/SimpleAppExt.scala
new file mode 100644
index 0000000..ce541b1
--- /dev/null
+++ b/src/main/scala/wow/doge/mygame/game/SimpleAppExt.scala
@@ -0,0 +1,132 @@
+package wow.doge.mygame.game
+
+import scala.collection.immutable.Queue
+
+import com.jme3.app.SimpleApplication
+import com.jme3.app.state.AppState
+import monix.bio.Task
+import monix.execution.CancelableFuture
+import monix.execution.Scheduler
+import monix.execution.atomic.Atomic
+import monix.execution.{CancelablePromise => Promise}
+import monix.reactive.MulticastStrategy
+import monix.reactive.Observable
+import monix.reactive.subjects.ConcurrentSubject
+import wow.doge.mygame.executors.GUIExecutorService
+import wow.doge.mygame.executors.Schedulers
+
+class SimpleAppExt(
+ schedulers: Schedulers,
+ appStates: AppState*
+) extends SimpleApplication(appStates: _*) {
+ import SimpleAppExt._
+
+ /**
+ * A non blocking synchronized queue using an immutable scala queue and monix's atomic class
+ */
+ private lazy val taskQueue2 = Atomic(Queue.empty[MyTask[_]])
+
+ private val tickSubject =
+ ConcurrentSubject[Float](multicast = MulticastStrategy.publish)(
+ schedulers.async
+ )
+
+ def tickObservable: Observable[Float] = tickSubject
+
+ override def simpleInitApp(): Unit = {}
+
+ override def simpleUpdate(tpf: Float): Unit = {
+ tickSubject.onNext(tpf)
+ }
+
+ override def stop(): Unit = {
+ tickSubject.onComplete()
+ super.stop()
+ }
+
+ def enqueueScala[T](cb: () => T): CancelableFuture[T] = {
+ val p = Promise[T]()
+ taskQueue2.transform(_ :+ MyTask(p, cb))
+ p.future
+ }
+
+ def enqueueL[T](cb: () => T): Task[T] =
+ Task.deferFuture(enqueueScala(cb))
+
+ override protected def runQueuedTasks(): Unit = {
+ taskQueue2.transform { current =>
+ current.dequeueOption.fold(current) {
+ case (MyTask(p, cb), updated) =>
+ p.success(cb())
+ updated
+ }
+ }
+
+ super.runQueuedTasks()
+ }
+
+ object JMEExecutorService extends GUIExecutorService {
+ override def execute(command: Runnable): Unit =
+ enqueueScala(() => command.run())
+ // enqueue(command)
+ // new SingleThreadEventExecutor()
+ // sys.addShutdownHook(JMEExecutorService.shutdown())
+ }
+
+ lazy val scheduler = Scheduler(JMEExecutorService)
+}
+object SimpleAppExt {
+ private[game] case class MyTask[T](p: Promise[T], cb: () => T)
+}
+
+// val ship = ed.createEntity()
+// val mbState = stateManager().state[EntityDataState]().map(_.getEntityData())
+// val mbState = Try(
+// stateManager()
+// .state[TestAppState]()
+// .entity
+// ).toOption.flatten.toRight(println("empty"))
+// // .flatMap(_.entity)
+// val x = mbState.flatMap(
+// _.query
+// .filter[TestComponent]("name", new Object())
+// // .filterOr[TestEntity](
+// // Filters
+// // .fieldEquals(classOf[TestEntity], "", null)
+// // )
+// .component[Tag]()
+// .component[TestComponent]()
+// .result
+// .toRight(println("failed"))
+// )
+
+// rootNode
+// .child(geom)
+// .child(geom)
+// .child(geom)
+// .child(geom)
+// .child(geom)
+// .child(geom)
+// .child(geom)
+// .child(geom)
+// Future(println("hello"))(jmeEC(this))
+// val wbActor: Future[ActorRef[Greeter.Greet]] = actorSystem.ask(
+// SpawnProtocol.Spawn(
+// behavior = Greeter(),
+// name = "listener",
+// DispatcherSelector.fromConfig("jme-dispatcher"),
+// _
+// )
+// )
+
+// wbActor.map(a => a.ask(Greeter.Greet("hello", _)).map(println))
+
+// Task(Promise[T]()).flatMap { p =>
+// Task(taskQueue2.transform(_ :+ MyTask(p, cb))) >>
+// Task.fromCancelablePromise(p)
+// }
+// Task.fromCancelablePromise {
+// val p = Promise[T]()
+// taskQueue2.transform(_ :+ MyTask(p, cb))
+// p
+// }
diff --git a/src/main/scala/wow/doge/mygame/game/entities/NpcActorSupervisor.scala b/src/main/scala/wow/doge/mygame/game/entities/NpcActorSupervisor.scala
new file mode 100644
index 0000000..dd97885
--- /dev/null
+++ b/src/main/scala/wow/doge/mygame/game/entities/NpcActorSupervisor.scala
@@ -0,0 +1,225 @@
+package wow.doge.mygame.game.entities
+
+import akka.actor.typed.ActorRef
+import akka.actor.typed.Behavior
+import akka.actor.typed.SupervisorStrategy
+import akka.actor.typed.scaladsl.ActorContext
+import akka.actor.typed.scaladsl.Behaviors
+import wow.doge.mygame.subsystems.events.Event
+import wow.doge.mygame.subsystems.events.EventBus
+import wow.doge.mygame.subsystems.events.EventsModule.GameEventBus
+import wow.doge.mygame.subsystems.events.TickEvent
+import wow.doge.mygame.subsystems.events.TickEvent.RenderTick
+import wow.doge.mygame.subsystems.movement.ImMovementActor
+import wow.doge.mygame.subsystems.events.EntityMovementEvent
+import wow.doge.mygame.subsystems.events.EntityMovementEvent.MovedLeft
+import wow.doge.mygame.subsystems.events.EntityMovementEvent.MovedUp
+import wow.doge.mygame.subsystems.events.EntityMovementEvent.MovedRight
+import wow.doge.mygame.subsystems.events.EntityMovementEvent.MovedDown
+import wow.doge.mygame.math.ImVector3f
+import wow.doge.mygame.game.subsystems.movement.CanMove
+import wow.doge.mygame.implicits._
+import akka.util.Timeout
+import scala.concurrent.duration._
+import scala.util.Success
+import scala.util.Failure
+
+object NpcActorSupervisor {
+ sealed trait Command
+ case class Move(pos: ImVector3f) extends Command
+ private case class UpdatePosition(pos: ImVector3f) extends Command
+ private case class LogError(err: Throwable) extends Command
+ case object MovementTick extends Command
+
+ final case class Props(
+ npcMovementActorBehavior: Behavior[NpcMovementActor2.Command],
+ npcName: String,
+ initialPos: ImVector3f
+ ) {
+ def create =
+ Behaviors.setup[Command] { ctx =>
+ val npcMovementActor = ctx.spawn(
+ (npcMovementActorBehavior),
+ s"npc-${npcName}-NpcMovementActor"
+ )
+
+ new NpcActorSupervisor(ctx, this)
+ .idle(State(npcMovementActor, initialPos))
+ }
+ }
+ final case class State(
+ npcMovementActor: ActorRef[NpcMovementActor2.Command],
+ currentPos: ImVector3f
+ )
+}
+class NpcActorSupervisor(
+ ctx: ActorContext[NpcActorSupervisor.Command],
+ props: NpcActorSupervisor.Props
+) {
+ import NpcActorSupervisor._
+ implicit val timeout = Timeout(1.second)
+ def idle(state: State): Behavior[NpcActorSupervisor.Command] =
+ Behaviors.receiveMessage[Command] {
+ case Move(pos) => {
+ state.npcMovementActor ! NpcMovementActor2.Move(pos)
+ val movementTimer = ctx.spawn(
+ GenericTimerActor.Props(ctx.self, MovementTick, 100.millis).create,
+ s"npc-${props.npcName}-NpcActorTimer"
+ )
+ movementTimer ! GenericTimerActor.Start
+ moving(state, pos, movementTimer)
+ }
+ case LogError(err) =>
+ ctx.log.warn(err.getMessage())
+ Behaviors.same
+ case _ => Behaviors.unhandled
+ }
+
+ def moving(
+ state: State,
+ targetPos: ImVector3f,
+ movementTimer: ActorRef[GenericTimerActor.Command]
+ ): Behavior[NpcActorSupervisor.Command] =
+ Behaviors.receiveMessagePartial[Command] {
+ case LogError(err) =>
+ ctx.log.warn(err.getMessage())
+ Behaviors.same
+ case Move(pos) => moving(state, pos, movementTimer)
+ case UpdatePosition(pos) =>
+ ctx.log.trace("Current pos = " + state.currentPos.toString())
+ moving(state.copy(currentPos = pos), targetPos, movementTimer)
+ case MovementTick =>
+ val dst = ImVector3f.dst(targetPos, state.currentPos)
+ if (dst <= 10f) {
+ state.npcMovementActor ! NpcMovementActor2.StopMoving
+ movementTimer ! GenericTimerActor.Stop
+ idle(state)
+ } else {
+ // ctx.log.debug("Difference = " + dst.toString())
+ // ctx.log.debug("Current pos = " + state.currentPos.toString())
+
+ ctx.ask(state.npcMovementActor, NpcMovementActor2.AskPosition(_)) {
+ case Success(value) =>
+ UpdatePosition(value)
+ case Failure(exception) => LogError(exception)
+ }
+ // Behaviors.same
+ moving(state, targetPos, movementTimer)
+ }
+ }
+}
+
+object NpcMovementActor2 {
+ sealed trait Command
+ case class AskPosition(replyTo: ActorRef[ImVector3f]) extends Command
+ case object StopMoving extends Command
+ case class Move(target: ImVector3f) extends Command
+
+ final class Props[T: CanMove](
+ val enqueueR: Function1[() => Unit, Unit],
+ val initialPos: ImVector3f,
+ val tickEventBus: GameEventBus[TickEvent],
+ val movable: T
+ ) {
+ def create =
+ Behaviors.setup[Command] { ctx =>
+ new NpcMovementActor2(ctx, this).receive(State(initialPos))
+ }
+ }
+
+ final case class State(currentPos: ImVector3f)
+}
+class NpcMovementActor2[T](
+ ctx: ActorContext[NpcMovementActor2.Command],
+ props: NpcMovementActor2.Props[T]
+) {
+ import NpcMovementActor2._
+ def receive(
+ state: State
+ )(implicit cm: CanMove[T]): Behavior[NpcMovementActor2.Command] =
+ Behaviors.receiveMessage[Command] {
+ case AskPosition(replyTo) =>
+ replyTo ! cm.location(props.movable)
+ Behaviors.same
+ case Move(target: ImVector3f) =>
+ props.enqueueR(() =>
+ cm.move(props.movable, (target - state.currentPos) * 0.005f)
+ )
+ receive(state = state.copy(currentPos = cm.location(props.movable)))
+ case StopMoving =>
+ ctx.log.debug(
+ "Position at Stop = " + cm.location(props.movable).toString
+ )
+ props.enqueueR(() => cm.stop(props.movable))
+ receive(state = state.copy(currentPos = cm.location(props.movable)))
+ }
+}
+
+object NpcMovementActor {
+ sealed trait Command
+ final case class Props(
+ imMovementActorBehavior: Behavior[ImMovementActor.Command],
+ npcName: String,
+ // movementActor: ActorRef[ImMovementActor.Command],
+ mainEventBus: ActorRef[
+ EventBus.Command[Event]
+ ],
+ tickEventBus: GameEventBus[TickEvent]
+ ) {
+
+ def create: Behavior[Command] =
+ Behaviors.setup { ctx =>
+ val movementActor = ctx.spawn(
+ Behaviors
+ .supervise(imMovementActorBehavior)
+ .onFailure[Exception](SupervisorStrategy.restart),
+ s"npc-${npcName}-MovementActorChild"
+ )
+ val npcMovementElBehavior = Behaviors.receiveMessagePartial[Event] {
+ case event: EntityMovementEvent =>
+ event match {
+ case MovedLeft(name, pressed) =>
+ if (name == npcName)
+ movementActor ! ImMovementActor.MovedLeft(pressed)
+ Behaviors.same
+ case MovedUp(name, pressed) =>
+ if (name == npcName)
+ movementActor ! ImMovementActor.MovedUp(pressed)
+ Behaviors.same
+ case MovedRight(name, pressed) =>
+ if (name == npcName)
+ movementActor ! ImMovementActor.MovedRight(pressed)
+ Behaviors.same
+ case MovedDown(name, pressed) =>
+ if (name == npcName)
+ movementActor ! ImMovementActor.MovedDown(pressed)
+ Behaviors.same
+ }
+ }
+
+ val npcMovementEl = ctx.spawn(
+ Behaviors
+ .supervise(npcMovementElBehavior)
+ .onFailure[Exception](SupervisorStrategy.restart),
+ s"npc-${npcName}-MovementEventHandler"
+ )
+ val renderTickElBehavior =
+ Behaviors.receiveMessage[RenderTick.type] {
+ case RenderTick =>
+ movementActor ! ImMovementActor.Tick
+ Behaviors.same
+ }
+
+ val renderTickEl =
+ ctx.spawn(
+ renderTickElBehavior,
+ s"npc-${npcName}-MovementTickListener"
+ )
+
+ mainEventBus ! EventBus.Subscribe(npcMovementEl)
+ tickEventBus ! EventBus.Subscribe(renderTickEl)
+ Behaviors.receiveMessage { msg => Behaviors.same }
+ }
+
+ }
+}
diff --git a/src/main/scala/wow/doge/mygame/game/nodes/PlayerActorSupervisor.scala b/src/main/scala/wow/doge/mygame/game/entities/player/PlayerActorSupervisor.scala
similarity index 54%
rename from src/main/scala/wow/doge/mygame/game/nodes/PlayerActorSupervisor.scala
rename to src/main/scala/wow/doge/mygame/game/entities/player/PlayerActorSupervisor.scala
index 1648ea4..0863763 100644
--- a/src/main/scala/wow/doge/mygame/game/nodes/PlayerActorSupervisor.scala
+++ b/src/main/scala/wow/doge/mygame/game/entities/player/PlayerActorSupervisor.scala
@@ -1,6 +1,7 @@
-package wow.doge.mygame.game.nodes
+package wow.doge.mygame.game.entities
import scala.concurrent.duration._
+import scala.util.Random
import akka.actor.typed.ActorRef
import akka.actor.typed.Behavior
@@ -9,26 +10,27 @@ 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.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.subsystems.events.EntityMovementEvent
-import wow.doge.mygame.subsystems.events.EntityMovementEvent.PlayerMovementEvent
+import wow.doge.mygame.subsystems.events.EventBus
+import wow.doge.mygame.subsystems.events.EventsModule.GameEventBus
import wow.doge.mygame.subsystems.events.PlayerCameraEvent
+import wow.doge.mygame.subsystems.events.PlayerMovementEvent
+import wow.doge.mygame.subsystems.events.TickEvent
+import wow.doge.mygame.subsystems.events.TickEvent.RenderTick
import wow.doge.mygame.subsystems.movement.ImMovementActor
object PlayerActorSupervisor {
sealed trait Command
-
final case class Props(
- enqueueR: Function1[() => Unit, Unit],
- camNode: CameraNode,
playerMovementEventBus: ActorRef[
EventBus.Command[PlayerMovementEvent]
],
- playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]]
+ playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]],
+ tickEventBus: GameEventBus[TickEvent],
+ imMovementActorBehavior: Behavior[ImMovementActor.Command],
+ playerCamELBehavior: Behavior[PlayerCameraEvent]
) {
def create[T: CanMove](movable: T) =
Behaviors.logMessages(
@@ -44,59 +46,40 @@ object PlayerActorSupervisor {
lazy val movementActor =
ctx.spawn(
Behaviors
- .supervise(
- ImMovementActor
- .Props(enqueueR, movable, playerMovementEventBus)
- .create
- )
+ .supervise(imMovementActorBehavior)
.onFailure[Exception](SupervisorStrategy.restart),
- "playerMovementActor"
+ "playerMovementActorChild"
)
- lazy val playerMovementEventHandler = ctx.spawn(
- Behaviors
- .supervise(PlayerMovementEventListener(movementActor))
- .onFailure[Exception](SupervisorStrategy.restart),
- "playerMovementEventHandler"
+ ctx.spawn(
+ PlayerMovementActor
+ .Props(movementActor, playerMovementEventBus, tickEventBus)
+ .create,
+ "playerMovementAcor"
)
- lazy val movementActorTimer = ctx.spawn(
- Behaviors
- .supervise(MovementActorTimer(movementActor))
- .onFailure[Exception](SupervisorStrategy.restart),
- "playerMovementActorTimer"
- )
-
lazy val playerCameraHandler = {
ctx.spawn(
Behaviors
- .supervise(
- PlayerCameraEventListener(camNode, enqueueR)
- )
+ .supervise(playerCamELBehavior)
.onFailure[Exception](SupervisorStrategy.restart),
"playerCameraHandler"
)
}
//init actors
- movementActorTimer ! MovementActorTimer.Start
- playerMovementEventBus ! EventBus.Subscribe(
- playerMovementEventHandler
- )
playerCameraEventBus ! EventBus.Subscribe(playerCameraHandler)
new PlayerActorSupervisor(
ctx,
this,
- Children(movementActor, playerMovementEventHandler)
+ Children(movementActor)
).receive
}
)
+
}
case class Children(
- movementActor: ActorRef[ImMovementActor.Command],
- playerMovementEventHandler: ActorRef[
- EntityMovementEvent.PlayerMovementEvent
- ]
+ movementActor: ActorRef[ImMovementActor.Command]
)
}
class PlayerActorSupervisor[T: CanMove](
@@ -113,47 +96,40 @@ class PlayerActorSupervisor[T: CanMove](
}
}
-object MovementActorTimer {
+object PlayerMovementActor {
sealed trait Command
- final case object Start extends Command
- final case object Stop extends Command
- private case object Send extends Command
- case object TimerKey
+ final case class Props(
+ movementActor: ActorRef[ImMovementActor.Command],
+ playerMovementEventBus: ActorRef[
+ EventBus.Command[PlayerMovementEvent]
+ ],
+ tickEventBus: GameEventBus[TickEvent]
+ ) {
- def apply(target: ActorRef[ImMovementActor.Command]) =
- Behaviors.withTimers[Command] { timers =>
- new MovementActorTimer(timers, target).idle
- }
-}
-class MovementActorTimer(
- timers: TimerScheduler[MovementActorTimer.Command],
- target: ActorRef[ImMovementActor.Command]
-) {
- import MovementActorTimer._
+ def create: Behavior[Command] =
+ Behaviors.setup { ctx =>
+ val playerMovementEl = ctx.spawn(
+ Behaviors
+ .supervise(PlayerMovementEventListener(movementActor))
+ .onFailure[Exception](SupervisorStrategy.restart),
+ "playerMovementEventHandler"
+ )
+ val renderTickElBehavior =
+ Behaviors.receiveMessage[RenderTick.type] {
+ case RenderTick =>
+ movementActor ! ImMovementActor.Tick
+ Behaviors.same
+ }
+ val renderTickEl =
+ ctx.spawn(renderTickElBehavior, "playerMovementTickListener")
- val idle: Behavior[Command] =
- Behaviors.receiveMessage { msg =>
- msg match {
- case Start =>
- timers.startTimerWithFixedDelay(TimerKey, Send, (60f / 144).millis)
- active
- case _ => Behaviors.unhandled
+ playerMovementEventBus ! EventBus.Subscribe(
+ playerMovementEl
+ )
+ tickEventBus ! EventBus.Subscribe(renderTickEl)
+ Behaviors.receiveMessage { msg => Behaviors.same }
}
- }
-
- val active: Behavior[Command] =
- Behaviors.receiveMessage { msg =>
- msg match {
- case Send =>
- target ! ImMovementActor.Tick
- Behaviors.same
- case Stop =>
- timers.cancel(TimerKey)
- idle
- case _ => Behaviors.unhandled
-
- }
- }
+ }
}
object GenericTimerActor {
@@ -161,7 +137,7 @@ object GenericTimerActor {
final case object Start extends Command
final case object Stop extends Command
private case object Send extends Command
- case object TimerKey
+ case class TimerKey(seed: Long)
case class Props[T](
target: ActorRef[T],
@@ -169,12 +145,13 @@ object GenericTimerActor {
timeInterval: FiniteDuration
) {
val create = Behaviors.withTimers[Command] { timers =>
- new GenericTimerActor(timers, this).idle
+ new GenericTimerActor(timers, TimerKey(Random.nextLong()), this).idle
}
}
}
class GenericTimerActor[T](
timers: TimerScheduler[GenericTimerActor.Command],
+ timerKey: GenericTimerActor.TimerKey,
props: GenericTimerActor.Props[T]
) {
import GenericTimerActor._
@@ -182,7 +159,7 @@ class GenericTimerActor[T](
val idle: Behavior[Command] =
Behaviors.receiveMessage {
case Start =>
- timers.startTimerWithFixedDelay(TimerKey, Send, props.timeInterval)
+ timers.startTimerWithFixedDelay(timerKey, Send, props.timeInterval)
active
case _ => Behaviors.unhandled
@@ -194,7 +171,7 @@ class GenericTimerActor[T](
props.target ! props.messageToSend
Behaviors.same
case Stop =>
- timers.cancel(TimerKey)
+ timers.cancel(timerKey)
idle
}
}
diff --git a/src/main/scala/wow/doge/mygame/game/nodes/PlayerCameraActor.scala b/src/main/scala/wow/doge/mygame/game/entities/player/PlayerCameraActor.scala
similarity index 94%
rename from src/main/scala/wow/doge/mygame/game/nodes/PlayerCameraActor.scala
rename to src/main/scala/wow/doge/mygame/game/entities/player/PlayerCameraActor.scala
index 5b3657f..0b3b966 100644
--- a/src/main/scala/wow/doge/mygame/game/nodes/PlayerCameraActor.scala
+++ b/src/main/scala/wow/doge/mygame/game/entities/player/PlayerCameraActor.scala
@@ -1,4 +1,4 @@
-package wow.doge.mygame.game.nodes
+package wow.doge.mygame.game.entities
import akka.actor.typed.scaladsl.ActorContext
import akka.actor.typed.scaladsl.Behaviors
diff --git a/src/main/scala/wow/doge/mygame/game/entities/player/PlayerController.scala b/src/main/scala/wow/doge/mygame/game/entities/player/PlayerController.scala
new file mode 100644
index 0000000..e22ca0e
--- /dev/null
+++ b/src/main/scala/wow/doge/mygame/game/entities/player/PlayerController.scala
@@ -0,0 +1,248 @@
+package wow.doge.mygame.game.entities
+
+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.implicits._
+import com.jme3.asset.AssetManager
+import com.jme3.bullet.BulletAppState
+import com.jme3.bullet.PhysicsSpace
+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.scene.Node
+import com.jme3.scene.control.CameraControl.ControlDirection
+import com.jme3.scene.shape.Box
+import com.softwaremill.macwire._
+import com.softwaremill.tagging._
+import io.odin.Logger
+import monix.bio.IO
+import monix.bio.Task
+import wow.doge.mygame.game.GameAppTags
+import wow.doge.mygame.game.SimpleAppExt
+import wow.doge.mygame.implicits._
+import wow.doge.mygame.math.ImVector3f
+import wow.doge.mygame.state.MyMaterial
+import wow.doge.mygame.subsystems.events.EventBus
+import wow.doge.mygame.subsystems.events.EventsModule.GameEventBus
+import wow.doge.mygame.subsystems.events.PlayerCameraEvent
+import wow.doge.mygame.subsystems.events.PlayerMovementEvent
+import wow.doge.mygame.subsystems.events.TickEvent
+import wow.doge.mygame.subsystems.movement.ImMovementActor
+import wow.doge.mygame.utils.AkkaUtils
+
+object PlayerControllerTags {
+ sealed trait PlayerTag
+ sealed trait PlayerCameraNode
+}
+
+object PlayerController {
+ sealed trait Error
+ case class CouldNotCreatePlayerNode(reason: String) extends Error
+ case class GenericError(reason: String) extends Error
+
+ class Props(
+ enqueueR: Function1[() => Unit, Unit],
+ rootNode: Node @@ GameAppTags.RootNode,
+ loggerL: Logger[Task],
+ physicsSpace: PhysicsSpace,
+ initialPlayerPos: ImVector3f = ImVector3f.ZERO,
+ spawnProtocol: ActorRef[SpawnProtocol.Command],
+ playerMovementEventBus: ActorRef[
+ EventBus.Command[PlayerMovementEvent]
+ ],
+ playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]],
+ playerPhysicsControl: BetterCharacterControl,
+ appScheduler: monix.execution.Scheduler,
+ playerNode: Node @@ PlayerControllerTags.PlayerTag,
+ cameraNode: CameraNode @@ PlayerControllerTags.PlayerCameraNode,
+ tickEventBus: GameEventBus[TickEvent]
+ )(implicit timeout: Timeout, scheduler: Scheduler) {
+ val create: IO[Error, Unit] =
+ (for {
+ playerActor <- AkkaUtils.spawnActorL(
+ spawnProtocol,
+ "playerActorSupervisor",
+ new PlayerActorSupervisor.Props(
+ playerMovementEventBus,
+ playerCameraEventBus,
+ tickEventBus,
+ ImMovementActor
+ .Props(enqueueR, playerPhysicsControl)
+ .create,
+ wireWith(PlayerCameraEventListener.apply _)
+ ).create(playerPhysicsControl)
+ )
+ _ <- IO {
+ physicsSpace += playerNode
+ physicsSpace += playerPhysicsControl
+ }
+ _ <- Task(rootNode += playerNode)
+ } yield ())
+ .onErrorHandleWith(e => IO.raiseError(GenericError(e.getMessage())))
+ .executeOn(appScheduler)
+ }
+
+ def apply(
+ app: SimpleAppExt,
+ modelPath: os.RelPath,
+ cam: Camera
+ )(assetManager: AssetManager, bulletAppState: BulletAppState) = {
+ lazy val playerPos = ImVector3f.ZERO
+ lazy val playerPhysicsControl = new BetterCharacterControl(1.5f, 6f, 1f)
+ .withJumpForce(ImVector3f(0, 5f, 0))
+ lazy val playerNode = new Node("PlayerNode")
+ .withChildren(
+ assetManager
+ .loadModel(modelPath)
+ .asInstanceOf[Node]
+ .withRotate(0, FastMath.PI, 0)
+ )
+ .withLocalTranslation(playerPos)
+ .withControl(playerPhysicsControl)
+
+ {
+ bulletAppState.physicsSpace += playerNode
+ bulletAppState.physicsSpace += playerPhysicsControl
+ }
+
+ {
+ app.rootNode += playerNode
+ }
+
+ playerPhysicsControl
+ }
+
+ object Defaults {
+ def defaultMesh = {
+ val b = Box(1, 1, 1)
+ val geom = Geometry("playerGeom", b)
+ geom
+ }
+ def defaultTexture(assetManager: AssetManager) =
+ MyMaterial(
+ assetManager = assetManager,
+ path = os.rel / "Common" / "MatDefs" / "Misc" / "Unshaded.j3md"
+ )
+
+ def defaultCamerNode(cam: Camera, playerPos: ImVector3f) =
+ new CameraNode("CameraNode", cam)
+ .withControlDir(ControlDirection.SpatialToCamera)
+ .withLocalTranslation(ImVector3f(0, 1.5f, 10))
+ .withLookAt(playerPos, ImVector3f.UNIT_Y)
+
+ def defaultPlayerNode(
+ assetManager: AssetManager,
+ modelPath: os.RelPath,
+ playerPos: ImVector3f,
+ camNode: CameraNode,
+ playerPhysicsControl: BetterCharacterControl
+ ) =
+ Either
+ .catchNonFatal(
+ Node("PlayerNode")
+ .withChildren(
+ camNode,
+ assetManager
+ .loadModel(modelPath)
+ .asInstanceOf[Node]
+ .withRotate(0, FastMath.PI, 0)
+ )
+ .withLocalTranslation(playerPos)
+ .withControl(playerPhysicsControl)
+ )
+ .map(_.taggedWith[PlayerControllerTags.PlayerTag])
+ .leftMap(e => PlayerController.CouldNotCreatePlayerNode(e.getMessage()))
+
+ def defaultNpcNode(
+ assetManager: AssetManager,
+ // modelPath: os.RelPath,
+ initialPos: ImVector3f,
+ npcPhysicsControl: BetterCharacterControl,
+ npcName: String
+ ) =
+ Either
+ .catchNonFatal(
+ Node(npcName)
+ .withChildren(
+ // assetManager
+ // .loadModel(modelPath)
+ // .asInstanceOf[Node]
+ // .withRotate(0, FastMath.PI, 0)
+ defaultMesh.withMaterial(defaultTexture(assetManager))
+ )
+ .withLocalTranslation(initialPos)
+ .withControl(npcPhysicsControl)
+ )
+ // .map(_.taggedWith[PlayerControllerTags.PlayerTag])
+ // .leftMap(e => PlayerController.CouldNotCreatePlayerNode(e.getMessage()))
+
+ def defaultPlayerPhysicsControl =
+ new BetterCharacterControl(1.5f, 6f, 1f)
+ .withJumpForce(ImVector3f(0, 5f, 0))
+ }
+}
+
+object Methods {
+ def spawnMovementActor(
+ enqueueR: Function1[() => Unit, Unit],
+ spawnProtocol: ActorRef[SpawnProtocol.Command],
+ movable: BetterCharacterControl @@ PlayerControllerTags.PlayerTag,
+ playerMovementEventBus: ActorRef[
+ EventBus.Command[PlayerMovementEvent]
+ ],
+ loggerL: Logger[Task]
+ )(implicit timeout: Timeout, scheduler: Scheduler) =
+ spawnProtocol.askL[ActorRef[ImMovementActor.Command]](
+ SpawnProtocol.Spawn(
+ ImMovementActor.Props(enqueueR, movable).create,
+ "imMovementActor",
+ Props.empty,
+ _
+ )
+ )
+ // def spawnPlayerActor(
+ // app: GameApp,
+ // spawnProtocol: ActorRef[SpawnProtocol.Command],
+ // movable: BetterCharacterControl @@ Player,
+ // playerMovementEventBus: ActorRef[
+ // EventBus.Command[PlayerMovementEvent]
+ // ]
+ // )(implicit timeout: Timeout, scheduler: Scheduler) =
+ // spawnProtocol.askL[ActorRef[PlayerActorSupervisor.Command]](
+ // SpawnProtocol.Spawn(
+ // new PlayerActorSupervisor.Props(
+ // app,
+ // movable,
+ // playerMovementEventBus
+ // ).create,
+ // "playerActor",
+ // Props.empty,
+ // _
+ // )
+ // )
+}
+
+// camNode <- IO(
+// _cameraNode.getOrElse(defaultCamerNode(camera, initialPlayerPos))
+// )
+// playerPhysicsControl <- IO(
+// _playerPhysicsControl
+// .getOrElse(defaultPlayerPhysicsControl)
+// .taggedWith[PlayerTag]
+// )
+// playerNode <- IO.fromEither(
+// _playerNode.fold(
+// defaultPlayerNode(
+// assetManager,
+// modelPath,
+// initialPlayerPos,
+// camNode,
+// playerPhysicsControl
+// )
+// )(_.asRight)
+// )
diff --git a/src/main/scala/wow/doge/mygame/game/nodes/PlayerEventListeners.scala b/src/main/scala/wow/doge/mygame/game/entities/player/PlayerEventListeners.scala
similarity index 91%
rename from src/main/scala/wow/doge/mygame/game/nodes/PlayerEventListeners.scala
rename to src/main/scala/wow/doge/mygame/game/entities/player/PlayerEventListeners.scala
index 2b49910..9389198 100644
--- a/src/main/scala/wow/doge/mygame/game/nodes/PlayerEventListeners.scala
+++ b/src/main/scala/wow/doge/mygame/game/entities/player/PlayerEventListeners.scala
@@ -1,4 +1,4 @@
-package wow.doge.mygame.game.nodes
+package wow.doge.mygame.game.entities
import akka.actor.typed.ActorRef
import akka.actor.typed.LogOptions
@@ -6,10 +6,10 @@ import akka.actor.typed.scaladsl.Behaviors
import com.jme3.scene.CameraNode
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.events.PlayerMovementEvent
import wow.doge.mygame.subsystems.movement.ImMovementActor
object PlayerMovementEventListener {
@@ -39,11 +39,9 @@ object PlayerMovementEventListener {
movementActor ! ImMovementActor.Jump
Behaviors.same
case PlayerRotatedRight =>
- // ctx.log.warn("right rotate not implemented yet")
movementActor ! ImMovementActor.RotateRight
Behaviors.same
case PlayerRotatedLeft =>
- // ctx.log.warn("left rotate not implemented yet")
movementActor ! ImMovementActor.RotateLeft
Behaviors.same
case PlayerCameraUp =>
diff --git a/src/main/scala/wow/doge/mygame/game/nodes/PlayerController.scala b/src/main/scala/wow/doge/mygame/game/nodes/PlayerController.scala
deleted file mode 100644
index 2dcc339..0000000
--- a/src/main/scala/wow/doge/mygame/game/nodes/PlayerController.scala
+++ /dev/null
@@ -1,222 +0,0 @@
-package wow.doge.mygame.game.nodes
-
-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.scene.Node
-import com.jme3.scene.control.CameraControl.ControlDirection
-import com.jme3.scene.shape.Box
-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 wow.doge.mygame.state.MyMaterial
-import wow.doge.mygame.subsystems.events.EntityMovementEvent.PlayerMovementEvent
-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) {}
-sealed trait PlayerTag
-sealed trait PlayerCameraNode
-
-object PlayerController {
- sealed trait Error
- case class GenericError(reason: String) extends Error
-
- class Props(
- enqueueR: Function1[() => Unit, Unit],
- rootNode: Ref[Task, Node],
- camera: Camera,
- loggerL: Logger[Task],
- assetManager: AssetManager,
- bulletAppState: BulletAppState,
- initialPlayerPos: ImVector3f = ImVector3f.ZERO,
- modelPath: os.RelPath,
- spawnProtocol: ActorRef[SpawnProtocol.Command],
- playerMovementEventBus: ActorRef[
- EventBus.Command[PlayerMovementEvent]
- ],
- playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]],
- _playerPhysicsControl: Option[BetterCharacterControl],
- _playerNode: Option[Node with PlayerTag] = None,
- _cameraNode: Option[CameraNode with PlayerCameraNode] = None,
- appScheduler: monix.execution.Scheduler
- )(implicit timeout: Timeout, scheduler: Scheduler) {
- import Defaults._
- val create: IO[Error, Unit] =
- // IO.raiseError(GenericError("not implemented yet"))
- (for {
- camNode <- IO(
- _cameraNode.getOrElse(defaultCamerNode(camera, initialPlayerPos))
- )
- playerPhysicsControl <- IO(
- _playerPhysicsControl
- .getOrElse(defaultPlayerPhysicsControl)
- .taggedWith[PlayerTag]
- )
- playerNode <- IO.fromEither(
- _playerNode.fold(
- defaultPlayerNode(
- assetManager,
- modelPath,
- initialPlayerPos,
- camNode,
- playerPhysicsControl
- )
- )(_.asRight)
- )
- playerActor <- AkkaUtils.spawnActorL(
- spawnProtocol,
- "playerActorSupervisor",
- new PlayerActorSupervisor.Props(
- enqueueR,
- camNode,
- playerMovementEventBus,
- playerCameraEventBus
- ).create(playerPhysicsControl)
- )
- _ <- IO {
- bulletAppState.physicsSpace += playerNode
- bulletAppState.physicsSpace += playerPhysicsControl
- }
- _ <- rootNode.update(_ :+ playerNode)
- } yield ())
- .onErrorHandleWith(e => IO.raiseError(GenericError(e.getMessage())))
- .executeOn(appScheduler)
- }
-
- def apply(
- app: GameApp,
- modelPath: os.RelPath,
- cam: Camera
- )(assetManager: AssetManager, bulletAppState: BulletAppState) = {
- lazy val playerPos = ImVector3f.ZERO
- lazy val playerPhysicsControl = new BetterCharacterControl(1.5f, 6f, 1f)
- .withJumpForce(ImVector3f(0, 5f, 0))
- lazy val playerNode = new Node("PlayerNode")
- .withChildren(
- assetManager
- .loadModel(modelPath)
- .asInstanceOf[Node]
- .withRotate(0, FastMath.PI, 0)
- )
- .withLocalTranslation(playerPos)
- .withControl(playerPhysicsControl)
-
- {
- bulletAppState.physicsSpace += playerNode
- bulletAppState.physicsSpace += playerPhysicsControl
- }
-
- {
- app.rootNode += playerNode
- }
-
- playerPhysicsControl
- }
-}
-
-object Defaults {
- lazy val defaultMesh = {
- val b = Box(1, 1, 1)
- val geom = Geometry("playerMesh", b)
- geom
- }
- def defaultTexture(assetManager: AssetManager) =
- MyMaterial(
- assetManager = assetManager,
- path = os.rel / "Common" / "MatDefs" / "Misc" / "Unshaded.j3md"
- )
-
- def defaultCamerNode(cam: Camera, playerPos: ImVector3f) =
- new CameraNode("CameraNode", cam)
- .withControlDir(ControlDirection.SpatialToCamera)
- .withLocalTranslation(ImVector3f(0, 1.5f, 10))
- .withLookAt(playerPos, ImVector3f.UNIT_Y)
-
- def defaultPlayerNode(
- assetManager: AssetManager,
- modelPath: os.RelPath,
- playerPos: ImVector3f,
- camNode: CameraNode,
- playerPhysicsControl: BetterCharacterControl
- ) =
- Either.catchNonFatal(
- Node("PlayerNode")
- .withChildren(
- camNode,
- assetManager
- .loadModel(modelPath)
- .asInstanceOf[Node]
- .withRotate(0, FastMath.PI, 0)
- )
- .withLocalTranslation(playerPos)
- .withControl(playerPhysicsControl)
- )
-
- lazy val defaultPlayerPhysicsControl =
- new BetterCharacterControl(1.5f, 6f, 1f)
- .withJumpForce(ImVector3f(0, 5f, 0))
-}
-
-object Methods {
- def spawnMovementActor(
- enqueueR: Function1[() => Unit, Unit],
- spawnProtocol: ActorRef[SpawnProtocol.Command],
- movable: BetterCharacterControl @@ PlayerTag,
- playerMovementEventBus: ActorRef[
- EventBus.Command[PlayerMovementEvent]
- ],
- loggerL: Logger[Task]
- )(implicit timeout: Timeout, scheduler: Scheduler) =
- spawnProtocol.askL[ActorRef[ImMovementActor.Command]](
- SpawnProtocol.Spawn(
- ImMovementActor.Props(enqueueR, movable, playerMovementEventBus).create,
- "imMovementActor",
- Props.empty,
- _
- )
- )
- // def spawnPlayerActor(
- // app: GameApp,
- // spawnProtocol: ActorRef[SpawnProtocol.Command],
- // movable: BetterCharacterControl @@ Player,
- // playerMovementEventBus: ActorRef[
- // EventBus.Command[PlayerMovementEvent]
- // ]
- // )(implicit timeout: Timeout, scheduler: Scheduler) =
- // spawnProtocol.askL[ActorRef[PlayerActorSupervisor.Command]](
- // SpawnProtocol.Spawn(
- // new PlayerActorSupervisor.Props(
- // app,
- // movable,
- // playerMovementEventBus
- // ).create,
- // "playerActor",
- // Props.empty,
- // _
- // )
- // )
-}
-// spawnPlayerActor(
-// app,
-// spawnProtocol,
-// playerPhysicsControl,
-// playerMovementEventBus
-// )
diff --git a/src/main/scala/wow/doge/mygame/game/subsystems/ai/GdxAiTest.scala b/src/main/scala/wow/doge/mygame/game/subsystems/ai/GdxAiTest.scala
index 124a72d..a5765df 100644
--- a/src/main/scala/wow/doge/mygame/game/subsystems/ai/GdxAiTest.scala
+++ b/src/main/scala/wow/doge/mygame/game/subsystems/ai/GdxAiTest.scala
@@ -1,8 +1,13 @@
package wow.doge.mygame.game.subsystems.ai
+import scala.collection.immutable.ArraySeq
+
import com.badlogic.gdx.ai.pfa.Connection
import wow.doge.mygame.game.subsystems.ai.gdx.MyIndexedGraph
-import scala.collection.immutable.ArraySeq
+import com.badlogic.gdx.ai.steer.Steerable
+import com.badlogic.gdx.math.Vector3
+import com.badlogic.gdx.ai.utils.Location
+import com.badlogic.gdx.ai.steer.behaviors.Arrive
// import com.badlogic.gdx.ai.pfa.indexed.IndexedGraph
// import scala.jdk.javaapi.CollectionConverters._
@@ -31,3 +36,50 @@ class CityGraph extends MyIndexedGraph[City] {
override def getNodeCount(): Int = ???
}
+
+class MySteerable extends Steerable[Vector3] {
+ val arrive = new Arrive[Vector3](this)
+
+ override def getPosition(): Vector3 = ???
+
+ override def getOrientation(): Float = ???
+
+ override def setOrientation(x$1: Float): Unit = ???
+
+ override def vectorToAngle(x$1: Vector3): Float = ???
+
+ override def angleToVector(x$1: Vector3, x$2: Float): Vector3 = ???
+
+ override def newLocation(): Location[Vector3] = ???
+
+ override def getZeroLinearSpeedThreshold(): Float = ???
+
+ override def setZeroLinearSpeedThreshold(x$1: Float): Unit = ???
+
+ override def getMaxLinearSpeed(): Float = ???
+
+ override def setMaxLinearSpeed(x$1: Float): Unit = ???
+
+ override def getMaxLinearAcceleration(): Float = ???
+
+ override def setMaxLinearAcceleration(x$1: Float): Unit = ???
+
+ override def getMaxAngularSpeed(): Float = ???
+
+ override def setMaxAngularSpeed(x$1: Float): Unit = ???
+
+ override def getMaxAngularAcceleration(): Float = ???
+
+ override def setMaxAngularAcceleration(x$1: Float): Unit = ???
+
+ override def getLinearVelocity(): Vector3 = ???
+
+ override def getAngularVelocity(): Float = ???
+
+ override def getBoundingRadius(): Float = ???
+
+ override def isTagged(): Boolean = ???
+
+ override def setTagged(x$1: Boolean): Unit = ???
+
+}
diff --git a/src/main/scala/wow/doge/mygame/game/subsystems/input/GameInputHandler.scala b/src/main/scala/wow/doge/mygame/game/subsystems/input/GameInputHandler.scala
index b8457d7..82379ec 100644
--- a/src/main/scala/wow/doge/mygame/game/subsystems/input/GameInputHandler.scala
+++ b/src/main/scala/wow/doge/mygame/game/subsystems/input/GameInputHandler.scala
@@ -9,20 +9,20 @@ 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.EventBus
+import wow.doge.mygame.subsystems.events.EventsModule.GameEventBus
import wow.doge.mygame.subsystems.events.PlayerCameraEvent
+import wow.doge.mygame.subsystems.events.PlayerMovementEvent
import wow.doge.mygame.utils.IOUtils._
object GameInputHandler {
final case class Props(
inputManager: InputManager,
- playerMovementEventBus: ActorRef[
- EventBus.Command[PlayerMovementEvent]
- ],
- playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]]
+ playerMovementEventBus: GameEventBus[PlayerMovementEvent],
+ playerCameraEventBus: GameEventBus[PlayerCameraEvent]
+ // tickEventBus: GameEventBus[TickEvent]
) {
def begin =
for {
@@ -66,12 +66,12 @@ object GameInputHandler {
def setupKeys(inputManager: InputManager) =
inputManager
.withMapping(
- PlayerAnalogInput.TurnRight.entryName,
+ PlayerAnalogMovementInput.TurnRight.entryName,
new KeyTrigger(KeyInput.KEY_RIGHT),
new MouseAxisTrigger(MouseInput.AXIS_X, true)
)
.withMapping(
- PlayerAnalogInput.TurnLeft.entryName,
+ PlayerAnalogMovementInput.TurnLeft.entryName,
new KeyTrigger(KeyInput.KEY_LEFT),
new MouseAxisTrigger(MouseInput.AXIS_X, false)
)
@@ -85,7 +85,6 @@ object GameInputHandler {
// new KeyTrigger(KeyInput.KEY_LEFT),
new MouseAxisTrigger(MouseInput.AXIS_Y, true)
)
- .setCursorVisible(false)
def generateMovementInputEvents(
inputManager: InputManager,
@@ -148,19 +147,18 @@ object GameInputHandler {
) = {
val name = "rotateMovementEventsGenerator"
inputManager
- .enumAnalogObservable(PlayerAnalogInput)
+ .enumAnalogObservable(PlayerAnalogMovementInput)
.sample(1.millis)
- // .map(e => e)
.doOnNext(analogEvent =>
analogEvent.binding match {
- case PlayerAnalogInput.TurnRight =>
+ case PlayerAnalogMovementInput.TurnRight =>
toTask(
playerMovementEventBus !! EventBus.Publish(
PlayerMovementEvent.PlayerRotatedRight,
name
)
)
- case PlayerAnalogInput.TurnLeft =>
+ case PlayerAnalogMovementInput.TurnLeft =>
toTask(
playerMovementEventBus !! EventBus.Publish(
PlayerMovementEvent.PlayerRotatedLeft,
@@ -179,7 +177,7 @@ object GameInputHandler {
inputManager
.analogObservable("CAMERA_UP", "CAMERA_DOWN")
.sample(1.millis)
- .mapEval(analogEvent =>
+ .doOnNext(analogEvent =>
analogEvent.binding.name match {
case "CAMERA_UP" =>
toTask(
diff --git a/src/main/scala/wow/doge/mygame/game/subsystems/input/InputConstant.scala b/src/main/scala/wow/doge/mygame/game/subsystems/input/InputConstant.scala
deleted file mode 100644
index 939114d..0000000
--- a/src/main/scala/wow/doge/mygame/game/subsystems/input/InputConstant.scala
+++ /dev/null
@@ -1,9 +0,0 @@
-package wow.doge.mygame.game.subsystems.input
-
-object InputConstants {
- val PLAYER_MOVE_LEFT = "PLAYER_MOVE_LEFT"
- val PLAYER_MOVE_RIGHT = "PLAYER_MOVE_RIGHT"
- val PLAYER_MOVE_FORWARD = "PLAYER_MOVE_FORWARD"
- val PLAYER_MOVE_BACKWARD = "PLAYER_MOVE_BACKWARD"
- val PLAYER_JUMP = "PLAYER_JUMP "
-}
diff --git a/src/main/scala/wow/doge/mygame/game/subsystems/input/InputEnums.scala b/src/main/scala/wow/doge/mygame/game/subsystems/input/InputEnums.scala
index 327ffca..3292220 100644
--- a/src/main/scala/wow/doge/mygame/game/subsystems/input/InputEnums.scala
+++ b/src/main/scala/wow/doge/mygame/game/subsystems/input/InputEnums.scala
@@ -12,9 +12,9 @@ object PlayerMovementInput extends Enum[PlayerMovementInput] {
case object Jump extends PlayerMovementInput
}
-sealed trait PlayerAnalogInput extends EnumEntry with UpperSnakecase
-object PlayerAnalogInput extends Enum[PlayerAnalogInput] {
+sealed trait PlayerAnalogMovementInput extends EnumEntry with UpperSnakecase
+object PlayerAnalogMovementInput extends Enum[PlayerAnalogMovementInput] {
val values = findValues
- case object TurnRight extends PlayerAnalogInput
- case object TurnLeft extends PlayerAnalogInput
+ case object TurnRight extends PlayerAnalogMovementInput
+ case object TurnLeft extends PlayerAnalogMovementInput
}
diff --git a/src/main/scala/wow/doge/mygame/game/subsystems/level/GameLevel.scala b/src/main/scala/wow/doge/mygame/game/subsystems/level/GameLevel.scala
index c260071..0c30d34 100644
--- a/src/main/scala/wow/doge/mygame/game/subsystems/level/GameLevel.scala
+++ b/src/main/scala/wow/doge/mygame/game/subsystems/level/GameLevel.scala
@@ -1,13 +1,14 @@
package wow.doge.mygame.game.subsystems.level
+import com.jme3.bullet.PhysicsSpace
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 com.jme3.scene.Spatial
+import com.softwaremill.tagging._
+import monix.bio.Task
+import wow.doge.mygame.game.GameAppTags
import wow.doge.mygame.implicits._
class GameLevel(
@@ -16,11 +17,14 @@ class GameLevel(
ambientLight: AmbientLight,
directionalLight: DirectionalLight
) {
- def addToGame(rootNode: Ref[Task, Node], physicsSpace: PhysicsSpace) = {
+ def addToGame(
+ rootNode: Node @@ GameAppTags.RootNode,
+ physicsSpace: PhysicsSpace
+ ) = {
for {
- _ <- rootNode.update(_ :+ model)
- _ <- rootNode.update(_ :+ ambientLight)
- _ <- rootNode.update(_ :+ directionalLight)
+ _ <- Task(rootNode += model)
+ _ <- Task(rootNode :+ ambientLight)
+ _ <- Task(rootNode :+ directionalLight)
_ <- Task(physicsSpace += model)
_ <- Task(physicsSpace += physicsControl)
} yield ()
diff --git a/src/main/scala/wow/doge/mygame/game/subsystems/movement/CanMove.scala b/src/main/scala/wow/doge/mygame/game/subsystems/movement/CanMove.scala
index 8485c5f..f4459c6 100644
--- a/src/main/scala/wow/doge/mygame/game/subsystems/movement/CanMove.scala
+++ b/src/main/scala/wow/doge/mygame/game/subsystems/movement/CanMove.scala
@@ -13,6 +13,7 @@ import wow.doge.mygame.subsystems.movement.RotateDir
trait CanMove[-A] {
// def getDirection(cam: Camera, cardinalDir: CardinalDirection): ImVector3f
def move(inst: A, direction: ImVector3f): Unit
+ def location(inst: A): ImVector3f
def jump(inst: A): Unit
def stop(inst: A): Unit
def rotate(inst: A, rotateDir: RotateDir): Unit
@@ -30,6 +31,8 @@ object CanMove {
// inst.setViewDirection(direction.mutable)
inst.setWalkDirection(direction.mutable.multLocal(50f))
}
+ override def location(inst: BetterCharacterControl) =
+ inst.getSpatial().getLocalTranslation().immutable
override def jump(inst: BetterCharacterControl): Unit = inst.jump()
override def rotate(
inst: BetterCharacterControl,
@@ -39,10 +42,10 @@ object CanMove {
rotateDir match {
case RotateDir.Left =>
new Quaternion()
- .fromAngleAxis(-10f * FastMath.DEG_TO_RAD, Vector3f.UNIT_Y)
+ .fromAngleAxis(-5 * FastMath.DEG_TO_RAD, Vector3f.UNIT_Y)
case RotateDir.Right =>
new Quaternion()
- .fromAngleAxis(10 * FastMath.DEG_TO_RAD, Vector3f.UNIT_Y)
+ .fromAngleAxis(5 * FastMath.DEG_TO_RAD, Vector3f.UNIT_Y)
}
val tmp = new Vector3f()
@@ -57,6 +60,8 @@ object CanMove {
override def move(inst: Spatial, direction: ImVector3f): Unit = {
inst.move(direction.mutable)
}
+ override def location(inst: Spatial) =
+ inst.getLocalTranslation().immutable
override def jump(inst: Spatial): Unit =
logger.warn("`Jump` is not implemented for type `Spatial`")
override def rotate(inst: Spatial, rotateDir: RotateDir): Unit = {
diff --git a/src/main/scala/wow/doge/mygame/game/subsystems/movement/MovementActor.scala b/src/main/scala/wow/doge/mygame/game/subsystems/movement/MovementActor.scala
index 9688f45..cd2c338 100644
--- a/src/main/scala/wow/doge/mygame/game/subsystems/movement/MovementActor.scala
+++ b/src/main/scala/wow/doge/mygame/game/subsystems/movement/MovementActor.scala
@@ -1,17 +1,14 @@
package wow.doge.mygame.subsystems.movement
-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.state.CardinalDirection
-import wow.doge.mygame.subsystems.events.EntityMovementEvent.PlayerMovementEvent
sealed trait RotateDir
object RotateDir {
@@ -35,21 +32,13 @@ object ImMovementActor {
final case class Props[T: CanMove](
enqueueR: Function1[() => Unit, Unit],
- movable: T,
- playerMovementEventBus: ActorRef[
- EventBus.Command[PlayerMovementEvent]
- ]
+ movable: T
+ // playerMovementEventBus: ActorRef[
+ // EventBus.Command[PlayerMovementEvent]
+ // ]
) {
def create: Behavior[Command] =
- Behaviors.setup(ctx => {
- ctx.log.info("Hello from MovementActor")
- // val playerMovementEventHandler = ctx.spawn(
- // PlayerMovementEventHandler(ctx.self),
- // "playerMovementEventHandler"
- // )
- // playerMovementEventBus ! EventBus.Subscribe(playerMovementEventHandler)
- new ImMovementActor(ctx, this).receive(State())
- })
+ Behaviors.setup(ctx => new ImMovementActor(ctx, this).receive(State()))
}
/**
@@ -59,19 +48,6 @@ object ImMovementActor {
*/
final case class State(cardinalDir: CardinalDirection = CardinalDirection())
- // def apply[T: CanMove](props: Props[T]): Behavior[Command] =
- // Behaviors.setup(ctx => {
- // ctx.log.info("Hello from MovementActor")
- // val playerMovementEventHandler = ctx.spawn(
- // PlayerMovementEventHandler(ctx.self),
- // "playerMovementEventHandler"
- // )
- // props.playerMovementEventBus ! EventBus.Subscribe(
- // playerMovementEventHandler
- // )
- // new ImMovementActor(ctx, props).receive(State())
- // })
-
}
class ImMovementActor[T](
diff --git a/src/main/scala/wow/doge/mygame/game/subsystems/ui/JmeJfx.scala b/src/main/scala/wow/doge/mygame/game/subsystems/ui/JmeJfx.scala
index 5bf3cfc..f40ab7a 100644
--- a/src/main/scala/wow/doge/mygame/game/subsystems/ui/JmeJfx.scala
+++ b/src/main/scala/wow/doge/mygame/game/subsystems/ui/JmeJfx.scala
@@ -1,43 +1,15 @@
package wow.doge.mygame.game.subsystems.ui
-import com.jme3.app.Application
-import com.jayfella.jme.jfx.JavaFxUI
-import scalafx.application.Platform
-import monix.execution.CancelablePromise
-import monix.bio.Task
-import cats.effect.concurrent.Deferred
import scala.concurrent.duration._
-import wow.doge.mygame.game.GameApp
+
+import com.jayfella.jme.jfx.JavaFxUI
+import monix.bio.Task
+import wow.doge.mygame.game.SimpleAppExt
object JFxUI {
- def apply(app: GameApp) =
+ def apply(app: SimpleAppExt) =
Task(JavaFxUI.initialize(app))
.executeOn(app.scheduler) >> Task.sleep(500.millis) >> Task(
JavaFxUI.getInstance()
)
- // Task {
- // Platform.runLater(() => {
- // println("here jfx")
- // JavaFxUI.initialize(app)
- // println("here2 jfx2")
- // val inst = JavaFxUI.getInstance()
- // println(inst)
- // })
- // }
- // Task.fromFuture {
- // val p = CancelablePromise[JavaFxUI]()
- // Platform.runLater(() => {
- // println("here")
- // JavaFxUI.initialize(app)
- // println("here2")
- // val inst = JavaFxUI.getInstance()
- // println(inst)
- // p.success(inst)
- // })
- // p.future
- // }
-// for {
-// d <- Deferred[Task, JavaFxUI]
-// _ <- Task(JavaFxUI.initialize(app))
-// } yield ()
}
diff --git a/src/main/scala/wow/doge/mygame/implicits/JavaFXMonixObservables.scala b/src/main/scala/wow/doge/mygame/implicits/JavaFXMonixObservables.scala
index 34b69d6..1650b5f 100644
--- a/src/main/scala/wow/doge/mygame/implicits/JavaFXMonixObservables.scala
+++ b/src/main/scala/wow/doge/mygame/implicits/JavaFXMonixObservables.scala
@@ -1,18 +1,12 @@
package wow.doge.mygame.implicits
-import javafx.{
- collections => jfxc,
- event => jfxe,
- geometry => jfxg,
- scene => jfxs,
- util => jfxu
-}
-import javafx.scene.{input => jfxsi, layout => jfxsl, paint => jfxsp}
-import scalafx.scene.Scene
-import monix.execution.Cancelable
-import monix.reactive.OverflowStrategy
-import monix.reactive.Observable
+import javafx.scene.{input => jfxsi}
+import javafx.{event => jfxe}
import monix.execution.Ack
+import monix.execution.Cancelable
+import monix.reactive.Observable
+import monix.reactive.OverflowStrategy
+import scalafx.scene.Scene
import scalafx.scene.control.ButtonBase
object JavaFXMonixObservables {
diff --git a/src/main/scala/wow/doge/mygame/implicits/observables/package.scala b/src/main/scala/wow/doge/mygame/implicits/observables/package.scala
index d587ffe..8d97f0c 100644
--- a/src/main/scala/wow/doge/mygame/implicits/observables/package.scala
+++ b/src/main/scala/wow/doge/mygame/implicits/observables/package.scala
@@ -1,18 +1,5 @@
package wow.doge.mygame.implicits
-import javafx.{
- collections => jfxc,
- event => jfxe,
- geometry => jfxg,
- scene => jfxs,
- util => jfxu
-}
-import javafx.scene.{input => jfxsi, layout => jfxsl, paint => jfxsp}
-import scalafx.scene.Scene
-import monix.execution.Cancelable
-import monix.reactive.OverflowStrategy
-import monix.reactive.Observable
-import monix.execution.Ack
-import scalafx.scene.control.Button
+
package object observables {}
diff --git a/src/main/scala/wow/doge/mygame/implicits/package.scala b/src/main/scala/wow/doge/mygame/implicits/package.scala
index e670a14..f08761b 100644
--- a/src/main/scala/wow/doge/mygame/implicits/package.scala
+++ b/src/main/scala/wow/doge/mygame/implicits/package.scala
@@ -6,6 +6,7 @@ import scala.reflect.ClassTag
import akka.actor.typed.ActorRef
import akka.actor.typed.Scheduler
import akka.util.Timeout
+import com.jayfella.jme.jfx.JavaFxUI
import com.jme3.app.Application
import com.jme3.app.SimpleApplication
import com.jme3.app.state.AppState
@@ -24,6 +25,7 @@ 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.light.Light
import com.jme3.math.Vector3f
import com.jme3.scene.CameraNode
import com.jme3.scene.Geometry
@@ -48,23 +50,23 @@ import monix.reactive.OverflowStrategy
import monix.reactive.observers.Subscriber
import wow.doge.mygame.math.ImVector3f
import wow.doge.mygame.state.MyBaseState
-import com.jme3.light.Light
-import com.jayfella.jme.jfx.JavaFxUI
+import com.jme3.material.Material
-case class ActionEvent(binding: Action, value: Boolean, tpf: Float)
-case class EnumActionEvent[T <: EnumEntry](
+final case class ActionEvent(binding: Action, value: Boolean, tpf: Float)
+final case class EnumActionEvent[T <: EnumEntry](
binding: T,
value: Boolean,
tpf: Float
)
-case class AnalogEvent(binding: Action, value: Float, tpf: Float)
-case class EnumAnalogEvent[T <: EnumEntry](
+final case class AnalogEvent(binding: Action, value: Float, tpf: Float)
+final case class EnumAnalogEvent[T <: EnumEntry](
binding: T,
value: Float,
tpf: Float
)
-case class PhysicsTickEvent(space: PhysicsSpace, tpf: Float)
+final class PrePhysicsTickEvent(val space: PhysicsSpace) extends AnyVal
+final class PhysicsTickEvent(val space: PhysicsSpace) extends AnyVal
package object implicits {
type PrePhysicsTickEvent = PhysicsTickEvent
@@ -334,6 +336,13 @@ package object implicits {
}
}
+ implicit final class GeometryExt(private val geom: Geometry) {
+ def withMaterial(mat: Material) = {
+ geom.setMaterial(mat)
+ geom
+ }
+ }
+
implicit final class EntityDataExt(private val ed: EntityData)
extends AnyVal {
@@ -356,10 +365,7 @@ package object implicits {
import akka.actor.typed.scaladsl.AskPattern._
/**
- * @param replyTo
- * @param timeout
- * @param scheduler
- * @return
+ * Same as [[ask]] but returns a [[Task]]
*/
def askL[Res](
replyTo: ActorRef[Res] => Req
@@ -378,12 +384,16 @@ package object implicits {
* @return
*/
def tellL(msg: Req) = UIO(a.tell(msg))
+
+ /**
+ * Same as [[tell]], but wrapped in a Task
+ *
+ * @param msg
+ * @return
+ */
def !!(msg: Req) = tellL(msg)
}
- // def ?[Res](replyTo: ActorRef[Res] => Req)(implicit timeout: Timeout, scheduler: Scheduler): Future[Res] = {
- // ask(replyTo)(timeout, scheduler)
- // }
implicit final class InputManagerExt(private val inputManager: InputManager)
extends AnyVal {
@@ -523,7 +533,7 @@ package object implicits {
def collisionObservable(): Observable[PhysicsCollisionEvent] = {
- Observable.create(OverflowStrategy.Unbounded) { sub =>
+ Observable.create(OverflowStrategy.DropOld(50)) { sub =>
val c = SingleAssignCancelable()
val cl = new PhysicsCollisionListener {
override def collision(event: PhysicsCollisionEvent): Unit = {
@@ -543,23 +553,45 @@ package object implicits {
}
}
- def physicsTickObservable(): PhysicsTickObservable = {
+ def prePhysicsTickObservable(): Observable[PrePhysicsTickEvent] = {
- Observable.create(OverflowStrategy.Unbounded) { sub =>
+ Observable.create(OverflowStrategy.DropOld(50)) { sub =>
val c = SingleAssignCancelable()
val cl = new PhysicsTickListener {
override def prePhysicsTick(space: PhysicsSpace, tpf: Float): Unit = {
- val event = PhysicsTickEvent(space, tpf)
- if (sub.onNext(Left(event)) == Ack.Stop) {
+ val event = new PrePhysicsTickEvent(space)
+ if (sub.onNext(event) == Ack.Stop) {
sub.onComplete()
c.cancel()
}
}
+ override def physicsTick(space: PhysicsSpace, tpf: Float): Unit = {}
+
+ }
+
+ space.addTickListener(cl)
+
+ c := Cancelable(() => space.removeTickListener(cl))
+ c
+ }
+ }
+
+ def physicsTickObservable(): Observable[PhysicsTickEvent] = {
+
+ Observable.create(OverflowStrategy.DropOld(50)) { sub =>
+ val c = SingleAssignCancelable()
+ val cl = new PhysicsTickListener {
+
+ override def prePhysicsTick(
+ space: PhysicsSpace,
+ tpf: Float
+ ): Unit = {}
+
override def physicsTick(space: PhysicsSpace, tpf: Float): Unit = {
- val event = PhysicsTickEvent(space, tpf)
- if (sub.onNext(Right(event)) == Ack.Stop) {
+ val event = new PhysicsTickEvent(space)
+ if (sub.onNext(event) == Ack.Stop) {
sub.onComplete()
c.cancel()
}
@@ -574,7 +606,7 @@ package object implicits {
}
}
- //TODO Create a typeclass for this
+ //TODO Consider creating a typeclass for this
def +=(anyObject: Any) = space.add(anyObject)
def :+(anyObject: Any) = {
diff --git a/src/main/scala/wow/doge/mygame/launcher/DefaultUI.scala b/src/main/scala/wow/doge/mygame/launcher/DefaultUI.scala
index 7dfb948..1971d3c 100644
--- a/src/main/scala/wow/doge/mygame/launcher/DefaultUI.scala
+++ b/src/main/scala/wow/doge/mygame/launcher/DefaultUI.scala
@@ -1,18 +1,17 @@
package wow.doge.mygame.launcher
import scalafx.geometry.Insets
+import scalafx.geometry.Orientation
+import scalafx.geometry.Pos
import scalafx.scene.Scene
+import scalafx.scene.control.Button
import scalafx.scene.effect.DropShadow
+import scalafx.scene.layout.FlowPane
import scalafx.scene.layout.HBox
+import scalafx.scene.layout.VBox
import scalafx.scene.paint.Color._
import scalafx.scene.paint._
import scalafx.scene.text.Text
-import scalafx.scene.control.Button
-import scalafx.scene.layout.VBox
-import scalafx.scene.layout.FlowPane
-import scalafx.geometry.Orientation
-import scalafx.geometry.Pos
-import scalafx.stage.Stage
object DefaultUI {
def scene(
@@ -64,39 +63,4 @@ object DefaultUI {
// }
}
- def box(launchButton: Button, exitButton: Button) =
- new VBox {
- children = Seq(
- new HBox {
- padding = Insets(50, 80, 50, 80)
- children = Seq(
- new Text {
- text = "JMonkeyEngine"
- style = "-fx-font: normal bold 50pt sans-serif"
- fill = new LinearGradient(endX = 0, stops = Stops(Red, DarkRed))
- },
- new Text {
- text = " Game"
- style = "-fx-font: italic bold 50pt sans-serif"
- fill = new LinearGradient(
- endX = 0,
- stops = Stops(White, DarkGray)
- )
- effect = new DropShadow {
- color = DarkGray
- radius = 15
- spread = 0.25
- }
- }
- )
- },
- new FlowPane {
- hgap = 10
- padding = Insets(50, 80, 50, 80)
- orientation = Orientation.Horizontal
- alignment = Pos.Center
- children = Seq(launchButton, exitButton)
- }
- )
- }
}
diff --git a/src/main/scala/wow/doge/mygame/launcher/Launcher.scala b/src/main/scala/wow/doge/mygame/launcher/Launcher.scala
index 73671cd..67084bc 100644
--- a/src/main/scala/wow/doge/mygame/launcher/Launcher.scala
+++ b/src/main/scala/wow/doge/mygame/launcher/Launcher.scala
@@ -1,34 +1,22 @@
package wow.doge.mygame.launcher
import scala.concurrent.duration.FiniteDuration
-import scalafx.application.JFXApp
-import scalafx.application.JFXApp.PrimaryStage
-import wow.doge.mygame.executors.Schedulers
-import cats.effect.Resource
-import monix.bio.Task
import scala.concurrent.duration._
-import javafx.application.Platform
-import scalafx.scene.control.Button
+
import cats.effect.concurrent.Deferred
-import wow.doge.mygame.utils.IOUtils._
+import javafx.application.Platform
+import monix.bio.Task
+import monix.catnap.CancelableF
import monix.eval.{Task => ETask}
import monix.reactive.Observable
-import monix.bio.Fiber
-import scalafx.stage.StageStyle
import scalafx.Includes._
-import wow.doge.mygame.utils.ResizeHelper
-import scalafx.scene.Scene
-import scalafx.scene.layout.VBox
+import scalafx.application.JFXApp
+import scalafx.application.JFXApp.PrimaryStage
+import scalafx.scene.control.Button
+import scalafx.stage.StageStyle
+import wow.doge.mygame.executors.Schedulers
import wow.doge.mygame.implicits.JavaFXMonixObservables._
-import monix.catnap.cancelables.SingleAssignCancelableF
-import monix.catnap.CancelableF
-// import wow.doge.mygame.implicits.JavaFXMonixObservables._
-
-// import scala.language.implicitConversions
-
-// object Stage {
-// implicit def sfxStage2jfx(v: Stage): jfxs.Stage = if (v != null) v.delegate else null
-// }
+import wow.doge.mygame.utils.IOUtils._
object Launcher {
sealed trait LauncherResult
@@ -41,19 +29,7 @@ object Launcher {
val schedulers: Schedulers,
val signal: Deferred[Task, LauncherResult]
) {
- // val resource2
- // : Resource[Task, (LauncherApp, Task[Ref[Task, Stage]], Fiber[Unit])] =
- // Resource.make(for {
- // app <- Task(new LauncherApp(this))
- // fib <- app.init.start
- // } yield ((app, app.stageRef, fib)))(_._3.cancel)
val create = Task(new Launcher(this))
-
- val resource: Resource[Task, Launcher] =
- Resource.make(for {
- app <- Task(new Launcher(this))
- // fib <- app.init.start
- } yield (app))(_ => Task.unit)
}
}
class Launcher private (props: Launcher.Props) {
@@ -62,7 +38,6 @@ class Launcher private (props: Launcher.Props) {
private lazy val launchButton = new Button {
text = "Launch"
}
- // private lazy val launchButtonObs =
private lazy val launchAction =
launchButton
@@ -72,7 +47,6 @@ class Launcher private (props: Launcher.Props) {
private lazy val exitButton = new Button {
text = "Exit"
}
- // private lazy val exitButtonObs =
private lazy val exitAction =
exitButton
@@ -80,9 +54,6 @@ class Launcher private (props: Launcher.Props) {
.doOnNext(_ => toTask(props.signal.complete(LauncherResult.Exit)))
private lazy val _scene =
- // new Scene {
- // content = new VBox
- // }
DefaultUI.scene(launchButton, exitButton)
private lazy val _stage = new PrimaryStage {
@@ -113,41 +84,21 @@ class Launcher private (props: Launcher.Props) {
)
}
- // var stage = internal.stage
-
- // lazy val stageRef = Ref.of[Task, Stage](internal.stage)
-// stage: => PrimaryStage
def init(delay: FiniteDuration = 2000.millis) =
for {
_ <- Task(Platform.setImplicitExit(false))
fib <- Task(internal.main(Array.empty)).start
_ <- Task.sleep(500.millis)
- // _ <- Task {
- // // lazy val _stage = new CustomStageBuilder()
- // // .setWindowTitle("CustomStage example")
- // // .setWindowColor("rgb(34,54,122)")
- // // .build()
- // internal.stage.scene =
- // DefaultUI.scene(internal.stage, launchButton, exitButton)
- // // _stage.setScene(DefaultUI.scene(launchButton, exitButton))
- // // JFXApp.Stage = _stage
- // }.executeOn(props.schedulers.fx)
- // c <- SingleAssignCancelableF[Task]
sceneDragFib <- toIO(sceneDragObservable.completedL).start
fib2 <- toIO(
Observable(launchAction, exitAction).merge
.doOnNext(_ =>
ETask(internal.stage.close()).executeOn(props.schedulers.fx)
)
- // .doOnNext(_ => toTask(fib.cancel))
.completedL
).start
c <- CancelableF[Task](fib.cancel >> fib2.cancel >> sceneDragFib.cancel)
- // _ <- Task {
- // internal.stage = stage
- // }.executeOn(props.schedulers.fx)
- // .delayExecution(delay)
} yield (c)
}
diff --git a/src/main/scala/wow/doge/mygame/math/ImVector3f.scala b/src/main/scala/wow/doge/mygame/math/ImVector3f.scala
index e630a46..b3dfe3d 100644
--- a/src/main/scala/wow/doge/mygame/math/ImVector3f.scala
+++ b/src/main/scala/wow/doge/mygame/math/ImVector3f.scala
@@ -1,5 +1,7 @@
package wow.doge.mygame.math;
+import Math.{abs, sqrt, pow}
+
case class ImVector3f(x: Float = 0f, y: Float = 0f, z: Float = 0f)
object ImVector3f {
@@ -8,4 +10,6 @@ object ImVector3f {
val UNIT_Y = ImVector3f(0, 1, 0)
val UNIT_Z = ImVector3f(0, 0, 1)
+ def dst(v1: ImVector3f, v2: ImVector3f) =
+ sqrt(pow(v1.x - v2.x, 2) + pow(v1.y - v2.y, 2) + pow(v1.z - v2.z, 2))
}
diff --git a/src/main/scala/wow/doge/mygame/subsystems/events/EventBus.scala b/src/main/scala/wow/doge/mygame/subsystems/events/EventBus.scala
index 6c1696d..c5decdb 100644
--- a/src/main/scala/wow/doge/mygame/subsystems/events/EventBus.scala
+++ b/src/main/scala/wow/doge/mygame/subsystems/events/EventBus.scala
@@ -1,4 +1,4 @@
-package wow.doge.mygame.events
+package wow.doge.mygame.subsystems.events
import scala.reflect.ClassTag
diff --git a/src/main/scala/wow/doge/mygame/subsystems/events/Events.scala b/src/main/scala/wow/doge/mygame/subsystems/events/Events.scala
index 37517f7..436e37e 100644
--- a/src/main/scala/wow/doge/mygame/subsystems/events/Events.scala
+++ b/src/main/scala/wow/doge/mygame/subsystems/events/Events.scala
@@ -1,14 +1,24 @@
-package wow.doge.mygame.events
+package wow.doge.mygame.subsystems.events
-object Events {
- sealed trait Event
- final case object BulletFired extends Event
+sealed trait Event
+final case object BulletFired extends Event
// type BulletFired = BulletFired.type
- final case class EventWithData(data: Int) extends Event
+final case class EventWithData(data: Int) extends Event
- sealed trait Tick extends Event
- object Tick {
- final case object RenderTick extends Tick
- final case object PhysicsTick extends Tick
- }
+sealed trait TickEvent extends Event
+object TickEvent {
+ final case object RenderTick extends TickEvent
+ final case object PhysicsTick extends TickEvent
+}
+
+sealed trait EntityMovementEvent extends Event
+object EntityMovementEvent {
+ final case class MovedLeft(name: String, pressed: Boolean)
+ extends EntityMovementEvent
+ final case class MovedUp(name: String, pressed: Boolean)
+ extends EntityMovementEvent
+ final case class MovedRight(name: String, pressed: Boolean)
+ extends EntityMovementEvent
+ final case class MovedDown(name: String, pressed: Boolean)
+ extends EntityMovementEvent
}
diff --git a/src/main/scala/wow/doge/mygame/subsystems/events/EventsModule.scala b/src/main/scala/wow/doge/mygame/subsystems/events/EventsModule.scala
index 8ab4495..0c3a106 100644
--- a/src/main/scala/wow/doge/mygame/subsystems/events/EventsModule.scala
+++ b/src/main/scala/wow/doge/mygame/subsystems/events/EventsModule.scala
@@ -10,22 +10,19 @@ 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 com.typesafe.scalalogging.{Logger => SLogger}
import org.slf4j.event.Level
-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.Event
+import wow.doge.mygame.subsystems.events.EventBus
+import wow.doge.mygame.subsystems.events.TickEvent
-class EventsModule2(
- spawnProtocol: ActorSystem[SpawnProtocol.Command]
-) {
+class EventsModule(spawnProtocol: ActorSystem[SpawnProtocol.Command]) {
implicit lazy val s = spawnProtocol.scheduler
implicit lazy val timeout = Timeout(1.second)
- lazy val eventBusLogger = SLLogger[EventBus[_]]
+ lazy val eventBusLogger = SLogger[EventBus[_]]
lazy val playerMovementEventBusTask =
createEventBus[PlayerMovementEvent]("movementEventBus")
@@ -33,6 +30,11 @@ class EventsModule2(
lazy val playerCameraEventBusTask =
createEventBus[PlayerCameraEvent]("playerCameraEventBus", Level.DEBUG)
+ lazy val tickEventBusTask =
+ createEventBus[TickEvent]("tickEventBus", Level.TRACE)
+
+ lazy val mainEventBusTask = createEventBus[Event]("mainEventBus")
+
def createEventBus[T](busName: String, logLevel: Level = Level.DEBUG) =
spawnProtocol.askL(
SpawnProtocol.Spawn[EventBus.Command[T]](
@@ -49,17 +51,8 @@ class EventsModule2(
_
)
)
-
- 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))
+}
+
+object EventsModule {
+ type GameEventBus[T] = ActorRef[EventBus.Command[T]]
}
diff --git a/src/main/scala/wow/doge/mygame/subsystems/events/MovementEvents.scala b/src/main/scala/wow/doge/mygame/subsystems/events/MovementEvents.scala
deleted file mode 100644
index c6b8e39..0000000
--- a/src/main/scala/wow/doge/mygame/subsystems/events/MovementEvents.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-package wow.doge.mygame.subsystems.events
-
-import wow.doge.mygame.game.subsystems.movement.CanMove
-
-sealed trait EntityMovementEvent
-object EntityMovementEvent {
- final case class MovedLeft[T: CanMove](pressed: Boolean, movable: T)
- extends EntityMovementEvent
- final case class MovedUp[T: CanMove](pressed: Boolean, movable: T)
- extends EntityMovementEvent
- final case class MovedRight[T: CanMove](pressed: Boolean, movable: T)
- extends EntityMovementEvent
- final case class MovedDown[T: CanMove](pressed: Boolean, movable: T)
- extends EntityMovementEvent
-
- sealed trait PlayerMovementEvent extends EntityMovementEvent
- object PlayerMovementEvent {
- final case class PlayerMovedLeft(pressed: Boolean)
- extends PlayerMovementEvent
- final case class PlayerMovedRight(pressed: Boolean)
- extends PlayerMovementEvent
- final case class PlayerMovedForward(pressed: Boolean)
- extends PlayerMovementEvent
- final case class PlayerMovedBackward(pressed: Boolean)
- extends PlayerMovementEvent
- final case object PlayerJumped extends PlayerMovementEvent
- final case object PlayerRotatedRight extends PlayerMovementEvent
- final case object PlayerRotatedLeft extends PlayerMovementEvent
- final case object PlayerCameraUp extends PlayerMovementEvent
- final case object PlayerCameraDown extends PlayerMovementEvent
-
- }
-}
diff --git a/src/main/scala/wow/doge/mygame/subsystems/events/PlayerCameraEvents.scala b/src/main/scala/wow/doge/mygame/subsystems/events/PlayerCameraEvents.scala
index f874ca1..1016f29 100644
--- a/src/main/scala/wow/doge/mygame/subsystems/events/PlayerCameraEvents.scala
+++ b/src/main/scala/wow/doge/mygame/subsystems/events/PlayerCameraEvents.scala
@@ -1,8 +1 @@
package wow.doge.mygame.subsystems.events
-
-sealed trait PlayerCameraEvent
-
-object PlayerCameraEvent {
- final case object CameraMovedUp extends PlayerCameraEvent
- final case object CameraMovedDown extends PlayerCameraEvent
-}
diff --git a/src/main/scala/wow/doge/mygame/subsystems/events/PlayerEvents.scala b/src/main/scala/wow/doge/mygame/subsystems/events/PlayerEvents.scala
new file mode 100644
index 0000000..6486c91
--- /dev/null
+++ b/src/main/scala/wow/doge/mygame/subsystems/events/PlayerEvents.scala
@@ -0,0 +1,24 @@
+package wow.doge.mygame.subsystems.events
+
+sealed trait PlayerMovementEvent
+object PlayerMovementEvent {
+ final case class PlayerMovedLeft(pressed: Boolean) extends PlayerMovementEvent
+ final case class PlayerMovedRight(pressed: Boolean)
+ extends PlayerMovementEvent
+ final case class PlayerMovedForward(pressed: Boolean)
+ extends PlayerMovementEvent
+ final case class PlayerMovedBackward(pressed: Boolean)
+ extends PlayerMovementEvent
+ final case object PlayerJumped extends PlayerMovementEvent
+ final case object PlayerRotatedRight extends PlayerMovementEvent
+ final case object PlayerRotatedLeft extends PlayerMovementEvent
+ final case object PlayerCameraUp extends PlayerMovementEvent
+ final case object PlayerCameraDown extends PlayerMovementEvent
+}
+
+sealed trait PlayerCameraEvent
+
+object PlayerCameraEvent {
+ final case object CameraMovedUp extends PlayerCameraEvent
+ final case object CameraMovedDown extends PlayerCameraEvent
+}
diff --git a/src/main/scala/wow/doge/mygame/subsystems/moddingsystem/ModdingSystem.scala b/src/main/scala/wow/doge/mygame/subsystems/moddingsystem/ModdingSystem.scala
index f85683d..f54af19 100644
--- a/src/main/scala/wow/doge/mygame/subsystems/moddingsystem/ModdingSystem.scala
+++ b/src/main/scala/wow/doge/mygame/subsystems/moddingsystem/ModdingSystem.scala
@@ -8,6 +8,7 @@ import scala.util.Try
import cats.implicits._
import io.circe._
+import io.circe.generic.JsonCodec
import io.circe.generic.semiauto._
import io.circe.parser._
import monix.bio.IO
@@ -15,7 +16,6 @@ import monix.bio.UIO
import monix.reactive.Consumer
import monix.reactive.Observable
import wow.doge.mygame.utils.IOUtils
-import io.circe.generic.JsonCodec
@JsonCodec
final case class Test1(hello1: String, hello2: String)
diff --git a/src/main/scala/wow/doge/mygame/subsystems/scriptsystem/ScriptSystemModule.scala b/src/main/scala/wow/doge/mygame/subsystems/scriptsystem/ScriptSystemModule.scala
index 5214c4e..975ce98 100644
--- a/src/main/scala/wow/doge/mygame/subsystems/scriptsystem/ScriptSystemModule.scala
+++ b/src/main/scala/wow/doge/mygame/subsystems/scriptsystem/ScriptSystemModule.scala
@@ -5,9 +5,9 @@ import akka.actor.typed.Scheduler
import akka.actor.typed.SpawnProtocol
import akka.util.Timeout
import cats.effect.Resource
+import monix.bio.Task
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)
diff --git a/src/main/scala/wow/doge/mygame/utils/AkkaUtils.scala b/src/main/scala/wow/doge/mygame/utils/AkkaUtils.scala
index d36c913..3c47b1c 100644
--- a/src/main/scala/wow/doge/mygame/utils/AkkaUtils.scala
+++ b/src/main/scala/wow/doge/mygame/utils/AkkaUtils.scala
@@ -22,4 +22,20 @@ object AkkaUtils {
_
)
)
+ def spawnActorL2[T](
+ behavior: Behavior[T],
+ actorName: String
+ )(implicit
+ timeout: Timeout,
+ scheduler: Scheduler,
+ spawnProtocol: ActorRef[SpawnProtocol.Command]
+ ) =
+ spawnProtocol.askL[ActorRef[T]](
+ SpawnProtocol.Spawn(
+ behavior,
+ actorName,
+ Props.empty,
+ _
+ )
+ )
}
diff --git a/src/main/scala/wow/doge/mygame/utils/BorderlessScene.scala b/src/main/scala/wow/doge/mygame/utils/BorderlessScene.scala
deleted file mode 100644
index 8fe3f0c..0000000
--- a/src/main/scala/wow/doge/mygame/utils/BorderlessScene.scala
+++ /dev/null
@@ -1,750 +0,0 @@
-package wow.doge.mygame.utils
-
-/*
- * Copyright (c) 2011-2019, ScalaFX Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the ScalaFX Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE SCALAFX PROJECT OR ITS CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-import javafx.scene.{input => jfxsi, layout => jfxsl, paint => jfxsp}
-import javafx.{
- collections => jfxc,
- event => jfxe,
- geometry => jfxg,
- scene => jfxs,
- util => jfxu
-}
-import scalafx.Includes._
-import scalafx.beans.property.{
- ObjectProperty,
- ReadOnlyDoubleProperty,
- ReadOnlyObjectProperty
-}
-import scalafx.collections._
-import scalafx.delegate.SFXDelegate
-import scalafx.geometry.NodeOrientation
-import scalafx.scene.image.WritableImage
-import scalafx.scene.input.{Dragboard, Mnemonic, TransferMode}
-import scalafx.scene.paint.Paint
-import com.goxr3plus.fxborderlessscene.borderless.{BorderlessScene => BScene}
-
-import scala.language.implicitConversions
-import scalafx.scene.Cursor
-import scalafx.scene._
-import scalafx.stage.Stage
-import scalafx.stage.StageStyle
-
-object BorderlessScene {
- implicit def sfxScene2jfx(v: BorderlessScene): Scene =
- if (v != null) v.delegate else null
-}
-
-/**
- * Wraps [[http://docs.oracle.com/javase/8/javafx/api/javafx/scene/Scene.html]].
- *
- * @constructor Create a new ScalaFX Scene with JavaFX Scene as delegate.
- * @param delegate JavaFX Scene delegated. Its default value is a JavaFX Scene with a
- * [[http://docs.oracle.com/javase/8/javafx/api/javafx/scene/Group.html Group]] as root Node.
- */
-class BorderlessScene(
- override val delegate: BScene
-) extends SFXDelegate[BScene] {
-
- def this(stage: Stage, stageStyle: StageStyle, parent: Parent) =
- this(new BScene(stage, stageStyle, parent))
-
- /**
- * Returns the root Node of the scene graph
- */
- def root: ObjectProperty[jfxs.Parent] = delegate.rootProperty
-
- /**
- * Sets the root Node of the scene graph
- */
- def root_=(v: Parent): Unit = {
- root() = v
- }
-
- /**
- * Returns Nodes children from this Scene's `root`.
- */
- def getChildren =
- root.value match {
- case group: jfxs.Group => group.getChildren
- case pane: jfxsl.Pane => pane.getChildren
- case _ =>
- throw new IllegalStateException(
- "Cannot access children of root: " + root + "\n" +
- "Use a class that extends Group or Pane, or override the getChildren method."
- )
- }
-
- /**
- * Returns scene's antialiasing setting.
- */
- def antialiasing: SceneAntialiasing = delegate.getAntiAliasing
-
- /**
- * Returns Content's Node children from this Scene's `root`.
- */
- def content: jfxc.ObservableList[jfxs.Node] = getChildren
-
- /**
- * Sets the list of Nodes children from this Scene's `root`, replacing the prior content. If you want append to
- * current content, use `add` or similar.
- *
- * @param c list of Nodes children from this Scene's `root` to replace prior content.
- */
- def content_=(c: Iterable[Node]): Unit = {
- fillSFXCollection(this.content, c)
- }
-
- /**
- * Sets a Node child, replacing the prior content. If you want append to current content, use `add` or similar.
- *
- * @param n Node child to replace prior content.
- */
- def content_=(n: Node): Unit = {
- fillSFXCollectionWithOne(this.content, n)
- }
-
- /**
- * Specifies the type of camera use for rendering this `Scene`.
- */
- def camera: ObjectProperty[jfxs.Camera] = delegate.cameraProperty
-
- def camera_=(v: Camera): Unit = {
- camera() = v
- }
-
- /**
- * Defines the mouse cursor for this `Scene`.
- */
- def cursor: ObjectProperty[jfxs.Cursor] = delegate.cursorProperty
-
- def cursor_=(v: Cursor): Unit = {
- cursor() = v
- }
-
- /** The effective node orientation of a scene resolves the inheritance of node orientation, returning either left-to-right or right-to-left. */
- def effectiveNodeOrientation: ReadOnlyObjectProperty[jfxg.NodeOrientation] =
- delegate.effectiveNodeOrientationProperty
-
- /**
- * Specifies the event dispatcher for this scene.
- */
- def eventDispatcher: ObjectProperty[jfxe.EventDispatcher] =
- delegate.eventDispatcherProperty
-
- def eventDispatcher_=(v: jfxe.EventDispatcher): Unit = {
- eventDispatcher() = v
- }
-
- /**
- * Defines the background fill of this Scene.
- */
- def fill: ObjectProperty[jfxsp.Paint] = delegate.fillProperty
-
- def fill_=(v: Paint): Unit = {
- fill() = v
- }
-
- /**
- * The height of this Scene
- */
- def height: ReadOnlyDoubleProperty = delegate.heightProperty
-
- /**
- * The width of this Scene
- */
- def width: ReadOnlyDoubleProperty = delegate.widthProperty
-
- def nodeOrientation: ObjectProperty[jfxg.NodeOrientation] =
- delegate.nodeOrientationProperty
-
- def nodeOrientation_=(v: NodeOrientation): Unit = {
- ObjectProperty.fillProperty[jfxg.NodeOrientation](this.nodeOrientation, v)
- }
-
- /**
- * Defines a function to be called when a mouse button has been clicked (pressed and released) on this `Scene`.
- */
- def onContextMenuRequested = delegate.onContextMenuRequestedProperty
-
- def onContextMenuRequested_=(
- v: jfxe.EventHandler[_ >: jfxsi.ContextMenuEvent]
- ): Unit = {
- onContextMenuRequested() = v
- }
-
- /**
- * Defines a function to be called when drag gesture has been detected.
- */
- def onDragDetected = delegate.onDragDetectedProperty
-
- def onDragDetected_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = {
- onDragDetected() = v
- }
-
- /**
- * Defines a function to be called when this `Scene` is a drag and drop gesture source after its data has been
- * dropped on a drop target.
- */
- def onDragDone = delegate.onDragDoneProperty
-
- def onDragDone_=(v: jfxe.EventHandler[_ >: jfxsi.DragEvent]): Unit = {
- onDragDone() = v
- }
-
- /**
- * Defines a function to be called when the mouse button is released on this `Scene` during drag and drop gesture.
- */
- def onDragDropped = delegate.onDragDroppedProperty
-
- def onDragDropped_=(v: jfxe.EventHandler[_ >: jfxsi.DragEvent]): Unit = {
- onDragDropped() = v
- }
-
- /**
- * Defines a function to be called when drag gesture enters this Scene.
- */
- def onDragEntered = delegate.onDragEnteredProperty
-
- def onDragEntered_=(v: jfxe.EventHandler[_ >: jfxsi.DragEvent]): Unit = {
- onDragEntered() = v
- }
-
- /**
- * Defines a function to be called when drag gesture exits this Scene.
- */
- def onDragExited = delegate.onDragExitedProperty
-
- def onDragExited_=(v: jfxe.EventHandler[_ >: jfxsi.DragEvent]): Unit = {
- onDragExited() = v
- }
-
- /**
- * Defines a function to be called when drag gesture progresses within this `Scene`.
- */
- def onDragOver = delegate.onDragOverProperty
-
- def onDragOver_=(v: jfxe.EventHandler[_ >: jfxsi.DragEvent]): Unit = {
- onDragOver() = v
- }
-
- /**
- * Defines a function to be called when this `Node` has input focus and the input method text has changed.
- */
- def onInputMethodTextChanged = delegate.onInputMethodTextChangedProperty
-
- def onInputMethodTextChanged_=(
- v: jfxe.EventHandler[_ >: jfxsi.InputMethodEvent]
- ): Unit = {
- onInputMethodTextChanged() = v
- }
-
- /**
- * Defines a function to be called when some `Node` of this `Scene` has input focus and a key has been pressed.
- */
- def onKeyPressed = delegate.onKeyPressedProperty
-
- def onKeyPressed_=(v: jfxe.EventHandler[_ >: jfxsi.KeyEvent]): Unit = {
- onKeyPressed() = v
- }
-
- /**
- * Defines a function to be called when some `Node` of this `Scene` has input focus and a key has been released.
- */
- def onKeyReleased = delegate.onKeyReleasedProperty
-
- def onKeyReleased_=(v: jfxe.EventHandler[_ >: jfxsi.KeyEvent]): Unit = {
- onKeyReleased() = v
- }
-
- /**
- * Defines a function to be called when some `Node` of this `Scene` has input focus and a key has been typed.
- */
- def onKeyTyped = delegate.onKeyTypedProperty
-
- def onKeyTyped_=(v: jfxe.EventHandler[_ >: jfxsi.KeyEvent]): Unit = {
- onKeyTyped() = v
- }
-
- /**
- * Defines a function to be called when a mouse button has been clicked (pressed and released) on this `Scene`.
- */
- def onMouseClicked = delegate.onMouseClickedProperty
-
- def onMouseClicked_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = {
- onMouseClicked() = v
- }
-
- /**
- * Defines a function to be called when a mouse button is pressed on this `Scene` and then dragged.
- */
- def onMouseDragged = delegate.onMouseDraggedProperty
-
- def onMouseDragged_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = {
- onMouseDragged() = v
- }
-
- /**
- * Defines a function to be called when a full press-drag-release gesture enters this `Scene`.
- */
- def onMouseDragEntered = delegate.onMouseDragEnteredProperty
-
- def onMouseDragEntered_=(
- v: jfxe.EventHandler[_ >: jfxsi.MouseDragEvent]
- ): Unit = {
- onMouseDragEntered() = v
- }
-
- /**
- * Defines a function to be called when a full press-drag-release gesture exits this `Scene`.
- */
- def onMouseDragExited = delegate.onMouseDragExitedProperty
-
- def onMouseDragExited_=(
- v: jfxe.EventHandler[_ >: jfxsi.MouseDragEvent]
- ): Unit = {
- onMouseDragExited() = v
- }
-
- /**
- * Defines a function to be called when a full press-drag-release gesture progresses within this `Scene`.
- */
- def onMouseDragOver = delegate.onMouseDragOverProperty
-
- def onMouseDragOver_=(
- v: jfxe.EventHandler[_ >: jfxsi.MouseDragEvent]
- ): Unit = {
- onMouseDragOver() = v
- }
-
- /**
- * Defines a function to be called when a full press-drag-release gesture ends within this `Scene`.
- */
- def onMouseDragReleased = delegate.onMouseDragReleasedProperty
-
- def onMouseDragReleased_=(
- v: jfxe.EventHandler[_ >: jfxsi.MouseDragEvent]
- ): Unit = {
- onMouseDragReleased() = v
- }
-
- /**
- * Defines a function to be called when the mouse enters this `Scene`.
- */
- def onMouseEntered = delegate.onMouseEnteredProperty
-
- def onMouseEntered_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = {
- onMouseEntered() = v
- }
-
- /**
- * Defines a function to be called when the mouse exits this `Scene`.
- */
- def onMouseExited = delegate.onMouseExitedProperty
-
- def onMouseExited_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = {
- onMouseExited() = v
- }
-
- /**
- * Defines a function to be called when mouse cursor moves within this `Scene` but no buttons have been pushed.
- */
- def onMouseMoved = delegate.onMouseMovedProperty
-
- def onMouseMoved_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = {
- onMouseMoved() = v
- }
-
- /**
- * Defines a function to be called when a mouse button has been pressed on this `Scene`.
- */
- def onMousePressed = delegate.onMousePressedProperty
-
- def onMousePressed_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = {
- onMousePressed() = v
- }
-
- /**
- * Defines a function to be called when a mouse button has been released on this `Scene`.
- */
- def onMouseReleased = delegate.onMouseReleasedProperty
-
- def onMouseReleased_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = {
- onMouseReleased() = v
- }
-
- /**
- * Defines a function to be called when user performs a scrolling action.
- */
- def onScroll = delegate.onScrollProperty
-
- def onScroll_=(v: jfxe.EventHandler[_ >: jfxsi.ScrollEvent]): Unit = {
- onScroll() = v
- }
-
- /**
- * The URL of the user-agent stylesheet that will be used by this Scene in place of the the platform-default
- * user-agent stylesheet. If the URL does not resolve to a valid location, the platform-default user-agent
- * stylesheet will be used.
- *
- * For additional information about using CSS with the scene graph, see the
- * [[http://docs.oracle.com/javase/8/javafx/api/javafx/scene/doc-files/cssref.html CSS Reference Guide]].
- *
- * @return The URL of the user-agent stylesheet that will be used by this SubScene, or null if has not been set.
- */
- def userAgentStylesheet: ObjectProperty[String] =
- delegate.userAgentStylesheetProperty
-
- /**
- * Set the URL of the user-agent stylesheet that will be used by this Scene in place of the the platform-default
- * user-agent stylesheet. If the URL does not resolve to a valid location, the platform-default user-agent
- * stylesheet will be used.
- *
- * For additional information about using CSS with the scene graph, see the
- * [[http://docs.oracle.com/javase/8/javafx/api/javafx/scene/doc-files/cssref.html CSS Reference Guide]].
- *
- * @param url The URL is a hierarchical URI of the form `[scheme:][//authority][path]`.
- * If the URL does not have a `[scheme:]` component, the URL is considered to be the `[path]`
- * component only. Any leading '/' character of the `[path]` is ignored and the `[path]` is
- * treated as a path relative to the root of the application's classpath.
- */
- def userAgentStylesheet_=(url: String): Unit = {
- ObjectProperty.fillProperty[String](userAgentStylesheet, url)
- }
-
- /**
- * The `Window` for this Scene
- */
- def window: ReadOnlyObjectProperty[javafx.stage.Window] =
- delegate.windowProperty
-
- /**
- * The horizontal location of this `Scene` on the `Window`.
- */
- def x: ReadOnlyDoubleProperty = delegate.xProperty
-
- /**
- * The vertical location of this `Scene` on the `Window`.
- */
- def y: ReadOnlyDoubleProperty = delegate.yProperty
-
- /**
- * Retrieves the depth buffer attribute for this scene.
- */
- def depthBuffer = delegate.isDepthBuffer
-
- /**
- * Gets an observable list of string URLs linking to the stylesheets to use with this Parent's contents.
- */
- def stylesheets: jfxc.ObservableList[String] = delegate.getStylesheets
-
- /**
- * Sets the list of stylesheets URLs, replacing the prior content. If you want append to current content, use `add` or
- * similar.
- *
- * @param c list of stylesheets URLs to replace prior content.
- */
- def stylesheets_=(c: Iterable[String]): Unit = {
- fillCollection(stylesheets, c)
- }
-
- /**
- * Looks for any node within the scene graph based on the specified CSS selector.
- *
- * @param selector The css selector to look up
- * @return A [[scala.Some]] containing the Node in the scene which matches the CSS selector, or [[scala.None]]
- * if none is found.
- */
- def lookup(selector: String): Option[Node] = Option(delegate.lookup(selector))
-
- /**
- * Registers the specified mnemonic.
- *
- * @param m The Mnemonic
- */
- def addMnemonic(m: Mnemonic): Unit = {
- delegate.addMnemonic(m)
- }
-
- /**
- * Unregisters the specified mnemonic.
- *
- * @param m The Mnemonic to be removed.
- */
- def removeMnemonic(m: Mnemonic): Unit = {
- delegate.removeMnemonic(m)
- }
-
- /**
- * Gets the list of mnemonics for this `Scene`.
- */
- def getMnemonics
- : jfxc.ObservableMap[jfxsi.KeyCombination, jfxc.ObservableList[
- jfxsi.Mnemonic
- ]] = delegate.getMnemonics
-
- /**
- * Gets the list of accelerators for this Scene.
- */
- def accelerators: jfxc.ObservableMap[jfxsi.KeyCombination, Runnable] =
- delegate.getAccelerators
-
- /**
- * Confirms a potential drag and drop gesture that is recognized over this `Scene`.
- *
- * @param transferModes The supported `TransferMode`(s) of this `Node`
- * @return A `Dragboard` to place this `Scene`'s data on
- */
- def startDragAndDrop(transferModes: TransferMode*): Dragboard =
- delegate.startDragAndDrop(transferModes.map(_.delegate): _*)
-
- /**
- * Starts a full press-drag-release gesture with this scene as gesture source.
- */
- def startFullDrag(): Unit = {
- delegate.startFullDrag()
- }
-
- /**
- * The scene's current focus owner node. This node's "focused" variable might be false if this scene has no window,
- * or if the window is inactive (window.focused == false).
- *
- * @since 2.2
- */
- def focusOwner: ReadOnlyObjectProperty[jfxs.Node] =
- delegate.focusOwnerProperty()
-
- /**
- * Defines a function to be called when user performs a rotation action.
- *
- * @since 2.2
- */
- def onRotate = delegate.onRotateProperty
-
- def onRotate_=(v: jfxe.EventHandler[_ >: jfxsi.RotateEvent]): Unit = {
- onRotate() = v
- }
-
- /**
- * Defines a function to be called when a rotation gesture ends.
- *
- * @since 2.2
- */
- def onRotationFinished = delegate.onRotationFinishedProperty()
-
- def onRotationFinished_=(
- v: jfxe.EventHandler[_ >: jfxsi.RotateEvent]
- ): Unit = {
- onRotationFinished() = v
- }
-
- /**
- * Defines a function to be called when a rotation gesture starts.
- *
- * @since 2.2
- */
- def onRotationStarted = delegate.onRotationFinishedProperty()
-
- def onRotationStarted_=(
- v: jfxe.EventHandler[_ >: jfxsi.RotateEvent]
- ): Unit = {
- onRotationStarted() = v
- }
-
- /**
- * Defines a function to be called when a Scroll gesture ends.
- *
- * @since 2.2
- */
- def onScrollFinished = delegate.onScrollFinishedProperty()
-
- def onScrollFinished_=(v: jfxe.EventHandler[_ >: jfxsi.ScrollEvent]): Unit = {
- onScrollFinished() = v
- }
-
- /**
- * Defines a function to be called when a Scroll gesture starts.
- *
- * @since 2.2
- */
- def onScrollStarted = delegate.onScrollStartedProperty()
-
- def onScrollStarted_=(v: jfxe.EventHandler[_ >: jfxsi.ScrollEvent]): Unit = {
- onScrollStarted() = v
- }
-
- /**
- * Defines a function to be called when a Swipe Down gesture starts.
- *
- * @since 2.2
- */
- def onSwipeDown = delegate.onSwipeDownProperty()
-
- def onSwipeDown_=(v: jfxe.EventHandler[_ >: jfxsi.SwipeEvent]): Unit = {
- onSwipeDown() = v
- }
-
- /**
- * Defines a function to be called when a Swipe Down gesture starts.
- *
- * @since 2.2
- */
- def onSwipeLeft = delegate.onSwipeLeftProperty()
-
- def onSwipeLeft_=(v: jfxe.EventHandler[_ >: jfxsi.SwipeEvent]): Unit = {
- onSwipeLeft() = v
- }
-
- /**
- * Defines a function to be called when a Swipe Up gesture starts.
- *
- * @since 2.2
- */
- def onSwipeUp = delegate.onSwipeUpProperty()
-
- def onSwipeUp_=(v: jfxe.EventHandler[_ >: jfxsi.SwipeEvent]): Unit = {
- onSwipeUp() = v
- }
-
- /**
- * Defines a function to be called when a Swipe Right gesture starts.
- *
- * @since 2.2
- */
- def onSwipeRight = delegate.onSwipeRightProperty()
-
- def onSwipeRight_=(v: jfxe.EventHandler[_ >: jfxsi.SwipeEvent]): Unit = {
- onSwipeRight() = v
- }
-
- /**
- * Defines a function to be called when user performs a Touch action.
- *
- * @since 2.2
- */
- def onZoom = delegate.onZoomProperty()
-
- def onZoom_=(v: jfxe.EventHandler[_ >: jfxsi.ZoomEvent]): Unit = {
- onZoom() = v
- }
-
- /**
- * Defines a function to be called when a Zoom gesture ends.
- *
- * @since 2.2
- */
- def onZoomFinished = delegate.onZoomFinishedProperty()
-
- def onZoomFinished_=(v: jfxe.EventHandler[_ >: jfxsi.ZoomEvent]): Unit = {
- onZoomFinished() = v
- }
-
- /**
- * Defines a function to be called when a Zoom gesture starts.
- *
- * @since 2.2
- */
- def onZoomStarted = delegate.onZoomStartedProperty()
-
- def onZoomStarted_=(v: jfxe.EventHandler[_ >: jfxsi.ZoomEvent]): Unit = {
- onZoomStarted() = v
- }
-
- /**
- * Defines a function to be called when user performs a Touch Moved action.
- *
- * @since 2.2
- */
- def onTouchMoved = delegate.onTouchMovedProperty()
-
- def onTouchMoved_=(v: jfxe.EventHandler[_ >: jfxsi.TouchEvent]): Unit = {
- onTouchMoved() = v
- }
-
- /**
- * Defines a function to be called when user performs a Touch Pressed action.
- *
- * @since 2.2
- */
- def onTouchPressed = delegate.onTouchPressedProperty()
-
- def onTouchPressed_=(v: jfxe.EventHandler[_ >: jfxsi.TouchEvent]): Unit = {
- onTouchPressed() = v
- }
-
- /**
- * Defines a function to be called when user performs a Touch Released action.
- *
- * @since 2.2
- */
- def onTouchReleased = delegate.onTouchReleasedProperty()
-
- def onTouchReleased_=(v: jfxe.EventHandler[_ >: jfxsi.TouchEvent]): Unit = {
- onTouchReleased() = v
- }
-
- /**
- * Defines a function to be called when user performs a Touch Stationary action.
- *
- * @since 2.2
- */
- def onTouchStationary = delegate.onTouchStationaryProperty()
-
- def onTouchStationary_=(v: jfxe.EventHandler[_ >: jfxsi.TouchEvent]): Unit = {
- onTouchStationary() = v
- }
-
- /**
- * Takes a snapshot of this scene and returns the rendered image when it is ready.
- *
- * @param image The writable image that will be used to hold the rendered scene.
- * @return the rendered image
- *
- * @since 2.2
- */
- def snapshot(image: WritableImage): WritableImage = delegate.snapshot(image)
-
- /**
- * Takes a snapshot of this scene at the next frame and calls the specified callback method when the image is ready.
- *
- * @param callback A function to be called when the image is ready.
- * @param image The writable image that will be used to hold the rendered scene.
- *
- * @since 2.2
- */
- def snapshot(callback: SnapshotResult => Unit, image: WritableImage): Unit = {
- val javaCallback = new jfxu.Callback[jfxs.SnapshotResult, java.lang.Void] {
- def call(result: jfxs.SnapshotResult): java.lang.Void = {
- callback(new SnapshotResult(result))
- null
- }
- }
- delegate.snapshot(javaCallback, image)
- }
-
-}
diff --git a/src/main/scala/wow/doge/mygame/utils/GenericConsoleStream.scala b/src/main/scala/wow/doge/mygame/utils/GenericConsoleStream.scala
index 3b1ac28..e4afd5a 100644
--- a/src/main/scala/wow/doge/mygame/utils/GenericConsoleStream.scala
+++ b/src/main/scala/wow/doge/mygame/utils/GenericConsoleStream.scala
@@ -4,10 +4,8 @@ import java.io.ByteArrayOutputStream
import java.io.OutputStream
import java.io.PrintStream
-import cats.effect.Resource
-import monix.bio.Task
-import scalafx.scene.control.TextArea
import scalafx.application.Platform
+import scalafx.scene.control.TextArea
trait ConsoleStreamable[T] {
def println(inst: T, text: String): Unit
@@ -18,7 +16,8 @@ class GenericConsoleStream[T](
outputStream: OutputStream,
val config: GenericConsoleStream.Config =
GenericConsoleStream.Config.default,
- private var streamable: Option[T] = None
+ // TODO make this atomic
+ private var _streamable: Option[T] = None
)(implicit
cs: ConsoleStreamable[T]
) extends PrintStream(outputStream, true) {
@@ -29,26 +28,24 @@ class GenericConsoleStream[T](
override def println(text: String): Unit =
if (config.exclusive) {
- printToStreamable(streamable, text)
+ printToStreamable(_streamable, text)
} else {
defaultOut.println(text)
- printToStreamable(streamable, text)
+ printToStreamable(_streamable, text)
}
override def print(text: String): Unit =
- streamable.foreach(s =>
- if (config.exclusive) {
- printToStreamable(streamable, text)
- } else {
- defaultOut.println(text)
- printToStreamable(streamable, text)
- }
- )
+ if (config.exclusive) {
+ printToStreamable(_streamable, text)
+ } else {
+ defaultOut.println(text)
+ printToStreamable(_streamable, text)
+ }
def :=(s: T) = {
- streamable match {
+ _streamable match {
case Some(value) =>
- case None => streamable = Some(s)
+ case None => _streamable = Some(s)
}
}
}
@@ -64,41 +61,25 @@ object GenericConsoleStream {
}
implicit val implJFXConsoleStreamForTextArea =
- new ConsoleStreamable[scalafx.scene.control.TextArea] {
+ new ConsoleStreamable[TextArea] {
override def println(
- ta: scalafx.scene.control.TextArea,
+ ta: TextArea,
text: String
): Unit =
- ta.appendText(text + "\n")
+ Platform.runLater(() => ta.appendText(text + "\n"))
override def print(
- ta: scalafx.scene.control.TextArea,
+ ta: TextArea,
text: String
): Unit =
- ta.appendText(text)
+ Platform.runLater(() => ta.appendText(text))
}
- // def textAreaStreamResource(ta: TextArea) =
- // Resource.make(
- // Task(
- // new GenericConsoleStream(
- // outputStream = new ByteArrayOutputStream(),
- // streamable = ta
- // )
- // )
- // )(s => Task(s.close()))
-
- def textAreaStream(
- // ta: TextArea
- ) =
- // Task(
+ def textAreaStream() =
new GenericConsoleStream[TextArea](
outputStream = new ByteArrayOutputStream()
- // streamable = ta
)
- // )
- // (s => Task(s.close()))
}