@vespura/vmenu-plugin 0.0.1 → 1.0.9
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/README.md +45 -45
- package/dist/client.js +37 -21
- package/dist/server.js +2 -2
- package/dist/types/client/diff.d.ts +1 -1
- package/dist/types/client/gate.d.ts +1 -1
- package/dist/types/client/host.d.ts +4 -4
- package/dist/types/client/index.d.ts +14 -14
- package/dist/types/client/item.d.ts +4 -4
- package/dist/types/client/items.d.ts +4 -4
- package/dist/types/client/key.d.ts +4 -4
- package/dist/types/client/menu.d.ts +5 -5
- package/dist/types/client/playerActions.d.ts +4 -4
- package/dist/types/client/plugin.d.ts +17 -11
- package/dist/types/client/themes.d.ts +1 -1
- package/dist/types/format.d.ts +1 -0
- package/dist/types/iife.d.ts +2 -2
- package/dist/types/server/index.d.ts +5 -5
- package/dist/types/server/server.d.ts +3 -3
- package/dist/vmenu.js +39 -24
- package/package.json +43 -44
package/README.md
CHANGED
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
# @vespura/vmenu-plugin
|
|
2
|
-
|
|
3
|
-
The TypeScript and JavaScript plugin API for vMenu Enhanced, the version of vMenu that runs on FiveM Enhanced (GTA V Enhanced).
|
|
4
|
-
|
|
5
|
-
A plugin is a normal FiveM resource of your own. With this package, your resource can add menus to vMenu, under a Plugins entry on its main menu. You describe the menu in code and the package talks to vMenu over events for you. vMenu never needs to know about your resource ahead of time.
|
|
6
|
-
|
|
7
|
-
Everything the C# plugin API can do is here too. That covers buttons, checkboxes, lists, sliders, dynamic lists, submenus, confirm rows, separators, keys, player actions, translations, permission and setting gates, notifications, text prompts and themes.
|
|
8
|
-
|
|
9
|
-
```ts
|
|
10
|
-
import { Gate, Text, VMenuPlugin } from '@vespura/vmenu-plugin/client';
|
|
11
|
-
|
|
12
|
-
const plugin = VMenuPlugin.create('My Plugin');
|
|
13
|
-
|
|
14
|
-
plugin.translations.add('en', { greet: 'Say hello' });
|
|
15
|
-
|
|
16
|
-
const enabled = plugin.settings.bool('Enabled', true, 'Turns my plugin on or off.');
|
|
17
|
-
|
|
18
|
-
const greet = plugin.rootMenu.addButton(Text.key('greet'), {
|
|
19
|
-
gate: Gate.permission('Greet').and(Gate.setting(enabled)),
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
greet.onSelected(() => plugin.notify(
|
|
23
|
-
|
|
24
|
-
await plugin.connect();
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
Your server script declares the permissions and settings through `@vespura/vmenu-plugin/server`:
|
|
28
|
-
|
|
29
|
-
```ts
|
|
30
|
-
import { ServerPluginDeclaration, VMenuServer } from '@vespura/vmenu-plugin/server';
|
|
31
|
-
|
|
32
|
-
await VMenuServer.register(
|
|
33
|
-
new ServerPluginDeclaration('My Plugin')
|
|
34
|
-
.addPermission('Greet', 'Lets someone use the greet button.')
|
|
35
|
-
.addBoolSetting('Enabled', true, 'Turns my plugin on or off.'),
|
|
36
|
-
);
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
The package ships ES modules, so bundle your client and server scripts with a bundler such as esbuild before FiveM loads them. Writing plain JavaScript without a bundler? The vMenu Enhanced release zip also has a single `vmenu.js` file in its `plugin-api` folder, to copy into your resource, with the exact same API on a global `vMenu` object.
|
|
40
|
-
|
|
41
|
-
The package version always matches the vMenu Enhanced release it belongs to. A full example resource lives in the [vMenu.ExamplePlugin](https://github.com/TomGrobbe/vMenu.ExamplePlugin) repository, and the documentation is at [docs.vespura.com](https://docs.vespura.com/vmenu/enhanced/plugins/typescript/).
|
|
42
|
-
|
|
43
|
-
## License
|
|
44
|
-
|
|
45
|
-
This package is licensed under the **GNU General Public License v3.0 or later**, `GPL-3.0-or-later`, the same license vMenu Enhanced itself uses. A plugin built on it is a work based on vMenu, so the license comes along with your plugin. Running it on your own server asks nothing of you. The moment you hand your plugin to somebody else, you owe them the complete source under this same license. The [C# package's readme](https://www.nuget.org/packages/vMenu.Enhanced.ClientAPI) explains this in more detail. This is a plain language summary, not legal advice.
|
|
1
|
+
# @vespura/vmenu-plugin
|
|
2
|
+
|
|
3
|
+
The TypeScript and JavaScript plugin API for vMenu Enhanced, the version of vMenu that runs on FiveM Enhanced (GTA V Enhanced).
|
|
4
|
+
|
|
5
|
+
A plugin is a normal FiveM resource of your own. With this package, your resource can add menus to vMenu, under a Plugins entry on its main menu. You describe the menu in code and the package talks to vMenu over events for you. vMenu never needs to know about your resource ahead of time.
|
|
6
|
+
|
|
7
|
+
Everything the C# plugin API can do is here too. That covers buttons, checkboxes, lists, sliders, dynamic lists, submenus, confirm rows, separators, keys, player actions, translations, permission and setting gates, notifications, text prompts and themes.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { Gate, NotifyStyle, Text, VMenuPlugin } from '@vespura/vmenu-plugin/client';
|
|
11
|
+
|
|
12
|
+
const plugin = VMenuPlugin.create('My Plugin');
|
|
13
|
+
|
|
14
|
+
plugin.translations.add('en', { greet: 'Say hello' });
|
|
15
|
+
|
|
16
|
+
const enabled = plugin.settings.bool('Enabled', true, 'Turns my plugin on or off.');
|
|
17
|
+
|
|
18
|
+
const greet = plugin.rootMenu.addButton(Text.key('greet'), {
|
|
19
|
+
gate: Gate.permission('Greet').and(Gate.setting(enabled)),
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
greet.onSelected(() => plugin.notify(NotifyStyle.Success, 'Hello!'));
|
|
23
|
+
|
|
24
|
+
await plugin.connect();
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Your server script declares the permissions and settings through `@vespura/vmenu-plugin/server`:
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { ServerPluginDeclaration, VMenuServer } from '@vespura/vmenu-plugin/server';
|
|
31
|
+
|
|
32
|
+
await VMenuServer.register(
|
|
33
|
+
new ServerPluginDeclaration('My Plugin')
|
|
34
|
+
.addPermission('Greet', 'Lets someone use the greet button.')
|
|
35
|
+
.addBoolSetting('Enabled', true, 'Turns my plugin on or off.'),
|
|
36
|
+
);
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The package ships ES modules, so bundle your client and server scripts with a bundler such as esbuild before FiveM loads them. Writing plain JavaScript without a bundler? The vMenu Enhanced release zip also has a single `vmenu.js` file in its `plugin-api` folder, to copy into your resource, with the exact same API on a global `vMenu` object.
|
|
40
|
+
|
|
41
|
+
The package version always matches the vMenu Enhanced release it belongs to. A full example resource lives in the [vMenu.ExamplePlugin](https://github.com/TomGrobbe/vMenu.ExamplePlugin) repository, and the documentation is at [docs.vespura.com](https://docs.vespura.com/vmenu/enhanced/plugins/typescript/).
|
|
42
|
+
|
|
43
|
+
## License
|
|
44
|
+
|
|
45
|
+
This package is licensed under the **GNU General Public License v3.0 or later**, `GPL-3.0-or-later`, the same license vMenu Enhanced itself uses. A plugin built on it is a work based on vMenu, so the license comes along with your plugin. Running it on your own server asks nothing of you. The moment you hand your plugin to somebody else, you owe them the complete source under this same license. The [C# package's readme](https://www.nuget.org/packages/vMenu.Enhanced.ClientAPI) explains this in more detail. This is a plain language summary, not legal advice.
|
package/dist/client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/version.ts
|
|
2
|
-
var version = true ? "
|
|
2
|
+
var version = true ? "1.0.9" : "0.0.0-local";
|
|
3
3
|
|
|
4
4
|
// src/text.ts
|
|
5
5
|
var Text = class _Text {
|
|
@@ -24,8 +24,8 @@ var Text = class _Text {
|
|
|
24
24
|
if (text === null || text === void 0) {
|
|
25
25
|
return void 0;
|
|
26
26
|
}
|
|
27
|
-
if (
|
|
28
|
-
return { text };
|
|
27
|
+
if (!(text instanceof _Text)) {
|
|
28
|
+
return { text: String(text) };
|
|
29
29
|
}
|
|
30
30
|
if (!text.isKey) {
|
|
31
31
|
return { text: text.value };
|
|
@@ -127,6 +127,10 @@ function formatFloat(value) {
|
|
|
127
127
|
const text = value.toFixed(4).replace(/0+$/, "");
|
|
128
128
|
return text.endsWith(".") ? `${text}0` : text;
|
|
129
129
|
}
|
|
130
|
+
function int(value) {
|
|
131
|
+
const number = Math.trunc(Number(value));
|
|
132
|
+
return Number.isFinite(number) ? number : 0;
|
|
133
|
+
}
|
|
130
134
|
|
|
131
135
|
// src/protocol.ts
|
|
132
136
|
var PROTOCOL_VERSION = 2;
|
|
@@ -673,6 +677,7 @@ var PluginList = class extends PluginItem {
|
|
|
673
677
|
return this.node.selectedIndex ?? 0;
|
|
674
678
|
}
|
|
675
679
|
set selectedIndex(value) {
|
|
680
|
+
value = int(value);
|
|
676
681
|
if (this.selectedIndex === value) {
|
|
677
682
|
return;
|
|
678
683
|
}
|
|
@@ -682,6 +687,7 @@ var PluginList = class extends PluginItem {
|
|
|
682
687
|
/** Replaces the options, optionally moving the selection at the same time. */
|
|
683
688
|
setOptions(options, selectedIndex) {
|
|
684
689
|
const refs = Text.toRefs(options);
|
|
690
|
+
selectedIndex = selectedIndex === void 0 ? void 0 : int(selectedIndex);
|
|
685
691
|
if (sameTexts(this.node.options, refs) && (selectedIndex === void 0 || selectedIndex === this.selectedIndex)) {
|
|
686
692
|
return;
|
|
687
693
|
}
|
|
@@ -764,6 +770,7 @@ var PluginSlider = class extends PluginItem {
|
|
|
764
770
|
return this.node.position ?? this.min;
|
|
765
771
|
}
|
|
766
772
|
set position(value) {
|
|
773
|
+
value = int(value);
|
|
767
774
|
if (this.position === value) {
|
|
768
775
|
return;
|
|
769
776
|
}
|
|
@@ -806,6 +813,7 @@ var PluginDynamicList = class extends PluginItem {
|
|
|
806
813
|
return this.node.value ?? "";
|
|
807
814
|
}
|
|
808
815
|
set value(value) {
|
|
816
|
+
value = String(value);
|
|
809
817
|
if (this.value === value) {
|
|
810
818
|
return;
|
|
811
819
|
}
|
|
@@ -823,7 +831,7 @@ var PluginDynamicList = class extends PluginItem {
|
|
|
823
831
|
case CallbackTypes.DynamicChanging:
|
|
824
832
|
if (typeof callback.left === "boolean") {
|
|
825
833
|
const next = this.changeRequested?.(callback.currentValue ?? "", callback.left);
|
|
826
|
-
if (
|
|
834
|
+
if (next !== null && next !== void 0) {
|
|
827
835
|
this.value = next;
|
|
828
836
|
}
|
|
829
837
|
}
|
|
@@ -1008,14 +1016,14 @@ var PluginMenu = class _PluginMenu {
|
|
|
1008
1016
|
addList(text, values, options) {
|
|
1009
1017
|
const node = this.newNode(EntryTypes.List, text, options);
|
|
1010
1018
|
node.options = Text.toRefs(values);
|
|
1011
|
-
node.selectedIndex = options?.selectedIndex ?? 0;
|
|
1019
|
+
node.selectedIndex = int(options?.selectedIndex ?? 0);
|
|
1012
1020
|
return this.attach(new PluginList(node, text), options);
|
|
1013
1021
|
}
|
|
1014
1022
|
/** Adds a list that asks for a second press before it does anything. */
|
|
1015
1023
|
addConfirmList(text, values, options) {
|
|
1016
1024
|
const node = this.newNode(EntryTypes.ConfirmList, text, options);
|
|
1017
1025
|
node.options = Text.toRefs(values);
|
|
1018
|
-
node.selectedIndex = options?.selectedIndex ?? 0;
|
|
1026
|
+
node.selectedIndex = int(options?.selectedIndex ?? 0);
|
|
1019
1027
|
const item = new PluginConfirmList(node, text);
|
|
1020
1028
|
if (options?.confirmationDescription !== void 0) {
|
|
1021
1029
|
item.confirmationDescription = options.confirmationDescription;
|
|
@@ -1025,16 +1033,16 @@ var PluginMenu = class _PluginMenu {
|
|
|
1025
1033
|
/** Adds a row with a bar the player drags between `min` and `max`. */
|
|
1026
1034
|
addSlider(text, min, max, position, options) {
|
|
1027
1035
|
const node = this.newNode(EntryTypes.Slider, text, options);
|
|
1028
|
-
node.min = min;
|
|
1029
|
-
node.max = max;
|
|
1030
|
-
node.position = position;
|
|
1036
|
+
node.min = int(min);
|
|
1037
|
+
node.max = int(max);
|
|
1038
|
+
node.position = int(position);
|
|
1031
1039
|
node.showDivider = options?.showDivider ?? false;
|
|
1032
1040
|
return this.attach(new PluginSlider(node, text), options);
|
|
1033
1041
|
}
|
|
1034
1042
|
/** Adds a row whose value your code works out each time the player scrolls it, through `changeRequested`. */
|
|
1035
1043
|
addDynamicList(text, initialValue, options) {
|
|
1036
1044
|
const node = this.newNode(EntryTypes.DynamicList, text, options);
|
|
1037
|
-
node.value = initialValue;
|
|
1045
|
+
node.value = String(initialValue);
|
|
1038
1046
|
return this.attach(new PluginDynamicList(node, text), options);
|
|
1039
1047
|
}
|
|
1040
1048
|
/** Adds a row that only shows text, used to split a menu into sections. */
|
|
@@ -1071,7 +1079,7 @@ var PluginMenu = class _PluginMenu {
|
|
|
1071
1079
|
description: Text.toRef(options?.description),
|
|
1072
1080
|
defaultKey,
|
|
1073
1081
|
defaultButton: options?.defaultButton,
|
|
1074
|
-
shadowedControl: options?.shadowedControl
|
|
1082
|
+
shadowedControl: options?.shadowedControl === void 0 ? void 0 : int(options.shadowedControl)
|
|
1075
1083
|
};
|
|
1076
1084
|
(_a = this.node).keys ?? (_a.keys = []);
|
|
1077
1085
|
this.node.keys.push(node);
|
|
@@ -1087,7 +1095,7 @@ var PluginMenu = class _PluginMenu {
|
|
|
1087
1095
|
*/
|
|
1088
1096
|
insertAt(index, add) {
|
|
1089
1097
|
const previous = this.insertIndex;
|
|
1090
|
-
this.insertIndex = clamp(index, 0, this.itemList.length);
|
|
1098
|
+
this.insertIndex = clamp(int(index), 0, this.itemList.length);
|
|
1091
1099
|
try {
|
|
1092
1100
|
add();
|
|
1093
1101
|
} finally {
|
|
@@ -1100,7 +1108,7 @@ var PluginMenu = class _PluginMenu {
|
|
|
1100
1108
|
if (from < 0) {
|
|
1101
1109
|
return;
|
|
1102
1110
|
}
|
|
1103
|
-
const to = clamp(index, 0, this.itemList.length - 1);
|
|
1111
|
+
const to = clamp(int(index), 0, this.itemList.length - 1);
|
|
1104
1112
|
if (to === from) {
|
|
1105
1113
|
return;
|
|
1106
1114
|
}
|
|
@@ -1314,12 +1322,13 @@ var PluginPlayerList = class extends PluginItem {
|
|
|
1314
1322
|
return this.node.selectedIndex ?? 0;
|
|
1315
1323
|
}
|
|
1316
1324
|
set selectedIndex(value) {
|
|
1317
|
-
this.node.selectedIndex = value;
|
|
1318
|
-
this.emit({ op: UpdateOps.SetSelectedIndex, itemId: this.id, index:
|
|
1325
|
+
this.node.selectedIndex = int(value);
|
|
1326
|
+
this.emit({ op: UpdateOps.SetSelectedIndex, itemId: this.id, index: this.node.selectedIndex });
|
|
1319
1327
|
}
|
|
1320
1328
|
/** Replaces the options, optionally moving the selection at the same time. */
|
|
1321
1329
|
setOptions(options, selectedIndex) {
|
|
1322
1330
|
this.node.options = Text.toRefs(options);
|
|
1331
|
+
selectedIndex = selectedIndex === void 0 ? void 0 : int(selectedIndex);
|
|
1323
1332
|
if (selectedIndex !== void 0) {
|
|
1324
1333
|
this.node.selectedIndex = selectedIndex;
|
|
1325
1334
|
}
|
|
@@ -1369,7 +1378,7 @@ var PluginPlayerActions = class {
|
|
|
1369
1378
|
addList(text, values, options) {
|
|
1370
1379
|
const node = this.newNode(EntryTypes.List, text, options);
|
|
1371
1380
|
node.options = Text.toRefs(values);
|
|
1372
|
-
node.selectedIndex = options?.selectedIndex ?? 0;
|
|
1381
|
+
node.selectedIndex = int(options?.selectedIndex ?? 0);
|
|
1373
1382
|
return this.attach(new PluginPlayerList(node, text), options);
|
|
1374
1383
|
}
|
|
1375
1384
|
/** Adds a row that only shows text. */
|
|
@@ -1448,9 +1457,9 @@ var PluginThemes = class {
|
|
|
1448
1457
|
return;
|
|
1449
1458
|
}
|
|
1450
1459
|
const current = list.current?.toLowerCase();
|
|
1451
|
-
this.availableValue = (list.themes
|
|
1460
|
+
this.availableValue = (Array.isArray(list.themes) ? list.themes : []).filter((theme) => typeof theme?.id === "string").map((theme) => ({
|
|
1452
1461
|
id: theme.id,
|
|
1453
|
-
name: theme.name,
|
|
1462
|
+
name: typeof theme.name === "string" ? theme.name : theme.id,
|
|
1454
1463
|
isCurrent: theme.id.toLowerCase() === current
|
|
1455
1464
|
}));
|
|
1456
1465
|
this.currentIdValue = list.current ?? void 0;
|
|
@@ -1489,6 +1498,12 @@ var PluginTranslations = class {
|
|
|
1489
1498
|
};
|
|
1490
1499
|
|
|
1491
1500
|
// src/client/plugin.ts
|
|
1501
|
+
var NotifyStyle = {
|
|
1502
|
+
Info: "info",
|
|
1503
|
+
Success: "success",
|
|
1504
|
+
Warning: "warning",
|
|
1505
|
+
Error: "error"
|
|
1506
|
+
};
|
|
1492
1507
|
var CarriedItemOps = /* @__PURE__ */ new Set([
|
|
1493
1508
|
UpdateOps.SetText,
|
|
1494
1509
|
UpdateOps.SetDescription,
|
|
@@ -1581,7 +1596,7 @@ var VMenuPlugin = class _VMenuPlugin {
|
|
|
1581
1596
|
if (!this.connected) {
|
|
1582
1597
|
return;
|
|
1583
1598
|
}
|
|
1584
|
-
emitLocal(PluginEvents.Notify, JSON.stringify({ style, text: Text.toRef(text), durationMs }));
|
|
1599
|
+
emitLocal(PluginEvents.Notify, JSON.stringify({ style, text: Text.toRef(text), durationMs: durationMs === void 0 ? void 0 : int(durationMs) }));
|
|
1585
1600
|
}
|
|
1586
1601
|
/** Asks the player for text through vMenu's input box. Resolves to null if they cancelled or the box was unavailable. */
|
|
1587
1602
|
async getText(title, options) {
|
|
@@ -1598,8 +1613,8 @@ var VMenuPlugin = class _VMenuPlugin {
|
|
|
1598
1613
|
requestId,
|
|
1599
1614
|
prompts: prompts.map((prompt) => ({
|
|
1600
1615
|
title: Text.toRef(prompt.title),
|
|
1601
|
-
maxLength: prompt.maxLength ?? 60,
|
|
1602
|
-
initial: prompt.initialValue ?? "",
|
|
1616
|
+
maxLength: int(prompt.maxLength ?? 60),
|
|
1617
|
+
initial: String(prompt.initialValue ?? ""),
|
|
1603
1618
|
suggestions: prompt.suggestions && prompt.suggestions.length > 0 ? prompt.suggestions.map((suggestion) => ({ value: suggestion.value, description: suggestion.description })) : void 0
|
|
1604
1619
|
}))
|
|
1605
1620
|
};
|
|
@@ -1877,6 +1892,7 @@ var VMenuPlugin = class _VMenuPlugin {
|
|
|
1877
1892
|
};
|
|
1878
1893
|
export {
|
|
1879
1894
|
Gate,
|
|
1895
|
+
NotifyStyle,
|
|
1880
1896
|
PluginBoolSetting,
|
|
1881
1897
|
PluginButton,
|
|
1882
1898
|
PluginCheckbox,
|
package/dist/server.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/version.ts
|
|
2
|
-
var version = true ? "
|
|
2
|
+
var version = true ? "1.0.9" : "0.0.0-local";
|
|
3
3
|
|
|
4
4
|
// src/format.ts
|
|
5
5
|
function formatFloat(value) {
|
|
@@ -111,7 +111,7 @@ var natives = globalThis;
|
|
|
111
111
|
var currentResource = () => natives.GetCurrentResourceName();
|
|
112
112
|
var emitLocal = (eventName, ...args) => natives.emit(eventName, ...args);
|
|
113
113
|
var onLocal = (eventName, handler) => natives.on(eventName, handler);
|
|
114
|
-
var isAceAllowed = (playerSource, object) => natives.IsPlayerAceAllowed(playerSource, object)
|
|
114
|
+
var isAceAllowed = (playerSource, object) => Boolean(natives.IsPlayerAceAllowed(playerSource, object));
|
|
115
115
|
var log = {
|
|
116
116
|
info: (resource, message) => console.log(`[${resource}] ${message}`),
|
|
117
117
|
warn: (resource, message) => console.warn(`[${resource}] ${message}`),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { GateNode, TextRef } from '../protocol';
|
|
1
|
+
import type { GateNode, TextRef } from '../protocol.js';
|
|
2
2
|
export declare function sameText(left: TextRef | undefined, right: TextRef | undefined): boolean;
|
|
3
3
|
export declare function sameTexts(left: TextRef[] | undefined, right: TextRef[] | undefined): boolean;
|
|
4
4
|
export declare function sameGate(left: GateNode | undefined, right: GateNode | undefined): boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { UpdateOp } from '../protocol';
|
|
2
|
-
import type { PluginItem } from './item';
|
|
3
|
-
import type { PluginKey } from './key';
|
|
4
|
-
import type { PluginMenu } from './menu';
|
|
1
|
+
import type { UpdateOp } from '../protocol.js';
|
|
2
|
+
import type { PluginItem } from './item.js';
|
|
3
|
+
import type { PluginKey } from './key.js';
|
|
4
|
+
import type { PluginMenu } from './menu.js';
|
|
5
5
|
export interface PluginHost {
|
|
6
6
|
readonly resource: string;
|
|
7
7
|
readonly isConnected: boolean;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
export { version } from '../version';
|
|
2
|
-
export { Text, type TextLike } from '../text';
|
|
3
|
-
export type { Unsubscribe } from '../signal';
|
|
4
|
-
export type { RegisterResult } from '../protocol';
|
|
5
|
-
export { Gate, type GateLike } from './gate';
|
|
6
|
-
export { PluginSetting, PluginBoolSetting, PluginIntSetting, PluginFloatSetting, PluginStringSetting, PluginSettings, } from './settings';
|
|
7
|
-
export { PluginItem, type ItemOptions } from './item';
|
|
8
|
-
export { PluginButton, PluginConfirmButton, PluginCheckbox, PluginList, PluginConfirmList, PluginSlider, PluginDynamicList, PluginSeparator, PluginSubmenu, } from './items';
|
|
9
|
-
export { PluginKey, type PluginKeyPress } from './key';
|
|
10
|
-
export { PluginMenu, type CheckboxOptions, type ConfirmOptions, type KeyOptions, type ListOptions, type SliderOptions, type SubmenuOptions, } from './menu';
|
|
11
|
-
export { PluginPlayerActions, PluginPlayerButton, PluginPlayerConfirmButton, PluginPlayerList, type PlayerTarget, } from './playerActions';
|
|
12
|
-
export { PluginThemes, type PluginTheme } from './themes';
|
|
13
|
-
export { PluginTranslations } from './translations';
|
|
14
|
-
export { VMenuPlugin,
|
|
1
|
+
export { version } from '../version.js';
|
|
2
|
+
export { Text, type TextLike } from '../text.js';
|
|
3
|
+
export type { Unsubscribe } from '../signal.js';
|
|
4
|
+
export type { RegisterResult } from '../protocol.js';
|
|
5
|
+
export { Gate, type GateLike } from './gate.js';
|
|
6
|
+
export { PluginSetting, PluginBoolSetting, PluginIntSetting, PluginFloatSetting, PluginStringSetting, PluginSettings, } from './settings.js';
|
|
7
|
+
export { PluginItem, type ItemOptions } from './item.js';
|
|
8
|
+
export { PluginButton, PluginConfirmButton, PluginCheckbox, PluginList, PluginConfirmList, PluginSlider, PluginDynamicList, PluginSeparator, PluginSubmenu, } from './items.js';
|
|
9
|
+
export { PluginKey, type PluginKeyPress } from './key.js';
|
|
10
|
+
export { PluginMenu, type CheckboxOptions, type ConfirmOptions, type KeyOptions, type ListOptions, type SliderOptions, type SubmenuOptions, } from './menu.js';
|
|
11
|
+
export { PluginPlayerActions, PluginPlayerButton, PluginPlayerConfirmButton, PluginPlayerList, type PlayerTarget, } from './playerActions.js';
|
|
12
|
+
export { PluginThemes, type PluginTheme } from './themes.js';
|
|
13
|
+
export { PluginTranslations } from './translations.js';
|
|
14
|
+
export { VMenuPlugin, NotifyStyle, type PluginPrompt, type PromptSuggestion } from './plugin.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { type UpdateOp } from '../protocol';
|
|
2
|
-
import { Signal, type Unsubscribe } from '../signal';
|
|
3
|
-
import { type TextLike } from '../text';
|
|
4
|
-
import { type GateLike } from './gate';
|
|
1
|
+
import { type UpdateOp } from '../protocol.js';
|
|
2
|
+
import { Signal, type Unsubscribe } from '../signal.js';
|
|
3
|
+
import { type TextLike } from '../text.js';
|
|
4
|
+
import { type GateLike } from './gate.js';
|
|
5
5
|
/** Properties every row accepts when you add it. Setting them here sends them along with the row itself. */
|
|
6
6
|
export interface ItemOptions {
|
|
7
7
|
/** A stable id of your own. Generated when left out. Unique within your plugin. */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Unsubscribe } from '../signal';
|
|
2
|
-
import { type TextLike } from '../text';
|
|
3
|
-
import { PluginItem } from './item';
|
|
4
|
-
import type { PluginMenu } from './menu';
|
|
1
|
+
import type { Unsubscribe } from '../signal.js';
|
|
2
|
+
import { type TextLike } from '../text.js';
|
|
3
|
+
import { PluginItem } from './item.js';
|
|
4
|
+
import type { PluginMenu } from './menu.js';
|
|
5
5
|
/** A row the player presses. */
|
|
6
6
|
export declare class PluginButton extends PluginItem {
|
|
7
7
|
private readonly selected;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { type Unsubscribe } from '../signal';
|
|
2
|
-
import { type TextLike } from '../text';
|
|
3
|
-
import { type GateLike } from './gate';
|
|
4
|
-
import type { PluginItem } from './item';
|
|
1
|
+
import { type Unsubscribe } from '../signal.js';
|
|
2
|
+
import { type TextLike } from '../text.js';
|
|
3
|
+
import { type GateLike } from './gate.js';
|
|
4
|
+
import type { PluginItem } from './item.js';
|
|
5
5
|
/**
|
|
6
6
|
* Which row the cursor was on when a key was pressed. At most one of the two is set, and neither
|
|
7
7
|
* when the menu is empty or the row is not one of yours.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { type Unsubscribe } from '../signal';
|
|
2
|
-
import { type TextLike } from '../text';
|
|
3
|
-
import { PluginItem, type ItemOptions } from './item';
|
|
4
|
-
import { PluginButton, PluginCheckbox, PluginConfirmButton, PluginConfirmList, PluginDynamicList, PluginList, PluginSeparator, PluginSlider, PluginSubmenu } from './items';
|
|
5
|
-
import { PluginKey } from './key';
|
|
1
|
+
import { type Unsubscribe } from '../signal.js';
|
|
2
|
+
import { type TextLike } from '../text.js';
|
|
3
|
+
import { PluginItem, type ItemOptions } from './item.js';
|
|
4
|
+
import { PluginButton, PluginCheckbox, PluginConfirmButton, PluginConfirmList, PluginDynamicList, PluginList, PluginSeparator, PluginSlider, PluginSubmenu } from './items.js';
|
|
5
|
+
import { PluginKey } from './key.js';
|
|
6
6
|
/** Extra properties for a confirm button or confirm list. */
|
|
7
7
|
export interface ConfirmOptions extends ItemOptions {
|
|
8
8
|
/** What the row asks before its second press. */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Unsubscribe } from '../signal';
|
|
2
|
-
import { type TextLike } from '../text';
|
|
3
|
-
import { PluginItem, type ItemOptions } from './item';
|
|
4
|
-
import { PluginSeparator } from './items';
|
|
1
|
+
import type { Unsubscribe } from '../signal.js';
|
|
2
|
+
import { type TextLike } from '../text.js';
|
|
3
|
+
import { PluginItem, type ItemOptions } from './item.js';
|
|
4
|
+
import { PluginSeparator } from './items.js';
|
|
5
5
|
/**
|
|
6
6
|
* The player a player action was used on, read from vMenu's Online Players snapshot. The snapshot
|
|
7
7
|
* can be stale and the player may have left, so your server side must check the target still exists
|
|
@@ -1,14 +1,20 @@
|
|
|
1
|
-
import { type RegisterResult } from '../protocol';
|
|
2
|
-
import { type Unsubscribe } from '../signal';
|
|
3
|
-
import { type TextLike } from '../text';
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
|
|
1
|
+
import { type RegisterResult } from '../protocol.js';
|
|
2
|
+
import { type Unsubscribe } from '../signal.js';
|
|
3
|
+
import { type TextLike } from '../text.js';
|
|
4
|
+
import { PluginMenu } from './menu.js';
|
|
5
|
+
import { PluginPlayerActions } from './playerActions.js';
|
|
6
|
+
import { PluginSettings } from './settings.js';
|
|
7
|
+
import { PluginThemes } from './themes.js';
|
|
8
|
+
import { PluginTranslations } from './translations.js';
|
|
9
|
+
/** How a notification is coloured in vMenu's notification area. The plain strings work too. */
|
|
10
|
+
export declare const NotifyStyle: {
|
|
11
|
+
readonly Info: 'info';
|
|
12
|
+
readonly Success: 'success';
|
|
13
|
+
readonly Warning: 'warning';
|
|
14
|
+
readonly Error: 'error';
|
|
15
|
+
};
|
|
10
16
|
/** How a notification is coloured in vMenu's notification area. */
|
|
11
|
-
export type NotifyStyle =
|
|
17
|
+
export type NotifyStyle = (typeof NotifyStyle)[keyof typeof NotifyStyle];
|
|
12
18
|
/** One suggestion row the input box offers while the player types. */
|
|
13
19
|
export interface PromptSuggestion {
|
|
14
20
|
/** What lands in the box when the suggestion is picked. */
|
|
@@ -30,7 +36,7 @@ export interface PluginPrompt {
|
|
|
30
36
|
* settings, then call `connect`. It registers again by itself whenever vMenu restarts, so everything
|
|
31
37
|
* you declared and changed since is restored.
|
|
32
38
|
*/
|
|
33
|
-
export declare class VMenuPlugin
|
|
39
|
+
export declare class VMenuPlugin {
|
|
34
40
|
private readonly displayName;
|
|
35
41
|
private readonly itemsById;
|
|
36
42
|
private readonly menusById;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Unsubscribe } from '../signal';
|
|
1
|
+
import { type Unsubscribe } from '../signal.js';
|
|
2
2
|
/** One of vMenu's looks. Hand the `id` to `themes.set` to put the menus in it, and show the `name` to the player. */
|
|
3
3
|
export interface PluginTheme {
|
|
4
4
|
readonly id: string;
|
package/dist/types/format.d.ts
CHANGED
package/dist/types/iife.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from './client/index';
|
|
2
|
-
export { ServerPluginDeclaration, VMenuServer } from './server/index';
|
|
1
|
+
export * from './client/index.js';
|
|
2
|
+
export { ServerPluginDeclaration, VMenuServer } from './server/index.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { version } from '../version';
|
|
2
|
-
export type { Unsubscribe } from '../signal';
|
|
3
|
-
export type { RegisterResult } from '../protocol';
|
|
4
|
-
export { ServerPluginDeclaration } from './declaration';
|
|
5
|
-
export { VMenuServer } from './server';
|
|
1
|
+
export { version } from '../version.js';
|
|
2
|
+
export type { Unsubscribe } from '../signal.js';
|
|
3
|
+
export type { RegisterResult } from '../protocol.js';
|
|
4
|
+
export { ServerPluginDeclaration } from './declaration.js';
|
|
5
|
+
export { VMenuServer } from './server.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type RegisterResult } from '../protocol';
|
|
2
|
-
import { type Unsubscribe } from '../signal';
|
|
3
|
-
import type { ServerPluginDeclaration } from './declaration';
|
|
1
|
+
import { type RegisterResult } from '../protocol.js';
|
|
2
|
+
import { type Unsubscribe } from '../signal.js';
|
|
3
|
+
import type { ServerPluginDeclaration } from './declaration.js';
|
|
4
4
|
/**
|
|
5
5
|
* The server side entry point for a plugin. Call `register` once at startup; registering again
|
|
6
6
|
* after a vMenu restart happens by itself. Then use `isPlayerAllowed` to check the permissions you declared.
|
package/dist/vmenu.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
// vMenu Enhanced plugin API for JavaScript, built for vMenu Enhanced
|
|
1
|
+
// vMenu Enhanced plugin API for JavaScript, built for vMenu Enhanced v1.0.9.
|
|
2
2
|
// Copy this file into your resource and load it before your own scripts, see https://docs.vespura.com/vmenu/enhanced/plugins/javascript/
|
|
3
|
-
// Licensed GPL-3.0-or-later, https://github.com/TomGrobbe/vMenu/blob/enhanced/LICENSE.md
|
|
4
3
|
"use strict";
|
|
5
4
|
var vMenu = (() => {
|
|
6
5
|
var __defProp = Object.defineProperty;
|
|
@@ -25,6 +24,7 @@ var vMenu = (() => {
|
|
|
25
24
|
var iife_exports = {};
|
|
26
25
|
__export(iife_exports, {
|
|
27
26
|
Gate: () => Gate,
|
|
27
|
+
NotifyStyle: () => NotifyStyle,
|
|
28
28
|
PluginBoolSetting: () => PluginBoolSetting,
|
|
29
29
|
PluginButton: () => PluginButton,
|
|
30
30
|
PluginCheckbox: () => PluginCheckbox,
|
|
@@ -57,7 +57,7 @@ var vMenu = (() => {
|
|
|
57
57
|
});
|
|
58
58
|
|
|
59
59
|
// src/version.ts
|
|
60
|
-
var version = true ? "
|
|
60
|
+
var version = true ? "1.0.9" : "0.0.0-local";
|
|
61
61
|
|
|
62
62
|
// src/text.ts
|
|
63
63
|
var Text = class _Text {
|
|
@@ -82,8 +82,8 @@ var vMenu = (() => {
|
|
|
82
82
|
if (text === null || text === void 0) {
|
|
83
83
|
return void 0;
|
|
84
84
|
}
|
|
85
|
-
if (
|
|
86
|
-
return { text };
|
|
85
|
+
if (!(text instanceof _Text)) {
|
|
86
|
+
return { text: String(text) };
|
|
87
87
|
}
|
|
88
88
|
if (!text.isKey) {
|
|
89
89
|
return { text: text.value };
|
|
@@ -161,7 +161,7 @@ var vMenu = (() => {
|
|
|
161
161
|
var getConvar = (name, fallback) => natives.GetConvar(name, fallback) ?? fallback;
|
|
162
162
|
var getKvp = (key) => natives.GetResourceKvpString(key) ?? void 0;
|
|
163
163
|
var setKvp = (key, value) => natives.SetResourceKvp(key, value);
|
|
164
|
-
var isAceAllowed = (playerSource, object) => natives.IsPlayerAceAllowed(playerSource, object)
|
|
164
|
+
var isAceAllowed = (playerSource, object) => Boolean(natives.IsPlayerAceAllowed(playerSource, object));
|
|
165
165
|
var log = {
|
|
166
166
|
info: (resource, message) => console.log(`[${resource}] ${message}`),
|
|
167
167
|
warn: (resource, message) => console.warn(`[${resource}] ${message}`),
|
|
@@ -186,6 +186,10 @@ var vMenu = (() => {
|
|
|
186
186
|
const text = value.toFixed(4).replace(/0+$/, "");
|
|
187
187
|
return text.endsWith(".") ? `${text}0` : text;
|
|
188
188
|
}
|
|
189
|
+
function int(value) {
|
|
190
|
+
const number = Math.trunc(Number(value));
|
|
191
|
+
return Number.isFinite(number) ? number : 0;
|
|
192
|
+
}
|
|
189
193
|
|
|
190
194
|
// src/protocol.ts
|
|
191
195
|
var PROTOCOL_VERSION = 2;
|
|
@@ -734,6 +738,7 @@ var vMenu = (() => {
|
|
|
734
738
|
return this.node.selectedIndex ?? 0;
|
|
735
739
|
}
|
|
736
740
|
set selectedIndex(value) {
|
|
741
|
+
value = int(value);
|
|
737
742
|
if (this.selectedIndex === value) {
|
|
738
743
|
return;
|
|
739
744
|
}
|
|
@@ -743,6 +748,7 @@ var vMenu = (() => {
|
|
|
743
748
|
/** Replaces the options, optionally moving the selection at the same time. */
|
|
744
749
|
setOptions(options, selectedIndex) {
|
|
745
750
|
const refs = Text.toRefs(options);
|
|
751
|
+
selectedIndex = selectedIndex === void 0 ? void 0 : int(selectedIndex);
|
|
746
752
|
if (sameTexts(this.node.options, refs) && (selectedIndex === void 0 || selectedIndex === this.selectedIndex)) {
|
|
747
753
|
return;
|
|
748
754
|
}
|
|
@@ -825,6 +831,7 @@ var vMenu = (() => {
|
|
|
825
831
|
return this.node.position ?? this.min;
|
|
826
832
|
}
|
|
827
833
|
set position(value) {
|
|
834
|
+
value = int(value);
|
|
828
835
|
if (this.position === value) {
|
|
829
836
|
return;
|
|
830
837
|
}
|
|
@@ -867,6 +874,7 @@ var vMenu = (() => {
|
|
|
867
874
|
return this.node.value ?? "";
|
|
868
875
|
}
|
|
869
876
|
set value(value) {
|
|
877
|
+
value = String(value);
|
|
870
878
|
if (this.value === value) {
|
|
871
879
|
return;
|
|
872
880
|
}
|
|
@@ -884,7 +892,7 @@ var vMenu = (() => {
|
|
|
884
892
|
case CallbackTypes.DynamicChanging:
|
|
885
893
|
if (typeof callback.left === "boolean") {
|
|
886
894
|
const next = this.changeRequested?.(callback.currentValue ?? "", callback.left);
|
|
887
|
-
if (
|
|
895
|
+
if (next !== null && next !== void 0) {
|
|
888
896
|
this.value = next;
|
|
889
897
|
}
|
|
890
898
|
}
|
|
@@ -1069,14 +1077,14 @@ var vMenu = (() => {
|
|
|
1069
1077
|
addList(text, values, options) {
|
|
1070
1078
|
const node = this.newNode(EntryTypes.List, text, options);
|
|
1071
1079
|
node.options = Text.toRefs(values);
|
|
1072
|
-
node.selectedIndex = options?.selectedIndex ?? 0;
|
|
1080
|
+
node.selectedIndex = int(options?.selectedIndex ?? 0);
|
|
1073
1081
|
return this.attach(new PluginList(node, text), options);
|
|
1074
1082
|
}
|
|
1075
1083
|
/** Adds a list that asks for a second press before it does anything. */
|
|
1076
1084
|
addConfirmList(text, values, options) {
|
|
1077
1085
|
const node = this.newNode(EntryTypes.ConfirmList, text, options);
|
|
1078
1086
|
node.options = Text.toRefs(values);
|
|
1079
|
-
node.selectedIndex = options?.selectedIndex ?? 0;
|
|
1087
|
+
node.selectedIndex = int(options?.selectedIndex ?? 0);
|
|
1080
1088
|
const item = new PluginConfirmList(node, text);
|
|
1081
1089
|
if (options?.confirmationDescription !== void 0) {
|
|
1082
1090
|
item.confirmationDescription = options.confirmationDescription;
|
|
@@ -1086,16 +1094,16 @@ var vMenu = (() => {
|
|
|
1086
1094
|
/** Adds a row with a bar the player drags between `min` and `max`. */
|
|
1087
1095
|
addSlider(text, min, max, position, options) {
|
|
1088
1096
|
const node = this.newNode(EntryTypes.Slider, text, options);
|
|
1089
|
-
node.min = min;
|
|
1090
|
-
node.max = max;
|
|
1091
|
-
node.position = position;
|
|
1097
|
+
node.min = int(min);
|
|
1098
|
+
node.max = int(max);
|
|
1099
|
+
node.position = int(position);
|
|
1092
1100
|
node.showDivider = options?.showDivider ?? false;
|
|
1093
1101
|
return this.attach(new PluginSlider(node, text), options);
|
|
1094
1102
|
}
|
|
1095
1103
|
/** Adds a row whose value your code works out each time the player scrolls it, through `changeRequested`. */
|
|
1096
1104
|
addDynamicList(text, initialValue, options) {
|
|
1097
1105
|
const node = this.newNode(EntryTypes.DynamicList, text, options);
|
|
1098
|
-
node.value = initialValue;
|
|
1106
|
+
node.value = String(initialValue);
|
|
1099
1107
|
return this.attach(new PluginDynamicList(node, text), options);
|
|
1100
1108
|
}
|
|
1101
1109
|
/** Adds a row that only shows text, used to split a menu into sections. */
|
|
@@ -1132,7 +1140,7 @@ var vMenu = (() => {
|
|
|
1132
1140
|
description: Text.toRef(options?.description),
|
|
1133
1141
|
defaultKey,
|
|
1134
1142
|
defaultButton: options?.defaultButton,
|
|
1135
|
-
shadowedControl: options?.shadowedControl
|
|
1143
|
+
shadowedControl: options?.shadowedControl === void 0 ? void 0 : int(options.shadowedControl)
|
|
1136
1144
|
};
|
|
1137
1145
|
(_a = this.node).keys ?? (_a.keys = []);
|
|
1138
1146
|
this.node.keys.push(node);
|
|
@@ -1148,7 +1156,7 @@ var vMenu = (() => {
|
|
|
1148
1156
|
*/
|
|
1149
1157
|
insertAt(index, add) {
|
|
1150
1158
|
const previous = this.insertIndex;
|
|
1151
|
-
this.insertIndex = clamp(index, 0, this.itemList.length);
|
|
1159
|
+
this.insertIndex = clamp(int(index), 0, this.itemList.length);
|
|
1152
1160
|
try {
|
|
1153
1161
|
add();
|
|
1154
1162
|
} finally {
|
|
@@ -1161,7 +1169,7 @@ var vMenu = (() => {
|
|
|
1161
1169
|
if (from < 0) {
|
|
1162
1170
|
return;
|
|
1163
1171
|
}
|
|
1164
|
-
const to = clamp(index, 0, this.itemList.length - 1);
|
|
1172
|
+
const to = clamp(int(index), 0, this.itemList.length - 1);
|
|
1165
1173
|
if (to === from) {
|
|
1166
1174
|
return;
|
|
1167
1175
|
}
|
|
@@ -1375,12 +1383,13 @@ var vMenu = (() => {
|
|
|
1375
1383
|
return this.node.selectedIndex ?? 0;
|
|
1376
1384
|
}
|
|
1377
1385
|
set selectedIndex(value) {
|
|
1378
|
-
this.node.selectedIndex = value;
|
|
1379
|
-
this.emit({ op: UpdateOps.SetSelectedIndex, itemId: this.id, index:
|
|
1386
|
+
this.node.selectedIndex = int(value);
|
|
1387
|
+
this.emit({ op: UpdateOps.SetSelectedIndex, itemId: this.id, index: this.node.selectedIndex });
|
|
1380
1388
|
}
|
|
1381
1389
|
/** Replaces the options, optionally moving the selection at the same time. */
|
|
1382
1390
|
setOptions(options, selectedIndex) {
|
|
1383
1391
|
this.node.options = Text.toRefs(options);
|
|
1392
|
+
selectedIndex = selectedIndex === void 0 ? void 0 : int(selectedIndex);
|
|
1384
1393
|
if (selectedIndex !== void 0) {
|
|
1385
1394
|
this.node.selectedIndex = selectedIndex;
|
|
1386
1395
|
}
|
|
@@ -1430,7 +1439,7 @@ var vMenu = (() => {
|
|
|
1430
1439
|
addList(text, values, options) {
|
|
1431
1440
|
const node = this.newNode(EntryTypes.List, text, options);
|
|
1432
1441
|
node.options = Text.toRefs(values);
|
|
1433
|
-
node.selectedIndex = options?.selectedIndex ?? 0;
|
|
1442
|
+
node.selectedIndex = int(options?.selectedIndex ?? 0);
|
|
1434
1443
|
return this.attach(new PluginPlayerList(node, text), options);
|
|
1435
1444
|
}
|
|
1436
1445
|
/** Adds a row that only shows text. */
|
|
@@ -1509,9 +1518,9 @@ var vMenu = (() => {
|
|
|
1509
1518
|
return;
|
|
1510
1519
|
}
|
|
1511
1520
|
const current = list.current?.toLowerCase();
|
|
1512
|
-
this.availableValue = (list.themes
|
|
1521
|
+
this.availableValue = (Array.isArray(list.themes) ? list.themes : []).filter((theme) => typeof theme?.id === "string").map((theme) => ({
|
|
1513
1522
|
id: theme.id,
|
|
1514
|
-
name: theme.name,
|
|
1523
|
+
name: typeof theme.name === "string" ? theme.name : theme.id,
|
|
1515
1524
|
isCurrent: theme.id.toLowerCase() === current
|
|
1516
1525
|
}));
|
|
1517
1526
|
this.currentIdValue = list.current ?? void 0;
|
|
@@ -1550,6 +1559,12 @@ var vMenu = (() => {
|
|
|
1550
1559
|
};
|
|
1551
1560
|
|
|
1552
1561
|
// src/client/plugin.ts
|
|
1562
|
+
var NotifyStyle = {
|
|
1563
|
+
Info: "info",
|
|
1564
|
+
Success: "success",
|
|
1565
|
+
Warning: "warning",
|
|
1566
|
+
Error: "error"
|
|
1567
|
+
};
|
|
1553
1568
|
var CarriedItemOps = /* @__PURE__ */ new Set([
|
|
1554
1569
|
UpdateOps.SetText,
|
|
1555
1570
|
UpdateOps.SetDescription,
|
|
@@ -1642,7 +1657,7 @@ var vMenu = (() => {
|
|
|
1642
1657
|
if (!this.connected) {
|
|
1643
1658
|
return;
|
|
1644
1659
|
}
|
|
1645
|
-
emitLocal(PluginEvents.Notify, JSON.stringify({ style, text: Text.toRef(text), durationMs }));
|
|
1660
|
+
emitLocal(PluginEvents.Notify, JSON.stringify({ style, text: Text.toRef(text), durationMs: durationMs === void 0 ? void 0 : int(durationMs) }));
|
|
1646
1661
|
}
|
|
1647
1662
|
/** Asks the player for text through vMenu's input box. Resolves to null if they cancelled or the box was unavailable. */
|
|
1648
1663
|
async getText(title, options) {
|
|
@@ -1659,8 +1674,8 @@ var vMenu = (() => {
|
|
|
1659
1674
|
requestId,
|
|
1660
1675
|
prompts: prompts.map((prompt) => ({
|
|
1661
1676
|
title: Text.toRef(prompt.title),
|
|
1662
|
-
maxLength: prompt.maxLength ?? 60,
|
|
1663
|
-
initial: prompt.initialValue ?? "",
|
|
1677
|
+
maxLength: int(prompt.maxLength ?? 60),
|
|
1678
|
+
initial: String(prompt.initialValue ?? ""),
|
|
1664
1679
|
suggestions: prompt.suggestions && prompt.suggestions.length > 0 ? prompt.suggestions.map((suggestion) => ({ value: suggestion.value, description: suggestion.description })) : void 0
|
|
1665
1680
|
}))
|
|
1666
1681
|
};
|
package/package.json
CHANGED
|
@@ -1,44 +1,43 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@vespura/vmenu-plugin",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Build vMenu Enhanced plugins in TypeScript or JavaScript.",
|
|
5
|
-
"license": "GPL-3.0-or-later",
|
|
6
|
-
"author": "Tom Grobbe",
|
|
7
|
-
"homepage": "https://docs.vespura.com/vmenu/enhanced/plugins/",
|
|
8
|
-
"repository": {
|
|
9
|
-
"type": "git",
|
|
10
|
-
"url": "git+https://github.com/TomGrobbe/vMenu.git",
|
|
11
|
-
"directory": "src/PluginApi/vMenu.Enhanced.JsAPI"
|
|
12
|
-
},
|
|
13
|
-
"keywords": [
|
|
14
|
-
"fivem",
|
|
15
|
-
"vmenu",
|
|
16
|
-
"plugin"
|
|
17
|
-
],
|
|
18
|
-
"type": "module",
|
|
19
|
-
"sideEffects": false,
|
|
20
|
-
"exports": {
|
|
21
|
-
"./client": {
|
|
22
|
-
"types": "./dist/types/client/index.d.ts",
|
|
23
|
-
"import": "./dist/client.js"
|
|
24
|
-
},
|
|
25
|
-
"./server": {
|
|
26
|
-
"types": "./dist/types/server/index.d.ts",
|
|
27
|
-
"import": "./dist/server.js"
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
"files": [
|
|
31
|
-
"dist",
|
|
32
|
-
"README.md",
|
|
33
|
-
"LICENSE.md"
|
|
34
|
-
],
|
|
35
|
-
"scripts": {
|
|
36
|
-
"check": "tsc --noEmit && node scripts/check-contracts.mjs",
|
|
37
|
-
"build": "node scripts/check-contracts.mjs && node scripts/build.mjs"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@vespura/vmenu-plugin",
|
|
3
|
+
"version": "1.0.9",
|
|
4
|
+
"description": "Build vMenu Enhanced plugins in TypeScript or JavaScript.",
|
|
5
|
+
"license": "GPL-3.0-or-later",
|
|
6
|
+
"author": "Tom Grobbe",
|
|
7
|
+
"homepage": "https://docs.vespura.com/vmenu/enhanced/plugins/",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/TomGrobbe/vMenu.git",
|
|
11
|
+
"directory": "src/PluginApi/vMenu.Enhanced.JsAPI"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"fivem",
|
|
15
|
+
"vmenu",
|
|
16
|
+
"plugin"
|
|
17
|
+
],
|
|
18
|
+
"type": "module",
|
|
19
|
+
"sideEffects": false,
|
|
20
|
+
"exports": {
|
|
21
|
+
"./client": {
|
|
22
|
+
"types": "./dist/types/client/index.d.ts",
|
|
23
|
+
"import": "./dist/client.js"
|
|
24
|
+
},
|
|
25
|
+
"./server": {
|
|
26
|
+
"types": "./dist/types/server/index.d.ts",
|
|
27
|
+
"import": "./dist/server.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"README.md",
|
|
33
|
+
"LICENSE.md"
|
|
34
|
+
],
|
|
35
|
+
"scripts": {
|
|
36
|
+
"check": "tsc --noEmit && node scripts/check-contracts.mjs",
|
|
37
|
+
"build": "node scripts/check-contracts.mjs && node scripts/build.mjs"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"esbuild": "0.28.2",
|
|
41
|
+
"typescript": "7.0.2"
|
|
42
|
+
}
|
|
43
|
+
}
|