summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--public/common/client.js60
-rw-r--r--public/common/grid.css2
-rw-r--r--public/images/cycle.svg1
-rw-r--r--server.js36
-rw-r--r--views/about.ejs3
-rw-r--r--views/join.ejs3
6 files changed, 86 insertions, 19 deletions
diff --git a/public/common/client.js b/public/common/client.js
index 26f953e..5185da1 100644
--- a/public/common/client.js
+++ b/public/common/client.js
@@ -1,4 +1,7 @@
+let game = null;
+let player = null;
let socket = null;
+
let chat_is_visible = false;
let chat_text = null;
let chat_key = null;
@@ -103,8 +106,8 @@ function add_chat_lines(log) {
}
}
-function load_chat(game) {
- chat_key = "chat/" + game;
+function load_chat(game_id) {
+ chat_key = "chat/" + game_id;
chat_text = document.querySelector(".chat_text");
chat_last_day = null;
chat_log = [];
@@ -137,9 +140,11 @@ function update_chat(log_start, log) {
function init_client(roles) {
let params = new URLSearchParams(window.location.search);
let title = window.location.pathname.split("/")[1];
- let game = params.get("game");
+ let game_id = params.get("game");
let role = params.get("role");
- let player = null;
+
+ game = null;
+ player = null;
const ROLE_SEL = [
".role.one",
@@ -161,13 +166,13 @@ function init_client(roles) {
".role.seven .role_user",
];
- load_chat(game);
+ load_chat(game_id);
- console.log("JOINING game", game, "role", role);
+ console.log("JOINING game", game_id, "role", role);
socket = io({
transports: ['websocket'],
- query: { title: title, game: game, role: role },
+ query: { title: title, game: game_id, role: role },
});
socket.on('connect', () => {
@@ -205,11 +210,13 @@ function init_client(roles) {
}
});
- socket.on('state', (state) => {
+ socket.on('state', (state, game_over) => {
console.log("STATE");
- on_update_log(state);
- on_update_bar(state, player);
- on_update(state, player);
+ game = state;
+ on_update_log();
+ on_update_bar();
+ on_update();
+ on_game_over(game_over);
});
socket.on('save', (msg) => {
@@ -264,22 +271,22 @@ function init_client(roles) {
drag_element_with_mouse(".chat_window", ".chat_header");
}
-function on_update_bar(state, player) {
- document.getElementById("prompt").textContent = state.prompt;
- if (state.actions)
+function on_update_bar() {
+ document.getElementById("prompt").textContent = game.prompt;
+ if (game.actions)
document.querySelector(".grid_top").classList.add("your_turn");
else
document.querySelector(".grid_top").classList.remove("your_turn");
}
-function on_update_log(state) {
+function on_update_log() {
let parent = document.getElementById("log");
- let to_delete = parent.children.length - state.log_start;
+ let to_delete = parent.children.length - game.log_start;
while (to_delete > 0) {
parent.removeChild(parent.firstChild);
--to_delete;
}
- for (let entry of state.log) {
+ for (let entry of game.log) {
let p = document.createElement("div");
p.textContent = entry;
parent.prepend(p);
@@ -411,3 +418,22 @@ function send_restore() {
function send_restart(scenario) {
socket.emit('restart', scenario);
}
+
+function on_game_over(game_over) {
+ if (player && player != "Observer") {
+ let rematch_button = document.querySelector("#rematch_button");
+ if (rematch_button)
+ {
+ if (game_over)
+ rematch_button.classList.remove("hide");
+ else
+ rematch_button.classList.add("hide");
+ }
+ }
+}
+
+function send_rematch() {
+ let params = new URLSearchParams(window.location.search);
+ let game = params.get("game");
+ window.location = '/rematch/' + game;
+}
diff --git a/public/common/grid.css b/public/common/grid.css
index 2e1b6b2..eb59357 100644
--- a/public/common/grid.css
+++ b/public/common/grid.css
@@ -175,7 +175,7 @@ html, body, div {
.grid_top button {
margin: 0 10px;
}
-.grid_top button.hide {
+.grid_top .hide {
display: none;
}
diff --git a/public/images/cycle.svg b/public/images/cycle.svg
new file mode 100644
index 0000000..349da30
--- /dev/null
+++ b/public/images/cycle.svg
@@ -0,0 +1 @@
+<svg style="height: 512px; width: 512px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><g class="" style="" transform="translate(0,0)"><path d="M252.314 19.957c-72.036.363-142.99 33.534-189.18 95.97-69.83 94.39-59.125 223.32 19.85 304.993l-37.238 50.332 151.22-22.613L174.35 297.42l-43.137 58.308c-44.08-54.382-47.723-133.646-4.16-192.53 30.676-41.466 77.863-63.504 125.758-63.753 16.344-.085 32.766 2.382 48.645 7.467l-6.963-46.55c-23.858-4.86-47.908-5.026-71.017-.997-59.232 7.322-113.994 39.918-148.157 91.215 35.65-65.89 103.774-105.918 176.043-107.744 1.673-.042 3.347-.063 5.023-.065 14.8-.01 29.748 1.596 44.597 4.905l48.608-7.268c-31.14-13.906-64.32-20.62-97.274-20.453zm212.93 22.055l-151.217 22.61 22.614 151.22 41.126-55.588c42.204 54.29 45.092 132.048 2.187 190.043-40.22 54.367-108.82 75.32-170.19 57.566l6.522 43.598c28.726 5.533 58.236 4.414 86.203-3.07 37.448-5.957 73.34-22.05 103.16-47.728-49.196 54.65-122.615 77.514-191.744 64.34l-55.8 8.344c99.03 43.7 218.402 14.77 285.51-75.938 69.13-93.445 59.34-220.743-17.483-302.53l39.114-52.866z" fill="#000" fill-opacity="1"></path></g></svg> \ No newline at end of file
diff --git a/server.js b/server.js
index 9dedb26..e5ca446 100644
--- a/server.js
+++ b/server.js
@@ -501,6 +501,21 @@ const QUERY_IS_ACTIVE = db.prepare("SELECT COUNT(*) FROM players WHERE game_id =
const QUERY_COUNT_OPEN_GAMES = db.prepare("SELECT COUNT(*) FROM games WHERE owner = ? AND status = 0").pluck();
const QUERY_DELETE_GAME = db.prepare("DELETE FROM games WHERE game_id = ?");
+const QUERY_REMATCH_FIND = db.prepare(`
+ SELECT game_id FROM games WHERE status=0 AND description=?
+`).pluck();
+
+const QUERY_REMATCH_CREATE = db.prepare(`
+ INSERT INTO games
+ (owner, title_id, scenario, private, random, ctime, mtime, description, status, state, chat)
+ SELECT
+ $user_id, title_id, scenario, private, random, datetime('now'), datetime('now'), $magic, 0, NULL, '[]'
+ FROM games
+ WHERE game_id = $game_id AND NOT EXISTS (
+ SELECT * FROM games WHERE status=0 AND description=$magic
+ )
+`);
+
app.get('/', function (req, res) {
res.render('index.ejs', { user: req.user, message: req.flash('message') });
});
@@ -630,6 +645,25 @@ app.get('/delete/:game_id', must_be_logged_in, function (req, res) {
}
});
+app.get('/rematch/:old_game_id', must_be_logged_in, function (req, res) {
+ LOG(req, "GET /rematch/" + req.params.old_game_id);
+ let old_game_id = req.params.old_game_id | 0;
+ try {
+ let magic = "\u{1F503} " + old_game_id;
+ let info = QUERY_REMATCH_CREATE.run({user_id: req.user.user_id, game_id: old_game_id, magic: magic});
+ if (info.changes == 1)
+ return res.redirect('/join/'+info.lastInsertRowid);
+ let new_game_id = QUERY_REMATCH_FIND.get(magic);
+ if (new_game_id)
+ return res.redirect('/join/'+new_game_id);
+ req.flash('message', "Can't create or find rematch game!");
+ return res.redirect('/join/'+old_game_id);
+ } catch (err) {
+ req.flash('message', err.toString());
+ return res.redirect('/join/'+old_game_id);
+ }
+});
+
app.get('/join/:game_id', must_be_logged_in, function (req, res) {
LOG(req, "GET /join/" + req.params.game_id);
let game_id = req.params.game_id | 0;
@@ -776,7 +810,7 @@ function send_state(socket, state) {
view.log_start = view.log.length;
socket.log_length = view.log.length;
view.log = view.log.slice(view.log_start);
- socket.emit('state', view);
+ socket.emit('state', view, state.state == 'game_over');
} catch (err) {
console.log(err);
return socket.emit('error', err.toString());
diff --git a/views/about.ejs b/views/about.ejs
index 8478301..fca63e0 100644
--- a/views/about.ejs
+++ b/views/about.ejs
@@ -52,6 +52,9 @@ see more of the map.
<li>
The <img src="/images/chat-bubble.svg"> button lights up if you have unread chat messages.
+<li>
+The <img src="/images/cycle.svg"> button appears when the game is over, and can be used to quickly start a rematch.
+
</ul>
<h2>
diff --git a/views/join.ejs b/views/join.ejs
index 42feaaf..2da5f03 100644
--- a/views/join.ejs
+++ b/views/join.ejs
@@ -81,6 +81,9 @@ Description: <%= game.description || "No description." %>
%>Waiting for players to join the game.<%
}
}
+ if (game.status == 2 && players.some(p => p.user_id == user.user_id)) {
+ %><form action="/rematch/<%= game.game_id %>"><button type="submit">Rematch</button></form><%
+ }
if (game.owner_id == user.user_id && (game.status == 0 || solo)) {
%><p><br><button onclick="confirm_delete()">Delete</button><%
}