diff --git a/.gitignore b/.gitignore index 3e20103..949de91 100644 --- a/.gitignore +++ b/.gitignore @@ -1,23 +1 @@ -* - -!.gitignore -!LICENCE -!README.md - -!Makefile -!docker-compose.yml -!.env - -!cont/ -!cont/front -!cont/back -!cont/front/* -!cont/back/* - - -!volumes/ -!volumes/front -!volumes/back -!volumes/front/* -!volumes/back/* - +volumes/ssl/transcendence.pem diff --git a/README.md b/README.md index 43e08d6..e69de29 100644 --- a/README.md +++ b/README.md @@ -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 -``` diff --git a/volumes/front/.gitignore b/volumes/front/.gitignore new file mode 100644 index 0000000..047e6a4 --- /dev/null +++ b/volumes/front/.gitignore @@ -0,0 +1,131 @@ + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* diff --git a/volumes/front/public/global.css b/volumes/front/public/global.css new file mode 100644 index 0000000..bb28a94 --- /dev/null +++ b/volumes/front/public/global.css @@ -0,0 +1,63 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} diff --git a/volumes/front/public/img/pog.jpg b/volumes/front/public/img/pog.jpg new file mode 100644 index 0000000..353331e Binary files /dev/null and b/volumes/front/public/img/pog.jpg differ diff --git a/volumes/front/public/img/pong.png b/volumes/front/public/img/pong.png new file mode 100644 index 0000000..72657d3 Binary files /dev/null and b/volumes/front/public/img/pong.png differ diff --git a/volumes/front/public/img/profileicon.png b/volumes/front/public/img/profileicon.png new file mode 100644 index 0000000..bdd467f Binary files /dev/null and b/volumes/front/public/img/profileicon.png differ diff --git a/volumes/front/public/vite.svg b/volumes/front/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/volumes/front/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/volumes/front/src/App.svelte b/volumes/front/src/App.svelte new file mode 100644 index 0000000..21b5cc3 --- /dev/null +++ b/volumes/front/src/App.svelte @@ -0,0 +1,82 @@ + + +
+ + {#if isSpectateOpen} +
(isSpectateOpen = false)} on:keydown={() => (isSpectateOpen = false)}> + +
+ {/if} + {#if isFriendOpen} +
(isFriendOpen = false)} on:keydown={() => (isFriendOpen = false)}> + +
+ {/if} + {#if isHistoryOpen} +
(isHistoryOpen = false)} on:keydown={() => (isHistoryOpen = false)}> + +
+ {/if} + {#if isProfileOpen} +
(isProfileOpen = false)} on:keydown={() => (isProfileOpen = false)}> + +
+ {/if} + + +
+ + diff --git a/volumes/front/src/app.d.ts b/volumes/front/src/app.d.ts new file mode 100644 index 0000000..59059b9 --- /dev/null +++ b/volumes/front/src/app.d.ts @@ -0,0 +1,5 @@ +declare global { + namespace App { + } +} + export {}; diff --git a/volumes/front/src/assets/svelte.svg b/volumes/front/src/assets/svelte.svg new file mode 100644 index 0000000..c5e0848 --- /dev/null +++ b/volumes/front/src/assets/svelte.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/volumes/front/src/components/Friends.svelte b/volumes/front/src/components/Friends.svelte new file mode 100644 index 0000000..452ec7b --- /dev/null +++ b/volumes/front/src/components/Friends.svelte @@ -0,0 +1,80 @@ + + + + +
+
+
+ {#if friends.length > 0} +

Monkey friends

+ {#each friends.slice(0, 10) as friend} +
  • + {friend.username} is {friend.status} +
  • + {/each} + {:else} +

    No friends to display

    + {/if} +
    +

    Add a friend

    +
    + + +
    +
    +
    +
    +
    + + diff --git a/volumes/front/src/components/MatchHistory.svelte b/volumes/front/src/components/MatchHistory.svelte new file mode 100644 index 0000000..68c9101 --- /dev/null +++ b/volumes/front/src/components/MatchHistory.svelte @@ -0,0 +1,58 @@ + + + + +
    +
    +
    + {#if matches.length > 0} +

    Last 10 monkey games

    + {#each matches.slice(0, 10) as match} +
  • + {match.winner} 1 - 0 {match.loser} + {#if match.points > 0} + +{match.points} + {:else} + {match.points} + {/if} + MP | rank #{match.rank} +
  • + {/each} + {:else} +

    No matches to display

    + {/if} +
    +
    +
    + + diff --git a/volumes/front/src/components/NavBar.svelte b/volumes/front/src/components/NavBar.svelte new file mode 100644 index 0000000..a101a28 --- /dev/null +++ b/volumes/front/src/components/NavBar.svelte @@ -0,0 +1,106 @@ + + + + + diff --git a/volumes/front/src/components/Play.svelte b/volumes/front/src/components/Play.svelte new file mode 100644 index 0000000..ca6f100 --- /dev/null +++ b/volumes/front/src/components/Play.svelte @@ -0,0 +1,38 @@ + + + +
    +

    Choose a gamemode

    + + + +
    + + diff --git a/volumes/front/src/components/Pong/Ball.ts b/volumes/front/src/components/Pong/Ball.ts new file mode 100644 index 0000000..cfb0828 --- /dev/null +++ b/volumes/front/src/components/Pong/Ball.ts @@ -0,0 +1,15 @@ +import { Point, Rect } from './utils'; + +export class Ball { + rect: Rect; + speed: Point; + color: string | CanvasGradient | CanvasPattern = 'white'; + + constructor(spawn: Point, size: Point = new Point(20, 20), speed: Point = new Point(10, 2)) { + this.rect = new Rect(spawn, size); + } + + draw(context: CanvasRenderingContext2D) { + this.rect.draw(context, this.color); + } +} diff --git a/volumes/front/src/components/Pong/Game.ts b/volumes/front/src/components/Pong/Game.ts new file mode 100644 index 0000000..8b37993 --- /dev/null +++ b/volumes/front/src/components/Pong/Game.ts @@ -0,0 +1,80 @@ +import { Ball } from './Ball'; +import { GAME_EVENTS } from './constants'; +import type { GameInfo, GameUpdate } from './constants'; +import { Paddle } from './Paddle'; +import { Player } from './Player'; +import { formatWebsocketData, Point } from './utils'; + +const BG_COLOR = 'black'; + +export class Game { + canvas: HTMLCanvasElement; + context: CanvasRenderingContext2D; + ball: Ball; + players: Player[]; + my_paddle: Paddle; + + constructor(canvas: HTMLCanvasElement, context: CanvasRenderingContext2D) { + this.canvas = canvas; + this.context = context; + this.players = []; + this.my_paddle = null; + } + + setInfo(data: GameInfo) { + this.canvas.width = data.mapSize.x; + this.canvas.height = data.mapSize.y; + + this.ball = new Ball(new Point(this.canvas.width / 2, this.canvas.height / 2), data.ballSize); + + const paddle1: Paddle = new Paddle(new Point(data.playerXOffset, this.canvas.height / 2), data.paddleSize); + const paddle2: Paddle = new Paddle( + new Point(this.canvas.width - data.playerXOffset, this.canvas.height / 2), + data.paddleSize + ); + this.players = [new Player(paddle1), new Player(paddle2)]; + this.my_paddle = this.players[data.yourPaddleIndex].paddle; + } + + start(socket: WebSocket) { + if (this.my_paddle) { + this.canvas.addEventListener('mousemove', (e) => { + this.my_paddle.move(e); + socket.send( + formatWebsocketData(GAME_EVENTS.PLAYER_MOVE, { + position: this.my_paddle.rect.center + }) + ); + }); + console.log('Game started!'); + } + } + + update(data: GameUpdate) { + if (this.players[0].paddle != this.my_paddle) { + this.players[0].paddle.rect.center = data.paddlesPositions[0]; + } + if (this.players[1].paddle != this.my_paddle) { + this.players[1].paddle.rect.center = data.paddlesPositions[1]; + } + this.ball.rect.center = data.ballPosition; + for (let i = 0; i < data.scores.length; i++) { + this.players[i].score = data.scores[i]; + } + } + + draw() { + this.context.fillStyle = BG_COLOR; + this.context.fillRect(0, 0, this.canvas.width, this.canvas.height); + + this.players.forEach((p) => p.draw(this.context)); + this.ball.draw(this.context); + + const max_width = 50; + this.context.font = '50px Arial'; + const text_width = this.context.measureText('0').width; + const text_offset = 50; + this.players[0].drawScore(this.canvas.width / 2 - (text_width + text_offset), max_width, this.context); + this.players[1].drawScore(this.canvas.width / 2 + text_offset, max_width, this.context); + } +} diff --git a/volumes/front/src/components/Pong/Paddle.ts b/volumes/front/src/components/Pong/Paddle.ts new file mode 100644 index 0000000..ee7f419 --- /dev/null +++ b/volumes/front/src/components/Pong/Paddle.ts @@ -0,0 +1,29 @@ +import { Point, Rect } from './utils'; + +export class Paddle { + rect: Rect; + color: string | CanvasGradient | CanvasPattern = 'white'; + + constructor(spawn: Point, size: Point = new Point(6, 100)) { + this.rect = new Rect(spawn, size); + } + + draw(context: CanvasRenderingContext2D) { + this.rect.draw(context, this.color); + } + + move(e: MouseEvent) { + const canvas = e.target as HTMLCanvasElement; + const rect = canvas.getBoundingClientRect(); + const new_y = ((e.clientY - rect.top) * canvas.height) / rect.height; + + const offset: number = this.rect.size.y / 2; + if (new_y - offset < 0) { + this.rect.center.y = offset; + } else if (new_y + offset > canvas.height) { + this.rect.center.y = canvas.height - offset; + } else { + this.rect.center.y = new_y; + } + } +} diff --git a/volumes/front/src/components/Pong/Player.ts b/volumes/front/src/components/Pong/Player.ts new file mode 100644 index 0000000..eec3dc9 --- /dev/null +++ b/volumes/front/src/components/Pong/Player.ts @@ -0,0 +1,19 @@ +import type { Paddle } from './Paddle'; + +export class Player { + paddle: Paddle; + score: number; + + constructor(paddle: Paddle) { + this.paddle = paddle; + this.score = 0; + } + + draw(context: CanvasRenderingContext2D) { + this.paddle.draw(context); + } + + drawScore(score_position_x: number, max_width: number, context: CanvasRenderingContext2D) { + context.fillText(this.score.toString(), score_position_x, 50, max_width); + } +} diff --git a/volumes/front/src/components/Pong/Pong.svelte b/volumes/front/src/components/Pong/Pong.svelte new file mode 100644 index 0000000..39ec273 --- /dev/null +++ b/volumes/front/src/components/Pong/Pong.svelte @@ -0,0 +1,58 @@ + + +
    + +
    +
    + +
    diff --git a/volumes/front/src/components/Pong/constants.ts b/volumes/front/src/components/Pong/constants.ts new file mode 100644 index 0000000..b06ad8d --- /dev/null +++ b/volumes/front/src/components/Pong/constants.ts @@ -0,0 +1,32 @@ +import { Point } from './utils'; + +export const GAME_EVENTS = { + START_GAME: 'START_GAME', + GAME_TICK: 'GAME_TICK', + PLAYER_MOVE: 'PLAYER_MOVE', + GET_GAME_INFO: 'GET_GAME_INFO' +}; + +export interface GameInfo extends GameInfoConstants { + yourPaddleIndex: number; +} +export interface GameInfoConstants { + mapSize: Point; + paddleSize: Point; + playerXOffset: number; + ballSize: Point; + winScore: number; +} +export const gameInfoConstants: GameInfoConstants = { + mapSize: new Point(600, 400), + paddleSize: new Point(6, 50), + playerXOffset: 50, + ballSize: new Point(20, 20), + winScore: 2 +}; + +export interface GameUpdate { + paddlesPositions: Point[]; + ballPosition: Point; + scores: number[]; +} diff --git a/volumes/front/src/components/Pong/utils.ts b/volumes/front/src/components/Pong/utils.ts new file mode 100644 index 0000000..b083261 --- /dev/null +++ b/volumes/front/src/components/Pong/utils.ts @@ -0,0 +1,88 @@ +export class Point { + x: number; + y: number; + + constructor(x: number, y: number) { + this.x = x; + this.y = y; + } + + //Returns a new point + add(other: Point) { + return new Point(this.x + other.x, this.y + other.y); + } + + //Modifies `this` point + add_inplace(other: Point) { + this.x += other.x; + this.y += other.y; + } + + clone(): Point { + return new Point(this.x, this.y); + } +} + +export class Rect { + center: Point; + size: Point; + + constructor(center: Point, size: Point) { + this.center = center; + this.size = size; + } + + draw(context: CanvasRenderingContext2D, color: string | CanvasGradient | CanvasPattern) { + const offset: Point = new Point(this.size.x / 2, this.size.y / 2); + + context.fillStyle = color; + context.fillRect(this.center.x - offset.x, this.center.y - offset.y, this.size.x, this.size.y); + } + + //True if `this` rect contains `other` rect in the x-axis + contains_x(other: Rect): boolean { + const offset: number = this.size.x / 2; + const offset_other: number = other.size.x / 2; + + if ( + this.center.x - offset <= other.center.x - offset_other && + this.center.x + offset >= other.center.x + offset_other + ) + return true; + return false; + } + + //True if `this` rect contains `other` rect in the y-axis + contains_y(other: Rect): boolean { + const offset: number = this.size.y / 2; + const offset_other: number = other.size.y / 2; + + if ( + this.center.y - offset <= other.center.y - offset_other && + this.center.y + offset >= other.center.y + offset_other + ) + return true; + return false; + } + + collides(other: Rect): boolean { + const offset: Point = new Point(this.size.x / 2, this.size.y / 2); + const offset_other: Point = new Point(other.size.x / 2, other.size.y / 2); + + if ( + this.center.x - offset.x < other.center.x + offset_other.x && + this.center.x + offset.x > other.center.x - offset_other.x && + this.center.y - offset.y < other.center.y + offset_other.y && + this.center.y + offset.y > other.center.y - offset_other.y + ) + return true; + return false; + } +} + +export function formatWebsocketData(event: string, data?: any): string { + return JSON.stringify({ + event, + data + }); +} diff --git a/volumes/front/src/components/Profile.svelte b/volumes/front/src/components/Profile.svelte new file mode 100644 index 0000000..210bb92 --- /dev/null +++ b/volumes/front/src/components/Profile.svelte @@ -0,0 +1,109 @@ + + +
    +
    +
    + Profile Icon +

    {realname}

    +
    + +
    +
    +
    +
    +
    + + +
    + +
    +

    Wins: {wins}

    +

    Losses: {losses}

    +

    Winrate: {(wins / (wins + losses)) * 100}%

    +

    Elo : {elo}

    +

    Rank: {rank}

    +
    + +
    +
    +
    +
    + + diff --git a/volumes/front/src/components/Spectate.svelte b/volumes/front/src/components/Spectate.svelte new file mode 100644 index 0000000..a9a4b36 --- /dev/null +++ b/volumes/front/src/components/Spectate.svelte @@ -0,0 +1,53 @@ + + + + +
    +
    +
    + {#if spectate.length > 0} +

    Monkey spectating

    + {#each spectate.slice(0, 10) as _spectate} +
  • + {_spectate.player1} VS {_spectate.player2} + +
  • + {/each} + {:else} +

    No matches to spectate

    + {/if} +
    +
    +
    + + diff --git a/volumes/front/src/main.ts b/volumes/front/src/main.ts new file mode 100644 index 0000000..9494003 --- /dev/null +++ b/volumes/front/src/main.ts @@ -0,0 +1,8 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export const prerender = true; +export default app; diff --git a/volumes/front/src/vite-env.d.ts b/volumes/front/src/vite-env.d.ts new file mode 100644 index 0000000..4078e74 --- /dev/null +++ b/volumes/front/src/vite-env.d.ts @@ -0,0 +1,2 @@ +/// +///