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