Implemented YoP and Monopoly
Lots of fixes Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
parent
83aafd981c
commit
96723e135c
@ -16,7 +16,7 @@ const Activity = ({ activity }) => {
|
||||
};
|
||||
|
||||
if (display) {
|
||||
setTimeout(() => hide(10000), 0);
|
||||
setTimeout(() => { hide(10000) }, 0);
|
||||
}
|
||||
|
||||
let message;
|
||||
|
@ -28,14 +28,17 @@
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
|
||||
.ChooseCard .Stack {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ChooseCard .Resource {
|
||||
width: 8em; /* 5x7 aspect ratio */
|
||||
/*
|
||||
width: 8em;
|
||||
height: 11.2em;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
*/
|
||||
}
|
||||
|
@ -1,21 +1,50 @@
|
||||
import React, { useState, useCallback } from "react";
|
||||
import "./ChooseCard.css";
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Resource from './Resource.js';
|
||||
|
||||
const ChooseCard = ({table, type}) => {
|
||||
const [cards, setCards] = useState([]);
|
||||
const count = (type === 'monopoly') ? 1 : 2;
|
||||
|
||||
const selectCard = useCallback((event) => {
|
||||
event.target.classList.toggle('Selected');
|
||||
|
||||
const selected = document.querySelectorAll('.ChooseCard .Selected');
|
||||
if (selected.length > count) {
|
||||
for (let i = 0; i < selected.length; i++) {
|
||||
selected[i].classList.remove('Selected');
|
||||
}
|
||||
setCards([]);
|
||||
return;
|
||||
}
|
||||
|
||||
let tmp = [];
|
||||
for (let i = 0; i < selected.length; i++) {
|
||||
tmp.push(selected[i].getAttribute('data-type'));
|
||||
}
|
||||
setCards(tmp);
|
||||
}, [ setCards ]);
|
||||
|
||||
if (!table.game) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
const selectCard = (card) => {
|
||||
table.selectResource(card);
|
||||
console.log(cards.length, count);
|
||||
|
||||
const submitCards = () => {
|
||||
table.selectResources(cards);
|
||||
}
|
||||
|
||||
const resources = [
|
||||
'wheat', 'brick', 'stone', 'sheep', 'wood'
|
||||
].map(type => {
|
||||
return <Resource type={type} key={type} count={1} select={() => selectCard(type)}/>;
|
||||
return <Resource
|
||||
key={type}
|
||||
type={type}
|
||||
count={count}
|
||||
onClick={selectCard}/>;
|
||||
});
|
||||
|
||||
let title;
|
||||
@ -24,7 +53,7 @@ const ChooseCard = ({table, type}) => {
|
||||
title = <><b>Monopoly</b>! Tap the resource type you want everyone to give you!</>;
|
||||
break;
|
||||
case 'year-of-plenty':
|
||||
title = <><b>Year of Plenty</b>! Tap the resource type and receive <b>2</b> from the bank!</>;
|
||||
title = <><b>Year of Plenty</b>! Tap the two resources you want to receive from the bank!</>;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -32,9 +61,10 @@ const ChooseCard = ({table, type}) => {
|
||||
<div className="ChooseCard">
|
||||
<Paper>
|
||||
<div className="Title">{ title }</div>
|
||||
<div style={{display: 'flex', flexDirection: 'row'}}>
|
||||
<div style={{display: 'flex', flexDirection: 'row', justifyContent: 'center'}}>
|
||||
{ resources }
|
||||
</div>
|
||||
<div className="Actions"><Button disabled={cards.length !== count} onClick={submitCards}>submit</Button></div>
|
||||
</Paper>
|
||||
</div>
|
||||
);
|
||||
|
@ -430,7 +430,7 @@ class Table extends React.Component {
|
||||
this.buildClicked = this.buildClicked.bind(this);
|
||||
this.closeCard = this.closeCard.bind(this);
|
||||
this.playCard = this.playCard.bind(this);
|
||||
this.selectResource = this.selectResource.bind(this);
|
||||
this.selectResources = this.selectResources.bind(this);
|
||||
|
||||
this.mouse = { x: 0, y: 0 };
|
||||
this.radius = 0.317;
|
||||
@ -503,8 +503,8 @@ class Table extends React.Component {
|
||||
return this.sendAction('chat', undefined, {message: message});
|
||||
}
|
||||
|
||||
selectResource(card) {
|
||||
return this.sendAction('select-resource', card);
|
||||
selectResources(cards) {
|
||||
return this.sendAction('select-resources', undefined, cards);
|
||||
}
|
||||
|
||||
playCard(card) {
|
||||
@ -569,7 +569,7 @@ class Table extends React.Component {
|
||||
if (this.errorTimeout) {
|
||||
clearTimeout(this.errorTimeout);
|
||||
}
|
||||
setTimeout(() => this.setState({error: undefined}), 3000);
|
||||
setTimeout(() => { this.setState({error: undefined}) }, 3000);
|
||||
if (this.state.error !== error) {
|
||||
this.setState({ error });
|
||||
}
|
||||
@ -951,7 +951,7 @@ class Table extends React.Component {
|
||||
const game = this.state.game,
|
||||
player = game ? game.player : undefined,
|
||||
isTurn = (game && game.turn && game.turn.color === game.color) ? true : false,
|
||||
showMessage = (game && game.state === 'lobby');
|
||||
showMessage = (game && (game.state === 'lobby' || !game.name));
|
||||
|
||||
let color;
|
||||
switch (game ? game.color : undefined) {
|
||||
@ -1057,7 +1057,7 @@ class Table extends React.Component {
|
||||
{ game
|
||||
&& isTurn
|
||||
&& game.turn.actions
|
||||
&& game.turn.actions.indexOf('select-resource') !== -1 &&
|
||||
&& game.turn.actions.indexOf('select-resources') !== -1 &&
|
||||
<ChooseCard table={this} type={game.turn.active}/>
|
||||
}
|
||||
|
||||
|
@ -762,18 +762,26 @@ const setPlayerName = (game, session, name) => {
|
||||
if (session.color) {
|
||||
return `You cannot change your name while you have a color selected.`;
|
||||
}
|
||||
|
||||
let rejoin = false;
|
||||
/* Check to ensure name is not already in use */
|
||||
if (game && name) for (let key in game.sessions) {
|
||||
const tmp = game.sessions[key];
|
||||
if (tmp === session) {
|
||||
continue;
|
||||
}
|
||||
if (tmp.name && tmp.name.toLowerCase() === name.toLowerCase()) {
|
||||
if (!tmp.player || (Date.now() - tmp.player.lastActive) > 60000) {
|
||||
rejoin = true;
|
||||
Object.assign(session, tmp);
|
||||
console.log(`${name} has been reallocated to a new session.`);
|
||||
console.log({ old: game.sessions[key], new: session });
|
||||
delete game.sessions[key];
|
||||
} else {
|
||||
return `${name} is already taken and has been active in the last minute.`;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log(`Attempting to create new player for ${name}`);
|
||||
}
|
||||
|
||||
if (name.toLowerCase() === 'the bank') {
|
||||
@ -789,7 +797,11 @@ const setPlayerName = (game, session, name) => {
|
||||
if (!old) {
|
||||
message = `A new player has entered the lobby as ${name}.`;
|
||||
} else {
|
||||
message = `${old} has changed their name to ${name}.`;
|
||||
if (rejoin) {
|
||||
message = `${name} has rejoined the game! Welcome back, ${name}.`;
|
||||
} else {
|
||||
message = `${old} has changed their name to ${name}.`;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return `You can not set your name to nothing!`;
|
||||
@ -1558,7 +1570,7 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
||||
const name = session.name;
|
||||
let message, index;
|
||||
|
||||
let corners, corner, card;
|
||||
let corners, corner, card, cards;
|
||||
|
||||
switch (action) {
|
||||
case "trade":
|
||||
@ -1857,7 +1869,7 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
||||
break;
|
||||
}
|
||||
let victim = game.players[value];
|
||||
const cards = [];
|
||||
cards = [];
|
||||
[ 'wheat', 'brick', 'sheep', 'stone', 'wood' ].forEach(field => {
|
||||
for (let i = 0; i < victim[field]; i++) {
|
||||
cards.push(field);
|
||||
@ -2000,12 +2012,12 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
||||
placeRoad(game, roads);
|
||||
break;
|
||||
case 'monopoly':
|
||||
game.turn.actions = [ 'select-resource' ];
|
||||
game.turn.actions = [ 'select-resources' ];
|
||||
game.turn.active = 'monopoly';
|
||||
addActivity(game, session, `${session.name} played the Monopoly card, and is selecting their resource type to claim.`);
|
||||
break;
|
||||
case 'year-of-plenty':
|
||||
game.turn.actions = [ 'select-resource' ];
|
||||
game.turn.actions = [ 'select-resources' ];
|
||||
game.turn.active = 'year-of-plenty';
|
||||
addActivity(game, session, `${session.name} played the Year of Plenty card.`);
|
||||
break;
|
||||
@ -2045,9 +2057,9 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
||||
|
||||
break;
|
||||
|
||||
case 'select-resource':
|
||||
case 'select-resources':
|
||||
if (!game || !game.turn || !game.turn.actions ||
|
||||
game.turn.actions.indexOf('select-resource') === -1) {
|
||||
game.turn.actions.indexOf('select-resources') === -1) {
|
||||
error = `Please, let's not cheat. Ok?`;
|
||||
console.log(game);
|
||||
break;
|
||||
@ -2058,26 +2070,53 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
||||
break;
|
||||
}
|
||||
|
||||
const type = value.trim();
|
||||
switch (type) {
|
||||
case 'wheat':
|
||||
case 'brick':
|
||||
case 'sheep':
|
||||
case 'stone':
|
||||
case 'wood':
|
||||
const count = (game.turn.active === 'monopoly') ? 1 : 2;
|
||||
|
||||
cards = req.body;
|
||||
|
||||
if (!cards || cards.length > count || cards.length === 0) {
|
||||
error = `You have chosen the wrong number of cards!`;
|
||||
break;
|
||||
default:
|
||||
error = `That is not a valid resource type!`;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
const isValidCard = (type) => {
|
||||
switch (type.trim()) {
|
||||
case 'wheat':
|
||||
case 'brick':
|
||||
case 'sheep':
|
||||
case 'stone':
|
||||
case 'wood':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
const selected = {};
|
||||
cards.forEach(card => {
|
||||
if (!isValidCard(card)) {
|
||||
error = `Invalid resource type!`;
|
||||
}
|
||||
if (card in selected) {
|
||||
selected[card]++;
|
||||
} else {
|
||||
selected[card] = 1;
|
||||
}
|
||||
});
|
||||
const display = [];
|
||||
for (let card in selected) {
|
||||
display.push(`${selected[card]} ${card}`);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
break;
|
||||
}
|
||||
addActivity(game, session, `${session.name} has chosen ${type}!`);
|
||||
|
||||
addActivity(game, session, `${session.name} has chosen ${display.join(', ')}!`);
|
||||
|
||||
switch (game.turn.active) {
|
||||
case 'monopoly':
|
||||
const gave = [];
|
||||
const gave = [], type = cards[0];
|
||||
let total = 0;
|
||||
for (let color in game.players) {
|
||||
const player = game.players[color];
|
||||
@ -2103,8 +2142,10 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
||||
break;
|
||||
|
||||
case 'year-of-plenty':
|
||||
session.player[type] += 2;
|
||||
addChatMessage(game, session, `${session.name} received 2 ${type} from the bank.`);
|
||||
cards.forEach(type => {
|
||||
session.player[type]++;
|
||||
});
|
||||
addChatMessage(game, session, `${session.name} received ${display.join(', ')} from the bank.`);
|
||||
break;
|
||||
}
|
||||
delete game.turn.active;
|
||||
@ -2620,6 +2661,11 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
||||
})
|
||||
|
||||
const ping = (session) => {
|
||||
if (!session.ws) {
|
||||
console.log(`Not sending ping to ${session.name} -- connection does not exist.`);
|
||||
return;
|
||||
}
|
||||
|
||||
session.ping = Date.now();
|
||||
console.log(`Sending ping to ${session.name}`);
|
||||
session.ws.send(JSON.stringify({ type: 'ping', ping: session.ping }));
|
||||
@ -2629,17 +2675,63 @@ const ping = (session) => {
|
||||
session.keepAlive = setTimeout(() => { ping(session); }, 2500);
|
||||
}
|
||||
|
||||
const wsInactive = (game, req) => {
|
||||
const session = getSession(game, req.session);
|
||||
|
||||
if (session && session.ws) {
|
||||
console.log(`Closing WebSocket to ${session.name} due to inactivity.`);
|
||||
session.ws.close();
|
||||
session.ws = undefined;
|
||||
}
|
||||
|
||||
/* Prevent future pings */
|
||||
if (req.keepAlive) {
|
||||
clearTimeout(req.keepAlive);
|
||||
}
|
||||
}
|
||||
|
||||
const resetDisconnectCheck = (game, req) => {
|
||||
if (req.disconnectCheck) {
|
||||
clearTimeout(req.disconnectCheck);
|
||||
}
|
||||
//req.disconnectCheck = setTimeout(() => { wsInactive(game, req) }, 20000);
|
||||
}
|
||||
|
||||
router.ws("/ws/:id", async (ws, req) => {
|
||||
const { id } = req.params;
|
||||
|
||||
/* Setup WebSocket event handlers prior to performing any async calls or
|
||||
* we may miss the first messages from clients */
|
||||
ws.on('error', (event) => {
|
||||
ws.on('error', async (event) => {
|
||||
console.error(`WebSocket error: `, event.message);
|
||||
const game = await loadGame(id);
|
||||
if (game) {
|
||||
const session = getSession(game, req.session);
|
||||
if (session && session.ws) {
|
||||
session.ws.close();
|
||||
session.ws = undefined;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ws.on('open', (event) => {
|
||||
ws.on('open', async (event) => {
|
||||
console.log(`WebSocket open: `, event.message);
|
||||
const game = await loadGame(id);
|
||||
if (game) {
|
||||
resetDisconnectCheck(game, req);
|
||||
}
|
||||
});
|
||||
|
||||
ws.on('close', async (event) => {
|
||||
const game = await loadGame(id);
|
||||
if (game) {
|
||||
const session = getSession(game, req.session);
|
||||
console.log(`WebSocket closed for ${session.name}`);
|
||||
if (session && session.ws) {
|
||||
session.ws.close();
|
||||
session.ws = undefined;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ws.on('message', async (message) => {
|
||||
@ -2656,9 +2748,11 @@ router.ws("/ws/:id", async (ws, req) => {
|
||||
switch (data.type) {
|
||||
case 'pong':
|
||||
console.log(`Latency for ${session.name ? session.name : 'Unammed'} is ${Date.now() - data.timestamp}`);
|
||||
resetDisconnectCheck(game, req);
|
||||
break;
|
||||
case 'game-update':
|
||||
console.log(`Player ${session.name ? session.name : 'Unnamed'} requested a game update.`);
|
||||
resetDisconnectCheck(game, req);
|
||||
sendGame(req, undefined, game, undefined, ws);
|
||||
break;
|
||||
}
|
||||
@ -2678,6 +2772,8 @@ router.ws("/ws/:id", async (ws, req) => {
|
||||
|
||||
const session = getSession(game, req.session);
|
||||
|
||||
resetDisconnectCheck(game, req);
|
||||
|
||||
console.log(`WebSocket connect from game ${id}:${session.name ? session.name : "Unnamed"}`);
|
||||
|
||||
if (session) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user