Add player list to game lobby
This commit is contained in:
parent
38a36aaa13
commit
3d2fb445ed
@ -16,6 +16,10 @@ public class Destinations {
|
||||
|
||||
public static final String OPPONENT_REPORTS = topicDestination("opponentReports");
|
||||
|
||||
public static final String PLAYER_JOINED = topicDestination("playerJoined");
|
||||
|
||||
public static final String PLAYER_LEFT = topicDestination("playerLeft");
|
||||
|
||||
public static final String PLAYER_REPORTS = topicDestination("playerReports");
|
||||
|
||||
public static final String PRACTICE_GAME = topicDestination("practiceGame");
|
||||
@ -26,8 +30,6 @@ public class Destinations {
|
||||
|
||||
public static final String SESSION_USERNAME = topicDestination("sessionUsername");
|
||||
|
||||
public static final String USER_JOINED = topicDestination("userJoined");
|
||||
|
||||
private static String topicDestination(String suffix) {
|
||||
return "/topic/" + suffix;
|
||||
}
|
||||
|
@ -2,19 +2,17 @@ package com.charego.lingo.client.multiplayer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import com.charego.lingo.common.LobbyData;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.messaging.simp.stomp.StompFrameHandler;
|
||||
import org.springframework.messaging.simp.stomp.StompHeaders;
|
||||
import org.springframework.messaging.simp.stomp.StompSession.Subscription;
|
||||
@ -142,9 +140,9 @@ public class MultiplayerPresenter implements FxmlController {
|
||||
username = UUID.randomUUID().toString().substring(0, 8);
|
||||
stompTemplate.getSession().send("/app/setUsername", username);
|
||||
|
||||
Collection<Game> games = restTemplate.exchange("/games", HttpMethod.GET, null, new GameList()).getBody();
|
||||
LobbyData lobbyData = restTemplate.getForObject("/data", LobbyData.class);
|
||||
boolean joinedGame = false;
|
||||
for (Game game : games) {
|
||||
for (Game game : lobbyData.getGames()) {
|
||||
if (game.getPlayerTwo() == null) {
|
||||
log.debug("Joining game...");
|
||||
stompTemplate.getSession().send("/app/joinGame", game.getId());
|
||||
@ -440,8 +438,4 @@ public class MultiplayerPresenter implements FxmlController {
|
||||
}
|
||||
}
|
||||
|
||||
private class GameList extends ParameterizedTypeReference<Collection<Game>> {
|
||||
// intentionally left empty
|
||||
}
|
||||
|
||||
}
|
||||
|
35
common/src/main/java/com/charego/lingo/common/LobbyData.java
Normal file
35
common/src/main/java/com/charego/lingo/common/LobbyData.java
Normal file
@ -0,0 +1,35 @@
|
||||
package com.charego.lingo.common;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class LobbyData {
|
||||
|
||||
private Collection<Game> games;
|
||||
|
||||
private Collection<Player> players;
|
||||
|
||||
public LobbyData() {
|
||||
// Empty constructor required for serialization
|
||||
}
|
||||
|
||||
public LobbyData(Collection<Game> games, Collection<Player> players) {
|
||||
this.games = games;
|
||||
this.players = players;
|
||||
}
|
||||
|
||||
public Collection<Game> getGames() {
|
||||
return games;
|
||||
}
|
||||
|
||||
public Collection<Player> getPlayers() {
|
||||
return players;
|
||||
}
|
||||
|
||||
public void setGames(Collection<Game> games) {
|
||||
this.games = games;
|
||||
}
|
||||
|
||||
public void setPlayers(Collection<Player> players) {
|
||||
this.players = players;
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@ package com.charego.lingo.server;
|
||||
|
||||
import static org.springframework.messaging.simp.SimpMessageHeaderAccessor.SESSION_ID_HEADER;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
@ -11,6 +10,8 @@ import java.util.TreeMap;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import com.charego.lingo.api.Destinations;
|
||||
import com.charego.lingo.common.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -24,14 +25,6 @@ import org.springframework.messaging.simp.annotation.SubscribeMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.charego.lingo.api.Destinations;
|
||||
import com.charego.lingo.common.ChatMessage;
|
||||
import com.charego.lingo.common.Game;
|
||||
import com.charego.lingo.common.GameLeftMessage;
|
||||
import com.charego.lingo.common.Player;
|
||||
import com.charego.lingo.common.Report;
|
||||
import com.charego.lingo.common.SetUsernameMessage;
|
||||
|
||||
@RestController
|
||||
public class LingoController {
|
||||
|
||||
@ -63,9 +56,9 @@ public class LingoController {
|
||||
return new ChatMessage(player.getUsername(), message);
|
||||
}
|
||||
|
||||
@RequestMapping("/games")
|
||||
public Collection<Game> getGames() {
|
||||
return gameById.values();
|
||||
@RequestMapping("/data")
|
||||
public LobbyData getLobbyData() {
|
||||
return new LobbyData(gameById.values(), sessionManager.getPlayers());
|
||||
}
|
||||
|
||||
@MessageMapping("/guess")
|
||||
@ -179,13 +172,12 @@ public class LingoController {
|
||||
final String username = player.getUsername();
|
||||
usernames.remove(username);
|
||||
final Game game = gameByPlayer.remove(player);
|
||||
if (game == null) {
|
||||
if (game != null) {
|
||||
leaveGame(game, player);
|
||||
}
|
||||
if (username != null) {
|
||||
log.info("{} left", username);
|
||||
send(Destinations.CHAT, new ChatMessage(null, username + " left"));
|
||||
}
|
||||
} else {
|
||||
leaveGame(game, player);
|
||||
send(Destinations.PLAYER_LEFT, username);
|
||||
}
|
||||
}
|
||||
|
||||
@ -256,7 +248,7 @@ public class LingoController {
|
||||
player.setUsername(username);
|
||||
log.info("{} --> {}", sessionId, username);
|
||||
sendToPlayer(player, Destinations.SESSION_USERNAME, new SetUsernameMessage(true, username, null));
|
||||
send(Destinations.USER_JOINED, new Object[] { username, sessionManager.getPlayerCount() });
|
||||
send(Destinations.PLAYER_JOINED, new Object[] { username, sessionManager.getPlayerCount() });
|
||||
} else {
|
||||
log.warn("{} -/> {} : Username taken", sessionId, username);
|
||||
final SetUsernameMessage response = new SetUsernameMessage(false, null, "Username taken");
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.charego.lingo.server;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
@ -44,6 +45,12 @@ public class SessionManager implements ApplicationListener<AbstractSubProtocolEv
|
||||
return playerBySession.size();
|
||||
}
|
||||
|
||||
public Collection<Player> getPlayers() {
|
||||
Collection<Player> allPlayers = new HashSet<>(playerBySession.values());
|
||||
allPlayers.removeIf(p -> p.getUsername() == null);
|
||||
return allPlayers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(AbstractSubProtocolEvent event) {
|
||||
if (event instanceof SessionConnectedEvent) {
|
||||
|
@ -10,6 +10,7 @@ var sessionId = null;
|
||||
var vm = new Vue({
|
||||
el: '#vue-app',
|
||||
data: {
|
||||
players: [],
|
||||
games: [],
|
||||
messages: [],
|
||||
username: null,
|
||||
@ -197,6 +198,16 @@ var vm = new Vue({
|
||||
}
|
||||
this.games.splice(indexToRemove, 1);
|
||||
},
|
||||
removePlayer: function(name) {
|
||||
var indexToRemove = null;
|
||||
for (var i = 0; i < this.players.length; i++) {
|
||||
if (this.players[i].username === name) {
|
||||
indexToRemove = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.players.splice(indexToRemove, 1);
|
||||
},
|
||||
onCanvasKeydown: function(e) {
|
||||
if (e.key === 'Backspace') {
|
||||
e.preventDefault();
|
||||
@ -362,7 +373,7 @@ function main() {
|
||||
}
|
||||
if (usernameSubscription === null) {
|
||||
usernameSubscription = client.subscribe(usernameTopic, usernameHandler);
|
||||
client.subscribe('/topic/userJoined', onUserJoined);
|
||||
client.subscribe('/topic/playerJoined', onPlayerJoined);
|
||||
}
|
||||
client.publish({destination: '/app/setUsername', body: usernameValue})
|
||||
}
|
||||
@ -398,7 +409,9 @@ function start() {
|
||||
}
|
||||
|
||||
// Load initial data
|
||||
doHttpGet('/games', function(games) {
|
||||
doHttpGet('/data', function(data) {
|
||||
var players = data.players;
|
||||
var games = data.games;
|
||||
for (var i = 0; i < games.length; i++) {
|
||||
var game = games[i];
|
||||
vm.games.push({
|
||||
@ -409,6 +422,12 @@ function start() {
|
||||
started: game.playerTwo !== null
|
||||
});
|
||||
}
|
||||
for (var i = 0; i < players.length; i++) {
|
||||
var player = players[i];
|
||||
vm.players.push({
|
||||
username: player.username
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Subscribe to updates
|
||||
@ -417,6 +436,7 @@ function start() {
|
||||
client.subscribe('/topic/gameHosted', onGameHosted);
|
||||
client.subscribe('/topic/gameJoined', onGameJoined);
|
||||
client.subscribe('/topic/gameLeft', onGameLeft);
|
||||
client.subscribe('/topic/playerLeft', onPlayerLeft);
|
||||
client.subscribe('/user/topic/opponentJoined', onOpponentJoined);
|
||||
client.subscribe('/user/topic/opponentReports', onOpponentReport);
|
||||
client.subscribe('/user/topic/playerReports', onPlayerReport);
|
||||
@ -511,9 +531,7 @@ function onGameJoined(message) {
|
||||
var playerOne = game.playerOne.username;
|
||||
var playerTwo = game.playerTwo.username;
|
||||
|
||||
var chatMessage = playerTwo + ' joined ' + playerOne + "'s game"
|
||||
console.log(chatMessage);
|
||||
addChatAnnouncement(chatMessage);
|
||||
console.log(playerTwo + ' joined ' + playerOne + "'s game");
|
||||
|
||||
var vueGame = null;
|
||||
for (var i = 0; i < vm.games.length; i++) {
|
||||
@ -614,7 +632,7 @@ function onPlayerReport(message) {
|
||||
}
|
||||
}
|
||||
|
||||
function onUserJoined(message) {
|
||||
function onPlayerJoined(message) {
|
||||
var report = JSON.parse(message.body);
|
||||
var username = report[0];
|
||||
var numUsers = report[1];
|
||||
@ -627,9 +645,18 @@ function onUserJoined(message) {
|
||||
}
|
||||
} else {
|
||||
addChatAnnouncement(username + ' joined');
|
||||
vm.players.push({
|
||||
username: username
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function onPlayerLeft(message) {
|
||||
var username = message.body;
|
||||
addChatAnnouncement(username + ' left');
|
||||
vm.removePlayer(username);
|
||||
}
|
||||
|
||||
function canShowNotification() {
|
||||
if (document.hidden === 'undefined' || document.hidden === false) {
|
||||
return false;
|
||||
|
@ -40,6 +40,18 @@
|
||||
<button v-show="inGame" @click="leaveGame" type="button" class="leave button">Leave game</button>
|
||||
<button v-show="!inGame" @click="hostGame5" type="button" class="create button">Create 5-letter game</button>
|
||||
<button v-show="!inGame" @click="hostGame6" type="button" class="create button">Create 6-letter game</button>
|
||||
<div class="panel">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Players</h3>
|
||||
</div>
|
||||
<div class="list-group">
|
||||
<div v-if="players.length === 0" class="list-group-item">There are no players</div>
|
||||
<template v-for="player in players">
|
||||
<div class="list-group-item user" v-if="player.username === username">{{ player.username }}</div>
|
||||
<div class="list-group-item" v-else>{{ player.username }}</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-bind:class="{ primary: inStartedGame }" class="game column">
|
||||
|
@ -125,6 +125,11 @@ button:hover:disabled {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.list-group-item.user {
|
||||
background-color: steelblue;
|
||||
color: white;
|
||||
}
|
||||
|
||||
button.list-group-item {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
|
Loading…
x
Reference in New Issue
Block a user