From f94bf511a3ea019f292cab6110175b365419b9b7 Mon Sep 17 00:00:00 2001 From: Anibus Date: Sun, 22 Nov 2020 12:39:56 +0300 Subject: [PATCH] Kick button, show player turn, can't join if 2-nd player alreay join --- app/actors/LobbieActor.scala | 57 ++++++++++++++++++++++------ app/actors/UserActor.scala | 24 ++++++++++-- app/assets/javascripts/index.js | 51 ++++++++++++++++--------- app/controllers/HomeController.scala | 2 +- conf/application.conf | 7 +--- 5 files changed, 100 insertions(+), 41 deletions(-) diff --git a/app/actors/LobbieActor.scala b/app/actors/LobbieActor.scala index 4170759..82c6f0b 100644 --- a/app/actors/LobbieActor.scala +++ b/app/actors/LobbieActor.scala @@ -1,6 +1,6 @@ package actors -import actors.UserActor.{GetName, HostLeaveLobby, RefreshLobbyInfo, SetUserAsHost} +import actors.UserActor.{GetName, HostLeaveLobby, LobbyFatal, RefreshLobbyInfo, SecondPlayerLeaveLobby, SetUserAsHost, SetUserAsObs, SetUserAsSecondPlayer} import akka.actor.{Actor, ActorLogging, ActorRef} import akka.event.LoggingReceive import com.typesafe.scalalogging.LazyLogging @@ -49,7 +49,14 @@ class LobbieActor(hostUser: LobbyUser) extends Actor with LazyLogging { } hostUser.actorRef.tell( - SetUserAsHost(LobbyInfo(hostUser.name, "", firstPlayerReady, secondPlayerReady, self.path.name, status.toString(), mapsLobby)), this.self) + SetUserAsHost(LobbyInfo( + UserInfo(hostUser.name,firstPlayerReady), + UserInfo("", secondPlayerReady), + self.path.name, + status.toString(), + playerTurn, + mapsLobby)), + this.self) implicit val timeout: Timeout = 1.second @@ -98,21 +105,38 @@ class LobbieActor(hostUser: LobbyUser) extends Actor with LazyLogging { } users.foreach(_ ! RefreshLobbyInfo(getLobbyInfoResponse)) + case KickSecondPlayer => + if (sender() == host.actorRef) { + secondPlayer.foreach(player => player.actorRef ! LobbyFatal("You were kicked from lobby!")) + secondPlayerReady = false + secondPlayer = None + users.foreach(_ ! RefreshLobbyInfo(getLobbyInfoResponse)) + } case JoinLobbyAsPlayer(sp) => logger.info(s"User ${sender.path.name} join lobby ${self.path.name} as player") - secondPlayer = Some(sp) - users = users + sp.actorRef - sp.actorRef.tell( - SetUserAsHost(LobbyInfo(hostUser.name, sp.name, firstPlayerReady, secondPlayerReady, self.path.name, status.toString(), mapsLobby)), this.self) - users.foreach(_ ! RefreshLobbyInfo(getLobbyInfoResponse)) + if (secondPlayer.isEmpty) { + secondPlayer = Some(sp) + users = users + sp.actorRef + sp.actorRef.tell( + SetUserAsSecondPlayer(getLobbyInfoResponse), this.self) + users.foreach(_ ! RefreshLobbyInfo(getLobbyInfoResponse)) + } else { + sp.actorRef ! LobbyFatal("Lobby already full") + } + case WatchLobby(_) => // add the watcher to the list users = users + sender + sender ! SetUserAsObs(getLobbyInfoResponse) case LeaveLobby => users = users - sender if(secondPlayer.exists(sp => sp.actorRef == sender)) secondPlayer = None if(host.actorRef == sender()){ users.foreach(_ ! HostLeaveLobby) + context.stop(self) + }else if(secondPlayer.exists(_.actorRef == sender())){ + users.foreach(_ ! SecondPlayerLeaveLobby) + context.stop(self) } if (users.isEmpty) { logger.info(s"Stop lobby ${self.path.name}") @@ -125,7 +149,13 @@ class LobbieActor(hostUser: LobbyUser) extends Actor with LazyLogging { private def getLobbyInfoResponse: LobbyInfo = { val user2Name = secondPlayer.map(_.name).getOrElse("") - LobbyInfo(host.name, user2Name, firstPlayerReady, secondPlayerReady, self.path.name, status.toString(), mapsLobby) + LobbyInfo( + UserInfo(host.name, firstPlayerReady), + UserInfo(user2Name, secondPlayerReady), + self.path.name, + status.toString(), + playerTurn, + mapsLobby) } } @@ -139,6 +169,8 @@ case class WatchLobby(lobbyName: String) case class JoinLobbyAsPlayer(lobbyUser: LobbyUser) +case object KickSecondPlayer + case object LeaveLobby case object SetReady @@ -147,12 +179,13 @@ case object SetNotReady case object InfoQuery -case class LobbyInfo(user1Name: String, - user2Name: String, - user1Ready: Boolean, - user2Ready: Boolean, +case class UserInfo(name: String, isReady: Boolean) + +case class LobbyInfo(user1Info: UserInfo, + user2Info: UserInfo, lobbyActorName: String, status: String, + playerTurn: BigDecimal, maps: Set[DeciderMap]) class LobbyStatus diff --git a/app/actors/UserActor.scala b/app/actors/UserActor.scala index 232f421..04031c2 100644 --- a/app/actors/UserActor.scala +++ b/app/actors/UserActor.scala @@ -1,6 +1,6 @@ package actors -import actors.UserActor.{GetName, HostLeaveLobby, RefreshLobbyInfo, SetUserAsHost, SetUserAsSecondPlayer} +import actors.UserActor.{GetName, HostLeaveLobby, LobbyFatal, RefreshLobbyInfo, SecondPlayerLeaveLobby, SetUserAsHost, SetUserAsSecondPlayer} import akka.actor._ import akka.event.LoggingReceive import akka.pattern.ask @@ -29,6 +29,8 @@ class UserActor(out: ActorRef, } } + 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]] { @@ -67,12 +69,20 @@ class UserActor(out: ActorRef, case HostLeaveLobby => logger.info(s"Host leave from lobby ${sender.path.name}") - out ! Json.obj("type" -> "hostLeaveLobby") + 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 => // Обрабатываем запросы с фронта @@ -104,6 +114,9 @@ class UserActor(out: ActorRef, 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") @@ -122,7 +135,6 @@ class UserActor(out: ActorRef, } case Failure(ex) => logger.error("Received error", ex) } - } } @@ -170,10 +182,14 @@ object UserActor { case class SetUserAsSecondPlayer(lobbyInfo: LobbyInfo) + case class SetUserAsObs(lobbyInfo: LobbyInfo) + + case class LobbyFatal(message: String) + case object CreateLobby case object HostLeaveLobby - + case object SecondPlayerLeaveLobby } diff --git a/app/assets/javascripts/index.js b/app/assets/javascripts/index.js index d6f15d1..19e5a44 100644 --- a/app/assets/javascripts/index.js +++ b/app/assets/javascripts/index.js @@ -37,16 +37,16 @@ window.onload = function() { var lobbiesAsTableRows = _.reduce(this.lobbies, function (memo, lobby) { - var joinButton = ''; + '' : ""; var observerButton = ''; return memo + '\n' + - ' '+ lobby.user1Name +'\n' + - ' '+ lobby.user2Name +'\n' + + ' '+ lobby.user1Info.name +'\n' + + ' '+ lobby.user2Info.name +'\n' + ' '+ lobby.status +'\n' + ' ' + joinButton + ' ' + observerButton + ' ' + @@ -129,6 +129,9 @@ window.onload = function() { switchToLobby(message.lobby.maps); renderPlayersAndStats(message.lobby); break; + case "lobbyError": + console.log(message); + disconnectLobby(message.error); case "lobbies": lobbyList.lobbies = message.lobbies; lobbyList.render(); @@ -173,6 +176,12 @@ function switchToLobby(maps) { $("#decider").show(); } +function disconnectLobby(error) { + $("#decider").hide(); + $("#lobbies").show(); + alert(error); +} + function renderMaps(maps) { var resHtml = ""; @@ -203,51 +212,51 @@ function renderPlayersAndStats(lobby) { var readyImg = ""; var notReadyImg = ""; - if(lobby.user1Name === userName){ - if(lobby.user1Ready){ + if(lobby.user1Info.name === userName){ + if(lobby.user1Info.isReady){ player1ReadyBtn = "" }else{ player1ReadyBtn = "" } }else{ - if(lobby.user1Ready){ + if(lobby.user1Info.isReady){ player1ReadyBtn = readyImg }else{ player1ReadyBtn = notReadyImg } } - if(lobby.user2Name === userName){ - if(lobby.user2Ready){ + if(lobby.user2Info.name === userName){ + if(lobby.user2Info.isReady){ player2ReadyBtn = "" }else{ player2ReadyBtn = "" } } else { - if(lobby.user2Ready){ + if(lobby.user2Info.isReady){ player2ReadyBtn = readyImg }else{ player2ReadyBtn = notReadyImg } } - console.log(lobby); - switch (lobby.status){ case "NotStarted()": - resHtml = "
" + lobby.user1Name + ": " + player1ReadyBtn +"
" - if(lobby.user2Name !== ""){ + resHtml = "
" + lobby.user1Info.name + ": " + player1ReadyBtn +"
" + if(lobby.user2Info.name !== ""){ var kickBtn = "" - if(lobby.user1Name === userName){ - kickBtn = ""; + if(lobby.user1Info.name === userName){ + kickBtn = ""; } - resHtml += "
" + lobby.user2Name + ": " + player2ReadyBtn + "
" + kickBtn + "
" + resHtml += "
" + lobby.user2Info.name + ": " + player2ReadyBtn + "
" + kickBtn + "
" }else{ resHtml += "
waiting 2-nd player...
" } break; case "Draft()": - resHtml = "
"+lobby.user1Name+ " vs " + lobby.user2Name +"
"; + console.log(lobby.turn); + var playerTurn = (lobby.playerTurn === 1) ? lobby.user1Info.name : lobby.user2Info.name + resHtml = "
"+lobby.user1Info.name + " vs " + lobby.user2Info.name +"
" + playerTurn +" turn
"; break; case "Finish()": var lastMap = _.find(lobby.maps, function (map){ @@ -288,6 +297,12 @@ function joinDecider(actorName){ })); } +function kickSecondPlayer(){ + ws.send(JSON.stringify({ + type: "kickSecondPlayer" + })); +} + function convertMapName (techMapName) { var mapName = techMapName.replace("2p_", "").replaceAll("_", " ") + " (2)"; return mapName.charAt(0).toUpperCase() + mapName.slice(1); diff --git a/app/controllers/HomeController.scala b/app/controllers/HomeController.scala index b34ec44..fef46c3 100644 --- a/app/controllers/HomeController.scala +++ b/app/controllers/HomeController.scala @@ -88,7 +88,7 @@ class HomeController @Inject()(cc: ControllerComponents) extends AbstractControl * Returns true if the value of the Origin header contains an acceptable value. */ def originMatches(origin: String): Boolean = { - origin.contains("localhost:9000") || origin.contains("localhost:19001") + origin.contains("139.59.210.74") || origin.contains("localhost") || origin.contains("localhost:9000") || origin.contains("localhost:19001") } /** diff --git a/conf/application.conf b/conf/application.conf index 26ce8df..7f4eaa7 100644 --- a/conf/application.conf +++ b/conf/application.conf @@ -1,13 +1,8 @@ -# https://www.playframework.com/documentation/latest/SecurityHeaders -# Connect to localhost:9000 for content security policy on websockets -play.filters.headers { - contentSecurityPolicy = "connect-src 'self' ws://localhost:9000" -} # https://www.playframework.com/documentation/latest/AllowedHostsFilter # Allow requests to localhost:9000. play.filters.hosts { - allowed = ["localhost:9000", "localhost"] + allowed = ["localhost:9000", "localhost", "139.59.210.74"] } maps = ["2p_battle_marshes", "2p_fallen_city", "2p_fata_morgana_[Rem]", "2p_meeting_of_minds", "2p_outer_reaches", "2p_quests_triumph", "2p_shrine_of_excellion_[Rem]", "2p_titan_fall_[Rem]", "2p_tranquilitys_end_[rem]", "2p_blood_river_[Rem]", "2p_emerald_river", "2p_deadly_fun_archeology", "2p_fraziersdemise"]