diff --git a/socket/.gitignore b/server/.gitignore similarity index 100% rename from socket/.gitignore rename to server/.gitignore diff --git a/socket/LICENSE b/server/LICENSE similarity index 100% rename from socket/LICENSE rename to server/LICENSE diff --git a/server/biome.json b/server/biome.json new file mode 100644 index 0000000..99345d8 --- /dev/null +++ b/server/biome.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json", + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2, + "lineWidth": 80 + }, + "linter": { + "enabled": true, + "rules": { + "suspicious": { + "noExplicitAny": "off" + }, + "recommended": true + } + }, + "organizeImports": { + "enabled": true + }, + "files": { + "ignore": [ + "node_modules", + "build" + ] + } +} diff --git a/server/package.json b/server/package.json new file mode 100644 index 0000000..fe77f45 --- /dev/null +++ b/server/package.json @@ -0,0 +1,33 @@ +{ + "name": "@cookie-clicker-brasil/socket", + "private": true, + "version": "1.0.1", + "main": "src/main.js", + "license": "Apache-2.0", + "author": "Sebastian Jn ", + "scripts": { + "start": "node build/main.js", + "build": "tsc --project tsconfig.json", + "dev": "tsnd --expose-gc --transpile-only --ignore-watch node_modules --respawn src/main.ts", + "lint": "npx @biomejs/biome lint --write", + "format": "npx @biomejs/biome format --write" + }, + "devDependencies": { + "@biomejs/biome": "1.9.4", + "@types/node": "^22.10.5", + "@types/socket.io": "^3.0.1", + "ts-node-dev": "^2.0.0", + "typescript": "^5.7.3" + }, + "dependencies": { + "socket.io": "^4.8.1" + }, + "engines": { + "npm": ">=8", + "node": ">=18" + }, + "repository": { + "type": "git", + "url": "https://github.com/sebastianjnuwu/cookie.git" + } +} diff --git a/socket/src/main.js b/server/src/main.ts similarity index 54% rename from socket/src/main.js rename to server/src/main.ts index 9e7b1ed..b042678 100644 --- a/socket/src/main.js +++ b/server/src/main.ts @@ -1,44 +1,41 @@ -import { Server } from "socket.io"; +import { Server, Socket } from "socket.io"; +import { Room, RoomData, LeaveRoomData, RejoinRoomData, StartGameData, UpdateCookiesData } from "./types/rooms"; -// Inicialização do servidor +// Initialize server const io = new Server(); -const ROOMS = {}; +const ROOMS: Record = {}; let roomIdCounter = 0; /** - * Gera um identificador único para cada jogador. - * @returns {number} O identificador gerado. + * Generates a unique identifier for each player. + * @returns The generated identifier. */ -function $generate_uuid() { +function generateUuid(): number { roomIdCounter += 1; return roomIdCounter; } /** - * Gera um código de sala aleatório. - * @returns {string} O código gerado para a sala. + * Generates a random room code. + * @returns The generated room code. */ -function $generate_code() { +function generateCode(): string { return Math.random().toString(36).substring(2, 8).toUpperCase(); } /** - * Evento de conexão de um novo cliente. - * @param {Socket} socket - O objeto socket que representa a conexão do cliente. + * Handles a new client connection. + * @param socket - The socket object representing the client connection. */ -io.on("connection", (socket) => { +io.on("connection", (socket: Socket) => { /** - * Manipula a criação ou entrada de um jogador em uma sala. - * @param {Object} data - Dados para criação ou entrada na sala. - * @param {string} [data.room_code] - O código da sala. Se não fornecido, uma nova sala será criada. - * @param {number} data.room_time - A duração da sala em minutos. - * @param {string} data.room_player - O nome do jogador entrando na sala. - * @throws {Error} Se a sala não existir ou se o jogador já estiver na sala. + * Handles player joining or creating a room. + * @param data - The data for creating or joining a room. */ - socket.on("room", ({ room_code, room_time, room_player }) => { + socket.on("room", ({ room_code, room_time, room_player }: RoomData) => { if (!room_code) { - room_code = $generate_code(); + room_code = generateCode(); ROOMS[room_code] = { code: room_code, date: new Date(), @@ -60,7 +57,7 @@ io.on("connection", (socket) => { socket.emit("err_socket", { err_socket: "ROOM_STATE_ERROR_IN_GAME" }); return; } - + if (room.state === "finished") { socket.emit("err_socket", { err_socket: "ROOM_STATE_ERROR_FINISHED" }); return; @@ -74,7 +71,7 @@ io.on("connection", (socket) => { socket.join(room_code); room.players.push({ - id: $generate_uuid(), + id: generateUuid(), date: new Date(), socket: socket.id, player_data: { cookies: null }, @@ -82,17 +79,17 @@ io.on("connection", (socket) => { }); io.to(room_code).emit("update_room", { room_player, room }); - console.log(`Player "${room_player}" joined room "${room_code}". Room state:`, room); + console.log( + `Player "${room_player}" joined room "${room_code}". Room state:`, + room, + ); }); /** - * Manipula a saída de um jogador de uma sala. - * @param {Object} data - Dados para sair da sala. - * @param {string} data.room_code - O código da sala. - * @param {string} data.room_player - O nome do jogador que está saindo. - * @throws {Error} Se a sala ou o jogador não forem encontrados. + * Handles player leaving a room. + * @param data - The data for leaving the room. */ - socket.on("leave_room", ({ room_code, room_player }) => { + socket.on("leave_room", ({ room_code, room_player }: LeaveRoomData) => { const room = ROOMS[room_code]; if (!room) { @@ -100,7 +97,9 @@ io.on("connection", (socket) => { return; } - room.players = room.players.filter(player => player.room_player !== room_player); + room.players = room.players.filter( + (player) => player.room_player !== room_player, + ); if (room.players.length === 0) { delete ROOMS[room_code]; @@ -113,37 +112,36 @@ io.on("connection", (socket) => { socket.leave(room_code); io.to(room_code).emit("update_room", { room_player, room }); - console.log(`Player ${room_player} (Socket ID: ${socket.id}) left room ${room_code}`); + console.log( + `Player ${room_player} (Socket ID: ${socket.id}) left room ${room_code}`, + ); }); /** - * Manipula o retorno de um jogador para uma sala. - * @param {Object} data - Dados para retornar à sala. - * @param {string} data.room_player - O nome do jogador retornando. - * @param {string} data.room_code - O código da sala. - * @throws {Error} Se a sala não for encontrada ou o jogador não estiver na sala. + * Handles player rejoining a room. + * @param data - The data for rejoining the room. */ - socket.on("rejoin_room", ({ room_player, room_code }) => { + socket.on("rejoin_room", ({ room_player, room_code }: RejoinRoomData) => { const room = ROOMS[room_code]; if (!room) return; - const player = room.players.find(player => player.room_player === room_player); + const player = room.players.find( + (player) => player.room_player === room_player, + ); if (player) { player.socket = socket.id; socket.join(room_code); io.to(room_code).emit("update_room", { room_player, room }); console.log(`Player "${room_player}" rejoined room "${room_code}".`); - } + } }); /** - * Inicia o jogo em uma sala. - * @param {Object} data - Dados para iniciar o jogo. - * @param {string} data.room_code - O código da sala. - * @throws {Error} Se a sala não existir. + * Starts the game in a room. + * @param data - The data to start the game. */ - socket.on("start_game", ({ room_code }) => { + socket.on("start_game", ({ room_code }: StartGameData) => { const room = ROOMS[room_code]; if (!room) { @@ -184,27 +182,26 @@ io.on("connection", (socket) => { console.log(`Room ${room_code} has been deleted.`); } - console.log(`Game in room "${room_code}" finished! Ranking:`, ranking); + console.log( + `Game in room "${room_code}" finished! Ranking:`, + ranking, + ); return; } time_game--; - }, 1000); + }, 1000); } countdown--; - }, 1000); + }, 1000); }); /** - * Atualiza o número de cookies de um jogador na sala. - * @param {Object} data - Dados para atualizar os cookies. - * @param {string} data.room_player - O nome do jogador. - * @param {string} data.room_code - O código da sala. - * @param {number} data.cookies - O número de cookies a ser atualizado. - * @throws {Error} Se a sala ou o jogador não forem encontrados ou se o valor de cookies for inválido. + * Updates the number of cookies for a player in the room. + * @param data - The data for updating the cookies. */ - socket.on("update_cookies", ({ room_player, room_code, cookies }) => { + socket.on("update_cookies", ({ room_player, room_code, cookies }: UpdateCookiesData) => { if (typeof cookies !== "number" || cookies < 0) { socket.emit("err_socket", { err_socket: "INVALID_COOKIES" }); return; @@ -217,14 +214,18 @@ io.on("connection", (socket) => { return; } - const player = room.players.find(player => player.room_player === room_player); + const player = room.players.find( + (player) => player.room_player === room_player, + ); if (player) { player.player_data.cookies = cookies; - console.log(`Player "${room_player}" in room "${room_code}" updated cookies to ${cookies}.`); + console.log( + `Player "${room_player}" in room "${room_code}" updated cookies to ${cookies}.`, + ); } }); }); -// Inicia o servidor na porta 3000 +// Start server on port 3000 io.listen(3000); diff --git a/server/src/types/rooms.d.ts b/server/src/types/rooms.d.ts new file mode 100644 index 0000000..d869010 --- /dev/null +++ b/server/src/types/rooms.d.ts @@ -0,0 +1,53 @@ +// types/rooms.d.ts + +/** Represents a room */ +export interface Room { + code: string; + date: Date; + players: Player[]; + owner: string; + time: number; + state: "waiting" | "in_game" | "finished"; +} + +/** Represents a player */ +export interface Player { + id: number; + date: Date; + socket: string; + player_data: { + cookies: number | null; + }; + room_player: string; +} + +/** Data received to create or join a room */ +export interface RoomData { + room_code?: string; + room_time: number; + room_player: string; +} + +/** Data for leaving a room */ +export interface LeaveRoomData { + room_code: string; + room_player: string; +} + +/** Data for rejoining a room */ +export interface RejoinRoomData { + room_code: string; + room_player: string; +} + +/** Data for starting a game */ +export interface StartGameData { + room_code: string; +} + +/** Data for updating cookies */ +export interface UpdateCookiesData { + room_code: string; + room_player: string; + cookies: number; +} diff --git a/server/tsconfig.json b/server/tsconfig.json new file mode 100644 index 0000000..61101b9 --- /dev/null +++ b/server/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "lib": ["ESNext"], + "module": "commonjs", + "moduleResolution": "node", + "target": "ESNext", + "outDir": "build", + "strictNullChecks": false, + "sourceMap": false, + "esModuleInterop": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "allowSyntheticDefaultImports": true, + "skipLibCheck": true, + "skipDefaultLibCheck": true, + "resolveJsonModule": true, + "importHelpers": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "build"] +} diff --git a/server/typos.toml b/server/typos.toml new file mode 100644 index 0000000..b80dc2a --- /dev/null +++ b/server/typos.toml @@ -0,0 +1,17 @@ +[default] +check-filename = true + +[files] +extend-exclude = [ + "www/src/js/modules", + "www/src/locales/lang", + "node_modules", + "android", + "socket" +] + +[default.extend-words] +strech = "strech" +contaienr = "contaienr" +collapsable = "collapsable" +styl = "styl" diff --git a/socket/package.json b/socket/package.json deleted file mode 100644 index 45ace6a..0000000 --- a/socket/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@cookie-clicker-brasil/socket", - "private": true, - "version": "1.0.1", - "main": "src/main.js", - "type": "module", - "license": "Apache-2.0", - "author": "Sebastian Jn ", - "dependencies": { - "socket.io": "^4.8.1" - }, - "engines": { - "npm": ">=8", - "node": ">=18" - }, - "repository": { - "type": "git", - "url": "https://github.com/sebastianjnuwu/cookie.git" - }, - "keywords": [ - "cookie-clicker", - "socket", - "real-time" - ] -} diff --git a/vite.config.ts b/vite.config.ts index 26e3f6b..a1da514 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -4,7 +4,7 @@ import "dotenv/config"; export default defineConfig({ root: "./www", - target: 'esnext', + target: "esnext", build: { outDir: "../build", minify: false, diff --git a/www/index.html b/www/index.html index d94c698..1b4f1a4 100644 --- a/www/index.html +++ b/www/index.html @@ -4,7 +4,7 @@ - Cookie Clicker Brasil + Cookie Clicker Brasil diff --git a/www/src/locales/lang/en-US.ts b/www/src/locales/lang/en-US.ts index 8b62d81..87b304d 100644 --- a/www/src/locales/lang/en-US.ts +++ b/www/src/locales/lang/en-US.ts @@ -1,56 +1,56 @@ // @lang/en-US const translation = { - general: { - cookies: "Cookies", - seconds: "Seconds", - timeLabel: "Time:", - start: "GO!", - message_now: "Now" - }, - splashScreen: { - splashClick: "Click..." - }, - menu: { - cookieTitle: "Cookie", - playButton: "Play", - settings: "Settings" - }, - ranking: { - rankingTitle: "Ranking", - roomCode: "Room Code:", - waiting: "Waiting...", - startButton: "Start", - leaveButton: "Leave" - }, - game: { - nicknameLabel: "Nickname", - gameOptionLabel: "Choose an option:", - randomRoom: "Join a random room", - createRoom: "Create a room", - joinRoom: "Join a room", - roomCodeLabel: "Room Code", - gameTimeLabel: "Game Time (in seconds)" - }, - room: { - no_room_player: "It seems you haven't set your nickname!", - no_room_time: "It seems you haven't set the room time!", - time_check: - "The room time must be greater than 10 seconds and less than or equal to 10 minutes!", - no_room_code: "It seems you haven't added the room code!", - no_connected: "It seems you've been disconnected from the Cookie game!" - }, - modal: { - cancel: "Cancel", - confirm: "Confirm" - }, - err_message: { - ROOM_NOT_FOUND: "The room was not found!", - ROOM_STATE_ERROR_IN_GAME: "The game has already started", + general: { + cookies: "Cookies", + seconds: "Seconds", + timeLabel: "Time:", + start: "GO!", + message_now: "Now", + }, + splashScreen: { + splashClick: "Click...", + }, + menu: { + cookieTitle: "Cookie", + playButton: "Play", + settings: "Settings", + }, + ranking: { + rankingTitle: "Ranking", + roomCode: "Room Code:", + waiting: "Waiting...", + startButton: "Start", + leaveButton: "Leave", + }, + game: { + nicknameLabel: "Nickname", + gameOptionLabel: "Choose an option:", + randomRoom: "Join a random room", + createRoom: "Create a room", + joinRoom: "Join a room", + roomCodeLabel: "Room Code", + gameTimeLabel: "Game Time (in seconds)", + }, + room: { + no_room_player: "It seems you haven't set your nickname!", + no_room_time: "It seems you haven't set the room time!", + time_check: + "The room time must be greater than 10 seconds and less than or equal to 10 minutes!", + no_room_code: "It seems you haven't added the room code!", + no_connected: "It seems you've been disconnected from the Cookie game!", + }, + modal: { + cancel: "Cancel", + confirm: "Confirm", + }, + err_message: { + ROOM_NOT_FOUND: "The room was not found!", + ROOM_STATE_ERROR_IN_GAME: "The game has already started", ROOM_STATE_ERROR_FINISHED: "The match is over", - PLAYER_EXISTS: "A player with this name already exists in the room.", - INVALID_COOKIES: "Invalid cookies data received.", - ROOM_CODE_NOT_FOUND: "The room code was not found." - } + PLAYER_EXISTS: "A player with this name already exists in the room.", + INVALID_COOKIES: "Invalid cookies data received.", + ROOM_CODE_NOT_FOUND: "The room code was not found.", + }, }; export default translation; diff --git a/www/src/locales/lang/es-ES.ts b/www/src/locales/lang/es-ES.ts index 0e09f30..faef360 100644 --- a/www/src/locales/lang/es-ES.ts +++ b/www/src/locales/lang/es-ES.ts @@ -45,13 +45,13 @@ const translation = { confirm: "Confirmar", }, err_message: { - ROOM_NOT_FOUND: "¡La sala no fue encontrada!", - ROOM_STATE_ERROR_IN_GAME: "El partido ya ha comenzado.", - ROOM_STATE_ERROR_FINISHED: "El partido ya termino", - PLAYER_EXISTS: "Ya existe un jugador con ese nombre en la sala.", - INVALID_COOKIES: "Datos de cookies inválidos recibidos.", - ROOM_CODE_NOT_FOUND: "No se encontró el código de la sala." -} + ROOM_NOT_FOUND: "¡La sala no fue encontrada!", + ROOM_STATE_ERROR_IN_GAME: "El partido ya ha comenzado.", + ROOM_STATE_ERROR_FINISHED: "El partido ya termino", + PLAYER_EXISTS: "Ya existe un jugador con ese nombre en la sala.", + INVALID_COOKIES: "Datos de cookies inválidos recibidos.", + ROOM_CODE_NOT_FOUND: "No se encontró el código de la sala.", + }, }; -export default translation; \ No newline at end of file +export default translation; diff --git a/www/src/locales/lang/pt-BR.ts b/www/src/locales/lang/pt-BR.ts index 7ad45f1..e947973 100644 --- a/www/src/locales/lang/pt-BR.ts +++ b/www/src/locales/lang/pt-BR.ts @@ -50,7 +50,7 @@ const translation = { PLAYER_EXISTS: "Já existe um jogador com esse nome na sala.", INVALID_COOKIES: "Dados de cookies inválidos recebidos.", ROOM_CODE_NOT_FOUND: "O código da sala não foi encontrado.", - } + }, }; -export default translation; \ No newline at end of file +export default translation; diff --git a/www/src/locales/main.ts b/www/src/locales/main.ts index cd5f4cb..d847d3c 100644 --- a/www/src/locales/main.ts +++ b/www/src/locales/main.ts @@ -4,29 +4,28 @@ import $ from "jquery"; import pt from "@lang/pt-BR.ts"; import en from "@lang/en-US.ts"; import es from "@lang/es-ES.ts"; - - i18next.init({ - lng: "pt-BR", - debug: false, - preload: true, - resources: { - "en-US": { - translation: en, - }, - "pt-BR": { - translation: pt, - }, - "es-ES": { - translation: es, - }, + +i18next.init({ + lng: "pt-BR", + debug: false, + preload: true, + resources: { + "en-US": { + translation: en, }, - interpolation: { - escapeValue: false, - useRawValueToEscape: true, + "pt-BR": { + translation: pt, }, - load: "all", - }); - + "es-ES": { + translation: es, + }, + }, + interpolation: { + escapeValue: false, + useRawValueToEscape: true, + }, + load: "all", +}); let lang: TFunction | undefined; diff --git a/www/src/plugins/admob.ts b/www/src/plugins/admob.ts index 2fd9bea..377c9af 100644 --- a/www/src/plugins/admob.ts +++ b/www/src/plugins/admob.ts @@ -38,7 +38,7 @@ function $remove_banner() { .catch((err) => { return console.error("Error hiding banner: ", err.message); }); -}; +} function $show_video() { const adId = "ca-app-pub-6690516270288705/7898187843"; @@ -53,7 +53,7 @@ function $show_video() { .catch((err) => { console.error("Error displaying rewarded interstitial: ", err.message); }); -}; +} $("#splash-screen").on("click", () => $show_banner()); diff --git a/www/src/ts/game.ts b/www/src/ts/game.ts index fce7bbc..f1980a0 100644 --- a/www/src/ts/game.ts +++ b/www/src/ts/game.ts @@ -179,17 +179,17 @@ $("#form_button").on("click", () => { // Handle socket errors socket.on("err_socket", ({ err_socket }: { err_socket: string }) => { - if (err_socket === 'ROOM_NOT_FOUND') { - showMessage(lang("err_message.ROOM_NOT_FOUND")); - } else if (err_socket === 'ROOM_STATE_ERROR_IN_GAME') { + if (err_socket === "ROOM_NOT_FOUND") { + showMessage(lang("err_message.ROOM_NOT_FOUND")); + } else if (err_socket === "ROOM_STATE_ERROR_IN_GAME") { showMessage(lang("err_message.ROOM_STATE_ERROR_IN_GAME")); - } else if (err_socket === 'ROOM_STATE_ERROR_FINISHED') { + } else if (err_socket === "ROOM_STATE_ERROR_FINISHED") { showMessage(lang("err_message.ROOM_STATE_ERROR_FINISHED")); - } else if (err_socket === 'PLAYER_EXISTS') { + } else if (err_socket === "PLAYER_EXISTS") { showMessage(lang("err_message.PLAYER_EXISTS")); - } else if (err_socket === 'INVALID_COOKIES') { + } else if (err_socket === "INVALID_COOKIES") { showMessage(lang("err_message.INVALID_COOKIES")); - } else if (err_socket === 'ROOM_CODE_NOT_FOUND') { + } else if (err_socket === "ROOM_CODE_NOT_FOUND") { showMessage(lang("err_message.ROOM_CODE_NOT_FOUND")); } }); @@ -231,7 +231,7 @@ $("#leave_room").on("click", () => { }); localStorage.setItem("code", null); - + $("ui").hide(); $("#start-screen").show(); });