@axpecter/lync 2.1.2 → 2.2.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/README.md +241 -349
- package/package.json +1 -1
- package/src/Types.luau +53 -13
- package/src/api/Group.luau +41 -51
- package/src/api/Packet.luau +163 -152
- package/src/api/Query.luau +224 -211
- package/src/api/Scope.luau +36 -38
- package/src/api/Signal.luau +68 -94
- package/src/codec/Base.luau +43 -23
- package/src/codec/composite/Array.luau +161 -152
- package/src/codec/composite/Map.luau +37 -53
- package/src/codec/composite/Optional.luau +15 -21
- package/src/codec/composite/Shared.luau +78 -41
- package/src/codec/composite/Struct.luau +64 -125
- package/src/codec/composite/Tagged.luau +15 -25
- package/src/codec/composite/Tuple.luau +15 -20
- package/src/codec/datatype/Buffer.luau +44 -51
- package/src/codec/datatype/CFrame.luau +72 -104
- package/src/codec/datatype/Color.luau +14 -10
- package/src/codec/datatype/Instance.luau +32 -42
- package/src/codec/datatype/IntVector.luau +24 -22
- package/src/codec/datatype/NumberRange.luau +21 -12
- package/src/codec/datatype/Ray.luau +13 -7
- package/src/codec/datatype/Rect.luau +13 -7
- package/src/codec/datatype/Region.luau +25 -22
- package/src/codec/datatype/Sequence.luau +144 -118
- package/src/codec/datatype/String.luau +29 -59
- package/src/codec/datatype/UDim.luau +29 -30
- package/src/codec/datatype/Vector.luau +89 -105
- package/src/codec/meta/Auto.luau +194 -246
- package/src/codec/meta/Bitfield.luau +37 -36
- package/src/codec/meta/Custom.luau +10 -10
- package/src/codec/meta/Enum.luau +8 -11
- package/src/codec/meta/Float.luau +16 -20
- package/src/codec/meta/Nothing.luau +2 -2
- package/src/codec/meta/Unknown.luau +22 -32
- package/src/codec/primitive/Bool.luau +9 -5
- package/src/codec/primitive/Float16.luau +13 -23
- package/src/codec/primitive/Int.luau +20 -28
- package/src/codec/primitive/Number.luau +6 -10
- package/src/codec/primitive/Signed.luau +32 -0
- package/src/codec/primitive/Varint.luau +59 -28
- package/src/index.d.ts +8 -2
- package/src/init.luau +133 -143
- package/src/internal/Baseline.luau +17 -18
- package/src/internal/Channel.luau +143 -212
- package/src/internal/Middleware.luau +37 -47
- package/src/internal/Pool.luau +10 -10
- package/src/internal/Registry.luau +38 -34
- package/src/internal/Transport.luau +28 -0
- package/src/internal/Util.luau +26 -0
- package/src/transport/Bridge.luau +32 -24
- package/src/transport/Client.luau +51 -53
- package/src/transport/Gate.luau +183 -113
- package/src/transport/Reader.luau +95 -66
- package/src/transport/Server.luau +130 -125
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
--!strict
|
|
2
2
|
--!optimize 2
|
|
3
|
-
-- Positional ordered codec. Like struct but indexed
|
|
3
|
+
-- Positional ordered codec. Like struct but indexed.
|
|
4
4
|
|
|
5
5
|
local Base = require(script.Parent.Parent.Base)
|
|
6
6
|
local Types = require(script.Parent.Parent.Parent.Types)
|
|
7
7
|
|
|
8
|
-
-- Private
|
|
8
|
+
-- Private ----------------------------------------------------------------
|
|
9
9
|
|
|
10
10
|
local alloc = Base.alloc
|
|
11
11
|
|
|
12
|
-
-- Public
|
|
12
|
+
-- Public -----------------------------------------------------------------
|
|
13
13
|
|
|
14
14
|
local Tuple = {}
|
|
15
15
|
|
|
@@ -20,46 +20,41 @@ function Tuple.define(...: Types.InternalCodec<any>): Types.InternalCodec<any>
|
|
|
20
20
|
error("[Lync] Lync.tuple: requires at least one codec")
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
local allDirect = true
|
|
25
|
-
local totalSize = 0
|
|
26
|
-
local hasUnknown = false
|
|
27
|
-
|
|
23
|
+
local allDirect, totalSize, hasUnknown = true, 0, false
|
|
28
24
|
for i = 1, count do
|
|
29
|
-
local c = codecs[i]
|
|
25
|
+
local c = codecs[i]
|
|
30
26
|
if c._hasUnknown then
|
|
31
27
|
hasUnknown = true
|
|
32
28
|
end
|
|
33
29
|
if not c._size or not c._directWrite or not c._directRead then
|
|
34
30
|
allDirect = false
|
|
35
|
-
|
|
31
|
+
elseif allDirect then
|
|
36
32
|
totalSize += c._size
|
|
37
33
|
end
|
|
38
34
|
end
|
|
39
|
-
|
|
40
35
|
table.freeze(codecs)
|
|
41
36
|
|
|
42
37
|
if allDirect then
|
|
43
|
-
-- Build precomputed offsets
|
|
44
38
|
local offsets = table.create(count)
|
|
45
39
|
local directWrites = table.create(count)
|
|
46
40
|
local directReads = table.create(count)
|
|
47
41
|
local cursor = 0
|
|
48
42
|
|
|
49
43
|
for i = 1, count do
|
|
50
|
-
local c = codecs[i]
|
|
44
|
+
local c = codecs[i]
|
|
51
45
|
offsets[i] = cursor
|
|
52
46
|
directWrites[i] = c._directWrite
|
|
53
47
|
directReads[i] = c._directRead
|
|
54
|
-
cursor += c._size
|
|
48
|
+
cursor += c._size :: number
|
|
55
49
|
end
|
|
56
|
-
|
|
57
50
|
table.freeze(offsets)
|
|
58
51
|
table.freeze(directWrites)
|
|
59
52
|
table.freeze(directReads)
|
|
60
53
|
|
|
61
|
-
local codec: any = {
|
|
54
|
+
local codec: Types.InternalCodec<any> = {
|
|
62
55
|
_size = totalSize,
|
|
56
|
+
_isTuple = true,
|
|
57
|
+
_elements = codecs,
|
|
63
58
|
|
|
64
59
|
_directWrite = function(b: buffer, off: number, value: any): ()
|
|
65
60
|
for i = 1, count do
|
|
@@ -95,15 +90,16 @@ function Tuple.define(...: Types.InternalCodec<any>): Types.InternalCodec<any>
|
|
|
95
90
|
return result, totalSize
|
|
96
91
|
end,
|
|
97
92
|
}
|
|
98
|
-
|
|
99
93
|
if hasUnknown then
|
|
100
94
|
codec._hasUnknown = true
|
|
101
95
|
end
|
|
102
96
|
return table.freeze(codec)
|
|
103
97
|
end
|
|
104
98
|
|
|
105
|
-
|
|
106
|
-
|
|
99
|
+
local codec: Types.InternalCodec<any> = {
|
|
100
|
+
_isTuple = true,
|
|
101
|
+
_elements = codecs,
|
|
102
|
+
|
|
107
103
|
write = function(ch: Types.ChannelState, value: any): ()
|
|
108
104
|
for i = 1, count do
|
|
109
105
|
codecs[i].write(ch, value[i])
|
|
@@ -121,7 +117,6 @@ function Tuple.define(...: Types.InternalCodec<any>): Types.InternalCodec<any>
|
|
|
121
117
|
return result, total
|
|
122
118
|
end,
|
|
123
119
|
}
|
|
124
|
-
|
|
125
120
|
if hasUnknown then
|
|
126
121
|
codec._hasUnknown = true
|
|
127
122
|
end
|
|
@@ -6,68 +6,61 @@ local Base = require(script.Parent.Parent.Base)
|
|
|
6
6
|
local Types = require(script.Parent.Parent.Parent.Types)
|
|
7
7
|
local Varint = require(script.Parent.Parent.primitive.Varint)
|
|
8
8
|
|
|
9
|
-
-- Private
|
|
9
|
+
-- Private ----------------------------------------------------------------
|
|
10
10
|
|
|
11
11
|
local alloc = Base.alloc
|
|
12
12
|
local INLINE = Varint.INLINE_MAX
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
local function writeBuffer(ch: Types.ChannelState, value: buffer): ()
|
|
15
|
+
local len = buffer.len(value)
|
|
16
|
+
local cursor = ch.cursor
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
if len <= INLINE then
|
|
19
|
+
if cursor + 1 + len > ch.size then
|
|
20
|
+
alloc(ch, 1 + len)
|
|
21
|
+
end
|
|
22
|
+
local b = ch.buff
|
|
23
|
+
buffer.writeu8(b, cursor, len)
|
|
24
|
+
if len > 0 then
|
|
25
|
+
buffer.copy(b, cursor + 1, value, 0, len)
|
|
26
|
+
end
|
|
27
|
+
ch.cursor = cursor + 1 + len
|
|
28
|
+
return
|
|
29
|
+
end
|
|
17
30
|
|
|
18
|
-
|
|
19
|
-
|
|
31
|
+
Varint.write(ch, len)
|
|
32
|
+
cursor = ch.cursor
|
|
33
|
+
if cursor + len > ch.size then
|
|
34
|
+
alloc(ch, len)
|
|
35
|
+
end
|
|
36
|
+
buffer.copy(ch.buff, cursor, value, 0, len)
|
|
37
|
+
ch.cursor = cursor + len
|
|
38
|
+
end
|
|
20
39
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
40
|
+
local function readBuffer(src: buffer, pos: number, _refs: { Instance }?): (buffer, number)
|
|
41
|
+
local len, lenBytes = Varint.readLengthPrefix(src, pos)
|
|
42
|
+
if len == 0 then
|
|
43
|
+
return buffer.create(0), lenBytes
|
|
44
|
+
end
|
|
24
45
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
local b = ch.buff
|
|
30
|
-
buffer.writeu8(b, cursor, len)
|
|
31
|
-
if len > 0 then
|
|
32
|
-
buffer.copy(b, cursor + 1, value, 0, len)
|
|
33
|
-
end
|
|
34
|
-
ch.cursor = cursor + 1 + len
|
|
35
|
-
else
|
|
36
|
-
Varint.write(ch, len)
|
|
37
|
-
cursor = ch.cursor
|
|
38
|
-
if cursor + len > ch.size then
|
|
39
|
-
alloc(ch, len)
|
|
40
|
-
end
|
|
41
|
-
buffer.copy(ch.buff, cursor, value, 0, len)
|
|
42
|
-
ch.cursor = cursor + len
|
|
43
|
-
end
|
|
44
|
-
end,
|
|
46
|
+
local dataStart = pos + lenBytes
|
|
47
|
+
if dataStart + len > buffer.len(src) then
|
|
48
|
+
error("[Lync] Buffer.read: length exceeds remaining buffer")
|
|
49
|
+
end
|
|
45
50
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
51
|
+
local out = buffer.create(len)
|
|
52
|
+
buffer.copy(out, 0, src, dataStart, len)
|
|
53
|
+
return out, lenBytes + len
|
|
54
|
+
end
|
|
50
55
|
|
|
51
|
-
|
|
52
|
-
len = b0
|
|
53
|
-
lenBytes = 1
|
|
54
|
-
else
|
|
55
|
-
len, lenBytes = Varint.read(src, pos)
|
|
56
|
-
end
|
|
56
|
+
-- Public -----------------------------------------------------------------
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
return buffer.create(0), lenBytes
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
local dataStart = pos + lenBytes
|
|
63
|
-
if dataStart + len > buffer.len(src) then
|
|
64
|
-
error("[Lync] Buffer: length exceeds remaining buffer")
|
|
65
|
-
end
|
|
58
|
+
local BufferCodec = {}
|
|
66
59
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
60
|
+
BufferCodec.buff = table.freeze({
|
|
61
|
+
_typeCheck = "buffer",
|
|
62
|
+
write = writeBuffer,
|
|
63
|
+
read = readBuffer,
|
|
64
|
+
})
|
|
72
65
|
|
|
73
66
|
return table.freeze(BufferCodec)
|
|
@@ -1,32 +1,35 @@
|
|
|
1
1
|
--!strict
|
|
2
2
|
--!native
|
|
3
|
-
-- CFrame codec with __call for smallest-three
|
|
3
|
+
-- CFrame codec with __call factory for smallest-three quaternion compression.
|
|
4
4
|
|
|
5
5
|
local Base = require(script.Parent.Parent.Base)
|
|
6
|
+
local Types = require(script.Parent.Parent.Parent.Types)
|
|
6
7
|
|
|
7
|
-
-- Constants
|
|
8
|
+
-- Constants --------------------------------------------------------------
|
|
8
9
|
|
|
9
10
|
local EPSILON = 2.4e-7
|
|
10
11
|
local EPSILON_SQ = EPSILON * EPSILON
|
|
11
|
-
|
|
12
|
-
local
|
|
13
|
-
local SIN = math.sin
|
|
14
|
-
local ABS = math.abs
|
|
15
|
-
local ROUND = math.round
|
|
16
|
-
local ACOS = math.acos
|
|
17
|
-
|
|
18
|
-
-- Smallest-three quantization constants
|
|
19
|
-
local INV_SQRT2 = 1 / SQRT(2)
|
|
12
|
+
|
|
13
|
+
local INV_SQRT2 = 1 / math.sqrt(2)
|
|
20
14
|
local Q_SCALE = 1023 / (2 * INV_SQRT2)
|
|
21
15
|
local Q_INV = (2 * INV_SQRT2) / 1023
|
|
22
16
|
|
|
17
|
+
-- Private ----------------------------------------------------------------
|
|
18
|
+
|
|
19
|
+
local alloc = Base.alloc
|
|
20
|
+
local sqrt = math.sqrt
|
|
21
|
+
local cos = math.cos
|
|
22
|
+
local sin = math.sin
|
|
23
|
+
local abs = math.abs
|
|
24
|
+
local round = math.round
|
|
25
|
+
local acos = math.acos
|
|
26
|
+
local clamp = math.clamp
|
|
27
|
+
|
|
23
28
|
local band = bit32.band
|
|
24
29
|
local bor = bit32.bor
|
|
25
30
|
local lshift = bit32.lshift
|
|
26
31
|
local rshift = bit32.rshift
|
|
27
32
|
|
|
28
|
-
-- Private: Lossless axis-angle (24 bytes) -----------------------------
|
|
29
|
-
|
|
30
33
|
local function writeLossless(b: buffer, off: number, value: CFrame): ()
|
|
31
34
|
local pos = value.Position
|
|
32
35
|
buffer.writef32(b, off, pos.X)
|
|
@@ -38,11 +41,11 @@ local function writeLossless(b: buffer, off: number, value: CFrame): ()
|
|
|
38
41
|
buffer.writef32(b, off + 12, 0)
|
|
39
42
|
buffer.writef32(b, off + 16, 0)
|
|
40
43
|
buffer.writef32(b, off + 20, 0)
|
|
41
|
-
|
|
42
|
-
buffer.writef32(b, off + 12, axis.X * angle)
|
|
43
|
-
buffer.writef32(b, off + 16, axis.Y * angle)
|
|
44
|
-
buffer.writef32(b, off + 20, axis.Z * angle)
|
|
44
|
+
return
|
|
45
45
|
end
|
|
46
|
+
buffer.writef32(b, off + 12, axis.X * angle)
|
|
47
|
+
buffer.writef32(b, off + 16, axis.Y * angle)
|
|
48
|
+
buffer.writef32(b, off + 20, axis.Z * angle)
|
|
46
49
|
end
|
|
47
50
|
|
|
48
51
|
local function readLossless(b: buffer, off: number): CFrame
|
|
@@ -58,53 +61,43 @@ local function readLossless(b: buffer, off: number): CFrame
|
|
|
58
61
|
return CFrame.new(px, py, pz)
|
|
59
62
|
end
|
|
60
63
|
|
|
61
|
-
local angle =
|
|
64
|
+
local angle = sqrt(sqLen)
|
|
62
65
|
local inv = 1 / angle
|
|
63
66
|
return CFrame.new(px, py, pz)
|
|
64
67
|
* CFrame.fromAxisAngle(Vector3.new(rx * inv, ry * inv, rz * inv), angle)
|
|
65
68
|
end
|
|
66
69
|
|
|
67
|
-
--
|
|
68
|
-
|
|
70
|
+
--[[
|
|
71
|
+
Compressed wire layout (16 bytes total):
|
|
72
|
+
[0..11] position 3x f32
|
|
73
|
+
[12..15] packed [largest:2][a:10][b:10][c:10] — smallest-three quat
|
|
74
|
+
]]
|
|
69
75
|
local function writeCompressed(b: buffer, off: number, value: CFrame): ()
|
|
70
|
-
-- Position: 3x f32
|
|
71
76
|
local pos = value.Position
|
|
72
77
|
buffer.writef32(b, off, pos.X)
|
|
73
78
|
buffer.writef32(b, off + 4, pos.Y)
|
|
74
79
|
buffer.writef32(b, off + 8, pos.Z)
|
|
75
80
|
|
|
76
|
-
--[[
|
|
77
|
-
Convert CFrame rotation to quaternion via axis-angle.
|
|
78
|
-
Then apply smallest-three: drop the largest component,
|
|
79
|
-
quantize the other three into 10 bits each, pack into u32.
|
|
80
|
-
]]
|
|
81
81
|
local axis, angle = value:ToAxisAngle()
|
|
82
|
-
local
|
|
83
|
-
local s =
|
|
82
|
+
local h = angle * 0.5
|
|
83
|
+
local s = sin(h)
|
|
84
84
|
local qx = axis.X * s
|
|
85
85
|
local qy = axis.Y * s
|
|
86
86
|
local qz = axis.Z * s
|
|
87
|
-
local qw =
|
|
88
|
-
|
|
89
|
-
-- Find largest component
|
|
90
|
-
local ax, ay, az, aw = ABS(qx), ABS(qy), ABS(qz), ABS(qw)
|
|
91
|
-
local largest = 3
|
|
92
|
-
local maxVal = aw
|
|
87
|
+
local qw = cos(h)
|
|
93
88
|
|
|
89
|
+
local ax, ay, az, aw = abs(qx), abs(qy), abs(qz), abs(qw)
|
|
90
|
+
local largest, maxVal = 3, aw
|
|
94
91
|
if ax > maxVal then
|
|
95
|
-
largest = 0
|
|
96
|
-
maxVal = ax
|
|
92
|
+
largest, maxVal = 0, ax
|
|
97
93
|
end
|
|
98
94
|
if ay > maxVal then
|
|
99
|
-
largest = 1
|
|
100
|
-
maxVal = ay
|
|
95
|
+
largest, maxVal = 1, ay
|
|
101
96
|
end
|
|
102
97
|
if az > maxVal then
|
|
103
98
|
largest = 2
|
|
104
|
-
maxVal = az
|
|
105
99
|
end
|
|
106
100
|
|
|
107
|
-
-- Negate quaternion if largest component is negative
|
|
108
101
|
local sign: number
|
|
109
102
|
if largest == 0 then
|
|
110
103
|
sign = if qx < 0 then -1 else 1
|
|
@@ -115,36 +108,24 @@ local function writeCompressed(b: buffer, off: number, value: CFrame): ()
|
|
|
115
108
|
else
|
|
116
109
|
sign = if qw < 0 then -1 else 1
|
|
117
110
|
end
|
|
118
|
-
qx
|
|
119
|
-
qy *= sign
|
|
120
|
-
qz *= sign
|
|
121
|
-
qw *= sign
|
|
111
|
+
qx, qy, qz, qw = qx * sign, qy * sign, qz * sign, qw * sign
|
|
122
112
|
|
|
123
|
-
|
|
124
|
-
local a, b2, c: number
|
|
113
|
+
local a, bComp, c: number
|
|
125
114
|
if largest == 0 then
|
|
126
|
-
a,
|
|
115
|
+
a, bComp, c = qy, qz, qw
|
|
127
116
|
elseif largest == 1 then
|
|
128
|
-
a,
|
|
117
|
+
a, bComp, c = qx, qz, qw
|
|
129
118
|
elseif largest == 2 then
|
|
130
|
-
a,
|
|
119
|
+
a, bComp, c = qx, qy, qw
|
|
131
120
|
else
|
|
132
|
-
a,
|
|
121
|
+
a, bComp, c = qx, qy, qz
|
|
133
122
|
end
|
|
134
123
|
|
|
135
|
-
|
|
136
|
-
local
|
|
137
|
-
local
|
|
138
|
-
local qc = ROUND((c + INV_SQRT2) * Q_SCALE)
|
|
139
|
-
|
|
140
|
-
-- Clamp to [0, 1023]
|
|
141
|
-
qa = if qa < 0 then 0 elseif qa > 1023 then 1023 else qa
|
|
142
|
-
qb = if qb < 0 then 0 elseif qb > 1023 then 1023 else qb
|
|
143
|
-
qc = if qc < 0 then 0 elseif qc > 1023 then 1023 else qc
|
|
124
|
+
local qa = clamp(round((a + INV_SQRT2) * Q_SCALE), 0, 1023)
|
|
125
|
+
local qb = clamp(round((bComp + INV_SQRT2) * Q_SCALE), 0, 1023)
|
|
126
|
+
local qc = clamp(round((c + INV_SQRT2) * Q_SCALE), 0, 1023)
|
|
144
127
|
|
|
145
|
-
|
|
146
|
-
local packed = bor(lshift(largest, 30), lshift(qa, 20), lshift(qb, 10), qc)
|
|
147
|
-
buffer.writeu32(b, off + 12, packed)
|
|
128
|
+
buffer.writeu32(b, off + 12, bor(lshift(largest, 30), lshift(qa, 20), lshift(qb, 10), qc))
|
|
148
129
|
end
|
|
149
130
|
|
|
150
131
|
local function readCompressed(b: buffer, off: number): CFrame
|
|
@@ -158,72 +139,59 @@ local function readCompressed(b: buffer, off: number): CFrame
|
|
|
158
139
|
local qb = band(rshift(packed, 10), 0x3FF)
|
|
159
140
|
local qc = band(packed, 0x3FF)
|
|
160
141
|
|
|
161
|
-
-- Dequantize from [0, 1023] to [-1/sqrt(2), 1/sqrt(2)]
|
|
162
142
|
local a = qa * Q_INV - INV_SQRT2
|
|
163
|
-
local
|
|
143
|
+
local bComp = qb * Q_INV - INV_SQRT2
|
|
164
144
|
local c = qc * Q_INV - INV_SQRT2
|
|
165
145
|
|
|
166
|
-
|
|
167
|
-
local
|
|
168
|
-
local d = SQRT(if sqSum < 1 then 1 - sqSum else 0)
|
|
146
|
+
local sqSum = a * a + bComp * bComp + c * c
|
|
147
|
+
local d = sqrt(if sqSum < 1 then 1 - sqSum else 0)
|
|
169
148
|
|
|
170
|
-
-- Place components
|
|
171
149
|
local qx, qy, qz, qw: number
|
|
172
150
|
if largest == 0 then
|
|
173
|
-
qx, qy, qz, qw = d, a,
|
|
151
|
+
qx, qy, qz, qw = d, a, bComp, c
|
|
174
152
|
elseif largest == 1 then
|
|
175
|
-
qx, qy, qz, qw = a, d,
|
|
153
|
+
qx, qy, qz, qw = a, d, bComp, c
|
|
176
154
|
elseif largest == 2 then
|
|
177
|
-
qx, qy, qz, qw = a,
|
|
155
|
+
qx, qy, qz, qw = a, bComp, d, c
|
|
178
156
|
else
|
|
179
|
-
qx, qy, qz, qw = a,
|
|
157
|
+
qx, qy, qz, qw = a, bComp, c, d
|
|
180
158
|
end
|
|
181
159
|
|
|
182
|
-
-- Build CFrame from position + quaternion
|
|
183
160
|
local origin = CFrame.new(px, py, pz)
|
|
184
161
|
if qx * qx + qy * qy + qz * qz < EPSILON_SQ then
|
|
185
162
|
return origin
|
|
186
163
|
end
|
|
187
164
|
|
|
188
|
-
|
|
189
|
-
local
|
|
190
|
-
local angle = 2 * ACOS(if qw > 1 then 1 elseif qw < -1 then -1 else qw)
|
|
165
|
+
local len = sqrt(qx * qx + qy * qy + qz * qz)
|
|
166
|
+
local angle = 2 * acos(clamp(qw, -1, 1))
|
|
191
167
|
local inv = 1 / len
|
|
192
168
|
return origin * CFrame.fromAxisAngle(Vector3.new(qx * inv, qy * inv, qz * inv), angle)
|
|
193
169
|
end
|
|
194
170
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
return Base.define(16, writeCompressed, readCompressed, {
|
|
198
|
-
_typeCheck = "CFrame",
|
|
199
|
-
})
|
|
171
|
+
local function compressedFactory(_self): Types.InternalCodec<CFrame>
|
|
172
|
+
return Base.define(16, writeCompressed, readCompressed, { _typeCheck = "CFrame" })
|
|
200
173
|
end
|
|
201
174
|
|
|
202
|
-
-- Public
|
|
175
|
+
-- Public -----------------------------------------------------------------
|
|
203
176
|
|
|
204
177
|
local CFrameCodec = {}
|
|
205
178
|
|
|
206
|
-
CFrameCodec.cframe = setmetatable(
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
return readLossless(src, pos), 24
|
|
224
|
-
end,
|
|
225
|
-
} :: any,
|
|
226
|
-
{ __call = compressedFactory }
|
|
227
|
-
)
|
|
179
|
+
CFrameCodec.cframe = table.freeze(setmetatable({
|
|
180
|
+
_size = 24,
|
|
181
|
+
_directWrite = writeLossless,
|
|
182
|
+
_directRead = readLossless,
|
|
183
|
+
_typeCheck = "CFrame",
|
|
184
|
+
write = function(ch: Types.ChannelState, value: CFrame): ()
|
|
185
|
+
local cursor = ch.cursor
|
|
186
|
+
if cursor + 24 > ch.size then
|
|
187
|
+
alloc(ch, 24)
|
|
188
|
+
end
|
|
189
|
+
writeLossless(ch.buff, cursor, value)
|
|
190
|
+
ch.cursor = cursor + 24
|
|
191
|
+
end,
|
|
192
|
+
read = function(src: buffer, pos: number, _refs: { Instance }?): (CFrame, number)
|
|
193
|
+
return readLossless(src, pos), 24
|
|
194
|
+
end,
|
|
195
|
+
}, table.freeze({ __call = compressedFactory })))
|
|
228
196
|
|
|
229
197
|
return table.freeze(CFrameCodec)
|
|
@@ -1,28 +1,32 @@
|
|
|
1
1
|
--!strict
|
|
2
2
|
--!optimize 2
|
|
3
|
-
-- Color3 codec. 3 bytes,
|
|
3
|
+
-- Color3 codec. 3 bytes, R/G/B u8 per channel, clamped to [0, 1].
|
|
4
4
|
|
|
5
5
|
local Base = require(script.Parent.Parent.Base)
|
|
6
6
|
|
|
7
|
-
-- Private
|
|
7
|
+
-- Private ----------------------------------------------------------------
|
|
8
8
|
|
|
9
9
|
local round = math.round
|
|
10
10
|
local clamp = math.clamp
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
local ColorCodec = {}
|
|
15
|
-
|
|
16
|
-
ColorCodec.color3 = Base.define(3, function(b: buffer, off: number, value: Color3): ()
|
|
12
|
+
local function writeColor3(b: buffer, off: number, value: Color3): ()
|
|
17
13
|
buffer.writeu8(b, off, round(clamp(value.R, 0, 1) * 255))
|
|
18
14
|
buffer.writeu8(b, off + 1, round(clamp(value.G, 0, 1) * 255))
|
|
19
15
|
buffer.writeu8(b, off + 2, round(clamp(value.B, 0, 1) * 255))
|
|
20
|
-
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
local function readColor3(b: buffer, off: number): Color3
|
|
21
19
|
return Color3.fromRGB(
|
|
22
20
|
buffer.readu8(b, off),
|
|
23
21
|
buffer.readu8(b, off + 1),
|
|
24
22
|
buffer.readu8(b, off + 2)
|
|
25
23
|
)
|
|
26
|
-
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
-- Public -----------------------------------------------------------------
|
|
27
|
+
|
|
28
|
+
local Color = {}
|
|
29
|
+
|
|
30
|
+
Color.color3 = Base.define(3, writeColor3, readColor3, { _typeCheck = "Color3" })
|
|
27
31
|
|
|
28
|
-
return table.freeze(
|
|
32
|
+
return table.freeze(Color)
|
|
@@ -2,58 +2,48 @@
|
|
|
2
2
|
--!optimize 2
|
|
3
3
|
-- Instance codec via sidecar reference array.
|
|
4
4
|
|
|
5
|
-
local
|
|
5
|
+
local Channel = require(script.Parent.Parent.Parent.internal.Channel)
|
|
6
6
|
local Types = require(script.Parent.Parent.Parent.Types)
|
|
7
7
|
|
|
8
|
-
-- Private
|
|
8
|
+
-- Private ----------------------------------------------------------------
|
|
9
9
|
|
|
10
|
-
local
|
|
11
|
-
local writeu16 = buffer.writeu16
|
|
10
|
+
local pushRef = Channel.pushRef
|
|
12
11
|
local readu16 = buffer.readu16
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
local function writeInstance(ch: Types.ChannelState, value: Instance): ()
|
|
14
|
+
pushRef(ch, value)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
local function readInstance(src: buffer, pos: number, refs: { Instance }?): (Instance, number)
|
|
18
|
+
if not refs then
|
|
19
|
+
error("[Lync] Instance.read: refs array is required")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
local idx = readu16(src, pos)
|
|
23
|
+
if idx < 1 or idx > #refs then
|
|
24
|
+
error(`[Lync] Instance.read: ref index {idx} out of bounds`)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
local inst = refs[idx]
|
|
28
|
+
if typeof(inst) ~= "Instance" then
|
|
29
|
+
error("[Lync] Instance.read: ref is not an Instance")
|
|
30
|
+
end
|
|
31
|
+
return inst, 2
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
-- Public -----------------------------------------------------------------
|
|
15
35
|
|
|
16
36
|
local InstanceCodec = {}
|
|
17
37
|
|
|
18
|
-
--
|
|
38
|
+
--[[
|
|
39
|
+
No _directWrite/_directRead: write needs ch.refs, so structs/arrays
|
|
40
|
+
cannot use the all-direct fast path with this codec.
|
|
41
|
+
]]
|
|
19
42
|
InstanceCodec.inst = table.freeze({
|
|
20
43
|
_size = 2,
|
|
21
44
|
_typeCheck = "Instance",
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if idx > 0xFFFF then
|
|
26
|
-
error("[Lync] Instance: ref overflow (>65535)")
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
ch.refs[idx] = value
|
|
30
|
-
ch.refCount = idx
|
|
31
|
-
|
|
32
|
-
local cursor = ch.cursor
|
|
33
|
-
if cursor + 2 > ch.size then
|
|
34
|
-
alloc(ch, 2)
|
|
35
|
-
end
|
|
36
|
-
writeu16(ch.buff, cursor, idx)
|
|
37
|
-
ch.cursor = cursor + 2
|
|
38
|
-
end,
|
|
39
|
-
|
|
40
|
-
read = function(src: buffer, pos: number, refs: { Instance }?): (Instance, number)
|
|
41
|
-
if not refs then
|
|
42
|
-
error("[Lync] Instance: read requires refs array")
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
local idx = readu16(src, pos)
|
|
46
|
-
if idx < 1 or idx > #refs then
|
|
47
|
-
error(`[Lync] Instance: ref index {idx} out of bounds`)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
local inst = refs[idx]
|
|
51
|
-
if typeof(inst) ~= "Instance" then
|
|
52
|
-
error("[Lync] Instance: invalid ref (expected Instance)")
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
return inst, 2
|
|
56
|
-
end,
|
|
57
|
-
} :: any)
|
|
45
|
+
write = writeInstance,
|
|
46
|
+
read = readInstance,
|
|
47
|
+
})
|
|
58
48
|
|
|
59
49
|
return table.freeze(InstanceCodec)
|