@esengine/server 4.4.0 → 4.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{Room-BnKpl5Sj.d.ts → Room-5owFVIFR.d.ts} +18 -0
- package/dist/auth/index.d.ts +4 -4
- package/dist/auth/testing/index.d.ts +2 -2
- package/dist/chunk-NWZLKNGV.js +2045 -0
- package/dist/chunk-NWZLKNGV.js.map +1 -0
- package/dist/{chunk-FACTBKJ3.js → chunk-T3QJOPNG.js} +37 -2
- package/dist/chunk-T3QJOPNG.js.map +1 -0
- package/dist/chunk-ZUTL4RI7.js +285 -0
- package/dist/chunk-ZUTL4RI7.js.map +1 -0
- package/dist/ecs/index.d.ts +31 -4
- package/dist/ecs/index.js +3 -280
- package/dist/ecs/index.js.map +1 -1
- package/dist/index-B1sr5YAl.d.ts +1076 -0
- package/dist/index.d.ts +1453 -7
- package/dist/index.js +1502 -4
- package/dist/index.js.map +1 -1
- package/dist/ratelimit/index.d.ts +1 -1
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.js +2 -2
- package/dist/{types-C7sS8Sfi.d.ts → types-BCTRacMF.d.ts} +2 -2
- package/package.json +2 -2
- package/dist/chunk-FACTBKJ3.js.map +0 -1
- package/dist/chunk-M7VONMZJ.js +0 -938
- package/dist/chunk-M7VONMZJ.js.map +0 -1
- package/dist/decorators-DY8nZ8Nh.d.ts +0 -26
- package/dist/index-lcuKuQsL.d.ts +0 -470
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/room/RoomManager.ts","../src/http/router.ts","../src/distributed/DistributedRoomManager.ts","../src/distributed/adapters/MemoryAdapter.ts","../src/router/loader.ts","../src/core/server.ts"],"names":["logger","createLogger","RoomManager","sendFn","sendBinaryFn","_definitions","Map","_rooms","_playerToRoom","_nextRoomId","_sendFn","_sendBinaryFn","define","name","roomClass","set","create","options","room","_createRoomInstance","_onRoomCreated","info","id","_name","_room","joinOrCreate","playerId","conn","_findAvailableRoom","player","_addPlayer","_onPlayerJoined","joinById","roomId","get","leave","reason","_removePlayer","_onPlayerLeft","handleMessage","type","data","_handleMessage","getRoom","getPlayerRoom","undefined","getRooms","Array","from","values","getRoomsByType","def","filter","isFull","isLocked","isDisposed","_generateRoomId","_getDefinition","warn","finalRoomId","_init","broadcastFn","players","send","disposeFn","_onRoomDisposed","_create","delete","_player","_roomId","parseRoutePath","path","paramNames","isStatic","includes","pattern","RegExp","escapeRegex","segments","split","map","segment","startsWith","paramName","slice","push","join","str","replace","matchRoute","routes","method","route","test","params","match","forEach","index","decodeURIComponent","createRequest","req","url","URL","headers","host","query","searchParams","value","key","body","parseBody","ip","trim","socket","remoteAddress","raw","pathname","Promise","resolve","chunks","on","chunk","rawBody","Buffer","concat","toString","contentType","JSON","parse","URLSearchParams","result","createResponse","res","statusCode","ended","response","status","code","header","setHeader","json","end","stringify","text","error","message","createOriginWhitelist","origins","whitelist","origin","applyCors","cors","credentials","isArray","requestOrigin","methods","allowedHeaders","maxAge","String","executeMiddlewares","middlewares","finalHandler","next","length","middleware","executeWithTimeout","handler","timeoutMs","resolved","timeoutPromise","_","reject","setTimeout","Error","race","then","writableEnded","isHandlerDefinition","isRouteMethods","Object","keys","some","extractHandler","methodHandler","timeout","createHttpRouter","globalMiddlewares","globalTimeout","parsedRoutes","handlerOrMethods","entries","corsOptions","handleRequest","httpReq","httpRes","allMiddlewares","executeHandler","DistributedRoomManager","adapter","config","_adapter","_config","_serverId","_heartbeatTimer","_snapshotTimer","_subscriptions","_isShuttingDown","serverId","serverAddress","serverPort","heartbeatInterval","snapshotInterval","migrationTimeout","enableFailover","capacity","metadata","start","isConnected","connect","_registerServer","_subscribeToEvents","_startHeartbeat","_startSnapshotTimer","stop","graceful","clearInterval","unsub","updateServer","_saveAllSnapshots","unregisterServer","registration","roomType","playerCount","maxPlayers","createdAt","Date","now","updatedAt","registerRoom","debug","unregisterRoom","catch","err","deleteSnapshot","updateRoom","request","_routeToRoom","_routeByType","joinOrCreateDistributed","lockKey","locked","acquireLock","_sleep","availableRoom","findAvailableRoom","redirect","releaseLock","saveSnapshot","_getDefinitionByRoom","snapshot","state","p","version","timestamp","restoreFromSnapshot","loadSnapshot","address","port","roomCount","size","_countTotalPlayers","lastHeartbeat","registerServer","subscribe","event","_handleServerOffline","roomMsgUnsub","_handleRoomMessage","setInterval","heartbeat","promises","allSettled","has","_query","offlineServerId","_tryRecoverRoomsFromServer","rooms","queryRooms","roomReg","acquired","success","publish","payload","fromServer","toServer","messageType","count","ms","sendToRemoteRoom","sendToRoom","getServers","queryDistributedRooms","MemoryAdapter","_connected","_servers","_snapshots","_locks","_subscribers","_subscriberId","_ttlCheckTimer","serverTtl","enableTtlCheck","ttlCheckInterval","_checkServerTtl","disconnect","clear","server","_ensureConnected","s","getServer","updates","assign","_countRoomsByServer","results","r","hasSpace","notLocked","offset","limit","getRoomsByServer","wildcardHandlers","Set","typeHandlers","console","add","handlers","ttlMs","existing","expireAt","owner","extendLock","lock","expiredServers","_clear","_getState","servers","snapshots","fileNameToHandlerName","fileName","baseName","part","charAt","toUpperCase","scanDirectory","dir","existsSync","files","readdirSync","withFileTypes","entry","isFile","loadApiHandlers","apiDir","filePath","fileUrl","pathToFileURL","href","module","definition","default","basename","loadMsgHandlers","msgDir","scanDirectoryRecursive","baseDir","fullPath","isDirectory","relativePath","relative","filePathToRoute","prefix","fullRoute","endsWith","loadHttpHandlers","httpDir","DEFAULT_CONFIG","httpPrefix","tickRate","createServer","opts","cwd","process","apiHandlers","msgHandlers","httpHandlers","mergedHttpRoutes","existingRoute","http","hasHttpRoutes","distributedConfig","distributed","isDistributed","enabled","apiDefs","JoinRoom","rpc","api","LeaveRoom","msgDefs","RoomMessage","msg","$redirect","protocol","currentTick","tickInterval","rpcServer","httpServer","sendBinary","roomManager","distributedManager","apiMap","msgMap","gameServer","connections","tick","apiHandlersObj","input","_input","ctx","schema","validate","pathStr","msgHandlersObj","httpRouter","createHttpServer","handled","serve","createConnData","onStart","onConnect","onDisconnect","listen","close","broadcast"],"mappings":"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","file":"chunk-NWZLKNGV.js","sourcesContent":["/**\n * @zh 房间管理器\n * @en Room manager\n */\n\nimport { Room, type RoomOptions } from './Room.js';\nimport type { Player } from './Player.js';\nimport { createLogger } from '../logger.js';\n\nconst logger = createLogger('Room');\n\n/**\n * @zh 房间类型\n * @en Room class type\n */\nexport type RoomClass<T extends Room = Room> = new () => T\n\n/**\n * @zh 房间定义\n * @en Room definition\n */\ninterface RoomDefinition {\n roomClass: RoomClass\n}\n\n/**\n * @zh 房间管理器\n * @en Room manager\n *\n * @zh 管理房间的创建、加入、离开等操作。可被 DistributedRoomManager 继承以支持分布式功能。\n * @en Manages room creation, joining, leaving, etc. Can be extended by DistributedRoomManager for distributed features.\n */\nexport class RoomManager {\n /**\n * @zh 房间类型定义映射\n * @en Room type definitions map\n */\n protected _definitions: Map<string, RoomDefinition> = new Map();\n\n /**\n * @zh 房间实例映射\n * @en Room instances map\n */\n protected _rooms: Map<string, Room> = new Map();\n\n /**\n * @zh 玩家到房间的映射\n * @en Player to room mapping\n */\n protected _playerToRoom: Map<string, string> = new Map();\n\n /**\n * @zh 下一个房间 ID 计数器\n * @en Next room ID counter\n */\n protected _nextRoomId = 1;\n\n /**\n * @zh 消息发送函数\n * @en Message send function\n */\n protected _sendFn: (conn: any, type: string, data: unknown) => void;\n\n /**\n * @zh 二进制发送函数\n * @en Binary send function\n */\n protected _sendBinaryFn?: (conn: any, data: Uint8Array) => void;\n\n constructor(\n sendFn: (conn: any, type: string, data: unknown) => void,\n sendBinaryFn?: (conn: any, data: Uint8Array) => void\n ) {\n this._sendFn = sendFn;\n this._sendBinaryFn = sendBinaryFn;\n }\n\n /**\n * @zh 注册房间类型\n * @en Define room type\n */\n define<T extends Room>(name: string, roomClass: RoomClass<T>): void {\n this._definitions.set(name, { roomClass });\n }\n\n /**\n * @zh 创建房间\n * @en Create room\n *\n * @param name - 房间类型名称 | Room type name\n * @param options - 房间配置 | Room options\n * @returns 房间实例或 null | Room instance or null\n */\n async create(name: string, options?: RoomOptions): Promise<Room | null> {\n const room = await this._createRoomInstance(name, options);\n if (room) {\n await this._onRoomCreated(name, room);\n logger.info(`Created: ${name} (${room.id})`);\n }\n return room;\n }\n\n /**\n * @zh 房间创建后的回调\n * @en Callback after room is created\n *\n * @param _name - 房间类型名称 | Room type name\n * @param _room - 房间实例 | Room instance\n */\n protected async _onRoomCreated(_name: string, _room: Room): Promise<void> {\n // 子类可覆盖以添加分布式注册等逻辑 | Subclass can override to add distributed registration logic\n }\n\n /**\n * @zh 加入或创建房间\n * @en Join or create room\n *\n * @param name - 房间类型名称 | Room type name\n * @param playerId - 玩家 ID | Player ID\n * @param conn - 玩家连接 | Player connection\n * @param options - 房间配置 | Room options\n * @returns 房间和玩家实例或 null | Room and player instance or null\n */\n async joinOrCreate(\n name: string,\n playerId: string,\n conn: any,\n options?: RoomOptions\n ): Promise<{ room: Room; player: Player } | null> {\n // 查找可加入的房间 | Find available room\n let room = this._findAvailableRoom(name);\n\n // 没有则创建 | Create if none exists\n if (!room) {\n room = await this.create(name, options);\n if (!room) return null;\n }\n\n // 加入房间 | Join room\n const player = await room._addPlayer(playerId, conn);\n if (!player) return null;\n\n this._onPlayerJoined(playerId, room.id, player);\n\n logger.info(`Player ${playerId} joined ${room.id}`);\n return { room, player };\n }\n\n /**\n * @zh 加入指定房间\n * @en Join specific room\n *\n * @param roomId - 房间 ID | Room ID\n * @param playerId - 玩家 ID | Player ID\n * @param conn - 玩家连接 | Player connection\n * @returns 房间和玩家实例或 null | Room and player instance or null\n */\n async joinById(\n roomId: string,\n playerId: string,\n conn: any\n ): Promise<{ room: Room; player: Player } | null> {\n const room = this._rooms.get(roomId);\n if (!room) return null;\n\n const player = await room._addPlayer(playerId, conn);\n if (!player) return null;\n\n this._onPlayerJoined(playerId, room.id, player);\n\n logger.info(`Player ${playerId} joined ${room.id}`);\n return { room, player };\n }\n\n /**\n * @zh 玩家离开\n * @en Player leave\n *\n * @param playerId - 玩家 ID | Player ID\n * @param reason - 离开原因 | Leave reason\n */\n async leave(playerId: string, reason?: string): Promise<void> {\n const roomId = this._playerToRoom.get(playerId);\n if (!roomId) return;\n\n const room = this._rooms.get(roomId);\n if (room) {\n await room._removePlayer(playerId, reason);\n }\n\n this._onPlayerLeft(playerId, roomId);\n logger.info(`Player ${playerId} left ${roomId}`);\n }\n\n /**\n * @zh 处理消息\n * @en Handle message\n */\n handleMessage(playerId: string, type: string, data: unknown): void {\n const roomId = this._playerToRoom.get(playerId);\n if (!roomId) return;\n\n const room = this._rooms.get(roomId);\n if (room) {\n room._handleMessage(type, data, playerId);\n }\n }\n\n /**\n * @zh 获取房间\n * @en Get room\n */\n getRoom(roomId: string): Room | undefined {\n return this._rooms.get(roomId);\n }\n\n /**\n * @zh 获取玩家所在房间\n * @en Get player's room\n */\n getPlayerRoom(playerId: string): Room | undefined {\n const roomId = this._playerToRoom.get(playerId);\n return roomId ? this._rooms.get(roomId) : undefined;\n }\n\n /**\n * @zh 获取所有房间\n * @en Get all rooms\n */\n getRooms(): ReadonlyArray<Room> {\n return Array.from(this._rooms.values());\n }\n\n /**\n * @zh 获取指定类型的所有房间\n * @en Get all rooms of a type\n */\n getRoomsByType(name: string): Room[] {\n const def = this._definitions.get(name);\n if (!def) return [];\n\n return Array.from(this._rooms.values()).filter(\n (room) => room instanceof def.roomClass\n );\n }\n\n /**\n * @zh 查找可用房间\n * @en Find available room\n *\n * @param name - 房间类型名称 | Room type name\n * @returns 可用房间或 null | Available room or null\n */\n protected _findAvailableRoom(name: string): Room | null {\n const def = this._definitions.get(name);\n if (!def) return null;\n\n for (const room of this._rooms.values()) {\n if (\n room instanceof def.roomClass &&\n !room.isFull &&\n !room.isLocked &&\n !room.isDisposed\n ) {\n return room;\n }\n }\n\n return null;\n }\n\n /**\n * @zh 生成房间 ID\n * @en Generate room ID\n *\n * @returns 新的房间 ID | New room ID\n */\n protected _generateRoomId(): string {\n return `room_${this._nextRoomId++}`;\n }\n\n /**\n * @zh 获取房间定义\n * @en Get room definition\n *\n * @param name - 房间类型名称 | Room type name\n * @returns 房间定义或 undefined | Room definition or undefined\n */\n protected _getDefinition(name: string): RoomDefinition | undefined {\n return this._definitions.get(name);\n }\n\n /**\n * @zh 内部创建房间实例\n * @en Internal create room instance\n *\n * @param name - 房间类型名称 | Room type name\n * @param options - 房间配置 | Room options\n * @param roomId - 可选的房间 ID(用于分布式恢复) | Optional room ID (for distributed recovery)\n * @returns 房间实例或 null | Room instance or null\n */\n protected async _createRoomInstance(\n name: string,\n options?: RoomOptions,\n roomId?: string\n ): Promise<Room | null> {\n const def = this._definitions.get(name);\n if (!def) {\n logger.warn(`Room type not found: ${name}`);\n return null;\n }\n\n const finalRoomId = roomId ?? this._generateRoomId();\n const room = new def.roomClass();\n\n room._init({\n id: finalRoomId,\n sendFn: this._sendFn,\n sendBinaryFn: this._sendBinaryFn,\n broadcastFn: (type, data) => {\n for (const player of room.players) {\n player.send(type, data);\n }\n },\n disposeFn: () => {\n this._onRoomDisposed(finalRoomId);\n }\n });\n\n this._rooms.set(finalRoomId, room);\n await room._create(options);\n\n return room;\n }\n\n /**\n * @zh 房间销毁回调\n * @en Room disposed callback\n *\n * @param roomId - 房间 ID | Room ID\n */\n protected _onRoomDisposed(roomId: string): void {\n this._rooms.delete(roomId);\n }\n\n /**\n * @zh 玩家加入房间后的回调\n * @en Callback after player joins room\n *\n * @param playerId - 玩家 ID | Player ID\n * @param roomId - 房间 ID | Room ID\n * @param player - 玩家实例 | Player instance\n */\n protected _onPlayerJoined(playerId: string, roomId: string, _player: Player): void {\n this._playerToRoom.set(playerId, roomId);\n }\n\n /**\n * @zh 玩家离开房间后的回调\n * @en Callback after player leaves room\n *\n * @param playerId - 玩家 ID | Player ID\n * @param _roomId - 房间 ID | Room ID\n */\n protected _onPlayerLeft(playerId: string, _roomId: string): void {\n this._playerToRoom.delete(playerId);\n }\n}\n","/**\n * @zh HTTP 路由器\n * @en HTTP Router\n *\n * @zh 支持路由参数、中间件和超时控制的 HTTP 路由实现\n * @en HTTP router with route parameters, middleware and timeout support\n */\n\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport { createLogger } from '../logger.js';\nimport type {\n HttpRequest,\n HttpResponse,\n HttpHandler,\n HttpRoutes,\n HttpRouteMethods,\n HttpMiddleware,\n HttpRouterOptions,\n HttpMethodHandler,\n HttpHandlerDefinition,\n CorsOptions\n} from './types.js';\n\nconst logger = createLogger('HTTP');\n\n// ============================================================================\n// 路由解析 | Route Parsing\n// ============================================================================\n\n/**\n * @zh 解析后的路由\n * @en Parsed route\n */\ninterface ParsedRoute {\n method: string;\n path: string;\n handler: HttpHandler;\n pattern: RegExp;\n paramNames: string[];\n middlewares: HttpMiddleware[];\n timeout?: number;\n isStatic: boolean;\n}\n\n/**\n * @zh 解析路由路径,提取参数名并生成匹配正则\n * @en Parse route path, extract param names and generate matching regex\n */\nfunction parseRoutePath(path: string): { pattern: RegExp; paramNames: string[]; isStatic: boolean } {\n const paramNames: string[] = [];\n const isStatic = !path.includes(':');\n\n if (isStatic) {\n return {\n pattern: new RegExp(`^${escapeRegex(path)}$`),\n paramNames,\n isStatic: true\n };\n }\n\n const segments = path.split('/').map(segment => {\n if (segment.startsWith(':')) {\n const paramName = segment.slice(1);\n paramNames.push(paramName);\n return '([^/]+)';\n }\n return escapeRegex(segment);\n });\n\n return {\n pattern: new RegExp(`^${segments.join('/')}$`),\n paramNames,\n isStatic: false\n };\n}\n\n/**\n * @zh 转义正则表达式特殊字符\n * @en Escape regex special characters\n */\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * @zh 匹配路由并提取参数\n * @en Match route and extract params\n */\nfunction matchRoute(\n routes: ParsedRoute[],\n path: string,\n method: string\n): { route: ParsedRoute; params: Record<string, string> } | null {\n // 优先匹配静态路由\n for (const route of routes) {\n if (!route.isStatic) continue;\n if (route.method !== '*' && route.method !== method) continue;\n if (route.pattern.test(path)) {\n return { route, params: {} };\n }\n }\n\n // 然后匹配动态路由\n for (const route of routes) {\n if (route.isStatic) continue;\n if (route.method !== '*' && route.method !== method) continue;\n\n const match = path.match(route.pattern);\n if (match) {\n const params: Record<string, string> = {};\n route.paramNames.forEach((name, index) => {\n params[name] = decodeURIComponent(match[index + 1]);\n });\n return { route, params };\n }\n }\n\n return null;\n}\n\n// ============================================================================\n// 请求/响应处理 | Request/Response Handling\n// ============================================================================\n\n/**\n * @zh 创建 HTTP 请求对象\n * @en Create HTTP request object\n */\nasync function createRequest(\n req: IncomingMessage,\n params: Record<string, string> = {}\n): Promise<HttpRequest> {\n const url = new URL(req.url ?? '/', `http://${req.headers.host ?? 'localhost'}`);\n\n const query: Record<string, string> = {};\n url.searchParams.forEach((value, key) => {\n query[key] = value;\n });\n\n let body: unknown = null;\n if (req.method === 'POST' || req.method === 'PUT' || req.method === 'PATCH') {\n body = await parseBody(req);\n }\n\n const ip =\n (req.headers['x-forwarded-for'] as string)?.split(',')[0]?.trim() ||\n req.socket?.remoteAddress ||\n 'unknown';\n\n return {\n raw: req,\n method: req.method ?? 'GET',\n path: url.pathname,\n params,\n query,\n headers: req.headers as Record<string, string | string[] | undefined>,\n body,\n ip\n };\n}\n\n/**\n * @zh 解析请求体\n * @en Parse request body\n */\nfunction parseBody(req: IncomingMessage): Promise<unknown> {\n return new Promise((resolve) => {\n const chunks: Buffer[] = [];\n\n req.on('data', (chunk: Buffer) => {\n chunks.push(chunk);\n });\n\n req.on('end', () => {\n const rawBody = Buffer.concat(chunks).toString('utf-8');\n\n if (!rawBody) {\n resolve(null);\n return;\n }\n\n const contentType = req.headers['content-type'] ?? '';\n\n if (contentType.includes('application/json')) {\n try {\n resolve(JSON.parse(rawBody));\n } catch {\n resolve(rawBody);\n }\n } else if (contentType.includes('application/x-www-form-urlencoded')) {\n const params = new URLSearchParams(rawBody);\n const result: Record<string, string> = {};\n params.forEach((value, key) => {\n result[key] = value;\n });\n resolve(result);\n } else {\n resolve(rawBody);\n }\n });\n\n req.on('error', () => {\n resolve(null);\n });\n });\n}\n\n/**\n * @zh 创建 HTTP 响应对象\n * @en Create HTTP response object\n */\nfunction createResponse(res: ServerResponse): HttpResponse {\n let statusCode = 200;\n let ended = false;\n\n const response: HttpResponse = {\n raw: res,\n\n status(code: number) {\n statusCode = code;\n return response;\n },\n\n header(name: string, value: string) {\n if (!ended) {\n res.setHeader(name, value);\n }\n return response;\n },\n\n json(data: unknown) {\n if (ended) return;\n ended = true;\n res.setHeader('Content-Type', 'application/json; charset=utf-8');\n res.statusCode = statusCode;\n res.end(JSON.stringify(data));\n },\n\n text(data: string) {\n if (ended) return;\n ended = true;\n res.setHeader('Content-Type', 'text/plain; charset=utf-8');\n res.statusCode = statusCode;\n res.end(data);\n },\n\n error(code: number, message: string) {\n if (ended) return;\n ended = true;\n res.setHeader('Content-Type', 'application/json; charset=utf-8');\n res.statusCode = code;\n res.end(JSON.stringify({ error: message }));\n }\n };\n\n return response;\n}\n\n// ============================================================================\n// CORS 处理 | CORS Handling\n// ============================================================================\n\n/**\n * @zh 将 origin 数组转换为白名单对象(用于 CodeQL 安全验证模式)\n * @en Convert origin array to whitelist object (for CodeQL security validation pattern)\n */\nfunction createOriginWhitelist(origins: readonly string[]): Record<string, true> {\n const whitelist: Record<string, true> = {};\n for (const origin of origins) {\n whitelist[origin] = true;\n }\n return whitelist;\n}\n\n/**\n * @zh 应用 CORS 头\n * @en Apply CORS headers\n *\n * @zh 安全规则:credentials 只能与固定 origin 或白名单一起使用,不能使用通配符或反射\n * @en Security rule: credentials can only be used with fixed origin or whitelist, not wildcard or reflect\n */\nfunction applyCors(res: ServerResponse, req: IncomingMessage, cors: CorsOptions): void {\n const credentials = cors.credentials ?? false;\n\n // 设置 Access-Control-Allow-Origin\n // 安全策略:当 credentials 为 true 时,只允许固定 origin 或白名单\n if (typeof cors.origin === 'string' && cors.origin !== '*') {\n // 固定字符串 origin(非通配符):服务器配置的固定值\n // Fixed string origin (non-wildcard): fixed value from server configuration\n // 安全:cors.origin 来自 createHttpRouter 的 options 参数,是编译时配置值\n // Security: cors.origin comes from createHttpRouter's options param, a compile-time config value\n res.setHeader('Access-Control-Allow-Origin', cors.origin);\n if (credentials) {\n res.setHeader('Access-Control-Allow-Credentials', 'true');\n }\n } else if (Array.isArray(cors.origin)) {\n // 白名单模式:使用对象键查找验证 origin(CodeQL 认可的安全模式)\n // Whitelist mode: use object key lookup to validate origin (CodeQL recognized safe pattern)\n const requestOrigin = req.headers.origin;\n if (typeof requestOrigin === 'string') {\n const whitelist = createOriginWhitelist(cors.origin);\n if (requestOrigin in whitelist) {\n res.setHeader('Access-Control-Allow-Origin', requestOrigin);\n if (credentials) {\n res.setHeader('Access-Control-Allow-Credentials', 'true');\n }\n }\n }\n // 不在白名单中:不设置 origin 头\n } else if (!credentials) {\n // 通配符或反射模式:仅在无 credentials 时允许\n // Wildcard or reflect mode: only allowed without credentials\n // 注意:为了通过 CodeQL 安全扫描,reflect 模式 (cors.origin === true) 等同于通配符\n // Note: For CodeQL security scanning, reflect mode (cors.origin === true) is treated as wildcard\n if (cors.origin === '*' || cors.origin === true) {\n res.setHeader('Access-Control-Allow-Origin', '*');\n }\n }\n // credentials + 通配符/反射:不设置任何 origin 头(安全拒绝)\n\n res.setHeader(\n 'Access-Control-Allow-Methods',\n cors.methods?.join(', ') ?? 'GET, POST, PUT, DELETE, PATCH, OPTIONS'\n );\n\n res.setHeader(\n 'Access-Control-Allow-Headers',\n cors.allowedHeaders?.join(', ') ?? 'Content-Type, Authorization'\n );\n\n if (cors.maxAge) {\n res.setHeader('Access-Control-Max-Age', String(cors.maxAge));\n }\n}\n\n// ============================================================================\n// 中间件执行 | Middleware Execution\n// ============================================================================\n\n/**\n * @zh 执行中间件链\n * @en Execute middleware chain\n */\nasync function executeMiddlewares(\n middlewares: HttpMiddleware[],\n req: HttpRequest,\n res: HttpResponse,\n finalHandler: () => Promise<void>\n): Promise<void> {\n let index = 0;\n\n const next = async (): Promise<void> => {\n if (index < middlewares.length) {\n const middleware = middlewares[index++];\n await middleware(req, res, next);\n } else {\n await finalHandler();\n }\n };\n\n await next();\n}\n\n// ============================================================================\n// 超时控制 | Timeout Control\n// ============================================================================\n\n/**\n * @zh 带超时的执行器\n * @en Execute with timeout\n */\nasync function executeWithTimeout(\n handler: () => Promise<void>,\n timeoutMs: number,\n res: ServerResponse\n): Promise<void> {\n let resolved = false;\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => {\n if (!resolved) {\n reject(new Error('Request timeout'));\n }\n }, timeoutMs);\n });\n\n try {\n await Promise.race([\n handler().then(() => { resolved = true; }),\n timeoutPromise\n ]);\n } catch (error) {\n if (error instanceof Error && error.message === 'Request timeout') {\n if (!res.writableEnded) {\n res.statusCode = 408;\n res.setHeader('Content-Type', 'application/json; charset=utf-8');\n res.end(JSON.stringify({ error: 'Request Timeout' }));\n }\n } else {\n throw error;\n }\n }\n}\n\n// ============================================================================\n// 路由解析辅助 | Route Parsing Helpers\n// ============================================================================\n\n/**\n * @zh 判断是否为处理器定义对象(带 handler 属性)\n * @en Check if value is a handler definition object (with handler property)\n */\nfunction isHandlerDefinition(value: unknown): value is HttpHandlerDefinition {\n return typeof value === 'object' && value !== null && 'handler' in value && typeof (value as HttpHandlerDefinition).handler === 'function';\n}\n\n/**\n * @zh 判断是否为路由方法映射对象\n * @en Check if value is a route methods mapping object\n */\nfunction isRouteMethods(value: unknown): value is HttpRouteMethods {\n if (typeof value !== 'object' || value === null) return false;\n const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'];\n return Object.keys(value).some(key => methods.includes(key));\n}\n\n/**\n * @zh 从方法处理器提取处理函数和配置\n * @en Extract handler and config from method handler\n */\nfunction extractHandler(methodHandler: HttpMethodHandler): {\n handler: HttpHandler;\n middlewares: HttpMiddleware[];\n timeout?: number;\n} {\n if (isHandlerDefinition(methodHandler)) {\n return {\n handler: methodHandler.handler,\n middlewares: methodHandler.middlewares ?? [],\n timeout: methodHandler.timeout\n };\n }\n return {\n handler: methodHandler,\n middlewares: [],\n timeout: undefined\n };\n}\n\n// ============================================================================\n// 主路由器 | Main Router\n// ============================================================================\n\n/**\n * @zh 创建 HTTP 路由器\n * @en Create HTTP router\n *\n * @example\n * ```typescript\n * const router = createHttpRouter({\n * '/users': {\n * GET: (req, res) => res.json([]),\n * POST: (req, res) => res.json({ created: true })\n * },\n * '/users/:id': {\n * GET: (req, res) => res.json({ id: req.params.id }),\n * DELETE: {\n * handler: (req, res) => res.json({ deleted: true }),\n * middlewares: [authMiddleware],\n * timeout: 5000\n * }\n * }\n * }, {\n * cors: true,\n * timeout: 30000,\n * middlewares: [loggerMiddleware]\n * });\n * ```\n */\nexport function createHttpRouter(\n routes: HttpRoutes,\n options: HttpRouterOptions = {}\n): (req: IncomingMessage, res: ServerResponse) => Promise<boolean> {\n const globalMiddlewares = options.middlewares ?? [];\n const globalTimeout = options.timeout;\n\n // 解析路由\n const parsedRoutes: ParsedRoute[] = [];\n\n for (const [path, handlerOrMethods] of Object.entries(routes)) {\n const { pattern, paramNames, isStatic } = parseRoutePath(path);\n\n if (typeof handlerOrMethods === 'function') {\n // 简单函数处理器\n parsedRoutes.push({\n method: '*',\n path,\n handler: handlerOrMethods,\n pattern,\n paramNames,\n middlewares: [],\n timeout: undefined,\n isStatic\n });\n } else if (isRouteMethods(handlerOrMethods)) {\n // 方法映射对象 { GET, POST, ... }\n for (const [method, methodHandler] of Object.entries(handlerOrMethods)) {\n if (methodHandler !== undefined) {\n const { handler, middlewares, timeout } = extractHandler(methodHandler);\n parsedRoutes.push({\n method,\n path,\n handler,\n pattern,\n paramNames,\n middlewares,\n timeout,\n isStatic\n });\n }\n }\n } else if (isHandlerDefinition(handlerOrMethods)) {\n // 带配置的处理器定义 { handler, middlewares, timeout }\n const { handler, middlewares, timeout } = extractHandler(handlerOrMethods);\n parsedRoutes.push({\n method: '*',\n path,\n handler,\n pattern,\n paramNames,\n middlewares,\n timeout,\n isStatic\n });\n }\n }\n\n // CORS 配置\n // 安全默认:cors: true 时不启用 credentials,避免凭证泄露\n // Safe default: cors: true doesn't enable credentials to prevent credential leak\n const corsOptions: CorsOptions | null =\n options.cors === true\n ? { origin: '*' }\n : options.cors === false\n ? null\n : options.cors ?? null;\n\n /**\n * @zh 处理 HTTP 请求\n * @en Handle HTTP request\n */\n return async function handleRequest(\n req: IncomingMessage,\n res: ServerResponse\n ): Promise<boolean> {\n const url = new URL(req.url ?? '/', `http://${req.headers.host ?? 'localhost'}`);\n const path = url.pathname;\n const method = req.method ?? 'GET';\n\n // 应用 CORS\n if (corsOptions) {\n applyCors(res, req, corsOptions);\n\n if (method === 'OPTIONS') {\n res.statusCode = 204;\n res.end();\n return true;\n }\n }\n\n // 查找匹配的路由\n const match = matchRoute(parsedRoutes, path, method);\n\n if (!match) {\n return false;\n }\n\n const { route, params } = match;\n\n try {\n const httpReq = await createRequest(req, params);\n const httpRes = createResponse(res);\n\n // 合并中间件:全局 + 路由级\n const allMiddlewares = [...globalMiddlewares, ...route.middlewares];\n\n // 确定超时时间:路由级 > 全局\n const timeout = route.timeout ?? globalTimeout;\n\n // 最终处理器\n const finalHandler = async () => {\n await route.handler(httpReq, httpRes);\n };\n\n // 执行中间件链 + 处理器\n const executeHandler = async () => {\n if (allMiddlewares.length > 0) {\n await executeMiddlewares(allMiddlewares, httpReq, httpRes, finalHandler);\n } else {\n await finalHandler();\n }\n };\n\n // 带超时执行\n if (timeout && timeout > 0) {\n await executeWithTimeout(executeHandler, timeout, res);\n } else {\n await executeHandler();\n }\n\n return true;\n } catch (error) {\n logger.error('Route handler error:', error);\n if (!res.writableEnded) {\n res.statusCode = 500;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'Internal Server Error' }));\n }\n return true;\n }\n };\n}\n","/**\n * @zh 分布式房间管理器\n * @en Distributed room manager\n *\n * @zh 继承 RoomManager,添加分布式功能支持。包括跨服务器房间注册、\n * 玩家路由、状态同步和故障转移。\n * @en Extends RoomManager with distributed features. Includes cross-server room\n * registration, player routing, state synchronization, and failover.\n */\n\nimport { RoomManager } from '../room/RoomManager.js';\nimport { Room, type RoomOptions } from '../room/Room.js';\nimport type { Player } from '../room/Player.js';\nimport type { IDistributedAdapter } from './adapters/IDistributedAdapter.js';\nimport type {\n DistributedRoomManagerConfig,\n RoomRegistration,\n RoutingResult,\n RoutingRequest,\n ServerRegistration,\n DistributedEvent,\n Unsubscribe\n} from './types.js';\nimport { createLogger } from '../logger.js';\n\nconst logger = createLogger('DistributedRoom');\n\n/**\n * @zh 分布式房间管理器配置(内部使用)\n * @en Distributed room manager configuration (internal use)\n */\ninterface InternalConfig extends Required<Omit<DistributedRoomManagerConfig, 'metadata'>> {\n metadata: Record<string, unknown>;\n}\n\n/**\n * @zh 分布式房间管理器\n * @en Distributed room manager\n *\n * @zh 扩展基础 RoomManager,添加以下功能:\n * - 服务器注册和心跳\n * - 跨服务器房间注册\n * - 玩家路由和重定向\n * - 状态快照和恢复\n * - 分布式锁防止竞态\n * @en Extends base RoomManager with:\n * - Server registration and heartbeat\n * - Cross-server room registration\n * - Player routing and redirection\n * - State snapshots and recovery\n * - Distributed locks to prevent race conditions\n */\nexport class DistributedRoomManager extends RoomManager {\n private readonly _adapter: IDistributedAdapter;\n private readonly _config: InternalConfig;\n private readonly _serverId: string;\n\n private _heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private _snapshotTimer: ReturnType<typeof setInterval> | null = null;\n private _subscriptions: Unsubscribe[] = [];\n private _isShuttingDown = false;\n\n /**\n * @zh 创建分布式房间管理器\n * @en Create distributed room manager\n *\n * @param adapter - 分布式适配器 | Distributed adapter\n * @param config - 配置 | Configuration\n * @param sendFn - 消息发送函数 | Message send function\n * @param sendBinaryFn - 二进制发送函数 | Binary send function\n */\n constructor(\n adapter: IDistributedAdapter,\n config: DistributedRoomManagerConfig,\n sendFn: (conn: any, type: string, data: unknown) => void,\n sendBinaryFn?: (conn: any, data: Uint8Array) => void\n ) {\n super(sendFn, sendBinaryFn);\n\n this._adapter = adapter;\n this._serverId = config.serverId;\n\n this._config = {\n serverId: config.serverId,\n serverAddress: config.serverAddress,\n serverPort: config.serverPort,\n heartbeatInterval: config.heartbeatInterval ?? 5000,\n snapshotInterval: config.snapshotInterval ?? 30000,\n migrationTimeout: config.migrationTimeout ?? 10000,\n enableFailover: config.enableFailover ?? true,\n capacity: config.capacity ?? 100,\n metadata: config.metadata ?? {}\n };\n }\n\n /**\n * @zh 获取服务器 ID\n * @en Get server ID\n */\n get serverId(): string {\n return this._serverId;\n }\n\n /**\n * @zh 获取分布式适配器\n * @en Get distributed adapter\n */\n get adapter(): IDistributedAdapter {\n return this._adapter;\n }\n\n /**\n * @zh 获取配置\n * @en Get configuration\n */\n get config(): Readonly<InternalConfig> {\n return this._config;\n }\n\n // =========================================================================\n // 生命周期 | Lifecycle\n // =========================================================================\n\n /**\n * @zh 启动分布式房间管理器\n * @en Start distributed room manager\n */\n async start(): Promise<void> {\n if (!this._adapter.isConnected()) {\n await this._adapter.connect();\n }\n\n // 注册服务器 | Register server\n await this._registerServer();\n\n // 订阅事件 | Subscribe to events\n await this._subscribeToEvents();\n\n // 启动心跳 | Start heartbeat\n this._startHeartbeat();\n\n // 启动快照(如果启用)| Start snapshots (if enabled)\n if (this._config.snapshotInterval > 0) {\n this._startSnapshotTimer();\n }\n\n logger.info(`Distributed room manager started: ${this._serverId}`);\n }\n\n /**\n * @zh 停止分布式房间管理器\n * @en Stop distributed room manager\n *\n * @param graceful - 是否优雅关闭(等待玩家退出)| Whether to gracefully shutdown (wait for players)\n */\n async stop(graceful = true): Promise<void> {\n this._isShuttingDown = true;\n\n // 停止定时器 | Stop timers\n if (this._heartbeatTimer) {\n clearInterval(this._heartbeatTimer);\n this._heartbeatTimer = null;\n }\n\n if (this._snapshotTimer) {\n clearInterval(this._snapshotTimer);\n this._snapshotTimer = null;\n }\n\n // 取消订阅 | Unsubscribe\n for (const unsub of this._subscriptions) {\n unsub();\n }\n this._subscriptions = [];\n\n if (graceful) {\n // 标记为 draining,停止接收新玩家 | Mark as draining, stop accepting new players\n await this._adapter.updateServer(this._serverId, { status: 'draining' });\n\n // 保存所有房间状态快照 | Save all room state snapshots\n await this._saveAllSnapshots();\n }\n\n // 注销服务器 | Unregister server\n await this._adapter.unregisterServer(this._serverId);\n\n logger.info(`Distributed room manager stopped: ${this._serverId}`);\n }\n\n // =========================================================================\n // 房间操作覆盖 | Room Operation Overrides\n // =========================================================================\n\n /**\n * @zh 房间创建后注册到分布式系统\n * @en Register room to distributed system after creation\n */\n protected override async _onRoomCreated(name: string, room: Room): Promise<void> {\n const registration: RoomRegistration = {\n roomId: room.id,\n roomType: name,\n serverId: this._serverId,\n serverAddress: `${this._config.serverAddress}:${this._config.serverPort}`,\n playerCount: room.players.length,\n maxPlayers: room.maxPlayers,\n isLocked: room.isLocked,\n metadata: {},\n createdAt: Date.now(),\n updatedAt: Date.now()\n };\n\n await this._adapter.registerRoom(registration);\n logger.debug(`Registered room: ${room.id}`);\n }\n\n /**\n * @zh 房间销毁时从分布式系统注销\n * @en Unregister room from distributed system when disposed\n */\n protected override _onRoomDisposed(roomId: string): void {\n super._onRoomDisposed(roomId);\n\n // 异步注销房间 | Async unregister room\n this._adapter.unregisterRoom(roomId).catch(err => {\n logger.error(`Failed to unregister room ${roomId}:`, err);\n });\n\n // 删除快照 | Delete snapshot\n this._adapter.deleteSnapshot(roomId).catch(err => {\n logger.error(`Failed to delete snapshot for ${roomId}:`, err);\n });\n }\n\n /**\n * @zh 玩家加入后更新分布式房间信息\n * @en Update distributed room info after player joins\n */\n protected override _onPlayerJoined(playerId: string, roomId: string, player: Player): void {\n super._onPlayerJoined(playerId, roomId, player);\n\n const room = this._rooms.get(roomId);\n if (room) {\n this._adapter.updateRoom(roomId, {\n playerCount: room.players.length,\n updatedAt: Date.now()\n }).catch(err => {\n logger.error(`Failed to update room ${roomId}:`, err);\n });\n }\n }\n\n /**\n * @zh 玩家离开后更新分布式房间信息\n * @en Update distributed room info after player leaves\n */\n protected override _onPlayerLeft(playerId: string, roomId: string): void {\n super._onPlayerLeft(playerId, roomId);\n\n const room = this._rooms.get(roomId);\n if (room) {\n this._adapter.updateRoom(roomId, {\n playerCount: room.players.length,\n updatedAt: Date.now()\n }).catch(err => {\n logger.error(`Failed to update room ${roomId}:`, err);\n });\n }\n }\n\n // =========================================================================\n // 分布式路由 | Distributed Routing\n // =========================================================================\n\n /**\n * @zh 路由玩家到合适的房间/服务器\n * @en Route player to appropriate room/server\n *\n * @param request - 路由请求 | Routing request\n * @returns 路由结果 | Routing result\n */\n async route(request: RoutingRequest): Promise<RoutingResult> {\n // 如果指定了房间 ID,直接查找 | If room ID specified, look it up directly\n if (request.roomId) {\n return this._routeToRoom(request.roomId);\n }\n\n // 按类型查找可用房间 | Find available room by type\n if (request.roomType) {\n return this._routeByType(request.roomType, request.query);\n }\n\n return { type: 'unavailable', reason: 'No room type or room ID specified' };\n }\n\n /**\n * @zh 加入或创建房间(分布式版本)\n * @en Join or create room (distributed version)\n *\n * @zh 此方法会:\n * 1. 先在分布式注册表中查找可用房间\n * 2. 如果找到其他服务器的房间,返回重定向\n * 3. 如果找到本地房间或需要创建,在本地处理\n * @en This method will:\n * 1. First search for available room in distributed registry\n * 2. If room found on another server, return redirect\n * 3. If local room found or creation needed, handle locally\n */\n async joinOrCreateDistributed(\n name: string,\n playerId: string,\n conn: any,\n options?: RoomOptions\n ): Promise<{ room: Room; player: Player } | { redirect: string } | null> {\n // 使用分布式锁防止竞态条件 | Use distributed lock to prevent race conditions\n const lockKey = `joinOrCreate:${name}`;\n const locked = await this._adapter.acquireLock(lockKey, 5000);\n\n if (!locked) {\n // 等待一小段时间后重试 | Wait and retry\n await this._sleep(100);\n return this.joinOrCreateDistributed(name, playerId, conn, options);\n }\n\n try {\n // 先在分布式注册表中查找 | First search in distributed registry\n const availableRoom = await this._adapter.findAvailableRoom(name);\n\n if (availableRoom) {\n // 检查是否在本地服务器 | Check if on local server\n if (availableRoom.serverId === this._serverId) {\n // 本地房间 | Local room\n return super.joinOrCreate(name, playerId, conn, options);\n } else {\n // 其他服务器,返回重定向 | Other server, return redirect\n return { redirect: availableRoom.serverAddress };\n }\n }\n\n // 没有可用房间,在本地创建 | No available room, create locally\n return super.joinOrCreate(name, playerId, conn, options);\n } finally {\n await this._adapter.releaseLock(lockKey);\n }\n }\n\n // =========================================================================\n // 状态管理 | State Management\n // =========================================================================\n\n /**\n * @zh 保存房间状态快照\n * @en Save room state snapshot\n *\n * @param roomId - 房间 ID | Room ID\n */\n async saveSnapshot(roomId: string): Promise<void> {\n const room = this._rooms.get(roomId);\n if (!room) return;\n\n const def = this._getDefinitionByRoom(room);\n if (!def) return;\n\n const snapshot = {\n roomId: room.id,\n roomType: def.name,\n state: room.state ?? {},\n players: room.players.map(p => ({\n id: p.id,\n data: p.data ?? {}\n })),\n version: Date.now(),\n timestamp: Date.now()\n };\n\n await this._adapter.saveSnapshot(snapshot);\n logger.debug(`Saved snapshot for room: ${roomId}`);\n }\n\n /**\n * @zh 从快照恢复房间\n * @en Restore room from snapshot\n *\n * @param roomId - 房间 ID | Room ID\n * @returns 是否成功恢复 | Whether restore was successful\n */\n async restoreFromSnapshot(roomId: string): Promise<boolean> {\n const snapshot = await this._adapter.loadSnapshot(roomId);\n if (!snapshot) return false;\n\n // 创建房间实例 | Create room instance\n const room = await this._createRoomInstance(\n snapshot.roomType,\n { state: snapshot.state },\n snapshot.roomId\n );\n\n if (!room) return false;\n\n // 注册到分布式系统 | Register to distributed system\n await this._onRoomCreated(snapshot.roomType, room);\n\n logger.info(`Restored room from snapshot: ${roomId}`);\n return true;\n }\n\n // =========================================================================\n // 私有方法 | Private Methods\n // =========================================================================\n\n /**\n * @zh 注册服务器到分布式系统\n * @en Register server to distributed system\n */\n private async _registerServer(): Promise<void> {\n const registration: ServerRegistration = {\n serverId: this._serverId,\n address: this._config.serverAddress,\n port: this._config.serverPort,\n roomCount: this._rooms.size,\n playerCount: this._countTotalPlayers(),\n capacity: this._config.capacity,\n status: 'online',\n lastHeartbeat: Date.now(),\n metadata: this._config.metadata\n };\n\n await this._adapter.registerServer(registration);\n }\n\n /**\n * @zh 订阅分布式事件\n * @en Subscribe to distributed events\n */\n private async _subscribeToEvents(): Promise<void> {\n // 订阅服务器离线事件以触发故障转移 | Subscribe to server offline for failover\n if (this._config.enableFailover) {\n const unsub = await this._adapter.subscribe('server:offline', (event) => {\n this._handleServerOffline(event);\n });\n this._subscriptions.push(unsub);\n }\n\n // 订阅房间消息事件 | Subscribe to room message events\n const roomMsgUnsub = await this._adapter.subscribe('room:message', (event) => {\n this._handleRoomMessage(event);\n });\n this._subscriptions.push(roomMsgUnsub);\n }\n\n /**\n * @zh 启动心跳定时器\n * @en Start heartbeat timer\n */\n private _startHeartbeat(): void {\n this._heartbeatTimer = setInterval(async () => {\n try {\n await this._adapter.heartbeat(this._serverId);\n await this._adapter.updateServer(this._serverId, {\n roomCount: this._rooms.size,\n playerCount: this._countTotalPlayers()\n });\n } catch (err) {\n logger.error('Heartbeat failed:', err);\n }\n }, this._config.heartbeatInterval);\n }\n\n /**\n * @zh 启动快照定时器\n * @en Start snapshot timer\n */\n private _startSnapshotTimer(): void {\n this._snapshotTimer = setInterval(async () => {\n await this._saveAllSnapshots();\n }, this._config.snapshotInterval);\n }\n\n /**\n * @zh 保存所有房间快照\n * @en Save all room snapshots\n */\n private async _saveAllSnapshots(): Promise<void> {\n const promises: Promise<void>[] = [];\n for (const roomId of this._rooms.keys()) {\n promises.push(this.saveSnapshot(roomId));\n }\n await Promise.allSettled(promises);\n }\n\n /**\n * @zh 路由到指定房间\n * @en Route to specific room\n */\n private async _routeToRoom(roomId: string): Promise<RoutingResult> {\n // 先检查本地 | Check local first\n if (this._rooms.has(roomId)) {\n return { type: 'local', roomId };\n }\n\n // 从分布式注册表查询 | Query from distributed registry\n const registration = await this._adapter.getRoom(roomId);\n if (!registration) {\n return { type: 'unavailable', reason: 'Room not found' };\n }\n\n if (registration.serverId === this._serverId) {\n return { type: 'local', roomId };\n }\n\n return {\n type: 'redirect',\n serverAddress: registration.serverAddress,\n roomId\n };\n }\n\n /**\n * @zh 按类型路由\n * @en Route by type\n */\n private async _routeByType(\n roomType: string,\n _query?: RoutingRequest['query']\n ): Promise<RoutingResult> {\n const availableRoom = await this._adapter.findAvailableRoom(roomType);\n\n if (!availableRoom) {\n // 没有可用房间,需要创建 | No available room, need to create\n return { type: 'create', roomId: undefined };\n }\n\n if (availableRoom.serverId === this._serverId) {\n return { type: 'local', roomId: availableRoom.roomId };\n }\n\n return {\n type: 'redirect',\n serverAddress: availableRoom.serverAddress,\n roomId: availableRoom.roomId\n };\n }\n\n /**\n * @zh 处理服务器离线事件\n * @en Handle server offline event\n */\n private _handleServerOffline(event: DistributedEvent): void {\n if (this._isShuttingDown) return;\n if (!this._config.enableFailover) return;\n\n const offlineServerId = event.serverId;\n if (offlineServerId === this._serverId) return;\n\n logger.info(`Server offline detected: ${offlineServerId}`);\n\n this._tryRecoverRoomsFromServer(offlineServerId).catch(err => {\n logger.error(`Failed to recover rooms from ${offlineServerId}:`, err);\n });\n }\n\n /**\n * @zh 尝试从离线服务器恢复房间\n * @en Try to recover rooms from offline server\n */\n private async _tryRecoverRoomsFromServer(offlineServerId: string): Promise<void> {\n // 检查是否有容量接收更多房间\n if (this._rooms.size >= this._config.capacity) {\n logger.warn(`Cannot recover rooms: server at capacity (${this._rooms.size}/${this._config.capacity})`);\n return;\n }\n\n // 查询该服务器上的所有房间\n const rooms = await this._adapter.queryRooms({ serverId: offlineServerId });\n if (rooms.length === 0) {\n logger.info(`No rooms to recover from ${offlineServerId}`);\n return;\n }\n\n logger.info(`Attempting to recover ${rooms.length} rooms from ${offlineServerId}`);\n\n for (const roomReg of rooms) {\n // 检查容量\n if (this._rooms.size >= this._config.capacity) {\n logger.warn('Reached capacity during recovery, stopping');\n break;\n }\n\n // 尝试获取恢复锁,防止多个服务器同时恢复同一房间\n const lockKey = `failover:${roomReg.roomId}`;\n const acquired = await this._adapter.acquireLock(lockKey, this._config.migrationTimeout);\n\n if (!acquired) {\n continue;\n }\n\n try {\n // 从快照恢复房间\n const success = await this.restoreFromSnapshot(roomReg.roomId);\n if (success) {\n logger.info(`Successfully recovered room ${roomReg.roomId}`);\n // 发布恢复事件\n await this._adapter.publish({\n type: 'room:migrated',\n serverId: this._serverId,\n roomId: roomReg.roomId,\n payload: {\n fromServer: offlineServerId,\n toServer: this._serverId\n },\n timestamp: Date.now()\n });\n }\n } finally {\n await this._adapter.releaseLock(lockKey);\n }\n }\n }\n\n /**\n * @zh 处理跨服务器房间消息\n * @en Handle cross-server room message\n */\n private _handleRoomMessage(event: DistributedEvent): void {\n if (!event.roomId) return;\n\n const room = this._rooms.get(event.roomId);\n if (!room) return;\n\n const payload = event.payload as { messageType: string; data: unknown; playerId?: string };\n if (payload.playerId) {\n room._handleMessage(payload.messageType, payload.data, payload.playerId);\n }\n }\n\n /**\n * @zh 统计总玩家数\n * @en Count total players\n */\n private _countTotalPlayers(): number {\n let count = 0;\n for (const room of this._rooms.values()) {\n count += room.players.length;\n }\n return count;\n }\n\n /**\n * @zh 根据房间实例获取定义\n * @en Get definition by room instance\n */\n private _getDefinitionByRoom(room: Room): { name: string } | null {\n for (const [name, def] of this._definitions) {\n if (room instanceof def.roomClass) {\n return { name };\n }\n }\n return null;\n }\n\n /**\n * @zh 休眠指定时间\n * @en Sleep for specified time\n */\n private _sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n\n /**\n * @zh 向其他服务器的房间发送消息\n * @en Send message to room on another server\n *\n * @param roomId - 房间 ID | Room ID\n * @param messageType - 消息类型 | Message type\n * @param data - 消息数据 | Message data\n * @param playerId - 发送者玩家 ID(可选)| Sender player ID (optional)\n */\n async sendToRemoteRoom(\n roomId: string,\n messageType: string,\n data: unknown,\n playerId?: string\n ): Promise<void> {\n await this._adapter.sendToRoom(roomId, messageType, data, playerId);\n }\n\n /**\n * @zh 获取所有在线服务器\n * @en Get all online servers\n */\n async getServers(): Promise<ServerRegistration[]> {\n return this._adapter.getServers();\n }\n\n /**\n * @zh 查询分布式房间\n * @en Query distributed rooms\n */\n async queryDistributedRooms(query: {\n roomType?: string;\n hasSpace?: boolean;\n notLocked?: boolean;\n metadata?: Record<string, unknown>;\n limit?: number;\n }): Promise<RoomRegistration[]> {\n return this._adapter.queryRooms(query);\n }\n}\n","/**\n * @zh 内存分布式适配器\n * @en Memory distributed adapter\n *\n * @zh 用于单机模式和测试的内存实现。所有数据存储在进程内存中。\n * @en In-memory implementation for single-server mode and testing. All data stored in process memory.\n */\n\nimport type { IDistributedAdapter } from './IDistributedAdapter.js';\nimport type {\n ServerRegistration,\n RoomRegistration,\n RoomQuery,\n RoomSnapshot,\n DistributedEvent,\n DistributedEventType,\n DistributedEventHandler,\n Unsubscribe\n} from '../types.js';\n\n/**\n * @zh 内存适配器配置\n * @en Memory adapter configuration\n */\nexport interface MemoryAdapterConfig {\n /**\n * @zh 服务器 TTL(毫秒),超时后视为离线\n * @en Server TTL (ms), considered offline after timeout\n * @default 15000\n */\n serverTtl?: number;\n\n /**\n * @zh 是否启用 TTL 检查\n * @en Whether to enable TTL check\n * @default true\n */\n enableTtlCheck?: boolean;\n\n /**\n * @zh TTL 检查间隔(毫秒)\n * @en TTL check interval (ms)\n * @default 5000\n */\n ttlCheckInterval?: number;\n}\n\n/**\n * @zh 内存分布式适配器\n * @en Memory distributed adapter\n */\nexport class MemoryAdapter implements IDistributedAdapter {\n private readonly _config: Required<MemoryAdapterConfig>;\n private _connected = false;\n\n // 存储\n private readonly _servers = new Map<string, ServerRegistration>();\n private readonly _rooms = new Map<string, RoomRegistration>();\n private readonly _snapshots = new Map<string, RoomSnapshot>();\n private readonly _locks = new Map<string, { owner: string; expireAt: number }>();\n\n // 事件订阅\n private readonly _subscribers = new Map<string, Set<DistributedEventHandler>>();\n private _subscriberId = 0;\n\n // TTL 检查定时器\n private _ttlCheckTimer: ReturnType<typeof setInterval> | null = null;\n\n constructor(config: MemoryAdapterConfig = {}) {\n this._config = {\n serverTtl: 15000,\n enableTtlCheck: true,\n ttlCheckInterval: 5000,\n ...config\n };\n }\n\n // =========================================================================\n // 生命周期 | Lifecycle\n // =========================================================================\n\n async connect(): Promise<void> {\n if (this._connected) return;\n\n this._connected = true;\n\n if (this._config.enableTtlCheck) {\n this._ttlCheckTimer = setInterval(\n () => this._checkServerTtl(),\n this._config.ttlCheckInterval\n );\n }\n }\n\n async disconnect(): Promise<void> {\n if (!this._connected) return;\n\n if (this._ttlCheckTimer) {\n clearInterval(this._ttlCheckTimer);\n this._ttlCheckTimer = null;\n }\n\n this._connected = false;\n this._servers.clear();\n this._rooms.clear();\n this._snapshots.clear();\n this._locks.clear();\n this._subscribers.clear();\n }\n\n isConnected(): boolean {\n return this._connected;\n }\n\n // =========================================================================\n // 服务器注册 | Server Registry\n // =========================================================================\n\n async registerServer(server: ServerRegistration): Promise<void> {\n this._ensureConnected();\n this._servers.set(server.serverId, { ...server, lastHeartbeat: Date.now() });\n\n await this.publish({\n type: 'server:online',\n serverId: server.serverId,\n payload: server,\n timestamp: Date.now()\n });\n }\n\n async unregisterServer(serverId: string): Promise<void> {\n this._ensureConnected();\n const server = this._servers.get(serverId);\n if (!server) return;\n\n this._servers.delete(serverId);\n\n // 清理该服务器的所有房间\n for (const [roomId, room] of this._rooms) {\n if (room.serverId === serverId) {\n this._rooms.delete(roomId);\n }\n }\n\n await this.publish({\n type: 'server:offline',\n serverId,\n payload: { serverId },\n timestamp: Date.now()\n });\n }\n\n async heartbeat(serverId: string): Promise<void> {\n this._ensureConnected();\n const server = this._servers.get(serverId);\n if (server) {\n server.lastHeartbeat = Date.now();\n }\n }\n\n async getServers(): Promise<ServerRegistration[]> {\n this._ensureConnected();\n return Array.from(this._servers.values()).filter(s => s.status === 'online');\n }\n\n async getServer(serverId: string): Promise<ServerRegistration | null> {\n this._ensureConnected();\n return this._servers.get(serverId) ?? null;\n }\n\n async updateServer(serverId: string, updates: Partial<ServerRegistration>): Promise<void> {\n this._ensureConnected();\n const server = this._servers.get(serverId);\n if (server) {\n Object.assign(server, updates);\n }\n }\n\n // =========================================================================\n // 房间注册 | Room Registry\n // =========================================================================\n\n async registerRoom(room: RoomRegistration): Promise<void> {\n this._ensureConnected();\n this._rooms.set(room.roomId, { ...room });\n\n // 更新服务器的房间计数\n const server = this._servers.get(room.serverId);\n if (server) {\n server.roomCount = this._countRoomsByServer(room.serverId);\n }\n\n await this.publish({\n type: 'room:created',\n serverId: room.serverId,\n roomId: room.roomId,\n payload: { roomType: room.roomType },\n timestamp: Date.now()\n });\n }\n\n async unregisterRoom(roomId: string): Promise<void> {\n this._ensureConnected();\n const room = this._rooms.get(roomId);\n if (!room) return;\n\n this._rooms.delete(roomId);\n this._snapshots.delete(roomId);\n\n // 更新服务器的房间计数\n const server = this._servers.get(room.serverId);\n if (server) {\n server.roomCount = this._countRoomsByServer(room.serverId);\n }\n\n await this.publish({\n type: 'room:disposed',\n serverId: room.serverId,\n roomId,\n payload: {},\n timestamp: Date.now()\n });\n }\n\n async updateRoom(roomId: string, updates: Partial<RoomRegistration>): Promise<void> {\n this._ensureConnected();\n const room = this._rooms.get(roomId);\n if (!room) return;\n\n Object.assign(room, updates, { updatedAt: Date.now() });\n\n await this.publish({\n type: 'room:updated',\n serverId: room.serverId,\n roomId,\n payload: updates,\n timestamp: Date.now()\n });\n }\n\n async getRoom(roomId: string): Promise<RoomRegistration | null> {\n this._ensureConnected();\n return this._rooms.get(roomId) ?? null;\n }\n\n async queryRooms(query: RoomQuery): Promise<RoomRegistration[]> {\n this._ensureConnected();\n\n let results = Array.from(this._rooms.values());\n\n // 按类型过滤\n if (query.roomType) {\n results = results.filter(r => r.roomType === query.roomType);\n }\n\n // 按空位过滤\n if (query.hasSpace) {\n results = results.filter(r => r.playerCount < r.maxPlayers);\n }\n\n // 按锁定状态过滤\n if (query.notLocked) {\n results = results.filter(r => !r.isLocked);\n }\n\n // 按元数据过滤\n if (query.metadata) {\n results = results.filter(r => {\n for (const [key, value] of Object.entries(query.metadata!)) {\n if (r.metadata[key] !== value) {\n return false;\n }\n }\n return true;\n });\n }\n\n // 分页\n if (query.offset) {\n results = results.slice(query.offset);\n }\n if (query.limit) {\n results = results.slice(0, query.limit);\n }\n\n return results;\n }\n\n async findAvailableRoom(roomType: string): Promise<RoomRegistration | null> {\n const rooms = await this.queryRooms({\n roomType,\n hasSpace: true,\n notLocked: true,\n limit: 1\n });\n return rooms[0] ?? null;\n }\n\n async getRoomsByServer(serverId: string): Promise<RoomRegistration[]> {\n this._ensureConnected();\n return Array.from(this._rooms.values()).filter(r => r.serverId === serverId);\n }\n\n // =========================================================================\n // 房间状态 | Room State\n // =========================================================================\n\n async saveSnapshot(snapshot: RoomSnapshot): Promise<void> {\n this._ensureConnected();\n this._snapshots.set(snapshot.roomId, { ...snapshot });\n }\n\n async loadSnapshot(roomId: string): Promise<RoomSnapshot | null> {\n this._ensureConnected();\n return this._snapshots.get(roomId) ?? null;\n }\n\n async deleteSnapshot(roomId: string): Promise<void> {\n this._ensureConnected();\n this._snapshots.delete(roomId);\n }\n\n // =========================================================================\n // 发布/订阅 | Pub/Sub\n // =========================================================================\n\n async publish(event: DistributedEvent): Promise<void> {\n this._ensureConnected();\n\n // 通知所有匹配的订阅者\n const wildcardHandlers = this._subscribers.get('*') ?? new Set();\n const typeHandlers = this._subscribers.get(event.type) ?? new Set();\n\n for (const handler of wildcardHandlers) {\n try {\n handler(event);\n } catch (error) {\n console.error('Event handler error:', error);\n }\n }\n\n for (const handler of typeHandlers) {\n try {\n handler(event);\n } catch (error) {\n console.error('Event handler error:', error);\n }\n }\n }\n\n async subscribe(\n pattern: DistributedEventType | '*',\n handler: DistributedEventHandler\n ): Promise<Unsubscribe> {\n this._ensureConnected();\n\n if (!this._subscribers.has(pattern)) {\n this._subscribers.set(pattern, new Set());\n }\n\n this._subscribers.get(pattern)!.add(handler);\n\n return () => {\n const handlers = this._subscribers.get(pattern);\n if (handlers) {\n handlers.delete(handler);\n if (handlers.size === 0) {\n this._subscribers.delete(pattern);\n }\n }\n };\n }\n\n async sendToRoom(\n roomId: string,\n messageType: string,\n data: unknown,\n playerId?: string\n ): Promise<void> {\n this._ensureConnected();\n\n const room = this._rooms.get(roomId);\n if (!room) return;\n\n await this.publish({\n type: 'room:message',\n serverId: room.serverId,\n roomId,\n payload: { messageType, data, playerId },\n timestamp: Date.now()\n });\n }\n\n // =========================================================================\n // 分布式锁 | Distributed Lock\n // =========================================================================\n\n async acquireLock(key: string, ttlMs: number): Promise<boolean> {\n this._ensureConnected();\n\n const now = Date.now();\n const existing = this._locks.get(key);\n\n // 检查锁是否已过期\n if (existing && existing.expireAt > now) {\n return false;\n }\n\n // 获取锁\n const owner = `lock_${++this._subscriberId}`;\n this._locks.set(key, { owner, expireAt: now + ttlMs });\n\n return true;\n }\n\n async releaseLock(key: string): Promise<void> {\n this._ensureConnected();\n this._locks.delete(key);\n }\n\n async extendLock(key: string, ttlMs: number): Promise<boolean> {\n this._ensureConnected();\n\n const lock = this._locks.get(key);\n if (!lock) return false;\n\n lock.expireAt = Date.now() + ttlMs;\n return true;\n }\n\n // =========================================================================\n // 私有方法 | Private Methods\n // =========================================================================\n\n private _ensureConnected(): void {\n if (!this._connected) {\n throw new Error('MemoryAdapter is not connected');\n }\n }\n\n private _countRoomsByServer(serverId: string): number {\n let count = 0;\n for (const room of this._rooms.values()) {\n if (room.serverId === serverId) {\n count++;\n }\n }\n return count;\n }\n\n private async _checkServerTtl(): Promise<void> {\n const now = Date.now();\n const expiredServers: string[] = [];\n\n for (const [serverId, server] of this._servers) {\n if (server.status === 'online' && now - server.lastHeartbeat > this._config.serverTtl) {\n server.status = 'offline';\n expiredServers.push(serverId);\n }\n }\n\n // 发布服务器离线事件\n for (const serverId of expiredServers) {\n await this.publish({\n type: 'server:offline',\n serverId,\n payload: { serverId, reason: 'heartbeat_timeout' },\n timestamp: now\n });\n }\n }\n\n // =========================================================================\n // 测试辅助方法 | Test Helper Methods\n // =========================================================================\n\n /**\n * @zh 清除所有数据(仅用于测试)\n * @en Clear all data (for testing only)\n */\n _clear(): void {\n this._servers.clear();\n this._rooms.clear();\n this._snapshots.clear();\n this._locks.clear();\n }\n\n /**\n * @zh 获取内部状态(仅用于测试)\n * @en Get internal state (for testing only)\n */\n _getState(): {\n servers: Map<string, ServerRegistration>;\n rooms: Map<string, RoomRegistration>;\n snapshots: Map<string, RoomSnapshot>;\n } {\n return {\n servers: this._servers,\n rooms: this._rooms,\n snapshots: this._snapshots\n };\n }\n}\n","/**\n * @zh 文件路由加载器\n * @en File-based router loader\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { createLogger } from '../logger.js';\nimport type {\n ApiDefinition,\n MsgDefinition,\n HttpDefinition,\n LoadedApiHandler,\n LoadedMsgHandler,\n LoadedHttpHandler,\n HttpMethod\n} from '../types/index.js';\n\nconst logger = createLogger('Server');\n\n/**\n * @zh 将文件名转换为 API/消息名称\n * @en Convert filename to API/message name\n *\n * @example\n * 'join.ts' -> 'Join'\n * 'spawn-agent.ts' -> 'SpawnAgent'\n * 'save_blueprint.ts' -> 'SaveBlueprint'\n */\nfunction fileNameToHandlerName(fileName: string): string {\n const baseName = fileName.replace(/\\.(ts|js|mts|mjs)$/, '');\n\n return baseName\n .split(/[-_]/)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join('');\n}\n\n/**\n * @zh 扫描目录获取所有处理器文件\n * @en Scan directory for all handler files\n */\nfunction scanDirectory(dir: string): string[] {\n if (!fs.existsSync(dir)) {\n return [];\n }\n\n const files: string[] = [];\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.isFile() && /\\.(ts|js|mts|mjs)$/.test(entry.name)) {\n // 跳过 index 和下划线开头的文件\n if (entry.name.startsWith('_') || entry.name.startsWith('index.')) {\n continue;\n }\n files.push(path.join(dir, entry.name));\n }\n }\n\n return files;\n}\n\n/**\n * @zh 加载 API 处理器\n * @en Load API handlers\n */\nexport async function loadApiHandlers(apiDir: string): Promise<LoadedApiHandler[]> {\n const files = scanDirectory(apiDir);\n const handlers: LoadedApiHandler[] = [];\n\n for (const filePath of files) {\n try {\n const fileUrl = pathToFileURL(filePath).href;\n const module = await import(fileUrl);\n const definition = module.default as ApiDefinition<unknown, unknown, unknown>;\n\n if (definition && typeof definition.handler === 'function') {\n const name = fileNameToHandlerName(path.basename(filePath));\n handlers.push({\n name,\n path: filePath,\n definition\n });\n }\n } catch (err) {\n logger.warn(`Failed to load API handler: ${filePath}`, err);\n }\n }\n\n return handlers;\n}\n\n/**\n * @zh 加载消息处理器\n * @en Load message handlers\n */\nexport async function loadMsgHandlers(msgDir: string): Promise<LoadedMsgHandler[]> {\n const files = scanDirectory(msgDir);\n const handlers: LoadedMsgHandler[] = [];\n\n for (const filePath of files) {\n try {\n const fileUrl = pathToFileURL(filePath).href;\n const module = await import(fileUrl);\n const definition = module.default as MsgDefinition<unknown, unknown>;\n\n if (definition && typeof definition.handler === 'function') {\n const name = fileNameToHandlerName(path.basename(filePath));\n handlers.push({\n name,\n path: filePath,\n definition\n });\n }\n } catch (err) {\n logger.warn(`Failed to load msg handler: ${filePath}`, err);\n }\n }\n\n return handlers;\n}\n\n/**\n * @zh 递归扫描目录获取所有处理器文件\n * @en Recursively scan directory for all handler files\n */\nfunction scanDirectoryRecursive(dir: string, baseDir: string = dir): Array<{ filePath: string; relativePath: string }> {\n if (!fs.existsSync(dir)) {\n return [];\n }\n\n const files: Array<{ filePath: string; relativePath: string }> = [];\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n files.push(...scanDirectoryRecursive(fullPath, baseDir));\n } else if (entry.isFile() && /\\.(ts|js|mts|mjs)$/.test(entry.name)) {\n if (entry.name.startsWith('_') || entry.name.startsWith('index.')) {\n continue;\n }\n const relativePath = path.relative(baseDir, fullPath);\n files.push({ filePath: fullPath, relativePath });\n }\n }\n\n return files;\n}\n\n/**\n * @zh 将文件路径转换为路由路径\n * @en Convert file path to route path\n *\n * @example\n * 'login.ts' -> '/login'\n * 'users/profile.ts' -> '/users/profile'\n * 'users/[id].ts' -> '/users/:id'\n */\nfunction filePathToRoute(relativePath: string, prefix: string): string {\n let route = relativePath\n .replace(/\\.(ts|js|mts|mjs)$/, '')\n .replace(/\\\\/g, '/')\n .replace(/\\[(\\w+)\\]/g, ':$1');\n\n if (!route.startsWith('/')) {\n route = '/' + route;\n }\n\n const fullRoute = prefix.endsWith('/')\n ? prefix.slice(0, -1) + route\n : prefix + route;\n\n return fullRoute;\n}\n\n/**\n * @zh 加载 HTTP 路由处理器\n * @en Load HTTP route handlers\n *\n * @example\n * ```typescript\n * // Directory structure:\n * // src/http/\n * // login.ts -> POST /api/login\n * // register.ts -> POST /api/register\n * // users/\n * // [id].ts -> GET /api/users/:id\n *\n * const handlers = await loadHttpHandlers('src/http', '/api')\n * ```\n */\nexport async function loadHttpHandlers(\n httpDir: string,\n prefix: string = '/api'\n): Promise<LoadedHttpHandler[]> {\n const files = scanDirectoryRecursive(httpDir);\n const handlers: LoadedHttpHandler[] = [];\n\n for (const { filePath, relativePath } of files) {\n try {\n const fileUrl = pathToFileURL(filePath).href;\n const module = await import(fileUrl);\n const definition = module.default as HttpDefinition<unknown>;\n\n if (definition && typeof definition.handler === 'function') {\n const route = filePathToRoute(relativePath, prefix);\n const method: HttpMethod = definition.method ?? 'POST';\n\n handlers.push({\n route,\n method,\n path: filePath,\n definition\n });\n }\n } catch (err) {\n logger.warn(`Failed to load HTTP handler: ${filePath}`, err);\n }\n }\n\n return handlers;\n}\n","/**\n * @zh 游戏服务器核心\n * @en Game server core\n */\n\nimport * as path from 'node:path';\nimport { createServer as createHttpServer, type Server as HttpServer } from 'node:http';\nimport { serve, type RpcServer } from '@esengine/rpc/server';\nimport { rpc } from '@esengine/rpc';\nimport { createLogger } from '../logger.js';\nimport type {\n ServerConfig,\n ServerConnection,\n GameServer,\n ApiContext,\n MsgContext,\n LoadedApiHandler,\n LoadedMsgHandler,\n LoadedHttpHandler\n} from '../types/index.js';\nimport type { HttpRoutes, HttpHandler } from '../http/types.js';\nimport type { Validator } from '../schema/index.js';\nimport { loadApiHandlers, loadMsgHandlers, loadHttpHandlers } from '../router/loader.js';\nimport { RoomManager, type RoomClass, type Room } from '../room/index.js';\nimport { createHttpRouter } from '../http/router.js';\nimport { DistributedRoomManager } from '../distributed/DistributedRoomManager.js';\nimport { MemoryAdapter } from '../distributed/adapters/MemoryAdapter.js';\n\n/**\n * @zh 默认配置\n * @en Default configuration\n */\nconst DEFAULT_CONFIG: Required<Omit<ServerConfig, 'onStart' | 'onConnect' | 'onDisconnect' | 'http' | 'cors' | 'httpDir' | 'httpPrefix' | 'distributed'>> & { httpDir: string; httpPrefix: string } = {\n port: 3000,\n apiDir: 'src/api',\n msgDir: 'src/msg',\n httpDir: 'src/http',\n httpPrefix: '/api',\n tickRate: 20\n};\n\n/**\n * @zh 创建游戏服务器\n * @en Create game server\n *\n * @example\n * ```typescript\n * import { createServer, Room, onMessage } from '@esengine/server'\n *\n * class GameRoom extends Room {\n * onJoin(player) {\n * this.broadcast('Joined', { id: player.id })\n * }\n * }\n *\n * const server = await createServer({ port: 3000 })\n * server.define('game', GameRoom)\n * await server.start()\n * ```\n */\nexport async function createServer(config: ServerConfig = {}): Promise<GameServer> {\n const opts = { ...DEFAULT_CONFIG, ...config };\n const cwd = process.cwd();\n const logger = createLogger('Server');\n\n // 加载文件路由处理器\n const apiHandlers = await loadApiHandlers(path.resolve(cwd, opts.apiDir));\n const msgHandlers = await loadMsgHandlers(path.resolve(cwd, opts.msgDir));\n\n // 加载 HTTP 文件路由\n const httpDir = config.httpDir ?? opts.httpDir;\n const httpPrefix = config.httpPrefix ?? opts.httpPrefix;\n const httpHandlers = await loadHttpHandlers(path.resolve(cwd, httpDir), httpPrefix);\n\n if (apiHandlers.length > 0) {\n logger.info(`Loaded ${apiHandlers.length} API handlers`);\n }\n if (msgHandlers.length > 0) {\n logger.info(`Loaded ${msgHandlers.length} message handlers`);\n }\n if (httpHandlers.length > 0) {\n logger.info(`Loaded ${httpHandlers.length} HTTP handlers`);\n }\n\n // 合并 HTTP 路由(文件路由 + 内联路由)\n const mergedHttpRoutes: HttpRoutes = {};\n\n // 先添加文件路由\n for (const handler of httpHandlers) {\n const existingRoute = mergedHttpRoutes[handler.route];\n if (existingRoute && typeof existingRoute !== 'function') {\n (existingRoute as Record<string, HttpHandler>)[handler.method] = handler.definition.handler;\n } else {\n mergedHttpRoutes[handler.route] = {\n [handler.method]: handler.definition.handler\n };\n }\n }\n\n // 再添加内联路由(覆盖文件路由)\n if (config.http) {\n for (const [route, handlerOrMethods] of Object.entries(config.http)) {\n if (typeof handlerOrMethods === 'function') {\n mergedHttpRoutes[route] = handlerOrMethods;\n } else {\n const existing = mergedHttpRoutes[route];\n if (existing && typeof existing !== 'function') {\n Object.assign(existing, handlerOrMethods);\n } else {\n mergedHttpRoutes[route] = handlerOrMethods;\n }\n }\n }\n }\n\n const hasHttpRoutes = Object.keys(mergedHttpRoutes).length > 0;\n\n // 分布式模式配置\n const distributedConfig = config.distributed;\n const isDistributed = distributedConfig?.enabled ?? false;\n\n // 动态构建协议\n const apiDefs: Record<string, ReturnType<typeof rpc.api>> = {\n // 内置 API\n JoinRoom: rpc.api(),\n LeaveRoom: rpc.api()\n };\n const msgDefs: Record<string, ReturnType<typeof rpc.msg>> = {\n // 内置消息(房间消息透传)\n RoomMessage: rpc.msg(),\n // 分布式重定向消息\n $redirect: rpc.msg()\n };\n\n for (const handler of apiHandlers) {\n apiDefs[handler.name] = rpc.api();\n }\n for (const handler of msgHandlers) {\n msgDefs[handler.name] = rpc.msg();\n }\n\n const protocol = rpc.define({\n api: apiDefs,\n msg: msgDefs\n });\n\n // 服务器状态\n let currentTick = 0;\n let tickInterval: ReturnType<typeof setInterval> | null = null;\n let rpcServer: RpcServer<typeof protocol, Record<string, unknown>> | null = null;\n let httpServer: HttpServer | null = null;\n\n // 发送函数(延迟绑定,因为 rpcServer 在 start() 后才创建)\n const sendFn = (conn: any, type: string, data: unknown) => {\n rpcServer?.send(conn, 'RoomMessage' as any, { type, data } as any);\n };\n\n // 二进制发送函数(使用原生 WebSocket 二进制帧,效率更高)\n const sendBinaryFn = (conn: any, data: Uint8Array) => {\n if (conn && typeof conn.sendBinary === 'function') {\n conn.sendBinary(data);\n }\n };\n\n // 房间管理器(立即初始化,以便 define() 可在 start() 前调用)\n let roomManager: RoomManager | DistributedRoomManager;\n let distributedManager: DistributedRoomManager | null = null;\n\n if (isDistributed && distributedConfig) {\n // 分布式模式\n const adapter = distributedConfig.adapter ?? new MemoryAdapter();\n distributedManager = new DistributedRoomManager(\n adapter,\n {\n serverId: distributedConfig.serverId,\n serverAddress: distributedConfig.serverAddress,\n serverPort: distributedConfig.serverPort ?? opts.port,\n heartbeatInterval: distributedConfig.heartbeatInterval,\n snapshotInterval: distributedConfig.snapshotInterval,\n enableFailover: distributedConfig.enableFailover,\n capacity: distributedConfig.capacity\n },\n sendFn,\n sendBinaryFn\n );\n roomManager = distributedManager;\n logger.info(`Distributed mode enabled (serverId: ${distributedConfig.serverId})`);\n } else {\n // 单机模式\n roomManager = new RoomManager(sendFn, sendBinaryFn);\n }\n\n // 构建 API 处理器映射\n const apiMap: Record<string, LoadedApiHandler> = {};\n for (const handler of apiHandlers) {\n apiMap[handler.name] = handler;\n }\n\n // 构建消息处理器映射\n const msgMap: Record<string, LoadedMsgHandler> = {};\n for (const handler of msgHandlers) {\n msgMap[handler.name] = handler;\n }\n\n // 游戏服务器实例\n const gameServer: GameServer & {\n rooms: RoomManager\n } = {\n get connections() {\n return (rpcServer?.connections ?? []) as ReadonlyArray<ServerConnection>;\n },\n\n get tick() {\n return currentTick;\n },\n\n get rooms() {\n return roomManager;\n },\n\n /**\n * @zh 注册房间类型\n * @en Define room type\n */\n define(name: string, roomClass: new () => unknown): void {\n roomManager.define(name, roomClass as RoomClass);\n },\n\n async start() {\n // 构建 API handlers\n const apiHandlersObj: Record<string, (input: unknown, conn: any) => Promise<unknown>> = {};\n\n // 内置 JoinRoom API\n apiHandlersObj['JoinRoom'] = async (input: any, conn) => {\n const { roomType, roomId, options } = input as {\n roomType?: string\n roomId?: string\n options?: Record<string, unknown>\n };\n\n if (roomId) {\n const result = await roomManager.joinById(roomId, conn.id, conn);\n if (!result) {\n throw new Error('Failed to join room');\n }\n return { roomId: result.room.id, playerId: result.player.id };\n }\n\n if (roomType) {\n // 分布式模式:使用 joinOrCreateDistributed\n if (distributedManager) {\n const result = await distributedManager.joinOrCreateDistributed(\n roomType,\n conn.id,\n conn,\n options\n );\n if (!result) {\n throw new Error('Failed to join or create room');\n }\n if ('redirect' in result) {\n // 发送重定向消息给客户端\n rpcServer?.send(conn, '$redirect' as any, {\n address: result.redirect,\n roomType\n } as any);\n return { redirect: result.redirect };\n }\n return { roomId: result.room.id, playerId: result.player.id };\n }\n\n // 单机模式\n const result = await roomManager.joinOrCreate(roomType, conn.id, conn, options);\n if (!result) {\n throw new Error('Failed to join or create room');\n }\n return { roomId: result.room.id, playerId: result.player.id };\n }\n\n throw new Error('roomType or roomId required');\n };\n\n // 内置 LeaveRoom API\n apiHandlersObj['LeaveRoom'] = async (_input, conn) => {\n await roomManager.leave(conn.id);\n return { success: true };\n };\n\n // 文件路由 API\n for (const [name, handler] of Object.entries(apiMap)) {\n apiHandlersObj[name] = async (input, conn) => {\n const ctx: ApiContext = {\n conn: conn as ServerConnection,\n server: gameServer\n };\n\n const definition = handler.definition as { schema?: Validator<unknown> };\n if (definition.schema) {\n const result = definition.schema.validate(input);\n if (!result.success) {\n const pathStr = result.error.path.length > 0\n ? ` at \"${result.error.path.join('.')}\"`\n : '';\n throw new Error(`Validation failed${pathStr}: ${result.error.message}`);\n }\n return handler.definition.handler(result.data, ctx);\n }\n\n return handler.definition.handler(input, ctx);\n };\n }\n\n // 构建消息 handlers\n const msgHandlersObj: Record<string, (data: unknown, conn: any) => void | Promise<void>> = {};\n\n // 内置 RoomMessage 处理\n msgHandlersObj['RoomMessage'] = async (data: any, conn) => {\n const { type, data: payload } = data as { type: string; data: unknown };\n roomManager.handleMessage(conn.id, type, payload);\n };\n\n // 文件路由消息\n for (const [name, handler] of Object.entries(msgMap)) {\n msgHandlersObj[name] = async (data, conn) => {\n const ctx: MsgContext = {\n conn: conn as ServerConnection,\n server: gameServer\n };\n\n const definition = handler.definition as { schema?: Validator<unknown> };\n if (definition.schema) {\n const result = definition.schema.validate(data);\n if (!result.success) {\n const pathStr = result.error.path.length > 0\n ? ` at \"${result.error.path.join('.')}\"`\n : '';\n logger.warn(`Message validation failed for ${name}${pathStr}: ${result.error.message}`);\n return;\n }\n await handler.definition.handler(result.data, ctx);\n return;\n }\n\n await handler.definition.handler(data, ctx);\n };\n }\n\n // 如果有 HTTP 路由,创建 HTTP 服务器\n if (hasHttpRoutes) {\n const httpRouter = createHttpRouter(mergedHttpRoutes, {\n cors: config.cors ?? true\n });\n\n httpServer = createHttpServer(async (req, res) => {\n // 先尝试 HTTP 路由\n const handled = await httpRouter(req, res);\n if (!handled) {\n // 未匹配的请求返回 404\n res.statusCode = 404;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'Not Found' }));\n }\n });\n\n // 使用 HTTP 服务器创建 RPC\n rpcServer = serve(protocol, {\n server: httpServer,\n createConnData: () => ({}),\n onStart: () => {\n logger.info(`Started on http://localhost:${opts.port}`);\n opts.onStart?.(opts.port);\n },\n onConnect: async (conn) => {\n await config.onConnect?.(conn as ServerConnection);\n },\n onDisconnect: async (conn) => {\n await roomManager?.leave(conn.id, 'disconnected');\n await config.onDisconnect?.(conn as ServerConnection);\n },\n api: apiHandlersObj as any,\n msg: msgHandlersObj as any\n });\n\n await rpcServer.start();\n\n // 启动 HTTP 服务器\n await new Promise<void>((resolve) => {\n httpServer!.listen(opts.port, () => resolve());\n });\n } else {\n // 仅 WebSocket 模式\n rpcServer = serve(protocol, {\n port: opts.port,\n createConnData: () => ({}),\n onStart: (p) => {\n logger.info(`Started on ws://localhost:${p}`);\n opts.onStart?.(p);\n },\n onConnect: async (conn) => {\n await config.onConnect?.(conn as ServerConnection);\n },\n onDisconnect: async (conn) => {\n await roomManager?.leave(conn.id, 'disconnected');\n await config.onDisconnect?.(conn as ServerConnection);\n },\n api: apiHandlersObj as any,\n msg: msgHandlersObj as any\n });\n\n await rpcServer.start();\n }\n\n // 启动分布式管理器\n if (distributedManager) {\n await distributedManager.start();\n }\n\n // 启动 tick 循环\n if (opts.tickRate > 0) {\n tickInterval = setInterval(() => {\n currentTick++;\n }, 1000 / opts.tickRate);\n }\n },\n\n async stop() {\n if (tickInterval) {\n clearInterval(tickInterval);\n tickInterval = null;\n }\n\n // 停止分布式管理器(优雅关闭)\n if (distributedManager) {\n await distributedManager.stop(true);\n }\n\n if (rpcServer) {\n await rpcServer.stop();\n rpcServer = null;\n }\n if (httpServer) {\n await new Promise<void>((resolve, reject) => {\n httpServer!.close((err) => {\n if (err) reject(err);\n else resolve();\n });\n });\n httpServer = null;\n }\n },\n\n broadcast(name, data) {\n rpcServer?.broadcast(name as any, data as any);\n },\n\n send(conn, name, data) {\n rpcServer?.send(conn as any, name as any, data as any);\n }\n };\n\n return gameServer as GameServer;\n}\n"]}
|
|
@@ -8,11 +8,13 @@ var _Player = class _Player {
|
|
|
8
8
|
__publicField(this, "data");
|
|
9
9
|
__publicField(this, "_conn");
|
|
10
10
|
__publicField(this, "_sendFn");
|
|
11
|
+
__publicField(this, "_sendBinaryFn");
|
|
11
12
|
__publicField(this, "_leaveFn");
|
|
12
13
|
this.id = options.id;
|
|
13
14
|
this.roomId = options.roomId;
|
|
14
15
|
this._conn = options.conn;
|
|
15
16
|
this._sendFn = options.sendFn;
|
|
17
|
+
this._sendBinaryFn = options.sendBinaryFn;
|
|
16
18
|
this._leaveFn = options.leaveFn;
|
|
17
19
|
this.data = options.initialData ?? {};
|
|
18
20
|
}
|
|
@@ -30,6 +32,36 @@ var _Player = class _Player {
|
|
|
30
32
|
send(type, data) {
|
|
31
33
|
this._sendFn(this._conn, type, data);
|
|
32
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* @zh 发送二进制数据给玩家
|
|
37
|
+
* @en Send binary data to player
|
|
38
|
+
*
|
|
39
|
+
* @zh 如果底层连接支持原生二进制帧,则直接发送;否则降级为 base64 编码通过 JSON 发送
|
|
40
|
+
* @en If underlying connection supports native binary frames, sends directly; otherwise falls back to base64 encoding via JSON
|
|
41
|
+
*/
|
|
42
|
+
sendBinary(data) {
|
|
43
|
+
if (this._sendBinaryFn) {
|
|
44
|
+
this._sendBinaryFn(this._conn, data);
|
|
45
|
+
} else {
|
|
46
|
+
this.send("$binary", {
|
|
47
|
+
data: this._toBase64(data)
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* @zh 将 Uint8Array 转换为 base64 字符串
|
|
53
|
+
* @en Convert Uint8Array to base64 string
|
|
54
|
+
*/
|
|
55
|
+
_toBase64(data) {
|
|
56
|
+
if (typeof Buffer !== "undefined") {
|
|
57
|
+
return Buffer.from(data).toString("base64");
|
|
58
|
+
}
|
|
59
|
+
let binary = "";
|
|
60
|
+
for (let i = 0; i < data.length; i++) {
|
|
61
|
+
binary += String.fromCharCode(data[i]);
|
|
62
|
+
}
|
|
63
|
+
return btoa(binary);
|
|
64
|
+
}
|
|
33
65
|
/**
|
|
34
66
|
* @zh 让玩家离开房间
|
|
35
67
|
* @en Make player leave the room
|
|
@@ -82,6 +114,7 @@ var _Room = class _Room {
|
|
|
82
114
|
__publicField(this, "_lastTickTime", 0);
|
|
83
115
|
__publicField(this, "_broadcastFn", null);
|
|
84
116
|
__publicField(this, "_sendFn", null);
|
|
117
|
+
__publicField(this, "_sendBinaryFn", null);
|
|
85
118
|
__publicField(this, "_disposeFn", null);
|
|
86
119
|
}
|
|
87
120
|
// ========================================================================
|
|
@@ -237,6 +270,7 @@ var _Room = class _Room {
|
|
|
237
270
|
_init(options) {
|
|
238
271
|
this._id = options.id;
|
|
239
272
|
this._sendFn = options.sendFn;
|
|
273
|
+
this._sendBinaryFn = options.sendBinaryFn ?? null;
|
|
240
274
|
this._broadcastFn = options.broadcastFn;
|
|
241
275
|
this._disposeFn = options.disposeFn;
|
|
242
276
|
}
|
|
@@ -259,6 +293,7 @@ var _Room = class _Room {
|
|
|
259
293
|
roomId: this._id,
|
|
260
294
|
conn,
|
|
261
295
|
sendFn: this._sendFn,
|
|
296
|
+
sendBinaryFn: this._sendBinaryFn ?? void 0,
|
|
262
297
|
leaveFn: /* @__PURE__ */ __name((p, reason) => this._removePlayer(p.id, reason), "leaveFn")
|
|
263
298
|
});
|
|
264
299
|
this._players.set(id, player);
|
|
@@ -334,5 +369,5 @@ function onMessage(type) {
|
|
|
334
369
|
__name(onMessage, "onMessage");
|
|
335
370
|
|
|
336
371
|
export { Player, Room, onMessage };
|
|
337
|
-
//# sourceMappingURL=chunk-
|
|
338
|
-
//# sourceMappingURL=chunk-
|
|
372
|
+
//# sourceMappingURL=chunk-T3QJOPNG.js.map
|
|
373
|
+
//# sourceMappingURL=chunk-T3QJOPNG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/room/Player.ts","../src/room/Room.ts","../src/room/decorators.ts"],"names":["Player","options","id","roomId","data","_conn","_sendFn","_sendBinaryFn","_leaveFn","conn","sendFn","sendBinaryFn","leaveFn","initialData","connection","send","type","sendBinary","_toBase64","Buffer","from","toString","binary","i","length","String","fromCharCode","btoa","leave","reason","MESSAGE_HANDLERS","Room","maxPlayers","tickRate","autoDispose","state","_id","_players","Map","_locked","_disposed","_tickInterval","_lastTickTime","_broadcastFn","_disposeFn","players","Array","values","playerCount","size","isFull","isLocked","isDisposed","onCreate","onJoin","player","onLeave","onTick","dt","onDispose","broadcast","broadcastExcept","except","getPlayer","get","kick","lock","unlock","dispose","_stopTick","clear","_init","broadcastFn","disposeFn","_create","_startTick","_addPlayer","undefined","p","_removePlayer","set","delete","_handleMessage","playerId","handlers","handler","method","call","performance","now","setInterval","clearInterval","registerMessageHandler","target","push","onMessage","propertyKey","_descriptor"],"mappings":"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","file":"chunk-T3QJOPNG.js","sourcesContent":["/**\n * @zh 玩家类\n * @en Player class\n */\n\nimport type { Connection } from '@esengine/rpc';\n\n/**\n * @zh 玩家接口\n * @en Player interface\n */\nexport interface IPlayer<TData = Record<string, unknown>> {\n readonly id: string\n readonly roomId: string\n data: TData\n send<T>(type: string, data: T): void\n sendBinary(data: Uint8Array): void\n leave(reason?: string): void\n}\n\n/**\n * @zh 玩家实现\n * @en Player implementation\n */\nexport class Player<TData = Record<string, unknown>> implements IPlayer<TData> {\n readonly id: string;\n readonly roomId: string;\n data: TData;\n\n private _conn: Connection<any>;\n private _sendFn: (conn: Connection<any>, type: string, data: unknown) => void;\n private _sendBinaryFn?: (conn: Connection<any>, data: Uint8Array) => void;\n private _leaveFn: (player: Player<TData>, reason?: string) => void;\n\n constructor(options: {\n id: string\n roomId: string\n conn: Connection<any>\n sendFn: (conn: Connection<any>, type: string, data: unknown) => void\n sendBinaryFn?: (conn: Connection<any>, data: Uint8Array) => void\n leaveFn: (player: Player<TData>, reason?: string) => void\n initialData?: TData\n }) {\n this.id = options.id;\n this.roomId = options.roomId;\n this._conn = options.conn;\n this._sendFn = options.sendFn;\n this._sendBinaryFn = options.sendBinaryFn;\n this._leaveFn = options.leaveFn;\n this.data = options.initialData ?? ({} as TData);\n }\n\n /**\n * @zh 获取底层连接\n * @en Get underlying connection\n */\n get connection(): Connection<any> {\n return this._conn;\n }\n\n /**\n * @zh 发送消息给玩家\n * @en Send message to player\n */\n send<T>(type: string, data: T): void {\n this._sendFn(this._conn, type, data);\n }\n\n /**\n * @zh 发送二进制数据给玩家\n * @en Send binary data to player\n *\n * @zh 如果底层连接支持原生二进制帧,则直接发送;否则降级为 base64 编码通过 JSON 发送\n * @en If underlying connection supports native binary frames, sends directly; otherwise falls back to base64 encoding via JSON\n */\n sendBinary(data: Uint8Array): void {\n if (this._sendBinaryFn) {\n this._sendBinaryFn(this._conn, data);\n } else {\n this.send('$binary', { data: this._toBase64(data) });\n }\n }\n\n /**\n * @zh 将 Uint8Array 转换为 base64 字符串\n * @en Convert Uint8Array to base64 string\n */\n private _toBase64(data: Uint8Array): string {\n if (typeof Buffer !== 'undefined') {\n return Buffer.from(data).toString('base64');\n }\n let binary = '';\n for (let i = 0; i < data.length; i++) {\n binary += String.fromCharCode(data[i]);\n }\n return btoa(binary);\n }\n\n /**\n * @zh 让玩家离开房间\n * @en Make player leave the room\n */\n leave(reason?: string): void {\n this._leaveFn(this, reason);\n }\n}\n","/**\n * @zh 房间基类\n * @en Room base class\n */\n\nimport { Player } from './Player.js';\n\n/**\n * @zh 房间配置\n * @en Room options\n */\nexport interface RoomOptions {\n [key: string]: unknown\n}\n\n/**\n * @zh 消息处理器元数据\n * @en Message handler metadata\n */\ninterface MessageHandlerMeta {\n type: string\n method: string\n}\n\n/**\n * @zh 消息处理器存储 key\n * @en Message handler storage key\n */\nconst MESSAGE_HANDLERS = Symbol('messageHandlers');\n\n/**\n * @zh 房间基类\n * @en Room base class\n *\n * @example\n * ```typescript\n * class GameRoom extends Room {\n * maxPlayers = 4\n * tickRate = 20\n *\n * onJoin(player: Player) {\n * this.broadcast('Joined', { id: player.id })\n * }\n *\n * @onMessage('Move')\n * handleMove(data: { x: number, y: number }, player: Player) {\n * // handle move\n * }\n * }\n * ```\n */\nexport abstract class Room<TState = any, TPlayerData = Record<string, unknown>> {\n // ========================================================================\n // 配置 | Configuration\n // ========================================================================\n\n /**\n * @zh 最大玩家数\n * @en Maximum players\n */\n maxPlayers = 16;\n\n /**\n * @zh Tick 速率(每秒),0 = 不自动 tick\n * @en Tick rate (per second), 0 = no auto tick\n */\n tickRate = 0;\n\n /**\n * @zh 空房间自动销毁\n * @en Auto dispose when empty\n */\n autoDispose = true;\n\n // ========================================================================\n // 状态 | State\n // ========================================================================\n\n /**\n * @zh 房间状态\n * @en Room state\n */\n state: TState = {} as TState;\n\n // ========================================================================\n // 内部属性 | Internal properties\n // ========================================================================\n\n private _id: string = '';\n private _players: Map<string, Player<TPlayerData>> = new Map();\n private _locked = false;\n private _disposed = false;\n private _tickInterval: ReturnType<typeof setInterval> | null = null;\n private _lastTickTime = 0;\n private _broadcastFn: ((type: string, data: unknown) => void) | null = null;\n private _sendFn: ((conn: any, type: string, data: unknown) => void) | null = null;\n private _sendBinaryFn: ((conn: any, data: Uint8Array) => void) | null = null;\n private _disposeFn: (() => void) | null = null;\n\n // ========================================================================\n // 只读属性 | Readonly properties\n // ========================================================================\n\n /**\n * @zh 房间 ID\n * @en Room ID\n */\n get id(): string {\n return this._id;\n }\n\n /**\n * @zh 所有玩家\n * @en All players\n */\n get players(): ReadonlyArray<Player<TPlayerData>> {\n return Array.from(this._players.values());\n }\n\n /**\n * @zh 玩家数量\n * @en Player count\n */\n get playerCount(): number {\n return this._players.size;\n }\n\n /**\n * @zh 是否已满\n * @en Is full\n */\n get isFull(): boolean {\n return this._players.size >= this.maxPlayers;\n }\n\n /**\n * @zh 是否已锁定\n * @en Is locked\n */\n get isLocked(): boolean {\n return this._locked;\n }\n\n /**\n * @zh 是否已销毁\n * @en Is disposed\n */\n get isDisposed(): boolean {\n return this._disposed;\n }\n\n // ========================================================================\n // 生命周期 | Lifecycle\n // ========================================================================\n\n /**\n * @zh 房间创建时调用\n * @en Called when room is created\n */\n onCreate(options?: RoomOptions): void | Promise<void> {}\n\n /**\n * @zh 玩家加入时调用\n * @en Called when player joins\n */\n onJoin(player: Player<TPlayerData>): void | Promise<void> {}\n\n /**\n * @zh 玩家离开时调用\n * @en Called when player leaves\n */\n onLeave(player: Player<TPlayerData>, reason?: string): void | Promise<void> {}\n\n /**\n * @zh 游戏循环\n * @en Game tick\n */\n onTick(dt: number): void {}\n\n /**\n * @zh 房间销毁时调用\n * @en Called when room is disposed\n */\n onDispose(): void | Promise<void> {}\n\n // ========================================================================\n // 公共方法 | Public methods\n // ========================================================================\n\n /**\n * @zh 广播消息给所有玩家\n * @en Broadcast message to all players\n */\n broadcast<T>(type: string, data: T): void {\n for (const player of this._players.values()) {\n player.send(type, data);\n }\n }\n\n /**\n * @zh 广播消息给除指定玩家外的所有玩家\n * @en Broadcast message to all players except one\n */\n broadcastExcept<T>(except: Player<TPlayerData>, type: string, data: T): void {\n for (const player of this._players.values()) {\n if (player.id !== except.id) {\n player.send(type, data);\n }\n }\n }\n\n /**\n * @zh 获取玩家\n * @en Get player by id\n */\n getPlayer(id: string): Player<TPlayerData> | undefined {\n return this._players.get(id);\n }\n\n /**\n * @zh 踢出玩家\n * @en Kick player\n */\n kick(player: Player<TPlayerData>, reason?: string): void {\n player.leave(reason ?? 'kicked');\n }\n\n /**\n * @zh 锁定房间\n * @en Lock room\n */\n lock(): void {\n this._locked = true;\n }\n\n /**\n * @zh 解锁房间\n * @en Unlock room\n */\n unlock(): void {\n this._locked = false;\n }\n\n /**\n * @zh 手动销毁房间\n * @en Manually dispose room\n */\n dispose(): void {\n if (this._disposed) return;\n this._disposed = true;\n\n this._stopTick();\n\n for (const player of this._players.values()) {\n player.leave('room_disposed');\n }\n this._players.clear();\n\n this.onDispose();\n this._disposeFn?.();\n }\n\n // ========================================================================\n // 内部方法 | Internal methods\n // ========================================================================\n\n /**\n * @internal\n */\n _init(options: {\n id: string\n sendFn: (conn: any, type: string, data: unknown) => void\n sendBinaryFn?: (conn: any, data: Uint8Array) => void\n broadcastFn: (type: string, data: unknown) => void\n disposeFn: () => void\n }): void {\n this._id = options.id;\n this._sendFn = options.sendFn;\n this._sendBinaryFn = options.sendBinaryFn ?? null;\n this._broadcastFn = options.broadcastFn;\n this._disposeFn = options.disposeFn;\n }\n\n /**\n * @internal\n */\n async _create(options?: RoomOptions): Promise<void> {\n await this.onCreate(options);\n this._startTick();\n }\n\n /**\n * @internal\n */\n async _addPlayer(id: string, conn: any): Promise<Player<TPlayerData> | null> {\n if (this._locked || this.isFull || this._disposed) {\n return null;\n }\n\n const player = new Player<TPlayerData>({\n id,\n roomId: this._id,\n conn,\n sendFn: this._sendFn!,\n sendBinaryFn: this._sendBinaryFn ?? undefined,\n leaveFn: (p, reason) => this._removePlayer(p.id, reason)\n });\n\n this._players.set(id, player);\n await this.onJoin(player);\n\n return player;\n }\n\n /**\n * @internal\n */\n async _removePlayer(id: string, reason?: string): Promise<void> {\n const player = this._players.get(id);\n if (!player) return;\n\n this._players.delete(id);\n await this.onLeave(player, reason);\n\n if (this.autoDispose && this._players.size === 0) {\n this.dispose();\n }\n }\n\n /**\n * @internal\n */\n _handleMessage(type: string, data: unknown, playerId: string): void {\n const player = this._players.get(playerId);\n if (!player) return;\n\n const handlers = (this.constructor as any)[MESSAGE_HANDLERS] as MessageHandlerMeta[] | undefined;\n if (handlers) {\n for (const handler of handlers) {\n if (handler.type === type) {\n const method = (this as any)[handler.method];\n if (typeof method === 'function') {\n method.call(this, data, player);\n }\n }\n }\n }\n }\n\n private _startTick(): void {\n if (this.tickRate <= 0) return;\n\n this._lastTickTime = performance.now();\n this._tickInterval = setInterval(() => {\n const now = performance.now();\n const dt = (now - this._lastTickTime) / 1000;\n this._lastTickTime = now;\n this.onTick(dt);\n }, 1000 / this.tickRate);\n }\n\n private _stopTick(): void {\n if (this._tickInterval) {\n clearInterval(this._tickInterval);\n this._tickInterval = null;\n }\n }\n}\n\n/**\n * @zh 获取消息处理器元数据\n * @en Get message handler metadata\n */\nexport function getMessageHandlers(target: any): MessageHandlerMeta[] {\n return target[MESSAGE_HANDLERS] || [];\n}\n\n/**\n * @zh 注册消息处理器元数据\n * @en Register message handler metadata\n */\nexport function registerMessageHandler(target: any, type: string, method: string): void {\n if (!target[MESSAGE_HANDLERS]) {\n target[MESSAGE_HANDLERS] = [];\n }\n target[MESSAGE_HANDLERS].push({ type, method });\n}\n","/**\n * @zh 房间装饰器\n * @en Room decorators\n */\n\nimport { registerMessageHandler } from './Room.js';\n\n/**\n * @zh 消息处理器装饰器\n * @en Message handler decorator\n *\n * @example\n * ```typescript\n * class GameRoom extends Room {\n * @onMessage('Move')\n * handleMove(data: { x: number, y: number }, player: Player) {\n * // handle move\n * }\n *\n * @onMessage('Chat')\n * handleChat(data: { text: string }, player: Player) {\n * this.broadcast('Chat', { from: player.id, text: data.text })\n * }\n * }\n * ```\n */\nexport function onMessage(type: string): MethodDecorator {\n return function (\n target: any,\n propertyKey: string | symbol,\n _descriptor: PropertyDescriptor\n ) {\n registerMessageHandler(target.constructor, type, propertyKey as string);\n };\n}\n"]}
|