@starktma/minecraft-utils 1.0.1 → 1.1.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/LICENSE +674 -674
- package/package.json +36 -36
- package/src/math/index.ts +129 -129
- package/src/minecraft/index.ts +62 -62
- package/tsconfig.json +22 -22
package/package.json
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@starktma/minecraft-utils",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"keywords": [],
|
|
8
|
-
"author": "",
|
|
9
|
-
"license": "ISC",
|
|
10
|
-
"type": "module",
|
|
11
|
-
"scripts": {
|
|
12
|
-
"build": "npx -p typescript tsc --project tsconfig.json"
|
|
13
|
-
},
|
|
14
|
-
"exports": {
|
|
15
|
-
".": {
|
|
16
|
-
"import": "./dist/index.js",
|
|
17
|
-
"types": "./dist/index.d.ts"
|
|
18
|
-
},
|
|
19
|
-
"./math": {
|
|
20
|
-
"import": "./dist/math/index.js",
|
|
21
|
-
"types": "./dist/math/index.d.ts"
|
|
22
|
-
},
|
|
23
|
-
"./minecraft": {
|
|
24
|
-
"import": "./dist/minecraft/index.js",
|
|
25
|
-
"types": "./dist/minecraft/index.d.ts"
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
"publishConfig": {
|
|
29
|
-
"access": "public"
|
|
30
|
-
},
|
|
31
|
-
"devDependencies": {
|
|
32
|
-
"@minecraft/server": "^2.1.0",
|
|
33
|
-
"@minecraft/server-ui": "^2.0.0",
|
|
34
|
-
"typescript": "^5.9.2"
|
|
35
|
-
}
|
|
36
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@starktma/minecraft-utils",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"keywords": [],
|
|
8
|
+
"author": "",
|
|
9
|
+
"license": "ISC",
|
|
10
|
+
"type": "module",
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "npx -p typescript tsc --project tsconfig.json"
|
|
13
|
+
},
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"import": "./dist/index.js",
|
|
17
|
+
"types": "./dist/index.d.ts"
|
|
18
|
+
},
|
|
19
|
+
"./math": {
|
|
20
|
+
"import": "./dist/math/index.js",
|
|
21
|
+
"types": "./dist/math/index.d.ts"
|
|
22
|
+
},
|
|
23
|
+
"./minecraft": {
|
|
24
|
+
"import": "./dist/minecraft/index.js",
|
|
25
|
+
"types": "./dist/minecraft/index.d.ts"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@minecraft/server": "^2.1.0",
|
|
33
|
+
"@minecraft/server-ui": "^2.0.0",
|
|
34
|
+
"typescript": "^5.9.2"
|
|
35
|
+
}
|
|
36
|
+
}
|
package/src/math/index.ts
CHANGED
|
@@ -1,129 +1,129 @@
|
|
|
1
|
-
import { Vector3 } from "@minecraft/server";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Converts an angle in degrees to radians.
|
|
5
|
-
*
|
|
6
|
-
* @param degrees - The angle in degrees to be converted.
|
|
7
|
-
* @returns The angle in radians.
|
|
8
|
-
*/
|
|
9
|
-
export function toRadians(degrees: number): number {
|
|
10
|
-
return degrees * (Math.PI / 180);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Converts an angle in radians to degrees.
|
|
15
|
-
*
|
|
16
|
-
* @param radians - The angle in radians to be converted.
|
|
17
|
-
* @returns The angle in degrees.
|
|
18
|
-
*/
|
|
19
|
-
export function calculateDistance(position1: Vector3, position2: Vector3): number {
|
|
20
|
-
return Math.sqrt(
|
|
21
|
-
Math.sqrt(Math.pow(position1.x - position2.x, 2) + Math.pow(position1.y - position2.y, 2)) + Math.pow(position1.z - position2.z, 2)
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Converts an angle in radians to degrees.
|
|
27
|
-
*
|
|
28
|
-
* @param radians - The angle in radians to be converted.
|
|
29
|
-
* @returns The angle in degrees.
|
|
30
|
-
*/
|
|
31
|
-
export function toDegrees(radians: number): number {
|
|
32
|
-
return radians * (180 / Math.PI);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Converts a hex color string to an RGBA object.
|
|
37
|
-
*
|
|
38
|
-
* @param hex - The hex color string, which can be in the formats #RGB, #RGBA, #RRGGBB, or #RRGGBBAA.
|
|
39
|
-
* @returns An object containing the red, green, blue, and alpha components as numbers between 0 and 1.
|
|
40
|
-
* @throws Error if the hex string is invalid.
|
|
41
|
-
*/
|
|
42
|
-
export function hexToRgba(hex: string): { red: number; green: number; blue: number; alpha: number } {
|
|
43
|
-
if (!/^#([a-fA-F0-9]{4}|[a-fA-F0-9]{8}|[a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/.test(hex)) {
|
|
44
|
-
throw new Error("Invalid hex color");
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
let normalized = hex.slice(1);
|
|
48
|
-
if (normalized.length === 3 || normalized.length === 4) {
|
|
49
|
-
normalized = normalized
|
|
50
|
-
.split("")
|
|
51
|
-
.map((c) => c + c)
|
|
52
|
-
.join("");
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const red = parseInt(normalized.substring(0, 2), 16) / 255;
|
|
56
|
-
const green = parseInt(normalized.substring(2, 4), 16) / 255;
|
|
57
|
-
const blue = parseInt(normalized.substring(4, 6), 16) / 255;
|
|
58
|
-
const alpha = (normalized.length === 8 ? parseInt(normalized.substring(6, 8), 16) : 255) / 255;
|
|
59
|
-
|
|
60
|
-
return { red, green, blue, alpha };
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Clamps a value between a minimum and maximum range.
|
|
65
|
-
*
|
|
66
|
-
* @param value - The value to be clamped.
|
|
67
|
-
* @param min - The minimum value of the range.
|
|
68
|
-
* @param max - The maximum value of the range.
|
|
69
|
-
* @returns The clamped value, which will be between `min` and `max`.
|
|
70
|
-
*/
|
|
71
|
-
export function clamp(value: number, min: number, max: number): number {
|
|
72
|
-
return Math.max(min, Math.min(max, value));
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Converts an angle in degrees to its signed equivalent in the range [-180, 180].
|
|
77
|
-
*
|
|
78
|
-
* @param angle - The angle in degrees to be converted.
|
|
79
|
-
* @returns The signed angle in degrees, normalized to the range [-180, 180].
|
|
80
|
-
*/
|
|
81
|
-
export function toSigned(angle: number): number {
|
|
82
|
-
const wrapped = ((angle % 360) + 360) % 360;
|
|
83
|
-
return wrapped > 180 ? wrapped - 360 : wrapped;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Converts an angle in degrees to its unsigned equivalent in the range [0, 360].
|
|
88
|
-
*
|
|
89
|
-
* @param angle - The angle in degrees to be converted.
|
|
90
|
-
* @returns The unsigned angle in degrees, normalized to the range [0, 360].
|
|
91
|
-
*/
|
|
92
|
-
export function toUnsigned(angle: number): number {
|
|
93
|
-
return ((angle % 360) + 360) % 360;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Calculates the shortest signed arc between two angles in degrees.
|
|
98
|
-
*
|
|
99
|
-
* @param from - The starting angle in degrees.
|
|
100
|
-
* @param to - The target angle in degrees.
|
|
101
|
-
* @returns The shortest arc in degrees from `from` to `to`.
|
|
102
|
-
*/
|
|
103
|
-
export function shortestArc(from: number, to: number): number {
|
|
104
|
-
return -toSigned((to - from + 360) % 360);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Checks if two positions are equal within a specified tolerance.
|
|
109
|
-
*
|
|
110
|
-
* @param a - The first position.
|
|
111
|
-
* @param b - The second position.
|
|
112
|
-
* @param tolerance - The tolerance for comparison (default is 0.5).
|
|
113
|
-
* @returns `true` if the positions are equal within the tolerance, otherwise `false`.
|
|
114
|
-
*/
|
|
115
|
-
export function positionsEqual(a: Vector3, b: Vector3, tolerance: number = 0.5): boolean {
|
|
116
|
-
return Math.abs(a.x - b.x) < tolerance && Math.abs(a.y - b.y) < tolerance && Math.abs(a.z - b.z) < tolerance;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Checks if a value is within a specified range.
|
|
121
|
-
*
|
|
122
|
-
* @param value - The value to check.
|
|
123
|
-
* @param min - The minimum value of the range.
|
|
124
|
-
* @param max - The maximum value of the range.
|
|
125
|
-
* @returns `true` if the value is within the range [min, max], otherwise `false`.
|
|
126
|
-
*/
|
|
127
|
-
export function inRange(value: number, min: number, max: number): boolean {
|
|
128
|
-
return value >= min && value <= max;
|
|
129
|
-
}
|
|
1
|
+
import { Vector3 } from "@minecraft/server";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Converts an angle in degrees to radians.
|
|
5
|
+
*
|
|
6
|
+
* @param degrees - The angle in degrees to be converted.
|
|
7
|
+
* @returns The angle in radians.
|
|
8
|
+
*/
|
|
9
|
+
export function toRadians(degrees: number): number {
|
|
10
|
+
return degrees * (Math.PI / 180);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Converts an angle in radians to degrees.
|
|
15
|
+
*
|
|
16
|
+
* @param radians - The angle in radians to be converted.
|
|
17
|
+
* @returns The angle in degrees.
|
|
18
|
+
*/
|
|
19
|
+
export function calculateDistance(position1: Vector3, position2: Vector3): number {
|
|
20
|
+
return Math.sqrt(
|
|
21
|
+
Math.sqrt(Math.pow(position1.x - position2.x, 2) + Math.pow(position1.y - position2.y, 2)) + Math.pow(position1.z - position2.z, 2)
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Converts an angle in radians to degrees.
|
|
27
|
+
*
|
|
28
|
+
* @param radians - The angle in radians to be converted.
|
|
29
|
+
* @returns The angle in degrees.
|
|
30
|
+
*/
|
|
31
|
+
export function toDegrees(radians: number): number {
|
|
32
|
+
return radians * (180 / Math.PI);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Converts a hex color string to an RGBA object.
|
|
37
|
+
*
|
|
38
|
+
* @param hex - The hex color string, which can be in the formats #RGB, #RGBA, #RRGGBB, or #RRGGBBAA.
|
|
39
|
+
* @returns An object containing the red, green, blue, and alpha components as numbers between 0 and 1.
|
|
40
|
+
* @throws Error if the hex string is invalid.
|
|
41
|
+
*/
|
|
42
|
+
export function hexToRgba(hex: string): { red: number; green: number; blue: number; alpha: number } {
|
|
43
|
+
if (!/^#([a-fA-F0-9]{4}|[a-fA-F0-9]{8}|[a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/.test(hex)) {
|
|
44
|
+
throw new Error("Invalid hex color");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
let normalized = hex.slice(1);
|
|
48
|
+
if (normalized.length === 3 || normalized.length === 4) {
|
|
49
|
+
normalized = normalized
|
|
50
|
+
.split("")
|
|
51
|
+
.map((c) => c + c)
|
|
52
|
+
.join("");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const red = parseInt(normalized.substring(0, 2), 16) / 255;
|
|
56
|
+
const green = parseInt(normalized.substring(2, 4), 16) / 255;
|
|
57
|
+
const blue = parseInt(normalized.substring(4, 6), 16) / 255;
|
|
58
|
+
const alpha = (normalized.length === 8 ? parseInt(normalized.substring(6, 8), 16) : 255) / 255;
|
|
59
|
+
|
|
60
|
+
return { red, green, blue, alpha };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Clamps a value between a minimum and maximum range.
|
|
65
|
+
*
|
|
66
|
+
* @param value - The value to be clamped.
|
|
67
|
+
* @param min - The minimum value of the range.
|
|
68
|
+
* @param max - The maximum value of the range.
|
|
69
|
+
* @returns The clamped value, which will be between `min` and `max`.
|
|
70
|
+
*/
|
|
71
|
+
export function clamp(value: number, min: number, max: number): number {
|
|
72
|
+
return Math.max(min, Math.min(max, value));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Converts an angle in degrees to its signed equivalent in the range [-180, 180].
|
|
77
|
+
*
|
|
78
|
+
* @param angle - The angle in degrees to be converted.
|
|
79
|
+
* @returns The signed angle in degrees, normalized to the range [-180, 180].
|
|
80
|
+
*/
|
|
81
|
+
export function toSigned(angle: number): number {
|
|
82
|
+
const wrapped = ((angle % 360) + 360) % 360;
|
|
83
|
+
return wrapped > 180 ? wrapped - 360 : wrapped;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Converts an angle in degrees to its unsigned equivalent in the range [0, 360].
|
|
88
|
+
*
|
|
89
|
+
* @param angle - The angle in degrees to be converted.
|
|
90
|
+
* @returns The unsigned angle in degrees, normalized to the range [0, 360].
|
|
91
|
+
*/
|
|
92
|
+
export function toUnsigned(angle: number): number {
|
|
93
|
+
return ((angle % 360) + 360) % 360;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Calculates the shortest signed arc between two angles in degrees.
|
|
98
|
+
*
|
|
99
|
+
* @param from - The starting angle in degrees.
|
|
100
|
+
* @param to - The target angle in degrees.
|
|
101
|
+
* @returns The shortest arc in degrees from `from` to `to`.
|
|
102
|
+
*/
|
|
103
|
+
export function shortestArc(from: number, to: number): number {
|
|
104
|
+
return -toSigned((to - from + 360) % 360);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Checks if two positions are equal within a specified tolerance.
|
|
109
|
+
*
|
|
110
|
+
* @param a - The first position.
|
|
111
|
+
* @param b - The second position.
|
|
112
|
+
* @param tolerance - The tolerance for comparison (default is 0.5).
|
|
113
|
+
* @returns `true` if the positions are equal within the tolerance, otherwise `false`.
|
|
114
|
+
*/
|
|
115
|
+
export function positionsEqual(a: Vector3, b: Vector3, tolerance: number = 0.5): boolean {
|
|
116
|
+
return Math.abs(a.x - b.x) < tolerance && Math.abs(a.y - b.y) < tolerance && Math.abs(a.z - b.z) < tolerance;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Checks if a value is within a specified range.
|
|
121
|
+
*
|
|
122
|
+
* @param value - The value to check.
|
|
123
|
+
* @param min - The minimum value of the range.
|
|
124
|
+
* @param max - The maximum value of the range.
|
|
125
|
+
* @returns `true` if the value is within the range [min, max], otherwise `false`.
|
|
126
|
+
*/
|
|
127
|
+
export function inRange(value: number, min: number, max: number): boolean {
|
|
128
|
+
return value >= min && value <= max;
|
|
129
|
+
}
|
package/src/minecraft/index.ts
CHANGED
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
import { Player, Entity, Block, Vector3, world } from "@minecraft/server";
|
|
2
|
-
import { calculateDistance, toUnsigned } from "../math";
|
|
3
|
-
|
|
4
|
-
export function getBlocksInASphere(centerBlock: Block | Entity, radius: number, innerRadius?: number) {
|
|
5
|
-
if (centerBlock) {
|
|
6
|
-
if (centerBlock instanceof Block && !centerBlock.isValid) return [];
|
|
7
|
-
let center = centerBlock.location;
|
|
8
|
-
let blocks: Block[] = [];
|
|
9
|
-
for (let x = center.x - radius; x < center.x + radius; x++) {
|
|
10
|
-
for (let y = center.y - radius; y < center.y + radius; y++) {
|
|
11
|
-
for (let z = center.z - radius; z < center.z + radius; z++) {
|
|
12
|
-
try {
|
|
13
|
-
let block = centerBlock.dimension.getBlock({ x: x, y: y, z: z });
|
|
14
|
-
if (
|
|
15
|
-
block &&
|
|
16
|
-
block.isValid &&
|
|
17
|
-
!block.isAir &&
|
|
18
|
-
!block.permutation.matches("minecraft:bedrock") &&
|
|
19
|
-
!block.permutation.matches("minecraft:barrier") &&
|
|
20
|
-
calculateDistance(center, block.location) <= radius &&
|
|
21
|
-
(!innerRadius || calculateDistance(center, block.location) >= innerRadius)
|
|
22
|
-
) {
|
|
23
|
-
blocks.push(block);
|
|
24
|
-
}
|
|
25
|
-
} catch (e) {}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return blocks;
|
|
30
|
-
}
|
|
31
|
-
return [];
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function displayActionbar(player: Player | undefined, ...message: any) {
|
|
35
|
-
const text = message.join(" ");
|
|
36
|
-
let target;
|
|
37
|
-
let selector;
|
|
38
|
-
target = player && player.isValid ? player : world.getDimension("overworld");
|
|
39
|
-
selector = player ? `@s` : `@a`;
|
|
40
|
-
target.runCommand(`title @s actionbar ${JSON.stringify(text)}`);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Snaps an angle to the nearest grid size.
|
|
45
|
-
*
|
|
46
|
-
* @param angle - The angle in degrees to be snapped.
|
|
47
|
-
* @returns The snapped unsigned angle in degrees.
|
|
48
|
-
*/
|
|
49
|
-
export function snapRotationToGrid(angle: number): number {
|
|
50
|
-
const gridSize = 90;
|
|
51
|
-
return Math.round(toUnsigned(angle) / gridSize) * gridSize;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Snaps a vector to the nearest integer coordinates.
|
|
56
|
-
*
|
|
57
|
-
* @param v - The vector to be snapped.
|
|
58
|
-
* @returns A new vector with each component rounded to the nearest integer.
|
|
59
|
-
*/
|
|
60
|
-
export function snapLocationToGrid(v: Vector3): Vector3 {
|
|
61
|
-
return { x: Math.round(v.x), y: Math.floor(v.y), z: Math.round(v.z) };
|
|
62
|
-
}
|
|
1
|
+
import { Player, Entity, Block, Vector3, world } from "@minecraft/server";
|
|
2
|
+
import { calculateDistance, toUnsigned } from "../math";
|
|
3
|
+
|
|
4
|
+
export function getBlocksInASphere(centerBlock: Block | Entity, radius: number, innerRadius?: number) {
|
|
5
|
+
if (centerBlock) {
|
|
6
|
+
if (centerBlock instanceof Block && !centerBlock.isValid) return [];
|
|
7
|
+
let center = centerBlock.location;
|
|
8
|
+
let blocks: Block[] = [];
|
|
9
|
+
for (let x = center.x - radius; x < center.x + radius; x++) {
|
|
10
|
+
for (let y = center.y - radius; y < center.y + radius; y++) {
|
|
11
|
+
for (let z = center.z - radius; z < center.z + radius; z++) {
|
|
12
|
+
try {
|
|
13
|
+
let block = centerBlock.dimension.getBlock({ x: x, y: y, z: z });
|
|
14
|
+
if (
|
|
15
|
+
block &&
|
|
16
|
+
block.isValid &&
|
|
17
|
+
!block.isAir &&
|
|
18
|
+
!block.permutation.matches("minecraft:bedrock") &&
|
|
19
|
+
!block.permutation.matches("minecraft:barrier") &&
|
|
20
|
+
calculateDistance(center, block.location) <= radius &&
|
|
21
|
+
(!innerRadius || calculateDistance(center, block.location) >= innerRadius)
|
|
22
|
+
) {
|
|
23
|
+
blocks.push(block);
|
|
24
|
+
}
|
|
25
|
+
} catch (e) {}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return blocks;
|
|
30
|
+
}
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function displayActionbar(player: Player | undefined, ...message: any) {
|
|
35
|
+
const text = message.join(" ");
|
|
36
|
+
let target;
|
|
37
|
+
let selector;
|
|
38
|
+
target = player && player.isValid ? player : world.getDimension("overworld");
|
|
39
|
+
selector = player ? `@s` : `@a`;
|
|
40
|
+
target.runCommand(`title @s actionbar ${JSON.stringify(text)}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Snaps an angle to the nearest grid size.
|
|
45
|
+
*
|
|
46
|
+
* @param angle - The angle in degrees to be snapped.
|
|
47
|
+
* @returns The snapped unsigned angle in degrees.
|
|
48
|
+
*/
|
|
49
|
+
export function snapRotationToGrid(angle: number): number {
|
|
50
|
+
const gridSize = 90;
|
|
51
|
+
return Math.round(toUnsigned(angle) / gridSize) * gridSize;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Snaps a vector to the nearest integer coordinates.
|
|
56
|
+
*
|
|
57
|
+
* @param v - The vector to be snapped.
|
|
58
|
+
* @returns A new vector with each component rounded to the nearest integer.
|
|
59
|
+
*/
|
|
60
|
+
export function snapLocationToGrid(v: Vector3): Vector3 {
|
|
61
|
+
return { x: Math.round(v.x), y: Math.floor(v.y), z: Math.round(v.z) };
|
|
62
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"module": "esnext",
|
|
4
|
-
"moduleResolution": "bundler",
|
|
5
|
-
"target": "ES2022",
|
|
6
|
-
"esModuleInterop": true,
|
|
7
|
-
"sourceMap": true,
|
|
8
|
-
"strict": true,
|
|
9
|
-
"forceConsistentCasingInFileNames": true,
|
|
10
|
-
"resolveJsonModule": true,
|
|
11
|
-
|
|
12
|
-
"composite": true,
|
|
13
|
-
"declaration": true,
|
|
14
|
-
"declarationMap": true,
|
|
15
|
-
"incremental": true,
|
|
16
|
-
"skipLibCheck": true,
|
|
17
|
-
"noEmitOnError": true,
|
|
18
|
-
"typeRoots": ["./node_modules/@types"],
|
|
19
|
-
"outDir": "./dist",
|
|
20
|
-
"rootDir": "./src"
|
|
21
|
-
}
|
|
22
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"module": "esnext",
|
|
4
|
+
"moduleResolution": "bundler",
|
|
5
|
+
"target": "ES2022",
|
|
6
|
+
"esModuleInterop": true,
|
|
7
|
+
"sourceMap": true,
|
|
8
|
+
"strict": true,
|
|
9
|
+
"forceConsistentCasingInFileNames": true,
|
|
10
|
+
"resolveJsonModule": true,
|
|
11
|
+
|
|
12
|
+
"composite": true,
|
|
13
|
+
"declaration": true,
|
|
14
|
+
"declarationMap": true,
|
|
15
|
+
"incremental": true,
|
|
16
|
+
"skipLibCheck": true,
|
|
17
|
+
"noEmitOnError": true,
|
|
18
|
+
"typeRoots": ["./node_modules/@types"],
|
|
19
|
+
"outDir": "./dist",
|
|
20
|
+
"rootDir": "./src"
|
|
21
|
+
}
|
|
22
|
+
}
|