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