Better error handling, birthdays, startup otbs, resource caching.
This commit is contained in:
@@ -348,6 +348,7 @@ class PlayerSummary extends React.Component {
|
||||
<PlayerTurnContainer player={player}
|
||||
game={this.props.game}
|
||||
ui={this.props.ui}
|
||||
hideForLarge={this.props.hideForLarge}
|
||||
screen={this.props.screen}
|
||||
showScreen={this.props.showScreen}/>
|
||||
</GroupBox>
|
||||
@@ -426,7 +427,9 @@ class PlayerTurnContainer extends React.Component {
|
||||
<br />
|
||||
</>
|
||||
) : (<></>)}
|
||||
{view}
|
||||
<div className={this.props.hideForLarge ? 'hide-for-large' : ''}>
|
||||
{view}
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
@@ -1885,7 +1888,7 @@ class Info extends React.Component {
|
||||
|
||||
const SCREENS = { summary: 'summary', misc: 'misc', farms: 'farms',
|
||||
cards: 'cards', trade: 'trade', loans: 'loans',
|
||||
action: 'action', info: 'info' };
|
||||
action: 'action', info: 'info', error: 'error' };
|
||||
|
||||
class BoardApp extends React.Component {
|
||||
iconToScreen = { user: SCREENS.summary, 'window-restore': SCREENS.cards,
|
||||
@@ -1948,6 +1951,10 @@ class BoardApp extends React.Component {
|
||||
.find(p => p.player.name === this.props.game.currentPlayer).player;
|
||||
this.setState({ currentPlayer });
|
||||
}
|
||||
|
||||
if (!prevProps.ui.exn && this.props.ui.exn) {
|
||||
this.setState({ screen: SCREENS.error });
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -2170,6 +2177,7 @@ class BoardApp extends React.Component {
|
||||
<PlayerSummary player={this.props.player}
|
||||
ui={this.props.ui}
|
||||
screen={this.state.screen}
|
||||
hideForLarge={true}
|
||||
game={this.props.game} showScreen={this.showScreen} />
|
||||
</div>
|
||||
<div className={this.tabClass(SCREENS.action)}>
|
||||
@@ -2212,6 +2220,11 @@ class BoardApp extends React.Component {
|
||||
<div className={this.tabClass(SCREENS.info)}>
|
||||
<Info harvestTable={this.props.ui.harvestTable} game={this.props.game} />
|
||||
</div>
|
||||
<div className={this.tabClass(SCREENS.error)}>
|
||||
<h3>Error</h3>
|
||||
<p>A server error occured.</p>
|
||||
<p><a href="/?reload-game=true">Reload game</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<div className='static-tab-container show-for-large'>
|
||||
<div className='tab show'>
|
||||
|
||||
@@ -39,3 +39,4 @@ export const AUTO_SKIP = 'auto-skip'
|
||||
export const MESSAGE = 'message'
|
||||
export const SET_HARVEST_TABLE = 'set-harvest-table'
|
||||
export const SET_MOVING_SKIP = 'set-moving-skip'
|
||||
export const SERVER_ERROR = 'server-error'
|
||||
|
||||
@@ -21,13 +21,14 @@ import { UPDATE_GAME, UPDATE_PLAYER, GAME_STATE, SET_SELECTED_CARD, SET_CARDS,
|
||||
MP_MOUSE, SET_MP_DIMS, MARK_ACTION_CHANGE_HANDLED, SET_NEXT_ACTION,
|
||||
MOVE_PLAYER, NEXT_UI_ACTION, NEXT_UI_ACTION_SILENT, ALERT, ALERT_HANDLED,
|
||||
AUTO_SKIP, MESSAGE, SET_HARVEST_TABLE, SET_CARD_ERROR,
|
||||
SET_MOVING_SKIP } from './actionTypes.js'
|
||||
SET_MOVING_SKIP, SERVER_ERROR } from './actionTypes.js'
|
||||
|
||||
export { updateGame, updatePlayer, gameState, setSelectedCard, setCards,
|
||||
spacePushPlayer, spaceClearPlayers, setOldMessages, setMessagePanelSpace,
|
||||
mpMouse, setMPDims, movePlayer, setNextAction, nextUIAction,
|
||||
markActionChangeHandled, nextUIActionSilent, alert, alertHandled,
|
||||
autoSkip, message, setHarvestTable, setCardError, setMovingSkip }
|
||||
autoSkip, message, setHarvestTable, setCardError, setMovingSkip,
|
||||
serverError }
|
||||
|
||||
function updateGame(update) {
|
||||
return { type: UPDATE_GAME,
|
||||
@@ -135,3 +136,7 @@ function setHarvestTable(table) {
|
||||
function setMovingSkip(skip) {
|
||||
return { type: SET_MOVING_SKIP, skip };
|
||||
}
|
||||
|
||||
function serverError(exn) {
|
||||
return { type: SERVER_ERROR, exn };
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import { updateGame, updatePlayer, gameState, setSelectedCard, setCards,
|
||||
movePlayer, setOldMessages, markActionChangeHandled,
|
||||
mpMouse, rolled, setNextAction, nextUIAction, nextUIActionSilent, alert,
|
||||
autoSkip, message, alertHandled, setHarvestTable,
|
||||
setCardError, setMovingSkip } from './actions.js'
|
||||
setCardError, setMovingSkip, serverError } from './actions.js'
|
||||
import { itemCard, fateCard } from 'game.js'
|
||||
|
||||
export { initialize, buy, roll, endTurn, loan, trade, submitTradeAccept,
|
||||
@@ -42,6 +42,7 @@ function handleMessage(evt) {
|
||||
|
||||
if (data.event === 'error') {
|
||||
console.log('error:' + data.exn);
|
||||
store.dispatch(serverError(data.exn));
|
||||
return;
|
||||
}
|
||||
batch(() => {
|
||||
|
||||
@@ -22,7 +22,7 @@ import { UPDATE_GAME, UPDATE_PLAYER, GAME_STATE, SET_SELECTED_CARD, SET_CARDS,
|
||||
SET_MP_DIMS, MOVE_PLAYER, SET_NEXT_ACTION, NEXT_UI_ACTION,
|
||||
MARK_ACTION_CHANGE_HANDLED, NEXT_UI_ACTION_SILENT, ALERT, ALERT_HANDLED,
|
||||
AUTO_SKIP, MESSAGE, SET_HARVEST_TABLE, SET_CARD_ERROR,
|
||||
SET_MOVING_SKIP } from './actionTypes.js'
|
||||
SET_MOVING_SKIP, SERVER_ERROR } from './actionTypes.js'
|
||||
import { GAME_STATES } from '../../constants.js'
|
||||
import { spaceContent, corners } from 'game.js'
|
||||
|
||||
@@ -124,7 +124,8 @@ const initialState = {
|
||||
autoSkip: false,
|
||||
playerSpaces: {},
|
||||
movingSkip: false,
|
||||
harvestTable: false },
|
||||
harvestTable: false,
|
||||
exn: false },
|
||||
spaces: spaces,
|
||||
space: null,
|
||||
// message panel dimenions
|
||||
@@ -228,6 +229,8 @@ export default function(state = initialState, action) {
|
||||
return { ...state, ui: { ...state.ui, harvestTable: action.table }};
|
||||
case SET_MOVING_SKIP:
|
||||
return { ...state, ui: { ...state.ui, movingSkip: action.skip }};
|
||||
case SERVER_ERROR:
|
||||
return { ...state, ui: { ...state.ui, exn: action.exn }};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ import LoginOrCreateAccount from '../login-or-create-account/LoginOrCreateAccoun
|
||||
import { startOrJoinGame } from '../start/actions.js'
|
||||
import { start } from '../app/actions.js'
|
||||
|
||||
import { itemCardShort } from 'game.js'
|
||||
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faArrowCircleLeft, faCog } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
@@ -63,6 +65,7 @@ class NewGame extends React.Component {
|
||||
auditThreshold: 250000,
|
||||
startingCash: 5000,
|
||||
startingDebt: 5000,
|
||||
startingOtbs: 2,
|
||||
trade: true,
|
||||
showLogin: false
|
||||
};
|
||||
@@ -71,10 +74,10 @@ class NewGame extends React.Component {
|
||||
handleInputChange = e => {
|
||||
const target = e.target,
|
||||
value = target.type === 'checkbox' && target.name !== 'trade'
|
||||
? target.name : target.value,
|
||||
? target.name : target.value,
|
||||
|
||||
name = target.type === 'checkbox' && target.name !== 'trade'
|
||||
? 'checkedColor' : target.name;
|
||||
? 'checkedColor' : target.name;
|
||||
|
||||
this.setState({
|
||||
[name]: value
|
||||
@@ -98,122 +101,129 @@ class NewGame extends React.Component {
|
||||
|
||||
render() {
|
||||
let titleBar = !this.props.hideBack ? (
|
||||
<Fragment>
|
||||
<a onClick={this.handleBack}>
|
||||
<Fragment>
|
||||
<a onClick={this.handleBack}>
|
||||
<FontAwesomeIcon icon={faArrowCircleLeft} />
|
||||
</a>
|
||||
{this.props.title}
|
||||
</Fragment>
|
||||
) : this.props.title,
|
||||
</a>
|
||||
{this.props.title}
|
||||
</Fragment>
|
||||
) : this.props.title,
|
||||
colors = this.props.colors.map(c => (
|
||||
<label key={c} className={'player player-selectable player-' + c + (this.state.checkedColor === c ? ' player-selected' : '')}>
|
||||
<input type='checkbox'
|
||||
checked={this.state.checkedColor === c}
|
||||
onChange={this.handleInputChange}
|
||||
name={c} />
|
||||
<input type='checkbox'
|
||||
checked={this.state.checkedColor === c}
|
||||
onChange={this.handleInputChange}
|
||||
name={c} />
|
||||
</label>
|
||||
)
|
||||
),
|
||||
),
|
||||
gameName = this.props.showGameName && (
|
||||
<Row>
|
||||
<Col width='12'>
|
||||
<label>Game Name
|
||||
<input type='text' name='gameName' value={this.state.gameName}
|
||||
required
|
||||
onChange={this.handleInputChange} />
|
||||
</label>
|
||||
</Col>
|
||||
<Col width='12'>
|
||||
<label>Game Name
|
||||
<input type='text' name='gameName' value={this.state.gameName}
|
||||
required
|
||||
onChange={this.handleInputChange} />
|
||||
</label>
|
||||
</Col>
|
||||
</Row>
|
||||
),
|
||||
settingsClass = this.state.showSettings ? '' : 'hidden',
|
||||
mainScreenClass = !this.state.showSettings ? '' : 'hidden';
|
||||
return (
|
||||
<GroupBox title={titleBar}>
|
||||
{this.props.user ? (
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<div className={mainScreenClass}>
|
||||
<Row>
|
||||
<Col width='12'>
|
||||
<label>Your Color</label>
|
||||
{colors}
|
||||
<br /><br />
|
||||
</Col>
|
||||
</Row>
|
||||
{gameName}
|
||||
</div>
|
||||
<div className={settingsClass}>
|
||||
<InputRow label='Down Payment'
|
||||
name='downPayment'
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.1}
|
||||
value={this.state.downPayment}
|
||||
onChange={this.handleInputChange} />
|
||||
<InputRow label='Loan Interest'
|
||||
name='loanInterest'
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.1}
|
||||
value={this.state.loanInterest}
|
||||
onChange={this.handleInputChange} />
|
||||
<InputRow label='Maximum Debt'
|
||||
name='maxDebt'
|
||||
min={0}
|
||||
step={5000}
|
||||
value={this.state.maxDebt}
|
||||
onChange={this.handleInputChange} />
|
||||
<InputRow label='Audit Threshold'
|
||||
name='auditThreshold'
|
||||
min={0}
|
||||
step={25000}
|
||||
value={this.state.auditThreshold}
|
||||
onChange={this.handleInputChange} />
|
||||
<InputRow label='Starting Cash'
|
||||
name='startingCash'
|
||||
min={0}
|
||||
step={1000}
|
||||
value={this.state.startingCash}
|
||||
onChange={this.handleInputChange} />
|
||||
<InputRow label='Starting Debt'
|
||||
name='startingDebt'
|
||||
min={0}
|
||||
step={1000}
|
||||
value={this.state.startingDebt}
|
||||
onChange={this.handleInputChange} />
|
||||
<Row>
|
||||
<Col width='12'>
|
||||
<label>
|
||||
<input type='checkbox'
|
||||
checked={this.state.trade}
|
||||
onChange={this.handleInputChange}
|
||||
name='trade' />
|
||||
Enable Trading
|
||||
</label>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<Row>
|
||||
<Col width='12'>
|
||||
<div className='new-game-submit-container'>
|
||||
<Button type='submit'>{this.props.button} Game</Button>
|
||||
{this.props.showGameName ? (
|
||||
<a onClick={this.toggleSettings}>
|
||||
<FontAwesomeIcon icon={faCog} size='lg' />
|
||||
</a>
|
||||
) : (<Fragment />)}
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</form>
|
||||
) : (
|
||||
<>
|
||||
<span>Sign in or create account to continue</span>
|
||||
<LoginOrCreateAccount login={this.props.login}
|
||||
createAccount={this.props.createAccount}
|
||||
errors={this.props.errors}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{this.props.user ? (
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<div className={mainScreenClass}>
|
||||
<Row>
|
||||
<Col width='12'>
|
||||
<label>Your Color</label>
|
||||
{colors}
|
||||
<br /><br />
|
||||
</Col>
|
||||
</Row>
|
||||
{gameName}
|
||||
</div>
|
||||
<div className={settingsClass}>
|
||||
<InputRow label='Down Payment'
|
||||
name='downPayment'
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.1}
|
||||
value={this.state.downPayment}
|
||||
onChange={this.handleInputChange} />
|
||||
<InputRow label='Loan Interest'
|
||||
name='loanInterest'
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.1}
|
||||
value={this.state.loanInterest}
|
||||
onChange={this.handleInputChange} />
|
||||
<InputRow label='Maximum Debt'
|
||||
name='maxDebt'
|
||||
min={0}
|
||||
step={5000}
|
||||
value={this.state.maxDebt}
|
||||
onChange={this.handleInputChange} />
|
||||
<InputRow label='Audit Threshold'
|
||||
name='auditThreshold'
|
||||
min={0}
|
||||
step={25000}
|
||||
value={this.state.auditThreshold}
|
||||
onChange={this.handleInputChange} />
|
||||
<InputRow label='Starting Cash'
|
||||
name='startingCash'
|
||||
min={0}
|
||||
step={1000}
|
||||
value={this.state.startingCash}
|
||||
onChange={this.handleInputChange} />
|
||||
<InputRow label='Starting Debt'
|
||||
name='startingDebt'
|
||||
min={0}
|
||||
step={1000}
|
||||
value={this.state.startingDebt}
|
||||
onChange={this.handleInputChange} />
|
||||
<InputRow label={'Number of Starting ' + itemCardShort}
|
||||
name='startingOtbs'
|
||||
min={0}
|
||||
max={8}
|
||||
step={1}
|
||||
value={this.state.startingOtbs}
|
||||
onChange={this.handleInputChange} />
|
||||
<Row>
|
||||
<Col width='12'>
|
||||
<label>
|
||||
<input type='checkbox'
|
||||
checked={this.state.trade}
|
||||
onChange={this.handleInputChange}
|
||||
name='trade' />
|
||||
Enable Trading
|
||||
</label>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<Row>
|
||||
<Col width='12'>
|
||||
<div className='new-game-submit-container'>
|
||||
<Button type='submit'>{this.props.button} Game</Button>
|
||||
{this.props.showGameName ? (
|
||||
<a onClick={this.toggleSettings}>
|
||||
<FontAwesomeIcon icon={faCog} size='lg' />
|
||||
</a>
|
||||
) : (<Fragment />)}
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</form>
|
||||
) : (
|
||||
<>
|
||||
<span>Sign in or create account to continue</span>
|
||||
<LoginOrCreateAccount login={this.props.login}
|
||||
createAccount={this.props.createAccount}
|
||||
errors={this.props.errors}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</GroupBox>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user