@babylonjs-toolkit/server 0.0.0-stage → 9.35.0

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.
Files changed (236) hide show
  1. package/CUSTOM.md +1690 -0
  2. package/DEPLOY.md +2012 -0
  3. package/README.md +1081 -2
  4. package/lib/AbuseLimits.d.ts +64 -0
  5. package/lib/AbuseLimits.js +121 -0
  6. package/lib/Authentication.d.ts +86 -0
  7. package/lib/Authentication.js +272 -0
  8. package/lib/BootSessionOwner.d.ts +86 -0
  9. package/lib/BootSessionOwner.js +116 -0
  10. package/lib/ColyseusLoggerAdapter.d.ts +32 -0
  11. package/lib/ColyseusLoggerAdapter.js +73 -0
  12. package/lib/DedicatedSceneRegistry.d.ts +52 -0
  13. package/lib/DedicatedSceneRegistry.js +74 -0
  14. package/lib/DedicatedSession.d.ts +152 -0
  15. package/lib/DedicatedSession.js +173 -0
  16. package/lib/DualTransport.d.ts +112 -0
  17. package/lib/DualTransport.js +197 -0
  18. package/lib/GameServer.d.ts +64 -0
  19. package/lib/GameServer.js +647 -0
  20. package/lib/GameServerConfig.d.ts +387 -0
  21. package/lib/GameServerConfig.js +1059 -0
  22. package/lib/GameServerLobbyRoom.d.ts +33 -0
  23. package/lib/GameServerLobbyRoom.js +56 -0
  24. package/lib/GameServerLogger.d.ts +111 -0
  25. package/lib/GameServerLogger.js +190 -0
  26. package/lib/GameServerMetrics.d.ts +158 -0
  27. package/lib/GameServerMetrics.js +276 -0
  28. package/lib/GameServerState.d.ts +164 -0
  29. package/lib/GameServerState.js +26 -0
  30. package/lib/HeadlessRuntime.d.ts +316 -0
  31. package/lib/HeadlessRuntime.js +380 -0
  32. package/lib/JoinGate.d.ts +34 -0
  33. package/lib/JoinGate.js +221 -0
  34. package/lib/NetworkAddresses.d.ts +33 -0
  35. package/lib/NetworkAddresses.js +90 -0
  36. package/lib/PlayerTokens.d.ts +17 -0
  37. package/lib/PlayerTokens.js +24 -0
  38. package/lib/RoomServerTransport.d.ts +73 -0
  39. package/lib/RoomServerTransport.js +90 -0
  40. package/lib/ServerEndpoints.d.ts +133 -0
  41. package/lib/ServerEndpoints.js +247 -0
  42. package/lib/ServerInit.d.ts +28 -0
  43. package/lib/ServerInit.js +113 -0
  44. package/lib/SessionRoom.d.ts +391 -0
  45. package/lib/SessionRoom.js +930 -0
  46. package/lib/TlsCertificates.d.ts +35 -0
  47. package/lib/TlsCertificates.js +130 -0
  48. package/lib/admin/AccountRoutes.d.ts +8 -0
  49. package/lib/admin/AccountRoutes.js +502 -0
  50. package/lib/admin/AdminAccounts.d.ts +329 -0
  51. package/lib/admin/AdminAccounts.js +607 -0
  52. package/lib/admin/AdminApiRouter.d.ts +202 -0
  53. package/lib/admin/AdminApiRouter.js +465 -0
  54. package/lib/admin/AdminApiTypes.d.ts +1782 -0
  55. package/lib/admin/AdminApiTypes.js +4 -0
  56. package/lib/admin/AdminAudit.d.ts +113 -0
  57. package/lib/admin/AdminAudit.js +266 -0
  58. package/lib/admin/AdminCli.d.ts +7 -0
  59. package/lib/admin/AdminCli.js +351 -0
  60. package/lib/admin/AdminClock.d.ts +51 -0
  61. package/lib/admin/AdminClock.js +10 -0
  62. package/lib/admin/AdminConsole.d.ts +39 -0
  63. package/lib/admin/AdminConsole.js +325 -0
  64. package/lib/admin/AdminConstants.d.ts +147 -0
  65. package/lib/admin/AdminConstants.js +167 -0
  66. package/lib/admin/AdminCrypto.d.ts +19 -0
  67. package/lib/admin/AdminCrypto.js +29 -0
  68. package/lib/admin/AdminExtensionsHost.d.ts +176 -0
  69. package/lib/admin/AdminExtensionsHost.js +307 -0
  70. package/lib/admin/AdminPasswords.d.ts +33 -0
  71. package/lib/admin/AdminPasswords.js +92 -0
  72. package/lib/admin/AdminPermissions.d.ts +28 -0
  73. package/lib/admin/AdminPermissions.js +74 -0
  74. package/lib/admin/AdminRecords.d.ts +196 -0
  75. package/lib/admin/AdminRecords.js +3 -0
  76. package/lib/admin/AdminRequestBodies.d.ts +47 -0
  77. package/lib/admin/AdminRequestBodies.js +84 -0
  78. package/lib/admin/AdminRequestGate.d.ts +38 -0
  79. package/lib/admin/AdminRequestGate.js +59 -0
  80. package/lib/admin/AdminResponses.d.ts +103 -0
  81. package/lib/admin/AdminResponses.js +164 -0
  82. package/lib/admin/AdminServices.d.ts +99 -0
  83. package/lib/admin/AdminServices.js +4 -0
  84. package/lib/admin/AdminStaticFiles.d.ts +29 -0
  85. package/lib/admin/AdminStaticFiles.js +97 -0
  86. package/lib/admin/AdminStore.d.ts +152 -0
  87. package/lib/admin/AdminStore.js +46 -0
  88. package/lib/admin/AlertChannels.d.ts +43 -0
  89. package/lib/admin/AlertChannels.js +120 -0
  90. package/lib/admin/AlertEngine.d.ts +231 -0
  91. package/lib/admin/AlertEngine.js +681 -0
  92. package/lib/admin/AlertRoutes.d.ts +8 -0
  93. package/lib/admin/AlertRoutes.js +180 -0
  94. package/lib/admin/ApiKeyRoutes.d.ts +8 -0
  95. package/lib/admin/ApiKeyRoutes.js +53 -0
  96. package/lib/admin/ApiKeys.d.ts +63 -0
  97. package/lib/admin/ApiKeys.js +167 -0
  98. package/lib/admin/AuditRoutes.d.ts +8 -0
  99. package/lib/admin/AuditRoutes.js +106 -0
  100. package/lib/admin/AuthToolRoutes.d.ts +13 -0
  101. package/lib/admin/AuthToolRoutes.js +164 -0
  102. package/lib/admin/BanList.d.ts +87 -0
  103. package/lib/admin/BanList.js +152 -0
  104. package/lib/admin/CborDecoder.d.ts +18 -0
  105. package/lib/admin/CborDecoder.js +201 -0
  106. package/lib/admin/ColyseusCloudClient.d.ts +313 -0
  107. package/lib/admin/ColyseusCloudClient.js +272 -0
  108. package/lib/admin/ColyseusCloudRoutes.d.ts +8 -0
  109. package/lib/admin/ColyseusCloudRoutes.js +91 -0
  110. package/lib/admin/ColyseusCloudService.d.ts +180 -0
  111. package/lib/admin/ColyseusCloudService.js +476 -0
  112. package/lib/admin/ColyseusCloudSettings.d.ts +16 -0
  113. package/lib/admin/ColyseusCloudSettings.js +29 -0
  114. package/lib/admin/ColyseusCloudViews.d.ts +105 -0
  115. package/lib/admin/ColyseusCloudViews.js +371 -0
  116. package/lib/admin/CommonPasswords.d.ts +6 -0
  117. package/lib/admin/CommonPasswords.js +19 -0
  118. package/lib/admin/ConfigOverrides.d.ts +174 -0
  119. package/lib/admin/ConfigOverrides.js +406 -0
  120. package/lib/admin/ConfigRoutes.d.ts +8 -0
  121. package/lib/admin/ConfigRoutes.js +91 -0
  122. package/lib/admin/ConsoleSessions.d.ts +112 -0
  123. package/lib/admin/ConsoleSessions.js +201 -0
  124. package/lib/admin/DedicatedRoutes.d.ts +21 -0
  125. package/lib/admin/DedicatedRoutes.js +254 -0
  126. package/lib/admin/ExtensionRoutes.d.ts +8 -0
  127. package/lib/admin/ExtensionRoutes.js +145 -0
  128. package/lib/admin/FileAdminStore.d.ts +157 -0
  129. package/lib/admin/FileAdminStore.js +349 -0
  130. package/lib/admin/FleetDirectory.d.ts +323 -0
  131. package/lib/admin/FleetDirectory.js +489 -0
  132. package/lib/admin/FleetLeader.d.ts +43 -0
  133. package/lib/admin/FleetLeader.js +89 -0
  134. package/lib/admin/FleetRoutes.d.ts +55 -0
  135. package/lib/admin/FleetRoutes.js +465 -0
  136. package/lib/admin/HealthWarnings.d.ts +10 -0
  137. package/lib/admin/HealthWarnings.js +95 -0
  138. package/lib/admin/LeaderboardRoutes.d.ts +8 -0
  139. package/lib/admin/LeaderboardRoutes.js +569 -0
  140. package/lib/admin/LogBuffer.d.ts +60 -0
  141. package/lib/admin/LogBuffer.js +92 -0
  142. package/lib/admin/LogRedaction.d.ts +15 -0
  143. package/lib/admin/LogRedaction.js +72 -0
  144. package/lib/admin/LogRoutes.d.ts +45 -0
  145. package/lib/admin/LogRoutes.js +307 -0
  146. package/lib/admin/MaintenanceMode.d.ts +41 -0
  147. package/lib/admin/MaintenanceMode.js +74 -0
  148. package/lib/admin/MaintenanceWindows.d.ts +91 -0
  149. package/lib/admin/MaintenanceWindows.js +207 -0
  150. package/lib/admin/MetricsRoutes.d.ts +8 -0
  151. package/lib/admin/MetricsRoutes.js +209 -0
  152. package/lib/admin/MetricsSampler.d.ts +124 -0
  153. package/lib/admin/MetricsSampler.js +211 -0
  154. package/lib/admin/OneTimeCodes.d.ts +60 -0
  155. package/lib/admin/OneTimeCodes.js +162 -0
  156. package/lib/admin/OpenIdConnect.d.ts +146 -0
  157. package/lib/admin/OpenIdConnect.js +335 -0
  158. package/lib/admin/Passkeys.d.ts +130 -0
  159. package/lib/admin/Passkeys.js +432 -0
  160. package/lib/admin/PlayerRoutes.d.ts +20 -0
  161. package/lib/admin/PlayerRoutes.js +676 -0
  162. package/lib/admin/RedisAdminStore.d.ts +114 -0
  163. package/lib/admin/RedisAdminStore.js +258 -0
  164. package/lib/admin/RolloutCoordinator.d.ts +99 -0
  165. package/lib/admin/RolloutCoordinator.js +321 -0
  166. package/lib/admin/ServerEvents.d.ts +57 -0
  167. package/lib/admin/ServerEvents.js +89 -0
  168. package/lib/admin/SessionRoutes.d.ts +113 -0
  169. package/lib/admin/SessionRoutes.js +386 -0
  170. package/lib/admin/UserRoutes.d.ts +8 -0
  171. package/lib/admin/UserRoutes.js +214 -0
  172. package/lib/cli.d.ts +2 -0
  173. package/lib/cli.js +221 -0
  174. package/lib/console/assets/index-CI5N7c-T.js +21 -0
  175. package/lib/console/assets/index-DPitvzLp.css +1 -0
  176. package/lib/console/favicon.svg +1 -0
  177. package/lib/console/index.html +16 -0
  178. package/lib/discord/DiscordOAuth.d.ts +57 -0
  179. package/lib/discord/DiscordOAuth.js +127 -0
  180. package/lib/discord/DiscordSessions.d.ts +79 -0
  181. package/lib/discord/DiscordSessions.js +135 -0
  182. package/lib/discord/DiscordSignInConstants.d.ts +54 -0
  183. package/lib/discord/DiscordSignInConstants.js +55 -0
  184. package/lib/discord/DiscordSignInRoutes.d.ts +51 -0
  185. package/lib/discord/DiscordSignInRoutes.js +359 -0
  186. package/lib/index.d.ts +24 -0
  187. package/lib/index.js +18 -0
  188. package/lib/leaderboards/FileLeaderboardRankStore.d.ts +293 -0
  189. package/lib/leaderboards/FileLeaderboardRankStore.js +808 -0
  190. package/lib/leaderboards/LeaderboardConstants.d.ts +63 -0
  191. package/lib/leaderboards/LeaderboardConstants.js +70 -0
  192. package/lib/leaderboards/LeaderboardError.d.ts +15 -0
  193. package/lib/leaderboards/LeaderboardError.js +20 -0
  194. package/lib/leaderboards/LeaderboardIdentity.d.ts +44 -0
  195. package/lib/leaderboards/LeaderboardIdentity.js +72 -0
  196. package/lib/leaderboards/LeaderboardPublicApi.d.ts +17 -0
  197. package/lib/leaderboards/LeaderboardPublicApi.js +389 -0
  198. package/lib/leaderboards/LeaderboardRankStore.d.ts +296 -0
  199. package/lib/leaderboards/LeaderboardRankStore.js +18 -0
  200. package/lib/leaderboards/LeaderboardRules.d.ts +122 -0
  201. package/lib/leaderboards/LeaderboardRules.js +472 -0
  202. package/lib/leaderboards/LeaderboardScheduler.d.ts +43 -0
  203. package/lib/leaderboards/LeaderboardScheduler.js +103 -0
  204. package/lib/leaderboards/LeaderboardService.d.ts +669 -0
  205. package/lib/leaderboards/LeaderboardService.js +1667 -0
  206. package/lib/leaderboards/LeaderboardTransfer.d.ts +35 -0
  207. package/lib/leaderboards/LeaderboardTransfer.js +580 -0
  208. package/lib/leaderboards/RedisLeaderboardRankStore.d.ts +282 -0
  209. package/lib/leaderboards/RedisLeaderboardRankStore.js +691 -0
  210. package/package.json +64 -4
  211. package/templates/init/Caddyfile +6 -0
  212. package/templates/init/DEPLOY.md +233 -0
  213. package/templates/init/Dockerfile +12 -0
  214. package/templates/init/app.json +21 -0
  215. package/templates/init/aws/README.md +118 -0
  216. package/templates/init/aws/ecs-fargate-alb.yml +207 -0
  217. package/templates/init/aws/ecs-fargate-nlb-quic.yml +210 -0
  218. package/templates/init/babylon-game-server.config.mjs +158 -0
  219. package/templates/init/colyseus-cloud/README.md +133 -0
  220. package/templates/init/colyseus-cloud/babylon-game-server.config.mjs +36 -0
  221. package/templates/init/colyseus-cloud/ecosystem.config.cjs +35 -0
  222. package/templates/init/colyseus-cloud/gitignore +6 -0
  223. package/templates/init/colyseus-cloud/package.json +15 -0
  224. package/templates/init/digitalocean-app.yaml +30 -0
  225. package/templates/init/docker-compose.full.yml +45 -0
  226. package/templates/init/docker-compose.websocket.yml +41 -0
  227. package/templates/init/fly.toml +56 -0
  228. package/templates/init/heroku.yml +11 -0
  229. package/templates/init/kubernetes/deployment.yaml +71 -0
  230. package/templates/init/kubernetes/redis.yaml +73 -0
  231. package/templates/init/kubernetes/service.yaml +24 -0
  232. package/templates/init/monitoring/grafana-dashboard.json +539 -0
  233. package/templates/init/monitoring/prometheus-alerts.yml +51 -0
  234. package/templates/init/monitoring/prometheus-scrape.yml +17 -0
  235. package/templates/init/railway.json +13 -0
  236. package/templates/init/render.yaml +19 -0
@@ -0,0 +1,112 @@
1
+ import type { Transport } from "colyseus";
2
+ import type { IncomingMessage, ServerResponse } from "node:http";
3
+ /** The members of an Express application the HTTP/3 transport uses (its matchmaking routes and the request handler). */
4
+ export interface ExpressApplication {
5
+ /** Handles one HTTPS request. */
6
+ (request: IncomingMessage, response: ServerResponse): void;
7
+ /** Adds middleware. */
8
+ use(handler: unknown): unknown;
9
+ /** Adds a POST route. */
10
+ post(path: string, handler: unknown): unknown;
11
+ }
12
+ /** The options of @colyseus/h3-transport's H3Transport (local shape: no type import of the optional package, D8). */
13
+ export interface H3TransportOptions {
14
+ /** The Express application serving HTTPS. */
15
+ app: ExpressApplication;
16
+ /** The certificate (PEM); omitted to let the transport make a development one. */
17
+ cert?: string;
18
+ /** The private key (PEM); omitted with cert. */
19
+ key?: string;
20
+ }
21
+ /** A bidirectional stream of a WebTransport session (the part the probe guard wraps). */
22
+ export interface Http3BidirectionalStream {
23
+ /** Bytes from the peer. */
24
+ readable: ReadableStream<Uint8Array>;
25
+ }
26
+ /** A WebTransport session as the HTTP/3 server hands it out (the part the probe guard wraps). */
27
+ export interface Http3Session {
28
+ /** Opens a bidirectional stream to the peer. */
29
+ createBidirectionalStream(): Promise<Http3BidirectionalStream>;
30
+ }
31
+ /** The HTTP/3 server of @fails-components/webtransport (the part the probe guard wraps). */
32
+ export interface Http3ServerInstance {
33
+ /**
34
+ * The incoming sessions of a path.
35
+ * @param path The path, e.g. "/".
36
+ * @returns The stream of sessions.
37
+ */
38
+ sessionStream(path: string): Promise<ReadableStream<Http3Session>>;
39
+ }
40
+ /** An H3Transport instance (local shape). Its inherited `server` is the HTTPS server, set once it listens. */
41
+ export interface H3TransportInstance extends Transport {
42
+ /** The HTTP/3 server, set once it listens. */
43
+ h3Server: Http3ServerInstance;
44
+ /** Accepts WebTransport sessions until shutdown; H3Transport.listen starts it. */
45
+ acceptIncomingSessions(): Promise<void>;
46
+ /**
47
+ * Listens for HTTPS (TCP) and HTTP/3 (UDP) on one port.
48
+ * @param port The port.
49
+ * @param hostname The bind address.
50
+ * @param backlog The TCP backlog.
51
+ * @param listeningListener Called once the HTTPS server listens.
52
+ * @returns The transport.
53
+ */
54
+ listen(port: number, hostname?: string, backlog?: number, listeningListener?: () => void): this;
55
+ /** Stops HTTPS and HTTP/3. */
56
+ shutdown(): void;
57
+ /**
58
+ * Delays every frame (Colyseus' latency simulation).
59
+ * @param milliseconds The added one-way latency.
60
+ */
61
+ simulateLatency(milliseconds: number): void;
62
+ }
63
+ /** The H3Transport class (local shape). */
64
+ export type H3TransportConstructor = new (options: H3TransportOptions) => H3TransportInstance;
65
+ /** A certificate generated by the optional package for WebTransport hash pinning (local shape). */
66
+ export interface GeneratedWebTransportCertificate {
67
+ /** The certificate (PEM). */
68
+ cert: string;
69
+ /** The private key (PEM). */
70
+ private: string;
71
+ /** The SHA-256 hash, as colon-separated hex pairs ("AB:CD:…"). */
72
+ fingerprint: string;
73
+ }
74
+ /** The optional package's exports the server uses (local shape). */
75
+ export interface H3TransportModule {
76
+ /** The HTTP/3 WebTransport transport. */
77
+ H3Transport: H3TransportConstructor;
78
+ /**
79
+ * Makes a short-lived ECDSA P-256 certificate that browsers accept by hash (serverCertificateHashes).
80
+ * @param attributes The subject attributes.
81
+ * @param options The validity.
82
+ * @returns The certificate, its key and hash.
83
+ */
84
+ generateWebTransportCertificate(attributes: {
85
+ shortName: string;
86
+ value: string;
87
+ }[], options: {
88
+ days: number;
89
+ }): Promise<GeneratedWebTransportCertificate>;
90
+ }
91
+ /** What createDualTransport needs. */
92
+ export interface DualTransportOptions {
93
+ /** The HTTPS/WSS certificate (PEM), or null to use the HTTP/3 one for HTTPS too. */
94
+ cert: string | null;
95
+ /** The private key (PEM), or null with cert. */
96
+ key: string | null;
97
+ /**
98
+ * True (development certificate) to give HTTP/3 its own short-lived self-signed certificate, pinned by hash: browsers
99
+ * refuse WebTransport to locally trusted roots such as mkcert's, but accept a pinned certificate. HTTPS keeps cert.
100
+ */
101
+ pinHttp3Certificate: boolean;
102
+ /** Largest WebSocket message, in bytes (limits.maxMessageBytes). */
103
+ maxPayload: number;
104
+ }
105
+ /**
106
+ * The transport of a server with UDP on (D8): HTTP/3 WebTransport and HTTPS from @colyseus/h3-transport, plus WebSocket
107
+ * upgrades on the same HTTPS server, so WebTransport and WebSocket players share one port and one session.
108
+ * @param options The certificate, key, HTTP/3 pinning and WebSocket message limit.
109
+ * @returns The transport.
110
+ * @throws Error(H3_MISSING_MESSAGE) when the optional package cannot be loaded.
111
+ */
112
+ export declare function createDualTransport(options: DualTransportOptions): Promise<Transport>;
@@ -0,0 +1,197 @@
1
+ import { WebSocketTransport } from "@colyseus/ws-transport";
2
+ import { createRequire } from "node:module";
3
+ import { networkInterfaces } from "node:os";
4
+ /** The optional HTTP/3 package, imported only when UDP is on (D8). A string-typed specifier keeps tsc from resolving it. */
5
+ const H3_TRANSPORT_PACKAGE = "@colyseus/h3-transport";
6
+ /** The error when UDP is on and the optional package is missing (its native build failed on this platform). */
7
+ const H3_MISSING_MESSAGE = "UDP needs @colyseus/h3-transport, which is not installed on this platform";
8
+ /** Milliseconds between WebSocket keep-alive pings. */
9
+ const PING_INTERVAL_MS = 10000;
10
+ /** Days the pinned HTTP/3 development certificate is valid; browsers accept hash pinning only up to 14 days. */
11
+ const PINNED_CERTIFICATE_DAYS = 10;
12
+ /** Common name of the pinned HTTP/3 development certificate. */
13
+ const PINNED_CERTIFICATE_NAME = "localhost";
14
+ /** The IPv4 "every interface" bind address. */
15
+ const IPV4_WILDCARD_HOST = "0.0.0.0";
16
+ /** The dual-stack "every interface" bind address (IPv6 and, mapped, IPv4). */
17
+ const DUAL_STACK_WILDCARD_HOST = "::";
18
+ /**
19
+ * The transport of a server with UDP on (D8): HTTP/3 WebTransport and HTTPS from @colyseus/h3-transport, plus WebSocket
20
+ * upgrades on the same HTTPS server, so WebTransport and WebSocket players share one port and one session.
21
+ * @param options The certificate, key, HTTP/3 pinning and WebSocket message limit.
22
+ * @returns The transport.
23
+ * @throws Error(H3_MISSING_MESSAGE) when the optional package cannot be loaded.
24
+ */
25
+ export async function createDualTransport(options) {
26
+ const h3Module = await importH3Transport();
27
+ const DualTransport = createDualTransportClass(h3Module.H3Transport);
28
+ const express = createRequire(import.meta.url)("express");
29
+ const app = express();
30
+ app.use(express.json());
31
+ const pinnedCertificate = options.pinHttp3Certificate
32
+ ? await h3Module.generateWebTransportCertificate([{ shortName: "CN", value: PINNED_CERTIFICATE_NAME }], { days: PINNED_CERTIFICATE_DAYS })
33
+ : null;
34
+ const h3Options = { app: app };
35
+ if (pinnedCertificate != null) {
36
+ h3Options.cert = pinnedCertificate.cert;
37
+ h3Options.key = pinnedCertificate.private;
38
+ }
39
+ else if (options.cert != null && options.key != null) {
40
+ h3Options.cert = options.cert;
41
+ h3Options.key = options.key;
42
+ }
43
+ const httpsMaterial = (pinnedCertificate != null && options.cert != null && options.key != null) ? { cert: options.cert, key: options.key } : null;
44
+ const webSocketTransport = new WebSocketTransport({ noServer: true, pingInterval: PING_INTERVAL_MS, maxPayload: options.maxPayload });
45
+ const transport = new DualTransport(h3Options, webSocketTransport, httpsMaterial);
46
+ // Matchmaking answers carry the hash, so the SDK pins it for its WebTransport connection.
47
+ if (pinnedCertificate != null)
48
+ transport.fingerprint = fingerprintBytes(pinnedCertificate.fingerprint);
49
+ return transport;
50
+ }
51
+ /**
52
+ * The bytes of a colon-separated hex hash.
53
+ * @param fingerprint The hash, "AB:CD:…".
54
+ * @returns The bytes.
55
+ */
56
+ function fingerprintBytes(fingerprint) {
57
+ return fingerprint.split(":").map((hexPair) => Number.parseInt(hexPair, 16));
58
+ }
59
+ /**
60
+ * The address the HTTP/3 and HTTPS servers bind. The HTTP/3 (UDP) server listens only on the address family it is
61
+ * given, and browsers and Node resolve "localhost" to ::1 first, so the IPv4 wildcard becomes the dual-stack wildcard
62
+ * whenever this machine has IPv6 (containers without IPv6 keep 0.0.0.0, where "::" would fail to bind).
63
+ * @param hostname The configured bind address.
64
+ * @returns The address to bind.
65
+ */
66
+ function http3BindHost(hostname) {
67
+ if (hostname !== IPV4_WILDCARD_HOST || !hasIpv6Interface())
68
+ return hostname;
69
+ return DUAL_STACK_WILDCARD_HOST;
70
+ }
71
+ /**
72
+ * Whether any network interface (loopback included) has an IPv6 address.
73
+ * @returns True when IPv6 is available.
74
+ */
75
+ function hasIpv6Interface() {
76
+ const interfaces = Object.values(networkInterfaces()).flatMap((addresses) => addresses ?? []);
77
+ return interfaces.some((address) => address.family === "IPv6");
78
+ }
79
+ /**
80
+ * Keeps a WebTransport session that ends before it sends its first message from crashing the server. The runtime probes
81
+ * the server with exactly such a session before it joins (D25). @colyseus/h3-transport reads a session's first message
82
+ * without a rejection handler, so a probe that closes leaves an unhandled rejection, which ends a Node process. The guard
83
+ * makes that first read wait forever instead of rejecting; the session's own close handling still cleans up.
84
+ * @param h3Server The transport's HTTP/3 server.
85
+ */
86
+ function guardProbeSessions(h3Server) {
87
+ const openSessionStream = h3Server.sessionStream.bind(h3Server);
88
+ h3Server.sessionStream = async (path) => {
89
+ const sessions = await openSessionStream(path);
90
+ const guard = new TransformStream({
91
+ transform: (session, controller) => controller.enqueue(guardFirstRead(session))
92
+ });
93
+ return sessions.pipeThrough(guard);
94
+ };
95
+ }
96
+ /**
97
+ * Makes the first read of a session's first bidirectional stream wait forever when the session ends before any data.
98
+ * @param session The session.
99
+ * @returns The same session, guarded.
100
+ */
101
+ function guardFirstRead(session) {
102
+ const createStream = session.createBidirectionalStream.bind(session);
103
+ session.createBidirectionalStream = async () => {
104
+ const stream = await createStream();
105
+ const getReader = stream.readable.getReader.bind(stream.readable);
106
+ stream.readable.getReader = (() => guardReader(getReader()));
107
+ return stream;
108
+ };
109
+ return session;
110
+ }
111
+ /**
112
+ * A reader whose first read never rejects: it resolves with the first chunk, or stays pending when the stream fails.
113
+ * Later reads are the reader's own (the transport's read loop handles their failures).
114
+ * @param reader The stream's reader.
115
+ * @returns The same reader, guarded.
116
+ */
117
+ function guardReader(reader) {
118
+ const read = reader.read.bind(reader);
119
+ let isFirstRead = true;
120
+ reader.read = () => {
121
+ if (!isFirstRead)
122
+ return read();
123
+ isFirstRead = false;
124
+ return new Promise((resolve) => {
125
+ read().then(resolve, ignoreEndedProbe);
126
+ });
127
+ };
128
+ return reader;
129
+ }
130
+ /** The rejection of a session that ended before its first message: nothing to do, the session cleans itself up. */
131
+ function ignoreEndedProbe() {
132
+ return;
133
+ }
134
+ /**
135
+ * Loads the optional HTTP/3 package.
136
+ * @returns Its module.
137
+ * @throws Error(H3_MISSING_MESSAGE) when it is not installed or its native part does not load.
138
+ */
139
+ async function importH3Transport() {
140
+ try {
141
+ return await import(H3_TRANSPORT_PACKAGE);
142
+ }
143
+ catch {
144
+ throw new Error(H3_MISSING_MESSAGE);
145
+ }
146
+ }
147
+ /**
148
+ * Builds the dual transport class on the loaded H3Transport (D8).
149
+ * @param h3TransportBase The H3Transport constructor of the optional package.
150
+ * @returns The DualTransport class.
151
+ */
152
+ function createDualTransportClass(h3TransportBase) {
153
+ return class DualTransport extends h3TransportBase {
154
+ /** The WebSocket transport sharing the HTTPS server (D8). */
155
+ webSocketTransport;
156
+ /** The HTTPS certificate when it differs from the HTTP/3 one (pinned development certificate), else null. */
157
+ httpsMaterial;
158
+ /**
159
+ * Creates the transport.
160
+ * @param h3Options The H3 options.
161
+ * @param webSocketTransport A noServer WebSocket transport.
162
+ * @param httpsMaterial The HTTPS certificate when it differs from the HTTP/3 one, else null.
163
+ */
164
+ constructor(h3Options, webSocketTransport, httpsMaterial) {
165
+ super(h3Options);
166
+ this.webSocketTransport = webSocketTransport;
167
+ this.httpsMaterial = httpsMaterial;
168
+ }
169
+ /**
170
+ * Listens for HTTPS + HTTP/3, then attaches WebSocket upgrades to the same HTTPS server.
171
+ * @param port The port (TCP and UDP).
172
+ * @param hostname The bind address.
173
+ * @param backlog The TCP backlog.
174
+ * @param listeningListener Called once both listen.
175
+ * @returns The transport.
176
+ */
177
+ listen(port, hostname, backlog, listeningListener) {
178
+ return super.listen(port, http3BindHost(hostname), backlog, () => {
179
+ if (this.httpsMaterial != null)
180
+ this.server.setSecureContext(this.httpsMaterial);
181
+ this.webSocketTransport.attachToServer(this.server);
182
+ if (listeningListener != null)
183
+ listeningListener();
184
+ });
185
+ }
186
+ /** Accepts WebTransport sessions, guarding the ones that end before they join (guardProbeSessions). */
187
+ acceptIncomingSessions() {
188
+ guardProbeSessions(this.h3Server);
189
+ return super.acceptIncomingSessions();
190
+ }
191
+ /** Stops WebSocket and HTTP/3. */
192
+ shutdown() {
193
+ this.webSocketTransport.shutdown();
194
+ super.shutdown();
195
+ }
196
+ };
197
+ }
@@ -0,0 +1,64 @@
1
+ import { type Endpoint } from "colyseus";
2
+ import { type ConfigSourceMap, type DeepPartial, type GameServerConfig } from "./GameServerConfig.js";
3
+ import { type GameServerHooks } from "./GameServerState.js";
4
+ import { type AdminTestingOptions } from "./admin/AdminClock.js";
5
+ import { type AdminExtensions } from "./admin/AdminExtensionsHost.js";
6
+ import { type DiscordTestingOptions } from "./discord/DiscordOAuth.js";
7
+ /** Options of createGameServer. */
8
+ export interface GameServerOptions {
9
+ /** Overrides of the defaults (D3). */
10
+ config?: DeepPartial<GameServerConfig>;
11
+ /** Lifecycle and custom-auth hooks. */
12
+ hooks?: GameServerHooks;
13
+ /** Extra HTTP endpoints made with createEndpoint (D15). */
14
+ routes?: Record<string, Endpoint>;
15
+ /**
16
+ * Drain on SIGTERM/SIGINT and exit 0, and drain on an uncaught error and exit 1 (CLI: true; API default false, D17).
17
+ * The handlers are in place before the boot sessions start, so a stop that arrives while they start still drains.
18
+ */
19
+ handleSignals?: boolean;
20
+ /** Custom admin actions, panels and admin event hooks of the web console (game-server-admin-console D25). */
21
+ admin?: AdminExtensions;
22
+ /** For tests only: a manual clock and shorter admin intervals (game-server-admin-console R10). */
23
+ adminTesting?: AdminTestingOptions;
24
+ /** For tests only: Discord's base URL (a fake Discord), discord-sign-in D15. */
25
+ discordTesting?: DiscordTestingOptions;
26
+ /** Where each option came from (the CLI passes loadGameServerConfigWithSources' map); every path is "code" without it. */
27
+ configSources?: ConfigSourceMap;
28
+ }
29
+ /** Where players and tools reach a running server. */
30
+ export interface GameServerUrls {
31
+ /** ws:// or wss:// URL of the SDK endpoint. */
32
+ webSocket: string;
33
+ /** http:// or https:// URL of the same endpoint (matchmaking, health). */
34
+ http: string;
35
+ /** https:// URL of the WebTransport endpoint, or null when UDP is off. */
36
+ webTransport: string | null;
37
+ }
38
+ /** A running Babylon Game Server. */
39
+ export interface GameServer {
40
+ /** The resolved config. */
41
+ readonly config: GameServerConfig;
42
+ /** The port it listens on (the free port picked for 0). */
43
+ readonly port: number;
44
+ /** Where players and tools reach it. */
45
+ readonly urls: GameServerUrls;
46
+ /** Stops at once: disconnects everyone (tests, scripts). */
47
+ close(): Promise<void>;
48
+ /** Stops taking players, lets sessions finish, then stops (D17). */
49
+ drain(): Promise<void>;
50
+ /** Starts a dedicated session of a configured scene; resolves the room id. */
51
+ startDedicatedSession(sessionName: string, sceneName: string): Promise<string>;
52
+ }
53
+ /**
54
+ * Starts the Babylon Game Server: the lobby room "fusion_lobby" and the session room "fusion_session", filtered by
55
+ * session name and listed in the lobby in real time. The toolkit runtime is loaded first so rooms run the browser's
56
+ * session logic. Programmatic callers pass overrides of the defaults; the CLI passes its loaded config (D3). Once it
57
+ * listens, the config's boot dedicated sessions start (D19), and with handleSignals SIGTERM/SIGINT or an uncaught error
58
+ * drain it (D17). A draining process gets no new rooms from the matchmaker of any process.
59
+ * @param options The config overrides, hooks, extra routes and signal handling.
60
+ * @returns The running server.
61
+ * @throws GameServerConfigError when the config is invalid; Error "admin extension <name>: <problem>" for a bad
62
+ * options.admin definition; Error when a boot dedicated session cannot start (the server is stopped again first).
63
+ */
64
+ export declare function createGameServer(options?: GameServerOptions): Promise<GameServer>;