UNPKG

boardgame.io

Version:
1,167 lines (1,024 loc) 38.6 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } require('./Debug-0ac3084e.js'); require('redux'); var turnOrder = require('./turn-order-d6c2e620.js'); require('immer'); require('./reducer-76d3a4df.js'); require('flatted'); var ai = require('./ai-1fb7bf89.js'); require('./initialize-18a8be06.js'); var client = require('./client-35f9483f.js'); var React = _interopDefault(require('react')); var PropTypes = _interopDefault(require('prop-types')); var Cookies = _interopDefault(require('react-cookies')); require('./base-bdd9c13b.js'); var socketio = require('./socketio-5ad3ebc5.js'); require('./master-2ed30af7.js'); require('socket.io-client'); /* * Copyright 2017 The boardgame.io Authors * * Use of this source code is governed by a MIT-style * license that can be found in the LICENSE file or at * https://opensource.org/licenses/MIT. */ /** * Client * * boardgame.io React client. * * @param {...object} game - The return value of `Game`. * @param {...object} numPlayers - The number of players. * @param {...object} board - The React component for the game. * @param {...object} loading - (optional) The React component for the loading state. * @param {...object} multiplayer - Set to a falsy value or a transportFactory, e.g., SocketIO() * @param {...object} debug - Enables the Debug UI. * @param {...object} enhancer - Optional enhancer to send to the Redux store * * Returns: * A React component that wraps board and provides an * API through props for it to interact with the framework * and dispatch actions such as MAKE_MOVE, GAME_EVENT, RESET, * UNDO and REDO. */ function Client(opts) { var _a; let { game, numPlayers, loading, board, multiplayer, enhancer, debug } = opts; // Component that is displayed before the client has synced // with the game master. if (loading === undefined) { const Loading = () => React.createElement("div", { className: "bgio-loading" }, "connecting..."); loading = Loading; } /* * WrappedBoard * * The main React component that wraps the passed in * board component and adds the API to its props. */ return _a = class WrappedBoard extends React.Component { constructor(props) { super(props); if (debug === undefined) { debug = props.debug; } this.client = client.Client({ game, debug, numPlayers, multiplayer, gameID: props.gameID, playerID: props.playerID, credentials: props.credentials, enhancer, }); } componentDidMount() { this.unsubscribe = this.client.subscribe(() => this.forceUpdate()); this.client.start(); } componentWillUnmount() { this.client.stop(); this.unsubscribe(); } componentDidUpdate(prevProps) { if (this.props.gameID != prevProps.gameID) { this.client.updateGameID(this.props.gameID); } if (this.props.playerID != prevProps.playerID) { this.client.updatePlayerID(this.props.playerID); } if (this.props.credentials != prevProps.credentials) { this.client.updateCredentials(this.props.credentials); } } render() { const state = this.client.getState(); if (state === null) { return React.createElement(loading); } let _board = null; if (board) { _board = React.createElement(board, { ...state, ...this.props, isMultiplayer: !!multiplayer, moves: this.client.moves, events: this.client.events, gameID: this.client.gameID, playerID: this.client.playerID, reset: this.client.reset, undo: this.client.undo, redo: this.client.redo, log: this.client.log, gameMetadata: this.client.gameMetadata, }); } return React.createElement("div", { className: "bgio-client" }, _board); } }, _a.propTypes = { // The ID of a game to connect to. // Only relevant in multiplayer. gameID: PropTypes.string, // The ID of the player associated with this client. // Only relevant in multiplayer. playerID: PropTypes.string, // This client's authentication credentials. // Only relevant in multiplayer. credentials: PropTypes.string, // Enable / disable the Debug UI. debug: PropTypes.any, }, _a.defaultProps = { gameID: 'default', playerID: null, credentials: null, debug: true, }, _a; } /* * Copyright 2018 The boardgame.io Authors * * Use of this source code is governed by a MIT-style * license that can be found in the LICENSE file or at * https://opensource.org/licenses/MIT. */ var _LobbyConnectionImpl = /*#__PURE__*/ function () { function _LobbyConnectionImpl(_ref) { var server = _ref.server, gameComponents = _ref.gameComponents, playerName = _ref.playerName, playerCredentials = _ref.playerCredentials; turnOrder._classCallCheck(this, _LobbyConnectionImpl); this.gameComponents = gameComponents; this.playerName = playerName || 'Visitor'; this.playerCredentials = playerCredentials; this.server = server; this.rooms = []; } turnOrder._createClass(_LobbyConnectionImpl, [{ key: "_baseUrl", value: function _baseUrl() { return "".concat(this.server || '', "/games"); } }, { key: "refresh", value: async function refresh() { try { this.rooms.length = 0; var resp = await fetch(this._baseUrl()); if (resp.status !== 200) { throw new Error('HTTP status ' + resp.status); } var json = await resp.json(); var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = json[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var gameName = _step.value; if (!this._getGameComponents(gameName)) continue; var gameResp = await fetch(this._baseUrl() + '/' + gameName); var gameJson = await gameResp.json(); var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = gameJson.rooms[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var inst = _step2.value; inst.gameName = gameName; } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2["return"] != null) { _iterator2["return"](); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } this.rooms = this.rooms.concat(gameJson.rooms); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator["return"] != null) { _iterator["return"](); } } finally { if (_didIteratorError) { throw _iteratorError; } } } } catch (error) { throw new Error('failed to retrieve list of games (' + error + ')'); } } }, { key: "_getGameInstance", value: function _getGameInstance(gameID) { var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = this.rooms[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var inst = _step3.value; if (inst['gameID'] === gameID) return inst; } } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3["return"] != null) { _iterator3["return"](); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } } }, { key: "_getGameComponents", value: function _getGameComponents(gameName) { var _iteratorNormalCompletion4 = true; var _didIteratorError4 = false; var _iteratorError4 = undefined; try { for (var _iterator4 = this.gameComponents[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { var comp = _step4.value; if (comp.game.name === gameName) return comp; } } catch (err) { _didIteratorError4 = true; _iteratorError4 = err; } finally { try { if (!_iteratorNormalCompletion4 && _iterator4["return"] != null) { _iterator4["return"](); } } finally { if (_didIteratorError4) { throw _iteratorError4; } } } } }, { key: "_findPlayer", value: function _findPlayer(playerName) { var _iteratorNormalCompletion5 = true; var _didIteratorError5 = false; var _iteratorError5 = undefined; try { for (var _iterator5 = this.rooms[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) { var inst = _step5.value; if (inst.players.some(function (player) { return player.name === playerName; })) return inst; } } catch (err) { _didIteratorError5 = true; _iteratorError5 = err; } finally { try { if (!_iteratorNormalCompletion5 && _iterator5["return"] != null) { _iterator5["return"](); } } finally { if (_didIteratorError5) { throw _iteratorError5; } } } } }, { key: "join", value: async function join(gameName, gameID, playerID) { try { var inst = this._findPlayer(this.playerName); if (inst) { throw new Error('player has already joined ' + inst.gameID); } inst = this._getGameInstance(gameID); if (!inst) { throw new Error('game instance ' + gameID + ' not found'); } var resp = await fetch(this._baseUrl() + '/' + gameName + '/' + gameID + '/join', { method: 'POST', body: JSON.stringify({ playerID: playerID, playerName: this.playerName }), headers: { 'Content-Type': 'application/json' } }); if (resp.status !== 200) throw new Error('HTTP status ' + resp.status); var json = await resp.json(); inst.players[Number.parseInt(playerID)].name = this.playerName; this.playerCredentials = json.playerCredentials; } catch (error) { throw new Error('failed to join room ' + gameID + ' (' + error + ')'); } } }, { key: "leave", value: async function leave(gameName, gameID) { try { var inst = this._getGameInstance(gameID); if (!inst) throw new Error('game instance not found'); var _iteratorNormalCompletion6 = true; var _didIteratorError6 = false; var _iteratorError6 = undefined; try { for (var _iterator6 = inst.players[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) { var player = _step6.value; if (player.name === this.playerName) { var resp = await fetch(this._baseUrl() + '/' + gameName + '/' + gameID + '/leave', { method: 'POST', body: JSON.stringify({ playerID: player.id, credentials: this.playerCredentials }), headers: { 'Content-Type': 'application/json' } }); if (resp.status !== 200) { throw new Error('HTTP status ' + resp.status); } delete player.name; delete this.playerCredentials; return; } } } catch (err) { _didIteratorError6 = true; _iteratorError6 = err; } finally { try { if (!_iteratorNormalCompletion6 && _iterator6["return"] != null) { _iterator6["return"](); } } finally { if (_didIteratorError6) { throw _iteratorError6; } } } throw new Error('player not found in room'); } catch (error) { throw new Error('failed to leave room ' + gameID + ' (' + error + ')'); } } }, { key: "disconnect", value: async function disconnect() { var inst = this._findPlayer(this.playerName); if (inst) { await this.leave(inst.gameName, inst.gameID); } this.rooms = []; this.playerName = 'Visitor'; } }, { key: "create", value: async function create(gameName, numPlayers) { try { var comp = this._getGameComponents(gameName); if (!comp) throw new Error('game not found'); if (numPlayers < comp.game.minPlayers || numPlayers > comp.game.maxPlayers) throw new Error('invalid number of players ' + numPlayers); var resp = await fetch(this._baseUrl() + '/' + gameName + '/create', { method: 'POST', body: JSON.stringify({ numPlayers: numPlayers }), headers: { 'Content-Type': 'application/json' } }); if (resp.status !== 200) throw new Error('HTTP status ' + resp.status); } catch (error) { throw new Error('failed to create room for ' + gameName + ' (' + error + ')'); } } }]); return _LobbyConnectionImpl; }(); /** * LobbyConnection * * Lobby model. * * @param {string} server - '<host>:<port>' of the server. * @param {Array} gameComponents - A map of Board and Game objects for the supported games. * @param {string} playerName - The name of the player. * @param {string} playerCredentials - The credentials currently used by the player, if any. * * Returns: * A JS object that synchronizes the list of running game instances with the server and provides an API to create/join/start instances. */ function LobbyConnection(opts) { return new _LobbyConnectionImpl(opts); } var LobbyLoginForm = /*#__PURE__*/ function (_React$Component) { turnOrder._inherits(LobbyLoginForm, _React$Component); function LobbyLoginForm() { var _getPrototypeOf2; var _this; turnOrder._classCallCheck(this, LobbyLoginForm); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = turnOrder._possibleConstructorReturn(this, (_getPrototypeOf2 = turnOrder._getPrototypeOf(LobbyLoginForm)).call.apply(_getPrototypeOf2, [this].concat(args))); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "state", { playerName: _this.props.playerName, nameErrorMsg: '' }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "onClickEnter", function () { if (_this.state.playerName === '') return; _this.props.onEnter(_this.state.playerName); }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "onKeyPress", function (event) { if (event.key === 'Enter') { _this.onClickEnter(); } }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "onChangePlayerName", function (event) { var name = event.target.value.trim(); _this.setState({ playerName: name, nameErrorMsg: name.length > 0 ? '' : 'empty player name' }); }); return _this; } turnOrder._createClass(LobbyLoginForm, [{ key: "render", value: function render() { return React.createElement("div", null, React.createElement("p", { className: "phase-title" }, "Choose a player name:"), React.createElement("input", { type: "text", value: this.state.playerName, onChange: this.onChangePlayerName, onKeyPress: this.onKeyPress }), React.createElement("span", { className: "buttons" }, React.createElement("button", { className: "buttons", onClick: this.onClickEnter }, "Enter")), React.createElement("br", null), React.createElement("span", { className: "error-msg" }, this.state.nameErrorMsg, React.createElement("br", null))); } }]); return LobbyLoginForm; }(React.Component); turnOrder._defineProperty(LobbyLoginForm, "propTypes", { playerName: PropTypes.string, onEnter: PropTypes.func.isRequired }); turnOrder._defineProperty(LobbyLoginForm, "defaultProps", { playerName: '' }); var LobbyRoomInstance = /*#__PURE__*/ function (_React$Component) { turnOrder._inherits(LobbyRoomInstance, _React$Component); function LobbyRoomInstance() { var _getPrototypeOf2; var _this; turnOrder._classCallCheck(this, LobbyRoomInstance); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = turnOrder._possibleConstructorReturn(this, (_getPrototypeOf2 = turnOrder._getPrototypeOf(LobbyRoomInstance)).call.apply(_getPrototypeOf2, [this].concat(args))); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "_createSeat", function (player) { return player.name || '[free]'; }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "_createButtonJoin", function (inst, seatId) { return React.createElement("button", { key: 'button-join-' + inst.gameID, onClick: function onClick() { return _this.props.onClickJoin(inst.gameName, inst.gameID, '' + seatId); } }, "Join"); }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "_createButtonLeave", function (inst) { return React.createElement("button", { key: 'button-leave-' + inst.gameID, onClick: function onClick() { return _this.props.onClickLeave(inst.gameName, inst.gameID); } }, "Leave"); }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "_createButtonPlay", function (inst, seatId) { return React.createElement("button", { key: 'button-play-' + inst.gameID, onClick: function onClick() { return _this.props.onClickPlay(inst.gameName, { gameID: inst.gameID, playerID: '' + seatId, numPlayers: inst.players.length }); } }, "Play"); }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "_createButtonSpectate", function (inst) { return React.createElement("button", { key: 'button-spectate-' + inst.gameID, onClick: function onClick() { return _this.props.onClickPlay(inst.gameName, { gameID: inst.gameID, numPlayers: inst.players.length }); } }, "Spectate"); }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "_createInstanceButtons", function (inst) { var playerSeat = inst.players.find(function (player) { return player.name === _this.props.playerName; }); var freeSeat = inst.players.find(function (player) { return !player.name; }); if (playerSeat && freeSeat) { // already seated: waiting for game to start return _this._createButtonLeave(inst); } if (freeSeat) { // at least 1 seat is available return _this._createButtonJoin(inst, freeSeat.id); } // room is full if (playerSeat) { return React.createElement("div", null, [_this._createButtonPlay(inst, playerSeat.id), _this._createButtonLeave(inst)]); } // allow spectating return _this._createButtonSpectate(inst); }); return _this; } turnOrder._createClass(LobbyRoomInstance, [{ key: "render", value: function render() { var room = this.props.room; var status = 'OPEN'; if (!room.players.find(function (player) { return !player.name; })) { status = 'RUNNING'; } return React.createElement("tr", { key: 'line-' + room.gameID }, React.createElement("td", { key: 'cell-name-' + room.gameID }, room.gameName), React.createElement("td", { key: 'cell-status-' + room.gameID }, status), React.createElement("td", { key: 'cell-seats-' + room.gameID }, room.players.map(this._createSeat).join(', ')), React.createElement("td", { key: 'cell-buttons-' + room.gameID }, this._createInstanceButtons(room))); } }]); return LobbyRoomInstance; }(React.Component); turnOrder._defineProperty(LobbyRoomInstance, "propTypes", { room: PropTypes.shape({ gameName: PropTypes.string.isRequired, gameID: PropTypes.string.isRequired, players: PropTypes.array.isRequired }), playerName: PropTypes.string.isRequired, onClickJoin: PropTypes.func.isRequired, onClickLeave: PropTypes.func.isRequired, onClickPlay: PropTypes.func.isRequired }); var LobbyCreateRoomForm = /*#__PURE__*/ function (_React$Component) { turnOrder._inherits(LobbyCreateRoomForm, _React$Component); function LobbyCreateRoomForm(props) { var _this; turnOrder._classCallCheck(this, LobbyCreateRoomForm); _this = turnOrder._possibleConstructorReturn(this, turnOrder._getPrototypeOf(LobbyCreateRoomForm).call(this, props)); /* fix min and max number of players */ turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "state", { selectedGame: 0, numPlayers: 2 }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "_createGameNameOption", function (game, idx) { return React.createElement("option", { key: 'name-option-' + idx, value: idx }, game.game.name); }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "_createNumPlayersOption", function (idx) { return React.createElement("option", { key: 'num-option-' + idx, value: idx }, idx); }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "_createNumPlayersRange", function (game) { return turnOrder._toConsumableArray(new Array(game.maxPlayers + 1).keys()).slice(game.minPlayers); }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "onChangeNumPlayers", function (event) { _this.setState({ numPlayers: Number.parseInt(event.target.value) }); }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "onChangeSelectedGame", function (event) { var idx = Number.parseInt(event.target.value); _this.setState({ selectedGame: idx, numPlayers: _this.props.games[idx].game.minPlayers }); }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "onClickCreate", function () { _this.props.createGame(_this.props.games[_this.state.selectedGame].game.name, _this.state.numPlayers); }); var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = props.games[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var game = _step.value; var game_details = game.game; if (!game_details.minPlayers) { game_details.minPlayers = 1; } if (!game_details.maxPlayers) { game_details.maxPlayers = 4; } console.assert(game_details.maxPlayers >= game_details.minPlayers); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator["return"] != null) { _iterator["return"](); } } finally { if (_didIteratorError) { throw _iteratorError; } } } _this.state = { selectedGame: 0, numPlayers: props.games[0].game.minPlayers }; return _this; } turnOrder._createClass(LobbyCreateRoomForm, [{ key: "render", value: function render() { var _this2 = this; return React.createElement("div", null, React.createElement("select", { value: this.state.selectedGame, onChange: function onChange(evt) { return _this2.onChangeSelectedGame(evt); } }, this.props.games.map(this._createGameNameOption)), React.createElement("span", null, "Players:"), React.createElement("select", { value: this.state.numPlayers, onChange: this.onChangeNumPlayers }, this._createNumPlayersRange(this.props.games[this.state.selectedGame].game).map(this._createNumPlayersOption)), React.createElement("span", { className: "buttons" }, React.createElement("button", { onClick: this.onClickCreate }, "Create"))); } }]); return LobbyCreateRoomForm; }(React.Component); turnOrder._defineProperty(LobbyCreateRoomForm, "propTypes", { games: PropTypes.array.isRequired, createGame: PropTypes.func.isRequired }); var LobbyPhases = { ENTER: 'enter', PLAY: 'play', LIST: 'list' }; /** * Lobby * * React lobby component. * * @param {Array} gameComponents - An array of Board and Game objects for the supported games. * @param {string} lobbyServer - Address of the lobby server (for example 'localhost:8000'). * If not set, defaults to the server that served the page. * @param {string} gameServer - Address of the game server (for example 'localhost:8001'). * If not set, defaults to the server that served the page. * @param {function} clientFactory - Function that is used to create the game clients. * @param {number} refreshInterval - Interval between server updates (default: 2000ms). * @param {bool} debug - Enable debug information (default: false). * * Returns: * A React component that provides a UI to create, list, join, leave, play or spectate game instances. */ var Lobby = /*#__PURE__*/ function (_React$Component) { turnOrder._inherits(Lobby, _React$Component); function Lobby(_props) { var _this; turnOrder._classCallCheck(this, Lobby); _this = turnOrder._possibleConstructorReturn(this, turnOrder._getPrototypeOf(Lobby).call(this, _props)); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "state", { phase: LobbyPhases.ENTER, playerName: 'Visitor', runningGame: null, errorMsg: '', credentialStore: {} }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "_createConnection", function (props) { var name = _this.state.playerName; _this.connection = LobbyConnection({ server: props.lobbyServer, gameComponents: props.gameComponents, playerName: name, playerCredentials: _this.state.credentialStore[name] }); }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "_updateCredentials", function (playerName, credentials) { _this.setState(function (prevState) { // clone store or componentDidUpdate will not be triggered var store = Object.assign({}, prevState.credentialStore); store[[playerName]] = credentials; return { credentialStore: store }; }); }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "_updateConnection", async function () { await _this.connection.refresh(); _this.forceUpdate(); }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "_enterLobby", function (playerName) { _this.setState({ playerName: playerName, phase: LobbyPhases.LIST }); }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "_exitLobby", async function () { await _this.connection.disconnect(); _this.setState({ phase: LobbyPhases.ENTER, errorMsg: '' }); }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "_createRoom", async function (gameName, numPlayers) { try { await _this.connection.create(gameName, numPlayers); await _this.connection.refresh(); // rerender _this.setState({}); } catch (error) { _this.setState({ errorMsg: error.message }); } }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "_joinRoom", async function (gameName, gameID, playerID) { try { await _this.connection.join(gameName, gameID, playerID); await _this.connection.refresh(); _this._updateCredentials(_this.connection.playerName, _this.connection.playerCredentials); } catch (error) { _this.setState({ errorMsg: error.message }); } }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "_leaveRoom", async function (gameName, gameID) { try { await _this.connection.leave(gameName, gameID); await _this.connection.refresh(); _this._updateCredentials(_this.connection.playerName, _this.connection.playerCredentials); } catch (error) { _this.setState({ errorMsg: error.message }); } }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "_startGame", function (gameName, gameOpts) { var gameCode = _this.connection._getGameComponents(gameName); if (!gameCode) { _this.setState({ errorMsg: 'game ' + gameName + ' not supported' }); return; } var multiplayer = undefined; if (gameOpts.numPlayers > 1) { if (_this.props.gameServer) { multiplayer = socketio.SocketIO({ server: _this.props.gameServer }); } else { multiplayer = socketio.SocketIO(); } } if (gameOpts.numPlayers == 1) { var maxPlayers = gameCode.game.maxPlayers; var bots = {}; for (var i = 1; i < maxPlayers; i++) { bots[i + ''] = ai.MCTSBot; } multiplayer = socketio.Local({ bots: bots }); } var app = _this.props.clientFactory({ game: gameCode.game, board: gameCode.board, debug: _this.props.debug, multiplayer: multiplayer }); var game = { app: app, gameID: gameOpts.gameID, playerID: gameOpts.numPlayers > 1 ? gameOpts.playerID : '0', credentials: _this.connection.playerCredentials }; _this.setState({ phase: LobbyPhases.PLAY, runningGame: game }); }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "_exitRoom", function () { _this.setState({ phase: LobbyPhases.LIST, runningGame: null }); }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "_getPhaseVisibility", function (phase) { return _this.state.phase !== phase ? 'hidden' : 'phase'; }); turnOrder._defineProperty(turnOrder._assertThisInitialized(_this), "renderRooms", function (rooms, playerName) { return rooms.map(function (room) { var gameID = room.gameID, gameName = room.gameName, players = room.players; return React.createElement(LobbyRoomInstance, { key: 'instance-' + gameID, room: { gameID: gameID, gameName: gameName, players: Object.values(players) }, playerName: playerName, onClickJoin: _this._joinRoom, onClickLeave: _this._leaveRoom, onClickPlay: _this._startGame }); }); }); _this._createConnection(_this.props); setInterval(_this._updateConnection, _this.props.refreshInterval); return _this; } turnOrder._createClass(Lobby, [{ key: "componentDidMount", value: function componentDidMount() { var cookie = Cookies.load('lobbyState') || {}; if (cookie.phase && cookie.phase === LobbyPhases.PLAY) { cookie.phase = LobbyPhases.LIST; } this.setState({ phase: cookie.phase || LobbyPhases.ENTER, playerName: cookie.playerName || 'Visitor', credentialStore: cookie.credentialStore || {} }); } }, { key: "componentDidUpdate", value: function componentDidUpdate(prevProps, prevState) { var name = this.state.playerName; var creds = this.state.credentialStore[name]; if (prevState.phase !== this.state.phase || prevState.credentialStore[name] !== creds || prevState.playerName !== name) { this._createConnection(this.props); this._updateConnection(); var cookie = { phase: this.state.phase, playerName: name, credentialStore: this.state.credentialStore }; Cookies.save('lobbyState', cookie, { path: '/' }); } } }, { key: "render", value: function render() { var _this$props = this.props, gameComponents = _this$props.gameComponents, renderer = _this$props.renderer; var _this$state = this.state, errorMsg = _this$state.errorMsg, playerName = _this$state.playerName, phase = _this$state.phase, runningGame = _this$state.runningGame; if (renderer) { return renderer({ errorMsg: errorMsg, gameComponents: gameComponents, rooms: this.connection.rooms, phase: phase, playerName: playerName, runningGame: runningGame, handleEnterLobby: this._enterLobby, handleExitLobby: this._exitLobby, handleCreateRoom: this._createRoom, handleJoinRoom: this._joinRoom, handleLeaveRoom: this._leaveRoom, handleExitRoom: this._exitRoom, handleRefreshRooms: this._updateConnection, handleStartGame: this._startGame }); } return React.createElement("div", { id: "lobby-view", style: { padding: 50 } }, React.createElement("div", { className: this._getPhaseVisibility(LobbyPhases.ENTER) }, React.createElement(LobbyLoginForm, { key: playerName, playerName: playerName, onEnter: this._enterLobby })), React.createElement("div", { className: this._getPhaseVisibility(LobbyPhases.LIST) }, React.createElement("p", null, "Welcome, ", playerName), React.createElement("div", { className: "phase-title", id: "game-creation" }, React.createElement("span", null, "Create a room:"), React.createElement(LobbyCreateRoomForm, { games: gameComponents, createGame: this._createRoom })), React.createElement("p", { className: "phase-title" }, "Join a room:"), React.createElement("div", { id: "instances" }, React.createElement("table", null, React.createElement("tbody", null, this.renderRooms(this.connection.rooms, playerName))), React.createElement("span", { className: "error-msg" }, errorMsg, React.createElement("br", null))), React.createElement("p", { className: "phase-title" }, "Rooms that become empty are automatically deleted.")), React.createElement("div", { className: this._getPhaseVisibility(LobbyPhases.PLAY) }, runningGame && React.createElement(runningGame.app, { gameID: runningGame.gameID, playerID: runningGame.playerID, credentials: runningGame.credentials }), React.createElement("div", { className: "buttons", id: "game-exit" }, React.createElement("button", { onClick: this._exitRoom }, "Exit game"))), React.createElement("div", { className: "buttons", id: "lobby-exit" }, React.createElement("button", { onClick: this._exitLobby }, "Exit lobby"))); } }]); return Lobby; }(React.Component); turnOrder._defineProperty(Lobby, "propTypes", { gameComponents: PropTypes.array.isRequired, lobbyServer: PropTypes.string, gameServer: PropTypes.string, debug: PropTypes.bool, clientFactory: PropTypes.func, refreshInterval: PropTypes.number }); turnOrder._defineProperty(Lobby, "defaultProps", { debug: false, clientFactory: Client, refreshInterval: 2000 }); exports.Client = Client; exports.Lobby = Lobby;