enable replay (built files)
This commit is contained in:
parent
7a7d6580fc
commit
81ef9cd704
4 changed files with 57 additions and 25 deletions
1
build/public/assets/index.1449524a.js
Normal file
1
build/public/assets/index.1449524a.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -4,7 +4,7 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
|
|
||||||
<title>🧩 jigsaw.hyottoko.club</title>
|
<title>🧩 jigsaw.hyottoko.club</title>
|
||||||
<script type="module" crossorigin src="/assets/index.50ee8245.js"></script>
|
<script type="module" crossorigin src="/assets/index.1449524a.js"></script>
|
||||||
<link rel="modulepreload" href="/assets/vendor.b622ee49.js">
|
<link rel="modulepreload" href="/assets/vendor.b622ee49.js">
|
||||||
<link rel="stylesheet" href="/assets/index.f7304069.css">
|
<link rel="stylesheet" href="/assets/index.f7304069.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ import WebSocket from 'ws';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import multer from 'multer';
|
import multer from 'multer';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
import readline from 'readline';
|
||||||
|
import stream from 'stream';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import { dirname } from 'path';
|
import { dirname } from 'path';
|
||||||
import sizeOf from 'image-size';
|
import sizeOf from 'image-size';
|
||||||
|
|
@ -215,7 +217,7 @@ var Util = {
|
||||||
asQueryArgs,
|
asQueryArgs,
|
||||||
};
|
};
|
||||||
|
|
||||||
const log$5 = logger('WebSocketServer.js');
|
const log$4 = logger('WebSocketServer.js');
|
||||||
/*
|
/*
|
||||||
Example config
|
Example config
|
||||||
|
|
||||||
|
|
@ -253,12 +255,12 @@ class WebSocketServer {
|
||||||
this._websocketserver.on('connection', (socket, request) => {
|
this._websocketserver.on('connection', (socket, request) => {
|
||||||
const pathname = new URL(this.config.connectstring).pathname;
|
const pathname = new URL(this.config.connectstring).pathname;
|
||||||
if (request.url.indexOf(pathname) !== 0) {
|
if (request.url.indexOf(pathname) !== 0) {
|
||||||
log$5.log('bad request url: ', request.url);
|
log$4.log('bad request url: ', request.url);
|
||||||
socket.close();
|
socket.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
socket.on('message', (data) => {
|
socket.on('message', (data) => {
|
||||||
log$5.log(`ws`, socket.protocol, data);
|
log$4.log(`ws`, socket.protocol, data);
|
||||||
this.evt.dispatch('message', { socket, data });
|
this.evt.dispatch('message', { socket, data });
|
||||||
});
|
});
|
||||||
socket.on('close', () => {
|
socket.on('close', () => {
|
||||||
|
|
@ -318,10 +320,10 @@ EV_SERVER_INIT: event sent to one client after that client
|
||||||
*/
|
*/
|
||||||
const EV_SERVER_EVENT = 1;
|
const EV_SERVER_EVENT = 1;
|
||||||
const EV_SERVER_INIT = 4;
|
const EV_SERVER_INIT = 4;
|
||||||
const EV_SERVER_INIT_REPLAY = 5;
|
const EV_SERVER_REPLAY_DATA = 5;
|
||||||
const EV_CLIENT_EVENT = 2;
|
const EV_CLIENT_EVENT = 2;
|
||||||
const EV_CLIENT_INIT = 3;
|
const EV_CLIENT_INIT = 3;
|
||||||
const EV_CLIENT_INIT_REPLAY = 6;
|
const EV_CLIENT_REPLAY_DATA = 6;
|
||||||
const LOG_HEADER = 1;
|
const LOG_HEADER = 1;
|
||||||
const LOG_ADD_PLAYER = 2;
|
const LOG_ADD_PLAYER = 2;
|
||||||
const LOG_UPDATE_PLAYER = 4;
|
const LOG_UPDATE_PLAYER = 4;
|
||||||
|
|
@ -342,10 +344,10 @@ const CHANGE_PLAYER = 3;
|
||||||
var Protocol = {
|
var Protocol = {
|
||||||
EV_SERVER_EVENT,
|
EV_SERVER_EVENT,
|
||||||
EV_SERVER_INIT,
|
EV_SERVER_INIT,
|
||||||
EV_SERVER_INIT_REPLAY,
|
EV_SERVER_REPLAY_DATA,
|
||||||
EV_CLIENT_EVENT,
|
EV_CLIENT_EVENT,
|
||||||
EV_CLIENT_INIT,
|
EV_CLIENT_INIT,
|
||||||
EV_CLIENT_INIT_REPLAY,
|
EV_CLIENT_REPLAY_DATA,
|
||||||
LOG_HEADER,
|
LOG_HEADER,
|
||||||
LOG_ADD_PLAYER,
|
LOG_ADD_PLAYER,
|
||||||
LOG_UPDATE_PLAYER,
|
LOG_UPDATE_PLAYER,
|
||||||
|
|
@ -514,6 +516,9 @@ function getPlayerIdByIndex(gameId, playerIndex) {
|
||||||
}
|
}
|
||||||
function getPlayer(gameId, playerId) {
|
function getPlayer(gameId, playerId) {
|
||||||
const idx = getPlayerIndexById(gameId, playerId);
|
const idx = getPlayerIndexById(gameId, playerId);
|
||||||
|
if (idx === -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return Util.decodePlayer(GAMES[gameId].players[idx]);
|
return Util.decodePlayer(GAMES[gameId].players[idx]);
|
||||||
}
|
}
|
||||||
function setPlayer(gameId, playerId, player) {
|
function setPlayer(gameId, playerId, player) {
|
||||||
|
|
@ -611,6 +616,9 @@ function getTilesSortedByZIndex(gameId) {
|
||||||
}
|
}
|
||||||
function changePlayer(gameId, playerId, change) {
|
function changePlayer(gameId, playerId, change) {
|
||||||
const player = getPlayer(gameId, playerId);
|
const player = getPlayer(gameId, playerId);
|
||||||
|
if (player === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (let k of Object.keys(change)) {
|
for (let k of Object.keys(change)) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
player[k] = change[k];
|
player[k] = change[k];
|
||||||
|
|
@ -890,9 +898,13 @@ function handleInput$1(gameId, playerId, input, ts) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const _playerChange = () => {
|
const _playerChange = () => {
|
||||||
|
const player = getPlayer(gameId, playerId);
|
||||||
|
if (!player) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
changes.push([
|
changes.push([
|
||||||
Protocol.CHANGE_PLAYER,
|
Protocol.CHANGE_PLAYER,
|
||||||
Util.encodePlayer(getPlayer(gameId, playerId)),
|
Util.encodePlayer(player),
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
// put both tiles (and their grouped tiles) in the same group
|
// put both tiles (and their grouped tiles) in the same group
|
||||||
|
|
@ -1175,7 +1187,6 @@ const PUBLIC_DIR = `${BASE_DIR}/build/public/`;
|
||||||
const DB_PATCHES_DIR = `${BASE_DIR}/src/dbpatches`;
|
const DB_PATCHES_DIR = `${BASE_DIR}/src/dbpatches`;
|
||||||
const DB_FILE = `${BASE_DIR}/data/db.sqlite`;
|
const DB_FILE = `${BASE_DIR}/data/db.sqlite`;
|
||||||
|
|
||||||
const log$4 = logger('GameLog.js');
|
|
||||||
const filename = (gameId) => `${DATA_DIR}/log_${gameId}.log`;
|
const filename = (gameId) => `${DATA_DIR}/log_${gameId}.log`;
|
||||||
const create = (gameId) => {
|
const create = (gameId) => {
|
||||||
const file = filename(gameId);
|
const file = filename(gameId);
|
||||||
|
|
@ -1195,20 +1206,35 @@ const _log = (gameId, ...args) => {
|
||||||
const str = JSON.stringify(args);
|
const str = JSON.stringify(args);
|
||||||
fs.appendFileSync(file, str + "\n");
|
fs.appendFileSync(file, str + "\n");
|
||||||
};
|
};
|
||||||
const get = (gameId) => {
|
const get = async (gameId, offset = 0, size = 10000) => {
|
||||||
const file = filename(gameId);
|
const file = filename(gameId);
|
||||||
if (!fs.existsSync(file)) {
|
if (!fs.existsSync(file)) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const lines = fs.readFileSync(file, 'utf-8').split("\n");
|
return new Promise((resolve) => {
|
||||||
return lines.filter((line) => !!line).map((line) => {
|
const instream = fs.createReadStream(file);
|
||||||
try {
|
const outstream = new stream.Writable();
|
||||||
return JSON.parse(line);
|
const rl = readline.createInterface(instream, outstream);
|
||||||
}
|
const lines = [];
|
||||||
catch (e) {
|
let i = -1;
|
||||||
log$4.log(line);
|
rl.on('line', (line) => {
|
||||||
log$4.log(e);
|
if (!line) {
|
||||||
}
|
// skip empty
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
if (offset > i) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (offset + size <= i) {
|
||||||
|
rl.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lines.push(JSON.parse(line));
|
||||||
|
});
|
||||||
|
rl.on('close', () => {
|
||||||
|
resolve(lines);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
var GameLog = {
|
var GameLog = {
|
||||||
|
|
@ -2021,14 +2047,20 @@ wss.on('message', async ({ socket, data }) => {
|
||||||
const msg = JSON.parse(data);
|
const msg = JSON.parse(data);
|
||||||
const msgType = msg[0];
|
const msgType = msg[0];
|
||||||
switch (msgType) {
|
switch (msgType) {
|
||||||
case Protocol.EV_CLIENT_INIT_REPLAY:
|
case Protocol.EV_CLIENT_REPLAY_DATA:
|
||||||
{
|
{
|
||||||
if (!GameLog.exists(gameId)) {
|
if (!GameLog.exists(gameId)) {
|
||||||
throw `[gamelog ${gameId} does not exist... ]`;
|
throw `[gamelog ${gameId} does not exist... ]`;
|
||||||
}
|
}
|
||||||
const log = GameLog.get(gameId);
|
const offset = msg[1];
|
||||||
const game = await Game.createGameObject(gameId, log[0][2], log[0][3], log[0][4], log[0][5] || ScoreMode.FINAL);
|
const size = msg[2];
|
||||||
notify([Protocol.EV_SERVER_INIT_REPLAY, Util.encodeGame(game), log], [socket]);
|
const log = await GameLog.get(gameId, offset, size);
|
||||||
|
let game = null;
|
||||||
|
if (offset === 0) {
|
||||||
|
// also need the game
|
||||||
|
game = await Game.createGameObject(gameId, log[0][2], log[0][3], log[0][4], log[0][5] || ScoreMode.FINAL);
|
||||||
|
}
|
||||||
|
notify([Protocol.EV_SERVER_REPLAY_DATA, log, game ? Util.encodeGame(game) : null], [socket]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Protocol.EV_CLIENT_INIT:
|
case Protocol.EV_CLIENT_INIT:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue