bc-deeplib 2.4.2 → 4.0.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.
package/dist/deeplib.js CHANGED
@@ -1,614 +1,4 @@
1
- var __create = Object.create;
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
8
- var __commonJS = (cb, mod) => function __require() {
9
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
- };
11
- var __copyProps = (to, from, except, desc) => {
12
- if (from && typeof from === "object" || typeof from === "function") {
13
- for (let key of __getOwnPropNames(from))
14
- if (!__hasOwnProp.call(to, key) && key !== except)
15
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
- }
17
- return to;
18
- };
19
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
- // If the importer is in node compatibility mode or this is not an ESM
21
- // file that has been converted to a CommonJS file using a Babel-
22
- // compatible transform (i.e. "__esModule" has not been set), then set
23
- // "default" to the CommonJS "module.exports" for node compatibility.
24
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
- mod
26
- ));
27
-
28
- // node_modules/.pnpm/bondage-club-mod-sdk@1.2.0/node_modules/bondage-club-mod-sdk/dist/bcmodsdk.js
29
- var require_bcmodsdk = __commonJS({
30
- "node_modules/.pnpm/bondage-club-mod-sdk@1.2.0/node_modules/bondage-club-mod-sdk/dist/bcmodsdk.js"(exports) {
31
- var bcModSdk = (function() {
32
- "use strict";
33
- const o = "1.2.0";
34
- function e(o2) {
35
- alert("Mod ERROR:\n" + o2);
36
- const e2 = new Error(o2);
37
- throw console.error(e2), e2;
38
- }
39
- __name(e, "e");
40
- const t = new TextEncoder();
41
- function n(o2) {
42
- return !!o2 && "object" == typeof o2 && !Array.isArray(o2);
43
- }
44
- __name(n, "n");
45
- function r(o2) {
46
- const e2 = /* @__PURE__ */ new Set();
47
- return o2.filter(((o3) => !e2.has(o3) && e2.add(o3)));
48
- }
49
- __name(r, "r");
50
- const i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Set();
51
- function c(o2) {
52
- a.has(o2) || (a.add(o2), console.warn(o2));
53
- }
54
- __name(c, "c");
55
- function s(o2) {
56
- const e2 = [], t2 = /* @__PURE__ */ new Map(), n2 = /* @__PURE__ */ new Set();
57
- for (const r3 of f.values()) {
58
- const i3 = r3.patching.get(o2.name);
59
- if (i3) {
60
- e2.push(...i3.hooks);
61
- for (const [e3, a2] of i3.patches.entries()) t2.has(e3) && t2.get(e3) !== a2 && c(`ModSDK: Mod '${r3.name}' is patching function ${o2.name} with same pattern that is already applied by different mod, but with different pattern:
62
- Pattern:
63
- ${e3}
64
- Patch1:
65
- ${t2.get(e3) || ""}
66
- Patch2:
67
- ${a2}`), t2.set(e3, a2), n2.add(r3.name);
68
- }
69
- }
70
- e2.sort(((o3, e3) => e3.priority - o3.priority));
71
- const r2 = (function(o3, e3) {
72
- if (0 === e3.size) return o3;
73
- let t3 = o3.toString().replaceAll("\r\n", "\n");
74
- for (const [n3, r3] of e3.entries()) t3.includes(n3) || c(`ModSDK: Patching ${o3.name}: Patch ${n3} not applied`), t3 = t3.replaceAll(n3, r3);
75
- return (0, eval)(`(${t3})`);
76
- })(o2.original, t2);
77
- let i2 = /* @__PURE__ */ __name(function(e3) {
78
- var t3, i3;
79
- const a2 = null === (i3 = (t3 = m.errorReporterHooks).hookChainExit) || void 0 === i3 ? void 0 : i3.call(t3, o2.name, n2), c2 = r2.apply(this, e3);
80
- return null == a2 || a2(), c2;
81
- }, "i");
82
- for (let t3 = e2.length - 1; t3 >= 0; t3--) {
83
- const n3 = e2[t3], r3 = i2;
84
- i2 = /* @__PURE__ */ __name(function(e3) {
85
- var t4, i3;
86
- const a2 = null === (i3 = (t4 = m.errorReporterHooks).hookEnter) || void 0 === i3 ? void 0 : i3.call(t4, o2.name, n3.mod), c2 = n3.hook.apply(this, [e3, (o3) => {
87
- if (1 !== arguments.length || !Array.isArray(e3)) throw new Error(`Mod ${n3.mod} failed to call next hook: Expected args to be array, got ${typeof o3}`);
88
- return r3.call(this, o3);
89
- }]);
90
- return null == a2 || a2(), c2;
91
- }, "i");
92
- }
93
- return { hooks: e2, patches: t2, patchesSources: n2, enter: i2, final: r2 };
94
- }
95
- __name(s, "s");
96
- function l(o2, e2 = false) {
97
- let r2 = i.get(o2);
98
- if (r2) e2 && (r2.precomputed = s(r2));
99
- else {
100
- let e3 = window;
101
- const a2 = o2.split(".");
102
- for (let t2 = 0; t2 < a2.length - 1; t2++) if (e3 = e3[a2[t2]], !n(e3)) throw new Error(`ModSDK: Function ${o2} to be patched not found; ${a2.slice(0, t2 + 1).join(".")} is not object`);
103
- const c2 = e3[a2[a2.length - 1]];
104
- if ("function" != typeof c2) throw new Error(`ModSDK: Function ${o2} to be patched not found`);
105
- const l2 = (function(o3) {
106
- let e4 = -1;
107
- for (const n2 of t.encode(o3)) {
108
- let o4 = 255 & (e4 ^ n2);
109
- for (let e5 = 0; e5 < 8; e5++) o4 = 1 & o4 ? -306674912 ^ o4 >>> 1 : o4 >>> 1;
110
- e4 = e4 >>> 8 ^ o4;
111
- }
112
- return ((-1 ^ e4) >>> 0).toString(16).padStart(8, "0").toUpperCase();
113
- })(c2.toString().replaceAll("\r\n", "\n")), d2 = { name: o2, original: c2, originalHash: l2 };
114
- r2 = Object.assign(Object.assign({}, d2), { precomputed: s(d2), router: /* @__PURE__ */ __name(() => {
115
- }, "router"), context: e3, contextProperty: a2[a2.length - 1] }), r2.router = /* @__PURE__ */ (function(o3) {
116
- return function(...e4) {
117
- return o3.precomputed.enter.apply(this, [e4]);
118
- };
119
- })(r2), i.set(o2, r2), e3[r2.contextProperty] = r2.router;
120
- }
121
- return r2;
122
- }
123
- __name(l, "l");
124
- function d() {
125
- for (const o2 of i.values()) o2.precomputed = s(o2);
126
- }
127
- __name(d, "d");
128
- function p() {
129
- const o2 = /* @__PURE__ */ new Map();
130
- for (const [e2, t2] of i) o2.set(e2, { name: e2, original: t2.original, originalHash: t2.originalHash, sdkEntrypoint: t2.router, currentEntrypoint: t2.context[t2.contextProperty], hookedByMods: r(t2.precomputed.hooks.map(((o3) => o3.mod))), patchedByMods: Array.from(t2.precomputed.patchesSources) });
131
- return o2;
132
- }
133
- __name(p, "p");
134
- const f = /* @__PURE__ */ new Map();
135
- function u(o2) {
136
- f.get(o2.name) !== o2 && e(`Failed to unload mod '${o2.name}': Not registered`), f.delete(o2.name), o2.loaded = false, d();
137
- }
138
- __name(u, "u");
139
- function g(o2, t2) {
140
- o2 && "object" == typeof o2 || e("Failed to register mod: Expected info object, got " + typeof o2), "string" == typeof o2.name && o2.name || e("Failed to register mod: Expected name to be non-empty string, got " + typeof o2.name);
141
- let r2 = `'${o2.name}'`;
142
- "string" == typeof o2.fullName && o2.fullName || e(`Failed to register mod ${r2}: Expected fullName to be non-empty string, got ${typeof o2.fullName}`), r2 = `'${o2.fullName} (${o2.name})'`, "string" != typeof o2.version && e(`Failed to register mod ${r2}: Expected version to be string, got ${typeof o2.version}`), o2.repository || (o2.repository = void 0), void 0 !== o2.repository && "string" != typeof o2.repository && e(`Failed to register mod ${r2}: Expected repository to be undefined or string, got ${typeof o2.version}`), null == t2 && (t2 = {}), t2 && "object" == typeof t2 || e(`Failed to register mod ${r2}: Expected options to be undefined or object, got ${typeof t2}`);
143
- const i2 = true === t2.allowReplace, a2 = f.get(o2.name);
144
- a2 && (a2.allowReplace && i2 || e(`Refusing to load mod ${r2}: it is already loaded and doesn't allow being replaced.
145
- Was the mod loaded multiple times?`), u(a2));
146
- const c2 = /* @__PURE__ */ __name((o3) => {
147
- let e2 = g2.patching.get(o3.name);
148
- return e2 || (e2 = { hooks: [], patches: /* @__PURE__ */ new Map() }, g2.patching.set(o3.name, e2)), e2;
149
- }, "c"), s2 = /* @__PURE__ */ __name((o3, t3) => (...n2) => {
150
- var i3, a3;
151
- const c3 = null === (a3 = (i3 = m.errorReporterHooks).apiEndpointEnter) || void 0 === a3 ? void 0 : a3.call(i3, o3, g2.name);
152
- g2.loaded || e(`Mod ${r2} attempted to call SDK function after being unloaded`);
153
- const s3 = t3(...n2);
154
- return null == c3 || c3(), s3;
155
- }, "s"), p2 = { unload: s2("unload", (() => u(g2))), hookFunction: s2("hookFunction", ((o3, t3, n2) => {
156
- "string" == typeof o3 && o3 || e(`Mod ${r2} failed to patch a function: Expected function name string, got ${typeof o3}`);
157
- const i3 = l(o3), a3 = c2(i3);
158
- "number" != typeof t3 && e(`Mod ${r2} failed to hook function '${o3}': Expected priority number, got ${typeof t3}`), "function" != typeof n2 && e(`Mod ${r2} failed to hook function '${o3}': Expected hook function, got ${typeof n2}`);
159
- const s3 = { mod: g2.name, priority: t3, hook: n2 };
160
- return a3.hooks.push(s3), d(), () => {
161
- const o4 = a3.hooks.indexOf(s3);
162
- o4 >= 0 && (a3.hooks.splice(o4, 1), d());
163
- };
164
- })), patchFunction: s2("patchFunction", ((o3, t3) => {
165
- "string" == typeof o3 && o3 || e(`Mod ${r2} failed to patch a function: Expected function name string, got ${typeof o3}`);
166
- const i3 = l(o3), a3 = c2(i3);
167
- n(t3) || e(`Mod ${r2} failed to patch function '${o3}': Expected patches object, got ${typeof t3}`);
168
- for (const [n2, i4] of Object.entries(t3)) "string" == typeof i4 ? a3.patches.set(n2, i4) : null === i4 ? a3.patches.delete(n2) : e(`Mod ${r2} failed to patch function '${o3}': Invalid format of patch '${n2}'`);
169
- d();
170
- })), removePatches: s2("removePatches", ((o3) => {
171
- "string" == typeof o3 && o3 || e(`Mod ${r2} failed to patch a function: Expected function name string, got ${typeof o3}`);
172
- const t3 = l(o3);
173
- c2(t3).patches.clear(), d();
174
- })), callOriginal: s2("callOriginal", ((o3, t3, n2) => {
175
- "string" == typeof o3 && o3 || e(`Mod ${r2} failed to call a function: Expected function name string, got ${typeof o3}`);
176
- const i3 = l(o3);
177
- return Array.isArray(t3) || e(`Mod ${r2} failed to call a function: Expected args array, got ${typeof t3}`), i3.original.apply(null != n2 ? n2 : globalThis, t3);
178
- })), getOriginalHash: s2("getOriginalHash", ((o3) => {
179
- "string" == typeof o3 && o3 || e(`Mod ${r2} failed to get hash: Expected function name string, got ${typeof o3}`);
180
- return l(o3).originalHash;
181
- })) }, g2 = { name: o2.name, fullName: o2.fullName, version: o2.version, repository: o2.repository, allowReplace: i2, api: p2, loaded: true, patching: /* @__PURE__ */ new Map() };
182
- return f.set(o2.name, g2), Object.freeze(p2);
183
- }
184
- __name(g, "g");
185
- function h() {
186
- const o2 = [];
187
- for (const e2 of f.values()) o2.push({ name: e2.name, fullName: e2.fullName, version: e2.version, repository: e2.repository });
188
- return o2;
189
- }
190
- __name(h, "h");
191
- let m;
192
- const y = void 0 === window.bcModSdk ? window.bcModSdk = (function() {
193
- const e2 = { version: o, apiVersion: 1, registerMod: g, getModsInfo: h, getPatchingInfo: p, errorReporterHooks: Object.seal({ apiEndpointEnter: null, hookEnter: null, hookChainExit: null }) };
194
- return m = e2, Object.freeze(e2);
195
- })() : (n(window.bcModSdk) || e("Failed to init Mod SDK: Name already in use"), 1 !== window.bcModSdk.apiVersion && e(`Failed to init Mod SDK: Different version already loaded ('1.2.0' vs '${window.bcModSdk.version}')`), window.bcModSdk.version !== o && alert(`Mod SDK warning: Loading different but compatible versions ('1.2.0' vs '${window.bcModSdk.version}')
196
- One of mods you are using is using an old version of SDK. It will work for now but please inform author to update`), window.bcModSdk);
197
- return "undefined" != typeof exports && (Object.defineProperty(exports, "__esModule", { value: true }), exports.default = y), y;
198
- })();
199
- }
200
- });
201
-
202
- // src/base/base_module.ts
203
- var BaseModule = class {
204
- static {
205
- __name(this, "BaseModule");
206
- }
207
- /**
208
- * An optional UI screen for configuring this module's settings.
209
- * Subclasses can override this getter to provide a `Subscreen` instance.
210
- * Modules with screens are automatically registered to the main menu.
211
- */
212
- get settingsScreen() {
213
- return null;
214
- }
215
- /**
216
- * The storage key under which this module's settings will be saved.
217
- * Defaults to the class name.
218
- *
219
- * Subclasses can override this if they require a custom storage key.
220
- */
221
- get settingsStorage() {
222
- return this.constructor.name;
223
- }
224
- /**
225
- * Retrieves the current settings for this module.
226
- * If no settings exist yet, registers default settings first.
227
- */
228
- get settings() {
229
- const modName = ModSdkManager.ModInfo.name;
230
- if (!this.settingsStorage) return {};
231
- if (!modStorage.playerStorage) {
232
- Player[modName] = {};
233
- this.registerDefaultSettings(modStorage.playerStorage);
234
- } else if (!modStorage.playerStorage[this.settingsStorage]) {
235
- this.registerDefaultSettings(modStorage.playerStorage);
236
- }
237
- return modStorage.playerStorage[this.settingsStorage];
238
- }
239
- /**
240
- * Persists new settings for this module.
241
- * Automatically initializes storage and defaults if they don't exist.
242
- */
243
- set settings(value) {
244
- const modName = ModSdkManager.ModInfo.name;
245
- const storage = new ModStorage(modName);
246
- if (!this.settingsStorage) return;
247
- if (!storage.playerStorage) {
248
- Player[modName] = {};
249
- this.registerDefaultSettings(modStorage.playerStorage);
250
- } else if (!storage.playerStorage[this.settingsStorage]) {
251
- this.registerDefaultSettings(modStorage.playerStorage);
252
- }
253
- storage.playerStorage[this.settingsStorage] = value;
254
- }
255
- /**
256
- * Initializes the module.
257
- * Default implementation registers default settings immediately.
258
- * Subclasses can override to perform additional setup.
259
- */
260
- init() {
261
- }
262
- /**
263
- * Registers default settings for this module in persistent storage.
264
- * Only runs if a storage key and default settings are defined.
265
- *
266
- * If some settings already exist, they will be merged with defaults.
267
- * Existing values will NOT be overwritten.
268
- */
269
- registerDefaultSettings(target) {
270
- const storage = this.settingsStorage;
271
- const defaults = this.defaultSettings;
272
- if (!storage || !defaults) return;
273
- if (Object.entries(this.defaultSettings).length === 0) return;
274
- target[storage] = deepMerge(this.defaultSettings, target[storage], { concatArrays: false, matchingOnly: true });
275
- }
276
- /**
277
- * Provides default settings for this module.
278
- * Subclasses should override this getter to return their defaults.
279
- */
280
- get defaultSettings() {
281
- return null;
282
- }
283
- /**
284
- * Called when the module is loaded into the system.
285
- * Subclasses should override to perform data loading or initialization.
286
- */
287
- load() {
288
- }
289
- /**
290
- * By default doesn't get called each frame, only once when the module is loaded.
291
- * Subclasses can override to implement runtime logic.
292
- */
293
- run() {
294
- }
295
- /**
296
- * Called when the module is being removed.
297
- * Subclasses can override to perform cleanup or save final state.
298
- */
299
- unload() {
300
- }
301
- };
302
-
303
- // src/base/base_subscreen.ts
304
- async function setSubscreen(subscreen) {
305
- if (!GUI.instance) {
306
- throw new Error("Attempt to set subscreen before init");
307
- }
308
- const screenName = typeof subscreen === "string" ? subscreen : subscreen?.options.name;
309
- const screenId = `${BaseSubscreen.id}_${screenName}`;
310
- await CommonSetScreen(...["DeepLibMod", `${screenId}`]);
311
- }
312
- __name(setSubscreen, "setSubscreen");
313
- var BaseSubscreen = class _BaseSubscreen {
314
- static {
315
- __name(this, "BaseSubscreen");
316
- }
317
- /** Global registry of currently rendered elements and their definitions. */
318
- static currentElements = [];
319
- /** Tracks the currently visible page number (1-based index). */
320
- static currentPage = 1;
321
- /** Runtime options for this subscreen. */
322
- options;
323
- /** Reference to the module this subscreen belongs to. */
324
- module;
325
- /** Identifier for internal use to avoid screen name collisions. */
326
- static id = CommonGenerateUniqueID();
327
- /** Optional configuration flags for a BaseSubscreen instance. */
328
- static subscreenOptions = {
329
- drawCharacter: true,
330
- name: "UNKNOWN",
331
- icon: "",
332
- background: "Sheet",
333
- doShowExitButton: true,
334
- doShowTitle: true,
335
- settingsWidth: 1e3,
336
- forceUpCharacter: false
337
- };
338
- /** The menu at the top of the subscreen */
339
- static menu = null;
340
- constructor(module) {
341
- if (module) this.module = module;
342
- const ctor = this.constructor;
343
- this.options = {
344
- ..._BaseSubscreen.subscreenOptions,
345
- ...ctor.subscreenOptions
346
- };
347
- const screenName = this.options.name;
348
- const screenId = `${_BaseSubscreen.id}_${screenName}`;
349
- exportToGlobal(`${screenId}Load`, this.load.bind(this));
350
- exportToGlobal(`${screenId}Run`, this.run.bind(this));
351
- exportToGlobal(`${screenId}Click`, this.click.bind(this));
352
- exportToGlobal(`${screenId}Exit`, this.exit.bind(this));
353
- exportToGlobal(`${screenId}Unload`, this.unload.bind(this));
354
- exportToGlobal(`${screenId}Resize`, this.resize.bind(this));
355
- exportToGlobal(`${screenId}Background`, this.options.background);
356
- CommonCSVCache[ScreenFileGetTranslation("DeepLibMod", screenId)] = [];
357
- }
358
- /** Changes the currently active subscreen. */
359
- async setSubscreen(screen) {
360
- return await setSubscreen(screen);
361
- }
362
- /** Gets this subscreen's settings object from its parent module. */
363
- get settings() {
364
- return this.module.settings;
365
- }
366
- /** Updates this subscreen's settings in its parent module. */
367
- set settings(value) {
368
- this.module.settings = value;
369
- }
370
- /**
371
- * Defines the paginated layout of the subscreen's settings UI.
372
- * Each element in the outer array is a page; each page contains `SettingElement`s.
373
- *
374
- * Subclasses should override to define their actual UI structure.
375
- */
376
- get pageStructure() {
377
- return [[]];
378
- }
379
- /** Gets the currently visible page's settings elements. */
380
- get currentPage() {
381
- return this.pageStructure[Math.min(_BaseSubscreen.currentPage - 1, this.pageStructure.length - 1)];
382
- }
383
- getPageLabel() {
384
- return CommonStringPartitionReplace(getText("settings.page.label"), {
385
- $currentPage$: `${_BaseSubscreen.currentPage}`,
386
- $totalPages$: `${this.pageStructure.length}`
387
- }).join("");
388
- }
389
- /**
390
- * Changes the visible page in a multi-page subscreen.
391
- * Automatically wraps around when going past the first or last page.
392
- */
393
- changePage(page, setLabel) {
394
- const totalPages = this.pageStructure.length;
395
- if (page > totalPages) page = 1;
396
- if (page < 1) page = totalPages;
397
- _BaseSubscreen.currentPage = page;
398
- this.managePageElementsVisibility();
399
- setLabel(this.getPageLabel());
400
- }
401
- /**
402
- * Updates the DOM to show only elements belonging to the current page.
403
- * All elements on other pages are hidden.
404
- */
405
- managePageElementsVisibility() {
406
- this.pageStructure.forEach((item, ix) => {
407
- item.forEach((setting) => {
408
- const element = ElementWrap(`${setting.id}-container`) ?? ElementWrap(`${setting.id}`);
409
- if (ix != _BaseSubscreen.currentPage - 1) {
410
- if (element) domUtil.hide(element);
411
- } else {
412
- if (element) domUtil.unhide(element);
413
- }
414
- });
415
- });
416
- }
417
- /**
418
- * Called when this subscreen is first displayed.
419
- * Builds the layout, initializes navigation, and renders all settings elements.
420
- *
421
- * Handles:
422
- * - Ensuring each module with a settings screen has its defaults loaded
423
- * - Creating navigation menus and back/next page controls
424
- * - Building and appending UI elements based on `pageStructure`
425
- * - Setting up exit button and tooltip
426
- * - Resetting to page 1
427
- */
428
- load() {
429
- for (const module of modules()) {
430
- if (!module.settingsScreen) continue;
431
- if (!module.settings || !Object.keys(module.settings).length) module.registerDefaultSettings(modStorage.playerStorage);
432
- }
433
- _BaseSubscreen.currentPage = 1;
434
- layout.getSubscreen();
435
- const settingsElement = layout.getSettingsDiv();
436
- layout.appendToSubscreen(settingsElement);
437
- _BaseSubscreen.menu = ElementMenu.Create("deeplib-nav-menu", []);
438
- layout.appendToSubscreen(_BaseSubscreen.menu);
439
- if (this.pageStructure.length > 1) {
440
- const backNext = advElement.createBackNext({
441
- id: "deeplib-page-back-next",
442
- next: /* @__PURE__ */ __name(({ setLabel }) => this.changePage(_BaseSubscreen.currentPage + 1, setLabel), "next"),
443
- initialNextTooltip: getText("settings.button.next_button_hint"),
444
- back: /* @__PURE__ */ __name(({ setLabel }) => this.changePage(_BaseSubscreen.currentPage - 1, setLabel), "back"),
445
- initialPrevTooltip: getText("settings.button.prev_button_hint"),
446
- initialLabel: this.getPageLabel()
447
- });
448
- _BaseSubscreen.menu.prepend(backNext);
449
- }
450
- if (this.options.help) {
451
- const onClick = this.options.help.onClick;
452
- let action = /* @__PURE__ */ __name(() => {
453
- }, "action");
454
- if (typeof onClick === "string" || onClick instanceof URL) {
455
- action = /* @__PURE__ */ __name(() => window.open(onClick, "_blank"), "action");
456
- } else if (typeof onClick === "function") {
457
- action = onClick;
458
- } else if (onClick instanceof _BaseSubscreen) {
459
- action = /* @__PURE__ */ __name(async () => await this.setSubscreen(onClick), "action");
460
- }
461
- this.options.help.tooltip ??= getText("settings.button.help_button_hint");
462
- this.options.help.icon ??= `${PUBLIC_URL}/dl_images/bookmark.svg`;
463
- const helpButton = advElement.createButton({
464
- id: "deeplib-help",
465
- size: [90, 90],
466
- onClick: action,
467
- options: {
468
- image: this.options.help.icon,
469
- tooltip: this.options.help.tooltip
470
- }
471
- });
472
- _BaseSubscreen.menu.append(helpButton);
473
- }
474
- if (this.options.doShowTitle) {
475
- const subscreenTitle = advElement.createLabel({
476
- id: "deeplib-subscreen-title",
477
- label: getText(`${this.options.name}.title`).replace("$ModVersion", ModSdkManager.ModInfo.version)
478
- });
479
- layout.appendToSubscreen(subscreenTitle);
480
- }
481
- if (this.options.doShowExitButton) {
482
- const exitButton = advElement.createButton({
483
- id: "deeplib-exit",
484
- size: [90, 90],
485
- onClick: /* @__PURE__ */ __name(() => {
486
- this.exit();
487
- }, "onClick"),
488
- options: {
489
- image: `${PUBLIC_URL}/dl_images/exit.svg`,
490
- tooltip: getText("settings.button.back_button_hint")
491
- }
492
- });
493
- _BaseSubscreen.menu.append(exitButton);
494
- }
495
- const tooltip = advElement.createTooltip();
496
- layout.appendToSubscreen(tooltip);
497
- this.pageStructure.forEach(
498
- (s) => s.forEach((item) => {
499
- let element;
500
- switch (item.type) {
501
- case "text":
502
- case "number":
503
- case "color":
504
- element = advElement.createInput(item);
505
- break;
506
- case "checkbox":
507
- element = advElement.createCheckbox(item);
508
- break;
509
- case "button":
510
- element = advElement.createButton(item);
511
- break;
512
- case "label":
513
- element = advElement.createLabel(item);
514
- break;
515
- case "custom":
516
- element = advElement.createCustom(item);
517
- break;
518
- case "dropdown":
519
- element = advElement.createDropdown(item);
520
- break;
521
- }
522
- layout.appendToSettingsDiv(element);
523
- })
524
- );
525
- this.managePageElementsVisibility();
526
- if (this.options.drawCharacter && this.options.forceUpCharacter) {
527
- CharacterAppearanceForceUpCharacter = Player.MemberNumber;
528
- } else {
529
- CharacterAppearanceForceUpCharacter = -1;
530
- }
531
- }
532
- /**
533
- * Called each frame while this subscreen is active.
534
- * Default behavior draws the player's character if `drawCharacter` is enabled.
535
- */
536
- run() {
537
- if (this.options.drawCharacter) DrawCharacter(Player, 50, 50, 0.9, false);
538
- }
539
- /**
540
- * Handles mouse clicks *on canvas* while the subscreen is active.
541
- * Default implementation is empty — subclasses may override.
542
- */
543
- click() {
544
- }
545
- /**
546
- * Exits this subscreen, returning to the main menu.
547
- * Also saves persistent storage changes.
548
- * Called after the `unload`.
549
- */
550
- exit() {
551
- CharacterAppearanceForceUpCharacter = -1;
552
- CharacterLoadCanvas(Player);
553
- const returnScreen = typeof this.options.returnScreen === "function" ? this.options.returnScreen() : this.options.returnScreen;
554
- if (returnScreen instanceof _BaseSubscreen || !returnScreen) {
555
- setSubscreen(returnScreen ?? "mainmenu").then(() => {
556
- modStorage.save();
557
- });
558
- } else if (Array.isArray(returnScreen)) {
559
- CommonSetScreen(...returnScreen).then(() => {
560
- modStorage.save();
561
- });
562
- }
563
- }
564
- /**
565
- * Called when the window is resized.
566
- * Also checks for overflow in the settings div and applies styling accordingly.
567
- */
568
- resize(_onLoad = false) {
569
- const offset = this.options.drawCharacter ? 0 : 380;
570
- const subscreen = layout.getSubscreen();
571
- const settingsDiv = layout.getSettingsDiv();
572
- ElementSetPosition(subscreen, 0, 0);
573
- ElementSetSize(subscreen, 2e3, 1e3);
574
- ElementSetFontSize(subscreen, "auto");
575
- ElementSetPosition(settingsDiv, 530 - offset, 170);
576
- ElementSetSize(settingsDiv, this.options.settingsWidth ?? 1e3 + offset, 660);
577
- if (this.options.doShowTitle) {
578
- ElementSetPosition("deeplib-subscreen-title", 530 - offset, 75);
579
- ElementSetSize("deeplib-subscreen-title", 800, 60);
580
- }
581
- ElementSetPosition("deeplib-nav-menu", 1905, 75, "top-right");
582
- ElementSetSize("deeplib-nav-menu", null, 90);
583
- ElementSetPosition(advElement.getTooltip() || "", 250, 850);
584
- ElementSetSize(advElement.getTooltip() || "", 1500, 70);
585
- _BaseSubscreen.currentElements.forEach((item) => {
586
- const element = item[0];
587
- const options = item[1];
588
- domUtil.autoSetPosition(options.id ?? element.id, options.position);
589
- domUtil.autoSetSize(options.id ?? element.id, options.size);
590
- });
591
- if (settingsDiv) {
592
- if (domUtil.hasOverflow(settingsDiv)?.vertical) {
593
- settingsDiv.classList.add("deeplib-overflow-box");
594
- } else {
595
- settingsDiv.classList.remove("deeplib-overflow-box");
596
- }
597
- }
598
- }
599
- /**
600
- * Called when this subscreen is being removed.
601
- * Resets the static element registry and removes the subscreen from the layout.
602
- * Called before `exit`.
603
- */
604
- unload() {
605
- _BaseSubscreen.currentElements = [];
606
- layout.removeSubscreen();
607
- }
608
- };
609
-
610
- // src/styles/index.scss
611
- var styles_default = `.deeplib-subscreen,
1
+ var de=Object.defineProperty;var s=(t,e)=>de(t,"name",{value:e,configurable:!0});var B=class{static{s(this,"BaseModule")}get settingsScreen(){return null}get settingsStorage(){return this.constructor.name}get settings(){return this.settingsStorage?(u.playerStorage?u.playerStorage[this.settingsStorage]||this.registerDefaultSettings(u.playerStorage):this.registerDefaultSettings(u.playerStorage),u.playerStorage[this.settingsStorage]):null}set settings(e){this.settingsStorage&&(u.playerStorage?u.playerStorage[this.settingsStorage]||this.registerDefaultSettings(u.playerStorage):this.registerDefaultSettings(u.playerStorage),u.playerStorage[this.settingsStorage]=e)}init(){}registerDefaultSettings(e){let i=this.settingsStorage,n=this.defaultSettings;!i||!n||Object.entries(this.defaultSettings).length!==0&&(e[i]=b(this.defaultSettings,e[i],{concatArrays:!1,matchingOnly:!0}))}get defaultSettings(){return null}load(){}run(){}unload(){}};async function T(t){if(!L.instance)throw new Error("Attempt to set subscreen before init");let e=typeof t=="string"?t:t?.options.name,i=`${m.id}_${e}`;await CommonSetScreen("DeepLibMod",`${i}`)}s(T,"setSubscreen");var m=class t{static{s(this,"BaseSubscreen")}static currentElements=[];static currentPage=1;options;module;static id=CommonGenerateUniqueID();static subscreenOptions={drawCharacter:!0,name:"UNKNOWN",icon:"",background:"Sheet",doShowExitButton:!0,doShowTitle:!0,settingsWidth:1e3,forceUpCharacter:!1};static menu=null;constructor(e){e&&(this.module=e);let i=this.constructor;this.options={...t.subscreenOptions,...i.subscreenOptions};let n=this.options.name,o=`${t.id}_${n}`;C(`${o}Load`,this.load.bind(this)),C(`${o}Run`,this.run.bind(this)),C(`${o}Click`,this.click.bind(this)),C(`${o}Exit`,this.exit.bind(this)),C(`${o}Unload`,this.unload.bind(this)),C(`${o}Resize`,this.resize.bind(this)),C(`${o}Background`,this.options.background),CommonCSVCache[ScreenFileGetTranslation("DeepLibMod",o)]=[]}async setSubscreen(e){return await T(e)}get settings(){return this.module.settings}set settings(e){this.module.settings=e}get pageStructure(){return[[]]}get currentPage(){return this.pageStructure[Math.min(t.currentPage-1,this.pageStructure.length-1)]}getPageLabel(){return CommonStringPartitionReplace(d("settings.page.label"),{$currentPage$:`${t.currentPage}`,$totalPages$:`${this.pageStructure.length}`}).join("")}changePage(e,i){let n=this.pageStructure.length;e>n&&(e=1),e<1&&(e=n),t.currentPage=e,this.managePageElementsVisibility(),i(this.getPageLabel())}managePageElementsVisibility(){this.pageStructure.forEach((e,i)=>{e.forEach(n=>{let o=ElementWrap(`${n.id}-container`)??ElementWrap(`${n.id}`);i!==t.currentPage-1?o&&G.hide(o):o&&G.unhide(o)})})}load(){for(let n of f())n.settingsScreen&&(!n.settings||!Object.keys(n.settings).length)&&n.registerDefaultSettings(u.playerStorage);t.currentPage=1,g.getSubscreen();let e=g.getSettingsDiv();if(g.appendToSubscreen(e),t.menu=ElementMenu.Create("deeplib-nav-menu",[]),g.appendToSubscreen(t.menu),this.pageStructure.length>1){let n=c.createBackNext({id:"deeplib-page-back-next",next:s(({setLabel:o})=>this.changePage(t.currentPage+1,o),"next"),initialNextTooltip:d("settings.button.next_button_hint"),back:s(({setLabel:o})=>this.changePage(t.currentPage-1,o),"back"),initialPrevTooltip:d("settings.button.prev_button_hint"),initialLabel:this.getPageLabel()});t.menu.prepend(n)}if(this.options.help){let n=this.options.help.onClick,o=s(()=>{},"action");typeof n=="string"||n instanceof URL?o=s(()=>window.open(n,"_blank"),"action"):typeof n=="function"?o=n:n instanceof t&&(o=s(async()=>await this.setSubscreen(n),"action")),this.options.help.tooltip??=d("settings.button.help_button_hint"),this.options.help.icon??=`${PUBLIC_URL}/dl_images/bookmark.svg`;let r=c.createButton({id:"deeplib-help",size:[90,90],onClick:o,options:{image:this.options.help.icon,tooltip:this.options.help.tooltip}});t.menu.append(r)}if(this.options.doShowTitle){let n=c.createLabel({id:"deeplib-subscreen-title",label:d(`${this.options.name}.title`).replace("$ModVersion",MOD_VERSION_CAPTION)});g.appendToSubscreen(n)}if(this.options.doShowExitButton){let n=c.createButton({id:"deeplib-exit",size:[90,90],onClick:s(()=>{this.exit()},"onClick"),options:{image:`${PUBLIC_URL}/dl_images/exit.svg`,tooltip:d("settings.button.back_button_hint")}});t.menu.append(n)}let i=c.createTooltip();g.appendToSubscreen(i),this.pageStructure.forEach(n=>n.forEach(o=>{let r;switch(o.type){case"text":case"number":case"color":r=c.createInput(o);break;case"checkbox":r=c.createCheckbox(o);break;case"button":r=c.createButton(o);break;case"label":r=c.createLabel(o);break;case"custom":r=c.createCustom(o);break;case"dropdown":r=c.createDropdown(o);break}g.appendToSettingsDiv(r)})),this.managePageElementsVisibility(),this.options.drawCharacter&&this.options.forceUpCharacter?CharacterAppearanceForceUpCharacter=Player.MemberNumber:CharacterAppearanceForceUpCharacter=-1}run(){this.options.drawCharacter&&DrawCharacter(Player,50,50,.9,!1)}click(){}exit(){CharacterAppearanceForceUpCharacter=-1,CharacterLoadCanvas(Player);let e=typeof this.options.returnScreen=="function"?this.options.returnScreen():this.options.returnScreen;e instanceof t||!e?T(e??"mainmenu").then(()=>{u.save()}):Array.isArray(e)&&CommonSetScreen(...e).then(()=>{u.save()})}resize(e=!1){let i=this.options.drawCharacter?0:380,n=g.getSubscreen(),o=g.getSettingsDiv();ElementSetPosition(n,0,0),ElementSetSize(n,2e3,1e3),ElementSetFontSize(n,"auto"),ElementSetPosition(o,530-i,170),ElementSetSize(o,this.options.settingsWidth??1e3+i,660),this.options.doShowTitle&&(ElementSetPosition("deeplib-subscreen-title",530-i,75),ElementSetSize("deeplib-subscreen-title",800,90)),ElementSetPosition("deeplib-nav-menu",1905,75,"top-right"),ElementSetSize("deeplib-nav-menu",null,90),ElementSetSize(c.getTooltip()||"",1500),t.currentElements.forEach(r=>{let a=r[0],l=r[1];G.autoSetPosition(l.id??a.id,l.position),G.autoSetSize(l.id??a.id,l.size)}),o&&(G.hasOverflow(o)?.vertical?o.classList.add("deeplib-overflow-box"):o.classList.remove("deeplib-overflow-box"))}unload(){t.currentElements=[],g.removeSubscreen()}};var $=`.deeplib-subscreen,
612
2
  .deeplib-modal {
613
3
  --deeplib-background-color: var(--tmd-main, white);
614
4
  --deeplib-element-color: var(--tmd-element, white);
@@ -677,6 +67,8 @@ var styles_default = `.deeplib-subscreen,
677
67
  color: var(--deeplib-text-color);
678
68
  user-select: none;
679
69
  pointer-events: none;
70
+ display: flex;
71
+ align-items: center;
680
72
  }
681
73
 
682
74
  .deeplib-text {
@@ -720,6 +112,18 @@ var styles_default = `.deeplib-subscreen,
720
112
  border: min(0.2vh, 0.1vw) solid var(--deeplib-border-color);
721
113
  z-index: 1;
722
114
  }
115
+ .deeplib-tooltip.anchor-top {
116
+ position: absolute;
117
+ top: min(1vh, 0.5vw);
118
+ left: 50%;
119
+ transform: translateX(-50%);
120
+ }
121
+ .deeplib-tooltip.anchor-bottom {
122
+ position: absolute;
123
+ bottom: min(1vh, 0.5vw);
124
+ left: 50%;
125
+ transform: translateX(-50%);
126
+ }
723
127
 
724
128
  .deeplib-overflow-box {
725
129
  border: var(--deeplib-border-color) solid var(--deeplib-border-width);
@@ -949,2225 +353,15 @@ var styles_default = `.deeplib-subscreen,
949
353
  height: 100dvh;
950
354
  background-color: rgba(0, 0, 0, 0.5);
951
355
  }
952
- /*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VSb290IjoiL21udC9zaGluZG93cy9TdHVmZi9Db2RlL2JjL0JDLURlZXBMaWIvc3JjL3N0eWxlcyIsInNvdXJjZXMiOlsidmFycy5zY3NzIiwiYnV0dG9ucy5zY3NzIiwiZWxlbWVudHMuc2NzcyIsImlucHV0cy5zY3NzIiwibWVzc2FnZXMuc2NzcyIsIm1vZGFsLnNjc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFBQTtFQUVFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOzs7QUNkRjtFQUNFO0VBQ0E7RUFDQTs7QUFFQTtFQUVFOztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUVBO0VBQ0E7RUFDQTs7QUFHRjtFQUNFOztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7O0FBR0Y7RUFDRTs7O0FDM0NKO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7OztBQUdGO0VBQ0U7RUFDQTtFQUNBOzs7QUFHRjtFQUNFO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOztBQUdFO0VBQ0U7RUFDQTs7QUFISjtFQU1FO0VBQ0E7O0FBR0Y7RUFDRTtFQUNBOzs7QUFJSjtFQUNFO0VBQ0E7RUFDQTtFQUNBOztBQUVBO0VBQ0U7OztBQUlKO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTtFQUNBO0VBQ0E7OztBQ2pISjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTs7QUFHRjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7QUFFQTtFQUNFO0VBQ0E7OztBQUtOO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7QUFFQTtFQUNFOztBQUdGO0VBQ0U7RUFDQTs7QUFHRjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7QUFFQTtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7QUFFQTtFQUNFO0VBQ0E7OztBQU9SO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTtFQUNBO0VBQ0E7RUFDQTs7QUFHRjtFQUNFOzs7QUN2Rko7RUFDRTtFQUNBOzs7QUFHRjtBQUFBO0VBRUU7RUFDQTtFQUNBOzs7QUFHRjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7O0FBR0Y7QUFBQTtFQUVFOzs7QUFHRjtFQUNFO0VBQ0E7RUFDQTs7O0FDN0JGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7QUFFQTtFQUNFO0VBQ0E7RUFDQTtFQUNBOztBQUdGO0VBQ0U7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBOztBQUVBO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTs7QUFLTjtFQUNFO0VBQ0E7RUFDQTtFQUNBOzs7QUFJSjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBIiwic291cmNlc0NvbnRlbnQiOlsiLmRlZXBsaWItc3Vic2NyZWVuLFxuLmRlZXBsaWItbW9kYWwge1xuICAtLWRlZXBsaWItYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tdG1kLW1haW4sIHdoaXRlKTtcbiAgLS1kZWVwbGliLWVsZW1lbnQtY29sb3I6IHZhcigtLXRtZC1lbGVtZW50LCB3aGl0ZSk7XG4gIC0tZGVlcGxpYi1lbGVtZW50LWhvdmVyLWNvbG9yOiB2YXIoLS10bWQtZWxlbWVudC1ob3ZlciwgY3lhbik7XG4gIC0tZGVlcGxpYi1hY2NlbnQtY29sb3I6IHZhcigtLXRtZC1hY2NlbnQsICNGRkZGODgpO1xuICAtLWRlZXBsaWItYmxvY2tlZC1jb2xvcjogdmFyKC0tdG1kLWJsb2NrZWQsIHJlZCk7XG4gIC0tZGVlcGxpYi10ZXh0LWNvbG9yOiB2YXIoLS10bWQtdGV4dCwgYmxhY2spO1xuICAtLWRlZXBsaWItaWNvbi1jb2xvcjogdmFyKC0tdG1kLWFjY2VudCwgYmxhY2spO1xuICAtLWRlZXBsaWItaWNvbi1ob3Zlci1jb2xvcjogdmFyKC0tdG1kLWFjY2VudC1ob3ZlciwgYmxhY2spO1xuICAtLWRlZXBsaWItYm9yZGVyLWNvbG9yOiB2YXIoLS10bWQtYWNjZW50LCBibGFjayk7XG4gIC0tZGVlcGxpYi1ib3JkZXItd2lkdGg6IG1pbigwLjJ2aCwgMC4xdncpO1xuICAtLWRlZXBsaWItYm9yZGVyLXdpZHRoOiBtaW4oMC4yZHZoLCAwLjFkdncpO1xuICAtLWRlZXBsaWItYm9yZGVyLXJhZGl1czogbWluKDF2aCwgMC41dncpO1xuICAtLWRlZXBsaWItYm9yZGVyLXJhZGl1czogbWluKDFkdmgsIDAuNWR2dyk7XG59XG4iLCIuZGVlcGxpYi1idXR0b24ge1xuICBjb2xvcjogdmFyKC0tZGVlcGxpYi10ZXh0LWNvbG9yKTtcbiAgd2lkdGg6IDEwMCU7XG4gIGhlaWdodDogMTAwJTtcblxuICAmLmJ1dHRvbi1zdHlsaW5nLFxuICAmLmJ1dHRvbi1zdHlsaW5nOjpiZWZvcmUge1xuICAgIGJvcmRlci1yYWRpdXM6IG1pbigxLjBkdmgsIDAuNWR2dyk7XG4gIH1cblxuICBpbWcge1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDAlO1xuICAgIGxlZnQ6IDAlO1xuICAgIHdpZHRoOiAxMDAlO1xuICAgIGhlaWdodDogMTAwJTtcbiAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiBsZWZ0O1xuICAgIGJhY2tncm91bmQtY29sb3I6IHZhcigtLWRlZXBsaWItaWNvbi1jb2xvcik7XG4gICAgYmFja2dyb3VuZC1ibGVuZC1tb2RlOiBtdWx0aXBseTtcbiAgICBiYWNrZ3JvdW5kLXNpemU6IGNvbnRhaW47XG4gICAgbWFzay1wb3NpdGlvbjogbGVmdDtcbiAgICBtYXNrLXNpemU6IGNvbnRhaW47XG4gICAgYmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJlcGVhdDtcbiAgICBtYXNrLXJlcGVhdDogbm8tcmVwZWF0O1xuICAgIGNvbG9yOiB0cmFuc3BhcmVudDtcblxuICAgIGJhY2tncm91bmQtaW1hZ2U6IHZhcigtLWltYWdlKTtcbiAgICBtYXNrLWltYWdlOiB2YXIoLS1pbWFnZSk7XG4gICAgcG9pbnRlci1ldmVudHM6IG5vbmU7XG4gIH1cblxuICAmOmhvdmVyIGltZyB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tZGVlcGxpYi1pY29uLWhvdmVyLWNvbG9yKTtcbiAgfVxuXG4gIC5idXR0b24tbGFiZWwge1xuICAgIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50ICFpbXBvcnRhbnQ7XG4gICAgY29sb3I6IHZhcigtLWRlZXBsaWItdGV4dC1jb2xvcik7XG4gICAgZm9udC1zaXplOiBtaW4oMy42ZHZoLCAxLjhkdncpO1xuICAgIGRpc3BsYXk6IGNvbnRlbnRzO1xuICB9XG5cbiAgLmJ1dHRvbi10b29sdGlwIHtcbiAgICBib3JkZXItcmFkaXVzOiBtaW4oMS4wZHZoLCAwLjVkdncpO1xuICB9XG59IiwiI2RlZXBsaWItcGFnZS1sYWJlbCB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICBwb2ludGVyLWV2ZW50czogbm9uZTtcbn1cblxuI2RlZXBsaWItc3Vic2NyZWVuLXRpdGxlIHtcbiAgdGV4dC1hbGlnbjogbGVmdDtcbiAgY29sb3I6IHZhcigtLWRlZXBsaWItdGV4dC1jb2xvcik7XG4gIHVzZXItc2VsZWN0OiBub25lO1xuICBwb2ludGVyLWV2ZW50czogbm9uZTtcbn1cblxuLmRlZXBsaWItdGV4dCB7XG4gIGNvbG9yOiB2YXIoLS1kZWVwbGliLXRleHQtY29sb3IpO1xufVxuXG4uZGVlcGxpYi1zdWJzY3JlZW4ge1xuICBwYWRkaW5nOiAwO1xuICBtYXJnaW46IDA7XG4gIHBvaW50ZXItZXZlbnRzOiBub25lO1xufVxuXG4uZGVlcGxpYi1zdWJzY3JlZW4gKiB7XG4gIGJveC1zaXppbmc6IGJvcmRlci1ib3g7XG4gIHBvaW50ZXItZXZlbnRzOiBhbGw7XG59XG5cbi5kZWVwbGliLXNldHRpbmdzIHtcbiAgZGlzcGxheTogZ3JpZDtcbiAgZ3JpZC1hdXRvLXJvd3M6IG1pbi1jb250ZW50O1xuICBwYWRkaW5nOiBtaW4oMS4wZHZoLCAwLjVkdncpO1xuICBnYXA6IDAuM2VtO1xufVxuXG4uZGVlcGxpYi1taXNjIHtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbi1yZXZlcnNlO1xuICBnYXA6IG1pbigxdmgsIDAuNXZ3KTtcbn1cblxuLmRlZXBsaWItdG9vbHRpcCB7XG4gIGJhY2tncm91bmQtY29sb3I6IHZhcigtLWRlZXBsaWItZWxlbWVudC1jb2xvcik7XG4gIGNvbG9yOiB2YXIoLS1kZWVwbGliLXRleHQtY29sb3IpO1xuICBkaXNwbGF5OiBmbGV4O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgYm9yZGVyLXJhZGl1czogbWluKDEuMGR2aCwgMC41ZHZ3KTtcbiAgcGFkZGluZzogbWluKDF2aCwgMC41dncpO1xuICBmb250LXNpemU6IDAuOGVtO1xuICBib3JkZXI6IG1pbigwLjJ2aCwgMC4xdncpIHNvbGlkIHZhcigtLWRlZXBsaWItYm9yZGVyLWNvbG9yKTtcbiAgei1pbmRleDogMTtcbn1cblxuLmRlZXBsaWItb3ZlcmZsb3ctYm94IHtcbiAgYm9yZGVyOiB2YXIoLS1kZWVwbGliLWJvcmRlci1jb2xvcikgc29saWQgdmFyKC0tZGVlcGxpYi1ib3JkZXItd2lkdGgpO1xufVxuXG4uZGVlcGxpYi1wcmV2LW5leHQge1xuICBkaXNwbGF5OiBmbGV4O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XG4gIGZsZXgtZGlyZWN0aW9uOiByb3c7XG4gIGdhcDogbWluKDJkdmgsIDFkdncpO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1kZWVwbGliLWVsZW1lbnQtY29sb3IpO1xuICBjb2xvcjogdmFyKC0tZGVlcGxpYi10ZXh0LWNvbG9yKTtcbiAgYm9yZGVyLXJhZGl1czogbWluKDEuMGR2aCwgMC41ZHZ3KTtcbiAgYm9yZGVyOiBtaW4oMC4ydmgsIDAuMXZ3KSBzb2xpZCB2YXIoLS1kZWVwbGliLWJvcmRlci1jb2xvcik7XG5cbiAgLmRlZXBsaWItcHJldi1uZXh0LWJ1dHRvbiB7XG4gICAgJjpob3ZlciB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1kZWVwbGliLWVsZW1lbnQtaG92ZXItY29sb3IpO1xuICAgICAgYm9yZGVyLXJhZGl1czogdmFyKC0tZGVlcGxpYi1ib3JkZXItcmFkaXVzKTtcbiAgICB9XG5cbiAgICBoZWlnaHQ6IDEwMCU7XG4gICAgYXNwZWN0LXJhdGlvOiAxO1xuICB9XG5cbiAgLmRlZXBsaWItcHJldi1uZXh0LWxhYmVsIHtcbiAgICB3aGl0ZS1zcGFjZTogbm93cmFwO1xuICAgIHVzZXItc2VsZWN0OiBub25lO1xuICB9XG59XG5cbiNkZWVwbGliLW5hdi1tZW51IHtcbiAgZGlzcGxheTogZmxleDtcbiAgZmxleC1kaXJlY3Rpb246IHJvdztcbiAgZ2FwOiBtaW4oMmR2aCwgMWR2dyk7XG4gIHotaW5kZXg6IDE7XG5cbiAgJj4uZGVlcGxpYi1idXR0b24ge1xuICAgIGZsZXg6IDEgMCBhdXRvO1xuICB9XG59XG5cbiNkZWVwbGliLXN0b3JhZ2UtbWV0ZXIge1xuICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gIHRvcDogMHB4O1xuICBsZWZ0OiAwcHg7XG4gIHdpZHRoOiAxMDAlO1xuICBoZWlnaHQ6IDEwMCU7XG4gIG92ZXJmbG93OiBoaWRkZW47XG4gIGJhY2tncm91bmQtY29sb3I6IHZhcigtLWRlZXBsaWItZWxlbWVudC1jb2xvcik7XG4gIGJvcmRlcjogdmFyKC0tZGVlcGxpYi1ib3JkZXItd2lkdGgpIHNvbGlkIHZhcigtLWRlZXBsaWItYm9yZGVyLWNvbG9yKTtcbiAgYm9yZGVyLXJhZGl1czogdmFyKC0tZGVlcGxpYi1ib3JkZXItcmFkaXVzKTtcbiAgei1pbmRleDogLTE7XG5cbiAgI2RlZXBsaWItc3RvcmFnZS1iYXIge1xuICAgIGhlaWdodDogMTAwJTtcbiAgICB3aWR0aDogMCU7XG4gICAgYmFja2dyb3VuZDogdmFyKC0tZGVlcGxpYi1hY2NlbnQtY29sb3IpO1xuICB9XG59IiwiLmRlZXBsaWItY2hlY2tib3gtY29udGFpbmVyIHtcbiAgZGlzcGxheTogZmxleDtcbiAgZmxleC1kaXJlY3Rpb246IHJvdztcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgZ2FwOiAwLjNlbTtcbiAgd2lkdGg6IGZpdC1jb250ZW50O1xuXG4gIHNwYW4ge1xuICAgIHVzZXItc2VsZWN0OiBub25lO1xuICB9XG5cbiAgLmRlZXBsaWItaW5wdXQge1xuICAgIHdpZHRoOiBtaW4oNXZoLCAyLjV2dyk7XG4gICAgaGVpZ2h0OiBtaW4oNXZoLCAyLjV2dyk7XG4gICAgd2lkdGg6IG1pbig1ZHZoLCAyLjVkdncpO1xuICAgIGhlaWdodDogbWluKDVkdmgsIDIuNWR2dyk7XG4gICAgYm9yZGVyLXJhZGl1czogbWluKDEuMHZoLCAwLjV2dyk7XG4gICAgYm9yZGVyLXJhZGl1czogbWluKDEuMGR2aCwgMC41ZHZ3KTtcblxuICAgICZbdHlwZT1cImNoZWNrYm94XCJdOmNoZWNrZWQ6OmJlZm9yZSB7XG4gICAgICB3aWR0aDogODAlO1xuICAgICAgaGVpZ2h0OiA4MCU7XG4gICAgfVxuICB9XG59XG5cbi5kZWVwbGliLWlucHV0LWNvbnRhaW5lciB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiByb3c7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGdhcDogMC4zZW07XG4gIHdpZHRoOiBmaXQtY29udGVudDtcblxuICBzcGFuIHtcbiAgICB1c2VyLXNlbGVjdDogbm9uZTtcbiAgfVxuXG4gICY6aGFzKC5kZWVwbGliLXRleHQpIHtcbiAgICBtYXJnaW4tdG9wOiBtaW4oMXZoLCAwLjV2dyk7XG4gICAgbWFyZ2luLXRvcDogbWluKDFkdmgsIDAuNWR2dyk7XG4gIH1cblxuICAuZGVlcGxpYi1pbnB1dCB7XG4gICAgZm9udC1zaXplOiAwLjZlbTtcbiAgICBwYWRkaW5nOiBtaW4oMXZoLCAwLjV2dyk7XG4gICAgcGFkZGluZzogbWluKDFkdmgsIDAuNWR2dyk7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7XG4gICAgb3V0bGluZTogbm9uZTtcbiAgICBtaW4taGVpZ2h0OiBtaW4oNXZoLCAyLjV2dyk7XG4gICAgbWluLWhlaWdodDogbWluKDVkdmgsIDIuNWR2dyk7XG4gICAgYm9yZGVyLXJhZGl1czogbWluKDEuMHZoLCAwLjV2dyk7XG4gICAgYm9yZGVyLXJhZGl1czogbWluKDEuMGR2aCwgMC41ZHZ3KTtcblxuICAgICZbdHlwZT1cImNvbG9yXCJdIHtcbiAgICAgIHBhZGRpbmc6IDBweDtcbiAgICAgIHdpZHRoOiBtaW4oNXZoLCAyLjV2dyk7XG4gICAgICBoZWlnaHQ6IG1pbig1dmgsIDIuNXZ3KTtcbiAgICAgIHdpZHRoOiBtaW4oNWR2aCwgMi41ZHZ3KTtcbiAgICAgIGhlaWdodDogbWluKDVkdmgsIDIuNWR2dyk7XG4gICAgICBib3JkZXItcmFkaXVzOiAwcHg7XG5cbiAgICAgICY6ZGlzYWJsZWQge1xuICAgICAgICBib3JkZXI6IHZhcigtLWRlZXBsaWItYmxvY2tlZC1jb2xvcikgc29saWQgdmFyKC0tZGVlcGxpYi1ib3JkZXItd2lkdGgpO1xuICAgICAgICBjdXJzb3I6IG5vdC1hbGxvd2VkO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5cbi5kZWVwbGliLWRyb3Bkb3duLWNvbnRhaW5lciB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiByb3c7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGdhcDogbWluKDJ2aCwgMXZ3KTtcbiAgZ2FwOiBtaW4oMmR2aCwgMWR2dyk7XG4gIGNvbG9yOiB2YXIoLS1kZWVwbGliLXRleHQtY29sb3IpO1xuICB3aWR0aDogZml0LWNvbnRlbnQ7XG5cbiAgc2VsZWN0IHtcbiAgICBwYWRkaW5nOiAwIG1pbigxdmgsIDAuNXZ3KTtcbiAgICBwYWRkaW5nOiAwIG1pbigxZHZoLCAwLjVkdncpO1xuICAgIGJvcmRlci1yYWRpdXM6IG1pbigxdmgsIDAuNXZ3KTtcbiAgICBib3JkZXItcmFkaXVzOiBtaW4oMWR2aCwgMC41ZHZ3KTtcbiAgfVxuXG4gIHNwYW4ge1xuICAgIHVzZXItc2VsZWN0OiBub25lO1xuICB9XG59IiwiLmRlZXBsaWItaGlnaGxpZ2h0LXRleHQge1xuICBmb250LXdlaWdodDogYm9sZDtcbiAgY29sb3I6IHJnYigyMDMsIDE4NSwgMjMpO1xufVxuXG4jVGV4dEFyZWFDaGF0TG9nW2RhdGEtY29sb3J0aGVtZT0nZGFyayddIGRpdi5DaGF0TWVzc2FnZS5kZWVwbGliLW1lc3NhZ2UsXG4jVGV4dEFyZWFDaGF0TG9nW2RhdGEtY29sb3J0aGVtZT0nZGFyazInXSBkaXYuQ2hhdE1lc3NhZ2UuZGVlcGxpYi1tZXNzYWdlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tZGVlcGxpYi1lbGVtZW50LWNvbG9yKTtcbiAgYm9yZGVyOiBtaW4oMC4yZHZoLCAwLjFkdncpIHNvbGlkIHZhcigtLWRlZXBsaWItYm9yZGVyLWNvbG9yKTtcbiAgY29sb3I6IHZhcigtLWRlZXBsaWItdGV4dC1jb2xvcik7XG59XG5cbiNUZXh0QXJlYUNoYXRMb2cgZGl2LkNoYXRNZXNzYWdlLmRlZXBsaWItbWVzc2FnZSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNlZWU7XG4gIGJvcmRlcjogbWluKDAuMmR2aCwgMC4xZHZ3KSBzb2xpZCAjNDQwMTcxO1xuICBjb2xvcjogIzExMTtcbiAgcGFkZGluZy1sZWZ0OiBtaW4oMC42ZHZoLCAwLjNkdncpO1xuICBkaXNwbGF5OiBibG9jaztcbiAgd2hpdGUtc3BhY2U6IG5vcm1hbDtcbn1cblxuI1RleHRBcmVhQ2hhdExvZ1tkYXRhLWNvbG9ydGhlbWU9J2RhcmsnXSBkaXYuQ2hhdE1lc3NhZ2UuZGVlcGxpYi1tZXNzYWdlIGEsXG4jVGV4dEFyZWFDaGF0TG9nW2RhdGEtY29sb3J0aGVtZT0nZGFyazInXSBkaXYuQ2hhdE1lc3NhZ2UuZGVlcGxpYi1tZXNzYWdlIGEge1xuICBjb2xvcjogdmFyKC0tZGVlcGxpYi10ZXh0LWNvbG9yKTtcbn1cblxuI1RleHRBcmVhQ2hhdExvZyBkaXYuQ2hhdE1lc3NhZ2UuZGVlcGxpYi1tZXNzYWdlIGEge1xuICBjdXJzb3I6IHBvaW50ZXI7XG4gIGZvbnQtd2VpZ2h0OiBib2xkO1xuICBjb2xvcjogIzExMTtcbn1cbiIsIi5kZWVwbGliLW1vZGFsIHtcbiAgcG9zaXRpb246IGZpeGVkO1xuICB0b3A6IDEwJTtcbiAgbGVmdDogNTAlO1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoLTUwJSk7XG4gIHotaW5kZXg6IDEwMDE7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBnYXA6IDAuNWVtO1xuICB3aWR0aDogbWF4KDUwZHZ3LCAyNWR2aCk7XG4gIGZvbnQtc2l6ZTogbWluKDRkdmgsIDJkdncpO1xuICBwYWRkaW5nOiBtaW4oMmR2aCwgMWR2dyk7XG4gIGJhY2tncm91bmQtY29sb3I6IHZhcigtLWRlZXBsaWItZWxlbWVudC1jb2xvcik7XG4gIGJvcmRlci1yYWRpdXM6IG1pbigxLjJkdmgsIDAuNmR2dyk7XG4gIGJvcmRlcjogbWluKDAuMmR2aCwgMC4xZHZ3KSBzb2xpZCB2YXIoLS1kZWVwbGliLWJvcmRlci1jb2xvcik7XG4gIGNvbG9yOiB2YXIoLS1kZWVwbGliLXRleHQtY29sb3IpO1xuXG4gIC5kZWVwbGliLW1vZGFsLWlucHV0IHtcbiAgICB3aWR0aDogMTAwJTtcbiAgICBmb250LXNpemU6IG1pbigyLjZkdmgsIDEuOGR2dyk7XG4gICAgYm9yZGVyLXJhZGl1czogbWluKDEuMGR2aCwgMC41ZHZ3KTtcbiAgICBwYWRkaW5nOiBtaW4oMWR2aCwgMC41ZHZ3KTtcbiAgfVxuXG4gIGlucHV0LmRlZXBsaWItbW9kYWwtaW5wdXQge1xuICAgIG1heC13aWR0aDogbWF4KDUwZHZoLCAyNWR2dyk7XG4gIH1cblxuICAuZGVlcGxpYi1tb2RhbC1idXR0b24tY29udGFpbmVyIHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGZsZXgtZGlyZWN0aW9uOiByb3c7XG4gICAganVzdGlmeS1jb250ZW50OiBmbGV4LWVuZDtcbiAgICBnYXA6IDAuNWVtO1xuICAgIHdpZHRoOiAxMDAlO1xuXG4gICAgLmRlZXBsaWItYnV0dG9uIHtcbiAgICAgIGZvbnQtc2l6ZTogMC44ZW07XG4gICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgd2lkdGg6IGF1dG87XG4gICAgICBwYWRkaW5nOiBtaW4oMC40dmgsIDAuMnZ3KSBtaW4oMnZoLCAxdncpO1xuXG4gICAgICAuYnV0dG9uLWxhYmVsIHtcbiAgICAgICAgZGlzcGxheTogY29udGVudHM7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLmRlZXBsaWItbW9kYWwtcHJvbXB0LWNvbnRhaW5lciB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIH1cbn1cblxuLmRlZXBsaWItbW9kYWwtYmxvY2tlciB7XG4gIHotaW5kZXg6IDEwMDA7XG4gIHBvc2l0aW9uOiBmaXhlZDtcbiAgdG9wOiAwO1xuICBsZWZ0OiAwO1xuICB3aWR0aDogMTAwZHZ3O1xuICBoZWlnaHQ6IDEwMGR2aDtcbiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgwLCAwLCAwLCAwLjUpO1xufVxuIl19 */`;
953
-
954
- // src/base/initialization.ts
955
- var modStorage;
956
- var sdk;
957
- var logger;
958
- function initMod(options) {
959
- sdk = new ModSdkManager(options.modInfo.info, options.modInfo.options);
960
- const MOD_NAME = ModSdkManager.ModInfo.name;
961
- modStorage = new ModStorage(ModSdkManager.ModInfo.name);
962
- logger = new Logger(MOD_NAME);
963
- Style.injectInline("deeplib-style", styles_default);
964
- logger.debug("Init wait");
965
- if (CurrentScreen == null || CurrentScreen === "Login") {
966
- options.beforeLogin?.();
967
- const removeHook = sdk.hookFunction("LoginResponse", 0, (args, next) => {
968
- logger.debug("Init! LoginResponse caught: ", args);
969
- next(args);
970
- const response = args[0];
971
- if (response === "InvalidNamePassword") return next(args);
972
- if (response && typeof response.Name === "string" && typeof response.AccountName === "string") {
973
- init(options);
974
- removeHook();
975
- }
976
- });
977
- } else {
978
- logger.debug(`Already logged in, initing ${MOD_NAME}`);
979
- init(options);
980
- }
981
- }
982
- __name(initMod, "initMod");
983
- async function init(options) {
984
- const MOD_NAME = ModSdkManager.ModInfo.name;
985
- const MOD_VERSION = ModSdkManager.ModInfo.version;
986
- if (window[MOD_NAME + "Loaded"]) return;
987
- modStorage.load();
988
- await Localization.init(options.translationOptions);
989
- if (options.modules && !initModules(options.modules)) {
990
- unloadMod();
991
- return;
992
- }
993
- await options.initFunction?.();
994
- if (options.mainMenuOptions)
995
- MainMenu.setOptions(options.mainMenuOptions);
996
- window[MOD_NAME + "Loaded"] = true;
997
- logger.log(`Loaded! Version: ${MOD_VERSION}`);
998
- }
999
- __name(init, "init");
1000
- function initModules(modulesToRegister) {
1001
- for (const module of modulesToRegister) {
1002
- registerModule(module);
1003
- }
1004
- for (const module of modules()) {
1005
- module.init();
1006
- }
1007
- for (const module of modules()) {
1008
- module.load();
1009
- }
1010
- for (const module of modules()) {
1011
- module.run();
1012
- }
1013
- for (const module of modules()) {
1014
- module.registerDefaultSettings(modStorage.playerStorage);
1015
- }
1016
- logger.debug("Modules Loaded.");
1017
- return true;
1018
- }
1019
- __name(initModules, "initModules");
1020
- function unloadMod() {
1021
- const MOD_NAME = ModSdkManager.ModInfo.name;
1022
- unloadModules();
1023
- delete window[MOD_NAME + "Loaded"];
1024
- logger.debug("Unloaded.");
1025
- return true;
1026
- }
1027
- __name(unloadMod, "unloadMod");
1028
- function unloadModules() {
1029
- for (const module of modules()) {
1030
- module.unload();
1031
- }
1032
- }
1033
- __name(unloadModules, "unloadModules");
1034
-
1035
- // src/base/modules.ts
1036
- var modulesMap = /* @__PURE__ */ new Map();
1037
- function modules() {
1038
- return [...modulesMap.values()];
1039
- }
1040
- __name(modules, "modules");
1041
- function registerModule(module) {
1042
- modulesMap.set(module.constructor.name, module);
1043
- return module;
1044
- }
1045
- __name(registerModule, "registerModule");
1046
- function getModule(moduleType) {
1047
- return modulesMap.get(moduleType);
1048
- }
1049
- __name(getModule, "getModule");
1050
-
1051
- // src/migrators/base_migrator.ts
1052
- var BaseMigrator = class {
1053
- static {
1054
- __name(this, "BaseMigrator");
1055
- }
1056
- };
1057
-
1058
- // src/modules/gui.ts
1059
- var GUI = class _GUI extends BaseModule {
1060
- static {
1061
- __name(this, "GUI");
1062
- }
1063
- /** The singleton instance of the GUI controller. */
1064
- static instance = null;
1065
- /** All subscreens managed by this GUI, including the main menu and module settings screens. */
1066
- _subscreens;
1067
- /** The mod's main menu screen. */
1068
- _mainMenu;
1069
- /** Options defining how the mod's settings button is displayed and behaves. */
1070
- _modButtonOptions;
1071
- /** Returns all registered subscreens. */
1072
- get subscreens() {
1073
- return this._subscreens;
1074
- }
1075
- /** Returns the main menu subscreen instance. */
1076
- get mainMenu() {
1077
- return this._mainMenu;
1078
- }
1079
- /**
1080
- * Creates the GUI instance and initializes the main menu.
1081
- *
1082
- * @throws If another `GUI` instance already exists.
1083
- */
1084
- constructor(guiOptions = null) {
1085
- super();
1086
- if (_GUI.instance) {
1087
- throw new Error("Duplicate initialization");
1088
- }
1089
- for (const module of modules()) {
1090
- if (!module.settingsScreen) continue;
1091
- }
1092
- this._mainMenu = guiOptions?.mainMenu ? new guiOptions.mainMenu(this) : new MainMenu(this);
1093
- this._subscreens = [this._mainMenu];
1094
- this._modButtonOptions = guiOptions;
1095
- _GUI.instance = this;
1096
- }
1097
- /**
1098
- * Loads the GUI and registers the mod's settings button in the extensions menu.
1099
- *
1100
- * - Creates subscreens for each module's settings screen.
1101
- * - Registers lifecycle callbacks for subscreens events.
1102
- * - Sets up the main menu and its subscreens.
1103
- */
1104
- load() {
1105
- if (!this._modButtonOptions) return;
1106
- for (const module of modules()) {
1107
- if (!module.settingsScreen) continue;
1108
- this._subscreens.push(new module.settingsScreen(module));
1109
- }
1110
- this._mainMenu.subscreens = this._subscreens;
1111
- PreferenceRegisterExtensionSetting({
1112
- Identifier: this._modButtonOptions.identifier,
1113
- ButtonText: this._modButtonOptions.buttonText,
1114
- Image: this._modButtonOptions.image,
1115
- load: /* @__PURE__ */ __name(async () => {
1116
- await setSubscreen(this._mainMenu);
1117
- }, "load"),
1118
- run: /* @__PURE__ */ __name(() => {
1119
- }, "run"),
1120
- click: /* @__PURE__ */ __name(() => {
1121
- }, "click"),
1122
- exit: /* @__PURE__ */ __name(() => {
1123
- }, "exit")
1124
- });
1125
- }
1126
- };
1127
-
1128
- // src/modules/version.ts
1129
- var VersionModule = class _VersionModule extends BaseModule {
1130
- static {
1131
- __name(this, "VersionModule");
1132
- }
1133
- /** Whether the current session is running a new version compared to stored data */
1134
- static isItNewVersion = false;
1135
- /** The current mod version (retrieved from `ModSdkManager.ModInfo.version`) */
1136
- static version;
1137
- static newVersionMessage = "";
1138
- /** List of registered migration handlers, sorted by version */
1139
- static migrators = [];
1140
- static beforeEach;
1141
- static afterEach;
1142
- static beforeAll;
1143
- static afterAll;
1144
- constructor(options) {
1145
- super();
1146
- _VersionModule.newVersionMessage = options.newVersionMessage;
1147
- if (options.migrators) {
1148
- _VersionModule.migrators = options.migrators;
1149
- _VersionModule.migrators.sort((a, b) => a.migrationVersion.localeCompare(b.migrationVersion));
1150
- }
1151
- _VersionModule.beforeEach = options.beforeEach;
1152
- _VersionModule.afterEach = options.afterEach;
1153
- _VersionModule.beforeAll = options.beforeAll;
1154
- _VersionModule.afterAll = options.afterAll;
1155
- }
1156
- /**
1157
- * Initializes the module on load:
1158
- * - Stores the current mod version.
1159
- * - Hooks into `ChatRoomSync` to show a "new version" message when applicable.
1160
- */
1161
- load() {
1162
- _VersionModule.version = ModSdkManager.ModInfo.version;
1163
- _VersionModule.checkVersionUpdate();
1164
- if (modStorage.playerStorage.GlobalModule.doShowNewVersionMessage && _VersionModule.isItNewVersion) {
1165
- _VersionModule.sendNewVersionMessage();
1166
- }
1167
- }
1168
- /**
1169
- * Checks if the stored version differs from the current version.
1170
- * If a new version is detected:
1171
- * - Flags the session as updated.
1172
- * - Runs applicable migrations.
1173
- * - Updates stored version in player data.
1174
- * - Saves `modStorage`.
1175
- */
1176
- static checkVersionUpdate() {
1177
- const previousVersion = _VersionModule.loadVersion();
1178
- const currentVersion = _VersionModule.version;
1179
- if (_VersionModule.isNewVersion(previousVersion, currentVersion)) {
1180
- _VersionModule.isItNewVersion = true;
1181
- _VersionModule.checkVersionMigration();
1182
- _VersionModule.saveVersion();
1183
- }
1184
- modStorage.save();
1185
- }
1186
- /**
1187
- * Executes migrations for all registered migrators whose `MigrationVersion`
1188
- * is newer than the previously stored version.
1189
- */
1190
- static checkVersionMigration() {
1191
- const previousVersion = _VersionModule.loadVersion();
1192
- const toMigrate = _VersionModule.migrators.filter(
1193
- (m) => _VersionModule.isNewVersion(previousVersion, m.migrationVersion)
1194
- );
1195
- if (!toMigrate.length) return;
1196
- _VersionModule.beforeAll?.();
1197
- for (const migrator of toMigrate) {
1198
- _VersionModule.beforeEach?.();
1199
- migrator.migrate();
1200
- deepLibLogger.info(
1201
- `Migrating ${ModSdkManager.ModInfo.name} from ${previousVersion} to ${migrator.migrationVersion} with ${migrator.constructor.name}`
1202
- );
1203
- _VersionModule.afterEach?.();
1204
- }
1205
- _VersionModule.afterAll?.();
1206
- }
1207
- /** Sends the currently configured "new version" message to the local player. */
1208
- static sendNewVersionMessage() {
1209
- if (!_VersionModule.newVersionMessage) return;
1210
- const beepLogLength = FriendListBeepLog.push({
1211
- MemberNumber: Player.MemberNumber,
1212
- MemberName: ModSdkManager.ModInfo.name,
1213
- ChatRoomName: getText("module.version.version_update"),
1214
- ChatRoomSpace: "X",
1215
- Private: false,
1216
- Sent: false,
1217
- Time: /* @__PURE__ */ new Date(),
1218
- Message: _VersionModule.newVersionMessage
1219
- });
1220
- const beepIdx = beepLogLength - 1;
1221
- const title = CommonStringPartitionReplace(getText("module.version.new_version_toast_title"), {
1222
- $modName$: ModSdkManager.ModInfo.name,
1223
- $modVersion$: _VersionModule.version
1224
- }).join("");
1225
- const data = FriendListBeepLog[beepIdx];
1226
- ServerShowBeep(_VersionModule.newVersionMessage, 1e4, {
1227
- memberNumber: data.MemberNumber,
1228
- memberName: data.MemberName,
1229
- chatRoomName: data.ChatRoomName,
1230
- ...data.Message && {
1231
- onClick: /* @__PURE__ */ __name(() => {
1232
- FriendListShowBeep(beepIdx);
1233
- }, "onClick")
1234
- }
1235
- }, title);
1236
- }
1237
- /**
1238
- * Determines if a given `candidate` version is newer than the `current` version.
1239
- *
1240
- * Version strings are expected in `MAJOR.MINOR.PATCH` format.
1241
- */
1242
- static isNewVersion(current, candidate) {
1243
- if (current !== void 0) {
1244
- const CURRENT_ = current.split("."), CANDIDATE_ = candidate.split(".");
1245
- for (let i = 0; i < 3; i++) {
1246
- if (CURRENT_[i] === CANDIDATE_[i]) {
1247
- continue;
1248
- }
1249
- return CANDIDATE_[i] > CURRENT_[i];
1250
- }
1251
- }
1252
- if (current === void 0 || current === "" || !current) {
1253
- return true;
1254
- }
1255
- return false;
1256
- }
1257
- /** Saves the current mod version into persistent player storage. */
1258
- static saveVersion() {
1259
- if (modStorage.playerStorage) {
1260
- Player[ModSdkManager.ModInfo.name].Version = _VersionModule.version;
1261
- }
1262
- }
1263
- /** Loads the stored mod version from persistent player storage. */
1264
- static loadVersion() {
1265
- return modStorage.playerStorage?.Version;
1266
- }
1267
- };
1268
-
1269
- // src/screens/debug.ts
1270
- var GuiDebug = class extends BaseSubscreen {
1271
- static {
1272
- __name(this, "GuiDebug");
1273
- }
1274
- static subscreenOptions = {
1275
- name: "debug"
1276
- };
1277
- get pageStructure() {
1278
- return [
1279
- [
1280
- {
1281
- type: "button",
1282
- id: "test-deeplib-big-button",
1283
- options: {
1284
- label: "Big Button",
1285
- tooltip: "This is a big button",
1286
- image: "Icons/Exit.png"
1287
- },
1288
- size: [405, 80],
1289
- onClick() {
1290
- deepLibLogger.info("Big Button Clicked");
1291
- }
1292
- },
1293
- {
1294
- type: "button",
1295
- id: "test-deeplib-small-button",
1296
- options: {
1297
- tooltip: "This is a small button",
1298
- image: "Icons/Exit.png"
1299
- },
1300
- size: [90, 90],
1301
- onClick() {
1302
- deepLibLogger.info("Small Button Clicked");
1303
- }
1304
- },
1305
- {
1306
- type: "checkbox",
1307
- id: "test-deeplib-checkbox",
1308
- label: "Checkbox",
1309
- description: "This is a checkbox",
1310
- setElementValue() {
1311
- return true;
1312
- },
1313
- setSettingValue(val) {
1314
- deepLibLogger.info("Checkbox value:", val);
1315
- }
1316
- },
1317
- {
1318
- type: "text",
1319
- id: "test-deeplib-text-input",
1320
- label: "Input",
1321
- description: "This is a text input",
1322
- setElementValue() {
1323
- return "Input Value";
1324
- },
1325
- setSettingValue(val) {
1326
- deepLibLogger.info("Input value:", val);
1327
- }
1328
- },
1329
- {
1330
- type: "number",
1331
- id: "test-deeplib-number-input",
1332
- label: "Input",
1333
- description: "This is a number input",
1334
- setElementValue() {
1335
- return "123";
1336
- },
1337
- setSettingValue(val) {
1338
- deepLibLogger.info("Input value:", val);
1339
- }
1340
- },
1341
- {
1342
- type: "label",
1343
- id: "test-deeplib-label",
1344
- label: "Label",
1345
- description: "This is a label"
1346
- }
1347
- ],
1348
- [
1349
- {
1350
- type: "button",
1351
- id: "test-deeplib-big-button2",
1352
- options: {
1353
- label: "Big Button",
1354
- tooltip: "This is a big button",
1355
- image: "Icons/Exit.png"
1356
- },
1357
- size: [405, 80],
1358
- onClick() {
1359
- deepLibLogger.info("Big Button Clicked");
1360
- }
1361
- },
1362
- {
1363
- type: "button",
1364
- id: "test-deeplib-small-button2",
1365
- options: {
1366
- tooltip: "This is a small button",
1367
- image: "Icons/Next.png"
1368
- },
1369
- size: [90, 90],
1370
- onClick() {
1371
- deepLibLogger.info("Small Button Clicked");
1372
- }
1373
- },
1374
- {
1375
- type: "checkbox",
1376
- id: "test-deeplib-checkbox2",
1377
- label: "Checkbox",
1378
- description: "This is a checkbox",
1379
- setElementValue() {
1380
- return true;
1381
- },
1382
- setSettingValue(val) {
1383
- deepLibLogger.info("Checkbox value:", val);
1384
- }
1385
- },
1386
- {
1387
- type: "text",
1388
- id: "test-deeplib-text-input2",
1389
- label: "Input",
1390
- description: "This is a text input",
1391
- setElementValue() {
1392
- return "Input Value";
1393
- },
1394
- setSettingValue(val) {
1395
- deepLibLogger.info("Input value:", val);
1396
- }
1397
- },
1398
- {
1399
- type: "number",
1400
- id: "test-deeplib-number-input2",
1401
- label: "Input",
1402
- description: "This is a number input",
1403
- setElementValue() {
1404
- return "123";
1405
- },
1406
- setSettingValue(val) {
1407
- deepLibLogger.info("Input value:", val);
1408
- }
1409
- },
1410
- {
1411
- type: "label",
1412
- id: "test-deeplib-label2",
1413
- label: "Label",
1414
- description: "This is a label"
1415
- },
1416
- {
1417
- type: "dropdown",
1418
- id: "test-deeplib-dropdown",
1419
- label: "Dropdown",
1420
- description: "This is a dropdown",
1421
- optionsList: ["Option 1", "Option 2", "Option 3"],
1422
- setElementValue() {
1423
- return "Option 2";
1424
- },
1425
- setSettingValue(val) {
1426
- deepLibLogger.info("Dropdown value:", val);
1427
- },
1428
- options: {
1429
- width: 200
1430
- }
1431
- }
1432
- ]
1433
- ];
1434
- }
1435
- };
1436
-
1437
- // src/utilities/common.ts
1438
- function isPlainObject(value) {
1439
- return value !== null && typeof value === "object" && Object.getPrototypeOf(value) === Object.prototype && !Array.isArray(value);
1440
- }
1441
- __name(isPlainObject, "isPlainObject");
1442
- function deepMerge(target, source, options = { concatArrays: true, matchingOnly: false }) {
1443
- if (target === void 0) return source;
1444
- if (source === void 0) return target;
1445
- if (Array.isArray(target) && Array.isArray(source) && options.concatArrays) {
1446
- return [...target, ...source];
1447
- }
1448
- if (isPlainObject(target) && isPlainObject(source)) {
1449
- const result = { ...target };
1450
- const keys = options.matchingOnly ? Object.keys(source).filter((k) => k in target) : Object.keys(source);
1451
- for (const key of keys) {
1452
- if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
1453
- result[key] = key in target ? deepMerge(target[key], source[key], options) : source[key];
1454
- }
1455
- return result;
1456
- }
1457
- return source;
1458
- }
1459
- __name(deepMerge, "deepMerge");
1460
- function shuffleArray(array) {
1461
- const temp = JSON.parse(JSON.stringify(array));
1462
- const ret = [];
1463
- while (temp.length > 0) {
1464
- const d = Math.floor(Math.random() * temp.length);
1465
- ret.push(temp[d]);
1466
- temp.splice(d, 1);
1467
- }
1468
- return ret;
1469
- }
1470
- __name(shuffleArray, "shuffleArray");
1471
- function exportToGlobal(name, value) {
1472
- const keys = name.split(".");
1473
- let current = globalThis;
1474
- for (let i = 0; i < keys.length - 1; i++) {
1475
- if (!current[keys[i]]) {
1476
- current[keys[i]] = {};
1477
- }
1478
- current = current[keys[i]];
1479
- }
1480
- current[keys[keys.length - 1]] = value;
1481
- }
1482
- __name(exportToGlobal, "exportToGlobal");
1483
- function hasGetter(obj, prop) {
1484
- while (obj && obj !== Object.prototype) {
1485
- const descriptor = Object.getOwnPropertyDescriptor(obj, prop);
1486
- if (descriptor?.get) return true;
1487
- obj = Object.getPrototypeOf(obj);
1488
- }
1489
- return false;
1490
- }
1491
- __name(hasGetter, "hasGetter");
1492
- function hasSetter(obj, prop) {
1493
- while (obj && obj !== Object.prototype) {
1494
- const descriptor = Object.getOwnPropertyDescriptor(obj, prop);
1495
- if (descriptor?.set) return true;
1496
- obj = Object.getPrototypeOf(obj);
1497
- }
1498
- return false;
1499
- }
1500
- __name(hasSetter, "hasSetter");
1501
- var byteToKB = /* @__PURE__ */ __name((nByte) => Math.round(nByte / 100) / 10, "byteToKB");
1502
-
1503
- // src/utilities/elements/elements.ts
1504
- var advElement = {
1505
- createButton: elementCreateButton,
1506
- createCheckbox: elementCreateCheckbox,
1507
- createInput: elementCreateInput,
1508
- createLabel: elementCreateLabel,
1509
- createCustom: elementCreateCustom,
1510
- createDropdown: elementCreateDropdown,
1511
- createTooltip: elementCreateTooltip,
1512
- getTooltip: elementGetTooltip,
1513
- setTooltip: elementSetTooltip,
1514
- createBackNext: elementPrevNext
1515
- };
1516
- function elementCreateButton(options) {
1517
- options.id ??= ElementGenerateID();
1518
- const elem = document.getElementById(options.id);
1519
- if (elem) return elem;
1520
- options.type = "button";
1521
- let image = void 0;
1522
- if (options.options?.image) {
1523
- image = options.options.image;
1524
- options.options.image = void 0;
1525
- }
1526
- const disabled = typeof options?.disabled === "function" ? options?.disabled() : options?.disabled;
1527
- const button = ElementButton.Create(
1528
- options.id,
1529
- options?.onClick ?? (() => {
1530
- }),
1531
- deepMerge({
1532
- labelPosition: "center"
1533
- }, options.options),
1534
- deepMerge({
1535
- button: {
1536
- classList: ["deeplib-button"],
1537
- attributes: {
1538
- disabled
1539
- },
1540
- children: [
1541
- image ? deepMerge({
1542
- tag: "img",
1543
- attributes: {
1544
- id: `${options.id}-image`,
1545
- alt: "",
1546
- decoding: "async",
1547
- loading: "lazy",
1548
- src: "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
1549
- // 1x1 transparent image to get rid of broken image
1550
- },
1551
- style: {
1552
- "--image": `url("${image}")`
1553
- }
1554
- }, options.htmlOptions?.img) : void 0
1555
- ]
1556
- }
1557
- }, options.htmlOptions ?? {})
1558
- );
1559
- BaseSubscreen.currentElements.push([button, options]);
1560
- return button;
1561
- }
1562
- __name(elementCreateButton, "elementCreateButton");
1563
- function elementCreateCheckbox(options) {
1564
- const elem = document.getElementById(options.id);
1565
- if (elem) return elem;
1566
- options.type = "checkbox";
1567
- const disabled = typeof options?.disabled === "function" ? options?.disabled() : options?.disabled;
1568
- const retElem = ElementCreate(deepMerge({
1569
- tag: "label",
1570
- classList: ["deeplib-checkbox-container"],
1571
- attributes: {
1572
- id: `${options.id}-container`,
1573
- for: options.id
1574
- },
1575
- children: [
1576
- deepMerge({
1577
- tag: "input",
1578
- classList: ["checkbox", "deeplib-input"],
1579
- attributes: {
1580
- type: "checkbox",
1581
- id: options.id,
1582
- disabled,
1583
- checked: options?.setElementValue?.() || void 0
1584
- },
1585
- eventListeners: {
1586
- change: /* @__PURE__ */ __name(function() {
1587
- options?.setSettingValue?.(this.checked);
1588
- }, "change")
1589
- }
1590
- }, options.htmlOptions?.checkbox),
1591
- deepMerge({
1592
- tag: "span",
1593
- classList: ["deeplib-text"],
1594
- attributes: {
1595
- id: `${options.id}-label`
1596
- },
1597
- children: [options.label]
1598
- }, options.htmlOptions?.label)
1599
- ]
1600
- }, options.htmlOptions?.container));
1601
- if (options.description) {
1602
- retElem.addEventListener("mouseover", () => {
1603
- elementSetTooltip(options.description || "");
1604
- });
1605
- retElem.addEventListener("mouseout", () => {
1606
- elementSetTooltip("");
1607
- });
1608
- }
1609
- BaseSubscreen.currentElements.push([retElem, options]);
1610
- return retElem;
1611
- }
1612
- __name(elementCreateCheckbox, "elementCreateCheckbox");
1613
- function elementCreateCustom(options) {
1614
- options.id ??= ElementGenerateID();
1615
- options.htmlOptions.attributes ??= {};
1616
- options.htmlOptions.attributes.id ??= options.id;
1617
- const elem = document.getElementById(options.htmlOptions.attributes.id);
1618
- if (elem) return elem;
1619
- options.type = "custom";
1620
- const retElem = ElementCreate(options.htmlOptions);
1621
- BaseSubscreen.currentElements.push([retElem, options]);
1622
- return retElem;
1623
- }
1624
- __name(elementCreateCustom, "elementCreateCustom");
1625
- function elementCreateInput(options) {
1626
- const elem = document.getElementById(options.id);
1627
- if (elem) return elem;
1628
- const disabled = typeof options?.disabled === "function" ? options?.disabled() : options?.disabled;
1629
- const retElem = ElementCreate(deepMerge({
1630
- tag: "label",
1631
- classList: ["deeplib-input-container"],
1632
- attributes: {
1633
- id: `${options.id}-container`,
1634
- for: options.id
1635
- },
1636
- children: [
1637
- deepMerge({
1638
- tag: "input",
1639
- classList: ["deeplib-input"],
1640
- attributes: {
1641
- type: options.type,
1642
- id: options.id,
1643
- placeholder: " ",
1644
- disabled,
1645
- value: options?.setElementValue?.() || void 0
1646
- },
1647
- eventListeners: {
1648
- input: /* @__PURE__ */ __name(function() {
1649
- options?.setSettingValue?.(this.value);
1650
- }, "input")
1651
- }
1652
- }, options.htmlOptions?.input),
1653
- options.label ? deepMerge({
1654
- tag: "span",
1655
- classList: ["deeplib-text"],
1656
- attributes: {
1657
- id: `${options.id}-label`
1658
- },
1659
- children: [options.label]
1660
- }, options.htmlOptions?.label) : void 0
1661
- ]
1662
- }, options.htmlOptions?.container));
1663
- if (options.description) {
1664
- retElem.addEventListener("mouseover", () => {
1665
- elementSetTooltip(options.description || "");
1666
- });
1667
- retElem.addEventListener("mouseout", () => {
1668
- elementSetTooltip("");
1669
- });
1670
- }
1671
- BaseSubscreen.currentElements.push([retElem, options]);
1672
- return retElem;
1673
- }
1674
- __name(elementCreateInput, "elementCreateInput");
1675
- function elementCreateLabel(options) {
1676
- const elem = document.getElementById(options.id);
1677
- if (elem) return elem;
1678
- options.type = "label";
1679
- const retElem = ElementCreate(deepMerge({
1680
- tag: "label",
1681
- classList: ["deeplib-label", "deeplib-text"],
1682
- attributes: {
1683
- id: options.id
1684
- },
1685
- children: [
1686
- options.label
1687
- ]
1688
- }, options.htmlOptions));
1689
- if (options.description) {
1690
- retElem.addEventListener("mouseover", () => {
1691
- elementSetTooltip(options.description || "");
1692
- });
1693
- retElem.addEventListener("mouseout", () => {
1694
- elementSetTooltip("");
1695
- });
1696
- }
1697
- BaseSubscreen.currentElements.push([retElem, options]);
1698
- return retElem;
1699
- }
1700
- __name(elementCreateLabel, "elementCreateLabel");
1701
- function elementCreateDropdown(options) {
1702
- options.id ??= ElementGenerateID();
1703
- const elem = document.getElementById(`${options.id}-container`);
1704
- if (elem) return elem;
1705
- options.type = "dropdown";
1706
- const retElem = ElementCreate(deepMerge({
1707
- tag: "label",
1708
- classList: ["deeplib-dropdown-container"],
1709
- attributes: {
1710
- id: `${options.id}-container`,
1711
- for: options.id
1712
- },
1713
- children: [
1714
- options.label ? deepMerge({
1715
- tag: "span",
1716
- classList: ["deeplib-text"],
1717
- attributes: {
1718
- id: `${options.id}-label`
1719
- },
1720
- children: [options.label]
1721
- }, options.htmlOptions?.label) : void 0,
1722
- ElementCreateDropdown(
1723
- options.id,
1724
- options.optionsList,
1725
- function() {
1726
- return options.setSettingValue?.(this.value);
1727
- },
1728
- options.options,
1729
- options.htmlOptions?.select
1730
- )
1731
- ],
1732
- eventListeners: {
1733
- mouseover: /* @__PURE__ */ __name(function() {
1734
- elementSetTooltip(options.description ?? "");
1735
- }, "mouseover"),
1736
- mouseout: /* @__PURE__ */ __name(function() {
1737
- elementSetTooltip("");
1738
- }, "mouseout")
1739
- }
1740
- }, options.htmlOptions?.container));
1741
- BaseSubscreen.currentElements.push([retElem, options]);
1742
- return retElem;
1743
- }
1744
- __name(elementCreateDropdown, "elementCreateDropdown");
1745
- function elementCreateTooltip() {
1746
- const element = ElementCreate({
1747
- tag: "div",
1748
- classList: ["deeplib-tooltip"],
1749
- attributes: {
1750
- id: "deeplib-tooltip"
1751
- },
1752
- style: {
1753
- display: "none"
1754
- }
1755
- });
1756
- return element;
1757
- }
1758
- __name(elementCreateTooltip, "elementCreateTooltip");
1759
- function elementGetTooltip() {
1760
- return document.getElementById("deeplib-tooltip") ?? void 0;
1761
- }
1762
- __name(elementGetTooltip, "elementGetTooltip");
1763
- function elementSetTooltip(text) {
1764
- const element = document.getElementById("deeplib-tooltip");
1765
- if (!element) return false;
1766
- element.innerHTML = text;
1767
- if (text === "") element.style.display = "none";
1768
- else element.style.display = "";
1769
- return true;
1770
- }
1771
- __name(elementSetTooltip, "elementSetTooltip");
1772
- function elementPrevNext(options) {
1773
- const elem = document.getElementById(options.id);
1774
- if (elem) return elem;
1775
- const setLabel = /* @__PURE__ */ __name((label) => {
1776
- const elem2 = document.getElementById(`${options.id}-label`);
1777
- if (!elem2) return false;
1778
- elem2.textContent = label;
1779
- }, "setLabel");
1780
- const setPrevTooltip = /* @__PURE__ */ __name((tooltip) => {
1781
- const elem2 = document.getElementById(`deeplib-prev-next-${options.id}-prev-button-tooltip`);
1782
- if (!elem2) return false;
1783
- elem2.textContent = tooltip;
1784
- }, "setPrevTooltip");
1785
- const setNextTooltip = /* @__PURE__ */ __name((tooltip) => {
1786
- const elem2 = document.getElementById(`deeplib-prev-next-${options.id}-next-button-tooltip`);
1787
- if (!elem2) return false;
1788
- elem2.textContent = tooltip;
1789
- }, "setNextTooltip");
1790
- const retElem = ElementCreate({
1791
- tag: "div",
1792
- classList: ["deeplib-prev-next"],
1793
- attributes: {
1794
- id: options.id
1795
- },
1796
- children: [
1797
- advElement.createButton({
1798
- id: `deeplib-prev-next-${options.id}-prev-button`,
1799
- onClick: /* @__PURE__ */ __name(() => {
1800
- options.back({
1801
- setLabel,
1802
- setBackTooltip: setPrevTooltip,
1803
- setNextTooltip
1804
- });
1805
- }, "onClick"),
1806
- htmlOptions: {
1807
- button: {
1808
- classList: ["deeplib-prev-next-button"]
1809
- }
1810
- },
1811
- options: {
1812
- noStyling: true,
1813
- image: `${PUBLIC_URL}/dl_images/arrow_left.svg`,
1814
- tooltip: options.initialPrevTooltip
1815
- }
1816
- }),
1817
- advElement.createLabel({
1818
- id: `${options.id}-label`,
1819
- label: options.initialLabel,
1820
- htmlOptions: {
1821
- classList: ["deeplib-prev-next-label"]
1822
- }
1823
- }),
1824
- advElement.createButton({
1825
- id: `deeplib-prev-next-${options.id}-next-button`,
1826
- onClick: /* @__PURE__ */ __name(() => {
1827
- options.next({
1828
- setLabel,
1829
- setBackTooltip: setPrevTooltip,
1830
- setNextTooltip
1831
- });
1832
- }, "onClick"),
1833
- htmlOptions: {
1834
- button: {
1835
- classList: ["deeplib-prev-next-button"]
1836
- }
1837
- },
1838
- options: {
1839
- noStyling: true,
1840
- image: `${PUBLIC_URL}/dl_images/arrow_right.svg`,
1841
- tooltip: options.initialNextTooltip
1842
- }
1843
- })
1844
- ]
1845
- });
1846
- return retElem;
1847
- }
1848
- __name(elementPrevNext, "elementPrevNext");
1849
- var Modal = class _Modal {
1850
- constructor(opts) {
1851
- this.opts = opts;
1852
- opts ??= {};
1853
- opts.closeOnBackdrop ??= true;
1854
- const promptId = `modal-prompt-${Date.now()}`;
1855
- const prompt = (CommonIsArray(opts.prompt) ? opts.prompt : [opts.prompt]).filter((i) => i != null) ?? [""];
1856
- this.dialog = ElementCreate({
1857
- tag: "dialog",
1858
- classList: ["deeplib-modal"],
1859
- attributes: {
1860
- role: "dialog",
1861
- "aria-modal": "true",
1862
- "aria-labelledby": promptId
1863
- },
1864
- style: {
1865
- fontFamily: CommonGetFontName()
1866
- },
1867
- children: [
1868
- {
1869
- tag: "div",
1870
- classList: ["deeplib-modal-prompt-container"],
1871
- children: [
1872
- ...prompt
1873
- ]
1874
- },
1875
- {
1876
- tag: "div",
1877
- classList: ["deeplib-modal-prompt"],
1878
- attributes: {
1879
- id: promptId
1880
- },
1881
- children: [
1882
- opts.input ? this.renderInput(opts.input) : void 0
1883
- ]
1884
- },
1885
- this.renderButtons()
1886
- ]
1887
- });
1888
- this.blocker = this.createBlocker();
1889
- this.renderButtons();
1890
- document.body.append(this.createBlocker(), this.dialog);
1891
- this.setupFocusTrap();
1892
- if (opts.timeoutMs) {
1893
- this.timeoutId = window.setTimeout(() => this.close("timeout"), opts.timeoutMs);
1894
- }
1895
- }
1896
- static {
1897
- __name(this, "Modal");
1898
- }
1899
- dialog;
1900
- blocker;
1901
- inputEl;
1902
- timeoutId;
1903
- /** Static modal queue. */
1904
- static queue = [];
1905
- /** Flag to indicate if a modal is currently being shown. */
1906
- static processing = false;
1907
- /**
1908
- * Displays the modal and resolves with the chosen action and input value.
1909
- */
1910
- show() {
1911
- return _Modal.enqueue(this);
1912
- }
1913
- /**
1914
- * Shows a simple alert modal with a single "OK" button.
1915
- */
1916
- static async alert(msg, timeoutMs) {
1917
- await new _Modal({
1918
- prompt: msg,
1919
- buttons: [{ action: "close", text: getText("modal.button.ok") }],
1920
- timeoutMs,
1921
- escapeAction: "close"
1922
- }).show();
1923
- }
1924
- /**
1925
- * Shows a confirmation modal with "Cancel" and "OK" buttons.
1926
- * Returns true if "OK" is clicked.
1927
- */
1928
- static async confirm(msg) {
1929
- const [action] = await new _Modal({
1930
- prompt: msg,
1931
- buttons: [{ text: getText("modal.button.decline"), action: "decline" }, { text: getText("modal.button.confirm"), action: "confirm" }],
1932
- escapeAction: "decline",
1933
- enterAction: "confirm"
1934
- }).show();
1935
- return action === "confirm";
1936
- }
1937
- /**
1938
- * Shows a prompt modal with an input field and "Submit"/"Cancel" buttons.
1939
- * Returns the input value if submitted, otherwise null.
1940
- */
1941
- static async prompt(msg, defaultValue = "") {
1942
- const [action, value] = await new _Modal({
1943
- prompt: msg,
1944
- timeoutMs: 0,
1945
- input: { type: "input", defaultValue },
1946
- buttons: [{ text: getText("modal.button.cancel"), action: "cancel" }, { text: getText("modal.button.submit"), action: "submit" }],
1947
- escapeAction: "cancel",
1948
- enterAction: "submit"
1949
- }).show();
1950
- return action === "submit" ? value : null;
1951
- }
1952
- /** Creates the input element for the modal, applying configuration and validation. */
1953
- renderInput(cfg) {
1954
- const el = document.createElement(cfg.type);
1955
- el.classList.add("deeplib-modal-input");
1956
- if (cfg.placeholder) el.placeholder = cfg.placeholder;
1957
- if (cfg.readOnly) el.readOnly = true;
1958
- if (cfg.defaultValue) el.value = cfg.defaultValue;
1959
- if (cfg.type === "textarea") el.rows = 5;
1960
- el.addEventListener("input", () => {
1961
- const err = cfg.validate?.(el.value);
1962
- el.setCustomValidity(err || "");
1963
- });
1964
- this.inputEl = el;
1965
- return el;
1966
- }
1967
- /** Creates modal action buttons from configuration. */
1968
- renderButtons() {
1969
- const container = document.createElement("div");
1970
- container.classList.add("deeplib-modal-button-container");
1971
- const btns = this.opts.buttons ? [...this.opts.buttons] : [];
1972
- btns.forEach((b) => {
1973
- const btn = advElement.createButton({
1974
- id: `deeplib-modal-${b.action}`,
1975
- onClick: /* @__PURE__ */ __name(() => this.close(b.action), "onClick"),
1976
- options: {
1977
- disabled: b.disabled,
1978
- label: b.text
1979
- }
1980
- });
1981
- container.append(btn);
1982
- });
1983
- return container;
1984
- }
1985
- /** Creates the modal backdrop blocker with optional click-to-close behavior. */
1986
- createBlocker() {
1987
- const blocker = document.createElement("div");
1988
- blocker.classList.add("deeplib-modal-blocker");
1989
- blocker.title = "Click to close";
1990
- if (this.opts.closeOnBackdrop !== false)
1991
- blocker.addEventListener("click", () => this.close("close"));
1992
- return blocker;
1993
- }
1994
- /** Implements a focus trap to keep keyboard navigation inside the modal. */
1995
- setupFocusTrap() {
1996
- const focusable = 'button, [href], input, textarea, select, [tabindex]:not([tabindex="-1"])';
1997
- const elements = Array.from(this.dialog.querySelectorAll(focusable));
1998
- const first = elements[0];
1999
- const last = elements[elements.length - 1];
2000
- this.dialog.addEventListener("keydown", (e) => {
2001
- if (e.key === "Tab") {
2002
- if (elements.length === 0) {
2003
- e.preventDefault();
2004
- return;
2005
- }
2006
- if (e.shiftKey) {
2007
- if (document.activeElement === first) {
2008
- last.focus();
2009
- e.preventDefault();
2010
- }
2011
- } else {
2012
- if (document.activeElement === last) {
2013
- first.focus();
2014
- e.preventDefault();
2015
- }
2016
- }
2017
- } else if (e.key === "Escape") {
2018
- e.stopPropagation();
2019
- this.close(this.opts.escapeAction ?? "close");
2020
- } else if (e.key === "Enter") {
2021
- if (elements.some((el) => el === document.activeElement) && document.activeElement !== this.inputEl) return;
2022
- e.preventDefault();
2023
- e.stopPropagation();
2024
- this.close(this.opts.enterAction ?? "submit");
2025
- }
2026
- });
2027
- window.requestAnimationFrame(() => {
2028
- (this.inputEl || first)?.focus();
2029
- });
2030
- }
2031
- /** Closes the modal, cleans up DOM, resolves promise, and shows next queued modal. */
2032
- close(action) {
2033
- if (this.timeoutId) clearTimeout(this.timeoutId);
2034
- this.dialog.close();
2035
- this.dialog.remove();
2036
- this.blocker.remove();
2037
- document.body.querySelector(".deeplib-modal-blocker")?.remove();
2038
- const value = this.inputEl?.value ?? "";
2039
- this.resolve([action, value]);
2040
- _Modal.dequeue();
2041
- }
2042
- /**
2043
- * An internal function where we will save promise function.
2044
- */
2045
- resolve = /* @__PURE__ */ __name(() => {
2046
- }, "resolve");
2047
- /** A function that adds a modal to the queue and returns a promise */
2048
- static enqueue(modal) {
2049
- _Modal.queue.push(modal);
2050
- if (!_Modal.processing) _Modal.dequeue();
2051
- return new Promise((resolve) => modal.resolve = resolve);
2052
- }
2053
- /** A function that processes the queue, removing the first modal */
2054
- static dequeue() {
2055
- const modal = _Modal.queue.shift();
2056
- if (modal) {
2057
- _Modal.processing = true;
2058
- modal.dialog.show();
2059
- } else {
2060
- _Modal.processing = false;
2061
- }
2062
- }
2063
- };
2064
-
2065
- // src/screens/main_menu.ts
2066
- var MainMenu = class _MainMenu extends BaseSubscreen {
2067
- static {
2068
- __name(this, "MainMenu");
2069
- }
2070
- subscreens = [];
2071
- static options = {};
2072
- static subscreenOptions = {
2073
- name: "mainmenu",
2074
- doShowExitButton: false,
2075
- settingsWidth: 600
2076
- };
2077
- constructor(module) {
2078
- super(module);
2079
- this.subscreens = module.subscreens;
2080
- }
2081
- load() {
2082
- if (!GUI.instance || CurrentModule !== "DeepLibMod") {
2083
- this.setSubscreen(this);
2084
- return;
2085
- }
2086
- super.load();
2087
- const exitButton = advElement.createButton({
2088
- id: "exit",
2089
- size: [90, 90],
2090
- onClick: /* @__PURE__ */ __name(() => {
2091
- this.exit();
2092
- }, "onClick"),
2093
- options: {
2094
- image: `${PUBLIC_URL}/dl_images/exit.svg`,
2095
- tooltip: getText("settings.button.back_button_hint")
2096
- }
2097
- });
2098
- const menu = document.getElementById("deeplib-nav-menu");
2099
- if (menu) {
2100
- ElementMenu.AppendButton(menu, exitButton);
2101
- }
2102
- for (const screen of this.subscreens) {
2103
- if (screen.options.name == "mainmenu") continue;
2104
- const button = advElement.createButton({
2105
- id: `${screen.options.name}-button`,
2106
- onClick: /* @__PURE__ */ __name(() => {
2107
- this.setSubscreen(screen);
2108
- }, "onClick"),
2109
- size: [null, 90],
2110
- options: {
2111
- image: screen.options.icon,
2112
- label: getText(`mainmenu.button.${screen.options.name}`)
2113
- }
2114
- });
2115
- layout.appendToSettingsDiv(button);
2116
- }
2117
- const miscDiv = layout.getMiscDiv();
2118
- layout.appendToSubscreen(miscDiv);
2119
- if (_MainMenu.options.wikiLink) {
2120
- const wikiButton = advElement.createButton({
2121
- id: "deeplib-wiki-button",
2122
- onClick: /* @__PURE__ */ __name(() => {
2123
- window.open(_MainMenu.options.wikiLink, "_blank");
2124
- }, "onClick"),
2125
- size: [null, 80],
2126
- options: {
2127
- image: `${PUBLIC_URL}/dl_images/notebook.svg`,
2128
- label: getText("mainmenu.button.wiki")
2129
- }
2130
- });
2131
- layout.appendToMiscDiv(wikiButton);
2132
- }
2133
- if (_MainMenu.options.repoLink) {
2134
- const repoButton = advElement.createButton({
2135
- id: "deeplib-repo-button",
2136
- onClick: /* @__PURE__ */ __name(() => {
2137
- window.open(_MainMenu.options.repoLink, "_blank");
2138
- }, "onClick"),
2139
- size: [null, 80],
2140
- options: {
2141
- image: `${PUBLIC_URL}/dl_images/git.svg`,
2142
- label: getText("mainmenu.button.repo")
2143
- }
2144
- });
2145
- layout.appendToMiscDiv(repoButton);
2146
- }
2147
- if (_MainMenu.options.resetSubscreen) {
2148
- const resetButton = advElement.createButton({
2149
- id: "deeplib-reset-button",
2150
- onClick: /* @__PURE__ */ __name(() => {
2151
- this.setSubscreen(_MainMenu.options.resetSubscreen);
2152
- }, "onClick"),
2153
- size: [null, 80],
2154
- options: {
2155
- image: `${PUBLIC_URL}/dl_images/trash_bin.svg`,
2156
- label: getText("mainmenu.button.reset")
2157
- }
2158
- });
2159
- layout.appendToMiscDiv(resetButton);
2160
- }
2161
- if (_MainMenu.options.importExportSubscreen) {
2162
- const importExportButton = advElement.createButton({
2163
- id: "deeplib-import-export-button",
2164
- onClick: /* @__PURE__ */ __name(() => {
2165
- this.setSubscreen(_MainMenu.options.importExportSubscreen);
2166
- }, "onClick"),
2167
- size: [null, 80],
2168
- options: {
2169
- image: `${PUBLIC_URL}/dl_images/transfer.svg`,
2170
- label: getText("mainmenu.button.import_export")
2171
- }
2172
- });
2173
- layout.appendToMiscDiv(importExportButton);
2174
- }
2175
- if (_MainMenu.options.storageFullnessIndicator) {
2176
- const maxStorageCapacityKB = 180;
2177
- const currentStorageCapacityKB = byteToKB(ModStorage.measureSize(modStorage.extensionStorage));
2178
- const fullness = (currentStorageCapacityKB / maxStorageCapacityKB * 100).toFixed(1);
2179
- const storageFullnessWrapper = advElement.createButton({
2180
- id: CommonGenerateUniqueID(),
2181
- size: [null, 80],
2182
- options: {
2183
- tooltipPosition: "left",
2184
- noStyling: true,
2185
- tooltip: CommonStringPartitionReplace(getText("mainmenu.meter.storage_hint"), {
2186
- $percentage$: `${fullness}`
2187
- }).join(""),
2188
- label: CommonStringPartitionReplace(getText("mainmenu.meter.storage_label"), {
2189
- $currentCapacity$: `${currentStorageCapacityKB}`,
2190
- $maxCapacity$: `${maxStorageCapacityKB}`
2191
- }).join("")
2192
- },
2193
- htmlOptions: {
2194
- button: {
2195
- children: [
2196
- {
2197
- tag: "div",
2198
- attributes: { id: "deeplib-storage-meter" },
2199
- children: [
2200
- {
2201
- tag: "div",
2202
- attributes: { id: "deeplib-storage-bar" },
2203
- style: { width: `${fullness}%` }
2204
- }
2205
- ]
2206
- }
2207
- ]
2208
- }
2209
- }
2210
- });
2211
- layout.appendToMiscDiv(storageFullnessWrapper);
2212
- }
2213
- if (IS_DEBUG) {
2214
- const debugButton = advElement.createButton({
2215
- id: "deeplib-debug-button",
2216
- onClick: /* @__PURE__ */ __name(() => {
2217
- this.setSubscreen(new GuiDebug());
2218
- }, "onClick"),
2219
- size: [90, 90],
2220
- options: {
2221
- image: `${PUBLIC_URL}/dl_images/bug.svg`
2222
- }
2223
- });
2224
- if (menu) {
2225
- ElementMenu.PrependItem(menu, debugButton);
2226
- }
2227
- }
2228
- }
2229
- run() {
2230
- super.run();
2231
- }
2232
- click() {
2233
- }
2234
- exit() {
2235
- CharacterAppearanceForceUpCharacter = -1;
2236
- CharacterLoadCanvas(Player);
2237
- const returnScreen = typeof this.options.returnScreen === "function" ? this.options.returnScreen() : this.options.returnScreen;
2238
- if (!returnScreen) {
2239
- PreferenceOpenSubscreen("Extensions").then(() => {
2240
- PreferenceSubscreenExtensionsClear();
2241
- });
2242
- } else if (returnScreen instanceof BaseSubscreen) {
2243
- setSubscreen(returnScreen).then(() => {
2244
- });
2245
- } else if (Array.isArray(returnScreen)) {
2246
- CommonSetScreen(...returnScreen);
2247
- }
2248
- }
2249
- resize() {
2250
- super.resize();
2251
- ElementSetPosition("deeplib-misc", 1905, 930, "bottom-right");
2252
- ElementSetSize("deeplib-misc", 405, null);
2253
- }
2254
- static setOptions(mainMenuOptions) {
2255
- _MainMenu.options = mainMenuOptions;
2256
- }
2257
- };
2258
-
2259
- // src/screens/import_export.ts
2260
- var GuiImportExport = class extends BaseSubscreen {
2261
- static {
2262
- __name(this, "GuiImportExport");
2263
- }
2264
- importExportOptions;
2265
- static subscreenOptions = {
2266
- name: "import-export"
2267
- };
2268
- constructor(importExportOptions) {
2269
- super();
2270
- this.importExportOptions = importExportOptions;
2271
- }
2272
- load() {
2273
- super.load();
2274
- const importFromFileButton = advElement.createButton({
2275
- id: "deeplib-import-file-button",
2276
- size: [600, 90],
2277
- onClick: /* @__PURE__ */ __name(() => {
2278
- this.dataImport("file");
2279
- }, "onClick"),
2280
- options: {
2281
- image: `${PUBLIC_URL}/dl_images/file_import.svg`,
2282
- label: getText("import-export.button.import_file")
2283
- }
2284
- });
2285
- layout.appendToSettingsDiv(importFromFileButton);
2286
- const exportToFileButton = advElement.createButton({
2287
- id: "deeplib-export-file-button",
2288
- size: [600, 90],
2289
- onClick: /* @__PURE__ */ __name(() => {
2290
- this.dataExport("file");
2291
- }, "onClick"),
2292
- options: {
2293
- image: `${PUBLIC_URL}/dl_images/file_export.svg`,
2294
- label: getText("import-export.button.export_file")
2295
- }
2296
- });
2297
- layout.appendToSettingsDiv(exportToFileButton);
2298
- const importFromClipboardButton = advElement.createButton({
2299
- id: "deeplib-import-clipboard-button",
2300
- size: [600, 90],
2301
- onClick: /* @__PURE__ */ __name(() => {
2302
- this.dataImport("clipboard");
2303
- }, "onClick"),
2304
- options: {
2305
- image: `${PUBLIC_URL}/dl_images/clipboard_import.svg`,
2306
- label: getText("import-export.button.import_clipboard")
2307
- }
2308
- });
2309
- layout.appendToSettingsDiv(importFromClipboardButton);
2310
- const exportToClipboardButton = advElement.createButton({
2311
- id: "deeplib-export-clipboard-button",
2312
- size: [600, 90],
2313
- onClick: /* @__PURE__ */ __name(() => {
2314
- this.dataExport("clipboard");
2315
- }, "onClick"),
2316
- options: {
2317
- image: `${PUBLIC_URL}/dl_images/clipboard_export.svg`,
2318
- label: getText("import-export.button.export_clipboard")
2319
- }
2320
- });
2321
- layout.appendToSettingsDiv(exportToClipboardButton);
2322
- }
2323
- resize() {
2324
- super.resize();
2325
- }
2326
- /** Exports the mod data using the specified method. */
2327
- async dataExport(transferMethod) {
2328
- try {
2329
- const data = LZString.compressToBase64(JSON.stringify(modStorage.playerStorage));
2330
- if (transferMethod === "clipboard") {
2331
- await this.exportToClipboard(data);
2332
- } else if (transferMethod === "file") {
2333
- if (!await this.exportToFile(data, "settings")) {
2334
- return;
2335
- }
2336
- ;
2337
- }
2338
- this.importExportOptions.onExport?.();
2339
- ToastManager.success("Data exported successfully.");
2340
- } catch (error) {
2341
- ToastManager.error("Data export failed.");
2342
- deepLibLogger.error(`Data export failed for ${ModSdkManager.ModInfo.name}.`, error);
2343
- }
2344
- }
2345
- /** Imports mod data using the specified method. */
2346
- async dataImport(transferMethod) {
2347
- try {
2348
- let importedData = "";
2349
- if (transferMethod === "clipboard") {
2350
- importedData = await this.importFromClipboard() ?? null;
2351
- } else if (transferMethod === "file") {
2352
- importedData = await this.importFromFile() ?? null;
2353
- }
2354
- if (!importedData) {
2355
- throw new Error("No data imported.");
2356
- }
2357
- const data = JSON.parse(LZString.decompressFromBase64(importedData) ?? "");
2358
- if (!data) {
2359
- throw new Error("Invalid data.");
2360
- }
2361
- for (const module of modules()) {
2362
- module.registerDefaultSettings(data);
2363
- }
2364
- modStorage.playerStorage = data;
2365
- this.importExportOptions.onImport?.();
2366
- ToastManager.success("Data imported successfully.");
2367
- } catch (error) {
2368
- ToastManager.error("Data import failed.");
2369
- deepLibLogger.error(`Data import failed for ${ModSdkManager.ModInfo.name}.`, error);
2370
- }
2371
- }
2372
- /** Saves data to a file using the browser's save dialog. */
2373
- async exportToFile(data, defaultFileName) {
2374
- const CUSTOM_EXTENSION = this.importExportOptions.customFileExtension.startsWith(".") ? this.importExportOptions.customFileExtension : "." + this.importExportOptions.customFileExtension;
2375
- const suggestedName = defaultFileName.endsWith(CUSTOM_EXTENSION) ? defaultFileName : defaultFileName + CUSTOM_EXTENSION;
2376
- if ("showSaveFilePicker" in window) {
2377
- try {
2378
- const handle = await window.showSaveFilePicker({
2379
- suggestedName,
2380
- types: [
2381
- {
2382
- description: "Custom Data Files",
2383
- accept: { "text/plain": [CUSTOM_EXTENSION] }
2384
- }
2385
- ]
2386
- });
2387
- const writable = await handle.createWritable();
2388
- await writable.write(data);
2389
- await writable.close();
2390
- return true;
2391
- } catch (error) {
2392
- throw new Error("File save cancelled or failed: " + error.message);
2393
- }
2394
- } else {
2395
- const fileName = await Modal.prompt("Enter file name", suggestedName);
2396
- if (fileName === null) {
2397
- return false;
2398
- } else if (fileName === "") {
2399
- throw new Error("File name cannot be empty.");
2400
- }
2401
- const blob = new Blob([data], { type: "text/plain" });
2402
- const link = ElementCreate({
2403
- tag: "a",
2404
- attributes: {
2405
- href: URL.createObjectURL(blob),
2406
- download: fileName.endsWith(CUSTOM_EXTENSION) ? fileName : fileName + CUSTOM_EXTENSION
2407
- }
2408
- });
2409
- link.click();
2410
- URL.revokeObjectURL(link.href);
2411
- return true;
2412
- }
2413
- }
2414
- /** Opens a file picker and reads the selected file's contents, importing the data. */
2415
- async importFromFile() {
2416
- const CUSTOM_EXTENSION = this.importExportOptions.customFileExtension.startsWith(".") ? this.importExportOptions.customFileExtension : "." + this.importExportOptions.customFileExtension;
2417
- async function importFromFileInternal(file) {
2418
- if (!file.name.endsWith(CUSTOM_EXTENSION)) {
2419
- throw new Error(`Invalid file type. Expected a ${CUSTOM_EXTENSION} file.`);
2420
- }
2421
- return new Promise((resolve, reject) => {
2422
- const reader = new FileReader();
2423
- reader.onload = () => resolve(reader.result);
2424
- reader.onerror = () => reject(new Error("Failed to read file."));
2425
- reader.readAsText(file);
2426
- });
2427
- }
2428
- __name(importFromFileInternal, "importFromFileInternal");
2429
- if ("showOpenFilePicker" in window) {
2430
- try {
2431
- const [fileHandle] = await window.showOpenFilePicker({
2432
- types: [
2433
- {
2434
- description: "Custom Data Files",
2435
- accept: { "text/plain": [CUSTOM_EXTENSION] }
2436
- }
2437
- ],
2438
- multiple: false
2439
- });
2440
- const file = await fileHandle.getFile();
2441
- return await importFromFileInternal(file);
2442
- } catch (error) {
2443
- throw new Error("File selection cancelled or failed: " + error.message);
2444
- }
2445
- } else {
2446
- return new Promise((resolve, reject) => {
2447
- const input = document.createElement("input");
2448
- input.type = "file";
2449
- input.accept = CUSTOM_EXTENSION;
2450
- input.onchange = async (event) => {
2451
- const file = event.target.files?.[0];
2452
- if (file) {
2453
- try {
2454
- const data = await importFromFileInternal(file);
2455
- resolve(data);
2456
- } catch (error) {
2457
- reject(error);
2458
- }
2459
- } else {
2460
- reject(new Error("No file selected."));
2461
- }
2462
- };
2463
- input.click();
2464
- });
2465
- }
2466
- }
2467
- /** Copies the given data to the clipboard. */
2468
- async exportToClipboard(data) {
2469
- return navigator.clipboard.writeText(data).catch((error) => {
2470
- throw new Error("Failed to copy data to clipboard." + error);
2471
- });
2472
- }
2473
- /** Prompts the user to enter data and returns it. */
2474
- async importFromClipboard() {
2475
- return Modal.prompt("Enter data to import").catch((error) => {
2476
- throw new Error("Failed to read data from clipboard." + error);
2477
- });
2478
- }
2479
- };
2480
-
2481
- // src/utilities/data.ts
2482
- var ModStorage = class _ModStorage {
2483
- static {
2484
- __name(this, "ModStorage");
2485
- }
2486
- /** Singleton instance of ModStorage */
2487
- static _instance = null;
2488
- /** The unique mod identifier used as key prefix in storage */
2489
- modName;
2490
- constructor(modName) {
2491
- if (!_ModStorage._instance) {
2492
- _ModStorage._instance = this;
2493
- this.modName = modName;
2494
- }
2495
- this.modName ??= modName;
2496
- return _ModStorage._instance;
2497
- }
2498
- get playerStorage() {
2499
- return Player[this.modName];
2500
- }
2501
- set playerStorage(value) {
2502
- Player[this.modName] = value;
2503
- }
2504
- get extensionStorage() {
2505
- return Player.ExtensionSettings[this.modName];
2506
- }
2507
- set extensionStorage(value) {
2508
- Player.ExtensionSettings[this.modName] = value;
2509
- }
2510
- setLocalStorage(key, value) {
2511
- localStorage.setItem(`${this.modName}_${key}`, _ModStorage.dataCompress(value));
2512
- }
2513
- getLocalStorage(key) {
2514
- const data = localStorage.getItem(`${this.modName}_${key}`);
2515
- if (!data) return null;
2516
- return _ModStorage.dataDecompress(data);
2517
- }
2518
- load() {
2519
- if (this.extensionStorage) {
2520
- const parsed = _ModStorage.dataDecompress(this.extensionStorage || "");
2521
- if (parsed === null || !Object.hasOwn(parsed, "Version")) {
2522
- this.playerStorage = {
2523
- Version: ModSdkManager.ModInfo.version
2524
- };
2525
- } else {
2526
- this.playerStorage = parsed;
2527
- }
2528
- ;
2529
- } else {
2530
- this.playerStorage = {};
2531
- }
2532
- }
2533
- save() {
2534
- if (!this.extensionStorage) this.extensionStorage = "";
2535
- this.extensionStorage = _ModStorage.dataCompress(this.playerStorage);
2536
- ServerPlayerExtensionSettingsSync(this.modName);
2537
- }
2538
- static dataDecompress(string) {
2539
- const d = LZString.decompressFromBase64(string);
2540
- let data = null;
2541
- try {
2542
- const decoded = JSON.parse(d);
2543
- data = decoded;
2544
- } catch (error) {
2545
- deepLibLogger.error(error);
2546
- }
2547
- return data;
2548
- }
2549
- static dataCompress(object) {
2550
- return LZString.compressToBase64(JSON.stringify(object));
2551
- }
2552
- static measureSize(data) {
2553
- try {
2554
- if (typeof data !== "string") {
2555
- data = JSON.stringify(data) || "";
2556
- }
2557
- if (typeof data === "string") {
2558
- return new TextEncoder().encode(data).byteLength;
2559
- }
2560
- throw new Error();
2561
- } catch {
2562
- return NaN;
2563
- }
2564
- }
2565
- };
2566
-
2567
- // src/utilities/elements/helpers.ts
2568
- var domUtil = {
2569
- /**
2570
- * Automatically sets the position of the element based on the given position.
2571
- * The position can be either a [x, y] tuple or a function returning such a tuple.
2572
- * If both x and y are defined, the element's position is updated accordingly.
2573
- */
2574
- autoSetPosition,
2575
- /**
2576
- * Automatically sets the size of the element based on the given size.
2577
- * The size can be either a [width, height] tuple or a function returning such a tuple.
2578
- * If both width and height are defined, the element's size is updated accordingly.
2579
- */
2580
- autoSetSize,
2581
- /**
2582
- * Hides the element by setting its CSS display property to 'none'.
2583
- * If the element cannot be found, the function does nothing.
2584
- */
2585
- hide,
2586
- /**
2587
- * Unhides the element by clearing its CSS display property (sets it to '').
2588
- * If the element cannot be found, the function does nothing.
2589
- */
2590
- unhide,
2591
- /**
2592
- * Checks if the element has overflow content.
2593
- * Returns an object indicating if there is any overflow,
2594
- * and specifically if there is vertical or horizontal overflow.
2595
- * Returns null if the element is not found.
2596
- */
2597
- hasOverflow
2598
- };
2599
- function autoSetPosition(_, position) {
2600
- let xPos = void 0;
2601
- let yPos = void 0;
2602
- if (Array.isArray(position)) {
2603
- xPos = position[0];
2604
- yPos = position[1];
2605
- } else if (typeof position === "function") {
2606
- const result = position();
2607
- xPos = result[0];
2608
- yPos = result[1];
2609
- }
2610
- if (xPos !== void 0 && yPos !== void 0) ElementSetPosition(_, xPos, yPos);
2611
- }
2612
- __name(autoSetPosition, "autoSetPosition");
2613
- function autoSetSize(_, size) {
2614
- let width = void 0;
2615
- let height = void 0;
2616
- if (Array.isArray(size)) {
2617
- width = size[0];
2618
- height = size[1];
2619
- } else if (typeof size === "function") {
2620
- const result = size();
2621
- width = result[0];
2622
- height = result[1];
2623
- }
2624
- if (width !== void 0 && height !== void 0) ElementSetSize(_, width, height);
2625
- }
2626
- __name(autoSetSize, "autoSetSize");
2627
- function hide(_) {
2628
- const element = ElementWrap(_);
2629
- if (!element) return;
2630
- element.style.display = "none";
2631
- }
2632
- __name(hide, "hide");
2633
- function unhide(_) {
2634
- const element = ElementWrap(_);
2635
- if (!element) return;
2636
- element.style.display = "";
2637
- }
2638
- __name(unhide, "unhide");
2639
- function hasOverflow(el) {
2640
- const element = ElementWrap(el);
2641
- if (!element) return null;
2642
- const vertical = element.scrollHeight > element.clientHeight;
2643
- const horizontal = element.scrollWidth > element.clientWidth;
2644
- return {
2645
- any: vertical || horizontal,
2646
- vertical,
2647
- horizontal
2648
- };
2649
- }
2650
- __name(hasOverflow, "hasOverflow");
2651
356
 
2652
- // src/utilities/elements/layout.ts
2653
- var layout = {
2654
- getSubscreen: elementGetSubscreenDiv,
2655
- appendToSubscreen: elementAppendToSubscreenDiv,
2656
- removeSubscreen: elementRemoveSubscreenDiv,
2657
- getSettingsDiv: elementGetSettingsDiv,
2658
- appendToSettingsDiv: elementAppendToSettingsDiv,
2659
- removeSettingsDiv: elementRemoveSettingsDiv,
2660
- getMiscDiv: elementGetMiscDiv,
2661
- appendToMiscDiv: elementAppendToMiscDiv,
2662
- removeMiscDiv: elementRemoveMiscDiv
2663
- };
2664
- function elementGetSubscreenDiv() {
2665
- const subscreenDiv = ElementWrap("deeplib-subscreen");
2666
- if (subscreenDiv) {
2667
- return subscreenDiv;
2668
- }
2669
- const div = ElementCreate({
2670
- tag: "div",
2671
- classList: ["deeplib-subscreen", "HideOnPopup"],
2672
- attributes: { id: "deeplib-subscreen" }
2673
- });
2674
- return document.body.appendChild(div);
2675
- }
2676
- __name(elementGetSubscreenDiv, "elementGetSubscreenDiv");
2677
- function elementRemoveSubscreenDiv() {
2678
- return elementGetSubscreenDiv()?.remove();
2679
- }
2680
- __name(elementRemoveSubscreenDiv, "elementRemoveSubscreenDiv");
2681
- function elementAppendToSubscreenDiv(...element) {
2682
- return elementGetSubscreenDiv()?.append(...element);
2683
- }
2684
- __name(elementAppendToSubscreenDiv, "elementAppendToSubscreenDiv");
2685
- function elementGetSettingsDiv() {
2686
- const settingsDiv = ElementWrap("deeplib-settings");
2687
- if (settingsDiv) {
2688
- return settingsDiv;
2689
- }
2690
- const div = ElementCreate({
2691
- tag: "div",
2692
- classList: ["deeplib-settings", "scroll-box"],
2693
- attributes: { id: "deeplib-settings" }
2694
- });
2695
- return div;
2696
- }
2697
- __name(elementGetSettingsDiv, "elementGetSettingsDiv");
2698
- function elementAppendToSettingsDiv(...element) {
2699
- return elementGetSettingsDiv()?.append(...element);
2700
- }
2701
- __name(elementAppendToSettingsDiv, "elementAppendToSettingsDiv");
2702
- function elementRemoveSettingsDiv() {
2703
- return elementGetSettingsDiv()?.remove();
2704
- }
2705
- __name(elementRemoveSettingsDiv, "elementRemoveSettingsDiv");
2706
- function elementGetMiscDiv() {
2707
- const miscDiv = ElementWrap("deeplib-misc");
2708
- if (miscDiv) {
2709
- return miscDiv;
2710
- }
2711
- const div = ElementCreate({
2712
- tag: "div",
2713
- classList: ["deeplib-misc"],
2714
- attributes: { id: "deeplib-misc" }
2715
- });
2716
- return div;
2717
- }
2718
- __name(elementGetMiscDiv, "elementGetMiscDiv");
2719
- function elementAppendToMiscDiv(...element) {
2720
- return elementGetMiscDiv()?.append(...element);
2721
- }
2722
- __name(elementAppendToMiscDiv, "elementAppendToMiscDiv");
2723
- function elementRemoveMiscDiv() {
2724
- return elementGetMiscDiv()?.remove();
2725
- }
2726
- __name(elementRemoveMiscDiv, "elementRemoveMiscDiv");
2727
-
2728
- // src/utilities/logger.ts
2729
- var Logger = class _Logger extends Array {
2730
- static {
2731
- __name(this, "Logger");
2732
- }
2733
- ModName = "DeepLib";
2734
- constructor(modName) {
2735
- super();
2736
- if (modName) {
2737
- this.ModName = modName;
2738
- }
2739
- }
2740
- _Log(level, ...args) {
2741
- const logEntry = {
2742
- logLevel: level,
2743
- args: [...args],
2744
- // trace: arguments.callee.caller.toString().split('\n'),
2745
- date: new Date(Date.now())
2746
- // `[${this.ModName}] ${formattedArgs}`
2747
- };
2748
- const userAgent = navigator.userAgent.toLowerCase();
2749
- if (userAgent.includes("chrome") || userAgent.includes("firefox")) {
2750
- const color = _Logger.colorizeLog(level);
2751
- args.forEach((arg) => {
2752
- if (typeof arg === "string") {
2753
- arg = `
2754
- %c${arg}`;
2755
- }
2756
- });
2757
- console.log(`%c${this.ModName}:`, color, ...args);
2758
- } else {
2759
- console.log(`${this.ModName}:`, ...args);
2760
- }
2761
- this.push(logEntry);
2762
- }
2763
- info(...args) {
2764
- this._Log("info", ...args);
2765
- }
2766
- log(...args) {
2767
- this._Log("log", ...args);
2768
- }
2769
- warn(...args) {
2770
- this._Log("warn", ...args);
2771
- }
2772
- error(...args) {
2773
- this._Log("error", ...args);
2774
- }
2775
- debug(...args) {
2776
- this._Log("debug", ...args);
2777
- }
2778
- static colorizeLog(logLevel) {
2779
- const colors = {
2780
- info: "color: #32CCCC",
2781
- log: "color: #CCCC32",
2782
- warn: "color: #eec355",
2783
- error: "color: #750b0b",
2784
- debug: "color: #9E4BCF"
2785
- };
2786
- return colors[logLevel];
2787
- }
2788
- };
2789
- var deepLibLogger = new Logger();
2790
-
2791
- // src/utilities/messages.ts
2792
- function sendLocalMessage(id, message, timeoutInSeconds) {
2793
- const element = ElementCreate({
2794
- tag: "div",
2795
- classList: ["ChatMessage", "deeplib-message", "ChatMessageNonDialogue"],
2796
- attributes: {
2797
- id: id ?? `DEEPLIB_LOCAL_MESSAGE_${Date.now()}`,
2798
- "data-time": ChatRoomCurrentTime(),
2799
- "data-sender": Player.MemberNumber?.toString()
2800
- },
2801
- children: [
2802
- {
2803
- tag: "span",
2804
- classList: ["deeplib-text"],
2805
- innerHTML: message.replaceAll("\n ", "")
2806
- },
2807
- {
2808
- tag: "br"
2809
- },
2810
- {
2811
- tag: "a",
2812
- classList: ["deeplib-text"],
2813
- attributes: {
2814
- href: "#"
2815
- },
2816
- innerHTML: "<b>Close (Click)</b>",
2817
- eventListeners: {
2818
- click: /* @__PURE__ */ __name(() => {
2819
- element.remove();
2820
- }, "click")
2821
- }
2822
- }
2823
- ]
2824
- });
2825
- ChatRoomAppendChat(element);
2826
- if (!timeoutInSeconds) return;
2827
- setTimeout(() => element.remove(), timeoutInSeconds * 1e3);
2828
- }
2829
- __name(sendLocalMessage, "sendLocalMessage");
2830
- function sendActionMessage(msg, target = void 0, dictionary = []) {
2831
- if (!msg) return;
2832
- ServerSend("ChatRoomChat", {
2833
- Content: "DEEPLIB_CUSTOM_ACTION",
2834
- Type: "Action",
2835
- Target: target ?? void 0,
2836
- Dictionary: [
2837
- { Tag: 'MISSING TEXT IN "Interface.csv": DEEPLIB_CUSTOM_ACTION', Text: msg },
2838
- ...dictionary
2839
- ]
2840
- });
357
+ #deeplib-modal-import_export .deeplib-modal-checkbox-container {
358
+ margin-top: 0.5em;
359
+ display: flex;
360
+ flex-direction: column;
361
+ gap: var(--half-gap);
2841
362
  }
2842
- __name(sendActionMessage, "sendActionMessage");
2843
-
2844
- // src/utilities/sdk.ts
2845
- var import_bondage_club_mod_sdk = __toESM(require_bcmodsdk(), 1);
2846
- var rawSdk = import_bondage_club_mod_sdk.default;
2847
- var bcModSdkRef = rawSdk.default ?? rawSdk;
2848
- var HookPriority = {
2849
- Observe: 0,
2850
- AddBehavior: 1,
2851
- ModifyBehavior: 5,
2852
- OverrideBehavior: 10,
2853
- Top: 100
2854
- };
2855
- var ModSdkManager = class _ModSdkManager {
2856
- static {
2857
- __name(this, "ModSdkManager");
2858
- }
2859
- static SDK;
2860
- static patchedFunctions = /* @__PURE__ */ new Map();
2861
- static ModInfo;
2862
- /** Registers a mod with the SDK and stores mod information. */
2863
- constructor(info, options) {
2864
- _ModSdkManager.SDK = bcModSdkRef.registerMod(info, options);
2865
- _ModSdkManager.ModInfo = info;
2866
- }
2867
- /** Retrieves or initializes patch data for a given target function. */
2868
- initPatchableFunction(target) {
2869
- let result = _ModSdkManager.patchedFunctions.get(target);
2870
- if (!result) {
2871
- result = {
2872
- name: target,
2873
- hooks: []
2874
- };
2875
- _ModSdkManager.patchedFunctions.set(target, result);
2876
- }
2877
- return result;
2878
- }
2879
- /**
2880
- * Hooks a function with a callback at a given priority.
2881
- *
2882
- * Prevents duplicate hooks.
2883
- */
2884
- hookFunction(target, priority, hook, module = null) {
2885
- const data = this.initPatchableFunction(target);
2886
- if (data.hooks.some((h) => h.hook === hook)) {
2887
- return () => null;
2888
- }
2889
- const removeCallback = _ModSdkManager.SDK?.hookFunction(target, priority, hook);
2890
- data.hooks.push({
2891
- hook,
2892
- priority,
2893
- module,
2894
- removeCallback
2895
- });
2896
- data.hooks.sort((a, b) => b.priority - a.priority);
2897
- return removeCallback;
2898
- }
2899
- /**
2900
- * Applies patches to a target function.
2901
- *
2902
- * **This method is DANGEROUS** to use and has high potential to conflict with other mods.
2903
- */
2904
- patchFunction(target, patches) {
2905
- _ModSdkManager.SDK?.patchFunction(target, patches);
2906
- }
2907
- /**
2908
- * Removes all patches from a target function.
2909
- */
2910
- unpatchFunction(target) {
2911
- _ModSdkManager.SDK?.removePatches(target);
2912
- }
2913
- /**
2914
- * Removes all hooks associated with a specific module from a target function.
2915
- */
2916
- removeHookByModule(target, module) {
2917
- const data = this.initPatchableFunction(target);
2918
- for (let i = data.hooks.length - 1; i >= 0; i--) {
2919
- if (data.hooks[i].module === module) {
2920
- data.hooks[i].removeCallback();
2921
- data.hooks.splice(i, 1);
2922
- }
2923
- }
2924
- return true;
2925
- }
2926
- /**
2927
- * Removes all hooks associated with a specific module across all patched functions.
2928
- */
2929
- removeAllHooksByModule(module) {
2930
- for (const data of _ModSdkManager.patchedFunctions.values()) {
2931
- for (let i = data.hooks.length - 1; i >= 0; i--) {
2932
- if (data.hooks[i].module === module) {
2933
- data.hooks[i].removeCallback();
2934
- data.hooks.splice(i, 1);
2935
- }
2936
- }
2937
- }
2938
- return true;
2939
- }
2940
- };
2941
-
2942
- // src/utilities/style.ts
2943
- var Style = {
2944
- /**
2945
- * Injects a CSS style block directly into the document head using a <style> tag.
2946
- * If a style element with the same `styleId` already exists, it won't inject again.
2947
- */
2948
- injectInline(styleId, styleSource) {
2949
- const isStyleLoaded = document.getElementById(styleId);
2950
- if (isStyleLoaded) return;
2951
- const styleElement = document.createElement("style");
2952
- styleElement.id = styleId;
2953
- styleElement.appendChild(document.createTextNode(styleSource));
2954
- document.head.appendChild(styleElement);
2955
- },
2956
- /**
2957
- * Injects a CSS stylesheet link into the document head using a <link> tag.
2958
- * If a link element with the same `styleId` already exists, it won't inject again.
2959
- */
2960
- injectEmbed(styleId, styleLink) {
2961
- const isStyleLoaded = document.getElementById(styleId);
2962
- if (isStyleLoaded) return;
2963
- const styleElement = document.createElement("link");
2964
- styleElement.id = styleId;
2965
- styleElement.rel = "stylesheet";
2966
- styleElement.href = styleLink;
2967
- document.head.appendChild(styleElement);
2968
- },
2969
- /**
2970
- * Removes a style element from the document head by its ID.
2971
- * Does nothing if the element is not found.
2972
- */
2973
- eject(id) {
2974
- const style = document.getElementById(id);
2975
- if (!style) return;
2976
- style.remove();
2977
- },
2978
- /**
2979
- * Reloads an inline style by removing the existing style element (if any)
2980
- * and injecting the new styles inline again.
2981
- */
2982
- reload(styleId, styleSource) {
2983
- Style.eject(styleId);
2984
- Style.injectInline(styleId, styleSource);
2985
- },
2986
- /** Fetches the text content of a stylesheet or any resource at the given link. */
2987
- async fetch(link) {
2988
- return fetch(link).then((res) => res.text());
2989
- }
2990
- };
2991
-
2992
- // src/utilities/translation.ts
2993
- var Localization = class _Localization {
2994
- static {
2995
- __name(this, "Localization");
2996
- }
2997
- static LibTranslation = {};
2998
- static ModTranslation = {};
2999
- static PathToModTranslation;
3000
- static PathToLibTranslation = `${PUBLIC_URL}/dl_translations/`;
3001
- static DefaultLanguage = "en";
3002
- /** Flag to prevent re-initialization */
3003
- static initialized = false;
3004
- /** Initialize the localization system by loading translation files. */
3005
- static async init(initOptions) {
3006
- if (_Localization.initialized) return;
3007
- _Localization.initialized = true;
3008
- _Localization.PathToModTranslation = (() => {
3009
- if (!initOptions?.pathToTranslationsFolder) return void 0;
3010
- return initOptions.pathToTranslationsFolder.endsWith("/") ? initOptions.pathToTranslationsFolder : `${initOptions.pathToTranslationsFolder}/`;
3011
- })();
3012
- _Localization.DefaultLanguage = initOptions?.defaultLanguage || _Localization.DefaultLanguage;
3013
- const lang = initOptions?.fixedLanguage ? _Localization.DefaultLanguage : TranslationLanguage.toLowerCase();
3014
- const libTranslation = await _Localization.fetchLanguageFile(_Localization.PathToLibTranslation, lang);
3015
- if (lang === _Localization.DefaultLanguage) {
3016
- _Localization.LibTranslation = libTranslation;
3017
- } else {
3018
- const fallbackTranslation = await _Localization.fetchLanguageFile(_Localization.PathToLibTranslation, _Localization.DefaultLanguage);
3019
- _Localization.LibTranslation = { ...fallbackTranslation, ...libTranslation };
3020
- }
3021
- if (!_Localization.PathToModTranslation) return;
3022
- const modTranslation = await _Localization.fetchLanguageFile(_Localization.PathToModTranslation, lang);
3023
- if (lang === _Localization.DefaultLanguage) {
3024
- _Localization.ModTranslation = modTranslation;
3025
- } else {
3026
- const fallbackTranslation = await _Localization.fetchLanguageFile(_Localization.PathToModTranslation, _Localization.DefaultLanguage);
3027
- _Localization.ModTranslation = { ...fallbackTranslation, ...modTranslation };
3028
- }
3029
- }
3030
- /** Get a translated string from mod translations by source tag. */
3031
- static getTextMod(srcTag) {
3032
- return _Localization.ModTranslation?.[srcTag] || void 0;
3033
- }
3034
- /** Get a translated string from library translations by source tag. */
3035
- static getTextLib(srcTag) {
3036
- return _Localization.LibTranslation?.[srcTag] || void 0;
3037
- }
3038
- /**
3039
- * Fetch and parse a language file from the given base URL and language code.
3040
- * Falls back to default language if the requested language file is unavailable.
3041
- */
3042
- static async fetchLanguageFile(baseUrl, lang) {
3043
- const response = await fetch(`${baseUrl}${lang}.lang`);
3044
- if (lang !== _Localization.DefaultLanguage && !response.ok) {
3045
- return this.fetchLanguageFile(baseUrl, _Localization.DefaultLanguage);
3046
- }
3047
- if (!response.ok) {
3048
- return {};
3049
- }
3050
- const langFileContent = await response.text();
3051
- return this.parseLanguageFile(langFileContent);
3052
- }
3053
- /**
3054
- * Parse the raw content of a language file into a TranslationDict.
3055
- * Ignores empty lines and comments starting with '#'.
3056
- */
3057
- static parseLanguageFile(content) {
3058
- const translations = {};
3059
- const lines = content.split("\n");
3060
- for (const line of lines) {
3061
- const trimmed = line.trim();
3062
- if (!trimmed || trimmed.startsWith("#")) continue;
3063
- const [key, ...rest] = trimmed.split("=");
3064
- translations[key.trim()] = rest.join("=").trim();
3065
- }
3066
- return translations;
3067
- }
3068
- };
3069
- var getText = /* @__PURE__ */ __name((srcTag) => {
3070
- return Localization.getTextMod(srcTag) || Localization.getTextLib(srcTag) || srcTag;
3071
- }, "getText");
3072
-
3073
- // src/utilities/event_channel.ts
3074
- var EventChannel = class {
3075
- constructor(channelName) {
3076
- this.channelName = channelName;
3077
- ModSdkManager.prototype.hookFunction("ChatRoomMessageProcessHidden", 0, (args, next) => {
3078
- if (!this.isChannelMessage(args[0])) {
3079
- return next(args);
3080
- }
3081
- const [message, sender] = args;
3082
- const { type, data } = message.Dictionary[0];
3083
- const listeners = this.listeners[type];
3084
- if (listeners) {
3085
- listeners.forEach((listener) => listener(data, sender));
3086
- }
3087
- return next(args);
3088
- }, `EventChannel-${channelName}`);
3089
- }
3090
- static {
3091
- __name(this, "EventChannel");
3092
- }
3093
- listeners = {};
3094
- unload() {
3095
- Object.keys(this.listeners).forEach((key) => delete this.listeners[key]);
3096
- ModSdkManager.prototype.removeHookByModule("ChatRoomMessageProcessHidden", `EventChannel-${this.channelName}`);
3097
- }
3098
- sendEvent(type, data, target = null) {
3099
- const packet = {
3100
- Type: "Hidden",
3101
- Content: this.channelName,
3102
- Sender: Player.MemberNumber,
3103
- ...target ? { Target: target } : {},
3104
- Dictionary: [
3105
- {
3106
- type,
3107
- data
3108
- }
3109
- ]
3110
- };
3111
- ServerSend("ChatRoomChat", packet);
3112
- }
3113
- registerListener(event, listener) {
3114
- const listeners = this.listeners[event] ?? [];
3115
- listeners.push(listener);
3116
- this.listeners[event] = listeners;
3117
- return () => this.unregisterListener(event, listener);
3118
- }
3119
- unregisterListener(event, listener) {
3120
- const listeners = this.listeners[event];
3121
- if (listeners) {
3122
- const index = listeners.indexOf(listener);
3123
- if (index !== -1) {
3124
- listeners.splice(index, 1);
3125
- }
3126
- }
3127
- }
3128
- isChannelMessage(message) {
3129
- return message && message.Type === "Hidden" && message.Content === this.channelName && message.Sender && message.Sender !== Player.MemberNumber && message.Dictionary && !!message.Dictionary[0]?.data && !!message.Dictionary[0]?.type || false;
3130
- }
3131
- };
3132
- export {
3133
- BaseMigrator,
3134
- BaseModule,
3135
- BaseSubscreen,
3136
- EventChannel,
3137
- GUI,
3138
- GuiDebug,
3139
- GuiImportExport,
3140
- HookPriority,
3141
- Localization,
3142
- Logger,
3143
- MainMenu,
3144
- ModSdkManager,
3145
- ModStorage,
3146
- Modal,
3147
- Style,
3148
- VersionModule,
3149
- advElement,
3150
- byteToKB,
3151
- deepLibLogger,
3152
- deepMerge,
3153
- domUtil,
3154
- exportToGlobal,
3155
- getModule,
3156
- getText,
3157
- hasGetter,
3158
- hasSetter,
3159
- initMod,
3160
- layout,
3161
- logger,
3162
- modStorage,
3163
- modules,
3164
- modulesMap,
3165
- registerModule,
3166
- sdk,
3167
- sendActionMessage,
3168
- sendLocalMessage,
3169
- setSubscreen,
3170
- shuffleArray,
3171
- unloadMod
3172
- };
363
+ /*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VSb290IjoiL2hvbWUvZGVvL0NvZGUvYmMvQkMtRGVlcExpYi9zcmMvc3R5bGVzIiwic291cmNlcyI6WyJ2YXJzLnNjc3MiLCJidXR0b25zLnNjc3MiLCJlbGVtZW50cy5zY3NzIiwiaW5wdXRzLnNjc3MiLCJtZXNzYWdlcy5zY3NzIiwibW9kYWwuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQUFBO0VBRUU7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7OztBQ2RGO0VBQ0U7RUFDQTtFQUNBOztBQUVBO0VBRUU7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBRUE7RUFDQTtFQUNBOztBQUdGO0VBQ0U7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTs7QUFHRjtFQUNFOzs7QUMzQ0o7RUFDRTtFQUNBO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7OztBQUdGO0VBQ0U7RUFDQTtFQUNBOzs7QUFHRjtFQUNFO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTtFQUNBO0VBQ0E7RUFDQTs7QUFHRjtFQUNFO0VBQ0E7RUFDQTtFQUNBOzs7QUFJSjtFQUNFOzs7QUFHRjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7QUFHRTtFQUNFO0VBQ0E7O0FBSEo7RUFNRTtFQUNBOztBQUdGO0VBQ0U7RUFDQTs7O0FBSUo7RUFDRTtFQUNBO0VBQ0E7RUFDQTs7QUFFQTtFQUNFOzs7QUFJSjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOztBQUVBO0VBQ0U7RUFDQTtFQUNBOzs7QUNqSUo7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBOztBQUVBO0VBQ0U7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTtFQUNBOzs7QUFLTjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTs7QUFHRjtFQUNFO0VBQ0E7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTtFQUNBOzs7QUFPUjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOztBQUVBO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7O0FBR0Y7RUFDRTs7O0FDdkZKO0VBQ0U7RUFDQTs7O0FBR0Y7QUFBQTtFQUVFO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0FBQUE7RUFFRTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7OztBQzdCRjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTtFQUNBO0VBQ0E7RUFDQTs7QUFHRjtFQUNFOztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7QUFFQTtFQUNFO0VBQ0E7RUFDQTtFQUNBOztBQUVBO0VBQ0U7O0FBS047RUFDRTtFQUNBO0VBQ0E7RUFDQTs7O0FBSUo7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7O0FBSUE7RUFDRTtFQUNBO0VBQ0E7RUFDQSIsInNvdXJjZXNDb250ZW50IjpbIi5kZWVwbGliLXN1YnNjcmVlbixcbi5kZWVwbGliLW1vZGFsIHtcbiAgLS1kZWVwbGliLWJhY2tncm91bmQtY29sb3I6IHZhcigtLXRtZC1tYWluLCB3aGl0ZSk7XG4gIC0tZGVlcGxpYi1lbGVtZW50LWNvbG9yOiB2YXIoLS10bWQtZWxlbWVudCwgd2hpdGUpO1xuICAtLWRlZXBsaWItZWxlbWVudC1ob3Zlci1jb2xvcjogdmFyKC0tdG1kLWVsZW1lbnQtaG92ZXIsIGN5YW4pO1xuICAtLWRlZXBsaWItYWNjZW50LWNvbG9yOiB2YXIoLS10bWQtYWNjZW50LCAjRkZGRjg4KTtcbiAgLS1kZWVwbGliLWJsb2NrZWQtY29sb3I6IHZhcigtLXRtZC1ibG9ja2VkLCByZWQpO1xuICAtLWRlZXBsaWItdGV4dC1jb2xvcjogdmFyKC0tdG1kLXRleHQsIGJsYWNrKTtcbiAgLS1kZWVwbGliLWljb24tY29sb3I6IHZhcigtLXRtZC1hY2NlbnQsIGJsYWNrKTtcbiAgLS1kZWVwbGliLWljb24taG92ZXItY29sb3I6IHZhcigtLXRtZC1hY2NlbnQtaG92ZXIsIGJsYWNrKTtcbiAgLS1kZWVwbGliLWJvcmRlci1jb2xvcjogdmFyKC0tdG1kLWFjY2VudCwgYmxhY2spO1xuICAtLWRlZXBsaWItYm9yZGVyLXdpZHRoOiBtaW4oMC4ydmgsIDAuMXZ3KTtcbiAgLS1kZWVwbGliLWJvcmRlci13aWR0aDogbWluKDAuMmR2aCwgMC4xZHZ3KTtcbiAgLS1kZWVwbGliLWJvcmRlci1yYWRpdXM6IG1pbigxdmgsIDAuNXZ3KTtcbiAgLS1kZWVwbGliLWJvcmRlci1yYWRpdXM6IG1pbigxZHZoLCAwLjVkdncpO1xufVxuIiwiLmRlZXBsaWItYnV0dG9uIHtcbiAgY29sb3I6IHZhcigtLWRlZXBsaWItdGV4dC1jb2xvcik7XG4gIHdpZHRoOiAxMDAlO1xuICBoZWlnaHQ6IDEwMCU7XG5cbiAgJi5idXR0b24tc3R5bGluZyxcbiAgJi5idXR0b24tc3R5bGluZzo6YmVmb3JlIHtcbiAgICBib3JkZXItcmFkaXVzOiBtaW4oMS4wZHZoLCAwLjVkdncpO1xuICB9XG5cbiAgaW1nIHtcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgdG9wOiAwJTtcbiAgICBsZWZ0OiAwJTtcbiAgICB3aWR0aDogMTAwJTtcbiAgICBoZWlnaHQ6IDEwMCU7XG4gICAgYmFja2dyb3VuZC1wb3NpdGlvbjogbGVmdDtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1kZWVwbGliLWljb24tY29sb3IpO1xuICAgIGJhY2tncm91bmQtYmxlbmQtbW9kZTogbXVsdGlwbHk7XG4gICAgYmFja2dyb3VuZC1zaXplOiBjb250YWluO1xuICAgIG1hc2stcG9zaXRpb246IGxlZnQ7XG4gICAgbWFzay1zaXplOiBjb250YWluO1xuICAgIGJhY2tncm91bmQtcmVwZWF0OiBuby1yZXBlYXQ7XG4gICAgbWFzay1yZXBlYXQ6IG5vLXJlcGVhdDtcbiAgICBjb2xvcjogdHJhbnNwYXJlbnQ7XG5cbiAgICBiYWNrZ3JvdW5kLWltYWdlOiB2YXIoLS1pbWFnZSk7XG4gICAgbWFzay1pbWFnZTogdmFyKC0taW1hZ2UpO1xuICAgIHBvaW50ZXItZXZlbnRzOiBub25lO1xuICB9XG5cbiAgJjpob3ZlciBpbWcge1xuICAgIGJhY2tncm91bmQtY29sb3I6IHZhcigtLWRlZXBsaWItaWNvbi1ob3Zlci1jb2xvcik7XG4gIH1cblxuICAuYnV0dG9uLWxhYmVsIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudCAhaW1wb3J0YW50O1xuICAgIGNvbG9yOiB2YXIoLS1kZWVwbGliLXRleHQtY29sb3IpO1xuICAgIGZvbnQtc2l6ZTogbWluKDMuNmR2aCwgMS44ZHZ3KTtcbiAgICBkaXNwbGF5OiBjb250ZW50cztcbiAgfVxuXG4gIC5idXR0b24tdG9vbHRpcCB7XG4gICAgYm9yZGVyLXJhZGl1czogbWluKDEuMGR2aCwgMC41ZHZ3KTtcbiAgfVxufSIsIiNkZWVwbGliLXBhZ2UtbGFiZWwge1xuICBkaXNwbGF5OiBmbGV4O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgcG9pbnRlci1ldmVudHM6IG5vbmU7XG59XG5cbiNkZWVwbGliLXN1YnNjcmVlbi10aXRsZSB7XG4gIHRleHQtYWxpZ246IGxlZnQ7XG4gIGNvbG9yOiB2YXIoLS1kZWVwbGliLXRleHQtY29sb3IpO1xuICB1c2VyLXNlbGVjdDogbm9uZTtcbiAgcG9pbnRlci1ldmVudHM6IG5vbmU7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG59XG5cbi5kZWVwbGliLXRleHQge1xuICBjb2xvcjogdmFyKC0tZGVlcGxpYi10ZXh0LWNvbG9yKTtcbn1cblxuLmRlZXBsaWItc3Vic2NyZWVuIHtcbiAgcGFkZGluZzogMDtcbiAgbWFyZ2luOiAwO1xuICBwb2ludGVyLWV2ZW50czogbm9uZTtcbn1cblxuLmRlZXBsaWItc3Vic2NyZWVuICoge1xuICBib3gtc2l6aW5nOiBib3JkZXItYm94O1xuICBwb2ludGVyLWV2ZW50czogYWxsO1xufVxuXG4uZGVlcGxpYi1zZXR0aW5ncyB7XG4gIGRpc3BsYXk6IGdyaWQ7XG4gIGdyaWQtYXV0by1yb3dzOiBtaW4tY29udGVudDtcbiAgcGFkZGluZzogbWluKDEuMGR2aCwgMC41ZHZ3KTtcbiAgZ2FwOiAwLjNlbTtcbn1cblxuLmRlZXBsaWItbWlzYyB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW4tcmV2ZXJzZTtcbiAgZ2FwOiBtaW4oMXZoLCAwLjV2dyk7XG59XG5cbi5kZWVwbGliLXRvb2x0aXAge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1kZWVwbGliLWVsZW1lbnQtY29sb3IpO1xuICBjb2xvcjogdmFyKC0tZGVlcGxpYi10ZXh0LWNvbG9yKTtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG4gIGJvcmRlci1yYWRpdXM6IG1pbigxLjBkdmgsIDAuNWR2dyk7XG4gIHBhZGRpbmc6IG1pbigxdmgsIDAuNXZ3KTtcbiAgZm9udC1zaXplOiAwLjhlbTtcbiAgYm9yZGVyOiBtaW4oMC4ydmgsIDAuMXZ3KSBzb2xpZCB2YXIoLS1kZWVwbGliLWJvcmRlci1jb2xvcik7XG4gIHotaW5kZXg6IDE7XG5cbiAgJi5hbmNob3ItdG9wIHtcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgdG9wOiBtaW4oMXZoLCAwLjV2dyk7XG4gICAgbGVmdDogNTAlO1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlWCgtNTAlKTtcbiAgfVxuXG4gICYuYW5jaG9yLWJvdHRvbSB7XG4gICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgIGJvdHRvbTogbWluKDF2aCwgMC41dncpO1xuICAgIGxlZnQ6IDUwJTtcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoLTUwJSk7XG4gIH1cbn1cblxuLmRlZXBsaWItb3ZlcmZsb3ctYm94IHtcbiAgYm9yZGVyOiB2YXIoLS1kZWVwbGliLWJvcmRlci1jb2xvcikgc29saWQgdmFyKC0tZGVlcGxpYi1ib3JkZXItd2lkdGgpO1xufVxuXG4uZGVlcGxpYi1wcmV2LW5leHQge1xuICBkaXNwbGF5OiBmbGV4O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XG4gIGZsZXgtZGlyZWN0aW9uOiByb3c7XG4gIGdhcDogbWluKDJkdmgsIDFkdncpO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1kZWVwbGliLWVsZW1lbnQtY29sb3IpO1xuICBjb2xvcjogdmFyKC0tZGVlcGxpYi10ZXh0LWNvbG9yKTtcbiAgYm9yZGVyLXJhZGl1czogbWluKDEuMGR2aCwgMC41ZHZ3KTtcbiAgYm9yZGVyOiBtaW4oMC4ydmgsIDAuMXZ3KSBzb2xpZCB2YXIoLS1kZWVwbGliLWJvcmRlci1jb2xvcik7XG5cbiAgLmRlZXBsaWItcHJldi1uZXh0LWJ1dHRvbiB7XG4gICAgJjpob3ZlciB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1kZWVwbGliLWVsZW1lbnQtaG92ZXItY29sb3IpO1xuICAgICAgYm9yZGVyLXJhZGl1czogdmFyKC0tZGVlcGxpYi1ib3JkZXItcmFkaXVzKTtcbiAgICB9XG5cbiAgICBoZWlnaHQ6IDEwMCU7XG4gICAgYXNwZWN0LXJhdGlvOiAxO1xuICB9XG5cbiAgLmRlZXBsaWItcHJldi1uZXh0LWxhYmVsIHtcbiAgICB3aGl0ZS1zcGFjZTogbm93cmFwO1xuICAgIHVzZXItc2VsZWN0OiBub25lO1xuICB9XG59XG5cbiNkZWVwbGliLW5hdi1tZW51IHtcbiAgZGlzcGxheTogZmxleDtcbiAgZmxleC1kaXJlY3Rpb246IHJvdztcbiAgZ2FwOiBtaW4oMmR2aCwgMWR2dyk7XG4gIHotaW5kZXg6IDE7XG5cbiAgJj4uZGVlcGxpYi1idXR0b24ge1xuICAgIGZsZXg6IDEgMCBhdXRvO1xuICB9XG59XG5cbiNkZWVwbGliLXN0b3JhZ2UtbWV0ZXIge1xuICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gIHRvcDogMHB4O1xuICBsZWZ0OiAwcHg7XG4gIHdpZHRoOiAxMDAlO1xuICBoZWlnaHQ6IDEwMCU7XG4gIG92ZXJmbG93OiBoaWRkZW47XG4gIGJhY2tncm91bmQtY29sb3I6IHZhcigtLWRlZXBsaWItZWxlbWVudC1jb2xvcik7XG4gIGJvcmRlcjogdmFyKC0tZGVlcGxpYi1ib3JkZXItd2lkdGgpIHNvbGlkIHZhcigtLWRlZXBsaWItYm9yZGVyLWNvbG9yKTtcbiAgYm9yZGVyLXJhZGl1czogdmFyKC0tZGVlcGxpYi1ib3JkZXItcmFkaXVzKTtcbiAgei1pbmRleDogLTE7XG5cbiAgI2RlZXBsaWItc3RvcmFnZS1iYXIge1xuICAgIGhlaWdodDogMTAwJTtcbiAgICB3aWR0aDogMCU7XG4gICAgYmFja2dyb3VuZDogdmFyKC0tZGVlcGxpYi1hY2NlbnQtY29sb3IpO1xuICB9XG59IiwiLmRlZXBsaWItY2hlY2tib3gtY29udGFpbmVyIHtcbiAgZGlzcGxheTogZmxleDtcbiAgZmxleC1kaXJlY3Rpb246IHJvdztcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgZ2FwOiAwLjNlbTtcbiAgd2lkdGg6IGZpdC1jb250ZW50O1xuXG4gIHNwYW4ge1xuICAgIHVzZXItc2VsZWN0OiBub25lO1xuICB9XG5cbiAgLmRlZXBsaWItaW5wdXQge1xuICAgIHdpZHRoOiBtaW4oNXZoLCAyLjV2dyk7XG4gICAgaGVpZ2h0OiBtaW4oNXZoLCAyLjV2dyk7XG4gICAgd2lkdGg6IG1pbig1ZHZoLCAyLjVkdncpO1xuICAgIGhlaWdodDogbWluKDVkdmgsIDIuNWR2dyk7XG4gICAgYm9yZGVyLXJhZGl1czogbWluKDEuMHZoLCAwLjV2dyk7XG4gICAgYm9yZGVyLXJhZGl1czogbWluKDEuMGR2aCwgMC41ZHZ3KTtcblxuICAgICZbdHlwZT1cImNoZWNrYm94XCJdOmNoZWNrZWQ6OmJlZm9yZSB7XG4gICAgICB3aWR0aDogODAlO1xuICAgICAgaGVpZ2h0OiA4MCU7XG4gICAgfVxuICB9XG59XG5cbi5kZWVwbGliLWlucHV0LWNvbnRhaW5lciB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiByb3c7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGdhcDogMC4zZW07XG4gIHdpZHRoOiBmaXQtY29udGVudDtcblxuICBzcGFuIHtcbiAgICB1c2VyLXNlbGVjdDogbm9uZTtcbiAgfVxuXG4gICY6aGFzKC5kZWVwbGliLXRleHQpIHtcbiAgICBtYXJnaW4tdG9wOiBtaW4oMXZoLCAwLjV2dyk7XG4gICAgbWFyZ2luLXRvcDogbWluKDFkdmgsIDAuNWR2dyk7XG4gIH1cblxuICAuZGVlcGxpYi1pbnB1dCB7XG4gICAgZm9udC1zaXplOiAwLjZlbTtcbiAgICBwYWRkaW5nOiBtaW4oMXZoLCAwLjV2dyk7XG4gICAgcGFkZGluZzogbWluKDFkdmgsIDAuNWR2dyk7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7XG4gICAgb3V0bGluZTogbm9uZTtcbiAgICBtaW4taGVpZ2h0OiBtaW4oNXZoLCAyLjV2dyk7XG4gICAgbWluLWhlaWdodDogbWluKDVkdmgsIDIuNWR2dyk7XG4gICAgYm9yZGVyLXJhZGl1czogbWluKDEuMHZoLCAwLjV2dyk7XG4gICAgYm9yZGVyLXJhZGl1czogbWluKDEuMGR2aCwgMC41ZHZ3KTtcblxuICAgICZbdHlwZT1cImNvbG9yXCJdIHtcbiAgICAgIHBhZGRpbmc6IDBweDtcbiAgICAgIHdpZHRoOiBtaW4oNXZoLCAyLjV2dyk7XG4gICAgICBoZWlnaHQ6IG1pbig1dmgsIDIuNXZ3KTtcbiAgICAgIHdpZHRoOiBtaW4oNWR2aCwgMi41ZHZ3KTtcbiAgICAgIGhlaWdodDogbWluKDVkdmgsIDIuNWR2dyk7XG4gICAgICBib3JkZXItcmFkaXVzOiAwcHg7XG5cbiAgICAgICY6ZGlzYWJsZWQge1xuICAgICAgICBib3JkZXI6IHZhcigtLWRlZXBsaWItYmxvY2tlZC1jb2xvcikgc29saWQgdmFyKC0tZGVlcGxpYi1ib3JkZXItd2lkdGgpO1xuICAgICAgICBjdXJzb3I6IG5vdC1hbGxvd2VkO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5cbi5kZWVwbGliLWRyb3Bkb3duLWNvbnRhaW5lciB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiByb3c7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGdhcDogbWluKDJ2aCwgMXZ3KTtcbiAgZ2FwOiBtaW4oMmR2aCwgMWR2dyk7XG4gIGNvbG9yOiB2YXIoLS1kZWVwbGliLXRleHQtY29sb3IpO1xuICB3aWR0aDogZml0LWNvbnRlbnQ7XG5cbiAgc2VsZWN0IHtcbiAgICBwYWRkaW5nOiAwIG1pbigxdmgsIDAuNXZ3KTtcbiAgICBwYWRkaW5nOiAwIG1pbigxZHZoLCAwLjVkdncpO1xuICAgIGJvcmRlci1yYWRpdXM6IG1pbigxdmgsIDAuNXZ3KTtcbiAgICBib3JkZXItcmFkaXVzOiBtaW4oMWR2aCwgMC41ZHZ3KTtcbiAgfVxuXG4gIHNwYW4ge1xuICAgIHVzZXItc2VsZWN0OiBub25lO1xuICB9XG59IiwiLmRlZXBsaWItaGlnaGxpZ2h0LXRleHQge1xuICBmb250LXdlaWdodDogYm9sZDtcbiAgY29sb3I6IHJnYigyMDMsIDE4NSwgMjMpO1xufVxuXG4jVGV4dEFyZWFDaGF0TG9nW2RhdGEtY29sb3J0aGVtZT0nZGFyayddIGRpdi5DaGF0TWVzc2FnZS5kZWVwbGliLW1lc3NhZ2UsXG4jVGV4dEFyZWFDaGF0TG9nW2RhdGEtY29sb3J0aGVtZT0nZGFyazInXSBkaXYuQ2hhdE1lc3NhZ2UuZGVlcGxpYi1tZXNzYWdlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tZGVlcGxpYi1lbGVtZW50LWNvbG9yKTtcbiAgYm9yZGVyOiBtaW4oMC4yZHZoLCAwLjFkdncpIHNvbGlkIHZhcigtLWRlZXBsaWItYm9yZGVyLWNvbG9yKTtcbiAgY29sb3I6IHZhcigtLWRlZXBsaWItdGV4dC1jb2xvcik7XG59XG5cbiNUZXh0QXJlYUNoYXRMb2cgZGl2LkNoYXRNZXNzYWdlLmRlZXBsaWItbWVzc2FnZSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNlZWU7XG4gIGJvcmRlcjogbWluKDAuMmR2aCwgMC4xZHZ3KSBzb2xpZCAjNDQwMTcxO1xuICBjb2xvcjogIzExMTtcbiAgcGFkZGluZy1sZWZ0OiBtaW4oMC42ZHZoLCAwLjNkdncpO1xuICBkaXNwbGF5OiBibG9jaztcbiAgd2hpdGUtc3BhY2U6IG5vcm1hbDtcbn1cblxuI1RleHRBcmVhQ2hhdExvZ1tkYXRhLWNvbG9ydGhlbWU9J2RhcmsnXSBkaXYuQ2hhdE1lc3NhZ2UuZGVlcGxpYi1tZXNzYWdlIGEsXG4jVGV4dEFyZWFDaGF0TG9nW2RhdGEtY29sb3J0aGVtZT0nZGFyazInXSBkaXYuQ2hhdE1lc3NhZ2UuZGVlcGxpYi1tZXNzYWdlIGEge1xuICBjb2xvcjogdmFyKC0tZGVlcGxpYi10ZXh0LWNvbG9yKTtcbn1cblxuI1RleHRBcmVhQ2hhdExvZyBkaXYuQ2hhdE1lc3NhZ2UuZGVlcGxpYi1tZXNzYWdlIGEge1xuICBjdXJzb3I6IHBvaW50ZXI7XG4gIGZvbnQtd2VpZ2h0OiBib2xkO1xuICBjb2xvcjogIzExMTtcbn1cbiIsIi5kZWVwbGliLW1vZGFsIHtcbiAgcG9zaXRpb246IGZpeGVkO1xuICB0b3A6IDEwJTtcbiAgbGVmdDogNTAlO1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoLTUwJSk7XG4gIHotaW5kZXg6IDEwMDE7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBnYXA6IDAuNWVtO1xuICB3aWR0aDogbWF4KDUwZHZ3LCAyNWR2aCk7XG4gIGZvbnQtc2l6ZTogbWluKDRkdmgsIDJkdncpO1xuICBwYWRkaW5nOiBtaW4oMmR2aCwgMWR2dyk7XG4gIGJhY2tncm91bmQtY29sb3I6IHZhcigtLWRlZXBsaWItZWxlbWVudC1jb2xvcik7XG4gIGJvcmRlci1yYWRpdXM6IG1pbigxLjJkdmgsIDAuNmR2dyk7XG4gIGJvcmRlcjogbWluKDAuMmR2aCwgMC4xZHZ3KSBzb2xpZCB2YXIoLS1kZWVwbGliLWJvcmRlci1jb2xvcik7XG4gIGNvbG9yOiB2YXIoLS1kZWVwbGliLXRleHQtY29sb3IpO1xuXG4gIC5kZWVwbGliLW1vZGFsLWlucHV0IHtcbiAgICB3aWR0aDogMTAwJTtcbiAgICBmb250LXNpemU6IG1pbigyLjZkdmgsIDEuOGR2dyk7XG4gICAgYm9yZGVyLXJhZGl1czogbWluKDEuMGR2aCwgMC41ZHZ3KTtcbiAgICBwYWRkaW5nOiBtaW4oMWR2aCwgMC41ZHZ3KTtcbiAgfVxuXG4gIGlucHV0LmRlZXBsaWItbW9kYWwtaW5wdXQge1xuICAgIG1heC13aWR0aDogbWF4KDUwZHZoLCAyNWR2dyk7XG4gIH1cblxuICAuZGVlcGxpYi1tb2RhbC1idXR0b24tY29udGFpbmVyIHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGZsZXgtZGlyZWN0aW9uOiByb3c7XG4gICAganVzdGlmeS1jb250ZW50OiBmbGV4LWVuZDtcbiAgICBnYXA6IDAuNWVtO1xuICAgIHdpZHRoOiAxMDAlO1xuXG4gICAgLmRlZXBsaWItYnV0dG9uIHtcbiAgICAgIGZvbnQtc2l6ZTogMC44ZW07XG4gICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgd2lkdGg6IGF1dG87XG4gICAgICBwYWRkaW5nOiBtaW4oMC40dmgsIDAuMnZ3KSBtaW4oMnZoLCAxdncpO1xuXG4gICAgICAuYnV0dG9uLWxhYmVsIHtcbiAgICAgICAgZGlzcGxheTogY29udGVudHM7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLmRlZXBsaWItbW9kYWwtcHJvbXB0LWNvbnRhaW5lciB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIH1cbn1cblxuLmRlZXBsaWItbW9kYWwtYmxvY2tlciB7XG4gIHotaW5kZXg6IDEwMDA7XG4gIHBvc2l0aW9uOiBmaXhlZDtcbiAgdG9wOiAwO1xuICBsZWZ0OiAwO1xuICB3aWR0aDogMTAwZHZ3O1xuICBoZWlnaHQ6IDEwMGR2aDtcbiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgwLCAwLCAwLCAwLjUpO1xufVxuXG4jZGVlcGxpYi1tb2RhbC1pbXBvcnRfZXhwb3J0IHtcbiAgLmRlZXBsaWItbW9kYWwtY2hlY2tib3gtY29udGFpbmVyIHtcbiAgICBtYXJnaW4tdG9wOiAwLjVlbTtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gICAgZ2FwOiB2YXIoLS1oYWxmLWdhcCk7XG4gIH1cbn0iXX0= */`;var F=class extends B{static{s(this,"DebugModule")}debugSettings={showRawTranslations:!1,showFileNames:!1,showIncomingServerTransactions:!1,incomingMessageFilterMode:"exclude",incomingMessageTypes:"",showOutcomingServerTransactions:!1,outcomingMessageFilterMode:"exclude",outcomingMessageTypes:"",showRawActivityNames:!1,showRawAssetNames:!1};load(){let e=u.getLocalStorage("debugOptions");e&&(this.debugSettings=Object.assign(this.debugSettings,e)),ue(),I.hookFunction("TextGet",S.ModifyBehavior,(i,n)=>{if(!this.debugSettings.showRawTranslations)return n(i);let[o]=i,r=TextScreenCache?.fileName()??"[unknown]";return this.debugSettings.showFileNames?`${r}::${o}`:o}),I.hookFunction("TextGetInScope",S.ModifyBehavior,(i,n)=>{if(!this.debugSettings.showRawTranslations)return n(i);let[o,r]=i,a=o.lastIndexOf("/");a===-1?a=0:a=a+1;let l=o.substring(a);return this.debugSettings.showFileNames?`${l}::${r}`:r}),I.hookFunction("InterfaceTextGet",S.ModifyBehavior,(i,n)=>{if(!this.debugSettings.showRawTranslations)return n(i);let[o]=i,r=InterfaceStringsPath.lastIndexOf("/");r===-1?r=0:r=r+1;let a=InterfaceStringsPath.substring(r);return this.debugSettings.showFileNames?`${a}::${o}`:o}),I.hookFunction("ActivityDictionaryText",S.ModifyBehavior,(i,n)=>{if(!this.debugSettings.showRawActivityNames)return n(i);let[o]=i;return o}),I.hookFunction("ElementButton.CreateForAsset",S.ModifyBehavior,(i,n)=>{if(!this.debugSettings.showRawAssetNames)return n(i);let[,o,,,r]=i;return o=("Asset"in o?o:{Asset:o}).Asset,r??={},r.label=o.Name,n(i)})}unload(){ge()}saveDebugSettings(){u.setLocalStorage("debugOptions",this.debugSettings)}},Z;function _(...t){let e=Array.isArray(t[0])&&typeof t[0][0]=="string"?t[0][0]:"[unknown]",i=Array.isArray(t[0])?t[0].slice(1):[],n=x("DebugModule");return n.debugSettings.showIncomingServerTransactions&&ee(e,n.debugSettings.incomingMessageTypes,n.debugSettings.incomingMessageFilterMode)&&p.debug("\u25BC Receive",e,...i),Z?.apply(this,t)}s(_,"processIncomingTransaction");var O;function q(...t){let e=typeof t[0]=="string"?t[0]:"[unknown]",i=Array.isArray(t[1])?t[1]:[t[1]],n=x("DebugModule");return n.debugSettings.showOutcomingServerTransactions&&ee(e,n.debugSettings.outcomingMessageTypes,n.debugSettings.outcomingMessageFilterMode)&&p.debug("\u25B2 Send",e,...i),O?.apply(this,t)}s(q,"processOutcomingTransaction");function ee(t,e,i){if(!e.trim())return!0;let o=e.split(",").map(r=>r.trim()).filter(r=>r.length>0).some(r=>t===r);return i==="include"?o:!o}s(ee,"shouldLogMessage");function ue(){Z===void 0&&typeof ServerSocket?.__proto__?.emitEvent=="function"&&(Z=ServerSocket.__proto__.emitEvent,ServerSocket.__proto__.emitEvent=_),O===void 0&&typeof ServerSocket?.__proto__?.emit=="function"&&(O=ServerSocket.__proto__.emit,ServerSocket.__proto__.emit=q)}s(ue,"loadServerTransactions");function ge(){Z&&ServerSocket.__proto__.emitEvent===_&&(ServerSocket.__proto__.emitEvent=Z,Z=void 0),O&&ServerSocket.__proto__.emit===q&&(ServerSocket.__proto__.emit=O,O=void 0)}s(ge,"unloadServerTransactions");var u,I,p,w;function st(t){import("https://cdn.jsdelivr.net/npm/bondage-club-mod-sdk@1.2.0/+esm").then(()=>{if(I=new E({name:t.modName,fullName:t.modName,version:MOD_VERSION,repository:t.modRepository}),w=t.modName,u=new X(t.modName),p=new V(w),N.injectInline("deeplib-style",$),p.debug("Init wait"),!CurrentScreen||CurrentScreen==="Login"){t.beforeLogin?.();let i=I.hookFunction("LoginResponse",0,(n,o)=>{p.debug("Init! LoginResponse caught: ",n),o(n);let r=n[0];if(r==="InvalidNamePassword")return o(n);r&&typeof r.Name=="string"&&typeof r.AccountName=="string"&&(te(t),i())})}else p.debug(`Already logged in, initing ${w}`),te(t)})}s(st,"initMod");async function te(t){if(window[t.modName+"Loaded"])return;u.load(),await M.init(t.translationOptions);let e=Object.entries(t.modules??{}),i=[];if(e.some(n=>n[1]instanceof R)||i.push(["VersionModule",new R]),IS_DEBUG&&!e.some(n=>n[1]instanceof F)&&i.push(["DebugModule",new F]),i.push(...e),!pe(i)){be();return}await t.initFunction?.(),t.mainMenuOptions&&x("GUI")&&k.setOptions({...t.mainMenuOptions,repoLink:t.modRepository}),window[t.modName+"Loaded"]=!0,p.log(`Loaded! Version: ${MOD_VERSION_CAPTION}`)}s(te,"init");function pe(t){for(let[e,i]of t)ie(e,i);for(let e of f()){let i=A(()=>e.init(),n=>n);i.ok||p.error(i.error)}for(let e of f()){let i=A(()=>e.load(),n=>n);i.ok||p.error(i.error)}for(let e of f()){let i=A(()=>e.run(),n=>n);i.ok||p.error(i.error)}for(let e of f())e.registerDefaultSettings(u.playerStorage);return p.debug("Modules Loaded."),!0}s(pe,"initModules");function be(){return me(),I.unload(),delete window[w+"Loaded"],p.debug("Unloaded."),!0}s(be,"unloadMod");function me(){for(let t of f())t.unload()}s(me,"unloadModules");var H=new Map;function f(){return[...H.values()]}s(f,"modules");function ie(t,e){return H.set(t,e),e}s(ie,"registerModule");function x(t){return H.get(t)}s(x,"getModule");var ne=class{static{s(this,"BaseMigrator")}};var L=class t extends B{static{s(this,"GUI")}static instance=null;_subscreens;_mainMenu;_modButtonOptions;get subscreens(){return this._subscreens}get mainMenu(){return this._mainMenu}constructor(e=null){if(super(),t.instance)throw new Error("Duplicate initialization");for(let i of f())i.settingsScreen;this._mainMenu=e?.mainMenu?new e.mainMenu(this):new k(this),this._subscreens=[this._mainMenu],this._modButtonOptions=e,t.instance=this}load(){if(this._modButtonOptions){for(let e of f())e.settingsScreen&&this._subscreens.push(new e.settingsScreen(e));this._mainMenu.subscreens=this._subscreens,PreferenceRegisterExtensionSetting({Identifier:this._modButtonOptions.identifier,ButtonText:this._modButtonOptions.buttonText,Image:this._modButtonOptions.image,load:s(async()=>{await T(this._mainMenu)},"load"),run:s(()=>{},"run"),click:s(()=>{},"click"),exit:s(()=>{},"exit")})}}};var R=class t extends B{static{s(this,"VersionModule")}static isItNewVersion=!1;static version;static newVersionMessage="";static migrators=[];static beforeEach;static afterEach;static beforeAll;static afterAll;constructor(e){super(),e??={},t.newVersionMessage=e.newVersionMessage,e.migrators&&(t.migrators=e.migrators,t.migrators.sort((i,n)=>i.migrationVersion.localeCompare(n.migrationVersion))),t.beforeEach=e.beforeEach,t.afterEach=e.afterEach,t.beforeAll=e.beforeAll,t.afterAll=e.afterAll}load(){t.version=MOD_VERSION,t.checkVersionUpdate(),u.playerStorage.GlobalModule.doShowNewVersionMessage&&t.isItNewVersion&&t.sendNewVersionMessage()}static checkVersionUpdate(){let e=t.loadVersion(),i=t.version;t.isNewVersion(e,i)&&(t.isItNewVersion=!0,t.checkVersionMigration(),t.saveVersion()),u.save()}static checkVersionMigration(){let e=t.loadVersion(),i=t.migrators.filter(n=>t.isNewVersion(e,n.migrationVersion));if(i.length){t.beforeAll?.();for(let n of i)t.beforeEach?.(),n.migrate(),p.info(`Migrating from ${e} to ${n.migrationVersion} with ${n.constructor.name}`),t.afterEach?.();t.afterAll?.()}}static sendNewVersionMessage(){if(!t.newVersionMessage)return;let i=FriendListBeepLog.push({MemberNumber:Player.MemberNumber,MemberName:w,ChatRoomName:d("module.version.version_update"),ChatRoomSpace:"X",Private:!1,Sent:!1,Time:new Date,Message:t.newVersionMessage})-1,n=CommonStringPartitionReplace(d("module.version.new_version_toast_title"),{$modName$:w,$modVersion$:t.version}).join(""),o=FriendListBeepLog[i];ServerShowBeep(t.newVersionMessage,1e4,{memberNumber:o.MemberNumber,memberName:o.MemberName,chatRoomName:o.ChatRoomName,...o.Message&&{onClick:s(()=>{FriendListShowBeep(i)},"onClick")}},n)}static isNewVersion(e,i){if(e!==void 0){let n=e.split("."),o=i.split(".");for(let r=0;r<3;r++)if(n[r]!==o[r])return o[r]>n[r]}return e===void 0||e===""||!e}static saveVersion(){u.playerStorage&&(u.playerStorage.Version=t.version)}static loadVersion(){return u.playerStorage?.Version}};var D=class extends m{static{s(this,"GuiDebug")}static subscreenOptions={name:"debug"};get pageStructure(){return[[{type:"checkbox",id:"debug-show-incoming-server-transactions",label:"Show Incoming Server Transactions",setElementValue:s(()=>this.module.debugSettings.showIncomingServerTransactions,"setElementValue"),setSettingValue:s(e=>{this.module.debugSettings.showIncomingServerTransactions=e},"setSettingValue")},{type:"dropdown",id:"debug-incoming-filter-mode",label:"Filter Mode",description:["Configure which incoming message types to show or hide.",ElementCreate({tag:"br"}),"Include: only show these message types.",ElementCreate({tag:"br"}),"Exclude: hide these message types."],optionsList:[{attributes:{value:"include",label:"Include",selected:this.module.debugSettings.incomingMessageFilterMode==="include"}},{attributes:{value:"exclude",label:"Exclude",selected:this.module.debugSettings.incomingMessageFilterMode==="exclude"}}],setSettingValue:s(e=>{this.module.debugSettings.incomingMessageFilterMode=e},"setSettingValue")},{type:"text",id:"debug-incoming-message-types",label:"Message Types",description:'Comma-separated list of message types (e.g., "ChatRoomChat, ChatRoomSync")',setElementValue:s(()=>this.module.debugSettings.incomingMessageTypes,"setElementValue"),setSettingValue:s(e=>{this.module.debugSettings.incomingMessageTypes=e},"setSettingValue")},{type:"checkbox",id:"debug-show-outcoming-server-transactions",label:"Show Outcoming Server Transactions",setElementValue:s(()=>this.module.debugSettings.showOutcomingServerTransactions,"setElementValue"),setSettingValue:s(e=>{this.module.debugSettings.showOutcomingServerTransactions=e},"setSettingValue")},{type:"dropdown",id:"debug-outcoming-filter-mode",label:"Filter Mode",description:["Configure which outcoming message types to show or hide.",ElementCreate({tag:"br"}),"Include: only show these message types.",ElementCreate({tag:"br"}),"Exclude: hide these message types."],optionsList:[{attributes:{value:"include",label:"Include",selected:this.module.debugSettings.outcomingMessageFilterMode==="include"}},{attributes:{value:"exclude",label:"Exclude",selected:this.module.debugSettings.outcomingMessageFilterMode==="exclude"}}],setSettingValue:s(e=>{this.module.debugSettings.outcomingMessageFilterMode=e},"setSettingValue")},{type:"text",id:"debug-outcoming-message-types",label:"Message Types",description:'Comma-separated list of message types (e.g., "ChatRoomMessage, AccountUpdate")',setElementValue:s(()=>this.module.debugSettings.outcomingMessageTypes,"setElementValue"),setSettingValue:s(e=>{this.module.debugSettings.outcomingMessageTypes=e},"setSettingValue")},{type:"checkbox",id:"debug-show-raw-translations",label:"Show Raw Translations",setElementValue:s(()=>this.module.debugSettings.showRawTranslations,"setElementValue"),setSettingValue:s(e=>{this.module.debugSettings.showRawTranslations=e},"setSettingValue")},{type:"checkbox",id:"debug-show-file-names",label:"Show File Names",description:"Show the file name of the translation in the translation string.",setElementValue:s(()=>this.module.debugSettings.showFileNames,"setElementValue"),setSettingValue:s(e=>{this.module.debugSettings.showFileNames=e},"setSettingValue")},{type:"checkbox",id:"debug-show-raw-asset-names",label:"Show Raw Asset Names",setElementValue:s(()=>this.module.debugSettings.showRawAssetNames,"setElementValue"),setSettingValue:s(e=>{this.module.debugSettings.showRawAssetNames=e},"setSettingValue")},{type:"checkbox",id:"debug-show-raw-activity-names",label:"Show Raw Activity Names",setElementValue:s(()=>this.module.debugSettings.showRawActivityNames,"setElementValue"),setSettingValue:s(e=>{this.module.debugSettings.showRawActivityNames=e},"setSettingValue")}],[{type:"button",id:"test-deeplib-big-button",options:{label:"Big Button",tooltip:"This is a big button",image:"Icons/Exit.png"},size:[405,80],onClick(){v.info("Big Button Clicked")}},{type:"button",id:"test-deeplib-small-button",options:{tooltip:"This is a small button",image:"Icons/Exit.png"},size:[90,90],onClick(){v.info("Small Button Clicked")}},{type:"checkbox",id:"test-deeplib-checkbox",label:"Checkbox",description:"This is a checkbox",setElementValue(){return!0},setSettingValue(e){v.info("Checkbox value:",e)}},{type:"text",id:"test-deeplib-text-input",label:"Input",description:"This is a text input",setElementValue(){return"Input Value"},setSettingValue(e){v.info("Input value:",e)}},{type:"number",id:"test-deeplib-number-input",label:"Input",description:"This is a number input",setElementValue(){return"123"},setSettingValue(e){v.info("Input value:",e)}},{type:"label",id:"test-deeplib-label",label:"Label",description:"This is a label"}],[{type:"button",id:"test-deeplib-big-button2",options:{label:"Big Button",tooltip:"This is a big button",image:"Icons/Exit.png"},size:[405,80],onClick(){v.info("Big Button Clicked")}},{type:"button",id:"test-deeplib-small-button2",options:{tooltip:"This is a small button",image:"Icons/Next.png"},size:[90,90],onClick(){v.info("Small Button Clicked")}},{type:"checkbox",id:"test-deeplib-checkbox2",label:"Checkbox",description:"This is a checkbox",setElementValue(){return!0},setSettingValue(e){v.info("Checkbox value:",e)}},{type:"text",id:"test-deeplib-text-input2",label:"Input",description:"This is a text input",setElementValue(){return"Input Value"},setSettingValue(e){v.info("Input value:",e)}},{type:"number",id:"test-deeplib-number-input2",label:"Input",description:"This is a number input",setElementValue(){return"123"},setSettingValue(e){v.info("Input value:",e)}},{type:"label",id:"test-deeplib-label2",label:"Label",description:"This is a label"},{type:"dropdown",id:"test-deeplib-dropdown",label:"Dropdown",description:"This is a dropdown",optionsList:["Option 1","Option 2","Option 3"],setElementValue(){return"Option 2"},setSettingValue(e){v.info("Dropdown value:",e)}}]]}exit(){this.module.saveDebugSettings(),super.exit()}};function oe(t){return t!==null&&typeof t=="object"&&Object.getPrototypeOf(t)===Object.prototype&&!Array.isArray(t)}s(oe,"isPlainObject");function b(t,e,i={concatArrays:!0,matchingOnly:!1}){if(t===void 0)return e;if(e===void 0)return t;if(Array.isArray(t)&&Array.isArray(e)&&i.concatArrays)return[...t,...e];if(oe(t)&&oe(e)){let n={...t},o=i.matchingOnly?Object.keys(e).filter(r=>r in t):Object.keys(e);for(let r of o)r==="__proto__"||r==="constructor"||r==="prototype"||(n[r]=r in t?b(t[r],e[r],i):e[r]);return n}return e}s(b,"deepMerge");function Gt(t){let e=JSON.parse(JSON.stringify(t)),i=[];for(;e.length>0;){let n=Math.floor(Math.random()*e.length);i.push(e[n]),e.splice(n,1)}return i}s(Gt,"shuffleArray");function C(t,e){let i=t.split("."),n=globalThis;for(let o=0;o<i.length-1;o++)n[i[o]]||(n[i[o]]={}),n=n[i[o]];n[i[i.length-1]]=e}s(C,"exportToGlobal");function z(t,e){for(;t&&t!==Object.prototype;){if(Object.getOwnPropertyDescriptor(t,e)?.get)return!0;t=Object.getPrototypeOf(t)}return!1}s(z,"hasGetter");function wt(t,e){for(;t&&t!==Object.prototype;){if(Object.getOwnPropertyDescriptor(t,e)?.set)return!0;t=Object.getPrototypeOf(t)}return!1}s(wt,"hasSetter");var se=s(t=>Math.round(t/100)/10,"byteToKB");function A(t,e){try{return{ok:!0,value:t()}}catch(i){return{ok:!1,error:e?e(i):i}}}s(A,"tryCatch");async function Tt(t,e){try{return{ok:!0,value:await t()}}catch(i){return{ok:!1,error:e?e(i):i}}}s(Tt,"tryCatchAsync");var c={createButton:he,createCheckbox:fe,createInput:ye,createLabel:Ie,createCustom:ve,createDropdown:xe,createTooltip:Be,getTooltip:re,setTooltip:j,createBackNext:Ce};function he(t){t.id??=ElementGenerateID();let e=document.getElementById(t.id);if(e)return e;t.type="button";let i;t.options?.image&&(i=t.options.image,t.options.image=void 0);let n=typeof t?.disabled=="function"?t?.disabled():t?.disabled,o=ElementButton.Create(t.id,t?.onClick??(()=>{}),b({labelPosition:"center"},t.options),b({button:{classList:["deeplib-button"],attributes:{disabled:n},children:[i?b({tag:"img",attributes:{id:`${t.id}-image`,alt:"",decoding:"async",loading:"lazy",src:"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"},style:{"--image":`url("${i}")`}},t.htmlOptions?.img):void 0]}},t.htmlOptions??{}));return m.currentElements.push([o,t]),o}s(he,"elementCreateButton");function fe(t){let e=document.getElementById(t.id);if(e)return e;t.type="checkbox";let i=typeof t?.disabled=="function"?t?.disabled():t?.disabled,n=ElementCreate(b({tag:"label",classList:["deeplib-checkbox-container"],attributes:{id:`${t.id}-container`,for:t.id},children:[b({tag:"input",classList:["checkbox","deeplib-input"],attributes:{type:"checkbox",id:t.id,disabled:i,checked:t?.setElementValue?.()||void 0},eventListeners:{change:s(function(){t?.setSettingValue?.(this.checked)},"change")}},t.htmlOptions?.checkbox),b({tag:"span",classList:["deeplib-text"],attributes:{id:`${t.id}-label`},children:[t.label]},t.htmlOptions?.label)]},t.htmlOptions?.container));return t.description&&(n.addEventListener("mouseover",function(o){U.call(this,o,t.description||null)}),n.addEventListener("mouseout",function(o){Q.call(this,o)})),m.currentElements.push([n,t]),n}s(fe,"elementCreateCheckbox");function ve(t){t.id??=ElementGenerateID(),t.htmlOptions.attributes??={},t.htmlOptions.attributes.id??=t.id;let e=document.getElementById(t.htmlOptions.attributes.id);if(e)return e;t.type="custom";let i=ElementCreate(t.htmlOptions);return m.currentElements.push([i,t]),i}s(ve,"elementCreateCustom");function ye(t){let e=document.getElementById(t.id);if(e)return e;let i=typeof t?.disabled=="function"?t?.disabled():t?.disabled,n=ElementCreate(b({tag:"label",classList:["deeplib-input-container"],attributes:{id:`${t.id}-container`,for:t.id},children:[b({tag:"input",classList:["deeplib-input"],attributes:{type:t.type,id:t.id,placeholder:" ",disabled:i,value:t?.setElementValue?.()||void 0},eventListeners:{input:s(function(){t?.setSettingValue?.(this.value)},"input")}},t.htmlOptions?.input),t.label?b({tag:"span",classList:["deeplib-text"],attributes:{id:`${t.id}-label`},children:[t.label]},t.htmlOptions?.label):void 0]},t.htmlOptions?.container));return t.description&&(n.addEventListener("mouseover",function(o){U.call(this,o,t.description||null)}),n.addEventListener("mouseout",function(o){Q.call(this,o)})),m.currentElements.push([n,t]),n}s(ye,"elementCreateInput");function Ie(t){let e=document.getElementById(t.id);if(e)return e;t.type="label";let i=ElementCreate(b({tag:"label",classList:["deeplib-label","deeplib-text"],attributes:{id:t.id},children:[t.label]},t.htmlOptions));return t.description&&(i.addEventListener("mouseover",function(n){U.call(this,n,t.description||null)}),i.addEventListener("mouseout",function(n){Q.call(this,n)})),m.currentElements.push([i,t]),i}s(Ie,"elementCreateLabel");function xe(t){t.id??=ElementGenerateID();let e=document.getElementById(`${t.id}-container`);if(e)return e;t.type="dropdown";let i=ElementCreate(b({tag:"label",classList:["deeplib-dropdown-container"],attributes:{id:`${t.id}-container`,for:t.id},children:[t.label?b({tag:"span",classList:["deeplib-text"],attributes:{id:`${t.id}-label`},children:[t.label]},t.htmlOptions?.label):void 0,ElementCreateDropdown(t.id,t.optionsList,function(){return t.setSettingValue?.(this.value)},t.options,t.htmlOptions?.select)],eventListeners:{mouseover:s(function(n){U.call(this,n,t.description||null)},"mouseover"),mouseout:s(function(n){Q.call(this,n)},"mouseout")}},t.htmlOptions?.container));return m.currentElements.push([i,t]),i}s(xe,"elementCreateDropdown");function Be(){return ElementCreate({tag:"div",classList:["deeplib-tooltip","anchor-bottom"],attributes:{id:"deeplib-tooltip"},style:{display:"none"}})}s(Be,"elementCreateTooltip");function re(){return document.getElementById("deeplib-tooltip")??void 0}s(re,"elementGetTooltip");function U(t,e){let i=this.getBoundingClientRect();j(e,"bottom");let n=re();if(n){n.offsetHeight;let o=n.getBoundingClientRect();(G.doRectsOverlap(i,o)?"top":"bottom")==="top"&&ae("top")}}s(U,"tooltipMouseOver");function Q(t){j(null)}s(Q,"tooltipMouseOut");function j(t,e="bottom"){let i=document.getElementById("deeplib-tooltip");if(!i)return!1;ae(e);let n=t==null?null:CommonIsObject(t)&&"tag"in t?[ElementCreate(t)]:CommonIsArray(t)?t.map(o=>CommonIsObject(o)&&"tag"in o?ElementCreate(o):typeof o=="string"||CommonIsObject(t)&&"tag"in t||o instanceof HTMLElement?o:null).filter(o=>o!==null):typeof t=="string"?[t]:null;return n===null?(i.childNodes.forEach(o=>o.remove()),i.style.display="none",!0):(i.replaceChildren(...n),i.style.display="",!0)}s(j,"elementSetTooltip");function ae(t){let e=document.getElementById("deeplib-tooltip");if(!e)return!1;e.classList.toggle("anchor-bottom",t==="bottom"),e.classList.toggle("anchor-top",t==="top")}s(ae,"elementSetTooltipPosition");function Ce(t){let e=document.getElementById(t.id);if(e)return e;let i=s(a=>{let l=document.getElementById(`${t.id}-label`);if(!l)return!1;l.textContent=a},"setLabel"),n=s(a=>{let l=document.getElementById(`deeplib-prev-next-${t.id}-prev-button-tooltip`);if(!l)return!1;l.textContent=a},"setPrevTooltip"),o=s(a=>{let l=document.getElementById(`deeplib-prev-next-${t.id}-next-button-tooltip`);if(!l)return!1;l.textContent=a},"setNextTooltip");return ElementCreate({tag:"div",classList:["deeplib-prev-next"],attributes:{id:t.id},children:[c.createButton({id:`deeplib-prev-next-${t.id}-prev-button`,onClick:s(()=>{t.back({setLabel:i,setBackTooltip:n,setNextTooltip:o})},"onClick"),htmlOptions:{button:{classList:["deeplib-prev-next-button"]}},options:{noStyling:!0,image:`${PUBLIC_URL}/dl_images/arrow_left.svg`,tooltip:t.initialPrevTooltip}}),c.createLabel({id:`${t.id}-label`,label:t.initialLabel,htmlOptions:{classList:["deeplib-prev-next-label"]}}),c.createButton({id:`deeplib-prev-next-${t.id}-next-button`,onClick:s(()=>{t.next({setLabel:i,setBackTooltip:n,setNextTooltip:o})},"onClick"),htmlOptions:{button:{classList:["deeplib-prev-next-button"]}},options:{noStyling:!0,image:`${PUBLIC_URL}/dl_images/arrow_right.svg`,tooltip:t.initialNextTooltip}})]})}s(Ce,"elementPrevNext");var k=class t extends m{static{s(this,"MainMenu")}subscreens=[];static options={};static subscreenOptions={name:"mainmenu",doShowExitButton:!1,settingsWidth:600};constructor(e){super(e),this.subscreens=e.subscreens}load(){if(!L.instance||CurrentModule!=="DeepLibMod"){this.setSubscreen(this);return}super.load();let e=c.createButton({id:"exit",size:[90,90],onClick:s(()=>{this.exit()},"onClick"),options:{image:`${PUBLIC_URL}/dl_images/exit.svg`,tooltip:d("settings.button.back_button_hint")}}),i=document.getElementById("deeplib-nav-menu");i&&i.append(e);for(let o of this.subscreens){if(o.options.name==="mainmenu")continue;let r=c.createButton({id:`${o.options.name}-button`,onClick:s(()=>{this.setSubscreen(o)},"onClick"),size:[null,90],options:{image:o.options.icon,label:d(`mainmenu.button.${o.options.name}`)}});g.appendToSettingsDiv(r)}let n=g.getMiscDiv();if(g.appendToSubscreen(n),t.options.wikiLink){let o=c.createButton({id:"deeplib-wiki-button",onClick:s(()=>{window.open(t.options.wikiLink,"_blank")},"onClick"),size:[null,80],options:{image:`${PUBLIC_URL}/dl_images/notebook.svg`,label:d("mainmenu.button.wiki")}});g.appendToMiscDiv(o)}if(t.options.repoLink){let o=c.createButton({id:"deeplib-repo-button",onClick:s(()=>{window.open(t.options.repoLink,"_blank")},"onClick"),size:[null,80],options:{image:`${PUBLIC_URL}/dl_images/git.svg`,label:d("mainmenu.button.repo")}});g.appendToMiscDiv(o)}if(t.options.resetSubscreen){let o=c.createButton({id:"deeplib-reset-button",onClick:s(()=>{this.setSubscreen(t.options.resetSubscreen)},"onClick"),size:[null,80],options:{image:`${PUBLIC_URL}/dl_images/trash_bin.svg`,label:d("mainmenu.button.reset")}});g.appendToMiscDiv(o)}if(t.options.importExportSubscreen){let o=c.createButton({id:"deeplib-import-export-button",onClick:s(()=>{this.setSubscreen(t.options.importExportSubscreen)},"onClick"),size:[null,80],options:{image:`${PUBLIC_URL}/dl_images/transfer.svg`,label:d("mainmenu.button.import_export")}});g.appendToMiscDiv(o)}if(t.options.storageFullnessIndicator){let r=se(u.storageSize()),a=(r/180*100).toFixed(1),l=c.createButton({id:CommonGenerateUniqueID(),size:[null,80],options:{tooltipPosition:"left",noStyling:!0,tooltip:CommonStringPartitionReplace(d("mainmenu.meter.storage_hint"),{$percentage$:`${a}`}).join(""),label:CommonStringPartitionReplace(d("mainmenu.meter.storage_label"),{$currentCapacity$:`${r}`,$maxCapacity$:"180"}).join("")},htmlOptions:{button:{children:[{tag:"div",attributes:{id:"deeplib-storage-meter"},children:[{tag:"div",attributes:{id:"deeplib-storage-bar"},style:{width:`${a}%`}}]}]}}});g.appendToMiscDiv(l)}if(IS_DEBUG||x("DebugModule")){let o=c.createButton({id:"deeplib-debug-button",onClick:s(()=>{this.setSubscreen(new D(x("DebugModule")))},"onClick"),size:[90,90],options:{image:`${PUBLIC_URL}/dl_images/bug.svg`}});i&&i.prepend(o)}}run(){super.run()}click(){}exit(){CharacterAppearanceForceUpCharacter=-1,CharacterLoadCanvas(Player);let e=typeof this.options.returnScreen=="function"?this.options.returnScreen():this.options.returnScreen;e?e instanceof m?T(e).then(()=>{}):Array.isArray(e)&&CommonSetScreen(...e):PreferenceOpenSubscreen("Extensions").then(()=>{PreferenceSubscreenExtensionsClear()})}resize(){super.resize(),ElementSetPosition("deeplib-misc",1905,930,"bottom-right"),ElementSetSize("deeplib-misc",405,null)}static setOptions(e){t.options=e}};var M=class t{static{s(this,"Localization")}static LibTranslation={};static ModTranslation={};static PathToModTranslation;static PathToLibTranslation=`${PUBLIC_URL}/dl_translations/`;static DefaultLanguage="en";static initialized=!1;static async init(e){if(t.initialized)return;t.initialized=!0,t.PathToModTranslation=(()=>{if(e?.pathToTranslationsFolder)return e.pathToTranslationsFolder.endsWith("/")?e.pathToTranslationsFolder:`${e.pathToTranslationsFolder}/`})(),t.DefaultLanguage=e?.defaultLanguage||t.DefaultLanguage;let i=e?.fixedLanguage?t.DefaultLanguage:TranslationLanguage.toLowerCase(),n=await t.fetchLanguageFile(t.PathToLibTranslation,i);if(i===t.DefaultLanguage)t.LibTranslation=n;else{let r=await t.fetchLanguageFile(t.PathToLibTranslation,t.DefaultLanguage);t.LibTranslation={...r,...n}}if(!t.PathToModTranslation)return;let o=await t.fetchLanguageFile(t.PathToModTranslation,i);if(i===t.DefaultLanguage)t.ModTranslation=o;else{let r=await t.fetchLanguageFile(t.PathToModTranslation,t.DefaultLanguage);t.ModTranslation={...r,...o}}}static getTextMod(e){return t.ModTranslation?.[e]||void 0}static getTextLib(e){return t.LibTranslation?.[e]||void 0}static async fetchLanguageFile(e,i){let n=await fetch(`${e}${i}.lang`);if(i!==t.DefaultLanguage&&!n.ok)return this.fetchLanguageFile(e,t.DefaultLanguage);if(!n.ok)return{};let o=await n.text();return this.parseLanguageFile(o)}static parseLanguageFile(e){let i={},n=e.split(`
364
+ `);for(let o of n){let r=o.trim();if(!r||r.startsWith("#"))continue;let[a,...l]=r.split("=");i[a.trim()]=l.join("=").trim()}return i}},d=s(t=>M.getTextMod(t)||M.getTextLib(t)||t,"getText");var W=class t{constructor(e){this.opts=e;e??={},e.closeOnBackdrop??=!0;let i=`modal-prompt-${Date.now()}`,n=(CommonIsArray(e.prompt)?e.prompt:[e.prompt]).filter(o=>o!==null)??[""];this.dialog=ElementCreate({tag:"dialog",classList:["deeplib-modal"],attributes:{id:this.opts.modalId??`modal-${Date.now()}`,role:"dialog","aria-modal":"true","aria-labelledby":i},style:{fontFamily:CommonGetFontName()},children:[{tag:"div",classList:["deeplib-modal-prompt-container"],children:[...n]},{tag:"div",classList:["deeplib-modal-prompt"],attributes:{id:i},children:[e.input?this.renderInput(e.input):void 0]},this.renderButtons()]}),this.blocker=this.createBlocker(),this.renderButtons(),document.body.append(this.createBlocker(),this.dialog),this.setupFocusTrap(),e.timeoutMs&&(this.timeoutId=window.setTimeout(()=>this.close("timeout"),e.timeoutMs))}static{s(this,"Modal")}dialog;blocker;inputEl;timeoutId;static queue=[];static processing=!1;show(){return t.enqueue(this)}static async alert(e,i={}){await new t({prompt:e,buttons:[{action:"close",text:d("modal.button.ok")}],timeoutMs:i.timeoutMs,escapeAction:"close",modalId:i.modalId}).show()}static async confirm(e,i={}){let[n]=await new t({prompt:e,buttons:[{text:d("modal.button.decline"),action:"decline"},{text:d("modal.button.confirm"),action:"confirm"}],escapeAction:"decline",enterAction:"confirm",modalId:i.modalId}).show();return n==="confirm"}static async prompt(e,i={}){let[n,o]=await new t({prompt:e,timeoutMs:0,input:{type:"input",defaultValue:i.defaultValue},buttons:[{text:d("modal.button.cancel"),action:"cancel"},{text:d("modal.button.submit"),action:"submit"}],escapeAction:"cancel",enterAction:"submit",modalId:i.modalId}).show();return n==="submit"?o:null}renderInput(e){let i=document.createElement(e.type);return i.classList.add("deeplib-modal-input"),e.placeholder&&(i.placeholder=e.placeholder),e.readOnly&&(i.readOnly=!0),e.defaultValue&&(i.value=e.defaultValue),e.type==="textarea"&&(i.rows=5),i.addEventListener("input",()=>{let n=e.validate?.(i.value);i.setCustomValidity(n||"")}),this.inputEl=i,i}renderButtons(){let e=document.createElement("div");return e.classList.add("deeplib-modal-button-container"),(this.opts.buttons?[...this.opts.buttons]:[]).forEach(n=>{let o=c.createButton({id:`deeplib-modal-${n.action}`,onClick:s(()=>this.close(n.action),"onClick"),options:{disabled:n.disabled,label:n.text}});e.append(o)}),e}createBlocker(){let e=document.createElement("div");return e.classList.add("deeplib-modal-blocker"),e.title="Click to close",this.opts.closeOnBackdrop!==!1&&e.addEventListener("click",()=>this.close("close")),e}setupFocusTrap(){let i=Array.from(this.dialog.querySelectorAll('button, [href], input, textarea, select, [tabindex]:not([tabindex="-1"])')),n=i[0],o=i[i.length-1];this.dialog.addEventListener("keydown",r=>{if(r.key==="Tab"){if(i.length===0){r.preventDefault();return}r.shiftKey?document.activeElement===n&&(o.focus(),r.preventDefault()):document.activeElement===o&&(n.focus(),r.preventDefault())}else if(r.key==="Escape")r.stopPropagation(),this.close(this.opts.escapeAction??"close");else if(r.key==="Enter"){if(i.some(a=>a===document.activeElement)&&document.activeElement!==this.inputEl)return;r.preventDefault(),r.stopPropagation(),this.close(this.opts.enterAction??"submit")}}),window.requestAnimationFrame(()=>{(this.inputEl||n)?.focus()})}close(e){this.timeoutId&&clearTimeout(this.timeoutId),this.dialog.close(),this.dialog.remove(),this.blocker.remove(),document.body.querySelector(".deeplib-modal-blocker")?.remove();let i=this.inputEl?.value??"";this.resolve([e,i]),t.dequeue()}resolve=s(()=>{},"resolve");static enqueue(e){return t.queue.push(e),t.processing||t.dequeue(),new Promise(i=>e.resolve=i)}static dequeue(){let e=t.queue.shift();e?(t.processing=!0,e.dialog.show()):t.processing=!1}};var le=class extends m{static{s(this,"GuiImportExport")}importExportOptions;static subscreenOptions={name:"import-export"};constructor(e){super(),this.importExportOptions=e}load(){super.load();let e=c.createButton({id:"deeplib-import-file-button",size:[600,90],onClick:s(()=>{this.dataImport("file")},"onClick"),options:{image:`${PUBLIC_URL}/dl_images/file_import.svg`,label:d("import-export.button.import_file")}});g.appendToSettingsDiv(e);let i=c.createButton({id:"deeplib-export-file-button",size:[600,90],onClick:s(()=>{this.dataExport("file")},"onClick"),options:{image:`${PUBLIC_URL}/dl_images/file_export.svg`,label:d("import-export.button.export_file")}});g.appendToSettingsDiv(i);let n=c.createButton({id:"deeplib-import-clipboard-button",size:[600,90],onClick:s(()=>{this.dataImport("clipboard")},"onClick"),options:{image:`${PUBLIC_URL}/dl_images/clipboard_import.svg`,label:d("import-export.button.import_clipboard")}});g.appendToSettingsDiv(n);let o=c.createButton({id:"deeplib-export-clipboard-button",size:[600,90],onClick:s(()=>{this.dataExport("clipboard")},"onClick"),options:{image:`${PUBLIC_URL}/dl_images/clipboard_export.svg`,label:d("import-export.button.export_clipboard")}});g.appendToSettingsDiv(o)}resize(){super.resize()}async dataExport(e){try{let i=await this.getSelectedModules(f(),"export");if(!i)return;if(i.length===0){ToastManager.error("No modules selected for export.");return}let n=this.buildExportPayload(i);if(e==="clipboard")await this.exportToClipboard(n);else if(e==="file"&&!await this.exportToFile(n,"settings"))return;this.importExportOptions.onExport?.(),ToastManager.success("Data exported successfully.")}catch(i){ToastManager.error("Data export failed."),p.error("Data export failed.",i)}}async dataImport(e){try{let i=e==="clipboard"?await this.importFromClipboard():await this.importFromFile();if(i===null)return;if(!i)throw new Error("No data");if(!await this.applyImportPayload(i))return;this.importExportOptions.onImport?.(),ToastManager.success("Data imported successfully.")}catch(i){ToastManager.error("Data import failed."),p.error("Data import failed.",i)}}async exportToFile(e,i){let n=this.importExportOptions.customFileExtension.startsWith(".")?this.importExportOptions.customFileExtension:"."+this.importExportOptions.customFileExtension,o=i.endsWith(n)?i:i+n;if("showSaveFilePicker"in window)try{let a=await(await window.showSaveFilePicker({suggestedName:o,types:[{description:"Custom Data Files",accept:{"text/plain":[n]}}]})).createWritable();return await a.write(e),await a.close(),!0}catch(r){throw new Error("File save cancelled or failed: "+r.message)}else{let r=await W.prompt("Enter file name",{defaultValue:o});if(r===null)return!1;if(r==="")throw new Error("File name cannot be empty.");let a=new Blob([e],{type:"text/plain"}),l=ElementCreate({tag:"a",attributes:{href:URL.createObjectURL(a),download:r.endsWith(n)?r:r+n}});return l.click(),URL.revokeObjectURL(l.href),!0}}async importFromFile(){let e=this.importExportOptions.customFileExtension.startsWith(".")?this.importExportOptions.customFileExtension:"."+this.importExportOptions.customFileExtension;async function i(n){if(!n.name.endsWith(e))throw new Error(`Invalid file type. Expected a ${e} file.`);return new Promise((o,r)=>{let a=new FileReader;a.onload=()=>o(a.result),a.onerror=()=>r(new Error("Failed to read file.")),a.readAsText(n)})}if(s(i,"importFromFileInternal"),"showOpenFilePicker"in window)try{let[n]=await window.showOpenFilePicker({types:[{description:"Custom Data Files",accept:{"text/plain":[e]}}],multiple:!1}),o=await n.getFile();return await i(o)}catch(n){throw new Error("File selection cancelled or failed: "+n.message)}else return new Promise((n,o)=>{let r=document.createElement("input");r.type="file",r.accept=e,r.onchange=async a=>{let l=a.target.files?.[0];if(l)try{let y=await i(l);n(y)}catch(y){o(y)}else o(new Error("No file selected."))},r.click()})}async exportToClipboard(e){return navigator.clipboard.writeText(e).catch(i=>{throw new Error("Failed to copy data to clipboard."+i)})}async importFromClipboard(){return W.prompt("Enter data to import").catch(e=>{throw new Error("Failed to read data from clipboard."+e)})}async getSelectedModules(e,i){let n=e.filter(h=>z(h,"settings")&&!!h.settings),o=Object.fromEntries(n.map(h=>[h.constructor.name,!0]));if(n.length===0)throw new Error("No modules to choose from.");let r=n.map(h=>c.createCheckbox({id:h.constructor.name,label:d(h.constructor.name),setElementValue:s(()=>o[h.constructor.name],"setElementValue"),setSettingValue:s(Y=>o[h.constructor.name]=Y,"setSettingValue")})),a=i==="import"?"import_export.import.select_modules":"import_export.export.select_modules";if(!await W.confirm([d(a),ElementCreate({tag:"br"}),d("import_export.text.not_sure"),{tag:"div",classList:["deeplib-modal-checkbox-container"],children:r}],{modalId:"deeplib-modal-import_export"}))return null;let y=Object.entries(o).filter(([h,Y])=>Y).map(([h])=>x(h)).filter(h=>!!h);if(y.length===0)throw new Error("No modules selected.");return y}buildExportPayload(e){let i={};for(let n of e)!z(n,"settings")||n.settings===null||(i[n.constructor.name]=n.settings);return LZString.compressToBase64(JSON.stringify(i))}async applyImportPayload(e){let i=JSON.parse(LZString.decompressFromBase64(e)??"");if(!i)throw new Error("Invalid import format.");let n=Object.keys(i).map(r=>x(r)).filter(r=>!!r),o=await this.getSelectedModules(n,"import");if(!o)return!1;if(o.length===0)throw new Error("No modules selected.");for(let r of o){let a=i[r.constructor.name];if(!a)continue;let l=b(r.defaultSettings,a);l&&(r.settings=l)}return!0}};var X=class t{static{s(this,"ModStorage")}static _instance=null;modName;constructor(e){return t._instance||(t._instance=this,this.modName=e),this.modName??=e,t._instance}get playerStorage(){return Player[this.modName]}set playerStorage(e){Player[this.modName]=e}get extensionStorage(){return Player.ExtensionSettings[this.modName]}set extensionStorage(e){Player.ExtensionSettings[this.modName]=e}setLocalStorage(e,i){localStorage.setItem(`${this.modName}_${e}`,t.dataCompress(i))}getLocalStorage(e){let i=localStorage.getItem(`${this.modName}_${e}`);return i?t.dataDecompress(i):null}load(){if(this.extensionStorage){let e=t.dataDecompress(this.extensionStorage||"");e===null||!Object.hasOwn(e,"Version")?this.playerStorage={Version:MOD_VERSION}:this.playerStorage=e}else this.playerStorage={}}save(){this.extensionStorage||(this.extensionStorage=""),this.extensionStorage=t.dataCompress(this.playerStorage),ServerPlayerExtensionSettingsSync(this.modName)}storageSize(){return t.measureSize(this.extensionStorage)}static dataDecompress(e){let i=LZString.decompressFromBase64(e),n=null;try{n=JSON.parse(i)}catch(o){p.error(o)}return n}static dataCompress(e){return LZString.compressToBase64(JSON.stringify(e))}static measureSize(e){try{if(typeof e!="string"&&(e=JSON.stringify(e)||""),typeof e=="string")return new TextEncoder().encode(e).byteLength;throw new Error}catch{return NaN}}};var G={autoSetPosition:Ge,autoSetSize:we,hide:Te,unhide:Le,hasOverflow:Se,doRectsOverlap:Ze};function Ge(t,e){let i,n,o;if(Array.isArray(e))i=e[0],n=e[1],o=e[2];else if(typeof e=="function"){let r=e();i=r[0],n=r[1],o=r[2]}i!==void 0&&n!==void 0&&ElementSetPosition(t,i,n,o)}s(Ge,"autoSetPosition");function we(t,e){let i,n;if(Array.isArray(e))i=e[0],n=e[1];else if(typeof e=="function"){let o=e();i=o[0],n=o[1]}i!==void 0&&n!==void 0&&ElementSetSize(t,i,n)}s(we,"autoSetSize");function Te(t){let e=ElementWrap(t);e&&(e.style.display="none")}s(Te,"hide");function Le(t){let e=ElementWrap(t);e&&(e.style.display="")}s(Le,"unhide");function Se(t){let e=ElementWrap(t);if(!e)return null;let i=e.scrollHeight>e.clientHeight,n=e.scrollWidth>e.clientWidth;return{any:i||n,vertical:i,horizontal:n}}s(Se,"hasOverflow");function Ze(t,e){return!(t.right<e.left||t.left>e.right||t.bottom<e.top||t.top>e.bottom)}s(Ze,"doRectsOverlap");var g={getSubscreen:P,appendToSubscreen:ke,removeSubscreen:Oe,getSettingsDiv:K,appendToSettingsDiv:Me,removeSettingsDiv:Ee,getMiscDiv:J,appendToMiscDiv:We,removeMiscDiv:Fe};function P(){let t=ElementWrap("deeplib-subscreen");if(t)return t;let e=ElementCreate({tag:"div",classList:["deeplib-subscreen","HideOnPopup"],attributes:{id:"deeplib-subscreen"}});return document.body.appendChild(e)}s(P,"elementGetSubscreenDiv");function Oe(){return P()?.remove()}s(Oe,"elementRemoveSubscreenDiv");function ke(...t){return P()?.append(...t)}s(ke,"elementAppendToSubscreenDiv");function K(){let t=ElementWrap("deeplib-settings");return t||ElementCreate({tag:"div",classList:["deeplib-settings","scroll-box"],attributes:{id:"deeplib-settings"}})}s(K,"elementGetSettingsDiv");function Me(...t){return K()?.append(...t)}s(Me,"elementAppendToSettingsDiv");function Ee(){return K()?.remove()}s(Ee,"elementRemoveSettingsDiv");function J(){let t=ElementWrap("deeplib-misc");return t||ElementCreate({tag:"div",classList:["deeplib-misc"],attributes:{id:"deeplib-misc"}})}s(J,"elementGetMiscDiv");function We(...t){return J()?.append(...t)}s(We,"elementAppendToMiscDiv");function Fe(){return J()?.remove()}s(Fe,"elementRemoveMiscDiv");var V=class t extends Array{static{s(this,"Logger")}ModName="DeepLib";constructor(e){super(),e&&(this.ModName=e)}_Log(e,...i){let n={logLevel:e,args:[...i],date:new Date(Date.now())},o=navigator.userAgent.toLowerCase();if(o.includes("chrome")||o.includes("firefox")){let r=t.colorizeLog(e);i.forEach(a=>{typeof a=="string"&&(a=`
365
+ %c${a}`)}),console.log(`%c${this.ModName}:`,r,...i)}else console.log(`${this.ModName}:`,...i);this.push(n)}info(...e){this._Log("info",...e)}log(...e){this._Log("log",...e)}warn(...e){this._Log("warn",...e)}error(...e){this._Log("error",...e)}debug(...e){this._Log("debug",...e)}static colorizeLog(e){return{info:"color: #32CCCC",log:"color: #CCCC32",warn:"color: #eec355",error:"color: #750b0b",debug:"color: #9E4BCF"}[e]}},v=new V;function ci(t,e,i){let n=ElementCreate({tag:"div",classList:["ChatMessage","deeplib-message","ChatMessageNonDialogue"],attributes:{id:t??`DEEPLIB_LOCAL_MESSAGE_${Date.now()}`,"data-time":ChatRoomCurrentTime(),"data-sender":Player.MemberNumber?.toString()},children:[{tag:"span",classList:["deeplib-text"],innerHTML:e.replaceAll(`
366
+ `,"")},{tag:"br"},{tag:"a",classList:["deeplib-text"],attributes:{href:"#"},innerHTML:"<b>Close (Click)</b>",eventListeners:{click:s(()=>{n.remove()},"click")}}]});ChatRoomAppendChat(n),i&&setTimeout(()=>n.remove(),i*1e3)}s(ci,"sendLocalMessage");function di(t,e=void 0,i=[]){t&&ServerSend("ChatRoomChat",{Content:"DEEPLIB_CUSTOM_ACTION",Type:"Action",Target:e??void 0,Dictionary:[{Tag:'MISSING TEXT IN "Interface.csv": DEEPLIB_CUSTOM_ACTION',Text:t},...i]})}s(di,"sendActionMessage");var S={Observe:0,AddBehavior:1,ModifyBehavior:5,OverrideBehavior:10,Top:100},E=class{static{s(this,"ModSdkManager")}SDK;patchedFunctions=new Map;constructor(e,i){this.SDK=bcModSdk.registerMod(e,i)}initPatchableFunction(e){let i=this.patchedFunctions.get(e);return i||(i={name:e,hooks:[]},this.patchedFunctions.set(e,i)),i}hookFunction(e,i,n,o=null){let r=this.initPatchableFunction(e);if(r.hooks.some(l=>l.hook===n))return()=>null;let a=this.SDK.hookFunction(e,i,n);return r.hooks.push({hook:n,priority:i,module:o,removeCallback:a}),r.hooks.sort((l,y)=>y.priority-l.priority),a}patchFunction(e,i){this.SDK.patchFunction(e,i)}unpatchFunction(e){this.SDK.removePatches(e)}removeHookByModule(e,i){let n=this.initPatchableFunction(e);for(let o=n.hooks.length-1;o>=0;o--)n.hooks[o].module===i&&(n.hooks[o].removeCallback(),n.hooks.splice(o,1));return!0}removeAllHooksByModule(e){for(let i of this.patchedFunctions.values())for(let n=i.hooks.length-1;n>=0;n--)i.hooks[n].module===e&&(i.hooks[n].removeCallback(),i.hooks.splice(n,1));return!0}unload(){this.SDK.unload()}};var N={injectInline(t,e){if(document.getElementById(t))return;let n=document.createElement("style");n.id=t,n.appendChild(document.createTextNode(e)),document.head.appendChild(n)},injectEmbed(t,e){if(document.getElementById(t))return;let n=document.createElement("link");n.id=t,n.rel="stylesheet",n.href=e,document.head.appendChild(n)},eject(t){let e=document.getElementById(t);e&&e.remove()},reload(t,e){N.eject(t),N.injectInline(t,e)},async fetch(t){return fetch(t).then(e=>e.text())}};var ce=class{constructor(e){this.channelName=e;I.hookFunction("ChatRoomMessageProcessHidden",0,(i,n)=>{if(!this.isChannelMessage(i[0]))return n(i);let[o,r]=i,{type:a,data:l}=o.Dictionary[0],y=this.listeners[a];return y&&y.forEach(h=>h(l,r)),n(i)},`EventChannel-${e}`)}static{s(this,"EventChannel")}listeners={};unload(){Object.keys(this.listeners).forEach(e=>delete this.listeners[e]),E.prototype.removeHookByModule("ChatRoomMessageProcessHidden",`EventChannel-${this.channelName}`)}sendEvent(e,i,n=null){let o={Type:"Hidden",Content:this.channelName,Sender:Player.MemberNumber,...n?{Target:n}:{},Dictionary:[{type:e,data:i}]};ServerSend("ChatRoomChat",o)}registerListener(e,i){let n=this.listeners[e]??[];return n.push(i),this.listeners[e]=n,()=>this.unregisterListener(e,i)}unregisterListener(e,i){let n=this.listeners[e];if(n){let o=n.indexOf(i);o!==-1&&n.splice(o,1)}}isChannelMessage(e){return e&&e.Type==="Hidden"&&e.Content===this.channelName&&e.Sender&&e.Sender!==Player.MemberNumber&&e.Dictionary&&!!e.Dictionary[0]?.data&&!!e.Dictionary[0]?.type||!1}};export{ne as BaseMigrator,B as BaseModule,m as BaseSubscreen,F as DebugModule,ce as EventChannel,L as GUI,D as GuiDebug,le as GuiImportExport,S as HookPriority,M as Localization,V as Logger,w as MOD_NAME,k as MainMenu,E as ModSdkManager,X as ModStorage,W as Modal,N as Style,R as VersionModule,c as advElement,se as byteToKB,v as deepLibLogger,b as deepMerge,G as domUtil,C as exportToGlobal,x as getModule,d as getText,z as hasGetter,wt as hasSetter,st as initMod,g as layout,p as modLogger,u as modStorage,f as modules,ie as registerModule,I as sdk,di as sendActionMessage,ci as sendLocalMessage,T as setSubscreen,Gt as shuffleArray,A as tryCatch,Tt as tryCatchAsync,be as unloadMod};
3173
367
  //# sourceMappingURL=deeplib.js.map