Testing out JmonkeyEngine to make a game in Scala with Akka Actors within a pure FP layer
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.

135 lines
3.8 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. package wow.doge.mygame
  2. import akka.actor.typed.scaladsl.Behaviors
  3. import wow.doge.mygame.game.GameApp
  4. import akka.actor.typed.Behavior
  5. import wow.doge.mygame.game.GameAppActor
  6. import cats.effect.Resource
  7. import akka.actor.typed.ActorSystem
  8. import monix.bio.Task
  9. import wow.doge.mygame.game.GameModule
  10. import io.odin._
  11. import io.odin.syntax._
  12. import wow.doge.mygame.executors.ExecutorsModule
  13. import akka.actor.typed.scaladsl.ActorContext
  14. import wow.doge.mygame.executors.Schedulers
  15. import com.softwaremill.macwire._
  16. import akka.actor.typed.SpawnProtocol
  17. import akka.actor.typed.Scheduler
  18. import wow.doge.mygame.utils.AkkaUtils
  19. import scala.concurrent.duration._
  20. import akka.actor.typed.ActorRef
  21. import wow.doge.mygame.implicits._
  22. trait MainModule extends GameModule with ExecutorsModule {
  23. def actorSystemResource(
  24. logger: Logger[Task],
  25. app: GameApp,
  26. schedulers: Schedulers
  27. ): Resource[Task, ActorSystem[RootActor.Command]] =
  28. Resource.make(logger.info("Creating Actor System") >> Task {
  29. ActorSystem(
  30. wire[RootActor.Props].create(RootActor.State.empty),
  31. name = "GameActorSystem"
  32. )
  33. })(sys =>
  34. logger.info("Shutting down actor system") >> Task(
  35. sys.terminate()
  36. )
  37. )
  38. def actorSystemResource2(
  39. logger: Logger[Task]
  40. ): Resource[Task, ActorSystem[SpawnProtocol.Command]] =
  41. Resource.make(logger.info("Creating Actor System") >> Task {
  42. ActorSystem(
  43. SpawnProtocol(),
  44. name = "GameActorSystem2"
  45. )
  46. })(sys =>
  47. logger.info("Shutting down actor system") >> Task(
  48. sys.terminate()
  49. )
  50. )
  51. def rootActorResource(
  52. loggerL: Logger[Task],
  53. app: GameApp,
  54. schedulers: Schedulers,
  55. spawnProtocol: ActorSystem[SpawnProtocol.Command]
  56. ): Resource[Task, ActorRef[RootActor.Command]] =
  57. Resource.make(
  58. loggerL.info("Creating Root Actor") >>
  59. AkkaUtils.spawnActorL(
  60. behavior = RootActor(app, schedulers, logger = loggerL),
  61. actorName = "RootActor",
  62. spawnProtocol = spawnProtocol
  63. )(1.seconds, spawnProtocol.scheduler)
  64. )(actor =>
  65. loggerL.info("Shutting down root actor") >> (actor !! RootActor.Stop)
  66. )
  67. }
  68. object RootActor {
  69. sealed trait Command
  70. final case class Start(akkaScheduler: Scheduler) extends Command
  71. final case object Stop extends Command
  72. final case class Props(
  73. app: GameApp,
  74. schedulers: Schedulers,
  75. logger: Logger[Task]
  76. ) {
  77. def create(state: State): Behavior[Command] =
  78. Behaviors.setup { ctx =>
  79. ctx.log.info("Hello from root actor")
  80. wire[RootActor].receive(State.empty)
  81. }
  82. }
  83. final case class State(initialized: Boolean = false)
  84. object State {
  85. val empty = State()
  86. }
  87. def apply(
  88. app: GameApp,
  89. schedulers: Schedulers,
  90. state: State = State.empty,
  91. logger: Logger[Task]
  92. ): Behavior[Command] =
  93. Behaviors.setup { ctx =>
  94. ctx.log.info("Hello from root actor")
  95. wire[RootActor].receive(state)
  96. }
  97. }
  98. class RootActor(
  99. ctx: ActorContext[RootActor.Command],
  100. app: GameApp,
  101. schedulers: Schedulers,
  102. logger: Logger[Task]
  103. ) {
  104. import RootActor._
  105. def receive(state: State): Behavior[Command] =
  106. Behaviors.receiveMessage(msg =>
  107. msg match {
  108. case Start(akkaScheduler) =>
  109. if (!state.initialized) {
  110. ctx.log.info("Starting GameAppActor")
  111. val spawnProtocol = ctx.spawn(SpawnProtocol(), "spawnProtocol")
  112. val _ = ctx.spawn(
  113. wire[GameAppActor.Props].create,
  114. "gameAppActor"
  115. // DispatcherSelector.fromConfig("jme-dispatcher")
  116. )
  117. receive(state.copy(initialized = true))
  118. } else {
  119. ctx.log.warn("Already Initialized")
  120. Behaviors.same
  121. }
  122. case Stop =>
  123. ctx.log.info("Stopping")
  124. Behaviors.stopped
  125. }
  126. )
  127. }