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,291 +1,291 @@
1
- import {DEFAULT_BASE_URL, DEFAULT_NOTICE_VERSION} from "../constants.js";
2
- import {normalizeBaseUrl} from "../runtime.js";
3
- import {browserCookies, cookieName, readBrowserCookie} from "./cookies.js";
4
- import {fetchGameVersion, fetchNoticeVersion, resolveServer, serverId} from "./servers.js";
5
- import {
6
- createInviteShipSpec,
7
- createShipSpec,
8
- fetchShipList,
9
- fetchShips as fetchSessionShips,
10
- shipRef
11
- } from "./ships.js";
12
- import {Connection} from "./connection.js";
13
- import {DredlessClient} from "../client/index.js";
14
- import {Session} from "./session.js";
15
-
16
- export class BrowserSession extends Session {
17
- constructor(baseUrl = DEFAULT_BASE_URL) {
18
- super(null, null, baseUrl);
19
- this.baseUrl = normalizeBaseUrl(baseUrl);
20
- this.ambientAuth = true;
21
- }
22
-
23
- get gameSession() {
24
- return browserCookies().get(cookieName(this.baseUrl, "game_session")) || "";
25
- }
26
-
27
- get gameToken() {
28
- return browserCookies().get(cookieName(this.baseUrl, "game_token")) || "";
29
- }
30
-
31
- get anonKey() {
32
- return this._anonKey || browserCookies().get(cookieName(this.baseUrl, "anon_key")) || "";
33
- }
34
-
35
- async readAnonKey() {
36
- const key = await readBrowserCookie(cookieName(this.baseUrl, "anon_key"));
37
- if (key) this._anonKey = key;
38
- return key || "";
39
- }
40
-
41
- async fetchAnonKey(noticeVersion = null) {
42
- this.noticeVersion = await browserNoticeVersion(noticeVersion, this.baseUrl);
43
- await createAnonLogin(this);
44
- const key = await this.readAnonKey();
45
- if (!key) throw new Error("Unable to read anon_key after anon login. Browser support is tested in page and content-script contexts; background, popup, worker, and other non-page contexts are unlikely to expose drednot.io cookies.");
46
- return key;
47
- }
48
-
49
- get noticeVersion() {
50
- return this._noticeVersion ?? browserCookies().get(cookieName(this.baseUrl, "notice_version")) ?? null;
51
- }
52
-
53
- set noticeVersion(value) {
54
- this._noticeVersion = value == null ? null : Number(value);
55
- if (typeof document === "undefined" || value == null) return;
56
- document.cookie = `${cookieName(this.baseUrl, "notice_version")}=${encodeURIComponent(String(value))}; path=/; SameSite=Lax`;
57
- }
58
-
59
- mergeSetCookies() {
60
- // Browsers own the cookie jar. Set-Cookie is intentionally not readable.
61
- }
62
-
63
- async joinShipConnection(server, ship = null) {
64
- return this.#joinBrowserConnection(server, ship, true);
65
- }
66
-
67
- async startShipConnection(server, ship = null) {
68
- return this.#joinBrowserConnection(server, ship, false);
69
- }
70
-
71
- async startNewShipConnection(server, name = "", color = "") {
72
- return this.#joinBrowserConnection(server, createShipSpec(name, color), false);
73
- }
74
-
75
- async joinInviteConnection(server, code) {
76
- return this.#joinBrowserConnection(server, createInviteShipSpec(code), false);
77
- }
78
-
79
- async joinShip(server, ship = null) {
80
- return readyBrowserClient(await this.joinShipConnection(server, ship));
81
- }
82
-
83
- async startShip(server, ship = null) {
84
- return readyBrowserClient(await this.startShipConnection(server, ship));
85
- }
86
-
87
- async startNewShip(server, name = "", color = "") {
88
- return readyBrowserClient(await this.startNewShipConnection(server, name, color));
89
- }
90
-
91
- async joinInvite(server, code) {
92
- return readyBrowserClient(await this.joinInviteConnection(server, code));
93
- }
94
-
95
- async #joinBrowserConnection(server, ship, neverLoad) {
96
- if (server == null) throw new Error("A server id or server object is required");
97
- const resolvedServer = await resolveServer(server, this.baseUrl);
98
- if (!resolvedServer) throw new Error(`Unable to resolve server ${serverId(server)}`);
99
- if (!this.gameVersion) this.gameVersion = await fetchGameVersion(this.baseUrl);
100
- if (this.noticeVersion == null) this.noticeVersion = DEFAULT_NOTICE_VERSION;
101
-
102
- const joinShip = ship == null ? createShipSpec("", "") : shipRef(ship);
103
- const response = await this.request("join", {
104
- method: "POST",
105
- mode: "cors",
106
- credentials: "include",
107
- referrer: `${this.baseUrl}/`,
108
- body: {
109
- join_info: {
110
- game_version: this.gameVersion,
111
- hide_badges: false,
112
- never_load: Boolean(neverLoad),
113
- server_id: resolvedServer.index,
114
- ship: joinShip
115
- }
116
- },
117
- headers: browserJoinHeaders(this.baseUrl)
118
- });
119
- if (!response.ok) throw new Error(`Join request failed: ${await response.text()}`);
120
- const join = await response.json();
121
- if (join.reject != null) {
122
- const error = new Error(joinRejectMessage(join.reject, {
123
- neverLoad,
124
- ship: joinShip,
125
- server: resolvedServer
126
- }));
127
- error.code = join.reject;
128
- error.join = join;
129
- throw error;
130
- }
131
- if (join.okay !== true) throw new Error("Bad join result");
132
-
133
- const token = join.game_token ?? join.gameToken ?? this.gameToken;
134
- return new Connection(this, token || "", join.net_port, Number.isInteger(join.server_id) ? join.server_id : resolvedServer.index, resolvedServer);
135
- }
136
-
137
- toJSON() {
138
- return {
139
- ...super.toJSON(),
140
- ambientAuth: true,
141
- cookies: Object.fromEntries(browserCookies())
142
- };
143
- }
144
- }
145
-
146
- let defaultBrowserSession = null;
147
-
148
- export function browserSession(baseUrl = DEFAULT_BASE_URL) {
149
- const normalized = normalizeBaseUrl(baseUrl);
150
- if (!defaultBrowserSession || defaultBrowserSession.baseUrl !== normalized) defaultBrowserSession = new BrowserSession(normalized);
151
- return defaultBrowserSession;
152
- }
153
-
154
- export function setBrowserSession(session = null) {
155
- defaultBrowserSession = session;
156
- return defaultBrowserSession;
157
- }
158
-
159
- export const createBrowserSession = browserSession;
160
-
161
- export async function createSession(noticeVersion = null, baseUrl = DEFAULT_BASE_URL) {
162
- const resolvedBaseUrl = normalizeBaseUrl(arguments.length >= 2 ? arguments[1] : baseUrl);
163
- const session = browserSession(resolvedBaseUrl);
164
- session.noticeVersion = await browserNoticeVersion(noticeVersion, resolvedBaseUrl);
165
- await session.fetchAccountStatus();
166
- return session;
167
- }
168
-
169
- export async function createAnonSession(anonKey = null, noticeVersion = null, baseUrl = DEFAULT_BASE_URL) {
170
- if (typeof noticeVersion === "string" && noticeVersion.includes("://") && (baseUrl == null || baseUrl === DEFAULT_BASE_URL)) {
171
- baseUrl = noticeVersion;
172
- noticeVersion = null;
173
- }
174
- const resolvedBaseUrl = normalizeBaseUrl(arguments.length >= 3 ? arguments[2] : baseUrl);
175
- const session = browserSession(resolvedBaseUrl);
176
- session.noticeVersion = await browserNoticeVersion(noticeVersion, resolvedBaseUrl);
177
- if (anonKey) {
178
- session._anonKey = String(anonKey);
179
- await setAmbientCookie(resolvedBaseUrl, "anon_key", anonKey);
180
- } else {
181
- await session.fetchAnonKey(session.noticeVersion);
182
- }
183
- await session.fetchAccountStatus();
184
- return session;
185
- }
186
-
187
- export async function fetchAnonKey(noticeVersion = null, baseUrl = DEFAULT_BASE_URL) {
188
- const resolvedBaseUrl = normalizeBaseUrl(arguments.length >= 2 ? arguments[1] : baseUrl);
189
- return browserSession(resolvedBaseUrl).fetchAnonKey(noticeVersion);
190
- }
191
-
192
- export const createAnonToken = fetchAnonKey;
193
-
194
- export async function fetchAccountStatus(session = null) {
195
- return (session || browserSession()).fetchAccountStatus();
196
- }
197
-
198
- export async function fetchShips(server, session = null) {
199
- return fetchSessionShips(session || browserSession(), server);
200
- }
201
-
202
- export async function fetchShipListForBrowser(server, session = null) {
203
- return fetchShipList(session || browserSession(), server);
204
- }
205
-
206
- export async function joinShip(server, ship = null, session = null) {
207
- return (session || browserSession()).joinShip(server, ship);
208
- }
209
-
210
- export async function startShip(server, ship = null, session = null) {
211
- return (session || browserSession()).startShip(server, ship);
212
- }
213
-
214
- export async function startNewShip(server, name = "", color = "", session = null) {
215
- return (session || browserSession()).startNewShip(server, name, color);
216
- }
217
-
218
- export async function joinInvite(server, code, session = null) {
219
- return (session || browserSession()).joinInvite(server, code);
220
- }
221
-
222
- async function readyBrowserClient(connection) {
223
- const client = new DredlessClient(connection);
224
- await client.whenReady();
225
- return client;
226
- }
227
-
228
- async function createAnonLogin(session) {
229
- const response = await session.request("account/login/anon", {
230
- method: "POST",
231
- mode: "cors",
232
- credentials: "include",
233
- referrer: `${session.baseUrl}/`,
234
- headers: browserAnonHeaders(session.baseUrl)
235
- });
236
- if (response.status === 503) throw new Error("Anon session creation is rate limited by the server");
237
- if (!response.ok) throw new Error(`account/login/anon failed: ${response.status} ${response.statusText}`);
238
- session.mergeSetCookies(response, ["anon_key", "game_session"]);
239
- }
240
-
241
- async function browserNoticeVersion(value, baseUrl = DEFAULT_BASE_URL) {
242
- if (value != null) return value;
243
- try {
244
- return await fetchNoticeVersion(baseUrl);
245
- } catch (_) {
246
- return DEFAULT_NOTICE_VERSION;
247
- }
248
- }
249
-
250
- async function setAmbientCookie(baseUrl, name, value) {
251
- const key = cookieName(baseUrl, name);
252
- if (typeof globalThis.cookieStore !== "undefined" && typeof globalThis.cookieStore.set === "function") {
253
- try {
254
- await globalThis.cookieStore.set(key, String(value));
255
- return;
256
- } catch (_) {
257
- // Fall through to document.cookie.
258
- }
259
- }
260
- if (typeof document === "undefined") return;
261
- document.cookie = `${key}=${encodeURIComponent(String(value))}; path=/; SameSite=Lax`;
262
- }
263
-
264
- function browserAnonHeaders(baseUrl) {
265
- const origin = normalizeBaseUrl(baseUrl);
266
- return {
267
- accept: "*/*",
268
- origin,
269
- referer: `${origin}/`
270
- };
271
- }
272
-
273
- function browserJoinHeaders(baseUrl) {
274
- const origin = normalizeBaseUrl(baseUrl);
275
- return {
276
- accept: "*/*",
277
- "content-type": "application/json",
278
- origin,
279
- referer: `${origin}/`
280
- };
281
- }
282
-
283
- function joinRejectMessage(code, {neverLoad, ship, server} = {}) {
284
- if (code === 4007 && neverLoad) {
285
- const name = ship?.name ? ` "${ship.name}"` : "";
286
- const id = ship?.id != null ? ` (${ship.id})` : "";
287
- const serverText = server?.description ? ` on ${server.description}` : "";
288
- return `join rejected: 4007. ${name}${id}${serverText} could not be joined with never_load=true. Use startShip(server, ship) instead of joinShip(server, ship) when loading or starting a saved ship.`;
289
- }
290
- return `join rejected: ${code}`;
291
- }
1
+ import {DEFAULT_BASE_URL, DEFAULT_NOTICE_VERSION} from "../constants.js";
2
+ import {normalizeBaseUrl} from "../runtime.js";
3
+ import {browserCookies, cookieName, readBrowserCookie} from "./cookies.js";
4
+ import {fetchGameVersion, fetchNoticeVersion, resolveServer, serverId} from "./servers.js";
5
+ import {
6
+ createInviteShipSpec,
7
+ createShipSpec,
8
+ fetchShipList,
9
+ fetchShips as fetchSessionShips,
10
+ shipRef
11
+ } from "./ships.js";
12
+ import {Connection} from "./connection.js";
13
+ import {DredlessClient} from "../client/index.js";
14
+ import {Session} from "./session.js";
15
+
16
+ export class BrowserSession extends Session {
17
+ constructor(baseUrl = DEFAULT_BASE_URL) {
18
+ super(null, null, baseUrl);
19
+ this.baseUrl = normalizeBaseUrl(baseUrl);
20
+ this.ambientAuth = true;
21
+ }
22
+
23
+ get gameSession() {
24
+ return browserCookies().get(cookieName(this.baseUrl, "game_session")) || "";
25
+ }
26
+
27
+ get gameToken() {
28
+ return browserCookies().get(cookieName(this.baseUrl, "game_token")) || "";
29
+ }
30
+
31
+ get anonKey() {
32
+ return this._anonKey || browserCookies().get(cookieName(this.baseUrl, "anon_key")) || "";
33
+ }
34
+
35
+ async readAnonKey() {
36
+ const key = await readBrowserCookie(cookieName(this.baseUrl, "anon_key"));
37
+ if (key) this._anonKey = key;
38
+ return key || "";
39
+ }
40
+
41
+ async fetchAnonKey(noticeVersion = null) {
42
+ this.noticeVersion = await browserNoticeVersion(noticeVersion, this.baseUrl);
43
+ await createAnonLogin(this);
44
+ const key = await this.readAnonKey();
45
+ if (!key) throw new Error("Unable to read anon_key after anon login. Browser support is tested in page and content-script contexts; background, popup, worker, and other non-page contexts are unlikely to expose drednot.io cookies.");
46
+ return key;
47
+ }
48
+
49
+ get noticeVersion() {
50
+ return this._noticeVersion ?? browserCookies().get(cookieName(this.baseUrl, "notice_version")) ?? null;
51
+ }
52
+
53
+ set noticeVersion(value) {
54
+ this._noticeVersion = value == null ? null : Number(value);
55
+ if (typeof document === "undefined" || value == null) return;
56
+ document.cookie = `${cookieName(this.baseUrl, "notice_version")}=${encodeURIComponent(String(value))}; path=/; SameSite=Lax`;
57
+ }
58
+
59
+ mergeSetCookies() {
60
+ // Browsers own the cookie jar. Set-Cookie is intentionally not readable.
61
+ }
62
+
63
+ async joinShipConnection(server, ship = null) {
64
+ return this.#joinBrowserConnection(server, ship, true);
65
+ }
66
+
67
+ async startShipConnection(server, ship = null) {
68
+ return this.#joinBrowserConnection(server, ship, false);
69
+ }
70
+
71
+ async startNewShipConnection(server, name = "", color = "") {
72
+ return this.#joinBrowserConnection(server, createShipSpec(name, color), false);
73
+ }
74
+
75
+ async joinInviteConnection(server, code) {
76
+ return this.#joinBrowserConnection(server, createInviteShipSpec(code), false);
77
+ }
78
+
79
+ async joinShip(server, ship = null) {
80
+ return readyBrowserClient(await this.joinShipConnection(server, ship));
81
+ }
82
+
83
+ async startShip(server, ship = null) {
84
+ return readyBrowserClient(await this.startShipConnection(server, ship));
85
+ }
86
+
87
+ async startNewShip(server, name = "", color = "") {
88
+ return readyBrowserClient(await this.startNewShipConnection(server, name, color));
89
+ }
90
+
91
+ async joinInvite(server, code) {
92
+ return readyBrowserClient(await this.joinInviteConnection(server, code));
93
+ }
94
+
95
+ async #joinBrowserConnection(server, ship, neverLoad) {
96
+ if (server == null) throw new Error("A server id or server object is required");
97
+ const resolvedServer = await resolveServer(server, this.baseUrl);
98
+ if (!resolvedServer) throw new Error(`Unable to resolve server ${serverId(server)}`);
99
+ if (!this.gameVersion) this.gameVersion = await fetchGameVersion(this.baseUrl);
100
+ if (this.noticeVersion == null) this.noticeVersion = DEFAULT_NOTICE_VERSION;
101
+
102
+ const joinShip = ship == null ? createShipSpec("", "") : shipRef(ship);
103
+ const response = await this.request("join", {
104
+ method: "POST",
105
+ mode: "cors",
106
+ credentials: "include",
107
+ referrer: `${this.baseUrl}/`,
108
+ body: {
109
+ join_info: {
110
+ game_version: this.gameVersion,
111
+ hide_badges: false,
112
+ never_load: Boolean(neverLoad),
113
+ server_id: resolvedServer.index,
114
+ ship: joinShip
115
+ }
116
+ },
117
+ headers: browserJoinHeaders(this.baseUrl)
118
+ });
119
+ if (!response.ok) throw new Error(`Join request failed: ${await response.text()}`);
120
+ const join = await response.json();
121
+ if (join.reject != null) {
122
+ const error = new Error(joinRejectMessage(join.reject, {
123
+ neverLoad,
124
+ ship: joinShip,
125
+ server: resolvedServer
126
+ }));
127
+ error.code = join.reject;
128
+ error.join = join;
129
+ throw error;
130
+ }
131
+ if (join.okay !== true) throw new Error("Bad join result");
132
+
133
+ const token = join.game_token ?? join.gameToken ?? this.gameToken;
134
+ return new Connection(this, token || "", join.net_port, Number.isInteger(join.server_id) ? join.server_id : resolvedServer.index, resolvedServer);
135
+ }
136
+
137
+ toJSON() {
138
+ return {
139
+ ...super.toJSON(),
140
+ ambientAuth: true,
141
+ cookies: Object.fromEntries(browserCookies())
142
+ };
143
+ }
144
+ }
145
+
146
+ let defaultBrowserSession = null;
147
+
148
+ export function browserSession(baseUrl = DEFAULT_BASE_URL) {
149
+ const normalized = normalizeBaseUrl(baseUrl);
150
+ if (!defaultBrowserSession || defaultBrowserSession.baseUrl !== normalized) defaultBrowserSession = new BrowserSession(normalized);
151
+ return defaultBrowserSession;
152
+ }
153
+
154
+ export function setBrowserSession(session = null) {
155
+ defaultBrowserSession = session;
156
+ return defaultBrowserSession;
157
+ }
158
+
159
+ export const createBrowserSession = browserSession;
160
+
161
+ export async function createSession(noticeVersion = null, baseUrl = DEFAULT_BASE_URL) {
162
+ const resolvedBaseUrl = normalizeBaseUrl(arguments.length >= 2 ? arguments[1] : baseUrl);
163
+ const session = browserSession(resolvedBaseUrl);
164
+ session.noticeVersion = await browserNoticeVersion(noticeVersion, resolvedBaseUrl);
165
+ await session.fetchAccountStatus();
166
+ return session;
167
+ }
168
+
169
+ export async function createAnonSession(anonKey = null, noticeVersion = null, baseUrl = DEFAULT_BASE_URL) {
170
+ if (typeof noticeVersion === "string" && noticeVersion.includes("://") && (baseUrl == null || baseUrl === DEFAULT_BASE_URL)) {
171
+ baseUrl = noticeVersion;
172
+ noticeVersion = null;
173
+ }
174
+ const resolvedBaseUrl = normalizeBaseUrl(arguments.length >= 3 ? arguments[2] : baseUrl);
175
+ const session = browserSession(resolvedBaseUrl);
176
+ session.noticeVersion = await browserNoticeVersion(noticeVersion, resolvedBaseUrl);
177
+ if (anonKey) {
178
+ session._anonKey = String(anonKey);
179
+ await setAmbientCookie(resolvedBaseUrl, "anon_key", anonKey);
180
+ } else {
181
+ await session.fetchAnonKey(session.noticeVersion);
182
+ }
183
+ await session.fetchAccountStatus();
184
+ return session;
185
+ }
186
+
187
+ export async function fetchAnonKey(noticeVersion = null, baseUrl = DEFAULT_BASE_URL) {
188
+ const resolvedBaseUrl = normalizeBaseUrl(arguments.length >= 2 ? arguments[1] : baseUrl);
189
+ return browserSession(resolvedBaseUrl).fetchAnonKey(noticeVersion);
190
+ }
191
+
192
+ export const createAnonToken = fetchAnonKey;
193
+
194
+ export async function fetchAccountStatus(session = null) {
195
+ return (session || browserSession()).fetchAccountStatus();
196
+ }
197
+
198
+ export async function fetchShips(server, session = null) {
199
+ return fetchSessionShips(session || browserSession(), server);
200
+ }
201
+
202
+ export async function fetchShipListForBrowser(server, session = null) {
203
+ return fetchShipList(session || browserSession(), server);
204
+ }
205
+
206
+ export async function joinShip(server, ship = null, session = null) {
207
+ return (session || browserSession()).joinShip(server, ship);
208
+ }
209
+
210
+ export async function startShip(server, ship = null, session = null) {
211
+ return (session || browserSession()).startShip(server, ship);
212
+ }
213
+
214
+ export async function startNewShip(server, name = "", color = "", session = null) {
215
+ return (session || browserSession()).startNewShip(server, name, color);
216
+ }
217
+
218
+ export async function joinInvite(server, code, session = null) {
219
+ return (session || browserSession()).joinInvite(server, code);
220
+ }
221
+
222
+ async function readyBrowserClient(connection) {
223
+ const client = new DredlessClient(connection);
224
+ await client.whenReady();
225
+ return client;
226
+ }
227
+
228
+ async function createAnonLogin(session) {
229
+ const response = await session.request("account/login/anon", {
230
+ method: "POST",
231
+ mode: "cors",
232
+ credentials: "include",
233
+ referrer: `${session.baseUrl}/`,
234
+ headers: browserAnonHeaders(session.baseUrl)
235
+ });
236
+ if (response.status === 503) throw new Error("Anon session creation is rate limited by the server");
237
+ if (!response.ok) throw new Error(`account/login/anon failed: ${response.status} ${response.statusText}`);
238
+ session.mergeSetCookies(response, ["anon_key", "game_session"]);
239
+ }
240
+
241
+ async function browserNoticeVersion(value, baseUrl = DEFAULT_BASE_URL) {
242
+ if (value != null) return value;
243
+ try {
244
+ return await fetchNoticeVersion(baseUrl);
245
+ } catch (_) {
246
+ return DEFAULT_NOTICE_VERSION;
247
+ }
248
+ }
249
+
250
+ async function setAmbientCookie(baseUrl, name, value) {
251
+ const key = cookieName(baseUrl, name);
252
+ if (typeof globalThis.cookieStore !== "undefined" && typeof globalThis.cookieStore.set === "function") {
253
+ try {
254
+ await globalThis.cookieStore.set(key, String(value));
255
+ return;
256
+ } catch (_) {
257
+ // Fall through to document.cookie.
258
+ }
259
+ }
260
+ if (typeof document === "undefined") return;
261
+ document.cookie = `${key}=${encodeURIComponent(String(value))}; path=/; SameSite=Lax`;
262
+ }
263
+
264
+ function browserAnonHeaders(baseUrl) {
265
+ const origin = normalizeBaseUrl(baseUrl);
266
+ return {
267
+ accept: "*/*",
268
+ origin,
269
+ referer: `${origin}/`
270
+ };
271
+ }
272
+
273
+ function browserJoinHeaders(baseUrl) {
274
+ const origin = normalizeBaseUrl(baseUrl);
275
+ return {
276
+ accept: "*/*",
277
+ "content-type": "application/json",
278
+ origin,
279
+ referer: `${origin}/`
280
+ };
281
+ }
282
+
283
+ function joinRejectMessage(code, {neverLoad, ship, server} = {}) {
284
+ if (code === 4007 && neverLoad) {
285
+ const name = ship?.name ? ` "${ship.name}"` : "";
286
+ const id = ship?.id != null ? ` (${ship.id})` : "";
287
+ const serverText = server?.description ? ` on ${server.description}` : "";
288
+ return `join rejected: 4007. ${name}${id}${serverText} could not be joined with never_load=true. Use startShip(server, ship) instead of joinShip(server, ship) when loading or starting a saved ship.`;
289
+ }
290
+ return `join rejected: ${code}`;
291
+ }
@@ -1 +1 @@
1
- export {Connection} from "../index.js";
1
+ export {Connection} from "../index.js";
@@ -1,31 +1,31 @@
1
- import {DEFAULT_BASE_URL} from "../constants.js";
2
- import {normalizeBaseUrl} from "../runtime.js";
3
- import {cookieName} from "./cookies.js";
4
-
5
- export class Connection {
6
- constructor(session, gameToken, netPort, serverId, server = null) {
7
- if (!session) throw new Error("Connection requires a session");
8
- if (!gameToken && !session.ambientAuth) throw new Error("Connection requires a game token");
9
- if (netPort == null) throw new Error("Connection requires a net port");
10
-
11
- this.session = session;
12
- this.baseUrl = normalizeBaseUrl(session.baseUrl || DEFAULT_BASE_URL);
13
- this.gameToken = gameToken ? String(gameToken) : "";
14
- this.netPort = Number(netPort);
15
- this.server = serverId && typeof serverId === "object" ? serverId : server;
16
- this.serverId = Number(serverId && typeof serverId === "object" ? serverId.index ?? serverId.id : serverId);
17
-
18
- this.session.cookies?.set(cookieName(this.baseUrl, "game_token"), this.gameToken);
19
- }
20
-
21
- toJSON() {
22
- return {
23
- baseUrl: this.baseUrl,
24
- gameToken: this.gameToken,
25
- netPort: this.netPort,
26
- serverId: this.serverId,
27
- server: this.server,
28
- session: this.session?.toJSON?.() || this.session
29
- };
30
- }
31
- }
1
+ import {DEFAULT_BASE_URL} from "../constants.js";
2
+ import {normalizeBaseUrl} from "../runtime.js";
3
+ import {cookieName} from "./cookies.js";
4
+
5
+ export class Connection {
6
+ constructor(session, gameToken, netPort, serverId, server = null) {
7
+ if (!session) throw new Error("Connection requires a session");
8
+ if (!gameToken && !session.ambientAuth) throw new Error("Connection requires a game token");
9
+ if (netPort == null) throw new Error("Connection requires a net port");
10
+
11
+ this.session = session;
12
+ this.baseUrl = normalizeBaseUrl(session.baseUrl || DEFAULT_BASE_URL);
13
+ this.gameToken = gameToken ? String(gameToken) : "";
14
+ this.netPort = Number(netPort);
15
+ this.server = serverId && typeof serverId === "object" ? serverId : server;
16
+ this.serverId = Number(serverId && typeof serverId === "object" ? serverId.index ?? serverId.id : serverId);
17
+
18
+ this.session.cookies?.set(cookieName(this.baseUrl, "game_token"), this.gameToken);
19
+ }
20
+
21
+ toJSON() {
22
+ return {
23
+ baseUrl: this.baseUrl,
24
+ gameToken: this.gameToken,
25
+ netPort: this.netPort,
26
+ serverId: this.serverId,
27
+ server: this.server,
28
+ session: this.session?.toJSON?.() || this.session
29
+ };
30
+ }
31
+ }