Newer
Older
import DataChannel from "./networking/DataChannel.js";
import Signaler from "./networking/Signaler.js";

Ben Eltschig
committed
/**
* @typedef {import("./SkribblServer.js").MessageToServer} MessageToServer
*/
/**
* @typedef {import("./SkribblServer.js").MessageToClient} MessageToClient
*/

Ben Eltschig
committed
/**
* Client/endpoint that manages a connection to a SkribblServer
*/
export default class SkribblClient {
/**
* Constructs a new client for a given game ID or DataChannel.

Ben Eltschig
committed
* @param {string|DataChannel<MessageToServer,MessageToClient>} idOrDataChannel
*/
constructor(idOrDataChannel){

Ben Eltschig
committed
/** @type {string[]} */
this._players = [];
/** @type {((players:string[])=>void)[]} */
this._onPlayersListChangeCallbacks = [];
this._readyPromise = (async()=>{

Ben Eltschig
committed
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}"`);

Ben Eltschig
committed
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;
}

Ben Eltschig
committed
this._onPlayersListChangeCallbacks.forEach(callback=>callback(this._players));
}
});
})();
}
/**
* Waits until the connection to the server is ready.
*/
async waitUntilReady(){
return this._readyPromise;
}

Ben Eltschig
committed
/**
* Joins the game with the given name.
* @param {string} name
*/
async join(name){

Ben Eltschig
committed
this._dataChannel.send({action:"join",name});

Ben Eltschig
committed
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);
}