@rbxts/replecs 0.0.1-rc.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/out/index.d.ts +3 -0
- package/out/init.luau +5 -0
- package/out/jecs.d.ts +1 -0
- package/out/jecs.luau +7 -0
- package/out/replecs/client.luau +354 -0
- package/out/replecs/common.luau +49 -0
- package/out/replecs/index.d.ts +96 -0
- package/out/replecs/init.luau +83 -0
- package/out/replecs/masking/init.luau +1191 -0
- package/out/replecs/masking/mask_generator.luau +97 -0
- package/out/replecs/server.luau +918 -0
- package/out/replecs/utils.luau +624 -0
- package/package.json +46 -0
|
@@ -0,0 +1,1191 @@
|
|
|
1
|
+
local jecs = require(script.Parent.Parent.jecs)
|
|
2
|
+
local utils = require(script.Parent.utils)
|
|
3
|
+
local mask_generator = require(script.mask_generator)
|
|
4
|
+
|
|
5
|
+
type Entity<T = any> = jecs.Entity<T>
|
|
6
|
+
|
|
7
|
+
type Bitmask = utils.Bitmask
|
|
8
|
+
type MaskGenerator = mask_generator.MaskGenerator
|
|
9
|
+
|
|
10
|
+
type MemberFilter = Set<Member>
|
|
11
|
+
type Member = any
|
|
12
|
+
type MaskHash = string
|
|
13
|
+
|
|
14
|
+
type Set<T> = { [T]: boolean }
|
|
15
|
+
type Map<K, V> = { [K]: V }
|
|
16
|
+
type Array<T> = { T }
|
|
17
|
+
|
|
18
|
+
type ComponentIndex<T> = {
|
|
19
|
+
[number]: { [Entity]: T },
|
|
20
|
+
}
|
|
21
|
+
type EntityComponentIndex<T> = {
|
|
22
|
+
[Entity]: ComponentIndex<T>,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type Lookup = {
|
|
26
|
+
generator: MaskGenerator,
|
|
27
|
+
-- filter in component lookups will never be nil
|
|
28
|
+
filter: MemberFilter?,
|
|
29
|
+
storage_group: StorageGroup,
|
|
30
|
+
}
|
|
31
|
+
type ComponentLookup = Lookup & {
|
|
32
|
+
band_generator: MaskGenerator,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type EntityChanges = {
|
|
36
|
+
tagged: { [Entity]: boolean },
|
|
37
|
+
component: { [Entity]: any },
|
|
38
|
+
removed: { [Entity]: boolean },
|
|
39
|
+
pairs: { [Entity]: Set<Entity> },
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
type LookupsList = {
|
|
43
|
+
entities: Map<Entity, Lookup>,
|
|
44
|
+
components: EntityComponentIndex<ComponentLookup>,
|
|
45
|
+
|
|
46
|
+
deletions: {
|
|
47
|
+
entities: Map<Entity, Lookup>,
|
|
48
|
+
components: EntityComponentIndex<Lookup>,
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
posponed: EntityComponentIndex<MemberFilter>,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export type ActiveEntity = {
|
|
55
|
+
components: ComponentIndex<boolean>,
|
|
56
|
+
component_count: number,
|
|
57
|
+
is_entity_mask: boolean,
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
type MaskInfo = {
|
|
61
|
+
bitmask: Bitmask,
|
|
62
|
+
hash: MaskHash,
|
|
63
|
+
members: Array<Member>,
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
type StorageGroup = {
|
|
67
|
+
mask: MaskInfo,
|
|
68
|
+
shared_with: EntityComponentIndex<boolean>,
|
|
69
|
+
is_empty: boolean,
|
|
70
|
+
|
|
71
|
+
deletions: {
|
|
72
|
+
entities: Set<Entity>,
|
|
73
|
+
components: EntityComponentIndex<boolean>,
|
|
74
|
+
},
|
|
75
|
+
deletions_count: number,
|
|
76
|
+
|
|
77
|
+
active: Map<Entity, ActiveEntity>, -- set of active entities
|
|
78
|
+
active_count: number,
|
|
79
|
+
|
|
80
|
+
changes: {
|
|
81
|
+
added: Map<Entity, boolean>,
|
|
82
|
+
changed: Map<Entity, EntityChanges>,
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
type Storages = {
|
|
87
|
+
[MaskHash]: StorageGroup,
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export type MaskingController = {
|
|
91
|
+
member_count: number,
|
|
92
|
+
member_indexes: { [Member]: number },
|
|
93
|
+
unreplicated: Set<Member>,
|
|
94
|
+
|
|
95
|
+
all_members_generator: MaskGenerator,
|
|
96
|
+
active_members_generator: MaskGenerator,
|
|
97
|
+
unactive_members_generator: MaskGenerator,
|
|
98
|
+
|
|
99
|
+
storages: Storages,
|
|
100
|
+
lookups: LookupsList,
|
|
101
|
+
|
|
102
|
+
register_member: (self: MaskingController, member: Member) -> (),
|
|
103
|
+
unregister_member: (self: MaskingController, member: Member) -> (),
|
|
104
|
+
activate_member: (self: MaskingController, member: Member) -> (),
|
|
105
|
+
member_is_active: (self: MaskingController, member: Member) -> boolean,
|
|
106
|
+
|
|
107
|
+
register_stop_entity: (self: MaskingController, entity: Entity) -> (),
|
|
108
|
+
register_stop_component: (
|
|
109
|
+
self: MaskingController,
|
|
110
|
+
entity: Entity,
|
|
111
|
+
component: Entity,
|
|
112
|
+
component_type: number
|
|
113
|
+
) -> (),
|
|
114
|
+
unregister_stop_entity: (self: MaskingController, entity: Entity) -> (),
|
|
115
|
+
unregister_stop_component: (
|
|
116
|
+
self: MaskingController,
|
|
117
|
+
entity: Entity,
|
|
118
|
+
component: Entity,
|
|
119
|
+
component_type: number
|
|
120
|
+
) -> (),
|
|
121
|
+
|
|
122
|
+
propagate_entity_addition: (self: MaskingController, entity: Entity) -> (),
|
|
123
|
+
|
|
124
|
+
start_entity: (self: MaskingController, entity: Entity, filter: MemberFilter?) -> (),
|
|
125
|
+
set_entity: (self: MaskingController, entity: Entity, filter: MemberFilter?) -> (),
|
|
126
|
+
stop_entity: (self: MaskingController, entity: Entity) -> (),
|
|
127
|
+
|
|
128
|
+
start_component: (
|
|
129
|
+
self: MaskingController,
|
|
130
|
+
entity: Entity,
|
|
131
|
+
component: Entity,
|
|
132
|
+
component_type: number,
|
|
133
|
+
filter: MemberFilter?
|
|
134
|
+
) -> (),
|
|
135
|
+
set_component: (
|
|
136
|
+
self: MaskingController,
|
|
137
|
+
entity: Entity,
|
|
138
|
+
component: Entity,
|
|
139
|
+
component_type: number,
|
|
140
|
+
filter: MemberFilter?
|
|
141
|
+
) -> (),
|
|
142
|
+
stop_component: (self: MaskingController, entity: Entity, component: Entity, component_type: number) -> (),
|
|
143
|
+
|
|
144
|
+
allocate_entity_addition: (
|
|
145
|
+
self: MaskingController,
|
|
146
|
+
entity: Entity,
|
|
147
|
+
component: Entity,
|
|
148
|
+
component_type: number
|
|
149
|
+
) -> (),
|
|
150
|
+
|
|
151
|
+
allocate_component_change: (self: MaskingController, entity: Entity, component: Entity, value: any) -> (),
|
|
152
|
+
allocate_tag_addition: (self: MaskingController, entity: Entity, tag: Entity) -> (),
|
|
153
|
+
allocate_pair_addition: (self: MaskingController, entity: Entity, relation: Entity, target: Entity) -> (),
|
|
154
|
+
|
|
155
|
+
allocate_component_removal: (self: MaskingController, entity: Entity, component: Entity) -> (),
|
|
156
|
+
allocate_tag_removal: (self: MaskingController, entity: Entity, tag: Entity) -> (),
|
|
157
|
+
allocate_pair_removal: (self: MaskingController, entity: Entity, relation: Entity, target: Entity) -> (),
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
local COMPONENT_TYPES = {
|
|
161
|
+
component = 1,
|
|
162
|
+
tag = 2,
|
|
163
|
+
pair = 3,
|
|
164
|
+
unreliable = 4,
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
local masking_controller = {}
|
|
168
|
+
masking_controller.__index = masking_controller
|
|
169
|
+
|
|
170
|
+
export type MaskingInternal = MaskingController & typeof(masking_controller)
|
|
171
|
+
|
|
172
|
+
function masking_controller.get_members_from_bitmask(controller: MaskingInternal, bitmask: Bitmask): Array<Member>
|
|
173
|
+
local members: { Member } = {}
|
|
174
|
+
for player, index in controller.member_indexes do
|
|
175
|
+
if bitmask:get(index) then
|
|
176
|
+
table.insert(members, player :: any)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
return members
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
local function create_component_indexes<T>()
|
|
183
|
+
return { {}, {}, {}, {} } :: ComponentIndex<T>
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
local function create_entity_changes(): EntityChanges
|
|
187
|
+
return {
|
|
188
|
+
tagged = {},
|
|
189
|
+
component = {},
|
|
190
|
+
removed = {},
|
|
191
|
+
pairs = {},
|
|
192
|
+
}
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
local function get_or_set_changes(storage: StorageGroup, entity: Entity)
|
|
196
|
+
local changes: EntityChanges = storage.changes.changed[entity]
|
|
197
|
+
if changes == nil then
|
|
198
|
+
changes = create_entity_changes()
|
|
199
|
+
storage.changes.changed[entity] = changes
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
return changes
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
function masking_controller.create_new_storage(
|
|
206
|
+
controller: MaskingInternal,
|
|
207
|
+
bitmask: Bitmask,
|
|
208
|
+
hash: string?,
|
|
209
|
+
members: Array<Member>?
|
|
210
|
+
): StorageGroup
|
|
211
|
+
return {
|
|
212
|
+
mask = {
|
|
213
|
+
bitmask = bitmask,
|
|
214
|
+
hash = hash or bitmask:tostring(),
|
|
215
|
+
members = members or controller:get_members_from_bitmask(bitmask),
|
|
216
|
+
},
|
|
217
|
+
is_empty = true,
|
|
218
|
+
shared_with = {},
|
|
219
|
+
|
|
220
|
+
changes = {
|
|
221
|
+
added = {},
|
|
222
|
+
changed = {},
|
|
223
|
+
},
|
|
224
|
+
|
|
225
|
+
active = {},
|
|
226
|
+
active_count = 0,
|
|
227
|
+
|
|
228
|
+
deletions = {
|
|
229
|
+
entities = {},
|
|
230
|
+
components = {},
|
|
231
|
+
},
|
|
232
|
+
deletions_count = 0,
|
|
233
|
+
}
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
local function is_include_filter(filter: MemberFilter): boolean
|
|
237
|
+
for player, allow in filter do
|
|
238
|
+
if allow then
|
|
239
|
+
return true
|
|
240
|
+
else
|
|
241
|
+
return false
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
return true
|
|
245
|
+
end
|
|
246
|
+
local function create_new_active(): ActiveEntity
|
|
247
|
+
return {
|
|
248
|
+
components = create_component_indexes() :: ComponentIndex<boolean>,
|
|
249
|
+
component_count = 0,
|
|
250
|
+
is_entity_mask = false,
|
|
251
|
+
}
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
local function create_new_changes(): EntityChanges
|
|
255
|
+
return {
|
|
256
|
+
tagged = {},
|
|
257
|
+
component = {},
|
|
258
|
+
removed = {},
|
|
259
|
+
pairs = {},
|
|
260
|
+
}
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
function masking_controller.get_or_create_storage_group(masking: MaskingInternal, bitmask: Bitmask): StorageGroup
|
|
264
|
+
local hash = bitmask:tostring()
|
|
265
|
+
local storage = masking.storages[hash]
|
|
266
|
+
|
|
267
|
+
if not storage then
|
|
268
|
+
storage = masking:create_new_storage(bitmask, hash)
|
|
269
|
+
masking.storages[hash] = storage
|
|
270
|
+
end
|
|
271
|
+
return storage
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
local function get_component_index_entry<T>(
|
|
275
|
+
index: EntityComponentIndex<T>,
|
|
276
|
+
entity: Entity,
|
|
277
|
+
component: Entity,
|
|
278
|
+
component_type: number
|
|
279
|
+
): T?
|
|
280
|
+
local entity_index = index[entity]
|
|
281
|
+
if entity_index == nil then
|
|
282
|
+
return nil
|
|
283
|
+
end
|
|
284
|
+
local component_index = entity_index[component_type]
|
|
285
|
+
|
|
286
|
+
return component_index and component_index[component] :: T?
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
local function set_component_index_entry<T>(
|
|
290
|
+
index: EntityComponentIndex<T>,
|
|
291
|
+
entity: Entity,
|
|
292
|
+
component: Entity,
|
|
293
|
+
component_type: number,
|
|
294
|
+
value: T
|
|
295
|
+
)
|
|
296
|
+
local entity_index = index[entity]
|
|
297
|
+
if entity_index == nil then
|
|
298
|
+
entity_index = create_component_indexes()
|
|
299
|
+
index[entity] = entity_index
|
|
300
|
+
end
|
|
301
|
+
entity_index[component_type][component] = value
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
local function remove_component_index_entry(
|
|
305
|
+
index: EntityComponentIndex<any>,
|
|
306
|
+
entity: Entity,
|
|
307
|
+
component: Entity,
|
|
308
|
+
component_type: number
|
|
309
|
+
)
|
|
310
|
+
local entity_index = index[entity]
|
|
311
|
+
if entity_index == nil then
|
|
312
|
+
return
|
|
313
|
+
end
|
|
314
|
+
entity_index[component_type][component] = nil
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
masking_controller.get_component_index_entry = get_component_index_entry
|
|
318
|
+
masking_controller.set_component_index_entry = set_component_index_entry
|
|
319
|
+
masking_controller.remove_component_index_entry = remove_component_index_entry
|
|
320
|
+
|
|
321
|
+
local function get_or_set_changed(storage: StorageGroup, entity: Entity, changed: EntityChanges?): EntityChanges
|
|
322
|
+
local storage_changed = storage.changes.changed[entity]
|
|
323
|
+
if storage_changed == nil then
|
|
324
|
+
storage_changed = changed or create_new_changes()
|
|
325
|
+
storage.changes.changed[entity] = storage_changed
|
|
326
|
+
end
|
|
327
|
+
return storage_changed
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
local function get_or_set_active(storage: StorageGroup, entity: Entity, active: ActiveEntity?): ActiveEntity
|
|
331
|
+
local storage_active = storage.active[entity]
|
|
332
|
+
if storage_active == nil then
|
|
333
|
+
storage_active = active or create_new_active()
|
|
334
|
+
storage.active[entity] = storage_active
|
|
335
|
+
storage.active_count += 1
|
|
336
|
+
end
|
|
337
|
+
return storage_active
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
local function remove_active(storage: StorageGroup, entity: Entity): ActiveEntity
|
|
341
|
+
local active = storage.active[entity]
|
|
342
|
+
if active then
|
|
343
|
+
storage.active[entity] = nil
|
|
344
|
+
storage.active_count -= 1
|
|
345
|
+
-- todo: check if empty
|
|
346
|
+
return active
|
|
347
|
+
end
|
|
348
|
+
return utils.logerror "attempted to remove an entity that wasn't active"
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
local function get_or_set_component_active(active: ActiveEntity, component: Entity, component_type: number)
|
|
352
|
+
local components = active.components[component_type]
|
|
353
|
+
if components[component] == nil then
|
|
354
|
+
components[component] = true
|
|
355
|
+
active.component_count += 1
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
local function remove_component_active(storage: StorageGroup, entity: Entity, component: Entity, component_type: number)
|
|
360
|
+
local active = storage.active[entity]
|
|
361
|
+
if not active then
|
|
362
|
+
return
|
|
363
|
+
end
|
|
364
|
+
local components = active.components[component_type]
|
|
365
|
+
|
|
366
|
+
if components[component] then
|
|
367
|
+
components[component] = nil
|
|
368
|
+
active.component_count -= 1
|
|
369
|
+
|
|
370
|
+
if active.component_count <= 0 and not active.is_entity_mask then
|
|
371
|
+
remove_active(storage, entity)
|
|
372
|
+
end
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
local function dissect_component_actives(
|
|
377
|
+
storage: StorageGroup,
|
|
378
|
+
entity: Entity,
|
|
379
|
+
shared_index: ComponentIndex<boolean>
|
|
380
|
+
): ActiveEntity?
|
|
381
|
+
local new_active: ActiveEntity
|
|
382
|
+
local active = storage.active[entity]
|
|
383
|
+
|
|
384
|
+
for component_type, components in active.components do
|
|
385
|
+
for component in components do
|
|
386
|
+
local is_shared = shared_index[component_type] and shared_index[component_type][component]
|
|
387
|
+
if is_shared then
|
|
388
|
+
new_active = new_active or create_new_active()
|
|
389
|
+
|
|
390
|
+
get_or_set_component_active(new_active, component, component_type)
|
|
391
|
+
remove_component_active(storage, entity, component, component_type)
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
end
|
|
395
|
+
return new_active
|
|
396
|
+
end
|
|
397
|
+
function dissect_component_changes(changes: EntityChanges, shared_index: ComponentIndex<boolean>)
|
|
398
|
+
local new_changes: EntityChanges
|
|
399
|
+
|
|
400
|
+
for component, change in changes.component do
|
|
401
|
+
local is_shared = shared_index[COMPONENT_TYPES.component] and shared_index[COMPONENT_TYPES.component][component]
|
|
402
|
+
if is_shared then
|
|
403
|
+
new_changes = new_changes or create_new_changes()
|
|
404
|
+
new_changes.component[component] = change
|
|
405
|
+
changes.component[component] = nil
|
|
406
|
+
end
|
|
407
|
+
end
|
|
408
|
+
for entity, entity_changes in changes.tagged do
|
|
409
|
+
local is_shared = shared_index[COMPONENT_TYPES.tag] and shared_index[COMPONENT_TYPES.tag][entity]
|
|
410
|
+
if is_shared then
|
|
411
|
+
new_changes = new_changes or create_new_changes()
|
|
412
|
+
new_changes.tagged[entity] = entity_changes
|
|
413
|
+
changes.tagged[entity] = nil
|
|
414
|
+
end
|
|
415
|
+
end
|
|
416
|
+
for entity, entity_changes in changes.pairs do
|
|
417
|
+
local is_shared = shared_index[COMPONENT_TYPES.pair] and shared_index[COMPONENT_TYPES.pair][entity]
|
|
418
|
+
if is_shared then
|
|
419
|
+
new_changes = new_changes or create_new_changes()
|
|
420
|
+
new_changes.pairs[entity] = entity_changes
|
|
421
|
+
changes.pairs[entity] = nil
|
|
422
|
+
end
|
|
423
|
+
end
|
|
424
|
+
return new_changes
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
local function merge_component_actives(current: ActiveEntity, target: ActiveEntity)
|
|
428
|
+
for component_type, components in current.components do
|
|
429
|
+
for component in components do
|
|
430
|
+
get_or_set_component_active(target, component, component_type)
|
|
431
|
+
end
|
|
432
|
+
end
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
local function merge_component_changes(current: EntityChanges, target: EntityChanges)
|
|
436
|
+
for component, change in current.component do
|
|
437
|
+
target.component[component] = change
|
|
438
|
+
end
|
|
439
|
+
for entity, entity_changes in current.tagged do
|
|
440
|
+
target.tagged[entity] = entity_changes
|
|
441
|
+
end
|
|
442
|
+
for entity, entity_changes in current.pairs do
|
|
443
|
+
target.pairs[entity] = entity_changes
|
|
444
|
+
end
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
function masking_controller.merge_component_filter(
|
|
448
|
+
masking: MaskingInternal,
|
|
449
|
+
entity: Entity,
|
|
450
|
+
component: Entity,
|
|
451
|
+
component_type: number
|
|
452
|
+
)
|
|
453
|
+
local component_lookup = get_component_index_entry(masking.lookups.components, entity, component, component_type)
|
|
454
|
+
local entity_lookup = masking.lookups.entities[entity]
|
|
455
|
+
if not entity_lookup then
|
|
456
|
+
utils.logerror "attempted to merge a component filter to an unactive entity"
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
if component_lookup ~= nil then
|
|
460
|
+
local new_storage = masking:move_component_storage(
|
|
461
|
+
entity,
|
|
462
|
+
component,
|
|
463
|
+
component_type,
|
|
464
|
+
component_lookup.storage_group,
|
|
465
|
+
entity_lookup.generator.bitmask
|
|
466
|
+
)
|
|
467
|
+
remove_component_index_entry(masking.lookups.components, entity, component, component_type)
|
|
468
|
+
remove_component_index_entry(new_storage.shared_with, entity, component, component_type)
|
|
469
|
+
else
|
|
470
|
+
get_or_set_component_active(entity_lookup.storage_group.active[entity], component, component_type)
|
|
471
|
+
end
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
function masking_controller.move_entity_storage(
|
|
475
|
+
masking: MaskingInternal,
|
|
476
|
+
entity: Entity,
|
|
477
|
+
storage: StorageGroup,
|
|
478
|
+
target: Bitmask
|
|
479
|
+
)
|
|
480
|
+
local target_storage = masking:get_or_create_storage_group(target)
|
|
481
|
+
if target_storage == storage then
|
|
482
|
+
return storage
|
|
483
|
+
end
|
|
484
|
+
local shared_with = storage.shared_with[entity]
|
|
485
|
+
|
|
486
|
+
local old_active = storage.active[entity]
|
|
487
|
+
local new_active = get_or_set_active(target_storage, entity, old_active)
|
|
488
|
+
|
|
489
|
+
new_active.is_entity_mask = true
|
|
490
|
+
|
|
491
|
+
if shared_with then
|
|
492
|
+
local dissected_active = dissect_component_actives(storage, entity, shared_with)
|
|
493
|
+
if dissected_active then
|
|
494
|
+
storage.active[entity] = dissected_active
|
|
495
|
+
else
|
|
496
|
+
remove_active(storage, entity)
|
|
497
|
+
end
|
|
498
|
+
else
|
|
499
|
+
remove_active(storage, entity)
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
if old_active ~= new_active then
|
|
503
|
+
merge_component_actives(old_active, new_active)
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
local old_changes = storage.changes.changed[entity]
|
|
507
|
+
if old_changes then
|
|
508
|
+
local new_changes = get_or_set_changed(target_storage, entity)
|
|
509
|
+
|
|
510
|
+
if shared_with then
|
|
511
|
+
local dissected_changes = dissect_component_changes(old_changes, shared_with)
|
|
512
|
+
if dissected_changes then
|
|
513
|
+
storage.changes.changed[entity] = dissected_changes
|
|
514
|
+
else
|
|
515
|
+
storage.changes.changed[entity] = nil
|
|
516
|
+
end
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
if old_changes ~= new_changes then
|
|
520
|
+
merge_component_changes(old_changes, new_changes)
|
|
521
|
+
end
|
|
522
|
+
end
|
|
523
|
+
return target_storage
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
function masking_controller.move_component_storage(
|
|
527
|
+
masking: MaskingInternal,
|
|
528
|
+
entity: Entity,
|
|
529
|
+
component: Entity,
|
|
530
|
+
component_type: number,
|
|
531
|
+
storage: StorageGroup,
|
|
532
|
+
target: Bitmask
|
|
533
|
+
)
|
|
534
|
+
local target_storage = masking:get_or_create_storage_group(target)
|
|
535
|
+
if target_storage == storage then
|
|
536
|
+
return storage
|
|
537
|
+
end
|
|
538
|
+
|
|
539
|
+
local new_active = get_or_set_active(target_storage, entity)
|
|
540
|
+
|
|
541
|
+
remove_component_active(storage, entity, component, component_type)
|
|
542
|
+
get_or_set_component_active(new_active, component, component_type)
|
|
543
|
+
|
|
544
|
+
set_component_index_entry(target_storage.shared_with, entity, component, component_type, true)
|
|
545
|
+
remove_component_index_entry(storage.shared_with, entity, component, component_type)
|
|
546
|
+
|
|
547
|
+
local changes = storage.changes.changed[entity]
|
|
548
|
+
if changes then
|
|
549
|
+
local target_changes = get_or_set_changed(target_storage, entity)
|
|
550
|
+
if component_type == COMPONENT_TYPES.component then
|
|
551
|
+
target_changes.component[component] = changes.component[component]
|
|
552
|
+
target_changes.removed[component] = changes.removed[component]
|
|
553
|
+
|
|
554
|
+
changes.component[component] = nil
|
|
555
|
+
changes.removed[component] = nil
|
|
556
|
+
elseif component_type == COMPONENT_TYPES.tag then
|
|
557
|
+
target_changes.tagged[component] = changes.tagged[component]
|
|
558
|
+
target_changes.removed[component] = changes.removed[component]
|
|
559
|
+
|
|
560
|
+
changes.tagged[component] = nil
|
|
561
|
+
changes.removed[component] = nil
|
|
562
|
+
elseif component_type == COMPONENT_TYPES.pair then
|
|
563
|
+
target_changes.pairs[component] = changes.pairs[component]
|
|
564
|
+
changes.pairs[component] = nil
|
|
565
|
+
end
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
--todo: move changes
|
|
569
|
+
|
|
570
|
+
return target_storage
|
|
571
|
+
end
|
|
572
|
+
|
|
573
|
+
function masking_controller.bind_component_generator(
|
|
574
|
+
masking: MaskingInternal,
|
|
575
|
+
entity: Entity,
|
|
576
|
+
component: Entity,
|
|
577
|
+
component_type: number,
|
|
578
|
+
base_generator: MaskGenerator
|
|
579
|
+
)
|
|
580
|
+
local entity_lookup = masking.lookups.entities[entity]
|
|
581
|
+
local component_lookups = masking.lookups.components[entity]
|
|
582
|
+
local component_lookup = component_lookups and component_lookups[component_type][component]
|
|
583
|
+
local generator = mask_generator.create(nil, function()
|
|
584
|
+
return entity_lookup.generator.bitmask:band(base_generator.bitmask)
|
|
585
|
+
end)
|
|
586
|
+
|
|
587
|
+
local function subscribed()
|
|
588
|
+
if not component_lookup then
|
|
589
|
+
component_lookup = component_lookups and component_lookups[component_type][component]
|
|
590
|
+
end
|
|
591
|
+
|
|
592
|
+
local current_storage = component_lookup.storage_group
|
|
593
|
+
local new_storage =
|
|
594
|
+
masking:move_component_storage(entity, component, component_type, current_storage, generator.bitmask)
|
|
595
|
+
|
|
596
|
+
component_lookup.storage_group = new_storage
|
|
597
|
+
end
|
|
598
|
+
|
|
599
|
+
generator:track(base_generator)
|
|
600
|
+
generator:track(masking.active_members_generator)
|
|
601
|
+
generator.subscribed = subscribed
|
|
602
|
+
|
|
603
|
+
return generator
|
|
604
|
+
end
|
|
605
|
+
|
|
606
|
+
function masking_controller.rebind_component_generators(masking: MaskingInternal, entity: Entity)
|
|
607
|
+
local component_lookups = masking.lookups.components[entity]
|
|
608
|
+
if component_lookups then
|
|
609
|
+
for component_type, lookups in component_lookups do
|
|
610
|
+
for component, lookup in lookups do
|
|
611
|
+
lookup.band_generator:destroy()
|
|
612
|
+
|
|
613
|
+
local binded_generator =
|
|
614
|
+
masking:bind_component_generator(entity, component, component_type, lookup.generator)
|
|
615
|
+
lookup.band_generator = binded_generator
|
|
616
|
+
binded_generator:run_subscribed()
|
|
617
|
+
end
|
|
618
|
+
end
|
|
619
|
+
end
|
|
620
|
+
end
|
|
621
|
+
|
|
622
|
+
function masking_controller.get_or_pospone_entity_lookup(
|
|
623
|
+
masking: MaskingInternal,
|
|
624
|
+
entity: Entity,
|
|
625
|
+
component: Entity,
|
|
626
|
+
component_type: number,
|
|
627
|
+
filter: MemberFilter?
|
|
628
|
+
): Lookup?
|
|
629
|
+
local lookup = masking.lookups.entities[entity]
|
|
630
|
+
if lookup then
|
|
631
|
+
return lookup
|
|
632
|
+
end
|
|
633
|
+
|
|
634
|
+
if filter == nil then
|
|
635
|
+
return nil
|
|
636
|
+
end
|
|
637
|
+
|
|
638
|
+
set_component_index_entry(masking.lookups.posponed, entity, component, component_type, filter)
|
|
639
|
+
return nil
|
|
640
|
+
end
|
|
641
|
+
|
|
642
|
+
function masking_controller.register_stop_entity(masking: MaskingInternal, entity: Entity)
|
|
643
|
+
local lookup = masking.lookups.entities[entity]
|
|
644
|
+
local storage = lookup.storage_group
|
|
645
|
+
|
|
646
|
+
if storage.deletions.entities[entity] then
|
|
647
|
+
return
|
|
648
|
+
end
|
|
649
|
+
storage.deletions.entities[entity] = true
|
|
650
|
+
storage.deletions_count += 1
|
|
651
|
+
end
|
|
652
|
+
|
|
653
|
+
function masking_controller.register_stop_component(
|
|
654
|
+
masking: MaskingInternal,
|
|
655
|
+
entity: Entity,
|
|
656
|
+
component: Entity,
|
|
657
|
+
component_type: number
|
|
658
|
+
)
|
|
659
|
+
local storage = masking:get_component_storage_group(entity, component, component_type) :: StorageGroup
|
|
660
|
+
|
|
661
|
+
local deletions = storage.deletions.components[entity]
|
|
662
|
+
if deletions == nil then
|
|
663
|
+
deletions = create_component_indexes() :: ComponentIndex<boolean>
|
|
664
|
+
deletions[component_type][component] = true
|
|
665
|
+
storage.deletions.components[entity] = deletions
|
|
666
|
+
storage.deletions_count += 1
|
|
667
|
+
else
|
|
668
|
+
if deletions[component_type][component] then
|
|
669
|
+
return
|
|
670
|
+
end
|
|
671
|
+
deletions[component_type][component] = true
|
|
672
|
+
storage.deletions_count += 1
|
|
673
|
+
end
|
|
674
|
+
end
|
|
675
|
+
function masking_controller.unregister_stop_entity(masking: MaskingInternal, entity: Entity)
|
|
676
|
+
local deletion_lookup = masking.lookups.deletions.entities[entity]
|
|
677
|
+
if not deletion_lookup then
|
|
678
|
+
return
|
|
679
|
+
end
|
|
680
|
+
local storage = deletion_lookup.storage_group
|
|
681
|
+
|
|
682
|
+
if storage.deletions.entities[entity] then
|
|
683
|
+
storage.deletions.entities[entity] = nil
|
|
684
|
+
storage.deletions_count -= 1
|
|
685
|
+
end
|
|
686
|
+
end
|
|
687
|
+
|
|
688
|
+
function masking_controller.unregister_stop_component(
|
|
689
|
+
masking: MaskingInternal,
|
|
690
|
+
entity: Entity,
|
|
691
|
+
component: Entity,
|
|
692
|
+
component_type: number
|
|
693
|
+
)
|
|
694
|
+
local deletion_lookup =
|
|
695
|
+
get_component_index_entry(masking.lookups.deletions.components, entity, component, component_type)
|
|
696
|
+
if deletion_lookup == nil then
|
|
697
|
+
return
|
|
698
|
+
end
|
|
699
|
+
local storage = deletion_lookup.storage_group
|
|
700
|
+
|
|
701
|
+
local deletions = storage.deletions.components[entity]
|
|
702
|
+
if deletions then
|
|
703
|
+
if deletions[component_type][component] then
|
|
704
|
+
deletions[component_type][component] = nil
|
|
705
|
+
storage.deletions_count -= 1
|
|
706
|
+
end
|
|
707
|
+
end
|
|
708
|
+
end
|
|
709
|
+
|
|
710
|
+
function masking_controller.propagate_entity_addition(masking: MaskingInternal, entity: Entity)
|
|
711
|
+
local entity_lookup = masking.lookups.entities[entity]
|
|
712
|
+
if entity_lookup then
|
|
713
|
+
entity_lookup.storage_group.changes.added[entity] = true
|
|
714
|
+
end
|
|
715
|
+
|
|
716
|
+
local component_lookups = masking.lookups.components[entity]
|
|
717
|
+
if component_lookups then
|
|
718
|
+
for component_type, lookups in component_lookups do
|
|
719
|
+
for component, lookup in lookups do
|
|
720
|
+
lookup.storage_group.changes.added[entity] = true
|
|
721
|
+
end
|
|
722
|
+
end
|
|
723
|
+
end
|
|
724
|
+
end
|
|
725
|
+
|
|
726
|
+
function masking_controller.update_entity_filter(masking: MaskingInternal, entity: Entity, filter: MemberFilter?)
|
|
727
|
+
local generator: MaskGenerator
|
|
728
|
+
if filter then
|
|
729
|
+
generator = masking:create_generator_from_filter(filter)
|
|
730
|
+
else
|
|
731
|
+
generator = mask_generator.follow(masking.active_members_generator)
|
|
732
|
+
end
|
|
733
|
+
local lookup = masking.lookups.entities[entity]
|
|
734
|
+
|
|
735
|
+
local function subscribed()
|
|
736
|
+
if not lookup then
|
|
737
|
+
lookup = masking.lookups.entities[entity]
|
|
738
|
+
end
|
|
739
|
+
local current_storage = lookup.storage_group
|
|
740
|
+
|
|
741
|
+
local new_storage = masking:move_entity_storage(entity, current_storage, generator.bitmask)
|
|
742
|
+
lookup.storage_group = new_storage
|
|
743
|
+
end
|
|
744
|
+
generator.subscribed = subscribed
|
|
745
|
+
return generator
|
|
746
|
+
end
|
|
747
|
+
|
|
748
|
+
function masking_controller.start_entity(masking: MaskingInternal, entity: Entity, filter: MemberFilter?)
|
|
749
|
+
local generator = masking:update_entity_filter(entity, filter)
|
|
750
|
+
|
|
751
|
+
local storage_group = masking:get_or_create_storage_group(generator.bitmask)
|
|
752
|
+
local active = get_or_set_active(storage_group, entity)
|
|
753
|
+
active.is_entity_mask = true
|
|
754
|
+
|
|
755
|
+
local new_lookup: Lookup = {
|
|
756
|
+
generator = generator,
|
|
757
|
+
filter = filter,
|
|
758
|
+
storage_group = storage_group,
|
|
759
|
+
}
|
|
760
|
+
masking.lookups.entities[entity] = new_lookup
|
|
761
|
+
|
|
762
|
+
local posponed = masking.lookups.posponed[entity]
|
|
763
|
+
if posponed then
|
|
764
|
+
for component_type, components in posponed do
|
|
765
|
+
for component, component_filter in components do
|
|
766
|
+
masking:start_component(entity, component, component_type, component_filter)
|
|
767
|
+
end
|
|
768
|
+
end
|
|
769
|
+
masking.lookups.posponed[entity] = nil
|
|
770
|
+
end
|
|
771
|
+
end
|
|
772
|
+
|
|
773
|
+
function masking_controller.set_entity(masking: MaskingInternal, entity: Entity, filter: MemberFilter?)
|
|
774
|
+
local lookup = masking.lookups.entities[entity]
|
|
775
|
+
if not lookup then
|
|
776
|
+
utils.logerror "attempted to modify the filter of an unactive entity"
|
|
777
|
+
end
|
|
778
|
+
lookup.generator:destroy()
|
|
779
|
+
|
|
780
|
+
local generator = masking:update_entity_filter(entity, filter)
|
|
781
|
+
|
|
782
|
+
lookup.generator = generator
|
|
783
|
+
lookup.filter = filter
|
|
784
|
+
|
|
785
|
+
generator:run_subscribed()
|
|
786
|
+
masking:rebind_component_generators(entity)
|
|
787
|
+
end
|
|
788
|
+
|
|
789
|
+
function masking_controller.stop_entity(masking: MaskingInternal, entity: Entity)
|
|
790
|
+
local lookup = masking.lookups.entities[entity]
|
|
791
|
+
if not lookup then
|
|
792
|
+
utils.logerror "attemped to stop an unactive entity"
|
|
793
|
+
end
|
|
794
|
+
|
|
795
|
+
local posponed = masking.lookups.posponed[entity]
|
|
796
|
+
|
|
797
|
+
local components_lookup = masking.lookups.components[entity]
|
|
798
|
+
if components_lookup then
|
|
799
|
+
for component_type, lookups in components_lookup do
|
|
800
|
+
for component, component_lookup in lookups do
|
|
801
|
+
component_lookup.band_generator:destroy()
|
|
802
|
+
component_lookup.generator:destroy()
|
|
803
|
+
remove_component_active(component_lookup.storage_group, entity, component, component_type)
|
|
804
|
+
|
|
805
|
+
local component_storage = component_lookup.storage_group
|
|
806
|
+
component_storage.shared_with[entity] = nil
|
|
807
|
+
component_storage.changes.added[entity] = nil
|
|
808
|
+
component_storage.changes.changed[entity] = nil
|
|
809
|
+
|
|
810
|
+
if posponed == nil then
|
|
811
|
+
posponed = create_component_indexes()
|
|
812
|
+
masking.lookups.posponed[entity] = posponed
|
|
813
|
+
end
|
|
814
|
+
posponed[component_type][component] = component_lookup.filter :: MemberFilter
|
|
815
|
+
end
|
|
816
|
+
end
|
|
817
|
+
end
|
|
818
|
+
|
|
819
|
+
lookup.generator:destroy()
|
|
820
|
+
remove_active(lookup.storage_group, entity)
|
|
821
|
+
lookup.storage_group.changes.added[entity] = nil
|
|
822
|
+
lookup.storage_group.changes.changed[entity] = nil
|
|
823
|
+
|
|
824
|
+
masking.lookups.components[entity] = nil
|
|
825
|
+
masking.lookups.entities[entity] = nil
|
|
826
|
+
end
|
|
827
|
+
|
|
828
|
+
function masking_controller.update_component_filter(
|
|
829
|
+
masking: MaskingInternal,
|
|
830
|
+
entity: Entity,
|
|
831
|
+
component: Entity,
|
|
832
|
+
component_type: number,
|
|
833
|
+
filter: MemberFilter
|
|
834
|
+
)
|
|
835
|
+
local generator = masking:create_generator_from_filter(filter)
|
|
836
|
+
local band_generator = masking:bind_component_generator(entity, component, component_type, generator)
|
|
837
|
+
return generator, band_generator
|
|
838
|
+
end
|
|
839
|
+
|
|
840
|
+
function masking_controller.start_component(
|
|
841
|
+
masking: MaskingInternal,
|
|
842
|
+
entity: Entity,
|
|
843
|
+
component: Entity,
|
|
844
|
+
component_type: number,
|
|
845
|
+
filter: MemberFilter?
|
|
846
|
+
)
|
|
847
|
+
local lookup = masking:get_or_pospone_entity_lookup(entity, component, component_type, filter)
|
|
848
|
+
if lookup == nil then
|
|
849
|
+
return
|
|
850
|
+
end
|
|
851
|
+
|
|
852
|
+
if filter == nil then
|
|
853
|
+
get_or_set_component_active(lookup.storage_group.active[entity], component, component_type)
|
|
854
|
+
return
|
|
855
|
+
end
|
|
856
|
+
|
|
857
|
+
local generator, band_generator = masking:update_component_filter(entity, component, component_type, filter)
|
|
858
|
+
local storage_group = masking:get_or_create_storage_group(band_generator.bitmask)
|
|
859
|
+
local active = get_or_set_active(storage_group, entity)
|
|
860
|
+
|
|
861
|
+
get_or_set_component_active(active, component, component_type)
|
|
862
|
+
set_component_index_entry(storage_group.shared_with, entity, component, component_type, true)
|
|
863
|
+
|
|
864
|
+
set_component_index_entry(masking.lookups.components, entity, component, component_type, {
|
|
865
|
+
generator = generator,
|
|
866
|
+
band_generator = band_generator,
|
|
867
|
+
filter = filter,
|
|
868
|
+
storage_group = storage_group,
|
|
869
|
+
})
|
|
870
|
+
end
|
|
871
|
+
|
|
872
|
+
function masking_controller.set_component(
|
|
873
|
+
masking: MaskingInternal,
|
|
874
|
+
entity: Entity,
|
|
875
|
+
component: Entity,
|
|
876
|
+
component_type: number,
|
|
877
|
+
filter: MemberFilter?
|
|
878
|
+
)
|
|
879
|
+
local lookup = masking:get_or_pospone_entity_lookup(entity, component, component_type, filter)
|
|
880
|
+
if lookup == nil then
|
|
881
|
+
return
|
|
882
|
+
end
|
|
883
|
+
local component_lookup = get_component_index_entry(masking.lookups.components, entity, component, component_type)
|
|
884
|
+
|
|
885
|
+
if filter == nil then
|
|
886
|
+
if component_lookup ~= nil then
|
|
887
|
+
component_lookup.band_generator:destroy()
|
|
888
|
+
component_lookup.generator:destroy()
|
|
889
|
+
|
|
890
|
+
masking:merge_component_filter(entity, component, component_type)
|
|
891
|
+
end
|
|
892
|
+
return
|
|
893
|
+
end
|
|
894
|
+
|
|
895
|
+
local generator, band_generator = masking:update_component_filter(entity, component, component_type, filter)
|
|
896
|
+
|
|
897
|
+
if component_lookup ~= nil then
|
|
898
|
+
component_lookup.band_generator:destroy()
|
|
899
|
+
component_lookup.generator:destroy()
|
|
900
|
+
|
|
901
|
+
component_lookup.band_generator = band_generator
|
|
902
|
+
component_lookup.generator = generator
|
|
903
|
+
component_lookup.filter = filter
|
|
904
|
+
|
|
905
|
+
band_generator:run_subscribed()
|
|
906
|
+
else
|
|
907
|
+
local desired_storage = masking:get_or_create_storage_group(band_generator.bitmask)
|
|
908
|
+
local new_storage: StorageGroup
|
|
909
|
+
|
|
910
|
+
if desired_storage and desired_storage == lookup.storage_group then
|
|
911
|
+
new_storage = lookup.storage_group
|
|
912
|
+
set_component_index_entry(desired_storage.shared_with, entity, component, component_type, true)
|
|
913
|
+
else
|
|
914
|
+
new_storage = masking:move_component_storage(
|
|
915
|
+
entity,
|
|
916
|
+
component,
|
|
917
|
+
component_type,
|
|
918
|
+
lookup.storage_group,
|
|
919
|
+
band_generator.bitmask
|
|
920
|
+
)
|
|
921
|
+
end
|
|
922
|
+
|
|
923
|
+
set_component_index_entry(masking.lookups.components, entity, component, component_type, {
|
|
924
|
+
generator = generator,
|
|
925
|
+
band_generator = band_generator,
|
|
926
|
+
filter = filter,
|
|
927
|
+
storage_group = new_storage,
|
|
928
|
+
})
|
|
929
|
+
end
|
|
930
|
+
end
|
|
931
|
+
|
|
932
|
+
function masking_controller.stop_component(
|
|
933
|
+
masking: MaskingInternal,
|
|
934
|
+
entity: Entity,
|
|
935
|
+
component: Entity,
|
|
936
|
+
component_type: number
|
|
937
|
+
)
|
|
938
|
+
local lookup = get_component_index_entry(masking.lookups.components, entity, component, component_type)
|
|
939
|
+
if lookup ~= nil then
|
|
940
|
+
lookup.band_generator:destroy()
|
|
941
|
+
lookup.generator:destroy()
|
|
942
|
+
|
|
943
|
+
remove_component_active(lookup.storage_group, entity, component, component_type)
|
|
944
|
+
remove_component_index_entry(lookup.storage_group.shared_with, entity, component, component_type)
|
|
945
|
+
remove_component_index_entry(masking.lookups.components, entity, component, component_type)
|
|
946
|
+
else
|
|
947
|
+
local entity_lookup = masking.lookups.entities[entity]
|
|
948
|
+
if entity_lookup then
|
|
949
|
+
remove_component_active(entity_lookup.storage_group, entity, component, component_type)
|
|
950
|
+
end
|
|
951
|
+
end
|
|
952
|
+
end
|
|
953
|
+
|
|
954
|
+
function masking_controller.get_component_storage_group(
|
|
955
|
+
masking: MaskingInternal,
|
|
956
|
+
entity: Entity,
|
|
957
|
+
component: Entity,
|
|
958
|
+
component_type: number
|
|
959
|
+
): StorageGroup
|
|
960
|
+
local component_lookup = masking_controller.get_component_index_entry(
|
|
961
|
+
masking.lookups.components,
|
|
962
|
+
entity,
|
|
963
|
+
component,
|
|
964
|
+
COMPONENT_TYPES.component
|
|
965
|
+
)
|
|
966
|
+
if component_lookup ~= nil then
|
|
967
|
+
return component_lookup.storage_group
|
|
968
|
+
else
|
|
969
|
+
local entity_lookup = masking.lookups.entities[entity]
|
|
970
|
+
if not entity_lookup then
|
|
971
|
+
utils.logerror "attempted to use an entity that is not active"
|
|
972
|
+
end
|
|
973
|
+
return entity_lookup.storage_group
|
|
974
|
+
end
|
|
975
|
+
end
|
|
976
|
+
|
|
977
|
+
function masking_controller.allocate_entity_addition(
|
|
978
|
+
masking: MaskingInternal,
|
|
979
|
+
entity: Entity,
|
|
980
|
+
component: Entity,
|
|
981
|
+
component_type: number
|
|
982
|
+
)
|
|
983
|
+
local lookup = get_component_index_entry(masking.lookups.components, entity, component, component_type)
|
|
984
|
+
if lookup ~= nil then
|
|
985
|
+
lookup.storage_group.changes.added[entity] = true
|
|
986
|
+
end
|
|
987
|
+
end
|
|
988
|
+
|
|
989
|
+
function masking_controller.allocate_component_change(
|
|
990
|
+
masking: MaskingInternal,
|
|
991
|
+
entity: Entity,
|
|
992
|
+
component: Entity,
|
|
993
|
+
value: any
|
|
994
|
+
)
|
|
995
|
+
local storage = masking:get_component_storage_group(entity, component, COMPONENT_TYPES.component)
|
|
996
|
+
local changes = get_or_set_changes(storage, entity)
|
|
997
|
+
changes.component[component] = value
|
|
998
|
+
end
|
|
999
|
+
|
|
1000
|
+
function masking_controller.allocate_tag_addition(masking: MaskingInternal, entity: Entity, tag: Entity)
|
|
1001
|
+
local storage = masking:get_component_storage_group(entity, tag, COMPONENT_TYPES.tag)
|
|
1002
|
+
local changes = get_or_set_changes(storage, entity)
|
|
1003
|
+
changes.tagged[tag] = true
|
|
1004
|
+
end
|
|
1005
|
+
|
|
1006
|
+
function masking_controller.allocate_pair_addition(
|
|
1007
|
+
masking: MaskingInternal,
|
|
1008
|
+
entity: Entity,
|
|
1009
|
+
relation: Entity,
|
|
1010
|
+
target: Entity
|
|
1011
|
+
)
|
|
1012
|
+
local storage = masking:get_component_storage_group(entity, relation, COMPONENT_TYPES.pair)
|
|
1013
|
+
local changes = get_or_set_changes(storage, entity)
|
|
1014
|
+
local targets = changes.pairs[relation]
|
|
1015
|
+
if targets == nil then
|
|
1016
|
+
targets = {}
|
|
1017
|
+
changes.pairs[relation] = targets
|
|
1018
|
+
end
|
|
1019
|
+
targets[target] = true
|
|
1020
|
+
end
|
|
1021
|
+
|
|
1022
|
+
function masking_controller.allocate_component_removal(masking: MaskingInternal, entity: Entity, component: Entity)
|
|
1023
|
+
local storage = masking:get_component_storage_group(entity, component, COMPONENT_TYPES.component)
|
|
1024
|
+
local changes = get_or_set_changes(storage, entity)
|
|
1025
|
+
|
|
1026
|
+
if changes.component[component] then
|
|
1027
|
+
changes.component[component] = nil
|
|
1028
|
+
end
|
|
1029
|
+
changes.removed[component] = true
|
|
1030
|
+
end
|
|
1031
|
+
|
|
1032
|
+
function masking_controller.allocate_tag_removal(masking: MaskingInternal, entity: Entity, tag: Entity)
|
|
1033
|
+
local storage = masking:get_component_storage_group(entity, tag, COMPONENT_TYPES.tag)
|
|
1034
|
+
local changes = get_or_set_changes(storage, entity)
|
|
1035
|
+
|
|
1036
|
+
if changes.tagged[tag] then
|
|
1037
|
+
changes.tagged[tag] = nil
|
|
1038
|
+
end
|
|
1039
|
+
changes.removed[tag] = true
|
|
1040
|
+
end
|
|
1041
|
+
|
|
1042
|
+
function masking_controller.allocate_pair_removal(
|
|
1043
|
+
masking: MaskingInternal,
|
|
1044
|
+
entity: Entity,
|
|
1045
|
+
relation: Entity,
|
|
1046
|
+
target: Entity
|
|
1047
|
+
)
|
|
1048
|
+
local storage = masking:get_component_storage_group(entity, relation, COMPONENT_TYPES.pair)
|
|
1049
|
+
local changes = get_or_set_changes(storage, entity)
|
|
1050
|
+
local targets = changes.pairs[relation]
|
|
1051
|
+
if targets == nil then
|
|
1052
|
+
targets = {}
|
|
1053
|
+
changes.pairs[relation] = targets
|
|
1054
|
+
end
|
|
1055
|
+
targets[target] = false
|
|
1056
|
+
end
|
|
1057
|
+
|
|
1058
|
+
function masking_controller.compact_members()
|
|
1059
|
+
-- TODO: implement
|
|
1060
|
+
end
|
|
1061
|
+
|
|
1062
|
+
function masking_controller.create_generator_from_filter(masking: MaskingInternal, filter: MemberFilter): MaskGenerator
|
|
1063
|
+
local is_include = is_include_filter(filter)
|
|
1064
|
+
if is_include then
|
|
1065
|
+
return masking:create_include_generator(filter) :: MaskGenerator
|
|
1066
|
+
else
|
|
1067
|
+
return masking:create_exclude_generator(filter) :: MaskGenerator
|
|
1068
|
+
end
|
|
1069
|
+
end
|
|
1070
|
+
|
|
1071
|
+
function masking_controller.create_exclude_generator(masking: MaskingInternal, exclude: MemberFilter): MaskGenerator
|
|
1072
|
+
local bitmask = utils.bitmask.from_set(masking.member_indexes, exclude, masking.member_count)
|
|
1073
|
+
local active = masking.active_members_generator
|
|
1074
|
+
|
|
1075
|
+
local generator = mask_generator.create(nil, function()
|
|
1076
|
+
return active.bitmask:band(bitmask:bnot())
|
|
1077
|
+
end)
|
|
1078
|
+
generator:track(active)
|
|
1079
|
+
|
|
1080
|
+
return generator
|
|
1081
|
+
end
|
|
1082
|
+
|
|
1083
|
+
-- TODO: check for players existing and register them if they don't
|
|
1084
|
+
function masking_controller.create_include_generator(masking: MaskingInternal, filter: MemberFilter): MaskGenerator
|
|
1085
|
+
local bitmask = utils.bitmask.from_set(masking.member_indexes, filter, masking.member_count)
|
|
1086
|
+
local active = masking.active_members_generator
|
|
1087
|
+
|
|
1088
|
+
local generator = mask_generator.create(nil, function()
|
|
1089
|
+
return bitmask:band(active.bitmask)
|
|
1090
|
+
end)
|
|
1091
|
+
generator:track(active)
|
|
1092
|
+
|
|
1093
|
+
return generator
|
|
1094
|
+
end
|
|
1095
|
+
|
|
1096
|
+
function masking_controller.create_all_members_generator(masking: MaskingInternal): MaskGenerator
|
|
1097
|
+
local filter: MemberFilter = {}
|
|
1098
|
+
for member in masking.member_indexes do
|
|
1099
|
+
filter[member] = true
|
|
1100
|
+
end
|
|
1101
|
+
local bitmask = utils.bitmask.from_set(masking.member_indexes, filter, masking.member_count)
|
|
1102
|
+
return mask_generator.create(bitmask)
|
|
1103
|
+
end
|
|
1104
|
+
function masking_controller.create_unactive_generator(masking: MaskingController): MaskGenerator
|
|
1105
|
+
local bitmask = utils.bitmask.from_set(masking.member_indexes, masking.unreplicated, masking.member_count)
|
|
1106
|
+
return mask_generator.create(bitmask)
|
|
1107
|
+
end
|
|
1108
|
+
function masking_controller.create_active_generator(masking: MaskingController): MaskGenerator
|
|
1109
|
+
local all = masking.all_members_generator
|
|
1110
|
+
local unactive = masking.unactive_members_generator
|
|
1111
|
+
|
|
1112
|
+
local new_generator = mask_generator.create(nil, function()
|
|
1113
|
+
return all.bitmask:band(unactive.bitmask:bnot())
|
|
1114
|
+
end)
|
|
1115
|
+
new_generator:track(all)
|
|
1116
|
+
new_generator:track(unactive)
|
|
1117
|
+
|
|
1118
|
+
return new_generator
|
|
1119
|
+
end
|
|
1120
|
+
|
|
1121
|
+
function masking_controller.register_member(masking: MaskingInternal, member: Member)
|
|
1122
|
+
if masking.member_indexes[member] then
|
|
1123
|
+
return
|
|
1124
|
+
end
|
|
1125
|
+
|
|
1126
|
+
local current = masking.member_count
|
|
1127
|
+
masking.member_indexes[member] = current
|
|
1128
|
+
masking.member_count += 1
|
|
1129
|
+
|
|
1130
|
+
masking.unreplicated[member] = true
|
|
1131
|
+
masking.unactive_members_generator.bitmask:set(current)
|
|
1132
|
+
masking.all_members_generator.bitmask:set(current)
|
|
1133
|
+
masking.active_members_generator:compute()
|
|
1134
|
+
end
|
|
1135
|
+
|
|
1136
|
+
function masking_controller.unregister_member(masking: MaskingInternal, member: Member)
|
|
1137
|
+
local index = masking.member_indexes[member]
|
|
1138
|
+
if index == nil then
|
|
1139
|
+
return
|
|
1140
|
+
end
|
|
1141
|
+
masking.member_indexes[member] = nil
|
|
1142
|
+
masking.member_count -= 1
|
|
1143
|
+
masking.all_members_generator.bitmask:clear(index)
|
|
1144
|
+
masking.active_members_generator:compute()
|
|
1145
|
+
end
|
|
1146
|
+
|
|
1147
|
+
function masking_controller.activate_member(masking: MaskingInternal, member: Member)
|
|
1148
|
+
local index = masking.member_indexes[member]
|
|
1149
|
+
if index == nil then
|
|
1150
|
+
masking:register_member(member)
|
|
1151
|
+
index = masking.member_indexes[member]
|
|
1152
|
+
end
|
|
1153
|
+
|
|
1154
|
+
masking.unreplicated[member] = nil
|
|
1155
|
+
masking.unactive_members_generator.bitmask:clear(index)
|
|
1156
|
+
masking.active_members_generator:compute()
|
|
1157
|
+
end
|
|
1158
|
+
|
|
1159
|
+
function masking_controller.member_is_active(masking: MaskingInternal, member: Member): boolean
|
|
1160
|
+
local index = masking.member_indexes[member]
|
|
1161
|
+
if index == nil then
|
|
1162
|
+
return false
|
|
1163
|
+
end
|
|
1164
|
+
|
|
1165
|
+
return masking.active_members_generator.bitmask:get(index)
|
|
1166
|
+
end
|
|
1167
|
+
|
|
1168
|
+
local function create(): MaskingController
|
|
1169
|
+
local self = {} :: MaskingInternal
|
|
1170
|
+
|
|
1171
|
+
self.member_indexes = {}
|
|
1172
|
+
self.member_count = 0
|
|
1173
|
+
self.storages = {}
|
|
1174
|
+
self.lookups = {
|
|
1175
|
+
entities = {},
|
|
1176
|
+
components = {},
|
|
1177
|
+
deletions = {
|
|
1178
|
+
entities = {},
|
|
1179
|
+
components = {},
|
|
1180
|
+
},
|
|
1181
|
+
posponed = {},
|
|
1182
|
+
}
|
|
1183
|
+
self.unreplicated = {}
|
|
1184
|
+
self.all_members_generator = masking_controller.create_all_members_generator(self)
|
|
1185
|
+
self.unactive_members_generator = masking_controller.create_unactive_generator(self)
|
|
1186
|
+
self.active_members_generator = masking_controller.create_active_generator(self)
|
|
1187
|
+
|
|
1188
|
+
return setmetatable(self, masking_controller) :: any
|
|
1189
|
+
end
|
|
1190
|
+
|
|
1191
|
+
return { create = create, masking_controller = masking_controller, COMPONENT_TYPES = COMPONENT_TYPES }
|