pull fixed conflicts
This commit is contained in:
@@ -94,10 +94,15 @@ async function clientAnnounceListener(this: WebSocket, data: string)
|
|||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify(body)
|
body: JSON.stringify(body)
|
||||||
});
|
})
|
||||||
if (!response.ok)
|
.catch(error => console.log("ERROR : " + error));
|
||||||
|
if (!response || !response.ok)
|
||||||
{
|
{
|
||||||
this.send(JSON.stringify( new ev.EventError((await response.json()).message) ));
|
let errMessage = "validate token error";
|
||||||
|
if (response) {
|
||||||
|
errMessage = (await response.json()).message;
|
||||||
|
}
|
||||||
|
this.send(JSON.stringify( new ev.EventError(errMessage) ));
|
||||||
clientTerminate(clientsMap.get(this.id));
|
clientTerminate(clientsMap.get(this.id));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -154,6 +159,8 @@ function publicMatchmaking(player: ClientPlayer)
|
|||||||
|
|
||||||
const compatiblePlayers: ClientPlayer[] = [];
|
const compatiblePlayers: ClientPlayer[] = [];
|
||||||
compatiblePlayers.push(player);
|
compatiblePlayers.push(player);
|
||||||
|
|
||||||
|
/* // Replace with this code to enable the possibility to play against self
|
||||||
for (const [id, client] of matchmakingMap)
|
for (const [id, client] of matchmakingMap)
|
||||||
{
|
{
|
||||||
if (client.matchOptions === matchOptions)
|
if (client.matchOptions === matchOptions)
|
||||||
@@ -163,10 +170,9 @@ function publicMatchmaking(player: ClientPlayer)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} */
|
||||||
|
|
||||||
// TODO: Replace with this code to disable the possibility to play against self
|
for (const [id, client] of matchmakingMap)
|
||||||
/* for (const [id, client] of matchmakingMap)
|
|
||||||
{
|
{
|
||||||
if (client.matchOptions === matchOptions && client.username !== player.username)
|
if (client.matchOptions === matchOptions && client.username !== player.username)
|
||||||
{
|
{
|
||||||
@@ -175,7 +181,7 @@ function publicMatchmaking(player: ClientPlayer)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} */
|
}
|
||||||
|
|
||||||
if (compatiblePlayers.length >= minPlayersNumber) {
|
if (compatiblePlayers.length >= minPlayersNumber) {
|
||||||
compatiblePlayers.forEach((client) => {
|
compatiblePlayers.forEach((client) => {
|
||||||
@@ -231,7 +237,6 @@ function privateMatchmaking(player: ClientPlayer)
|
|||||||
token : player.token
|
token : player.token
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.then(x => x.json())
|
|
||||||
.catch(error => console.log("ERROR : " + error));
|
.catch(error => console.log("ERROR : " + error));
|
||||||
clientTerminate(player);
|
clientTerminate(player);
|
||||||
}
|
}
|
||||||
@@ -253,17 +258,25 @@ function createGameSession(playersArr: ClientPlayer[], matchOptions: en.MatchOpt
|
|||||||
client.socket.once("message", playerReadyConfirmationListener);
|
client.socket.once("message", playerReadyConfirmationListener);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let gameSessionPlayersIterator = gameSession.playersMap.values();
|
||||||
|
const eventMatchmakingComplete = new ev.EventMatchmakingComplete(
|
||||||
|
(<ClientPlayer>gameSessionPlayersIterator.next().value).username,
|
||||||
|
(<ClientPlayer>gameSessionPlayersIterator.next().value).username
|
||||||
|
);
|
||||||
|
|
||||||
// REFACTORING: Not pretty, hardcoded two players.
|
// REFACTORING: Not pretty, hardcoded two players.
|
||||||
// Could be done in gameSession maybe ?
|
// Could be done in gameSession maybe ?
|
||||||
const gameSessionPlayersIterator = gameSession.playersMap.values();
|
gameSessionPlayersIterator = gameSession.playersMap.values();
|
||||||
let player: ClientPlayer;
|
let player: ClientPlayer;
|
||||||
player = (<ClientPlayer>gameSessionPlayersIterator.next().value);
|
player = (<ClientPlayer>gameSessionPlayersIterator.next().value);
|
||||||
player.racket = gameSession.components.playerLeft;
|
player.racket = gameSession.components.playerLeft;
|
||||||
player.socket.send(JSON.stringify( new ev.EventMatchmakingComplete(en.PlayerSide.left) ));
|
eventMatchmakingComplete.side = en.PlayerSide.left;
|
||||||
|
player.socket.send(JSON.stringify( eventMatchmakingComplete ));
|
||||||
|
|
||||||
player = (<ClientPlayer>gameSessionPlayersIterator.next().value);
|
player = (<ClientPlayer>gameSessionPlayersIterator.next().value);
|
||||||
player.racket = gameSession.components.playerRight;
|
player.racket = gameSession.components.playerRight;
|
||||||
player.socket.send(JSON.stringify( new ev.EventMatchmakingComplete(en.PlayerSide.right) ));
|
eventMatchmakingComplete.side = en.PlayerSide.right;
|
||||||
|
player.socket.send(JSON.stringify( eventMatchmakingComplete ));
|
||||||
// REFACTORING
|
// REFACTORING
|
||||||
|
|
||||||
setTimeout(function abortMatch() {
|
setTimeout(function abortMatch() {
|
||||||
|
|||||||
@@ -18,10 +18,13 @@ export class EventAssignId extends ServerEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class EventMatchmakingComplete extends ServerEvent {
|
export class EventMatchmakingComplete extends ServerEvent {
|
||||||
side: en.PlayerSide;
|
side: en.PlayerSide = en.PlayerSide.noSide;
|
||||||
constructor(side: en.PlayerSide) {
|
playerOneUsername: string;
|
||||||
|
playerTwoUsername: string;
|
||||||
|
constructor(playerOneUsername: string, playerTwoUsername: string) {
|
||||||
super(en.EventTypes.matchmakingComplete);
|
super(en.EventTypes.matchmakingComplete);
|
||||||
this.side = side;
|
this.playerOneUsername = playerOneUsername;
|
||||||
|
this.playerTwoUsername = playerTwoUsername;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -92,7 +92,8 @@ export class GameService {
|
|||||||
}
|
}
|
||||||
this.userRepository.save(user);
|
this.userRepository.save(user);
|
||||||
}
|
}
|
||||||
if (grantTicketDto.isGameIsWithInvitation === true && user.status !== STATUS.IN_GAME)
|
// if (grantTicketDto.isGameIsWithInvitation === true && user.status !== STATUS.IN_GAME) // WIP: need to fix STATUS.IN_GAME
|
||||||
|
if (grantTicketDto.isGameIsWithInvitation === true)
|
||||||
{
|
{
|
||||||
const secondUser : Partial<User> = await this.userService.findOne(grantTicketDto.playerTwoUsername)
|
const secondUser : Partial<User> = await this.userService.findOne(grantTicketDto.playerTwoUsername)
|
||||||
if (!secondUser || secondUser.username === user.username)
|
if (!secondUser || secondUser.username === user.username)
|
||||||
@@ -104,17 +105,18 @@ export class GameService {
|
|||||||
tok.numberOfRegisteredUser = 0;
|
tok.numberOfRegisteredUser = 0;
|
||||||
tok.token = encryptedTextToReturn;
|
tok.token = encryptedTextToReturn;
|
||||||
this.tokenGameRepository.save(tok);
|
this.tokenGameRepository.save(tok);
|
||||||
this.userService.updateStatus(user.id, "In Pool")
|
this.userService.updateStatus(user.id, STATUS.IN_POOL)
|
||||||
return res.status(HttpStatus.OK).json({ token : encryptedTextToReturn });
|
return res.status(HttpStatus.OK).json({ token : encryptedTextToReturn });
|
||||||
}
|
}
|
||||||
else if (grantTicketDto.isGameIsWithInvitation === false && user.status !== STATUS.IN_GAME) {
|
// else if (grantTicketDto.isGameIsWithInvitation === false && user.status !== STATUS.IN_GAME) { // WIP: need to fix STATUS.IN_GAME
|
||||||
|
else if (grantTicketDto.isGameIsWithInvitation === false) {
|
||||||
const encryptedTextToReturn = await this.encryptToken(user.username + '_'
|
const encryptedTextToReturn = await this.encryptToken(user.username + '_'
|
||||||
+ grantTicketDto.gameOptions + '_' + grantTicketDto.isGameIsWithInvitation + '_' + new Date())
|
+ grantTicketDto.gameOptions + '_' + grantTicketDto.isGameIsWithInvitation + '_' + new Date())
|
||||||
const tok = this.tokenGameRepository.create(grantTicketDto);
|
const tok = this.tokenGameRepository.create(grantTicketDto);
|
||||||
tok.numberOfRegisteredUser = 0;
|
tok.numberOfRegisteredUser = 0;
|
||||||
tok.token = encryptedTextToReturn;
|
tok.token = encryptedTextToReturn;
|
||||||
this.tokenGameRepository.save(tok);
|
this.tokenGameRepository.save(tok);
|
||||||
this.userService.updateStatus(user.id, "In Pool")
|
this.userService.updateStatus(user.id, STATUS.IN_POOL)
|
||||||
return res.status(HttpStatus.OK).json({ token : encryptedTextToReturn });
|
return res.status(HttpStatus.OK).json({ token : encryptedTextToReturn });
|
||||||
}
|
}
|
||||||
return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({message : "Internal Server Error"});
|
return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({message : "Internal Server Error"});
|
||||||
@@ -140,13 +142,13 @@ export class GameService {
|
|||||||
const userOne : User = await this.userRepository.createQueryBuilder('user')
|
const userOne : User = await this.userRepository.createQueryBuilder('user')
|
||||||
.where("user.username = :username", {username : tokenGame.playerOneUsername})
|
.where("user.username = :username", {username : tokenGame.playerOneUsername})
|
||||||
.getOne();
|
.getOne();
|
||||||
this.userService.updateStatus(userOne.id, "In Game")
|
this.userService.updateStatus(userOne.id, STATUS.IN_GAME)
|
||||||
const userTwo : User = await this.userRepository.createQueryBuilder('user')
|
const userTwo : User = await this.userRepository.createQueryBuilder('user')
|
||||||
.where("user.username = :username", {username : tokenGame.playerTwoUsername})
|
.where("user.username = :username", {username : tokenGame.playerTwoUsername})
|
||||||
.getOne();
|
.getOne();
|
||||||
this.deleteToken(userOne)
|
this.deleteToken(userOne)
|
||||||
this.deleteToken(userTwo)
|
this.deleteToken(userTwo)
|
||||||
this.userService.updateStatus(userTwo.id, "In Game")
|
this.userService.updateStatus(userTwo.id, STATUS.IN_GAME)
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -166,7 +168,7 @@ export class GameService {
|
|||||||
const user : User = await this.userRepository.createQueryBuilder('user')
|
const user : User = await this.userRepository.createQueryBuilder('user')
|
||||||
.where("user.username = :username", {username : tokenGame.playerOneUsername})
|
.where("user.username = :username", {username : tokenGame.playerOneUsername})
|
||||||
.getOne();
|
.getOne();
|
||||||
this.userService.updateStatus(user.id, "In Game")
|
this.userService.updateStatus(user.id, STATUS.IN_GAME)
|
||||||
this.deleteToken(user)
|
this.deleteToken(user)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -196,7 +198,7 @@ export class GameService {
|
|||||||
|
|
||||||
async declineInvitation(user : User, token : string, @Res() res : Response)
|
async declineInvitation(user : User, token : string, @Res() res : Response)
|
||||||
{
|
{
|
||||||
if (user.status !== "Connected")
|
if (user.status !== STATUS.CONNECTED)
|
||||||
return res.status(HttpStatus.FORBIDDEN).json({message : "You must not be in game to decline an invitation"});
|
return res.status(HttpStatus.FORBIDDEN).json({message : "You must not be in game to decline an invitation"});
|
||||||
console.log("On décline l'invitation")
|
console.log("On décline l'invitation")
|
||||||
const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokengame')
|
const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokengame')
|
||||||
@@ -221,10 +223,10 @@ export class GameService {
|
|||||||
{
|
{
|
||||||
const playerOne = await this.userRepository.findOneBy({username : tokenGame.playerOneUsername})
|
const playerOne = await this.userRepository.findOneBy({username : tokenGame.playerOneUsername})
|
||||||
const playerTwo = await this.userRepository.findOneBy({username : tokenGame.playerTwoUsername})
|
const playerTwo = await this.userRepository.findOneBy({username : tokenGame.playerTwoUsername})
|
||||||
if (playerOne.status !== "Disconnected")
|
if (playerOne.status !== STATUS.DISCONNECTED)
|
||||||
this.userService.updateStatus(playerOne.id, "Connected")
|
this.userService.updateStatus(playerOne.id, STATUS.CONNECTED)
|
||||||
if (playerTwo.status !== "Disconnected")
|
if (playerTwo.status !== STATUS.DISCONNECTED)
|
||||||
this.userService.updateStatus(playerTwo.id, "Connected")
|
this.userService.updateStatus(playerTwo.id, STATUS.CONNECTED)
|
||||||
return this.tokenGameRepository.remove(tokenGame);
|
return this.tokenGameRepository.remove(tokenGame);
|
||||||
}
|
}
|
||||||
return new HttpException("Token not found !", HttpStatus.NOT_FOUND)
|
return new HttpException("Token not found !", HttpStatus.NOT_FOUND)
|
||||||
@@ -232,7 +234,7 @@ export class GameService {
|
|||||||
|
|
||||||
async acceptInvitation(user : User, token : string, @Res() res : Response)
|
async acceptInvitation(user : User, token : string, @Res() res : Response)
|
||||||
{
|
{
|
||||||
if (user.status !== "Connected")
|
if (user.status !== STATUS.CONNECTED)
|
||||||
return res.status(HttpStatus.FORBIDDEN).send("")
|
return res.status(HttpStatus.FORBIDDEN).send("")
|
||||||
const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokenGame')
|
const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokenGame')
|
||||||
.andWhere('tokenGame.playerTwoUsername = :playerTwoUsername', {playerTwoUsername : user.username})
|
.andWhere('tokenGame.playerTwoUsername = :playerTwoUsername', {playerTwoUsername : user.username})
|
||||||
@@ -294,8 +296,8 @@ export class GameService {
|
|||||||
this.userService.incrementVictories(playerOne.id)
|
this.userService.incrementVictories(playerOne.id)
|
||||||
this.userService.incrementDefeats(playerTwo.id)
|
this.userService.incrementDefeats(playerTwo.id)
|
||||||
}
|
}
|
||||||
this.userService.updateStatus(playerOne.id, "Connected")
|
this.userService.updateStatus(playerOne.id, STATUS.CONNECTED)
|
||||||
this.userService.updateStatus(playerTwo.id, "Connected")
|
this.userService.updateStatus(playerTwo.id, STATUS.CONNECTED)
|
||||||
return HttpStatus.OK
|
return HttpStatus.OK
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -1,9 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
// routing
|
import Router, { replace } from "svelte-spa-router";
|
||||||
// may not need {link} here
|
|
||||||
import Router, { link, replace } from "svelte-spa-router";
|
|
||||||
import { primaryRoutes } from "./routes/primaryRoutes.js";
|
import { primaryRoutes } from "./routes/primaryRoutes.js";
|
||||||
// import primaryRoutes from "./routes/primaryRoutes.svelte";
|
|
||||||
|
|
||||||
const conditionsFailed = (event) => {
|
const conditionsFailed = (event) => {
|
||||||
console.error('conditionsFailed event', event.detail);
|
console.error('conditionsFailed event', event.detail);
|
||||||
@@ -15,6 +12,5 @@
|
|||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- <h1>Testing</h1> -->
|
|
||||||
<Router routes={primaryRoutes} on:conditionsFailed={conditionsFailed}/>
|
<Router routes={primaryRoutes} on:conditionsFailed={conditionsFailed}/>
|
||||||
|
|
||||||
|
|||||||
@@ -4,14 +4,7 @@
|
|||||||
|
|
||||||
<h1>We are sorry!</h1>
|
<h1>We are sorry!</h1>
|
||||||
<p>This isn't a url that we use.</p>
|
<p>This isn't a url that we use.</p>
|
||||||
<!-- <img src="https://picsum.photos/id/685/800/400" alt="img"> -->
|
|
||||||
<p>Go home you're drunk.</p>
|
<p>Go home you're drunk.</p>
|
||||||
<a href="/" use:link>
|
<a href="/" use:link>
|
||||||
<h2>Take me home →</h2>
|
<h2>Take me home →</h2>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<style>
|
|
||||||
/* img {
|
|
||||||
width: 100%;
|
|
||||||
} */
|
|
||||||
</style>
|
|
||||||
@@ -74,7 +74,6 @@
|
|||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
} */
|
} */
|
||||||
|
|
||||||
|
|
||||||
header {
|
header {
|
||||||
/* didn't work... */
|
/* didn't work... */
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount, onDestroy } from "svelte";
|
import { onMount, onDestroy } from "svelte";
|
||||||
import Header from '../../pieces/Header.svelte';
|
|
||||||
import { fade, fly } from 'svelte/transition';
|
import { fade, fly } from 'svelte/transition';
|
||||||
|
|
||||||
|
import Header from '../../pieces/Header.svelte';
|
||||||
|
import { fetchAvatar } from "../../pieces/utils";
|
||||||
|
|
||||||
import * as pong from "./client/pong";
|
import * as pong from "./client/pong";
|
||||||
import { gameState } from "./client/ws";
|
import { gameState } from "./client/ws";
|
||||||
@@ -12,6 +13,9 @@
|
|||||||
let user;
|
let user;
|
||||||
let allUsers;
|
let allUsers;
|
||||||
|
|
||||||
|
let playerOneAvatar;
|
||||||
|
let playerTwoAvatar;
|
||||||
|
|
||||||
//Game's stuff
|
//Game's stuff
|
||||||
const options = new pong.InitOptions();
|
const options = new pong.InitOptions();
|
||||||
const gameAreaId = "game_area";
|
const gameAreaId = "game_area";
|
||||||
@@ -26,9 +30,10 @@
|
|||||||
let showWaitPage = false;
|
let showWaitPage = false;
|
||||||
|
|
||||||
let invitations = [];
|
let invitations = [];
|
||||||
|
|
||||||
let watchGameStateInterval;
|
let watchGameStateInterval;
|
||||||
const watchGameStateIntervalRate = 142;
|
const watchGameStateIntervalRate = 142;
|
||||||
|
let watchMatchStartInterval;
|
||||||
|
const watchMatchStartIntervalRate = 111;
|
||||||
|
|
||||||
onMount( async() => {
|
onMount( async() => {
|
||||||
user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`)
|
user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`)
|
||||||
@@ -39,6 +44,7 @@
|
|||||||
})
|
})
|
||||||
|
|
||||||
onDestroy( async() => {
|
onDestroy( async() => {
|
||||||
|
clearInterval(watchMatchStartInterval);
|
||||||
clearInterval(watchGameStateInterval);
|
clearInterval(watchGameStateInterval);
|
||||||
pong.destroy();
|
pong.destroy();
|
||||||
})
|
})
|
||||||
@@ -76,6 +82,7 @@
|
|||||||
showWaitPage = false;
|
showWaitPage = false;
|
||||||
if (response.ok && token)
|
if (response.ok && token)
|
||||||
{
|
{
|
||||||
|
watchMatchStartInterval = setInterval(watchMatchStart, watchMatchStartIntervalRate);
|
||||||
watchGameStateInterval = setInterval(watchGameState, watchGameStateIntervalRate);
|
watchGameStateInterval = setInterval(watchGameState, watchGameStateIntervalRate);
|
||||||
pong.init(matchOptions, options, gameAreaId, token);
|
pong.init(matchOptions, options, gameAreaId, token);
|
||||||
hiddenGame = false;
|
hiddenGame = false;
|
||||||
@@ -106,6 +113,7 @@
|
|||||||
console.log(invitation);
|
console.log(invitation);
|
||||||
if (invitation.token)
|
if (invitation.token)
|
||||||
{
|
{
|
||||||
|
watchMatchStartInterval = setInterval(watchMatchStart, watchMatchStartIntervalRate);
|
||||||
watchGameStateInterval = setInterval(watchGameState, watchGameStateIntervalRate);
|
watchGameStateInterval = setInterval(watchGameState, watchGameStateIntervalRate);
|
||||||
options.playerOneUsername = invitation.playerOneUsername;
|
options.playerOneUsername = invitation.playerOneUsername;
|
||||||
options.playerTwoUsername = invitation.playerTwoUsername;
|
options.playerTwoUsername = invitation.playerTwoUsername;
|
||||||
@@ -117,16 +125,24 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function watchMatchStart()
|
||||||
|
{
|
||||||
|
if (gameState.matchStarted)
|
||||||
|
{
|
||||||
|
clearInterval(watchMatchStartInterval);
|
||||||
|
playerOneAvatar = await fetchAvatar(gameState.playerOneUsername);
|
||||||
|
playerTwoAvatar = await fetchAvatar(gameState.playerTwoUsername);
|
||||||
|
gameState.matchStarted = gameState.matchStarted; // trigger Svelte reactivity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const watchGameState = () => {
|
const watchGameState = () => {
|
||||||
console.log("watchGameState");
|
console.log("watchGameState");
|
||||||
if (gameState) { // trigger Svelte reactivity
|
|
||||||
gameState.matchStarted = gameState.matchStarted;
|
|
||||||
gameState.matchEnded = gameState.matchEnded;
|
|
||||||
gameState.matchAborted = gameState.matchAborted;
|
|
||||||
}
|
|
||||||
if (gameState.matchAborted || gameState.matchEnded)
|
if (gameState.matchAborted || gameState.matchEnded)
|
||||||
{
|
{
|
||||||
clearInterval(watchGameStateInterval);
|
clearInterval(watchGameStateInterval);
|
||||||
|
gameState.matchEnded = gameState.matchEnded; // trigger Svelte reactivity
|
||||||
|
gameState.matchAborted = gameState.matchAborted; // trigger Svelte reactivity
|
||||||
console.log("watchGameState, end");
|
console.log("watchGameState, end");
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
resetPage();
|
resetPage();
|
||||||
@@ -176,6 +192,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function leaveMatch() {
|
function leaveMatch() {
|
||||||
|
clearInterval(watchMatchStartInterval);
|
||||||
clearInterval(watchGameStateInterval);
|
clearInterval(watchGameStateInterval);
|
||||||
resetPage();
|
resetPage();
|
||||||
};
|
};
|
||||||
@@ -213,6 +230,14 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if !hiddenGame}
|
{#if !hiddenGame}
|
||||||
|
{#if gameState.matchStarted}
|
||||||
|
<div class="div_game">
|
||||||
|
<img class="avatar" src="{playerOneAvatar}" alt="player one avatar">
|
||||||
|
'{gameState.playerOneUsername}' VS '{gameState.playerTwoUsername}'
|
||||||
|
<img class="avatar" src="{playerTwoAvatar}" alt="player two avatar">
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
{#if gameState.matchStarted && !gameState.matchEnded}
|
{#if gameState.matchStarted && !gameState.matchEnded}
|
||||||
<div class="div_game">
|
<div class="div_game">
|
||||||
<button class="pong_button" on:click={leaveMatch}>forfeit</button>
|
<button class="pong_button" on:click={leaveMatch}>forfeit</button>
|
||||||
@@ -356,5 +381,11 @@ canvas {
|
|||||||
font-size: x-large;
|
font-size: x-large;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
.avatar {
|
||||||
|
min-height: 100px;
|
||||||
|
min-width: 100px;
|
||||||
|
|
||||||
|
max-width: 100px;
|
||||||
|
max-height: 100px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount, onDestroy } from "svelte";
|
import { onMount, onDestroy } from "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 Header from '../../pieces/Header.svelte';
|
||||||
|
import MatchListElem from "../../pieces/MatchListElem.svelte";
|
||||||
|
import type { Match } from "../../pieces/Match";
|
||||||
|
import { fetchAvatar } from "../../pieces/utils";
|
||||||
|
|
||||||
import * as pongSpectator from "./client/pongSpectator";
|
import * as pongSpectator from "./client/pongSpectator";
|
||||||
import { gameState } from "./client/ws";
|
import { gameState } from "./client/ws";
|
||||||
@@ -13,14 +15,17 @@
|
|||||||
let user;
|
let user;
|
||||||
let allUsers;
|
let allUsers;
|
||||||
|
|
||||||
//Game's stuff client side only
|
let playerOneAvatar;
|
||||||
|
let playerTwoAvatar;
|
||||||
|
|
||||||
|
//Game's stuff
|
||||||
const gameAreaId = "game_area";
|
const gameAreaId = "game_area";
|
||||||
let sound = "off";
|
let sound = "off";
|
||||||
let matchList = [];
|
|
||||||
|
|
||||||
//html boolean for pages
|
//html boolean for pages
|
||||||
let hiddenGame = true;
|
let hiddenGame = true;
|
||||||
|
|
||||||
|
let matchList: Match[] = [];
|
||||||
let watchGameStateInterval;
|
let watchGameStateInterval;
|
||||||
const watchGameStateIntervalRate = 142;
|
const watchGameStateIntervalRate = 142;
|
||||||
|
|
||||||
@@ -39,22 +44,27 @@
|
|||||||
pongSpectator.destroy();
|
pongSpectator.destroy();
|
||||||
})
|
})
|
||||||
|
|
||||||
async function initGameSpectator(gameSessionId: string, matchOptions: pongSpectator.MatchOptions)
|
async function initGameSpectator(match: Match)
|
||||||
{
|
{
|
||||||
watchGameStateInterval = setInterval(watchGameState, watchGameStateIntervalRate);
|
watchGameStateInterval = setInterval(watchGameState, watchGameStateIntervalRate);
|
||||||
pongSpectator.init(matchOptions, sound, gameAreaId, gameSessionId);
|
pongSpectator.init(match.gameOptions, sound, gameAreaId, match.gameServerIdOfTheMatch);
|
||||||
|
|
||||||
|
// Users avatar
|
||||||
|
gameState.playerOneUsername = match.playerOneUsername;
|
||||||
|
gameState.playerTwoUsername = match.playerTwoUsername;
|
||||||
|
playerOneAvatar = await fetchAvatar(gameState.playerOneUsername);
|
||||||
|
playerTwoAvatar = await fetchAvatar(gameState.playerTwoUsername);
|
||||||
|
|
||||||
hiddenGame = false;
|
hiddenGame = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const watchGameState = () => {
|
const watchGameState = () => {
|
||||||
console.log("watchGameState")
|
console.log("watchGameState")
|
||||||
if (gameState) { // trigger Svelte reactivity
|
// gameState.matchStarted = gameState.matchStarted; // trigger Svelte reactivity
|
||||||
gameState.matchStarted = gameState.matchStarted;
|
|
||||||
gameState.matchEnded = gameState.matchEnded;
|
|
||||||
gameState.matchAborted = gameState.matchAborted;
|
|
||||||
}
|
|
||||||
if (gameState.matchAborted || gameState.matchEnded)
|
if (gameState.matchAborted || gameState.matchEnded)
|
||||||
{
|
{
|
||||||
|
gameState.matchEnded = gameState.matchEnded; // trigger Svelte reactivity
|
||||||
|
gameState.matchAborted = gameState.matchAborted; // trigger Svelte reactivity
|
||||||
clearInterval(watchGameStateInterval);
|
clearInterval(watchGameStateInterval);
|
||||||
console.log("watchGameState, end")
|
console.log("watchGameState, end")
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -80,7 +90,6 @@
|
|||||||
.then( x => x.json() );
|
.then( x => x.json() );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<!-- -->
|
<!-- -->
|
||||||
|
|
||||||
@@ -102,6 +111,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if !hiddenGame}
|
{#if !hiddenGame}
|
||||||
|
<div class="div_game">
|
||||||
|
<img class="avatar" src="{playerOneAvatar}" alt="player one avatar">
|
||||||
|
'{gameState.playerOneUsername}' VS '{gameState.playerTwoUsername}'
|
||||||
|
<img class="avatar" src="{playerTwoAvatar}" alt="player two avatar">
|
||||||
|
</div>
|
||||||
|
|
||||||
{#if !gameState.matchEnded}
|
{#if !gameState.matchEnded}
|
||||||
<div class="div_game">
|
<div class="div_game">
|
||||||
<button class="pong_button" on:click={leaveMatch}>leave</button>
|
<button class="pong_button" on:click={leaveMatch}>leave</button>
|
||||||
@@ -127,7 +142,7 @@
|
|||||||
{#if matchList.length !== 0}
|
{#if matchList.length !== 0}
|
||||||
<menu id="match_list">
|
<menu id="match_list">
|
||||||
{#each matchList as match}
|
{#each matchList as match}
|
||||||
<MatchListElem match={match} on:click={(e) => initGameSpectator(match.gameServerIdOfTheMatch, match.gameOptions)} />
|
<MatchListElem match={match} on:click={(e) => initGameSpectator(match)} />
|
||||||
{/each}
|
{/each}
|
||||||
</menu>
|
</menu>
|
||||||
{:else}
|
{:else}
|
||||||
@@ -195,10 +210,15 @@ canvas {
|
|||||||
font-size: x-large;
|
font-size: x-large;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#match_list {
|
#match_list {
|
||||||
font-family: 'Courier New', Courier, monospace;
|
font-family: 'Courier New', Courier, monospace;
|
||||||
font-size: large;
|
font-size: large;
|
||||||
}
|
}
|
||||||
|
.avatar {
|
||||||
|
min-height: 100px;
|
||||||
|
min-width: 100px;
|
||||||
|
|
||||||
|
max-width: 100px;
|
||||||
|
max-height: 100px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ 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, resetGameState } from "./ws.js";
|
import { socket, gameState } 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";
|
||||||
|
|
||||||
@@ -57,5 +57,5 @@ export function destroyBase()
|
|||||||
}
|
}
|
||||||
setGc(null);
|
setGc(null);
|
||||||
setMatchOptions(null);
|
setMatchOptions(null);
|
||||||
resetGameState();
|
gameState.resetGameState();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import { initBase, destroyBase, computeMatchOptions } from "./init.js";
|
|||||||
export { computeMatchOptions } from "./init.js";
|
export { computeMatchOptions } from "./init.js";
|
||||||
export { MatchOptions } from "../shared_js/enums.js"
|
export { MatchOptions } from "../shared_js/enums.js"
|
||||||
|
|
||||||
/* 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 { setStartFunction } from "./global.js"
|
import { setStartFunction } from "./global.js"
|
||||||
|
|
||||||
|
|||||||
@@ -10,16 +10,22 @@ import { muteFlag, 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 const gameState = {
|
class GameState {
|
||||||
matchStarted: false,
|
matchStarted: boolean;
|
||||||
matchEnded: false,
|
matchEnded: boolean;
|
||||||
matchAborted: false
|
matchAborted: boolean;
|
||||||
}
|
playerOneUsername: string;
|
||||||
|
playerTwoUsername: string;
|
||||||
export function resetGameState() {
|
constructor() {
|
||||||
gameState.matchStarted = false;
|
this.resetGameState();
|
||||||
gameState.matchEnded = false;
|
}
|
||||||
gameState.matchAborted = false;
|
resetGameState() {
|
||||||
|
this.matchStarted = false;
|
||||||
|
this.matchEnded = false;
|
||||||
|
this.matchAborted = false;
|
||||||
|
this.playerOneUsername = "";
|
||||||
|
this.playerTwoUsername = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClientInfo {
|
class ClientInfo {
|
||||||
@@ -39,6 +45,7 @@ class ClientInfoSpectator {
|
|||||||
|
|
||||||
const wsUrl = "ws://" + process.env.WEBSITE_HOST + ":" + process.env.WEBSITE_PORT + "/pong";
|
const wsUrl = "ws://" + process.env.WEBSITE_HOST + ":" + process.env.WEBSITE_PORT + "/pong";
|
||||||
export let socket: WebSocket;
|
export let socket: WebSocket;
|
||||||
|
export const gameState = new GameState();
|
||||||
export const clientInfo = new ClientInfo();
|
export const clientInfo = new ClientInfo();
|
||||||
export const clientInfoSpectator = new ClientInfoSpectator(); // WIP, could refactor this
|
export const clientInfoSpectator = new ClientInfoSpectator(); // WIP, could refactor this
|
||||||
|
|
||||||
@@ -85,6 +92,8 @@ function preMatchListener(this: WebSocket, event: MessageEvent)
|
|||||||
break;
|
break;
|
||||||
case en.EventTypes.matchmakingComplete:
|
case en.EventTypes.matchmakingComplete:
|
||||||
clientInfo.side = (<ev.EventMatchmakingComplete>data).side;
|
clientInfo.side = (<ev.EventMatchmakingComplete>data).side;
|
||||||
|
gameState.playerOneUsername = (<ev.EventMatchmakingComplete>data).playerOneUsername;
|
||||||
|
gameState.playerTwoUsername = (<ev.EventMatchmakingComplete>data).playerTwoUsername;
|
||||||
if (clientInfo.side === en.PlayerSide.left)
|
if (clientInfo.side === en.PlayerSide.left)
|
||||||
{
|
{
|
||||||
clientInfo.racket = gc.playerLeft;
|
clientInfo.racket = gc.playerLeft;
|
||||||
|
|||||||
@@ -18,10 +18,13 @@ export class EventAssignId extends ServerEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class EventMatchmakingComplete extends ServerEvent {
|
export class EventMatchmakingComplete extends ServerEvent {
|
||||||
side: en.PlayerSide;
|
side: en.PlayerSide = en.PlayerSide.noSide;
|
||||||
constructor(side: en.PlayerSide) {
|
playerOneUsername: string;
|
||||||
|
playerTwoUsername: string;
|
||||||
|
constructor(playerOneUsername: string, playerTwoUsername: string) {
|
||||||
super(en.EventTypes.matchmakingComplete);
|
super(en.EventTypes.matchmakingComplete);
|
||||||
this.side = side;
|
this.playerOneUsername = playerOneUsername;
|
||||||
|
this.playerTwoUsername = playerTwoUsername;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 { push } from 'svelte-spa-router';
|
||||||
|
|
||||||
import Chat from '../../pieces/chat/Chat.svelte';
|
import Chat from '../../pieces/chat/Chat.svelte';
|
||||||
|
|
||||||
@@ -19,13 +19,11 @@
|
|||||||
|
|
||||||
<Chat color="bisque"/>
|
<Chat color="bisque"/>
|
||||||
|
|
||||||
<!-- is this if excessive? -->
|
|
||||||
<div class="outer">
|
<div class="outer">
|
||||||
<!-- OHHHH i could use #await instead of if and have an nice loading page! -->
|
|
||||||
{#if user !== undefined}
|
{#if user !== undefined}
|
||||||
<GenerateUserDisplay user={user} primary={true}/>
|
<GenerateUserDisplay user={user}/>
|
||||||
|
<button on:click={() => (push('/profile/settings'))}>Profile Settings</button>
|
||||||
{:else}
|
{:else}
|
||||||
<!-- might be unnecessary since you can't access the page without fetching the user -->
|
|
||||||
<h2>Sorry</h2>
|
<h2>Sorry</h2>
|
||||||
<div>Failed to load current</div>
|
<div>Failed to load current</div>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -36,140 +34,7 @@
|
|||||||
div.outer{
|
div.outer{
|
||||||
max-width: 960px;
|
max-width: 960px;
|
||||||
margin: 40px auto;
|
margin: 40px auto;
|
||||||
}
|
|
||||||
|
|
||||||
/* The main part */
|
|
||||||
main{
|
|
||||||
max-width: 960px;
|
|
||||||
margin: 40px auto;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Normal CSS stuff */
|
|
||||||
.avatar{
|
|
||||||
max-width: 150px;
|
|
||||||
/* padding: 5px; */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The variable rich section */
|
|
||||||
section.main-stats{
|
|
||||||
max-width: 600px;
|
|
||||||
margin: 40px auto;
|
|
||||||
text-align: center;
|
|
||||||
/* i think i want to use a grid? */
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(3, 1fr);
|
|
||||||
/* not sure about this, maybe top should be larger? */
|
|
||||||
grid-template-rows: repeat(3, 1fr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the stuff in the grid*/
|
|
||||||
section.main-stats h4{
|
|
||||||
grid-column: 1 / span 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.username{
|
|
||||||
font-size: 1.5em;
|
|
||||||
font-weight: bold;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.rank {
|
|
||||||
/* color: black; */
|
|
||||||
font-size: 1.2em;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Glittery Star Stuff */
|
|
||||||
|
|
||||||
|
|
||||||
:root {
|
|
||||||
--purple: rgb(123, 31, 162);
|
|
||||||
--violet: rgb(103, 58, 183);
|
|
||||||
--pink: rgb(244, 143, 177);
|
|
||||||
/* make shit gold? */
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes background-pan {
|
|
||||||
from {
|
|
||||||
background-position: 0% center;
|
|
||||||
}
|
|
||||||
|
|
||||||
to {
|
|
||||||
background-position: -200% center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes scale {
|
|
||||||
from, to {
|
|
||||||
transform: scale(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
50% {
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes rotate {
|
|
||||||
from {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
to {
|
|
||||||
transform: rotate(180deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
div > .glitter {
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
div > .glitter > .glitter-star {
|
|
||||||
--size: clamp(20px, 1.5vw, 30px);
|
|
||||||
|
|
||||||
animation: scale 700ms ease forwards;
|
|
||||||
display: block;
|
|
||||||
height: var(--size);
|
|
||||||
left: var(--star-left);
|
|
||||||
position: absolute;
|
|
||||||
top: var(--star-top);
|
|
||||||
width: var(--size);
|
|
||||||
}
|
|
||||||
|
|
||||||
div > .glitter > .glitter-star > svg {
|
|
||||||
animation: rotate 1000ms linear infinite;
|
|
||||||
display: block;
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
|
|
||||||
div > .glitter > .glitter-star > svg > path {
|
|
||||||
fill: var(--violet);
|
|
||||||
}
|
|
||||||
|
|
||||||
div > .glitter > .glitter-text {
|
|
||||||
animation: background-pan 3s linear infinite;
|
|
||||||
/* background-image: linear-gradient( */
|
|
||||||
background: linear-gradient(
|
|
||||||
to right,
|
|
||||||
var(--purple),
|
|
||||||
var(--violet),
|
|
||||||
var(--pink),
|
|
||||||
var(--purple)
|
|
||||||
);
|
|
||||||
background-size: 200%;
|
|
||||||
|
|
||||||
/* Keep these for Safari and chrome */
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
-webkit-text-fill-color: transparent;
|
|
||||||
|
|
||||||
/* These are for Firefox */
|
|
||||||
background-clip: text;
|
|
||||||
color: transparent;
|
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -177,7 +177,7 @@
|
|||||||
console.log('Block a non friend user, their username')
|
console.log('Block a non friend user, their username')
|
||||||
console.log(aUsername)
|
console.log(aUsername)
|
||||||
|
|
||||||
sentFriendRequest = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/relations`, {
|
let sentFriendRequest = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/relations`, {
|
||||||
method : "POST",
|
method : "POST",
|
||||||
headers: { 'Content-Type': 'application/json'},
|
headers: { 'Content-Type': 'application/json'},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
|
||||||
import Header from "../../pieces/Header.svelte";
|
import Header from "../../pieces/Header.svelte";
|
||||||
import Router from "svelte-spa-router";
|
import Router from "svelte-spa-router";
|
||||||
import { profileRoutes, prefix } from "../../routes/profileRoutes.js";
|
import { profileRoutes, prefix } from "../../routes/profileRoutes.js";
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
import { push } from 'svelte-spa-router';
|
import { push } from 'svelte-spa-router';
|
||||||
|
|
||||||
import Button from '../../pieces/Button.svelte';
|
import Button from '../../pieces/Button.svelte';
|
||||||
|
import { fetchAvatar } from "../../pieces/utils";
|
||||||
|
|
||||||
let user;
|
let user;
|
||||||
let avatar, newAvatar;
|
let avatar, newAvatar;
|
||||||
@@ -26,29 +27,10 @@
|
|||||||
}
|
}
|
||||||
// i don't unerstand why this is necessary but it really doesn't like it otherwise
|
// i don't unerstand why this is necessary but it really doesn't like it otherwise
|
||||||
nameTmp = user.username;
|
nameTmp = user.username;
|
||||||
console.log(user.username)
|
|
||||||
|
|
||||||
set.tfa = user.isEnabledTwoFactorAuth;
|
set.tfa = user.isEnabledTwoFactorAuth;
|
||||||
|
|
||||||
// tmp
|
avatar = await fetchAvatar(user.username);
|
||||||
// console.log('this is what is in the avatar before fetch')
|
|
||||||
// console.log(avatar)
|
|
||||||
|
|
||||||
await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/avatar`, {method: "GET"})
|
|
||||||
.then(response => {return response.blob()})
|
|
||||||
.then(data => {
|
|
||||||
const url = URL.createObjectURL(data);
|
|
||||||
avatar = url;
|
|
||||||
})
|
|
||||||
.catch(() => errors.avatar = 'Sorry your avatar could not be loaded' );
|
|
||||||
|
|
||||||
// .then(() => errors.avatar = '' ) // unnecessary i think cuz in on mount...
|
|
||||||
|
|
||||||
// tmp
|
|
||||||
// console.log('this is what is in the avatar')
|
|
||||||
// console.log(avatar)
|
|
||||||
// console.log('this is what is in the NEW Avatar')
|
|
||||||
// console.log(newAvatar)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const settingsHandler = async() => {
|
const settingsHandler = async() => {
|
||||||
@@ -100,7 +82,7 @@
|
|||||||
const data = new FormData();
|
const data = new FormData();
|
||||||
data.append("file", newAvatar[0]);
|
data.append("file", newAvatar[0]);
|
||||||
|
|
||||||
// tmp
|
// tmp
|
||||||
console.log(data);
|
console.log(data);
|
||||||
|
|
||||||
const responseWhenChangeAvatar = fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/avatar`,
|
const responseWhenChangeAvatar = fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/avatar`,
|
||||||
@@ -117,13 +99,7 @@
|
|||||||
errors.avatar = responseFromServer.statusText;
|
errors.avatar = responseFromServer.statusText;
|
||||||
}
|
}
|
||||||
|
|
||||||
await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/avatar`, {method: "GET"})
|
avatar = await fetchAvatar(user.username);
|
||||||
.then(response => {return response.blob()})
|
|
||||||
.then(data => {
|
|
||||||
const url = URL.createObjectURL(data);
|
|
||||||
avatar = url;
|
|
||||||
})
|
|
||||||
.catch(() => errors.avatar = 'Sorry your avatar could not be loaded' );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -39,8 +39,7 @@
|
|||||||
|
|
||||||
|
|
||||||
{#if user !== undefined}
|
{#if user !== undefined}
|
||||||
<GenerateUserDisplay user={user} primary={false}/>
|
<GenerateUserDisplay user={user}/>
|
||||||
<!-- <GenerateUserDisplay user={user} primary={true}/> -->
|
|
||||||
{:else}
|
{:else}
|
||||||
<h2>Sorry</h2>
|
<h2>Sorry</h2>
|
||||||
<div>Failed to load user {aUsername}</div>
|
<div>Failed to load user {aUsername}</div>
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
|
import { fetchAvatar } from "./utils";
|
||||||
|
|
||||||
export let user;
|
export let user;
|
||||||
export let primary; // kinda useless, not sure what i was going for... Might be userful after all
|
|
||||||
let rank = '';
|
let rank = '';
|
||||||
let avatar;
|
let avatar;
|
||||||
// avatar needs to be updated!!!
|
// avatar needs to be updated!!!
|
||||||
@@ -14,25 +14,7 @@
|
|||||||
|
|
||||||
onMount( async() => {
|
onMount( async() => {
|
||||||
// console.log('Generate User Display, on mount ' + user.username)
|
// console.log('Generate User Display, on mount ' + user.username)
|
||||||
if (primary) {
|
avatar = await fetchAvatar(user.username);
|
||||||
await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/avatar`, {method: "GET"})
|
|
||||||
.then(response => {return response.blob()})
|
|
||||||
.then(data => {
|
|
||||||
const url = URL.createObjectURL(data);
|
|
||||||
avatar = url;
|
|
||||||
})
|
|
||||||
.catch(() => errors.avatar = 'Sorry your avatar could not be loaded' );
|
|
||||||
// console.log('avatar: ')
|
|
||||||
// console.log(avatar)
|
|
||||||
} else {
|
|
||||||
await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/avatar?username=${user.username}`, {method: "GET"})
|
|
||||||
.then(response => {return response.blob()})
|
|
||||||
.then(data => {
|
|
||||||
const url = URL.createObjectURL(data);
|
|
||||||
avatar = url;
|
|
||||||
})
|
|
||||||
.catch(() => errors.avatar = 'Sorry your avatar could not be loaded' );
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,11 @@
|
|||||||
import { location } from 'svelte-spa-router';
|
import { location } from 'svelte-spa-router';
|
||||||
|
|
||||||
|
|
||||||
|
// no need, it's just for links
|
||||||
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?
|
||||||
|
|
||||||
|
$: current = $location;
|
||||||
|
|
||||||
let handleClickLogout = async () => {
|
let handleClickLogout = async () => {
|
||||||
await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/auth/logout`, {
|
await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/auth/logout`, {
|
||||||
@@ -23,15 +25,12 @@
|
|||||||
<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'))}>Play</button>
|
<button class:selected="{current === '/game'}" on:click={() => (push('/game'))}>Play</button>
|
||||||
<button on:click={() => (push('/spectator'))}>Spectate</button>
|
<button class:selected="{current === '/spectator'}" on:click={() => (push('/spectator'))}>Spectate</button>
|
||||||
<button on:click={() => (push('/ranking'))}>Ranking</button>
|
<button class:selected="{current === '/ranking'}" on:click={() => (push('/ranking'))}>Ranking</button>
|
||||||
{#if $location !== '/profile'}
|
<button class:selected="{current === '/profile'}" on:click={() => (push('/profile'))}>My Profile</button>
|
||||||
<button on:click={() => (push('/profile'))}>My Profile</button>
|
<!-- <button class:selected="{current === '/profile/settings'}" on:click={() => (push('/profile/settings'))}>Settings</button> -->
|
||||||
{:else if $location === '/profile'}
|
<button class:selected="{current === '/profile/friends'}" on:click={() => (push('/profile/friends'))}>Friends</button>
|
||||||
<button on:click={() => (push('/profile/settings'))}>Settings</button>
|
|
||||||
{/if}
|
|
||||||
<button on:click={() => (push('/profile/friends'))}>Friends</button>
|
|
||||||
<button on:click={handleClickLogout}>Log Out</button>
|
<button on:click={handleClickLogout}>Log Out</button>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
@@ -54,6 +53,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.selected {
|
||||||
|
background-color: chocolate;
|
||||||
|
text-decoration: underline;
|
||||||
|
/* TMP so it's obvious but we need to pick good colors */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* There is a bunch of unncessary shit in here... why so many flex grids, why is everything the same class? just seemed easier but... */
|
/* There is a bunch of unncessary shit in here... why so many flex grids, why is everything the same class? just seemed easier but... */
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
10
srcs/requirements/svelte/api_front/src/pieces/Match.ts
Normal file
10
srcs/requirements/svelte/api_front/src/pieces/Match.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
import type { MatchOptions } from "../pages/game/client/pongSpectator";
|
||||||
|
export { MatchOptions } from "../pages/game/client/pongSpectator";
|
||||||
|
|
||||||
|
export class Match {
|
||||||
|
gameServerIdOfTheMatch: string;
|
||||||
|
gameOptions: MatchOptions;
|
||||||
|
playerOneUsername: string;
|
||||||
|
playerTwoUsername: string;
|
||||||
|
}
|
||||||
@@ -1,14 +1,9 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount, onDestroy } from "svelte";
|
import { onMount, onDestroy } from "svelte";
|
||||||
import { MatchOptions } from "../pages/game/client/pongSpectator";
|
import { Match, MatchOptions} from "./Match";
|
||||||
|
|
||||||
export let match: {
|
export let match: Match;
|
||||||
gameServerIdOfTheMatch: string,
|
|
||||||
gameOptions: MatchOptions,
|
|
||||||
playerOneUsername: string,
|
|
||||||
playerTwoUsername: string
|
|
||||||
};
|
|
||||||
|
|
||||||
let matchOptionsString = "";
|
let matchOptionsString = "";
|
||||||
|
|
||||||
@@ -32,7 +27,7 @@
|
|||||||
|
|
||||||
<li>
|
<li>
|
||||||
<button on:click>
|
<button on:click>
|
||||||
"{match.playerOneUsername}" VS "{match.playerTwoUsername}"
|
'{match.playerOneUsername}' VS '{match.playerTwoUsername}'
|
||||||
<br/> [{matchOptionsString}]
|
<br/> [{matchOptionsString}]
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
17
srcs/requirements/svelte/api_front/src/pieces/utils.ts
Normal file
17
srcs/requirements/svelte/api_front/src/pieces/utils.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
export async function fetchAvatar(username: string)
|
||||||
|
{
|
||||||
|
return fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/avatar?username=${username}`)
|
||||||
|
.then((response) => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Avatar not retrieved");
|
||||||
|
}
|
||||||
|
return response.blob();
|
||||||
|
})
|
||||||
|
.then((blob) => {
|
||||||
|
return URL.createObjectURL(blob);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log("catch fetchAvatar: ", error);
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -9,7 +9,6 @@ import Ranking from '../pages/game/Ranking.svelte';
|
|||||||
import GameSpectator from '../pages/game/GameSpectator.svelte';
|
import GameSpectator from '../pages/game/GameSpectator.svelte';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const primaryRoutes = {
|
export const primaryRoutes = {
|
||||||
'/': SplashPage,
|
'/': SplashPage,
|
||||||
'/2fa': TwoFactorAuthentication,
|
'/2fa': TwoFactorAuthentication,
|
||||||
|
|||||||
Reference in New Issue
Block a user