153 lines
4.4 KiB
JavaScript
153 lines
4.4 KiB
JavaScript
import {del, get, set} from 'idb-keyval';
|
|
|
|
import {encode} from '@/net/packets/index.js';
|
|
import Server from '@/net/server.js';
|
|
import {withResolvers} from '@/util/promise.js';
|
|
import {readAsset} from '@/util/resources.js';
|
|
|
|
import createEcs from './create/ecs.js';
|
|
import './create/forest.js';
|
|
import './create/homestead.js';
|
|
import './create/player.js';
|
|
import './create/town.js';
|
|
|
|
import Engine from './engine.js';
|
|
|
|
class WorkerServer extends Server {
|
|
constructor() {
|
|
super();
|
|
this.fs = {};
|
|
}
|
|
static qualify(path) {
|
|
return ['UNIVERSE', path].join('/');
|
|
}
|
|
async readAsset(path) {
|
|
const resource = await readAsset(path);
|
|
return resource
|
|
? resource
|
|
: 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) {
|
|
await engine.disconnectPlayer(0);
|
|
engine.stop();
|
|
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 before = withResolvers();
|
|
const promises = [before.promise];
|
|
const accepted = [
|
|
'/app/server/engine.js',
|
|
'/app/server/create/player.js',
|
|
'/app/server/create/forest.js',
|
|
'/app/server/create/town.js',
|
|
'/app/server/create/homestead.js',
|
|
];
|
|
let isAccepted = false;
|
|
import.meta.hot.on('vite:beforeUpdate', async ({updates}) => {
|
|
isAccepted = !!updates.find(({acceptedPath}) => accepted.includes(acceptedPath));
|
|
if (!isAccepted) {
|
|
return;
|
|
}
|
|
await engine.disconnectPlayer(0);
|
|
engine.stop();
|
|
await engine.saveEcses();
|
|
before.resolve();
|
|
});
|
|
import.meta.hot.accept('./engine.js');
|
|
import.meta.hot.accept('./create/player.js', async ({default: createPlayer}) => {
|
|
const {promise, resolve} = withResolvers();
|
|
promises.push(promise);
|
|
await before.promise;
|
|
const oldPlayer = await engine.loadPlayer(0);
|
|
const player = await createPlayer(0);
|
|
// Less jarring
|
|
player.Ecs = oldPlayer.Ecs;
|
|
player.Direction = oldPlayer.Direction;
|
|
player.Position = oldPlayer.Position;
|
|
await engine.savePlayer(0, player);
|
|
resolve();
|
|
});
|
|
import.meta.hot.accept('./create/forest.js', async ({default: createForest}) => {
|
|
const {promise, resolve} = withResolvers();
|
|
promises.push(promise);
|
|
await before.promise;
|
|
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);
|
|
resolve();
|
|
});
|
|
import.meta.hot.accept('./create/homestead.js', async ({default: createHomestead}) => {
|
|
const {promise, resolve} = withResolvers();
|
|
promises.push(promise);
|
|
await before.promise;
|
|
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);
|
|
resolve();
|
|
});
|
|
import.meta.hot.accept('./create/town.js', async ({default: createTown}) => {
|
|
const {promise, resolve} = withResolvers();
|
|
promises.push(promise);
|
|
await before.promise;
|
|
delete engine.ecses['town'];
|
|
await engine.server.removeData('town');
|
|
const town = createEcs(engine.Ecs);
|
|
for (const entity of await createTown()) {
|
|
await town.create(entity);
|
|
}
|
|
await engine.saveEcs('town', town);
|
|
resolve();
|
|
});
|
|
import.meta.hot.on('vite:afterUpdate', async () => {
|
|
if (!isAccepted) {
|
|
return;
|
|
}
|
|
await Promise.all(promises);
|
|
postMessage(encode({type: 'ConnectionStatus', payload: 'aborted'}));
|
|
postMessage(encode({type: 'EcsChange'}));
|
|
close();
|
|
});
|
|
import.meta.hot.accept();
|
|
}
|