import { NetworkService } from "./NetworkService.js"; import { Player } from "./Player.js"; import { BaseService } from "./BaseService.js"; import { Auth } from "../core/Auth.js"; /** * Players manager * - Tracks connected players after successful auth (0x01 0x03) */ export class Players extends BaseService { constructor(networkService,isClient) { super("Players"); this.InstanceId = "Players"; // For replication system if (isClient) { this.networkService = networkService; this.networkService.registerHandler(0x00, 0x04, (payload) => { // Auth response from server, parse it const decoder = new TextDecoder(); const msg = decoder.decode(payload); console.debug("[Players] Received auth response from server:", msg); if (msg.startsWith("AUTH_SUCCESS|")) { const playerName = msg.split("|")[1]; const id = msg.split("|")[2]; console.debug(`[Players] You have logged in as ${playerName}`); // Create a local Player instance const player = new Player( id, playerName, null ); this.players = new Map(); this.players.set(null, player); // single local player this.LocalPlayer = player; player.SetParent(this); } else { console.warn("[Players] Auth failed or unknown response:", msg); } }); return; } this.networkService = networkService; this.players = new Map(); // id -> Player this.authenticator = new Auth(); // Listen for auth packets this.networkService.registerHandler(0x01, 0x03, async (payload, ws) => { if (ws.isAuthed) return; // Already authed, ignore additional auth attempts console.debug("[Players] Received auth packet:", "CENSORED"); // Assume payload is a string (player name) let token; try { // Decode bytes const decoder = new TextDecoder(); token = decoder.decode(payload); } catch (e) { console.warn("[Players] Invalid auth payload:", payload); networkService.KickClientLater(ws, 4000, "Invalid auth payload, please try again."); return; } // Verify token (dummy implementation) const id = await this.authenticator.verifySessionToken(token); if (id === null) { // Kick off the client networkService.KickClientLater(ws, 4001, "Authentication failed; are you logged in?"); // Reason must be understandable as its shown to the user return; } console.debug(`[Players] Client authenticated as ${id}`); ws.isAuthed = true; // Mark ws as authed // Create Player instance const name = await this.authenticator.getUserNameById(id); const player = new Player(id, name, ws ); this.players.set(ws, player); player.SetParent(this); // Listen for disconnection ws.on("close", () => { this.players.delete(ws); player.Destroy(); console.debug(`[Players] Player ${name} (${id}) disconnected.`); }); console.debug(`[Players] Player ${name} (${id}) connected.`); // Send auth success packet const encoder = new TextEncoder(); const successPayload = encoder.encode("AUTH_SUCCESS|" + name + "|" + id); this.networkService.sendToClient(ws, 0x00, 0x04, successPayload); }); } /** * Get all connected players */ getAll() { return Array.from(this.players.values()); } /** * Remove player by ws */ removeByWs(ws) { this.players.delete(ws); } /** * Get player by ws */ getByWs(ws) { return this.players.get(ws); } }