|
|
|
|
@@ -14,7 +14,6 @@ import * as c from "./constants.js"
|
|
|
|
|
import { Client, ClientPlayer, ClientSpectator } from "./class/Client.js"
|
|
|
|
|
import { GameSession } from "./class/GameSession.js"
|
|
|
|
|
import { shortId } from "./utils.js";
|
|
|
|
|
import { gameSessionIdPLACEHOLDER } from "./constants.js";
|
|
|
|
|
|
|
|
|
|
const wsPort = 8042;
|
|
|
|
|
export const wsServer = new WebSocketServer<WebSocket>({host: "0.0.0.0", port: wsPort, path: "/pong"});
|
|
|
|
|
@@ -23,12 +22,12 @@ const matchmakingMap: Map<string, ClientPlayer> = new Map; // socket.id/ClientPl
|
|
|
|
|
const privateMatchmakingMap: Map<string, ClientPlayer> = new Map; // socket.id/ClientPlayer (duplicates with clientsMap)
|
|
|
|
|
const gameSessionsMap: Map<string, GameSession> = new Map; // GameSession.id(url)/GameSession
|
|
|
|
|
|
|
|
|
|
wsServer.on("connection", connectionListener);
|
|
|
|
|
wsServer.on("error", errorListener);
|
|
|
|
|
wsServer.on("close", closeListener);
|
|
|
|
|
wsServer.on("connection", serverConnectionListener);
|
|
|
|
|
wsServer.on("error", serverErrorListener);
|
|
|
|
|
wsServer.on("close", serverCloseListener);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function connectionListener(socket: WebSocket, request: IncomingMessage)
|
|
|
|
|
function serverConnectionListener(socket: WebSocket, request: IncomingMessage)
|
|
|
|
|
{
|
|
|
|
|
const id = uuidv4();
|
|
|
|
|
const client = new Client(socket, id);
|
|
|
|
|
@@ -40,7 +39,11 @@ function connectionListener(socket: WebSocket, request: IncomingMessage)
|
|
|
|
|
console.log(`client ${shortId(client.id)} is alive`);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
socket.on("error", function errorPrint(this: WebSocket, err: Error) {
|
|
|
|
|
socket.on("close", function removeClient() {
|
|
|
|
|
clientTerminate(client);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
socket.on("error", function errorLog(this: WebSocket, err: Error) {
|
|
|
|
|
console.log(`error socket ${shortId(this.id)}:`);
|
|
|
|
|
console.log(`${err.name}: ${err.message}`);
|
|
|
|
|
if (err.stack) {
|
|
|
|
|
@@ -48,7 +51,7 @@ function connectionListener(socket: WebSocket, request: IncomingMessage)
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
socket.on("message", function log(data: string) {
|
|
|
|
|
socket.on("message", function messageLog(data: string) {
|
|
|
|
|
try {
|
|
|
|
|
const event: ev.ClientEvent = JSON.parse(data);
|
|
|
|
|
if (event.type === en.EventTypes.clientInput) {
|
|
|
|
|
@@ -69,13 +72,11 @@ async function clientAnnounceListener(this: WebSocket, data: string)
|
|
|
|
|
const msg : ev.ClientAnnounce = JSON.parse(data);
|
|
|
|
|
if (msg.type === en.EventTypes.clientAnnounce)
|
|
|
|
|
{
|
|
|
|
|
// TODO: reconnection with msg.clientId ?
|
|
|
|
|
// "/pong" to play, "/pong?ID_OF_A_GAMESESSION" to spectate (or something like that)
|
|
|
|
|
// BONUS: reconnection with msg.clientId ?
|
|
|
|
|
if (msg.role === en.ClientRole.player)
|
|
|
|
|
{
|
|
|
|
|
const announce: ev.ClientAnnouncePlayer = <ev.ClientAnnouncePlayer>msg;
|
|
|
|
|
|
|
|
|
|
// WIP nest, fetch token validation
|
|
|
|
|
const body = {
|
|
|
|
|
playerOneUsername: announce.username,
|
|
|
|
|
playerTwoUsername: "",
|
|
|
|
|
@@ -96,7 +97,7 @@ async function clientAnnounceListener(this: WebSocket, data: string)
|
|
|
|
|
});
|
|
|
|
|
if (!response.ok)
|
|
|
|
|
{
|
|
|
|
|
this.send(JSON.stringify( new ev.EventError((await response.json()).message)));
|
|
|
|
|
this.send(JSON.stringify( new ev.EventError((await response.json()).message) ));
|
|
|
|
|
clientTerminate(clientsMap.get(this.id));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
@@ -122,13 +123,14 @@ async function clientAnnounceListener(this: WebSocket, data: string)
|
|
|
|
|
const announce: ev.ClientAnnounceSpectator = <ev.ClientAnnounceSpectator>msg;
|
|
|
|
|
const gameSession = gameSessionsMap.get(announce.gameSessionId);
|
|
|
|
|
if (!gameSession) {
|
|
|
|
|
this.send(JSON.stringify( new ev.EventError("invalid gameSessionId")));
|
|
|
|
|
this.send(JSON.stringify( new ev.EventError("invalid gameSessionId") ));
|
|
|
|
|
clientTerminate(clientsMap.get(this.id));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const spectator = clientsMap.get(this.id) as ClientSpectator;
|
|
|
|
|
spectator.gameSession = gameSession;
|
|
|
|
|
gameSession.spectatorsMap.set(spectator.id, spectator);
|
|
|
|
|
spectator.socket.once("message", spectatorReadyConfirmationListener);
|
|
|
|
|
this.send(JSON.stringify( new ev.ServerEvent(en.EventTypes.matchStart) ));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -224,7 +226,7 @@ function privateMatchmaking(player: ClientPlayer)
|
|
|
|
|
|
|
|
|
|
function createGameSession(playersArr: ClientPlayer[], matchOptions: en.MatchOptions)
|
|
|
|
|
{
|
|
|
|
|
// const id = gameSessionIdPLACEHOLDER; // Force ID, TESTING SPECTATOR
|
|
|
|
|
// const id = c.gameSessionIdPLACEHOLDER; // Force ID, TESTING SPECTATOR
|
|
|
|
|
const id = uuidv4();
|
|
|
|
|
const gameSession = new GameSession(id, matchOptions);
|
|
|
|
|
gameSessionsMap.set(id, gameSession);
|
|
|
|
|
@@ -274,7 +276,6 @@ async function playerReadyConfirmationListener(this: WebSocket, data: string)
|
|
|
|
|
gameSession.unreadyPlayersMap.delete(this.id);
|
|
|
|
|
if (gameSession.unreadyPlayersMap.size === 0)
|
|
|
|
|
{
|
|
|
|
|
// WIP nest , send gameSession.id
|
|
|
|
|
const gameSessionPlayersIterator = gameSession.playersMap.values();
|
|
|
|
|
const body = {
|
|
|
|
|
gameServerIdOfTheMatch : gameSession.id,
|
|
|
|
|
@@ -341,6 +342,28 @@ export function clientInputListener(this: WebSocket, data: string)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function spectatorReadyConfirmationListener(this: WebSocket, data: string)
|
|
|
|
|
{
|
|
|
|
|
try {
|
|
|
|
|
const msg : ev.ClientEvent = JSON.parse(data);
|
|
|
|
|
if (msg.type === en.EventTypes.clientSpectatorReady)
|
|
|
|
|
{
|
|
|
|
|
const client = clientsMap.get(this.id);
|
|
|
|
|
const gameSession = client.gameSession;
|
|
|
|
|
const scoreUpdate = new ev.EventScoreUpdate(gameSession.components.scoreLeft, gameSession.components.scoreRight);
|
|
|
|
|
this.send(JSON.stringify(scoreUpdate));
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
console.log("Invalid spectatorReadyConfirmation");
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
catch (e) {
|
|
|
|
|
console.log("Invalid JSON (spectatorReadyConfirmationListener)");
|
|
|
|
|
}
|
|
|
|
|
this.once("message", spectatorReadyConfirmationListener);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////
|
|
|
|
|
////////////
|
|
|
|
|
|
|
|
|
|
@@ -390,13 +413,13 @@ export function clientTerminate(client: Client)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function closeListener()
|
|
|
|
|
function serverCloseListener()
|
|
|
|
|
{
|
|
|
|
|
clearInterval(pingInterval);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function errorListener(error: Error)
|
|
|
|
|
function serverErrorListener(error: Error)
|
|
|
|
|
{
|
|
|
|
|
console.log("Error: " + JSON.stringify(error));
|
|
|
|
|
}
|
|
|
|
|
|