lenix 1.8.8 → 1.8.11
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/client/_init.ts +9 -4
- package/client/client.ts +155 -181
- package/client/nearest.ts +5 -5
- package/client/nui.ts +6 -1
- package/client/pool.ts +7 -3
- package/nui/_init.ts +4 -0
- package/nui/index.ts +1 -0
- package/package.json +2 -2
- package/server/server.ts +17 -19
- package/shared/index.ts +0 -1
- package/shared/types.ts +7 -2
- package/shared/repeat.ts +0 -34
package/client/_init.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { asserts, type JsonValue } from '@lenix/lenix'
|
|
2
2
|
import type { Request } from '../shared/types.ts'
|
|
3
|
-
import { onNui } from './nui.ts'
|
|
3
|
+
import { state, onNui } from './nui.ts'
|
|
4
4
|
|
|
5
5
|
type Resolve = {
|
|
6
6
|
success: true,
|
|
@@ -22,8 +22,8 @@ onNui<Request<JsonValue, '__nuiServer', {
|
|
|
22
22
|
}
|
|
23
23
|
}>>('__nuiServer', async ({ id, data }) => {
|
|
24
24
|
const { timeout = DEFAULT_TIMEOUT, requestData } = data
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
|
|
26
|
+
const response = await new Promise<Resolve>(resolve => {
|
|
27
27
|
requestId = requestId + 1
|
|
28
28
|
const currentRequestId = requestId
|
|
29
29
|
pendingResolves[currentRequestId] = resolve
|
|
@@ -47,7 +47,7 @@ onNui<Request<JsonValue, '__nuiServer', {
|
|
|
47
47
|
}
|
|
48
48
|
}, timeout)
|
|
49
49
|
})
|
|
50
|
-
|
|
50
|
+
|
|
51
51
|
asserts(response.success, `server nui<${id}> timed out after ${timeout}ms, possible slow respose or request does not exist`)
|
|
52
52
|
|
|
53
53
|
return response.returned
|
|
@@ -63,3 +63,8 @@ onNui<Request<true, '__nuiFocus', {
|
|
|
63
63
|
SetNuiFocus(keyboard, cursor)
|
|
64
64
|
return true
|
|
65
65
|
})
|
|
66
|
+
|
|
67
|
+
onNui<Request<null, '__nuiInit'>>('__nuiInit', () => {
|
|
68
|
+
state.nuiReady = true
|
|
69
|
+
return null
|
|
70
|
+
})
|
package/client/client.ts
CHANGED
|
@@ -1,197 +1,171 @@
|
|
|
1
1
|
import type { JsonValue } from '@lenix/lenix'
|
|
2
|
-
import { repeat } from '
|
|
2
|
+
import { repeat } from '../../../typescript/repeat.ts'
|
|
3
3
|
import type { Vec3, Vec4 } from '../shared/types.ts'
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
export const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
coords
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return coords
|
|
57
|
-
})(),
|
|
58
|
-
|
|
59
|
-
/* */
|
|
60
|
-
teleport: (
|
|
61
|
-
entity: number,
|
|
62
|
-
x: number,
|
|
63
|
-
y: number,
|
|
64
|
-
z: number,
|
|
65
|
-
h?: number,
|
|
66
|
-
keepTasks = false,
|
|
67
|
-
keepIK = false,
|
|
68
|
-
doWarp = false
|
|
69
|
-
) => {
|
|
70
|
-
SetEntityCoordsNoOffset(entity, x, y, z, keepTasks, keepIK, doWarp)
|
|
71
|
-
h && SetEntityHeading(entity, h)
|
|
72
|
-
},
|
|
6
|
+
export const entity = {
|
|
7
|
+
/**
|
|
8
|
+
* Gets the local entity handle from a network ID.
|
|
9
|
+
*
|
|
10
|
+
* Network IDs are shared, but entity handles are local.
|
|
11
|
+
* The returned handle is only valid on the current machine.
|
|
12
|
+
*
|
|
13
|
+
* If no network ID is provided, this resolves your own player ped
|
|
14
|
+
* by first getting its network ID.
|
|
15
|
+
*
|
|
16
|
+
* Examples:
|
|
17
|
+
* - entity(vehicleNetId) -> local vehicle handle
|
|
18
|
+
* - entity(pedNetId) -> local ped handle
|
|
19
|
+
* - entity() -> your own player ped handle
|
|
20
|
+
*/
|
|
21
|
+
handle: (entityNetId: number) => NetworkGetEntityFromNetworkId(entityNetId),
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Gets the network ID for an entity.
|
|
25
|
+
*
|
|
26
|
+
* Entity handles are local to the current machine.
|
|
27
|
+
* Network IDs are shared references for networked entities.
|
|
28
|
+
*
|
|
29
|
+
* If no entity is provided, this uses your own player ped.
|
|
30
|
+
*
|
|
31
|
+
* Examples:
|
|
32
|
+
* - netId(vehicle) -> network ID of that vehicle
|
|
33
|
+
* - netId(targetPed) -> network ID of that ped
|
|
34
|
+
* - netId() -> network ID of your own player ped
|
|
35
|
+
*/
|
|
36
|
+
netId: (entity: number) => NetworkGetNetworkIdFromEntity(entity),
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Gets entity coordinates and heading.
|
|
40
|
+
*/
|
|
41
|
+
coords: (() => {
|
|
42
|
+
function coords(entity?: number, excludeH?: true, isAlive?: boolean): Vec3
|
|
43
|
+
function coords(entity?: number, excludeH?: false, isAlive?: boolean): Vec4
|
|
44
|
+
function coords(handle = player.entity(), excludeH = false, isAlive = true) {
|
|
45
|
+
const entityCoords = GetEntityCoords(handle, isAlive) as Vec3
|
|
46
|
+
|
|
47
|
+
if (excludeH) return entityCoords
|
|
48
|
+
|
|
49
|
+
return [
|
|
50
|
+
...entityCoords,
|
|
51
|
+
GetEntityHeading(handle)
|
|
52
|
+
]
|
|
53
|
+
}
|
|
73
54
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
},
|
|
55
|
+
return coords
|
|
56
|
+
})(),
|
|
57
|
+
|
|
58
|
+
/* */
|
|
59
|
+
teleport: (
|
|
60
|
+
x: number,
|
|
61
|
+
y: number,
|
|
62
|
+
z: number,
|
|
63
|
+
handle: number = player.entity(),
|
|
64
|
+
h?: number,
|
|
65
|
+
keepTasks = false,
|
|
66
|
+
keepIK = false,
|
|
67
|
+
doWarp = false
|
|
68
|
+
) => {
|
|
69
|
+
SetEntityCoordsNoOffset(handle, x, y, z, keepTasks, keepIK, doWarp)
|
|
70
|
+
h && SetEntityHeading(handle, h)
|
|
71
|
+
},
|
|
92
72
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
73
|
+
/* */
|
|
74
|
+
playAnim: async (
|
|
75
|
+
ped: number,
|
|
76
|
+
dict: string,
|
|
77
|
+
name: string,
|
|
78
|
+
blendIn = 2.0,
|
|
79
|
+
blendOut = 2.0,
|
|
80
|
+
duration = -1,
|
|
81
|
+
flag = 0,
|
|
82
|
+
playbackFrom = 0.0,
|
|
83
|
+
x = false,
|
|
84
|
+
y = false,
|
|
85
|
+
z = false
|
|
86
|
+
) => {
|
|
87
|
+
RequestAnimDict(dict)
|
|
88
|
+
await repeat(() => HasAnimDictLoaded(dict), true)
|
|
89
|
+
TaskPlayAnim(ped, dict, name, blendIn, blendOut, duration, flag, playbackFrom, x, y, z)
|
|
98
90
|
},
|
|
99
|
-
player: {
|
|
100
|
-
/**
|
|
101
|
-
* Gets a client player ID.
|
|
102
|
-
*
|
|
103
|
-
* If a server ID is provided, this converts that server ID into a client
|
|
104
|
-
* player ID on the current client.
|
|
105
|
-
*
|
|
106
|
-
* If no server ID is provided, this returns your own client player ID.
|
|
107
|
-
*
|
|
108
|
-
* Examples:
|
|
109
|
-
* - id(targetServerId) -> target player's client player ID
|
|
110
|
-
* - id() -> your own client player ID
|
|
111
|
-
*/
|
|
112
|
-
id: (serverId?: number) => serverId !== undefined ? GetPlayerFromServerId(serverId) : PlayerId(),
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Gets a player's server ID from their client player ID.
|
|
116
|
-
*
|
|
117
|
-
* Client player IDs are local to each client.
|
|
118
|
-
* Server IDs, also called source IDs, identify connected players on the server.
|
|
119
|
-
*
|
|
120
|
-
* If no client player ID is provided, this uses your own client player ID.
|
|
121
|
-
*
|
|
122
|
-
* Examples:
|
|
123
|
-
* - serverId(targetPlayerId) -> target player's server ID
|
|
124
|
-
* - serverId() -> your own server ID
|
|
125
|
-
*/
|
|
126
|
-
serverId(playerId?: number) {
|
|
127
|
-
return GetPlayerServerId(playerId ?? this.id())
|
|
128
|
-
},
|
|
129
91
|
|
|
130
|
-
|
|
131
|
-
|
|
92
|
+
/* */
|
|
93
|
+
stopAnim: (ped: number, dict: string) => {
|
|
94
|
+
RemoveAnimDict(dict)
|
|
95
|
+
ClearPedTasks(ped)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
132
98
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
99
|
+
export const player = {
|
|
100
|
+
/**
|
|
101
|
+
* Gets a client player ID.
|
|
102
|
+
*
|
|
103
|
+
* If a server ID is provided, this converts that server ID into a client
|
|
104
|
+
* player ID on the current
|
|
105
|
+
*
|
|
106
|
+
* If no server ID is provided, this returns your own client player ID.
|
|
107
|
+
*
|
|
108
|
+
* Examples:
|
|
109
|
+
* - id(targetServerId) -> target player's client player ID
|
|
110
|
+
* - id() -> your own client player ID
|
|
111
|
+
*/
|
|
112
|
+
id: (serverId?: number) => serverId !== undefined ? GetPlayerFromServerId(serverId) : PlayerId(),
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Gets a player's server ID from their client player ID.
|
|
116
|
+
*
|
|
117
|
+
* Client player IDs are local to each
|
|
118
|
+
* Server IDs, also called source IDs, identify connected players on the server.
|
|
119
|
+
*
|
|
120
|
+
* If no client player ID is provided, this uses your own client player ID.
|
|
121
|
+
*
|
|
122
|
+
* Examples:
|
|
123
|
+
* - serverId(targetPlayerId) -> target player's server ID
|
|
124
|
+
* - serverId() -> your own server ID
|
|
125
|
+
*/
|
|
126
|
+
serverId(playerId?: number) {
|
|
127
|
+
return GetPlayerServerId(playerId ?? this.id())
|
|
128
|
+
},
|
|
137
129
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
excludeH?: T,
|
|
141
|
-
isAlive?: boolean
|
|
142
|
-
): T extends true ? Vec3 : Vec4 {
|
|
143
|
-
return (
|
|
144
|
-
excludeH === true
|
|
145
|
-
? client.entity.coords(this.entity(), true, isAlive)
|
|
146
|
-
: client.entity.coords(this.entity(), false, isAlive)
|
|
147
|
-
) as T extends true ? Vec3 : Vec4;
|
|
148
|
-
},
|
|
130
|
+
/* */
|
|
131
|
+
entity: (playerId?: number) => playerId !== undefined ? GetPlayerPed(playerId) : PlayerPedId(),
|
|
149
132
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
z: number,
|
|
155
|
-
h?: number,
|
|
156
|
-
keepTasks = false,
|
|
157
|
-
keepIK = false,
|
|
158
|
-
doWarp = false
|
|
159
|
-
) {
|
|
160
|
-
return client.entity.teleport(this.entity(), x, y, z, h, keepTasks, keepIK, doWarp)
|
|
161
|
-
},
|
|
133
|
+
/* */
|
|
134
|
+
netId(playerId: number): number {
|
|
135
|
+
return PedToNet(entity.handle(playerId))
|
|
136
|
+
},
|
|
162
137
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
SetResourceKvp(key, JSON.stringify(init))
|
|
185
|
-
return init as Storage[K] extends JsonValue ? Storage[K] : never
|
|
138
|
+
/* */
|
|
139
|
+
storage: {
|
|
140
|
+
set: <Storage>(
|
|
141
|
+
...[key, value]: {
|
|
142
|
+
[K in keyof Storage]: Storage[K] extends JsonValue
|
|
143
|
+
? [key: Extract<K, string>, value: Storage[K]]
|
|
144
|
+
: never
|
|
145
|
+
}[keyof Storage]
|
|
146
|
+
) => SetResourceKvp(key, JSON.stringify(value)),
|
|
147
|
+
|
|
148
|
+
get: <Storage, K extends Extract<keyof Storage, string>>(
|
|
149
|
+
key: K,
|
|
150
|
+
init?: Storage[K] extends JsonValue ? Storage[K] : never
|
|
151
|
+
): Storage[K] extends JsonValue ? Storage[K] : never => {
|
|
152
|
+
const value = GetResourceKvpString(key)
|
|
153
|
+
|
|
154
|
+
if (value === null) {
|
|
155
|
+
if (init === undefined) {
|
|
156
|
+
throw `Storage<${key}> was never assigned`
|
|
186
157
|
}
|
|
187
158
|
|
|
188
|
-
|
|
189
|
-
|
|
159
|
+
SetResourceKvp(key, JSON.stringify(init))
|
|
160
|
+
return init as Storage[K] extends JsonValue ? Storage[K] : never
|
|
161
|
+
}
|
|
190
162
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
163
|
+
return JSON.parse(value) as Storage[K] extends JsonValue ? Storage[K] : never
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
delete: <Storage>(
|
|
167
|
+
key: Extract<keyof Storage, string>
|
|
168
|
+
) => DeleteResourceKvp(key),
|
|
169
|
+
/* TODO: add on event */
|
|
196
170
|
}
|
|
197
|
-
}
|
|
171
|
+
}
|
package/client/nearest.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Vec3 } from '../shared/types.ts'
|
|
2
|
-
import {
|
|
2
|
+
import { entity } from './client.ts'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Finds the nearest coordinates from a list.
|
|
@@ -50,7 +50,7 @@ const player = (
|
|
|
50
50
|
const playerPed = GetPlayerPed(playerId)
|
|
51
51
|
const vehicle = GetVehiclePedIsIn(playerPed, false)
|
|
52
52
|
const playerCoords: Vec3 = vehicle === 0
|
|
53
|
-
?
|
|
53
|
+
? entity.coords(playerPed, true)
|
|
54
54
|
: GetWorldPositionOfEntityBone(playerPed, 0) as Vec3
|
|
55
55
|
|
|
56
56
|
const distance = Vdist(
|
|
@@ -83,15 +83,15 @@ const player = (
|
|
|
83
83
|
/**
|
|
84
84
|
* Finds the nearest vehicle around an entity.
|
|
85
85
|
*/
|
|
86
|
-
const vehicle = (
|
|
87
|
-
const coords: Vec3 =
|
|
86
|
+
const vehicle = (entityHandle: number, radialSpace: number): number | undefined => {
|
|
87
|
+
const coords: Vec3 = entity.coords(entityHandle, true)
|
|
88
88
|
const vehicles = GetGamePool('CVehicle') as number[]
|
|
89
89
|
|
|
90
90
|
let closest: number | undefined
|
|
91
91
|
let closestDistance = radialSpace
|
|
92
92
|
|
|
93
93
|
for (const vehicle of vehicles) {
|
|
94
|
-
const vehCoords: Vec3 =
|
|
94
|
+
const vehCoords: Vec3 = entity.coords(vehicle, true)
|
|
95
95
|
const x = coords[0] - vehCoords[0]
|
|
96
96
|
const y = coords[1] - vehCoords[1]
|
|
97
97
|
const z = coords[2] - vehCoords[2]
|
package/client/nui.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import type { NuiFetchGeneric } from '../shared/types.ts'
|
|
2
|
+
import { State } from '@lenix/lenix'
|
|
3
|
+
|
|
4
|
+
export const state = new State({ nuiReady: false as boolean })
|
|
2
5
|
|
|
3
6
|
/**
|
|
4
7
|
* Sends an event from the game client to the NUI browser.
|
|
@@ -29,8 +32,10 @@ export const onNui = <T extends NuiFetchGeneric>(
|
|
|
29
32
|
) => {
|
|
30
33
|
try {
|
|
31
34
|
reply(await cb(data))
|
|
32
|
-
} catch(e) {
|
|
35
|
+
} catch (e) {
|
|
33
36
|
throw e
|
|
34
37
|
}
|
|
35
38
|
})
|
|
36
39
|
}
|
|
40
|
+
|
|
41
|
+
export const isNuiReady = () => state.nuiReady
|
package/client/pool.ts
CHANGED
|
@@ -4,10 +4,12 @@ let running = false
|
|
|
4
4
|
/**
|
|
5
5
|
* Adds a task to a shared FiveM tick pool.
|
|
6
6
|
*/
|
|
7
|
-
export const pool = (
|
|
8
|
-
tasks.
|
|
7
|
+
export const pool = (cb: () => void): () => boolean => {
|
|
8
|
+
const cleanUp = () => tasks.delete(cb)
|
|
9
|
+
tasks.add(cb)
|
|
9
10
|
|
|
10
|
-
if (running) return
|
|
11
|
+
if (running) return cleanUp
|
|
12
|
+
|
|
11
13
|
running = true
|
|
12
14
|
|
|
13
15
|
const tick = setTick(() => {
|
|
@@ -25,4 +27,6 @@ export const pool = (func: () => void): void => {
|
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
29
|
})
|
|
30
|
+
|
|
31
|
+
return cleanUp
|
|
28
32
|
}
|
package/nui/_init.ts
ADDED
package/nui/index.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lenix",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.11",
|
|
4
4
|
"description": "Typed FiveM utilities for client, server, shared, and NUI scripts",
|
|
5
5
|
"author": "Lenix",
|
|
6
6
|
"license": "MIT",
|
|
@@ -47,6 +47,6 @@
|
|
|
47
47
|
"typescript": "^5"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@lenix/lenix": "npm:@jsr/lenix__lenix@1.8.
|
|
50
|
+
"@lenix/lenix": "npm:@jsr/lenix__lenix@1.8.19"
|
|
51
51
|
}
|
|
52
52
|
}
|
package/server/server.ts
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
|
-
export const
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
},
|
|
19
|
-
}
|
|
1
|
+
export const entity = {
|
|
2
|
+
handle: (netId: number) => NetworkGetEntityFromNetworkId(netId),
|
|
3
|
+
handleBySource: (source: number) => GetPlayerPed(source.toString()),
|
|
4
|
+
teleport: (
|
|
5
|
+
entity: number,
|
|
6
|
+
x: number,
|
|
7
|
+
y: number,
|
|
8
|
+
z: number,
|
|
9
|
+
h?: number,
|
|
10
|
+
clearArea = false,
|
|
11
|
+
alive = true,
|
|
12
|
+
deadDisable = false,
|
|
13
|
+
ragdol = false
|
|
14
|
+
) => {
|
|
15
|
+
SetEntityCoords(entity, x, y, z, alive, deadDisable, ragdol, clearArea)
|
|
16
|
+
h && SetEntityHeading(entity, h)
|
|
17
|
+
},
|
|
20
18
|
}
|
package/shared/index.ts
CHANGED
package/shared/types.ts
CHANGED
|
@@ -3,12 +3,17 @@ import type { JsonValue } from "@lenix/lenix"
|
|
|
3
3
|
/**
|
|
4
4
|
* Three-dimensional coordinates plus heading.
|
|
5
5
|
*/
|
|
6
|
-
export type Vec4 = [number, number, number, number]
|
|
6
|
+
export type Vec4 = readonly [number, number, number, number]
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Three-dimensional coordinates.
|
|
10
10
|
*/
|
|
11
|
-
export type Vec3 = [number, number, number]
|
|
11
|
+
export type Vec3 = readonly [number, number, number]
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Two-dimensional coordinates.
|
|
15
|
+
*/
|
|
16
|
+
export type Vec2 = readonly [number, number, number]
|
|
12
17
|
|
|
13
18
|
/**
|
|
14
19
|
* Typed event tuple containing an event id and positional parameters.
|
package/shared/repeat.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/* */
|
|
2
|
-
export function repeat<T>(check: () => T): Promise<T>
|
|
3
|
-
export function repeat<T, C extends T>(
|
|
4
|
-
check: () => T,
|
|
5
|
-
untilOrEqual: C | ((checked: T) => checked is C),
|
|
6
|
-
each?: number,
|
|
7
|
-
): Promise<C>
|
|
8
|
-
export function repeat<T>(
|
|
9
|
-
check: () => T,
|
|
10
|
-
untilOrEqual?: T | ((checked: T) => boolean),
|
|
11
|
-
each?: number,
|
|
12
|
-
): Promise<T> {
|
|
13
|
-
const hasCondition = arguments.length > 1
|
|
14
|
-
const predicate = typeof untilOrEqual === 'function'
|
|
15
|
-
? untilOrEqual as (checked: T) => boolean
|
|
16
|
-
: undefined
|
|
17
|
-
|
|
18
|
-
return new Promise(resolve => {
|
|
19
|
-
const interval = setInterval(() => {
|
|
20
|
-
const checked = check()
|
|
21
|
-
|
|
22
|
-
const met = predicate
|
|
23
|
-
? predicate(checked)
|
|
24
|
-
: hasCondition
|
|
25
|
-
? checked === untilOrEqual
|
|
26
|
-
: checked !== undefined && checked !== null
|
|
27
|
-
|
|
28
|
-
if (!met) return
|
|
29
|
-
|
|
30
|
-
clearInterval(interval)
|
|
31
|
-
resolve(checked)
|
|
32
|
-
}, each)
|
|
33
|
-
})
|
|
34
|
-
}
|