@block_factory/lib 0.0.1 → 0.0.2
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/index.d.ts +5 -1
- package/index.js +127 -0
- package/index.ts +6 -1
- package/package.json +1 -1
- package/util/Form.d.ts +10 -75
- package/util/Form.ts +8 -239
- package/util/FormAction.d.ts +41 -0
- package/util/FormAction.ts +207 -0
- package/util/_Form.ts +246 -0
package/index.d.ts
CHANGED
|
@@ -3,8 +3,10 @@ import { Signal } from "./util/Signal";
|
|
|
3
3
|
import { Vec2, Vec3 } from "./util/Vector";
|
|
4
4
|
import { RawText } from "./util/RawText";
|
|
5
5
|
import { Command } from "./util/Command";
|
|
6
|
+
import { Form } from "./util/Form";
|
|
7
|
+
import { ActionFormCtor, IButtonOptions, IActionFormResponse, IActionFormData } from "./util/FormAction";
|
|
6
8
|
|
|
7
|
-
export { MathUtils, Signal, Vec2, Vec3, RawText, Command }
|
|
9
|
+
export { MathUtils, Signal, Vec2, Vec3, RawText, Command, Form, ActionFormCtor, IButtonOptions, IActionFormResponse, IActionFormData }
|
|
8
10
|
|
|
9
11
|
export declare const BlockFactory: {
|
|
10
12
|
MathUtils: typeof MathUtils;
|
|
@@ -13,4 +15,6 @@ export declare const BlockFactory: {
|
|
|
13
15
|
Vec3: typeof Vec3;
|
|
14
16
|
RawText: typeof RawText;
|
|
15
17
|
Command: typeof Command;
|
|
18
|
+
Form: typeof Form;
|
|
19
|
+
IActionFormData: typeof IActionFormData;
|
|
16
20
|
};
|
package/index.js
CHANGED
|
@@ -480,8 +480,11 @@ var Command;
|
|
|
480
480
|
((Command2) => {
|
|
481
481
|
class ICustomCommand {
|
|
482
482
|
constructor() {
|
|
483
|
+
/** Whether cheats must be enabled */
|
|
483
484
|
__publicField(this, "cheatsRequired");
|
|
485
|
+
/** Required command parameters */
|
|
484
486
|
__publicField(this, "mandatoryParameters");
|
|
487
|
+
/** Optional command parameters */
|
|
485
488
|
__publicField(this, "optionalParameters");
|
|
486
489
|
}
|
|
487
490
|
}
|
|
@@ -505,6 +508,126 @@ system.beforeEvents.startup.subscribe(
|
|
|
505
508
|
}
|
|
506
509
|
);
|
|
507
510
|
|
|
511
|
+
// util/Form.ts
|
|
512
|
+
var _Form = class _Form {
|
|
513
|
+
static isOccupied(player) {
|
|
514
|
+
return _Form.occupiedPlayers.has(player.id);
|
|
515
|
+
}
|
|
516
|
+
setOccupied(player, occupied) {
|
|
517
|
+
if (occupied) _Form.occupiedPlayers.add(player.id);
|
|
518
|
+
else _Form.occupiedPlayers.delete(player.id);
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
__publicField(_Form, "occupiedPlayers", /* @__PURE__ */ new Set());
|
|
522
|
+
__publicField(_Form, "returnText", "Back");
|
|
523
|
+
var Form = _Form;
|
|
524
|
+
|
|
525
|
+
// util/FormAction.ts
|
|
526
|
+
import { ActionFormData } from "@minecraft/server-ui";
|
|
527
|
+
var RETURN_ID = "d7213196-4cb6-4199-a40b-22fbf2d944ef";
|
|
528
|
+
var IActionFormData = class extends Form {
|
|
529
|
+
constructor() {
|
|
530
|
+
super(...arguments);
|
|
531
|
+
__publicField(this, "form", new ActionFormData());
|
|
532
|
+
__publicField(this, "_buttons", /* @__PURE__ */ new Map());
|
|
533
|
+
__publicField(this, "_nextButtonIndex", 0);
|
|
534
|
+
__publicField(this, "_id", "untitled");
|
|
535
|
+
}
|
|
536
|
+
title(titleText) {
|
|
537
|
+
this.form.title(titleText);
|
|
538
|
+
this._id = typeof titleText === "string" ? titleText : JSON.stringify(titleText);
|
|
539
|
+
return this;
|
|
540
|
+
}
|
|
541
|
+
body(bodyText) {
|
|
542
|
+
this.form.body(bodyText);
|
|
543
|
+
return this;
|
|
544
|
+
}
|
|
545
|
+
divider() {
|
|
546
|
+
this.form.divider();
|
|
547
|
+
return this;
|
|
548
|
+
}
|
|
549
|
+
header(text) {
|
|
550
|
+
this.form.header(text);
|
|
551
|
+
return this;
|
|
552
|
+
}
|
|
553
|
+
label(text) {
|
|
554
|
+
this.form.label(text);
|
|
555
|
+
return this;
|
|
556
|
+
}
|
|
557
|
+
button(text, options = {}) {
|
|
558
|
+
if (options.iconPath) this.form.button(text, options.iconPath);
|
|
559
|
+
else this.form.button(text);
|
|
560
|
+
const id = options.id ?? this._nextButtonIndex;
|
|
561
|
+
const allowReturn = options.allowReturn ?? true;
|
|
562
|
+
this._buttons.set(this._nextButtonIndex, {
|
|
563
|
+
id,
|
|
564
|
+
subForm: options.subForm,
|
|
565
|
+
allowReturn
|
|
566
|
+
});
|
|
567
|
+
this._nextButtonIndex++;
|
|
568
|
+
return this;
|
|
569
|
+
}
|
|
570
|
+
async show(player) {
|
|
571
|
+
if (Form.isOccupied(player)) {
|
|
572
|
+
throw new Error(`Player ${player.id} is already occupied by form: ${this._id}`);
|
|
573
|
+
}
|
|
574
|
+
this.setOccupied(player, true);
|
|
575
|
+
try {
|
|
576
|
+
return await this._showInternal(player, []);
|
|
577
|
+
} finally {
|
|
578
|
+
this.setOccupied(player, false);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
async _showChained(player, returnStack) {
|
|
582
|
+
return await this._showInternal(player, returnStack);
|
|
583
|
+
}
|
|
584
|
+
_wrapResponse(response, id) {
|
|
585
|
+
return {
|
|
586
|
+
canceled: response.canceled,
|
|
587
|
+
cancelationReason: response.cancelationReason,
|
|
588
|
+
selection: response.selection,
|
|
589
|
+
id
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
async _showInternal(player, returnStack) {
|
|
593
|
+
this.form = new ActionFormData();
|
|
594
|
+
this._buttons.clear();
|
|
595
|
+
this._nextButtonIndex = 0;
|
|
596
|
+
this.build(player);
|
|
597
|
+
if (returnStack.length > 0) {
|
|
598
|
+
this.form.button(Form.returnText);
|
|
599
|
+
this._buttons.set(this._nextButtonIndex, {
|
|
600
|
+
id: RETURN_ID,
|
|
601
|
+
subForm: returnStack[returnStack.length - 1],
|
|
602
|
+
allowReturn: true
|
|
603
|
+
});
|
|
604
|
+
this._nextButtonIndex++;
|
|
605
|
+
}
|
|
606
|
+
const response = await this.form.show(player);
|
|
607
|
+
if (response.canceled) {
|
|
608
|
+
const wrapped2 = this._wrapResponse(response, void 0);
|
|
609
|
+
this.onCancel?.(player, wrapped2);
|
|
610
|
+
return wrapped2;
|
|
611
|
+
}
|
|
612
|
+
const meta = response.selection !== void 0 ? this._buttons.get(response.selection) : void 0;
|
|
613
|
+
if (meta?.id === RETURN_ID && meta.subForm) {
|
|
614
|
+
const prevCtor = returnStack[returnStack.length - 1];
|
|
615
|
+
const newStack = returnStack.slice(0, -1);
|
|
616
|
+
const prev = new prevCtor();
|
|
617
|
+
return await prev._showChained(player, newStack);
|
|
618
|
+
}
|
|
619
|
+
const wrapped = this._wrapResponse(response, meta?.id);
|
|
620
|
+
this.onSubmit(player, wrapped);
|
|
621
|
+
if (meta?.subForm) {
|
|
622
|
+
const next = new meta.subForm();
|
|
623
|
+
const allowReturn = meta.allowReturn ?? true;
|
|
624
|
+
const nextStack = allowReturn ? [...returnStack, this.constructor] : [...returnStack];
|
|
625
|
+
return await next._showChained(player, nextStack);
|
|
626
|
+
}
|
|
627
|
+
return wrapped;
|
|
628
|
+
}
|
|
629
|
+
};
|
|
630
|
+
|
|
508
631
|
// index.ts
|
|
509
632
|
var BlockFactory;
|
|
510
633
|
((BlockFactory2) => {
|
|
@@ -514,10 +637,14 @@ var BlockFactory;
|
|
|
514
637
|
Vec3;
|
|
515
638
|
RawText;
|
|
516
639
|
Command;
|
|
640
|
+
Form;
|
|
641
|
+
IActionFormData;
|
|
517
642
|
})(BlockFactory || (BlockFactory = {}));
|
|
518
643
|
export {
|
|
519
644
|
BlockFactory,
|
|
520
645
|
Command,
|
|
646
|
+
Form,
|
|
647
|
+
IActionFormData,
|
|
521
648
|
MathUtils,
|
|
522
649
|
RawText,
|
|
523
650
|
Signal,
|
package/index.ts
CHANGED
|
@@ -3,8 +3,11 @@ import { Signal } from "./util/Signal";
|
|
|
3
3
|
import { Vec2, Vec3 } from "./util/Vector";
|
|
4
4
|
import { RawText } from "./util/RawText";
|
|
5
5
|
import { Command } from "./util/Command";
|
|
6
|
+
import { Form } from "./util/Form";
|
|
7
|
+
import { ActionFormCtor, IButtonOptions, IActionFormResponse, IActionFormData } from "./util/FormAction";
|
|
8
|
+
|
|
9
|
+
export { MathUtils, Signal, Vec2, Vec3, RawText, Command, Form, ActionFormCtor, IButtonOptions, IActionFormResponse, IActionFormData };
|
|
6
10
|
|
|
7
|
-
export { MathUtils, Signal, Vec2, Vec3, RawText, Command }
|
|
8
11
|
|
|
9
12
|
export namespace BlockFactory {
|
|
10
13
|
MathUtils;
|
|
@@ -13,4 +16,6 @@ export namespace BlockFactory {
|
|
|
13
16
|
Vec3;
|
|
14
17
|
RawText;
|
|
15
18
|
Command;
|
|
19
|
+
Form;
|
|
20
|
+
IActionFormData;
|
|
16
21
|
}
|
package/package.json
CHANGED
package/util/Form.d.ts
CHANGED
|
@@ -1,75 +1,10 @@
|
|
|
1
|
-
import { Player, RawMessage } from "@minecraft/server";
|
|
2
|
-
|
|
3
|
-
declare class Form {
|
|
4
|
-
readonly
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
export interface FormActionData {
|
|
12
|
-
response: ActionFormResponse;
|
|
13
|
-
indexId?: string | number;
|
|
14
|
-
}
|
|
15
|
-
export declare class ActionForm extends Form {
|
|
16
|
-
private readonly actionForm;
|
|
17
|
-
private buttonMap;
|
|
18
|
-
private buttons;
|
|
19
|
-
private titleText;
|
|
20
|
-
private bodyText;
|
|
21
|
-
title(title: string | RawMessage): void;
|
|
22
|
-
body(body: string | RawMessage): void;
|
|
23
|
-
button(indexId: string, text: string | RawMessage, iconPath?: string): void;
|
|
24
|
-
showForm(player: Player): Promise<FormActionData>;
|
|
25
|
-
private generateButtons;
|
|
26
|
-
}
|
|
27
|
-
export interface TextField {
|
|
28
|
-
indexId: string;
|
|
29
|
-
label: string | RawMessage;
|
|
30
|
-
placeholder: string | RawMessage;
|
|
31
|
-
defaultValue?: string;
|
|
32
|
-
}
|
|
33
|
-
export interface Dropdown {
|
|
34
|
-
indexId: string;
|
|
35
|
-
label: string | RawMessage;
|
|
36
|
-
options: string[];
|
|
37
|
-
defaultValueIndex?: number;
|
|
38
|
-
}
|
|
39
|
-
export interface Slider {
|
|
40
|
-
indexId: string;
|
|
41
|
-
label: string | RawMessage;
|
|
42
|
-
min: number;
|
|
43
|
-
max: number;
|
|
44
|
-
step: number;
|
|
45
|
-
defaultValue?: number;
|
|
46
|
-
}
|
|
47
|
-
export interface Toggle {
|
|
48
|
-
indexId: string;
|
|
49
|
-
label: string | RawMessage;
|
|
50
|
-
defaultValue?: boolean;
|
|
51
|
-
}
|
|
52
|
-
export type FormValue = string | boolean | number | undefined;
|
|
53
|
-
export interface FormModalData {
|
|
54
|
-
response: ModalFormResponse;
|
|
55
|
-
indexMap?: Map<string, FormValue>;
|
|
56
|
-
}
|
|
57
|
-
export declare class ModalForm extends Form {
|
|
58
|
-
private readonly modalForm;
|
|
59
|
-
private widgitMap;
|
|
60
|
-
private indexMap;
|
|
61
|
-
private widgets;
|
|
62
|
-
title(title: string | RawMessage): void;
|
|
63
|
-
label(label: string | RawMessage): void;
|
|
64
|
-
header(header: string | RawMessage): void;
|
|
65
|
-
divider(): void;
|
|
66
|
-
textField(indexId: string, label: string | RawMessage, placeholder: string | RawMessage, defaultValue?: string): void;
|
|
67
|
-
dropdown(indexId: string, label: string | RawMessage, options: string[], defaultValueIndex?: number): void;
|
|
68
|
-
slider(indexId: string, label: string | RawMessage, min: number, max: number, step: number, defaultValue?: number): void;
|
|
69
|
-
toggle(indexId: string, label: string | RawMessage, defaultValue?: boolean): void;
|
|
70
|
-
showForm(player: Player): Promise<FormModalData>;
|
|
71
|
-
private processWidgets;
|
|
72
|
-
private processValues;
|
|
73
|
-
}
|
|
74
|
-
export {};
|
|
75
|
-
//# sourceMappingURL=Form.d.ts.map
|
|
1
|
+
import { Player, RawMessage } from "@minecraft/server";
|
|
2
|
+
|
|
3
|
+
export declare abstract class Form {
|
|
4
|
+
private static readonly occupiedPlayers: Set<string>;
|
|
5
|
+
static returnText: RawMessage | string;
|
|
6
|
+
|
|
7
|
+
static isOccupied(player: Player): boolean;
|
|
8
|
+
|
|
9
|
+
protected setOccupied(player: Player, occupied: boolean): void;
|
|
10
|
+
}
|
package/util/Form.ts
CHANGED
|
@@ -1,246 +1,15 @@
|
|
|
1
|
-
/*
|
|
2
|
-
**************************************************
|
|
3
|
-
Copyright (c) Block Factory - All rights reserved.
|
|
4
|
-
**************************************************
|
|
5
|
-
Author: Donthedev <https://github.com/voxeldon>
|
|
6
|
-
**************************************************
|
|
7
|
-
*/
|
|
8
1
|
import { Player, RawMessage } from "@minecraft/server";
|
|
9
|
-
import { ActionFormData, ActionFormResponse, ModalFormData, ModalFormDataDropdownOptions, ModalFormDataSliderOptions, ModalFormDataTextFieldOptions, ModalFormDataToggleOptions, ModalFormResponse } from "@minecraft/server-ui";
|
|
10
2
|
|
|
11
|
-
|
|
3
|
+
export abstract class Form {
|
|
4
|
+
private static readonly occupiedPlayers: Set<string> = new Set();
|
|
5
|
+
public static returnText: RawMessage | string = "Back";
|
|
12
6
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
return occupiedPlayers.has(player.id);
|
|
16
|
-
})
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface Button {
|
|
20
|
-
indexId: string | number;
|
|
21
|
-
text: string | RawMessage;
|
|
22
|
-
iconPath?: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface FormActionData {
|
|
26
|
-
response: ActionFormResponse;
|
|
27
|
-
indexId?: string | number;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export class ActionForm extends Form {
|
|
31
|
-
private readonly actionForm: ActionFormData = new ActionFormData();
|
|
32
|
-
private buttonMap: Map<number, string | number> = new Map<number, string | number>();
|
|
33
|
-
private buttons: Button[] = [];
|
|
34
|
-
private titleText: string | RawMessage | undefined;
|
|
35
|
-
private bodyText: string | RawMessage | undefined;
|
|
36
|
-
|
|
37
|
-
public title(title: string | RawMessage): void {
|
|
38
|
-
this.titleText = title;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
public body(body: string | RawMessage): void {
|
|
42
|
-
this.bodyText = body;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
public button(indexId: string, text: string | RawMessage, iconPath?: string): void {
|
|
46
|
-
this.buttons.push({ indexId, text, iconPath });
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
public async showForm(player: Player): Promise<FormActionData> {
|
|
50
|
-
if (this.titleText === undefined || this.bodyText === undefined) {
|
|
51
|
-
throw Error('Title and body must be set before showing the form');
|
|
52
|
-
}
|
|
53
|
-
this.actionForm.title(this.titleText);
|
|
54
|
-
this.actionForm.body(this.bodyText);
|
|
55
|
-
this.generateButtons();
|
|
56
|
-
|
|
57
|
-
occupiedPlayers.add(player.id);
|
|
58
|
-
|
|
59
|
-
const response: ActionFormResponse = await this.actionForm.show(player).finally(() => {
|
|
60
|
-
occupiedPlayers.delete(player.id);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
const return_data: FormActionData = {
|
|
64
|
-
response: response,
|
|
65
|
-
indexId: undefined
|
|
66
|
-
};
|
|
67
|
-
if (response.selection !== undefined && response.selection !== null) {
|
|
68
|
-
const selection: string | number | undefined = this.buttonMap.get(response.selection);
|
|
69
|
-
return_data.indexId = selection;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return return_data;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
private generateButtons() {
|
|
76
|
-
let buttonIndex: number = 0;
|
|
77
|
-
this.buttons.forEach(button => {
|
|
78
|
-
if (button.iconPath) {
|
|
79
|
-
this.actionForm.button(button.text, button.iconPath);
|
|
80
|
-
} else {
|
|
81
|
-
this.actionForm.button(button.text);
|
|
82
|
-
}
|
|
83
|
-
this.buttonMap.set(buttonIndex, button.indexId);
|
|
84
|
-
buttonIndex++;
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
enum WidgetType {
|
|
90
|
-
TextField = 'textField',
|
|
91
|
-
Dropdown = 'dropdown',
|
|
92
|
-
Slider = 'slider',
|
|
93
|
-
Toggle = 'toggle'
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
interface Widget {
|
|
97
|
-
typeId: string,
|
|
98
|
-
widget: any
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
export interface TextField {
|
|
102
|
-
indexId: string,
|
|
103
|
-
label: string | RawMessage,
|
|
104
|
-
placeholder: string | RawMessage,
|
|
105
|
-
defaultValue?: string
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export interface Dropdown {
|
|
109
|
-
indexId: string,
|
|
110
|
-
label: string | RawMessage,
|
|
111
|
-
options: string[],
|
|
112
|
-
defaultValueIndex?: number
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export interface Slider {
|
|
116
|
-
indexId: string,
|
|
117
|
-
label: string | RawMessage,
|
|
118
|
-
min: number,
|
|
119
|
-
max: number,
|
|
120
|
-
step: number,
|
|
121
|
-
defaultValue?: number
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
export interface Toggle {
|
|
125
|
-
indexId: string,
|
|
126
|
-
label: string | RawMessage,
|
|
127
|
-
defaultValue?: boolean
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export type FormValue = string | boolean | number | undefined;
|
|
131
|
-
|
|
132
|
-
export interface FormModalData {
|
|
133
|
-
response: ModalFormResponse;
|
|
134
|
-
indexMap?: Map<string, FormValue>;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export class ModalForm extends Form {
|
|
138
|
-
private readonly modalForm: ModalFormData = new ModalFormData();
|
|
139
|
-
private widgitMap: Map<number, string> = new Map<number, string>();
|
|
140
|
-
private indexMap: Map<string, FormValue> = new Map<string, FormValue>();
|
|
141
|
-
private widgets: Widget[] = [];
|
|
142
|
-
|
|
143
|
-
public title(title: string | RawMessage): void {
|
|
144
|
-
this.modalForm.title(title);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
public label(label: string | RawMessage): void {
|
|
148
|
-
this.modalForm.label(label);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
public header(header: string | RawMessage): void {
|
|
152
|
-
this.modalForm.header(header);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
public divider(): void {
|
|
156
|
-
this.modalForm.divider();
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
public textField(indexId: string, label: string | RawMessage, placeholder: string | RawMessage, defaultValue?: string): void {
|
|
160
|
-
this.widgets.push({ typeId: WidgetType.TextField, widget: { indexId, label, placeholder, defaultValue } });
|
|
161
|
-
}
|
|
162
|
-
public dropdown(indexId: string, label: string | RawMessage, options: string[], defaultValueIndex?: number): void {
|
|
163
|
-
this.widgets.push({ typeId: WidgetType.Dropdown, widget: { indexId, label, options, defaultValueIndex } });
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
public slider(indexId: string, label: string | RawMessage, min: number, max: number, step: number, defaultValue?: number): void {
|
|
167
|
-
this.widgets.push({ typeId: WidgetType.Slider, widget: { indexId, label, min, max, step, defaultValue } });
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
public toggle(indexId: string, label: string | RawMessage, defaultValue?: boolean): void {
|
|
171
|
-
this.widgets.push({ typeId: WidgetType.Toggle, widget: { indexId, label, defaultValue } });
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
public async showForm(player: Player): Promise<FormModalData> {
|
|
175
|
-
this.processWidgets();
|
|
176
|
-
occupiedPlayers.add(player.id);
|
|
177
|
-
|
|
178
|
-
const response: ModalFormResponse = await this.modalForm.show(player).finally(() => {
|
|
179
|
-
occupiedPlayers.delete(player.id);
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
const return_data: FormModalData = {
|
|
183
|
-
response: response,
|
|
184
|
-
indexMap: undefined
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
if (response.formValues !== null && response.formValues !== undefined) {
|
|
188
|
-
this.processValues(response.formValues);
|
|
189
|
-
return_data.indexMap = this.indexMap;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
return return_data;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
private processWidgets(): void {
|
|
196
|
-
let widgitIndex: number = 0;
|
|
197
|
-
|
|
198
|
-
for (const widget of this.widgets) {
|
|
199
|
-
if (widget.typeId === WidgetType.TextField) {
|
|
200
|
-
const textField: TextField = widget.widget;
|
|
201
|
-
const options: ModalFormDataTextFieldOptions = {
|
|
202
|
-
defaultValue: textField?.defaultValue
|
|
203
|
-
};
|
|
204
|
-
this.modalForm.textField(textField.label, textField.placeholder, options);
|
|
205
|
-
this.widgitMap.set(widgitIndex, textField.indexId);
|
|
206
|
-
}
|
|
207
|
-
else if (widget.typeId === WidgetType.Dropdown) {
|
|
208
|
-
const dropdown: Dropdown = widget.widget;
|
|
209
|
-
const options: ModalFormDataDropdownOptions = {
|
|
210
|
-
defaultValueIndex: dropdown?.defaultValueIndex
|
|
211
|
-
};
|
|
212
|
-
this.modalForm.dropdown(dropdown.label, dropdown.options, options);
|
|
213
|
-
this.widgitMap.set(widgitIndex, dropdown.indexId);
|
|
214
|
-
|
|
215
|
-
}
|
|
216
|
-
else if (widget.typeId === WidgetType.Slider) {
|
|
217
|
-
const slider: Slider = widget.widget;
|
|
218
|
-
const options: ModalFormDataSliderOptions = {
|
|
219
|
-
defaultValue: slider?.defaultValue,
|
|
220
|
-
valueStep: slider.step
|
|
221
|
-
};
|
|
222
|
-
this.modalForm.slider(slider.label, slider.min, slider.max, options);
|
|
223
|
-
this.widgitMap.set(widgitIndex, slider.indexId);
|
|
224
|
-
}
|
|
225
|
-
else if (widget.typeId === WidgetType.Toggle) {
|
|
226
|
-
const toggle: Toggle = widget.widget;
|
|
227
|
-
const options: ModalFormDataToggleOptions = {
|
|
228
|
-
defaultValue: toggle?.defaultValue
|
|
229
|
-
}
|
|
230
|
-
this.modalForm.toggle(toggle.label, options);
|
|
231
|
-
this.widgitMap.set(widgitIndex, toggle.indexId);
|
|
232
|
-
}
|
|
233
|
-
widgitIndex += 1;
|
|
234
|
-
}
|
|
7
|
+
public static isOccupied(player: Player): boolean {
|
|
8
|
+
return Form.occupiedPlayers.has(player.id);
|
|
235
9
|
}
|
|
236
10
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
const value: FormValue = i?.valueOf();
|
|
241
|
-
const indexId: string | undefined = this.widgitMap.get(widgitIndex);
|
|
242
|
-
if (indexId) this.indexMap.set(indexId, value);
|
|
243
|
-
widgitIndex++;
|
|
244
|
-
}
|
|
11
|
+
protected setOccupied(player: Player, occupied: boolean): void {
|
|
12
|
+
if (occupied) Form.occupiedPlayers.add(player.id);
|
|
13
|
+
else Form.occupiedPlayers.delete(player.id);
|
|
245
14
|
}
|
|
246
15
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Form } from "@block_factory/lib/util/Form";
|
|
2
|
+
import { Player, RawMessage } from "@minecraft/server";
|
|
3
|
+
import { ActionFormData, FormCancelationReason } from "@minecraft/server-ui";
|
|
4
|
+
|
|
5
|
+
export declare type ActionFormCtor<T extends IActionFormData = IActionFormData> = new () => T;
|
|
6
|
+
|
|
7
|
+
export declare interface IButtonOptions {
|
|
8
|
+
id?: string | number;
|
|
9
|
+
iconPath?: string;
|
|
10
|
+
subForm?: ActionFormCtor;
|
|
11
|
+
allowReturn?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export declare interface IActionFormResponse {
|
|
15
|
+
readonly cancelationReason?: FormCancelationReason;
|
|
16
|
+
readonly canceled: boolean;
|
|
17
|
+
readonly selection?: number;
|
|
18
|
+
readonly id?: string | number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export declare abstract class IActionFormData extends Form {
|
|
22
|
+
protected form: ActionFormData;
|
|
23
|
+
|
|
24
|
+
protected abstract build(player: Player): void;
|
|
25
|
+
|
|
26
|
+
protected abstract onSubmit(player: Player, response: IActionFormResponse): void;
|
|
27
|
+
|
|
28
|
+
protected onCancel?(player: Player, response: IActionFormResponse): void;
|
|
29
|
+
|
|
30
|
+
title(titleText: RawMessage | string): this;
|
|
31
|
+
body(bodyText: RawMessage | string): this;
|
|
32
|
+
divider(): this;
|
|
33
|
+
header(text: RawMessage | string): this;
|
|
34
|
+
label(text: RawMessage | string): this;
|
|
35
|
+
|
|
36
|
+
button(text: RawMessage | string, options?: IButtonOptions): this;
|
|
37
|
+
|
|
38
|
+
show(player: Player): Promise<IActionFormResponse>;
|
|
39
|
+
|
|
40
|
+
protected _showChained(player: Player, returnStack: ActionFormCtor[]): Promise<IActionFormResponse>;
|
|
41
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { Form } from "@block_factory/lib/util/Form";
|
|
2
|
+
import { Player, RawMessage } from "@minecraft/server";
|
|
3
|
+
import { ActionFormData, ActionFormResponse, FormCancelationReason } from "@minecraft/server-ui";
|
|
4
|
+
|
|
5
|
+
const RETURN_ID = "d7213196-4cb6-4199-a40b-22fbf2d944ef";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Constructor type for ActionForm classes.
|
|
9
|
+
* Used for sub-form navigation and chaining.
|
|
10
|
+
*/
|
|
11
|
+
export type ActionFormCtor<T extends IActionFormData = IActionFormData> = new () => T;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Options used when adding a button to an ActionForm.
|
|
15
|
+
*/
|
|
16
|
+
export interface IButtonOptions {
|
|
17
|
+
/**
|
|
18
|
+
* Logical identifier returned in the form response.
|
|
19
|
+
* If omitted, the numeric button index is used.
|
|
20
|
+
*/
|
|
21
|
+
id?: string | number;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Optional icon path from a resource pack.
|
|
25
|
+
*/
|
|
26
|
+
iconPath?: string;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Form class to open when this button is selected.
|
|
30
|
+
*/
|
|
31
|
+
subForm?: ActionFormCtor;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Whether the sub-form is allowed to return to this form.
|
|
35
|
+
* Defaults to true.
|
|
36
|
+
*/
|
|
37
|
+
allowReturn?: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
type ButtonMeta = {
|
|
41
|
+
id: string | number;
|
|
42
|
+
subForm?: ActionFormCtor;
|
|
43
|
+
allowReturn: boolean;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Normalized response object returned by IActionFormData.
|
|
48
|
+
*/
|
|
49
|
+
export interface IActionFormResponse {
|
|
50
|
+
/**
|
|
51
|
+
* Reason the form was canceled, if applicable.
|
|
52
|
+
*/
|
|
53
|
+
readonly cancelationReason?: FormCancelationReason;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Whether the form was canceled by the player.
|
|
57
|
+
*/
|
|
58
|
+
readonly canceled: boolean;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Raw button index selected by the player.
|
|
62
|
+
*/
|
|
63
|
+
readonly selection?: number;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Logical button id associated with the selection.
|
|
67
|
+
*/
|
|
68
|
+
readonly id?: string | number;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Abstract base class for ActionForm-based menus.
|
|
73
|
+
*
|
|
74
|
+
* Provides:
|
|
75
|
+
* - Button id mapping
|
|
76
|
+
* - Occupied player handling
|
|
77
|
+
* - Sub-form chaining with automatic Back navigation
|
|
78
|
+
* - Normalized response objects
|
|
79
|
+
*/
|
|
80
|
+
export abstract class IActionFormData extends Form {
|
|
81
|
+
protected form: ActionFormData = new ActionFormData();
|
|
82
|
+
|
|
83
|
+
private _buttons = new Map<number, ButtonMeta>();
|
|
84
|
+
private _nextButtonIndex = 0;
|
|
85
|
+
private _id: string = "untitled";
|
|
86
|
+
|
|
87
|
+
protected abstract build(player: Player): void;
|
|
88
|
+
|
|
89
|
+
protected abstract onSubmit( player: Player, response: IActionFormResponse): void;
|
|
90
|
+
|
|
91
|
+
protected onCancel?(player: Player, response: IActionFormResponse): void;
|
|
92
|
+
|
|
93
|
+
public title(titleText: RawMessage | string): this {
|
|
94
|
+
this.form.title(titleText);
|
|
95
|
+
this._id = typeof titleText === "string" ? titleText : JSON.stringify(titleText);
|
|
96
|
+
return this;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public body(bodyText: RawMessage | string): this { this.form.body(bodyText); return this;}
|
|
100
|
+
|
|
101
|
+
public divider(): this { this.form.divider(); return this;}
|
|
102
|
+
|
|
103
|
+
public header(text: RawMessage | string): this { this.form.header(text); return this;}
|
|
104
|
+
|
|
105
|
+
public label(text: RawMessage | string): this { this.form.label(text); return this;}
|
|
106
|
+
|
|
107
|
+
public button(text: RawMessage | string, options: IButtonOptions = {}): this {
|
|
108
|
+
if (options.iconPath) this.form.button(text, options.iconPath);
|
|
109
|
+
else this.form.button(text);
|
|
110
|
+
|
|
111
|
+
const id: string | number = options.id ?? this._nextButtonIndex;
|
|
112
|
+
const allowReturn = options.allowReturn ?? true;
|
|
113
|
+
|
|
114
|
+
this._buttons.set(this._nextButtonIndex, {
|
|
115
|
+
id,
|
|
116
|
+
subForm: options.subForm,
|
|
117
|
+
allowReturn,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
this._nextButtonIndex++;
|
|
121
|
+
return this;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
public async show(player: Player): Promise<IActionFormResponse> {
|
|
125
|
+
if (Form.isOccupied(player)) {
|
|
126
|
+
throw new Error(`Player ${player.id} is already occupied by form: ${this._id}`);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
this.setOccupied(player, true);
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
return await this._showInternal(player, []);
|
|
133
|
+
} finally {
|
|
134
|
+
this.setOccupied(player, false);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
protected async _showChained(player: Player,returnStack: ActionFormCtor[]): Promise<IActionFormResponse> {
|
|
139
|
+
return await this._showInternal(player, returnStack);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
private _wrapResponse(response: ActionFormResponse,id?: string | number): IActionFormResponse {
|
|
143
|
+
return {
|
|
144
|
+
canceled: response.canceled,
|
|
145
|
+
cancelationReason: response.cancelationReason,
|
|
146
|
+
selection: response.selection,
|
|
147
|
+
id,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private async _showInternal(player: Player, returnStack: ActionFormCtor[]): Promise<IActionFormResponse> {
|
|
152
|
+
|
|
153
|
+
this.form = new ActionFormData();
|
|
154
|
+
|
|
155
|
+
this._buttons.clear();
|
|
156
|
+
this._nextButtonIndex = 0;
|
|
157
|
+
|
|
158
|
+
this.build(player);
|
|
159
|
+
|
|
160
|
+
if (returnStack.length > 0) {
|
|
161
|
+
this.form.button(Form.returnText);
|
|
162
|
+
this._buttons.set(this._nextButtonIndex, {
|
|
163
|
+
id: RETURN_ID,
|
|
164
|
+
subForm: returnStack[returnStack.length - 1],
|
|
165
|
+
allowReturn: true,
|
|
166
|
+
});
|
|
167
|
+
this._nextButtonIndex++;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const response = await this.form.show(player);
|
|
171
|
+
|
|
172
|
+
if (response.canceled) {
|
|
173
|
+
const wrapped = this._wrapResponse(response, undefined);
|
|
174
|
+
this.onCancel?.(player, wrapped);
|
|
175
|
+
return wrapped;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const meta =
|
|
179
|
+
response.selection !== undefined
|
|
180
|
+
? this._buttons.get(response.selection)
|
|
181
|
+
: undefined;
|
|
182
|
+
|
|
183
|
+
if (meta?.id === RETURN_ID && meta.subForm) {
|
|
184
|
+
const prevCtor = returnStack[returnStack.length - 1];
|
|
185
|
+
const newStack = returnStack.slice(0, -1);
|
|
186
|
+
const prev = new prevCtor();
|
|
187
|
+
return await prev._showChained(player, newStack);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const wrapped = this._wrapResponse(response, meta?.id);
|
|
191
|
+
|
|
192
|
+
this.onSubmit(player, wrapped);
|
|
193
|
+
|
|
194
|
+
if (meta?.subForm) {
|
|
195
|
+
const next = new meta.subForm();
|
|
196
|
+
const allowReturn = meta.allowReturn ?? true;
|
|
197
|
+
|
|
198
|
+
const nextStack = allowReturn
|
|
199
|
+
? [...returnStack, this.constructor as ActionFormCtor]
|
|
200
|
+
: [...returnStack];
|
|
201
|
+
|
|
202
|
+
return await next._showChained(player, nextStack);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return wrapped;
|
|
206
|
+
}
|
|
207
|
+
}
|
package/util/_Form.ts
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/*
|
|
2
|
+
**************************************************
|
|
3
|
+
Copyright (c) Block Factory - All rights reserved.
|
|
4
|
+
**************************************************
|
|
5
|
+
Author: Donthedev <https://github.com/voxeldon>
|
|
6
|
+
**************************************************
|
|
7
|
+
*/
|
|
8
|
+
import { Player, RawMessage } from "@minecraft/server";
|
|
9
|
+
import { ActionFormData, ActionFormResponse, ModalFormData, ModalFormDataDropdownOptions, ModalFormDataSliderOptions, ModalFormDataTextFieldOptions, ModalFormDataToggleOptions, ModalFormResponse } from "@minecraft/server-ui";
|
|
10
|
+
|
|
11
|
+
const occupiedPlayers: Set<string> = new Set();
|
|
12
|
+
|
|
13
|
+
class Form {
|
|
14
|
+
public readonly isOccupied = ((player: Player): boolean => {
|
|
15
|
+
return occupiedPlayers.has(player.id);
|
|
16
|
+
})
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface Button {
|
|
20
|
+
indexId: string | number;
|
|
21
|
+
text: string | RawMessage;
|
|
22
|
+
iconPath?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface FormActionData {
|
|
26
|
+
response: ActionFormResponse;
|
|
27
|
+
indexId?: string | number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export class ActionForm extends Form {
|
|
31
|
+
private readonly actionForm: ActionFormData = new ActionFormData();
|
|
32
|
+
private buttonMap: Map<number, string | number> = new Map<number, string | number>();
|
|
33
|
+
private buttons: Button[] = [];
|
|
34
|
+
private titleText: string | RawMessage | undefined;
|
|
35
|
+
private bodyText: string | RawMessage | undefined;
|
|
36
|
+
|
|
37
|
+
public title(title: string | RawMessage): void {
|
|
38
|
+
this.titleText = title;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public body(body: string | RawMessage): void {
|
|
42
|
+
this.bodyText = body;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public button(indexId: string, text: string | RawMessage, iconPath?: string): void {
|
|
46
|
+
this.buttons.push({ indexId, text, iconPath });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public async showForm(player: Player): Promise<FormActionData> {
|
|
50
|
+
if (this.titleText === undefined || this.bodyText === undefined) {
|
|
51
|
+
throw Error('Title and body must be set before showing the form');
|
|
52
|
+
}
|
|
53
|
+
this.actionForm.title(this.titleText);
|
|
54
|
+
this.actionForm.body(this.bodyText);
|
|
55
|
+
this.generateButtons();
|
|
56
|
+
|
|
57
|
+
occupiedPlayers.add(player.id);
|
|
58
|
+
|
|
59
|
+
const response: ActionFormResponse = await this.actionForm.show(player).finally(() => {
|
|
60
|
+
occupiedPlayers.delete(player.id);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const return_data: FormActionData = {
|
|
64
|
+
response: response,
|
|
65
|
+
indexId: undefined
|
|
66
|
+
};
|
|
67
|
+
if (response.selection !== undefined && response.selection !== null) {
|
|
68
|
+
const selection: string | number | undefined = this.buttonMap.get(response.selection);
|
|
69
|
+
return_data.indexId = selection;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return return_data;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private generateButtons() {
|
|
76
|
+
let buttonIndex: number = 0;
|
|
77
|
+
this.buttons.forEach(button => {
|
|
78
|
+
if (button.iconPath) {
|
|
79
|
+
this.actionForm.button(button.text, button.iconPath);
|
|
80
|
+
} else {
|
|
81
|
+
this.actionForm.button(button.text);
|
|
82
|
+
}
|
|
83
|
+
this.buttonMap.set(buttonIndex, button.indexId);
|
|
84
|
+
buttonIndex++;
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
enum WidgetType {
|
|
90
|
+
TextField = 'textField',
|
|
91
|
+
Dropdown = 'dropdown',
|
|
92
|
+
Slider = 'slider',
|
|
93
|
+
Toggle = 'toggle'
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
interface Widget {
|
|
97
|
+
typeId: string,
|
|
98
|
+
widget: any
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export interface TextField {
|
|
102
|
+
indexId: string,
|
|
103
|
+
label: string | RawMessage,
|
|
104
|
+
placeholder: string | RawMessage,
|
|
105
|
+
defaultValue?: string
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface Dropdown {
|
|
109
|
+
indexId: string,
|
|
110
|
+
label: string | RawMessage,
|
|
111
|
+
options: string[],
|
|
112
|
+
defaultValueIndex?: number
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export interface Slider {
|
|
116
|
+
indexId: string,
|
|
117
|
+
label: string | RawMessage,
|
|
118
|
+
min: number,
|
|
119
|
+
max: number,
|
|
120
|
+
step: number,
|
|
121
|
+
defaultValue?: number
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface Toggle {
|
|
125
|
+
indexId: string,
|
|
126
|
+
label: string | RawMessage,
|
|
127
|
+
defaultValue?: boolean
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export type FormValue = string | boolean | number | undefined;
|
|
131
|
+
|
|
132
|
+
export interface FormModalData {
|
|
133
|
+
response: ModalFormResponse;
|
|
134
|
+
indexMap?: Map<string, FormValue>;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export class ModalForm extends Form {
|
|
138
|
+
private readonly modalForm: ModalFormData = new ModalFormData();
|
|
139
|
+
private widgitMap: Map<number, string> = new Map<number, string>();
|
|
140
|
+
private indexMap: Map<string, FormValue> = new Map<string, FormValue>();
|
|
141
|
+
private widgets: Widget[] = [];
|
|
142
|
+
|
|
143
|
+
public title(title: string | RawMessage): void {
|
|
144
|
+
this.modalForm.title(title);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
public label(label: string | RawMessage): void {
|
|
148
|
+
this.modalForm.label(label);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
public header(header: string | RawMessage): void {
|
|
152
|
+
this.modalForm.header(header);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
public divider(): void {
|
|
156
|
+
this.modalForm.divider();
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
public textField(indexId: string, label: string | RawMessage, placeholder: string | RawMessage, defaultValue?: string): void {
|
|
160
|
+
this.widgets.push({ typeId: WidgetType.TextField, widget: { indexId, label, placeholder, defaultValue } });
|
|
161
|
+
}
|
|
162
|
+
public dropdown(indexId: string, label: string | RawMessage, options: string[], defaultValueIndex?: number): void {
|
|
163
|
+
this.widgets.push({ typeId: WidgetType.Dropdown, widget: { indexId, label, options, defaultValueIndex } });
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
public slider(indexId: string, label: string | RawMessage, min: number, max: number, step: number, defaultValue?: number): void {
|
|
167
|
+
this.widgets.push({ typeId: WidgetType.Slider, widget: { indexId, label, min, max, step, defaultValue } });
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
public toggle(indexId: string, label: string | RawMessage, defaultValue?: boolean): void {
|
|
171
|
+
this.widgets.push({ typeId: WidgetType.Toggle, widget: { indexId, label, defaultValue } });
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
public async showForm(player: Player): Promise<FormModalData> {
|
|
175
|
+
this.processWidgets();
|
|
176
|
+
occupiedPlayers.add(player.id);
|
|
177
|
+
|
|
178
|
+
const response: ModalFormResponse = await this.modalForm.show(player).finally(() => {
|
|
179
|
+
occupiedPlayers.delete(player.id);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
const return_data: FormModalData = {
|
|
183
|
+
response: response,
|
|
184
|
+
indexMap: undefined
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (response.formValues !== null && response.formValues !== undefined) {
|
|
188
|
+
this.processValues(response.formValues);
|
|
189
|
+
return_data.indexMap = this.indexMap;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return return_data;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
private processWidgets(): void {
|
|
196
|
+
let widgitIndex: number = 0;
|
|
197
|
+
|
|
198
|
+
for (const widget of this.widgets) {
|
|
199
|
+
if (widget.typeId === WidgetType.TextField) {
|
|
200
|
+
const textField: TextField = widget.widget;
|
|
201
|
+
const options: ModalFormDataTextFieldOptions = {
|
|
202
|
+
defaultValue: textField?.defaultValue
|
|
203
|
+
};
|
|
204
|
+
this.modalForm.textField(textField.label, textField.placeholder, options);
|
|
205
|
+
this.widgitMap.set(widgitIndex, textField.indexId);
|
|
206
|
+
}
|
|
207
|
+
else if (widget.typeId === WidgetType.Dropdown) {
|
|
208
|
+
const dropdown: Dropdown = widget.widget;
|
|
209
|
+
const options: ModalFormDataDropdownOptions = {
|
|
210
|
+
defaultValueIndex: dropdown?.defaultValueIndex
|
|
211
|
+
};
|
|
212
|
+
this.modalForm.dropdown(dropdown.label, dropdown.options, options);
|
|
213
|
+
this.widgitMap.set(widgitIndex, dropdown.indexId);
|
|
214
|
+
|
|
215
|
+
}
|
|
216
|
+
else if (widget.typeId === WidgetType.Slider) {
|
|
217
|
+
const slider: Slider = widget.widget;
|
|
218
|
+
const options: ModalFormDataSliderOptions = {
|
|
219
|
+
defaultValue: slider?.defaultValue,
|
|
220
|
+
valueStep: slider.step
|
|
221
|
+
};
|
|
222
|
+
this.modalForm.slider(slider.label, slider.min, slider.max, options);
|
|
223
|
+
this.widgitMap.set(widgitIndex, slider.indexId);
|
|
224
|
+
}
|
|
225
|
+
else if (widget.typeId === WidgetType.Toggle) {
|
|
226
|
+
const toggle: Toggle = widget.widget;
|
|
227
|
+
const options: ModalFormDataToggleOptions = {
|
|
228
|
+
defaultValue: toggle?.defaultValue
|
|
229
|
+
}
|
|
230
|
+
this.modalForm.toggle(toggle.label, options);
|
|
231
|
+
this.widgitMap.set(widgitIndex, toggle.indexId);
|
|
232
|
+
}
|
|
233
|
+
widgitIndex += 1;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
private processValues(formValues: FormValue[]): void {
|
|
238
|
+
let widgitIndex: number = 0;
|
|
239
|
+
for (const i of formValues) {
|
|
240
|
+
const value: FormValue = i?.valueOf();
|
|
241
|
+
const indexId: string | undefined = this.widgitMap.get(widgitIndex);
|
|
242
|
+
if (indexId) this.indexMap.set(indexId, value);
|
|
243
|
+
widgitIndex++;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|