Trading seems to be working
Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
parent
c6b29ff580
commit
4ab1aa9220
@ -7,19 +7,20 @@
|
|||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
margin: 0.25em;
|
margin: 0.25em;
|
||||||
cursor: pointer;
|
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: white;
|
color: white;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Resource[disabled] {
|
.Resource:not([disabled]) {
|
||||||
filter: grayscale(75%);
|
cursor: pointer;
|
||||||
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Resource:hover {
|
.Resource:not([disabled]):hover {
|
||||||
filter: brightness(150%);
|
filter: brightness(150%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,6 +541,10 @@ class Table extends React.Component {
|
|||||||
return this.sendAction('trade', 'accept', trade);
|
return this.sendAction('trade', 'accept', trade);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cancelTrade(trade) {
|
||||||
|
return this.sendAction('trade', 'cancel', trade);
|
||||||
|
}
|
||||||
|
|
||||||
rejectTrade(trade) {
|
rejectTrade(trade) {
|
||||||
return this.sendAction('trade', 'reject', trade);
|
return this.sendAction('trade', 'reject', trade);
|
||||||
}
|
}
|
||||||
@ -743,7 +747,7 @@ class Table extends React.Component {
|
|||||||
if (isDead) {
|
if (isDead) {
|
||||||
console.log(`Short circuiting keep-alive`);
|
console.log(`Short circuiting keep-alive`);
|
||||||
} else {
|
} else {
|
||||||
console.log(`${this.game.name} Resetting keep-alive: ${(Date.now() - this.game.startTime) / 1000}`);
|
console.log(`${this.game.name} Resetting keep-alive. Last ping: ${(Date.now() - this.lastPing) / 1000}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.keepAlive) {
|
if (this.keepAlive) {
|
||||||
@ -754,7 +758,7 @@ class Table extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.keepAlive = setTimeout(() => {
|
this.keepAlive = setTimeout(() => {
|
||||||
console.log(`${this.game.name} No ping after 10 seconds: ${(Date.now() - this.game.startTime) / 1000}`);
|
console.log(`${this.game.name} No ping after 10 seconds. Last ping: ${(Date.now() - this.lastPing) / 1000}`);
|
||||||
this.setState({ noNetwork: true });
|
this.setState({ noNetwork: true });
|
||||||
if (this.ws) {
|
if (this.ws) {
|
||||||
this.ws.close();
|
this.ws.close();
|
||||||
@ -786,9 +790,10 @@ class Table extends React.Component {
|
|||||||
console.log(`Attempting WebSocket connection to ${new_uri}`);
|
console.log(`Attempting WebSocket connection to ${new_uri}`);
|
||||||
|
|
||||||
this.ws = new WebSocket(new_uri);
|
this.ws = new WebSocket(new_uri);
|
||||||
|
this.lastPing = this.game.timestamp;
|
||||||
|
|
||||||
this.ws.addEventListener('open', (event) => {
|
this.ws.addEventListener('open', (event) => {
|
||||||
console.log(`${this.game.name} WebSocket open: Sending game-update request: ${(Date.now() - this.game.startTime) / 1000}`);
|
console.log(`${this.game.name} WebSocket open: Sending game-update request: ${(Date.now() - this.lastPing) / 1000}`);
|
||||||
this.ws.send(JSON.stringify({ type: 'game-update' }));
|
this.ws.send(JSON.stringify({ type: 'game-update' }));
|
||||||
this.resetKeepAlive();
|
this.resetKeepAlive();
|
||||||
});
|
});
|
||||||
@ -814,6 +819,7 @@ class Table extends React.Component {
|
|||||||
this.setError(error);
|
this.setError(error);
|
||||||
break;
|
break;
|
||||||
case 'ping':
|
case 'ping':
|
||||||
|
this.lastPing = data.ping;
|
||||||
this.ws.send(JSON.stringify({ type: 'pong', timestamp: data.ping }));
|
this.ws.send(JSON.stringify({ type: 'pong', timestamp: data.ping }));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -824,12 +830,12 @@ class Table extends React.Component {
|
|||||||
|
|
||||||
this.ws.addEventListener('error', (event) => {
|
this.ws.addEventListener('error', (event) => {
|
||||||
this.setState({ error: event.message });
|
this.setState({ error: event.message });
|
||||||
console.error(`${this.game.name} WebSocket error: ${(Date.now() - this.game.startTime) / 1000}`);
|
console.error(`${this.game.name} WebSocket error: ${(Date.now() - this.game.lastPing) / 1000}`);
|
||||||
this.resetKeepAlive(true);
|
this.resetKeepAlive(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.ws.addEventListener('close', (event) => {
|
this.ws.addEventListener('close', (event) => {
|
||||||
console.log(`${this.game.name} WebSocket close: ${(Date.now() - this.game.startTime) / 1000}`);
|
console.log(`${this.game.name} WebSocket close: ${(Date.now() - this.game.lastPing) / 1000}`);
|
||||||
this.setState({ error: event.message });
|
this.setState({ error: event.message });
|
||||||
this.resetKeepAlive(true);
|
this.resetKeepAlive(true);
|
||||||
});
|
});
|
||||||
@ -910,6 +916,10 @@ class Table extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
if (this.ws) {
|
||||||
|
this.ws.close();
|
||||||
|
this.ws = null;
|
||||||
|
}
|
||||||
if (this.loadTimer) {
|
if (this.loadTimer) {
|
||||||
clearTimeout(this.loadTimer);
|
clearTimeout(this.loadTimer);
|
||||||
this.loadTimer = 0;
|
this.loadTimer = 0;
|
||||||
|
@ -32,12 +32,6 @@
|
|||||||
margin: 0.5em 0;
|
margin: 0.5em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Trade .Resource {
|
|
||||||
cursor: pointer;
|
|
||||||
width: 3.75em; /* 5x7 aspect ratio */
|
|
||||||
height: 3.75em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Trade .Resource {
|
.Trade .Resource {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -53,6 +47,11 @@
|
|||||||
margin: 0.75rem;
|
margin: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Trade b {
|
||||||
|
margin-left: 0.25rem;
|
||||||
|
margin-right: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
.Trade .Direction {
|
.Trade .Direction {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -64,6 +63,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.Trade .Resource:hover {
|
.Trade .Resource:hover {
|
||||||
|
filter: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Trade .Transfer {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Trade .Transfer .Resource:hover {
|
||||||
filter: brightness(125%);
|
filter: brightness(125%);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,42 +117,52 @@
|
|||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.TradePlayer {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
width: 100%;
|
|
||||||
align-items: center;
|
|
||||||
padding: 2px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.TradePlayer > * {
|
|
||||||
margin-right: 0.25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Trade .Transfers {
|
.Trade .Transfers {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-items: flex-start;
|
justify-items: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Trade .ResourceCounter {
|
.Trade .TradeLine {
|
||||||
display: flex;
|
width: 100%;
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.TradeLine {
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
padding: 2px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.TradeLine > div {
|
.Trade .TradeLine > div {
|
||||||
display: flex;
|
display: inline-flex;
|
||||||
flex-grow: 1;
|
align-items: center;
|
||||||
|
margin-right: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.TradeLine > div > div {
|
.Trade .TradeLine > div > div {
|
||||||
margin-left: 0.25em;
|
margin-left: 0.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Trade .TradeLine .Resource {
|
||||||
|
height: 1.5rem;
|
||||||
|
width: 1.5rem;
|
||||||
|
min-width: 1.5rem;
|
||||||
|
min-height: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Trade .TradeLine .Resource > div {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
width: 1rem;
|
||||||
|
height: 1rem;
|
||||||
|
line-height: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Trade .TradeLine .TradeActions {
|
||||||
|
flex-grow: 1;
|
||||||
|
display: inline-flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Trade .TradeLine .TradeActions > * {
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
}
|
@ -71,21 +71,61 @@ const Trade = ({table}) => {
|
|||||||
gets: offer.gives.slice()
|
gets: offer.gives.slice()
|
||||||
};
|
};
|
||||||
let _gives = {}, _gets = {};
|
let _gives = {}, _gets = {};
|
||||||
|
console.log(gives, gets);
|
||||||
trade.gives.forEach(give => _gives[give.type] = give.count);
|
trade.gives.forEach(give => _gives[give.type] = give.count);
|
||||||
trade.gets.forEach(get => _gets[get.type] = get.count);
|
trade.gets.forEach(get => _gets[get.type] = get.count);
|
||||||
table.offerTrade(trade);
|
table.offerTrade(trade);
|
||||||
setGives(_gives);
|
console.log(_gives, _gets);
|
||||||
setGets(_gets);
|
setGives(Object.assign({}, empty, _gives));
|
||||||
|
setGets(Object.assign({}, empty, _gets));
|
||||||
}, [setGives, setGets, table]);
|
}, [setGives, setGets, table]);
|
||||||
|
|
||||||
let transfers = [];
|
let transfers = [];
|
||||||
|
|
||||||
transfers = [ 'brick', 'wood', 'wheat', 'sheep', 'stone' ].map(resource => { return createTransfer(resource); });
|
transfers = [ 'brick', 'wood', 'wheat', 'sheep', 'stone' ].map(resource => { return createTransfer(resource); });
|
||||||
|
|
||||||
if (!table.game) {
|
if (!table.game || !player) {
|
||||||
return (<></>);
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const canMeetOffer = (player, offer) => {
|
||||||
|
for (let i = 0; i < offer.gets.length; i++) {
|
||||||
|
const get = offer.gets[i];
|
||||||
|
if (player[get.type] < get.count) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const isCompatibleOffer = (player, offer) => {
|
||||||
|
let valid = player.gets.length === offer.gives.length &&
|
||||||
|
player.gives.length === offer.gets.length;
|
||||||
|
|
||||||
|
if (!valid) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.gets.forEach(get => {
|
||||||
|
if (!valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
valid = offer.gives.find(item =>
|
||||||
|
(item.type === get.type || item.type === '*') &&
|
||||||
|
item.count === get.count) !== undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (valid) player.gives.forEach(give => {
|
||||||
|
if (!valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
valid = offer.gets.find(item =>
|
||||||
|
(item.type === give.type || item.type === 'bank') &&
|
||||||
|
item.count === give.count) !== undefined;
|
||||||
|
});
|
||||||
|
return valid;
|
||||||
|
};
|
||||||
|
|
||||||
const game = table.game;
|
const game = table.game;
|
||||||
|
|
||||||
const isTurn = (table.game.turn && table.game.turn.color === table.game.color) ? true : false;
|
const isTurn = (table.game.turn && table.game.turn.color === table.game.color) ? true : false;
|
||||||
@ -108,6 +148,10 @@ const Trade = ({table}) => {
|
|||||||
table.offerTrade(trade);
|
table.offerTrade(trade);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cancelOffer = (offer) => {
|
||||||
|
table.cancelTrade(offer);
|
||||||
|
}
|
||||||
|
|
||||||
const acceptClicked = (offer) => {
|
const acceptClicked = (offer) => {
|
||||||
table.acceptTrade(offer);
|
table.acceptTrade(offer);
|
||||||
};
|
};
|
||||||
@ -116,32 +160,61 @@ const Trade = ({table}) => {
|
|||||||
table.cancelTrading();
|
table.cancelTrading();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Non-current player has rejected the active player's
|
/* Player has rejected the active player's bid or active player rejected
|
||||||
* bid */
|
* the other player's bid */
|
||||||
const rejectClicked = (trade) => {
|
const rejectClicked = (trade) => {
|
||||||
table.rejectTrade(trade);
|
table.rejectTrade(trade);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Create list of players with active trades */
|
||||||
let players = [];
|
let players = [];
|
||||||
for (let color in table.game.players) {
|
for (let color in table.game.players) {
|
||||||
const item = table.game.players[color],
|
const item = table.game.players[color],
|
||||||
name = getPlayerName(table.game.sessions, color);
|
name = getPlayerName(table.game.sessions, color);
|
||||||
if (name && table.game.name !== name) {
|
|
||||||
players.push({
|
/* Only list players with an offer */
|
||||||
name: name,
|
if (table.game.turn.name !== name &&
|
||||||
color: color,
|
(!item.gets || item.gets.length === 0
|
||||||
valid: false,
|
|| !item.gives || item.gives.lenght === 0)) {
|
||||||
gets: item.gets ? item.gets : [],
|
continue;
|
||||||
gives: item.gives ? item.gives : [],
|
|
||||||
offerRejected: item.offerRejected ? true : false
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (table.game.turn.name === name && item.negotiatorRejectedOffer) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tmp = {
|
||||||
|
self: table.game.name === name,
|
||||||
|
name: name,
|
||||||
|
color: color,
|
||||||
|
valid: false,
|
||||||
|
gets: item.gets ? item.gets : [],
|
||||||
|
gives: item.gives ? item.gives : [],
|
||||||
|
offerRejected: (table.game.turn.name !== name) ? (item.offerRejected ? true : false) : false,
|
||||||
|
negotiatorRejectedOffer: item.negotiatorRejectedOffer
|
||||||
|
};
|
||||||
|
tmp.canSubmit = (item.gets.length && item.gives.length);
|
||||||
|
players.push(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
players.sort((A, B) => {
|
players.sort((A, B) => {
|
||||||
return A.name.localeCompare(B.name);
|
return A.name.localeCompare(B.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const trade = {gives: [], gets: []};
|
||||||
|
for (let type in gives) {
|
||||||
|
if (gives[type]) {
|
||||||
|
trade.gets.push({ type, count: gives[type]});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let type in gets) {
|
||||||
|
if (gets[type]) {
|
||||||
|
trade.gives.push({ type, count: gets[type]});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const isOfferSubmitted = isCompatibleOffer(table.game.player, trade),
|
||||||
|
isOfferValid = trade.gives.length && trade.gets.length;
|
||||||
|
|
||||||
if (isTurn && table.game.player && table.game.player.banks) {
|
if (isTurn && table.game.player && table.game.player.banks) {
|
||||||
table.game.player.banks.forEach(bank => {
|
table.game.player.banks.forEach(bank => {
|
||||||
const count = (bank === 'bank') ? 3 : 2;
|
const count = (bank === 'bank') ? 3 : 2;
|
||||||
@ -163,105 +236,69 @@ const Trade = ({table}) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!player) {
|
|
||||||
return <></>;
|
|
||||||
}
|
|
||||||
|
|
||||||
let canAccept = false;
|
|
||||||
|
|
||||||
if (table.game.turn.offer) {
|
if (table.game.turn.offer) {
|
||||||
players.forEach(trade => {
|
if (isTurn) {
|
||||||
trade.valid = trade.gets.length
|
players.forEach(trade => trade.valid = isCompatibleOffer(table.game.turn.offer, trade));
|
||||||
&& trade.gives.length
|
} else {
|
||||||
&& trade.gets.length === game.turn.offer.gives.length
|
const found = players.find(item => item.name === table.game.turn.name);
|
||||||
&& trade.gives.length === game.turn.offer.gets.length;
|
if (found) {
|
||||||
if (!trade.valid) {
|
found.valid = canMeetOffer(player, table.game.turn.offer);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
trade.gets.forEach(get => {
|
}
|
||||||
if (!trade.valid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (get.type !== 'bank') {
|
|
||||||
const offer = table.game.turn.offer.gives.find(give => give.type === get.type);
|
|
||||||
trade.valid = offer && (offer.count === get.count);
|
|
||||||
} else {
|
|
||||||
/* Doesn't matter what the resource type is so long as there
|
|
||||||
* are enough of the one kind */
|
|
||||||
trade.valid = table.game.turn.offer.gives[0].count === get.count;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!trade.valid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
trade.gives.forEach(give => {
|
|
||||||
if (!trade.valid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (give.type !== '*') {
|
|
||||||
const offer = table.game.turn.offer.gets.find(get => give.type === get.type);
|
|
||||||
trade.valid = offer && (offer.count === give.count);
|
|
||||||
} else {
|
|
||||||
/* Doesn't matter what the resource type is so long as there
|
|
||||||
* are enough of the one kind */
|
|
||||||
trade.valid = table.game.turn.offer.gets[0].count === give.count;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
canAccept = true;
|
|
||||||
table.game.turn.offer.gets.forEach(item => {
|
|
||||||
if (!canAccept) {
|
|
||||||
canAccept = (item.type in game.player);
|
|
||||||
}
|
|
||||||
if (!canAccept) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
canAccept = (game.player[item.type] >= item.count);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
players = players.map((item, index) => {
|
players = players.map((item, index) => {
|
||||||
if (item.offerRejected) {
|
if (item.negotiatorRejectedOffer && isTurn) {
|
||||||
return <div className="TradePlayer" key={`player-${item.name}-${index}`}>
|
return <></>;
|
||||||
<PlayerColor color={item.color}/>
|
|
||||||
<div>{item.name}</div>
|
|
||||||
<div className='TradeLine'>
|
|
||||||
has rejected your offer.
|
|
||||||
</div>
|
|
||||||
</div>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const _gets = item.gets.map(get =>
|
const rejected = (item.offerRejected || item.negotiatorRejectedOffer);
|
||||||
`${get.count} ${(get.type === 'bank') ? 'of any one resource' : get.type}`)
|
|
||||||
.join(', '),
|
const _gets = item.gets.length ? item.gets.map((get, index) => <div key={`get-${get.type}-${index}`}>
|
||||||
_gives = item.gives.map(give =>
|
{ get.type === 'bank' && <div key={`get-bank-${index}`}><b>4</b> of any resource</div>}
|
||||||
`${give.count} ${(give.type === '*') ? 'of any resource' : give.type}`)
|
{ get.type !== 'bank' && <Resource key={`get-${get.type}-${index}`} disabled label type={get.type} count={get.count}/> }
|
||||||
.join(', ');
|
</div>) : undefined,
|
||||||
|
_gives = item.gives.length ? item.gives.map((give, index) => <div key={`give-${give.type}-${index}`}>
|
||||||
|
{ give.type === '*' && <><b>1</b> of any resource</>}
|
||||||
|
{ give.type !== '*' && <Resource disabled label type={give.type} count={give.count}/> }
|
||||||
|
</div>) : undefined
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="TradePlayer" key={`player-${item.name}-${index}`}>
|
<div className="TradeLine" key={`player-${item.name}-${index}`}>
|
||||||
<PlayerColor color={item.color}/>
|
<PlayerColor color={item.color}/>
|
||||||
<div>{item.name}</div>
|
{ rejected && <>Your offer to give {_gets} in exchange for {_gives} was rejected.</> }
|
||||||
<div className='TradeLine'>
|
{ !rejected && <>{item.self ? 'You' : item.name}</> }
|
||||||
{ _gets !== '' && _gives !== '' &&
|
{ !rejected && _gets && _gives &&
|
||||||
<div>wants {_gets} and will give {_gives}.
|
<>{item.self ? ' want' : ' wants'} {_gets} and will give {_gives}.</>
|
||||||
</div>
|
}
|
||||||
|
{ !rejected && (_gets === undefined || _gives === undefined) &&
|
||||||
|
<>{item.self ? ' have' : ' has'} not submitted a trade offer.</>
|
||||||
|
}
|
||||||
|
|
||||||
|
<div className="TradeActions">
|
||||||
|
{ !item.self && isTurn &&
|
||||||
|
<Button disabled={!item.valid}
|
||||||
|
onClick={() => acceptClicked(item)}>accept</Button>
|
||||||
}
|
}
|
||||||
{ (_gets === '' || _gives === '') &&
|
|
||||||
<div>has not submitted a trade offer.
|
{ !isTurn && item.color === table.game.turn.color &&
|
||||||
</div>
|
<Button disabled={!item.valid}
|
||||||
|
onClick={() => agreeClicked(item)}>agree</Button>
|
||||||
|
}
|
||||||
|
|
||||||
|
{ item.name !== 'The bank' && !item.self &&
|
||||||
|
<Button disabled={!item.gets.length ||
|
||||||
|
!item.gives.length || player.offerRejected}
|
||||||
|
onClick={() => rejectClicked(item)}>reject</Button>
|
||||||
|
}
|
||||||
|
|
||||||
|
{ item.self &&
|
||||||
|
<Button disabled={isOfferSubmitted || !isOfferValid} onClick={offerClicked}>Offer</Button>
|
||||||
|
}
|
||||||
|
|
||||||
|
{ item.self &&
|
||||||
|
<Button disabled onClick={() => cancelOffer(item)}>cancel</Button>
|
||||||
}
|
}
|
||||||
{ isTurn && <Button disabled={!item.valid}
|
|
||||||
onClick={() => acceptClicked(item)}>accept</Button> }
|
|
||||||
{ !isTurn && item.color === table.game.turn.color && <>
|
|
||||||
<Button disabled={!canAccept}
|
|
||||||
onClick={() => agreeClicked(item)}>agree</Button>
|
|
||||||
<Button disabled={!item.gets.length ||
|
|
||||||
!item.gives.length || player.offerRejected}
|
|
||||||
onClick={() => rejectClicked(item)}>reject</Button>
|
|
||||||
</> }
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -278,7 +315,7 @@ const Trade = ({table}) => {
|
|||||||
</div>
|
</div>
|
||||||
{ !player.haveResources && <b>You have no resources to participate in this trade.</b> }
|
{ !player.haveResources && <b>You have no resources to participate in this trade.</b> }
|
||||||
<Button
|
<Button
|
||||||
onClick={offerClicked}>Offer to give giveLine in exchange for getLine</Button>
|
onClick={offerClicked}>Offer</Button>
|
||||||
|
|
||||||
{ player.haveResources &&
|
{ player.haveResources &&
|
||||||
<div className="Transfers">
|
<div className="Transfers">
|
||||||
|
@ -176,6 +176,16 @@ const playerFromColor = (game, color) => {
|
|||||||
return undefined;
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const playerFromName = (game, name) => {
|
||||||
|
for (let id in game.sessions) {
|
||||||
|
if (game.sessions[id].name === name) {
|
||||||
|
return game.sessions[id].player;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const processGameOrder = (game, player, dice) => {
|
const processGameOrder = (game, player, dice) => {
|
||||||
let message;
|
let message;
|
||||||
|
|
||||||
@ -1554,6 +1564,7 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
|||||||
game.players[key].gives = [];
|
game.players[key].gives = [];
|
||||||
game.players[key].gets = [];
|
game.players[key].gets = [];
|
||||||
delete game.players[key].offerRejected;
|
delete game.players[key].offerRejected;
|
||||||
|
delete game.players[key].negotiatorRejectedOffer;
|
||||||
}
|
}
|
||||||
addActivity(game, session, `${name} requested to begin trading negotiations.`);
|
addActivity(game, session, `${name} requested to begin trading negotiations.`);
|
||||||
break;
|
break;
|
||||||
@ -1589,6 +1600,8 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
|||||||
|
|
||||||
session.player.gives = offer.gives;
|
session.player.gives = offer.gives;
|
||||||
session.player.gets = offer.gets;
|
session.player.gets = offer.gets;
|
||||||
|
delete session.player.offerRejected;
|
||||||
|
delete session.player.negotiatorRejectedOffer;
|
||||||
|
|
||||||
if (game.turn.name === name) {
|
if (game.turn.name === name) {
|
||||||
/* This is a new offer from the active player -- reset everyone's
|
/* This is a new offer from the active player -- reset everyone's
|
||||||
@ -1604,8 +1617,23 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
|||||||
|
|
||||||
/* Any player can reject an offer */
|
/* Any player can reject an offer */
|
||||||
if (value === 'reject') {
|
if (value === 'reject') {
|
||||||
session.player.offerRejected = true;
|
const offer = req.body;
|
||||||
addActivity(game, session, `${session.name} rejected ${game.turn.name}'s offer.`);
|
|
||||||
|
/* If the active player rejected an offer, they rejected another player */
|
||||||
|
if (game.turn.name === name) {
|
||||||
|
console.log(`Rejected `, offer);
|
||||||
|
const other = playerFromName(game, offer.name);
|
||||||
|
if (other) {
|
||||||
|
other.negotiatorRejectedOffer = true;
|
||||||
|
} else {
|
||||||
|
console.log(`Could not find ${offer.name}`);
|
||||||
|
}
|
||||||
|
addActivity(game, session, `${session.name} rejected ${offer.name}'s offer.`);
|
||||||
|
} else {
|
||||||
|
session.player.offerRejected = true;
|
||||||
|
addActivity(game, session, `${session.name} rejected ${game.turn.name}'s offer.`);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1674,10 +1702,11 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
|||||||
player[item.type] -= item.count;
|
player[item.type] -= item.count;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const from = (offer.name === 'The bank') ? 'the bank' : offer.name;
|
||||||
addChatMessage(game, session, `${session.name} traded ` +
|
addChatMessage(game, session, `${session.name} traded ` +
|
||||||
` ${offerToString(session.player)} ` +
|
` ${offerToString(session.player)} ` +
|
||||||
`from ${(offer.name === 'The bank') ? 'the bank' : offer.name}.`);
|
`from ${from}.`);
|
||||||
|
addActivity(game, session, `${session.name} accepted a trade from ${from}.`)
|
||||||
delete game.turn.offer;
|
delete game.turn.offer;
|
||||||
if (target) {
|
if (target) {
|
||||||
delete target.gives;
|
delete target.gives;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user