diff options
author | Thomas Hintz <t@thintz.com> | 2020-04-22 18:57:15 -0700 |
---|---|---|
committer | Thomas Hintz <t@thintz.com> | 2020-04-22 18:57:15 -0700 |
commit | b947c646cf6c3be92fc711c7988a93b52b3b6bdb (patch) | |
tree | e79a01ffccaabf870a1f4e37b02dc9becf46b8c0 | |
parent | 7ba6f19133377113d2521f3bcd790e16a35b21b3 (diff) | |
download | farm-leave-game.tar.gz |
wipleave-game
-rw-r--r-- | assets/img/cake.svg | 45 | ||||
-rw-r--r-- | src/components/farm/Board.jsx | 87 | ||||
-rw-r--r-- | src/components/farm/interface.js | 15 | ||||
-rw-r--r-- | src/components/farm/reducers.js | 7 | ||||
-rw-r--r-- | src/server/db.scm | 5 | ||||
-rw-r--r-- | src/server/farm.scm | 48 | ||||
-rw-r--r-- | src/style.scss | 2 |
7 files changed, 188 insertions, 21 deletions
diff --git a/assets/img/cake.svg b/assets/img/cake.svg new file mode 100644 index 0000000..c80f899 --- /dev/null +++ b/assets/img/cake.svg @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + version="1.1" + x="0px" + y="0px" + viewBox="0 0 80.125 79.983627" + xml:space="preserve" + id="svg4786" + sodipodi:docname="cake.svg" + width="80.125" + height="79.983627" + inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><metadata + id="metadata4792"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs + id="defs4790" /><sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="2560" + inkscape:window-height="1375" + id="namedview4788" + showgrid="false" + inkscape:zoom="9.424" + inkscape:cx="40.23" + inkscape:cy="27.714" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg4786" /><path + d="M 79.125,21.572625 H 62.26 v -7.523 c 2.469,-0.565 4.319,-2.775 4.319,-5.4129999 0,-2.758 -4.007,-7.411 -4.811,-8.31599999 -0.379,-0.428 -1.116,-0.427 -1.496,0 -0.803,0.90499999 -4.81,5.55899999 -4.81,8.31599999 0,2.8059999 2.092,5.1269999 4.798,5.4989999 v 7.437 H 48.247 v -7.523 c 2.469,-0.565 4.319,-2.775 4.319,-5.4129999 0,-2.758 -4.007,-7.411 -4.811,-8.31599999 -0.38,-0.428 -1.116,-0.427 -1.496,0 -0.803,0.90499999 -4.81,5.55899999 -4.81,8.31599999 0,2.8059999 2.092,5.1269999 4.798,5.4989999 v 7.437 H 34.233 v -7.523 c 2.469,-0.565 4.319,-2.775 4.319,-5.4129999 0,-2.758 -4.007,-7.411 -4.811,-8.31599999 -0.379,-0.428 -1.116,-0.427 -1.496,0 -0.803,0.90499999 -4.81,5.55899999 -4.81,8.31599999 0,2.8059999 2.092,5.1269999 4.798,5.4989999 v 7.437 H 20.219 v -7.523 c 2.469,-0.565 4.319,-2.775 4.319,-5.4129999 0,-2.758 -4.007,-7.411 -4.811,-8.31599999 -0.38,-0.428 -1.116,-0.427 -1.496,0 -0.803,0.90499999 -4.81,5.55899999 -4.81,8.31599999 0,2.8059999 2.092,5.1269999 4.798,5.4989999 v 7.437 H 1.129 c -0.552,0 -1,0.447 -1,1 v 8.891 c 0,0.062 0.006,0.123 0.017,0.182 0.062,3.042 1.68,5.705 4.084,7.237 v 26.175 H 3.543 c -1.954,0 -3.543,1.59 -3.543,3.543 v 2.023 c 0,1.683 1.181,3.089 2.757,3.449 0.007,0.027 0.002,0.054 0.012,0.081 l 1.717,4.771 c 0.254,0.702 1.133,1.059 2.613,1.059 h 65.803 c 1.48,0 2.359,-0.356 2.613,-1.06 l 1.717,-4.771 c 0.01,-0.027 0.005,-0.054 0.012,-0.081 1.575,-0.36 2.756,-1.766 2.756,-3.449 v -2.023 c 0,-1.953 -1.589,-3.543 -3.543,-3.543 H 75.77 v -26.013 c 2.601,-1.53 4.355,-4.351 4.355,-7.581 v -8.891 c 0,-0.552 -0.448,-0.999 -1,-0.999 z M 57.462,8.6356251 c 0,-1.337 1.953,-4.153 3.558,-6.11 1.668,2.035 3.559,4.833 3.559,6.11 0,1.9619999 -1.596,3.5579999 -3.559,3.5579999 -1.961,0 -3.558,-1.596 -3.558,-3.5579999 z m -14.013,0 c 0,-1.337 1.953,-4.153 3.558,-6.11 1.668,2.035 3.559,4.833 3.559,6.11 0,1.9619999 -1.596,3.5579999 -3.559,3.5579999 -1.962,0 -3.558,-1.596 -3.558,-3.5579999 z m -14.014,0 c 0,-1.337 1.953,-4.153 3.558,-6.11 1.668,2.035 3.559,4.833 3.559,6.11 0,1.9619999 -1.596,3.5579999 -3.559,3.5579999 -1.962,0 -3.558,-1.596 -3.558,-3.5579999 z m -14.014,0 c 0,-1.337 1.953,-4.153 3.558,-6.11 1.668,2.035 3.559,4.833 3.559,6.11 0,1.9619999 -1.596,3.5579999 -3.559,3.5579999 -1.961,0 -3.558,-1.596 -3.558,-3.5579999 z M 72.901,77.983625 H 7.099 c -0.38,0 -0.672,-0.038 -0.854,-0.077 l -1.346,-3.739 h 70.202 l -1.346,3.739 c -0.181,0.039 -0.474,0.077 -0.854,0.077 z m 5.099,-9.384 v 2.023 c 0,0.852 -0.692,1.544 -1.543,1.544 H 3.543 c -0.851,0 -1.543,-0.692 -1.543,-1.544 v -2.023 c 0,-0.851 0.692,-1.543 1.543,-1.543 h 72.914 c 0.851,0 1.543,0.692 1.543,1.543 z m -4.23,-3.543 H 6.23 v -25.229 c 0.855,0.278 1.765,0.433 2.712,0.433 3.383,0 6.327,-1.919 7.798,-4.727 1.472,2.808 4.415,4.727 7.798,4.727 3.383,0 6.327,-1.919 7.798,-4.727 1.472,2.808 4.415,4.727 7.798,4.727 3.383,0 6.327,-1.919 7.798,-4.727 1.472,2.808 4.415,4.727 7.798,4.727 3.383,0 6.326,-1.919 7.798,-4.727 1.472,2.808 4.415,4.727 7.798,4.727 0.848,0 1.666,-0.127 2.442,-0.352 v 25.148 z m 4.355,-33.594 c 0,3.748 -3.049,6.798 -6.798,6.798 -3.749,0 -6.798,-3.05 -6.798,-6.798 0,-0.553 -0.448,-1 -1,-1 -0.552,0 -1,0.447 -1,1 0,3.748 -3.049,6.798 -6.798,6.798 -3.749,0 -6.798,-3.05 -6.798,-6.798 0,-0.553 -0.448,-1 -1,-1 -0.552,0 -1,0.447 -1,1 0,3.748 -3.05,6.798 -6.798,6.798 -3.748,0 -6.798,-3.05 -6.798,-6.798 0,-0.553 -0.448,-1 -1,-1 -0.552,0 -1,0.447 -1,1 0,3.748 -3.05,6.798 -6.798,6.798 -3.748,0 -6.798,-3.05 -6.798,-6.798 0,-0.553 -0.448,-1 -1,-1 -0.552,0 -1,0.447 -1,1 0,3.748 -3.05,6.798 -6.798,6.798 -3.748,0 -6.798,-3.05 -6.798,-6.798 0,-0.059 -0.005,-0.116 -0.015,-0.172 v -7.719 h 75.996 v 7.891 z" + id="path4780" + inkscape:connector-curvature="0" /></svg>
\ No newline at end of file diff --git a/src/components/farm/Board.jsx b/src/components/farm/Board.jsx index f9a3143..74386ee 100644 --- a/src/components/farm/Board.jsx +++ b/src/components/farm/Board.jsx @@ -47,7 +47,8 @@ import { setSelectedCard, setMessagePanelSpace, setMPDims, movePlayer, setMovingSkip } from './actions.js' import { buy, roll, endTurn, loan, trade, submitTradeAccept, submitTradeDeny, submitTradeCancel, audit, - buyUncleBert, skip, endAiTurn, startGame } from './interface.js' + buyUncleBert, skip, endAiTurn, startGame, readyToStart, + leaveGame } from './interface.js' function netWorth(player) { return ((player.assets.hay + player.assets.grain) * 2000) + @@ -1810,6 +1811,11 @@ class AlertOverlay extends React.Component { this.hide(e); this.props.handler(); } + + cancelButtonClick = e => { + e.preventDefault(); + this.props.cancelHandler(); + } // <label><input type='checkbox' onClick={this.hidePermanent} /> {`Don't show again`}</label> render() { @@ -1823,7 +1829,17 @@ class AlertOverlay extends React.Component { <div className='alert-overlay-contents'> {this.props.children} <br /> - <Button onClick={this.buttonClick}>{this.props.buttonText}</Button> + <div> + <Button onClick={this.buttonClick} disabled={!!this.props.disabled}>{this.props.buttonText}</Button> + {this.props.cancelButtonText ? ( + <> + {' '} + <Button onClick={this.cancelButtonClick} disabled={!!this.props.cancelDisabled}> + {this.props.cancelButtonText} + </Button> + </> + ): (<></>)} + </div> {!this.props.preventHiding ? (<a onClick={this.hide}>close</a>) : (<></>)} </div> </div> @@ -1916,6 +1932,44 @@ class Info extends React.Component { } } +class StartGame extends React.Component { + render() { + const { auditThreshold, downPayment, loanInterest, maxDebt, startingOtbs, startingCash, startingDebt } = this.props.game.settings; + const { name } = this.props.game; + return ( + <> + <h1>Lobby</h1> + <p> + <b>Game</b>: {name} + </p> + <h3>Players</h3> + <ul> + <li>{this.props.player.name}</li> + {this.props.game.otherPlayers.map((p, i) => ( + <li key={i}> + {p.player.name} + </li> + ))} + </ul> + <h4>Game Settings</h4> + <ul> + <li><b>Audit Threshold</b>: ${formatMoney(auditThreshold)}</li> + <li><b>Max Debt</b>: ${formatMoney(maxDebt)}</li> + <li><b>Loan Interest</b>: {loanInterest * 100}%</li> + <li><b>Required Down Payment</b>: ${formatMoney(downPayment)}</li> + <li><b>Starting {itemCardShort}</b>: {startingOtbs}</li> + <li><b>Starting Cash</b>: ${formatMoney(startingCash)}</li> + <li><b>Starting Debt</b>: ${formatMoney(startingDebt)}</li> + </ul> + <label> + <input type="checkbox" onChange={this.props.toggleReady} /> + Ready to start + </label> + </> + ); + } +} + const SCREENS = { summary: 'summary', misc: 'misc', farms: 'farms', cards: 'cards', trade: 'trade', loans: 'loans', action: 'action', info: 'info', error: 'error' }; @@ -1933,7 +1987,8 @@ class BoardApp extends React.Component { screen: SCREENS.summary, card: props.ui.card, timerId: false, - currentPlayer: this.props.player + currentPlayer: this.props.player, + readyToStart: false }; this.myRef = React.createRef(); this.actionRef = React.createRef(); @@ -2038,6 +2093,11 @@ class BoardApp extends React.Component { } } + startGameToggleReady = () => { + this.setState(state => { return { readyToStart: !state.readyToStart }; }); + readyToStart(); + } + render() { let alertOverlay; const alert = this.props.ui.unhandledAlert; @@ -2079,21 +2139,16 @@ class BoardApp extends React.Component { alertHandled={this.props.alertHandled} buttonText='Start Game' hideHandler={() => 'nothing'} + cancelButtonText='Leave Game' + cancelHandler={leaveGame} + cancelDisabled={this.state.readyToStart} preventHiding={true} + disabled={!this.props.game.readyToStart} handler={startGame}> - <Fragment> - <h1>Pre Game</h1> - <p>When all players have joined click 'Start Game'!</p> - <h3>Players</h3> - <ul> - <li>{this.props.player.name}</li> - {this.props.game.otherPlayers.map((p, i) => ( - <li key={i}> - {p.player.name} - </li> - ))} - </ul> - </Fragment> + <StartGame player={this.props.player} + game={this.props.game} + toggleReady={this.startGameToggleReady} + /> </AlertOverlay> ); } else if (alert && alert.type === ALERTS.proposedTrade) { diff --git a/src/components/farm/interface.js b/src/components/farm/interface.js index 635b106..ff98acf 100644 --- a/src/components/farm/interface.js +++ b/src/components/farm/interface.js @@ -31,7 +31,7 @@ import { itemCard, fateCard } from 'game.js' export { initialize, buy, roll, endTurn, loan, trade, submitTradeAccept, submitTradeDeny, submitTradeCancel, audit, handleMessage, nextAction, buyUncleBert, actionsFinished, skip, endAiTurn, - startGame } + startGame, readyToStart, leaveGame } let store; let movingTimer = 0; @@ -46,6 +46,9 @@ function handleMessage(evt) { return; } batch(() => { + if (data.event === 'left-game') { + window.location.href = window.location.pathname; + } if (data.game.state === GAME_STATES.preGame) { store.dispatch(alert(ALERTS.preGame, '', 'pre-game')); } @@ -80,7 +83,7 @@ function handleMessage(evt) { store.dispatch(movePlayer(data.player.space, -1, data.player.color)); store.dispatch(setHarvestTable(data.harvestTable)); } - // new player(s) added to game, put them on the board + // player(s) added or removed from game, put them on the board if (data.game.otherPlayers.length !== store.getState().farm.game.otherPlayers.length) { const otherPlayers = store.getState().farm.game.otherPlayers; const newPlayers = data.game.otherPlayers.filter( @@ -199,6 +202,14 @@ function startGame() { sendCommand({ type: 'start-game' }); } +function readyToStart() { + sendCommand({ type: 'ready-to-start' }); +} + +function leaveGame() { + sendCommand({ type: 'leave-game' }); +} + // TODO share with Board.jsx // http://stackoverflow.com/questions/149055 function formatMoney(n) { diff --git a/src/components/farm/reducers.js b/src/components/farm/reducers.js index 865130b..0196ff0 100644 --- a/src/components/farm/reducers.js +++ b/src/components/farm/reducers.js @@ -105,10 +105,15 @@ const initialState = { state: GAME_STATES.preTurn, turn: 0, oldMessages: [], + name: '', settings: { downPayment: 0.2, loanInterest: 0.2, maxDebt: 50000, - auditThreshold: 250000 } + auditThreshold: 250000, + startingOtbs: 2, + startingCash: 5000, + startingDebt: 5000 }, + readyToStart: false }, ui: { card: { type: 'no-card', contents: '', total: 0 }, cards: [], diff --git a/src/server/db.scm b/src/server/db.scm index 17138e6..417207d 100644 --- a/src/server/db.scm +++ b/src/server/db.scm @@ -127,6 +127,11 @@ (exec (sql db "insert into user_games(user_id, game_id) values (?, ?);") user-id game-id))) +(define (db-remove-user-game user-id game-id) + (with-db (db) + (exec (sql db "delete from user_games where user_id=? and game_id=?;") + user-id game-id))) + (define (db-fetch-user-games user-id) (with-db (db) (query fetch-column diff --git a/src/server/farm.scm b/src/server/farm.scm index 7cc723e..53370d2 100644 --- a/src/server/farm.scm +++ b/src/server/farm.scm @@ -127,7 +127,8 @@ (mutex initform: (make-mutex 'player) accessor: player-mutex) (harvesting initform: #f accessor: player-harvesting) (hay-doubled initform: #f accessor: player-hay-doubled) - (corn-doubled initform: #f accessor: player-corn-doubled))) + (corn-doubled initform: #f accessor: player-corn-doubled) + (ready-to-start initform: #f accessor: player-ready-to-start))) (define-class <ai> (<player>) ((processing-turn initform: #f accessor: ai-processing-turn))) @@ -564,11 +565,19 @@ #f)) (state . ,(symbol->string (game-state g))) (turn . ,(game-turn g)) + (name . ,(game-name g)) (settings . ((downPayment . ,(game-setting 'down-payment g)) (loanInterest . ,(game-setting 'loan-interest g)) (maxDebt . ,(game-setting 'max-debt g)) (auditThreshold . ,(game-setting 'audit-threshold g)) - (trade . ,(game-setting 'trade g)))))))) + (startingOtbs . ,(game-setting 'starting-otbs g)) + (startingCash . ,(game-setting 'starting-cash g)) + (startingDebt . ,(game-setting 'starting-debt g)) + (trade . ,(game-setting 'trade g)))) + (readyToStart . ,(fold (lambda (p r) + (and (player-ready-to-start p) r)) + #t + (game-players g))))))) (define (buy-crop crop unnormalized-crop amount cash-value player game) (let ((total-cost (* amount (alist-ref unnormalized-crop @@ -1424,6 +1433,41 @@ (session-set! (sid) 'game-id #f) (session-set! (sid) 'user-id #f) (create-start-response "start-init")) + ((string=? type "ready-to-start") + (safe-set! (player-ready-to-start (*player*)) (not (player-ready-to-start (*player*)))) + (message-players! (*game*) (*player*) '() type: "update") + (create-ws-response (*player*) "update" '())) + ((string=? type "kick-player") + (let ((kicked-player (find (lambda (p) + (equal? (player-name p) (alist-ref 'name msg))) + (game-players (*game*))))) + (safe-set! (game-colors (*game*)) + (cons (player-color kicked-player) (game-colors (*game*)))) + (safe-set! (game-otbs (*game*)) + (append (game-otbs (*game*)) + (player-otbs kicked-player))) + (safe-set! (game-players (*game*)) + (filter (lambda (p) + (eq? p kicked-player)) + (game-players (*game*)))) + (db-remove-user-game (player-user-id kicked-player) (game-id (*game*)))) + (message-players! (*game*) (*player*) '() type: "update") + (create-ws-response (*player*) "update" '())) + ((string=? type "leave-game") + (safe-set! (game-colors (*game*)) + (cons (player-color (*player*)) (game-colors (*game*)))) + (safe-set! (game-otbs (*game*)) + (append (game-otbs (*game*)) + (player-otbs (*player*)))) + (safe-set! (game-players (*game*)) + (filter (lambda (p) + (not (eq? p (*player*)))) + (game-players (*game*)))) + (when (not (null? (game-players (*game*)))) + (safe-set! (game-current-player (*game*)) (car (game-players (*game*))))) + (db-remove-user-game (player-user-id (*player*)) (game-id (*game*))) + (message-players! (*game*) (*player*) '() type: "left-game") + (create-ws-response (*player*) "left-game" '())) ((string=? type "start-game") (safe-set! (game-state (*game*)) 'pre-turn) (db-update-game (game-id (*game*)) (symbol->string (game-state (*game*))) diff --git a/src/style.scss b/src/style.scss index df63c66..ecc8bbe 100644 --- a/src/style.scss +++ b/src/style.scss @@ -798,6 +798,8 @@ $trade-margin: 3rem; color: white; } .alert-overlay-contents { + max-height: 90vh; + overflow: auto; background: $light-color; padding: 2rem; display: flex; |