bc-deeplib 1.1.2 → 1.1.3
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.d.ts +319 -13
- package/dist/deeplib.js +173 -17
- package/dist/deeplib.js.map +2 -2
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/vendored_types/declarations.d.ts +40 -0
- package/package.json +1 -1
package/dist/deeplib.js
CHANGED
|
@@ -958,20 +958,34 @@ var GUI = class _GUI extends BaseModule {
|
|
|
958
958
|
static {
|
|
959
959
|
__name(this, "GUI");
|
|
960
960
|
}
|
|
961
|
+
/** The singleton instance of the GUI controller. */
|
|
961
962
|
static instance = null;
|
|
963
|
+
/** All subscreens managed by this GUI, including the main menu and module settings screens. */
|
|
962
964
|
_subscreens;
|
|
965
|
+
/** The mod's main menu screen. */
|
|
963
966
|
_mainMenu;
|
|
967
|
+
/** The currently active subscreen, or `null` if none is active. */
|
|
964
968
|
_currentSubscreen = null;
|
|
969
|
+
/** Options defining how the mod's settings button is displayed and behaves. */
|
|
965
970
|
_modButtonOptions;
|
|
971
|
+
/** Returns all registered subscreens. */
|
|
966
972
|
get subscreens() {
|
|
967
973
|
return this._subscreens;
|
|
968
974
|
}
|
|
975
|
+
/** Returns the main menu subscreen instance. */
|
|
969
976
|
get mainMenu() {
|
|
970
977
|
return this._mainMenu;
|
|
971
978
|
}
|
|
979
|
+
/** Returns the currently active subscreen. */
|
|
972
980
|
get currentSubscreen() {
|
|
973
981
|
return this._currentSubscreen;
|
|
974
982
|
}
|
|
983
|
+
/**
|
|
984
|
+
* Sets the current subscreen.
|
|
985
|
+
* Accepts either a `BaseSubscreen` instance or the `name` of a subscreen.
|
|
986
|
+
*
|
|
987
|
+
* @throws If a string is provided but no subscreen with that name exists.
|
|
988
|
+
*/
|
|
975
989
|
set currentSubscreen(subscreen) {
|
|
976
990
|
if (this._currentSubscreen) {
|
|
977
991
|
this._currentSubscreen.unload();
|
|
@@ -988,7 +1002,11 @@ var GUI = class _GUI extends BaseModule {
|
|
|
988
1002
|
this._currentSubscreen.resize(true);
|
|
989
1003
|
}
|
|
990
1004
|
}
|
|
991
|
-
/**
|
|
1005
|
+
/**
|
|
1006
|
+
* Creates the GUI instance and initializes the main menu.
|
|
1007
|
+
*
|
|
1008
|
+
* @throws If another `GUI` instance already exists.
|
|
1009
|
+
*/
|
|
992
1010
|
constructor(modButtonOptions) {
|
|
993
1011
|
super();
|
|
994
1012
|
if (_GUI.instance) {
|
|
@@ -1002,9 +1020,13 @@ var GUI = class _GUI extends BaseModule {
|
|
|
1002
1020
|
this._modButtonOptions = modButtonOptions;
|
|
1003
1021
|
_GUI.instance = this;
|
|
1004
1022
|
}
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1023
|
+
/**
|
|
1024
|
+
* Loads the GUI and registers the mod's settings button in the extensions menu.
|
|
1025
|
+
*
|
|
1026
|
+
* - Creates subscreens for each module's settings screen.
|
|
1027
|
+
* - Registers lifecycle callbacks for subscreens events.
|
|
1028
|
+
* - Sets up the main menu and its subscreens.
|
|
1029
|
+
*/
|
|
1008
1030
|
load() {
|
|
1009
1031
|
for (const module of modules()) {
|
|
1010
1032
|
if (!module.settingsScreen) continue;
|
|
@@ -1015,36 +1037,34 @@ var GUI = class _GUI extends BaseModule {
|
|
|
1015
1037
|
Identifier: this._modButtonOptions.Identifier,
|
|
1016
1038
|
ButtonText: this._modButtonOptions.ButtonText,
|
|
1017
1039
|
Image: this._modButtonOptions.Image,
|
|
1018
|
-
load:
|
|
1040
|
+
load: /* @__PURE__ */ __name(() => {
|
|
1019
1041
|
setSubscreen(new MainMenu(this));
|
|
1020
|
-
}),
|
|
1021
|
-
run:
|
|
1042
|
+
}, "load"),
|
|
1043
|
+
run: /* @__PURE__ */ __name(() => {
|
|
1022
1044
|
if (this._currentSubscreen) {
|
|
1023
|
-
MainCanvas.textAlign = "left";
|
|
1024
1045
|
this._currentSubscreen.run();
|
|
1025
|
-
MainCanvas.textAlign = "center";
|
|
1026
1046
|
const newCanvasPosition = [MainCanvas.canvas.offsetLeft, MainCanvas.canvas.offsetTop, MainCanvas.canvas.clientWidth, MainCanvas.canvas.clientHeight];
|
|
1027
1047
|
if (!CommonArraysEqual(newCanvasPosition, DrawCanvasPosition)) {
|
|
1028
1048
|
DrawCanvasPosition = newCanvasPosition;
|
|
1029
1049
|
this._currentSubscreen.resize(false);
|
|
1030
1050
|
}
|
|
1031
1051
|
}
|
|
1032
|
-
}),
|
|
1033
|
-
click:
|
|
1052
|
+
}, "run"),
|
|
1053
|
+
click: /* @__PURE__ */ __name(() => {
|
|
1034
1054
|
if (this._currentSubscreen) {
|
|
1035
1055
|
this._currentSubscreen.click();
|
|
1036
1056
|
}
|
|
1037
|
-
}),
|
|
1038
|
-
exit:
|
|
1057
|
+
}, "click"),
|
|
1058
|
+
exit: /* @__PURE__ */ __name(() => {
|
|
1039
1059
|
if (this._currentSubscreen) {
|
|
1040
1060
|
this._currentSubscreen.exit();
|
|
1041
1061
|
}
|
|
1042
|
-
}),
|
|
1043
|
-
unload:
|
|
1062
|
+
}, "exit"),
|
|
1063
|
+
unload: /* @__PURE__ */ __name(() => {
|
|
1044
1064
|
if (this._currentSubscreen) {
|
|
1045
1065
|
this._currentSubscreen.unload();
|
|
1046
1066
|
}
|
|
1047
|
-
})
|
|
1067
|
+
}, "unload")
|
|
1048
1068
|
});
|
|
1049
1069
|
}
|
|
1050
1070
|
};
|
|
@@ -1054,10 +1074,19 @@ var VersionModule = class _VersionModule extends BaseModule {
|
|
|
1054
1074
|
static {
|
|
1055
1075
|
__name(this, "VersionModule");
|
|
1056
1076
|
}
|
|
1077
|
+
/** Whether the current session is running a new version compared to stored data */
|
|
1057
1078
|
static isItNewVersion = false;
|
|
1079
|
+
/** The current mod version (retrieved from `ModSdkManager.ModInfo.version`) */
|
|
1058
1080
|
static Version;
|
|
1081
|
+
/** Message to display when a new version is detected */
|
|
1059
1082
|
static NewVersionMessage = "";
|
|
1083
|
+
/** List of registered migration handlers, sorted by version */
|
|
1060
1084
|
static Migrators = [];
|
|
1085
|
+
/**
|
|
1086
|
+
* Initializes the module on load:
|
|
1087
|
+
* - Stores the current mod version.
|
|
1088
|
+
* - Hooks into `ChatRoomSync` to show a "new version" message when applicable.
|
|
1089
|
+
*/
|
|
1061
1090
|
load() {
|
|
1062
1091
|
_VersionModule.Version = ModSdkManager.ModInfo.version;
|
|
1063
1092
|
ModSdkManager.prototype.hookFunction(
|
|
@@ -1072,6 +1101,14 @@ var VersionModule = class _VersionModule extends BaseModule {
|
|
|
1072
1101
|
"VersionModule"
|
|
1073
1102
|
);
|
|
1074
1103
|
}
|
|
1104
|
+
/**
|
|
1105
|
+
* Checks if the stored version differs from the current version.
|
|
1106
|
+
* If a new version is detected:
|
|
1107
|
+
* - Flags the session as updated.
|
|
1108
|
+
* - Runs applicable migrations.
|
|
1109
|
+
* - Updates stored version in player data.
|
|
1110
|
+
* - Saves `modStorage`.
|
|
1111
|
+
*/
|
|
1075
1112
|
static checkVersionUpdate() {
|
|
1076
1113
|
const PreviousVersion = _VersionModule.loadVersion();
|
|
1077
1114
|
const CurrentVersion = _VersionModule.Version;
|
|
@@ -1082,6 +1119,10 @@ var VersionModule = class _VersionModule extends BaseModule {
|
|
|
1082
1119
|
}
|
|
1083
1120
|
modStorage.save();
|
|
1084
1121
|
}
|
|
1122
|
+
/**
|
|
1123
|
+
* Executes migrations for all registered migrators whose `MigrationVersion`
|
|
1124
|
+
* is newer than the previously stored version.
|
|
1125
|
+
*/
|
|
1085
1126
|
static checkVersionMigration() {
|
|
1086
1127
|
const PreviousVersion = _VersionModule.loadVersion();
|
|
1087
1128
|
for (const migrator of _VersionModule.Migrators) {
|
|
@@ -1091,16 +1132,27 @@ var VersionModule = class _VersionModule extends BaseModule {
|
|
|
1091
1132
|
}
|
|
1092
1133
|
}
|
|
1093
1134
|
}
|
|
1135
|
+
/**
|
|
1136
|
+
* Registers a new migrator for handling version-specific changes.
|
|
1137
|
+
* Migrators are sorted by their `MigrationVersion` in ascending order.
|
|
1138
|
+
*/
|
|
1094
1139
|
static registerMigrator(migrator) {
|
|
1095
1140
|
_VersionModule.Migrators.push(migrator);
|
|
1096
1141
|
_VersionModule.Migrators.sort((a, b) => a.MigrationVersion.localeCompare(b.MigrationVersion));
|
|
1097
1142
|
}
|
|
1143
|
+
/** Sets the message that will be displayed when a new version is detected. */
|
|
1098
1144
|
static setNewVersionMessage(newVersionMessage) {
|
|
1099
1145
|
_VersionModule.NewVersionMessage = newVersionMessage;
|
|
1100
1146
|
}
|
|
1147
|
+
/** Sends the currently configured "new version" message to the local player. */
|
|
1101
1148
|
static sendNewVersionMessage() {
|
|
1102
1149
|
sendLocalMessage("deeplib-new-version", _VersionModule.NewVersionMessage);
|
|
1103
1150
|
}
|
|
1151
|
+
/**
|
|
1152
|
+
* Determines if a given `candidate` version is newer than the `current` version.
|
|
1153
|
+
*
|
|
1154
|
+
* Version strings are expected in `MAJOR.MINOR.PATCH` format.
|
|
1155
|
+
*/
|
|
1104
1156
|
static isNewVersion(current, candidate) {
|
|
1105
1157
|
if (current !== void 0) {
|
|
1106
1158
|
const CURRENT_ = current.split("."), CANDIDATE_ = candidate.split(".");
|
|
@@ -1116,11 +1168,13 @@ var VersionModule = class _VersionModule extends BaseModule {
|
|
|
1116
1168
|
}
|
|
1117
1169
|
return false;
|
|
1118
1170
|
}
|
|
1171
|
+
/** Saves the current mod version into persistent player storage. */
|
|
1119
1172
|
static saveVersion() {
|
|
1120
1173
|
if (modStorage.playerStorage) {
|
|
1121
1174
|
Player[ModSdkManager.ModInfo.name].Version = _VersionModule.Version;
|
|
1122
1175
|
}
|
|
1123
1176
|
}
|
|
1177
|
+
/** Loads the stored mod version from persistent player storage. */
|
|
1124
1178
|
static loadVersion() {
|
|
1125
1179
|
return modStorage.playerStorage?.Version;
|
|
1126
1180
|
}
|
|
@@ -1686,22 +1740,39 @@ var Modal = class _Modal {
|
|
|
1686
1740
|
blocker;
|
|
1687
1741
|
inputEl;
|
|
1688
1742
|
timeoutId;
|
|
1743
|
+
/** Static modal queue. */
|
|
1689
1744
|
static queue = [];
|
|
1745
|
+
/** Flag to indicate if a modal is currently being shown. */
|
|
1690
1746
|
static processing = false;
|
|
1747
|
+
/**
|
|
1748
|
+
* Displays the modal and resolves with the chosen action and input value.
|
|
1749
|
+
*/
|
|
1691
1750
|
show() {
|
|
1692
1751
|
return _Modal.enqueue(this);
|
|
1693
1752
|
}
|
|
1753
|
+
/**
|
|
1754
|
+
* Shows a simple alert modal with a single "OK" button.
|
|
1755
|
+
*/
|
|
1694
1756
|
static async alert(msg, timeoutMs) {
|
|
1695
1757
|
await new _Modal({ prompt: msg, buttons: [{ action: "close", text: "OK" }], timeoutMs }).show();
|
|
1696
1758
|
}
|
|
1759
|
+
/**
|
|
1760
|
+
* Shows a confirmation modal with "Cancel" and "OK" buttons.
|
|
1761
|
+
* Returns true if "OK" is clicked.
|
|
1762
|
+
*/
|
|
1697
1763
|
static async confirm(msg) {
|
|
1698
1764
|
const [action] = await new _Modal({ prompt: msg, buttons: [{ text: "Cancel", action: "cancel" }, { text: "OK", action: "ok" }] }).show();
|
|
1699
1765
|
return action === "ok";
|
|
1700
1766
|
}
|
|
1767
|
+
/**
|
|
1768
|
+
* Shows a prompt modal with an input field and "Submit"/"Cancel" buttons.
|
|
1769
|
+
* Returns the input value if submitted, otherwise null.
|
|
1770
|
+
*/
|
|
1701
1771
|
static async prompt(msg, defaultValue = "") {
|
|
1702
1772
|
const [action, value] = await new _Modal({ prompt: msg, timeoutMs: 0, input: { type: "input", defaultValue }, buttons: [{ text: "Cancel", action: "cancel" }, { text: "Submit", action: "submit" }] }).show();
|
|
1703
1773
|
return action === "submit" ? value : null;
|
|
1704
1774
|
}
|
|
1775
|
+
/** Creates the input element for the modal, applying configuration and validation. */
|
|
1705
1776
|
renderInput(cfg) {
|
|
1706
1777
|
const el = document.createElement(cfg.type);
|
|
1707
1778
|
el.classList.add("deeplib-modal-input");
|
|
@@ -1716,6 +1787,7 @@ var Modal = class _Modal {
|
|
|
1716
1787
|
this.inputEl = el;
|
|
1717
1788
|
return el;
|
|
1718
1789
|
}
|
|
1790
|
+
/** Creates modal action buttons from configuration. */
|
|
1719
1791
|
renderButtons() {
|
|
1720
1792
|
const container = document.createElement("div");
|
|
1721
1793
|
container.classList.add("deeplib-modal-button-container");
|
|
@@ -1731,6 +1803,7 @@ var Modal = class _Modal {
|
|
|
1731
1803
|
});
|
|
1732
1804
|
return container;
|
|
1733
1805
|
}
|
|
1806
|
+
/** Creates the modal backdrop blocker with optional click-to-close behavior. */
|
|
1734
1807
|
createBlocker() {
|
|
1735
1808
|
const blocker = document.createElement("div");
|
|
1736
1809
|
blocker.classList.add("deeplib-modal-blocker");
|
|
@@ -1739,6 +1812,7 @@ var Modal = class _Modal {
|
|
|
1739
1812
|
blocker.addEventListener("click", () => this.close("close"));
|
|
1740
1813
|
return blocker;
|
|
1741
1814
|
}
|
|
1815
|
+
/** Implements a focus trap to keep keyboard navigation inside the modal. */
|
|
1742
1816
|
setupFocusTrap() {
|
|
1743
1817
|
const focusable = 'button, [href], input, textarea, select, [tabindex]:not([tabindex="-1"])';
|
|
1744
1818
|
const elements = Array.from(this.dialog.querySelectorAll(focusable));
|
|
@@ -1770,6 +1844,7 @@ var Modal = class _Modal {
|
|
|
1770
1844
|
(this.inputEl || first)?.focus();
|
|
1771
1845
|
});
|
|
1772
1846
|
}
|
|
1847
|
+
/** Closes the modal, cleans up DOM, resolves promise, and shows next queued modal. */
|
|
1773
1848
|
close(action) {
|
|
1774
1849
|
if (this.timeoutId) clearTimeout(this.timeoutId);
|
|
1775
1850
|
this.dialog.close();
|
|
@@ -1802,7 +1877,6 @@ var Modal = class _Modal {
|
|
|
1802
1877
|
}
|
|
1803
1878
|
}
|
|
1804
1879
|
};
|
|
1805
|
-
window.Modal = Modal;
|
|
1806
1880
|
|
|
1807
1881
|
// src/screens/main_menu.ts
|
|
1808
1882
|
var MainMenu = class _MainMenu extends BaseSubscreen {
|
|
@@ -1994,6 +2068,7 @@ var GuiImportExport = class extends BaseSubscreen {
|
|
|
1994
2068
|
resize() {
|
|
1995
2069
|
super.resize();
|
|
1996
2070
|
}
|
|
2071
|
+
/** Exports the mod data using the specified method. */
|
|
1997
2072
|
async dataExport(transferMethod) {
|
|
1998
2073
|
try {
|
|
1999
2074
|
const data = LZString.compressToBase64(JSON.stringify(modStorage.playerStorage));
|
|
@@ -2009,6 +2084,7 @@ var GuiImportExport = class extends BaseSubscreen {
|
|
|
2009
2084
|
deepLibLogger.error(`Data export failed for ${ModSdkManager.ModInfo.name}.`, error);
|
|
2010
2085
|
}
|
|
2011
2086
|
}
|
|
2087
|
+
/** Imports mod data using the specified method. */
|
|
2012
2088
|
async dataImport(transferMethod) {
|
|
2013
2089
|
try {
|
|
2014
2090
|
let importedData = "";
|
|
@@ -2032,6 +2108,7 @@ var GuiImportExport = class extends BaseSubscreen {
|
|
|
2032
2108
|
deepLibLogger.error(`Data import failed for ${ModSdkManager.ModInfo.name}.`, error);
|
|
2033
2109
|
}
|
|
2034
2110
|
}
|
|
2111
|
+
/** Saves data to a file using the browser's save dialog. */
|
|
2035
2112
|
async exportToFile(data, defaultFileName) {
|
|
2036
2113
|
const CUSTOM_EXTENSION = this.importExportOptions.customFileExtension.startsWith(".") ? this.importExportOptions.customFileExtension : "." + this.importExportOptions.customFileExtension;
|
|
2037
2114
|
const suggestedName = defaultFileName.endsWith(CUSTOM_EXTENSION) ? defaultFileName : defaultFileName + CUSTOM_EXTENSION;
|
|
@@ -2071,6 +2148,7 @@ var GuiImportExport = class extends BaseSubscreen {
|
|
|
2071
2148
|
URL.revokeObjectURL(link.href);
|
|
2072
2149
|
}
|
|
2073
2150
|
}
|
|
2151
|
+
/** Opens a file picker and reads the selected file's contents, importing the data. */
|
|
2074
2152
|
async importFromFile() {
|
|
2075
2153
|
const CUSTOM_EXTENSION = this.importExportOptions.customFileExtension.startsWith(".") ? this.importExportOptions.customFileExtension : "." + this.importExportOptions.customFileExtension;
|
|
2076
2154
|
async function importFromFileInternal(file) {
|
|
@@ -2123,11 +2201,13 @@ var GuiImportExport = class extends BaseSubscreen {
|
|
|
2123
2201
|
});
|
|
2124
2202
|
}
|
|
2125
2203
|
}
|
|
2204
|
+
/** Copies the given data to the clipboard. */
|
|
2126
2205
|
async exportToClipboard(data) {
|
|
2127
2206
|
return navigator.clipboard.writeText(data).catch((error) => {
|
|
2128
2207
|
throw new Error("Failed to copy data to clipboard." + error);
|
|
2129
2208
|
});
|
|
2130
2209
|
}
|
|
2210
|
+
/** Prompts the user to enter data and returns it. */
|
|
2131
2211
|
async importFromClipboard() {
|
|
2132
2212
|
return Modal.prompt("Enter data to import").catch((error) => {
|
|
2133
2213
|
throw new Error("Failed to read data from clipboard." + error);
|
|
@@ -2140,7 +2220,9 @@ var ModStorage = class _ModStorage {
|
|
|
2140
2220
|
static {
|
|
2141
2221
|
__name(this, "ModStorage");
|
|
2142
2222
|
}
|
|
2223
|
+
/** Singleton instance of ModStorage */
|
|
2143
2224
|
static _instance = null;
|
|
2225
|
+
/** The unique mod identifier used as key prefix in storage */
|
|
2144
2226
|
modName;
|
|
2145
2227
|
constructor(modName) {
|
|
2146
2228
|
if (!_ModStorage._instance) {
|
|
@@ -2206,10 +2288,34 @@ var ModStorage = class _ModStorage {
|
|
|
2206
2288
|
|
|
2207
2289
|
// src/utilities/elements/helpers.ts
|
|
2208
2290
|
var domUtil = {
|
|
2291
|
+
/**
|
|
2292
|
+
* Automatically sets the position of the element based on the given position.
|
|
2293
|
+
* The position can be either a [x, y] tuple or a function returning such a tuple.
|
|
2294
|
+
* If both x and y are defined, the element's position is updated accordingly.
|
|
2295
|
+
*/
|
|
2209
2296
|
autoSetPosition,
|
|
2297
|
+
/**
|
|
2298
|
+
* Automatically sets the size of the element based on the given size.
|
|
2299
|
+
* The size can be either a [width, height] tuple or a function returning such a tuple.
|
|
2300
|
+
* If both width and height are defined, the element's size is updated accordingly.
|
|
2301
|
+
*/
|
|
2210
2302
|
autoSetSize,
|
|
2303
|
+
/**
|
|
2304
|
+
* Hides the element by setting its CSS display property to 'none'.
|
|
2305
|
+
* If the element cannot be found, the function does nothing.
|
|
2306
|
+
*/
|
|
2211
2307
|
hide,
|
|
2308
|
+
/**
|
|
2309
|
+
* Unhides the element by clearing its CSS display property (sets it to '').
|
|
2310
|
+
* If the element cannot be found, the function does nothing.
|
|
2311
|
+
*/
|
|
2212
2312
|
unhide,
|
|
2313
|
+
/**
|
|
2314
|
+
* Checks if the element has overflow content.
|
|
2315
|
+
* Returns an object indicating if there is any overflow,
|
|
2316
|
+
* and specifically if there is vertical or horizontal overflow.
|
|
2317
|
+
* Returns null if the element is not found.
|
|
2318
|
+
*/
|
|
2213
2319
|
hasOverflow
|
|
2214
2320
|
};
|
|
2215
2321
|
function autoSetPosition(_, position) {
|
|
@@ -2487,10 +2593,12 @@ var ModSdkManager = class _ModSdkManager {
|
|
|
2487
2593
|
static SDK;
|
|
2488
2594
|
static patchedFunctions = /* @__PURE__ */ new Map();
|
|
2489
2595
|
static ModInfo;
|
|
2596
|
+
/** Registers a mod with the SDK and stores mod information. */
|
|
2490
2597
|
constructor(info, options) {
|
|
2491
2598
|
_ModSdkManager.SDK = bcModSdkRef.registerMod(info, options);
|
|
2492
2599
|
_ModSdkManager.ModInfo = info;
|
|
2493
2600
|
}
|
|
2601
|
+
/** Retrieves or initializes patch data for a given target function. */
|
|
2494
2602
|
initPatchableFunction(target) {
|
|
2495
2603
|
let result = _ModSdkManager.patchedFunctions.get(target);
|
|
2496
2604
|
if (!result) {
|
|
@@ -2502,6 +2610,11 @@ var ModSdkManager = class _ModSdkManager {
|
|
|
2502
2610
|
}
|
|
2503
2611
|
return result;
|
|
2504
2612
|
}
|
|
2613
|
+
/**
|
|
2614
|
+
* Hooks a function with a callback at a given priority.
|
|
2615
|
+
*
|
|
2616
|
+
* Prevents duplicate hooks.
|
|
2617
|
+
*/
|
|
2505
2618
|
hookFunction(target, priority, hook, module = null) {
|
|
2506
2619
|
const data = this.initPatchableFunction(target);
|
|
2507
2620
|
if (data.hooks.some((h) => h.hook === hook)) {
|
|
@@ -2517,12 +2630,23 @@ var ModSdkManager = class _ModSdkManager {
|
|
|
2517
2630
|
data.hooks.sort((a, b) => b.priority - a.priority);
|
|
2518
2631
|
return removeCallback;
|
|
2519
2632
|
}
|
|
2633
|
+
/**
|
|
2634
|
+
* Applies patches to a target function.
|
|
2635
|
+
*
|
|
2636
|
+
* **This method is DANGEROUS** to use and has high potential to conflict with other mods.
|
|
2637
|
+
*/
|
|
2520
2638
|
patchFunction(target, patches) {
|
|
2521
2639
|
_ModSdkManager.SDK?.patchFunction(target, patches);
|
|
2522
2640
|
}
|
|
2641
|
+
/**
|
|
2642
|
+
* Removes all patches from a target function.
|
|
2643
|
+
*/
|
|
2523
2644
|
unpatchFunction(target) {
|
|
2524
2645
|
_ModSdkManager.SDK?.removePatches(target);
|
|
2525
2646
|
}
|
|
2647
|
+
/**
|
|
2648
|
+
* Removes all hooks associated with a specific module from a target function.
|
|
2649
|
+
*/
|
|
2526
2650
|
removeHookByModule(target, module) {
|
|
2527
2651
|
const data = this.initPatchableFunction(target);
|
|
2528
2652
|
for (let i = data.hooks.length - 1; i >= 0; i--) {
|
|
@@ -2533,6 +2657,9 @@ var ModSdkManager = class _ModSdkManager {
|
|
|
2533
2657
|
}
|
|
2534
2658
|
return true;
|
|
2535
2659
|
}
|
|
2660
|
+
/**
|
|
2661
|
+
* Removes all hooks associated with a specific module across all patched functions.
|
|
2662
|
+
*/
|
|
2536
2663
|
removeAllHooksByModule(module) {
|
|
2537
2664
|
for (const data of _ModSdkManager.patchedFunctions.values()) {
|
|
2538
2665
|
for (let i = data.hooks.length - 1; i >= 0; i--) {
|
|
@@ -2548,6 +2675,10 @@ var ModSdkManager = class _ModSdkManager {
|
|
|
2548
2675
|
|
|
2549
2676
|
// src/utilities/style.ts
|
|
2550
2677
|
var Style = {
|
|
2678
|
+
/**
|
|
2679
|
+
* Injects a CSS style block directly into the document head using a <style> tag.
|
|
2680
|
+
* If a style element with the same `styleId` already exists, it won't inject again.
|
|
2681
|
+
*/
|
|
2551
2682
|
injectInline(styleId, styleSource) {
|
|
2552
2683
|
const isStyleLoaded = document.getElementById(styleId);
|
|
2553
2684
|
if (isStyleLoaded) return;
|
|
@@ -2556,6 +2687,10 @@ var Style = {
|
|
|
2556
2687
|
styleElement.appendChild(document.createTextNode(styleSource));
|
|
2557
2688
|
document.head.appendChild(styleElement);
|
|
2558
2689
|
},
|
|
2690
|
+
/**
|
|
2691
|
+
* Injects a CSS stylesheet link into the document head using a <link> tag.
|
|
2692
|
+
* If a link element with the same `styleId` already exists, it won't inject again.
|
|
2693
|
+
*/
|
|
2559
2694
|
injectEmbed(styleId, styleLink) {
|
|
2560
2695
|
const isStyleLoaded = document.getElementById(styleId);
|
|
2561
2696
|
if (isStyleLoaded) return;
|
|
@@ -2565,15 +2700,24 @@ var Style = {
|
|
|
2565
2700
|
styleElement.href = styleLink;
|
|
2566
2701
|
document.head.appendChild(styleElement);
|
|
2567
2702
|
},
|
|
2703
|
+
/**
|
|
2704
|
+
* Removes a style element from the document head by its ID.
|
|
2705
|
+
* Does nothing if the element is not found.
|
|
2706
|
+
*/
|
|
2568
2707
|
eject(id) {
|
|
2569
2708
|
const style = document.getElementById(id);
|
|
2570
2709
|
if (!style) return;
|
|
2571
2710
|
style.remove();
|
|
2572
2711
|
},
|
|
2712
|
+
/**
|
|
2713
|
+
* Reloads an inline style by removing the existing style element (if any)
|
|
2714
|
+
* and injecting the new styles inline again.
|
|
2715
|
+
*/
|
|
2573
2716
|
reload(styleId, styleSource) {
|
|
2574
2717
|
Style.eject(styleId);
|
|
2575
2718
|
Style.injectInline(styleId, styleSource);
|
|
2576
2719
|
},
|
|
2720
|
+
/** Fetches the text content of a stylesheet or any resource at the given link. */
|
|
2577
2721
|
async fetch(link) {
|
|
2578
2722
|
return fetch(link).then((res) => res.text());
|
|
2579
2723
|
}
|
|
@@ -2589,7 +2733,9 @@ var Localization = class _Localization {
|
|
|
2589
2733
|
static PathToModTranslation;
|
|
2590
2734
|
static PathToLibTranslation = `${PUBLIC_URL}/dl_translations/`;
|
|
2591
2735
|
static DefaultLanguage = "en";
|
|
2736
|
+
/** Flag to prevent re-initialization */
|
|
2592
2737
|
static initialized = false;
|
|
2738
|
+
/** Initialize the localization system by loading translation files. */
|
|
2593
2739
|
static async init(initOptions) {
|
|
2594
2740
|
if (_Localization.initialized) return;
|
|
2595
2741
|
_Localization.initialized = true;
|
|
@@ -2615,12 +2761,18 @@ var Localization = class _Localization {
|
|
|
2615
2761
|
_Localization.ModTranslation = { ...fallbackTranslation, ...modTranslation };
|
|
2616
2762
|
}
|
|
2617
2763
|
}
|
|
2764
|
+
/** Get a translated string from mod translations by source tag. */
|
|
2618
2765
|
static getTextMod(srcTag) {
|
|
2619
2766
|
return _Localization.ModTranslation?.[srcTag] || void 0;
|
|
2620
2767
|
}
|
|
2768
|
+
/** Get a translated string from library translations by source tag. */
|
|
2621
2769
|
static getTextLib(srcTag) {
|
|
2622
2770
|
return _Localization.LibTranslation?.[srcTag] || void 0;
|
|
2623
2771
|
}
|
|
2772
|
+
/**
|
|
2773
|
+
* Fetch and parse a language file from the given base URL and language code.
|
|
2774
|
+
* Falls back to default language if the requested language file is unavailable.
|
|
2775
|
+
*/
|
|
2624
2776
|
static async fetchLanguageFile(baseUrl, lang) {
|
|
2625
2777
|
const response = await fetch(`${baseUrl}${lang}.lang`);
|
|
2626
2778
|
if (lang !== _Localization.DefaultLanguage && !response.ok) {
|
|
@@ -2632,6 +2784,10 @@ var Localization = class _Localization {
|
|
|
2632
2784
|
const langFileContent = await response.text();
|
|
2633
2785
|
return this.parseLanguageFile(langFileContent);
|
|
2634
2786
|
}
|
|
2787
|
+
/**
|
|
2788
|
+
* Parse the raw content of a language file into a TranslationDict.
|
|
2789
|
+
* Ignores empty lines and comments starting with '#'.
|
|
2790
|
+
*/
|
|
2635
2791
|
static parseLanguageFile(content) {
|
|
2636
2792
|
const translations = {};
|
|
2637
2793
|
const lines = content.split("\n");
|