@sagl/server 0.1.0-next.51 → 0.1.0-next.55

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/query.js ADDED
@@ -0,0 +1,220 @@
1
+ // The query: what anyone can learn about the server without joining it,
2
+ // over UDP on its game port (the core answers) and, if the gamemode turns
3
+ // it on, over HTTP. Asking one is query-client.ts (also @sagl/query).
4
+ import * as fs from "node:fs";
5
+ import * as http from "node:http";
6
+ import * as path from "node:path";
7
+ const PLAYERS = { none: 0, count: 1, list: 2 };
8
+ const MAX_TEXT = 1000;
9
+ const MAX_VALUE = 256;
10
+ function checkText(what, s, max = MAX_TEXT) {
11
+ if (typeof s !== "string")
12
+ throw new TypeError(`query: ${what} must be a string`);
13
+ if (s.length > max)
14
+ throw new RangeError(`query: ${what} is over ${max} characters`);
15
+ return s;
16
+ }
17
+ function checkInfo(info) {
18
+ const out = {};
19
+ if (info.description !== undefined)
20
+ out.description = checkText("description", info.description);
21
+ if (info.gamemode !== undefined)
22
+ out.gamemode = checkText("gamemode", info.gamemode, 64);
23
+ if (info.language !== undefined)
24
+ out.language = checkText("language", info.language, 64);
25
+ if (info.tags !== undefined) {
26
+ if (!Array.isArray(info.tags) || info.tags.length > 32)
27
+ throw new TypeError("query: tags must be an array of up to 32 strings");
28
+ out.tags = info.tags.map((t) => checkText("a tag", t, 32));
29
+ }
30
+ if (info.links !== undefined) {
31
+ out.links = {};
32
+ for (const [name, url] of Object.entries(info.links)) {
33
+ checkText("a link's name", name, 32);
34
+ let u;
35
+ try {
36
+ u = new URL(checkText(`links.${name}`, url, 512));
37
+ }
38
+ catch {
39
+ throw new TypeError(`query: links.${name} isn't a URL: ${url}`);
40
+ }
41
+ if (u.protocol !== "http:" && u.protocol !== "https:")
42
+ throw new TypeError(`query: links.${name} must be http(s): ${url}`);
43
+ out.links[name] = url;
44
+ }
45
+ }
46
+ return out;
47
+ }
48
+ /**
49
+ * `server.query`: what the server tells anyone who asks without joining
50
+ * (server lists, a browser in the game): its name, version, players and
51
+ * branding (the core's), and the gamemode's own fields and values.
52
+ *
53
+ * ```ts
54
+ * server.query.info = {
55
+ * description: "Los Santos roleplay, whitelisted.",
56
+ * gamemode: "Roleplay", language: "en", tags: ["rp", "whitelist"],
57
+ * links: { website: "https://example.com", discord: "https://discord.gg/example" },
58
+ * };
59
+ * server.query.set("map", "Los Santos");
60
+ * setInterval(() => server.query.set("cops", copsOnDuty()), 10_000);
61
+ * await server.query.http({ port: 8080 }); // and over HTTP, for websites
62
+ * ```
63
+ */
64
+ export class ServerQuery {
65
+ #native;
66
+ #clientFiles;
67
+ #info = {};
68
+ #values = new Map();
69
+ #players = "list";
70
+ #pending = false;
71
+ #http = null;
72
+ /** @internal */
73
+ constructor(native, clientFiles) {
74
+ this.#native = native;
75
+ this.#clientFiles = clientFiles;
76
+ }
77
+ /** The gamemode's fields: set as a whole (`update` changes some). */
78
+ get info() {
79
+ return structuredClone(this.#info);
80
+ }
81
+ set info(info) {
82
+ this.#info = checkInfo(info);
83
+ this.#push();
84
+ }
85
+ /** Changes some of `info`, keeping the rest. */
86
+ update(info) {
87
+ this.info = { ...this.#info, ...info };
88
+ }
89
+ /**
90
+ * One of the gamemode's values (`"map"`, `"cops"`, `"event"`, ...), shown
91
+ * under `values`: a string (up to 256 characters), number, boolean or
92
+ * null. Up to 64 of them.
93
+ */
94
+ set(key, value) {
95
+ checkText("a value's key", key, 64);
96
+ if (typeof value === "string")
97
+ checkText(`values.${key}`, value, MAX_VALUE);
98
+ else if (typeof value === "number" && !Number.isFinite(value))
99
+ throw new RangeError(`query: values.${key} must be finite`);
100
+ else if (value !== null && typeof value !== "number" && typeof value !== "boolean") {
101
+ throw new TypeError(`query: values.${key} must be a string, number, boolean or null`);
102
+ }
103
+ if (!this.#values.has(key) && this.#values.size >= 64)
104
+ throw new RangeError("query: 64 values at most");
105
+ if (this.#values.get(key) === value && this.#values.has(key))
106
+ return;
107
+ this.#values.set(key, value);
108
+ this.#push();
109
+ }
110
+ get(key) {
111
+ return this.#values.get(key);
112
+ }
113
+ delete(key) {
114
+ const had = this.#values.delete(key);
115
+ if (had)
116
+ this.#push();
117
+ return had;
118
+ }
119
+ /** The values, as an object (a copy). */
120
+ get values() {
121
+ return Object.fromEntries(this.#values);
122
+ }
123
+ /** The player list (`"list"`, the default), just how many are on (`"count"`), or neither. */
124
+ get players() {
125
+ return this.#players;
126
+ }
127
+ set players(p) {
128
+ if (!(p in PLAYERS))
129
+ throw new TypeError(`query: players must be "list", "count" or "none"`);
130
+ this.#players = p;
131
+ this.#push();
132
+ }
133
+ /** What a query gets now. */
134
+ get result() {
135
+ return JSON.parse(this.#native.queryJson());
136
+ }
137
+ /**
138
+ * Serves the query over HTTP too, for websites: `GET /` (or `/query`)
139
+ * the same JSON a UDP query gets, `GET /logo` the logo. Any site may
140
+ * read them (CORS). Resolves once it's listening.
141
+ */
142
+ http(options) {
143
+ if (this.#http)
144
+ throw new Error("query: HTTP is on already (close it first)");
145
+ const server = http.createServer((req, res) => this.#serve(req, res));
146
+ this.#http = server;
147
+ return new Promise((resolve, reject) => {
148
+ server.once("error", (e) => {
149
+ this.#http = null;
150
+ reject(e);
151
+ });
152
+ server.listen(options.port, options.host, () => resolve());
153
+ });
154
+ }
155
+ /** Stops serving HTTP. */
156
+ closeHttp() {
157
+ const server = this.#http;
158
+ this.#http = null;
159
+ if (!server)
160
+ return Promise.resolve();
161
+ return new Promise((resolve) => server.close(() => resolve()));
162
+ }
163
+ #serve(req, res) {
164
+ const url = (req.url ?? "/").split("?")[0];
165
+ const headers = { "Access-Control-Allow-Origin": "*" };
166
+ if (req.method !== "GET" && req.method !== "HEAD") {
167
+ res.writeHead(405, { ...headers, Allow: "GET, HEAD" }).end();
168
+ return;
169
+ }
170
+ if (url === "/" || url === "/query") {
171
+ const body = this.#native.queryJson();
172
+ res.writeHead(200, { ...headers, "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-cache" });
173
+ res.end(req.method === "HEAD" ? undefined : body);
174
+ return;
175
+ }
176
+ if (url === "/logo") {
177
+ const logo = JSON.parse(this.#native.queryJson()).branding.logo;
178
+ const file = logo && this.#clientFiles ? this.#logoPath(logo.sha256) : null;
179
+ if (!logo || !file) {
180
+ res.writeHead(404, headers).end();
181
+ return;
182
+ }
183
+ const etag = `"${logo.sha256}"`;
184
+ if (req.headers["if-none-match"] === etag) {
185
+ res.writeHead(304, { ...headers, ETag: etag }).end();
186
+ return;
187
+ }
188
+ fs.readFile(file, (err, data) => {
189
+ if (err) {
190
+ res.writeHead(500, headers).end();
191
+ return;
192
+ }
193
+ const type = data[0] === 0x89 ? "image/png" : "image/jpeg";
194
+ res.writeHead(200, { ...headers, "Content-Type": type, ETag: etag, "Cache-Control": "public, max-age=300" });
195
+ res.end(req.method === "HEAD" ? undefined : data);
196
+ });
197
+ return;
198
+ }
199
+ res.writeHead(404, headers).end();
200
+ }
201
+ #logoPath(sha256) {
202
+ const f = this.#native.clientFiles().find((c) => c.sha256 === sha256);
203
+ return f && this.#clientFiles ? path.join(this.#clientFiles, f.path) : null;
204
+ }
205
+ // To the core, once per tick of changes.
206
+ #push() {
207
+ if (this.#pending)
208
+ return;
209
+ this.#pending = true;
210
+ queueMicrotask(() => {
211
+ this.#pending = false;
212
+ const fields = { ...this.#info };
213
+ if (this.#values.size)
214
+ fields.values = Object.fromEntries(this.#values);
215
+ const json = JSON.stringify(fields);
216
+ this.#native.setQuery(json === "{}" ? "" : json.slice(1, -1), PLAYERS[this.#players]);
217
+ });
218
+ }
219
+ }
220
+ //# sourceMappingURL=query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
@@ -24,6 +24,11 @@ type Spec = {
24
24
  * client/src/script_things.cpp: add a new one to all three.
25
25
  */
26
26
  export declare const BUILT_IN_SCREEN_EFFECTS: Readonly<Record<string, Readonly<ScreenEffectParams>>>;
27
+ /** Effects as they were (`ScreenEffects.snapshot` / `save`), to go back to. */
28
+ export interface ScreenEffectsSnapshot {
29
+ /** Back to them: those on now that weren't in it go, they come back as they were. */
30
+ restore(fadeMs?: number): void;
31
+ }
27
32
  /**
28
33
  * A full-screen effect on one player's screen, or on everyone's
29
34
  * (`player.screenEffects.add`, `server.screenEffects.add`): a pixel shader
@@ -43,6 +48,10 @@ export declare class ScreenEffect {
43
48
  set(params: ScreenEffectParams): this;
44
49
  /** Takes it off, fading out over `fadeMs` (default 0: at once). */
45
50
  remove(fadeMs?: number): void;
51
+ /** @internal On again (`ScreenEffects.restore`), with these parameters. */
52
+ revive(params: ScreenEffectParams, fadeMs: number): void;
53
+ /** @internal Its parameters as they are (`ScreenEffects.save`). */
54
+ snapshot(): ScreenEffectParams;
46
55
  /** @internal */
47
56
  spec(fadeMs: number): Spec;
48
57
  }
@@ -93,6 +102,33 @@ export declare class ScreenEffects {
93
102
  get list(): ScreenEffect[];
94
103
  /** Takes every one off, fading out over `fadeMs`. */
95
104
  clear(fadeMs?: number): void;
105
+ /**
106
+ * The effects on now, with their parameters, to go back to: `restore()`
107
+ * on what this returns. Doesn't touch what `save()` remembers, so a
108
+ * cutscene can take its own (as `Mission.cinematic` does).
109
+ */
110
+ snapshot(): ScreenEffectsSnapshot;
111
+ /**
112
+ * Remembers the effects on now, with their parameters, for `restore()`
113
+ * (replacing what was saved before). Returns the snapshot too.
114
+ *
115
+ * ```ts
116
+ * player.screenEffects.save();
117
+ * player.screenEffects.clear(300);
118
+ * player.screenEffects.add("tiltshift"); // the scene's own
119
+ * // ...
120
+ * player.screenEffects.restore(500); // theirs back, the scene's gone
121
+ * ```
122
+ */
123
+ save(): ScreenEffectsSnapshot;
124
+ /**
125
+ * Back to what `save()` last remembered, whatever happened since
126
+ * (cleared, reset, others added): those on now that weren't saved go, and
127
+ * the saved ones come back as they were (the same `ScreenEffect`s, so code
128
+ * holding them carries on), fading over `fadeMs`. Nothing saved: every one
129
+ * goes. The save stays, to restore again.
130
+ */
131
+ restore(fadeMs?: number): void;
96
132
  /** @internal A player joined: everyone's on their screen too. */
97
133
  joined(player: Player): void;
98
134
  }
@@ -128,6 +128,16 @@ export class ScreenEffect {
128
128
  this.#active = false;
129
129
  this.#send(null, Math.max(0, Math.trunc(fadeMs)));
130
130
  }
131
+ /** @internal On again (`ScreenEffects.restore`), with these parameters. */
132
+ revive(params, fadeMs) {
133
+ this.#params = structuredClone(params);
134
+ this.#active = true;
135
+ this.#send(this.spec(fadeMs), 0);
136
+ }
137
+ /** @internal Its parameters as they are (`ScreenEffects.save`). */
138
+ snapshot() {
139
+ return structuredClone(this.#params);
140
+ }
131
141
  /** @internal */
132
142
  spec(fadeMs) {
133
143
  const e = encode(this.#params, this.#sizes);
@@ -193,9 +203,14 @@ export class ScreenEffects {
193
203
  throw new ReferenceError(`no screen effect or client file "${effect}"`);
194
204
  }
195
205
  const id = this.#next++;
196
- const added = new ScreenEffect(effect, shader, params, options, (spec, fadeMs) => {
206
+ // (Its first send comes from its constructor, before `added` is set:
207
+ // the list gets it below.)
208
+ let added;
209
+ added = new ScreenEffect(effect, shader, params, options, (spec, fadeMs) => {
197
210
  if (!spec)
198
211
  this.#effects.delete(id);
212
+ else if (added)
213
+ this.#effects.set(id, added);
199
214
  for (const p of this.#targets())
200
215
  this.#sendTo(p, id, spec, fadeMs);
201
216
  });
@@ -234,6 +249,52 @@ export class ScreenEffects {
234
249
  for (const e of this.list)
235
250
  e.remove(fadeMs);
236
251
  }
252
+ /**
253
+ * The effects on now, with their parameters, to go back to: `restore()`
254
+ * on what this returns. Doesn't touch what `save()` remembers, so a
255
+ * cutscene can take its own (as `Mission.cinematic` does).
256
+ */
257
+ snapshot() {
258
+ const saved = this.list.map((effect) => ({ effect, params: effect.snapshot() }));
259
+ return { restore: (fadeMs = 0) => this.#restore(saved, fadeMs) };
260
+ }
261
+ /**
262
+ * Remembers the effects on now, with their parameters, for `restore()`
263
+ * (replacing what was saved before). Returns the snapshot too.
264
+ *
265
+ * ```ts
266
+ * player.screenEffects.save();
267
+ * player.screenEffects.clear(300);
268
+ * player.screenEffects.add("tiltshift"); // the scene's own
269
+ * // ...
270
+ * player.screenEffects.restore(500); // theirs back, the scene's gone
271
+ * ```
272
+ */
273
+ save() {
274
+ return (this.#saved = this.snapshot());
275
+ }
276
+ /**
277
+ * Back to what `save()` last remembered, whatever happened since
278
+ * (cleared, reset, others added): those on now that weren't saved go, and
279
+ * the saved ones come back as they were (the same `ScreenEffect`s, so code
280
+ * holding them carries on), fading over `fadeMs`. Nothing saved: every one
281
+ * goes. The save stays, to restore again.
282
+ */
283
+ restore(fadeMs = 0) {
284
+ if (this.#saved)
285
+ this.#saved.restore(fadeMs);
286
+ else
287
+ this.clear(fadeMs);
288
+ }
289
+ #saved = null;
290
+ #restore(saved, fadeMs) {
291
+ const keep = new Set(saved.map((s) => s.effect));
292
+ for (const e of this.list)
293
+ if (!keep.has(e))
294
+ e.remove(fadeMs);
295
+ for (const { effect, params } of saved)
296
+ effect.revive(params, effect.active ? 0 : fadeMs);
297
+ }
237
298
  /** @internal A player joined: everyone's on their screen too. */
238
299
  joined(player) {
239
300
  for (const [id, e] of this.#effects)
@@ -1 +1 @@
1
- {"version":3,"file":"screeneffects.js","sourceRoot":"","sources":["../src/screeneffects.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"screeneffects.js","sourceRoot":"","sources":["../src/screeneffects.ts"],"names":[],"mappings":"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"}
package/dist/server.d.ts CHANGED
@@ -1,4 +1,7 @@
1
1
  import { type WeaponViolationReason } from "./native.js";
2
+ import { type AuthMiddleware } from "./auth.js";
3
+ import { ServerQuery, type QueryInfo, type QueryPlayers, type QueryHttpOptions } from "./query.js";
4
+ import type { QueryValue } from "./query-client.js";
2
5
  import { Player, type Vector3 } from "./player.js";
3
6
  import { Vehicle } from "./vehicle.js";
4
7
  import { Ped, type PedSettings } from "./ped.js";
@@ -116,6 +119,23 @@ export interface ServerOptions {
116
119
  clientFiles?: string;
117
120
  /** How the server looks to joining players: see `Branding`. */
118
121
  branding?: Branding;
122
+ /**
123
+ * What the server tells anyone who asks without joining (server lists,
124
+ * the game's browser): the gamemode's fields, values and how much of the
125
+ * player list to show, and `http` to serve it over HTTP too. See
126
+ * `server.query`.
127
+ */
128
+ query?: QueryInfo & {
129
+ values?: Record<string, QueryValue>;
130
+ players?: QueryPlayers;
131
+ http?: QueryHttpOptions;
132
+ };
133
+ /**
134
+ * Signing in: every player must start the game with a token (`--token`),
135
+ * which this checks as they connect. See `server.auth`. Left out, anyone
136
+ * can join (and the gamemode can sign them in its own way, in game).
137
+ */
138
+ auth?: AuthMiddleware;
119
139
  }
120
140
  /**
121
141
  * The server's look, sent to players first thing as they join: the loading
@@ -470,6 +490,8 @@ export declare class Server {
470
490
  readonly options: Readonly<ServerOptions>;
471
491
  /** Operator console on stdin; add commands with `server.console.command()`. */
472
492
  readonly console: Console;
493
+ /** The query: what anyone can learn without joining (see `ServerQuery`). */
494
+ readonly query: ServerQuery;
473
495
  /** JavaScript run (sandboxed) in every player's game: see `ClientScripts`. */
474
496
  readonly clientScripts: ClientScripts;
475
497
  /** The pause menu's map, everyone's: see `GameMap`. */
@@ -567,6 +589,34 @@ export declare class Server {
567
589
  get stuntBonus(): boolean;
568
590
  set stuntBonus(on: boolean);
569
591
  /** Connected players. */
592
+ /**
593
+ * Signing in: a function that checks each player's token as they
594
+ * connect (or null: anyone can join). Players then need a token to join
595
+ * (`sagl.exe --token ...`); without one they're turned away.
596
+ *
597
+ * ```ts
598
+ * server.auth = async ({ token }) => {
599
+ * const user = await accounts.verify(token); // your own service
600
+ * if (!user) return "Your sign-in has expired: sign in again on the website";
601
+ * if (user.banned) return false;
602
+ * return { name: user.username, accountId: user.id, metadata: { avatar: user.avatarUrl } };
603
+ * };
604
+ * ```
605
+ *
606
+ * It returns:
607
+ * - what to let them in as: `name`, `accountId`, `metadata`, all
608
+ * optional. Nothing at all lets them in as they are.
609
+ * - a message to turn them away with it, or `false` for "Sign-in failed".
610
+ *
611
+ * Throwing, or not answering in `authTimeout` ms, turns them away too, and
612
+ * the error is logged. Someone signing in with an account that's already
613
+ * on kicks the old session ("You signed in somewhere else").
614
+ */
615
+ get auth(): AuthMiddleware | null;
616
+ set auth(fn: AuthMiddleware | null);
617
+ /** How long `auth` may take, in ms, before they're turned away. Default 15000. */
618
+ get authTimeout(): number;
619
+ set authTimeout(ms: number);
570
620
  get players(): Player[];
571
621
  player(id: number): Player | undefined;
572
622
  /**
package/dist/server.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import { native } from "./native.js";
2
+ import { Auth } from "./auth.js";
3
+ import { ServerQuery } from "./query.js";
2
4
  import { Player } from "./player.js";
3
5
  import { Vehicle } from "./vehicle.js";
4
6
  import { Ped, setPedSpeaker } from "./ped.js";
@@ -37,6 +39,8 @@ export class Server {
37
39
  options;
38
40
  /** Operator console on stdin; add commands with `server.console.command()`. */
39
41
  console;
42
+ /** The query: what anyone can learn without joining (see `ServerQuery`). */
43
+ query;
40
44
  /** JavaScript run (sandboxed) in every player's game: see `ClientScripts`. */
41
45
  clientScripts;
42
46
  /** The pause menu's map, everyone's: see `GameMap`. */
@@ -92,6 +96,7 @@ export class Server {
92
96
  #warnedAsyncVeto = false;
93
97
  #channels = new Map();
94
98
  #branding = {};
99
+ #auth;
95
100
  constructor(options = {}) {
96
101
  this.options = options;
97
102
  this.#native = new native.NativeServer({
@@ -113,7 +118,13 @@ export class Server {
113
118
  indicatorSound: options.indicators?.sound === false ? "-" : (options.indicators?.sound ?? ""),
114
119
  clientFiles: options.clientFiles,
115
120
  });
121
+ this.#auth = new Auth(this.#native, (accountId) => {
122
+ for (const p of this.players)
123
+ if (p.accountId === accountId)
124
+ p.kick("You signed in somewhere else");
125
+ });
116
126
  this.#native.setHooks({
127
+ auth: (ticket, token, name, ip, host, port, clientVersion) => this.#auth.request(ticket, { token, name, ip, host, port, clientVersion }),
117
128
  join: (id) => this.#onJoin(id),
118
129
  quit: (id, reason) => this.#onQuit(id, reason),
119
130
  damage: (victimId, attackerId, hit, attackerPedId) => this.#onDamage(victimId, this.#attacker(attackerId, attackerPedId), hit),
@@ -411,6 +422,20 @@ export class Server {
411
422
  this.clientScripts = new ClientScripts(this.#native);
412
423
  if (options.branding)
413
424
  this.branding = options.branding;
425
+ if (options.auth)
426
+ this.auth = options.auth;
427
+ this.query = new ServerQuery(this.#native, options.clientFiles);
428
+ if (options.query) {
429
+ const { values, players, http, ...info } = options.query;
430
+ this.query.info = info;
431
+ for (const [k, v] of Object.entries(values ?? {}))
432
+ this.query.set(k, v);
433
+ if (players)
434
+ this.query.players = players;
435
+ if (http) {
436
+ this.query.http(http).catch((e) => console.error(`query: HTTP on port ${http.port}: ${e.message}`));
437
+ }
438
+ }
414
439
  this.map = new GameMap(this.#native, -1);
415
440
  let nextDraw = 1_000_000; // apart from players' own ids
416
441
  this.draw = new ServerDraw(this.#native, () => this.players, () => nextDraw++);
@@ -500,6 +525,7 @@ export class Server {
500
525
  this.#checkpointTimer = null;
501
526
  }
502
527
  this.console.stop();
528
+ void this.query.closeHttp();
503
529
  this.#native.shutdown();
504
530
  }
505
531
  // ---- Events -----------------------------------------------------------------
@@ -639,6 +665,8 @@ export class Server {
639
665
  }
640
666
  #onJoin(id) {
641
667
  const player = new Player(this.#native, id, (vid) => this.#vehicleById(vid));
668
+ const { token, signedIn } = this.#auth.take(id);
669
+ player.signedIn(token, signedIn?.accountId ?? null, signedIn?.metadata ?? {});
642
670
  this.#players.set(id, player);
643
671
  if (this.options.splash) {
644
672
  // Up until the gamemode hides it (or the timeout does).
@@ -792,6 +820,44 @@ export class Server {
792
820
  this.#native.nameTagOptions(player.id, Math.max(0, o.distance), o.lineOfSight, o.ids, o.bars);
793
821
  }
794
822
  /** Connected players. */
823
+ /**
824
+ * Signing in: a function that checks each player's token as they
825
+ * connect (or null: anyone can join). Players then need a token to join
826
+ * (`sagl.exe --token ...`); without one they're turned away.
827
+ *
828
+ * ```ts
829
+ * server.auth = async ({ token }) => {
830
+ * const user = await accounts.verify(token); // your own service
831
+ * if (!user) return "Your sign-in has expired: sign in again on the website";
832
+ * if (user.banned) return false;
833
+ * return { name: user.username, accountId: user.id, metadata: { avatar: user.avatarUrl } };
834
+ * };
835
+ * ```
836
+ *
837
+ * It returns:
838
+ * - what to let them in as: `name`, `accountId`, `metadata`, all
839
+ * optional. Nothing at all lets them in as they are.
840
+ * - a message to turn them away with it, or `false` for "Sign-in failed".
841
+ *
842
+ * Throwing, or not answering in `authTimeout` ms, turns them away too, and
843
+ * the error is logged. Someone signing in with an account that's already
844
+ * on kicks the old session ("You signed in somewhere else").
845
+ */
846
+ get auth() {
847
+ return this.#auth.middleware;
848
+ }
849
+ set auth(fn) {
850
+ this.#auth.middleware = fn;
851
+ }
852
+ /** How long `auth` may take, in ms, before they're turned away. Default 15000. */
853
+ get authTimeout() {
854
+ return this.#auth.timeoutMs;
855
+ }
856
+ set authTimeout(ms) {
857
+ if (!(ms > 0))
858
+ throw new RangeError("authTimeout must be positive");
859
+ this.#auth.timeoutMs = ms;
860
+ }
795
861
  get players() {
796
862
  return [...this.#players.values()];
797
863
  }