206 lines
6.5 KiB
Scala
206 lines
6.5 KiB
Scala
package actors
|
||
|
||
import actors.UserActor.{GetName, HostLeaveLobby, LobbyFatal, RefreshLobbyInfo, SecondPlayerLeaveLobby, SetUserAsHost, SetUserAsObs, SetUserAsSecondPlayer}
|
||
import akka.actor._
|
||
import akka.event.LoggingReceive
|
||
import akka.pattern.ask
|
||
import akka.util.Timeout
|
||
import com.typesafe.scalalogging.LazyLogging
|
||
import play.api.libs.json._
|
||
|
||
import scala.concurrent.ExecutionContext.Implicits.global
|
||
import scala.concurrent.duration.DurationInt
|
||
import scala.util.{Failure, Success}
|
||
|
||
class UserActor(out: ActorRef,
|
||
userParentActor: ActorRef,
|
||
lobbiesActor: ActorRef) extends Actor with LazyLogging {
|
||
|
||
implicit val timeout: Timeout = 3.seconds
|
||
|
||
var lobbieActor: Option[ActorRef] = None
|
||
|
||
implicit val mapJson: Writes[DeciderMap] = new Writes[DeciderMap] {
|
||
def writes(deciderMap: DeciderMap): JsValue = {
|
||
Json.obj(
|
||
"map" -> deciderMap.map,
|
||
"isBanned" -> deciderMap.isBanned
|
||
)
|
||
}
|
||
}
|
||
|
||
implicit val userInfoWrites: OWrites[UserInfo] = Json.writes[UserInfo]
|
||
|
||
implicit val lobbyWrites: OWrites[LobbyInfo] = Json.writes[LobbyInfo]
|
||
|
||
implicit val lobbyResponseWrites: Writes[List[LobbyInfo]] = new Writes[List[LobbyInfo]] {
|
||
|
||
override def writes(o: List[LobbyInfo]): JsValue = {
|
||
JsArray(o.map(lobby => Json.toJson(lobby)))
|
||
}
|
||
}
|
||
|
||
var name = ""
|
||
|
||
override def preStart(): Unit = {
|
||
super.preStart()
|
||
|
||
configureDefaultStocks()
|
||
}
|
||
|
||
def configureDefaultStocks(): Unit = {
|
||
logger.info(s"Creating user actor")
|
||
}
|
||
|
||
override def receive: Receive = LoggingReceive {
|
||
|
||
case GetName =>
|
||
sender ! name
|
||
|
||
case SetUserAsHost(lobbyInfo) =>
|
||
val lobbyActor = sender()
|
||
logger.info(s"Receive set user ${self.path.name} as host from ${lobbyActor.path.name}")
|
||
setUserAsJoinedOrCreatedLobby(lobbyActor, lobbyInfo)
|
||
|
||
case SetUserAsSecondPlayer(lobbyInfo) =>
|
||
val lobbyActor = sender()
|
||
logger.info(s"Receive set user ${self.path.name} as second player from ${lobbyActor.path.name}")
|
||
setUserAsJoinedOrCreatedLobby(lobbyActor, lobbyInfo)
|
||
|
||
case SetUserAsObs(lobbyInfo) =>
|
||
val lobbyActor = sender()
|
||
logger.info(s"Receive set user ${self.path.name} as second player from ${lobbyActor.path.name}")
|
||
setUserAsJoinedOrCreatedLobby(lobbyActor, lobbyInfo)
|
||
|
||
case HostLeaveLobby =>
|
||
logger.info(s"Host leave from lobby ${sender.path.name}")
|
||
out ! Json.obj("type" -> "lobbyError", "error" -> "Host leave lobby")
|
||
|
||
case SecondPlayerLeaveLobby =>
|
||
logger.info(s"Second player lobby ${sender.path.name}")
|
||
out ! Json.obj("type" -> "lobbyError", "error" -> "Second player leave lobby")
|
||
|
||
case RefreshLobbyInfo(lobbyInfo) =>
|
||
logger.trace(s"Refresh lobby info: $lobbyInfo")
|
||
out ! Json.obj("type" -> "refreshLobby", "lobby" -> lobbyInfo)
|
||
|
||
case LobbyFatal(message) => // После этого сообщения выход из лобби
|
||
logger.warn(s"Lobby error: $message")
|
||
out ! Json.obj("type" -> "lobbyError", "error" -> message)
|
||
|
||
case json: JsValue =>
|
||
// Обрабатываем запросы с фронта
|
||
|
||
val comType = (json \ "type").asOpt[String]
|
||
comType match {
|
||
case Some("userName") =>
|
||
name = (json \ "name").as[String]
|
||
logger.debug(s"Set user name: $name for actor ${this.self}")
|
||
case Some("getAllUsers") =>
|
||
val userActorsFuture = (userParentActor ? UserParentActor.GetAllUsers).mapTo[Iterable[ActorRef]]
|
||
userActorsFuture.map(actorRefs => {
|
||
logger.debug(s"There are ${actorRefs.size} users on site")
|
||
actorRefs.map(userActorRef => userActorRef ? GetName).map(res => {
|
||
res.onComplete {
|
||
case Success(name) => logger.debug(s"There is $name on site")
|
||
}
|
||
})
|
||
})
|
||
|
||
case Some("createDecider") =>
|
||
lobbiesActor ! CreateLobby(name)
|
||
|
||
case Some("leaveDecider") =>
|
||
lobbieActor.foreach(lobby => lobby ! LeaveLobby)
|
||
|
||
case Some("setReady") =>
|
||
lobbieActor.foreach(lobby => lobby ! SetReady)
|
||
|
||
case Some("setNotReady") =>
|
||
lobbieActor.foreach(lobby => lobby ! SetNotReady)
|
||
|
||
case Some("kickSecondPlayer") =>
|
||
lobbieActor.foreach(lobby => lobby ! KickSecondPlayer)
|
||
|
||
case Some("joinDecider") =>
|
||
val lobbyActorName = (json \ "lobbyActorName").as[String]
|
||
logger.info(s"Player ${self.path.name} join lobby $lobbyActorName")
|
||
lobbiesActor ! JoinLobbyByActorName(lobbyActorName, name)
|
||
|
||
case Some("observerDecider") =>
|
||
val lobbyActorName = (json \ "lobbyActorName").as[String]
|
||
logger.info(s"Player ${self.path.name} observe lobby $lobbyActorName")
|
||
lobbiesActor ! ObserveLobbyByActorName(lobbyActorName)
|
||
|
||
case Some("banMap") =>
|
||
val map = (json \ "map").as[String]
|
||
lobbieActor.foreach(lobby => lobby ! BanMap(map))
|
||
|
||
case Some("getLobbies") =>
|
||
logger.debug("Get all lobby request")
|
||
(lobbiesActor ? GetAllLobbies).mapTo[List[RefreshLobbyInfo]] onComplete {
|
||
case Success(lobbies) => {
|
||
logger.info(s"Received lobbies: $lobbies")
|
||
out ! Json.obj("type" -> "lobbies", "lobbies" -> lobbies.map(res => res.lobbyInfo))
|
||
}
|
||
case Failure(ex) => logger.error("Received error", ex)
|
||
}
|
||
}
|
||
}
|
||
|
||
private def setUserAsJoinedOrCreatedLobby(lobbyActor: ActorRef, lobbyInfo: LobbyInfo): Unit = {
|
||
this.lobbieActor = Some(lobbyActor)
|
||
out ! Json.obj("type" -> "switchToLobby", "lobby" -> lobbyInfo)
|
||
}
|
||
|
||
}
|
||
|
||
class UserParentActor(actorSystem: ActorSystem) extends Actor with ActorLogging {
|
||
|
||
import UserParentActor._
|
||
|
||
override def receive: Receive = LoggingReceive {
|
||
case Create(id, out, lobbiesActor) =>
|
||
val child: ActorRef = actorSystem.actorOf(Props(classOf[UserActor], out, self, lobbiesActor), s"userActor-$id")
|
||
sender() ! child
|
||
case GetAllUsers =>
|
||
sender() ! context.children
|
||
}
|
||
}
|
||
|
||
|
||
object UserParentActor {
|
||
|
||
case class Create(id: String, out: ActorRef, lobbiesActor: ActorRef)
|
||
|
||
case object GetAllUsers
|
||
|
||
}
|
||
|
||
object UserActor {
|
||
|
||
trait Factory {
|
||
// Corresponds to the @Assisted parameters defined in the constructor
|
||
def apply(out: ActorRef): Actor
|
||
}
|
||
|
||
case object GetName
|
||
|
||
case class RefreshLobbyInfo(lobbyInfo: LobbyInfo)
|
||
|
||
case class SetUserAsHost(lobbyInfo: LobbyInfo)
|
||
|
||
case class SetUserAsSecondPlayer(lobbyInfo: LobbyInfo)
|
||
|
||
case class SetUserAsObs(lobbyInfo: LobbyInfo)
|
||
|
||
case class LobbyFatal(message: String)
|
||
|
||
case object CreateLobby
|
||
|
||
case object HostLeaveLobby
|
||
|
||
case object SecondPlayerLeaveLobby
|
||
}
|
||
|