small changes in make_env

This commit is contained in:
simplonco
2023-01-03 11:41:34 +01:00
56 changed files with 2296 additions and 1678 deletions

12
.gitignore vendored
View File

@@ -15,13 +15,11 @@ Thumbs.db
*.log *.log
# compiled output # compiled output
/dist
node_modules node_modules
./srcs/requirement/api_back/node_modules ./srcs/requirement/nestjs/api_back/dist
./srcs/requirement/api_back/dist ./srcs/requirements/svelte/api_front/public/build/
./srcs/requirement/api_front/node_modules
./srcs/requirement/api_front/public/build
# Logs # Logs
logs logs
*.log *.log
@@ -53,3 +51,7 @@ lerna-debug.log*
!.vscode/tasks.json !.vscode/tasks.json
!.vscode/launch.json !.vscode/launch.json
!.vscode/extensions.json !.vscode/extensions.json
.env
memo.txt

View File

@@ -1,3 +1,6 @@
- CONFLICT srcs/requirements/svelte/api_front/public/build/bundle.js
- CONFLICT srcs/requirements/svelte/api_front/public/build/bundle.js.map
### Pour lancer le docker : ### Pour lancer le docker :

View File

@@ -1,6 +1,7 @@
#! /usr/bin/env bash #! /usr/bin/env bash
ENV_FILE_DOCKER=./srcs/.env
ENV_FILE_SVELTE=./srcs/requirements/svelte/api_front/.env
# Function to generate passwords # Function to generate passwords
# #
@@ -12,87 +13,74 @@
echo $(openssl rand -base64 32 | tr "/" "_" ); echo $(openssl rand -base64 32 | tr "/" "_" );
} }
function make_env_for_docker_and_svelte
{
# This script is used to create a new environment for the project. echo "Creating a new environment for docker"
# NODE_ENV=""
ENV_FILE_DOCKER=./srcs/.env # Ask if dev or prod environment
ENV_FILE_NESTJS=./srcs/requirements/nestjs/api_back/.env while [ "$NODE_ENV" != "1" ] && [ "$NODE_ENV" != "2" ]; do
# Check for existing .env read -p "Enter the env configuration for nestjs : \"1\" for development OR \"2\" for production : " NODE_ENV
if [ -f "$ENV_FILE_DOCKER" ] && [ -f "$ENV_FILE_NESTJS" ]; then
echo "The file $ENV_FILE_DOCKER and $ENV_FILE_NESTJS already exists. Do you want to overwrite them ? (y/n)"
OVERWRITE=""
# Ask to overwrite the .env files
while [ "$OVERWRITE" != "y" ] && [ "$OVERWRITE" != "n" ]; do
read -p "Enter your choice : " OVERWRITE
done done
if [ "$OVERWRITE" = "y" ]; then if [ "$NODE_ENV" = "1" ]; then
rm "$ENV_FILE_DOCKER" && rm "$ENV_FILE_NESTJS" echo "NODE_ENV=development" > "$ENV_FILE_DOCKER"
docker rmi -f postgres
else else
echo "The file $ENV_FILE_DOCKER and $ENV_FILE_NESTJS will not be overwritten. The script will exit." echo "NODE_ENV=production" > "$ENV_FILE_DOCKER"
exit 0
fi fi
fi read -p "Enter the name of the host like \"localhost\" : " PROJECT_HOST
echo "WEBSITE_HOST=$PROJECT_HOST" >> "$ENV_FILE_DOCKER"
echo "WEBSITE_PORT=8080" >> "$ENV_FILE_DOCKER"
echo "POSTGRES_USER=postgres" >> "$ENV_FILE_DOCKER"
echo "#if change postgres pswd, do make destroy" >> "$ENV_FILE_DOCKER"
echo "POSTGRES_PASSWORD=$(generate_password)" >> "$ENV_FILE_DOCKER"
echo "POSTGRES_DB=transcendance_db" >> "$ENV_FILE_DOCKER"
echo "POSTGRES_HOST=postgresql" >> "$ENV_FILE_DOCKER"
echo "POSTGRES_PORT=5432" >> "$ENV_FILE_DOCKER"
echo "REDIS_HOST=redis" >> "$ENV_FILE_DOCKER"
echo "REDIS_PORT=6379" >> "$ENV_FILE_DOCKER"
echo "REDIS_PASSWORD=$(generate_password)" >> "$ENV_FILE_DOCKER"
# Connection to 42
echo "In the next steps, we'll need to enter the client secret and client id of the 42 api"
read -p "Enter the client id of the 42 api : " CLIENT_ID
echo "FORTYTWO_CLIENT_ID=$CLIENT_ID" >> "$ENV_FILE_DOCKER"
read -p "Enter the client secret of the 42 api : " CLIENT_SECRET
echo "FORTYTWO_CLIENT_SECRET=$CLIENT_SECRET" >> "$ENV_FILE_DOCKER"
FT_CALLBACK="http://\$WEBSITE_HOST:\$WEBSITE_PORT/api/v2/auth/redirect"
echo "FORTYTWO_CALLBACK_URL=$FT_CALLBACK" >> "$ENV_FILE_DOCKER"
# Other configs
echo "COOKIE_SECRET=$(generate_password)" >> "$ENV_FILE_DOCKER"
echo "PORT=3000" >> "$ENV_FILE_DOCKER"
echo "TWO_FACTOR_AUTHENTICATION_APP_NAME=Transcendance" >> "$ENV_FILE_DOCKER"
echo "TICKET_FOR_PLAYING_GAME_SECRET=$(generate_password)" >> "$ENV_FILE_DOCKER"
grep "^WEBSITE_" "$ENV_FILE_DOCKER" > "$ENV_FILE_SVELTE"
}
function choose_options_and_process {
if [ -f "$ENV_FILE_DOCKER" ]; then
echo "The file $ENV_FILE_DOCKER already exists. Do you want to overwrite it ? (y/n)"
OVERWRITE=""
# Ask to overwrite the .env files
while [ "$OVERWRITE" != "y" ] && [ "$OVERWRITE" != "n" ]; do
read -p "Enter your choice : " OVERWRITE
done
if [ "$OVERWRITE" = "y" ]; then
rm "$ENV_FILE_DOCKER" && rm "$ENV_FILE_SVELTE"
docker rmi -f postgres
make_env_for_docker_and_svelte
else
if [ ! -f "$ENV_FILE_SVELTE" ]; then
grep "^WEBSITE_" "$ENV_FILE_DOCKER" > "$ENV_FILE_SVELTE"
fi
echo "The file $ENV_FILE_DOCKER will not be overwritten. The script will exit."
exit 0
fi
else
make_env_for_docker_and_svelte
fi
}
# Create a new environment for docker
# Create a new environment for docker choose_options_and_process
#
echo "Creating a new environment for docker"
NODE_ENV=""
# Ask if dev or prod environment
while [ "$NODE_ENV" != "1" ] && [ "$NODE_ENV" != "2" ]; do
read -p "Enter the env configuration for nestjs : \"1\" for development OR \"2\" for production : " NODE_ENV
done
if [ "$NODE_ENV" = "1" ]; then
echo "NODE_ENV=development" > "$ENV_FILE_DOCKER"
else
echo "NODE_ENV=production" > "$ENV_FILE_DOCKER"
fi
# Env variables
read -p "Enter the name of the host like \"localhost\" : " PROJECT_HOST
echo "WEBSITE_HOST=$PROJECT_HOST" >> "$ENV_FILE_DOCKER"
echo "WEBSITE_PORT=8080" >> "$ENV_FILE_DOCKER"
echo "POSTGRES_USER=postgres" >> "$ENV_FILE_DOCKER"
echo "#if change postgres pswd, do make destroy" >> "$ENV_FILE_DOCKER"
echo "POSTGRES_PASSWORD=$(generate_password)" >> "$ENV_FILE_DOCKER"
echo "POSTGRES_DB=transcendance_db" >> "$ENV_FILE_DOCKER"
echo "POSTGRES_HOST=postgresql" >> "$ENV_FILE_DOCKER"
echo "POSTGRES_PORT=5432" >> "$ENV_FILE_DOCKER"
echo "REDIS_HOST=redis" >> "$ENV_FILE_DOCKER"
echo "REDIS_PORT=6379" >> "$ENV_FILE_DOCKER"
echo "REDIS_PASSWORD=$(generate_password)" >> "$ENV_FILE_DOCKER"
# Create a new environment for nestjs
#
echo "Creating a new environment for nestjs"
echo "NODE_ENV=\$NODE_ENV" > "$ENV_FILE_NESTJS"
echo "WEBSITE_HOST=\$WEBSITE_HOST" >> "$ENV_FILE_NESTJS"
echo "WEBSITE_PORT=\$WEBSITE_PORT" >> "$ENV_FILE_NESTJS"
echo "POSTGRES_USER=\$POSTGRES_USER" >> "$ENV_FILE_NESTJS"
echo "POSTGRES_PASSWORD=\$POSTGRES_PASSWORD" >> "$ENV_FILE_NESTJS"
echo "POSTGRES_DB=\$POSTGRES_DB" >> "$ENV_FILE_NESTJS"
echo "POSTGRES_HOST=\$POSTGRES_HOST" >> "$ENV_FILE_NESTJS"
echo "POSTGRES_PORT=\$POSTGRES_PORT" >> "$ENV_FILE_NESTJS"
# Connection to 42
echo "In the next steps, we'll need to enter the client secret and client id of the 42 api"
read -p "Enter the client id of the 42 api : " CLIENT_ID
echo "FORTYTWO_CLIENT_ID=$CLIENT_ID" >> "$ENV_FILE_NESTJS"
read -p "Enter the client secret of the 42 api : " CLIENT_SECRET
echo "FORTYTWO_CLIENT_SECRET=$CLIENT_SECRET" >> "$ENV_FILE_NESTJS"
FT_CALLBACK="http://\$WEBSITE_HOST:\$WEBSITE_PORT/api/v2/auth/redirect"
echo "FORTYTWO_CALLBACK_URL=$FT_CALLBACK" >> "$ENV_FILE_NESTJS"
# Other configs
echo "COOKIE_SECRET=$(generate_password)" >> "$ENV_FILE_NESTJS"
echo "PORT=3000" >> "$ENV_FILE_NESTJS"
echo "TWO_FACTOR_AUTHENTICATION_APP_NAME=Transcendance" >> "$ENV_FILE_NESTJS"
echo "TICKET_FOR_PLAYING_GAME_SECRET=$(generate_password)" >> "$ENV_FILE_NESTJS"
# it's finished !
#
echo "The environment has been created successfully. You can now wait for the docker to build the project." echo "The environment has been created successfully. You can now wait for the docker to build the project."

View File

@@ -1,12 +0,0 @@
NODE_ENV=development
WEBSITE_HOST=transcendance
WEBSITE_PORT=8080
POSTGRES_USER=postgres
#if change postgres pswd, do make destroy
POSTGRES_PASSWORD=m7V8CkL+wl+SU1GagenTWP3oyPJx8JJG+tHRiENxoZQ=
POSTGRES_DB=transcendance_db
POSTGRES_HOST=postgresql
POSTGRES_PORT=5432
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=JKDf9vhE4bb5+JW0CvRXVJ2rcV33Bs1MGcQmCxdL+Qs=

View File

@@ -5,24 +5,27 @@ services:
context: ./requirements/nestjs context: ./requirements/nestjs
target: development target: development
dockerfile: Dockerfile dockerfile: Dockerfile
no_cache: true environment:
args: POSTGRES_USER: "${POSTGRES_USER}"
- NODE_ENV=${NODE_ENV} POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
- WEBSITE_HOST=${WEBSITE_HOST} POSTGRES_DB: "${POSTGRES_DB}"
- WEBSITE_PORT=${WEBSITE_PORT} POSTGRES_HOST: "${POSTGRES_HOST}"
- POSTGRES_USER=${POSTGRES_USER} POSTGRES_PORT: "${POSTGRES_PORT}"
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD} NODE_ENV: "${NODE_ENV}"
- POSTGRES_DB=${POSTGRES_DB} WEBSITE_HOST: "${WEBSITE_HOST}"
- POSTGRES_HOST=${POSTGRES_HOST} WEBSITE_PORT: "${WEBSITE_PORT}"
- POSTGRES_PORT=${POSTGRES_PORT} REDIS_HOST: "${REDIS_HOST}"
REDIS_PORT: "${REDIS_PORT}"
FORTYTWO_CLIENT_ID: "${FORTYTWO_CLIENT_ID}"
FORTYTWO_CLIENT_SECRET : "${FORTYTWO_CLIENT_SECRET}"
FORTYTWO_CALLBACK_URL: "${FORTYTWO_CALLBACK_URL}"
COOKIE_SECRET: "${COOKIE_SECRET}"
TWO_FACTOR_AUTHENTICATION_APP_NAME : "${TWO_FACTOR_AUTHENTICATION_APP_NAME}"
TICKET_FOR_PLAYING_GAME_SECRET : "${TICKET_FOR_PLAYING_GAME_SECRET}"
volumes: volumes:
- ./requirements/nestjs/api_back/src:/usr/app/src - ./requirements/nestjs/api_back/src:/usr/app/src
- ./requirements/nestjs/api_back/test:/usr/app/test/ - ./requirements/nestjs/api_back/test:/usr/app/test/
- nestjs_photos_volume:/usr/app/src/uploads/avatars - nestjs_photos_volume:/usr/app/src/uploads/avatars
env_file:
- .env
environment:
NODE_ENV: "${NODE_ENV}"
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
- postgresql - postgresql
@@ -52,9 +55,9 @@ services:
- ./requirements/svelte/api_front/public:/usr/app/public/ - ./requirements/svelte/api_front/public:/usr/app/public/
ports: ports:
- "35729:35729" - "35729:35729"
env_file:
- .env
environment: environment:
WEBSITE_HOST: "${WEBSITE_HOST}"
WEBSITE_PORT: "${WEBSITE_PORT}"
NODE_ENV: "${NODE_ENV}" NODE_ENV: "${NODE_ENV}"
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:

View File

@@ -48,7 +48,10 @@ export class GameSession {
timeout += c.newRoundDelay*0.5; timeout += c.newRoundDelay*0.5;
}); });
} }
resume(s: GameSession) { resume(s?: GameSession)
{
if (!s) { s = this; }
s.playersMap.forEach( (client) => { s.playersMap.forEach( (client) => {
client.socket.on("message", clientInputListener); client.socket.on("message", clientInputListener);
}); });
@@ -59,7 +62,10 @@ export class GameSession {
s.playersUpdateInterval = setInterval(s._playersUpdate, c.playersUpdateIntervalMS, s); s.playersUpdateInterval = setInterval(s._playersUpdate, c.playersUpdateIntervalMS, s);
s.spectatorsUpdateInterval = setInterval(s._spectatorsUpdate, c.spectatorsUpdateIntervalMS, s); s.spectatorsUpdateInterval = setInterval(s._spectatorsUpdate, c.spectatorsUpdateIntervalMS, s);
} }
pause(s: GameSession) { pause(s?: GameSession)
{
if (!s) { s = this; }
s.playersMap.forEach( (client) => { s.playersMap.forEach( (client) => {
client.socket.off("message", clientInputListener); client.socket.off("message", clientInputListener);
}); });
@@ -68,6 +74,19 @@ export class GameSession {
clearInterval(s.playersUpdateInterval); clearInterval(s.playersUpdateInterval);
clearInterval(s.spectatorsUpdateInterval); clearInterval(s.spectatorsUpdateInterval);
} }
destroy(s?: GameSession)
{
if (!s) { s = this; }
s.pause();
s.spectatorsMap.forEach((client) => {
clientTerminate(client);
});
s.playersMap.forEach((client) => {
clientTerminate(client);
});
}
instantInputDebug(client: ClientPlayer) { instantInputDebug(client: ClientPlayer) {
this._handleInput(c.fixedDeltaTime, client); this._handleInput(c.fixedDeltaTime, client);
} }
@@ -135,11 +154,12 @@ export class GameSession {
else if (ball.pos.x < 0 - ball.width) { else if (ball.pos.x < 0 - ball.width) {
++gc.scoreRight; ++gc.scoreRight;
} }
const scoreUpdate = new ev.EventScoreUpdate(gc.scoreLeft, gc.scoreRight);
this.playersMap.forEach( (client) => { this.playersMap.forEach( (client) => {
client.socket.send(JSON.stringify(new ev.EventScoreUpdate(gc.scoreLeft, gc.scoreRight))); client.socket.send(JSON.stringify(scoreUpdate));
}); });
this.spectatorsMap.forEach( (client) => { this.spectatorsMap.forEach( (client) => {
client.socket.send(JSON.stringify(new ev.EventScoreUpdate(gc.scoreLeft, gc.scoreRight))); client.socket.send(JSON.stringify(scoreUpdate));
}); });
} }
private _playersUpdate(s: GameSession) { private _playersUpdate(s: GameSession) {
@@ -148,9 +168,9 @@ export class GameSession {
s.lastStateSnapshot.lastInputId = client.lastInputId; s.lastStateSnapshot.lastInputId = client.lastInputId;
client.socket.send(JSON.stringify(s.lastStateSnapshot)); client.socket.send(JSON.stringify(s.lastStateSnapshot));
}); });
s.lastStateSnapshot.lastInputId = 0;
} }
private _spectatorsUpdate(s: GameSession) { private _spectatorsUpdate(s: GameSession) {
s.lastStateSnapshot.lastInputId = 0;
s.spectatorsMap.forEach( (client) => { s.spectatorsMap.forEach( (client) => {
client.socket.send(JSON.stringify(s.lastStateSnapshot)); client.socket.send(JSON.stringify(s.lastStateSnapshot));
}); });
@@ -200,31 +220,40 @@ export class GameSession {
ball.speed = ball.baseSpeed; ball.speed = ball.baseSpeed;
ball.ballInPlay = true; ball.ballInPlay = true;
} }
private _checkDisconnexions() { private _checkDisconnexions()
{
if (this.playersMap.size !== 2) if (this.playersMap.size !== 2)
{ {
this.matchEnded = true; this.matchEnded = true;
if (this.playersMap.size != 0) if (this.playersMap.size != 0) {
{ this._forfeit();
console.log("Forfeit Ending"); }
const gc = this.components; else {
const luckyWinner: ClientPlayer = this.playersMap.values().next().value; // WIP: envoyer un truc à Nest ? Genre "match draw"
if (luckyWinner.racket === gc.playerLeft) { this.destroy();
this._matchEnd(en.PlayerSide.left, true);
}
else {
this._matchEnd(en.PlayerSide.right, true);
}
} }
return true; return true;
} }
return false; return false;
} }
private _forfeit()
{
this.matchEnded = true;
console.log("Forfeit Ending");
const gc = this.components;
const luckyWinner: ClientPlayer = this.playersMap.values().next().value;
if (luckyWinner.racket === gc.playerLeft) {
this._matchEnd(en.PlayerSide.left, true);
}
else {
this._matchEnd(en.PlayerSide.right, true);
}
}
private async _matchEnd(winner: en.PlayerSide, forfeit_flag: boolean = false) private async _matchEnd(winner: en.PlayerSide, forfeit_flag: boolean = false)
{ {
this.matchEnded = true; this.matchEnded = true;
let eventEnd: ev.EventMatchEnd; const eventEnd = new ev.EventMatchEnd(winner, forfeit_flag);
eventEnd = new ev.EventMatchEnd(winner, forfeit_flag);
this.playersMap.forEach( (client) => { this.playersMap.forEach( (client) => {
client.socket.send(JSON.stringify(eventEnd)); client.socket.send(JSON.stringify(eventEnd));
}); });
@@ -232,7 +261,21 @@ export class GameSession {
client.socket.send(JSON.stringify(eventEnd)); client.socket.send(JSON.stringify(eventEnd));
}); });
// TODO: mettre à jour la route pour gerer les forfaits (actuellement le plus haut score gagne par defaut)
const gc = this.components; const gc = this.components;
console.log("================================= MATCH ENDED");
if (forfeit_flag) {
if (winner === en.PlayerSide.left)
{
gc.scoreLeft = 3
gc.scoreRight = 0
}
else
{
gc.scoreLeft = 0
gc.scoreRight = 3
}
}
await fetch(c.addressBackEnd + "/game/gameserver/updategame", await fetch(c.addressBackEnd + "/game/gameserver/updategame",
{ {
method: "POST", method: "POST",
@@ -246,15 +289,7 @@ export class GameSession {
}) })
}); });
const gameSession = this; setTimeout(this.destroy, 15000, this);
setTimeout(function kickRemainingClients() {
gameSession.spectatorsMap.forEach((client) => {
clientTerminate(client);
});
gameSession.playersMap.forEach((client) => {
clientTerminate(client);
});
}, 15000);
// logs // logs
if (winner === en.PlayerSide.left) { if (winner === en.PlayerSide.left) {

View File

@@ -14,7 +14,6 @@ import * as c from "./constants.js"
import { Client, ClientPlayer, ClientSpectator } from "./class/Client.js" import { Client, ClientPlayer, ClientSpectator } from "./class/Client.js"
import { GameSession } from "./class/GameSession.js" import { GameSession } from "./class/GameSession.js"
import { shortId } from "./utils.js"; import { shortId } from "./utils.js";
import { gameSessionIdPLACEHOLDER } from "./constants.js";
const wsPort = 8042; const wsPort = 8042;
export const wsServer = new WebSocketServer<WebSocket>({host: "0.0.0.0", port: wsPort, path: "/pong"}); 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 privateMatchmakingMap: Map<string, ClientPlayer> = new Map; // socket.id/ClientPlayer (duplicates with clientsMap)
const gameSessionsMap: Map<string, GameSession> = new Map; // GameSession.id(url)/GameSession const gameSessionsMap: Map<string, GameSession> = new Map; // GameSession.id(url)/GameSession
wsServer.on("connection", connectionListener); wsServer.on("connection", serverConnectionListener);
wsServer.on("error", errorListener); wsServer.on("error", serverErrorListener);
wsServer.on("close", closeListener); wsServer.on("close", serverCloseListener);
function connectionListener(socket: WebSocket, request: IncomingMessage) function serverConnectionListener(socket: WebSocket, request: IncomingMessage)
{ {
const id = uuidv4(); const id = uuidv4();
const client = new Client(socket, id); const client = new Client(socket, id);
@@ -40,7 +39,19 @@ function connectionListener(socket: WebSocket, request: IncomingMessage)
console.log(`client ${shortId(client.id)} is alive`); console.log(`client ${shortId(client.id)} is alive`);
}); });
socket.on("message", function log(data: string) { 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) {
console.log(`err.stack: ${err.stack}`);
}
});
socket.on("message", function messageLog(data: string) {
try { try {
const event: ev.ClientEvent = JSON.parse(data); const event: ev.ClientEvent = JSON.parse(data);
if (event.type === en.EventTypes.clientInput) { if (event.type === en.EventTypes.clientInput) {
@@ -61,13 +72,11 @@ async function clientAnnounceListener(this: WebSocket, data: string)
const msg : ev.ClientAnnounce = JSON.parse(data); const msg : ev.ClientAnnounce = JSON.parse(data);
if (msg.type === en.EventTypes.clientAnnounce) if (msg.type === en.EventTypes.clientAnnounce)
{ {
// TODO: reconnection with msg.clientId ? // BONUS: reconnection with msg.clientId ?
// "/pong" to play, "/pong?ID_OF_A_GAMESESSION" to spectate (or something like that)
if (msg.role === en.ClientRole.player) if (msg.role === en.ClientRole.player)
{ {
const announce: ev.ClientAnnouncePlayer = <ev.ClientAnnouncePlayer>msg; const announce: ev.ClientAnnouncePlayer = <ev.ClientAnnouncePlayer>msg;
// WIP nest, fetch token validation
const body = { const body = {
playerOneUsername: announce.username, playerOneUsername: announce.username,
playerTwoUsername: "", playerTwoUsername: "",
@@ -88,7 +97,7 @@ async function clientAnnounceListener(this: WebSocket, data: string)
}); });
if (!response.ok) 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)); clientTerminate(clientsMap.get(this.id));
return; return;
} }
@@ -96,10 +105,13 @@ async function clientAnnounceListener(this: WebSocket, data: string)
const player = clientsMap.get(this.id) as ClientPlayer; const player = clientsMap.get(this.id) as ClientPlayer;
player.matchOptions = announce.matchOptions; player.matchOptions = announce.matchOptions;
player.token = announce.token; player.token = announce.token;
announce.isInvitedPerson ? player.username = announce.playerTwoUsername : player.username = announce.username; player.username = announce.username;
this.send(JSON.stringify( new ev.EventAssignId(this.id) )); // unused this.send(JSON.stringify( new ev.EventAssignId(this.id) )); // unused
this.send(JSON.stringify( new ev.ServerEvent(en.EventTypes.matchmakingInProgress) )); this.send(JSON.stringify( new ev.ServerEvent(en.EventTypes.matchmakingInProgress) ));
if (announce.privateMatch) { if (announce.privateMatch) {
if (announce.isInvitedPerson) {
player.username = announce.playerTwoUsername;
}
privateMatchmaking(player); privateMatchmaking(player);
} }
else { else {
@@ -111,13 +123,14 @@ async function clientAnnounceListener(this: WebSocket, data: string)
const announce: ev.ClientAnnounceSpectator = <ev.ClientAnnounceSpectator>msg; const announce: ev.ClientAnnounceSpectator = <ev.ClientAnnounceSpectator>msg;
const gameSession = gameSessionsMap.get(announce.gameSessionId); const gameSession = gameSessionsMap.get(announce.gameSessionId);
if (!gameSession) { 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)); clientTerminate(clientsMap.get(this.id));
return; return;
} }
const spectator = clientsMap.get(this.id) as ClientSpectator; const spectator = clientsMap.get(this.id) as ClientSpectator;
spectator.gameSession = gameSession; spectator.gameSession = gameSession;
gameSession.spectatorsMap.set(spectator.id, spectator); gameSession.spectatorsMap.set(spectator.id, spectator);
spectator.socket.once("message", spectatorReadyConfirmationListener);
this.send(JSON.stringify( new ev.ServerEvent(en.EventTypes.matchStart) )); this.send(JSON.stringify( new ev.ServerEvent(en.EventTypes.matchStart) ));
} }
} }
@@ -213,7 +226,7 @@ function privateMatchmaking(player: ClientPlayer)
function createGameSession(playersArr: ClientPlayer[], matchOptions: en.MatchOptions) 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 id = uuidv4();
const gameSession = new GameSession(id, matchOptions); const gameSession = new GameSession(id, matchOptions);
gameSessionsMap.set(id, gameSession); gameSessionsMap.set(id, gameSession);
@@ -263,7 +276,6 @@ async function playerReadyConfirmationListener(this: WebSocket, data: string)
gameSession.unreadyPlayersMap.delete(this.id); gameSession.unreadyPlayersMap.delete(this.id);
if (gameSession.unreadyPlayersMap.size === 0) if (gameSession.unreadyPlayersMap.size === 0)
{ {
// WIP nest , send gameSession.id
const gameSessionPlayersIterator = gameSession.playersMap.values(); const gameSessionPlayersIterator = gameSession.playersMap.values();
const body = { const body = {
gameServerIdOfTheMatch : gameSession.id, gameServerIdOfTheMatch : gameSession.id,
@@ -330,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);
}
//////////// ////////////
//////////// ////////////
@@ -363,11 +397,10 @@ export function clientTerminate(client: Client)
if (client.gameSession) if (client.gameSession)
{ {
client.gameSession.playersMap.delete(client.id); client.gameSession.playersMap.delete(client.id);
client.gameSession.spectatorsMap.delete(client.id);
if (client.gameSession.playersMap.size === 0) if (client.gameSession.playersMap.size === 0)
{ {
clearInterval(client.gameSession.playersUpdateInterval); client.gameSession.destroy();
clearInterval(client.gameSession.spectatorsUpdateInterval);
clearInterval(client.gameSession.gameLoopInterval);
gameSessionsMap.delete(client.gameSession.id); gameSessionsMap.delete(client.gameSession.id);
} }
} }
@@ -381,13 +414,13 @@ export function clientTerminate(client: Client)
} }
function closeListener() function serverCloseListener()
{ {
clearInterval(pingInterval); clearInterval(pingInterval);
} }
function errorListener(error: Error) function serverErrorListener(error: Error)
{ {
console.log("Error: " + JSON.stringify(error)); console.log("Error: " + JSON.stringify(error));
} }

View File

@@ -26,5 +26,5 @@ export const movingWallPosMax = Math.floor(w*0.12);
export const movingWallSpeed = Math.floor(w*0.08); export const movingWallSpeed = Math.floor(w*0.08);
export const gameSessionIdPLACEHOLDER = "42"; // TESTING SPECTATOR PLACEHOLDER export const gameSessionIdPLACEHOLDER = "match-id-test-42"; // TESTING SPECTATOR PLACEHOLDER
// for testing, force gameSession.id in wsServer.ts->matchmaking() // for testing, force gameSession.id in wsServer.ts->createGameSession()

View File

@@ -19,6 +19,7 @@ export enum EventTypes {
// Client // Client
clientAnnounce, clientAnnounce,
clientPlayerReady, clientPlayerReady,
clientSpectatorReady,
clientInput, clientInput,
} }

View File

@@ -2,47 +2,9 @@ FROM node:alpine AS development
WORKDIR /usr/app WORKDIR /usr/app
ARG NODE_ENV
ARG WEBSITE_HOST
ARG WEBSITE_PORT
ARG POSTGRES_USER
ARG POSTGRES_PASSWORD
ARG POSTGRES_DB
ARG POSTGRES_HOST
ARG POSTGRES_PORT
COPY ./api_back ./ COPY ./api_back ./
COPY ./api_back/src/uploads/avatars/default.png ./uploads/avatars/default.png COPY ./api_back/src/uploads/avatars/default.png ./uploads/avatars/default.png
COPY ./api_back/.env ./.env
#RUN sed -i "s/\$NODE_ENV/${NODE_ENV}/g" ./.env && \
# sed -i "s/\$WEBSITE_HOST/${WEBSITE_HOST}/g" ./.env && \
# sed -i "s/\$WEBSITE_PORT/${WEBSITE_PORT}/g" ./.env && \
# sed -i "s/\$POSTGRES_USER/${POSTGRES_USER}/g" ./.env && \
# sed -i "s/\$POSTGRES_PASSWORD/${POSTGRES_PASSWORD}/g" ./.env && \
# sed -i "s/\$POSTGRES_DB/${POSTGRES_DB}/g" ./.env && \
# sed -i "s/\$POSTGRES_HOST/${POSTGRES_HOST}/g" ./.env && \
# sed -i "s/\$POSTGRES_PORT/${POSTGRES_PORT}/g" ./.env
RUN sed -i "s/\$NODE_ENV/${NODE_ENV}/g" ./.env RUN npm i
RUN sed -i "s/\$WEBSITE_HOST/${WEBSITE_HOST}/g" ./.env
RUN sed -i "s/\$WEBSITE_PORT/${WEBSITE_PORT}/g" ./.env
RUN sed -i "s/\$POSTGRES_USER/${POSTGRES_USER}/g" ./.env
RUN echo ["$POSTGRESS_PASSWORD"] && \
echo ["$POSTGRESS_PASSWORD"] && \
echo ["$POSTGRESS_PASSWORD"] && \
echo ["$POSTGRESS_PASSWORD"] && \
echo ["$POSTGRESS_PASSWORD"] && \
echo ["$POSTGRESS_PASSWORD"] && \
echo ["$POSTGRESS_PASSWORD"] && \
sed -i "s/\$POSTGRES_PASSWORD/'${POSTGRESS_PASSWORD}'/g" ./.env
RUN sed -i "s/\$POSTGRES_DB/${POSTGRES_DB}/g" ./.env
RUN sed -i "s/\$POSTGRES_HOST/${POSTGRES_HOST}/g" ./.env
RUN sed -i "s/\$POSTGRES_PORT/${POSTGRES_PORT}/g" ./.env
RUN npm install
RUN npm ci
CMD [ "npm", "run", "start:dev" ] CMD [ "npm", "run", "start:dev" ]

View File

@@ -1,15 +0,0 @@
NODE_ENV=$NODE_ENV
WEBSITE_HOST=$WEBSITE_HOST
WEBSITE_PORT=$WEBSITE_PORT
POSTGRES_USER=$POSTGRES_USER
POSTGRES_PASSWORD=$POSTGRES_PASSWORD
POSTGRES_DB=$POSTGRES_DB
POSTGRES_HOST=$POSTGRES_HOST
POSTGRES_PORT=$POSTGRES_PORT
FORTYTWO_CLIENT_ID=u-s4t2ud-49dc7b539bcfe1acb48b928b2b281671c99fc5bfab1faca57a536ab7e0075500
FORTYTWO_CLIENT_SECRET=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
FORTYTWO_CALLBACK_URL=http://$WEBSITE_HOST:$WEBSITE_PORT/api/v2/auth/redirect
COOKIE_SECRET=wABcR5SytbN4kiPa_4Y8IhhdLDb4Yn0EvVvOPZRQf4Q=
PORT=3000
TWO_FACTOR_AUTHENTICATION_APP_NAME=Transcendance
TICKET_FOR_PLAYING_GAME_SECRET=hvt8PQo3o+BHimS0RO5viln65yF9zMIuZFEmhxQGdik=

View File

@@ -19,7 +19,6 @@
"@nestjs/typeorm": "^9.0.1", "@nestjs/typeorm": "^9.0.1",
"@nestjs/websockets": "^9.2.1", "@nestjs/websockets": "^9.2.1",
"@types/express-session": "^1.17.5", "@types/express-session": "^1.17.5",
"@types/redis": "^4.0.11",
"@types/validator": "^13.7.9", "@types/validator": "^13.7.9",
"class-transformer": "^0.5.1", "class-transformer": "^0.5.1",
"class-validator": "^0.13.2", "class-validator": "^0.13.2",
@@ -48,7 +47,7 @@
"@types/express": "^4.17.13", "@types/express": "^4.17.13",
"@types/jest": "28.1.8", "@types/jest": "28.1.8",
"@types/multer": "^1.4.7", "@types/multer": "^1.4.7",
"@types/node": "^16.0.0", "@types/node": "^16.18.11",
"@types/passport-local": "^1.0.34", "@types/passport-local": "^1.0.34",
"@types/supertest": "^2.0.11", "@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/eslint-plugin": "^5.0.0",
@@ -1694,65 +1693,6 @@
"@nestjs/core": "^9.0.0" "@nestjs/core": "^9.0.0"
} }
}, },
"node_modules/@nestjs/platform-express/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dependencies": {
"ms": "2.0.0"
}
},
"node_modules/@nestjs/platform-express/node_modules/express": {
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz",
"integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==",
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
"body-parser": "1.20.0",
"content-disposition": "0.5.4",
"content-type": "~1.0.4",
"cookie": "0.5.0",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"finalhandler": "1.2.0",
"fresh": "0.5.2",
"http-errors": "2.0.0",
"merge-descriptors": "1.0.1",
"methods": "~1.1.2",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
"path-to-regexp": "0.1.7",
"proxy-addr": "~2.0.7",
"qs": "6.10.3",
"range-parser": "~1.2.1",
"safe-buffer": "5.2.1",
"send": "0.18.0",
"serve-static": "1.15.0",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"type-is": "~1.6.18",
"utils-merge": "1.0.1",
"vary": "~1.1.2"
},
"engines": {
"node": ">= 0.10.0"
}
},
"node_modules/@nestjs/platform-express/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node_modules/@nestjs/platform-express/node_modules/path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
},
"node_modules/@nestjs/platform-socket.io": { "node_modules/@nestjs/platform-socket.io": {
"version": "9.2.1", "version": "9.2.1",
"resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-9.2.1.tgz", "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-9.2.1.tgz",
@@ -1787,11 +1727,6 @@
"node": ">=10.0.0" "node": ">=10.0.0"
} }
}, },
"node_modules/@nestjs/platform-socket.io/node_modules/tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
},
"node_modules/@nestjs/schematics": { "node_modules/@nestjs/schematics": {
"version": "9.0.3", "version": "9.0.3",
"resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-9.0.3.tgz", "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-9.0.3.tgz",
@@ -1960,11 +1895,6 @@
} }
} }
}, },
"node_modules/@nestjs/websockets/node_modules/tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
},
"node_modules/@nodelib/fs.scandir": { "node_modules/@nodelib/fs.scandir": {
"version": "2.1.5", "version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -2381,9 +2311,9 @@
} }
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "16.18.10", "version": "16.18.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.10.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz",
"integrity": "sha512-XU1+v7h81p7145ddPfjv7jtWvkSilpcnON3mQ+bDi9Yuf7OI56efOglXRyXWgQ57xH3fEQgh7WOJMncRHVew5w==" "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA=="
}, },
"node_modules/@types/parse-json": { "node_modules/@types/parse-json": {
"version": "4.0.0", "version": "4.0.0",
@@ -2437,15 +2367,6 @@
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
"integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw=="
}, },
"node_modules/@types/redis": {
"version": "4.0.11",
"resolved": "https://registry.npmjs.org/@types/redis/-/redis-4.0.11.tgz",
"integrity": "sha512-bI+gth8La8Wg/QCR1+V1fhrL9+LZUSWfcqpOj2Kc80ZQ4ffbdL173vQd5wovmoV9i071FU9oP2g6etLuEwb6Rg==",
"deprecated": "This is a stub types definition. redis provides its own type definitions, so you do not need this installed.",
"dependencies": {
"redis": "*"
}
},
"node_modules/@types/semver": { "node_modules/@types/semver": {
"version": "7.3.13", "version": "7.3.13",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
@@ -3372,11 +3293,6 @@
"ieee754": "^1.1.13" "ieee754": "^1.1.13"
} }
}, },
"node_modules/buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
},
"node_modules/buffer-from": { "node_modules/buffer-from": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
@@ -4070,14 +3986,6 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/ecdsa-sig-formatter": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
"dependencies": {
"safe-buffer": "^5.0.1"
}
},
"node_modules/ee-first": { "node_modules/ee-first": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -6533,25 +6441,6 @@
"graceful-fs": "^4.1.6" "graceful-fs": "^4.1.6"
} }
}, },
"node_modules/jwa": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
"dependencies": {
"buffer-equal-constant-time": "1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"node_modules/jws": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
"dependencies": {
"jwa": "^1.4.1",
"safe-buffer": "^5.0.1"
}
},
"node_modules/kleur": { "node_modules/kleur": {
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
@@ -6630,11 +6519,6 @@
"optional": true, "optional": true,
"peer": true "peer": true
}, },
"node_modules/lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
"integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="
},
"node_modules/lodash.isarguments": { "node_modules/lodash.isarguments": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
@@ -6642,31 +6526,6 @@
"optional": true, "optional": true,
"peer": true "peer": true
}, },
"node_modules/lodash.isboolean": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
"integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="
},
"node_modules/lodash.isinteger": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
"integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="
},
"node_modules/lodash.isnumber": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
"integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="
},
"node_modules/lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
},
"node_modules/lodash.isstring": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
"integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="
},
"node_modules/lodash.memoize": { "node_modules/lodash.memoize": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@@ -6679,11 +6538,6 @@
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true "dev": true
}, },
"node_modules/lodash.once": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
},
"node_modules/log-symbols": { "node_modules/log-symbols": {
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
@@ -6720,6 +6574,7 @@
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"dependencies": { "dependencies": {
"yallist": "^4.0.0" "yallist": "^4.0.0"
}, },
@@ -8300,6 +8155,7 @@
"version": "7.3.8", "version": "7.3.8",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
"dev": true,
"dependencies": { "dependencies": {
"lru-cache": "^6.0.0" "lru-cache": "^6.0.0"
}, },
@@ -11132,11 +10988,6 @@
"socket.io-adapter": "~2.4.0", "socket.io-adapter": "~2.4.0",
"socket.io-parser": "~4.2.0" "socket.io-parser": "~4.2.0"
} }
},
"tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
} }
} }
}, },
@@ -11250,13 +11101,6 @@
"iterare": "1.2.1", "iterare": "1.2.1",
"object-hash": "3.0.0", "object-hash": "3.0.0",
"tslib": "2.4.1" "tslib": "2.4.1"
},
"dependencies": {
"tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
}
} }
}, },
"@nodelib/fs.scandir": { "@nodelib/fs.scandir": {
@@ -11642,9 +11486,9 @@
} }
}, },
"@types/node": { "@types/node": {
"version": "16.18.10", "version": "16.18.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.10.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz",
"integrity": "sha512-XU1+v7h81p7145ddPfjv7jtWvkSilpcnON3mQ+bDi9Yuf7OI56efOglXRyXWgQ57xH3fEQgh7WOJMncRHVew5w==" "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA=="
}, },
"@types/parse-json": { "@types/parse-json": {
"version": "4.0.0", "version": "4.0.0",
@@ -11698,14 +11542,6 @@
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
"integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw=="
}, },
"@types/redis": {
"version": "4.0.11",
"resolved": "https://registry.npmjs.org/@types/redis/-/redis-4.0.11.tgz",
"integrity": "sha512-bI+gth8La8Wg/QCR1+V1fhrL9+LZUSWfcqpOj2Kc80ZQ4ffbdL173vQd5wovmoV9i071FU9oP2g6etLuEwb6Rg==",
"requires": {
"redis": "*"
}
},
"@types/semver": { "@types/semver": {
"version": "7.3.13", "version": "7.3.13",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
@@ -12397,11 +12233,6 @@
"ieee754": "^1.1.13" "ieee754": "^1.1.13"
} }
}, },
"buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
},
"buffer-from": { "buffer-from": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
@@ -12906,14 +12737,6 @@
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-8.0.3.tgz", "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-8.0.3.tgz",
"integrity": "sha512-SErOMvge0ZUyWd5B0NXMQlDkN+8r+HhVUsxgOO7IoPDOdDRD2JjExpN6y3KnFR66jsJMwSn1pqIivhU5rcJiNg==" "integrity": "sha512-SErOMvge0ZUyWd5B0NXMQlDkN+8r+HhVUsxgOO7IoPDOdDRD2JjExpN6y3KnFR66jsJMwSn1pqIivhU5rcJiNg=="
}, },
"ecdsa-sig-formatter": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
"requires": {
"safe-buffer": "^5.0.1"
}
},
"ee-first": { "ee-first": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -14766,25 +14589,6 @@
"universalify": "^2.0.0" "universalify": "^2.0.0"
} }
}, },
"jwa": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
"requires": {
"buffer-equal-constant-time": "1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"jws": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
"requires": {
"jwa": "^1.4.1",
"safe-buffer": "^5.0.1"
}
},
"kleur": { "kleur": {
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
@@ -14845,11 +14649,6 @@
"optional": true, "optional": true,
"peer": true "peer": true
}, },
"lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
"integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="
},
"lodash.isarguments": { "lodash.isarguments": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
@@ -14857,31 +14656,6 @@
"optional": true, "optional": true,
"peer": true "peer": true
}, },
"lodash.isboolean": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
"integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="
},
"lodash.isinteger": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
"integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="
},
"lodash.isnumber": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
"integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="
},
"lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
},
"lodash.isstring": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
"integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="
},
"lodash.memoize": { "lodash.memoize": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@@ -14894,11 +14668,6 @@
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true "dev": true
}, },
"lodash.once": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
},
"log-symbols": { "log-symbols": {
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
@@ -14925,6 +14694,7 @@
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"requires": { "requires": {
"yallist": "^4.0.0" "yallist": "^4.0.0"
} }
@@ -16078,6 +15848,7 @@
"version": "7.3.8", "version": "7.3.8",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
"dev": true,
"requires": { "requires": {
"lru-cache": "^6.0.0" "lru-cache": "^6.0.0"
} }

View File

@@ -59,7 +59,7 @@
"@types/express": "^4.17.13", "@types/express": "^4.17.13",
"@types/jest": "28.1.8", "@types/jest": "28.1.8",
"@types/multer": "^1.4.7", "@types/multer": "^1.4.7",
"@types/node": "^16.0.0", "@types/node": "^16.18.11",
"@types/passport-local": "^1.0.34", "@types/passport-local": "^1.0.34",
"@types/supertest": "^2.0.11", "@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/eslint-plugin": "^5.0.0",

View File

@@ -4,7 +4,7 @@ import {
WebSocketServer, WebSocketServer,
MessageBody, MessageBody,
OnGatewayConnection, OnGatewayConnection,
OnGatewayDisconnect, OnGatewayDisconnect,
} from '@nestjs/websockets'; } from '@nestjs/websockets';
import { UsersService } from 'src/users/users.service'; import { UsersService } from 'src/users/users.service';
import { PaginationQueryDto } from 'src/common/dto/pagination-query.dto'; import { PaginationQueryDto } from 'src/common/dto/pagination-query.dto';

View File

@@ -24,5 +24,13 @@ export const storageForAvatar = {
const extension : string = MIME_TYPES[file.mimetype]; const extension : string = MIME_TYPES[file.mimetype];
cb(null, `${filename}${extension}`); cb(null, `${filename}${extension}`);
} }
}) }),
fileFilter: (req, file, cb) => {
if (file.mimetype === 'image/png' || file.mimetype === 'image/jpg' || file.mimetype === 'image/jpeg') {
cb(null, true);
}
else {
cb(null, false);
}
}
} }

View File

@@ -17,6 +17,9 @@ export class Game {
@Column({default : 0, nullable : true}) @Column({default : 0, nullable : true})
playerTwoUsernameResult : number playerTwoUsernameResult : number
@Column({default : 0})
gameOptions: number
@Column({unique : true}) @Column({unique : true})
gameServerIdOfTheMatch: string gameServerIdOfTheMatch: string

View File

@@ -13,6 +13,14 @@ export class GameController {
constructor (private readonly gameService : GameService) { } constructor (private readonly gameService : GameService) { }
@Get('match/all')
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
async getMatchesForSpectator()
{
return this.gameService.getMatchesForSpectator();
}
@Get('ranking') @Get('ranking')
@UseGuards(AuthenticateGuard) @UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard) @UseGuards(TwoFactorGuard)

View File

@@ -28,6 +28,21 @@ export class GameService {
private readonly friendShipService : FriendshipService private readonly friendShipService : FriendshipService
) { } ) { }
async getMatchesForSpectator() {
const games = await this.gameRepository.createQueryBuilder("game")
.where('game.isMatchIsFinished = :isMatchIsFinished', {isMatchIsFinished : false})
.getMany();
const gamesToReturn : Partial<Game>[] = []
for (const game of games)
{
gamesToReturn.push({gameServerIdOfTheMatch : game.gameServerIdOfTheMatch,
gameOptions : game.gameOptions, playerOneUsername : game.playerOneUsername,
playerTwoUsername : game.playerTwoUsername})
console.log("Is match is finished : " + game.isMatchIsFinished)
}
return gamesToReturn;
}
async getRankingForAllUsers(currentUser : User) { async getRankingForAllUsers(currentUser : User) {
const users = await this.userRepository.createQueryBuilder("user") const users = await this.userRepository.createQueryBuilder("user")
.leftJoinAndSelect("user.stats", "stats") .leftJoinAndSelect("user.stats", "stats")
@@ -255,6 +270,8 @@ export class GameService {
game.playerOneUsernameResult = updateGameDto.playerOneUsernameResult game.playerOneUsernameResult = updateGameDto.playerOneUsernameResult
game.playerTwoUsernameResult = updateGameDto.playerTwoUsernameResult game.playerTwoUsernameResult = updateGameDto.playerTwoUsernameResult
this.gameRepository.save(game); this.gameRepository.save(game);
console.log("On a sauvegardé la partie. Game :")
console.log(game)
const playerOne = await this.userRepository.findOneBy({username : game.playerOneUsername}) const playerOne = await this.userRepository.findOneBy({username : game.playerOneUsername})
const playerTwo = await this.userRepository.findOneBy({username : game.playerTwoUsername}) const playerTwo = await this.userRepository.findOneBy({username : game.playerTwoUsername})
if (!playerOne || !playerTwo) if (!playerOne || !playerTwo)

View File

@@ -1,5 +1,5 @@
import { import {
Body, Controller, Delete, Get, NotFoundException, Param, Patch, Post, Query, Redirect, Req, Res, UploadedFile, UseGuards, UseInterceptors Body, Controller, Delete, Get, NotFoundException,HttpStatus, Param, Patch, Post, Query, Redirect, Req, Res, UploadedFile, UseGuards, UseInterceptors
} from '@nestjs/common'; } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express'; import { FileInterceptor } from '@nestjs/platform-express';
import { Response } from 'express'; import { Response } from 'express';
@@ -31,19 +31,6 @@ export class UsersController {
///////////////////////// RUD ////////////////////////// ///////////////////////// RUD //////////////////////////
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
/**
* On ne fait de création via une route
* car un utilisateur est crée à la première connexion avec l'Oauth de 42.
*/
// @UseGuards(AuthenticateGuard)
// @UseGuards(TwoFactorGuard)
// @Get()
// findOne(@Req() req) {
// console.log("Backend Getting current user");
// return this.usersService.findOne(req.user.id);
// }
@UseGuards(AuthenticateGuard) @UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard) @UseGuards(TwoFactorGuard)
@Get() @Get()
@@ -100,9 +87,14 @@ export class UsersController {
@UseGuards(TwoFactorGuard) @UseGuards(TwoFactorGuard)
@Post('avatar') @Post('avatar')
@UseInterceptors(FileInterceptor('file', storageForAvatar)) @UseInterceptors(FileInterceptor('file', storageForAvatar))
uploadAvatar(@UploadedFile() file, @Req() request){ uploadAvatar(@UploadedFile() file, @Req() request, @Res() res){
const user : User = request.user; const user : User = request.user;
this.usersService.updateAvatar(user.id, file.filename); if (file)
{
this.usersService.updateAvatar(user.id, file.filename);
return res.status(HttpStatus.OK).json({message : "Avatar updated"});
}
return res.status(HttpStatus.UNSUPPORTED_MEDIA_TYPE).json({message : "Unsupported media type. Please use a valid image file."});
} }
@UseGuards(AuthenticateGuard) @UseGuards(AuthenticateGuard)

View File

@@ -8,3 +8,4 @@
!api_front/*.json !api_front/*.json
!api_front/*.html !api_front/*.html
!api_front/*.lock !api_front/*.lock
!api_front/.env

View File

@@ -1,107 +0,0 @@
# This repo is no longer maintained. Consider using `npm init vite` and selecting the `svelte` option or — if you want a full-fledged app framework and don't mind using pre-1.0 software — use [SvelteKit](https://kit.svelte.dev), the official application framework for Svelte.
---
# svelte app
This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template.
To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit):
```bash
npx degit sveltejs/template svelte-app
cd svelte-app
```
*Note that you will need to have [Node.js](https://nodejs.org) installed.*
## Get started
Install the dependencies...
```bash
cd svelte-app
npm install
```
...then start [Rollup](https://rollupjs.org):
```bash
npm run dev
```
Navigate to [localhost:8080](http://localhost:8080). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes.
By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`.
If you're using [Visual Studio Code](https://code.visualstudio.com/) we recommend installing the official extension [Svelte for VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). If you are using other editors you may need to install a plugin in order to get syntax highlighting and intellisense.
## Building and running in production mode
To create an optimised version of the app:
```bash
npm run build
```
You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com).
## Single-page app mode
By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere.
If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json:
```js
"start": "sirv public --single"
```
## Using TypeScript
This template comes with a script to set up a TypeScript development environment, you can run it immediately after cloning the template with:
```bash
node scripts/setupTypeScript.js
```
Or remove the script via:
```bash
rm scripts/setupTypeScript.js
```
If you want to use `baseUrl` or `path` aliases within your `tsconfig`, you need to set up `@rollup/plugin-alias` to tell Rollup to resolve the aliases. For more info, see [this StackOverflow question](https://stackoverflow.com/questions/63427935/setup-tsconfig-path-in-svelte).
## Deploying to the web
### With [Vercel](https://vercel.com)
Install `vercel` if you haven't already:
```bash
npm install -g vercel
```
Then, from within your project folder:
```bash
cd public
vercel deploy --name my-project
```
### With [surge](https://surge.sh/)
Install `surge` if you haven't already:
```bash
npm install -g surge
```
Then, from within your project folder:
```bash
npm run build
surge public my-project.surge.sh
```

View File

@@ -8,6 +8,8 @@
"name": "svelte-app", "name": "svelte-app",
"version": "1.0.0", "version": "1.0.0",
"dependencies": { "dependencies": {
"@rollup/plugin-replace": "^5.0.2",
"dotenv": "^16.0.3",
"sirv-cli": "^2.0.0", "sirv-cli": "^2.0.0",
"socket.io-client": "^4.5.4", "socket.io-client": "^4.5.4",
"svelte-spa-router": "^3.3.0" "svelte-spa-router": "^3.3.0"
@@ -17,6 +19,7 @@
"@rollup/plugin-node-resolve": "^11.0.0", "@rollup/plugin-node-resolve": "^11.0.0",
"@rollup/plugin-typescript": "^8.0.0", "@rollup/plugin-typescript": "^8.0.0",
"@tsconfig/svelte": "^2.0.0", "@tsconfig/svelte": "^2.0.0",
"@types/node": "^18.11.18",
"rollup": "^2.3.4", "rollup": "^2.3.4",
"rollup-plugin-css-only": "^3.1.0", "rollup-plugin-css-only": "^3.1.0",
"rollup-plugin-livereload": "^2.0.0", "rollup-plugin-livereload": "^2.0.0",
@@ -109,8 +112,7 @@
"node_modules/@jridgewell/sourcemap-codec": { "node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.14", "version": "1.4.14",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="
"dev": true
}, },
"node_modules/@jridgewell/trace-mapping": { "node_modules/@jridgewell/trace-mapping": {
"version": "0.3.17", "version": "0.3.17",
@@ -203,6 +205,63 @@
"rollup": "^1.20.0||^2.0.0" "rollup": "^1.20.0||^2.0.0"
} }
}, },
"node_modules/@rollup/plugin-replace": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-5.0.2.tgz",
"integrity": "sha512-M9YXNekv/C/iHHK+cvORzfRYfPbq0RDD8r0G+bMiTXjNGKulPnCT9O3Ss46WfhI6ZOCgApOP7xAdmCQJ+U2LAA==",
"dependencies": {
"@rollup/pluginutils": "^5.0.1",
"magic-string": "^0.27.0"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/plugin-replace/node_modules/@rollup/pluginutils": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz",
"integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==",
"dependencies": {
"@types/estree": "^1.0.0",
"estree-walker": "^2.0.2",
"picomatch": "^2.3.1"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/plugin-replace/node_modules/@types/estree": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz",
"integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ=="
},
"node_modules/@rollup/plugin-replace/node_modules/magic-string": {
"version": "0.27.0",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz",
"integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.13"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@rollup/plugin-typescript": { "node_modules/@rollup/plugin-typescript": {
"version": "8.5.0", "version": "8.5.0",
"resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.5.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.5.0.tgz",
@@ -267,9 +326,9 @@
"dev": true "dev": true
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "18.11.9", "version": "18.11.18",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz",
"integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==", "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==",
"dev": true "dev": true
}, },
"node_modules/@types/pug": { "node_modules/@types/pug": {
@@ -522,6 +581,14 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/dotenv": {
"version": "16.0.3",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz",
"integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==",
"engines": {
"node": ">=12"
}
},
"node_modules/engine.io-client": { "node_modules/engine.io-client": {
"version": "6.2.3", "version": "6.2.3",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.3.tgz", "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.3.tgz",
@@ -580,8 +647,7 @@
"node_modules/estree-walker": { "node_modules/estree-walker": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
"dev": true
}, },
"node_modules/fast-glob": { "node_modules/fast-glob": {
"version": "3.2.12", "version": "3.2.12",
@@ -1056,7 +1122,6 @@
"version": "2.3.1", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"engines": { "engines": {
"node": ">=8.6" "node": ">=8.6"
}, },
@@ -1171,7 +1236,7 @@
"version": "2.79.1", "version": "2.79.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
"integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
"dev": true, "devOptional": true,
"bin": { "bin": {
"rollup": "dist/bin/rollup" "rollup": "dist/bin/rollup"
}, },

View File

@@ -13,6 +13,7 @@
"@rollup/plugin-node-resolve": "^11.0.0", "@rollup/plugin-node-resolve": "^11.0.0",
"@rollup/plugin-typescript": "^8.0.0", "@rollup/plugin-typescript": "^8.0.0",
"@tsconfig/svelte": "^2.0.0", "@tsconfig/svelte": "^2.0.0",
"@types/node": "^18.11.18",
"rollup": "^2.3.4", "rollup": "^2.3.4",
"rollup-plugin-css-only": "^3.1.0", "rollup-plugin-css-only": "^3.1.0",
"rollup-plugin-livereload": "^2.0.0", "rollup-plugin-livereload": "^2.0.0",
@@ -25,6 +26,8 @@
"typescript": "^4.0.0" "typescript": "^4.0.0"
}, },
"dependencies": { "dependencies": {
"@rollup/plugin-replace": "^5.0.2",
"dotenv": "^16.0.3",
"sirv-cli": "^2.0.0", "sirv-cli": "^2.0.0",
"socket.io-client": "^4.5.4", "socket.io-client": "^4.5.4",
"svelte-spa-router": "^3.3.0" "svelte-spa-router": "^3.3.0"

View File

@@ -1,33 +0,0 @@
header.svelte-7t4byu.svelte-7t4byu{overflow-y:hidden}.grid-container.svelte-7t4byu.svelte-7t4byu{position:absolute;left:0;top:0;box-sizing:border-box;width:100%;height:100%;white-space:nowrap;margin-bottom:0px;overflow:hidden;padding:20px 40px;margin:0px;display:grid;grid-template-columns:repeat(12, 1fr);grid-template-rows:1fr 1fr 1fr 1fr 1fr;align-items:center}header.svelte-7t4byu h1.svelte-7t4byu{grid-column:1 / 7;grid-row:1;padding:20px;border:1px solid bisque}header.svelte-7t4byu nav.svelte-7t4byu{grid-column:7 / 13;grid-row:1;justify-self:end;padding:20px;border:1px solid bisque}header.svelte-7t4byu h2.svelte-7t4byu{grid-row:3;grid-column:5 / span 4;justify-self:center;border:1px solid black;z-index:3}header.svelte-7t4byu h2 div.svelte-7t4byu{font-size:2em}nav.svelte-7t4byu div.svelte-7t4byu{display:inline;color:bisque;font-weight:bold}nav.svelte-7t4byu>div.svelte-7t4byu{padding-left:1em}nav.svelte-7t4byu div.svelte-7t4byu:hover{text-decoration:underline;cursor:pointer}main.svelte-1cznfcz.svelte-1cznfcz{text-align:center;padding-top:40px;padding-bottom:40px}form.svelte-1cznfcz.svelte-1cznfcz{padding-top:15px}form.svelte-1cznfcz input.svelte-1cznfcz{max-width:330px}.error.svelte-1cznfcz.svelte-1cznfcz{font-weight:bold;font-size:0.8em;color:red}div.wrapper.svelte-1q8uute{display:flexbox;align-items:center}div.wrapper.svelte-1q8uute{display:flexbox;align-items:center}@font-face{font-family:"Bit5x3";src:url("/fonts/Bit5x3.woff2") format("woff2"),
local("Bit5x3"),
url("/fonts/Bit5x3.woff") format("woff");font-weight:normal;font-style:normal;font-display:swap}#game_page.svelte-y455cj.svelte-y455cj{margin:0;background-color:#222425;position:relative;width:100%;height:100%}#canvas_container.svelte-y455cj.svelte-y455cj{margin-top:20px;text-align:center}#users_name.svelte-y455cj.svelte-y455cj{text-align:center;font-family:"Bit5x3";color:rgb(245, 245, 245);font-size:x-large}#div_game.svelte-y455cj.svelte-y455cj{margin-top:20px;text-align:center;font-family:"Bit5x3";color:rgb(245, 245, 245);font-size:x-large}#error_notification.svelte-y455cj.svelte-y455cj{text-align:center;display:block;font-family:"Bit5x3";color:rgb(143, 19, 19);font-size:x-large}#div_game.svelte-y455cj fieldset.svelte-y455cj{max-width:50vw;width:auto;margin:0 auto}#div_game.svelte-y455cj fieldset div.svelte-y455cj{padding:10px}#pong_button.svelte-y455cj.svelte-y455cj{font-family:"Bit5x3";color:rgb(245, 245, 245);background-color:#333333;font-size:x-large;padding:10px}canvas.svelte-y455cj.svelte-y455cj{background-color:#333333;max-width:75vw;width:80%}canvas.svelte-1bstsd0{width:100%;height:100%;background-color:#666}@font-face{font-family:'Bondi';src:url('/fonts/Bondi.ttf.woff') format('woff'),
url('/fonts/Bondi.ttf.svg#Bondi') format('svg'),
url('/fonts/Bondi.ttf.eot'),
url('/fonts/Bondi.ttf.eot?#iefix') format('embedded-opentype');font-weight:normal;font-style:normal}header.svelte-1aisfio.svelte-1aisfio{background:#618174;margin:0}header.svelte-1aisfio.svelte-1aisfio{position:sticky;display:grid;grid-template-columns:1fr 1fr 1fr}h1.svelte-1aisfio.svelte-1aisfio{font-family:'Bondi'}h1.svelte-1aisfio.svelte-1aisfio{margin:0;text-align:left;display:flex;justify-self:center;align-self:center}img.svelte-1aisfio.svelte-1aisfio{cursor:pointer;max-width:40px;padding:7px 20px;justify-self:left}nav.svelte-1aisfio.svelte-1aisfio{display:flex;justify-content:right}nav.svelte-1aisfio button.svelte-1aisfio{margin:7px 20px;border-radius:4px}div.outer.svelte-1tyjf3q{max-width:960px;margin:40px auto}:root{--purple:rgb(123, 31, 162);--violet:rgb(103, 58, 183);--pink:rgb(244, 143, 177)}@keyframes svelte-1tyjf3q-background-pan{from{background-position:0% center}to{background-position:-200% center}}@keyframes svelte-1tyjf3q-scale{from,to{transform:scale(0)}50%{transform:scale(1)}}@keyframes svelte-1tyjf3q-rotate{from{transform:rotate(0deg)}to{transform:rotate(180deg)}}main.svelte-qtbld7{text-align:center}div.cards.svelte-qtbld7{display:grid;grid-template-columns:1fr 1fr;grid-gap:20px}img.svelte-qtbld7{width:60px}form.svelte-qtbld7{text-align:center}.form-field.svelte-qtbld7{padding:10px}.label.svelte-qtbld7{font-weight:bold}.inline-check.svelte-qtbld7{display:inline}.error.svelte-qtbld7{font-size:0.8em;font-weight:bold;color:red}.success.svelte-qtbld7{font-size:0.8em;font-weight:bold;color:green}div.top-grid.svelte-55f7si{display:grid;grid-template-columns:repeat(12, 1fr);height:85vh}div.all-users-sidebar.svelte-55f7si{grid-column:1 / span 2;background:white}div.a-user.svelte-55f7si{display:inline-block}div.status.svelte-55f7si{font-size:0.6em;font-weight:bold}div[class^="a-user"].svelte-55f7si:hover{text-decoration:underline;font-weight:bold;cursor:pointer}div.main-display.svelte-55f7si{grid-column:3 / span 10}.error.svelte-55f7si{font-size:0.8em;font-weight:bold;color:red}div.outer.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu{max-width:960px;margin:40px auto}main.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu{max-width:960px;margin:40px auto;text-align:center}.avatar.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu{max-width:150px}section.main-stats.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu{max-width:600px;margin:40px auto;text-align:center;display:grid;grid-template-columns:repeat(3, 1fr);grid-template-rows:repeat(3, 1fr)}section.main-stats.svelte-16aefqu h4.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu{grid-column:1 / span 3}div.username.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu{font-size:1.5em;font-weight:bold;padding-bottom:5px}div.rank.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu{font-size:1.2em;font-weight:bold}:root{--purple:rgb(123, 31, 162);--violet:rgb(103, 58, 183);--pink:rgb(244, 143, 177)}@keyframes svelte-16aefqu-background-pan{from{background-position:0% center}to{background-position:-200% center}}@keyframes svelte-16aefqu-scale{from,to{transform:scale(0)}50%{transform:scale(1)}}@keyframes svelte-16aefqu-rotate{from{transform:rotate(0deg)}to{transform:rotate(180deg)}}div.svelte-16aefqu>.glitter.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu{display:inline-block;position:relative}div.svelte-16aefqu>.glitter.svelte-16aefqu>.glitter-star.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu{--size:clamp(20px, 1.5vw, 30px);animation:svelte-16aefqu-scale 700ms ease forwards;display:block;height:var(--size);left:var(--star-left);position:absolute;top:var(--star-top);width:var(--size)}div.svelte-16aefqu>.glitter.svelte-16aefqu>.glitter-star.svelte-16aefqu>svg.svelte-16aefqu.svelte-16aefqu{animation:svelte-16aefqu-rotate 1000ms linear infinite;display:block;opacity:0.7}div.svelte-16aefqu>.glitter.svelte-16aefqu>.glitter-star.svelte-16aefqu>svg.svelte-16aefqu>path.svelte-16aefqu{fill:var(--violet)}div.svelte-16aefqu>.glitter.svelte-16aefqu>.glitter-text.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu{animation:svelte-16aefqu-background-pan 3s linear infinite;background:linear-gradient(
to right,
var(--purple),
var(--violet),
var(--pink),
var(--purple)
);background-size:200%;-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;color:transparent;white-space:nowrap}.card.svelte-8smyff{background:white;padding:20px;border-radius:6px;box-shadow:0px 2px 4px rgba(0,0,0,0.1)}button.svelte-1u0z9cq{border:0;cursor:pointer;border-radius:6px;padding:8px 12px;font-weight:bold;box-shadow:1px 2px 3px rgba(0,0,0,0.2)}.primary.svelte-1u0z9cq{background:#d91b42;color:white}.secondary.svelte-1u0z9cq{background:#45c496;color:white}.flat.svelte-1u0z9cq{box-shadow:none}.primary.inverse.svelte-1u0z9cq{color:#d91b42;background:white;border:2px solid #d91b42}.secondary.inverse.svelte-1u0z9cq{color:#45c496;background:white;border:2px solid #45c496}.chat_box.svelte-6ej1tr{display:flex;position:fixed;bottom:20px;right:20px;padding:0px;width:auto;height:auto;border:1px solid black;z-index:1}.chat_box.svelte-6ej1tr *{-ms-overflow-style:none;scrollbar-width:none}.chat_box.svelte-6ej1tr *::-webkit-scrollbar{display:none}.chat_box.svelte-6ej1tr .grid_box{display:grid;margin:5px;gap:5px;width:300px;height:400px}.chat_box.svelte-6ej1tr .grid_box *{display:flex;flex-direction:column;position:relative;box-sizing:border-box}.chat_box.svelte-6ej1tr .grid_box p{padding:10px;font-size:15px}.chat_box.svelte-6ej1tr .panel{overflow-y:scroll}.chat_box.svelte-6ej1tr .panel > *{margin-top:10px;margin-bottom:10px}.chat_box.svelte-6ej1tr .__show_if_only_child{display:none}.chat_box.svelte-6ej1tr .__show_if_only_child:only-child{display:flex;color:rgb(100, 100, 100)}.chat_box.svelte-6ej1tr .__center{margin-left:auto;margin-right:auto}.chat_box.svelte-6ej1tr .__border_top{border-top:1px solid black}.chat_box.svelte-6ej1tr .__check_change_next:checked ~ .__to_show{display:flex}.chat_box.svelte-6ej1tr .__check_change_next:checked ~ .__to_block,.chat_box.svelte-6ej1tr .__check_change_next:checked ~ .__to_block *{pointer-events:none;color:rgb(100, 100, 100)}.chat_box.svelte-6ej1tr .__to_show{display:none}.grid_box.svelte-fc4a40 .chat{grid-area:chat}.grid_box.svelte-fc4a40{gap:0px;grid:' chat ' auto
/ auto }.chat_box.close .grid_box.svelte-fc4a40{margin:0px;width:auto;height:auto}.grid_box.svelte-1jygwt2 .settings {grid-area:settings}.grid_box.svelte-1jygwt2 .close {grid-area:close}.grid_box.svelte-1jygwt2 .new {grid-area:new}.grid_box.svelte-1jygwt2 .panel_home{grid-area:panel_home}.grid_box.svelte-1jygwt2.svelte-1jygwt2{grid:' settings new close ' auto
' panel_home panel_home panel_home ' 1fr
/ auto 1fr auto }.panel_home.svelte-1jygwt2 p.title.svelte-1jygwt2{margin:10px auto 0px auto}.grid_box.svelte-1quyp80 .back {grid-area:back}.grid_box.svelte-1quyp80 .room_name {grid-area:room_name}.grid_box.svelte-1quyp80 .close {grid-area:close}.grid_box.svelte-1quyp80 .panel_msg {grid-area:panel_msg}.grid_box.svelte-1quyp80 .send {grid-area:send}.grid_box.svelte-1quyp80 .panel_write{grid-area:panel_write}.grid_box.svelte-1quyp80.svelte-1quyp80{grid:' back room_name room_name close ' auto
' panel_msg panel_msg panel_msg panel_msg ' 1fr
' panel_write panel_write send send ' auto
/ auto 1fr auto auto }.grid_box.svelte-1quyp80 .panel_write.svelte-1quyp80{border:none;overflow:visible}.grid_box.svelte-1quyp80 .text_area.svelte-1quyp80{display:block;position:absolute;bottom:0px;left:0px;width:100%;height:100%;overflow-x:hidden;overflow-y:scroll;background-color:white;border:1px solid black}.grid_box.svelte-1quyp80 .text_area.svelte-1quyp80:focus{height:auto;min-height:100%;max-height:300px}.grid_box.svelte-1quyp80 .panel_write .text_area.svelte-1quyp80 *{display:block ruby}.grid_box.svelte-1quyp80 .panel_msg.svelte-1quyp80{flex-direction:column-reverse;border:1px solid black}.grid_box.svelte-1quyp80 .msg_thread.svelte-1quyp80{width:100%;padding:0px 5px}.grid_box.svelte-1b4c0qx .back {grid-area:back}.grid_box.svelte-1b4c0qx .new {grid-area:new}.grid_box.svelte-1b4c0qx .close {grid-area:close}.grid_box.svelte-1b4c0qx .panel_new{grid-area:panel_new}.grid_box.svelte-1b4c0qx{grid:' back new close ' auto
' panel_new panel_new panel_new ' 1fr
/ auto 1fr auto }.grid_box.svelte-1lfmc2m .back {grid-area:back}.grid_box.svelte-1lfmc2m .settings {grid-area:settings}.grid_box.svelte-1lfmc2m .close {grid-area:close}.grid_box.svelte-1lfmc2m .panel_settings{grid-area:panel_settings}.grid_box.svelte-1lfmc2m{grid:' back settings close ' auto
' panel_settings panel_settings panel_settings ' 1fr
/ auto 1fr auto }.grid_box.svelte-1sv7l8q .back {grid-area:back}.grid_box.svelte-1sv7l8q .room_name {grid-area:room_name}.grid_box.svelte-1sv7l8q .close {grid-area:close}.grid_box.svelte-1sv7l8q .panel_room_set{grid-area:panel_room_set}.grid_box.svelte-1sv7l8q{grid:' back room_name close ' auto
' panel_room_set panel_room_set panel_room_set ' 1fr
/ auto 1fr auto }.grid_box.svelte-2tekts .back {grid-area:back}.grid_box.svelte-2tekts .room_name {grid-area:room_name}.grid_box.svelte-2tekts .close {grid-area:close}.grid_box.svelte-2tekts .panel_protected{grid-area:panel_protected}.grid_box.svelte-2tekts.svelte-2tekts{grid:' back room_name close ' auto
' panel_protected panel_protected panel_protected ' 1fr
/ auto 1fr auto }form.svelte-2tekts input[type=submit].svelte-2tekts{margin-top:20px}.grid_box.svelte-1cmnkcw .back {grid-area:back}.grid_box.svelte-1cmnkcw .create {grid-area:create}.grid_box.svelte-1cmnkcw .close {grid-area:close}.grid_box.svelte-1cmnkcw .panel_create{grid-area:panel_create}.grid_box.svelte-1cmnkcw.svelte-1cmnkcw.svelte-1cmnkcw{grid:' back create close ' auto
' panel_create panel_create panel_create ' 1fr
/ auto 1fr auto }form.svelte-1cmnkcw input[type=radio].svelte-1cmnkcw.svelte-1cmnkcw{display:none}form.svelte-1cmnkcw label._radio.svelte-1cmnkcw.svelte-1cmnkcw{margin:0px 20px 0px auto;padding-right:10px;cursor:pointer}form.svelte-1cmnkcw label._radio p.svelte-1cmnkcw.svelte-1cmnkcw{margin-top:0px;margin-bottom:0px}form.svelte-1cmnkcw label._radio.svelte-1cmnkcw.svelte-1cmnkcw::after{content:"";position:absolute;top:calc(50% - 6px);right:0px;width:12px;height:12px;border-radius:6px;border:2px solid rgb(150, 150, 150);box-sizing:border-box;cursor:pointer}form.svelte-1cmnkcw input[type=radio].svelte-1cmnkcw:checked+label._radio.svelte-1cmnkcw::after{background-color:rgb(200, 200, 200)}form.svelte-1cmnkcw input[type=submit].svelte-1cmnkcw.svelte-1cmnkcw{margin-top:20px}.grid_box.svelte-yo0any .back {grid-area:back}.grid_box.svelte-yo0any .back {grid-area:back}.grid_box.svelte-yo0any .user {grid-area:user}.grid_box.svelte-yo0any .close {grid-area:close}.grid_box.svelte-yo0any .panel_mute{grid-area:panel_mute}.grid_box.svelte-yo0any.svelte-yo0any.svelte-yo0any{grid:' back user close ' auto
' panel_mute panel_mute panel_mute ' 1fr
/ auto 1fr auto }form.svelte-yo0any input[type=checkbox].svelte-yo0any.svelte-yo0any{display:none}form.svelte-yo0any label._checkbox.svelte-yo0any.svelte-yo0any{margin:0px auto 0px 10px;padding-left:10px;cursor:pointer}form.svelte-yo0any label._checkbox.svelte-yo0any.svelte-yo0any::after{content:"";position:absolute;top:calc(50% - 6px);left:0px;width:12px;height:12px;border:2px solid rgb(150, 150, 150);box-sizing:border-box;cursor:pointer}form.svelte-yo0any input[type=checkbox].svelte-yo0any:checked+label._checkbox.svelte-yo0any::after{background-color:rgb(200, 200, 200)}form.svelte-yo0any label._select.svelte-yo0any.svelte-yo0any{flex-direction:row}form.svelte-yo0any label._select p.svelte-yo0any.svelte-yo0any{margin:0px}form.svelte-yo0any select.svelte-yo0any.svelte-yo0any{margin:auto auto auto 10px;background-color:rgb(220, 220, 220);border:none;padding:5px;cursor:pointer}form.svelte-yo0any select.svelte-yo0any.svelte-yo0any:hover{background-color:rgb(200, 200, 200)}form.svelte-yo0any input[type=submit].svelte-yo0any.svelte-yo0any{margin-top:20px}.grid_box.svelte-1fj8iha .back {grid-area:back}.grid_box.svelte-1fj8iha .user {grid-area:user}.grid_box.svelte-1fj8iha .close {grid-area:close}.grid_box.svelte-1fj8iha .room_name {grid-area:room_name}.grid_box.svelte-1fj8iha .panel_user{grid-area:panel_user}.grid_box.svelte-1fj8iha{grid:' back user close ' auto
' room_name room_name room_name ' auto
' panel_user panel_user panel_user ' 1fr
/ auto 1fr auto }.panel_user.svelte-1fj8iha{margin-top:-5px}button.svelte-b72wpv.svelte-b72wpv{padding:0px;margin:auto;width:100%;cursor:pointer;outline:none;border:none;background-color:rgb(220, 220, 220)}button.svelte-b72wpv p.svelte-b72wpv{width:100%;margin:auto;text-align:center}button.svelte-b72wpv.svelte-b72wpv:hover{background-color:rgb(200, 200, 200)}button.svelte-b72wpv.svelte-b72wpv:active{background-color:rgb(190, 190, 190)}.list.svelte-b72wpv.svelte-b72wpv:not(:hover){background-color:rgb(240, 240, 240)}.list.svelte-b72wpv p.svelte-b72wpv{text-align:left}.transparent.svelte-b72wpv.svelte-b72wpv:not(:hover){background-color:transparent}.deactivate.svelte-b72wpv.svelte-b72wpv{background-color:transparent;pointer-events:none}.icon.svelte-b72wpv p.svelte-b72wpv{display:none}.icon.svelte-b72wpv.svelte-b72wpv:not(:hover){background-color:transparent}.icon.svelte-b72wpv.svelte-b72wpv{width:30px;height:100%;padding:0px}.dots.svelte-b72wpv.svelte-b72wpv::after{content:'\2807';font-size:20px;position:absolute;top:50%;left:0px;width:100%;height:auto;text-align:center;transform:translateY(-50%);cursor:pointer}.close.svelte-b72wpv.svelte-b72wpv::before{content:"";position:absolute;top:calc(50% - 1px);left:5px;width:20px;height:2px;background-color:black}.back.svelte-b72wpv.svelte-b72wpv::before{content:"";position:absolute;top:calc(50% - 6px - 1px);left:6px;width:14px;height:14px;border-left:1px solid black;border-bottom:1px solid black;transform:rotate(45deg)}.blocked.svelte-b72wpv.svelte-b72wpv{padding-left:30px}.blocked.svelte-b72wpv.svelte-b72wpv::before{content:"";position:absolute;top:calc(50% - 2px);left:10px;cursor:pointer;width:13px;height:10px;border-radius:2px;background-color:rgb(110, 110, 110)}.blocked.svelte-b72wpv.svelte-b72wpv::after{content:"";position:absolute;top:calc(50% - 9px);left:12px;cursor:pointer;width:9px;height:13px;border-radius:5px;box-sizing:border-box;border:3px solid rgb(110, 110, 110)}.chat_msg.svelte-14xxpbz.svelte-14xxpbz{margin:5px auto;padding:5px;border-radius:5px}.chat_msg.svelte-14xxpbz.svelte-14xxpbz{margin-left:0px;background-color:rgb(210, 210, 210);max-width:80%}.chat_msg.svelte-14xxpbz p.svelte-14xxpbz{padding:0px}.chat_msg.svelte-14xxpbz p.name.svelte-14xxpbz{margin:0px;font-size:12px;color:rgb(100, 100, 100)}.chat_msg.svelte-14xxpbz p.msg.svelte-14xxpbz{margin:5px 0px}.chat_msg.svelte-14xxpbz p.msg.svelte-14xxpbz *{display:inline}.chat_msg.me.svelte-14xxpbz.svelte-14xxpbz{margin-right:0px;margin-left:auto;background-color:rgb(210, 110, 10)}.chat_msg.me.svelte-14xxpbz p.name.svelte-14xxpbz{display:none}.chat_msg.SERVER.svelte-14xxpbz.svelte-14xxpbz{margin-left:auto;background-color:transparent}.chat_msg.SERVER.svelte-14xxpbz p.name.svelte-14xxpbz{display:none}.chat_msg.SERVER.svelte-14xxpbz p.msg.svelte-14xxpbz{margin:0px auto;font-size:12px;color:rgb(100, 100, 100)}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -6,8 +6,13 @@ import { terser } from 'rollup-plugin-terser';
import sveltePreprocess from 'svelte-preprocess'; import sveltePreprocess from 'svelte-preprocess';
import typescript from '@rollup/plugin-typescript'; import typescript from '@rollup/plugin-typescript';
import css from 'rollup-plugin-css-only'; import css from 'rollup-plugin-css-only';
import replace from '@rollup/plugin-replace';
import dotenv from 'dotenv';
const production = !process.env.ROLLUP_WATCH; const production = !process.env.ROLLUP_WATCH;
dotenv.config();
function serve() { function serve() {
let server; let server;
@@ -30,6 +35,7 @@ function serve() {
}; };
} }
export default { export default {
input: 'src/main.ts', input: 'src/main.ts',
output: { output: {
@@ -46,6 +52,10 @@ export default {
dev: !production dev: !production
} }
}), }),
replace({
'process.env.WEBSITE_HOST': `'${process.env.WEBSITE_HOST}'`,
'process.env.WEBSITE_PORT': `'${process.env.WEBSITE_PORT}'`,
}),
// we'll extract any component CSS out into // we'll extract any component CSS out into
// a separate file - better for performance // a separate file - better for performance
css({ output: 'bundle.css' }), css({ output: 'bundle.css' }),

View File

@@ -1,5 +0,0 @@
<script context="module">
export const Domain = "transcendance";
export const Port = "8080";
export const PortIo = "8080";
</script>

View File

@@ -1,4 +1,7 @@
import App from './App.svelte'; import App from './App.svelte';
import dotenv from 'dotenv';
dotenv.config();
const app = new App({ const app = new App({
target: document.body, target: document.body,
props: { props: {
@@ -6,4 +9,4 @@ const app = new App({
} }
}); });
export default app; export default app;
//# sourceMappingURL=main.js.map //# sourceMappingURL=main.js.map

View File

@@ -7,4 +7,4 @@ const app = new App({
} }
}); });
export default app; export default app;

View File

@@ -1,35 +0,0 @@
<script lang="ts">
import Header from '../pieces/Header.svelte';
import MatchListElem from "../pieces/MatchListElem.svelte";
let arr = [
{
id: "match-01",
playerOneUsername: "toto",
playerTwoUsername: "bruno",
},
{
id: "match-02",
playerOneUsername: "bertand",
playerTwoUsername: "cassandre",
},
{
id: "match-03",
playerOneUsername: "madeleine",
playerTwoUsername: "jack",
},
];
</script>
<!-- -->
<Header/>
<menu>
{#each arr as match}
<MatchListElem match={match}/>
{/each}
</menu>
<!-- -->
<style>
</style>

View File

@@ -2,14 +2,12 @@
import Canvas from "../pieces/Canvas.svelte"; import Canvas from "../pieces/Canvas.svelte";
import { push } from "svelte-spa-router"; import { push } from "svelte-spa-router";
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { get } from "svelte/store";
import { Domain, Port } from "../Constantes.svelte";
let user; let user;
onMount(async () => { onMount(async () => {
user = await fetch(`http://${Domain}:${Port}/api/v2/user`) user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`)
.then((resp) => resp.json()) .then((resp) => resp.json())
// i mean i could do a failed to load user or some shit, maybe with a .catch or something? but atm why bother // i mean i could do a failed to load user or some shit, maybe with a .catch or something? but atm why bother
@@ -33,14 +31,14 @@
}); });
const login = async() => { const login = async() => {
window.location.href = `http://${Domain}:${Port}/api/v2/auth`; window.location.href = `http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/auth`;
console.log('you are now logged in'); console.log('you are now logged in');
} }
// i could prolly put this in it's own compoent, i seem to use it in several places... or maybe just some JS? like no need for html // i could prolly put this in it's own compoent, i seem to use it in several places... or maybe just some JS? like no need for html
// we could .then( () => replace('/') ) need the func so TS compatible... // we could .then( () => replace('/') ) need the func so TS compatible...
const logout = async() => { const logout = async() => {
await fetch(`http://${Domain}:${Port}/api/v2/auth/logout`, { await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/auth/logout`, {
method: 'POST', method: 'POST',
}); });
user = undefined; user = undefined;

View File

@@ -1,26 +1,14 @@
<script lang="ts"> <script lang="ts">
import { onMount } from "svelte"; import { onMount } from "svelte";
import { push } from "svelte-spa-router"; import { push } from "svelte-spa-router";
import { Domain, Port } from "../Constantes.svelte";
// onMount( async() => {
// await fetch(`http://${Domain}:${Port}/api/v2/auth/2fa/generate`,
// {
// method: 'POST',
// })
// .then(response => {return response.blob()})
// .then(blob => {
// const url = URL.createObjectURL(blob);
// qrCodeImg = url;
// });
// });
let qrCodeImg; let qrCodeImg;
let qrCode = ""; let qrCode = "";
let wrongCode = ""; let wrongCode = "";
const fetchQrCodeImg = (async() => { const fetchQrCodeImg = (async() => {
await fetch(`http://${Domain}:${Port}/api/v2/auth/2fa/generate`, await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/auth/2fa/generate`,
{ {
method: 'POST', method: 'POST',
}) })
@@ -32,7 +20,7 @@
})() })()
const submitCode = async() => { const submitCode = async() => {
const response = await fetch(`http://${Domain}:${Port}/api/v2/auth/2fa/check`, const response = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/auth/2fa/check`,
{ {
method : 'POST', method : 'POST',
headers : { headers : {

View File

@@ -3,12 +3,10 @@
import { onMount, onDestroy } from "svelte"; import { onMount, onDestroy } from "svelte";
import Header from '../../pieces/Header.svelte'; import Header from '../../pieces/Header.svelte';
import { fade, fly } from 'svelte/transition'; import { fade, fly } from 'svelte/transition';
import { Domain, Port } from "../../Constantes.svelte";
import * as pong from "./client/pong"; import * as pong from "./client/pong";
import { gameState } from "./client/ws";
// Pour Chérif: variables indiquant l'état du match
import { matchEnded, matchAbort } from "./client/ws";
//user's stuff //user's stuff
let user; let user;
@@ -37,39 +35,25 @@
let idOfIntevalCheckTerminationOfTheMatch; let idOfIntevalCheckTerminationOfTheMatch;
onMount( async() => { onMount( async() => {
user = await fetch(`http://${Domain}:${Port}/api/v2/user`) user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`)
.then( x => x.json() ); .then( x => x.json() );
allUsers = await fetch(`http://${Domain}:${Port}/api/v2/user/all`) allUsers = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/all`)
.then( x => x.json() ); .then( x => x.json() );
options.playerOneUsername = user.username; options.playerOneUsername = user.username;
}) })
onDestroy( async() => { onDestroy( async() => {
options.playerOneUsername = user.username;
showError = false;
showMatchEnded = false;
optionsAreNotSet = true
options.playerTwoUsername = "";
options.isSomeoneIsInvited = false;
options.isInvitedPerson = false;
options.moving_walls = false;
options.multi_balls = false;
errorMessageWhenAttemptingToGetATicket = "";
hiddenGame = true;
isThereAnyInvitation = false;
invitations = [];
pong.destroy();
clearInterval(idOfIntevalCheckTerminationOfTheMatch); clearInterval(idOfIntevalCheckTerminationOfTheMatch);
pong.destroy();
}) })
const initGame = async() => const initGame = async() =>
{ {
optionsAreNotSet = false; optionsAreNotSet = false;
showWaitPage = true; showWaitPage = true;
idOfIntevalCheckTerminationOfTheMatch = setInterval(matchTermitation, 1000);
const matchOptions = pong.computeMatchOptions(options); const matchOptions = pong.computeMatchOptions(options);
const responseWhenGrantToken = fetch(`http://${Domain}:${Port}/api/v2/game/ticket`, { const responseWhenGrantToken = fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/ticket`, {
method : "POST", method : "POST",
headers : {'Content-Type': 'application/json'}, headers : {'Content-Type': 'application/json'},
body : JSON.stringify({ body : JSON.stringify({
@@ -88,40 +72,36 @@
{ {
console.log(responseInjson) console.log(responseInjson)
console.log("On refuse le ticket"); console.log("On refuse le ticket");
clearInterval(idOfIntevalCheckTerminationOfTheMatch);
errorMessageWhenAttemptingToGetATicket = responseInjson.message; errorMessageWhenAttemptingToGetATicket = responseInjson.message;
showError = true; showError = true;
options.playerTwoUsername = ""; options.reset();
options.playerOneUsername = user.username; options.playerOneUsername = user.username;
options.isSomeoneIsInvited = false;
options.isInvitedPerson = false;
options.moving_walls = false;
options.multi_balls = false;
setTimeout(() => { setTimeout(() => {
showError = false;
showWaitPage = false
optionsAreNotSet = true optionsAreNotSet = true
showError = false;
// showWaitPage = false // ???
}, 5000); }, 5000);
} }
else if (token) else if (token)
{ {
options.isInvitedPerson = false idOfIntevalCheckTerminationOfTheMatch = setInterval(matchTermitation, 1000);
// options.isInvitedPerson = false // ???
pong.init(options, gameAreaId, token); pong.init(options, gameAreaId, token);
hiddenGame = false; hiddenGame = false;
} }
// TODO: Un "else" peut-être ? Si pas de token on fait un truc ?
// Si on ne rentre pas dans le else if, du coup il ne se passe rien.
} }
// Pour Cherif: renommer en un truc du genre "initGameForInvitedPlayer" ? const initGameForInvitedPlayer = async(invitation : any) =>
const initGameForPrivateParty = async(invitation : any) =>
{ {
idOfIntevalCheckTerminationOfTheMatch = setInterval(matchTermitation, 1000);
optionsAreNotSet = false optionsAreNotSet = false
showWaitPage = true showWaitPage = true
console.log("invitation : ") console.log("invitation : ")
console.log(invitation) console.log(invitation)
if (invitation.token) if (invitation.token)
{ {
idOfIntevalCheckTerminationOfTheMatch = setInterval(matchTermitation, 1000);
options.playerOneUsername = invitation.playerOneUsername; options.playerOneUsername = invitation.playerOneUsername;
options.playerTwoUsername = invitation.playerTwoUsername; options.playerTwoUsername = invitation.playerTwoUsername;
options.isSomeoneIsInvited = true; options.isSomeoneIsInvited = true;
@@ -134,32 +114,20 @@
const matchTermitation = () => { const matchTermitation = () => {
console.log("Ping matchTermitation") console.log("Ping matchTermitation")
if (matchAbort || matchEnded) if (gameState.matchAbort || gameState.matchEnded)
{ {
clearInterval(idOfIntevalCheckTerminationOfTheMatch); clearInterval(idOfIntevalCheckTerminationOfTheMatch);
console.log("matchTermitation was called") console.log("matchTermitation was called")
showWaitPage = false showWaitPage = false
matchAbort ? gameState.matchAbort ?
errorMessageWhenAttemptingToGetATicket = "The match has been aborted" errorMessageWhenAttemptingToGetATicket = "The match has been aborted"
: errorMessageWhenAttemptingToGetATicket = "The match is finished !" : errorMessageWhenAttemptingToGetATicket = "The match is finished !"
matchAbort ? showError = true : showMatchEnded = true; gameState.matchAbort ? showError = true : showMatchEnded = true;
setTimeout(() => { setTimeout(() => {
hiddenGame = true; resetPage();
showError = false;
showMatchEnded = false;
optionsAreNotSet = true
options.playerTwoUsername = "";
options.playerOneUsername = user.username;
options.isSomeoneIsInvited = false;
options.isInvitedPerson = false;
options.moving_walls = false;
options.multi_balls = false;
errorMessageWhenAttemptingToGetATicket = ""; errorMessageWhenAttemptingToGetATicket = "";
options.playerTwoUsername = "";
hiddenGame = true;
isThereAnyInvitation = false; isThereAnyInvitation = false;
invitations = []; invitations = []; // ???
pong.destroy();
console.log("matchTermitation : setTimeout") console.log("matchTermitation : setTimeout")
}, 5000); }, 5000);
} }
@@ -174,13 +142,13 @@
const showInvitation = async() => { const showInvitation = async() => {
showGameOption = false; showGameOption = false;
showInvitations = true; showInvitations = true;
invitations = await fetch(`http://${Domain}:${Port}/api/v2/game/invitations`) invitations = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/invitations`)
.then(x => x.json()) .then(x => x.json())
invitations.length !== 0 ? isThereAnyInvitation = true : isThereAnyInvitation = false invitations.length !== 0 ? isThereAnyInvitation = true : isThereAnyInvitation = false
} }
const rejectInvitation = async(invitation) => { const rejectInvitation = async(invitation) => {
await fetch(`http://${Domain}:${Port}/api/v2/game/decline`, { await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/decline`, {
method: "POST", method: "POST",
headers: { 'Content-Type': 'application/json'}, headers: { 'Content-Type': 'application/json'},
body: JSON.stringify({ body: JSON.stringify({
@@ -193,7 +161,7 @@
} }
const acceptInvitation = async(invitation : any) => { const acceptInvitation = async(invitation : any) => {
const res = await fetch(`http://${Domain}:${Port}/api/v2/game/accept`, { const res = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/accept`, {
method: "POST", method: "POST",
headers: { 'Content-Type': 'application/json'}, headers: { 'Content-Type': 'application/json'},
body: JSON.stringify({ body: JSON.stringify({
@@ -207,12 +175,27 @@
if (res.status === 200) if (res.status === 200)
{ {
showInvitation() showInvitation()
initGameForPrivateParty(invitation) initGameForInvitedPlayer(invitation)
} }
//Au final c'est utile ! //Au final c'est utile !
initGameForPrivateParty(invitation) initGameForInvitedPlayer(invitation) // Luke: normal de initGameForInvitedPlayer() sur un "res.status" different de 200 ?
} }
function leaveMatch() {
resetPage();
};
function resetPage() {
hiddenGame = true;
optionsAreNotSet = true
showError = false;
showMatchEnded = false;
options.reset();
options.playerOneUsername = user.username;
pong.destroy();
};
</script> </script>
<Header /> <Header />
@@ -233,9 +216,16 @@
</fieldset> </fieldset>
</div> </div>
{/if} {/if}
<div id="canvas_container" hidden={hiddenGame}> <div id="canvas_container" hidden={hiddenGame}>
<canvas id={gameAreaId}/> <canvas id={gameAreaId}/>
</div> </div>
{#if !hiddenGame}
<div id="div_game">
<button id="pong_button" on:click={leaveMatch}>forfeit</button>
</div>
{/if}
{#if showWaitPage === true} {#if showWaitPage === true}
<div id="div_game" in:fly="{{ y: 10, duration: 1000 }}"> <div id="div_game" in:fly="{{ y: 10, duration: 1000 }}">
@@ -251,44 +241,41 @@
{#if optionsAreNotSet} {#if optionsAreNotSet}
{#if showGameOption === true} {#if showGameOption === true}
<div id="game_option"> <div id="game_option">
<form on:submit|preventDefault={() => initGame()}> <div id="div_game">
<div id="div_game"> <button id="pong_button" on:click={showInvitation}>Show invitations</button>
<button id="pong_button" on:click={showInvitation}>Show invitations</button> <fieldset>
<fieldset> <legend>game options</legend>
<legend>game options</legend> <div>
<div> <input type="checkbox" id="multi_balls" name="multi_balls" bind:checked={options.multi_balls}>
<input type="checkbox" id="multi_balls" name="multi_balls" bind:checked={options.multi_balls}> <label for="multi_balls">Multiples balls</label>
<label for="multi_balls">Multiples balls</label> </div>
</div> <div>
<div> <input type="checkbox" id="moving_walls" name="moving_walls" bind:checked={options.moving_walls}>
<input type="checkbox" id="moving_walls" name="moving_walls" bind:checked={options.moving_walls}> <label for="moving_walls">Moving walls</label>
<label for="moving_walls">Moving walls</label> </div>
</div> <div>
<div> <p>sound :</p>
<p>sound :</p> <input type="radio" id="sound_on" name="sound_selector" bind:group={options.sound} value="on">
<input type="radio" id="sound_on" name="sound_selector" bind:group={options.sound} value="on"> <label for="sound_on">on</label>
<label for="sound_on">on</label> <input type="radio" id="sound_off" name="sound_selector" bind:group={options.sound} value="off">
<input type="radio" id="sound_off" name="sound_selector" bind:group={options.sound} value="off"> <label for="sound_off">off</label>
<label for="sound_off">off</label> </div>
</div> <div>
<div> <input type="checkbox" id="isSomeoneIsInvited" bind:checked={options.isSomeoneIsInvited}>
<input type="checkbox" id="isSomeoneIsInvited" bind:checked={options.isSomeoneIsInvited}> <label for="moving_walls">Invite a friend</label>
<label for="moving_walls">Invite a friend</label> </div>
</div> {#if options.isSomeoneIsInvited === true}
{#if options.isSomeoneIsInvited === true} <select bind:value={options.playerTwoUsername}>
<select bind:value={options.playerTwoUsername}> {#each allUsers as user }
{#each allUsers as user } <option value={user.username}>{user.username}</option>
<option value={user.username}>{user.username}</option> {/each}
{/each} </select>
</select> {/if}
{/if} <div>
<div> <button id="pong_button" on:click={initGame}>PLAY</button>
<button id="pong_button" >PLAY</button> </div>
</div> </fieldset>
</fieldset> </div>
</div>
</form>
</div> </div>
{/if} {/if}
@@ -344,12 +331,12 @@
/* max-height: 80vh; */ /* max-height: 80vh; */
/* overflow: hidden; */ /* overflow: hidden; */
} }
canvas {
#users_name { /* background-color: #ff0000; */
text-align: center; background-color: #333333;
font-family: "Bit5x3"; max-width: 75vw;
color: rgb(245, 245, 245); /* max-height: 100vh; */
font-size: x-large; width: 80%;
} }
#div_game { #div_game {
@@ -359,15 +346,6 @@
color: rgb(245, 245, 245); color: rgb(245, 245, 245);
font-size: x-large; font-size: x-large;
} }
#error_notification {
text-align: center;
display: block;
font-family: "Bit5x3";
color: rgb(143, 19, 19);
font-size: x-large;
}
#div_game fieldset { #div_game fieldset {
max-width: 50vw; max-width: 50vw;
width: auto; width: auto;
@@ -383,12 +361,19 @@
font-size: x-large; font-size: x-large;
padding: 10px; padding: 10px;
} }
canvas {
/* background-color: #ff0000; */ #users_name { /* UNUSED */
background-color: #333333; text-align: center;
max-width: 75vw; font-family: "Bit5x3";
/* max-height: 100vh; */ color: rgb(245, 245, 245);
width: 80%; font-size: x-large;
}
#error_notification { /* UNUSED */
text-align: center;
display: block;
font-family: "Bit5x3";
color: rgb(143, 19, 19);
font-size: x-large;
} }
</style> </style>

View File

@@ -2,13 +2,13 @@
<script lang="ts"> <script lang="ts">
import { onMount, onDestroy } from "svelte"; import { onMount, onDestroy } from "svelte";
import Header from '../../pieces/Header.svelte'; import Header from '../../pieces/Header.svelte';
import MatchListElem from "../../pieces/MatchListElem.svelte";
import { fade, fly } from 'svelte/transition'; import { fade, fly } from 'svelte/transition';
import { Domain, Port } from "../../Constantes.svelte";
import * as pongSpectator from "./client/pongSpectator"; import * as pongSpectator from "./client/pongSpectator";
import { gameState } from "./client/ws";
// Pour Chérif: variables indiquant l'état du match import { gameSessionIdPLACEHOLDER } from "./shared_js/constants";
import { matchEnded, matchAbort } from "./client/ws";
//user's stuff //user's stuff
let user; let user;
@@ -16,30 +16,82 @@
//Game's stuff client side only //Game's stuff client side only
const gameAreaId = "game_area"; const gameAreaId = "game_area";
let sound = "off";
// const dummyMatchList = [
// {
// gameSessionId: gameSessionIdPLACEHOLDER,
// matchOptions: pongSpectator.MatchOptions.noOption,
// playerOneUsername: "toto",
// playerTwoUsername: "bruno",
// },
// {
// gameSessionId: gameSessionIdPLACEHOLDER,
// matchOptions: pongSpectator.MatchOptions.multiBalls,
// playerOneUsername: "pl1",
// playerTwoUsername: "pl2",
// },
// {
// gameSessionId: "id6543",
// matchOptions: pongSpectator.MatchOptions.movingWalls | pongSpectator.MatchOptions.multiBalls,
// playerOneUsername: "bertand",
// playerTwoUsername: "cassandre",
// },
// {
// gameSessionId: "id3452",
// matchOptions: pongSpectator.MatchOptions.multiBalls,
// playerOneUsername: "madeleine",
// playerTwoUsername: "jack",
// },
// ];
let matchList = [];
//html boolean for pages //html boolean for pages
let hiddenGame = true; let hiddenGame = true;
let hiddenMatchList = false;
onMount( async() => { onMount( async() => {
user = await fetch(`http://${Domain}:${Port}/api/v2/user`) user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`)
.then( x => x.json() ); .then( x => x.json() );
allUsers = await fetch(`http://${Domain}:${Port}/api/v2/user/all`) allUsers = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/all`)
.then( x => x.json() ); .then( x => x.json() );
// WIP: fetch for match list here
const responseForMatchList = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/match/all`)
const jsonForMatchList = await responseForMatchList.json();
matchList = jsonForMatchList;
console.log("matchList");
if (matchList.length <= 0)
hiddenMatchList = true;
console.log(matchList);
}) })
onDestroy( async() => { onDestroy( async() => {
pongSpectator.destroy(); pongSpectator.destroy();
}) })
const initGameSpectator = async() => { async function initGameSpectator(gameSessionId: string, matchOptions: pongSpectator.MatchOptions) {
let gameSessionId = "ID_PLACEHOLDER"; // PLACEHOLDER
let matchOptions = 0; // PLACEHOLDER
let sound = "off"; // PLACEHOLDER
pongSpectator.init(matchOptions, sound, gameAreaId, gameSessionId); pongSpectator.init(matchOptions, sound, gameAreaId, gameSessionId);
hiddenGame = false; hiddenGame = false;
}; };
function leaveMatch() {
resetPage();
};
async function resetPage() {
hiddenGame = true;
pongSpectator.destroy();
// WIP: fetch for match list here
matchList = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/match/all`)
.then( x => x.json() );
console.log("matchList");
if (matchList.length <= 0)
hiddenMatchList = true;
console.log(matchList);
};
</script> </script>
<!-- -->
<Header /> <Header />
<!-- <div id="game_page"> Replacement for <body>. <!-- <div id="game_page"> Replacement for <body>.
@@ -50,7 +102,92 @@
<canvas id={gameAreaId}/> <canvas id={gameAreaId}/>
</div> </div>
{#if hiddenGame}
<div id="div_game">
<div id="game_options">
<fieldset>
{#if hiddenMatchList}
<legend>no match available</legend>
{:else}
<legend>options</legend>
<div>
<p>sound :</p>
<input type="radio" id="sound_on" name="sound_selector" bind:group={sound} value="on">
<label for="sound_on">on</label>
<input type="radio" id="sound_off" name="sound_selector" bind:group={sound} value="off">
<label for="sound_off">off</label>
</div>
<menu id="match_list">
{#each matchList as match}
<MatchListElem match={match} on:click={(e) => initGameSpectator(match.gameServerIdOfTheMatch, match.gameOptions)} />
{/each}
</menu>
{/if}
</fieldset>
</div>
</div>
{:else}
<div id="div_game">
<button id="pong_button" on:click={leaveMatch}>leave match</button>
</div>
{/if}
</div> <!-- div "game_page" --> </div> <!-- div "game_page" -->
<!-- -->
<style> <style>
@font-face {
font-family: "Bit5x3";
src:
url("/fonts/Bit5x3.woff2") format("woff2"),
local("Bit5x3"),
url("/fonts/Bit5x3.woff") format("woff");
font-weight: normal;
font-style: normal;
font-display: swap;
}
#game_page {
margin: 0;
background-color: #222425;
position: relative;
width: 100%;
height: 100%;
}
#canvas_container {
margin-top: 20px;
text-align: center;
}
canvas {
background-color: #333333;
max-width: 75vw;
width: 80%;
}
#div_game {
margin-top: 20px;
text-align: center;
font-family: "Bit5x3";
color: rgb(245, 245, 245);
font-size: x-large;
}
#div_game fieldset {
max-width: 50vw;
width: auto;
margin: 0 auto;
}
#div_game fieldset div {
padding: 10px;
}
#match_list {
font-family: 'Courier New', Courier, monospace;
font-size: large;
}
#pong_button {
font-family: "Bit5x3";
color: rgb(245, 245, 245);
background-color: #333333;
font-size: x-large;
padding: 10px;
}
</style> </style>

View File

@@ -2,16 +2,16 @@
<script lang="ts"> <script lang="ts">
import { onMount, onDestroy } from "svelte"; import { onMount, onDestroy } from "svelte";
import Header from "../../pieces/Header.svelte"; import Header from "../../pieces/Header.svelte";
import { Domain, Port } from "../../Constantes.svelte";
//user's stuff //user's stuff
let currentUser; let currentUser;
let allUsers = []; let allUsers = [];
let idInterval; let idInterval;
onMount( async() => { onMount( async() => {
currentUser = await fetch(`http://${Domain}:${Port}/api/v2/user`) currentUser = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`)
.then( x => x.json() ); .then( x => x.json() );
allUsers = await fetch(`http://${Domain}:${Port}/api/v2/game/ranking`) allUsers = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/ranking`)
.then( x => x.json() ); .then( x => x.json() );
idInterval = setInterval(fetchScores, 10000); idInterval = setInterval(fetchScores, 10000);
}) })
@@ -21,7 +21,7 @@
}) })
function fetchScores() { function fetchScores() {
fetch(`http://${Domain}:${Port}/api/v2/game/ranking`) fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/ranking`)
.then( x => x.json() ) .then( x => x.json() )
.then( x => allUsers = x ); .then( x => allUsers = x );
} }

View File

@@ -1,21 +1,32 @@
import * as c from "./constants.js" import * as c from "./constants.js"
export const soundPongArr: HTMLAudioElement[] = []; // export const soundPongArr: HTMLAudioElement[] = [];
export const soundPongArr: HTMLAudioElement[] = [
new Audio("http://transcendance:8080/sound/pong/"+1+".ogg"),
new Audio("http://transcendance:8080/sound/pong/"+2+".ogg")
];
export const soundRoblox = new Audio("http://transcendance:8080/sound/roblox-oof.ogg"); export const soundRoblox = new Audio("http://transcendance:8080/sound/roblox-oof.ogg");
export function initAudio(sound: string) export function initAudio(sound: string)
{ {
let muteFlag = true; let muteFlag: boolean;
if (sound === "on") { if (sound === "on") {
muteFlag = false; muteFlag = false;
} }
else {
muteFlag = true;
}
for (let i = 0; i <= 32; i++) { /* for (let i = 0; i <= 32; i++) {
soundPongArr.push(new Audio("http://transcendance:8080/sound/pong/"+i+".ogg")); soundPongArr.push(new Audio("http://transcendance:8080/sound/pong/"+i+".ogg"));
soundPongArr[i].volume = c.soundPongVolume; soundPongArr[i].volume = c.soundPongVolume;
soundPongArr[i].muted = muteFlag; soundPongArr[i].muted = muteFlag;
} } */
soundPongArr.forEach((value) => {
value.volume = c.soundRobloxVolume;
value.muted = muteFlag;
});
soundRoblox.volume = c.soundRobloxVolume; soundRoblox.volume = c.soundRobloxVolume;
soundRoblox.muted = muteFlag; soundRoblox.muted = muteFlag;
} }

View File

@@ -7,4 +7,13 @@ export class InitOptions {
isInvitedPerson = false; isInvitedPerson = false;
playerOneUsername = ""; playerOneUsername = "";
playerTwoUsername = ""; playerTwoUsername = "";
reset() {
this.sound = "off";
this.multi_balls = false;
this.moving_walls = false;
this.isSomeoneIsInvited = false;
this.isInvitedPerson = false;
this.playerOneUsername = "";
this.playerTwoUsername = "";
}
} }

View File

@@ -1,7 +1,8 @@
import * as c from "./constants.js"; import * as c from "./constants.js";
import * as en from "../shared_js/enums.js" import * as en from "../shared_js/enums.js"
import { gc, matchOptions, clientInfo, clientInfoSpectator} from "./global.js"; import { gc, matchOptions } from "./global.js";
import { clientInfo, clientInfoSpectator} from "./ws.js";
import { wallsMovements } from "../shared_js/wallsMovement.js"; import { wallsMovements } from "../shared_js/wallsMovement.js";
import type { RacketClient } from "./class/RectangleClient.js"; import type { RacketClient } from "./class/RectangleClient.js";
import type { VectorInteger } from "../shared_js/class/Vector.js"; import type { VectorInteger } from "../shared_js/class/Vector.js";

View File

@@ -3,27 +3,24 @@ import * as en from "../shared_js/enums.js";
import type { GameArea } from "./class/GameArea.js"; import type { GameArea } from "./class/GameArea.js";
import type { GameComponentsClient } from "./class/GameComponentsClient.js"; import type { GameComponentsClient } from "./class/GameComponentsClient.js";
// export {pong, gc, matchOptions} from "./pong.js"
export {socket, clientInfo, clientInfoSpectator} from "./ws.js"
export let pong: GameArea; export let pong: GameArea;
export let gc: GameComponentsClient; export let gc: GameComponentsClient;
export let matchOptions: en.MatchOptions = en.MatchOptions.noOption; export let matchOptions: en.MatchOptions = en.MatchOptions.noOption;
export function initPong(value: GameArea) { export function setPong(value: GameArea) {
pong = value; pong = value;
} }
export function initGc(value: GameComponentsClient) { export function setGc(value: GameComponentsClient) {
gc = value; gc = value;
} }
export function initMatchOptions(value: en.MatchOptions) { export function setMatchOptions(value: en.MatchOptions) {
matchOptions = value; matchOptions = value;
} }
export let startFunction: () => void; export let startFunction: () => void;
export function initStartFunction(value: () => void) { export function setStartFunction(value: () => void) {
startFunction = value; startFunction = value;
} }

View File

@@ -1,10 +1,10 @@
import { pong, gc, socket, clientInfo } from "./global.js" import { pong, gc } from "./global.js"
import { socket, clientInfo, gameState } from "./ws.js"
import * as ev from "../shared_js/class/Event.js" import * as ev from "../shared_js/class/Event.js"
import * as en from "../shared_js/enums.js" import * as en from "../shared_js/enums.js"
import { InputHistory } from "./class/InputHistory.js" import { InputHistory } from "./class/InputHistory.js"
import * as c from "./constants.js"; import * as c from "./constants.js";
import { matchEnded } from "./ws.js";
export let gridDisplay = false; export let gridDisplay = false;
@@ -44,7 +44,7 @@ export function handleInput()
playerMovements(delta_time, keys); playerMovements(delta_time, keys);
} }
if (!matchEnded) { if (!gameState.matchEnded) {
socket.send(JSON.stringify(inputState)); socket.send(JSON.stringify(inputState));
} }
// setTimeout(testInputDelay, 100); // setTimeout(testInputDelay, 100);

View File

@@ -3,12 +3,12 @@ import * as c from "./constants.js"
import * as en from "../shared_js/enums.js" import * as en from "../shared_js/enums.js"
import { GameArea } from "./class/GameArea.js"; import { GameArea } from "./class/GameArea.js";
import { GameComponentsClient } from "./class/GameComponentsClient.js"; import { GameComponentsClient } from "./class/GameComponentsClient.js";
import { socket } from "./ws.js"; import { socket, resetGameState } from "./ws.js";
import { initAudio } from "./audio.js"; import { initAudio } from "./audio.js";
import type { InitOptions } from "./class/InitOptions.js"; import type { InitOptions } from "./class/InitOptions.js";
import { pong } from "./global.js" import { pong } from "./global.js"
import { initPong, initGc, initMatchOptions } from "./global.js" import { setPong, setGc, setMatchOptions } from "./global.js"
export function computeMatchOptions(options: InitOptions) export function computeMatchOptions(options: InitOptions)
{ {
@@ -26,10 +26,10 @@ export function computeMatchOptions(options: InitOptions)
export function initBase(matchOptions: en.MatchOptions, sound: string, gameAreaId: string) export function initBase(matchOptions: en.MatchOptions, sound: string, gameAreaId: string)
{ {
initMatchOptions(matchOptions);
initAudio(sound); initAudio(sound);
initPong(new GameArea(gameAreaId)); setMatchOptions(matchOptions);
initGc(new GameComponentsClient(matchOptions, pong.ctx)); setPong(new GameArea(gameAreaId));
setGc(new GameComponentsClient(matchOptions, pong.ctx));
} }
export function destroyBase() export function destroyBase()
@@ -39,9 +39,10 @@ export function destroyBase()
clearInterval(pong.handleInputInterval); clearInterval(pong.handleInputInterval);
clearInterval(pong.gameLoopInterval); clearInterval(pong.gameLoopInterval);
clearInterval(pong.drawLoopInterval); clearInterval(pong.drawLoopInterval);
initPong(null); setPong(null);
} }
if (socket && socket.OPEN) { if (socket && socket.OPEN) {
socket.close(); socket.close();
} }
resetGameState();
} }

View File

@@ -12,15 +12,17 @@ export { computeMatchOptions } from "./init.js";
/* TODO: A way to delay the init of variables, but still use "const" not "let" ? */ /* TODO: A way to delay the init of variables, but still use "const" not "let" ? */
import { pong, gc } from "./global.js" import { pong, gc } from "./global.js"
import { initStartFunction } from "./global.js" import { setStartFunction } from "./global.js"
let abortControllerKeydown: AbortController;
let abortControllerKeyup: AbortController;
export function init(options: InitOptions, gameAreaId: string, token: string) export function init(options: InitOptions, gameAreaId: string, token: string)
{ {
const matchOptions = computeMatchOptions(options); const matchOptions = computeMatchOptions(options);
initBase(matchOptions, options.sound, gameAreaId); initBase(matchOptions, options.sound, gameAreaId);
initStartFunction(start); setStartFunction(start);
if (options.isSomeoneIsInvited) { if (options.isSomeoneIsInvited) {
initWebSocket(matchOptions, token, options.playerOneUsername, true, options.playerTwoUsername, options.isInvitedPerson); initWebSocket(matchOptions, token, options.playerOneUsername, true, options.playerTwoUsername, options.isInvitedPerson);
} }
@@ -32,6 +34,14 @@ export function init(options: InitOptions, gameAreaId: string, token: string)
export function destroy() export function destroy()
{ {
destroyBase(); destroyBase();
if (abortControllerKeydown) {
abortControllerKeydown.abort();
abortControllerKeydown = null;
}
if (abortControllerKeyup) {
abortControllerKeyup.abort();
abortControllerKeyup = null;
}
} }
function start() function start()
@@ -41,20 +51,40 @@ function start()
gc.text1.clear(); gc.text1.clear();
gc.text1.text = `${count}`; gc.text1.text = `${count}`;
gc.text1.update(); gc.text1.update();
}, resume); }, start_after_countdown);
}
function start_after_countdown()
{
abortControllerKeydown = new AbortController();
window.addEventListener(
'keydown',
(e) => { pong.addKey(e.key); },
{signal: abortControllerKeydown.signal}
);
abortControllerKeyup = new AbortController();
window.addEventListener(
'keyup',
(e) => { pong.deleteKey(e.key);},
{signal: abortControllerKeyup.signal}
);
resume();
} }
function resume() function resume()
{ {
gc.text1.text = ""; gc.text1.text = "";
window.addEventListener('keydown', function (e) {
pong.addKey(e.key);
});
window.addEventListener('keyup', function (e) {
pong.deleteKey(e.key);
});
pong.handleInputInterval = window.setInterval(handleInput, c.handleInputIntervalMS); pong.handleInputInterval = window.setInterval(handleInput, c.handleInputIntervalMS);
// pong.handleInputInterval = window.setInterval(sendLoop, c.sendLoopIntervalMS); // pong.handleInputInterval = window.setInterval(sendLoop, c.sendLoopIntervalMS);
pong.gameLoopInterval = window.setInterval(gameLoop, c.gameLoopIntervalMS); pong.gameLoopInterval = window.setInterval(gameLoop, c.gameLoopIntervalMS);
pong.drawLoopInterval = window.setInterval(drawLoop, c.drawLoopIntervalMS); pong.drawLoopInterval = window.setInterval(drawLoop, c.drawLoopIntervalMS);
} }
function pause() // unused
{
clearInterval(pong.handleInputInterval);
clearInterval(pong.gameLoopInterval);
clearInterval(pong.drawLoopInterval);
}

View File

@@ -6,17 +6,18 @@ import { drawLoop } from "./draw.js";
import { initWebSocketSpectator } from "./ws.js"; import { initWebSocketSpectator } from "./ws.js";
import { initBase, destroyBase, computeMatchOptions } from "./init.js"; import { initBase, destroyBase, computeMatchOptions } from "./init.js";
export { computeMatchOptions } from "./init.js"; export { computeMatchOptions } from "./init.js";
export { MatchOptions } from "../shared_js/enums.js"
/* TODO: A way to delay the init of variables, but still use "const" not "let" ? */ /* TODO: A way to delay the init of variables, but still use "const" not "let" ? */
import { pong, gc } from "./global.js" import { pong, gc } from "./global.js"
import { initStartFunction } from "./global.js" import { setStartFunction } from "./global.js"
export function init(matchOptions: en.MatchOptions, sound: string, gameAreaId: string, gameSessionId: string) export function init(matchOptions: en.MatchOptions, sound: string, gameAreaId: string, gameSessionId: string)
{ {
initBase(matchOptions, sound, gameAreaId); initBase(matchOptions, sound, gameAreaId);
initStartFunction(start); setStartFunction(start);
initWebSocketSpectator(gameSessionId); initWebSocketSpectator(gameSessionId);
} }
@@ -35,3 +36,9 @@ function resume()
pong.gameLoopInterval = window.setInterval(gameLoopSpectator, c.gameLoopIntervalMS); pong.gameLoopInterval = window.setInterval(gameLoopSpectator, c.gameLoopIntervalMS);
pong.drawLoopInterval = window.setInterval(drawLoop, c.drawLoopIntervalMS); pong.drawLoopInterval = window.setInterval(drawLoop, c.drawLoopIntervalMS);
} }
function pause() // unused
{
clearInterval(pong.gameLoopInterval);
clearInterval(pong.drawLoopInterval);
}

View File

@@ -10,8 +10,15 @@ import { soundRoblox } from "./audio.js"
import { sleep } from "./utils.js"; import { sleep } from "./utils.js";
import { Vector, VectorInteger } from "../shared_js/class/Vector.js"; import { Vector, VectorInteger } from "../shared_js/class/Vector.js";
export let matchEnded = false; export const gameState = {
export let matchAbort = false; matchEnded: false,
matchAbort: false
}
export function resetGameState() {
gameState.matchEnded = false;
gameState.matchAbort = false;
}
class ClientInfo { class ClientInfo {
id = ""; id = "";
@@ -57,7 +64,6 @@ function logListener(this: WebSocket, event: MessageEvent) {
} }
function errorListener(this: WebSocket, event: MessageEvent) { function errorListener(this: WebSocket, event: MessageEvent) {
console.log("errorListener");
const data: ev.ServerEvent = JSON.parse(event.data); const data: ev.ServerEvent = JSON.parse(event.data);
if (data.type === en.EventTypes.error) { if (data.type === en.EventTypes.error) {
console.log("actual Error"); console.log("actual Error");
@@ -98,12 +104,9 @@ function preMatchListener(this: WebSocket, event: MessageEvent)
startFunction(); startFunction();
break; break;
case en.EventTypes.matchAbort: case en.EventTypes.matchAbort:
matchAbort = true; gameState.matchAbort = true;
socket.removeEventListener("message", preMatchListener); socket.removeEventListener("message", preMatchListener);
msg.matchAbort(); msg.matchAbort();
setTimeout(() => {
matchAbort = false;
}, 1000);
break; break;
} }
} }
@@ -204,7 +207,7 @@ function scoreUpdate(data: ev.EventScoreUpdate)
function matchEnd(data: ev.EventMatchEnd) function matchEnd(data: ev.EventMatchEnd)
{ {
matchEnded = true; gameState.matchEnded = true;
socket.close(); socket.close();
if (data.winner === clientInfo.side) { if (data.winner === clientInfo.side) {
msg.win(); msg.win();
@@ -215,9 +218,6 @@ function matchEnd(data: ev.EventMatchEnd)
else { else {
msg.lose(); msg.lose();
} }
setTimeout(() => {
matchEnded = false;
}, 1000);
} }
/* Spectator */ /* Spectator */
@@ -229,6 +229,7 @@ export function initWebSocketSpectator(gameSessionId: string)
socket.send(JSON.stringify( new ev.ClientAnnounceSpectator(gameSessionId) )); socket.send(JSON.stringify( new ev.ClientAnnounceSpectator(gameSessionId) ));
}); });
// socket.addEventListener("message", logListener); // for testing purpose // socket.addEventListener("message", logListener); // for testing purpose
socket.addEventListener("message", errorListener);
socket.addEventListener("message", preMatchListenerSpectator); socket.addEventListener("message", preMatchListenerSpectator);
clientInfoSpectator.playerLeftNextPos = new VectorInteger(gc.playerLeft.pos.x, gc.playerLeft.pos.y); clientInfoSpectator.playerLeftNextPos = new VectorInteger(gc.playerLeft.pos.x, gc.playerLeft.pos.y);
@@ -243,6 +244,7 @@ export function preMatchListenerSpectator(this: WebSocket, event: MessageEvent)
{ {
socket.removeEventListener("message", preMatchListenerSpectator); socket.removeEventListener("message", preMatchListenerSpectator);
socket.addEventListener("message", inGameListenerSpectator); socket.addEventListener("message", inGameListenerSpectator);
socket.send(JSON.stringify( new ev.ClientEvent(en.EventTypes.clientSpectatorReady) ));
startFunction(); startFunction();
} }
} }
@@ -318,7 +320,7 @@ function scoreUpdateSpectator(data: ev.EventScoreUpdate)
function matchEndSpectator(data: ev.EventMatchEnd) function matchEndSpectator(data: ev.EventMatchEnd)
{ {
console.log("matchEndSpectator"); console.log("matchEndSpectator");
matchEnded = true; gameState.matchEnded = true;
socket.close(); socket.close();
// WIP // WIP
/* msg.win(); /* msg.win();

View File

@@ -26,5 +26,5 @@ export const movingWallPosMax = Math.floor(w*0.12);
export const movingWallSpeed = Math.floor(w*0.08); export const movingWallSpeed = Math.floor(w*0.08);
export const gameSessionIdPLACEHOLDER = "42"; // TESTING SPECTATOR PLACEHOLDER export const gameSessionIdPLACEHOLDER = "match-id-test-42"; // TESTING SPECTATOR PLACEHOLDER
// for testing, force gameSession.id in wsServer.ts->matchmaking() // for testing, force gameSession.id in wsServer.ts->createGameSession()

View File

@@ -19,6 +19,7 @@ export enum EventTypes {
// Client // Client
clientAnnounce, clientAnnounce,
clientPlayerReady, clientPlayerReady,
clientSpectatorReady,
clientInput, clientInput,
} }

View File

@@ -2,7 +2,7 @@
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import GenerateUserDisplay from '../../pieces/GenerateUserDisplay.svelte'; import GenerateUserDisplay from '../../pieces/GenerateUserDisplay.svelte';
import { Domain, Port } from "../../Constantes.svelte";
import Chat from '../../pieces/chat/Chat.svelte'; import Chat from '../../pieces/chat/Chat.svelte';
@@ -10,7 +10,7 @@
onMount( async() => { onMount( async() => {
// console.log('mounting profile display') // console.log('mounting profile display')
user = await fetch(`http://${Domain}:${Port}/api/v2/user`) user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`)
.then( (x) => x.json() ); .then( (x) => x.json() );
}) })

View File

@@ -2,7 +2,7 @@
import { onMount } from "svelte"; import { onMount } from "svelte";
import { binding_callbacks } from "svelte/internal"; import { binding_callbacks } from "svelte/internal";
import { Domain, Port } from "../../Constantes.svelte";
import Button from "../../pieces/Button.svelte"; import Button from "../../pieces/Button.svelte";
import DisplayAUser from "../../pieces/DisplayAUser.svelte"; import DisplayAUser from "../../pieces/DisplayAUser.svelte";
@@ -39,7 +39,7 @@ could be a list of friends and if they're active but i can't see that yet
onMount( async() => { onMount( async() => {
// yea no idea what // yea no idea what
// i mean do i fetch user? i will for now // i mean do i fetch user? i will for now
user = await fetch(`http://${Domain}:${Port}/api/v2/user`) user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`)
.then( (x) => x.json() ); .then( (x) => x.json() );
// userBeingViewed = user; // userBeingViewed = user;
@@ -47,26 +47,26 @@ could be a list of friends and if they're active but i can't see that yet
// console.log(user) // console.log(user)
// console.log(user.username) // console.log(user.username)
myFriends = await fetch(`http://${Domain}:${Port}/api/v2/network/myfriends`) myFriends = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/myfriends`)
.then( (x) => x.json() ); .then( (x) => x.json() );
// console.log('my friends') // console.log('my friends')
// console.log(myFriends) // console.log(myFriends)
requestsMade = await fetch(`http://${Domain}:${Port}/api/v2/network/pending`) requestsMade = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/pending`)
.then( x => x.json() ); .then( x => x.json() );
// console.log('Requests pending '); // console.log('Requests pending ');
// console.log(requestsMade); // console.log(requestsMade);
requestsRecieved = await fetch(`http://${Domain}:${Port}/api/v2/network/received`) requestsRecieved = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/received`)
.then( x => x.json() ); .then( x => x.json() );
// console.log('Requests received '); // console.log('Requests received ');
// console.log(requestsRecieved); // console.log(requestsRecieved);
allUsers = await fetch(`http://${Domain}:${Port}/api/v2/user/all`) allUsers = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/all`)
.then( x => x.json() ); .then( x => x.json() );
// console.log('got all users ' + allUsers) // console.log('got all users ' + allUsers)
@@ -75,20 +75,20 @@ could be a list of friends and if they're active but i can't see that yet
const displayAllUsers = async() => { const displayAllUsers = async() => {
allUsers = await fetch(`http://${Domain}:${Port}/api/v2/user/all`) allUsers = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/all`)
.then( x => x.json() ); .then( x => x.json() );
// console.log('got all users ' + allUsers) // console.log('got all users ' + allUsers)
}; };
const displayAllFriends = async() => { const displayAllFriends = async() => {
myFriends = await fetch(`http://${Domain}:${Port}/api/v2/network/myfriends`) myFriends = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/myfriends`)
.then( x => x.json() ); .then( x => x.json() );
// console.log('got all friends ' + allFriends) // console.log('got all friends ' + allFriends)
}; };
const displayRequestsMade = async() => { const displayRequestsMade = async() => {
requestsMade = await fetch(`http://${Domain}:${Port}/api/v2/network/pending`) requestsMade = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/pending`)
.then( x => x.json() ); .then( x => x.json() );
// console.log('got requests made ' + requestsMade) // console.log('got requests made ' + requestsMade)
}; };
@@ -107,7 +107,7 @@ could be a list of friends and if they're active but i can't see that yet
} }
if (valid) { if (valid) {
sentFriendRequest = await fetch(`http://${Domain}:${Port}/api/v2/network/myfriends`, { sentFriendRequest = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/myfriends`, {
method : "POST", method : "POST",
headers: { 'Content-Type': 'application/json'}, headers: { 'Content-Type': 'application/json'},
body: JSON.stringify({ body: JSON.stringify({
@@ -125,7 +125,7 @@ could be a list of friends and if they're active but i can't see that yet
// sendUsername = userBeingViewed.username; // sendUsername = userBeingViewed.username;
// prolly like fetch if you're friends or not? // prolly like fetch if you're friends or not?
// GET `http://${Domain}:${Port}/api/v2/networks/myfriends?username=aUser` but i need to make that as long as Cherif // GET `http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/networks/myfriends?username=aUser` but i need to make that as long as Cherif
// doesn't have a better option // doesn't have a better option
// like i want this thing to return the Friendship ID ideally // like i want this thing to return the Friendship ID ideally
}; };

View File

@@ -3,7 +3,7 @@
import Card from '../../pieces/Card.svelte'; import Card from '../../pieces/Card.svelte';
import {onMount} from 'svelte'; import {onMount} from 'svelte';
import { push } from 'svelte-spa-router'; import { push } from 'svelte-spa-router';
import { Domain, Port } from "../../Constantes.svelte";
import Button from '../../pieces/Button.svelte'; import Button from '../../pieces/Button.svelte';
let user; let user;
@@ -17,7 +17,7 @@
let success = {username: '', avatar: '' }; let success = {username: '', avatar: '' };
onMount( async() => { onMount( async() => {
user = await fetch(`http://${Domain}:${Port}/api/v2/user`) user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`)
.then( (x) => x.json() ); .then( (x) => x.json() );
// do a .catch? // do a .catch?
@@ -34,7 +34,7 @@
// console.log('this is what is in the avatar before fetch') // console.log('this is what is in the avatar before fetch')
// console.log(avatar) // console.log(avatar)
await fetch(`http://${Domain}:${Port}/api/v2/user/avatar`, {method: "GET"}) await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/avatar`, {method: "GET"})
.then(response => {return response.blob()}) .then(response => {return response.blob()})
.then(data => { .then(data => {
const url = URL.createObjectURL(data); const url = URL.createObjectURL(data);
@@ -64,7 +64,7 @@
else { else {
errors.username = ''; errors.username = '';
} }
await fetch(`http://${Domain}:${Port}/api/v2/user`, { await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`, {
method: 'PATCH', method: 'PATCH',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
@@ -101,15 +101,21 @@
// tmp // tmp
console.log(data); console.log(data);
await fetch(`http://${Domain}:${Port}/api/v2/user/avatar`, const responseWhenChangeAvatar = fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/avatar`,
{ {
method : 'POST', method : 'POST',
body : data, body : data,
}) })
.then(() => uploadAvatarSuccess = true ) // for some reason it needs to be a function, i think a TS thing, not a promis otherwise const responseFromServer = await responseWhenChangeAvatar;
.then(() => success.avatar = 'Your changes have been saved') if (responseFromServer.ok === true) {
.catch(() => errors.avatar = 'Sorry failed to upload your new Avatar' ); uploadAvatarSuccess = true;
await fetch(`http://${Domain}:${Port}/api/v2/user/avatar`, {method: "GET"}) success.avatar = 'Your avatar has been updated';
}
else {
errors.avatar = responseFromServer.statusText;
}
await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/avatar`, {method: "GET"})
.then(response => {return response.blob()}) .then(response => {return response.blob()})
.then(data => { .then(data => {
const url = URL.createObjectURL(data); const url = URL.createObjectURL(data);

View File

@@ -2,7 +2,7 @@
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import GenerateUserDisplay from './GenerateUserDisplay.svelte'; import GenerateUserDisplay from './GenerateUserDisplay.svelte';
import { Domain, Port } from "../Constantes.svelte";
// import {updateGeneratedUser} from './GenerateUserDisplay.svelte'; // import {updateGeneratedUser} from './GenerateUserDisplay.svelte';
export let aUsername; export let aUsername;
@@ -10,8 +10,8 @@
onMount( async() => { onMount( async() => {
console.log('Display aUser username: '+ aUsername) console.log('Display aUser username: '+ aUsername)
//`http://${Domain}:${Port}/api/v2/user?username=NomDuUserATrouve` //`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user?username=NomDuUserATrouve`
user = await fetch(`http://${Domain}:${Port}/api/v2/user?username=${aUsername}`) user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user?username=${aUsername}`)
.then( (x) => x.json() ); .then( (x) => x.json() );
// console.log('Display a user: ') // console.log('Display a user: ')
@@ -27,15 +27,15 @@
const updateUser = async(updatedUser) => { const updateUser = async(updatedUser) => {
console.log('Display Update aUser username: '+ updateUser) console.log('Display Update aUser username: '+ updateUser)
//`http://${Domain}:${Port}/api/v2/user?username=NomDuUserATrouve` //`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user?username=NomDuUserATrouve`
user = await fetch(`http://${Domain}:${Port}/api/v2/user?username=${updateUser}`) user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user?username=${updateUser}`)
.then( (x) => x.json() ); .then( (x) => x.json() );
}; };
// export const updateUser = async(updatedUser) => { // export const updateUser = async(updatedUser) => {
// console.log('Display Update aUser username: '+ updateUser) // console.log('Display Update aUser username: '+ updateUser)
// //`http://${Domain}:${Port}/api/v2/user?username=NomDuUserATrouve` // //`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user?username=NomDuUserATrouve`
// user = await fetch(`http://${Domain}:${Port}/api/v2/user?username=${updateUser}`) // user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user?username=${updateUser}`)
// .then( (x) => x.json() ); // .then( (x) => x.json() );
// updateGeneratedUser(updateUser); // updateGeneratedUser(updateUser);

View File

@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { Domain, Port } from "../Constantes.svelte";
export let user; export let user;
export let primary; export let primary;
@@ -12,7 +12,7 @@
onMount( async() => { onMount( async() => {
// using this for now cuz for some reason there is yet to be a way to fet another person's avatar // using this for now cuz for some reason there is yet to be a way to fet another person's avatar
if (primary) { if (primary) {
await fetch(`http://${Domain}:${Port}/api/v2/user/avatar`, {method: "GET"}) await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/avatar`, {method: "GET"})
.then(response => {return response.blob()}) .then(response => {return response.blob()})
.then(data => { .then(data => {
const url = URL.createObjectURL(data); const url = URL.createObjectURL(data);
@@ -43,7 +43,7 @@
let index = 0, interval = 1000; let index = 0, interval = 1000;
const rand = (min, max) => const rand = (min, max) =>
Math.floor(Math.random() * (max - min + 1)) + min; Math.floor(Math.random() * (max - min + 1)) + min;
// it's unhappy that "star" isn't typeset, no idea what to do about it... // it's unhappy that "star" isn't typeset, no idea what to do about it...
@@ -65,7 +65,7 @@
for (let i = 0; i < 3; i++) { for (let i = 0; i < 3; i++) {
setTimeout(() => { setTimeout(() => {
animate(stars[i]); animate(stars[i]);
setInterval(() => animate(stars[i]), 1000); setInterval(() => animate(stars[i]), 1000);
}, index++ * (interval / 3)) }, index++ * (interval / 3))
} }
@@ -80,7 +80,7 @@
<!-- <img class="icon" src="{user.image_url}" alt="default user icon"> --> <!-- <img class="icon" src="{user.image_url}" alt="default user icon"> -->
<img class="avatar" src="{avatar}" alt="default user icon"> <img class="avatar" src="{avatar}" alt="default user icon">
<div class="username">{user.username}</div> <div class="username">{user.username}</div>
<div class="rank">Rank: <div class="rank">Rank:
<span class="glitter"> <span class="glitter">
<span bind:this={stars[0]} class="glitter-star"> <span bind:this={stars[0]} class="glitter-star">
<svg viewBox="0 0 512 512"> <svg viewBox="0 0 512 512">
@@ -166,7 +166,7 @@
/* Glittery Star Stuff */ /* Glittery Star Stuff */
:root { :root {
--purple: rgb(123, 31, 162); --purple: rgb(123, 31, 162);
--violet: rgb(103, 58, 183); --violet: rgb(103, 58, 183);
--pink: rgb(244, 143, 177); --pink: rgb(244, 143, 177);
@@ -177,7 +177,7 @@
from { from {
background-position: 0% center; background-position: 0% center;
} }
to { to {
background-position: -200% center; background-position: -200% center;
} }
@@ -187,7 +187,7 @@
from, to { from, to {
transform: scale(0); transform: scale(0);
} }
50% { 50% {
transform: scale(1); transform: scale(1);
} }
@@ -197,7 +197,7 @@
from { from {
transform: rotate(0deg); transform: rotate(0deg);
} }
to { to {
transform: rotate(180deg); transform: rotate(180deg);
} }
@@ -242,7 +242,7 @@
var(--purple) var(--purple)
); );
background-size: 200%; background-size: 200%;
/* Keep these for Safari and chrome */ /* Keep these for Safari and chrome */
-webkit-background-clip: text; -webkit-background-clip: text;
-webkit-text-fill-color: transparent; -webkit-text-fill-color: transparent;

View File

@@ -1,14 +1,14 @@
<script lang="ts"> <script lang="ts">
import { push } from "svelte-spa-router"; import { push } from "svelte-spa-router";
import { location } from 'svelte-spa-router'; import { location } from 'svelte-spa-router';
import { Domain, Port } from "../Constantes.svelte";
import active from 'svelte-spa-router/active' import active from 'svelte-spa-router/active'
// or i could leave them all and not display if they're active? // or i could leave them all and not display if they're active?
let handleClickLogout = async () => { let handleClickLogout = async () => {
await fetch(`http://${Domain}:${Port}/api/v2/auth/logout`, { await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/auth/logout`, {
method: 'POST', method: 'POST',
}) })
// .then(resp => resp.json) // .then(resp => resp.json)
@@ -25,8 +25,8 @@
<img src="/img/potato_logo.png" alt="Potato Pong Logo" on:click={() => (push('/'))}> <img src="/img/potato_logo.png" alt="Potato Pong Logo" on:click={() => (push('/'))}>
<h1>Potato Pong</h1> <h1>Potato Pong</h1>
<nav> <nav>
<button on:click={() => (push('/game'))}>Game</button> <button on:click={() => (push('/game'))}>Play</button>
<button on:click={() => (push('/matchlist'))}>Match List</button> <button on:click={() => (push('/spectator'))}>Spectate</button>
<button on:click={() => (push('/ranking'))}>Ranking</button> <button on:click={() => (push('/ranking'))}>Ranking</button>
{#if $location !== '/profile'} {#if $location !== '/profile'}
<button on:click={() => (push('/profile'))}>My Profile</button> <button on:click={() => (push('/profile'))}>My Profile</button>

View File

@@ -1,15 +1,40 @@
<script lang="ts"> <script lang="ts">
import { onMount, onDestroy } from "svelte";
import { MatchOptions } from "../pages/game/client/pongSpectator";
export let match: { export let match: {
id: string, gameServerIdOfTheMatch: string,
gameOptions: MatchOptions,
playerOneUsername: string, playerOneUsername: string,
playerTwoUsername: string playerTwoUsername: string
}; };
let matchOptionsString = "";
onMount( async() => {
if (match.gameOptions === MatchOptions.noOption) {
matchOptionsString = "standard";
}
else {
if (match.gameOptions & MatchOptions.multiBalls) {
matchOptionsString += "multi balls";
}
if (match.gameOptions & MatchOptions.movingWalls) {
if (matchOptionsString) { matchOptionsString += ", "; }
matchOptionsString += "moving walls";
}
}
})
</script> </script>
<!-- --> <!-- -->
<li> <li>
{match.id} "{match.playerOneUsername}" VS "{match.playerTwoUsername}" <button on:click>
"{match.playerOneUsername}" VS "{match.playerTwoUsername}"
<br/> [{matchOptionsString}]
</button>
</li> </li>

View File

@@ -2,14 +2,13 @@
<script lang="ts"> <script lang="ts">
import Layouts from './Chat_layouts.svelte'; import Layouts from './Chat_layouts.svelte';
import { Domain, PortIo } from "../../Constantes.svelte";
export let color = "transparent"; export let color = "transparent";
/* web sockets with socket.io /* web sockets with socket.io
*/ */
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import io from 'socket.io-client'; import io from 'socket.io-client';
const socket = io(`http://${Domain}:${PortIo}`, { const socket = io(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}`, {
path: '/chat' path: '/chat'
}); });
onMount(async => { onMount(async => {

View File

@@ -7,7 +7,7 @@ import { wrap } from 'svelte-spa-router/wrap'
import TestPage from '../pages/TmpTestPage.svelte'; import TestPage from '../pages/TmpTestPage.svelte';
import Game from '../pages/game/Game.svelte'; import Game from '../pages/game/Game.svelte';
import Ranking from '../pages/game/Ranking.svelte'; import Ranking from '../pages/game/Ranking.svelte';
import SpectatorMatchList from '../pages/SpectatorMatchList.svelte'; import GameSpectator from '../pages/game/GameSpectator.svelte';
@@ -15,7 +15,7 @@ export const primaryRoutes = {
'/': SplashPage, '/': SplashPage,
'/2fa': TwoFactorAuthentication, '/2fa': TwoFactorAuthentication,
'/game': Game, '/game': Game,
'/matchlist': SpectatorMatchList, '/spectator': GameSpectator,
'/ranking' : Ranking, '/ranking' : Ranking,
'/profile': wrap({ '/profile': wrap({
component: ProfilePage, component: ProfilePage,