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