@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
|
@@ -1,119 +1,94 @@
|
|
|
1
1
|
--!strict
|
|
2
2
|
--!optimize 2
|
|
3
|
-
-- Ordered intercept chains
|
|
3
|
+
-- Ordered intercept chains returning Connection objects.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
local Signal = require(script.Parent.Parent.api.Signal)
|
|
6
|
+
local Types = require(script.Parent.Parent.Types)
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
handlers: { Handler },
|
|
9
|
-
snapshot: { Handler }?,
|
|
10
|
-
}
|
|
8
|
+
-- State ---------------------------------------------------------------
|
|
11
9
|
|
|
12
|
-
|
|
10
|
+
local _sendSignal = Signal.create()
|
|
11
|
+
local _receiveSignal = Signal.create()
|
|
12
|
+
local _dropSignal = Signal.create()
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
-- Public --------------------------------------------------------------
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
local Middleware = {}
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
function Middleware.onSend(fn: (data: any, name: string, player: Player?) -> any): Types.Connection
|
|
19
|
+
return _sendSignal:connect(fn)
|
|
20
|
+
end
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
function Middleware.onReceive(
|
|
23
|
+
fn: (data: any, name: string, player: Player?) -> any
|
|
24
|
+
): Types.Connection
|
|
25
|
+
return _receiveSignal:connect(fn)
|
|
26
|
+
end
|
|
22
27
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if result == nil or result == DROP then
|
|
28
|
-
return nil
|
|
29
|
-
end
|
|
30
|
-
current = result
|
|
31
|
-
end
|
|
32
|
-
return current
|
|
28
|
+
function Middleware.onDrop(
|
|
29
|
+
fn: (player: Player, reason: string, name: string, data: any?) -> ()
|
|
30
|
+
): Types.Connection
|
|
31
|
+
return _dropSignal:connect(fn)
|
|
33
32
|
end
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
--[[
|
|
35
|
+
Runs send middleware chain. Returns transformed data, or DROP sentinel.
|
|
36
|
+
If no hooks, returns data unchanged (zero overhead).
|
|
37
|
+
]]
|
|
38
|
+
function Middleware.runSend(data: any, name: string, player: Player?): any
|
|
39
|
+
local count = _sendSignal._count[1]
|
|
38
40
|
if count == 0 then
|
|
39
41
|
return data
|
|
40
42
|
end
|
|
41
43
|
|
|
42
|
-
local
|
|
43
|
-
|
|
44
|
-
snapshot = table.clone(handlers)
|
|
45
|
-
chain.snapshot = snapshot
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
local ok: boolean
|
|
49
|
-
local result: any
|
|
50
|
-
|
|
51
|
-
if count == 1 then
|
|
52
|
-
ok, result = pcall(snapshot[1], data, name, player)
|
|
53
|
-
else
|
|
54
|
-
ok, result = pcall(runChain, snapshot, data, name, player)
|
|
55
|
-
end
|
|
44
|
+
local entries = _sendSignal._entries
|
|
45
|
+
local result = data
|
|
56
46
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
47
|
+
for i = 1, count do
|
|
48
|
+
local entry = entries[i]
|
|
49
|
+
if entry._state ~= 0 then -- not disconnected
|
|
50
|
+
local returned = entry.fn(result, name, player)
|
|
51
|
+
if returned ~= nil then
|
|
52
|
+
result = returned
|
|
53
|
+
end
|
|
54
|
+
end
|
|
64
55
|
end
|
|
65
56
|
|
|
66
57
|
return result
|
|
67
58
|
end
|
|
68
59
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return function(): ()
|
|
74
|
-
local pos = table.find(chain.handlers, fn)
|
|
75
|
-
if pos then
|
|
76
|
-
table.remove(chain.handlers, pos)
|
|
77
|
-
chain.snapshot = nil
|
|
78
|
-
end
|
|
60
|
+
function Middleware.runReceive(data: any, name: string, player: Player?): any
|
|
61
|
+
local count = _receiveSignal._count[1]
|
|
62
|
+
if count == 0 then
|
|
63
|
+
return data
|
|
79
64
|
end
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
-- Public --------------------------------------------------------------
|
|
83
65
|
|
|
84
|
-
local
|
|
66
|
+
local entries = _receiveSignal._entries
|
|
67
|
+
local result = data
|
|
85
68
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return function(): ()
|
|
95
|
-
remover()
|
|
96
|
-
Middleware.hasSend = #_send.handlers > 0
|
|
69
|
+
for i = 1, count do
|
|
70
|
+
local entry = entries[i]
|
|
71
|
+
if entry._state ~= 0 then
|
|
72
|
+
local returned = entry.fn(result, name, player)
|
|
73
|
+
if returned ~= nil then
|
|
74
|
+
result = returned
|
|
75
|
+
end
|
|
76
|
+
end
|
|
97
77
|
end
|
|
98
|
-
end
|
|
99
78
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
Middleware.hasReceive = true
|
|
79
|
+
return result
|
|
80
|
+
end
|
|
103
81
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
Middleware.hasReceive = #_receive.handlers > 0
|
|
107
|
-
end
|
|
82
|
+
function Middleware.fireDrop(player: Player, reason: string, name: string, data: any?): ()
|
|
83
|
+
_dropSignal:fireSync(player, reason, name, data)
|
|
108
84
|
end
|
|
109
85
|
|
|
110
|
-
function Middleware.
|
|
111
|
-
return
|
|
86
|
+
function Middleware.hasSendHooks(): boolean
|
|
87
|
+
return _sendSignal._count[1] > 0
|
|
112
88
|
end
|
|
113
89
|
|
|
114
|
-
function Middleware.
|
|
115
|
-
return
|
|
90
|
+
function Middleware.hasReceiveHooks(): boolean
|
|
91
|
+
return _receiveSignal._count[1] > 0
|
|
116
92
|
end
|
|
117
93
|
|
|
118
|
-
|
|
119
|
-
return Middleware
|
|
94
|
+
return table.freeze(Middleware)
|
package/src/internal/Pool.luau
CHANGED
|
@@ -1,67 +1,56 @@
|
|
|
1
1
|
--!strict
|
|
2
2
|
--!optimize 2
|
|
3
|
-
-- Stack-based ChannelState pool
|
|
3
|
+
-- Stack-based ChannelState pool for per-player channel reuse.
|
|
4
4
|
|
|
5
5
|
local Channel = require(script.Parent.Channel)
|
|
6
6
|
local Types = require(script.Parent.Parent.Types)
|
|
7
7
|
|
|
8
|
-
type ChannelState = Types.ChannelState
|
|
9
|
-
|
|
10
8
|
-- Constants -----------------------------------------------------------
|
|
11
9
|
|
|
12
|
-
local
|
|
10
|
+
local DEFAULT_SIZE = 16
|
|
13
11
|
|
|
14
12
|
-- State ---------------------------------------------------------------
|
|
15
13
|
|
|
16
|
-
local _stack
|
|
14
|
+
local _stack: { Types.ChannelState } = {}
|
|
17
15
|
local _depth = 0
|
|
18
|
-
local _maxSize =
|
|
16
|
+
local _maxSize = DEFAULT_SIZE
|
|
19
17
|
|
|
20
18
|
-- Public --------------------------------------------------------------
|
|
21
19
|
|
|
22
20
|
local Pool = {}
|
|
23
21
|
|
|
24
|
-
|
|
25
|
-
function Pool.setMaxSize(count: number): ()
|
|
26
|
-
if count < 2 or count > 128 then
|
|
27
|
-
error(`[Lync] Pool max size must be 2-128, got {count}`)
|
|
28
|
-
end
|
|
29
|
-
_maxSize = count
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
function Pool.getMaxSize(): number
|
|
33
|
-
return _maxSize
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
function Pool.acquire(): ChannelState
|
|
22
|
+
function Pool.acquire(): Types.ChannelState
|
|
37
23
|
if _depth > 0 then
|
|
38
24
|
local ch = _stack[_depth]
|
|
39
25
|
_stack[_depth] = nil :: any
|
|
40
26
|
_depth -= 1
|
|
27
|
+
Channel.reset(ch)
|
|
41
28
|
return ch
|
|
42
29
|
end
|
|
43
30
|
|
|
44
31
|
return Channel.create()
|
|
45
32
|
end
|
|
46
33
|
|
|
47
|
-
function Pool.release(ch: ChannelState): ()
|
|
48
|
-
ch.cursor = 0
|
|
49
|
-
ch.lastId = -1
|
|
50
|
-
ch.countPos = 0
|
|
51
|
-
ch.itemCount = 0
|
|
52
|
-
table.clear(ch.refs)
|
|
53
|
-
table.clear(ch.deltas)
|
|
54
|
-
ch.prevDump = nil
|
|
55
|
-
|
|
34
|
+
function Pool.release(ch: Types.ChannelState): ()
|
|
56
35
|
if _depth >= _maxSize then
|
|
57
|
-
return
|
|
36
|
+
return
|
|
58
37
|
end
|
|
59
38
|
|
|
60
39
|
_depth += 1
|
|
61
40
|
_stack[_depth] = ch
|
|
62
41
|
end
|
|
63
42
|
|
|
64
|
-
function Pool.size
|
|
43
|
+
function Pool.setMaxSize(size: number): ()
|
|
44
|
+
_maxSize = size
|
|
45
|
+
|
|
46
|
+
-- Trim excess
|
|
47
|
+
while _depth > _maxSize do
|
|
48
|
+
_stack[_depth] = nil :: any
|
|
49
|
+
_depth -= 1
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
function Pool.count(): number
|
|
65
54
|
return _depth
|
|
66
55
|
end
|
|
67
56
|
|
|
@@ -1,79 +1,71 @@
|
|
|
1
1
|
--!strict
|
|
2
2
|
--!optimize 2
|
|
3
|
-
-- Deterministic ID assignment
|
|
3
|
+
-- Deterministic packet/query ID assignment. Sequential 7-bit IDs.
|
|
4
4
|
|
|
5
|
-
local
|
|
5
|
+
local Signal = require(script.Parent.Parent.api.Signal)
|
|
6
6
|
local Types = require(script.Parent.Parent.Types)
|
|
7
7
|
|
|
8
|
-
type Codec<T> = Types.Codec<T>
|
|
9
|
-
type Registration = Types.Registration
|
|
10
|
-
type RateLimitConfig = Types.RateLimitConfig
|
|
11
|
-
|
|
12
8
|
-- Constants -----------------------------------------------------------
|
|
13
9
|
|
|
14
10
|
local KIND_PACKET = 0
|
|
15
11
|
local KIND_REQUEST = 1
|
|
16
12
|
local KIND_RESPONSE = 2
|
|
17
|
-
local
|
|
13
|
+
local MAX_ID = 127
|
|
18
14
|
|
|
19
15
|
-- State ---------------------------------------------------------------
|
|
20
16
|
|
|
21
|
-
local
|
|
22
|
-
local
|
|
23
|
-
local
|
|
17
|
+
local _nextId = 0
|
|
18
|
+
local _byId: { [number]: Types.Registration } = {}
|
|
19
|
+
local _byName: { [string]: Types.Registration } = {}
|
|
20
|
+
|
|
21
|
+
-- Public --------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
local Registry = {}
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
Registry.KIND_PACKET = KIND_PACKET
|
|
26
|
+
Registry.KIND_REQUEST = KIND_REQUEST
|
|
27
|
+
Registry.KIND_RESPONSE = KIND_RESPONSE
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
function Registry.register(
|
|
28
30
|
name: string,
|
|
29
|
-
baseName: string,
|
|
30
|
-
codec: Codec<any>,
|
|
31
|
-
isUnreliable: boolean,
|
|
32
31
|
kind: number,
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
codec: Types.InternalCodec<any>,
|
|
33
|
+
isUnreliable: boolean,
|
|
34
|
+
partner: number?,
|
|
35
|
+
needsGate: boolean,
|
|
36
|
+
headerSize: number,
|
|
37
|
+
timestampMode: number,
|
|
38
|
+
openFn: (ch: Types.ChannelState, id: number) -> (),
|
|
39
|
+
rateLimit: Types.RateLimitConfig?,
|
|
35
40
|
validate: ((data: any, player: Player) -> (boolean, string?))?,
|
|
36
|
-
maxPayloadBytes: number
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
error(`[Lync] Duplicate registration: "{name}"`)
|
|
41
|
-
end
|
|
42
|
-
if _nextId > MAX_PACKETS then
|
|
43
|
-
error(`[Lync] Registration limit reached: {MAX_PACKETS} max`)
|
|
44
|
-
end
|
|
41
|
+
maxPayloadBytes: number?
|
|
42
|
+
): Types.Registration
|
|
43
|
+
_nextId += 1
|
|
44
|
+
local id = _nextId
|
|
45
45
|
|
|
46
|
-
if
|
|
47
|
-
|
|
48
|
-
error(`[Lync] maxPerSecond must be positive: "{name}"`)
|
|
49
|
-
end
|
|
50
|
-
if rateLimit.burstAllowance and rateLimit.burstAllowance <= 0 then
|
|
51
|
-
error(`[Lync] burstAllowance must be positive: "{name}"`)
|
|
52
|
-
end
|
|
46
|
+
if id > MAX_ID then
|
|
47
|
+
error(`[Lync] Registry: ID limit exceeded ({MAX_ID}), too many packets/queries`)
|
|
53
48
|
end
|
|
54
49
|
|
|
55
|
-
if
|
|
56
|
-
error(`[Lync]
|
|
50
|
+
if _byName[name] and kind ~= KIND_RESPONSE then
|
|
51
|
+
error(`[Lync] Registry: duplicate name "{name}"`)
|
|
57
52
|
end
|
|
58
53
|
|
|
59
|
-
local
|
|
60
|
-
_nextId += 1
|
|
61
|
-
|
|
62
|
-
local reg: Registration = {
|
|
54
|
+
local reg: Types.Registration = {
|
|
63
55
|
id = id,
|
|
64
56
|
name = name,
|
|
65
|
-
|
|
57
|
+
kind = kind,
|
|
66
58
|
codec = codec,
|
|
67
59
|
isUnreliable = isUnreliable,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
signal = signal,
|
|
60
|
+
partner = partner,
|
|
61
|
+
signal = Signal.create(),
|
|
71
62
|
rateLimit = rateLimit,
|
|
72
63
|
validate = validate,
|
|
73
|
-
needsGate =
|
|
64
|
+
needsGate = needsGate,
|
|
74
65
|
maxPayloadBytes = maxPayloadBytes,
|
|
75
|
-
timestampMode = timestampMode
|
|
76
|
-
|
|
66
|
+
timestampMode = timestampMode,
|
|
67
|
+
headerSize = headerSize,
|
|
68
|
+
_openFn = openFn,
|
|
77
69
|
bytesSent = 0,
|
|
78
70
|
bytesReceived = 0,
|
|
79
71
|
fires = 0,
|
|
@@ -81,83 +73,34 @@ local function assign(
|
|
|
81
73
|
drops = 0,
|
|
82
74
|
}
|
|
83
75
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
-- Public --------------------------------------------------------------
|
|
90
|
-
|
|
91
|
-
local Registry = {
|
|
92
|
-
KIND_PACKET = KIND_PACKET,
|
|
93
|
-
KIND_REQUEST = KIND_REQUEST,
|
|
94
|
-
KIND_RESPONSE = KIND_RESPONSE,
|
|
95
|
-
}
|
|
76
|
+
_byId[id] = reg
|
|
77
|
+
if kind ~= KIND_RESPONSE then
|
|
78
|
+
_byName[name] = reg
|
|
79
|
+
end
|
|
96
80
|
|
|
97
|
-
|
|
98
|
-
name: string,
|
|
99
|
-
codec: Codec<any>,
|
|
100
|
-
isUnreliable: boolean,
|
|
101
|
-
signal: any,
|
|
102
|
-
rateLimit: RateLimitConfig?,
|
|
103
|
-
validate: ((data: any, player: Player) -> (boolean, string?))?,
|
|
104
|
-
maxPayloadBytes: number?,
|
|
105
|
-
timestampMode: number?
|
|
106
|
-
): Registration
|
|
107
|
-
return assign(
|
|
108
|
-
name,
|
|
109
|
-
name,
|
|
110
|
-
codec,
|
|
111
|
-
isUnreliable,
|
|
112
|
-
KIND_PACKET,
|
|
113
|
-
signal,
|
|
114
|
-
rateLimit,
|
|
115
|
-
validate,
|
|
116
|
-
maxPayloadBytes,
|
|
117
|
-
timestampMode
|
|
118
|
-
)
|
|
81
|
+
return reg
|
|
119
82
|
end
|
|
120
83
|
|
|
121
|
-
function Registry.
|
|
122
|
-
|
|
123
|
-
requestCodec: Codec<any>,
|
|
124
|
-
responseCodec: Codec<any>,
|
|
125
|
-
requestSignal: any,
|
|
126
|
-
responseSignal: any,
|
|
127
|
-
rateLimit: RateLimitConfig?,
|
|
128
|
-
validate: ((data: any, player: Player) -> (boolean, string?))?
|
|
129
|
-
): (Registration, Registration)
|
|
130
|
-
local req = assign(
|
|
131
|
-
`{name}:req`,
|
|
132
|
-
name,
|
|
133
|
-
requestCodec,
|
|
134
|
-
false,
|
|
135
|
-
KIND_REQUEST,
|
|
136
|
-
requestSignal,
|
|
137
|
-
rateLimit,
|
|
138
|
-
validate
|
|
139
|
-
)
|
|
140
|
-
local resp =
|
|
141
|
-
assign(`{name}:resp`, name, responseCodec, false, KIND_RESPONSE, responseSignal, nil, nil)
|
|
142
|
-
|
|
143
|
-
req.partner = resp.id
|
|
144
|
-
resp.partner = req.id
|
|
145
|
-
return req, resp
|
|
84
|
+
function Registry.get(id: number): Types.Registration?
|
|
85
|
+
return _byId[id]
|
|
146
86
|
end
|
|
147
87
|
|
|
148
|
-
function Registry.
|
|
149
|
-
return
|
|
88
|
+
function Registry.getByName(name: string): Types.Registration?
|
|
89
|
+
return _byName[name]
|
|
150
90
|
end
|
|
151
91
|
|
|
152
|
-
function Registry.
|
|
153
|
-
|
|
154
|
-
return if id then _entries[id] else nil
|
|
92
|
+
function Registry.count(): number
|
|
93
|
+
return _nextId
|
|
155
94
|
end
|
|
156
95
|
|
|
157
|
-
function Registry.
|
|
158
|
-
|
|
159
|
-
|
|
96
|
+
function Registry.all(): { Types.Registration }
|
|
97
|
+
local result = table.create(_nextId)
|
|
98
|
+
for i = 1, _nextId do
|
|
99
|
+
if _byId[i] then
|
|
100
|
+
table.insert(result, _byId[i])
|
|
101
|
+
end
|
|
160
102
|
end
|
|
103
|
+
return result
|
|
161
104
|
end
|
|
162
105
|
|
|
163
106
|
return table.freeze(Registry)
|
|
@@ -1,67 +1,88 @@
|
|
|
1
1
|
--!strict
|
|
2
2
|
--!optimize 2
|
|
3
|
-
--
|
|
3
|
+
-- Remote instance creation and access.
|
|
4
4
|
|
|
5
|
-
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
|
6
5
|
local RunService = game:GetService("RunService")
|
|
7
6
|
|
|
8
7
|
-- Constants -----------------------------------------------------------
|
|
9
8
|
|
|
10
|
-
local
|
|
11
|
-
local
|
|
12
|
-
local UNRELIABLE = "U"
|
|
13
|
-
local TIMEOUT = 10
|
|
9
|
+
local RELIABLE_NAME = "LyncReliable"
|
|
10
|
+
local UNRELIABLE_NAME = "LyncUnreliable"
|
|
14
11
|
|
|
15
12
|
-- State ---------------------------------------------------------------
|
|
16
13
|
|
|
17
|
-
local _reliable: RemoteEvent
|
|
18
|
-
local _unreliable: UnreliableRemoteEvent
|
|
14
|
+
local _reliable: RemoteEvent? = nil
|
|
15
|
+
local _unreliable: UnreliableRemoteEvent? = nil
|
|
16
|
+
local _isServer = RunService:IsServer()
|
|
19
17
|
|
|
20
18
|
-- Public --------------------------------------------------------------
|
|
21
19
|
|
|
22
20
|
local Bridge = {}
|
|
23
21
|
|
|
24
|
-
function Bridge.setup(): ()
|
|
25
|
-
if
|
|
26
|
-
local
|
|
27
|
-
|
|
22
|
+
function Bridge.setup(container: Instance): ()
|
|
23
|
+
if _isServer then
|
|
24
|
+
local re = Instance.new("RemoteEvent")
|
|
25
|
+
re.Name = RELIABLE_NAME
|
|
26
|
+
re.Parent = container
|
|
28
27
|
|
|
29
|
-
local
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
local ure = Instance.new("UnreliableRemoteEvent")
|
|
29
|
+
ure.Name = UNRELIABLE_NAME
|
|
30
|
+
ure.Parent = container
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
_reliable = re
|
|
33
|
+
_unreliable = ure
|
|
34
|
+
else
|
|
35
|
+
_reliable = container:WaitForChild(RELIABLE_NAME) :: RemoteEvent
|
|
36
|
+
_unreliable = container:WaitForChild(UNRELIABLE_NAME) :: UnreliableRemoteEvent
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
function Bridge.reliable(): RemoteEvent
|
|
41
|
+
return _reliable :: RemoteEvent
|
|
42
|
+
end
|
|
36
43
|
|
|
37
|
-
|
|
44
|
+
function Bridge.unreliable(): UnreliableRemoteEvent
|
|
45
|
+
return _unreliable :: UnreliableRemoteEvent
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
function Bridge.isServer(): boolean
|
|
49
|
+
return _isServer
|
|
50
|
+
end
|
|
38
51
|
|
|
39
|
-
|
|
40
|
-
|
|
52
|
+
function Bridge.fireServer(data: buffer, refs: { Instance }): ()
|
|
53
|
+
local re = _reliable :: RemoteEvent
|
|
54
|
+
if #refs > 0 then
|
|
55
|
+
re:FireServer(data, refs)
|
|
41
56
|
else
|
|
42
|
-
|
|
43
|
-
if not folder then
|
|
44
|
-
error("[Lync] Network folder not found, is the server started?")
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
local reliable = folder:WaitForChild(RELIABLE, TIMEOUT)
|
|
48
|
-
if not reliable then
|
|
49
|
-
error("[Lync] Reliable remote not found")
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
local unreliable = folder:WaitForChild(UNRELIABLE, TIMEOUT)
|
|
53
|
-
if not unreliable then
|
|
54
|
-
error("[Lync] Unreliable remote not found")
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
_reliable = reliable :: RemoteEvent
|
|
58
|
-
_unreliable = unreliable :: UnreliableRemoteEvent
|
|
57
|
+
re:FireServer(data)
|
|
59
58
|
end
|
|
59
|
+
end
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
function Bridge.fireClient(player: Player, data: buffer, refs: { Instance }): ()
|
|
62
|
+
local re = _reliable :: RemoteEvent
|
|
63
|
+
if #refs > 0 then
|
|
64
|
+
re:FireClient(player, data, refs)
|
|
65
|
+
else
|
|
66
|
+
re:FireClient(player, data)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
function Bridge.fireServerUnreliable(data: buffer, refs: { Instance }): ()
|
|
71
|
+
local ure = _unreliable :: UnreliableRemoteEvent
|
|
72
|
+
if #refs > 0 then
|
|
73
|
+
ure:FireServer(data, refs)
|
|
74
|
+
else
|
|
75
|
+
ure:FireServer(data)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
function Bridge.fireClientUnreliable(player: Player, data: buffer, refs: { Instance }): ()
|
|
80
|
+
local ure = _unreliable :: UnreliableRemoteEvent
|
|
81
|
+
if #refs > 0 then
|
|
82
|
+
ure:FireClient(player, data, refs)
|
|
83
|
+
else
|
|
84
|
+
ure:FireClient(player, data)
|
|
85
|
+
end
|
|
64
86
|
end
|
|
65
87
|
|
|
66
|
-
|
|
67
|
-
return Bridge
|
|
88
|
+
return table.freeze(Bridge)
|