Reconnects all seem to be working, except in video
Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
parent
76c243c5f1
commit
41753d8011
@ -49,6 +49,8 @@ const Table = () => {
|
|||||||
const [buildActive, setBuildActive] = useState(false);
|
const [buildActive, setBuildActive] = useState(false);
|
||||||
const [cardActive, setCardActive] = useState(undefined);
|
const [cardActive, setCardActive] = useState(undefined);
|
||||||
const [winnerDismissed, setWinnerDismissed] = useState(undefined);
|
const [winnerDismissed, setWinnerDismissed] = useState(undefined);
|
||||||
|
const [global, setGlobal] = useState({ setPeers });
|
||||||
|
const [count, setCount] = useState(0);
|
||||||
const fields = [ 'id', 'state', 'color', 'name', 'private' ];
|
const fields = [ 'id', 'state', 'color', 'name', 'private' ];
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -159,11 +161,25 @@ const Table = () => {
|
|||||||
|
|
||||||
const resetConnection = cbResetConnection();
|
const resetConnection = cbResetConnection();
|
||||||
|
|
||||||
|
if (global.ws !== connection
|
||||||
|
|| global.name !== name
|
||||||
|
|| global.gameId !== gameId
|
||||||
|
|| global.peers !== peers) {
|
||||||
|
console.log(`board - (app) - setting global`, global,
|
||||||
|
{connection, name, gameId, peers});
|
||||||
|
setGlobal({
|
||||||
|
ws: connection,
|
||||||
|
name, gameId, peers,
|
||||||
|
setPeers
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const onWsError = (event) => {
|
const onWsError = (event) => {
|
||||||
console.error(`ws: error`, event);
|
console.error(`ws: error`, event);
|
||||||
const error = `Connection to Ketr Ketran game server failed! ` +
|
const error = `Connection to Ketr Ketran game server failed! ` +
|
||||||
`Connection attempt will be retried every 5 seconds.`;
|
`Connection attempt will be retried every 5 seconds.`;
|
||||||
setError(error);
|
setError(error);
|
||||||
|
setGlobal(Object.assign({}, global, { ws: undefined }));
|
||||||
setWs(undefined); /* clear the socket */
|
setWs(undefined); /* clear the socket */
|
||||||
setConnection(undefined); /* clear the connection */
|
setConnection(undefined); /* clear the connection */
|
||||||
resetConnection();
|
resetConnection();
|
||||||
@ -174,6 +190,7 @@ const Table = () => {
|
|||||||
`Attempting to reconnect...`;
|
`Attempting to reconnect...`;
|
||||||
console.warn(`ws: close`);
|
console.warn(`ws: close`);
|
||||||
setError(error);
|
setError(error);
|
||||||
|
setGlobal(Object.assign({}, global, { ws: undefined }));
|
||||||
setWs(undefined); /* clear the socket */
|
setWs(undefined); /* clear the socket */
|
||||||
setConnection(undefined); /* clear the connection */
|
setConnection(undefined); /* clear the connection */
|
||||||
resetConnection();
|
resetConnection();
|
||||||
@ -258,11 +275,12 @@ const Table = () => {
|
|||||||
} else {
|
} else {
|
||||||
new_uri = "ws";
|
new_uri = "ws";
|
||||||
}
|
}
|
||||||
new_uri = `${new_uri}://${loc.host}${base}/api/v1/games/ws/${gameId}`;
|
new_uri = `${new_uri}://${loc.host}${base}/api/v1/games/ws/${gameId}?${count}`;
|
||||||
console.log(`Attempting WebSocket connection to ${new_uri}`);
|
console.log(`Attempting WebSocket connection to ${new_uri}`);
|
||||||
setWs(new WebSocket(new_uri));
|
setWs(new WebSocket(new_uri));
|
||||||
setConnection(undefined);
|
setConnection(undefined);
|
||||||
setRetryConnection(false);
|
setRetryConnection(false);
|
||||||
|
setCount(count + 1);
|
||||||
return unbind;
|
return unbind;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,9 +305,14 @@ const Table = () => {
|
|||||||
ws.removeEventListener('error', cbError);
|
ws.removeEventListener('error', cbError);
|
||||||
ws.removeEventListener('message', cbMessage);
|
ws.removeEventListener('message', cbMessage);
|
||||||
}
|
}
|
||||||
}, [ setWs, connection, setConnection, retryConnection, setRetryConnection, gameId, ws, refWsOpen, refWsMessage, refWsClose, refWsError ]);
|
}, [ ws, setWs, connection, setConnection,
|
||||||
|
retryConnection, setRetryConnection, gameId,
|
||||||
|
refWsOpen, refWsMessage, refWsClose, refWsError, count, setCount
|
||||||
|
]);
|
||||||
|
|
||||||
return <GlobalContext.Provider value={{ ws: connection, name, gameId, peers, setPeers }}>
|
console.log(`board - (app) - Render with ws: ${ws ? '!' : ''}NULL, connection: ${connection ? '!' : ''}NULL`);
|
||||||
|
|
||||||
|
return <GlobalContext.Provider value={global}>
|
||||||
<MediaAgent/>
|
<MediaAgent/>
|
||||||
{ /* <PingPong/> */ }
|
{ /* <PingPong/> */ }
|
||||||
<div className="Table">
|
<div className="Table">
|
||||||
|
@ -56,13 +56,9 @@ const Board = () => {
|
|||||||
'placements', 'turn', 'state', 'color', 'longestRoadLength'
|
'placements', 'turn', 'state', 'color', 'longestRoadLength'
|
||||||
], []);
|
], []);
|
||||||
|
|
||||||
console.log(`board - render ws is ${!ws ? 'NULL' : (ws.readyState === ws.OPEN ? 'OPEN' : '!OPEN')}`);
|
console.log(`board - ws`, ws);
|
||||||
|
|
||||||
const onWsMessage = (event) => {
|
const onWsMessage = (event) => {
|
||||||
if (hack !== ws) {
|
|
||||||
console.error(`Setting hack`)
|
|
||||||
hack = ws;
|
|
||||||
}
|
|
||||||
if (ws && ws !== event.target) {
|
if (ws && ws !== event.target) {
|
||||||
console.error(`Disconnect occur?`);
|
console.error(`Disconnect occur?`);
|
||||||
}
|
}
|
||||||
@ -141,30 +137,24 @@ const Board = () => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const refWs = useRef(ws);
|
|
||||||
const refWsMessage = useRef(onWsMessage);
|
const refWsMessage = useRef(onWsMessage);
|
||||||
useEffect(() => { refWsMessage.current = onWsMessage; });
|
useEffect(() => { refWsMessage.current = onWsMessage; });
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!ws) { return; }
|
if (ws !== hack) {
|
||||||
refWs.current = ws;
|
console.log(`board - setting out-of-scope hack`);
|
||||||
console.log('board - bind');
|
hack = ws;
|
||||||
if (hack !== ws) {
|
|
||||||
console.log(`board - ws and hack are different`);
|
|
||||||
}
|
}
|
||||||
|
if (!ws) { return; }
|
||||||
|
console.log('board - bind');
|
||||||
const cbMessage = e => refWsMessage.current(e);
|
const cbMessage = e => refWsMessage.current(e);
|
||||||
ws.addEventListener('message', cbMessage);
|
ws.addEventListener('message', cbMessage);
|
||||||
return () => {
|
return () => {
|
||||||
console.log('board - unbind');
|
console.log('board - unbind');
|
||||||
ws.removeEventListener('message', cbMessage);
|
ws.removeEventListener('message', cbMessage);
|
||||||
}
|
}
|
||||||
}, [ws, refWsMessage]);
|
}, [ws]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log(`board - initial get`);
|
if (!ws) { return; }
|
||||||
if (!ws) {
|
|
||||||
console.log(`board - initial get - no ws`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.log(`board - ws is set`);
|
|
||||||
ws.send(JSON.stringify({
|
ws.send(JSON.stringify({
|
||||||
type: 'get',
|
type: 'get',
|
||||||
fields
|
fields
|
||||||
@ -214,89 +204,22 @@ const Board = () => {
|
|||||||
|
|
||||||
onResize();
|
onResize();
|
||||||
|
|
||||||
const Tile = ({tile}) => {
|
useEffect(() => {
|
||||||
const onClick = (event) => {
|
console.log(`Generating static corner data... should only occur once per reload.`);
|
||||||
console.log(`Tile clicked: ${tile.index}`);
|
const onCornerClicked = (event, corner) => {
|
||||||
};
|
|
||||||
|
|
||||||
return <div className="Tile"
|
|
||||||
onClick={onClick}
|
|
||||||
data-index={tile.index}
|
|
||||||
style={{
|
|
||||||
top: `${tile.top}px`,
|
|
||||||
left: `${tile.left}px`,
|
|
||||||
width: `${tileImageWidth}px`,
|
|
||||||
height: `${tileImageHeight}px`,
|
|
||||||
backgroundImage: `url(${assetsPath}/gfx/tiles-${tile.type}.png)`,
|
|
||||||
backgroundPositionY: `-${tile.card*tileHeight}px`
|
|
||||||
}}
|
|
||||||
><div className="Tile-Shape"/></div>;
|
|
||||||
};
|
|
||||||
/*
|
|
||||||
useRef didn't work...
|
|
||||||
const staticSendCallback = (type, index) => {
|
|
||||||
ws.send(JSON.stringify({
|
|
||||||
type, index
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
const refStaticSendCallback = useRef(staticSendCallback);
|
|
||||||
useEffect(() => { refStaticSendCallback.current = staticSendCallback; });
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const sendPlacement = function(...) doesn't work.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* const sendPlacement = useCallabck(...) doesn't work.
|
|
||||||
*
|
|
||||||
* However it is required for dependency tracking.
|
|
||||||
*/
|
|
||||||
const sendPlacement = useCallback((type, index) => {
|
|
||||||
console.log(`board - sendPlacement - ws is ${!ws ? 'NULL' : (ws.readyState === ws.OPEN ? 'OPEN' : '!OPEN')}`);
|
|
||||||
if (ws !== hack) {
|
|
||||||
console.error(`hack and ws are different!`);
|
|
||||||
if (refWs.current === hack) {
|
|
||||||
console.log(`refWs is correct!`);
|
|
||||||
} else {
|
|
||||||
refWs.current = hack;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
refWs.current.send(JSON.stringify({
|
|
||||||
type, index
|
|
||||||
}));
|
|
||||||
}, [ws, refWs]);
|
|
||||||
|
|
||||||
const onRoadClicked = useCallback((road) => {
|
|
||||||
console.log(`Road clicked: ${road.index}`);
|
|
||||||
sendPlacement('place-road', road.index);
|
|
||||||
}, [sendPlacement]);
|
|
||||||
|
|
||||||
const Road = useCallback(({road}) => {
|
|
||||||
return <div className="Road"
|
|
||||||
onClick={() => { onRoadClicked(road) }}
|
|
||||||
data-index={road.index}
|
|
||||||
style={{
|
|
||||||
transform: `translate(-50%, -50%) rotate(${road.angle}deg)`,
|
|
||||||
top: `${road.top}px`,
|
|
||||||
left: `${road.left}px`
|
|
||||||
}}
|
|
||||||
><div className="Road-Shape"/></div>;
|
|
||||||
}, [onRoadClicked]);
|
|
||||||
|
|
||||||
const onCornerClicked = useCallback((event, corner) => {
|
|
||||||
let type;
|
let type;
|
||||||
if (event.currentTarget.getAttribute('data-type') === 'settlement') {
|
if (event.currentTarget.getAttribute('data-type') === 'settlement') {
|
||||||
type = 'place-city';
|
type = 'place-city2';
|
||||||
} else {
|
} else {
|
||||||
type = 'place-settlement';
|
type = 'place-settlement';
|
||||||
}
|
}
|
||||||
sendPlacement(type, corner.index);
|
if (!hack) { console.error(`board - onCornerClicked - ws is NULL`); return; }
|
||||||
}, [sendPlacement]);
|
ws.send(JSON.stringify({
|
||||||
|
type, index: corner.index
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
const Corner = useCallback(({corner}) => {
|
const Corner = ({corner}) => {
|
||||||
return <div className="Corner"
|
return <div className="Corner"
|
||||||
onClick={(event) => { onCornerClicked(event, corner) }}
|
onClick={(event) => { onCornerClicked(event, corner) }}
|
||||||
data-index={corner.index}
|
data-index={corner.index}
|
||||||
@ -305,108 +228,9 @@ useRef didn't work...
|
|||||||
left: `${corner.left}px`
|
left: `${corner.left}px`
|
||||||
}}
|
}}
|
||||||
><div className="Corner-Shape"/></div>;
|
><div className="Corner-Shape"/></div>;
|
||||||
}, [onCornerClicked]);
|
};
|
||||||
|
|
||||||
const onPipClicked = useCallback((pip) => {
|
const generateCorners = () => {
|
||||||
sendPlacement('place-robber', pip.index);
|
|
||||||
}, [sendPlacement]);
|
|
||||||
|
|
||||||
const Pip = useCallback(({pip}) => {
|
|
||||||
return <div className="Pip"
|
|
||||||
onClick={() => { onPipClicked(pip) }}
|
|
||||||
data-roll={pip.roll}
|
|
||||||
data-index={pip.index}
|
|
||||||
style={{
|
|
||||||
top: `${pip.top}px`,
|
|
||||||
left: `${pip.left}px`,
|
|
||||||
backgroundImage: `url(${assetsPath}/gfx/pip-numbers.png)`,
|
|
||||||
backgroundPositionX: `${ 100. * (pip.order % 6) / 5.}%`,
|
|
||||||
backgroundPositionY: `${ 100 * Math.floor(pip.order / 6) / 5. }%`
|
|
||||||
}}
|
|
||||||
><div className="Pip-Shape"/></div>;
|
|
||||||
}, [onPipClicked]);
|
|
||||||
|
|
||||||
const generateRoads = useCallback(() => {
|
|
||||||
let row = 0, rowCount = 0;
|
|
||||||
let y = -2.5 + tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
|
|
||||||
x = -tileHalfHeight -(rows[row] - 1) * 0.5 * tileHeight;
|
|
||||||
|
|
||||||
let index = 0;
|
|
||||||
let road;
|
|
||||||
|
|
||||||
const corners = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < 21; i++) {
|
|
||||||
const lastRow = row === rows.length - 1;
|
|
||||||
if (row > 2 && rowCount === 0) {
|
|
||||||
road = {
|
|
||||||
index: index++,
|
|
||||||
angle: -60,
|
|
||||||
top: y-0.5*tileHalfHeight,
|
|
||||||
left: x-tileHalfHeight
|
|
||||||
};
|
|
||||||
corners.push(<Road key={`road-${index}}`} road={road}/>);
|
|
||||||
}
|
|
||||||
|
|
||||||
road = {
|
|
||||||
index: index++,
|
|
||||||
angle: 240,
|
|
||||||
top: y,
|
|
||||||
left: x
|
|
||||||
};
|
|
||||||
corners.push(<Road key={`road-${index}}`} road={road}/>);
|
|
||||||
|
|
||||||
road = {
|
|
||||||
index: index++,
|
|
||||||
angle: -60,
|
|
||||||
top: y-0.5*tileHalfHeight,
|
|
||||||
left: x+tileHalfHeight
|
|
||||||
};
|
|
||||||
corners.push(<Road key={`road-${index}}`} road={road}/>);
|
|
||||||
|
|
||||||
if (!lastRow) {
|
|
||||||
road = {
|
|
||||||
index: index++,
|
|
||||||
angle: 0,
|
|
||||||
top: y,
|
|
||||||
left: x
|
|
||||||
};
|
|
||||||
corners.push(<Road key={`road-${index}}`} road={road}/>);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (++rowCount === rows[row]) {
|
|
||||||
if (!lastRow) {
|
|
||||||
road = {
|
|
||||||
index: index++,
|
|
||||||
angle: 0,
|
|
||||||
top: y,
|
|
||||||
left: x+2.*tileHalfHeight
|
|
||||||
};
|
|
||||||
corners.push(<Road key={`road-${index}}`} road={road}/>);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (row > 2) {
|
|
||||||
road = {
|
|
||||||
index: index++,
|
|
||||||
angle: 60,
|
|
||||||
top: y-0.5*tileHalfHeight,
|
|
||||||
left: x+3.*tileHalfHeight
|
|
||||||
};
|
|
||||||
corners.push(<Road key={`road-${index}}`} road={road}/>);
|
|
||||||
}
|
|
||||||
|
|
||||||
row++;
|
|
||||||
rowCount = 0;
|
|
||||||
y += tileHeight - 10.5;
|
|
||||||
x = -tileHalfHeight - (rows[row] - 1) * 0.5 * tileHeight;
|
|
||||||
} else {
|
|
||||||
x += tileHeight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return corners;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const generateCorners = useCallback(() => {
|
|
||||||
let row = 0, rowCount = 0;
|
let row = 0, rowCount = 0;
|
||||||
let y = -8 + 0.5 * tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
|
let y = -8 + 0.5 * tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
|
||||||
x = -tileHalfHeight -(rows[row] - 1) * 0.5 * tileHeight;
|
x = -tileHalfHeight -(rows[row] - 1) * 0.5 * tileHeight;
|
||||||
@ -464,120 +288,265 @@ useRef didn't work...
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return corners;
|
return corners;
|
||||||
}, []);
|
|
||||||
|
|
||||||
const generatePips = function (pipOrder) {
|
|
||||||
let row = 0, rowCount = 0;
|
|
||||||
let y = tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
|
|
||||||
x = -(rows[row] - 1) * 0.5 * tileHeight;
|
|
||||||
let index = 0;
|
|
||||||
let pip;
|
|
||||||
return pipOrder.map(order => {
|
|
||||||
pip = {
|
|
||||||
roll: pips[order].roll,
|
|
||||||
index: index++,
|
|
||||||
top: y,
|
|
||||||
left: x,
|
|
||||||
order: order
|
|
||||||
};
|
|
||||||
const div = <Pip
|
|
||||||
pip={pip}
|
|
||||||
key={`pip-${order}`}
|
|
||||||
/>;
|
|
||||||
|
|
||||||
if (++rowCount === rows[row]) {
|
|
||||||
row++;
|
|
||||||
rowCount = 0;
|
|
||||||
y += tileWidth;
|
|
||||||
x = - (rows[row] - 1) * 0.5 * tileHeight;
|
|
||||||
} else {
|
|
||||||
x += tileHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
return div;
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
setCornerElements(generateCorners());
|
||||||
|
}, [ws, setCornerElements]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCornerElements(generateCorners());
|
const Road = ({road}) => {
|
||||||
setRoadElements(generateRoads());
|
const onRoadClicked = (road) => {
|
||||||
}, [setCornerElements, setRoadElements, generateCorners, generateRoads]);
|
console.log(`Road clicked: ${road.index}`);
|
||||||
|
if (!ws) { console.error(`board - onRoadClicked - ws is NULL`); return; }
|
||||||
console.log(`board - Generate board - ${signature}`);
|
ws.send(JSON.stringify({
|
||||||
console.log(`board - tileOrder - `, tileOrder);
|
type: 'place-road', index: road.index
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
const generateTiles = function (tileOrder) {
|
return <div className="Road"
|
||||||
let row = 0, rowCount = 0;
|
onClick={() => { onRoadClicked(road) }}
|
||||||
let y = tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
|
data-index={road.index}
|
||||||
x = -(rows[row] - 1) * 0.5 * tileHeight;
|
|
||||||
let index = 0;
|
|
||||||
return tileOrder.map(order => {
|
|
||||||
const tile = Object.assign({},
|
|
||||||
tiles[order],
|
|
||||||
{ index: index++, left: x, top: y});
|
|
||||||
|
|
||||||
let div = <Tile
|
|
||||||
key={`${tile.type}-${tile.card}`}
|
|
||||||
tile={tile}
|
|
||||||
/>;
|
|
||||||
|
|
||||||
if (++rowCount === rows[row]) {
|
|
||||||
row++;
|
|
||||||
rowCount = 0;
|
|
||||||
y += tileWidth;
|
|
||||||
x = - (rows[row] - 1) * 0.5 * tileHeight;
|
|
||||||
} else {
|
|
||||||
x += tileHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
return div;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const generateBorders = function(borderOrder) {
|
|
||||||
const sides = 6;
|
|
||||||
let side = -1;
|
|
||||||
return borderOrder.map(order => {
|
|
||||||
const border = borders[order];
|
|
||||||
side++;
|
|
||||||
let x = + Math.sin(Math.PI - side / sides * 2. * Math.PI) * radius,
|
|
||||||
y = Math.cos(Math.PI - side / sides * 2. * Math.PI) * radius;
|
|
||||||
let prev = (order === 0) ? 6 : order;
|
|
||||||
const file = `borders-${order+1}.${prev}.png`;
|
|
||||||
return <div
|
|
||||||
key={`border-${order}`}
|
|
||||||
className="Border"
|
|
||||||
border={border}
|
|
||||||
style={{
|
style={{
|
||||||
width: `${borderImageWidth}px`,
|
transform: `translate(-50%, -50%) rotate(${road.angle}deg)`,
|
||||||
height: `${borderImageHeight}px`,
|
top: `${road.top}px`,
|
||||||
top: `${y}px`,
|
left: `${road.left}px`
|
||||||
left: `${x}px`,
|
|
||||||
transform: `rotate(${side*(360/sides)}deg) translate(${borderOffsetX}px, ${borderOffsetY}px) scale(-1, -1)`,
|
|
||||||
backgroundImage: `url(${assetsPath}/gfx/${file} )`
|
|
||||||
}}
|
}}
|
||||||
/>;
|
><div className="Road-Shape"/></div>;
|
||||||
});
|
};
|
||||||
};
|
|
||||||
|
const generateRoads = () => {
|
||||||
|
let row = 0, rowCount = 0;
|
||||||
|
let y = -2.5 + tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
|
||||||
|
x = -tileHalfHeight -(rows[row] - 1) * 0.5 * tileHeight;
|
||||||
|
|
||||||
|
let index = 0;
|
||||||
|
let road;
|
||||||
|
|
||||||
|
const corners = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < 21; i++) {
|
||||||
|
const lastRow = row === rows.length - 1;
|
||||||
|
if (row > 2 && rowCount === 0) {
|
||||||
|
road = {
|
||||||
|
index: index++,
|
||||||
|
angle: -60,
|
||||||
|
top: y-0.5*tileHalfHeight,
|
||||||
|
left: x-tileHalfHeight
|
||||||
|
};
|
||||||
|
corners.push(<Road key={`road-${index}}`} road={road}/>);
|
||||||
|
}
|
||||||
|
|
||||||
|
road = {
|
||||||
|
index: index++,
|
||||||
|
angle: 240,
|
||||||
|
top: y,
|
||||||
|
left: x
|
||||||
|
};
|
||||||
|
corners.push(<Road key={`road-${index}}`} road={road}/>);
|
||||||
|
|
||||||
|
road = {
|
||||||
|
index: index++,
|
||||||
|
angle: -60,
|
||||||
|
top: y-0.5*tileHalfHeight,
|
||||||
|
left: x+tileHalfHeight
|
||||||
|
};
|
||||||
|
corners.push(<Road key={`road-${index}}`} road={road}/>);
|
||||||
|
|
||||||
|
if (!lastRow) {
|
||||||
|
road = {
|
||||||
|
index: index++,
|
||||||
|
angle: 0,
|
||||||
|
top: y,
|
||||||
|
left: x
|
||||||
|
};
|
||||||
|
corners.push(<Road key={`road-${index}}`} road={road}/>);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++rowCount === rows[row]) {
|
||||||
|
if (!lastRow) {
|
||||||
|
road = {
|
||||||
|
index: index++,
|
||||||
|
angle: 0,
|
||||||
|
top: y,
|
||||||
|
left: x+2.*tileHalfHeight
|
||||||
|
};
|
||||||
|
corners.push(<Road key={`road-${index}}`} road={road}/>);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row > 2) {
|
||||||
|
road = {
|
||||||
|
index: index++,
|
||||||
|
angle: 60,
|
||||||
|
top: y-0.5*tileHalfHeight,
|
||||||
|
left: x+3.*tileHalfHeight
|
||||||
|
};
|
||||||
|
corners.push(<Road key={`road-${index}}`} road={road}/>);
|
||||||
|
}
|
||||||
|
|
||||||
|
row++;
|
||||||
|
rowCount = 0;
|
||||||
|
y += tileHeight - 10.5;
|
||||||
|
x = -tileHalfHeight - (rows[row] - 1) * 0.5 * tileHeight;
|
||||||
|
} else {
|
||||||
|
x += tileHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return corners;
|
||||||
|
}
|
||||||
|
setRoadElements(generateRoads());
|
||||||
|
}, [ws, setRoadElements]);
|
||||||
|
|
||||||
|
/* Generate Pip, Tile, and Border elements */
|
||||||
|
useEffect(() => {
|
||||||
|
const Pip = ({pip}) => {
|
||||||
|
const onPipClicked = (pip) => {
|
||||||
|
if (!ws) { console.error(`board - sendPlacement - ws is NULL`); return; }
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
type: 'place-robber', index: pip.index
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
return <div className="Pip"
|
||||||
|
onClick={() => { onPipClicked(pip) }}
|
||||||
|
data-roll={pip.roll}
|
||||||
|
data-index={pip.index}
|
||||||
|
style={{
|
||||||
|
top: `${pip.top}px`,
|
||||||
|
left: `${pip.left}px`,
|
||||||
|
backgroundImage: `url(${assetsPath}/gfx/pip-numbers.png)`,
|
||||||
|
backgroundPositionX: `${ 100. * (pip.order % 6) / 5.}%`,
|
||||||
|
backgroundPositionY: `${ 100 * Math.floor(pip.order / 6) / 5. }%`
|
||||||
|
}}
|
||||||
|
><div className="Pip-Shape"/></div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const generatePips = function (pipOrder) {
|
||||||
|
let row = 0, rowCount = 0;
|
||||||
|
let y = tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
|
||||||
|
x = -(rows[row] - 1) * 0.5 * tileHeight;
|
||||||
|
let index = 0;
|
||||||
|
let pip;
|
||||||
|
return pipOrder.map(order => {
|
||||||
|
pip = {
|
||||||
|
roll: pips[order].roll,
|
||||||
|
index: index++,
|
||||||
|
top: y,
|
||||||
|
left: x,
|
||||||
|
order: order
|
||||||
|
};
|
||||||
|
const div = <Pip
|
||||||
|
pip={pip}
|
||||||
|
key={`pip-${order}`}
|
||||||
|
/>;
|
||||||
|
|
||||||
|
if (++rowCount === rows[row]) {
|
||||||
|
row++;
|
||||||
|
rowCount = 0;
|
||||||
|
y += tileWidth;
|
||||||
|
x = - (rows[row] - 1) * 0.5 * tileHeight;
|
||||||
|
} else {
|
||||||
|
x += tileHeight;
|
||||||
|
}
|
||||||
|
|
||||||
if ((signature && signature !== generated)
|
return div;
|
||||||
&& (pips && pipOrder && borders && borderOrder
|
});
|
||||||
&& tiles && tileOrder)) {
|
};
|
||||||
setPipElements(generatePips(pipOrder));
|
|
||||||
setBorderElements(generateBorders(borderOrder));
|
const Tile = ({tile}) => {
|
||||||
setTileElements(generateTiles(tileOrder));
|
return <div className="Tile"
|
||||||
|
data-index={tile.index}
|
||||||
setGenerated(signature);
|
style={{
|
||||||
}/*, [
|
top: `${tile.top}px`,
|
||||||
|
left: `${tile.left}px`,
|
||||||
|
width: `${tileImageWidth}px`,
|
||||||
|
height: `${tileImageHeight}px`,
|
||||||
|
backgroundImage: `url(${assetsPath}/gfx/tiles-${tile.type}.png)`,
|
||||||
|
backgroundPositionY: `-${tile.card*tileHeight}px`
|
||||||
|
}}
|
||||||
|
><div className="Tile-Shape"/></div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const generateTiles = function (tileOrder) {
|
||||||
|
let row = 0, rowCount = 0;
|
||||||
|
let y = tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
|
||||||
|
x = -(rows[row] - 1) * 0.5 * tileHeight;
|
||||||
|
let index = 0;
|
||||||
|
return tileOrder.map(order => {
|
||||||
|
const tile = Object.assign({},
|
||||||
|
tiles[order],
|
||||||
|
{ index: index++, left: x, top: y});
|
||||||
|
let div = <Tile
|
||||||
|
key={`${tile.type}-${tile.card}`}
|
||||||
|
tile={tile}
|
||||||
|
/>;
|
||||||
|
if (++rowCount === rows[row]) {
|
||||||
|
row++;
|
||||||
|
rowCount = 0;
|
||||||
|
y += tileWidth;
|
||||||
|
x = - (rows[row] - 1) * 0.5 * tileHeight;
|
||||||
|
} else {
|
||||||
|
x += tileHeight;
|
||||||
|
}
|
||||||
|
return div;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const generateBorders = function(borderOrder) {
|
||||||
|
const sides = 6;
|
||||||
|
let side = -1;
|
||||||
|
return borderOrder.map(order => {
|
||||||
|
const border = borders[order];
|
||||||
|
side++;
|
||||||
|
let x = + Math.sin(Math.PI - side / sides * 2. * Math.PI) * radius,
|
||||||
|
y = Math.cos(Math.PI - side / sides * 2. * Math.PI) * radius;
|
||||||
|
let prev = (order === 0) ? 6 : order;
|
||||||
|
const file = `borders-${order+1}.${prev}.png`;
|
||||||
|
return <div
|
||||||
|
key={`border-${order}`}
|
||||||
|
className="Border"
|
||||||
|
border={border}
|
||||||
|
style={{
|
||||||
|
width: `${borderImageWidth}px`,
|
||||||
|
height: `${borderImageHeight}px`,
|
||||||
|
top: `${y}px`,
|
||||||
|
left: `${x}px`,
|
||||||
|
transform: `rotate(${side*(360/sides)}deg) translate(${borderOffsetX}px, ${borderOffsetY}px) scale(-1, -1)`,
|
||||||
|
backgroundImage: `url(${assetsPath}/gfx/${file} )`
|
||||||
|
}}
|
||||||
|
/>;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (borders && borderOrder) {
|
||||||
|
console.log(`board - Generate board - borders`);
|
||||||
|
setBorderElements(generateBorders(borderOrder));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tiles && tileOrder) {
|
||||||
|
console.log(`board - Generate board - tiles`);
|
||||||
|
setTileElements(generateTiles(tileOrder));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Regenerate pips every time; it uses ws */
|
||||||
|
if (pips && pipOrder) {
|
||||||
|
console.log(`board - Generate board - pips`);
|
||||||
|
setPipElements(generatePips(pipOrder));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signature && signature !== generated) {
|
||||||
|
console.log(`board - Regnerating for ${signature}`);
|
||||||
|
setGenerated(signature);
|
||||||
|
}
|
||||||
|
}, [
|
||||||
signature, generated,
|
signature, generated,
|
||||||
setPipElements, setBorderElements, setTileElements,
|
pips, pipOrder, borders, borderOrder, tiles, tileOrder,
|
||||||
borderOrder, borders, pipOrder, pips, tileOrder, tiles
|
ws
|
||||||
]);*/
|
]);
|
||||||
|
|
||||||
console.log(`board - rendering tileOrder - `, tileOrder);
|
/* Re-render turn info after every render */
|
||||||
|
useEffect(() => {
|
||||||
console.log(`board - todo - look into debouncing the direct DOM update`);
|
if (!turn) { return; }
|
||||||
if (turn) {
|
|
||||||
let nodes = document.querySelectorAll('.Active');
|
let nodes = document.querySelectorAll('.Active');
|
||||||
for (let i = 0; i < nodes.length; i++) {
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
nodes[i].classList.remove('Active');
|
nodes[i].classList.remove('Active');
|
||||||
@ -595,15 +564,15 @@ useRef didn't work...
|
|||||||
nodes[i].classList.add('Active');
|
nodes[i].classList.add('Active');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
if (placements) {
|
/* Re-render placements after every render */
|
||||||
|
useEffect(() => {
|
||||||
|
if (!placements) { return; }
|
||||||
/* Set color and type based on placement data from the server */
|
/* Set color and type based on placement data from the server */
|
||||||
placements.corners.forEach((corner, index) => {
|
placements.corners.forEach((corner, index) => {
|
||||||
const el = document.querySelector(`.Corner[data-index="${index}"]`);
|
const el = document.querySelector(`.Corner[data-index="${index}"]`);
|
||||||
if (!el) {
|
if (!el) { return; }
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!corner.color) {
|
if (!corner.color) {
|
||||||
el.removeAttribute('data-color');
|
el.removeAttribute('data-color');
|
||||||
el.removeAttribute('data-type');
|
el.removeAttribute('data-type');
|
||||||
@ -614,9 +583,7 @@ useRef didn't work...
|
|||||||
});
|
});
|
||||||
placements.roads.forEach((road, index) => {
|
placements.roads.forEach((road, index) => {
|
||||||
const el = document.querySelector(`.Road[data-index="${index}"]`);
|
const el = document.querySelector(`.Road[data-index="${index}"]`);
|
||||||
if (!el) {
|
if (!el) { return; }
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!road.color) {
|
if (!road.color) {
|
||||||
el.removeAttribute('data-color');
|
el.removeAttribute('data-color');
|
||||||
} else {
|
} else {
|
||||||
@ -645,9 +612,7 @@ useRef didn't work...
|
|||||||
if (turn.limits['roads']) {
|
if (turn.limits['roads']) {
|
||||||
turn.limits['roads'].forEach(index => {
|
turn.limits['roads'].forEach(index => {
|
||||||
const el = document.querySelector(`.Road[data-index="${index}"]`);
|
const el = document.querySelector(`.Road[data-index="${index}"]`);
|
||||||
if (!el) {
|
if (!el) { return; }
|
||||||
return;
|
|
||||||
}
|
|
||||||
el.classList.add('Option');
|
el.classList.add('Option');
|
||||||
el.setAttribute('data-color', turn.color);
|
el.setAttribute('data-color', turn.color);
|
||||||
});
|
});
|
||||||
@ -655,9 +620,7 @@ useRef didn't work...
|
|||||||
if (turn.limits['corners']) {
|
if (turn.limits['corners']) {
|
||||||
turn.limits['corners'].forEach(index => {
|
turn.limits['corners'].forEach(index => {
|
||||||
const el = document.querySelector(`.Corner[data-index="${index}"]`);
|
const el = document.querySelector(`.Corner[data-index="${index}"]`);
|
||||||
if (!el) {
|
if (!el) { return; }
|
||||||
return;
|
|
||||||
}
|
|
||||||
el.classList.add('Option');
|
el.classList.add('Option');
|
||||||
el.setAttribute('data-color', turn.color);
|
el.setAttribute('data-color', turn.color);
|
||||||
});
|
});
|
||||||
@ -665,26 +628,21 @@ useRef didn't work...
|
|||||||
if (turn.limits['tiles']) {
|
if (turn.limits['tiles']) {
|
||||||
turn.limits['tiles'].forEach(index => {
|
turn.limits['tiles'].forEach(index => {
|
||||||
const el = document.querySelector(`.Tile[data-index="${index}"]`);
|
const el = document.querySelector(`.Tile[data-index="${index}"]`);
|
||||||
if (!el) {
|
if (!el) { return; }
|
||||||
return;
|
|
||||||
}
|
|
||||||
el.classList.add('Option');
|
el.classList.add('Option');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (turn.limits['pips']) {
|
if (turn.limits['pips']) {
|
||||||
turn.limits['pips'].forEach(index => {
|
turn.limits['pips'].forEach(index => {
|
||||||
const el = document.querySelector(`.Pip[data-index="${index}"]`);
|
const el = document.querySelector(`.Pip[data-index="${index}"]`);
|
||||||
if (!el) {
|
if (!el) { return; }
|
||||||
return;
|
|
||||||
}
|
|
||||||
el.classList.add('Option');
|
el.classList.add('Option');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/* Clear the robber */
|
||||||
useEffect(() => {
|
nodes = document.querySelectorAll(`.Pip.Robber`);
|
||||||
let nodes = document.querySelectorAll(`.Pip.Robber`);
|
|
||||||
for (let i = 0; i < nodes.length; i++) {
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
nodes[i].classList.remove('Robber');
|
nodes[i].classList.remove('Robber');
|
||||||
[ 'Robert', 'Roberta', 'Velocirobber' ].forEach(robberName =>
|
[ 'Robert', 'Roberta', 'Velocirobber' ].forEach(robberName =>
|
||||||
@ -692,6 +650,7 @@ useRef didn't work...
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Place the robber */
|
||||||
if (robber !== undefined) {
|
if (robber !== undefined) {
|
||||||
const el = document.querySelector(`.Pip[data-index="${robber}"]`);
|
const el = document.querySelector(`.Pip[data-index="${robber}"]`);
|
||||||
if (el) {
|
if (el) {
|
||||||
@ -701,7 +660,6 @@ useRef didn't work...
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const canAction = (action) => {
|
const canAction = (action) => {
|
||||||
return (turn && Array.isArray(turn.actions) && turn.actions.indexOf(action) !== -1);
|
return (turn && Array.isArray(turn.actions) && turn.actions.indexOf(action) !== -1);
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user