diff --git a/package.json b/package.json
index 8a51a5b..9fe5c6e 100755
--- a/package.json
+++ b/package.json
@@ -15,6 +15,7 @@
"private": true,
"dependencies": {
"@material-ui/core": "^4.9.11",
+ "@material-ui/lab": "^4.0.0-alpha.50",
"animakit-expander": "^2.1.4",
"bluebird": "^3.5.5",
"bootstrap": "^4.4.1",
diff --git a/server/app.js b/server/app.js
index 4c1ba2f..05c1ada 100755
--- a/server/app.js
+++ b/server/app.js
@@ -85,7 +85,7 @@ app.use(function(req, res, next){
app.use(session({
store: new SQLiteStore({ db: config.get("sessions.db") }),
secret: config.get("sessions.store-secret"),
- cookie: { maxAge: 7 * 24 * 60 * 60 * 1000 }, // 1 week
+ cookie: { maxAge: 21 * 24 * 60 * 60 * 1000 }, // 3 weeks
saveUninitialized: false,
resave: true
}));
diff --git a/server/routes/games.js b/server/routes/games.js
index 50a916e..9b627d6 100755
--- a/server/routes/games.js
+++ b/server/routes/games.js
@@ -102,7 +102,60 @@ const games = {};
router.get("/:id", (req, res/*, next*/) => {
console.log("GET games/" + req.params.id);
if (req.params.id in games) {
- return res.status(200).send(games[req.params.id]);
+ const game = games[req.params.id];
+ return res.status(200).send(Object.assign({}, game, {
+ timestamp: Date.now(),
+ activePlayer: req.session.activePlayer
+ }));
+ } else {
+ const error = `Game not found: ${req.params.id}`;
+ return res.status(404).send(error);
+ }
+});
+
+router.put("/:id", (req, res/*, next*/) => {
+ console.log("PUT games/" + req.params.id);
+ if (req.params.id in games) {
+ const game = games[req.params.id],
+ changes = req.body;
+
+ console.log(JSON.stringify(changes, null, 2));
+
+ for (let change in changes) {
+ switch (change) {
+ case "players":
+ console.log("Player change.");
+ for (let player in changes.players) {
+ const playerChange = changes.players[player];
+ if (playerChange.name != "") {
+ game.chat.push({ from: player, date: Date.now(), message: `${player} is now '${playerChange.name}'.` });
+ req.session.activePlayer = player;
+ game.players[player].status = `Just joined`;
+ } else {
+ game.chat.push({ from: player, date: Date.now(), message: `${player} is no longer claimed.` });
+ req.session.activePlayer = "";
+ game.players[player].status = `Not active`;
+ }
+ game.players[player].name = playerChange.name;
+ }
+ break;
+ case "chat":
+ console.log("Chat change.");
+ game.chat.push({
+ from: changes.chat.player,
+ date: Date.now(),
+ message: changes.chat.message
+ });
+ if (game.chat.length > 10) {
+ game.chat.splice(0, game.chat.length - 10);
+ }
+ break;
+ }
+ }
+ return res.status(200).send(Object.assign({}, game, {
+ timestamp: Date.now(),
+ activePlayer: req.session.activePlayer
+ }));
} else {
const error = `Game not found: ${req.params.id}`;
return res.status(404).send(error);
@@ -117,12 +170,13 @@ router.post("/", (req, res/*, next*/) => {
tiles: [],
pips: [],
borders: [],
- tokens: [
- { player: "R", roads: 15, cities: 4, settlements: 5, points: 0 },
- { player: "O", roads: 15, cities: 4, settlements: 5, points: 0 },
- { player: "B", roads: 15, cities: 4, settlements: 5, points: 0 },
- { player: "W", roads: 15, cities: 4, settlements: 5, points: 0 }
- ],
+ tokens: [],
+ players: {
+ R: { roads: 15, cities: 4, settlements: 5, points: 0, name: "", status: "Not active" },
+ O: { roads: 15, cities: 4, settlements: 5, points: 0, name: "", status: "Not active" },
+ B: { roads: 15, cities: 4, settlements: 5, points: 0, name: "", status: "Not active" },
+ W: { roads: 15, cities: 4, settlements: 5, points: 0, name: "", status: "Not active" }
+ },
developmentCards: assetData.developmentCards.slice(),
dice: [ 0, 0 ],
sheep: 19,
@@ -154,7 +208,10 @@ router.post("/", (req, res/*, next*/) => {
games[game.id] = game;
console.log(`New game created: ${game.id}`);
- return res.status(200).send(game);
+ return res.status(200).send(Object.assign({}, game, {
+ timestamp: Date.now(),
+ activePlayer: req.session.activePlayer
+ }));
});
diff --git a/sessions.db b/sessions.db
index 7294b5f..aa94acb 100644
Binary files a/sessions.db and b/sessions.db differ
diff --git a/src/Board.css b/src/Board.css
index cd24d45..02c8e00 100755
--- a/src/Board.css
+++ b/src/Board.css
@@ -43,8 +43,6 @@
}
.Chat {
- right: 0;
- bottom: 0;
padding: 0.5em;
width: 30vmax;
display: inline-block;
@@ -60,6 +58,25 @@
overflow-y: scroll;
}
+.Players {
+ padding: 0.5em;
+ width: 30vmax;
+ display: inline-block;
+ opacity: 0.7;
+}
+
+#ChatList {
+ scroll-behavior: smooth;
+}
+
+.Players > * {
+ width: 100%;
+}
+
+.Players .nameInput {
+ flex-grow: 1;
+}
+
.Stack > *:not(:first-child) {
margin-left: -4.5em;
}
diff --git a/src/Board.js b/src/Board.js
index 3d5f73a..0309807 100755
--- a/src/Board.js
+++ b/src/Board.js
@@ -7,9 +7,38 @@ import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText';
import ListItemAvatar from '@material-ui/core/ListItemAvatar';
+import { makeStyles } from '@material-ui/core/styles';
+import { deepOrange, lightBlue, red, grey } from '@material-ui/core/colors';
+import Avatar from '@material-ui/core/Avatar';
+import Switch from '@material-ui/core/Switch';
import Moment from 'react-moment';
import moment from 'moment';
+const useStyles = makeStyles((theme) => ({
+ root: {
+ display: 'flex',
+ '& > *': {
+ margin: theme.spacing(1),
+ },
+ },
+ R: {
+ color: theme.palette.getContrastText(red[500]),
+ backgroundColor: red[500],
+ },
+ O: {
+ color: theme.palette.getContrastText(deepOrange[500]),
+ backgroundColor: deepOrange[500],
+ },
+ W: {
+ color: theme.palette.getContrastText(grey[100]),
+ backgroundColor: grey[100],
+ },
+ B: {
+ color: theme.palette.getContrastText(lightBlue[500]),
+ backgroundColor: lightBlue[500],
+ },
+}));
+
const hexagonRatio = 1.1547005,
tileHeight = 0.16,
tileWidth = tileHeight * hexagonRatio,
@@ -179,49 +208,145 @@ class Resource extends React.Component {
}
};
-class Chat extends React.Component {
- constructor(props) {
- super(props);
- this.chatInput = this.chatInput.bind(this);
- }
-
- chatInput(event) {
+const Chat = ({ game, promoteGameState }) => {
+ const chatInput = (event) => {
console.log(event.target.value);
- }
+ };
- chatKeyPress(event) {
+ const chatKeyPress = (event) => {
if (event.key == "Enter") {
console.log(`Send: ${event.target.value}`);
+ promoteGameState({ chat: { player: game.activePlayer, message: event.target.value }});
event.target.value = "";
}
+ };
+
+ const classes = useStyles();
+
+ useEffect(() => {
+ const chatList = document.getElementById("ChatList");
+ chatList.scrollTop = chatList.scrollHeight - chatList.offsetHeight;
+ })
+ console.log(JSON.stringify(game, null, 2));
+
+ const timeDelta = game.timestamp - Date.now();
+
+ const messages = game.chat.map((item, index) => {
+ const timestamp = moment(item.date - timeDelta).fromNow();
+ return (
+
+ { messages }
+
+
- { messages }
-
-
+ { players }
+
+