package wow.doge.mygame.game.entities import akka.actor.typed.ActorRef import akka.actor.typed.DispatcherSelector import com.jme3.bullet.control.BetterCharacterControl import com.jme3.renderer.Camera import com.jme3.scene.CameraNode import com.jme3.scene.Geometry import com.jme3.scene.Node import com.jme3.scene.Spatial 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.AppError import wow.doge.mygame.executors.Schedulers.AsyncScheduler import wow.doge.mygame.game.GameApp import wow.doge.mygame.implicits._ import wow.doge.mygame.math.ImVector3f import wow.doge.mygame.subsystems.events.EventsModule.GameEventBus import wow.doge.mygame.subsystems.events.PlayerEvent import wow.doge.mygame.subsystems.events.TickEvent import wow.doge.mygame.subsystems.movement.ImMovementActor import wow.doge.mygame.types._ import wow.doge.mygame.utils.wrappers.jme._ object PlayerController { sealed trait Error case class CouldNotCreatePlayerModel(reason: AssetManager.Error) extends Error object Tags { sealed trait PlayerNode sealed trait PlayerCameraNode sealed trait PlayerCameraPivotNode } type PlayerNode = Node @@ Tags.PlayerNode type PlayerCameraNode = CameraNode @@ Tags.PlayerCameraNode type PlayerCameraPivotNode = Node @@ Tags.PlayerCameraPivotNode class Props( gameApp: GameApp, enqueueR: Function1[() => Unit, Unit], rootNode: RootNode, loggerL: Logger[Task], physicsSpace: PhysicsSpace, initialPlayerPos: ImVector3f, playerEventBus: GameEventBus[PlayerEvent], playerPhysicsControl: BetterCharacterControl, // appScheduler: monix.execution.Scheduler, scheduler: AsyncScheduler, playerNode: PlayerNode, cameraNode: PlayerCameraNode, cameraPivotNode: PlayerCameraPivotNode, tickEventBus: GameEventBus[TickEvent], camera: Camera ) { val playerActorBehavior = { val movementActorBeh = new ImMovementActor.Props( enqueueR, camera ).behavior(playerPhysicsControl) new PlayerActorSupervisor.Props( playerEventBus, tickEventBus, movementActorBeh, scheduler ).behavior } val playerActor = gameApp.spawnGameActor( playerActorBehavior, // Some("playerActorSupervisor"), props = DispatcherSelector.default() ) val create: IO[AppError, ActorRef[PlayerActorSupervisor.Command]] = (for { // playerActor <- // // AkkaUtils.spawnActorL(playerActorBehavior, "playerActorSupervisor") // gameApp.spawnGameActor( // playerActorBehavior, // Some("playerActorSupervisor"), // props = DispatcherSelector.default() // ) pa <- playerActor _ <- (for { _ <- rootNode += playerNode _ <- physicsSpace += playerNode _ <- physicsSpace += playerPhysicsControl _ = cameraPivotNode += cameraNode _ <- rootNode += cameraPivotNode } yield ()).mapError(AppError.AppNodeError) } yield pa) } object Defaults { def defaultMesh = { val b = Box(1, 1, 1) val geom = Geometry("playerGeom", b) geom } def defaultCamerNode( cam: Camera, // playerNode: Node, // cameraPivotNode: Node, playerPos: ImVector3f ) = new CameraNode("CameraNode", cam) // .withControlDir(ControlDirection.SpatialToCamera) .withLocalTranslation(ImVector3f(0, 1.5f, 10)) .withLookAt(playerPos, ImVector3f.UnitY) def defaultPlayerNode( playerPos: ImVector3f, playerModel: Node, // camNode: CameraNode, playerPhysicsControl: BetterCharacterControl ) = Node("PlayerNode") .withChildren(playerModel) .withLocalTranslation(playerPos) .withControl(playerPhysicsControl) .taggedWith[Tags.PlayerNode] def defaultNpcNode( // assetManager: AssetManager, npcModel: Spatial, initialPos: ImVector3f, npcPhysicsControl: BetterCharacterControl, npcName: String ) = // Either // .catchNonFatal( Node(npcName) .withChildren( // defaultMesh.withMaterial(defaultTexture(assetManager)) npcModel ) .withLocalTranslation(initialPos) .withControl(npcPhysicsControl) // ) def defaultPlayerPhysicsControl = new BetterCharacterControl(1.5f, 6f, 1f) .withJumpForce(ImVector3f(0, 5f, 0)) } }