@block_factory/lib 0.0.1
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/esbuild.config.mjs +18 -0
- package/index.d.ts +16 -0
- package/index.js +526 -0
- package/index.ts +16 -0
- package/package.json +32 -0
- package/tsconfig.json +27 -0
- package/util/Command.d.ts +23 -0
- package/util/Command.ts +124 -0
- package/util/Form.d.ts +75 -0
- package/util/Form.ts +246 -0
- package/util/Math.d.ts +14 -0
- package/util/Math.ts +68 -0
- package/util/RawText.d.ts +33 -0
- package/util/RawText.ts +76 -0
- package/util/Signal.d.ts +9 -0
- package/util/Signal.ts +73 -0
- package/util/Vector.d.ts +60 -0
- package/util/Vector.ts +388 -0
package/util/Command.ts
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CustomCommand,
|
|
3
|
+
CommandPermissionLevel,
|
|
4
|
+
CustomCommandParameter,
|
|
5
|
+
CustomCommandOrigin,
|
|
6
|
+
CustomCommandResult,
|
|
7
|
+
system,
|
|
8
|
+
StartupEvent
|
|
9
|
+
} from "@minecraft/server";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Command utilities and base classes for defining and registering
|
|
13
|
+
* Minecraft Bedrock custom commands.
|
|
14
|
+
*
|
|
15
|
+
* Provides:
|
|
16
|
+
* - `ICustomCommand` base class
|
|
17
|
+
* - `RegisterCustomCommand` decorator/function
|
|
18
|
+
* - Internal command registry used during startup
|
|
19
|
+
*/
|
|
20
|
+
export namespace Command {
|
|
21
|
+
/**
|
|
22
|
+
* Base class for all custom commands.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* import { Command } from "@block_factory/lib";
|
|
27
|
+
* import {
|
|
28
|
+
* world,
|
|
29
|
+
* system,
|
|
30
|
+
* CommandPermissionLevel,
|
|
31
|
+
* CustomCommandParameter,
|
|
32
|
+
* CustomCommandParamType,
|
|
33
|
+
* CustomCommandOrigin,
|
|
34
|
+
* CustomCommandResult,
|
|
35
|
+
* CustomCommandStatus
|
|
36
|
+
* } from "@minecraft/server";
|
|
37
|
+
*
|
|
38
|
+
* @Command.RegisterCustomCommand
|
|
39
|
+
* export default class TestCommand extends Command.ICustomCommand {
|
|
40
|
+
* public name = "bf_sd:test_cmd";
|
|
41
|
+
* public description = "Test command for debugging purposes.";
|
|
42
|
+
* public permissionLevel = CommandPermissionLevel.Admin;
|
|
43
|
+
*
|
|
44
|
+
* public optionalParameters: CustomCommandParameter[] = [
|
|
45
|
+
* { type: CustomCommandParamType.Integer, name: "size" }
|
|
46
|
+
* ];
|
|
47
|
+
*
|
|
48
|
+
* public execute(
|
|
49
|
+
* origin: CustomCommandOrigin,
|
|
50
|
+
* value: number
|
|
51
|
+
* ): CustomCommandResult | undefined {
|
|
52
|
+
* const entity = origin.sourceEntity;
|
|
53
|
+
* if (!entity)
|
|
54
|
+
* return {
|
|
55
|
+
* status: CustomCommandStatus.Failure,
|
|
56
|
+
* message: "Command fail"
|
|
57
|
+
* };
|
|
58
|
+
*
|
|
59
|
+
* system.run(() => {
|
|
60
|
+
* world.sendMessage(`Running Test: ${value}`);
|
|
61
|
+
* });
|
|
62
|
+
*
|
|
63
|
+
* return {
|
|
64
|
+
* status: CustomCommandStatus.Success,
|
|
65
|
+
* message: "Completed Test"
|
|
66
|
+
* };
|
|
67
|
+
* }
|
|
68
|
+
* }
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export abstract class ICustomCommand implements CustomCommand {
|
|
72
|
+
|
|
73
|
+
/** Command identifier (e.g. `bf_sd:test_cmd`) */
|
|
74
|
+
public abstract name: string;
|
|
75
|
+
|
|
76
|
+
/** Short description shown in help */
|
|
77
|
+
public abstract description: string;
|
|
78
|
+
|
|
79
|
+
/** Required permission level to execute */
|
|
80
|
+
public abstract permissionLevel: CommandPermissionLevel;
|
|
81
|
+
|
|
82
|
+
/** Whether cheats must be enabled */
|
|
83
|
+
public cheatsRequired?: boolean;
|
|
84
|
+
|
|
85
|
+
/** Required command parameters */
|
|
86
|
+
public mandatoryParameters?: CustomCommandParameter[];
|
|
87
|
+
|
|
88
|
+
/** Optional command parameters */
|
|
89
|
+
public optionalParameters?: CustomCommandParameter[];
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Executes the command.
|
|
93
|
+
* @param origin Command execution context
|
|
94
|
+
* @param args Parsed command arguments
|
|
95
|
+
*/
|
|
96
|
+
public abstract execute(
|
|
97
|
+
origin: CustomCommandOrigin,
|
|
98
|
+
...args: any[]
|
|
99
|
+
): CustomCommandResult | undefined;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/** Internal list of registered command instances */
|
|
103
|
+
export const customCommands: ICustomCommand[] = [];
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Registers a command class.
|
|
107
|
+
* Can be used as a decorator: `@RegisterCustomCommand`.
|
|
108
|
+
*/
|
|
109
|
+
export function RegisterCustomCommand<
|
|
110
|
+
T extends { new(): ICustomCommand }
|
|
111
|
+
>(customCommand: T): void {
|
|
112
|
+
const instance = new customCommand();
|
|
113
|
+
customCommands.push(instance);
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
system.beforeEvents.startup.subscribe(
|
|
118
|
+
(event: StartupEvent) => {
|
|
119
|
+
const { customCommandRegistry } = event;
|
|
120
|
+
for (const command of Command.customCommands) {
|
|
121
|
+
customCommandRegistry.registerCommand(command, command.execute);
|
|
122
|
+
};
|
|
123
|
+
},
|
|
124
|
+
);
|
package/util/Form.d.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Player, RawMessage } from "@minecraft/server";
|
|
2
|
+
import { ActionFormResponse, ModalFormResponse } from "@minecraft/server-ui";
|
|
3
|
+
declare class Form {
|
|
4
|
+
readonly isOccupied: (player: Player) => boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface Button {
|
|
7
|
+
indexId: string | number;
|
|
8
|
+
text: string | RawMessage;
|
|
9
|
+
iconPath?: string;
|
|
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
|
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
|
+
}
|
package/util/Math.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Vector2, Vector3 } from "@minecraft/server";
|
|
2
|
+
|
|
3
|
+
export declare namespace MathUtils {
|
|
4
|
+
function clamp(value: number, min: number, max: number): number;
|
|
5
|
+
function lerp(start: number, end: number, factor: number): number;
|
|
6
|
+
function toRadians(degrees: number): number;
|
|
7
|
+
function toDegrees(radians: number): number;
|
|
8
|
+
function fromRotation(rotation: Vector2): Vector3;
|
|
9
|
+
function rotateOffset(offset: Vector3, yawDegrees: number): Vector3;
|
|
10
|
+
function distance3D(pointA: Vector3, pointB: Vector3): number;
|
|
11
|
+
function randomInt(min: number, max: number): number;
|
|
12
|
+
function randomFloat(min: number, max: number): number;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=Math.d.ts.map
|
package/util/Math.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Vector2, Vector3 } from "@minecraft/server";
|
|
2
|
+
|
|
3
|
+
export namespace MathUtils {
|
|
4
|
+
/** Clamps a number between a minimum and maximum value */
|
|
5
|
+
export function clamp(value: number, min: number, max: number): number {
|
|
6
|
+
return Math.min(Math.max(value, min), max);
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
/** Linearly interpolates between two values based on a given factor (0 to 1) */
|
|
10
|
+
export function lerp(start: number, end: number, factor: number): number {
|
|
11
|
+
return start + (end - start) * clamp(factor, 0, 1);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/** Converts degrees to radians */
|
|
15
|
+
export function toRadians(degrees: number): number {
|
|
16
|
+
return degrees * (Math.PI / 180);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/** Converts radians to degrees */
|
|
20
|
+
export function toDegrees(radians: number): number {
|
|
21
|
+
return radians * (180 / Math.PI);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export function fromRotation(rotation: Vector2): Vector3 {
|
|
25
|
+
const rotationH = toRadians(rotation.y * -1);
|
|
26
|
+
const z0 = Math.cos(rotationH);
|
|
27
|
+
const x0 = Math.sin(rotationH);
|
|
28
|
+
|
|
29
|
+
const rotationV = toRadians(rotation.x * -1);
|
|
30
|
+
const h = Math.cos(rotationV);
|
|
31
|
+
const v = Math.sin(rotationV);
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
x: h * x0,
|
|
35
|
+
y: v,
|
|
36
|
+
z: h * z0
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export function rotateOffset(offset: Vector3, yawDegrees: number): Vector3 {
|
|
41
|
+
const yaw = -yawDegrees * Math.PI / 180;
|
|
42
|
+
const cos = Math.cos(yaw);
|
|
43
|
+
const sin = Math.sin(yaw);
|
|
44
|
+
return {
|
|
45
|
+
x: offset.x * cos - offset.z * sin,
|
|
46
|
+
y: offset.y,
|
|
47
|
+
z: offset.x * sin + offset.z * cos
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/** Calculates the distance between two points in 3D space */
|
|
52
|
+
export function distance3D(pointA: Vector3, pointB: Vector3): number {
|
|
53
|
+
const dx = pointB.x - pointA.x;
|
|
54
|
+
const dy = pointB.y - pointA.y;
|
|
55
|
+
const dz = pointB.z - pointA.z;
|
|
56
|
+
return Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/** Generates a random integer between min and max (inclusive) */
|
|
60
|
+
export function randomInt(min: number, max: number): number {
|
|
61
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/** Generates a random float between min and max */
|
|
65
|
+
export function randomFloat(min: number, max: number): number {
|
|
66
|
+
return Math.random() * (max - min) + min;
|
|
67
|
+
};
|
|
68
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { RawMessage } from "@minecraft/server";
|
|
2
|
+
|
|
3
|
+
export declare namespace RawText {
|
|
4
|
+
export const TEXT: (value: string) => RawMessage;
|
|
5
|
+
export const TRANSLATE: (key: string, ...params: string[]) => RawMessage;
|
|
6
|
+
export const SCORE: (name: string, objective: string) => RawMessage;
|
|
7
|
+
export const MESSAGE: (...rawText: RawMessage[]) => RawMessage;
|
|
8
|
+
export const FORMAT: {
|
|
9
|
+
DarkRed: RawMessage;
|
|
10
|
+
Red: RawMessage;
|
|
11
|
+
Gold: RawMessage;
|
|
12
|
+
Yellow: RawMessage;
|
|
13
|
+
Green: RawMessage;
|
|
14
|
+
Lime: RawMessage;
|
|
15
|
+
Aqua: RawMessage;
|
|
16
|
+
Cyan: RawMessage;
|
|
17
|
+
DarkBlue: RawMessage;
|
|
18
|
+
Blue: RawMessage;
|
|
19
|
+
Magenta: RawMessage;
|
|
20
|
+
Purple: RawMessage;
|
|
21
|
+
White: RawMessage;
|
|
22
|
+
Gray: RawMessage;
|
|
23
|
+
DarkGray: RawMessage;
|
|
24
|
+
Black: RawMessage;
|
|
25
|
+
Obfuscated: RawMessage;
|
|
26
|
+
Bold: RawMessage;
|
|
27
|
+
StrikeThrough: RawMessage;
|
|
28
|
+
Italic: RawMessage;
|
|
29
|
+
Reset: RawMessage;
|
|
30
|
+
NewLine: RawMessage;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=RawText.d.ts.map
|
package/util/RawText.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { RawMessage } from '@minecraft/server';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Utility helpers for building rawtext messages.
|
|
5
|
+
*/
|
|
6
|
+
export namespace RawText {
|
|
7
|
+
/**
|
|
8
|
+
* Creates a simple text component.
|
|
9
|
+
* @param value - The text value.
|
|
10
|
+
* @returns Text component object.
|
|
11
|
+
*/
|
|
12
|
+
export const TEXT = (value: string): RawMessage => ({
|
|
13
|
+
text: value
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Creates a translation component with optional 'with' parameters.
|
|
18
|
+
* @param key - The translation key.
|
|
19
|
+
* @param params - The optional parameters for translation.
|
|
20
|
+
* @returns Translation component object.
|
|
21
|
+
*/
|
|
22
|
+
export const TRANSLATE = (key: string, ...params: string[]): RawMessage => ({
|
|
23
|
+
translate: key,
|
|
24
|
+
with: params.length ? params : undefined
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Creates a score component.
|
|
29
|
+
* @param name - The entity's name whose score is being displayed.
|
|
30
|
+
* @param objective - The name of the score objective.
|
|
31
|
+
* @returns Score component object.
|
|
32
|
+
*/
|
|
33
|
+
export const SCORE = (name: string, objective: string): RawMessage => ({
|
|
34
|
+
score: {
|
|
35
|
+
name: name,
|
|
36
|
+
objective: objective
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Wraps various text components into a rawtext structure.
|
|
42
|
+
* @param rawText - The raw text components.
|
|
43
|
+
* @returns Raw text object.
|
|
44
|
+
*/
|
|
45
|
+
export const MESSAGE = (...rawText: RawMessage[]): RawMessage => ({
|
|
46
|
+
rawtext: rawText
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Common formatting and color codes.
|
|
51
|
+
*/
|
|
52
|
+
export const FORMAT = {
|
|
53
|
+
DarkRed: TEXT('§4'),
|
|
54
|
+
Red: TEXT('§c'),
|
|
55
|
+
Gold: TEXT('§6'),
|
|
56
|
+
Yellow: TEXT('§e'),
|
|
57
|
+
Green: TEXT('§2'),
|
|
58
|
+
Lime: TEXT('§a'),
|
|
59
|
+
Aqua: TEXT('§b'),
|
|
60
|
+
Cyan: TEXT('§3'),
|
|
61
|
+
DarkBlue: TEXT('§1'),
|
|
62
|
+
Blue: TEXT('§9'),
|
|
63
|
+
Magenta: TEXT('§d'),
|
|
64
|
+
Purple: TEXT('§5'),
|
|
65
|
+
White: TEXT('§f'),
|
|
66
|
+
Gray: TEXT('§7'),
|
|
67
|
+
DarkGray: TEXT('§8'),
|
|
68
|
+
Black: TEXT('§0'),
|
|
69
|
+
Obfuscated: TEXT('§k'),
|
|
70
|
+
Bold: TEXT('§l'),
|
|
71
|
+
StrikeThrough: TEXT('§m'),
|
|
72
|
+
Italic: TEXT('§o'),
|
|
73
|
+
Reset: TEXT('§r'),
|
|
74
|
+
NewLine: TEXT('\n')
|
|
75
|
+
}
|
|
76
|
+
}
|
package/util/Signal.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type Callback<T = void> = (data: T) => void;
|
|
2
|
+
export declare class Signal<T = void> {
|
|
3
|
+
private listeners;
|
|
4
|
+
connect(callback: Callback<T>): void;
|
|
5
|
+
disconnect(callback?: Callback<T>): boolean;
|
|
6
|
+
once(callback: Callback<T>): void;
|
|
7
|
+
emit(data: T): void;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=Signal.d.ts.map
|