@axpecter/lync 2.3.3 → 3.0.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/LICENSE +21 -0
- package/README.md +302 -299
- package/Types.luau +215 -0
- package/api/Define.luau +154 -0
- package/api/Lifecycle.luau +119 -0
- package/api/Packet.luau +108 -0
- package/api/Query.luau +149 -0
- package/api/Set.luau +189 -0
- package/channel/Blocks.luau +124 -0
- package/channel/Group.luau +118 -0
- package/channel/Link.luau +135 -0
- package/channel/Outbox.luau +261 -0
- package/channel/Recipients.luau +129 -0
- package/channel/Transport.luau +138 -0
- package/codec/Base.luau +236 -0
- package/codec/Composites.luau +128 -0
- package/codec/Datatypes.luau +162 -0
- package/codec/Legality.luau +61 -0
- package/codec/Scalars.luau +72 -0
- package/codec/Text.luau +89 -0
- package/codec/init.luau +39 -0
- package/index.d.ts +285 -0
- package/init.luau +91 -0
- package/kernel/Bits.luau +16 -0
- package/kernel/Catalog.luau +121 -0
- package/kernel/Heap.luau +80 -0
- package/kernel/Listeners.luau +95 -0
- package/kernel/Log.luau +197 -0
- package/kernel/Tally.luau +128 -0
- package/kernel/Threads.luau +44 -0
- package/kernel/Wide.luau +267 -0
- package/package.json +15 -32
- package/runtime/Boundary.luau +180 -0
- package/runtime/Dispatch.luau +91 -0
- package/runtime/Handles.luau +114 -0
- package/runtime/Handshake.luau +90 -0
- package/runtime/Pending.luau +196 -0
- package/runtime/Router.luau +379 -0
- package/runtime/Session.luau +731 -0
- package/shape/Compile.luau +340 -0
- package/shape/Folds.luau +332 -0
- package/shape/Frames.luau +170 -0
- package/shape/Grid.luau +169 -0
- package/shape/Ir.luau +540 -0
- package/shape/Joins.luau +125 -0
- package/shape/Legality.luau +273 -0
- package/shape/Lower.luau +419 -0
- package/shape/Order.luau +64 -0
- package/shape/Regions.luau +113 -0
- package/shape/Rotation.luau +472 -0
- package/shape/Serial.luau +258 -0
- package/shape/Words.luau +89 -0
- package/shape/emit/Block.luau +453 -0
- package/shape/emit/Column.luau +338 -0
- package/shape/emit/Leaf.luau +462 -0
- package/shape/emit/Word.luau +234 -0
- package/shape/emit/init.luau +222 -0
- package/shape/init.luau +78 -0
- package/state/Apply.luau +330 -0
- package/state/Audience.luau +126 -0
- package/state/Catchup.luau +218 -0
- package/state/Coalesce.luau +43 -0
- package/state/Fieldset.luau +177 -0
- package/state/Newest.luau +339 -0
- package/state/Plan.luau +441 -0
- package/state/Sections.luau +468 -0
- package/state/Store.luau +188 -0
- package/state/Sync.luau +762 -0
- package/wire/Bytes.luau +118 -0
- package/wire/Clock.luau +37 -0
- package/wire/Protocol.luau +110 -0
- package/wire/Sequence.luau +40 -0
- package/wire/Varint.luau +124 -0
- package/src/Types.luau +0 -180
- package/src/api/Group.luau +0 -156
- package/src/api/Packet.luau +0 -317
- package/src/api/Query.luau +0 -338
- package/src/api/Scope.luau +0 -90
- package/src/api/Signal.luau +0 -193
- package/src/codec/Base.luau +0 -136
- package/src/codec/composite/Array.luau +0 -473
- package/src/codec/composite/Map.luau +0 -485
- package/src/codec/composite/Optional.luau +0 -54
- package/src/codec/composite/Shared.luau +0 -311
- package/src/codec/composite/Struct.luau +0 -494
- package/src/codec/composite/Tagged.luau +0 -103
- package/src/codec/composite/Tuple.luau +0 -143
- package/src/codec/datatype/Buffer.luau +0 -66
- package/src/codec/datatype/CFrame.luau +0 -109
- package/src/codec/datatype/Color.luau +0 -32
- package/src/codec/datatype/Instance.luau +0 -52
- package/src/codec/datatype/IntVector.luau +0 -39
- package/src/codec/datatype/NumberRange.luau +0 -39
- package/src/codec/datatype/Ray.luau +0 -36
- package/src/codec/datatype/Rect.luau +0 -31
- package/src/codec/datatype/Region.luau +0 -62
- package/src/codec/datatype/Sequence.luau +0 -184
- package/src/codec/datatype/String.luau +0 -94
- package/src/codec/datatype/UDim.luau +0 -46
- package/src/codec/datatype/Vector.luau +0 -130
- package/src/codec/meta/Auto.luau +0 -318
- package/src/codec/meta/Bitfield.luau +0 -160
- package/src/codec/meta/Custom.luau +0 -33
- package/src/codec/meta/DeltaScalar.luau +0 -390
- package/src/codec/meta/Enum.luau +0 -50
- package/src/codec/meta/Float.luau +0 -38
- package/src/codec/meta/Nothing.luau +0 -13
- package/src/codec/meta/Unknown.luau +0 -41
- package/src/codec/primitive/Bool.luau +0 -26
- package/src/codec/primitive/Float16.luau +0 -99
- package/src/codec/primitive/Int.luau +0 -59
- package/src/codec/primitive/Number.luau +0 -24
- package/src/codec/primitive/Signed.luau +0 -32
- package/src/codec/primitive/Varint.luau +0 -165
- package/src/codec/primitive/Zint.luau +0 -99
- package/src/index.d.ts +0 -423
- package/src/init.luau +0 -362
- package/src/internal/Baseline.luau +0 -57
- package/src/internal/Channel.luau +0 -484
- package/src/internal/Middleware.luau +0 -100
- package/src/internal/Pool.luau +0 -66
- package/src/internal/Registry.luau +0 -119
- package/src/internal/Transport.luau +0 -28
- package/src/transport/Bridge.luau +0 -110
- package/src/transport/Client.luau +0 -97
- package/src/transport/Gate.luau +0 -488
- package/src/transport/Reader.luau +0 -331
- package/src/transport/Server.luau +0 -233
- package/src/util/Array.luau +0 -18
- package/src/util/Buffer.luau +0 -90
- package/src/util/Constants.luau +0 -30
- package/src/util/Log.luau +0 -68
- package/src/util/Player.luau +0 -14
- package/src/util/Quantize.luau +0 -84
- package/src/util/Quat.luau +0 -124
package/src/api/Group.luau
DELETED
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
--!strict
|
|
2
|
-
--!optimize 2
|
|
3
|
-
-- Named player sets with __iter and auto-cleanup on PlayerRemoving.
|
|
4
|
-
|
|
5
|
-
local Players = game:GetService("Players")
|
|
6
|
-
|
|
7
|
-
local Array = require(script.Parent.Parent.util.Array)
|
|
8
|
-
local Log = require(script.Parent.Parent.util.Log)
|
|
9
|
-
|
|
10
|
-
-- Public types -----------------------------------------------------------
|
|
11
|
-
|
|
12
|
-
export type GroupHandle = {
|
|
13
|
-
add: (self: GroupHandle, player: Player) -> boolean,
|
|
14
|
-
remove: (self: GroupHandle, player: Player) -> boolean,
|
|
15
|
-
has: (self: GroupHandle, player: Player) -> boolean,
|
|
16
|
-
count: (self: GroupHandle) -> number,
|
|
17
|
-
destroy: (self: GroupHandle) -> (),
|
|
18
|
-
_lyncKind: "group",
|
|
19
|
-
_members: { [Player]: boolean },
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
type GroupInternal = GroupHandle & { _count: number, _name: string }
|
|
23
|
-
|
|
24
|
-
-- State ------------------------------------------------------------------
|
|
25
|
-
|
|
26
|
-
local _groups: { [string]: GroupInternal } = {}
|
|
27
|
-
-- Reverse index used by PlayerRemoving so we don't scan every group on disconnect.
|
|
28
|
-
local _playerCleanup: { [Player]: { Group } } = {}
|
|
29
|
-
local _cleanupConnected = false
|
|
30
|
-
|
|
31
|
-
-- Private ----------------------------------------------------------------
|
|
32
|
-
|
|
33
|
-
local swapRemove = Array.swapRemove
|
|
34
|
-
|
|
35
|
-
-- Connect once on the first Group.create; subsequent creates reuse the same connection.
|
|
36
|
-
local function ensureCleanup(): ()
|
|
37
|
-
if _cleanupConnected then
|
|
38
|
-
return
|
|
39
|
-
end
|
|
40
|
-
_cleanupConnected = true
|
|
41
|
-
|
|
42
|
-
Players.PlayerRemoving:Connect(function(player: Player)
|
|
43
|
-
local groups = _playerCleanup[player]
|
|
44
|
-
if not groups then
|
|
45
|
-
return
|
|
46
|
-
end
|
|
47
|
-
for _, group in groups do
|
|
48
|
-
group._members[player] = nil
|
|
49
|
-
group._count -= 1
|
|
50
|
-
end
|
|
51
|
-
_playerCleanup[player] = nil
|
|
52
|
-
end)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
local function untrackCleanup(player: Player, group: GroupInternal): ()
|
|
56
|
-
local cleanup = _playerCleanup[player]
|
|
57
|
-
if not cleanup then
|
|
58
|
-
return
|
|
59
|
-
end
|
|
60
|
-
local idx = table.find(cleanup, group)
|
|
61
|
-
if idx then
|
|
62
|
-
swapRemove(cleanup, idx)
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
-- Public -----------------------------------------------------------------
|
|
67
|
-
|
|
68
|
-
local Group = {}
|
|
69
|
-
|
|
70
|
-
local GroupMeta = {}
|
|
71
|
-
GroupMeta.__index = GroupMeta
|
|
72
|
-
|
|
73
|
-
-- __iter lets `for player in group do` skip the explicit :members() call.
|
|
74
|
-
function GroupMeta.__iter(self: GroupInternal): (any, any, any)
|
|
75
|
-
return next, self._members, nil
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
function GroupMeta.add(self: GroupInternal, player: Player): boolean
|
|
79
|
-
if self._members[player] then
|
|
80
|
-
return false
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
self._members[player] = true
|
|
84
|
-
self._count += 1
|
|
85
|
-
|
|
86
|
-
local cleanup = _playerCleanup[player]
|
|
87
|
-
if not cleanup then
|
|
88
|
-
cleanup = {}
|
|
89
|
-
_playerCleanup[player] = cleanup
|
|
90
|
-
end
|
|
91
|
-
table.insert(cleanup, self)
|
|
92
|
-
return true
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
function GroupMeta.remove(self: GroupInternal, player: Player): boolean
|
|
96
|
-
if not self._members[player] then
|
|
97
|
-
return false
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
self._members[player] = nil
|
|
101
|
-
self._count -= 1
|
|
102
|
-
untrackCleanup(player, self)
|
|
103
|
-
return true
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
function GroupMeta.has(self: GroupInternal, player: Player): boolean
|
|
107
|
-
return self._members[player] == true
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
function GroupMeta.count(self: GroupInternal): number
|
|
111
|
-
return self._count
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
function GroupMeta.destroy(self: GroupInternal): ()
|
|
115
|
-
if _groups[self._name] == self then
|
|
116
|
-
_groups[self._name] = nil
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
for player in self._members do
|
|
120
|
-
untrackCleanup(player, self)
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
table.clear(self._members)
|
|
124
|
-
self._count = 0
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
table.freeze(GroupMeta)
|
|
128
|
-
|
|
129
|
-
function Group.create(name: string): GroupHandle
|
|
130
|
-
if _groups[name] then
|
|
131
|
-
Log.error(`"{name}" already exists`)
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
ensureCleanup()
|
|
135
|
-
|
|
136
|
-
local group = setmetatable({
|
|
137
|
-
_lyncKind = "group" :: "group",
|
|
138
|
-
_members = {} :: { [Player]: boolean },
|
|
139
|
-
_count = 0,
|
|
140
|
-
_name = name,
|
|
141
|
-
}, GroupMeta) :: any
|
|
142
|
-
|
|
143
|
-
_groups[name] = group
|
|
144
|
-
return group
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
function Group.reset(): ()
|
|
148
|
-
for _, group in _groups do
|
|
149
|
-
table.clear(group._members)
|
|
150
|
-
group._count = 0
|
|
151
|
-
end
|
|
152
|
-
table.clear(_groups)
|
|
153
|
-
table.clear(_playerCleanup)
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
return table.freeze(Group)
|
package/src/api/Packet.luau
DELETED
|
@@ -1,317 +0,0 @@
|
|
|
1
|
-
--!strict
|
|
2
|
-
--!optimize 2
|
|
3
|
-
-- Packet definition: send, on, once, wait, stats.
|
|
4
|
-
|
|
5
|
-
local Players = game:GetService("Players")
|
|
6
|
-
local RunService = game:GetService("RunService")
|
|
7
|
-
|
|
8
|
-
local Baseline = require(script.Parent.Parent.internal.Baseline)
|
|
9
|
-
local Channel = require(script.Parent.Parent.internal.Channel)
|
|
10
|
-
local Log = require(script.Parent.Parent.util.Log)
|
|
11
|
-
local Middleware = require(script.Parent.Parent.internal.Middleware)
|
|
12
|
-
local Player = require(script.Parent.Parent.util.Player)
|
|
13
|
-
local Registry = require(script.Parent.Parent.internal.Registry)
|
|
14
|
-
local Shared = require(script.Parent.Parent.codec.composite.Shared)
|
|
15
|
-
local Transport = require(script.Parent.Parent.internal.Transport)
|
|
16
|
-
local Types = require(script.Parent.Parent.Types)
|
|
17
|
-
|
|
18
|
-
-- Constants --------------------------------------------------------------
|
|
19
|
-
|
|
20
|
-
local IS_SERVER = RunService:IsServer()
|
|
21
|
-
|
|
22
|
-
-- mode: TS_* tag; headerSize: 1 (frame byte) + timestamp bytes (1, 2, or 8).
|
|
23
|
-
local TS_MODES: { [string]: { mode: number, headerSize: number } } = table.freeze({
|
|
24
|
-
frame = table.freeze({ mode = Channel.TS_FRAME, headerSize = 2 }),
|
|
25
|
-
offset = table.freeze({ mode = Channel.TS_OFFSET, headerSize = 3 }),
|
|
26
|
-
full = table.freeze({ mode = Channel.TS_FULL, headerSize = 9 }),
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
local EMPTY_OPTIONS: Types.PacketOptions = table.freeze({})
|
|
30
|
-
|
|
31
|
-
-- Private ----------------------------------------------------------------
|
|
32
|
-
|
|
33
|
-
local isPlayer = Player.is
|
|
34
|
-
|
|
35
|
-
local function resolveTimestampMode(ts: ("frame" | "offset" | "full")?): (number, number)
|
|
36
|
-
if ts == nil then
|
|
37
|
-
return Channel.TS_NONE, 1
|
|
38
|
-
end
|
|
39
|
-
local entry = TS_MODES[ts]
|
|
40
|
-
Channel.enableTimestamps()
|
|
41
|
-
return entry.mode, entry.headerSize
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
-- Public types -----------------------------------------------------------
|
|
45
|
-
|
|
46
|
-
export type PacketHandle<T> = {
|
|
47
|
-
send: (self: PacketHandle<T>, data: T, target: any?) -> (),
|
|
48
|
-
on: (
|
|
49
|
-
self: PacketHandle<T>,
|
|
50
|
-
fn: (data: T, sender: Player?, timestamp: number?) -> ()
|
|
51
|
-
) -> Types.Connection,
|
|
52
|
-
once: (
|
|
53
|
-
self: PacketHandle<T>,
|
|
54
|
-
fn: (data: T, sender: Player?, timestamp: number?) -> ()
|
|
55
|
-
) -> Types.Connection,
|
|
56
|
-
wait: (self: PacketHandle<T>) -> (T, Player?, number?),
|
|
57
|
-
name: (self: PacketHandle<T>) -> string,
|
|
58
|
-
stats: (self: PacketHandle<T>) -> Types.PacketStats,
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
-- Public -----------------------------------------------------------------
|
|
62
|
-
|
|
63
|
-
local Packet = {}
|
|
64
|
-
|
|
65
|
-
function Packet.define<T>(
|
|
66
|
-
name: string,
|
|
67
|
-
codec: Types.InternalCodec<T>,
|
|
68
|
-
options: Types.PacketOptions?
|
|
69
|
-
): PacketHandle<T>
|
|
70
|
-
local opts = options or EMPTY_OPTIONS
|
|
71
|
-
local isUnreliable = opts.unreliable or false
|
|
72
|
-
|
|
73
|
-
-- Delta + unreliable is unsafe: a dropped frame permanently desyncs the receiver baseline.
|
|
74
|
-
if isUnreliable and codec._isDelta then
|
|
75
|
-
Log.error(
|
|
76
|
-
`"{name}" delta codecs need reliable transport (lost packets desync the baseline)`
|
|
77
|
-
)
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
if codec._hasUnknown and not opts.validate then
|
|
81
|
-
Log.warn(`"{name}" uses unknown codec without validate; data bypasses schema validation`)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
if codec._isDelta then
|
|
85
|
-
Baseline.markHasDelta()
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
local tsMode, headerSize = resolveTimestampMode(opts.timestamp)
|
|
89
|
-
local openFn = Channel.resolveOpenFn(tsMode, name)
|
|
90
|
-
|
|
91
|
-
local reg = Registry.register({
|
|
92
|
-
name = name,
|
|
93
|
-
kind = Registry.KIND_PACKET,
|
|
94
|
-
codec = codec,
|
|
95
|
-
isUnreliable = isUnreliable,
|
|
96
|
-
partner = nil,
|
|
97
|
-
needsGate = IS_SERVER,
|
|
98
|
-
headerSize = headerSize,
|
|
99
|
-
timestampMode = tsMode,
|
|
100
|
-
openFn = openFn,
|
|
101
|
-
rateLimit = opts.rateLimit,
|
|
102
|
-
validate = opts.validate,
|
|
103
|
-
maxPayloadBytes = opts.maxPayloadBytes,
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
local function sendToPlayer(player: Player, data: any): ()
|
|
107
|
-
local ch = Transport.server().getChannel(player, isUnreliable)
|
|
108
|
-
Channel.writeBatch(ch, reg, data)
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
local function bumpFires(): ()
|
|
112
|
-
if Channel.statsEnabled() then
|
|
113
|
-
reg.fires += 1
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
--[[
|
|
118
|
-
Run the send middleware chain. Returns (dropped, value). A nil value
|
|
119
|
-
is a legitimate payload (Lync.nothing); only the explicit Lync.DROP
|
|
120
|
-
sentinel or a hook returning DROP triggers the drop branch.
|
|
121
|
-
]]
|
|
122
|
-
local function applySend(data: any, player: Player?): (boolean, any)
|
|
123
|
-
if not Middleware.hasSendHooks() then
|
|
124
|
-
return false, data
|
|
125
|
-
end
|
|
126
|
-
local sendData = Middleware.runSend(data, name, player)
|
|
127
|
-
if typeof(sendData) == "table" and sendData._lyncKind == "drop" then
|
|
128
|
-
return true, nil
|
|
129
|
-
end
|
|
130
|
-
return false, sendData
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
-- Non-delta codecs are stateless wire-encoders, so broadcast can encode
|
|
134
|
-
-- once and bufCopy the payload to every player. Falls through if the
|
|
135
|
-
-- encoded payload includes ref indices (the indices would need rewriting
|
|
136
|
-
-- per channel, which no codec exposes).
|
|
137
|
-
local canEncodeOnce = not codec._isDelta and not codec._hasDelta
|
|
138
|
-
|
|
139
|
-
local function broadcast(players: { Player }, data: any): ()
|
|
140
|
-
local count = #players
|
|
141
|
-
if count == 0 then
|
|
142
|
-
bumpFires()
|
|
143
|
-
return
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
if canEncodeOnce then
|
|
147
|
-
local scratch = Shared.acquireScratch()
|
|
148
|
-
scratch.currentPacket = name
|
|
149
|
-
codec.write(scratch, data)
|
|
150
|
-
scratch.currentPacket = nil
|
|
151
|
-
if scratch.refCount == 0 then
|
|
152
|
-
local payload = scratch.buff
|
|
153
|
-
local payloadLen = scratch.cursor
|
|
154
|
-
local server = Transport.server()
|
|
155
|
-
local getChannel = if isUnreliable
|
|
156
|
-
then server.getUnreliableChannel
|
|
157
|
-
else server.getReliableChannel
|
|
158
|
-
-- Channel.writeBatchEncoded is hot-swapped by enableStats; re-read per call.
|
|
159
|
-
local writeBatchEncoded = Channel.writeBatchEncoded
|
|
160
|
-
for i = 1, count do
|
|
161
|
-
writeBatchEncoded(getChannel(players[i]), reg, payload, payloadLen)
|
|
162
|
-
end
|
|
163
|
-
Shared.releaseScratch()
|
|
164
|
-
bumpFires()
|
|
165
|
-
return
|
|
166
|
-
end
|
|
167
|
-
Shared.releaseScratch()
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
for i = 1, count do
|
|
171
|
-
sendToPlayer(players[i], data)
|
|
172
|
-
end
|
|
173
|
-
bumpFires()
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
--[[
|
|
177
|
-
Resolve a target table into a { Player } list. Returns nil for unknown
|
|
178
|
-
sentinel kinds; the caller errors with the original target type.
|
|
179
|
-
]]
|
|
180
|
-
local function resolveAudience(target: any): { Player }?
|
|
181
|
-
local kind = target._lyncKind
|
|
182
|
-
if kind == "all" then
|
|
183
|
-
return Players:GetPlayers()
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
if kind == "except" then
|
|
187
|
-
local excluded = target._excluded :: { [Player]: boolean }
|
|
188
|
-
local all = Players:GetPlayers()
|
|
189
|
-
local list = table.create(#all)
|
|
190
|
-
local n = 0
|
|
191
|
-
for _, player in all do
|
|
192
|
-
if not excluded[player] then
|
|
193
|
-
n += 1
|
|
194
|
-
list[n] = player
|
|
195
|
-
end
|
|
196
|
-
end
|
|
197
|
-
return list
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
if kind == "group" then
|
|
201
|
-
local members = target._members :: { [Player]: boolean }
|
|
202
|
-
local list: { Player } = {}
|
|
203
|
-
local n = 0
|
|
204
|
-
for player in members do
|
|
205
|
-
n += 1
|
|
206
|
-
list[n] = player
|
|
207
|
-
end
|
|
208
|
-
return list
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
if kind == nil then
|
|
212
|
-
-- Plain { Player } array. Validate entries on the way to a clean list.
|
|
213
|
-
local list: { Player } = {}
|
|
214
|
-
local n = 0
|
|
215
|
-
for _, player in target do
|
|
216
|
-
if isPlayer(player) then
|
|
217
|
-
n += 1
|
|
218
|
-
list[n] = player :: Player
|
|
219
|
-
end
|
|
220
|
-
end
|
|
221
|
-
return list
|
|
222
|
-
end
|
|
223
|
-
|
|
224
|
-
return nil
|
|
225
|
-
end
|
|
226
|
-
|
|
227
|
-
local function sendToTarget(data: any, target: any): ()
|
|
228
|
-
if isPlayer(target) then
|
|
229
|
-
local dropped, sendData = applySend(data, target :: Player)
|
|
230
|
-
if dropped then
|
|
231
|
-
return
|
|
232
|
-
end
|
|
233
|
-
sendToPlayer(target :: Player, sendData)
|
|
234
|
-
bumpFires()
|
|
235
|
-
return
|
|
236
|
-
end
|
|
237
|
-
|
|
238
|
-
if typeof(target) == "table" then
|
|
239
|
-
local dropped, sendData = applySend(data, nil)
|
|
240
|
-
if dropped then
|
|
241
|
-
return
|
|
242
|
-
end
|
|
243
|
-
local audience = resolveAudience(target)
|
|
244
|
-
if audience then
|
|
245
|
-
broadcast(audience, sendData)
|
|
246
|
-
return
|
|
247
|
-
end
|
|
248
|
-
end
|
|
249
|
-
|
|
250
|
-
Log.error(`"{name}" expected Player, table, Group, or Lync.all, got {typeof(target)}`)
|
|
251
|
-
end
|
|
252
|
-
|
|
253
|
-
local function sendFromServer(data: any, target: any): ()
|
|
254
|
-
if target == nil then
|
|
255
|
-
Log.error(`"{name}" server send requires a target`)
|
|
256
|
-
end
|
|
257
|
-
sendToTarget(data, target)
|
|
258
|
-
end
|
|
259
|
-
|
|
260
|
-
local function sendFromClient(data: any): ()
|
|
261
|
-
local dropped, sendData = applySend(data, nil)
|
|
262
|
-
if dropped then
|
|
263
|
-
return
|
|
264
|
-
end
|
|
265
|
-
local ch = Transport.client().getChannel(isUnreliable)
|
|
266
|
-
Channel.writeBatch(ch, reg, sendData)
|
|
267
|
-
bumpFires()
|
|
268
|
-
end
|
|
269
|
-
|
|
270
|
-
type Self = PacketHandle<T>
|
|
271
|
-
type Listener = (data: T, sender: Player?, timestamp: number?) -> ()
|
|
272
|
-
|
|
273
|
-
local handle = {
|
|
274
|
-
send = function(_self: Self, data: T, target: any?): ()
|
|
275
|
-
if IS_SERVER then
|
|
276
|
-
sendFromServer(data, target)
|
|
277
|
-
else
|
|
278
|
-
sendFromClient(data)
|
|
279
|
-
end
|
|
280
|
-
end,
|
|
281
|
-
|
|
282
|
-
on = function(_self: Self, fn: Listener): Types.Connection
|
|
283
|
-
return reg.signal:connect(fn :: any)
|
|
284
|
-
end,
|
|
285
|
-
|
|
286
|
-
once = function(_self: Self, fn: Listener): Types.Connection
|
|
287
|
-
local conn: Types.Connection
|
|
288
|
-
conn = reg.signal:connect(function(...: any)
|
|
289
|
-
conn:disconnect()
|
|
290
|
-
fn(...)
|
|
291
|
-
end)
|
|
292
|
-
return conn
|
|
293
|
-
end,
|
|
294
|
-
|
|
295
|
-
wait = function(_self: Self): (T, Player?, number?)
|
|
296
|
-
return reg.signal:wait()
|
|
297
|
-
end,
|
|
298
|
-
|
|
299
|
-
name = function(_self: Self): string
|
|
300
|
-
return reg.name
|
|
301
|
-
end,
|
|
302
|
-
|
|
303
|
-
stats = function(_self: Self): Types.PacketStats
|
|
304
|
-
return {
|
|
305
|
-
bytesSent = reg.bytesSent,
|
|
306
|
-
bytesReceived = reg.bytesReceived,
|
|
307
|
-
fires = reg.fires,
|
|
308
|
-
recvFires = reg.recvFires,
|
|
309
|
-
drops = reg.drops,
|
|
310
|
-
}
|
|
311
|
-
end,
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
return table.freeze(handle) :: PacketHandle<T>
|
|
315
|
-
end
|
|
316
|
-
|
|
317
|
-
return table.freeze(Packet)
|