import DataChannel from "./networking/DataChannel.js"; import Signaler from "./networking/Signaler.js"; /** * Client/endpoint that manages a connection to a SkribblServer */ export default class SkribblClient { /** * Constructs a new client for a given game ID or DataChannel. * @param {string|DataChannel} idOrDataChannel */ constructor(idOrDataChannel){ /** @type {string[]} */ this._players = []; /** @type {((players:string[])=>void)[]} */ this._onPlayersListChangeCallbacks = []; this._readyPromise = (async()=>{ this._dataChannel = idOrDataChannel instanceof DataChannel?idOrDataChannel:await Signaler.join(idOrDataChannel); await this._dataChannel.waitUntilReady(); this._dataChannel.onMessage(message=>{ console.log(`message from server: "${message}"`); if (message.startsWith("players add ")){ let name = message.split(" ").slice(2).join(" "); this._players.push(name); this._onPlayersListChangeCallbacks.forEach(callback=>callback(this._players)); }else if(message.startsWith("players list ")){ let json = message.split(" ").slice(2).join(" "); this._players = JSON.parse(json); this._onPlayersListChangeCallbacks.forEach(callback=>callback(this._players)); } }); })(); } /** * Waits until the connection to the server is ready. */ async waitUntilReady(){ return this._readyPromise; } /** * Joins the game with the given name. * @param {string} name */ async join(name){ this._dataChannel.send(`join ${name}`); let message = await this._dataChannel.next(); if (message!=="yup"){ throw new Error(`Failed to join! Server response: "${message}"`); } } /** * Registers a callback whenever the list of players in the game changes, and once when it is registered. * @param {(players:string[])=>void} callback */ onPlayersListChange(callback){ this._onPlayersListChangeCallbacks.push(callback); callback(this._players); } }