@rbxts/replecs 0.0.1-rc.1 → 0.1.0-alpha2

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.
@@ -1,12 +1,16 @@
1
- local jecs = require(script.Parent.Parent.jecs)
2
- local utils = require(script.Parent.utils)
3
- local mask_generator = require(script.mask_generator)
1
+ --!native
2
+ --!optimize 2
3
+
4
+ local jecs = require "../jecs"
5
+ local utils = require "./utils"
6
+ local mask_generator = require "@self/mask_generator"
4
7
 
5
8
  type Entity<T = any> = jecs.Entity<T>
6
9
 
7
10
  type Bitmask = utils.Bitmask
8
11
  type MaskGenerator = mask_generator.MaskGenerator
9
12
 
13
+ type GivenFilter = MemberFilter | any
10
14
  type MemberFilter = Set<Member>
11
15
  type Member = any
12
16
  type MaskHash = string
@@ -15,23 +19,30 @@ type Set<T> = { [T]: boolean }
15
19
  type Map<K, V> = { [K]: V }
16
20
  type Array<T> = { T }
17
21
 
18
- type ComponentIndex<T> = {
22
+ export type FunctionFilter = (player: Player) -> boolean
23
+
24
+ export type ComponentIndex<T> = {
19
25
  [number]: { [Entity]: T },
20
26
  }
21
- type EntityComponentIndex<T> = {
27
+ export type EntityComponentIndex<T> = {
22
28
  [Entity]: ComponentIndex<T>,
23
29
  }
24
30
 
25
31
  type Lookup = {
26
32
  generator: MaskGenerator,
27
- -- filter in component lookups will never be nil
28
33
  filter: MemberFilter?,
29
34
  storage_group: StorageGroup,
30
35
  }
36
+
31
37
  type ComponentLookup = Lookup & {
32
38
  band_generator: MaskGenerator,
33
39
  }
34
40
 
41
+ type EntityLookup = Lookup & {
42
+ filtered_components: ComponentIndex<ComponentLookup>,
43
+ components: ComponentIndex<true>,
44
+ }
45
+
35
46
  export type EntityChanges = {
36
47
  tagged: { [Entity]: boolean },
37
48
  component: { [Entity]: any },
@@ -39,16 +50,17 @@ export type EntityChanges = {
39
50
  pairs: { [Entity]: Set<Entity> },
40
51
  }
41
52
 
53
+ type PostponedList = ComponentIndex<{ filter: MemberFilter? }>
54
+
42
55
  type LookupsList = {
43
- entities: Map<Entity, Lookup>,
44
- components: EntityComponentIndex<ComponentLookup>,
56
+ entities: Map<Entity, EntityLookup>,
45
57
 
46
58
  deletions: {
47
59
  entities: Map<Entity, Lookup>,
48
60
  components: EntityComponentIndex<Lookup>,
49
61
  },
50
62
 
51
- posponed: EntityComponentIndex<MemberFilter>,
63
+ postponed: { [Entity]: PostponedList },
52
64
  }
53
65
 
54
66
  export type ActiveEntity = {
@@ -90,6 +102,7 @@ type Storages = {
90
102
  export type MaskingController = {
91
103
  member_count: number,
92
104
  member_indexes: { [Member]: number },
105
+ compact_count: number,
93
106
  unreplicated: Set<Member>,
94
107
 
95
108
  all_members_generator: MaskGenerator,
@@ -124,6 +137,7 @@ export type MaskingController = {
124
137
  start_entity: (self: MaskingController, entity: Entity, filter: MemberFilter?) -> (),
125
138
  set_entity: (self: MaskingController, entity: Entity, filter: MemberFilter?) -> (),
126
139
  stop_entity: (self: MaskingController, entity: Entity) -> (),
140
+ cleanup_entity: (self: MaskingController, entity: Entity) -> (),
127
141
 
128
142
  start_component: (
129
143
  self: MaskingController,
@@ -179,8 +193,20 @@ function masking_controller.get_members_from_bitmask(controller: MaskingInternal
179
193
  return members
180
194
  end
181
195
 
196
+ local function get_usable_filter(filter: (MemberFilter | any)?): MemberFilter?
197
+ if filter then
198
+ if type(filter) == "table" then
199
+ return filter
200
+ else
201
+ return { [filter] = true }
202
+ end
203
+ else
204
+ return nil
205
+ end
206
+ end
207
+
182
208
  local function create_component_indexes<T>()
183
- return { {}, {}, {}, {} } :: ComponentIndex<T>
209
+ return { {}, {}, {}, {} } :: ComponentIndex<any>
184
210
  end
185
211
 
186
212
  local function create_entity_changes(): EntityChanges
@@ -234,7 +260,7 @@ function masking_controller.create_new_storage(
234
260
  end
235
261
 
236
262
  local function is_include_filter(filter: MemberFilter): boolean
237
- for player, allow in filter do
263
+ for _, allow in filter do
238
264
  if allow then
239
265
  return true
240
266
  else
@@ -260,17 +286,6 @@ local function create_new_changes(): EntityChanges
260
286
  }
261
287
  end
262
288
 
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
289
  local function get_component_index_entry<T>(
275
290
  index: EntityComponentIndex<T>,
276
291
  entity: Entity,
@@ -373,6 +388,27 @@ local function remove_component_active(storage: StorageGroup, entity: Entity, co
373
388
  end
374
389
  end
375
390
 
391
+ function masking_controller.get_or_create_storage_group(masking: MaskingInternal, bitmask: Bitmask): StorageGroup
392
+ local hash = bitmask:tostring()
393
+ local storage = masking.storages[hash]
394
+
395
+ if not storage then
396
+ storage = masking:create_new_storage(bitmask, hash)
397
+ masking.storages[hash] = storage
398
+ end
399
+ return storage
400
+ end
401
+
402
+ function masking_controller.get_component_lookup(
403
+ masking: MaskingInternal,
404
+ entity: Entity,
405
+ component: Entity,
406
+ component_type: number
407
+ ): (ComponentLookup, EntityLookup)
408
+ local entity_lookup = masking.lookups.entities[entity]
409
+ return entity_lookup.filtered_components[component_type][component], entity_lookup
410
+ end
411
+
376
412
  local function dissect_component_actives(
377
413
  storage: StorageGroup,
378
414
  entity: Entity,
@@ -450,8 +486,7 @@ function masking_controller.merge_component_filter(
450
486
  component: Entity,
451
487
  component_type: number
452
488
  )
453
- local component_lookup = get_component_index_entry(masking.lookups.components, entity, component, component_type)
454
- local entity_lookup = masking.lookups.entities[entity]
489
+ local component_lookup, entity_lookup = masking:get_component_lookup(entity, component, component_type)
455
490
  if not entity_lookup then
456
491
  utils.logerror "attempted to merge a component filter to an unactive entity"
457
492
  end
@@ -464,7 +499,7 @@ function masking_controller.merge_component_filter(
464
499
  component_lookup.storage_group,
465
500
  entity_lookup.generator.bitmask
466
501
  )
467
- remove_component_index_entry(masking.lookups.components, entity, component, component_type)
502
+ entity_lookup.filtered_components[component_type][component] = nil
468
503
  remove_component_index_entry(new_storage.shared_with, entity, component, component_type)
469
504
  else
470
505
  get_or_set_component_active(entity_lookup.storage_group.active[entity], component, component_type)
@@ -577,16 +612,14 @@ function masking_controller.bind_component_generator(
577
612
  component_type: number,
578
613
  base_generator: MaskGenerator
579
614
  )
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]
615
+ local component_lookup, entity_lookup = masking:get_component_lookup(entity, component, component_type)
583
616
  local generator = mask_generator.create(nil, function()
584
617
  return entity_lookup.generator.bitmask:band(base_generator.bitmask)
585
618
  end)
586
619
 
587
620
  local function subscribed()
588
621
  if not component_lookup then
589
- component_lookup = component_lookups and component_lookups[component_type][component]
622
+ component_lookup = entity_lookup.filtered_components[component_type][component]
590
623
  end
591
624
 
592
625
  local current_storage = component_lookup.storage_group
@@ -604,9 +637,9 @@ function masking_controller.bind_component_generator(
604
637
  end
605
638
 
606
639
  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
640
+ local entity_lookup = masking.lookups.entities[entity]
641
+ if entity_lookup then
642
+ for component_type, lookups in entity_lookup.filtered_components do
610
643
  for component, lookup in lookups do
611
644
  lookup.band_generator:destroy()
612
645
 
@@ -619,23 +652,24 @@ function masking_controller.rebind_component_generators(masking: MaskingInternal
619
652
  end
620
653
  end
621
654
 
622
- function masking_controller.get_or_pospone_entity_lookup(
655
+ function masking_controller.get_or_postpone_entity_lookup(
623
656
  masking: MaskingInternal,
624
657
  entity: Entity,
625
658
  component: Entity,
626
659
  component_type: number,
627
660
  filter: MemberFilter?
628
- ): Lookup?
661
+ ): EntityLookup?
629
662
  local lookup = masking.lookups.entities[entity]
630
663
  if lookup then
631
664
  return lookup
632
665
  end
633
666
 
634
- if filter == nil then
635
- return nil
667
+ if filter ~= nil then
668
+ set_component_index_entry(masking.lookups.postponed, entity, component, component_type, { filter = filter })
669
+ else
670
+ set_component_index_entry(masking.lookups.postponed, entity, component, component_type, { filter = nil })
636
671
  end
637
672
 
638
- set_component_index_entry(masking.lookups.posponed, entity, component, component_type, filter)
639
673
  return nil
640
674
  end
641
675
 
@@ -711,12 +745,9 @@ function masking_controller.propagate_entity_addition(masking: MaskingInternal,
711
745
  local entity_lookup = masking.lookups.entities[entity]
712
746
  if entity_lookup then
713
747
  entity_lookup.storage_group.changes.added[entity] = true
714
- end
715
748
 
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
749
+ for _, lookups in entity_lookup.filtered_components do
750
+ for _, lookup in lookups do
720
751
  lookup.storage_group.changes.added[entity] = true
721
752
  end
722
753
  end
@@ -745,32 +776,36 @@ function masking_controller.update_entity_filter(masking: MaskingInternal, entit
745
776
  return generator
746
777
  end
747
778
 
748
- function masking_controller.start_entity(masking: MaskingInternal, entity: Entity, filter: MemberFilter?)
779
+ function masking_controller.start_entity(masking: MaskingInternal, entity: Entity, given_filter: GivenFilter?)
780
+ local filter = get_usable_filter(given_filter)
749
781
  local generator = masking:update_entity_filter(entity, filter)
750
782
 
751
783
  local storage_group = masking:get_or_create_storage_group(generator.bitmask)
752
784
  local active = get_or_set_active(storage_group, entity)
753
785
  active.is_entity_mask = true
754
786
 
755
- local new_lookup: Lookup = {
787
+ local new_lookup: EntityLookup = {
756
788
  generator = generator,
757
789
  filter = filter,
758
790
  storage_group = storage_group,
791
+ filtered_components = create_component_indexes(),
792
+ components = create_component_indexes(),
759
793
  }
760
794
  masking.lookups.entities[entity] = new_lookup
761
795
 
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)
796
+ local postponed = masking.lookups.postponed[entity]
797
+ if postponed then
798
+ for component_type, components in postponed do
799
+ for component, postoned_info in components do
800
+ masking:start_component(entity, component, component_type, postoned_info.filter)
767
801
  end
768
802
  end
769
- masking.lookups.posponed[entity] = nil
803
+ masking.lookups.postponed[entity] = nil
770
804
  end
771
805
  end
772
806
 
773
- function masking_controller.set_entity(masking: MaskingInternal, entity: Entity, filter: MemberFilter?)
807
+ function masking_controller.set_entity(masking: MaskingInternal, entity: Entity, given_filter: GivenFilter?)
808
+ local filter = get_usable_filter(given_filter)
774
809
  local lookup = masking.lookups.entities[entity]
775
810
  if not lookup then
776
811
  utils.logerror "attempted to modify the filter of an unactive entity"
@@ -792,27 +827,24 @@ function masking_controller.stop_entity(masking: MaskingInternal, entity: Entity
792
827
  utils.logerror "attemped to stop an unactive entity"
793
828
  end
794
829
 
795
- local posponed = masking.lookups.posponed[entity]
830
+ local postponed = masking.lookups.postponed[entity]
796
831
 
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)
832
+ for component_type, lookups in lookup.filtered_components do
833
+ for component, component_lookup in lookups do
834
+ component_lookup.band_generator:destroy()
835
+ component_lookup.generator:destroy()
836
+ remove_component_active(component_lookup.storage_group, entity, component, component_type)
804
837
 
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
838
+ local component_storage = component_lookup.storage_group
839
+ component_storage.shared_with[entity] = nil
840
+ component_storage.changes.added[entity] = nil
841
+ component_storage.changes.changed[entity] = nil
809
842
 
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
843
+ if postponed == nil then
844
+ postponed = create_component_indexes() :: PostponedList
845
+ masking.lookups.postponed[entity] = postponed
815
846
  end
847
+ postponed[component_type][component] = { filter = component_lookup.filter }
816
848
  end
817
849
  end
818
850
 
@@ -821,10 +853,16 @@ function masking_controller.stop_entity(masking: MaskingInternal, entity: Entity
821
853
  lookup.storage_group.changes.added[entity] = nil
822
854
  lookup.storage_group.changes.changed[entity] = nil
823
855
 
824
- masking.lookups.components[entity] = nil
825
856
  masking.lookups.entities[entity] = nil
826
857
  end
827
858
 
859
+ function masking_controller.cleanup_entity(masking: MaskingInternal, entity: Entity)
860
+ masking.lookups.entities[entity] = nil
861
+ masking.lookups.postponed[entity] = nil
862
+ masking.lookups.deletions.entities[entity] = nil
863
+ masking.lookups.deletions.components[entity] = nil
864
+ end
865
+
828
866
  function masking_controller.update_component_filter(
829
867
  masking: MaskingInternal,
830
868
  entity: Entity,
@@ -842,9 +880,10 @@ function masking_controller.start_component(
842
880
  entity: Entity,
843
881
  component: Entity,
844
882
  component_type: number,
845
- filter: MemberFilter?
883
+ given_filter: GivenFilter?
846
884
  )
847
- local lookup = masking:get_or_pospone_entity_lookup(entity, component, component_type, filter)
885
+ local filter = get_usable_filter(given_filter)
886
+ local lookup = masking:get_or_postpone_entity_lookup(entity, component, component_type, filter)
848
887
  if lookup == nil then
849
888
  return
850
889
  end
@@ -861,12 +900,13 @@ function masking_controller.start_component(
861
900
  get_or_set_component_active(active, component, component_type)
862
901
  set_component_index_entry(storage_group.shared_with, entity, component, component_type, true)
863
902
 
864
- set_component_index_entry(masking.lookups.components, entity, component, component_type, {
903
+ local component_lookup: ComponentLookup = {
865
904
  generator = generator,
866
905
  band_generator = band_generator,
867
- filter = filter,
906
+ filter = filter :: MemberFilter?, -- what
868
907
  storage_group = storage_group,
869
- })
908
+ }
909
+ lookup.filtered_components[component_type][component] = component_lookup
870
910
  end
871
911
 
872
912
  function masking_controller.set_component(
@@ -874,13 +914,14 @@ function masking_controller.set_component(
874
914
  entity: Entity,
875
915
  component: Entity,
876
916
  component_type: number,
877
- filter: MemberFilter?
917
+ given_filter: GivenFilter?
878
918
  )
879
- local lookup = masking:get_or_pospone_entity_lookup(entity, component, component_type, filter)
919
+ local filter = get_usable_filter(given_filter)
920
+ local lookup = masking:get_or_postpone_entity_lookup(entity, component, component_type, filter)
880
921
  if lookup == nil then
881
922
  return
882
923
  end
883
- local component_lookup = get_component_index_entry(masking.lookups.components, entity, component, component_type)
924
+ local component_lookup = lookup.filtered_components[component_type][component]
884
925
 
885
926
  if filter == nil then
886
927
  if component_lookup ~= nil then
@@ -919,13 +960,13 @@ function masking_controller.set_component(
919
960
  band_generator.bitmask
920
961
  )
921
962
  end
922
-
923
- set_component_index_entry(masking.lookups.components, entity, component, component_type, {
963
+ local new_lookup: ComponentLookup = {
924
964
  generator = generator,
925
965
  band_generator = band_generator,
926
- filter = filter,
966
+ filter = filter :: MemberFilter?,
927
967
  storage_group = new_storage,
928
- })
968
+ }
969
+ lookup.filtered_components[component_type][component] = new_lookup
929
970
  end
930
971
  end
931
972
 
@@ -935,16 +976,15 @@ function masking_controller.stop_component(
935
976
  component: Entity,
936
977
  component_type: number
937
978
  )
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()
979
+ local component_lookup, entity_lookup = masking:get_component_lookup(entity, component, component_type)
980
+ if component_lookup ~= nil then
981
+ component_lookup.band_generator:destroy()
982
+ component_lookup.generator:destroy()
942
983
 
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)
984
+ remove_component_active(component_lookup.storage_group, entity, component, component_type)
985
+ remove_component_index_entry(component_lookup.storage_group.shared_with, entity, component, component_type)
986
+ entity_lookup.filtered_components[component_type][component] = nil
946
987
  else
947
- local entity_lookup = masking.lookups.entities[entity]
948
988
  if entity_lookup then
949
989
  remove_component_active(entity_lookup.storage_group, entity, component, component_type)
950
990
  end
@@ -957,20 +997,14 @@ function masking_controller.get_component_storage_group(
957
997
  component: Entity,
958
998
  component_type: number
959
999
  ): StorageGroup
960
- local component_lookup = masking_controller.get_component_index_entry(
961
- masking.lookups.components,
962
- entity,
963
- component,
964
- COMPONENT_TYPES.component
965
- )
1000
+ local component_lookup, entity_lookup = masking:get_component_lookup(entity, component, component_type)
1001
+
966
1002
  if component_lookup ~= nil then
967
1003
  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
1004
+ elseif entity_lookup then
973
1005
  return entity_lookup.storage_group
1006
+ else
1007
+ error "attempted to use an entity that is not active"
974
1008
  end
975
1009
  end
976
1010
 
@@ -980,7 +1014,7 @@ function masking_controller.allocate_entity_addition(
980
1014
  component: Entity,
981
1015
  component_type: number
982
1016
  )
983
- local lookup = get_component_index_entry(masking.lookups.components, entity, component, component_type)
1017
+ local lookup = masking:get_component_lookup(entity, component, component_type)
984
1018
  if lookup ~= nil then
985
1019
  lookup.storage_group.changes.added[entity] = true
986
1020
  end
@@ -1055,8 +1089,123 @@ function masking_controller.allocate_pair_removal(
1055
1089
  targets[target] = false
1056
1090
  end
1057
1091
 
1058
- function masking_controller.compact_members()
1059
- -- TODO: implement
1092
+ local function remap_bitmask(
1093
+ bitmask: Bitmask,
1094
+ from: { [Member]: number },
1095
+ target: { [Member]: number },
1096
+ size: number?
1097
+ ): Bitmask
1098
+ local result = utils.bitmask.create(size)
1099
+ for member, index in target do
1100
+ local old_index = from[member]
1101
+ if old_index then
1102
+ local old_bit = bitmask:get(old_index)
1103
+ if old_bit then
1104
+ result:set(index, old_bit)
1105
+ else
1106
+ result:clear(index)
1107
+ end
1108
+ end
1109
+ end
1110
+ return result
1111
+ end
1112
+
1113
+ function masking_controller.merge_storages(
1114
+ masking: MaskingInternal,
1115
+ old_storage: StorageGroup,
1116
+ new_storage: StorageGroup
1117
+ )
1118
+ for entity, active in old_storage.active do
1119
+ local new_active = get_or_set_active(new_storage, entity)
1120
+ merge_component_actives(new_active, active)
1121
+
1122
+ if active.is_entity_mask then
1123
+ local lookup = masking.lookups.entities[entity]
1124
+ lookup.storage_group = new_storage
1125
+ new_active.is_entity_mask = true
1126
+ end
1127
+ end
1128
+ for entity, shared_components in old_storage.shared_with do
1129
+ for component_type, components in shared_components do
1130
+ for component in components do
1131
+ set_component_index_entry(new_storage.shared_with, entity, component, component_type, true)
1132
+
1133
+ local lookup = masking:get_component_lookup(entity, component, component_type)
1134
+ if lookup ~= nil then
1135
+ lookup.storage_group = new_storage
1136
+ end
1137
+ end
1138
+ end
1139
+ end
1140
+ for entity, changes in old_storage.changes.changed do
1141
+ local new_changes = get_or_set_changes(new_storage, entity)
1142
+ merge_component_changes(new_changes, changes)
1143
+ end
1144
+ for entity in old_storage.deletions.entities do
1145
+ new_storage.deletions.entities[entity] = true
1146
+ end
1147
+ for entity, deleted_components in old_storage.deletions.components do
1148
+ for component_type, components in deleted_components do
1149
+ for component in components do
1150
+ set_component_index_entry(new_storage.deletions.components, entity, component, component_type, true)
1151
+ end
1152
+ end
1153
+ end
1154
+ end
1155
+
1156
+ function masking_controller.compact_members(masking: MaskingInternal)
1157
+ -- we dont recompute as nothing should've changed
1158
+ -- so this should be hopefully quite cheap
1159
+ local old_indexes = masking.member_indexes
1160
+ local new_indexes: { [Member]: number } = {}
1161
+
1162
+ local new_count = 0
1163
+ for member in old_indexes do
1164
+ new_indexes[member] = new_count
1165
+ new_count += 1
1166
+ end
1167
+ masking.member_indexes = new_indexes
1168
+ masking.member_count = new_count
1169
+
1170
+ for _, entity_lookup in masking.lookups.entities do
1171
+ local generator = entity_lookup.generator
1172
+ generator.bitmask = remap_bitmask(generator.bitmask, old_indexes, new_indexes, new_count)
1173
+
1174
+ for _, lookups in entity_lookup.filtered_components do
1175
+ for _, component_lookup in lookups do
1176
+ local component_generator = component_lookup.generator
1177
+ generator.bitmask = remap_bitmask(component_generator.bitmask, old_indexes, new_indexes, new_count)
1178
+
1179
+ local band_generator = component_lookup.band_generator
1180
+ band_generator.bitmask = remap_bitmask(band_generator.bitmask, old_indexes, new_indexes, new_count)
1181
+ end
1182
+ end
1183
+ end
1184
+
1185
+ local all = masking.all_members_generator
1186
+ local unactive = masking.unactive_members_generator
1187
+ local active = masking.active_members_generator
1188
+
1189
+ all.bitmask = remap_bitmask(all.bitmask, old_indexes, new_indexes, new_count)
1190
+ unactive.bitmask = remap_bitmask(unactive.bitmask, old_indexes, new_indexes, new_count)
1191
+ active.bitmask = remap_bitmask(active.bitmask, old_indexes, new_indexes, new_count)
1192
+
1193
+ local new_storages: Storages = {}
1194
+
1195
+ for _, storage in masking.storages do
1196
+ local new_bitmask = remap_bitmask(storage.mask.bitmask, old_indexes, new_indexes, new_count)
1197
+ storage.mask.bitmask = new_bitmask
1198
+ local new_hash = new_bitmask:tostring()
1199
+ storage.mask.hash = new_hash
1200
+ storage.mask.members = masking:get_members_from_bitmask(new_bitmask)
1201
+
1202
+ local existing = new_storages[new_hash]
1203
+ if existing then
1204
+ masking:merge_storages(storage, existing)
1205
+ else
1206
+ new_storages[new_hash] = storage
1207
+ end
1208
+ end
1060
1209
  end
1061
1210
 
1062
1211
  function masking_controller.create_generator_from_filter(masking: MaskingInternal, filter: MemberFilter): MaskGenerator
@@ -1131,6 +1280,10 @@ function masking_controller.register_member(masking: MaskingInternal, member: Me
1131
1280
  masking.unactive_members_generator.bitmask:set(current)
1132
1281
  masking.all_members_generator.bitmask:set(current)
1133
1282
  masking.active_members_generator:compute()
1283
+
1284
+ if masking.member_count >= masking.compact_count then
1285
+ masking:compact_members()
1286
+ end
1134
1287
  end
1135
1288
 
1136
1289
  function masking_controller.unregister_member(masking: MaskingInternal, member: Member)
@@ -1170,6 +1323,7 @@ local function create(): MaskingController
1170
1323
 
1171
1324
  self.member_indexes = {}
1172
1325
  self.member_count = 0
1326
+ self.compact_count = 100
1173
1327
  self.storages = {}
1174
1328
  self.lookups = {
1175
1329
  entities = {},
@@ -1178,7 +1332,7 @@ local function create(): MaskingController
1178
1332
  entities = {},
1179
1333
  components = {},
1180
1334
  },
1181
- posponed = {},
1335
+ postponed = {},
1182
1336
  }
1183
1337
  self.unreplicated = {}
1184
1338
  self.all_members_generator = masking_controller.create_all_members_generator(self)
@@ -1,4 +1,7 @@
1
- local utils = require(script.Parent.Parent.utils)
1
+ --!native
2
+ --!optimize 2
3
+
4
+ local utils = require "../utils"
2
5
 
3
6
  type ComputeCallback = (generator: MaskGenerator) -> utils.Bitmask
4
7
  type SubscribeCallback = (generator: MaskGenerator) -> ()
@@ -40,7 +43,7 @@ function mask_generator.unmark_tracked(generator: GeneratorInternal, to_untrack:
40
43
 
41
44
  if last and last ~= to_untrack then
42
45
  generator.tracked_by[index] = last
43
- generator.tracked_indexes[last] = index
46
+ generator.tracked_indexes[last :: GeneratorInternal] = index
44
47
  end
45
48
 
46
49
  generator.tracked_indexes[to_untrack] = nil
@@ -49,17 +52,17 @@ end
49
52
 
50
53
  function mask_generator.run_subscribed(generator: GeneratorInternal)
51
54
  if generator.subscribed then
52
- generator.subscribed(generator)
55
+ generator.subscribed(generator :: GeneratorInternal)
53
56
  end
54
57
  end
55
58
 
56
59
  function mask_generator.compute(generator: GeneratorInternal)
57
60
  if generator.compute_callback then
58
- local result = generator.compute_callback(generator)
61
+ local result = generator.compute_callback(generator :: GeneratorInternal)
59
62
  generator.bitmask = result
60
63
  end
61
64
  if generator.subscribed then
62
- generator.subscribed(generator)
65
+ generator.subscribed(generator :: GeneratorInternal)
63
66
  end
64
67
 
65
68
  for _, tracking in generator.tracked_by do