forked from nova/jmonkey-test
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.
201 lines
5.7 KiB
201 lines
5.7 KiB
package wow.doge.mygame.game.nodes
|
|
|
|
import akka.actor.typed.scaladsl.Behaviors
|
|
import akka.actor.typed.scaladsl.ActorContext
|
|
import wow.doge.mygame.subsystems.movement.ImMovementActor
|
|
import wow.doge.mygame.game.GameApp
|
|
import akka.actor.typed.ActorRef
|
|
import wow.doge.mygame.events.EventBus
|
|
import wow.doge.mygame.subsystems.events.EntityMovementEvent.PlayerMovementEvent
|
|
import wow.doge.mygame.subsystems.events.EntityMovementEvent
|
|
import akka.actor.typed.scaladsl.TimerScheduler
|
|
import akka.actor.typed.Behavior
|
|
import scala.concurrent.duration._
|
|
import akka.actor.typed.LogOptions
|
|
import org.slf4j.event.Level
|
|
import com.typesafe.scalalogging.Logger
|
|
import akka.actor.typed.SupervisorStrategy
|
|
import com.jme3.scene.CameraNode
|
|
import wow.doge.mygame.subsystems.events.PlayerCameraEvent
|
|
import wow.doge.mygame.game.subsystems.movement.CanMove
|
|
import wow.doge.mygame.implicits._
|
|
|
|
object PlayerActorSupervisor {
|
|
sealed trait Command
|
|
|
|
final case class Props(
|
|
app: GameApp,
|
|
camNode: CameraNode,
|
|
playerMovementEventBus: ActorRef[
|
|
EventBus.Command[PlayerMovementEvent]
|
|
],
|
|
playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]]
|
|
) {
|
|
def create[T: CanMove](movable: T) =
|
|
Behaviors.logMessages(
|
|
LogOptions()
|
|
.withLevel(Level.TRACE)
|
|
.withLogger(
|
|
Logger[PlayerActorSupervisor[T]].underlying
|
|
),
|
|
Behaviors.setup[Command] { ctx =>
|
|
ctx.log.info("Hello from PlayerActor")
|
|
|
|
// spawn children actors
|
|
lazy val movementActor =
|
|
ctx.spawn(
|
|
Behaviors
|
|
.supervise(
|
|
ImMovementActor
|
|
.Props(app, movable, playerMovementEventBus)
|
|
.create
|
|
)
|
|
.onFailure[Exception](SupervisorStrategy.restart),
|
|
"playerMovementActor"
|
|
)
|
|
lazy val playerMovementEventHandler = ctx.spawn(
|
|
Behaviors
|
|
.supervise(PlayerMovementEventListener(movementActor))
|
|
.onFailure[Exception](SupervisorStrategy.restart),
|
|
"playerMovementEventHandler"
|
|
)
|
|
lazy val movementActorTimer = ctx.spawn(
|
|
Behaviors
|
|
.supervise(MovementActorTimer(movementActor))
|
|
.onFailure[Exception](SupervisorStrategy.restart),
|
|
"playerMovementActorTimer"
|
|
)
|
|
|
|
lazy val playerCameraHandler = {
|
|
ctx.spawn(
|
|
Behaviors
|
|
.supervise(
|
|
PlayerCameraEventListener(camNode, app.enqueueR)
|
|
)
|
|
.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)
|
|
).receive
|
|
}
|
|
)
|
|
}
|
|
|
|
case class Children(
|
|
movementActor: ActorRef[ImMovementActor.Command],
|
|
playerMovementEventHandler: ActorRef[
|
|
EntityMovementEvent.PlayerMovementEvent
|
|
]
|
|
)
|
|
}
|
|
class PlayerActorSupervisor[T: CanMove](
|
|
ctx: ActorContext[PlayerActorSupervisor.Command],
|
|
props: PlayerActorSupervisor.Props,
|
|
children: PlayerActorSupervisor.Children
|
|
) {
|
|
import PlayerActorSupervisor._
|
|
def receive =
|
|
Behaviors.receiveMessage[Command] {
|
|
case _ =>
|
|
// children.movementActor ! ImMovementActor.MovedDown(true)
|
|
Behaviors.same
|
|
}
|
|
}
|
|
|
|
object MovementActorTimer {
|
|
sealed trait Command
|
|
final case object Start extends Command
|
|
final case object Stop extends Command
|
|
private case object Send extends Command
|
|
case object TimerKey
|
|
|
|
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._
|
|
|
|
val idle: Behavior[Command] =
|
|
Behaviors.receiveMessage { msg =>
|
|
msg match {
|
|
case Start =>
|
|
timers.startTimerWithFixedDelay(TimerKey, Send, (60f / 144).millis)
|
|
active
|
|
case _ => Behaviors.unhandled
|
|
}
|
|
}
|
|
|
|
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 {
|
|
sealed trait Command
|
|
final case object Start extends Command
|
|
final case object Stop extends Command
|
|
private case object Send extends Command
|
|
case object TimerKey
|
|
|
|
case class Props[T](
|
|
target: ActorRef[T],
|
|
messageToSend: T,
|
|
timeInterval: FiniteDuration
|
|
) {
|
|
val create = Behaviors.withTimers[Command] { timers =>
|
|
new GenericTimerActor(timers, this).idle
|
|
}
|
|
}
|
|
}
|
|
class GenericTimerActor[T](
|
|
timers: TimerScheduler[GenericTimerActor.Command],
|
|
props: GenericTimerActor.Props[T]
|
|
) {
|
|
import GenericTimerActor._
|
|
|
|
val idle: Behavior[Command] =
|
|
Behaviors.receiveMessage {
|
|
case Start =>
|
|
timers.startTimerWithFixedDelay(TimerKey, Send, props.timeInterval)
|
|
active
|
|
case _ => Behaviors.unhandled
|
|
|
|
}
|
|
|
|
val active: Behavior[Command] =
|
|
Behaviors.receiveMessagePartial {
|
|
case Send =>
|
|
props.target ! props.messageToSend
|
|
Behaviors.same
|
|
case Stop =>
|
|
timers.cancel(TimerKey)
|
|
idle
|
|
}
|
|
}
|