Update player actor
Make stats observable hot Remove concurrentsubject
This commit is contained in:
parent
92aae68254
commit
1422d91b14
@ -377,6 +377,7 @@ class MainAppDelegate(
|
|||||||
playerActor
|
playerActor
|
||||||
.askL(PlayerActorSupervisor.GetStatsObservable(_))
|
.askL(PlayerActorSupervisor.GetStatsObservable(_))
|
||||||
.onErrorHandleWith(TimeoutError.from)
|
.onErrorHandleWith(TimeoutError.from)
|
||||||
|
.flatten
|
||||||
playerHud <-
|
playerHud <-
|
||||||
UIO
|
UIO
|
||||||
.deferAction(implicit s =>
|
.deferAction(implicit s =>
|
||||||
@ -391,7 +392,6 @@ class MainAppDelegate(
|
|||||||
children = List(
|
children = List(
|
||||||
new Label("Health") { textFill = Color.White },
|
new Label("Health") { textFill = Color.White },
|
||||||
new Label("100") {
|
new Label("100") {
|
||||||
text == "hello"
|
|
||||||
text <-- statsObs
|
text <-- statsObs
|
||||||
.doOnNextF(i => loggerL.debug(show"Received stats: $i"))
|
.doOnNextF(i => loggerL.debug(show"Received stats: $i"))
|
||||||
.map(_.hp.toInt.toString)
|
.map(_.hp.toInt.toString)
|
||||||
@ -504,6 +504,7 @@ class MainAppDelegate(
|
|||||||
.hideErrors
|
.hideErrors
|
||||||
.startAndForget
|
.startAndForget
|
||||||
sched <- UIO.pure(schedulers.async)
|
sched <- UIO.pure(schedulers.async)
|
||||||
|
fxSched <- UIO.pure(schedulers.fx)
|
||||||
playerActor <- wire[PlayerController.Props].create
|
playerActor <- wire[PlayerController.Props].create
|
||||||
} yield playerActor
|
} yield playerActor
|
||||||
}
|
}
|
||||||
|
@ -6,28 +6,15 @@ import scala.util.Success
|
|||||||
|
|
||||||
import akka.actor.typed.ActorRef
|
import akka.actor.typed.ActorRef
|
||||||
import akka.actor.typed.Behavior
|
import akka.actor.typed.Behavior
|
||||||
import akka.actor.typed.SupervisorStrategy
|
|
||||||
import akka.actor.typed.scaladsl.ActorContext
|
import akka.actor.typed.scaladsl.ActorContext
|
||||||
import akka.actor.typed.scaladsl.Behaviors
|
import akka.actor.typed.scaladsl.Behaviors
|
||||||
import akka.util.Timeout
|
import akka.util.Timeout
|
||||||
import cats.syntax.eq._
|
|
||||||
import cats.syntax.show._
|
import cats.syntax.show._
|
||||||
import monix.execution.CancelableFuture
|
import monix.execution.CancelableFuture
|
||||||
import monix.execution.CancelablePromise
|
import monix.execution.CancelablePromise
|
||||||
import wow.doge.mygame.game.subsystems.movement.CanMove
|
import wow.doge.mygame.game.subsystems.movement.CanMove
|
||||||
import wow.doge.mygame.implicits._
|
import wow.doge.mygame.implicits._
|
||||||
import wow.doge.mygame.math.ImVector3f
|
import wow.doge.mygame.math.ImVector3f
|
||||||
import wow.doge.mygame.subsystems.events.EntityMovementEvent
|
|
||||||
import wow.doge.mygame.subsystems.events.EntityMovementEvent.MovedDown
|
|
||||||
import wow.doge.mygame.subsystems.events.EntityMovementEvent.MovedLeft
|
|
||||||
import wow.doge.mygame.subsystems.events.EntityMovementEvent.MovedRight
|
|
||||||
import wow.doge.mygame.subsystems.events.EntityMovementEvent.MovedUp
|
|
||||||
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.utils.GenericTimerActor
|
import wow.doge.mygame.utils.GenericTimerActor
|
||||||
|
|
||||||
object NpcActorSupervisor {
|
object NpcActorSupervisor {
|
||||||
@ -236,76 +223,3 @@ class NpcMovementActor[T](
|
|||||||
Behaviors.same
|
Behaviors.same
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object NpcMovementActorNotUsed {
|
|
||||||
sealed trait Command
|
|
||||||
class Props(
|
|
||||||
imMovementActorBehavior: Behavior[ImMovementActor.Command],
|
|
||||||
npcName: String,
|
|
||||||
// movementActor: ActorRef[ImMovementActor.Command],
|
|
||||||
mainEventBus: ActorRef[
|
|
||||||
EventBus.Command[Event]
|
|
||||||
],
|
|
||||||
tickEventBus: GameEventBus[TickEvent]
|
|
||||||
) {
|
|
||||||
|
|
||||||
def behavior: Behavior[Command] =
|
|
||||||
Behaviors.setup { ctx =>
|
|
||||||
val movementActor = ctx.spawn(
|
|
||||||
Behaviors
|
|
||||||
.supervise(imMovementActorBehavior)
|
|
||||||
.onFailure[Exception](
|
|
||||||
SupervisorStrategy.restart.withLimit(2, 100.millis)
|
|
||||||
),
|
|
||||||
s"npc-${npcName}-MovementActorChild"
|
|
||||||
)
|
|
||||||
val npcMovementElBehavior = Behaviors.receiveMessagePartial[Event] {
|
|
||||||
case event: EntityMovementEvent =>
|
|
||||||
event match {
|
|
||||||
case MovedLeft(name, pressed) =>
|
|
||||||
if (name === npcName)
|
|
||||||
movementActor ! ImMovementActor.MoveLeft(pressed)
|
|
||||||
Behaviors.same
|
|
||||||
case MovedUp(name, pressed) =>
|
|
||||||
if (name === npcName)
|
|
||||||
movementActor ! ImMovementActor.MoveUp(pressed)
|
|
||||||
Behaviors.same
|
|
||||||
case MovedRight(name, pressed) =>
|
|
||||||
if (name === npcName)
|
|
||||||
movementActor ! ImMovementActor.MoveRight(pressed)
|
|
||||||
Behaviors.same
|
|
||||||
case MovedDown(name, pressed) =>
|
|
||||||
if (name === npcName)
|
|
||||||
movementActor ! ImMovementActor.MoveDown(pressed)
|
|
||||||
Behaviors.same
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val npcMovementEl = ctx.spawn(
|
|
||||||
Behaviors
|
|
||||||
.supervise(npcMovementElBehavior)
|
|
||||||
.onFailure[Exception](
|
|
||||||
SupervisorStrategy.restart.withLimit(2, 100.millis)
|
|
||||||
),
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -14,11 +14,8 @@ import akka.actor.typed.scaladsl.Behaviors
|
|||||||
import akka.util.Timeout
|
import akka.util.Timeout
|
||||||
import cats.syntax.show._
|
import cats.syntax.show._
|
||||||
import com.typesafe.scalalogging.Logger
|
import com.typesafe.scalalogging.Logger
|
||||||
import monix.eval.Coeval
|
|
||||||
import monix.execution.AsyncQueue
|
import monix.execution.AsyncQueue
|
||||||
import monix.reactive.Observable
|
import monix.reactive.Observable
|
||||||
import monix.reactive.OverflowStrategy
|
|
||||||
import monix.reactive.subjects.ConcurrentSubject
|
|
||||||
import org.slf4j.event.Level
|
import org.slf4j.event.Level
|
||||||
import wow.doge.mygame.Dispatchers
|
import wow.doge.mygame.Dispatchers
|
||||||
import wow.doge.mygame.executors.Schedulers.AsyncScheduler
|
import wow.doge.mygame.executors.Schedulers.AsyncScheduler
|
||||||
@ -30,6 +27,8 @@ import wow.doge.mygame.subsystems.events.PlayerEvent
|
|||||||
import wow.doge.mygame.subsystems.events.TickEvent
|
import wow.doge.mygame.subsystems.events.TickEvent
|
||||||
import wow.doge.mygame.subsystems.events.TickEvent.RenderTick
|
import wow.doge.mygame.subsystems.events.TickEvent.RenderTick
|
||||||
import wow.doge.mygame.subsystems.movement.ImMovementActor
|
import wow.doge.mygame.subsystems.movement.ImMovementActor
|
||||||
|
import wow.doge.mygame.executors.Schedulers
|
||||||
|
import monix.bio.UIO
|
||||||
object PlayerActorSupervisor {
|
object PlayerActorSupervisor {
|
||||||
|
|
||||||
type Ref = ActorRef[PlayerActorSupervisor.Command]
|
type Ref = ActorRef[PlayerActorSupervisor.Command]
|
||||||
@ -54,7 +53,7 @@ object PlayerActorSupervisor {
|
|||||||
extends Command
|
extends Command
|
||||||
final case class GetStatus(replyTo: ActorRef[Status]) extends Command
|
final case class GetStatus(replyTo: ActorRef[Status]) extends Command
|
||||||
final case class GetStatsObservable(
|
final case class GetStatsObservable(
|
||||||
replyTo: ActorRef[Observable[CharacterStats]]
|
replyTo: ActorRef[UIO[Observable[CharacterStats]]]
|
||||||
) extends Command
|
) extends Command
|
||||||
|
|
||||||
private case object Die extends Command
|
private case object Die extends Command
|
||||||
@ -62,13 +61,13 @@ object PlayerActorSupervisor {
|
|||||||
response: (Boolean, CharacterStats),
|
response: (Boolean, CharacterStats),
|
||||||
replyTo: ActorRef[Unit]
|
replyTo: ActorRef[Unit]
|
||||||
) extends Command
|
) extends Command
|
||||||
// private final case class InternalTakeDamage(old: Int, value: Int) extends Command
|
|
||||||
private final case class LogError(ex: Throwable) extends Command
|
private final case class LogError(ex: Throwable) extends Command
|
||||||
class Props(
|
class Props(
|
||||||
val playerEventBus: GameEventBus[PlayerEvent],
|
val playerEventBus: GameEventBus[PlayerEvent],
|
||||||
val tickEventBus: GameEventBus[TickEvent],
|
val tickEventBus: GameEventBus[TickEvent],
|
||||||
val imMovementActorBehavior: Behavior[ImMovementActor.Command],
|
val imMovementActorBehavior: Behavior[ImMovementActor.Command],
|
||||||
val scheduler: AsyncScheduler
|
val scheduler: AsyncScheduler,
|
||||||
|
val fxScheduler: Schedulers.FxScheduler
|
||||||
) {
|
) {
|
||||||
def behavior =
|
def behavior =
|
||||||
Behaviors.logMessages(
|
Behaviors.logMessages(
|
||||||
@ -142,12 +141,6 @@ object PlayerActorSupervisor {
|
|||||||
ctx,
|
ctx,
|
||||||
this,
|
this,
|
||||||
Children(playerMovementActor, playerStatsActor),
|
Children(playerMovementActor, playerStatsActor),
|
||||||
ConcurrentSubject.publish(
|
|
||||||
OverflowStrategy.DropOldAndSignal(
|
|
||||||
50,
|
|
||||||
dropped => Coeval.pure(None)
|
|
||||||
)
|
|
||||||
)(scheduler.value),
|
|
||||||
AsyncQueue.bounded(10)(scheduler.value)
|
AsyncQueue.bounded(10)(scheduler.value)
|
||||||
).aliveState
|
).aliveState
|
||||||
}
|
}
|
||||||
@ -164,7 +157,6 @@ class PlayerActorSupervisor(
|
|||||||
ctx: ActorContext[PlayerActorSupervisor.Command],
|
ctx: ActorContext[PlayerActorSupervisor.Command],
|
||||||
props: PlayerActorSupervisor.Props,
|
props: PlayerActorSupervisor.Props,
|
||||||
children: PlayerActorSupervisor.Children,
|
children: PlayerActorSupervisor.Children,
|
||||||
statsSubject: ConcurrentSubject[CharacterStats, CharacterStats],
|
|
||||||
statsQueue: AsyncQueue[CharacterStats]
|
statsQueue: AsyncQueue[CharacterStats]
|
||||||
) {
|
) {
|
||||||
import PlayerActorSupervisor._
|
import PlayerActorSupervisor._
|
||||||
@ -173,11 +165,6 @@ class PlayerActorSupervisor(
|
|||||||
Behaviors
|
Behaviors
|
||||||
.receiveMessage[Command] {
|
.receiveMessage[Command] {
|
||||||
case TakeDamage(value, replyTo) =>
|
case TakeDamage(value, replyTo) =>
|
||||||
// children.movementActor ! ImMovementActor.MovedDown(true)
|
|
||||||
// ctx.ask(children.statsActor, StatsActor.CurrentStats(_)) {
|
|
||||||
// case Success(status) => InternalTakeDamage(status.hp, value)
|
|
||||||
// case Failure(ex) => LogError(ex)
|
|
||||||
// }
|
|
||||||
ctx.ask(children.statsActor, StatsActor.TakeDamageResult(value, _)) {
|
ctx.ask(children.statsActor, StatsActor.TakeDamageResult(value, _)) {
|
||||||
case Success(response) => DamageResponse(response, replyTo)
|
case Success(response) => DamageResponse(response, replyTo)
|
||||||
case Failure(ex) => LogError(ex)
|
case Failure(ex) => LogError(ex)
|
||||||
@ -193,7 +180,6 @@ class PlayerActorSupervisor(
|
|||||||
}
|
}
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
case CurrentStats(replyTo) =>
|
case CurrentStats(replyTo) =>
|
||||||
// ctx.ask(children.statsActor, StatsActor.CurrentStats())
|
|
||||||
children.statsActor ! StatsActor.CurrentStats(replyTo)
|
children.statsActor ! StatsActor.CurrentStats(replyTo)
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
case Heal(value) =>
|
case Heal(value) =>
|
||||||
@ -202,18 +188,18 @@ class PlayerActorSupervisor(
|
|||||||
case GetStatus(replyTo) =>
|
case GetStatus(replyTo) =>
|
||||||
replyTo ! Status.Alive
|
replyTo ! Status.Alive
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
// case _ => Behaviors.unhandled
|
|
||||||
// case InternalTakeDamage(hp, damage) =>
|
|
||||||
// if (hp - damage <= 0) dead
|
|
||||||
// else {
|
|
||||||
// children.statsActor ! StatsActor.TakeDamage(damage)
|
|
||||||
// Behaviors.same
|
|
||||||
// }
|
|
||||||
case GetStatsObservable(replyTo) =>
|
case GetStatsObservable(replyTo) =>
|
||||||
import monix.{eval => me}
|
import monix.{eval => me}
|
||||||
replyTo ! Observable.repeatEvalF(
|
replyTo !
|
||||||
me.Task.deferFuture(statsQueue.poll())
|
UIO(
|
||||||
)
|
Observable
|
||||||
|
.repeatEvalF(
|
||||||
|
me.Task.deferFuture(statsQueue.poll())
|
||||||
|
)
|
||||||
|
.publish(props.fxScheduler.value)
|
||||||
|
.refCount
|
||||||
|
)
|
||||||
|
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
case DamageResponse(response, replyTo) =>
|
case DamageResponse(response, replyTo) =>
|
||||||
response match {
|
response match {
|
||||||
@ -235,7 +221,6 @@ class PlayerActorSupervisor(
|
|||||||
.receiveSignal {
|
.receiveSignal {
|
||||||
case (_, PostStop) =>
|
case (_, PostStop) =>
|
||||||
ctx.log.infoP("stopped")
|
ctx.log.infoP("stopped")
|
||||||
statsSubject.onComplete()
|
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
}
|
}
|
||||||
val deadState = Behaviors
|
val deadState = Behaviors
|
||||||
@ -262,7 +247,6 @@ class PlayerActorSupervisor(
|
|||||||
.receiveSignal {
|
.receiveSignal {
|
||||||
case (_, PostStop) =>
|
case (_, PostStop) =>
|
||||||
ctx.log.infoP("stopped")
|
ctx.log.infoP("stopped")
|
||||||
statsSubject.onComplete()
|
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import wow.doge.mygame.subsystems.events.TickEvent
|
|||||||
import wow.doge.mygame.subsystems.movement.ImMovementActor
|
import wow.doge.mygame.subsystems.movement.ImMovementActor
|
||||||
import wow.doge.mygame.types._
|
import wow.doge.mygame.types._
|
||||||
import wow.doge.mygame.utils.wrappers.jme._
|
import wow.doge.mygame.utils.wrappers.jme._
|
||||||
|
import wow.doge.mygame.executors.Schedulers
|
||||||
|
|
||||||
object PlayerController {
|
object PlayerController {
|
||||||
sealed trait Error
|
sealed trait Error
|
||||||
@ -50,8 +51,8 @@ object PlayerController {
|
|||||||
initialPlayerPos: ImVector3f,
|
initialPlayerPos: ImVector3f,
|
||||||
playerEventBus: GameEventBus[PlayerEvent],
|
playerEventBus: GameEventBus[PlayerEvent],
|
||||||
playerPhysicsControl: BetterCharacterControl,
|
playerPhysicsControl: BetterCharacterControl,
|
||||||
// appScheduler: monix.execution.Scheduler,
|
|
||||||
scheduler: AsyncScheduler,
|
scheduler: AsyncScheduler,
|
||||||
|
fxScheduler: Schedulers.FxScheduler,
|
||||||
playerNode: PlayerNode,
|
playerNode: PlayerNode,
|
||||||
cameraNode: PlayerCameraNode,
|
cameraNode: PlayerCameraNode,
|
||||||
cameraPivotNode: PlayerCameraPivotNode,
|
cameraPivotNode: PlayerCameraPivotNode,
|
||||||
@ -67,7 +68,8 @@ object PlayerController {
|
|||||||
playerEventBus,
|
playerEventBus,
|
||||||
tickEventBus,
|
tickEventBus,
|
||||||
movementActorBeh,
|
movementActorBeh,
|
||||||
scheduler
|
scheduler,
|
||||||
|
fxScheduler
|
||||||
).behavior
|
).behavior
|
||||||
}
|
}
|
||||||
val playerActor =
|
val playerActor =
|
||||||
|
@ -12,7 +12,9 @@ import com.jme3.scene.Spatial.DFSMode
|
|||||||
import monix.execution.Scheduler.Implicits.global
|
import monix.execution.Scheduler.Implicits.global
|
||||||
import org.scalatest.funsuite.AnyFunSuite
|
import org.scalatest.funsuite.AnyFunSuite
|
||||||
import wow.doge.mygame.utils.wrappers.jme.CollisionShapeFactory
|
import wow.doge.mygame.utils.wrappers.jme.CollisionShapeFactory
|
||||||
|
import scala.annotation.nowarn
|
||||||
|
|
||||||
|
@nowarn("msg=method get in class LeftProjection is deprecated")
|
||||||
class CollisionShapeFactoryTest extends AnyFunSuite {
|
class CollisionShapeFactoryTest extends AnyFunSuite {
|
||||||
test("Test for WrongArgumentError") {
|
test("Test for WrongArgumentError") {
|
||||||
val res = CollisionShapeFactory
|
val res = CollisionShapeFactory
|
||||||
|
Loading…
Reference in New Issue
Block a user