silphius/app/websocket.js

110 lines
2.7 KiB
JavaScript
Raw Normal View History

2024-06-29 09:52:23 -05:00
import {mkdir, readFile, unlink, writeFile} from 'node:fs/promises';
2024-06-14 15:18:55 -05:00
import {dirname, join} from 'node:path';
2024-06-10 22:42:30 -05:00
import {WebSocketServer} from 'ws';
2024-06-14 15:18:55 -05:00
import Server from '@/net/server/server.js';
import {getSession} from '@/session.server.js';
2024-06-23 07:00:10 -05:00
import Engine from './engine.js';
2024-06-10 22:42:30 -05:00
2024-06-29 06:28:27 -05:00
const isInsecure = process.env.SILPHIUS_INSECURE_HTTP;
2024-06-10 22:42:30 -05:00
const wss = new WebSocketServer({
noServer: true,
});
function onUpgrade(request, socket, head) {
const {pathname} = new URL(request.url, 'wss://base.url');
if (pathname === '/ws') {
wss.handleUpgrade(request, socket, head, function done(ws) {
wss.emit('connection', ws, request);
});
}
else {
socket.destroy();
}
}
2024-06-13 21:00:40 -05:00
let engine;
let onConnect;
2024-06-10 22:42:30 -05:00
2024-06-13 21:00:40 -05:00
function createOnConnect(engine) {
2024-06-14 15:18:55 -05:00
onConnect = async (ws, request) => {
ws.on('close', async () => {
await engine.disconnectPlayer(ws);
2024-06-13 21:00:40 -05:00
})
ws.on('message', (packed) => {
engine.server.accept(ws, new DataView(packed.buffer, packed.byteOffset, packed.length));
});
2024-06-14 15:18:55 -05:00
const session = await getSession(request.headers['cookie']);
await engine.connectPlayer(ws, session.get('id'));
2024-06-13 21:00:40 -05:00
};
wss.on('connection', onConnect);
}
2024-06-10 22:42:30 -05:00
2024-06-13 21:00:40 -05:00
class SocketServer extends Server {
2024-06-14 15:18:55 -05:00
async ensurePath(path) {
await mkdir(path, {recursive: true});
}
static qualify(path) {
return join(import.meta.dirname, 'data', 'remote', 'UNIVERSE', path);
}
2024-06-27 07:37:20 -05:00
async readAsset(path) {
const url = new URL(path, 'https://localhost:3000')
2024-06-29 06:28:27 -05:00
if (isInsecure) {
2024-06-27 07:37:20 -05:00
url.protocol = 'http:';
}
2024-06-27 13:56:43 -05:00
return fetch(url.href).then((response) => (
response.ok ? response.arrayBuffer() : new ArrayBuffer(0)
));
2024-06-27 07:37:20 -05:00
}
2024-06-14 15:18:55 -05:00
async readData(path) {
const qualified = this.constructor.qualify(path);
await this.ensurePath(dirname(qualified));
return readFile(qualified);
}
2024-06-29 09:52:23 -05:00
async removeData(path) {
await unlink(path);
}
2024-06-14 15:18:55 -05:00
async writeData(path, view) {
const qualified = this.constructor.qualify(path);
await this.ensurePath(dirname(qualified));
await writeFile(qualified, view);
}
2024-06-13 21:00:40 -05:00
transmit(ws, packed) { ws.send(packed); }
}
2024-06-10 22:42:30 -05:00
2024-06-13 21:00:40 -05:00
async function createEngine(Engine) {
engine = new Engine(SocketServer);
await engine.load();
engine.start();
return engine;
}
2024-06-10 22:42:30 -05:00
2024-06-13 21:00:40 -05:00
async function remakeServer(Engine) {
if (onConnect) {
wss.off('connection', onConnect);
}
if (engine) {
for (const [connection] of engine.connectedPlayers) {
connection.close();
}
2024-06-10 22:42:30 -05:00
}
2024-06-13 21:00:40 -05:00
createOnConnect(await createEngine(Engine));
}
2024-06-18 04:36:32 -05:00
(async () => {
await remakeServer(Engine);
})();
2024-06-13 21:00:40 -05:00
if (import.meta.hot) {
2024-06-23 07:00:10 -05:00
import.meta.hot.accept('./engine.js', async ({default: Engine}) => {
2024-06-13 21:00:40 -05:00
await remakeServer(Engine);
});
}
export default async function listen(server) {
server.on('upgrade', onUpgrade);
2024-06-10 22:42:30 -05:00
}