@vespura/vmenu-plugin 0.0.0-stage → 1.0.8
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/LICENSE.md +678 -0
- package/README.md +45 -3
- package/dist/client.js +1923 -0
- package/dist/server.js +267 -0
- package/dist/types/client/diff.d.ts +4 -0
- package/dist/types/client/gate.d.ts +24 -0
- package/dist/types/client/host.d.ts +18 -0
- package/dist/types/client/index.d.ts +14 -0
- package/dist/types/client/item.d.ts +71 -0
- package/dist/types/client/items.d.ts +96 -0
- package/dist/types/client/key.d.ts +38 -0
- package/dist/types/client/menu.d.ts +142 -0
- package/dist/types/client/playerActions.d.ts +68 -0
- package/dist/types/client/plugin.d.ts +119 -0
- package/dist/types/client/preferences.d.ts +2 -0
- package/dist/types/client/settings.d.ts +49 -0
- package/dist/types/client/themes.d.ts +36 -0
- package/dist/types/client/translations.d.ts +10 -0
- package/dist/types/fivem.d.ts +14 -0
- package/dist/types/format.d.ts +2 -0
- package/dist/types/iife.d.ts +2 -0
- package/dist/types/protocol.d.ts +270 -0
- package/dist/types/server/declaration.d.ts +31 -0
- package/dist/types/server/index.d.ts +5 -0
- package/dist/types/server/server.d.ts +30 -0
- package/dist/types/signal.d.ts +12 -0
- package/dist/types/text.d.ts +20 -0
- package/dist/types/version.d.ts +2 -0
- package/dist/vmenu.js +2111 -0
- package/package.json +43 -6
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
export declare const PROTOCOL_VERSION = 2;
|
|
2
|
+
export declare const SERVER_PROTOCOL_VERSION = 1;
|
|
3
|
+
export declare const VMENU_RESOURCE = "vMenu.Enhanced";
|
|
4
|
+
export declare const PluginEvents: {
|
|
5
|
+
readonly Probe: 'vMenu.Enhanced:Plugins:Probe';
|
|
6
|
+
readonly Register: 'vMenu.Enhanced:Plugins:Register';
|
|
7
|
+
readonly Unregister: 'vMenu.Enhanced:Plugins:Unregister';
|
|
8
|
+
readonly Update: 'vMenu.Enhanced:Plugins:Update';
|
|
9
|
+
readonly Notify: 'vMenu.Enhanced:Plugins:Notify';
|
|
10
|
+
readonly Prompt: 'vMenu.Enhanced:Plugins:Prompt';
|
|
11
|
+
readonly SetTheme: 'vMenu.Enhanced:Plugins:SetTheme';
|
|
12
|
+
readonly RegisterThemes: 'vMenu.Enhanced:Plugins:RegisterThemes';
|
|
13
|
+
readonly Ready: 'vMenu.Enhanced:Plugins:Ready';
|
|
14
|
+
readonly ServerProbe: 'vMenu.Enhanced:Plugins:Server:Probe';
|
|
15
|
+
readonly ServerRegister: 'vMenu.Enhanced:Plugins:Server:Register';
|
|
16
|
+
readonly ServerDenied: 'vMenu.Enhanced:Plugins:Server:Denied';
|
|
17
|
+
readonly ServerReady: 'vMenu.Enhanced:Plugins:Server:Ready';
|
|
18
|
+
readonly readyFor: (resource: string) => string;
|
|
19
|
+
readonly registerResultFor: (resource: string) => string;
|
|
20
|
+
readonly eventFor: (resource: string) => string;
|
|
21
|
+
readonly promptResultFor: (resource: string) => string;
|
|
22
|
+
readonly themesFor: (resource: string) => string;
|
|
23
|
+
readonly themesRegisteredFor: (resource: string) => string;
|
|
24
|
+
readonly serverReadyFor: (resource: string) => string;
|
|
25
|
+
readonly serverRegisterResultFor: (resource: string) => string;
|
|
26
|
+
};
|
|
27
|
+
export declare const RefreshPermissionsEvent = "vMenu.Enhanced:Permissions:Refresh";
|
|
28
|
+
export declare const EntryTypes: {
|
|
29
|
+
readonly Button: 'button';
|
|
30
|
+
readonly Checkbox: 'checkbox';
|
|
31
|
+
readonly List: 'list';
|
|
32
|
+
readonly Slider: 'slider';
|
|
33
|
+
readonly DynamicList: 'dynamicList';
|
|
34
|
+
readonly Submenu: 'submenu';
|
|
35
|
+
readonly Separator: 'separator';
|
|
36
|
+
readonly ConfirmButton: 'confirmButton';
|
|
37
|
+
readonly ConfirmList: 'confirmList';
|
|
38
|
+
};
|
|
39
|
+
export declare const NodeEvents: {
|
|
40
|
+
readonly Opened: 'opened';
|
|
41
|
+
readonly Closed: 'closed';
|
|
42
|
+
readonly IndexChanged: 'indexChanged';
|
|
43
|
+
readonly Highlighted: 'highlighted';
|
|
44
|
+
};
|
|
45
|
+
export declare const SettingTypes: {
|
|
46
|
+
readonly Bool: 'bool';
|
|
47
|
+
readonly Int: 'int';
|
|
48
|
+
readonly Float: 'float';
|
|
49
|
+
readonly String: 'string';
|
|
50
|
+
};
|
|
51
|
+
export declare const CallbackTypes: {
|
|
52
|
+
readonly ItemSelected: 'itemSelected';
|
|
53
|
+
readonly CheckboxChanged: 'checkboxChanged';
|
|
54
|
+
readonly ListIndexChanged: 'listIndexChanged';
|
|
55
|
+
readonly ListSelected: 'listSelected';
|
|
56
|
+
readonly SliderMoved: 'sliderMoved';
|
|
57
|
+
readonly SliderSelected: 'sliderSelected';
|
|
58
|
+
readonly DynamicSelected: 'dynamicSelected';
|
|
59
|
+
readonly DynamicChanging: 'dynamicChanging';
|
|
60
|
+
readonly Confirmed: 'confirmed';
|
|
61
|
+
readonly ItemHighlighted: 'itemHighlighted';
|
|
62
|
+
readonly MenuOpened: 'menuOpened';
|
|
63
|
+
readonly MenuClosed: 'menuClosed';
|
|
64
|
+
readonly MenuIndexChanged: 'menuIndexChanged';
|
|
65
|
+
readonly PlayerActionSelected: 'playerActionSelected';
|
|
66
|
+
readonly PlayerActionConfirmed: 'playerActionConfirmed';
|
|
67
|
+
readonly PlayerActionListSelected: 'playerActionListSelected';
|
|
68
|
+
readonly KeyPressed: 'keyPressed';
|
|
69
|
+
};
|
|
70
|
+
export declare const UpdateOps: {
|
|
71
|
+
readonly SetText: 'setText';
|
|
72
|
+
readonly SetDescription: 'setDescription';
|
|
73
|
+
readonly SetLabel: 'setLabel';
|
|
74
|
+
readonly SetLockedDescription: 'setLockedDescription';
|
|
75
|
+
readonly SetConfirmationDescription: 'setConfirmationDescription';
|
|
76
|
+
readonly SetIcons: 'setIcons';
|
|
77
|
+
readonly SetChecked: 'setChecked';
|
|
78
|
+
readonly SetOptions: 'setOptions';
|
|
79
|
+
readonly SetSelectedIndex: 'setSelectedIndex';
|
|
80
|
+
readonly SetSliderPosition: 'setSliderPosition';
|
|
81
|
+
readonly SetValue: 'setValue';
|
|
82
|
+
readonly SetVisible: 'setVisible';
|
|
83
|
+
readonly SetEnabled: 'setEnabled';
|
|
84
|
+
readonly SetGate: 'setGate';
|
|
85
|
+
readonly SetLog: 'setLog';
|
|
86
|
+
readonly SetBehaviour: 'setBehaviour';
|
|
87
|
+
readonly SetItemEvents: 'setItemEvents';
|
|
88
|
+
readonly AddItems: 'addItems';
|
|
89
|
+
readonly RemoveItems: 'removeItems';
|
|
90
|
+
readonly ClearMenu: 'clearMenu';
|
|
91
|
+
readonly MoveItem: 'moveItem';
|
|
92
|
+
readonly AddPlayerActions: 'addPlayerActions';
|
|
93
|
+
readonly SetMenuTitle: 'setMenuTitle';
|
|
94
|
+
readonly SetMenuSubtitle: 'setMenuSubtitle';
|
|
95
|
+
readonly OpenMenu: 'openMenu';
|
|
96
|
+
readonly CloseMenu: 'closeMenu';
|
|
97
|
+
readonly SelectItem: 'selectItem';
|
|
98
|
+
readonly SetMenuEvents: 'setMenuEvents';
|
|
99
|
+
readonly SetFilter: 'setFilter';
|
|
100
|
+
readonly ClearFilter: 'clearFilter';
|
|
101
|
+
readonly AddKeys: 'addKeys';
|
|
102
|
+
readonly SetKeyText: 'setKeyText';
|
|
103
|
+
readonly SetKeyEnabled: 'setKeyEnabled';
|
|
104
|
+
readonly SetKeyGate: 'setKeyGate';
|
|
105
|
+
readonly MergeTranslations: 'mergeTranslations';
|
|
106
|
+
};
|
|
107
|
+
export interface TextRef {
|
|
108
|
+
text?: string;
|
|
109
|
+
key?: string;
|
|
110
|
+
args?: Record<string, TextRef>;
|
|
111
|
+
}
|
|
112
|
+
export interface GateNode {
|
|
113
|
+
permission?: string;
|
|
114
|
+
setting?: string;
|
|
115
|
+
all?: GateNode[];
|
|
116
|
+
any?: GateNode[];
|
|
117
|
+
}
|
|
118
|
+
export interface ItemNode {
|
|
119
|
+
id: string;
|
|
120
|
+
type: string;
|
|
121
|
+
text?: TextRef;
|
|
122
|
+
description?: TextRef;
|
|
123
|
+
label?: TextRef;
|
|
124
|
+
lockedDescription?: TextRef;
|
|
125
|
+
gate?: GateNode;
|
|
126
|
+
behaviour?: string;
|
|
127
|
+
leftIcon?: string;
|
|
128
|
+
rightIcon?: string;
|
|
129
|
+
events?: string[];
|
|
130
|
+
visible?: boolean;
|
|
131
|
+
enabled?: boolean;
|
|
132
|
+
log?: boolean;
|
|
133
|
+
checked?: boolean;
|
|
134
|
+
checkStyle?: string;
|
|
135
|
+
options?: TextRef[];
|
|
136
|
+
selectedIndex?: number;
|
|
137
|
+
min?: number;
|
|
138
|
+
max?: number;
|
|
139
|
+
position?: number;
|
|
140
|
+
showDivider?: boolean;
|
|
141
|
+
value?: string;
|
|
142
|
+
confirmationDescription?: TextRef;
|
|
143
|
+
menu?: MenuNode;
|
|
144
|
+
}
|
|
145
|
+
export interface KeyNode {
|
|
146
|
+
id: string;
|
|
147
|
+
text?: TextRef;
|
|
148
|
+
description?: TextRef;
|
|
149
|
+
defaultKey: string;
|
|
150
|
+
defaultButton?: string;
|
|
151
|
+
shadowedControl?: number;
|
|
152
|
+
gate?: GateNode;
|
|
153
|
+
enabled?: boolean;
|
|
154
|
+
}
|
|
155
|
+
export interface MenuNode {
|
|
156
|
+
id: string;
|
|
157
|
+
title?: TextRef;
|
|
158
|
+
subtitle?: TextRef;
|
|
159
|
+
events?: string[];
|
|
160
|
+
items: ItemNode[];
|
|
161
|
+
keys?: KeyNode[];
|
|
162
|
+
}
|
|
163
|
+
export interface SettingNode {
|
|
164
|
+
name: string;
|
|
165
|
+
type: string;
|
|
166
|
+
default: string;
|
|
167
|
+
description: string;
|
|
168
|
+
}
|
|
169
|
+
export interface UpdateOp {
|
|
170
|
+
op: string;
|
|
171
|
+
itemId?: string;
|
|
172
|
+
menuId?: string;
|
|
173
|
+
keyId?: string;
|
|
174
|
+
textValue?: TextRef;
|
|
175
|
+
leftIcon?: string;
|
|
176
|
+
rightIcon?: string;
|
|
177
|
+
flag?: boolean;
|
|
178
|
+
index?: number;
|
|
179
|
+
value?: string;
|
|
180
|
+
options?: TextRef[];
|
|
181
|
+
gate?: GateNode;
|
|
182
|
+
items?: ItemNode[];
|
|
183
|
+
itemIds?: string[];
|
|
184
|
+
beforeItemId?: string;
|
|
185
|
+
events?: string[];
|
|
186
|
+
keys?: KeyNode[];
|
|
187
|
+
language?: string;
|
|
188
|
+
entries?: Record<string, string>;
|
|
189
|
+
}
|
|
190
|
+
export interface PluginCallback {
|
|
191
|
+
type: string;
|
|
192
|
+
menuId?: string;
|
|
193
|
+
itemId?: string;
|
|
194
|
+
keyId?: string;
|
|
195
|
+
disabledItemId?: string;
|
|
196
|
+
checked?: boolean;
|
|
197
|
+
oldIndex?: number;
|
|
198
|
+
newIndex?: number;
|
|
199
|
+
selectedIndex?: number;
|
|
200
|
+
oldPosition?: number;
|
|
201
|
+
newPosition?: number;
|
|
202
|
+
position?: number;
|
|
203
|
+
value?: string;
|
|
204
|
+
currentValue?: string;
|
|
205
|
+
left?: boolean;
|
|
206
|
+
targetServerId?: number;
|
|
207
|
+
targetName?: string;
|
|
208
|
+
}
|
|
209
|
+
export interface RegisterRequest {
|
|
210
|
+
protocolVersion: number;
|
|
211
|
+
displayName?: TextRef;
|
|
212
|
+
descriptionKey?: string;
|
|
213
|
+
translations?: Record<string, Record<string, string>>;
|
|
214
|
+
settings?: SettingNode[];
|
|
215
|
+
menu?: MenuNode;
|
|
216
|
+
playerActions?: ItemNode[];
|
|
217
|
+
}
|
|
218
|
+
/** vMenu's answer to a registration. Errors mean it was refused, warnings mean it was accepted with parts skipped. */
|
|
219
|
+
export interface RegisterResult {
|
|
220
|
+
/** Whether vMenu took the registration. */
|
|
221
|
+
accepted: boolean;
|
|
222
|
+
/** The protocol version vMenu speaks. */
|
|
223
|
+
protocolVersion: number;
|
|
224
|
+
/** Why the registration was refused. */
|
|
225
|
+
errors: string[];
|
|
226
|
+
/** What vMenu skipped while accepting it. */
|
|
227
|
+
warnings: string[];
|
|
228
|
+
}
|
|
229
|
+
export interface PromptRequest {
|
|
230
|
+
requestId: number;
|
|
231
|
+
prompts: {
|
|
232
|
+
title?: TextRef;
|
|
233
|
+
maxLength: number;
|
|
234
|
+
initial: string;
|
|
235
|
+
suggestions?: {
|
|
236
|
+
value: string;
|
|
237
|
+
description?: string;
|
|
238
|
+
}[];
|
|
239
|
+
}[];
|
|
240
|
+
}
|
|
241
|
+
export interface PromptResult {
|
|
242
|
+
requestId: number;
|
|
243
|
+
cancelled: boolean;
|
|
244
|
+
busy: boolean;
|
|
245
|
+
answers?: string[];
|
|
246
|
+
}
|
|
247
|
+
export interface ThemeList {
|
|
248
|
+
themes?: {
|
|
249
|
+
id: string;
|
|
250
|
+
name: string;
|
|
251
|
+
}[];
|
|
252
|
+
current?: string;
|
|
253
|
+
configured?: string;
|
|
254
|
+
overridden?: boolean;
|
|
255
|
+
}
|
|
256
|
+
export interface ServerRegisterRequest {
|
|
257
|
+
protocolVersion: number;
|
|
258
|
+
displayName: string;
|
|
259
|
+
permissions?: {
|
|
260
|
+
name: string;
|
|
261
|
+
description: string;
|
|
262
|
+
staffOnly: boolean;
|
|
263
|
+
}[];
|
|
264
|
+
settings?: SettingNode[];
|
|
265
|
+
loggedItems?: {
|
|
266
|
+
itemId: string;
|
|
267
|
+
description: string;
|
|
268
|
+
}[];
|
|
269
|
+
}
|
|
270
|
+
export declare function normalizeResult(raw: Partial<RegisterResult> | undefined): RegisterResult | undefined;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Everything a plugin's server side declares with vMenu: a display name for the generated example
|
|
3
|
+
* files, the permission names it wants under its own scope, and the convar settings vMenu should
|
|
4
|
+
* describe to server owners. Names are short: vMenu composes the full
|
|
5
|
+
* `vMenu.Enhanced.Plugins.<Id>.<Name>` form from the resource name.
|
|
6
|
+
*/
|
|
7
|
+
export declare class ServerPluginDeclaration {
|
|
8
|
+
readonly displayName: string;
|
|
9
|
+
private readonly permissions;
|
|
10
|
+
private readonly settings;
|
|
11
|
+
private readonly loggedItems;
|
|
12
|
+
/** @param displayName Used in the generated example files, so owners see which plugin a section belongs to. */
|
|
13
|
+
constructor(displayName: string);
|
|
14
|
+
/** Declares a permission. `staffOnly` marks it as staff only in the generated permissions example. */
|
|
15
|
+
addPermission(name: string, description: string, staffOnly?: boolean): this;
|
|
16
|
+
/**
|
|
17
|
+
* Lets the server owner see a line in their webhook whenever somebody uses this row. The client
|
|
18
|
+
* half still has to set `log` on it. `description` is a noun phrase dropped into vMenu's own
|
|
19
|
+
* wording, as in "turned the anti-grief shield on".
|
|
20
|
+
*/
|
|
21
|
+
addLoggedItem(itemId: string, description: string): this;
|
|
22
|
+
/** Declares an on or off setting. */
|
|
23
|
+
addBoolSetting(name: string, defaultValue: boolean, description: string): this;
|
|
24
|
+
/** Declares a whole number setting. */
|
|
25
|
+
addIntSetting(name: string, defaultValue: number, description: string): this;
|
|
26
|
+
/** Declares a decimal number setting. */
|
|
27
|
+
addFloatSetting(name: string, defaultValue: number, description: string): this;
|
|
28
|
+
/** Declares a text setting. */
|
|
29
|
+
addStringSetting(name: string, defaultValue: string, description: string): this;
|
|
30
|
+
private add;
|
|
31
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type RegisterResult } from '../protocol.js';
|
|
2
|
+
import { type Unsubscribe } from '../signal.js';
|
|
3
|
+
import type { ServerPluginDeclaration } from './declaration.js';
|
|
4
|
+
/**
|
|
5
|
+
* The server side entry point for a plugin. Call `register` once at startup; registering again
|
|
6
|
+
* after a vMenu restart happens by itself. Then use `isPlayerAllowed` to check the permissions you declared.
|
|
7
|
+
*/
|
|
8
|
+
export declare const VMenuServer: {
|
|
9
|
+
/**
|
|
10
|
+
* Declares the plugin with vMenu. The promise resolves on vMenu's first answer, which can be a
|
|
11
|
+
* while when vMenu starts later than the plugin. It never rejects: a refusal arrives as a result
|
|
12
|
+
* with `accepted` false.
|
|
13
|
+
*/
|
|
14
|
+
register(pluginDeclaration: ServerPluginDeclaration): Promise<RegisterResult>;
|
|
15
|
+
/**
|
|
16
|
+
* Whether a player holds one of the plugin's own permissions, by its short name. Also honours the
|
|
17
|
+
* container grants a server owner may have used instead of the exact name.
|
|
18
|
+
*/
|
|
19
|
+
isPlayerAllowed(playerSource: string | number, permissionName: string): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* The same check as `isPlayerAllowed`, but a refusal is also reported to vMenu's security webhook.
|
|
22
|
+
* Use it where a legitimate client could only ever have sent the thing you are handling while
|
|
23
|
+
* allowed, and keep `isPlayerAllowed` for ordinary branching.
|
|
24
|
+
*/
|
|
25
|
+
requirePermission(playerSource: string | number, permissionName: string): boolean;
|
|
26
|
+
/** Refreshes permissions for one or more players. Passing no ids refreshes every connected player. */
|
|
27
|
+
refreshPermissions(...serverIds: number[]): void;
|
|
28
|
+
/** Called on every registration answer, including automatic re-registrations. */
|
|
29
|
+
onRegistrationAnswered(handler: (result: RegisterResult) => void): Unsubscribe;
|
|
30
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Call it to stop receiving the event you subscribed to. */
|
|
2
|
+
export type Unsubscribe = () => void;
|
|
3
|
+
export declare class Signal<T extends unknown[]> {
|
|
4
|
+
private readonly resource;
|
|
5
|
+
private readonly name;
|
|
6
|
+
private handlers;
|
|
7
|
+
constructor(resource: () => string, name: string);
|
|
8
|
+
get hasHandlers(): boolean;
|
|
9
|
+
add(handler: (...args: T) => void): Unsubscribe;
|
|
10
|
+
fire(...args: T): void;
|
|
11
|
+
}
|
|
12
|
+
export declare function describe(error: unknown): string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Anything that can be shown as text: a plain string is a literal, a {@link Text} can also be a translation key. */
|
|
2
|
+
export type TextLike = string | Text;
|
|
3
|
+
/**
|
|
4
|
+
* A piece of display text, either a literal or a key into your plugin's translation tables. A plain
|
|
5
|
+
* string is a literal, so translating is always deliberate. vMenu resolves keys against the tables
|
|
6
|
+
* you registered, following its selected language with your English table as the fallback.
|
|
7
|
+
*/
|
|
8
|
+
export declare class Text {
|
|
9
|
+
private readonly value;
|
|
10
|
+
private readonly isKey;
|
|
11
|
+
private readonly args?;
|
|
12
|
+
private constructor();
|
|
13
|
+
/** Text shown exactly as written, never translated. */
|
|
14
|
+
static literal(text: string): Text;
|
|
15
|
+
/**
|
|
16
|
+
* A translation key, optionally with named placeholder values. In the translated string,
|
|
17
|
+
* `{name}` is replaced with the matching value, which can itself be a literal or another key.
|
|
18
|
+
*/
|
|
19
|
+
static key(key: string, args?: Record<string, TextLike>): Text;
|
|
20
|
+
}
|