diff --git a/index.js b/index.js index 2a6c1c4..6feab4b 100644 --- a/index.js +++ b/index.js @@ -510,7 +510,7 @@ io.on('connection', async (socket) => { socket.on('place ship', async (type, posX, posY, rot) => { const playerGame = await GInfo.getPlayerGameData(socket); - if (playerGame.data.state === 'preparation') { + if (playerGame && playerGame.data.state === 'preparation') { const playerShips = await GInfo.getPlayerShips(socket); let canPlace = bships.validateShipPosition(playerShips, type, posX, posY, rot); let shipAvailable = bships.getShipsAvailable(playerShips)[type] > 0; @@ -534,7 +534,7 @@ io.on('connection', async (socket) => { socket.on('remove ship', async (posX, posY) => { const playerGame = await GInfo.getPlayerGameData(socket); - if (playerGame.data.state === 'preparation') { + if (playerGame && playerGame.data.state === 'preparation') { const deletedShip = await GInfo.removeShip(socket, posX, posY); socket.emit("removed ship", { posX: posX, posY: posY, type: deletedShip.type }); await GInfo.incrStat(socket, 'placedShips', -1); @@ -544,7 +544,7 @@ io.on('connection', async (socket) => { socket.on('shoot', async (posX, posY) => { let playerGame = await GInfo.getPlayerGameData(socket); - if (playerGame.data.state === 'action') { + if (playerGame && playerGame.data.state === 'action') { if (bships.checkTurn(playerGame.data, socket.session.id)) { const enemyIdx = socket.session.id === playerGame.data.hostId ? 1 : 0; diff --git a/lang/en.json b/lang/en.json index a9413b5..d8f752a 100644 --- a/lang/en.json +++ b/lang/en.json @@ -111,6 +111,9 @@ "You cannot place a ship like this": "You cannot place a ship like this", "You have ran out of ships of that type": "You have ran out of ships of that type", - "You have already shot at this field": "You have already shot at this field" + "You have already shot at this field": "You have already shot at this field", + + "Victory": "Victory", + "Defeat": "Defeat" } } \ No newline at end of file diff --git a/lang/pl.json b/lang/pl.json index 45f346f..ef2b30c 100644 --- a/lang/pl.json +++ b/lang/pl.json @@ -113,6 +113,9 @@ "You cannot place a ship like this": "Nie możesz tak postawić statku", "You have ran out of ships of that type": "Skończyły ci się statki tego typu", - "You have already shot at this field": "Już strzelałeś w to pole" + "You have already shot at this field": "Już strzelałeś w to pole", + + "Victory": "Zwycięstwo", + "Defeat": "Porażka" } } \ No newline at end of file diff --git a/public/assets/js/socket-game.js b/public/assets/js/socket-game.js index fd6d0a0..949da8a 100644 --- a/public/assets/js/socket-game.js +++ b/public/assets/js/socket-game.js @@ -15,8 +15,17 @@ if ($(window).width() <= 820) { animation: "shift-toward-subtle", interactive: true, content: (reference) => { + // Need to fix this + + console.log("a"); let fieldData = `${$(reference).data('pos-x')}, ${$(reference).data('pos-y')}`; + let pos = occupiedFields.find((elem) => elem.pos[0] == $(reference).data('pos-x') && elem.pos[1] == $(reference).data('pos-y')); + + if (pos) { + return $('#removeTippyTemplate').html().replaceAll("[[FIELDPOS]]", fieldData); + } + return $('#mainTippyTemplate').html().replaceAll("[[FIELDPOS]]", fieldData); }, }); @@ -39,6 +48,8 @@ $('#board .field').on('click', function () { if (new Date().getTime() / 1000 - lastTimeClick > 0.3) { if ($(window).width() > 820) { socket.emit("place ship", selectedShip, $(this).data('pos-x'), $(this).data('pos-y'), shipRotation); + + navigator.vibrate(200); lastTimeClick = new Date().getTime() / 1000; } } @@ -48,12 +59,15 @@ function manualPlace(posX, posY) { hoveredShip = null; refreshBoardView(); socket.emit("place ship", selectedShip, posX, posY, shipRotation); + lastTimeClick = new Date().getTime() / 1000; } $('#secondaryBoard .field').on('click', function () { if (new Date().getTime() / 1000 - lastTimeClick > 0.3) { if ($(window).width() > 820) { socket.emit("shoot", $(this).data('pos-x'), $(this).data('pos-y')); + + navigator.vibrate(200); lastTimeClick = new Date().getTime() / 1000; } } @@ -61,17 +75,29 @@ $('#secondaryBoard .field').on('click', function () { function manualShoot(posX, posY) { socket.emit("shoot", posX, posY); + lastTimeClick = new Date().getTime() / 1000; } $('.field').on('contextmenu', function () { if ($(this).hasClass('active') && new Date().getTime() / 1000 - lastTimeClick > 0.3) { - let originPos = occupiedFields.find((elem) => elem.pos[0] == $(this).data('pos-x') && elem.pos[1] == $(this).data('pos-y')).origin; + let pos = occupiedFields.find((elem) => elem.pos[0] == $(this).data('pos-x') && elem.pos[1] == $(this).data('pos-y')); - socket.emit("remove ship", originPos[0], originPos[1]); - lastTimeClick = new Date().getTime() / 1000; + if (pos) { + socket.emit("remove ship", pos.origin[0], pos.origin[1]); + lastTimeClick = new Date().getTime() / 1000; + } } }); +function manualRemove(posX, posY) { + let pos = occupiedFields.find((elem) => elem.pos[0] == posX && elem.pos[1] == posY); + + if (pos) { + socket.emit("remove ship", pos.origin[0], pos.origin[1]); + lastTimeClick = new Date().getTime() / 1000; + } +} + socket.on('toast', (msg) => { Toastify({ text: msg, @@ -170,7 +196,7 @@ var updateTimer = setInterval(() => { } else { const UTCNow = Math.floor((new Date()).getTime() / 1000); - const time = Math.abs(UTCNow - timerDestination); + const time = Math.max(timerDestination - UTCNow, 0); if (time < 10) { $("#timer").addClass("active"); @@ -190,10 +216,10 @@ socket.on("game finished", (winnerIdx, oppName) => { $("#opponent").html(`Vs. ${oppName}`); if (winnerIdx === playerIdx) { - $("#state").html("Zwycięstwo"); + $("#state").html(locale["Victory"]); $("#state").addClass("dynamic"); } else { - $("#state").html("Porażka"); + $("#state").html(locale["Defeat"]); $("#state").addClass("danger"); } @@ -228,7 +254,6 @@ socket.on('turn update', (turnData) => { timerDestination = turnData.timerToUTC; gamePhase = turnData.phase; - refreshBoardView(); }); socket.on('player left', () => { diff --git a/public/assets/js/socket.js b/public/assets/js/socket.js index bddf35e..6603ce7 100644 --- a/public/assets/js/socket.js +++ b/public/assets/js/socket.js @@ -7,16 +7,22 @@ socket.on("joined", (nick) => { $("#oppNameField").html(nick); switchView("preparingGame"); lockUI(false); + + console.log("Player joined the game:", nick); }); socket.on("player left", () => { lockUI(true); switchView("mainMenuView"); lockUI(false); + + console.log("Player left the game"); }); socket.on("gameReady", (gameId) => { + console.log("Game is ready, redirecting in 2 seconds. Game ID:", gameId); setTimeout(() => { + console.log("Redirecting..."); window.location.replace("/game?id=" + gameId); }, 2000); }); @@ -58,19 +64,22 @@ socket.emit("my profile", (profile) => { } $(".matchList").html(matchHistoryDOM); + console.log("Profile data fetched successfully"); }); socket.emit("whats my nick", (myNickname) => { nickname = myNickname; $("#profileButton").html(nickname); - console.log(nickname); + console.log("Received player nickname:", myNickname); }); $("#createGameButton").on("click", function () { lockUI(true); + console.log("Creating a lobby..."); socket.emit("create lobby", (response) => { switch (response.status) { case "ok": + console.log("Lobby created"); $("#createGameCode").val(response.gameCode); switchView("pvpCreateView"); returnLock = true; @@ -78,12 +87,14 @@ $("#createGameButton").on("click", function () { break; case "alreadyInLobby": + console.log("Lobby creation failed (player is already in a lobby)"); $("#createGameCode").val(response.gameCode); switchView("pvpCreateView"); lockUI(false); break; default: + console.log("Lobby creation failed (unknown)"); alert(`${window.locale["Unknown error occured"]}\n${window.locale["Status:"]} ${response.status}`); lockUI(false); break; @@ -107,9 +118,11 @@ form.addEventListener('submit', (e) => { e.preventDefault(); if (input.value && input.value.length === 6) { lockUI(true); + console.log("Joining a lobby with code:", input.value); socket.emit("join lobby", input.value, (response) => { switch (response.status) { case "ok": + console.log("Joined a lobby by:", response.oppNickname); $("#oppNameField").html(response.oppNickname); switchView("preparingGame"); lockUI(false); diff --git a/utils/auth.js b/utils/auth.js index d84aaa5..63c8ff2 100644 --- a/utils/auth.js +++ b/utils/auth.js @@ -84,6 +84,8 @@ export class MailAuth { const row = response[0]; resolve({ status: 1, uid: row.user_id }); + + conn.end(); }); }); } @@ -99,6 +101,8 @@ export class MailAuth { } else { resolve(null); } + + conn.end(); }); }); } @@ -187,6 +191,8 @@ export class MailAuth { resolve({ status: 1, uid: row.user_id }); + + conn.end(); }); }); } @@ -199,6 +205,8 @@ export class MailAuth { else conn.query(`INSERT INTO statistics(match_id, user_id, board, won) VALUES (${conn.escape(matchId)}, ${conn.escape(hostId)}, ${conn.escape(JSON.stringify(boards[0]))}, ${conn.escape(winnerIdx == 0 ? 1 : 0)}), (${conn.escape(matchId)}, ${conn.escape(guestId)}, ${conn.escape(JSON.stringify(boards[1]))}, ${conn.escape(winnerIdx == 1 ? 1 : 0)})`, async (error, response) => { if (error) reject(error); else resolve(); + + conn.end(); }); }); }); @@ -207,7 +215,7 @@ export class MailAuth { getProfile(userId) { return new Promise((resolve, reject) => { const conn = mysql.createConnection(this.mysqlOptions); - conn.query(`SELECT nickname, account_creation FROM accounts WHERE user_id = ${conn.escape(userId)}; SELECT ROUND((AVG(statistics.won)) * 100) AS winrate, COUNT(statistics.match_id) AS alltime_matches, COUNT(CASE WHEN (YEAR(matches.date) = YEAR(NOW()) AND MONTH(matches.date) = MONTH(NOW())) THEN matches.match_id END) AS monthly_matches FROM accounts NATURAL JOIN statistics NATURAL JOIN matches WHERE accounts.user_id = ${conn.escape(userId)}; SELECT statistics.match_id, accounts.nickname AS opponent, matches.match_type, statistics.won, matches.duration, matches.date FROM statistics JOIN matches ON matches.match_id = statistics.match_id JOIN accounts ON accounts.user_id = (CASE WHEN matches.host_id != statistics.user_id THEN matches.host_id ELSE matches.guest_id END) WHERE statistics.user_id = ${conn.escape(userId)} LIMIT 10;`, async (error, response) => { + conn.query(`SELECT nickname, account_creation FROM accounts WHERE user_id = ${conn.escape(userId)}; SELECT ROUND((AVG(statistics.won)) * 100) AS winrate, COUNT(statistics.match_id) AS alltime_matches, COUNT(CASE WHEN (YEAR(matches.date) = YEAR(NOW()) AND MONTH(matches.date) = MONTH(NOW())) THEN matches.match_id END) AS monthly_matches FROM accounts NATURAL JOIN statistics NATURAL JOIN matches WHERE accounts.user_id = ${conn.escape(userId)}; SELECT statistics.match_id, accounts.nickname AS opponent, matches.match_type, statistics.won, matches.duration, matches.date FROM statistics JOIN matches ON matches.match_id = statistics.match_id JOIN accounts ON accounts.user_id = (CASE WHEN matches.host_id != statistics.user_id THEN matches.host_id ELSE matches.guest_id END) WHERE statistics.user_id = ${conn.escape(userId)} ORDER BY matches.date DESC LIMIT 10;`, async (error, response) => { if (error) reject(error); else { if (response[0].length === 0 || response[1].length === 0) { @@ -219,6 +227,8 @@ export class MailAuth { resolve({ profile, stats, matchHistory }); } + + conn.end(); }); }); } @@ -241,6 +251,8 @@ export class MailAuth { conn.query(`UPDATE accounts SET nickname = ${conn.escape(nickname)} WHERE user_id = ${conn.escape(uid)}`, (error) => { if (error) reject(error); resolve(); + + conn.end(); }); }); } @@ -251,6 +263,8 @@ export class MailAuth { conn.query(`SELECT nickname FROM accounts WHERE user_id = ${conn.escape(uid)}`, (error, response) => { if (error) reject(error); resolve(response[0].nickname); + + conn.end(); }); }); } diff --git a/views/board.handlebars b/views/board.handlebars index 1e46171..d335253 100644 --- a/views/board.handlebars +++ b/views/board.handlebars @@ -46,6 +46,10 @@ +
+ +
+
@@ -67,6 +71,9 @@ "Three-masted": "{{ t 'board.Three-masted' }}", "Four-masted": "{{ t 'board.Four-masted' }}", + "Victory": "{{ t 'board.Victory' }}", + "Defeat": "{{ t 'board.Defeat' }}", + "Preparation phase": "{{ t 'board.Preparation phase' }}", "Your turn": "{{ t 'board.Your turn' }}", "Opponents turn": "{{ t 'board.Opponents turn' }}",