index.ts 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. // Server entry point. Runs headless (`npm run server`) or inside an Electron utilityProcess.
  2. import { DEFAULT_MAP_ID, NET_PORT } from '../shared/constants';
  3. import { loadCharacterStats, loadMap, loadMaterials, resolveAssetsDir } from './assets';
  4. import { Game } from './game';
  5. import { GameServer } from './net';
  6. interface ParentPort {
  7. postMessage(message: unknown): void;
  8. }
  9. /** Set by Electron when this file runs in a utilityProcess. */
  10. const parentPort = (process as { parentPort?: ParentPort }).parentPort;
  11. function arg(name: string): string | undefined {
  12. const prefix = `--${name}=`;
  13. return process.argv.find((a) => a.startsWith(prefix))?.slice(prefix.length);
  14. }
  15. function main(): void {
  16. const assetsDir = resolveAssetsDir();
  17. const mapId = arg('map') ?? DEFAULT_MAP_ID;
  18. const port = Number(arg('port') ?? NET_PORT);
  19. // The only place the seed is drawn; everything downstream uses the seeded RNG.
  20. const seed = Number(arg('seed') ?? Date.now() % 0x7fffffff);
  21. const materials = loadMaterials(assetsDir);
  22. const { definition, terrain } = loadMap(assetsDir, mapId, materials);
  23. const game = new Game({
  24. map: definition,
  25. terrain,
  26. materials,
  27. seed,
  28. loadCharacter: (id) => loadCharacterStats(assetsDir, id),
  29. });
  30. const server = new GameServer(game, port, '0.0.0.0', () => {
  31. console.log(`[server] map "${mapId}" (seed ${seed}) listening on :${port}`);
  32. parentPort?.postMessage({ type: 'ready', port });
  33. });
  34. server.start();
  35. const shutdown = (): void => {
  36. server.close();
  37. process.exit(0);
  38. };
  39. process.on('SIGINT', shutdown);
  40. process.on('SIGTERM', shutdown);
  41. }
  42. try {
  43. main();
  44. } catch (err) {
  45. console.error('[server] failed to start:', err);
  46. parentPort?.postMessage({ type: 'error', message: err instanceof Error ? err.message : String(err) });
  47. process.exit(1);
  48. }