@amxts/menu-core 0.1.0 → 0.2.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/src/internal.ts CHANGED
@@ -1,328 +1,350 @@
1
- /**
2
- * Menu Core's own bookkeeping: registrations, viewers, a menu's items and the
3
- * menu being drawn. Not part of the API.
4
- */
5
- import { Player } from "@amxts/core";
6
- import { ActionHandler, ActionTest, ConditionFilter, ConditionTest, ListRow, ListSource, MenuText, PlaceholderValue, Requirement, RestrictionTest, RowTest } from "./types";
7
-
8
- /** Whether an item is shown, or can be chosen: `player` looks, `target` is the row's or the menu's. */
9
- export type ItemTest = (player: Player, target: number) => boolean;
10
- /** Whether a menu opens for the player. */
11
- export type OpenTest = (player: Player) => boolean;
12
-
13
- /**
14
- * One way an item can look, shown when its `when` holds - the first that
15
- * does. A menu file's `variants`, or "A|B" in menu.ini, where `when` is the
16
- * condition column's piece.
17
- */
18
- export interface Variant {
19
- name: string;
20
- /** Names; "" is always. */
21
- when: string;
22
- /** Action names, built-in ones among them. */
23
- action: string;
24
- }
25
-
26
- /** A requirement of an item - `visible`, or one of `enabled`: a test from code, or a line of names from a menu file. */
27
- export interface Check {
28
- test: ItemTest | null;
29
- /** Names, as a menu file's `when` gives them; "" with a test. */
30
- when: string;
31
- /** Beside the item while it says no; null for the item's `message`. */
32
- message: MenuText | null;
33
- }
34
-
35
- export interface MenuItem {
36
- /** Its text; "A|B" in it are variants when `ini`. */
37
- label: MenuText;
38
- /** Action names, "X|Y" a variant each when `ini`. */
39
- action: string;
40
- /** Text after the name: "%hp%". */
41
- placeholder: string;
42
- /** Left out while it says no: it takes no slot. */
43
- visible: Check | null;
44
- /** Greyed out while one says no: the first that does gives its message. */
45
- enabled: Check[];
46
- /** Beside the item while a requirement without a message of its own greys it out. */
47
- message: MenuText | null;
48
- /**
49
- * An item of menu.ini or of a Pawn plugin: "A|B" in the text are variants,
50
- * `condition` "C1|C2" picks one - greyed out, without a reason, when none
51
- * holds - and `restriction` greys it out with `restrictionMessage`.
52
- */
53
- ini: boolean;
54
- /** INI's condition names, "C1|C2" a variant each; "" is always. */
55
- condition: string;
56
- /** INI's restriction names, space-separated. */
57
- restriction: string;
58
- /** INI's message: "NAME:message|NAME2:message", or one message. */
59
- restrictionMessage: string;
60
- spaceBefore: number;
61
- spaceAfter: number;
62
- /** The slot a fixed item takes, from 0; -1 in the flow. */
63
- slot: number;
64
- /** Variants given one by one (a menu file's `variants`); null for the item's own text and action, or "A|B" when `ini`. */
65
- variants: Variant[] | null;
66
- }
67
-
68
- /** An item made in code, or read from a YAML or JSON file: its text and action, in `slot` - -1 for the flow. */
69
- export function blankItem(label: MenuText, action: string, slot: number) {
70
- const item: MenuItem = { label, action, placeholder: "", visible: null, enabled: [], message: null, ini: false, condition: "", restriction: "", restrictionMessage: "", spaceBefore: 0, spaceAfter: 0, slot, variants: null };
71
- return item;
72
- }
73
-
74
- /** An item as menu.ini's columns and the mc_* natives give it. */
75
- export function iniItem(label: string, placeholder: string, condition: string, action: string, restriction: string, message: string, slot: number) {
76
- const item = blankItem(label, action, slot);
77
- item.ini = true;
78
- item.placeholder = placeholder;
79
- item.condition = condition;
80
- item.restriction = restriction;
81
- item.restrictionMessage = message;
82
- return item;
83
- }
84
-
85
- /** Puts an item among the menu's items: at `at`, from 0, or at the end when it is -1 or past them. */
86
- export function insertItem(menu: string, item: MenuItem, at: number) {
87
- const items = stateOf(menu).items;
88
- if (at >= 0 && at < items.length) items.splice(at, 0, item);
89
- else items.push(item);
90
- }
91
-
92
- /** A requirement of a menu file: its names, and the message beside the item while they do not hold - "" for the item's. */
93
- export interface RequirementSpec {
94
- when: string;
95
- message: string;
96
- }
97
-
98
- /** An item as a menu file describes it, whatever the file's format. */
99
- export interface ItemSpec {
100
- name: string;
101
- placeholder: string;
102
- action: string;
103
- /** Whether it is INI's: "A|B" variants, and the three columns below. */
104
- ini: boolean;
105
- condition: string;
106
- restriction: string;
107
- restrictionMessage: string;
108
- /** YAML's and JSON's: names the item is shown under, "" for always. */
109
- visible: string;
110
- enabled: RequirementSpec[];
111
- message: string;
112
- spaceBefore: number;
113
- spaceAfter: number;
114
- /** The slot of a fixed item, from 0; -1 in the flow. */
115
- slot: number;
116
- variants: Variant[] | null;
117
- }
118
-
119
- /** A filter of a list menu as a menu file gives it: INI's condition, or YAML's and JSON's `when`. */
120
- export interface FilterSpec {
121
- condition: string;
122
- when: string;
123
- message: string;
124
- }
125
-
126
- /**
127
- * What a name in a menu file names: checked once every plugin has had its
128
- * say. A "requirement" - YAML's and JSON's `visible`, `enabled`, `when` - is a
129
- * restriction or a condition; INI's columns are one or the other.
130
- */
131
- export type NameKind = "condition" | "action" | "restriction" | "requirement" | "placeholder";
132
-
133
- /** A name a menu file uses, and where: "configs/menu.yaml:12:9". */
134
- export interface NameUse {
135
- kind: NameKind;
136
- name: string;
137
- where: string;
138
- /** An INI item's condition or action column: "A|B", a line a variant. */
139
- variants: boolean;
140
- }
141
-
142
- /** A menu as a menu file describes it, whatever the file's format. */
143
- export interface MenuSpec {
144
- name: string;
145
- title: string;
146
- activeOn: string;
147
- hideBack: boolean;
148
- hideExit: boolean;
149
- locked: boolean;
150
- sharedTimer: boolean;
151
- time: number;
152
- onTimeout: string;
153
- /** An items menu's items; a list menu's row template, its VIEW. */
154
- items: ItemSpec[];
155
- fixed: ItemSpec[];
156
- filters: FilterSpec[];
157
- names: NameUse[];
158
- }
159
-
160
- /** What a menu file holds: its menus, and the words of [MAIN] - "" for those it leaves out. */
161
- export interface MenuFile {
162
- /** The file's path; "" when no file was found. */
163
- file: string;
164
- /** Whether the file has nothing at all in it: the fallback file is read instead. */
165
- empty: boolean;
166
- labels: Labels;
167
- menus: MenuSpec[];
168
- }
169
-
170
- /** Rows of a list menu that fail it are left out; `message` says so when none is left. */
171
- export interface ListFilter {
172
- /** Condition names, as menu.ini and Pawn plugins give them; "" otherwise. */
173
- condition: string;
174
- /** Names, as a YAML or JSON file's `when` gives them; "" otherwise. */
175
- when: string;
176
- test: RowTest | null;
177
- message: string;
178
- }
179
-
180
- /** What a menu has besides its public fields: its items, filters and its own placeholders. */
181
- export interface MenuState {
182
- items: MenuItem[];
183
- /** Items that keep their slot on every page. */
184
- fixed: MenuItem[];
185
- filters: ListFilter[];
186
- placeholders: PlaceholderEntry[];
187
- /** The menu opens only while it says yes; null for always. */
188
- activeWhen: OpenTest | null;
189
- }
190
-
191
- const states = new Map<string, MenuState>();
192
-
193
- /** The state of the menu of that name, made on first use. */
194
- export function stateOf(name: string) {
195
- if (!states.has(name)) {
196
- const made: MenuState = { items: [], fixed: [], filters: [], placeholders: [], activeWhen: null };
197
- states.set(name, made);
198
- }
199
-
200
- return states.get(name);
201
- }
202
-
203
- /**
204
- * The text a MenuText gives the player: a string given for it is already a
205
- * function returning it, as the compiler holds this type.
206
- */
207
- export function textOf(value: MenuText, player: Player, target: number) {
208
- // @ts-ignore: a function here - see MenuText
209
- return value(player, target);
210
- }
211
-
212
- /**
213
- * An item's `enabled` as the list of requirements it is held as: a function
214
- * given for it is already a list of one, `[{ when: test }]`.
215
- */
216
- export function checksOf(enabled: ((player: Player, target: number) => boolean) | Requirement[]) {
217
- // @ts-ignore: a list here - see MenuItemOptions.enabled
218
- const requirements: Requirement[] = enabled;
219
- return requirements.map(checkOf);
220
- }
221
-
222
- /** A requirement from code, as an item holds it. */
223
- function checkOf(requirement: Requirement) {
224
- const check: Check = { test: requirement.when, when: "", message: requirement.message ?? null };
225
- return check;
226
- }
227
-
228
- /** A list menu's filter by condition names - menu.ini's FILTER, a Pawn plugin's MP_FILTER. */
229
- export function addNamedFilter(menu: string, condition: string, message: string) {
230
- if (condition.length == 0) return;
231
- stateOf(menu).filters.push({ condition, when: "", test: null, message });
232
- }
233
-
234
- export interface ConditionEntry {
235
- name: string;
236
- test: ConditionTest;
237
- }
238
-
239
- export interface ActionEntry {
240
- name: string;
241
- run: ActionHandler;
242
- }
243
-
244
- export interface PlaceholderEntry {
245
- name: string;
246
- value: PlaceholderValue;
247
- }
248
-
249
- export interface RestrictionEntry {
250
- name: string;
251
- test: RestrictionTest;
252
- message: string;
253
- }
254
-
255
- export interface ActionCheck {
256
- menu: string;
257
- action: string;
258
- test: ActionTest;
259
- }
260
-
261
- export interface FilterEntry {
262
- name: string;
263
- filter: ConditionFilter;
264
- }
265
-
266
- export interface SourceEntry {
267
- /** The menu's name upper-cased: any case names the same menu's source. */
268
- menu: string;
269
- rows: ListSource;
270
- }
271
-
272
- /** What a shown slot does when its key is pressed. */
273
- export interface ShownSlot {
274
- action: string;
275
- target: number;
276
- }
277
-
278
- /** A place on the way back: the menu, by name, and its page. */
279
- export interface HistoryStep {
280
- menu: string;
281
- page: number;
282
- }
283
-
284
- /** A player's side of it: the menu he looks at, where he came from, his countdown. */
285
- export interface Viewer {
286
- /** The name of the menu he looks at; "" for none. */
287
- menu: string;
288
- page: number;
289
- target: number;
290
- history: HistoryStep[];
291
- slots: ShownSlot[];
292
- /** The rows the open menu pages through. */
293
- rows: number;
294
- /** What the menu shows, as it was last drawn. */
295
- text: string;
296
- locked: boolean;
297
- timer: number;
298
- /** The handle of his countdown's timer, 0 when none runs. */
299
- ticker: number;
300
- depth: number;
301
- }
302
-
303
- /** A list menu's rows as they are drawn: a source's, or the players. */
304
- export interface Listing {
305
- rows: ListRow[];
306
- fromSource: boolean;
307
- /** The rows that can be chosen - text lines are not counted. */
308
- count: number;
309
- }
310
-
311
- /** What the menu shows while it is drawn. */
312
- export interface Screen {
313
- text: string;
314
- keys: number[];
315
- slots: ShownSlot[];
316
- }
317
-
318
- /** The menu's own words, from [MAIN] of the file; a lang key or the text itself. */
319
- export interface Labels {
320
- exit: string;
321
- back: string;
322
- next: string;
323
- number: string;
324
- disabled: string;
325
- page: string;
326
- time: string;
327
- prefix: string;
328
- }
1
+ /**
2
+ * Menu Core's own bookkeeping: registrations, viewers, a menu's items and the
3
+ * menu being drawn. Not part of the API.
4
+ */
5
+ import { ActionHandler, ActionTest, ConditionFilter, ConditionTest, ListRow, ListSource, MenuContext, MenuText, PlaceholderValue, Requirement, RestrictionTest, RowTest } from "./types";
6
+
7
+ /** Whether an item is shown, or can be chosen; whether a menu opens. */
8
+ export type ItemTest = (context: MenuContext) => boolean;
9
+
10
+ /**
11
+ * One way an item can look, shown when its `when` holds - the first that
12
+ * does. A menu file's `variants`, or "A|B" in menu.ini, where `when` is the
13
+ * condition column's piece.
14
+ */
15
+ export interface Variant {
16
+ name: string;
17
+ /** Names; "" is always. */
18
+ when: string;
19
+ /** Action names, built-in ones among them. */
20
+ action: string;
21
+ }
22
+
23
+ /** A requirement of an item - `visible`, or one of `enabled`: a test from code, or a line of names from a menu file. */
24
+ export interface Check {
25
+ test: ItemTest | null;
26
+ /** Names, as a menu file's `when` gives them; "" with a test. */
27
+ when: string;
28
+ /** Beside the item while it says no; null for the item's `message`. */
29
+ message: MenuText | null;
30
+ }
31
+
32
+ export interface MenuItem {
33
+ /** Its text; "A|B" in it are variants when `ini`. */
34
+ label: MenuText;
35
+ /** Action names, "X|Y" a variant each when `ini`. */
36
+ action: string;
37
+ /** Text after the name: "%hp%". */
38
+ placeholder: string;
39
+ /** Left out while it says no: it takes no slot. */
40
+ visible: Check | null;
41
+ /** Greyed out while one says no: the first that does gives its message. */
42
+ enabled: Check[];
43
+ /** Beside the item while a requirement without a message of its own greys it out. */
44
+ message: MenuText | null;
45
+ /**
46
+ * An item of menu.ini or of a Pawn plugin: "A|B" in the text are variants,
47
+ * `condition` "C1|C2" picks one - greyed out, without a reason, when none
48
+ * holds - and `restriction` greys it out with `restrictionMessage`.
49
+ */
50
+ ini: boolean;
51
+ /** INI's condition names, "C1|C2" a variant each; "" is always. */
52
+ condition: string;
53
+ /** INI's restriction names, space-separated. */
54
+ restriction: string;
55
+ /** INI's message: "NAME:message|NAME2:message", or one message. */
56
+ restrictionMessage: string;
57
+ spaceBefore: number;
58
+ spaceAfter: number;
59
+ /** The slot a fixed item takes, from 0; -1 in the flow. */
60
+ slot: number;
61
+ /** Variants given one by one (a menu file's `variants`); null for the item's own text and action, or "A|B" when `ini`. */
62
+ variants: Variant[] | null;
63
+ /** The plugin that gave it, as `callingPlugin()` numbers it: it goes when that plugin stops. 0 for the module's own - a menu file's, a Pawn plugin's. */
64
+ from: number;
65
+ }
66
+
67
+ /** An item made in code, or read from a YAML or JSON file: its text and action, in `slot` - -1 for the flow. */
68
+ export function blankItem(label: MenuText, action: string, slot: number) {
69
+ const item: MenuItem = { label, action, placeholder: "", visible: null, enabled: [], message: null, ini: false, condition: "", restriction: "", restrictionMessage: "", spaceBefore: 0, spaceAfter: 0, slot, variants: null, from: 0 };
70
+ return item;
71
+ }
72
+
73
+ /** An item as menu.ini's columns and the mc_* natives give it. */
74
+ export function iniItem(label: string, placeholder: string, condition: string, action: string, restriction: string, message: string, slot: number) {
75
+ const item = blankItem(label, action, slot);
76
+ item.ini = true;
77
+ item.placeholder = placeholder;
78
+ item.condition = condition;
79
+ item.restriction = restriction;
80
+ item.restrictionMessage = message;
81
+ return item;
82
+ }
83
+
84
+ /** Puts an item among the menu's items: at `at`, from 0, or at the end when it is -1 or past them. */
85
+ export function insertItem(menu: string, item: MenuItem, at: number) {
86
+ const items = stateOf(menu).items;
87
+ if (at >= 0 && at < items.length) items.splice(at, 0, item);
88
+ else items.push(item);
89
+ }
90
+
91
+ /** A requirement of a menu file: its names, and the message beside the item while they do not hold - "" for the item's. */
92
+ export interface RequirementSpec {
93
+ when: string;
94
+ message: string;
95
+ }
96
+
97
+ /** An item as a menu file describes it, whatever the file's format. */
98
+ export interface ItemSpec {
99
+ name: string;
100
+ placeholder: string;
101
+ action: string;
102
+ /** Whether it is INI's: "A|B" variants, and the three columns below. */
103
+ ini: boolean;
104
+ condition: string;
105
+ restriction: string;
106
+ restrictionMessage: string;
107
+ /** YAML's and JSON's: names the item is shown under, "" for always. */
108
+ visible: string;
109
+ enabled: RequirementSpec[];
110
+ message: string;
111
+ spaceBefore: number;
112
+ spaceAfter: number;
113
+ /** The slot of a fixed item, from 0; -1 in the flow. */
114
+ slot: number;
115
+ variants: Variant[] | null;
116
+ }
117
+
118
+ /** A filter of a list menu as a menu file gives it: INI's condition, or YAML's and JSON's `when`. */
119
+ export interface FilterSpec {
120
+ condition: string;
121
+ when: string;
122
+ message: string;
123
+ }
124
+
125
+ /**
126
+ * What a name in a menu file names: checked once every plugin has had its
127
+ * say. A "requirement" - YAML's and JSON's `visible`, `enabled`, `when` - is a
128
+ * restriction or a condition; INI's columns are one or the other.
129
+ */
130
+ export type NameKind = "condition" | "action" | "restriction" | "requirement" | "placeholder";
131
+
132
+ /** A name a menu file uses, and where: "configs/menu.yaml:12:9". */
133
+ export interface NameUse {
134
+ kind: NameKind;
135
+ name: string;
136
+ where: string;
137
+ /** An INI item's condition or action column: "A|B", a line a variant. */
138
+ variants: boolean;
139
+ }
140
+
141
+ /** A menu as a menu file describes it, whatever the file's format. */
142
+ export interface MenuSpec {
143
+ name: string;
144
+ title: string;
145
+ activeOn: string;
146
+ hideBack: boolean;
147
+ hideExit: boolean;
148
+ locked: boolean;
149
+ sharedTimer: boolean;
150
+ time: number;
151
+ onTimeout: string;
152
+ /** An items menu's items; a list menu's row template, its VIEW. */
153
+ items: ItemSpec[];
154
+ fixed: ItemSpec[];
155
+ filters: FilterSpec[];
156
+ names: NameUse[];
157
+ }
158
+
159
+ /** What a menu file holds: its menus, and the words of [MAIN] - "" for those it leaves out. */
160
+ export interface MenuFile {
161
+ /** The file's path; "" when no file was found. */
162
+ file: string;
163
+ /** Whether the file has nothing at all in it: the fallback file is read instead. */
164
+ empty: boolean;
165
+ labels: Labels;
166
+ menus: MenuSpec[];
167
+ }
168
+
169
+ /** Rows of a list menu that fail it are left out; `message` says so when none is left. */
170
+ export interface ListFilter {
171
+ /** Condition names, as menu.ini and Pawn plugins give them; "" otherwise. */
172
+ condition: string;
173
+ /** Names, as a YAML or JSON file's `when` gives them; "" otherwise. */
174
+ when: string;
175
+ test: RowTest | null;
176
+ message: string;
177
+ /** The plugin that gave it, as `callingPlugin()` numbers it: it goes when that plugin stops. 0 for the module's own - a menu file's, a Pawn plugin's. */
178
+ from: number;
179
+ }
180
+
181
+ /** What a menu has besides its public fields: its items, filters and its own placeholders. */
182
+ export interface MenuState {
183
+ items: MenuItem[];
184
+ /** Items that keep their slot on every page. */
185
+ fixed: MenuItem[];
186
+ filters: ListFilter[];
187
+ placeholders: PlaceholderEntry[];
188
+ /** The menu opens only while it says yes; null for always. */
189
+ activeWhen: ItemTest | null;
190
+ /** The plugin that made the menu in code, as `callingPlugin()` numbers it: the menu goes when that plugin stops. 0 for the module's own. */
191
+ from: number;
192
+ }
193
+
194
+ const states = new Map<string, MenuState>();
195
+
196
+ /** The state of the menu of that name, made on first use. */
197
+ export function stateOf(name: string) {
198
+ if (!states.has(name)) {
199
+ const made: MenuState = { items: [], fixed: [], filters: [], placeholders: [], activeWhen: null, from: 0 };
200
+ states.set(name, made);
201
+ }
202
+
203
+ return states.get(name);
204
+ }
205
+
206
+ /** Forgets the state of the menu of that name: a menu that went. */
207
+ export function forgetState(name: string) {
208
+ states.delete(name);
209
+ }
210
+
211
+ /**
212
+ * The text a MenuText gives for the context: a string given for it is already
213
+ * a function returning it, as the compiler holds this type.
214
+ */
215
+ export function textOf(value: MenuText, context: MenuContext) {
216
+ // @ts-ignore: a function here - see MenuText
217
+ return value(context);
218
+ }
219
+
220
+ /**
221
+ * An item's `enabled` as the list of requirements it is held as: a function
222
+ * given for it is already a list of one, `[{ when: test }]`.
223
+ */
224
+ export function checksOf(enabled: ((context: MenuContext) => boolean) | Requirement[]) {
225
+ // @ts-ignore: a list here - see MenuItemOptions.enabled
226
+ const requirements: Requirement[] = enabled;
227
+ return requirements.map(checkOf);
228
+ }
229
+
230
+ /** A requirement from code, as an item holds it. */
231
+ function checkOf(requirement: Requirement) {
232
+ const check: Check = { test: requirement.when, when: "", message: requirement.message ?? null };
233
+ return check;
234
+ }
235
+
236
+ /** A list menu's filter by condition names - menu.ini's FILTER, a Pawn plugin's MP_FILTER. */
237
+ export function addNamedFilter(menu: string, condition: string, message: string) {
238
+ if (condition.length == 0) return;
239
+ stateOf(menu).filters.push({ condition, when: "", test: null, message, from: 0 });
240
+ }
241
+
242
+ export interface ConditionEntry {
243
+ name: string;
244
+ test: ConditionTest;
245
+ /** The plugin that gave it, as `callingPlugin()` numbers it: it goes when that plugin stops. 0 for the module's own - a menu file's, a Pawn plugin's. */
246
+ from: number;
247
+ }
248
+
249
+ export interface ActionEntry {
250
+ name: string;
251
+ run: ActionHandler;
252
+ /** The plugin that gave it, as `callingPlugin()` numbers it: it goes when that plugin stops. 0 for the module's own - a menu file's, a Pawn plugin's. */
253
+ from: number;
254
+ }
255
+
256
+ export interface PlaceholderEntry {
257
+ name: string;
258
+ value: PlaceholderValue;
259
+ /** The plugin that gave it, as `callingPlugin()` numbers it: it goes when that plugin stops. 0 for the module's own - a menu file's, a Pawn plugin's. */
260
+ from: number;
261
+ }
262
+
263
+ export interface RestrictionEntry {
264
+ name: string;
265
+ test: RestrictionTest;
266
+ message: string;
267
+ /** The plugin that gave it, as `callingPlugin()` numbers it: it goes when that plugin stops. 0 for the module's own - a menu file's, a Pawn plugin's. */
268
+ from: number;
269
+ }
270
+
271
+ export interface ActionCheck {
272
+ menu: string;
273
+ action: string;
274
+ test: ActionTest;
275
+ /** The plugin that gave it, as `callingPlugin()` numbers it: it goes when that plugin stops. 0 for the module's own - a menu file's, a Pawn plugin's. */
276
+ from: number;
277
+ }
278
+
279
+ export interface FilterEntry {
280
+ name: string;
281
+ filter: ConditionFilter;
282
+ /** The plugin that gave it, as `callingPlugin()` numbers it: it goes when that plugin stops. 0 for the module's own - a menu file's, a Pawn plugin's. */
283
+ from: number;
284
+ }
285
+
286
+ export interface SourceEntry {
287
+ /** The menu's name upper-cased: any case names the same menu's source. */
288
+ menu: string;
289
+ rows: ListSource;
290
+ /** The plugin that gave it, as `callingPlugin()` numbers it: it goes when that plugin stops. 0 for the module's own - a menu file's, a Pawn plugin's. */
291
+ from: number;
292
+ }
293
+
294
+ /** What a shown slot does when its key is pressed. */
295
+ export interface ShownSlot {
296
+ action: string;
297
+ target: number;
298
+ }
299
+
300
+ /** A place on the way back: the menu, by name, and its page. */
301
+ export interface HistoryStep {
302
+ menu: string;
303
+ page: number;
304
+ }
305
+
306
+ /** A player's side of it: the menu he looks at, where he came from, his countdown. */
307
+ export interface Viewer {
308
+ /** The name of the menu he looks at; "" for none. */
309
+ menu: string;
310
+ page: number;
311
+ target: number;
312
+ history: HistoryStep[];
313
+ slots: ShownSlot[];
314
+ /** The rows the open menu pages through. */
315
+ rows: number;
316
+ /** What the menu shows, as it was last drawn. */
317
+ text: string;
318
+ locked: boolean;
319
+ timer: number;
320
+ /** The handle of his countdown's timer, 0 when none runs. */
321
+ ticker: number;
322
+ depth: number;
323
+ }
324
+
325
+ /** A list menu's rows as they are drawn: a source's, or the players. */
326
+ export interface Listing {
327
+ rows: ListRow[];
328
+ fromSource: boolean;
329
+ /** The rows that can be chosen - text lines are not counted. */
330
+ count: number;
331
+ }
332
+
333
+ /** What the menu shows while it is drawn. */
334
+ export interface Screen {
335
+ text: string;
336
+ keys: number[];
337
+ slots: ShownSlot[];
338
+ }
339
+
340
+ /** The menu's own words, from [MAIN] of the file; a lang key or the text itself. */
341
+ export interface Labels {
342
+ exit: string;
343
+ back: string;
344
+ next: string;
345
+ number: string;
346
+ disabled: string;
347
+ page: string;
348
+ time: string;
349
+ prefix: string;
350
+ }