You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
4.1 KiB
130 lines
4.1 KiB
package wow.doge.mygame.game
|
|
|
|
import scala.concurrent.duration._
|
|
|
|
import akka.actor.typed.ActorRef
|
|
import akka.actor.typed.Behavior
|
|
import akka.actor.typed.Props
|
|
import akka.actor.typed.SpawnProtocol
|
|
import akka.actor.typed.scaladsl.AskPattern._
|
|
import akka.util.Timeout
|
|
import cats.effect.Resource
|
|
import com.jme3.bullet.BulletAppState
|
|
import com.jme3.input.InputManager
|
|
import com.jme3.system.AppSettings
|
|
import com.softwaremill.tagging._
|
|
import io.odin.Logger
|
|
import monix.bio.Fiber
|
|
import monix.bio.IO
|
|
import monix.bio.Task
|
|
import monix.bio.UIO
|
|
import wow.doge.mygame.AppError
|
|
import wow.doge.mygame.AppError.TimeoutError
|
|
import wow.doge.mygame.Dispatchers
|
|
import wow.doge.mygame.executors.JMERunner
|
|
import wow.doge.mygame.executors.Schedulers
|
|
import wow.doge.mygame.game.subsystems.ui.JFxUI
|
|
import wow.doge.mygame.implicits._
|
|
import wow.doge.mygame.subsystems.events.EventsModule.GameEventBus
|
|
import wow.doge.mygame.subsystems.events.TickEvent
|
|
import wow.doge.mygame.types._
|
|
import wow.doge.mygame.utils.AkkaUtils
|
|
import wow.doge.mygame.utils.wrappers.jme._
|
|
object GameAppTags {
|
|
sealed trait RootNode
|
|
sealed trait GuiNode
|
|
}
|
|
|
|
class GameApp private[game] (
|
|
logger: Logger[Task],
|
|
app: SimpleAppExt,
|
|
gameActor: ActorRef[GameAppActor.Command],
|
|
gameSpawnProtocol: ActorRef[SpawnProtocol.Command],
|
|
akkaScheduler: AkkaScheduler
|
|
) {
|
|
def inputManager: UIO[InputManager] = UIO(app.getInputManager())
|
|
val assetManager = new AssetManager(app.getAssetManager())
|
|
val guiNode: GuiNode =
|
|
AppNode2(app.getGuiNode()).taggedWith[GameAppTags.GuiNode]
|
|
// def flyCam = Option(app.getFlyByCamera())
|
|
def camera = UIO(app.getCamera())
|
|
def viewPort = UIO(app.getViewPort())
|
|
val rootNode: RootNode =
|
|
AppNode2(app.getRootNode()).taggedWith[GameAppTags.RootNode]
|
|
val physicsSpace =
|
|
new PhysicsSpace(app.bulletAppState.physicsSpace)
|
|
def enqueue(cb: () => Unit) = app.enqueueR(() => cb())
|
|
def enqueueL[T](cb: () => T): Task[T] = app.enqueueL(cb)
|
|
|
|
def whenTerminated: IO[AppError, Unit] =
|
|
IO.deferFuture(app.whenTerminated).onErrorHandleWith(TimeoutError.from)
|
|
|
|
def spawnGameActor[T](
|
|
behavior: Behavior[T],
|
|
actorName: Option[String] = None,
|
|
props: Props = Dispatchers.jmeDispatcher
|
|
)(implicit name: sourcecode.Name) =
|
|
AkkaUtils.spawnActorL(behavior, actorName, props)(
|
|
2.seconds,
|
|
akkaScheduler.value,
|
|
gameSpawnProtocol,
|
|
name
|
|
)
|
|
|
|
def scheduler = JmeScheduler(app.scheduler)
|
|
def jfxUI = JFxUI(app)
|
|
|
|
}
|
|
|
|
class GameAppResource(
|
|
logger: Logger[Task],
|
|
jmeThread: JmeScheduler,
|
|
schedulers: Schedulers,
|
|
tickEventBus: GameEventBus[TickEvent]
|
|
)(implicit
|
|
timeout: Timeout,
|
|
scheduler: AkkaScheduler,
|
|
spawnProtocol: ActorRef[SpawnProtocol.Command]
|
|
) {
|
|
implicit val as = scheduler.value
|
|
def resource
|
|
: Resource[UIO, Either[AppError, (GameApp, Fiber[Nothing, Unit])]] =
|
|
Resource.make(
|
|
(for {
|
|
app <- UIO(new SimpleAppExt(schedulers, new BulletAppState))
|
|
_ <- UIO(JMERunner.runner = app)
|
|
_ <- UIO {
|
|
val settings = new AppSettings(true)
|
|
settings.setVSync(true)
|
|
|
|
/**
|
|
* disables the launcher
|
|
* We'll be making our own launcher anyway
|
|
*/
|
|
app.setShowSettings(false)
|
|
app.setSettings(settings)
|
|
}
|
|
|
|
fib <- UIO(app.start).executeOn(jmeThread.value).start
|
|
_ <- Task.deferFuture(app.started).onErrorHandleWith(TimeoutError.from)
|
|
gameAppActor <- AkkaUtils.spawnActorL(
|
|
new GameAppActor.Props(tickEventBus).behavior,
|
|
Some("testGameActor"),
|
|
props = Dispatchers.jmeDispatcher
|
|
)
|
|
_ <- gameAppActor !! GameAppActor.Start
|
|
sp <-
|
|
gameAppActor
|
|
.askL(GameAppActor.GetSpawnProtocol)
|
|
.onErrorHandleWith(TimeoutError.from)
|
|
gameApp <- UIO(new GameApp(logger, app, gameAppActor, sp, scheduler))
|
|
_ <- UIO {
|
|
val fut = () => gameAppActor.ask(GameAppActor.Stop).flatten
|
|
app.cancelToken = Some(fut)
|
|
}
|
|
} yield (gameApp, fib)).attempt
|
|
) {
|
|
case Right(gameApp -> fib) => fib.cancel
|
|
case Left(error) => IO.terminate(new Exception(error.toString))
|
|
}
|
|
}
|