silphius/app/net/server/worker.js
2024-07-11 16:01:16 -05:00

130 lines
3.8 KiB
JavaScript

import {del, get, set} from 'idb-keyval';
import {encode} from '@/packets/index.js';
import createEcs from '../../create-ecs.js';
import '../../create-forest.js';
import '../../create-homestead.js';
import '../../create-player.js';
import Engine from '../../engine.js';
import Server from './server.js';
class WorkerServer extends Server {
constructor() {
super();
this.fs = {};
}
static qualify(path) {
return ['UNIVERSE', path].join('/');
}
async readAsset(path) {
return fetch(path).then((response) => (
response.ok ? response.arrayBuffer() : new ArrayBuffer(0)
));
}
async readData(path) {
const data = await get(this.constructor.qualify(path));
if ('undefined' !== typeof data) {
return data;
}
const error = new Error();
error.code = 'ENOENT';
throw error;
}
async removeData(path) {
await del(this.constructor.qualify(path));
}
async writeData(path, view) {
await set(this.constructor.qualify(path), view);
}
transmit(connection, packed) { postMessage(packed); }
}
const engine = new Engine(WorkerServer);
onmessage = async (event) => {
if (0 === event.data) {
engine.stop();
await engine.disconnectPlayer(0);
await engine.saveEcses();
postMessage(0);
return;
}
engine.server.accept(0, event.data);
};
(async () => {
await engine.load();
engine.start();
await engine.connectPlayer(0, 0);
postMessage(encode({type: 'ConnectionStatus', payload: 'connected'}));
})();
if (import.meta.hot) {
const createResolver = () => {
let r;
const promise = new Promise((resolve) => {
r = resolve;
});
promise.resolve = r;
return promise;
};
const beforeResolver = createResolver();
const resolvers = [];
import.meta.hot.on('vite:beforeUpdate', async () => {
engine.stop();
await engine.disconnectPlayer(0);
await engine.saveEcses();
beforeResolver.resolve();
});
import.meta.hot.accept('../../engine.js');
import.meta.hot.accept('../../create-player.js', async ({default: createPlayer}) => {
const resolver = createResolver();
resolvers.push(resolver);
await beforeResolver;
const oldBuffer = await engine.server.readData('players/0');
const oldPlayer = JSON.parse((new TextDecoder()).decode(oldBuffer));
const buffer = await createPlayer(0);
const player = JSON.parse((new TextDecoder()).decode(buffer));
// Less jarring
player.Ecs = oldPlayer.Ecs;
player.Direction = oldPlayer.Direction;
player.Position = oldPlayer.Position;
await engine.server.writeData('players/0', (new TextEncoder()).encode(JSON.stringify(player)));
resolver.resolve();
});
import.meta.hot.accept('../../create-forest.js', async ({default: createForest}) => {
const resolver = createResolver();
resolvers.push(resolver);
await beforeResolver;
delete engine.ecses['forests/0'];
await engine.server.removeData('forests/0');
const forest = createEcs(engine.Ecs);
for (const entity of await createForest()) {
await forest.create(entity);
}
await engine.saveEcs('forests/0', forest);
resolver.resolve();
});
import.meta.hot.accept('../../create-homestead.js', async ({default: createHomestead}) => {
const resolver = createResolver();
resolvers.push(resolver);
await beforeResolver;
delete engine.ecses['homesteads/0'];
await engine.server.removeData('homesteads/0');
const homestead = createEcs(engine.Ecs);
for (const entity of await createHomestead('0')) {
await homestead.create(entity);
}
await engine.saveEcs('homesteads/0', homestead);
resolver.resolve();
});
import.meta.hot.on('vite:afterUpdate', async () => {
await Promise.all(resolvers);
postMessage(encode({type: 'ConnectionStatus', payload: 'aborted'}));
close();
});
import.meta.hot.accept();
}