A lot of refactoring for new lobby

This commit is contained in:
Andrew 2023-03-04 15:05:34 +07:00
parent 943af813e6
commit cb411b59b3

View file

@ -52,8 +52,9 @@ class Client {
class Game { class Game {
private id: String; private id: String;
private player1: Client; private guesser: Client;
private player2: Client; private suggester: Client;
private tries: number;
private guesses: Set<String>; private guesses: Set<String>;
private colors: Set<String>; private colors: Set<String>;
@ -62,10 +63,13 @@ class Game {
return this.id; return this.id;
} }
public get Guesser() { public get Guesser() {
return this.player1; return this.guesser;
} }
public get Suggester() { public get Suggester() {
return this.player2; return this.suggester;
}
public get Tries() {
return this.tries;
} }
public get Guesses() { public get Guesses() {
return this.guesses; return this.guesses;
@ -74,10 +78,11 @@ class Game {
return this.colors; return this.colors;
} }
constructor(id: String, player1: Client, player2: Client) { constructor(id: String, guesser: Client, suggester: Client, tries: number) {
this.id = id; this.id = id;
this.player1 = player1; this.guesser = guesser;
this.player2 = player2; this.suggester = suggester;
this.tries = tries;
this.guesses = new Set<String>(); this.guesses = new Set<String>();
this.colors = new Set<String>(); this.colors = new Set<String>();
@ -88,10 +93,10 @@ class Game {
} }
public Opponent(player: Client): Client { public Opponent(player: Client): Client {
if (this.player1 === player) { if (this.guesser === player) {
return this.player2; return this.suggester;
} }
return this.player1; return this.guesser;
} }
public Guess(player: Client, guess: String) { public Guess(player: Client, guess: String) {
@ -120,42 +125,60 @@ class Game {
} }
public GameLost() { public GameLost() {
return this.guesses.size >= 10; const countOfGuesses = this.guesses.size;
const countOfCorrectGuesses = Array.from(this.guesses).filter((guess) => this.colors.has(guess)).length;
return countOfGuesses - countOfCorrectGuesses >= this.tries;
} }
public simplify() { public simplify() {
return { return {
id: this.id, id: this.id,
player1: this.player1.login, guesser: this.guesser.login,
player2: this.player2.login, suggester: this.suggester.login,
tries: this.tries,
}; };
} }
} }
class Room { class AvailableGame {
private _availablePlayers: Map<String, Client>; private _id: String;
private _player: Client;
private _tries: number;
private _neededRole: String;
public get availablePlayers() { public get id(): String {
return this._availablePlayers; return this._id;
}
public get player(): Client {
return this._player;
}
public get tries(): number {
return this._tries;
}
public get neededRole(): String {
return this._neededRole;
} }
constructor() { constructor(id: String, player: Client, tries: number, neededRole: String) {
this._availablePlayers = new Map<String, Client>(); this._id = id;
this._player = player;
this._tries = tries;
this._neededRole = neededRole;
} }
public addPlayer(player: Client) { simplify() {
this._availablePlayers.set(player.login, player); return {
} id: this.id,
player: this.player.login,
public removePlayer(player: Client) { tries: this.tries,
this._availablePlayers.delete(player.login); neededRole: this.neededRole,
};
} }
} }
let registeredClients: Client[] = []; let registeredClients: Client[] = [];
let onlineClients: Map<Socket, Client> = new Map<Socket, Client>(); let onlineClients: Map<Socket, Client> = new Map<Socket, Client>();
let guessersRoom: Room = new Room(); let availableGames: Map<String, AvailableGame> = new Map<String, AvailableGame>();
let suggestersRoom: Room = new Room();
let runningGames: Map<String, Game> = new Map<String, Game>(); let runningGames: Map<String, Game> = new Map<String, Game>();
app.get("/", (req, res) => { app.get("/", (req, res) => {
@ -209,146 +232,164 @@ io.on("connection", (socket) => {
onlineClients.set(socket, new Client(login, password)); onlineClients.set(socket, new Client(login, password));
socket.emit("login", true, "User logged in successfully"); socket.emit("login", true, "User logged in successfully");
registerSocketLoggedInFunctions(socket);
io.emit("updateNeeded"); io.emit("updateNeeded");
}); });
socket.on("getUpdate", () => { socket.on("disconnect", () => {
const client = onlineClients.get(socket); const client = onlineClients.get(socket);
if (client === undefined) { if (client !== undefined) {
socket.emit("update", false, 403); console.log("user " + client.login + " disconnected");
return; for (const game of Array.from(availableGames.values())) {
if (game.player === client) {
availableGames.delete(game.id);
return;
}
}
if (client.inGame) {
const game = Array.from(runningGames.values()).find((game) => game.Guesser === client || game.Suggester === client);
if (game !== undefined) {
const opponentPlayer = game.Opponent(client);
const otherClientSocket = Array.from(onlineClients.keys()).find((key) => onlineClients.get(key)?.login === opponentPlayer.login);
if (otherClientSocket !== undefined) {
otherClientSocket.emit("leaveGameResponse", true, 410);
}
client.setInGame(false);
opponentPlayer.setInGame(false);
runningGames.delete(game.Id);
}
}
onlineClients.delete(socket);
} else {
console.log("anonymous disconnected");
} }
io.emit("updateNeeded");
});
});
instrument(io, {
mode: "development",
auth: {
type: "basic",
username: "admin",
password: "$2a$12$84FqmSh7yVv46tdygZ2rNuJYqWPXYtYC3JxjSJBY8PyXB0Oe8qCfO",
},
});
server.listen(9800, () => {
console.log("⚡️ listening on *:9800");
});
function registerSocketLoggedInFunctions(socket: Socket) {
socket.on("getUpdate", getUpdateEventHandler);
socket.on("createGame", createGameEventHandler);
socket.on("joinGame", joinGameEventHandler);
socket.on("removeGame", removeGameEventHandler);
socket.on("chat", chatEventHandler);
socket.on("guess", guessEventHandler);
socket.on("leaveGame", leaveGameEventHandler);
const client = onlineClients.get(socket)!;
function getUpdateEventHandler(): void {
socket.emit("update", true, { socket.emit("update", true, {
guessers: Array.from(guessersRoom.availablePlayers.values()).map((e) => e.login), availableGames: Array.from(availableGames.values()).map((e) => e.simplify()),
suggesters: Array.from(suggestersRoom.availablePlayers.values()).map((e) => e.login),
}); });
}); }
socket.on("join", (room) => { function createGameEventHandler(tries: number, role: String): void {
const client = onlineClients.get(socket); if (client.inGame) {
if (client === undefined) { socket.emit("createGameResponse", false, "Player is already in game");
socket.emit("joinResponse", false, 403);
return; return;
} }
if (client.inGame || guessersRoom.availablePlayers.has(client.login) || suggestersRoom.availablePlayers.has(client.login)) { if (tries < 20 || tries > 50) {
socket.emit("joinResponse", false, 400); socket.emit("createGameResponse", false, "Tries must be between 20 and 50");
return; return;
} }
if (room === "guessers") { if (role !== "guesser" && role !== "suggester") {
guessersRoom.addPlayer(client); socket.emit("createGameResponse", false, "Role must be 'guesser' or 'suggester'");
console.log("user " + client.login + " joined guessers"); return;
socket.emit("joinResponse", [true]); }
io.emit("updateNeeded");
} else if (room === "suggesters") { for (const game of Array.from(availableGames.values())) {
suggestersRoom.addPlayer(client); if (game.player.login === client.login) {
console.log("user " + client.login + " joined suggesters"); socket.emit("createGameResponse", false, "You already created a game");
socket.emit("joinResponse", [true]); return;
io.emit("updateNeeded"); }
}
const game = new AvailableGame(uuidv4(), client, tries, role);
availableGames.set(game.id, game);
io.emit("updateNeeded");
}
function joinGameEventHandler(gameId: String): void {
const game = availableGames.get(gameId);
if (game === undefined) {
socket.emit("joinGameResponse", false, "Game does not exist");
return;
}
if (game.player.login === client.login) {
socket.emit("joinGameResponse", false, "You cannot join your own game");
return;
}
if (game.player.inGame) {
socket.emit("joinGameResponse", false, "Player is already in game");
return;
}
const gameSocket = Array.from(onlineClients.keys()).find((key) => onlineClients.get(key)?.login === game.player.login);
if (gameSocket === undefined) {
socket.emit("joinGameResponse", false, "Player is not online");
return;
}
availableGames.delete(gameId);
io.emit("updateNeeded");
let suggester: Client;
let guesser: Client;
if (game.neededRole === "suggester") {
suggester = client;
guesser = game.player;
} else { } else {
socket.emit("joinResponse", false, 400); suggester = game.player;
console.log("user " + client.login + " tried to join non existing room"); guesser = client;
} }
}); suggester.setInGame(true);
guesser.setInGame(true);
const gameInfo = new Game(uuidv4(), guesser, suggester, game.tries);
const suggesterSocket = Array.from(onlineClients.keys()).find((key) => onlineClients.get(key)?.login === suggester.login)!;
const guesserSocket = Array.from(onlineClients.keys()).find((key) => onlineClients.get(key)?.login === guesser.login)!;
suggesterSocket.emit("joinGameResponse", true, gameInfo.simplify(), Array.from(gameInfo.Colors));
guesserSocket.emit("joinGameResponse", true, gameInfo.simplify(), []);
runningGames.set(gameInfo.Id, gameInfo);
}
socket.on("leave", (room) => { function removeGameEventHandler(gameId: String): void {
const client = onlineClients.get(socket); const game = availableGames.get(gameId);
if (client === undefined) { if (game === undefined) {
socket.emit("leaveResponse", false, 403); socket.emit("removeGameResponse", false, "Game does not exist");
return; return;
} }
if (client.inGame || (!guessersRoom.availablePlayers.has(client.login) && !suggestersRoom.availablePlayers.has(client.login))) { if (game.player.login !== client.login) {
socket.emit("leaveResponse", false, 400); socket.emit("removeGameResponse", false, "You cannot remove game that is not yours");
return; return;
} }
if (room === "guessers") { availableGames.delete(gameId);
guessersRoom.removePlayer(client); io.emit("updateNeeded");
console.log("user " + client.login + " left guessers"); }
socket.emit("leaveResponse", [true]);
io.emit("updateNeeded");
} else if (room === "suggesters") {
suggestersRoom.removePlayer(client);
console.log("user " + client.login + " left suggesters");
socket.emit("leaveResponse", [true]);
io.emit("updateNeeded");
} else {
socket.emit("leaveResponse", false, 400);
console.log("user " + client.login + " tried to left non existing room");
}
});
socket.on("sendRequest", (sendTo) => {
const client = onlineClients.get(socket);
if (client === undefined) {
socket.emit("sendRequestResponse", false, 403);
return;
}
if (client.inGame || sendTo === client.login) {
socket.emit("sendRequestResponse", false, 400);
return;
}
const otherClientSocket = Array.from(onlineClients.keys()).find((key) => onlineClients.get(key)?.login === sendTo);
if (otherClientSocket === undefined) {
socket.emit("sendRequestResponse", false, 404);
return;
}
otherClientSocket.emit("gameRequest", client.login);
socket.emit("sendRequestResponse", [true]);
});
socket.on("requestResponse", (requester: String, response: Boolean) => {
const client = onlineClients.get(socket);
if (client === undefined) {
socket.emit("requestResponseResult", false, 403);
return;
}
if (client.inGame || requester === client.login) {
socket.emit("requestResponseResult", false, 400);
return;
}
const otherClientSocket = Array.from(onlineClients.keys()).find((key) => onlineClients.get(key)?.login === requester);
if (otherClientSocket === undefined) {
socket.emit("requestResponseResult", false, 404);
return;
}
const otherClient = onlineClients.get(otherClientSocket)!;
if (response) {
const isClientInGuessers = guessersRoom.availablePlayers.has(client.login);
guessersRoom.removePlayer(client);
suggestersRoom.removePlayer(client);
guessersRoom.removePlayer(otherClient);
suggestersRoom.removePlayer(otherClient);
io.emit("updateNeeded");
const game = new Game(uuidv4(), isClientInGuessers ? client : otherClient, isClientInGuessers ? otherClient : client);
runningGames.set(game.Id, game);
client.setInGame(true);
otherClient.setInGame(true);
socket.emit("requestResponseResult", true, game.simplify(), Array.from(game.Guesses));
otherClientSocket.emit("requestResponseResult", true, game.simplify(), Array.from(game.Colors));
} else {
socket.emit("requestResponseResult", false, `You declined ${client.login} request`);
otherClientSocket.emit("requestResponseResult", false, `${client.login} declined your request`);
}
});
socket.on("chat", (gameId, message) => {
const client = onlineClients.get(socket);
if (client === undefined) {
socket.emit("chatResponse", false, 403);
return;
}
function chatEventHandler(gameId: String, message: String): void {
const game = runningGames.get(gameId); const game = runningGames.get(gameId);
if (game === undefined || !client.inGame) { if (game === undefined || !client.inGame) {
socket.emit("chatResponse", false, 400); socket.emit("chatResponse", false, 400);
@ -374,15 +415,9 @@ io.on("connection", (socket) => {
from: client.login, from: client.login,
message, message,
}); });
}); }
socket.on("guess", (gameId, guess) => {
const client = onlineClients.get(socket);
if (client === undefined) {
socket.emit("guessResponse", false, 403);
return;
}
function guessEventHandler(gameId: String, guess: String): void {
const game = runningGames.get(gameId); const game = runningGames.get(gameId);
if (game === undefined || !client.inGame) { if (game === undefined || !client.inGame) {
socket.emit("guessResponse", false, 400); socket.emit("guessResponse", false, 400);
@ -428,15 +463,9 @@ io.on("connection", (socket) => {
opponentPlayer.setInGame(false); opponentPlayer.setInGame(false);
runningGames.delete(gameId); runningGames.delete(gameId);
} }
}); }
socket.on("leaveGame", (gameId) => {
const client = onlineClients.get(socket);
if (client === undefined) {
socket.emit("guessResponse", false, 403);
return;
}
function leaveGameEventHandler(gameId: String): void {
const game = runningGames.get(gameId); const game = runningGames.get(gameId);
if (game === undefined || !client.inGame) { if (game === undefined || !client.inGame) {
socket.emit("guessResponse", false, 400); socket.emit("guessResponse", false, 400);
@ -455,46 +484,5 @@ io.on("connection", (socket) => {
client.setInGame(false); client.setInGame(false);
opponentPlayer.setInGame(false); opponentPlayer.setInGame(false);
runningGames.delete(game.Id); runningGames.delete(game.Id);
}); }
}
socket.on("disconnect", () => {
const client = onlineClients.get(socket);
if (client !== undefined) {
console.log("user " + client.login + " disconnected");
guessersRoom.removePlayer(client);
suggestersRoom.removePlayer(client);
if (client.inGame) {
const game = Array.from(runningGames.values()).find((game) => game.Guesser === client || game.Suggester === client);
if (game !== undefined) {
const opponentPlayer = game.Opponent(client);
const otherClientSocket = Array.from(onlineClients.keys()).find((key) => onlineClients.get(key)?.login === opponentPlayer.login);
if (otherClientSocket !== undefined) {
otherClientSocket.emit("leaveGameResponse", true, 410);
}
client.setInGame(false);
opponentPlayer.setInGame(false);
runningGames.delete(game.Id);
}
}
onlineClients.delete(socket);
} else {
console.log("anonymous disconnected");
}
io.emit("updateNeeded");
});
});
instrument(io, {
mode: "development",
auth: {
type: "basic",
username: "admin",
password: "$2a$12$84FqmSh7yVv46tdygZ2rNuJYqWPXYtYC3JxjSJBY8PyXB0Oe8qCfO",
},
});
server.listen(9800, () => {
console.log("⚡️ listening on *:9800");
});