UNPKG

colyseus

Version:

Multiplayer Framework for Node.js

278 lines (276 loc) 9.7 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // bundles/colyseus/src/vite.ts var vite_exports = {}; __export(vite_exports, { colyseus: () => colyseus, createColyseusViteServerEntry: () => createColyseusViteServerEntry, reloadColyseusViteRooms: () => reloadColyseusViteRooms }); module.exports = __toCommonJS(vite_exports); var matchMaker = __toESM(require("@colyseus/core/MatchMaker"), 1); var import_core = require("@colyseus/core"); var import_Transport = require("@colyseus/core/Transport"); var VIRTUAL_SERVER_ENTRY = "virtual:colyseus-server-entry"; var RESOLVED_VIRTUAL_SERVER_ENTRY = "\0" + VIRTUAL_SERVER_ENTRY; function getServerExport(mod) { return mod.server || mod.default?.server; } function getRoomsExport(mod) { return mod.rooms || mod.default?.rooms; } function createColyseusViteServerEntry(options) { const port = options.port ?? 2567; const lines = [ `import { Server, registerRoomDefinitions } from "colyseus";` ]; if (options.serveClient) { lines.push( `import express from "express";`, `import { fileURLToPath } from "url";`, `import { dirname, join } from "path";`, ``, `const __dirname = dirname(fileURLToPath(import.meta.url));`, `const clientDir = join(__dirname, "../client");` ); } lines.push( ``, `const entry = await import(${JSON.stringify(options.serverEntry)});`, `const server = entry.server ?? entry.default?.server;`, `const rooms = entry.rooms ?? entry.default?.rooms;`, ``, `if (server) {` ); if (options.serveClient) { lines.push( ` await server["_onTransportReady"];`, ` if (server.transport.getExpressApp) {`, ` const app = server.transport.getExpressApp();`, ` app.use(express.static(clientDir));`, ` app.get("*all", (req, res) => res.sendFile(join(clientDir, "index.html")));`, ` }` ); } lines.push( ` server.listen(${port});`, `} else if (rooms) {`, ` const gameServer = new Server();`, ` registerRoomDefinitions(rooms);`, ` gameServer.listen(${port});`, `} else {`, ` throw new Error('[colyseus] Server entry should export \`server = defineServer(...)\` or \`rooms\`.');`, `}` ); return lines.join("\n"); } async function reloadColyseusViteRooms(importModule, serverEntry, currentRoomNames = []) { const mod = await importModule(serverEntry); (0, import_core.unregisterRoomDefinitions)(currentRoomNames); const server = getServerExport(mod); const rooms = getRoomsExport(mod) || server?.["~rooms"]; if (!rooms) { return { roomNames: [], hasRooms: false, server }; } return { roomNames: (0, import_core.registerRoomDefinitions)(rooms), hasRooms: true, server }; } function colyseus(options) { let viteServer; let currentRoomNames = []; let currentAppHandler = null; let expressApp = null; let isStarted = false; return [ { name: "colyseus:config", config() { return { builder: {}, build: { outDir: "dist/client" }, environments: { colyseus: { consumer: "server", resolve: { // Externalize all dependencies so they share the same module // instances (and matchMaker singleton) with the plugin process. // Without this, Vite re-evaluates workspace/linked packages in // the runner, creating isolated singletons — breaking monitor, etc. external: true }, build: { outDir: "dist/server", ssr: true, rollupOptions: { input: VIRTUAL_SERVER_ENTRY, output: { entryFileNames: "server.mjs" } } } } } }; }, resolveId(id) { if (id === VIRTUAL_SERVER_ENTRY) { return RESOLVED_VIRTUAL_SERVER_ENTRY; } }, load(id) { if (id === RESOLVED_VIRTUAL_SERVER_ENTRY) { return createColyseusViteServerEntry(options); } } }, { name: "colyseus:dev-server", configureServer(server) { viteServer = server; server.middlewares.use((0, import_core.createNodeMatchmakingMiddleware)()); server.middlewares.use((req, res, next) => { if (!currentAppHandler) { return next(); } currentAppHandler(req, res, next); }); return async () => { if (!server.httpServer) { throw new Error("[colyseus] Vite HTTP server not available."); } await loadServerModule(); console.log("[colyseus] Server ready on Vite's HTTP server"); }; } }, { name: "colyseus:hmr", hotUpdate({ file, modules }) { if (this.environment?.name === "colyseus" && modules.length > 0) { loadServerModule().then(() => { if (!options.quiet) { console.log(`[colyseus] Server code reloaded (${file})`); } }).catch((e) => { console.error("[colyseus] Failed to reload server module:", e); }); } } } ]; async function loadServerModule() { const env = viteServer.environments.colyseus; if (!env) { console.error("[colyseus] Environment not found"); return; } try { if (isStarted && env.runner.evaluatedModules) { env.runner.evaluatedModules.clear(); } if (!isStarted) { (0, import_core.setDevMode)(true); await matchMaker.setup(); const wsModule = await (options.loadWsTransport ? options.loadWsTransport() : (0, import_core.dynamicImport)("@colyseus/ws-transport")); const transport = new wsModule.WebSocketTransport({ noServer: true }); if (typeof transport.attachToServer !== "function") { throw new Error("[colyseus] Vite dev mode requires a transport with attachToServer()."); } transport.attachToServer(viteServer.httpServer, { filter(req) { return /^\/[a-zA-Z0-9_-]+\/[a-zA-Z0-9_-]+\/?$/.test( new URL(req.url || "", "http://localhost").pathname ); } }); (0, import_Transport.setTransport)(transport); } const mod = await env.runner.import(options.serverEntry); const config = getServerExport(mod); const rooms = getRoomsExport(mod) || config?.["~rooms"]; const router = config?.router; if (!expressApp && config?.options?.express) { try { const express = (await (0, import_core.dynamicImport)("express")).default; expressApp = express(); config.options.express(expressApp); } catch (e) { console.warn("[colyseus] Express not available. Install express to use the express option."); } } if (router || expressApp) { const routerHandler = router ? (0, import_core.toNodeHandler)(router.handler) : null; currentAppHandler = (req, res, next) => { if (router?.findRoute(req.method, req.url?.split("?")[0]) !== void 0) { routerHandler(req, res); } else if (expressApp) { expressApp(req, res, next); } else { next(); } }; } else { currentAppHandler = null; } (0, import_core.unregisterRoomDefinitions)(currentRoomNames); if (rooms) { currentRoomNames = (0, import_core.registerRoomDefinitions)(rooms); } else { currentRoomNames = []; console.warn( "[colyseus] Server entry should export `server = defineServer(...)` or `rooms`." ); } if (!isStarted) { await matchMaker.accept(); isStarted = true; } else { await matchMaker.hotReload(); } if (!options.quiet) { for (const roomName of currentRoomNames) { console.log(`[colyseus] Room defined: "${roomName}"`); } } } catch (e) { console.error("[colyseus] Failed to load server module:", e); } } } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { colyseus, createColyseusViteServerEntry, reloadColyseusViteRooms });