dredless 0.2.0 → 0.3.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 (80) hide show
  1. package/README.md +65 -48
  2. package/dist/browser/dredless.global.js +12047 -0
  3. package/dist/browser/dredless.global.js.map +7 -0
  4. package/docs/API_REFERENCE.md +2481 -2481
  5. package/docs/BROWSER_API.md +98 -98
  6. package/docs/NODE_API.md +359 -359
  7. package/package.json +40 -35
  8. package/src/browser-global.js +3 -0
  9. package/src/browser.d.ts +212 -212
  10. package/src/browser.js +133 -133
  11. package/src/client/core.js +1202 -1202
  12. package/src/client/domains/index.js +1818 -1818
  13. package/src/client/index.d.ts +2 -2
  14. package/src/client/index.js +1 -1
  15. package/src/compression/lz4.d.ts +1 -1
  16. package/src/compression/lz4.js +112 -112
  17. package/src/constants.js +74 -74
  18. package/src/crypto/chacha-native.d.ts +9 -9
  19. package/src/crypto/chacha-native.js +48 -48
  20. package/src/crypto/chacha.d.ts +25 -25
  21. package/src/crypto/chacha.js +274 -274
  22. package/src/events.js +39 -39
  23. package/src/index.d.ts +2277 -2277
  24. package/src/index.js +125 -125
  25. package/src/network/browser-session.js +291 -291
  26. package/src/network/connection.d.ts +1 -1
  27. package/src/network/connection.js +31 -31
  28. package/src/network/cookies.js +85 -85
  29. package/src/network/http.js +34 -34
  30. package/src/network/index.d.ts +4 -4
  31. package/src/network/index.js +4 -4
  32. package/src/network/servers.d.ts +7 -7
  33. package/src/network/servers.js +133 -133
  34. package/src/network/session.d.ts +7 -7
  35. package/src/network/session.js +320 -320
  36. package/src/network/ships.d.ts +12 -12
  37. package/src/network/ships.js +73 -73
  38. package/src/node.d.ts +2 -2
  39. package/src/node.js +8 -8
  40. package/src/protocol/codec/binary.d.ts +3 -3
  41. package/src/protocol/codec/binary.js +52 -52
  42. package/src/protocol/codec/msgpack.d.ts +3 -3
  43. package/src/protocol/codec/msgpack.js +555 -555
  44. package/src/protocol/inbound/frame.d.ts +1 -1
  45. package/src/protocol/inbound/frame.js +8 -8
  46. package/src/protocol/inbound/world-payload.d.ts +3 -3
  47. package/src/protocol/inbound/world-payload.js +21 -21
  48. package/src/protocol/index.d.ts +11 -11
  49. package/src/protocol/index.js +19 -19
  50. package/src/protocol/outbound/blueprint.d.ts +22 -22
  51. package/src/protocol/outbound/blueprint.js +36 -36
  52. package/src/protocol/outbound/commands.d.ts +3 -3
  53. package/src/protocol/outbound/commands.js +149 -149
  54. package/src/protocol/outbound/comms.d.ts +28 -28
  55. package/src/protocol/outbound/comms.js +40 -40
  56. package/src/protocol/outbound/inventory.d.ts +64 -64
  57. package/src/protocol/outbound/inventory.js +147 -147
  58. package/src/protocol/outbound/ship-management.d.ts +84 -84
  59. package/src/protocol/outbound/ship-management.js +221 -221
  60. package/src/protocol/outbound/sign.d.ts +18 -18
  61. package/src/protocol/outbound/sign.js +45 -45
  62. package/src/protocol/outbound/ui-config.d.ts +157 -157
  63. package/src/protocol/outbound/ui-config.js +578 -578
  64. package/src/runtime.js +36 -36
  65. package/src/state/generator-maze.d.ts +32 -32
  66. package/src/state/generator-maze.js +370 -370
  67. package/src/state/index.d.ts +3 -3
  68. package/src/state/index.js +3 -3
  69. package/src/state/items.js +20 -20
  70. package/src/state/model/decoder.js +1554 -1554
  71. package/src/state/model/index.d.ts +33 -33
  72. package/src/state/model/index.js +2 -2
  73. package/src/state/model/loader-config.js +1020 -1020
  74. package/src/state/model/reader.js +69 -69
  75. package/src/state/model/state.js +1257 -1257
  76. package/src/state/overworld.js +72 -72
  77. package/src/state/tilesets.js +53 -53
  78. package/src/state/world/index.d.ts +29 -29
  79. package/src/state/world/index.js +180 -180
  80. 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";