@axpecter/lync 2.0.0 → 2.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/README.md +475 -426
- package/package.json +1 -1
- package/src/Types.luau +63 -31
- package/src/api/Group.luau +101 -106
- package/src/api/Packet.luau +187 -186
- package/src/api/Query.luau +223 -284
- package/src/api/Scope.luau +46 -57
- package/src/api/Signal.luau +104 -137
- package/src/codec/Base.luau +69 -20
- package/src/codec/composite/Array.luau +179 -270
- package/src/codec/composite/Map.luau +97 -347
- package/src/codec/composite/Optional.luau +27 -24
- package/src/codec/composite/Shared.luau +96 -65
- package/src/codec/composite/Struct.luau +200 -360
- package/src/codec/composite/Tagged.luau +62 -187
- package/src/codec/composite/Tuple.luau +79 -103
- package/src/codec/datatype/Buffer.luau +49 -21
- package/src/codec/datatype/CFrame.luau +207 -30
- package/src/codec/datatype/Color.luau +21 -11
- package/src/codec/datatype/Instance.luau +28 -21
- package/src/codec/datatype/IntVector.luau +33 -21
- package/src/codec/datatype/NumberRange.luau +19 -10
- package/src/codec/datatype/Ray.luau +26 -22
- package/src/codec/datatype/Rect.luau +20 -16
- package/src/codec/datatype/Region.luau +51 -45
- package/src/codec/datatype/Sequence.luau +64 -56
- package/src/codec/datatype/String.luau +89 -56
- package/src/codec/datatype/UDim.luau +40 -22
- package/src/codec/datatype/Vector.luau +181 -17
- package/src/codec/meta/Auto.luau +295 -253
- package/src/codec/meta/Bitfield.luau +104 -148
- package/src/codec/meta/Custom.luau +8 -4
- package/src/codec/meta/Enum.luau +29 -57
- package/src/codec/meta/Float.luau +64 -0
- package/src/codec/meta/Nothing.luau +9 -5
- package/src/codec/meta/Unknown.luau +44 -36
- package/src/codec/primitive/Bool.luau +16 -26
- package/src/codec/primitive/Float16.luau +58 -64
- package/src/codec/primitive/Int.luau +68 -0
- package/src/codec/primitive/Number.luau +21 -43
- package/src/codec/primitive/Varint.luau +67 -46
- package/src/index.d.ts +249 -335
- package/src/init.luau +319 -207
- package/src/internal/Baseline.luau +29 -24
- package/src/internal/Channel.luau +333 -278
- package/src/internal/Middleware.luau +60 -85
- package/src/internal/Pool.luau +19 -30
- package/src/internal/Registry.luau +56 -113
- package/src/transport/Bridge.luau +64 -43
- package/src/transport/Client.luau +59 -170
- package/src/transport/Gate.luau +282 -142
- package/src/transport/Reader.luau +148 -140
- package/src/transport/Server.luau +138 -488
- package/src/api/Namespace.luau +0 -256
- package/src/codec/meta/Quantized.luau +0 -174
package/src/api/Namespace.luau
DELETED
|
@@ -1,256 +0,0 @@
|
|
|
1
|
-
--!strict
|
|
2
|
-
--!optimize 2
|
|
3
|
-
-- Scoped packet/query groups with batch ops and local middleware.
|
|
4
|
-
|
|
5
|
-
local Middleware = require(script.Parent.Parent.internal.Middleware)
|
|
6
|
-
local Packet = require(script.Parent.Packet)
|
|
7
|
-
local Query = require(script.Parent.Query)
|
|
8
|
-
local Types = require(script.Parent.Parent.Types)
|
|
9
|
-
|
|
10
|
-
type Connection = Types.Connection
|
|
11
|
-
type PacketConfig<T> = Types.PacketConfig<T>
|
|
12
|
-
type QueryConfig<R, S> = Types.QueryConfig<R, S>
|
|
13
|
-
|
|
14
|
-
-- Constants -----------------------------------------------------------
|
|
15
|
-
|
|
16
|
-
local MAX_NAMESPACES = 64
|
|
17
|
-
|
|
18
|
-
-- State ---------------------------------------------------------------
|
|
19
|
-
|
|
20
|
-
local _registered = {} :: { [string]: true }
|
|
21
|
-
local _count = 0
|
|
22
|
-
|
|
23
|
-
-- Private -------------------------------------------------------------
|
|
24
|
-
|
|
25
|
-
type NamespaceConfig = Types.NamespaceConfig
|
|
26
|
-
|
|
27
|
-
type NamespaceFields = {
|
|
28
|
-
_name: string,
|
|
29
|
-
_packets: { [string]: Packet.Packet },
|
|
30
|
-
_queries: { [string]: Query.Query },
|
|
31
|
-
_tracked: { Connection },
|
|
32
|
-
_removers: { () -> () },
|
|
33
|
-
packets: { [string]: Packet.Packet },
|
|
34
|
-
queries: { [string]: Query.Query },
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
local function prefixName(nsName: string, name: string): string
|
|
38
|
-
return `{nsName}.{name}`
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
-- Wraps a middleware handler so it only fires for packets in this namespace.
|
|
42
|
-
local function scopedHandler(
|
|
43
|
-
nsName: string,
|
|
44
|
-
handler: (data: any, name: string, player: Player?) -> any?
|
|
45
|
-
): (data: any, name: string, player: Player?) -> any?
|
|
46
|
-
local prefix = nsName .. "."
|
|
47
|
-
local prefixLen = #prefix
|
|
48
|
-
|
|
49
|
-
return function(data: any, name: string, player: Player?): any?
|
|
50
|
-
if string.sub(name, 1, prefixLen) ~= prefix then
|
|
51
|
-
return data
|
|
52
|
-
end
|
|
53
|
-
return handler(data, name, player)
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
local NamespaceImpl = {}
|
|
58
|
-
NamespaceImpl.__index = NamespaceImpl
|
|
59
|
-
|
|
60
|
-
export type Namespace = typeof(setmetatable({} :: NamespaceFields, NamespaceImpl))
|
|
61
|
-
|
|
62
|
-
-- Listens on every packet in this namespace. Returns a Connection.
|
|
63
|
-
function NamespaceImpl.listenAll(
|
|
64
|
-
self: Namespace,
|
|
65
|
-
callback: (
|
|
66
|
-
name: string,
|
|
67
|
-
data: any,
|
|
68
|
-
sender: Player?,
|
|
69
|
-
timestamp: number?
|
|
70
|
-
) -> ()
|
|
71
|
-
): Connection
|
|
72
|
-
local connections = {} :: { Connection }
|
|
73
|
-
local prefix = self._name .. "."
|
|
74
|
-
local prefixLen = #prefix
|
|
75
|
-
|
|
76
|
-
for fullName, packet in self._packets do
|
|
77
|
-
local shortName = string.sub(fullName, prefixLen + 1)
|
|
78
|
-
local conn = packet:listen(function(data: any, sender: Player?, timestamp: number?): ()
|
|
79
|
-
callback(shortName, data, sender, timestamp)
|
|
80
|
-
end)
|
|
81
|
-
table.insert(connections, conn)
|
|
82
|
-
table.insert(self._tracked, conn)
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
local bundle: Connection
|
|
86
|
-
bundle = {
|
|
87
|
-
connected = true,
|
|
88
|
-
disconnect = function(self: Connection): ()
|
|
89
|
-
if not self.connected then
|
|
90
|
-
return
|
|
91
|
-
end
|
|
92
|
-
self.connected = false
|
|
93
|
-
|
|
94
|
-
for _, inner in connections do
|
|
95
|
-
if inner.connected then
|
|
96
|
-
inner:disconnect()
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
end,
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return bundle
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
-- Disconnects every listenAll connection. Does not remove scoped middleware.
|
|
106
|
-
function NamespaceImpl.disconnectAll(self: Namespace): ()
|
|
107
|
-
for _, conn in self._tracked do
|
|
108
|
-
if conn.connected then
|
|
109
|
-
conn:disconnect()
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
table.clear(self._tracked)
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
-- Registers send middleware scoped to this namespace. Returns a remover.
|
|
116
|
-
function NamespaceImpl.onSend(
|
|
117
|
-
self: Namespace,
|
|
118
|
-
handler: (data: any, name: string, player: Player?) -> any?
|
|
119
|
-
): () -> ()
|
|
120
|
-
local wrapped = scopedHandler(self._name, handler)
|
|
121
|
-
local remover = Middleware.addSend(wrapped)
|
|
122
|
-
table.insert(self._removers, remover)
|
|
123
|
-
|
|
124
|
-
return function(): ()
|
|
125
|
-
remover()
|
|
126
|
-
local idx = table.find(self._removers, remover)
|
|
127
|
-
if idx then
|
|
128
|
-
table.remove(self._removers, idx)
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
-- Registers receive middleware scoped to this namespace. Returns a remover.
|
|
134
|
-
function NamespaceImpl.onReceive(
|
|
135
|
-
self: Namespace,
|
|
136
|
-
handler: (data: any, name: string, player: Player?) -> any?
|
|
137
|
-
): () -> ()
|
|
138
|
-
local wrapped = scopedHandler(self._name, handler)
|
|
139
|
-
local remover = Middleware.addReceive(wrapped)
|
|
140
|
-
table.insert(self._removers, remover)
|
|
141
|
-
|
|
142
|
-
return function(): ()
|
|
143
|
-
remover()
|
|
144
|
-
local idx = table.find(self._removers, remover)
|
|
145
|
-
if idx then
|
|
146
|
-
table.remove(self._removers, idx)
|
|
147
|
-
end
|
|
148
|
-
end
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
-- Kills all listeners and removes all scoped middleware. Full cleanup.
|
|
152
|
-
function NamespaceImpl.destroy(self: Namespace): ()
|
|
153
|
-
self:disconnectAll()
|
|
154
|
-
|
|
155
|
-
for _, remover in self._removers do
|
|
156
|
-
remover()
|
|
157
|
-
end
|
|
158
|
-
table.clear(self._removers)
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
-- Returns every packet name(without prefix) in this namespace.
|
|
162
|
-
function NamespaceImpl.packetNames(self: Namespace): { string }
|
|
163
|
-
local result = {} :: { string }
|
|
164
|
-
local prefix = self._name .. "."
|
|
165
|
-
local prefixLen = #prefix
|
|
166
|
-
|
|
167
|
-
for fullName in self._packets do
|
|
168
|
-
table.insert(result, string.sub(fullName, prefixLen + 1))
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
table.sort(result)
|
|
172
|
-
return result
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
-- Returns every query name(without prefix) in this namespace.
|
|
176
|
-
function NamespaceImpl.queryNames(self: Namespace): { string }
|
|
177
|
-
local result = {} :: { string }
|
|
178
|
-
local prefix = self._name .. "."
|
|
179
|
-
local prefixLen = #prefix
|
|
180
|
-
|
|
181
|
-
for fullName in self._queries do
|
|
182
|
-
table.insert(result, string.sub(fullName, prefixLen + 1))
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
table.sort(result)
|
|
186
|
-
return result
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
table.freeze(NamespaceImpl)
|
|
190
|
-
|
|
191
|
-
-- Public --------------------------------------------------------------
|
|
192
|
-
|
|
193
|
-
local NamespaceModule = {}
|
|
194
|
-
|
|
195
|
-
-- Defines a namespace. Names are auto-prefixed to prevent collisions.
|
|
196
|
-
function NamespaceModule.define(name: string, config: NamespaceConfig): Namespace
|
|
197
|
-
if #name == 0 then
|
|
198
|
-
error("[Lync] Namespace name must not be empty")
|
|
199
|
-
end
|
|
200
|
-
if _registered[name] then
|
|
201
|
-
error(`[Lync] Duplicate namespace: "{name}"`)
|
|
202
|
-
end
|
|
203
|
-
if _count >= MAX_NAMESPACES then
|
|
204
|
-
error(`[Lync] Namespace limit reached: {MAX_NAMESPACES}`)
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
_count += 1
|
|
208
|
-
_registered[name] = true
|
|
209
|
-
|
|
210
|
-
local packets = {} :: { [string]: Packet.Packet }
|
|
211
|
-
local queries = {} :: { [string]: Query.Query }
|
|
212
|
-
local packetsByShort = {} :: { [string]: Packet.Packet }
|
|
213
|
-
local queriesByShort = {} :: { [string]: Query.Query }
|
|
214
|
-
|
|
215
|
-
if config.packets then
|
|
216
|
-
for shortName, packetConfig in config.packets do
|
|
217
|
-
local fullName = prefixName(name, shortName)
|
|
218
|
-
local packet = Packet.define(fullName, packetConfig)
|
|
219
|
-
packets[fullName] = packet
|
|
220
|
-
packetsByShort[shortName] = packet
|
|
221
|
-
end
|
|
222
|
-
end
|
|
223
|
-
|
|
224
|
-
if config.queries then
|
|
225
|
-
for shortName, queryConfig in config.queries do
|
|
226
|
-
local fullName = prefixName(name, shortName)
|
|
227
|
-
local query = Query.define(fullName, queryConfig)
|
|
228
|
-
queries[fullName] = query
|
|
229
|
-
queriesByShort[shortName] = query
|
|
230
|
-
end
|
|
231
|
-
end
|
|
232
|
-
|
|
233
|
-
local nsFields: NamespaceFields = {
|
|
234
|
-
_name = name,
|
|
235
|
-
_packets = packets,
|
|
236
|
-
_queries = queries,
|
|
237
|
-
_tracked = {} :: { Connection },
|
|
238
|
-
_removers = {} :: { () -> () },
|
|
239
|
-
packets = table.freeze(packetsByShort),
|
|
240
|
-
queries = table.freeze(queriesByShort),
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
-- Inject dynamic short-name accessors (ns.Hit, ns.Stats, etc.)
|
|
244
|
-
-- These bypass the typed fields; consumers should prefer ns.packets.X / ns.queries.X.
|
|
245
|
-
local raw = nsFields :: any
|
|
246
|
-
for shortName, packet in packetsByShort do
|
|
247
|
-
raw[shortName] = packet
|
|
248
|
-
end
|
|
249
|
-
for shortName, query in queriesByShort do
|
|
250
|
-
raw[shortName] = query
|
|
251
|
-
end
|
|
252
|
-
|
|
253
|
-
return setmetatable(nsFields, NamespaceImpl)
|
|
254
|
-
end
|
|
255
|
-
|
|
256
|
-
return table.freeze(NamespaceModule)
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
--!strict
|
|
2
|
-
--!native
|
|
3
|
-
-- Fixed-point compression. Maps float ranges to integer ranges.
|
|
4
|
-
|
|
5
|
-
local Channel = require(script.Parent.Parent.Parent.internal.Channel)
|
|
6
|
-
local Types = require(script.Parent.Parent.Parent.Types)
|
|
7
|
-
|
|
8
|
-
type ChannelState = Types.ChannelState
|
|
9
|
-
type Codec<T> = Types.Codec<T>
|
|
10
|
-
|
|
11
|
-
local alloc = Channel.alloc
|
|
12
|
-
|
|
13
|
-
-- Constants -----------------------------------------------------------
|
|
14
|
-
|
|
15
|
-
local clamp = math.clamp
|
|
16
|
-
local round = math.round
|
|
17
|
-
local ceil = math.ceil
|
|
18
|
-
local min = math.min
|
|
19
|
-
local max = math.max
|
|
20
|
-
|
|
21
|
-
local U32_MAX = 4294967295
|
|
22
|
-
|
|
23
|
-
-- Private -------------------------------------------------------------
|
|
24
|
-
|
|
25
|
-
local function selectIO(bytes: number): ((b: buffer, offset: number, v: number) -> (), (
|
|
26
|
-
b: buffer,
|
|
27
|
-
offset: number
|
|
28
|
-
) -> number)
|
|
29
|
-
if bytes == 1 then
|
|
30
|
-
return buffer.writeu8, buffer.readu8
|
|
31
|
-
end
|
|
32
|
-
if bytes == 2 then
|
|
33
|
-
return buffer.writeu16, buffer.readu16
|
|
34
|
-
end
|
|
35
|
-
return buffer.writeu32, buffer.readu32
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
local function selectWidth(maxInt: number): number
|
|
39
|
-
if maxInt <= 255 then
|
|
40
|
-
return 1
|
|
41
|
-
end
|
|
42
|
-
if maxInt <= 65535 then
|
|
43
|
-
return 2
|
|
44
|
-
end
|
|
45
|
-
return 4
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
-- Public --------------------------------------------------------------
|
|
49
|
-
|
|
50
|
-
local Quantized = {}
|
|
51
|
-
|
|
52
|
-
-- Shared validation and precomputation for both float and vec3 quantizers.
|
|
53
|
-
local function setup(
|
|
54
|
-
minVal: number,
|
|
55
|
-
maxVal: number,
|
|
56
|
-
precision: number
|
|
57
|
-
): (number?, number?, number?, any?, any?, number?, number?)
|
|
58
|
-
if minVal > maxVal then
|
|
59
|
-
error(`[Lync] Quantized min > max: {minVal} > {maxVal}`)
|
|
60
|
-
end
|
|
61
|
-
if precision <= 0 then
|
|
62
|
-
error(`[Lync] Quantized precision must be positive: {precision}`)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
local delta = maxVal - minVal
|
|
66
|
-
if delta == 0 then
|
|
67
|
-
return nil
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
local maxInt = min(U32_MAX, max(1, ceil(delta / precision)))
|
|
71
|
-
local bytes = selectWidth(maxInt)
|
|
72
|
-
local wfn, rfn = selectIO(bytes)
|
|
73
|
-
local invDelta = 1 / delta
|
|
74
|
-
local invMaxInt = delta / maxInt
|
|
75
|
-
|
|
76
|
-
return delta, maxInt, bytes, wfn, rfn, invDelta, invMaxInt
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
function Quantized.float(minVal: number, maxVal: number, precision: number): Codec<number>
|
|
80
|
-
local delta, maxInt, bytes, wfn, rfn, invDelta, invMaxInt = setup(minVal, maxVal, precision)
|
|
81
|
-
if not delta then
|
|
82
|
-
return table.freeze({
|
|
83
|
-
_size = 0,
|
|
84
|
-
_directWrite = function(_b: buffer, _offset: number, _value: number): () end,
|
|
85
|
-
_directRead = function(_b: buffer, _offset: number): number
|
|
86
|
-
return minVal
|
|
87
|
-
end,
|
|
88
|
-
write = function(_ch: ChannelState, _value: number): () end,
|
|
89
|
-
read = function(_src: buffer, _pos: number, _refs: { Instance }?): (number, number)
|
|
90
|
-
return minVal, 0
|
|
91
|
-
end,
|
|
92
|
-
})
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
return table.freeze({
|
|
96
|
-
_size = bytes,
|
|
97
|
-
_directWrite = function(b: buffer, offset: number, value: number): ()
|
|
98
|
-
wfn(b, offset, round(clamp((value - minVal) * invDelta, 0, 1) * maxInt))
|
|
99
|
-
end,
|
|
100
|
-
_directRead = function(b: buffer, offset: number): number
|
|
101
|
-
return rfn(b, offset) * invMaxInt + minVal
|
|
102
|
-
end,
|
|
103
|
-
write = function(ch: ChannelState, value: number): ()
|
|
104
|
-
local c = ch.cursor
|
|
105
|
-
if c + bytes > ch.size then
|
|
106
|
-
alloc(ch, bytes)
|
|
107
|
-
end
|
|
108
|
-
wfn(ch.buff, c, round(clamp((value - minVal) * invDelta, 0, 1) * maxInt))
|
|
109
|
-
ch.cursor = c + bytes
|
|
110
|
-
end,
|
|
111
|
-
read = function(src: buffer, pos: number, _refs: { Instance }?): (number, number)
|
|
112
|
-
return rfn(src, pos) * invMaxInt + minVal, bytes
|
|
113
|
-
end,
|
|
114
|
-
})
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
function Quantized.vec3(minVal: number, maxVal: number, precision: number): Codec<Vector3>
|
|
118
|
-
local delta, maxInt, compBytes, wfn, rfn, invDelta, invMaxInt = setup(minVal, maxVal, precision)
|
|
119
|
-
if not delta then
|
|
120
|
-
local val = Vector3.new(minVal, minVal, minVal)
|
|
121
|
-
return table.freeze({
|
|
122
|
-
_size = 0,
|
|
123
|
-
_directWrite = function(_b: buffer, _offset: number, _value: Vector3): () end,
|
|
124
|
-
_directRead = function(_b: buffer, _offset: number): Vector3
|
|
125
|
-
return val
|
|
126
|
-
end,
|
|
127
|
-
write = function(_ch: ChannelState, _value: Vector3): () end,
|
|
128
|
-
read = function(_src: buffer, _pos: number, _refs: { Instance }?): (Vector3, number)
|
|
129
|
-
return val, 0
|
|
130
|
-
end,
|
|
131
|
-
})
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
local totalBytes = compBytes * 3
|
|
135
|
-
local stride = compBytes
|
|
136
|
-
local stride2 = compBytes * 2
|
|
137
|
-
|
|
138
|
-
return table.freeze({
|
|
139
|
-
_size = totalBytes,
|
|
140
|
-
_directWrite = function(b: buffer, offset: number, value: Vector3): ()
|
|
141
|
-
wfn(b, offset, round(clamp((value.X - minVal) * invDelta, 0, 1) * maxInt))
|
|
142
|
-
wfn(b, offset + stride, round(clamp((value.Y - minVal) * invDelta, 0, 1) * maxInt))
|
|
143
|
-
wfn(b, offset + stride2, round(clamp((value.Z - minVal) * invDelta, 0, 1) * maxInt))
|
|
144
|
-
end,
|
|
145
|
-
_directRead = function(b: buffer, offset: number): Vector3
|
|
146
|
-
return Vector3.new(
|
|
147
|
-
rfn(b, offset) * invMaxInt + minVal,
|
|
148
|
-
rfn(b, offset + stride) * invMaxInt + minVal,
|
|
149
|
-
rfn(b, offset + stride2) * invMaxInt + minVal
|
|
150
|
-
)
|
|
151
|
-
end,
|
|
152
|
-
write = function(ch: ChannelState, value: Vector3): ()
|
|
153
|
-
local c = ch.cursor
|
|
154
|
-
if c + totalBytes > ch.size then
|
|
155
|
-
alloc(ch, totalBytes)
|
|
156
|
-
end
|
|
157
|
-
local b = ch.buff
|
|
158
|
-
wfn(b, c, round(clamp((value.X - minVal) * invDelta, 0, 1) * maxInt))
|
|
159
|
-
wfn(b, c + stride, round(clamp((value.Y - minVal) * invDelta, 0, 1) * maxInt))
|
|
160
|
-
wfn(b, c + stride2, round(clamp((value.Z - minVal) * invDelta, 0, 1) * maxInt))
|
|
161
|
-
ch.cursor = c + totalBytes
|
|
162
|
-
end,
|
|
163
|
-
read = function(src: buffer, pos: number, _refs: { Instance }?): (Vector3, number)
|
|
164
|
-
return Vector3.new(
|
|
165
|
-
rfn(src, pos) * invMaxInt + minVal,
|
|
166
|
-
rfn(src, pos + stride) * invMaxInt + minVal,
|
|
167
|
-
rfn(src, pos + stride2) * invMaxInt + minVal
|
|
168
|
-
),
|
|
169
|
-
totalBytes
|
|
170
|
-
end,
|
|
171
|
-
})
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
return table.freeze(Quantized)
|