Browse Source

Update player actor

Make stats observable hot
Remove concurrentsubject
development
Rohan Sircar 3 years ago
parent
commit
1422d91b14
  1. 3
      src/main/scala/wow/doge/mygame/MainApp.scala
  2. 86
      src/main/scala/wow/doge/mygame/game/entities/NpcActorSupervisor.scala
  3. 46
      src/main/scala/wow/doge/mygame/game/entities/player/PlayerActorSupervisor.scala
  4. 6
      src/main/scala/wow/doge/mygame/game/entities/player/PlayerController.scala
  5. 2
      src/test/scala/wow/doge/mygame/CollisionShapeFactoryTest.scala

3
src/main/scala/wow/doge/mygame/MainApp.scala

@ -377,6 +377,7 @@ class MainAppDelegate(
playerActor
.askL(PlayerActorSupervisor.GetStatsObservable(_))
.onErrorHandleWith(TimeoutError.from)
.flatten
playerHud <-
UIO
.deferAction(implicit s =>
@ -391,7 +392,6 @@ class MainAppDelegate(
children = List(
new Label("Health") { textFill = Color.White },
new Label("100") {
text == "hello"
text <-- statsObs
.doOnNextF(i => loggerL.debug(show"Received stats: $i"))
.map(_.hp.toInt.toString)
@ -504,6 +504,7 @@ class MainAppDelegate(
.hideErrors
.startAndForget
sched <- UIO.pure(schedulers.async)
fxSched <- UIO.pure(schedulers.fx)
playerActor <- wire[PlayerController.Props].create
} yield playerActor
}

86
src/main/scala/wow/doge/mygame/game/entities/NpcActorSupervisor.scala

@ -6,28 +6,15 @@ import scala.util.Success
import akka.actor.typed.ActorRef
import akka.actor.typed.Behavior
import akka.actor.typed.SupervisorStrategy
import akka.actor.typed.scaladsl.ActorContext
import akka.actor.typed.scaladsl.Behaviors
import akka.util.Timeout
import cats.syntax.eq._
import cats.syntax.show._
import monix.execution.CancelableFuture
import monix.execution.CancelablePromise
import wow.doge.mygame.game.subsystems.movement.CanMove
import wow.doge.mygame.implicits._
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
object NpcActorSupervisor {
@ -236,76 +223,3 @@ class NpcMovementActor[T](
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)
}
}
}

46
src/main/scala/wow/doge/mygame/game/entities/player/PlayerActorSupervisor.scala

@ -14,11 +14,8 @@ import akka.actor.typed.scaladsl.Behaviors
import akka.util.Timeout
import cats.syntax.show._
import com.typesafe.scalalogging.Logger
import monix.eval.Coeval
import monix.execution.AsyncQueue
import monix.reactive.Observable
import monix.reactive.OverflowStrategy
import monix.reactive.subjects.ConcurrentSubject
import org.slf4j.event.Level
import wow.doge.mygame.Dispatchers
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.RenderTick
import wow.doge.mygame.subsystems.movement.ImMovementActor
import wow.doge.mygame.executors.Schedulers
import monix.bio.UIO
object PlayerActorSupervisor {
type Ref = ActorRef[PlayerActorSupervisor.Command]
@ -54,7 +53,7 @@ object PlayerActorSupervisor {
extends Command
final case class GetStatus(replyTo: ActorRef[Status]) extends Command
final case class GetStatsObservable(
replyTo: ActorRef[Observable[CharacterStats]]
replyTo: ActorRef[UIO[Observable[CharacterStats]]]
) extends Command
private case object Die extends Command
@ -62,13 +61,13 @@ object PlayerActorSupervisor {
response: (Boolean, CharacterStats),
replyTo: ActorRef[Unit]
) extends Command
// private final case class InternalTakeDamage(old: Int, value: Int) extends Command
private final case class LogError(ex: Throwable) extends Command
class Props(
val playerEventBus: GameEventBus[PlayerEvent],
val tickEventBus: GameEventBus[TickEvent],
val imMovementActorBehavior: Behavior[ImMovementActor.Command],
val scheduler: AsyncScheduler
val scheduler: AsyncScheduler,
val fxScheduler: Schedulers.FxScheduler
) {
def behavior =
Behaviors.logMessages(
@ -142,12 +141,6 @@ object PlayerActorSupervisor {
ctx,
this,
Children(playerMovementActor, playerStatsActor),
ConcurrentSubject.publish(
OverflowStrategy.DropOldAndSignal(
50,
dropped => Coeval.pure(None)
)
)(scheduler.value),
AsyncQueue.bounded(10)(scheduler.value)
).aliveState
}
@ -164,7 +157,6 @@ class PlayerActorSupervisor(
ctx: ActorContext[PlayerActorSupervisor.Command],
props: PlayerActorSupervisor.Props,
children: PlayerActorSupervisor.Children,
statsSubject: ConcurrentSubject[CharacterStats, CharacterStats],
statsQueue: AsyncQueue[CharacterStats]
) {
import PlayerActorSupervisor._
@ -173,11 +165,6 @@ class PlayerActorSupervisor(
Behaviors
.receiveMessage[Command] {
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, _)) {
case Success(response) => DamageResponse(response, replyTo)
case Failure(ex) => LogError(ex)
@ -193,7 +180,6 @@ class PlayerActorSupervisor(
}
Behaviors.same
case CurrentStats(replyTo) =>
// ctx.ask(children.statsActor, StatsActor.CurrentStats())
children.statsActor ! StatsActor.CurrentStats(replyTo)
Behaviors.same
case Heal(value) =>
@ -202,18 +188,18 @@ class PlayerActorSupervisor(
case GetStatus(replyTo) =>
replyTo ! Status.Alive
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) =>
import monix.{eval => me}
replyTo ! Observable.repeatEvalF(
me.Task.deferFuture(statsQueue.poll())
)
replyTo !
UIO(
Observable
.repeatEvalF(
me.Task.deferFuture(statsQueue.poll())
)
.publish(props.fxScheduler.value)
.refCount
)
Behaviors.same
case DamageResponse(response, replyTo) =>
response match {
@ -235,7 +221,6 @@ class PlayerActorSupervisor(
.receiveSignal {
case (_, PostStop) =>
ctx.log.infoP("stopped")
statsSubject.onComplete()
Behaviors.same
}
val deadState = Behaviors
@ -262,7 +247,6 @@ class PlayerActorSupervisor(
.receiveSignal {
case (_, PostStop) =>
ctx.log.infoP("stopped")
statsSubject.onComplete()
Behaviors.same
}
}

6
src/main/scala/wow/doge/mygame/game/entities/player/PlayerController.scala

@ -24,6 +24,7 @@ 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._
import wow.doge.mygame.executors.Schedulers
object PlayerController {
sealed trait Error
@ -50,8 +51,8 @@ object PlayerController {
initialPlayerPos: ImVector3f,
playerEventBus: GameEventBus[PlayerEvent],
playerPhysicsControl: BetterCharacterControl,
// appScheduler: monix.execution.Scheduler,
scheduler: AsyncScheduler,
fxScheduler: Schedulers.FxScheduler,
playerNode: PlayerNode,
cameraNode: PlayerCameraNode,
cameraPivotNode: PlayerCameraPivotNode,
@ -67,7 +68,8 @@ object PlayerController {
playerEventBus,
tickEventBus,
movementActorBeh,
scheduler
scheduler,
fxScheduler
).behavior
}
val playerActor =

2
src/test/scala/wow/doge/mygame/CollisionShapeFactoryTest.scala

@ -12,7 +12,9 @@ import com.jme3.scene.Spatial.DFSMode
import monix.execution.Scheduler.Implicits.global
import org.scalatest.funsuite.AnyFunSuite
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 {
test("Test for WrongArgumentError") {
val res = CollisionShapeFactory

Loading…
Cancel
Save