package wow.doge.mygame.subsystems.events import scala.concurrent.duration._ import scala.reflect.ClassTag import akka.actor.typed.ActorRef import akka.actor.typed.LogOptions import akka.actor.typed.Props import akka.actor.typed.Scheduler import akka.actor.typed.SpawnProtocol import akka.actor.typed.SupervisorStrategy import akka.actor.typed.scaladsl.Behaviors import akka.util.Timeout import com.typesafe.scalalogging.{Logger => SLogger} import monix.bio.IO import org.slf4j.event.Level import wow.doge.mygame.AppError import wow.doge.mygame.AppError.TimeoutError import wow.doge.mygame.implicits._ import wow.doge.mygame.subsystems.events.Event import wow.doge.mygame.subsystems.events.EventBus import wow.doge.mygame.subsystems.events.TickEvent class EventsModule( scheduler: Scheduler, spawnProtocol: ActorRef[SpawnProtocol.Command] ) { import EventsModule._ implicit val s = scheduler implicit val sp = spawnProtocol implicit val timeout = Timeout(1.second) val eventBusLogger = SLogger[EventBus[_]] val playerEventBus: IO[AppError, GameEventBus[PlayerEvent]] = createEventBus[PlayerEvent]() // val playerCameraEventBusTask = // createEventBus[PlayerCameraEvent](Level.DEBUG) val tickEventBus: IO[AppError, GameEventBus[TickEvent]] = createEventBus[TickEvent](Level.TRACE) val mainEventBus: IO[AppError, GameEventBus[Event]] = createEventBus[Event]() def createEventBus[T: ClassTag]( logLevel: Level = Level.DEBUG, busName: Option[String] = None )(implicit name: sourcecode.Name) = spawnProtocol .askL( SpawnProtocol.Spawn[EventBus.Command[T]]( Behaviors.logMessages( logOptions = LogOptions() .withLevel(logLevel) .withLogger(eventBusLogger.underlying), Behaviors .supervise(EventBus[T]()) .onFailure[Exception]( SupervisorStrategy.restart.withLimit(2, 100.millis) ) ), busName.fold(name.value)(identity), Props.empty, _ ) ) .onErrorHandleWith(TimeoutError.from) } object EventsModule { type GameEventBus[T] = ActorRef[EventBus.Command[T]] }