@rbxts/replecs 0.4.0-rc.2.ts.1 → 0.4.0-rc.4
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/out/replecs/client/init.luau +22 -16
- package/out/replecs/handshake.luau +35 -0
- package/out/replecs/index.d.ts +43 -0
- package/out/replecs/init.luau +8 -0
- package/out/replecs/server/filter_group.luau +297 -123
- package/out/replecs/server/init.luau +177 -140
- package/out/replecs/server/registry.luau +30 -1
- package/out/replecs/shared.luau +3 -1
- package/out/replecs/types.luau +3 -0
- package/out/replecs/ver.luau +1 -1
- package/package.json +3 -2
|
@@ -1,196 +1,370 @@
|
|
|
1
|
+
--!optimize 2
|
|
1
2
|
local types = require (script.Parent.Parent:WaitForChild('types'))
|
|
2
3
|
local registry = require (script.Parent:WaitForChild('registry'))
|
|
3
4
|
local bitmasks = require (script.Parent:WaitForChild('bitmasks'))
|
|
4
5
|
local utils = require (script.Parent:WaitForChild('utils'))
|
|
5
|
-
local common = require (script.Parent.Parent:WaitForChild('common'))
|
|
6
6
|
|
|
7
7
|
type Bitmask = buffer
|
|
8
|
+
type Player = any
|
|
8
9
|
|
|
9
10
|
type FilterSimple = types.FilterSimple
|
|
11
|
+
type FilterPredicator = types.FilterPredicator
|
|
10
12
|
|
|
11
13
|
type Set<T> = { [T]: boolean }
|
|
12
|
-
type Map<K, V> = { [K]: V }
|
|
13
14
|
type Array<T> = { T }
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
type Registry = registry.Registry
|
|
16
|
+
|
|
17
|
+
local KINDS = {
|
|
18
|
+
source = 1,
|
|
19
|
+
predicate = 2,
|
|
20
|
+
intersect = 3,
|
|
21
|
+
union = 4,
|
|
22
|
+
exclude = 5,
|
|
20
23
|
}
|
|
21
24
|
|
|
22
|
-
export type
|
|
25
|
+
export type FilterNodeClass = {
|
|
26
|
+
kind: number,
|
|
27
|
+
registry: Registry?,
|
|
23
28
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
29
|
+
inputs: Array<FilterNode>,
|
|
30
|
+
input_versions: Array<number>,
|
|
31
|
+
dependents: Set<FilterNode>,
|
|
28
32
|
|
|
29
|
-
export type FilterGroupClass = {
|
|
30
|
-
registry: registry.Registry,
|
|
31
|
-
parent: FilterGroup?,
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
value: Bitmask?,
|
|
35
|
+
scratch: Bitmask?,
|
|
36
|
+
version: number,
|
|
37
|
+
dirty: boolean,
|
|
38
|
+
resolved_epoch: number,
|
|
39
|
+
resolved_cycle: number,
|
|
37
40
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
-- source only
|
|
42
|
+
member_set: Set<Player>?,
|
|
43
|
+
inverted: boolean?,
|
|
44
|
+
predicator: FilterPredicator?,
|
|
42
45
|
}
|
|
43
46
|
|
|
44
|
-
local
|
|
45
|
-
|
|
47
|
+
local filter_node = {}
|
|
48
|
+
filter_node.__index = filter_node
|
|
46
49
|
|
|
47
|
-
export type
|
|
50
|
+
export type FilterNode = FilterNodeClass & typeof(filter_node)
|
|
51
|
+
export type FilterOperand = FilterNode | FilterSimple
|
|
48
52
|
|
|
49
|
-
function
|
|
50
|
-
return typeof(value) == "table" and getmetatable(value) ==
|
|
53
|
+
function filter_node.is_filter_node(value: any): boolean
|
|
54
|
+
return typeof(value) == "table" and getmetatable(value) == filter_node
|
|
51
55
|
end
|
|
52
56
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
function filter_node.bind(node: FilterNode, reg: Registry)
|
|
58
|
+
if node.registry == reg then
|
|
59
|
+
return
|
|
60
|
+
end
|
|
61
|
+
if node.registry then
|
|
62
|
+
error "filter is already bound to a different server"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
node.registry = reg
|
|
66
|
+
node.value = buffer.create(reg.bitmask_size)
|
|
67
|
+
node.scratch = buffer.create(reg.bitmask_size)
|
|
68
|
+
|
|
69
|
+
for _, input in node.inputs do
|
|
70
|
+
filter_node.bind(input, reg)
|
|
56
71
|
end
|
|
57
72
|
end
|
|
58
73
|
|
|
59
|
-
function
|
|
60
|
-
local
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
74
|
+
local function create_node(kind: number, reg: Registry?): FilterNode
|
|
75
|
+
local self: FilterNodeClass = {
|
|
76
|
+
kind = kind,
|
|
77
|
+
registry = nil,
|
|
78
|
+
|
|
79
|
+
inputs = {},
|
|
80
|
+
input_versions = {},
|
|
81
|
+
dependents = setmetatable({}, { __mode = "k" }) :: any,
|
|
82
|
+
|
|
83
|
+
value = nil,
|
|
84
|
+
scratch = nil,
|
|
85
|
+
version = 0,
|
|
86
|
+
dirty = true,
|
|
87
|
+
resolved_epoch = -1,
|
|
88
|
+
resolved_cycle = -1,
|
|
89
|
+
|
|
90
|
+
member_set = nil,
|
|
91
|
+
inverted = nil,
|
|
92
|
+
predicator = nil,
|
|
93
|
+
}
|
|
94
|
+
setmetatable(self, filter_node)
|
|
95
|
+
|
|
96
|
+
local node = self :: any
|
|
97
|
+
if reg then
|
|
98
|
+
filter_node.bind(node, reg)
|
|
99
|
+
end
|
|
100
|
+
return node
|
|
64
101
|
end
|
|
65
102
|
|
|
66
|
-
function
|
|
67
|
-
|
|
68
|
-
local index = connected.listeners_indexes[listener]
|
|
69
|
-
if not index then
|
|
103
|
+
local function mark_dirty(node: FilterNode)
|
|
104
|
+
if node.dirty then
|
|
70
105
|
return
|
|
71
106
|
end
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
connected.listeners[index] = last_listener
|
|
76
|
-
connected.listeners_indexes[last_listener] = index
|
|
107
|
+
node.dirty = true
|
|
108
|
+
for dependent in node.dependents do
|
|
109
|
+
mark_dirty(dependent)
|
|
77
110
|
end
|
|
78
|
-
connected.listeners_indexes[listener] = nil
|
|
79
111
|
end
|
|
80
112
|
|
|
81
|
-
local function
|
|
82
|
-
if
|
|
83
|
-
|
|
84
|
-
else
|
|
85
|
-
return self.registry:create_bitmask_from_member(filter)
|
|
113
|
+
local function assert_source(node: FilterNode, method: string)
|
|
114
|
+
if node.kind ~= KINDS.source then
|
|
115
|
+
error(`{method}() is only available on source filters, derived filters are read only`)
|
|
86
116
|
end
|
|
87
117
|
end
|
|
88
118
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
119
|
+
|
|
120
|
+
local function resolve_source(node: FilterNode, reg: Registry, scratch: Bitmask)
|
|
121
|
+
bitmasks.clear(scratch)
|
|
122
|
+
for member in node.member_set :: Set<Player> do
|
|
123
|
+
local index = registry.resolve_member(reg, member)
|
|
124
|
+
if index then
|
|
125
|
+
bitmasks.set(scratch, index)
|
|
126
|
+
end
|
|
95
127
|
end
|
|
128
|
+
if node.inverted then
|
|
129
|
+
bitmasks.exclude(reg.registered_bitmask, scratch, scratch)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
96
132
|
|
|
97
|
-
local filter_bitmask = create_filter_bitmask(self, filter.filter)
|
|
98
133
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
134
|
+
local function resolve_predicate(node: FilterNode, reg: Registry, scratch: Bitmask)
|
|
135
|
+
bitmasks.clear(scratch)
|
|
136
|
+
local predicator = node.predicator :: FilterPredicator
|
|
137
|
+
for member, index in reg.client_indexes do
|
|
138
|
+
if predicator(member) then
|
|
139
|
+
bitmasks.set(scratch, index)
|
|
140
|
+
end
|
|
105
141
|
end
|
|
106
142
|
end
|
|
107
143
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
local
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
144
|
+
|
|
145
|
+
local function resolve_computed(node: FilterNode, scratch: Bitmask): boolean
|
|
146
|
+
local inputs = node.inputs
|
|
147
|
+
local input_versions = node.input_versions
|
|
148
|
+
|
|
149
|
+
local changed = false
|
|
150
|
+
for i, input in inputs do
|
|
151
|
+
filter_node.resolve(input)
|
|
152
|
+
if input.version ~= input_versions[i] then
|
|
153
|
+
changed = true
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
if not changed then
|
|
157
|
+
return false
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
for i, input in inputs do
|
|
161
|
+
input_versions[i] = input.version
|
|
115
162
|
end
|
|
116
163
|
|
|
117
|
-
|
|
118
|
-
|
|
164
|
+
bitmasks.load(inputs[1].value :: Bitmask, scratch)
|
|
165
|
+
local kind = node.kind
|
|
166
|
+
local op: (Bitmask, Bitmask, Bitmask) -> () = if kind == KINDS.intersect
|
|
167
|
+
then bitmasks.band
|
|
168
|
+
elseif kind == KINDS.union then bitmasks.bor
|
|
169
|
+
else bitmasks.exclude
|
|
170
|
+
for i = 2, #inputs do
|
|
171
|
+
op(scratch, inputs[i].value :: Bitmask, scratch)
|
|
172
|
+
end
|
|
173
|
+
return true
|
|
119
174
|
end
|
|
120
175
|
|
|
121
|
-
function filter_group.calculate_down(self: FilterGroup, parent_bitmask: Bitmask)
|
|
122
|
-
local bitmask = bitmasks.clone(parent_bitmask, bitmasks.get_buffer_size(self.registry.client_next_index))
|
|
123
|
-
filter_group.apply_filter(self, bitmask)
|
|
124
176
|
|
|
125
|
-
|
|
177
|
+
function filter_node.resolve(node: FilterNode): Bitmask
|
|
178
|
+
local reg = node.registry
|
|
179
|
+
if not reg then
|
|
180
|
+
error "filter is not bound to a server, pass it to a set_* call first"
|
|
181
|
+
end
|
|
182
|
+
local value = node.value :: Bitmask
|
|
183
|
+
local kind = node.kind
|
|
184
|
+
|
|
185
|
+
if kind == KINDS.predicate then
|
|
186
|
+
if node.resolved_cycle == reg.cycle then
|
|
187
|
+
return value
|
|
188
|
+
end
|
|
189
|
+
node.resolved_cycle = reg.cycle
|
|
190
|
+
elseif not node.dirty and node.resolved_epoch == reg.epoch then
|
|
191
|
+
return value
|
|
192
|
+
end
|
|
193
|
+
node.dirty = false
|
|
194
|
+
node.resolved_epoch = reg.epoch
|
|
195
|
+
|
|
196
|
+
local scratch = node.scratch :: Bitmask
|
|
197
|
+
if kind == KINDS.source then
|
|
198
|
+
resolve_source(node, reg, scratch)
|
|
199
|
+
elseif kind == KINDS.predicate then
|
|
200
|
+
resolve_predicate(node, reg, scratch)
|
|
201
|
+
elseif not resolve_computed(node, scratch) then
|
|
202
|
+
return value
|
|
203
|
+
end
|
|
126
204
|
|
|
127
|
-
|
|
128
|
-
|
|
205
|
+
if bitmasks.equals(scratch, value) then
|
|
206
|
+
return value
|
|
129
207
|
end
|
|
208
|
+
node.value = scratch
|
|
209
|
+
node.scratch = value
|
|
210
|
+
node.version += 1
|
|
211
|
+
return scratch
|
|
130
212
|
end
|
|
131
213
|
|
|
132
|
-
|
|
133
|
-
|
|
214
|
+
function filter_node.set(self: FilterNode, filter: FilterSimple)
|
|
215
|
+
assert_source(self, "set")
|
|
134
216
|
|
|
135
|
-
local
|
|
136
|
-
|
|
137
|
-
|
|
217
|
+
local members: Set<Player> = {}
|
|
218
|
+
local inverted = false
|
|
219
|
+
if typeof(filter) == "table" then
|
|
220
|
+
inverted = not utils.is_include_filter(filter)
|
|
221
|
+
for member, allow in filter :: Set<Player> do
|
|
222
|
+
if allow == inverted then
|
|
223
|
+
error "a filter set cannot mix included and excluded players"
|
|
224
|
+
end
|
|
225
|
+
members[member] = true
|
|
226
|
+
end
|
|
138
227
|
else
|
|
139
|
-
|
|
228
|
+
members[filter] = true
|
|
140
229
|
end
|
|
141
230
|
|
|
142
|
-
|
|
231
|
+
self.member_set = members
|
|
232
|
+
self.inverted = inverted
|
|
233
|
+
mark_dirty(self)
|
|
143
234
|
end
|
|
144
235
|
|
|
145
|
-
function
|
|
146
|
-
|
|
147
|
-
|
|
236
|
+
function filter_node.add(self: FilterNode, player: Player)
|
|
237
|
+
assert_source(self, "add")
|
|
238
|
+
local members = self.member_set :: Set<Player>
|
|
239
|
+
if members[player] then
|
|
240
|
+
return
|
|
148
241
|
end
|
|
242
|
+
members[player] = true
|
|
243
|
+
mark_dirty(self)
|
|
244
|
+
end
|
|
149
245
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
246
|
+
function filter_node.remove(self: FilterNode, player: Player)
|
|
247
|
+
assert_source(self, "remove")
|
|
248
|
+
local members = self.member_set :: Set<Player>
|
|
249
|
+
if not members[player] then
|
|
250
|
+
return
|
|
251
|
+
end
|
|
252
|
+
members[player] = nil
|
|
253
|
+
mark_dirty(self)
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
function filter_node.clear(self: FilterNode)
|
|
257
|
+
assert_source(self, "clear")
|
|
258
|
+
local members = self.member_set :: Set<Player>
|
|
259
|
+
if next(members) == nil then
|
|
260
|
+
return
|
|
261
|
+
end
|
|
262
|
+
table.clear(members)
|
|
263
|
+
mark_dirty(self)
|
|
155
264
|
end
|
|
156
265
|
|
|
157
|
-
function filter_group.filter(self: FilterGroup, filter: FilterSimple)
|
|
158
|
-
local mode = FILTER_MODES.exclude
|
|
159
266
|
|
|
160
|
-
|
|
161
|
-
|
|
267
|
+
function filter_node.create_source(reg: Registry?, initial: FilterSimple?): FilterNode
|
|
268
|
+
local node = create_node(KINDS.source, reg)
|
|
269
|
+
node.member_set = {}
|
|
270
|
+
node.inverted = false
|
|
271
|
+
if initial ~= nil then
|
|
272
|
+
filter_node.set(node, initial)
|
|
162
273
|
end
|
|
274
|
+
return node
|
|
275
|
+
end
|
|
163
276
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
277
|
+
function filter_node.create_everyone(reg: Registry?): FilterNode
|
|
278
|
+
local node = create_node(KINDS.source, reg)
|
|
279
|
+
node.member_set = {}
|
|
280
|
+
node.inverted = true
|
|
281
|
+
return node
|
|
169
282
|
end
|
|
170
283
|
|
|
171
|
-
function
|
|
172
|
-
local
|
|
173
|
-
|
|
284
|
+
function filter_node.create_predicate(reg: Registry?, predicator: FilterPredicator): FilterNode
|
|
285
|
+
local node = create_node(KINDS.predicate, reg)
|
|
286
|
+
node.predicator = predicator
|
|
287
|
+
return node
|
|
288
|
+
end
|
|
174
289
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
290
|
+
local function to_node(operand: FilterOperand): FilterNode
|
|
291
|
+
if filter_node.is_filter_node(operand) then
|
|
292
|
+
return operand :: FilterNode
|
|
293
|
+
end
|
|
294
|
+
return filter_node.create_source(nil, operand :: FilterSimple)
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
local function create_computed(kind: number, base: FilterNode, operands: Array<FilterOperand>): FilterNode
|
|
298
|
+
local node = create_node(kind, nil)
|
|
299
|
+
local inputs = node.inputs
|
|
300
|
+
local input_versions = node.input_versions
|
|
301
|
+
|
|
302
|
+
inputs[1] = base
|
|
303
|
+
input_versions[1] = -1
|
|
304
|
+
local reg = base.registry
|
|
305
|
+
|
|
306
|
+
for i, operand in operands do
|
|
307
|
+
local input = to_node(operand)
|
|
308
|
+
inputs[i + 1] = input
|
|
309
|
+
input_versions[i + 1] = -1
|
|
310
|
+
reg = reg or input.registry
|
|
311
|
+
end
|
|
183
312
|
|
|
184
|
-
|
|
185
|
-
|
|
313
|
+
for _, input in inputs do
|
|
314
|
+
input.dependents[node] = true
|
|
315
|
+
end
|
|
316
|
+
if reg then
|
|
317
|
+
filter_node.bind(node, reg)
|
|
318
|
+
end
|
|
319
|
+
return node
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
function filter_node.filter(self: FilterNode, ...: FilterOperand): FilterNode
|
|
323
|
+
return create_computed(KINDS.intersect, self, { ... })
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
function filter_node.extend(self: FilterNode, ...: FilterOperand): FilterNode
|
|
327
|
+
return create_computed(KINDS.union, self, { ... })
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
function filter_node.exclude(self: FilterNode, ...: FilterOperand): FilterNode
|
|
331
|
+
return create_computed(KINDS.exclude, self, { ... })
|
|
186
332
|
end
|
|
187
333
|
|
|
188
|
-
function filter_group.derive(self: FilterGroup): FilterGroup
|
|
189
|
-
local derived = filter_group.create(self.registry)
|
|
190
|
-
derived.parent = self
|
|
191
334
|
|
|
192
|
-
|
|
193
|
-
|
|
335
|
+
function filter_node.members(self: FilterNode): Set<Player>
|
|
336
|
+
local value = filter_node.resolve(self)
|
|
337
|
+
local index_clients = (self.registry :: Registry).index_clients
|
|
338
|
+
|
|
339
|
+
local members: Set<Player> = {}
|
|
340
|
+
bitmasks.iter_set(value, function(index)
|
|
341
|
+
local client = index_clients[index]
|
|
342
|
+
if client ~= nil then
|
|
343
|
+
members[client] = true
|
|
344
|
+
end
|
|
345
|
+
end)
|
|
346
|
+
return members
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
local function lookup_index(reg: Registry, player: Player): number?
|
|
350
|
+
local index = reg.client_indexes[player]
|
|
351
|
+
if index then
|
|
352
|
+
return index
|
|
353
|
+
end
|
|
354
|
+
local aliased = reg.client_aliases[player]
|
|
355
|
+
if aliased == nil then
|
|
356
|
+
return nil
|
|
357
|
+
end
|
|
358
|
+
return reg.client_indexes[aliased]
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
function filter_node.contains(self: FilterNode, player: Player): boolean
|
|
362
|
+
local value = filter_node.resolve(self)
|
|
363
|
+
local index = lookup_index(self.registry :: Registry, player)
|
|
364
|
+
if index == nil then
|
|
365
|
+
return false
|
|
366
|
+
end
|
|
367
|
+
return bitmasks.test(value, index)
|
|
194
368
|
end
|
|
195
369
|
|
|
196
|
-
return
|
|
370
|
+
return filter_node
|