Skip to content
Snippets Groups Projects
SkribblClient.js 2.17 KiB
Newer Older
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);
	}