Files
Soulstorm-tournament-decider/app/actors/UserActor.scala
T
2026-08-15 13:32:08 +03:00

261 lines
8.7 KiB
Scala

package actors
import actors.UserActor.{BanMapMessage, GetName, HostLeaveLobby, LobbyFatal, Message, RefreshLobbyInfo, SecondPlayerLeaveLobby, SendBanMapMessage, SendMessage, 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,
ip: String) extends Actor with LazyLogging {
implicit val timeout: Timeout = 3.seconds
val ipAddress: String = ip
var lobbieActor: Option[ActorRef] = None
implicit val mapJson: Writes[DeciderMap] = new Writes[DeciderMap] {
def writes(deciderMap: DeciderMap): JsValue = {
Json.obj(
"map" -> deciderMap.map,
"description" -> deciderMap.description,
"isBanned" -> deciderMap.isBanned
)
}
}
implicit val selectedRacesWrites: OWrites[SelectedRaces] = Json.writes[SelectedRaces]
implicit val userInfoWrites: OWrites[UserInfo] = Json.writes[UserInfo]
implicit val lobbyWrites: Writes[LobbyInfo] = new Writes[LobbyInfo]{
override def writes(lobby: LobbyInfo) = Json.obj(
"user1Info" -> lobby.user1Info,
"user2Info" -> lobby.user2Info,
"lobbyActorName" -> lobby.lobbyActorName,
"deciderName" -> lobby.deciderName,
"status" -> lobby.status,
"playerTurn" -> lobby.playerTurn,
"selectedType" -> lobby.selectedType,
"maps" -> Json.toJson(lobby.maps)
)
}
implicit val messageWrites: OWrites[Message] = Json.writes[Message]
implicit val messageBanMapWrites: OWrites[BanMapMessage] = Json.writes[BanMapMessage]
implicit val lobbyResponseWrites: Writes[List[LobbyInfo]] = new Writes[List[LobbyInfo]] {
override def writes(o: List[LobbyInfo]): JsValue = {
JsArray(o.map(lobby => Json.obj(
"user1Info" -> lobby.user1Info,
"user2Info" -> lobby.user2Info,
"lobbyActorName" -> lobby.lobbyActorName,
"deciderName" -> lobby.deciderName,
"status" -> lobby.status,
"playerTurn" -> lobby.playerTurn,
"selectedType" -> lobby.selectedType,
"maps" -> Json.toJson(lobby.maps)
)))
}
}
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 SendMessage(message) =>
logger.debug(s"Send message $message")
out ! Json.obj("type" -> "sendMessage", "message" -> message)
case SendBanMapMessage(mapBanMessage) =>
logger.debug(s"Send ban map message $mapBanMessage")
out ! Json.obj("type" -> "sendMapBanMessage", "message" -> mapBanMessage)
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("createDecider") =>
val deciderName = (json \ "deciderName").as[String]
LobbiesActor.actor ! CreateLobby(name, deciderName)
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("sendMessage") =>
val message = (json \ "message").as[String]
lobbieActor.foreach(lobby => lobby ! MessageForLobby(message))
case Some("changeLobbyType") =>
val lobbyType = (json \ "lobbyType").as[String]
lobbieActor.foreach(lobby => lobby ! ChangeLobbyType(lobbyType))
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.actor ! JoinLobbyByActorName(lobbyActorName, name)
case Some("observerDecider") =>
val lobbyActorName = (json \ "lobbyActorName").as[String]
logger.info(s"Player ${self.path.name} observe lobby $lobbyActorName")
LobbiesActor.actor ! ObserveLobbyByActorName(lobbyActorName)
case Some("banMap") =>
val map = (json \ "map").as[String]
lobbieActor.foreach(lobby => lobby ! BanMap(map))
case Some("selectRace") =>
logger.info("RACES: " + json.toString())
val races = (json \ "mainRaces").as[List[Int]]
val additionalRaces = (json \ "additionalRaces").as[List[Int]]
val raceTextInput = (json \ "raceTextInput").as[String]
lobbieActor.foreach(lobby => lobby ! SelectedRaces(races, additionalRaces, raceTextInput))
case Some("getLobbies") =>
logger.debug("Get all lobby request")
(LobbiesActor.actor ? GetAllLobbies).mapTo[List[RefreshLobbyInfo]] onComplete {
case Success(lobbies) => {
logger.debug(s"Received lobbies: $lobbies")
out ! Json.obj("type" -> "lobbies", "lobbies" -> lobbies.map(res => res.lobbyInfo))
}
case Failure(ex) => logger.error("Received error", ex)
}
case Some(value) =>
logger.error(s"Command '$value' not expected")
case None =>
logger.error(s"Field 'type' should be specified in incoming json'")
}
}
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, ipAddress, out) =>
val child: ActorRef = actorSystem.actorOf(Props(classOf[UserActor], out, self, ipAddress), s"userActor-$id")
sender() ! child
case GetAllUsers =>
System.out.print("12123" + context.children)
sender() ! context.children
}
}
object UserParentActor {
case class Create(id: String, ipAddress: String, out: 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 Message(userName: String, message: String)
case class SendMessage(message: Message)
case class BanMapMessage(user: String, mapTechName: String)
case class SendBanMapMessage(message: BanMapMessage)
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
}