From 4dd5be7e2f2eeeac6862950806e0cf9993275c85 Mon Sep 17 00:00:00 2001 From: milo Date: Wed, 28 Jan 2026 17:17:25 +0100 Subject: [PATCH] hell yeah --- src/server/routes/api.js | 77 ++++++++++++++++++++++++++++++++++++++- src/server/socket.js | 8 ++-- src/utils/marketNotifs.js | 3 +- 3 files changed, 82 insertions(+), 6 deletions(-) diff --git a/src/server/routes/api.js b/src/server/routes/api.js index de8a493..931e139 100644 --- a/src/server/routes/api.js +++ b/src/server/routes/api.js @@ -24,7 +24,7 @@ import { } from "../../database/index.js"; // --- Game State Imports --- -import { activePolls, activePredis, activeSlowmodes, skins } from "../../game/state.js"; +import { activePolls, activePredis, activeSlowmodes, skins, activeSnakeGames } from "../../game/state.js"; // --- Utility and API Imports --- import { formatTime, isMeleeSkin, isVCTSkin, isChampionsSkin, getVCTRegion } from "../../utils/index.js"; @@ -32,7 +32,7 @@ import { DiscordRequest } from "../../api/discord.js"; // --- Discord.js Builder Imports --- import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from "discord.js"; -import { emitDataUpdated, socketEmit } from "../socket.js"; +import { emitDataUpdated, socketEmit, onGameOver } from "../socket.js"; import { handleCaseOpening } from "../../utils/marketNotifs.js"; import { drawCaseContent, drawCaseSkin, getSkinUpgradeProbs } from "../../utils/caseOpening.js"; @@ -1204,6 +1204,79 @@ export function apiRoutes(client, io) { return res.status(200).json({ message: "Prédi close" }); }); + router.post("/snake/reward", async (req, res) => { + const { discordId, score, isWin } = req.body; + console.log(`[SNAKE][SOLO]${discordId}: score=${score}, isWin=${isWin}`); + try { + const user = getUser.get(discordId); + if (!user) return res.status(404).json({ message: "Utilisateur introuvable" }); + const reward = isWin ? score * 2 : score; + const newCoins = user.coins + reward; + updateUserCoins.run({ id: discordId, coins: newCoins }); + insertLog.run({ + id: `${discordId}-snake-reward-${Date.now()}`, + user_id: discordId, + action: "SNAKE_GAME_REWARD", + coins_amount: reward, + user_new_amount: newCoins, + target_user_id: null, + }); + await emitDataUpdated({ table: "users", action: "update" }); + return res.status(200).json({ message: `Récompense de ${reward} FlopoCoins attribuée !` }); + } catch (e) { + console.error("Error rewarding snake game:", e); + return res.status(500).json({ message: "Erreur lors de l'attribution de la récompense" }); + } + }); + + router.post("/queue/leave", async (req, res) => { + const { discordId, game, reason } = req.body; + if (game === "snake" && (reason === "beforeunload" || reason === "route-leave")) { + + const lobby = Object.values(activeSnakeGames).find( + (l) => (l.p1.id === discordId || l.p2.id === discordId) && !l.gameOver, + ); + if (!lobby) return; + + const player = lobby.p1.id === discordId ? lobby.p1 : lobby.p2; + const otherPlayer = lobby.p1.id === discordId ? lobby.p2 : lobby.p1; + if (player.gameOver === true) return res.status(200).json({ message: "Déjà quitté" }); + player.gameOver = true; + otherPlayer.win = true; + + lobby.lastmove = Date.now(); + + // Broadcast the updated state to both players + await socketEmit("snakegamestate", { + lobby: { + p1: lobby.p1, + p2: lobby.p2, + }, + }); + + // Check if game should end + if (lobby.p1.gameOver && lobby.p2.gameOver) { + // Both players finished - determine winner + let winnerId = null; + if (lobby.p1.win && !lobby.p2.win) { + winnerId = lobby.p1.id; + } else if (lobby.p2.win && !lobby.p1.win) { + winnerId = lobby.p2.id; + } else if (lobby.p1.score > lobby.p2.score) { + winnerId = lobby.p1.id; + } else if (lobby.p2.score > lobby.p1.score) { + winnerId = lobby.p2.id; + } + // If scores are equal, winnerId remains null (draw) + await onGameOver(client, "snake", discordId, winnerId, "", { p1: lobby.p1.score, p2: lobby.p2.score }); + } else if (lobby.p1.win || lobby.p2.win) { + // One player won by filling the grid + const winnerId = lobby.p1.win ? lobby.p1.id : lobby.p2.id; + await onGameOver(client, "snake", discordId, winnerId, "", { p1: lobby.p1.score, p2: lobby.p2.score }); + } + } + }); + // --- Admin Routes --- router.post("/buy-coins", (req, res) => { diff --git a/src/server/socket.js b/src/server/socket.js index a085569..aa82a73 100644 --- a/src/server/socket.js +++ b/src/server/socket.js @@ -36,6 +36,8 @@ export function initializeSocket(server, client) { registerSnakeEvents(socket, client); socket.on("tictactoe:queue:leave", async ({ discordId }) => await refreshQueuesForUser(discordId, client)); + socket.on("connect4:queue:leave", async ({ discordId }) => await refreshQueuesForUser(discordId, client)); + socket.on("snake:queue:leave", async ({ discordId }) => await refreshQueuesForUser(discordId, client)); // catch tab kills / network drops socket.on("disconnecting", async () => { @@ -210,7 +212,7 @@ async function onSnakeGameStateUpdate(client, eventData) { player.snake = snake; player.food = food; player.score = score; - player.gameOver = gameOver; + player.gameOver = gameOver === true ? true : false; player.win = win; lobby.lastmove = Date.now(); @@ -245,7 +247,7 @@ async function onSnakeGameStateUpdate(client, eventData) { } } -async function onGameOver(client, gameType, playerId, winnerId, reason = "", scores = null) { +export async function onGameOver(client, gameType, playerId, winnerId, reason = "", scores = null) { const { activeGames, title } = getGameAssets(gameType); const gameKey = Object.keys(activeGames).find((key) => key.includes(playerId)); const game = gameKey ? activeGames[gameKey] : undefined; @@ -514,7 +516,7 @@ async function updateDiscordMessage(client, game, title, resultText = "") { } else if (title === "Puissance 4") { description = `**🔴 ${game.p1.name}** vs **${game.p2.name} 🟡**\n\n${formatConnect4BoardForDiscord(game.board)}`; } else if (title === "Snake 1v1") { - description = `**🐍 ${game.p1.name}** (${game.p1.score}) vs **${game.p2.name} 🐍** (${game.p2.score})`; + description = `**🐍 ${game.p1.name}** (${game.p1.score}) vs (${game.p2.score}) **${game.p2.name}** `; } if (resultText) description += `\n### ${resultText}`; diff --git a/src/utils/marketNotifs.js b/src/utils/marketNotifs.js index 6f9baec..6413b2d 100644 --- a/src/utils/marketNotifs.js +++ b/src/utils/marketNotifs.js @@ -211,7 +211,8 @@ export async function handleMarketOfferClosing(offerId, client) { // Send notification in guild channel try { - const guildChannel = await client.channels.fetch(process.env.BOT_CHANNEL_ID); + const guild = await client.guilds.fetch(process.env.BOT_GUILD_ID); + const guildChannel = await guild.channels.fetch(process.env.BOT_CHANNEL_ID); const embed = new EmbedBuilder() .setTitle("🔔 Fin des enchères") .setDescription(