dredless 0.2.0 → 0.2.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.
Files changed (77) hide show
  1. package/README.md +48 -48
  2. package/docs/API_REFERENCE.md +2481 -2481
  3. package/docs/BROWSER_API.md +98 -98
  4. package/docs/NODE_API.md +359 -359
  5. package/package.json +34 -34
  6. package/src/browser.d.ts +212 -212
  7. package/src/browser.js +133 -133
  8. package/src/client/core.js +1202 -1202
  9. package/src/client/domains/index.js +1818 -1818
  10. package/src/client/index.d.ts +2 -2
  11. package/src/client/index.js +1 -1
  12. package/src/compression/lz4.d.ts +1 -1
  13. package/src/compression/lz4.js +112 -112
  14. package/src/constants.js +74 -74
  15. package/src/crypto/chacha-native.d.ts +9 -9
  16. package/src/crypto/chacha-native.js +48 -48
  17. package/src/crypto/chacha.d.ts +25 -25
  18. package/src/crypto/chacha.js +274 -274
  19. package/src/events.js +39 -39
  20. package/src/index.d.ts +2277 -2277
  21. package/src/index.js +125 -125
  22. package/src/network/browser-session.js +291 -291
  23. package/src/network/connection.d.ts +1 -1
  24. package/src/network/connection.js +31 -31
  25. package/src/network/cookies.js +85 -85
  26. package/src/network/http.js +34 -34
  27. package/src/network/index.d.ts +4 -4
  28. package/src/network/index.js +4 -4
  29. package/src/network/servers.d.ts +7 -7
  30. package/src/network/servers.js +133 -133
  31. package/src/network/session.d.ts +7 -7
  32. package/src/network/session.js +320 -320
  33. package/src/network/ships.d.ts +12 -12
  34. package/src/network/ships.js +73 -73
  35. package/src/node.d.ts +2 -2
  36. package/src/node.js +8 -8
  37. package/src/protocol/codec/binary.d.ts +3 -3
  38. package/src/protocol/codec/binary.js +52 -52
  39. package/src/protocol/codec/msgpack.d.ts +3 -3
  40. package/src/protocol/codec/msgpack.js +555 -555
  41. package/src/protocol/inbound/frame.d.ts +1 -1
  42. package/src/protocol/inbound/frame.js +8 -8
  43. package/src/protocol/inbound/world-payload.d.ts +3 -3
  44. package/src/protocol/inbound/world-payload.js +21 -21
  45. package/src/protocol/index.d.ts +11 -11
  46. package/src/protocol/index.js +19 -19
  47. package/src/protocol/outbound/blueprint.d.ts +22 -22
  48. package/src/protocol/outbound/blueprint.js +36 -36
  49. package/src/protocol/outbound/commands.d.ts +3 -3
  50. package/src/protocol/outbound/commands.js +149 -149
  51. package/src/protocol/outbound/comms.d.ts +28 -28
  52. package/src/protocol/outbound/comms.js +40 -40
  53. package/src/protocol/outbound/inventory.d.ts +64 -64
  54. package/src/protocol/outbound/inventory.js +147 -147
  55. package/src/protocol/outbound/ship-management.d.ts +84 -84
  56. package/src/protocol/outbound/ship-management.js +221 -221
  57. package/src/protocol/outbound/sign.d.ts +18 -18
  58. package/src/protocol/outbound/sign.js +45 -45
  59. package/src/protocol/outbound/ui-config.d.ts +157 -157
  60. package/src/protocol/outbound/ui-config.js +578 -578
  61. package/src/runtime.js +36 -36
  62. package/src/state/generator-maze.d.ts +32 -32
  63. package/src/state/generator-maze.js +370 -370
  64. package/src/state/index.d.ts +3 -3
  65. package/src/state/index.js +3 -3
  66. package/src/state/items.js +20 -20
  67. package/src/state/model/decoder.js +1554 -1554
  68. package/src/state/model/index.d.ts +33 -33
  69. package/src/state/model/index.js +2 -2
  70. package/src/state/model/loader-config.js +1020 -1020
  71. package/src/state/model/reader.js +69 -69
  72. package/src/state/model/state.js +1257 -1257
  73. package/src/state/overworld.js +72 -72
  74. package/src/state/tilesets.js +53 -53
  75. package/src/state/world/index.d.ts +29 -29
  76. package/src/state/world/index.js +180 -180
  77. package/src/state/world/state.js +297 -297
@@ -1,85 +1,85 @@
1
- import {DEFAULT_BASE_URL} from "../constants.js";
2
- import {hostName, normalizeBaseUrl} from "../runtime.js";
3
-
4
- export function cookiePrefix(baseUrl = DEFAULT_BASE_URL) {
5
- const host = hostName(baseUrl);
6
- if (host === "test.drednot.io") return "test_";
7
- if (host === "local.drednot.io") return "local_";
8
- return "";
9
- }
10
-
11
- export const cookieName = (baseUrl, name) => `${cookiePrefix(baseUrl)}${name}`;
12
-
13
- export function parseCookies(text = "") {
14
- const cookies = new Map();
15
- for (const part of String(text).split(/;\s*/)) {
16
- const index = part.indexOf("=");
17
- if (index <= 0) continue;
18
- cookies.set(part.slice(0, index).trim(), decodeURIComponent(part.slice(index + 1).trim()));
19
- }
20
- return cookies;
21
- }
22
-
23
- export function browserCookies() {
24
- return canReadDocumentCookie() ? parseCookies(document.cookie || "") : new Map();
25
- }
26
-
27
- export function canReadDocumentCookie() {
28
- try {
29
- return typeof document !== "undefined" && typeof document.cookie === "string";
30
- } catch (_) {
31
- return false;
32
- }
33
- }
34
-
35
- export function hasCookieStore() {
36
- return typeof globalThis.cookieStore !== "undefined" && typeof globalThis.cookieStore.getAll === "function";
37
- }
38
-
39
- export async function readBrowserCookie(name) {
40
- if (hasCookieStore()) {
41
- try {
42
- const cookie = typeof globalThis.cookieStore.get === "function" ? await globalThis.cookieStore.get(name) : null;
43
- if (cookie?.value != null) return cookie.value;
44
- } catch (_) {
45
- // Fall through to document.cookie below.
46
- }
47
- }
48
- return browserCookies().get(name) || "";
49
- }
50
-
51
- export function setCookieValues(baseUrl, source = {}) {
52
- const base = normalizeBaseUrl(baseUrl);
53
- const values = source instanceof Map ? source : source?.cookies instanceof Map ? source.cookies : Object.entries(source || {});
54
- const cookies = new Map(values);
55
- const prefix = cookiePrefix(base);
56
- const anonKey = source.anonKey || source.anon_key;
57
- const gameSession = source.gameSession || source.game_session;
58
- const noticeVersion = source.noticeVersion || source.notice_version;
59
- if (anonKey && !cookies.has(`${prefix}anon_key`)) cookies.set(`${prefix}anon_key`, anonKey);
60
- if (gameSession && !cookies.has(`${prefix}game_session`)) cookies.set(`${prefix}game_session`, gameSession);
61
- if (noticeVersion && !cookies.has(`${prefix}notice_version`)) cookies.set(`${prefix}notice_version`, noticeVersion);
62
- return cookies;
63
- }
64
-
65
- export function cookieHeader(baseUrl, source = {}) {
66
- return [...setCookieValues(baseUrl, source)].map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join("; ");
67
- }
68
-
69
- export function readSetCookies(headers, names = ["game_session", "anon_key"], baseUrl = DEFAULT_BASE_URL) {
70
- const values = typeof headers?.getSetCookie === "function"
71
- ? headers.getSetCookie()
72
- : headers?.get?.("set-cookie") ? [headers.get("set-cookie")] : [];
73
- const found = new Map();
74
- const prefix = cookiePrefix(baseUrl);
75
- for (const header of values) {
76
- for (const name of names) {
77
- for (const key of prefix ? [name, `${prefix}${name}`] : [name]) {
78
- const regex = new RegExp(`(?:^|,\\s*)${key}=([^;]+)`, "g");
79
- let match;
80
- while ((match = regex.exec(header))) found.set(key, decodeURIComponent(match[1]));
81
- }
82
- }
83
- }
84
- return found;
85
- }
1
+ import {DEFAULT_BASE_URL} from "../constants.js";
2
+ import {hostName, normalizeBaseUrl} from "../runtime.js";
3
+
4
+ export function cookiePrefix(baseUrl = DEFAULT_BASE_URL) {
5
+ const host = hostName(baseUrl);
6
+ if (host === "test.drednot.io") return "test_";
7
+ if (host === "local.drednot.io") return "local_";
8
+ return "";
9
+ }
10
+
11
+ export const cookieName = (baseUrl, name) => `${cookiePrefix(baseUrl)}${name}`;
12
+
13
+ export function parseCookies(text = "") {
14
+ const cookies = new Map();
15
+ for (const part of String(text).split(/;\s*/)) {
16
+ const index = part.indexOf("=");
17
+ if (index <= 0) continue;
18
+ cookies.set(part.slice(0, index).trim(), decodeURIComponent(part.slice(index + 1).trim()));
19
+ }
20
+ return cookies;
21
+ }
22
+
23
+ export function browserCookies() {
24
+ return canReadDocumentCookie() ? parseCookies(document.cookie || "") : new Map();
25
+ }
26
+
27
+ export function canReadDocumentCookie() {
28
+ try {
29
+ return typeof document !== "undefined" && typeof document.cookie === "string";
30
+ } catch (_) {
31
+ return false;
32
+ }
33
+ }
34
+
35
+ export function hasCookieStore() {
36
+ return typeof globalThis.cookieStore !== "undefined" && typeof globalThis.cookieStore.getAll === "function";
37
+ }
38
+
39
+ export async function readBrowserCookie(name) {
40
+ if (hasCookieStore()) {
41
+ try {
42
+ const cookie = typeof globalThis.cookieStore.get === "function" ? await globalThis.cookieStore.get(name) : null;
43
+ if (cookie?.value != null) return cookie.value;
44
+ } catch (_) {
45
+ // Fall through to document.cookie below.
46
+ }
47
+ }
48
+ return browserCookies().get(name) || "";
49
+ }
50
+
51
+ export function setCookieValues(baseUrl, source = {}) {
52
+ const base = normalizeBaseUrl(baseUrl);
53
+ const values = source instanceof Map ? source : source?.cookies instanceof Map ? source.cookies : Object.entries(source || {});
54
+ const cookies = new Map(values);
55
+ const prefix = cookiePrefix(base);
56
+ const anonKey = source.anonKey || source.anon_key;
57
+ const gameSession = source.gameSession || source.game_session;
58
+ const noticeVersion = source.noticeVersion || source.notice_version;
59
+ if (anonKey && !cookies.has(`${prefix}anon_key`)) cookies.set(`${prefix}anon_key`, anonKey);
60
+ if (gameSession && !cookies.has(`${prefix}game_session`)) cookies.set(`${prefix}game_session`, gameSession);
61
+ if (noticeVersion && !cookies.has(`${prefix}notice_version`)) cookies.set(`${prefix}notice_version`, noticeVersion);
62
+ return cookies;
63
+ }
64
+
65
+ export function cookieHeader(baseUrl, source = {}) {
66
+ return [...setCookieValues(baseUrl, source)].map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join("; ");
67
+ }
68
+
69
+ export function readSetCookies(headers, names = ["game_session", "anon_key"], baseUrl = DEFAULT_BASE_URL) {
70
+ const values = typeof headers?.getSetCookie === "function"
71
+ ? headers.getSetCookie()
72
+ : headers?.get?.("set-cookie") ? [headers.get("set-cookie")] : [];
73
+ const found = new Map();
74
+ const prefix = cookiePrefix(baseUrl);
75
+ for (const header of values) {
76
+ for (const name of names) {
77
+ for (const key of prefix ? [name, `${prefix}${name}`] : [name]) {
78
+ const regex = new RegExp(`(?:^|,\\s*)${key}=([^;]+)`, "g");
79
+ let match;
80
+ while ((match = regex.exec(header))) found.set(key, decodeURIComponent(match[1]));
81
+ }
82
+ }
83
+ }
84
+ return found;
85
+ }
@@ -1,34 +1,34 @@
1
- import {getFetch, isBrowser, normalizeBaseUrl, resolveUrl} from "../runtime.js";
2
- import {cookieHeader} from "./cookies.js";
3
-
4
- export class HttpClient {
5
- constructor({baseUrl, session = null} = {}) {
6
- this.baseUrl = normalizeBaseUrl(baseUrl);
7
- this.session = session;
8
- }
9
-
10
- async request(path, init = {}) {
11
- const headers = new Headers(init.headers || {});
12
- const body = this.#body(init.body, headers);
13
- const cookie = this.session && !isBrowser() ? cookieHeader(this.baseUrl, this.session) : "";
14
- if (cookie) headers.set("cookie", cookie);
15
- return getFetch()(resolveUrl(this.baseUrl, path), {
16
- ...init,
17
- body,
18
- headers,
19
- credentials: isBrowser() ? "include" : init.credentials
20
- });
21
- }
22
-
23
- async json(path, init = {}) {
24
- const response = await this.request(path, init);
25
- if (!response.ok) throw new Error(`${path} failed: ${response.status} ${response.statusText}`);
26
- return response.json();
27
- }
28
-
29
- #body(body, headers) {
30
- if (body == null || typeof body === "string" || body instanceof ArrayBuffer || ArrayBuffer.isView(body)) return body;
31
- if (!headers.has("content-type")) headers.set("content-type", "application/json");
32
- return JSON.stringify(body);
33
- }
34
- }
1
+ import {getFetch, isBrowser, normalizeBaseUrl, resolveUrl} from "../runtime.js";
2
+ import {cookieHeader} from "./cookies.js";
3
+
4
+ export class HttpClient {
5
+ constructor({baseUrl, session = null} = {}) {
6
+ this.baseUrl = normalizeBaseUrl(baseUrl);
7
+ this.session = session;
8
+ }
9
+
10
+ async request(path, init = {}) {
11
+ const headers = new Headers(init.headers || {});
12
+ const body = this.#body(init.body, headers);
13
+ const cookie = this.session && !isBrowser() ? cookieHeader(this.baseUrl, this.session) : "";
14
+ if (cookie) headers.set("cookie", cookie);
15
+ return getFetch()(resolveUrl(this.baseUrl, path), {
16
+ ...init,
17
+ body,
18
+ headers,
19
+ credentials: isBrowser() ? "include" : init.credentials
20
+ });
21
+ }
22
+
23
+ async json(path, init = {}) {
24
+ const response = await this.request(path, init);
25
+ if (!response.ok) throw new Error(`${path} failed: ${response.status} ${response.statusText}`);
26
+ return response.json();
27
+ }
28
+
29
+ #body(body, headers) {
30
+ if (body == null || typeof body === "string" || body instanceof ArrayBuffer || ArrayBuffer.isView(body)) return body;
31
+ if (!headers.has("content-type")) headers.set("content-type", "application/json");
32
+ return JSON.stringify(body);
33
+ }
34
+ }
@@ -1,4 +1,4 @@
1
- export * from "./connection.js";
2
- export * from "./servers.js";
3
- export * from "./ships.js";
4
- export * from "./session.js";
1
+ export * from "./connection.js";
2
+ export * from "./servers.js";
3
+ export * from "./ships.js";
4
+ export * from "./session.js";
@@ -1,4 +1,4 @@
1
- export {Connection} from "./connection.js";
2
- export {fetchGameVersion, fetchNoticeVersion, fetchServers, resolveServer} from "./servers.js";
3
- export {fetchShips, fetchShipList, createShipSpec, createInviteShipSpec, shipRef} from "./ships.js";
4
- export {Session, AnonSession, createSession, createAnonSession, createAnonToken} from "./session.js";
1
+ export {Connection} from "./connection.js";
2
+ export {fetchGameVersion, fetchNoticeVersion, fetchServers, resolveServer} from "./servers.js";
3
+ export {fetchShips, fetchShipList, createShipSpec, createInviteShipSpec, shipRef} from "./ships.js";
4
+ export {Session, AnonSession, createSession, createAnonSession, createAnonToken} from "./session.js";
@@ -1,7 +1,7 @@
1
- export {
2
- fetchNoticeVersion,
3
- fetchGameVersion,
4
- fetchServers,
5
- type Server,
6
- type ServerRef
7
- } from "../index.js";
1
+ export {
2
+ fetchNoticeVersion,
3
+ fetchGameVersion,
4
+ fetchServers,
5
+ type Server,
6
+ type ServerRef
7
+ } from "../index.js";
@@ -1,133 +1,133 @@
1
- import {DEFAULT_BASE_URL} from "../constants.js";
2
- import {hostName, normalizeBaseUrl} from "../runtime.js";
3
- import {HttpClient} from "./http.js";
4
-
5
- const cache = new Map();
6
-
7
- class ServerDirectory {
8
- constructor(baseUrl = DEFAULT_BASE_URL) {
9
- this.baseUrl = normalizeBaseUrl(baseUrl);
10
- this.meta = null;
11
- }
12
-
13
- async load() {
14
- if (cache.has(this.baseUrl)) {
15
- this.meta = await cache.get(this.baseUrl);
16
- return this;
17
- }
18
- const promise = this.#fetchMeta();
19
- cache.set(this.baseUrl, promise);
20
- this.meta = await promise;
21
- return this;
22
- }
23
-
24
- async version() {
25
- await this.load();
26
- if (!this.meta.version) throw new Error("Unable to locate GAME_VERSION in drednot bundle");
27
- return this.meta.version;
28
- }
29
-
30
- async list() {
31
- return this.servers();
32
- }
33
-
34
- async servers() {
35
- await this.load();
36
- if (!this.meta.serverInfo) throw new Error("Unable to locate server list in drednot bundle");
37
- return this.meta.serverInfo.servers;
38
- }
39
-
40
- async get(id = null) {
41
- return this.pick(id);
42
- }
43
-
44
- async pick(id = null) {
45
- const servers = await this.servers();
46
- return servers.find((server) => server.index === Number(id)) || servers[0] || null;
47
- }
48
-
49
- async #fetchMeta() {
50
- const response = await new HttpClient({baseUrl: this.baseUrl}).request("index.html");
51
- if (!response.ok) throw new Error(`Failed to fetch bundle: ${response.status} ${response.statusText}`);
52
- const text = await response.text();
53
- return {text, version: parseGameVersion(text), serverInfo: parseServerInfo(text, this.baseUrl)};
54
- }
55
- }
56
-
57
- export const fetchGameVersion = (baseUrl = DEFAULT_BASE_URL) => new ServerDirectory(baseUrl).version();
58
- export const fetchServers = (baseUrl = DEFAULT_BASE_URL) => new ServerDirectory(baseUrl).servers();
59
-
60
- export async function fetchNoticeVersion(baseUrl = DEFAULT_BASE_URL) {
61
- const response = await new HttpClient({baseUrl}).request("index.html");
62
- if (!response.ok) throw new Error(`Failed to fetch notice version: ${response.status} ${response.statusText}`);
63
- const text = await response.text();
64
- const version = parseNoticeVersion(text);
65
- if (version == null) throw new Error("Unable to locate notice version in drednot page");
66
- return version;
67
- }
68
-
69
- export async function resolveServer(server, baseUrl = DEFAULT_BASE_URL) {
70
- if (server && typeof server === "object") return server;
71
- const id = Number(server);
72
- const servers = await fetchServers(baseUrl);
73
- return servers.find((item) => item.index === id) || null;
74
- }
75
-
76
- export function serverId(server) {
77
- if (server && typeof server === "object") return Number(server.index ?? server.id);
78
- return Number(server);
79
- }
80
-
81
- function parseGameVersion(text) {
82
- return text.match(/Object\.defineProperty\(exports,"GAME_VERSION",\{enumerable:true,get:\(\)=>e\}\);const e="([^"]+)"/)?.[1] || null;
83
- }
84
-
85
- function parseNoticeVersion(text) {
86
- const moduleMatch = text.match(/Object\.defineProperty\(exports,"checkNotice"[\s\S]{0,8000}?setCookie\)\("notice_version",([A-Za-z_$][\w$]*)\)/);
87
- if (moduleMatch) {
88
- const constant = moduleMatch[1];
89
- const prefix = text.slice(Math.max(0, moduleMatch.index - 1000), moduleMatch.index + moduleMatch[0].length);
90
- const constantMatch = prefix.match(new RegExp(`const\\s+${constant}\\s*=\\s*(\\d+)\\s*;`));
91
- if (constantMatch) return Number(constantMatch[1]);
92
- }
93
-
94
- const patterns = [
95
- /notice_version["']?\s*[:=]\s*["']?(\d+)/i,
96
- /noticeVersion["']?\s*[:=]\s*["']?(\d+)/i,
97
- /NOTICE_VERSION["']?\s*[:=]\s*["']?(\d+)/,
98
- /notice[^0-9]{0,40}version[^0-9]{0,20}(\d+)/i
99
- ];
100
- for (const pattern of patterns) {
101
- const match = text.match(pattern);
102
- if (match) return Number(match[1]);
103
- }
104
- return null;
105
- }
106
-
107
- function parseServerInfo(text, baseUrl) {
108
- const host = hostName(baseUrl);
109
- const match = text.match(/const n=(true|false);const \$="([^"]+)";const o="([^"]+)";const T="([^"]+)";const t="([^"]+)";const S=\[([^\]]+)\];const c=\[([^\]]+)\];const A="([^"]+)";const I="([^"]+)"/s);
110
- if (!match) return null;
111
- const [localDomain, baseDomain, testDomain, testGameDomain] = match.slice(2, 6);
112
- const domains = [...match[6].matchAll(/"((?:[^"\\]|\\.)*)"/g)].map((m) => m[1]);
113
- const names = [...match[7].matchAll(/"((?:[^"\\]|\\.)*)"/g)].map((m) => m[1]);
114
- const meta = {
115
- localDomain,
116
- baseDomain,
117
- testDomain,
118
- testGameDomain,
119
- masterDomain: match[8],
120
- testMasterDomain: match[9]
121
- };
122
- if (host === localDomain) return {mode: "local", servers: [server(0, localDomain, "Local Test 1")], meta};
123
- if (host === testDomain) return {mode: "test", servers: [server(0, testGameDomain, "Public Test")], meta};
124
- return {
125
- mode: "production",
126
- servers: domains.map((domain, index) => server(index, domain, names[index] || `Server ${index + 1}`)),
127
- meta
128
- };
129
- }
130
-
131
- function server(index, domain, description) {
132
- return {index, domain, description, playerCount: 0, maxPlayerCount: 0, ping: null};
133
- }
1
+ import {DEFAULT_BASE_URL} from "../constants.js";
2
+ import {hostName, normalizeBaseUrl} from "../runtime.js";
3
+ import {HttpClient} from "./http.js";
4
+
5
+ const cache = new Map();
6
+
7
+ class ServerDirectory {
8
+ constructor(baseUrl = DEFAULT_BASE_URL) {
9
+ this.baseUrl = normalizeBaseUrl(baseUrl);
10
+ this.meta = null;
11
+ }
12
+
13
+ async load() {
14
+ if (cache.has(this.baseUrl)) {
15
+ this.meta = await cache.get(this.baseUrl);
16
+ return this;
17
+ }
18
+ const promise = this.#fetchMeta();
19
+ cache.set(this.baseUrl, promise);
20
+ this.meta = await promise;
21
+ return this;
22
+ }
23
+
24
+ async version() {
25
+ await this.load();
26
+ if (!this.meta.version) throw new Error("Unable to locate GAME_VERSION in drednot bundle");
27
+ return this.meta.version;
28
+ }
29
+
30
+ async list() {
31
+ return this.servers();
32
+ }
33
+
34
+ async servers() {
35
+ await this.load();
36
+ if (!this.meta.serverInfo) throw new Error("Unable to locate server list in drednot bundle");
37
+ return this.meta.serverInfo.servers;
38
+ }
39
+
40
+ async get(id = null) {
41
+ return this.pick(id);
42
+ }
43
+
44
+ async pick(id = null) {
45
+ const servers = await this.servers();
46
+ return servers.find((server) => server.index === Number(id)) || servers[0] || null;
47
+ }
48
+
49
+ async #fetchMeta() {
50
+ const response = await new HttpClient({baseUrl: this.baseUrl}).request("index.html");
51
+ if (!response.ok) throw new Error(`Failed to fetch bundle: ${response.status} ${response.statusText}`);
52
+ const text = await response.text();
53
+ return {text, version: parseGameVersion(text), serverInfo: parseServerInfo(text, this.baseUrl)};
54
+ }
55
+ }
56
+
57
+ export const fetchGameVersion = (baseUrl = DEFAULT_BASE_URL) => new ServerDirectory(baseUrl).version();
58
+ export const fetchServers = (baseUrl = DEFAULT_BASE_URL) => new ServerDirectory(baseUrl).servers();
59
+
60
+ export async function fetchNoticeVersion(baseUrl = DEFAULT_BASE_URL) {
61
+ const response = await new HttpClient({baseUrl}).request("index.html");
62
+ if (!response.ok) throw new Error(`Failed to fetch notice version: ${response.status} ${response.statusText}`);
63
+ const text = await response.text();
64
+ const version = parseNoticeVersion(text);
65
+ if (version == null) throw new Error("Unable to locate notice version in drednot page");
66
+ return version;
67
+ }
68
+
69
+ export async function resolveServer(server, baseUrl = DEFAULT_BASE_URL) {
70
+ if (server && typeof server === "object") return server;
71
+ const id = Number(server);
72
+ const servers = await fetchServers(baseUrl);
73
+ return servers.find((item) => item.index === id) || null;
74
+ }
75
+
76
+ export function serverId(server) {
77
+ if (server && typeof server === "object") return Number(server.index ?? server.id);
78
+ return Number(server);
79
+ }
80
+
81
+ function parseGameVersion(text) {
82
+ return text.match(/Object\.defineProperty\(exports,"GAME_VERSION",\{enumerable:true,get:\(\)=>e\}\);const e="([^"]+)"/)?.[1] || null;
83
+ }
84
+
85
+ function parseNoticeVersion(text) {
86
+ const moduleMatch = text.match(/Object\.defineProperty\(exports,"checkNotice"[\s\S]{0,8000}?setCookie\)\("notice_version",([A-Za-z_$][\w$]*)\)/);
87
+ if (moduleMatch) {
88
+ const constant = moduleMatch[1];
89
+ const prefix = text.slice(Math.max(0, moduleMatch.index - 1000), moduleMatch.index + moduleMatch[0].length);
90
+ const constantMatch = prefix.match(new RegExp(`const\\s+${constant}\\s*=\\s*(\\d+)\\s*;`));
91
+ if (constantMatch) return Number(constantMatch[1]);
92
+ }
93
+
94
+ const patterns = [
95
+ /notice_version["']?\s*[:=]\s*["']?(\d+)/i,
96
+ /noticeVersion["']?\s*[:=]\s*["']?(\d+)/i,
97
+ /NOTICE_VERSION["']?\s*[:=]\s*["']?(\d+)/,
98
+ /notice[^0-9]{0,40}version[^0-9]{0,20}(\d+)/i
99
+ ];
100
+ for (const pattern of patterns) {
101
+ const match = text.match(pattern);
102
+ if (match) return Number(match[1]);
103
+ }
104
+ return null;
105
+ }
106
+
107
+ function parseServerInfo(text, baseUrl) {
108
+ const host = hostName(baseUrl);
109
+ const match = text.match(/const n=(true|false);const \$="([^"]+)";const o="([^"]+)";const T="([^"]+)";const t="([^"]+)";const S=\[([^\]]+)\];const c=\[([^\]]+)\];const A="([^"]+)";const I="([^"]+)"/s);
110
+ if (!match) return null;
111
+ const [localDomain, baseDomain, testDomain, testGameDomain] = match.slice(2, 6);
112
+ const domains = [...match[6].matchAll(/"((?:[^"\\]|\\.)*)"/g)].map((m) => m[1]);
113
+ const names = [...match[7].matchAll(/"((?:[^"\\]|\\.)*)"/g)].map((m) => m[1]);
114
+ const meta = {
115
+ localDomain,
116
+ baseDomain,
117
+ testDomain,
118
+ testGameDomain,
119
+ masterDomain: match[8],
120
+ testMasterDomain: match[9]
121
+ };
122
+ if (host === localDomain) return {mode: "local", servers: [server(0, localDomain, "Local Test 1")], meta};
123
+ if (host === testDomain) return {mode: "test", servers: [server(0, testGameDomain, "Public Test")], meta};
124
+ return {
125
+ mode: "production",
126
+ servers: domains.map((domain, index) => server(index, domain, names[index] || `Server ${index + 1}`)),
127
+ meta
128
+ };
129
+ }
130
+
131
+ function server(index, domain, description) {
132
+ return {index, domain, description, playerCount: 0, maxPlayerCount: 0, ping: null};
133
+ }
@@ -1,7 +1,7 @@
1
- export {
2
- Session,
3
- AnonSession,
4
- createSession,
5
- createAnonSession,
6
- createAnonToken
7
- } from "../index.js";
1
+ export {
2
+ Session,
3
+ AnonSession,
4
+ createSession,
5
+ createAnonSession,
6
+ createAnonToken
7
+ } from "../index.js";