import DataChannel from "./networking/DataChannel.js"; import Signaler from "./networking/Signaler.js"; /** * @typedef {import("./SkribblServer.js").MessageToServer} MessageToServer */ /** * @typedef {import("./SkribblServer.js").MessageToClient} MessageToClient */ /** * 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<MessageToServer,MessageToClient>} idOrDataChannel */ constructor(idOrDataChannel){ /** @type {string[]} */ this._players = []; /** @type {((players:string[])=>void)[]} */ this._onPlayersListChangeCallbacks = []; this._readyPromise = (async()=>{ if (idOrDataChannel instanceof DataChannel){ this._dataChannel = idOrDataChannel; }else{ /** @type {DataChannel<MessageToServer,MessageToClient>} */ this._dataChannel = DataChannel.from(await Signaler.join(idOrDataChannel),JSON.stringify,JSON.parse); } await this._dataChannel.waitUntilReady(); this._dataChannel.onMessage(message=>{ console.log(`message from server: "${message}"`); if (message!=="yup"&&message!=="nope"&&message.action=="updatePlayerList"){ let update = message.update; if (update.type=="add"){ this._players.push(update.player); }else if(update.type=="set"){ this._players = update.players; } 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({action:"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); } }