@rbxts/replecs 0.3.1 → 0.4.0-rc.2
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 +1760 -0
- package/out/replecs/common.luau +17 -3
- package/out/replecs/cursor.luau +268 -0
- package/out/replecs/handshake.luau +108 -0
- package/out/replecs/init.luau +59 -15
- package/out/replecs/server/bitmasks.luau +322 -0
- package/out/replecs/server/filter_group.luau +196 -0
- package/out/replecs/server/init.luau +3937 -0
- package/out/replecs/server/registry.luau +178 -0
- package/out/replecs/server/utils.luau +20 -0
- package/out/replecs/shared.luau +70 -0
- package/out/replecs/types.luau +31 -16
- package/out/replecs/utils.luau +14 -784
- package/out/replecs/ver.luau +1 -1
- package/package.json +5 -3
- package/out/replecs/client.luau +0 -1673
- package/out/replecs/index.d.ts +0 -257
- package/out/replecs/masking/init.luau +0 -1695
- package/out/replecs/masking/mask_generator.luau +0 -106
- package/out/replecs/server.luau +0 -2216
- package/out/tsconfig.tsbuildinfo +0 -1
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
--!optimize 2
|
|
2
|
+
|
|
3
|
+
type Bitmask = buffer
|
|
4
|
+
|
|
5
|
+
local BITS_PER_ENTRY = 32
|
|
6
|
+
local BYTES_PER_ENTRY = 4
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
local function to_binary(n: number): string
|
|
10
|
+
local result = ""
|
|
11
|
+
while n > 0 do
|
|
12
|
+
result = (n % 2) .. result
|
|
13
|
+
n = math.floor(n / 2)
|
|
14
|
+
end
|
|
15
|
+
return string.rep("0", 32 - #result) .. result
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
local function bitmask_read_entry(bitmask: Bitmask, len: number, offset: number)
|
|
20
|
+
if offset >= len then
|
|
21
|
+
return 0
|
|
22
|
+
else
|
|
23
|
+
return buffer.readu32(bitmask, offset)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
local function bitmasks_band(a: Bitmask, b: Bitmask, output: Bitmask)
|
|
29
|
+
local len_a = buffer.len(a)
|
|
30
|
+
local len_b = buffer.len(b)
|
|
31
|
+
local len_min = math.min(len_a, len_b)
|
|
32
|
+
|
|
33
|
+
for offset = 0, buffer.len(output) - BYTES_PER_ENTRY, BYTES_PER_ENTRY do
|
|
34
|
+
if offset >= len_min then
|
|
35
|
+
buffer.writeu32(output, offset, 0)
|
|
36
|
+
else
|
|
37
|
+
local a_val = buffer.readu32(a, offset)
|
|
38
|
+
local b_val = buffer.readu32(b, offset)
|
|
39
|
+
buffer.writeu32(output, offset, bit32.band(a_val, b_val))
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
local function bitmasks_bor(a: Bitmask, b: Bitmask, output: Bitmask)
|
|
46
|
+
local len_a = buffer.len(a)
|
|
47
|
+
local len_b = buffer.len(b)
|
|
48
|
+
|
|
49
|
+
for offset = 0, buffer.len(output) - BYTES_PER_ENTRY, BYTES_PER_ENTRY do
|
|
50
|
+
local a_val = if offset >= len_a then 0 else buffer.readu32(a, offset)
|
|
51
|
+
local b_val = if offset >= len_b then 0 else buffer.readu32(b, offset)
|
|
52
|
+
buffer.writeu32(output, offset, bit32.bor(a_val, b_val))
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
local function bitmasks_read_entry(bitmask: Bitmask, len: number, offset: number)
|
|
58
|
+
if offset >= len then
|
|
59
|
+
return 0
|
|
60
|
+
else
|
|
61
|
+
return buffer.readu32(bitmask, offset)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
local function bitmasks_get_index(index: number): (number, number)
|
|
67
|
+
local entry_index = math.floor(index / BITS_PER_ENTRY)
|
|
68
|
+
local bit_position = index % BITS_PER_ENTRY
|
|
69
|
+
return entry_index, bit_position
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
local function bitmasks_set(bitmask: Bitmask, index: number)
|
|
74
|
+
local entry, offset = bitmasks_get_index(index)
|
|
75
|
+
local buffer_offset = entry * BYTES_PER_ENTRY
|
|
76
|
+
local len = buffer.len(bitmask)
|
|
77
|
+
if buffer_offset >= len then
|
|
78
|
+
return
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
local current = buffer.readu32(bitmask, buffer_offset)
|
|
82
|
+
local mask = bit32.lshift(1, offset)
|
|
83
|
+
buffer.writeu32(bitmask, buffer_offset, bit32.bor(current, mask))
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
local function bitmasks_reset(bitmask: Bitmask, index: number)
|
|
88
|
+
local entry, offset = bitmasks_get_index(index)
|
|
89
|
+
local buffer_offset = entry * BYTES_PER_ENTRY
|
|
90
|
+
local len = buffer.len(bitmask)
|
|
91
|
+
if buffer_offset >= len then
|
|
92
|
+
return
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
local current = buffer.readu32(bitmask, buffer_offset)
|
|
96
|
+
local mask = bit32.bnot(bit32.lshift(1, offset))
|
|
97
|
+
buffer.writeu32(bitmask, buffer_offset, bit32.band(current, mask))
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
local function bitmasks_test(bitmask: Bitmask, index: number): boolean
|
|
102
|
+
local entry, offset = bitmasks_get_index(index)
|
|
103
|
+
local buffer_offset = entry * BYTES_PER_ENTRY
|
|
104
|
+
|
|
105
|
+
local len = buffer.len(bitmask)
|
|
106
|
+
if buffer_offset >= len then
|
|
107
|
+
return false
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
local current = buffer.readu32(bitmask, buffer_offset)
|
|
111
|
+
local value = bit32.band(bit32.rshift(current, offset), 1)
|
|
112
|
+
return value == 1
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
local function bitmasks_exclude(base: Bitmask, exclude: Bitmask, output: Bitmask)
|
|
117
|
+
local len_base = buffer.len(base)
|
|
118
|
+
local len_exclude = buffer.len(exclude)
|
|
119
|
+
|
|
120
|
+
for offset = 0, buffer.len(output) - BYTES_PER_ENTRY, BYTES_PER_ENTRY do
|
|
121
|
+
local base_val = bitmasks_read_entry(base, len_base, offset)
|
|
122
|
+
local exclude_val = bitmasks_read_entry(exclude, len_exclude, offset)
|
|
123
|
+
buffer.writeu32(output, offset, bit32.band(base_val, bit32.bnot(exclude_val)))
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
local function bitmasks_load(source: Bitmask, target: Bitmask)
|
|
130
|
+
local source_len = buffer.len(source)
|
|
131
|
+
local target_len = buffer.len(target)
|
|
132
|
+
|
|
133
|
+
buffer.copy(target, 0, source, 0)
|
|
134
|
+
local difference = target_len - source_len
|
|
135
|
+
if difference > 0 then
|
|
136
|
+
buffer.fill(target, source_len, 0, difference)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
local function bitmasks_clear(bitmask: Bitmask)
|
|
143
|
+
buffer.fill(bitmask, 0, 0)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
local function bitmasks_clone(template: Bitmask, size: number?)
|
|
147
|
+
local buf_len = buffer.len(template)
|
|
148
|
+
local cloned = buffer.create((size and math.max(size, buf_len)) or buf_len)
|
|
149
|
+
buffer.copy(cloned, 0, template, 0)
|
|
150
|
+
return cloned
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
local function bitmask_hash(bitmask: Bitmask)
|
|
155
|
+
local highest_entry = -1
|
|
156
|
+
|
|
157
|
+
for i = buffer.len(bitmask) - BYTES_PER_ENTRY, 0, -BYTES_PER_ENTRY do
|
|
158
|
+
local value = buffer.readu32(bitmask, i)
|
|
159
|
+
if value ~= 0 then
|
|
160
|
+
highest_entry = i
|
|
161
|
+
break
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
if highest_entry == -1 then
|
|
166
|
+
return ""
|
|
167
|
+
end
|
|
168
|
+
do -- raw bytes as the key; trailing zero entries are trimmed so equal bit
|
|
169
|
+
-- sets hash the same regardless of buffer size
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
return buffer.readstring(bitmask, 0, highest_entry + BYTES_PER_ENTRY)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
local function bitmask_get_hole_mask(index: number): number
|
|
189
|
+
local _, bit_position = bitmasks_get_index(index)
|
|
190
|
+
return bit32.bnot(bit32.lshift(1, bit_position))
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
local function bitmask_punch_hole_mask(bitmask: Bitmask, mask: number, index: number)
|
|
197
|
+
local entry = math.floor(index / BITS_PER_ENTRY)
|
|
198
|
+
local buffer_offset = entry * BYTES_PER_ENTRY
|
|
199
|
+
if buffer_offset >= buffer.len(bitmask) then
|
|
200
|
+
return
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
local current = buffer.readu32(bitmask, buffer_offset)
|
|
204
|
+
buffer.writeu32(bitmask, buffer_offset, bit32.band(current, mask))
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
local function bitmask_iter_set(bitmask: Bitmask, callback: (index: number) -> ())
|
|
211
|
+
for offset = 0, buffer.len(bitmask) - BYTES_PER_ENTRY, BYTES_PER_ENTRY do
|
|
212
|
+
local word = buffer.readu32(bitmask, offset)
|
|
213
|
+
local base = offset * 8 -- byte offset * 8 = bit index of entry start
|
|
214
|
+
|
|
215
|
+
while word ~= 0 do
|
|
216
|
+
callback(base + bit32.countrz(word))
|
|
217
|
+
word = bit32.band(word, word - 1)
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
export type BitmaskDeltas = {
|
|
223
|
+
added: Bitmask,
|
|
224
|
+
removed: Bitmask,
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
local function load_bitmask_deltas(deltas: BitmaskDeltas)
|
|
229
|
+
buffer.fill(deltas.added, 0, 0)
|
|
230
|
+
buffer.fill(deltas.removed, 0, 0)
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
local function calculate_bitmask_deltas(last: Bitmask, target: Bitmask, output: BitmaskDeltas)
|
|
235
|
+
local len_last = buffer.len(last)
|
|
236
|
+
local len_target = buffer.len(target)
|
|
237
|
+
local added = output.added
|
|
238
|
+
local removed = output.removed
|
|
239
|
+
|
|
240
|
+
-- we asume the output have been loaded, this means it has been cleared
|
|
241
|
+
local len_added = buffer.len(added)
|
|
242
|
+
local len_removed = buffer.len(removed)
|
|
243
|
+
|
|
244
|
+
for offset = 0, math.max(len_added, len_removed) - BYTES_PER_ENTRY, BYTES_PER_ENTRY do
|
|
245
|
+
local last_val = bitmask_read_entry(last, len_last, offset)
|
|
246
|
+
local target_val = bitmask_read_entry(target, len_target, offset)
|
|
247
|
+
|
|
248
|
+
local added_delta = bit32.band(target_val, bit32.bnot(last_val))
|
|
249
|
+
local removed_delta = bit32.band(last_val, bit32.bnot(target_val))
|
|
250
|
+
|
|
251
|
+
buffer.writeu32(added, offset, added_delta)
|
|
252
|
+
buffer.writeu32(removed, offset, removed_delta)
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
local function bitmask_equals(a: Bitmask, b: Bitmask): boolean
|
|
258
|
+
local len_a = buffer.len(a)
|
|
259
|
+
local len_b = buffer.len(b)
|
|
260
|
+
|
|
261
|
+
for offset = 0, math.max(len_a, len_b) - BYTES_PER_ENTRY, BYTES_PER_ENTRY do
|
|
262
|
+
if bitmasks_read_entry(a, len_a, offset) ~= bitmasks_read_entry(b, len_b, offset) then
|
|
263
|
+
return false
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
return true
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
local function bitmask_is_empty(bitmask: Bitmask): boolean
|
|
271
|
+
for offset = 0, buffer.len(bitmask) - BYTES_PER_ENTRY, BYTES_PER_ENTRY do
|
|
272
|
+
if buffer.readu32(bitmask, offset) ~= 0 then
|
|
273
|
+
return false
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
return true
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
local function bitmask_get_buffer_size(bits: number)
|
|
281
|
+
return math.ceil(bits / BITS_PER_ENTRY) * BYTES_PER_ENTRY
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
local function bitmask_create_filled(bits: number): Bitmask
|
|
288
|
+
local size = bitmask_get_buffer_size(bits)
|
|
289
|
+
local bitmask = buffer.create(size)
|
|
290
|
+
buffer.fill(bitmask, 0, 0xFF)
|
|
291
|
+
|
|
292
|
+
local tail = bits % BITS_PER_ENTRY
|
|
293
|
+
if tail ~= 0 then
|
|
294
|
+
buffer.writeu32(bitmask, size - BYTES_PER_ENTRY, bit32.lshift(1, tail) - 1)
|
|
295
|
+
end
|
|
296
|
+
return bitmask
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
return {
|
|
300
|
+
band = bitmasks_band,
|
|
301
|
+
bor = bitmasks_bor,
|
|
302
|
+
read_entry = bitmasks_read_entry,
|
|
303
|
+
get_index = bitmasks_get_index,
|
|
304
|
+
set = bitmasks_set,
|
|
305
|
+
reset = bitmasks_reset,
|
|
306
|
+
test = bitmasks_test,
|
|
307
|
+
exclude = bitmasks_exclude,
|
|
308
|
+
iter_set = bitmask_iter_set,
|
|
309
|
+
load = bitmasks_load,
|
|
310
|
+
clear = bitmasks_clear,
|
|
311
|
+
clone = bitmasks_clone,
|
|
312
|
+
hash = bitmask_hash,
|
|
313
|
+
equals = bitmask_equals,
|
|
314
|
+
is_empty = bitmask_is_empty,
|
|
315
|
+
get_buffer_size = bitmask_get_buffer_size,
|
|
316
|
+
create_filled = bitmask_create_filled,
|
|
317
|
+
get_hole_mask = bitmask_get_hole_mask,
|
|
318
|
+
punch_hole_mask = bitmask_punch_hole_mask,
|
|
319
|
+
|
|
320
|
+
calculate_bitmask_deltas = calculate_bitmask_deltas,
|
|
321
|
+
load_bitmask_deltas = load_bitmask_deltas,
|
|
322
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
local types = require (script.Parent.Parent:WaitForChild('types'))
|
|
2
|
+
local registry = require (script.Parent:WaitForChild('registry'))
|
|
3
|
+
local bitmasks = require (script.Parent:WaitForChild('bitmasks'))
|
|
4
|
+
local utils = require (script.Parent:WaitForChild('utils'))
|
|
5
|
+
local common = require (script.Parent.Parent:WaitForChild('common'))
|
|
6
|
+
|
|
7
|
+
type Bitmask = buffer
|
|
8
|
+
|
|
9
|
+
type FilterSimple = types.FilterSimple
|
|
10
|
+
|
|
11
|
+
type Set<T> = { [T]: boolean }
|
|
12
|
+
type Map<K, V> = { [K]: V }
|
|
13
|
+
type Array<T> = { T }
|
|
14
|
+
|
|
15
|
+
type Listener = (Bitmask) -> ()
|
|
16
|
+
|
|
17
|
+
type ListenerConnections = {
|
|
18
|
+
listeners: { Listener },
|
|
19
|
+
listeners_indexes: { [Listener]: number },
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type FilterMode = number
|
|
23
|
+
|
|
24
|
+
export type FilterEntry = {
|
|
25
|
+
mode: FilterMode,
|
|
26
|
+
filter: FilterSimple,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type FilterGroupClass = {
|
|
30
|
+
registry: registry.Registry,
|
|
31
|
+
parent: FilterGroup?,
|
|
32
|
+
|
|
33
|
+
derived: Set<FilterGroup>,
|
|
34
|
+
assigned_filter: FilterEntry?,
|
|
35
|
+
connected_listeners: ListenerConnections,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
local FILTER_MODES = {
|
|
39
|
+
extend = 1,
|
|
40
|
+
exclude = 2,
|
|
41
|
+
include = 3,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
local filter_group = {}
|
|
45
|
+
filter_group.__index = filter_group
|
|
46
|
+
|
|
47
|
+
export type FilterGroup = FilterGroupClass & typeof(filter_group)
|
|
48
|
+
|
|
49
|
+
function filter_group.is_filter_group(value: any): boolean
|
|
50
|
+
return typeof(value) == "table" and getmetatable(value) == filter_group
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
local function fire_listeners(self: FilterGroup, bitmask: Bitmask)
|
|
54
|
+
for _, listener in self.connected_listeners.listeners do
|
|
55
|
+
listener(bitmask)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
function filter_group.connect(self: FilterGroup, listener: Listener)
|
|
60
|
+
local connected = self.connected_listeners
|
|
61
|
+
local index = #connected.listeners + 1
|
|
62
|
+
connected.listeners[index] = listener
|
|
63
|
+
connected.listeners_indexes[listener] = index
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
function filter_group.disconnect(self: FilterGroup, listener: Listener)
|
|
67
|
+
local connected = self.connected_listeners
|
|
68
|
+
local index = connected.listeners_indexes[listener]
|
|
69
|
+
if not index then
|
|
70
|
+
return
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
local last_listener = table.remove(connected.listeners)
|
|
74
|
+
if last_listener and last_listener ~= listener then
|
|
75
|
+
connected.listeners[index] = last_listener
|
|
76
|
+
connected.listeners_indexes[last_listener] = index
|
|
77
|
+
end
|
|
78
|
+
connected.listeners_indexes[listener] = nil
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
local function create_filter_bitmask(self: FilterGroup, filter: FilterSimple): Bitmask
|
|
82
|
+
if typeof(filter) == "table" then
|
|
83
|
+
return self.registry:create_bitmask_from_set(filter)
|
|
84
|
+
else
|
|
85
|
+
return self.registry:create_bitmask_from_member(filter)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
-- the filter bitmask is resolved from the raw filter here, at calculation
|
|
90
|
+
-- time, so clients registered after the filter was assigned still resolve
|
|
91
|
+
function filter_group.apply_filter(self: FilterGroup, bitmask: Bitmask)
|
|
92
|
+
local filter = self.assigned_filter
|
|
93
|
+
if not filter then
|
|
94
|
+
return
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
local filter_bitmask = create_filter_bitmask(self, filter.filter)
|
|
98
|
+
|
|
99
|
+
if filter.mode == FILTER_MODES.extend then
|
|
100
|
+
bitmasks.bor(bitmask, filter_bitmask, bitmask)
|
|
101
|
+
elseif filter.mode == FILTER_MODES.exclude then
|
|
102
|
+
bitmasks.exclude(bitmask, filter_bitmask, bitmask)
|
|
103
|
+
elseif filter.mode == FILTER_MODES.include then
|
|
104
|
+
bitmasks.band(bitmask, filter_bitmask, bitmask)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
function filter_group.calculate_up(self: FilterGroup): Bitmask
|
|
109
|
+
local parent = self.parent
|
|
110
|
+
local bitmask: Bitmask
|
|
111
|
+
if parent then
|
|
112
|
+
bitmask = filter_group.calculate_up(parent)
|
|
113
|
+
else
|
|
114
|
+
bitmask = bitmasks.create_filled(self.registry.client_next_index)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
filter_group.apply_filter(self, bitmask)
|
|
118
|
+
return bitmask
|
|
119
|
+
end
|
|
120
|
+
|
|
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
|
+
|
|
125
|
+
fire_listeners(self, bitmask)
|
|
126
|
+
|
|
127
|
+
for derived in self.derived do
|
|
128
|
+
filter_group.calculate_down(derived, bitmask)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
local function recalculate_filter_group(group: FilterGroup)
|
|
133
|
+
local parent = group.parent
|
|
134
|
+
|
|
135
|
+
local parent_bitmask: Bitmask
|
|
136
|
+
if parent then
|
|
137
|
+
parent_bitmask = filter_group.calculate_up(parent)
|
|
138
|
+
else
|
|
139
|
+
parent_bitmask = bitmasks.create_filled(group.registry.client_next_index)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
filter_group.calculate_down(group, parent_bitmask)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
function filter_group.extend(self: FilterGroup, filter: FilterSimple)
|
|
146
|
+
if not utils.get_used_filter_type(filter) then
|
|
147
|
+
common.log_error "extend() only accepts include filters"
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
self.assigned_filter = {
|
|
151
|
+
mode = FILTER_MODES.extend,
|
|
152
|
+
filter = filter,
|
|
153
|
+
}
|
|
154
|
+
recalculate_filter_group(self)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
function filter_group.filter(self: FilterGroup, filter: FilterSimple)
|
|
158
|
+
local mode = FILTER_MODES.exclude
|
|
159
|
+
|
|
160
|
+
if utils.get_used_filter_type(filter) then
|
|
161
|
+
mode = FILTER_MODES.include
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
self.assigned_filter = {
|
|
165
|
+
mode = mode,
|
|
166
|
+
filter = filter,
|
|
167
|
+
}
|
|
168
|
+
recalculate_filter_group(self)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
function filter_group.create(client_registry: registry.Registry): FilterGroup
|
|
172
|
+
local self: FilterGroupClass = {
|
|
173
|
+
registry = client_registry,
|
|
174
|
+
|
|
175
|
+
parent = nil,
|
|
176
|
+
connected_listeners = {
|
|
177
|
+
listeners = {},
|
|
178
|
+
listeners_indexes = {},
|
|
179
|
+
},
|
|
180
|
+
derived = setmetatable({}, { __mode = "k" }) :: any,
|
|
181
|
+
assigned_filter = nil,
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
setmetatable(self, filter_group)
|
|
185
|
+
return self :: any
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
function filter_group.derive(self: FilterGroup): FilterGroup
|
|
189
|
+
local derived = filter_group.create(self.registry)
|
|
190
|
+
derived.parent = self
|
|
191
|
+
|
|
192
|
+
self.derived[derived] = true
|
|
193
|
+
return derived
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
return filter_group
|