Merge branch 'main' of https://github.com/viastolfi/maettleship into docker-deployment

Get last updates from main
docker-deployment
Vincent ASTOLFI 9 months ago
commit a53c8342d3

@ -1,7 +1,7 @@
# Maettleship # Maettleship
Maettleship is a simple online battleship game that I design for maë (my grilfriend) when lectures are boring. Maettleship is a simple online battleship game that I design for maë (my grilfriend) when lectures are boring.
It's made entirely in javascript using nodejs for the server part with socketio and express module. It's made entirely in javascript using nodejs for the server part with socketio and express module. I also use mysql for all my database part. Finally, I use docker and a vps that I pay for online deployment
# Requirement # Requirement
@ -9,15 +9,21 @@ To use maettleship you'll need the following app on your computer
* node js and npm * node js and npm
* mysql * mysql
* A firefox derived web browser (Don't know why it doesn't work on chrome)
# Installation # Installation
Later, maettleship will be usable online but you can test it localy now if you want ! ### Online
Follow those first steps to get started I recently add a branch called `docker-deployment` which I use to deploy maettleship on an online vps. I can't give you the url now cause there is still a lot of security problem that I want to fix first, but be patient it'll come.
### Locally
Follow those first steps to get started if tou want to run maettleship locally
``` ```
git clone https://github.com/viastolfi/maettleship.git git clone https://github.com/viastolfi/maettleship.git
cd maettleship
npm install npm install
``` ```
@ -28,19 +34,20 @@ mysql -u user -p
> mysql source db_script.sql > mysql source db_script.sql
``` ```
Finally, you need a `.env`file with your personnal mysql information so follow those steps. Finally, you need a `.env`file with your personnal mysql information so follow those steps. You also need this file to specify your cookie's private key so you can create them
``` ```
touch .env touch .env
``` ```
The .env file should look like thah The .env file should look like that
``` ```
DB_USER=userName DB_USER=userName
DB_PASSWORD=UserPassword DB_PASSWORD=UserPassword
DB_NAME=maettleship DB_NAME=maettleship
DB_HOST=localhost DB_HOST=localhost
COOKIE_SECRET_KEY=secret_key
``` ```
Now you can start the server using the following command on your terminal. Now you can start the server using the following command on your terminal.
@ -58,27 +65,31 @@ The current state of maettleship is the following one
- [X] Player left the game situation handled - [X] Player left the game situation handled
- [X] End game (partially handled) - [X] End game (partially handled)
- [X] Create an account and add it on the database - [X] Create an account and add it on the database
- [X] Connection to your account
# TODO # TODO
Those point are the feature I still need to introduce Those point are the feature I still need to introduce
- [ ] Security improvement (hashed password, sql injection handling)
- [ ] Fix all the problems linked to my rooms implementation
- [ ] Rematch - [ ] Rematch
- [ ] Connection to your account - [ ] Player historic (link to its account)
- [ ] Player historic (link to his account)
- [ ] Global scoreboard - [ ] Global scoreboard
- [ ] General error handling - [ ] General error handling
- [ ] (lot of) debug - [ ] (lot of) debug
# Author # Author
This project is entirely made by me (ASTOLFI Vincent) This project is entirely made by me (ASTOLFI Vincent). I suggest you to check on my github profile if you want to see the other project I've done for my studies or the ones I do in my free time.
# Acknowledgement # Acknowledgement
Here is a cool list of the different docs I use on this project Here is a cool list of the different docs I used on this project
- [socket.io documentation](https://socket.io/fr/docs/v4/) - [socket.io documentation](https://socket.io/fr/docs/v4/)
- [express documentation](https://expressjs.com/) - [express documentation](https://expressjs.com/)
- [mysql documentation](https://dev.mysql.com/doc/) - [mysql documentation](https://dev.mysql.com/doc/)
- [nodejs documentation](https://nodejs.org/docs/latest/api/) - [nodejs documentation](https://nodejs.org/docs/latest/api/)
This project aim to be fully functionnable one day so any recommendation is welcome !

@ -8,9 +8,14 @@ class Player {
this.username = username this.username = username
this.grid = new Grid(); this.grid = new Grid();
this.pieces = []; this.pieces = [];
this.createPiece()
}
createPiece() {
this.pieces.push(new Piece(1, { x: 0, y: 0 }, { x: 0, y: 0 })); this.pieces.push(new Piece(1, { x: 0, y: 0 }, { x: 0, y: 0 }));
this.pieces.push(new Piece(2, { x: 2, y: 2 }, { x: 2, y: 3 })); this.pieces.push(new Piece(2, { x: 2, y: 2 }, { x: 2, y: 3 }));
this.pieces.push(new Piece(3, { x: 4, y: 3 }, { x: 4, y: 5 }))
this.pieces.forEach((piece) => { this.pieces.forEach((piece) => {
for (let i = piece.startPos.x; i <= piece.endPos.x; i++) { for (let i = piece.startPos.x; i <= piece.endPos.x; i++) {
for (let j = piece.startPos.y; j <= piece.endPos.y; j++) { for (let j = piece.startPos.y; j <= piece.endPos.y; j++) {
@ -21,19 +26,11 @@ class Player {
}); });
} }
resetPiece() {
this.pieces = []
this.createPiece()
}
createPiece() {
this.pieces.push(new Piece(1, { x: 0, y: 0 }, { x: 0, y: 0 }));
this.pieces.push(new Piece(2, { x: 2, y: 2 }, { x: 2, y: 3 }));
}
resetGrid() { resetGrid() {
this.grid = new Grid() this.grid = new Grid()
this.resetPiece() this.pieces = []
this.createPiece()
} }
} }

@ -136,7 +136,6 @@ io.on("connection", (socket) => {
socket.on("disconnect", () => { socket.on("disconnect", () => {
const index = players.findIndex((p) => p.id === socket.id) const index = players.findIndex((p) => p.id === socket.id)
// if there is no room this line creates error
const roomIndex = rooms.findIndex(room => const roomIndex = rooms.findIndex(room =>
room.players.some((player) => player.id === socket.id) room.players.some((player) => player.id === socket.id)
); );
@ -157,13 +156,14 @@ io.on("connection", (socket) => {
} }
} }
players.splice(index, 1) if (index !== -1) {
players.splice(index, 1)
}
console.log(`Player disconnected: ${socket.id}`); console.log(`Player disconnected: ${socket.id}`);
}) })
socket.on("first connection", (socketId) => { socket.on("first connection", (socketId) => {
// error my occurs if cookie is expired
const cookies = socket.request.headers.cookie; const cookies = socket.request.headers.cookie;
const authToken = cookies.split('; ').find(cookie => cookie.startsWith('authToken=')).split('=')[1]; const authToken = cookies.split('; ').find(cookie => cookie.startsWith('authToken=')).split('=')[1];
@ -267,19 +267,14 @@ io.on("connection", (socket) => {
}); });
socket.on("game ended", (roomId) => { socket.on("game ended", (roomId) => {
const room = rooms.find((r) => r.id === roomId)
const roomIndex = rooms.findIndex((r) => r.id === roomId) const roomIndex = rooms.findIndex((r) => r.id === roomId)
room.players.forEach(player => { rooms[roomIndex].players.forEach(player => {
player.resetGrid() player.resetGrid()
io.to(player.id).emit("go to menu") io.to(player.id).emit("go to menu")
}); });
room.players = [] rooms.splice(roomIndex, 1)
rooms.slice(roomIndex, 1)
delete room
console.log("rooms list : ", rooms)
}) })
socket.on("reset grid", (roomId) => { socket.on("reset grid", (roomId) => {
@ -318,5 +313,5 @@ const sendMoveToPlayers = (moveData) => {
http.listen(port, () => { http.listen(port, () => {
console.log(`Listening on http://localhost:${port}`); //console.log(`Listening on http://localhost:${port}`);
}); });

@ -47,7 +47,7 @@
<canvas id="own_board" width="301" height="301"></canvas> <canvas id="own_board" width="301" height="301"></canvas>
<canvas <canvas
id="ennemy_board" id="ennemy_board"
class="hidden-element" style="display: none;"
width="301" width="301"
height="301" height="301"
></canvas> ></canvas>
@ -62,9 +62,9 @@
<p id="playerInfo"></p> <p id="playerInfo"></p>
<div id="inGameNotification"> <div id="inGameNotification">
<h2 class="hidden-element" id="play_notification">You have to play</h2> <h2 style="display: none;" id="play_notification">You have to play</h2>
<h2 class="hidden-element" id="hit_notification">Hit !</h2> <h2 style="display: none;" id="hit_notification">Hit !</h2>
<h2 class="hidden-element" id="win_notification">WIN !</h2> <h2 style="display: none;" id="win_notification">WIN !</h2>
</div> </div>
<script src="https://cdn.socket.io/4.7.5/socket.io.min.js"></script> <script src="https://cdn.socket.io/4.7.5/socket.io.min.js"></script>

@ -20,7 +20,7 @@ function startConnection() {
socket.on("start game", (username) => { socket.on("start game", (username) => {
const ennemyBoard = document.querySelector("#ennemy_board"); const ennemyBoard = document.querySelector("#ennemy_board");
ennemyBoard.classList.remove("hidden-element"); ennemyBoard.style.display = 'block'
drawGrid(); drawGrid();
drawEnnemyGrid(); drawEnnemyGrid();
@ -31,13 +31,13 @@ socket.on("end game", () => {
const ennemyBoard = document.querySelector("#ennemy_board"); const ennemyBoard = document.querySelector("#ennemy_board");
const loader = document.querySelector("#loader"); const loader = document.querySelector("#loader");
loader.classList.remove("hidden-element"); loader.style.display = 'block'
ennemyBoard.classList.add("hidden-element"); ennemyBoard.style.display = 'none'
}); });
socket.on("play", () => { socket.on("play", () => {
const notification = document.querySelector("#play_notification"); const notification = document.querySelector("#play_notification");
notification.classList.remove("hidden-element"); notification.style.display = 'block'
play(); play();
}); });
@ -45,13 +45,13 @@ socket.on("played move", (isHit, isWin) => {
const hitNotification = document.querySelector("#hit_notification"); const hitNotification = document.querySelector("#hit_notification");
const winNotification = document.querySelector("#win_notification"); const winNotification = document.querySelector("#win_notification");
if (isHit) hitNotification.classList.remove("hidden-element"); if (isHit) hitNotification.style.display = 'block'
else hitNotification.classList.add("hidden-element"); else hitNotification.style.display = 'none'
if (isWin) gameEnd() if (isWin) gameEnd()
if (isWin) winNotification.classList.remove("hidden-element"); if (isWin) winNotification.style.display = 'block'
else winNotification.classList.add("hidden-element"); else winNotification.style.display = 'none'
drawGrid(); drawGrid();
drawEnnemyGrid(); drawEnnemyGrid();
@ -63,22 +63,32 @@ socket.on('opponent left', () => {
}) })
socket.on("go to menu", () => { socket.on("go to menu", () => {
goToMenu()
})
function goToMenu() {
const modal = document.getElementById("gameEndedModal") const modal = document.getElementById("gameEndedModal")
const ennemyGrid = document.getElementById("ennemy_board") const ennemyGrid = document.getElementById("ennemy_board")
const loader = document.getElementById("loader")
const roomkeyHolder = document.getElementById("roomkeyHolder") const roomkeyHolder = document.getElementById("roomkeyHolder")
const notifications = document.getElementById("inGameNotification") const loader = document.querySelector("#loader");
const playNotification = document.querySelector("#play_notification");
const hitNotification = document.querySelector("#hit_notification");
const winNotification = document.querySelector("#win_notification");
roomId = "" roomId = ""
notifications.style.display = 'none' playNotification.style.display = 'none'
hitNotification.style.display = 'none'
winNotification.style.display = 'none'
modal.style.display = 'none' modal.style.display = 'none'
ennemyGrid.style.display = 'none' ennemyGrid.style.display = 'none'
loader.classList.remove = "hidden-element" loader.style.display = 'block'
roomkeyHolder.style.display = 'none'
roomkeyHolder.innerHTML = ""
roomkeyHolder.style.display = 'block'
drawGrid() drawGrid()
}) }
function gameEnd() { function gameEnd() {
const modal = document.getElementById('gameEndedModal'); const modal = document.getElementById('gameEndedModal');
@ -88,7 +98,7 @@ function gameEnd() {
export function sendMove(move) { export function sendMove(move) {
const notification = document.querySelector("#play_notification"); const notification = document.querySelector("#play_notification");
socket.emit("play", roomId, socket.id, move); socket.emit("play", roomId, socket.id, move);
notification.classList.add("hidden-element"); notification.style.display = 'none'
} }
function onCreateRoom() { function onCreateRoom() {
@ -96,7 +106,7 @@ function onCreateRoom() {
event.preventDefault(); event.preventDefault();
const loader = document.querySelector("#loader"); const loader = document.querySelector("#loader");
const roomkeyHolder = document.querySelector("#roomkeyHolder"); const roomkeyHolder = document.querySelector("#roomkeyHolder");
loader.classList.add("hidden-element"); loader.style.display = 'none';
socket.emit("room creation", socket.id, (response) => { socket.emit("room creation", socket.id, (response) => {
roomId = response.roomId; roomId = response.roomId;
@ -124,7 +134,7 @@ function onJoinRoom() {
errorHolder.append("Error : Room Id don't exist") errorHolder.append("Error : Room Id don't exist")
} }
} else { } else {
loader.classList.add("hidden-element"); loader.style.display = "none";
roomkeyHolder.innerHTML += `Your room key is : <strong>` + roomId + `</strong>`; roomkeyHolder.innerHTML += `Your room key is : <strong>` + roomId + `</strong>`;
} }
}); });
@ -135,13 +145,11 @@ function onJoinRoom() {
document.getElementById('closeModalButton').addEventListener('click', () => { document.getElementById('closeModalButton').addEventListener('click', () => {
const modal = document.getElementById('opponentLeftModal'); const modal = document.getElementById('opponentLeftModal');
const ennemyBoard = document.querySelector("#ennemy_board");
ennemyBoard.classList.add("hidden-element");
modal.style.display = 'none'; modal.style.display = 'none';
socket.emit("reset grid", roomId) socket.emit("reset grid", roomId)
drawGrid()
goToMenu()
}); });
document.getElementById('goToMenuButton').addEventListener('click', () => { document.getElementById('goToMenuButton').addEventListener('click', () => {

Loading…
Cancel
Save