Resolve #7 - Players can now leave a game.
This commit is contained in:
@@ -27,6 +27,15 @@ newPlayer lobbyId name = send defaultSettings
|
||||
} |> fromJson playerSecretDecoder
|
||||
|
||||
|
||||
leave : String -> Secret -> Task.Task Http.Error LobbyAndHand
|
||||
leave lobbyId secret = send defaultSettings
|
||||
{ verb = "POST"
|
||||
, headers = [("Content-Type", "application/json")]
|
||||
, url = url ("/lobbies/" ++ lobbyId ++ "/players/" ++ (toString secret.id) ++ "/leave") []
|
||||
, body = Http.string ("{ \"secret\": \"" ++ secret.secret ++ "\"}")
|
||||
} |> fromJson lobbyAndHandDecoder
|
||||
|
||||
|
||||
addDeck : String -> Secret -> String -> Task.Task Http.Error LobbyAndHand
|
||||
addDeck lobbyId secret deckId = lobbyAction lobbyId (commandEncoder "addDeck" secret [ ("deckId", string deckId) ])
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ type Action
|
||||
| GameEvent Event
|
||||
| AddAi
|
||||
| DismissPlayerNotification (Maybe Notification.Player)
|
||||
| LeaveLobby
|
||||
|
||||
|
||||
eventEffects : Lobby -> Lobby -> Effects.Effects Action
|
||||
|
||||
@@ -74,7 +74,7 @@ diffRound oldRound newRound =
|
||||
in
|
||||
if differentRound then
|
||||
List.filterMap identity
|
||||
[ Maybe.map roundEnd oldRound
|
||||
[ oldRound `Maybe.andThen` roundEnd
|
||||
, Maybe.map roundStart newRound
|
||||
, newRound `Maybe.andThen` (\newRound -> case newRound.responses of
|
||||
Hidden count -> Just (roundPlayed count)
|
||||
@@ -124,13 +124,13 @@ roundJudging round =
|
||||
in
|
||||
RoundJudging played
|
||||
|
||||
roundEnd : Round -> Event
|
||||
roundEnd : Round -> Maybe Event
|
||||
roundEnd round =
|
||||
let
|
||||
responses = case round.responses of
|
||||
Hidden _ -> Nothing
|
||||
Revealed responses -> Just responses
|
||||
played = Maybe.map .cards responses |> Maybe.withDefault []
|
||||
playedByAndWinner = responses `Maybe.andThen` .playedByAndWinner |> Maybe.withDefault (PlayedByAndWinner [] 0)
|
||||
played = Maybe.map .cards responses
|
||||
playedByAndWinner = responses `Maybe.andThen` .playedByAndWinner
|
||||
in
|
||||
RoundEnd round.call round.czar played playedByAndWinner
|
||||
Maybe.map2 (RoundEnd round.call round.czar) played playedByAndWinner
|
||||
|
||||
@@ -38,14 +38,14 @@ port tasks = game.tasks
|
||||
port notifications : Signal String
|
||||
|
||||
|
||||
port jsAction : Signal (Maybe LobbyIdAndSecret)
|
||||
port jsAction
|
||||
port subscription : Signal (Maybe LobbyIdAndSecret)
|
||||
port subscription
|
||||
= game.model
|
||||
|> Signal.map (\setupModel -> case setupModel of
|
||||
Waiting -> Nothing
|
||||
Started model -> Just model.jsAction
|
||||
Started model -> Just model.subscription
|
||||
)
|
||||
|> Signal.filterMap identity Nothing
|
||||
|> Signal.filterMap (Maybe.withDefault Nothing) Nothing
|
||||
|
||||
|
||||
port initialState : Signal InitialState
|
||||
|
||||
@@ -11,7 +11,7 @@ import MassiveDecks.Models.Notification as Notification
|
||||
|
||||
type alias Model =
|
||||
{ state : State
|
||||
, jsAction : Maybe LobbyIdAndSecret
|
||||
, subscription : Maybe (Maybe LobbyIdAndSecret)
|
||||
, global: Global
|
||||
}
|
||||
|
||||
|
||||
@@ -90,6 +90,12 @@ update action global data = case action of
|
||||
in
|
||||
(model global updatedData, Effects.none)
|
||||
|
||||
LeaveLobby ->
|
||||
({ state = SStart { name = "", lobbyId = "" }, subscription = Just Nothing, global = global },
|
||||
(API.leave data.lobby.id data.secret)
|
||||
|> Task.map (\_ -> NoAction)
|
||||
|> API.toEffect)
|
||||
|
||||
GameEvent event ->
|
||||
case event of
|
||||
PlayerStatus id status ->
|
||||
@@ -135,7 +141,7 @@ updateLobby data lobby =
|
||||
model : Global -> ConfigData -> Model
|
||||
model global data =
|
||||
{ state = SConfig data
|
||||
, jsAction = Nothing
|
||||
, subscription = Nothing
|
||||
, global = global
|
||||
}
|
||||
|
||||
@@ -143,7 +149,7 @@ model global data =
|
||||
modelSub : Global -> String -> Secret -> ConfigData -> Model
|
||||
modelSub global lobbyId secret data =
|
||||
{ state = SConfig data
|
||||
, jsAction = Just { lobbyId = lobbyId, secret = secret }
|
||||
, subscription = Just (Just { lobbyId = lobbyId, secret = secret })
|
||||
, global = global
|
||||
}
|
||||
|
||||
|
||||
@@ -81,6 +81,22 @@ update action global data = case action of
|
||||
in
|
||||
(model { global | seed = seed } { data | shownPlayed = shownPlayed }, Effects.none)
|
||||
|
||||
DismissPlayerNotification notification ->
|
||||
let
|
||||
updatedData =
|
||||
if data.playerNotification == notification then
|
||||
{ data | playerNotification = Maybe.map Notification.hide data.playerNotification }
|
||||
else
|
||||
data
|
||||
in
|
||||
(model global updatedData, Effects.none)
|
||||
|
||||
LeaveLobby ->
|
||||
({ state = SStart { name = "", lobbyId = "" }, subscription = Just Nothing, global = global },
|
||||
(API.leave data.lobby.id data.secret)
|
||||
|> Task.map (\_ -> NoAction)
|
||||
|> API.toEffect)
|
||||
|
||||
GameEvent event ->
|
||||
case event of
|
||||
RoundPlayed amount ->
|
||||
@@ -115,10 +131,15 @@ update action global data = case action of
|
||||
|
||||
notificationChange : Global -> PlayingData -> Maybe Notification.Player -> (Model, Effects.Effects Action)
|
||||
notificationChange global data notification =
|
||||
(model global { data | playerNotification = Maybe.oneOf
|
||||
[ notification
|
||||
, data.playerNotification
|
||||
]} , Effects.none)
|
||||
let
|
||||
newNotification = Maybe.oneOf
|
||||
[ notification
|
||||
, data.playerNotification
|
||||
]
|
||||
in
|
||||
( model global { data | playerNotification = newNotification}
|
||||
, Task.sleep (Time.second * 5) `Task.andThen` (\_ -> Task.succeed (DismissPlayerNotification newNotification)) |> Effects.task
|
||||
)
|
||||
|
||||
|
||||
addShownPlayed : Int -> List Attribute -> Seed -> (List Attribute, Effects.Effects Action, Seed)
|
||||
@@ -167,7 +188,7 @@ positioning rotation horizontalPos left verticalPos =
|
||||
model : Global -> PlayingData -> Model
|
||||
model global data =
|
||||
{ state = SPlaying data
|
||||
, jsAction = Nothing
|
||||
, subscription = Nothing
|
||||
, global = global
|
||||
}
|
||||
|
||||
@@ -175,7 +196,7 @@ model global data =
|
||||
modelSub : Global -> String -> Secret -> PlayingData -> Model
|
||||
modelSub global lobbyId secret data =
|
||||
{ state = SPlaying data
|
||||
, jsAction = Just { lobbyId = lobbyId, secret = secret }
|
||||
, subscription = Just (Just { lobbyId = lobbyId, secret = secret })
|
||||
, global = global
|
||||
}
|
||||
|
||||
@@ -183,7 +204,7 @@ modelSub global lobbyId secret data =
|
||||
configModel : Global -> ConfigData -> Model
|
||||
configModel global data =
|
||||
{ state = SConfig data
|
||||
, jsAction = Nothing
|
||||
, subscription = Nothing
|
||||
, global = global
|
||||
}
|
||||
|
||||
|
||||
@@ -46,17 +46,16 @@ roundContents address data round =
|
||||
|> List.any (\player -> player.status == Played)
|
||||
callFill = case round.responses of
|
||||
Revealed responses ->
|
||||
Maybe.withDefault [] (Maybe.map (Util.get responses.cards) data.considering)
|
||||
Maybe.withDefault [] (data.considering `Maybe.andThen` (Util.get responses.cards))
|
||||
Hidden _ ->
|
||||
picked
|
||||
pickedOrChosen = case round.responses of
|
||||
Revealed responses ->
|
||||
case data.considering of
|
||||
Just considering ->
|
||||
let
|
||||
consideringCards = Util.get responses.cards considering
|
||||
in
|
||||
[ consideringView address considering consideringCards isCzar ]
|
||||
case Util.get responses.cards considering of
|
||||
Just consideringCards -> [ consideringView address considering consideringCards isCzar ]
|
||||
Nothing -> []
|
||||
Nothing -> []
|
||||
Hidden _ -> pickedView address pickedWithIndex (Card.slots round.call) data.shownPlayed
|
||||
playedOrHand = case round.responses of
|
||||
@@ -84,7 +83,7 @@ winnerContentsAndHeader address round players =
|
||||
let
|
||||
cards = round.responses
|
||||
winning = Card.winningCards cards round.playedByAndWinner |> Maybe.withDefault []
|
||||
winner = (Util.get players round.playedByAndWinner.winner).name
|
||||
winner = Maybe.map .name (Util.get players round.playedByAndWinner.winner) |> Maybe.withDefault ""
|
||||
in
|
||||
([ div [ class "winner mui-panel" ]
|
||||
[ h1 [] [ icon "trophy" ]
|
||||
|
||||
@@ -40,14 +40,14 @@ root : List Html -> Html
|
||||
root contents = div [ class "content" ] contents
|
||||
|
||||
|
||||
gameMenu : Html
|
||||
gameMenu = div [ class "menu mui-dropdown" ]
|
||||
gameMenu : Signal.Address Action -> Html
|
||||
gameMenu address = div [ class "menu mui-dropdown" ]
|
||||
[ button [ class "mui-btn mui-btn--small mui-btn--primary"
|
||||
, attribute "data-mui-toggle" "dropdown"
|
||||
] [ icon "ellipsis-h" ]
|
||||
, ul [ class "mui-dropdown__menu mui-dropdown__menu--right" ]
|
||||
[ li [] [ a [ href "#", attribute "onClick" "inviteOverlay(event)" ] [ icon "bullhorn", text " Invite Players" ] ]
|
||||
, li [] [ a [ href "#" ] [ icon "sign-out", text " Leave Game" ] ]
|
||||
, li [] [ a [ onClick address LeaveLobby ] [ icon "sign-out", text " Leave Game" ] ]
|
||||
, li [ class "mui-divider" ] []
|
||||
, li [] [ a [ href "#", attribute "onClick" "aboutOverlay(event)" ] [ icon "info-circle", text " About" ] ]
|
||||
, li [] [ a [ href "https://github.com/Lattyware/massivedecks/issues/new", target "_blank" ]
|
||||
|
||||
@@ -54,7 +54,7 @@ appHeader address contents notification = (header [] [ div [ class "mui-appbar m
|
||||
[ div [ class "mui--appbar-line-height" ]
|
||||
[ span [] (List.append [ scoresButton True, scoresButton False ] (notificationPopup address notification))
|
||||
, span [ id "title", class "mui--text-title mui--visible-xs-inline-block" ] contents
|
||||
, gameMenu ] ] ])
|
||||
, gameMenu address ] ] ])
|
||||
|
||||
|
||||
scoresButton : Bool -> Html
|
||||
|
||||
@@ -54,6 +54,12 @@ update action global data = case action of
|
||||
(Config.modelSub global lobbyId secret
|
||||
(Config.initialData lobbyAndHand.lobby secret), Effects.none)
|
||||
|
||||
Notification _ ->
|
||||
(model global data, Effects.none)
|
||||
|
||||
DismissPlayerNotification _ ->
|
||||
(model global data, Effects.none)
|
||||
|
||||
other ->
|
||||
(model global data,
|
||||
DisplayError ("Got an action (" ++ (toString other) ++ ") that can't be handled in the current state (Start).")
|
||||
@@ -64,7 +70,7 @@ update action global data = case action of
|
||||
model : Global -> StartData -> Model
|
||||
model global data =
|
||||
{ state = SStart data
|
||||
, jsAction = Nothing
|
||||
, subscription = Nothing
|
||||
, global = global
|
||||
}
|
||||
|
||||
|
||||
@@ -24,16 +24,15 @@ remove list index =
|
||||
(List.take index list) ++ (List.drop (index + 1) list)
|
||||
|
||||
|
||||
get : List a -> Int -> a
|
||||
get : List a -> Int -> Maybe a
|
||||
get list index = case List.drop index list of
|
||||
[] -> Native.Error.raise <| "Attempted to take element " ++ toString index
|
||||
++ " of list " ++ toString list
|
||||
(item::_) -> item
|
||||
[] -> Nothing
|
||||
(item :: _) -> Just item
|
||||
|
||||
|
||||
getAll : List a -> List Int -> List a
|
||||
getAll list indices =
|
||||
List.map (get list) indices
|
||||
List.filterMap (get list) indices
|
||||
|
||||
|
||||
getAllWithIndex : List a -> List Int -> List (Int, a)
|
||||
|
||||
@@ -17,7 +17,7 @@ import akka.util.Timeout
|
||||
import controllers.massivedecks.game.Actions.Lobby
|
||||
import controllers.massivedecks.game.Actions.Lobby.GetLobby
|
||||
import controllers.massivedecks.game.Actions.Player.Formatters._
|
||||
import controllers.massivedecks.game.Actions.Player.{AddAi, GetHand, NewPlayer}
|
||||
import controllers.massivedecks.game.Actions.Player.{Leave, AddAi, GetHand, NewPlayer}
|
||||
import controllers.massivedecks.game.Actions.Store.{LobbyAction, NewLobby, PlayerAction}
|
||||
import controllers.massivedecks.game.NotFoundException
|
||||
import models.massivedecks.Player.{Id, Secret}
|
||||
@@ -75,6 +75,16 @@ class Application @Inject() (@Named("store") store: ActorRef)(implicit ec: Execu
|
||||
resultOrError(store ? PlayerAction(lobbyId, AddAi))
|
||||
}
|
||||
|
||||
def leave(lobbyId: String, playerId: Int) = Action.async(parse.json) { request: Request[JsValue] =>
|
||||
(request.body \ "secret").validate[String].asOpt match {
|
||||
case Some(secret) =>
|
||||
resultOrError(store ? PlayerAction(lobbyId, Leave(Secret(Id(playerId), secret))))
|
||||
|
||||
case None =>
|
||||
Future.successful(BadRequest("Badly formed secret provided."))
|
||||
}
|
||||
}
|
||||
|
||||
private def resultOrError(response: Future[Any]): Future[Result] = {
|
||||
val result: Future[Try[JsValue]] = response.mapTo[Try[JsValue]]
|
||||
result.map({
|
||||
|
||||
@@ -21,13 +21,13 @@ object Actions {
|
||||
sealed trait Action
|
||||
case object GetLobby extends Action
|
||||
sealed trait Command extends Action
|
||||
case class Register(secret: Secret, socket: ActorRef) extends Action
|
||||
case class Unregister(secret: Secret, socket: ActorRef) extends Action
|
||||
case class AddDeck(secret: Secret, deckId: String) extends Command
|
||||
case class NewGame(secret: Secret) extends Command
|
||||
case class Play(secret: Secret, ids: List[Int]) extends Command
|
||||
case class Choose(secret: Secret, winner: Int) extends Command
|
||||
case class GetLobbyAndHand(secret: Secret) extends Command
|
||||
case class Register(secret: Secret, socket: ActorRef) extends Action
|
||||
case class Unregister(secret: Secret, socket: ActorRef) extends Action
|
||||
|
||||
object Action {
|
||||
def apply(json: JsValue): Option[Command] =
|
||||
@@ -61,9 +61,11 @@ object Actions {
|
||||
sealed trait Action
|
||||
case class NewPlayer(name: String) extends Action
|
||||
case class GetHand(secret: Secret) extends Action
|
||||
case class Leave(secret: Secret) extends Action
|
||||
case object AddAi extends Action
|
||||
|
||||
object Formatters {
|
||||
implicit val leaveFormat : Format[Leave] = Json.format[Leave]
|
||||
implicit val newPlayerFormat: Format[NewPlayer] = Json.format[NewPlayer]
|
||||
implicit val getHandFormat: Format[GetHand] = Json.format[GetHand]
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import models.massivedecks.Game.Formatters._
|
||||
import models.massivedecks.Player.Secret
|
||||
import controllers.massivedecks.cardcast.CardCastDeck
|
||||
import controllers.massivedecks.game.Game.AddRetrievedDeck
|
||||
import controllers.massivedecks.game.Actions.Player.{AddAi, GetHand, NewPlayer}
|
||||
import controllers.massivedecks.game.Actions.Player.{Leave, AddAi, GetHand, NewPlayer}
|
||||
import controllers.massivedecks.game.Actions.Lobby._
|
||||
|
||||
class Game @Inject()(private val state: State, @Assisted private val id: String)(implicit ec: ExecutionContext) extends Actor {
|
||||
@@ -100,6 +100,12 @@ class Game @Inject()(private val state: State, @Assisted private val id: String)
|
||||
Json.toJson("")
|
||||
}
|
||||
|
||||
case Leave(secret) =>
|
||||
sender() ! Try {
|
||||
state.leave(secret)
|
||||
Json.toJson(state.lobbyAndHand(secret))
|
||||
}
|
||||
|
||||
case _ =>
|
||||
sender() ! Try {
|
||||
throw new IllegalArgumentException("Unknown message: " + message)
|
||||
|
||||
@@ -74,7 +74,7 @@ class State @Inject()(private val cardCast: CardCastAPI, @Assisted val id: Strin
|
||||
}
|
||||
|
||||
def newGame(secret: Secret): Unit = {
|
||||
if (players.length < State.minimumPlayers) {
|
||||
if (numberOfPlayers < State.minimumPlayers) {
|
||||
throw new IllegalStateException(s"You need a minimum of ${State.minimumPlayers} to start a game.")
|
||||
}
|
||||
if (game.isDefined) {
|
||||
@@ -169,14 +169,30 @@ class State @Inject()(private val cardCast: CardCastAPI, @Assisted val id: Strin
|
||||
sendNotifications()
|
||||
}
|
||||
|
||||
def sendNotifications(): Unit = {
|
||||
for (socket <- notifications) {
|
||||
socket ! Json.toJson(lobby).toString()
|
||||
def leave(secret: Secret): Unit = {
|
||||
val id = validateSecretAndGetId(secret)
|
||||
setPlayerStatus(id, Left, force=true)
|
||||
playedInRound = playedInRound.filterKeys(pId => pId != id)
|
||||
if (numberOfPlayers < State.minimumPlayers) {
|
||||
endGame()
|
||||
}
|
||||
game match {
|
||||
case Some(state) =>
|
||||
if (state.round.czar == id) {
|
||||
invalidateRound()
|
||||
} else {
|
||||
if (numberOfPlayersInRound == numberOfPlayersWhoHavePlayed) {
|
||||
beginJudging()
|
||||
}
|
||||
}
|
||||
case None =>
|
||||
}
|
||||
sendNotifications()
|
||||
}
|
||||
|
||||
def register(secret: Secret, socket: ActorRef): Unit = {
|
||||
val id = validateSecretAndGetId(secret)
|
||||
require(playerForId(id).status != Left, "You have left this game.")
|
||||
setPlayerStatus(id, playerStatusIfConnected(id), force=true)
|
||||
notifications = socket :: notifications
|
||||
sendNotifications()
|
||||
@@ -189,6 +205,23 @@ class State @Inject()(private val cardCast: CardCastAPI, @Assisted val id: Strin
|
||||
sendNotifications()
|
||||
}
|
||||
|
||||
private def endGame(): Unit = {
|
||||
playedOrder = None
|
||||
playedInRound = Map()
|
||||
game = None
|
||||
czarIndex = 0
|
||||
}
|
||||
|
||||
private def invalidateRound(): Unit = {
|
||||
advanceRound()
|
||||
}
|
||||
|
||||
private def sendNotifications(): Unit = {
|
||||
for (socket <- notifications) {
|
||||
socket ! Json.toJson(lobby).toString()
|
||||
}
|
||||
}
|
||||
|
||||
private def playerForId(id: Id): Player = players.find(item => item.id == id).get
|
||||
|
||||
private def nextCzar(): Id = {
|
||||
@@ -197,7 +230,7 @@ class State @Inject()(private val cardCast: CardCastAPI, @Assisted val id: Strin
|
||||
}
|
||||
val playerId = players(czarIndex).id
|
||||
czarIndex += 1
|
||||
if (ais.exists(ai => ai.id == playerId)) {
|
||||
if (ais.exists(ai => ai.id == playerId) || playerForId(playerId).status == Left) {
|
||||
nextCzar()
|
||||
} else {
|
||||
playerId
|
||||
@@ -222,6 +255,7 @@ class State @Inject()(private val cardCast: CardCastAPI, @Assisted val id: Strin
|
||||
}
|
||||
}
|
||||
|
||||
private def numberOfPlayers = players.count(player => player.status != Left)
|
||||
private def numberOfPlayersInRound = playedInRound.size
|
||||
private def numberOfPlayersWhoHavePlayed = playedInRound.values.count(play => play.isDefined)
|
||||
|
||||
@@ -236,9 +270,9 @@ class State @Inject()(private val cardCast: CardCastAPI, @Assisted val id: Strin
|
||||
}
|
||||
|
||||
private def advanceRound(): Unit = {
|
||||
val state = validateInGameAndGetState()
|
||||
playedOrder = None
|
||||
playedInRound = Map()
|
||||
val state = validateInGameAndGetState()
|
||||
game = Some(state.copy(round = Round(nextCzar(), state.deck.drawCall(), Responses.hidden(0))))
|
||||
for (player <- players) {
|
||||
setPlayerStatus(player.id, NotPlayed)
|
||||
@@ -248,16 +282,19 @@ class State @Inject()(private val cardCast: CardCastAPI, @Assisted val id: Strin
|
||||
|
||||
private val stickyStatus: Set[Status] = Set(Disconnected, Left, Ai)
|
||||
|
||||
private def setPlayerStatus(id: Id, status: Status, force: Boolean = false): Unit =
|
||||
players = players.map(player => if (player.id == id) {
|
||||
if (force || !stickyStatus.contains(player.status)) {
|
||||
player.copy(status = status)
|
||||
private def setPlayerStatus(id: Id, status: Status, force: Boolean = false): Unit = {
|
||||
if (playerForId(id).status != Left) {
|
||||
players = players.map(player => if (player.id == id) {
|
||||
if (force || !stickyStatus.contains(player.status)) {
|
||||
player.copy(status = status)
|
||||
} else {
|
||||
player
|
||||
}
|
||||
} else {
|
||||
player
|
||||
}
|
||||
} else {
|
||||
player
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private def validateInGameAndGetState(): GameState = game match {
|
||||
case Some(state) => state
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
<body>
|
||||
<script src="@routes.Assets.at("javascripts/Main.js")"></script>
|
||||
<script>
|
||||
var socket = null;
|
||||
var gameCode = window.location.hash.substr(1);
|
||||
var existingGame = localStorage.getItem("existingGame");
|
||||
if (existingGame != null) {
|
||||
@@ -34,7 +35,9 @@
|
||||
};
|
||||
|
||||
var game = Elm.fullscreen(Elm.MassiveDecks.Main, { notifications: "", initialState: initialState });
|
||||
game.ports.initialState.send(initialState)
|
||||
|
||||
game.ports.initialState.send(initialState);
|
||||
|
||||
function openWebSocket(lobbyId, secret) {
|
||||
var loc = window.location, new_uri;
|
||||
if (loc.protocol === "https:") {
|
||||
@@ -44,7 +47,10 @@
|
||||
}
|
||||
new_uri += "//" + loc.host;
|
||||
new_uri += loc.pathname + "lobbies/" + lobbyId + "/notifications";
|
||||
var socket = new WebSocket(new_uri);
|
||||
if (socket != null) {
|
||||
socket.close();
|
||||
}
|
||||
socket = new WebSocket(new_uri);
|
||||
socket.onopen = function (event) {
|
||||
socket.send(JSON.stringify(secret));
|
||||
}
|
||||
@@ -52,15 +58,26 @@
|
||||
game.ports.notifications.send(event.data);
|
||||
}
|
||||
socket.onclose = function (event) {
|
||||
openWebSocket(lobbyId, secret);
|
||||
if (socket != null) {
|
||||
openWebSocket(lobbyId, secret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
game.ports.jsAction.subscribe(function (lobbyIdAndSecret) {
|
||||
game.ports.subscription.subscribe(function (lobbyIdAndSecret) {
|
||||
console.log(lobbyIdAndSecret);
|
||||
if (lobbyIdAndSecret != null) {
|
||||
localStorage.setItem("existingGame", JSON.stringify(lobbyIdAndSecret))
|
||||
openWebSocket(lobbyIdAndSecret.lobbyId, lobbyIdAndSecret.secret);
|
||||
window.location = "#" + lobbyIdAndSecret.lobbyId;
|
||||
} else {
|
||||
if (socket != null) {
|
||||
window.location = "#";
|
||||
localStorage.removeItem("existingGame");
|
||||
var oldSocket = socket;
|
||||
socket = null;
|
||||
oldSocket.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
+8
-7
@@ -4,13 +4,14 @@
|
||||
|
||||
GET / controllers.massivedecks.Application.index()
|
||||
|
||||
POST /lobbies controllers.massivedecks.Application.createLobby()
|
||||
GET /lobbies/:id controllers.massivedecks.Application.getLobby(id: String)
|
||||
GET /lobbies/:id/notifications controllers.massivedecks.Application.notifications(id: String)
|
||||
POST /lobbies/:lobbyId controllers.massivedecks.Application.command(lobbyId: String)
|
||||
POST /lobbies/:lobbyId/players controllers.massivedecks.Application.newPlayer(lobbyId: String)
|
||||
POST /lobbies/:lobbyId/players/newAi controllers.massivedecks.Application.newAi(lobbyId: String)
|
||||
POST /lobbies/:lobbyId/players/:playerId controllers.massivedecks.Application.getPlayer(lobbyId: String, playerId: Int)
|
||||
POST /lobbies controllers.massivedecks.Application.createLobby()
|
||||
GET /lobbies/:id controllers.massivedecks.Application.getLobby(id: String)
|
||||
GET /lobbies/:id/notifications controllers.massivedecks.Application.notifications(id: String)
|
||||
POST /lobbies/:lobbyId controllers.massivedecks.Application.command(lobbyId: String)
|
||||
POST /lobbies/:lobbyId/players controllers.massivedecks.Application.newPlayer(lobbyId: String)
|
||||
POST /lobbies/:lobbyId/players/newAi controllers.massivedecks.Application.newAi(lobbyId: String)
|
||||
POST /lobbies/:lobbyId/players/:playerId controllers.massivedecks.Application.getPlayer(lobbyId: String, playerId: Int)
|
||||
POST /lobbies/:lobbyId/players/:playerId/leave controllers.massivedecks.Application.leave(lobbyId: String, playerId: Int)
|
||||
|
||||
# Map static resources from the /public folder to the /assets URL path
|
||||
GET /assets/*file controllers.Assets.at(path="/public", file: String)
|
||||
|
||||
Reference in New Issue
Block a user