@axpecter/lync 1.3.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 +300 -0
- package/package.json +38 -0
- package/src/Types.luau +63 -0
- package/src/api/Group.luau +126 -0
- package/src/api/Namespace.luau +226 -0
- package/src/api/Packet.luau +147 -0
- package/src/api/Query.luau +295 -0
- package/src/api/Signal.luau +224 -0
- package/src/codec/Base.luau +49 -0
- package/src/codec/composite/Array.luau +275 -0
- package/src/codec/composite/Map.luau +395 -0
- package/src/codec/composite/Optional.luau +47 -0
- package/src/codec/composite/Shared.luau +151 -0
- package/src/codec/composite/Struct.luau +440 -0
- package/src/codec/composite/Tagged.luau +222 -0
- package/src/codec/composite/Tuple.luau +143 -0
- package/src/codec/datatype/Buffer.luau +44 -0
- package/src/codec/datatype/CFrame.luau +51 -0
- package/src/codec/datatype/Color.luau +22 -0
- package/src/codec/datatype/Instance.luau +48 -0
- package/src/codec/datatype/IntVector.luau +25 -0
- package/src/codec/datatype/NumberRange.luau +14 -0
- package/src/codec/datatype/Ray.luau +27 -0
- package/src/codec/datatype/Rect.luau +21 -0
- package/src/codec/datatype/Region.luau +58 -0
- package/src/codec/datatype/Sequence.luau +129 -0
- package/src/codec/datatype/String.luau +87 -0
- package/src/codec/datatype/UDim.luau +27 -0
- package/src/codec/datatype/Vector.luau +25 -0
- package/src/codec/meta/Auto.luau +353 -0
- package/src/codec/meta/Bitfield.luau +191 -0
- package/src/codec/meta/Custom.luau +27 -0
- package/src/codec/meta/Enum.luau +80 -0
- package/src/codec/meta/Nothing.luau +9 -0
- package/src/codec/meta/Quantized.luau +170 -0
- package/src/codec/meta/Unknown.luau +35 -0
- package/src/codec/primitive/Bool.luau +30 -0
- package/src/codec/primitive/Float16.luau +111 -0
- package/src/codec/primitive/Number.luau +48 -0
- package/src/codec/primitive/Varint.luau +76 -0
- package/src/index.d.ts +279 -0
- package/src/init.luau +161 -0
- package/src/internal/Baseline.luau +41 -0
- package/src/internal/Channel.luau +235 -0
- package/src/internal/Middleware.luau +109 -0
- package/src/internal/Pool.luau +68 -0
- package/src/internal/Registry.luau +146 -0
- package/src/transport/Bridge.luau +66 -0
- package/src/transport/Client.luau +151 -0
- package/src/transport/Gate.luau +222 -0
- package/src/transport/Reader.luau +175 -0
- package/src/transport/Server.luau +364 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!native
|
|
3
|
+
-- Positional ordered codec. Like struct but indexed, not keyed.
|
|
4
|
+
|
|
5
|
+
local Channel = require (script.Parent.Parent.Parent.internal.Channel)
|
|
6
|
+
local alloc = Channel.alloc
|
|
7
|
+
local Types = require (script.Parent.Parent.Parent.Types)
|
|
8
|
+
|
|
9
|
+
type ChannelState = Types.ChannelState
|
|
10
|
+
type Codec<T> = Types.Codec<T>
|
|
11
|
+
|
|
12
|
+
-- Public -----------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
local Tuple = {}
|
|
15
|
+
|
|
16
|
+
function Tuple.define (...: Codec<any>): Codec<{ any }>
|
|
17
|
+
local codecs = { ... }
|
|
18
|
+
local count = #codecs
|
|
19
|
+
if count == 0 then
|
|
20
|
+
error ("[Lync] Tuple requires at least one codec")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
table.freeze (codecs)
|
|
24
|
+
|
|
25
|
+
local canDirect = true
|
|
26
|
+
local totalSize: number = 0
|
|
27
|
+
local directWrites = table.create (count) :: { any }
|
|
28
|
+
local directReads = table.create (count) :: { any }
|
|
29
|
+
local fieldSizes = table.create (count) :: { number }
|
|
30
|
+
|
|
31
|
+
for i = 1, count do
|
|
32
|
+
local codec = codecs[i] :: any
|
|
33
|
+
local size = codec._size
|
|
34
|
+
local dw = codec._directWrite
|
|
35
|
+
local dr = codec._directRead
|
|
36
|
+
|
|
37
|
+
if size and dw and dr then
|
|
38
|
+
fieldSizes[i] = size
|
|
39
|
+
directWrites[i] = dw
|
|
40
|
+
directReads[i] = dr
|
|
41
|
+
totalSize += size
|
|
42
|
+
else
|
|
43
|
+
canDirect = false
|
|
44
|
+
if size then
|
|
45
|
+
totalSize += size
|
|
46
|
+
else
|
|
47
|
+
totalSize = nil :: any
|
|
48
|
+
end
|
|
49
|
+
break
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
-- Recompute totalSize for generic path if direct failed partway
|
|
54
|
+
if not canDirect then
|
|
55
|
+
totalSize = 0 :: any
|
|
56
|
+
for i = 1, count do
|
|
57
|
+
local size = (codecs[i] :: any)._size
|
|
58
|
+
if size then
|
|
59
|
+
totalSize = (totalSize :: number) + size
|
|
60
|
+
else
|
|
61
|
+
totalSize = nil :: any
|
|
62
|
+
break
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
if canDirect then
|
|
68
|
+
table.freeze (directWrites)
|
|
69
|
+
table.freeze (directReads)
|
|
70
|
+
table.freeze (fieldSizes)
|
|
71
|
+
|
|
72
|
+
local function directWriteBody (b: buffer, c: number, value: { any }): ()
|
|
73
|
+
for i = 1, count do
|
|
74
|
+
directWrites[i] (b, c, value[i])
|
|
75
|
+
c += fieldSizes[i]
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
local function directReadBody (b: buffer, pos: number): { any }
|
|
80
|
+
local result = table.create (count)
|
|
81
|
+
local c = pos
|
|
82
|
+
for i = 1, count do
|
|
83
|
+
result[i] = directReads[i] (b, c)
|
|
84
|
+
c += fieldSizes[i]
|
|
85
|
+
end
|
|
86
|
+
return result
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
return table.freeze ({
|
|
90
|
+
_size = totalSize,
|
|
91
|
+
_directWrite = directWriteBody,
|
|
92
|
+
_directRead = directReadBody,
|
|
93
|
+
write = function (ch: ChannelState, value: { any }): ()
|
|
94
|
+
local c = ch.cursor
|
|
95
|
+
if c + totalSize > ch.size then
|
|
96
|
+
alloc (ch, totalSize)
|
|
97
|
+
end
|
|
98
|
+
directWriteBody (ch.buff, c, value)
|
|
99
|
+
ch.cursor = c + totalSize
|
|
100
|
+
end,
|
|
101
|
+
read = function (src: buffer, pos: number, _refs: { Instance }?): ({ any }, number)
|
|
102
|
+
return directReadBody (src, pos), totalSize
|
|
103
|
+
end,
|
|
104
|
+
})
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
local writeFns = table.create (count) :: { any }
|
|
108
|
+
local readFns = table.create (count) :: { any }
|
|
109
|
+
for i = 1, count do
|
|
110
|
+
writeFns[i] = codecs[i].write
|
|
111
|
+
readFns[i] = codecs[i].read
|
|
112
|
+
end
|
|
113
|
+
table.freeze (writeFns)
|
|
114
|
+
table.freeze (readFns)
|
|
115
|
+
|
|
116
|
+
local hasFixedTotal = totalSize ~= nil
|
|
117
|
+
|
|
118
|
+
return table.freeze ({
|
|
119
|
+
_size = totalSize,
|
|
120
|
+
write = function (ch: ChannelState, value: { any }): ()
|
|
121
|
+
if hasFixedTotal then
|
|
122
|
+
alloc (ch, totalSize :: number)
|
|
123
|
+
end
|
|
124
|
+
for i = 1, count do
|
|
125
|
+
writeFns[i] (ch, value[i])
|
|
126
|
+
end
|
|
127
|
+
end,
|
|
128
|
+
read = function (src: buffer, pos: number, refs: { Instance }?): ({ any }, number)
|
|
129
|
+
local result = table.create (count)
|
|
130
|
+
local absPos = pos
|
|
131
|
+
|
|
132
|
+
for i = 1, count do
|
|
133
|
+
local value, n = readFns[i] (src, absPos, refs)
|
|
134
|
+
result[i] = value
|
|
135
|
+
absPos += n
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
return result, absPos - pos
|
|
139
|
+
end,
|
|
140
|
+
})
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
return table.freeze (Tuple)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!native
|
|
3
|
+
-- Raw buffer codec with varint length prefix.
|
|
4
|
+
|
|
5
|
+
local Channel = require (script.Parent.Parent.Parent.internal.Channel)
|
|
6
|
+
local alloc = Channel.alloc
|
|
7
|
+
local Types = require (script.Parent.Parent.Parent.Types)
|
|
8
|
+
local Varint = require (script.Parent.Parent.primitive.Varint)
|
|
9
|
+
|
|
10
|
+
type ChannelState = Types.ChannelState
|
|
11
|
+
|
|
12
|
+
-- Public -----------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
local Buffer = {}
|
|
15
|
+
|
|
16
|
+
Buffer.buff = table.freeze ({
|
|
17
|
+
write = function (ch: ChannelState, value: buffer): ()
|
|
18
|
+
local len = buffer.len (value)
|
|
19
|
+
Varint.write (ch, len)
|
|
20
|
+
local c = ch.cursor
|
|
21
|
+
if c + len > ch.size then
|
|
22
|
+
alloc (ch, len)
|
|
23
|
+
end
|
|
24
|
+
buffer.copy (ch.buff, c, value, 0, len)
|
|
25
|
+
ch.cursor = c + len
|
|
26
|
+
end,
|
|
27
|
+
read = function (src: buffer, pos: number, _refs: { Instance }?): (buffer, number)
|
|
28
|
+
local len, lenBytes = Varint.read (src, pos)
|
|
29
|
+
if len == 0 then
|
|
30
|
+
return buffer.create (0), lenBytes
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
local remaining = buffer.len (src) - pos - lenBytes
|
|
34
|
+
if len > remaining then
|
|
35
|
+
error (`[Lync] Buffer length exceeds remaining: {len} > {remaining}`)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
local out = buffer.create (len)
|
|
39
|
+
buffer.copy (out, 0, src, pos + lenBytes, len)
|
|
40
|
+
return out, lenBytes + len
|
|
41
|
+
end,
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
return table.freeze (Buffer)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!native
|
|
3
|
+
-- Axis-angle CFrame codec. Zero axis at identity for clean deltas.
|
|
4
|
+
|
|
5
|
+
local Base = require (script.Parent.Parent.Base)
|
|
6
|
+
|
|
7
|
+
-- f32 machine epsilon * 2 to absorb round-trip noise.
|
|
8
|
+
local EPSILON = 2.4e-7
|
|
9
|
+
local sqrt = math.sqrt
|
|
10
|
+
|
|
11
|
+
local function writeCFrame (b: buffer, c: number, value: CFrame): ()
|
|
12
|
+
local position = value.Position
|
|
13
|
+
local axis, angle = value:ToAxisAngle ()
|
|
14
|
+
|
|
15
|
+
buffer.writef32 (b, c, position.X)
|
|
16
|
+
buffer.writef32 (b, c + 4, position.Y)
|
|
17
|
+
buffer.writef32 (b, c + 8, position.Z)
|
|
18
|
+
|
|
19
|
+
if angle < EPSILON then
|
|
20
|
+
buffer.writef32 (b, c + 12, 0)
|
|
21
|
+
buffer.writef32 (b, c + 16, 0)
|
|
22
|
+
buffer.writef32 (b, c + 20, 0)
|
|
23
|
+
else
|
|
24
|
+
buffer.writef32 (b, c + 12, axis.X * angle)
|
|
25
|
+
buffer.writef32 (b, c + 16, axis.Y * angle)
|
|
26
|
+
buffer.writef32 (b, c + 20, axis.Z * angle)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
local function readCFrame (b: buffer, pos: number): CFrame
|
|
31
|
+
local px = buffer.readf32 (b, pos)
|
|
32
|
+
local py = buffer.readf32 (b, pos + 4)
|
|
33
|
+
local pz = buffer.readf32 (b, pos + 8)
|
|
34
|
+
local rx = buffer.readf32 (b, pos + 12)
|
|
35
|
+
local ry = buffer.readf32 (b, pos + 16)
|
|
36
|
+
local rz = buffer.readf32 (b, pos + 20)
|
|
37
|
+
|
|
38
|
+
local angle = sqrt (rx * rx + ry * ry + rz * rz)
|
|
39
|
+
local origin = CFrame.new (px, py, pz)
|
|
40
|
+
|
|
41
|
+
if angle < EPSILON then
|
|
42
|
+
return origin
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
local inv = 1 / angle
|
|
46
|
+
return origin * CFrame.fromAxisAngle (Vector3.new (rx * inv, ry * inv, rz * inv), angle)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
return table.freeze ({
|
|
50
|
+
cframe = Base.define (24, writeCFrame, readCFrame),
|
|
51
|
+
})
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!native
|
|
3
|
+
-- Color3 codec. 3 bytes, 0-255 per channel, clamped.
|
|
4
|
+
|
|
5
|
+
local Base = require (script.Parent.Parent.Base)
|
|
6
|
+
|
|
7
|
+
local round = math.round
|
|
8
|
+
local clamp = math.clamp
|
|
9
|
+
|
|
10
|
+
return table.freeze ({
|
|
11
|
+
color3 = Base.define (3, function (b: buffer, o: number, v: Color3): ()
|
|
12
|
+
buffer.writeu8 (b, o, round (clamp (v.R, 0, 1) * 255))
|
|
13
|
+
buffer.writeu8 (b, o + 1, round (clamp (v.G, 0, 1) * 255))
|
|
14
|
+
buffer.writeu8 (b, o + 2, round (clamp (v.B, 0, 1) * 255))
|
|
15
|
+
end, function (b: buffer, o: number): Color3
|
|
16
|
+
return Color3.fromRGB (
|
|
17
|
+
buffer.readu8 (b, o),
|
|
18
|
+
buffer.readu8 (b, o + 1),
|
|
19
|
+
buffer.readu8 (b, o + 2)
|
|
20
|
+
)
|
|
21
|
+
end),
|
|
22
|
+
})
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!native
|
|
3
|
+
-- Instance codec via sidecar reference array.
|
|
4
|
+
|
|
5
|
+
local Channel = require (script.Parent.Parent.Parent.internal.Channel)
|
|
6
|
+
local alloc = Channel.alloc
|
|
7
|
+
local Types = require (script.Parent.Parent.Parent.Types)
|
|
8
|
+
|
|
9
|
+
type ChannelState = Types.ChannelState
|
|
10
|
+
|
|
11
|
+
-- Public -----------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
local InstanceCodec = {}
|
|
14
|
+
|
|
15
|
+
InstanceCodec.inst = table.freeze ({
|
|
16
|
+
_size = 2,
|
|
17
|
+
write = function (ch: ChannelState, value: Instance): ()
|
|
18
|
+
local refs = ch.refs
|
|
19
|
+
local idx = #refs + 1
|
|
20
|
+
if idx > 65535 then
|
|
21
|
+
error (`[Lync] Instance ref overflow: {idx} exceeds u16 max`)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
refs[idx] = value
|
|
25
|
+
|
|
26
|
+
local c = ch.cursor
|
|
27
|
+
if c + 2 > ch.size then
|
|
28
|
+
alloc (ch, 2)
|
|
29
|
+
end
|
|
30
|
+
buffer.writeu16 (ch.buff, c, idx)
|
|
31
|
+
ch.cursor = c + 2
|
|
32
|
+
end,
|
|
33
|
+
read = function (src: buffer, pos: number, refs: { Instance }?): (Instance, number)
|
|
34
|
+
local idx = buffer.readu16 (src, pos)
|
|
35
|
+
if not refs then
|
|
36
|
+
error ("[Lync] Instance read requires refs array")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
local inst = refs[idx]
|
|
40
|
+
if not inst then
|
|
41
|
+
error (`[Lync] Instance ref index out of bounds: {idx}`)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
return inst, 2
|
|
45
|
+
end,
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
return table.freeze (InstanceCodec)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!native
|
|
3
|
+
-- Vector2int16 (4B) and Vector3int16 (6B) codecs.
|
|
4
|
+
|
|
5
|
+
local Base = require (script.Parent.Parent.Base)
|
|
6
|
+
|
|
7
|
+
return table.freeze ({
|
|
8
|
+
vec2int16 = Base.define (4, function (b: buffer, o: number, v: Vector2int16): ()
|
|
9
|
+
buffer.writei16 (b, o, v.X)
|
|
10
|
+
buffer.writei16 (b, o + 2, v.Y)
|
|
11
|
+
end, function (b: buffer, o: number): Vector2int16
|
|
12
|
+
return Vector2int16.new (buffer.readi16 (b, o), buffer.readi16 (b, o + 2))
|
|
13
|
+
end),
|
|
14
|
+
vec3int16 = Base.define (6, function (b: buffer, o: number, v: Vector3int16): ()
|
|
15
|
+
buffer.writei16 (b, o, v.X)
|
|
16
|
+
buffer.writei16 (b, o + 2, v.Y)
|
|
17
|
+
buffer.writei16 (b, o + 4, v.Z)
|
|
18
|
+
end, function (b: buffer, o: number): Vector3int16
|
|
19
|
+
return Vector3int16.new (
|
|
20
|
+
buffer.readi16 (b, o),
|
|
21
|
+
buffer.readi16 (b, o + 2),
|
|
22
|
+
buffer.readi16 (b, o + 4)
|
|
23
|
+
)
|
|
24
|
+
end),
|
|
25
|
+
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!native
|
|
3
|
+
-- NumberRange codec. 8 bytes: min f32 + max f32.
|
|
4
|
+
|
|
5
|
+
local Base = require (script.Parent.Parent.Base)
|
|
6
|
+
|
|
7
|
+
return table.freeze ({
|
|
8
|
+
numberRange = Base.define (8, function (b: buffer, o: number, v: NumberRange): ()
|
|
9
|
+
buffer.writef32 (b, o, v.Min)
|
|
10
|
+
buffer.writef32 (b, o + 4, v.Max)
|
|
11
|
+
end, function (b: buffer, o: number): NumberRange
|
|
12
|
+
return NumberRange.new (buffer.readf32 (b, o), buffer.readf32 (b, o + 4))
|
|
13
|
+
end),
|
|
14
|
+
})
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!native
|
|
3
|
+
-- Ray codec. 24 bytes: origin vec3 + direction vec3.
|
|
4
|
+
|
|
5
|
+
local Base = require (script.Parent.Parent.Base)
|
|
6
|
+
|
|
7
|
+
return table.freeze ({
|
|
8
|
+
ray = Base.define (24, function (b: buffer, o: number, v: Ray): ()
|
|
9
|
+
local origin = v.Origin
|
|
10
|
+
local direction = v.Direction
|
|
11
|
+
buffer.writef32 (b, o, origin.X)
|
|
12
|
+
buffer.writef32 (b, o + 4, origin.Y)
|
|
13
|
+
buffer.writef32 (b, o + 8, origin.Z)
|
|
14
|
+
buffer.writef32 (b, o + 12, direction.X)
|
|
15
|
+
buffer.writef32 (b, o + 16, direction.Y)
|
|
16
|
+
buffer.writef32 (b, o + 20, direction.Z)
|
|
17
|
+
end, function (b: buffer, o: number): Ray
|
|
18
|
+
return Ray.new (
|
|
19
|
+
Vector3.new (buffer.readf32 (b, o), buffer.readf32 (b, o + 4), buffer.readf32 (b, o + 8)),
|
|
20
|
+
Vector3.new (
|
|
21
|
+
buffer.readf32 (b, o + 12),
|
|
22
|
+
buffer.readf32 (b, o + 16),
|
|
23
|
+
buffer.readf32 (b, o + 20)
|
|
24
|
+
)
|
|
25
|
+
)
|
|
26
|
+
end),
|
|
27
|
+
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!native
|
|
3
|
+
-- Rect codec. 16 bytes: 4x f32.
|
|
4
|
+
|
|
5
|
+
local Base = require (script.Parent.Parent.Base)
|
|
6
|
+
|
|
7
|
+
return table.freeze ({
|
|
8
|
+
rect = Base.define (16, function (b: buffer, o: number, v: Rect): ()
|
|
9
|
+
buffer.writef32 (b, o, v.Min.X)
|
|
10
|
+
buffer.writef32 (b, o + 4, v.Min.Y)
|
|
11
|
+
buffer.writef32 (b, o + 8, v.Max.X)
|
|
12
|
+
buffer.writef32 (b, o + 12, v.Max.Y)
|
|
13
|
+
end, function (b: buffer, o: number): Rect
|
|
14
|
+
return Rect.new (
|
|
15
|
+
buffer.readf32 (b, o),
|
|
16
|
+
buffer.readf32 (b, o + 4),
|
|
17
|
+
buffer.readf32 (b, o + 8),
|
|
18
|
+
buffer.readf32 (b, o + 12)
|
|
19
|
+
)
|
|
20
|
+
end),
|
|
21
|
+
})
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!native
|
|
3
|
+
-- Region3 (24B) and Region3int16 (12B) codecs.
|
|
4
|
+
|
|
5
|
+
local Base = require (script.Parent.Parent.Base)
|
|
6
|
+
|
|
7
|
+
local function writeRegion3 (b: buffer, o: number, v: Region3): ()
|
|
8
|
+
local cf = v.CFrame
|
|
9
|
+
local size = v.Size
|
|
10
|
+
local halfSize = size * 0.5
|
|
11
|
+
local pos = cf.Position
|
|
12
|
+
local minV = pos - halfSize
|
|
13
|
+
local maxV = pos + halfSize
|
|
14
|
+
buffer.writef32 (b, o, minV.X)
|
|
15
|
+
buffer.writef32 (b, o + 4, minV.Y)
|
|
16
|
+
buffer.writef32 (b, o + 8, minV.Z)
|
|
17
|
+
buffer.writef32 (b, o + 12, maxV.X)
|
|
18
|
+
buffer.writef32 (b, o + 16, maxV.Y)
|
|
19
|
+
buffer.writef32 (b, o + 20, maxV.Z)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
local function readRegion3 (b: buffer, o: number): Region3
|
|
23
|
+
return Region3.new (
|
|
24
|
+
Vector3.new (buffer.readf32 (b, o), buffer.readf32 (b, o + 4), buffer.readf32 (b, o + 8)),
|
|
25
|
+
Vector3.new (
|
|
26
|
+
buffer.readf32 (b, o + 12),
|
|
27
|
+
buffer.readf32 (b, o + 16),
|
|
28
|
+
buffer.readf32 (b, o + 20)
|
|
29
|
+
)
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
return table.freeze ({
|
|
34
|
+
region3 = Base.define (24, writeRegion3, readRegion3),
|
|
35
|
+
region3int16 = Base.define (12, function (b: buffer, o: number, v: Region3int16): ()
|
|
36
|
+
local minV = v.Min
|
|
37
|
+
local maxV = v.Max
|
|
38
|
+
buffer.writei16 (b, o, minV.X)
|
|
39
|
+
buffer.writei16 (b, o + 2, minV.Y)
|
|
40
|
+
buffer.writei16 (b, o + 4, minV.Z)
|
|
41
|
+
buffer.writei16 (b, o + 6, maxV.X)
|
|
42
|
+
buffer.writei16 (b, o + 8, maxV.Y)
|
|
43
|
+
buffer.writei16 (b, o + 10, maxV.Z)
|
|
44
|
+
end, function (b: buffer, o: number): Region3int16
|
|
45
|
+
return Region3int16.new (
|
|
46
|
+
Vector3int16.new (
|
|
47
|
+
buffer.readi16 (b, o),
|
|
48
|
+
buffer.readi16 (b, o + 2),
|
|
49
|
+
buffer.readi16 (b, o + 4)
|
|
50
|
+
),
|
|
51
|
+
Vector3int16.new (
|
|
52
|
+
buffer.readi16 (b, o + 6),
|
|
53
|
+
buffer.readi16 (b, o + 8),
|
|
54
|
+
buffer.readi16 (b, o + 10)
|
|
55
|
+
)
|
|
56
|
+
)
|
|
57
|
+
end),
|
|
58
|
+
})
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!native
|
|
3
|
+
-- NumberSequence and ColorSequence codecs with varint length prefix.
|
|
4
|
+
|
|
5
|
+
local Channel = require (script.Parent.Parent.Parent.internal.Channel)
|
|
6
|
+
local alloc = Channel.alloc
|
|
7
|
+
local Types = require (script.Parent.Parent.Parent.Types)
|
|
8
|
+
local Varint = require (script.Parent.Parent.primitive.Varint)
|
|
9
|
+
|
|
10
|
+
type ChannelState = Types.ChannelState
|
|
11
|
+
|
|
12
|
+
type ChannelState = Types.ChannelState
|
|
13
|
+
|
|
14
|
+
-- Constants --------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
local NS_STRIDE = 12
|
|
17
|
+
local CS_STRIDE = 7
|
|
18
|
+
|
|
19
|
+
local round = math.round
|
|
20
|
+
local clamp = math.clamp
|
|
21
|
+
|
|
22
|
+
-- Public -----------------------------------------------------------------
|
|
23
|
+
|
|
24
|
+
local Sequence = {}
|
|
25
|
+
|
|
26
|
+
Sequence.numberSequence = table.freeze ({
|
|
27
|
+
write = function (ch: ChannelState, value: NumberSequence): ()
|
|
28
|
+
local keypoints = value.Keypoints
|
|
29
|
+
local count = #keypoints
|
|
30
|
+
Varint.write (ch, count)
|
|
31
|
+
|
|
32
|
+
if count == 0 then
|
|
33
|
+
return
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
local totalBytes = count * NS_STRIDE
|
|
37
|
+
local c = ch.cursor
|
|
38
|
+
if c + totalBytes > ch.size then
|
|
39
|
+
alloc (ch, totalBytes)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
local b = ch.buff
|
|
43
|
+
for i = 1, count do
|
|
44
|
+
local kp = keypoints[i]
|
|
45
|
+
buffer.writef32 (b, c, kp.Time)
|
|
46
|
+
buffer.writef32 (b, c + 4, kp.Value)
|
|
47
|
+
buffer.writef32 (b, c + 8, kp.Envelope)
|
|
48
|
+
c += NS_STRIDE
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
ch.cursor = c
|
|
52
|
+
end,
|
|
53
|
+
read = function (src: buffer, pos: number, _refs: { Instance }?): (NumberSequence, number)
|
|
54
|
+
local count, lenBytes = Varint.read (src, pos)
|
|
55
|
+
local absPos = pos + lenBytes
|
|
56
|
+
|
|
57
|
+
if count == 0 then
|
|
58
|
+
return NumberSequence.new (0), lenBytes
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
local keypoints = table.create (count)
|
|
62
|
+
for i = 1, count do
|
|
63
|
+
keypoints[i] = NumberSequenceKeypoint.new (
|
|
64
|
+
buffer.readf32 (src, absPos),
|
|
65
|
+
buffer.readf32 (src, absPos + 4),
|
|
66
|
+
buffer.readf32 (src, absPos + 8)
|
|
67
|
+
)
|
|
68
|
+
absPos += NS_STRIDE
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
return NumberSequence.new (keypoints), absPos - pos
|
|
72
|
+
end,
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
Sequence.colorSequence = table.freeze ({
|
|
76
|
+
write = function (ch: ChannelState, value: ColorSequence): ()
|
|
77
|
+
local keypoints = value.Keypoints
|
|
78
|
+
local count = #keypoints
|
|
79
|
+
Varint.write (ch, count)
|
|
80
|
+
|
|
81
|
+
if count == 0 then
|
|
82
|
+
return
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
local totalBytes = count * CS_STRIDE
|
|
86
|
+
local c = ch.cursor
|
|
87
|
+
if c + totalBytes > ch.size then
|
|
88
|
+
alloc (ch, totalBytes)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
local b = ch.buff
|
|
92
|
+
for i = 1, count do
|
|
93
|
+
local kp = keypoints[i]
|
|
94
|
+
local color = kp.Value
|
|
95
|
+
buffer.writef32 (b, c, kp.Time)
|
|
96
|
+
buffer.writeu8 (b, c + 4, round (clamp (color.R, 0, 1) * 255))
|
|
97
|
+
buffer.writeu8 (b, c + 5, round (clamp (color.G, 0, 1) * 255))
|
|
98
|
+
buffer.writeu8 (b, c + 6, round (clamp (color.B, 0, 1) * 255))
|
|
99
|
+
c += CS_STRIDE
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
ch.cursor = c
|
|
103
|
+
end,
|
|
104
|
+
read = function (src: buffer, pos: number, _refs: { Instance }?): (ColorSequence, number)
|
|
105
|
+
local count, lenBytes = Varint.read (src, pos)
|
|
106
|
+
local absPos = pos + lenBytes
|
|
107
|
+
|
|
108
|
+
if count == 0 then
|
|
109
|
+
return ColorSequence.new (Color3.new ()), lenBytes
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
local keypoints = table.create (count)
|
|
113
|
+
for i = 1, count do
|
|
114
|
+
keypoints[i] = ColorSequenceKeypoint.new (
|
|
115
|
+
buffer.readf32 (src, absPos),
|
|
116
|
+
Color3.fromRGB (
|
|
117
|
+
buffer.readu8 (src, absPos + 4),
|
|
118
|
+
buffer.readu8 (src, absPos + 5),
|
|
119
|
+
buffer.readu8 (src, absPos + 6)
|
|
120
|
+
)
|
|
121
|
+
)
|
|
122
|
+
absPos += CS_STRIDE
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
return ColorSequence.new (keypoints), absPos - pos
|
|
126
|
+
end,
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
return table.freeze (Sequence)
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!native
|
|
3
|
+
-- Variable-length string codec with varint length prefix.
|
|
4
|
+
|
|
5
|
+
local Channel = require (script.Parent.Parent.Parent.internal.Channel)
|
|
6
|
+
local alloc = Channel.alloc
|
|
7
|
+
local Types = require (script.Parent.Parent.Parent.Types)
|
|
8
|
+
local Varint = require (script.Parent.Parent.primitive.Varint)
|
|
9
|
+
|
|
10
|
+
type ChannelState = Types.ChannelState
|
|
11
|
+
|
|
12
|
+
-- Constants --------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
local floor = math.floor
|
|
15
|
+
|
|
16
|
+
-- Public -----------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
local String = {}
|
|
19
|
+
|
|
20
|
+
String.string = table.freeze ({
|
|
21
|
+
write = function (ch: ChannelState, value: string): ()
|
|
22
|
+
local len = #value
|
|
23
|
+
|
|
24
|
+
if len < 128 then
|
|
25
|
+
local total = 1 + len
|
|
26
|
+
local c = ch.cursor
|
|
27
|
+
if c + total > ch.size then
|
|
28
|
+
alloc (ch, total)
|
|
29
|
+
end
|
|
30
|
+
local b = ch.buff
|
|
31
|
+
buffer.writeu8 (b, c, len)
|
|
32
|
+
if len > 0 then
|
|
33
|
+
buffer.writestring (b, c + 1, value)
|
|
34
|
+
end
|
|
35
|
+
ch.cursor = c + total
|
|
36
|
+
else
|
|
37
|
+
Varint.write (ch, len)
|
|
38
|
+
local c = ch.cursor
|
|
39
|
+
if c + len > ch.size then
|
|
40
|
+
alloc (ch, len)
|
|
41
|
+
end
|
|
42
|
+
buffer.writestring (ch.buff, c, value)
|
|
43
|
+
ch.cursor = c + len
|
|
44
|
+
end
|
|
45
|
+
end,
|
|
46
|
+
read = function (src: buffer, pos: number, _refs: { Instance }?): (string, number)
|
|
47
|
+
local len, lenBytes = Varint.read (src, pos)
|
|
48
|
+
if len == 0 then
|
|
49
|
+
return "", lenBytes
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
local remaining = buffer.len (src) - pos - lenBytes
|
|
53
|
+
if len > remaining then
|
|
54
|
+
error (`[Lync] String length exceeds buffer: {len} > {remaining}`)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
return buffer.readstring (src, pos + lenBytes, len), lenBytes + len
|
|
58
|
+
end,
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
function String.bounded (maxLength: number): any
|
|
62
|
+
if maxLength <= 0 or maxLength ~= floor (maxLength) then
|
|
63
|
+
error (`[Lync] boundedString maxLength must be a positive integer, got {maxLength}`)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
return table.freeze ({
|
|
67
|
+
write = String.string.write,
|
|
68
|
+
read = function (src: buffer, pos: number, _refs: { Instance }?): (string, number)
|
|
69
|
+
local len, lenBytes = Varint.read (src, pos)
|
|
70
|
+
if len > maxLength then
|
|
71
|
+
error (`[Lync] String length {len} exceeds max {maxLength}`)
|
|
72
|
+
end
|
|
73
|
+
if len == 0 then
|
|
74
|
+
return "", lenBytes
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
local remaining = buffer.len (src) - pos - lenBytes
|
|
78
|
+
if len > remaining then
|
|
79
|
+
error (`[Lync] String length exceeds buffer: {len} > {remaining}`)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
return buffer.readstring (src, pos + lenBytes, len), lenBytes + len
|
|
83
|
+
end,
|
|
84
|
+
})
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
return table.freeze (String)
|