@rbxts/replecs 0.1.0-alpha7 → 0.1.0-alpha9-test5

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.
@@ -26,6 +26,7 @@ type EntityStorage = {
26
26
  tags: { [Entity]: boolean },
27
27
  values: { [Entity]: any },
28
28
  pairs: { [Entity]: Set<Entity> },
29
+ pairs_values: { [Entity]: Map<Entity, any> },
29
30
  }
30
31
 
31
32
  type Storage = { [Entity]: EntityStorage }
@@ -40,6 +41,9 @@ export type Server = {
40
41
  hooks: common.WorldHooks,
41
42
  alive_tracked: Set<Entity>,
42
43
 
44
+ is_dirty: boolean,
45
+ requires_shared_lookup: { Entity },
46
+
43
47
  track_info: TrackInfo,
44
48
  additions: Set<Entity>,
45
49
  custom_ids: Map<Entity, Entity<any>>,
@@ -62,6 +66,8 @@ export type Server = {
62
66
  collect_unreliable: (self: Server) -> () -> (Player, buffer, { { any } }),
63
67
  mark_player_ready: (self: Server, player: Player) -> (),
64
68
  is_player_ready: (self: Server, player: Player) -> boolean,
69
+ add_player_alias: (self: Server, client: Player, alias: any) -> (),
70
+ remove_player_alias: (self: Server, alias: any) -> (),
65
71
  }
66
72
 
67
73
  local cursor = utils.cursor
@@ -74,18 +80,20 @@ local TRACK_TYPES = {
74
80
  component = 1,
75
81
  tag = 2,
76
82
  pair = 3,
83
+ pair_value = 4,
77
84
  }
85
+
78
86
  local PACKET_TYPES = {
79
87
  full = 1,
80
88
  unreliable = 2,
81
89
  reliable = 3,
82
90
  }
91
+
83
92
  local MAX_PACKET_SIZE = 900
84
93
  local ENTITY_ID_TYPES = {
85
94
  entity = 1,
86
95
  custom = 2,
87
96
  shared = 3,
88
- global = 4,
89
97
  }
90
98
  local ECS_COMPONENT = jecs.Component
91
99
 
@@ -104,7 +112,7 @@ local function track_entity_lifetime(server: Server, entity: Entity)
104
112
  server.world:add(entity, server.components.__alive_tracking__)
105
113
  end
106
114
 
107
- local function get_or_set_entity_storage(server: Server, entity: Entity)
115
+ local function get_or_set_entity_storage(server: Server, entity: Entity): EntityStorage
108
116
  local storage = server.storage[entity]
109
117
 
110
118
  if not storage then
@@ -112,6 +120,7 @@ local function get_or_set_entity_storage(server: Server, entity: Entity)
112
120
  tags = {},
113
121
  values = {},
114
122
  pairs = {},
123
+ pairs_values = {},
115
124
  }
116
125
  server.storage[entity] = storage
117
126
  end
@@ -129,6 +138,23 @@ local function allocate_component_change(server: Server, entity: Entity, compone
129
138
  server.masking:allocate_component_change(entity, component, non_nil)
130
139
  end
131
140
  end
141
+ local function allocate_pair_value_change(server: Server, entity: Entity, relation: Entity, target: Entity, value: any)
142
+ local storage = get_or_set_entity_storage(server, entity)
143
+
144
+ local non_nil = if value == nil then NIL_COMPONENT_VALUE else value
145
+
146
+ local values = storage.pairs_values[relation]
147
+ if values == nil then
148
+ values = {}
149
+ storage.pairs_values[relation] = values
150
+ end
151
+ values[target] = non_nil
152
+
153
+ if not server.additions[entity] and server.track_info.entities[entity] then
154
+ server.masking:allocate_pair_value_change(entity, relation, target, non_nil)
155
+ end
156
+ end
157
+
132
158
  local function allocate_tag_addition(server: Server, entity: Entity, tag: Entity)
133
159
  local storage = get_or_set_entity_storage(server, entity)
134
160
  storage.tags[tag] = true
@@ -159,6 +185,18 @@ local function allocate_component_removal(server: Server, entity: Entity, compon
159
185
  server.masking:allocate_component_removal(entity, component)
160
186
  end
161
187
  end
188
+ local function allocate_pair_value_removal(server: Server, entity: Entity, relation: Entity, target: Entity)
189
+ local storage = get_or_set_entity_storage(server, entity)
190
+ local values = storage.pairs_values[relation]
191
+ if values then
192
+ values[target] = nil
193
+ end
194
+
195
+ if not server.additions[entity] and server.track_info.entities[entity] then
196
+ server.masking:allocate_pair_value_removal(entity, relation, target)
197
+ end
198
+ end
199
+
162
200
  local function allocate_tag_removal(server: Server, entity: Entity, tag: Entity)
163
201
  local storage = get_or_set_entity_storage(server, entity)
164
202
  storage.tags[tag] = nil
@@ -182,6 +220,8 @@ end
182
220
  local function cleanup_entity(server: Server, entity: Entity)
183
221
  server.alive_tracked[entity] = nil
184
222
  server.storage[entity] = nil
223
+ server.global_ids[entity] = nil
224
+ server.custom_ids[entity] = nil
185
225
  server.additions[entity] = nil
186
226
  server.masking:cleanup_entity(entity)
187
227
  end
@@ -207,20 +247,31 @@ local function track_component(server: Server, component: Entity<any>)
207
247
  allocate_component_change(server, entity, component, value)
208
248
  elseif track_type == TRACK_TYPES.tag then
209
249
  allocate_tag_addition(server, entity, component)
210
- else
250
+ elseif track_type == TRACK_TYPES.pair then
211
251
  if not IS_PAIR(id) then
212
252
  return
213
253
  end
214
254
  allocate_pair_addition(server, entity, component, PAIR_SECOND(world, id))
255
+ elseif track_type == TRACK_TYPES.pair_value then
256
+ if not IS_PAIR(id) then
257
+ return
258
+ end
259
+ allocate_pair_value_change(server, entity, component, PAIR_SECOND(world, id), value)
215
260
  end
216
261
  end))
217
- hook(hooks.changed(world, component, function(entity, _id, value)
262
+ hook(hooks.changed(world, component, function(entity, id, value)
218
263
  local track_type = info[entity]
219
264
  if not track_type then
220
265
  return
221
266
  end
222
- -- no check here because only components can trigger changed (I think?)
223
- allocate_component_change(server, entity, component, value)
267
+ if track_type == TRACK_TYPES.component then
268
+ allocate_component_change(server, entity, component, value)
269
+ elseif track_type == TRACK_TYPES.pair_value then
270
+ if not IS_PAIR(id) then
271
+ return
272
+ end
273
+ allocate_pair_value_change(server, entity, component, PAIR_SECOND(world, id), value)
274
+ end
224
275
  end))
225
276
  hook(hooks.removed(world, component, function(entity, id)
226
277
  local track_type = info[entity]
@@ -232,11 +283,16 @@ local function track_component(server: Server, component: Entity<any>)
232
283
  allocate_component_removal(server, entity, component)
233
284
  elseif track_type == TRACK_TYPES.tag then
234
285
  allocate_tag_removal(server, entity, component)
235
- else
286
+ elseif track_type == TRACK_TYPES.pair then
236
287
  if not IS_PAIR(id) then
237
288
  return
238
289
  end
239
290
  allocate_pair_removal(server, entity, component, PAIR_SECOND(world, id))
291
+ elseif track_type == TRACK_TYPES.pair_value then
292
+ if not IS_PAIR(id) then
293
+ return
294
+ end
295
+ allocate_pair_value_removal(server, entity, component, PAIR_SECOND(world, id))
240
296
  end
241
297
  end))
242
298
 
@@ -245,7 +301,6 @@ end
245
301
 
246
302
  local function track_entity_component(server: Server, entity: Entity, component: Entity<any>)
247
303
  local world = server.world
248
-
249
304
  local info = server.track_info.components[component]
250
305
  if not info then
251
306
  info = track_component(server, component)
@@ -254,7 +309,6 @@ local function track_entity_component(server: Server, entity: Entity, component:
254
309
  local entity_storage = get_or_set_entity_storage(server, entity)
255
310
 
256
311
  if world:has(component, ECS_COMPONENT) then
257
- -- component
258
312
  if world:has(entity, component) then
259
313
  local value = world:get(entity, component)
260
314
 
@@ -269,7 +323,6 @@ local function track_entity_component(server: Server, entity: Entity, component:
269
323
 
270
324
  return COMPONENT_TYPES.component
271
325
  else
272
- -- tag
273
326
  if world:has(entity, component) then
274
327
  entity_storage.tags[component] = true
275
328
  end
@@ -287,20 +340,39 @@ local function track_entity_pair(server: Server, entity: Entity, relation: Entit
287
340
  end
288
341
 
289
342
  local entity_storage = get_or_set_entity_storage(server, entity)
290
- local targets = {}
291
- local index = 0
292
343
 
293
- while true do
294
- local target = world:target(entity, relation, index)
295
- if not target then
296
- break
344
+ if world:has(relation, ECS_COMPONENT) then
345
+ local targets = {} :: Map<Entity, any>
346
+
347
+ local index = 0
348
+ while true do
349
+ local target = world:target(entity, relation, index)
350
+ if not target then
351
+ break
352
+ end
353
+ index += 1
354
+ local value = world:get(entity, jecs.pair(relation, target))
355
+ targets[target] = if value == nil then NIL_COMPONENT_VALUE else value :: any
297
356
  end
298
- index += 1
299
- targets[target] = true
300
- end
301
- entity_storage.pairs[relation] = targets
357
+ entity_storage.pairs_values[relation] = targets
358
+ info[entity] = TRACK_TYPES.pair_value
359
+ return COMPONENT_TYPES.pair_value
360
+ else
361
+ local targets = {} :: Set<Entity>
302
362
 
303
- info[entity] = TRACK_TYPES.pair
363
+ local index = 0
364
+ while true do
365
+ local target = world:target(entity, relation, index)
366
+ if not target then
367
+ break
368
+ end
369
+ index += 1
370
+ targets[target] = true
371
+ end
372
+ entity_storage.pairs[relation] = targets
373
+ info[entity] = TRACK_TYPES.pair
374
+ return COMPONENT_TYPES.pair
375
+ end
304
376
  end
305
377
 
306
378
  local function untrack_entity_component(server: Server, entity: Entity, component: Entity<any>): number?
@@ -320,17 +392,20 @@ local function untrack_entity_component(server: Server, entity: Entity, componen
320
392
  return listen_type
321
393
  end
322
394
 
323
- local function untrack_entity_pair(server: Server, entity: Entity, relation: Entity)
395
+ local function untrack_entity_pair(server: Server, entity: Entity, relation: Entity): number?
324
396
  local info = server.track_info.components[relation]
325
397
  if not info then
326
- return
398
+ return nil
327
399
  end
400
+ local listen_type = info[entity]
328
401
  info[entity] = nil
329
402
 
330
403
  local storage = server.storage[entity]
331
404
  if storage then
332
405
  storage.pairs[relation] = nil
406
+ storage.pairs_values[relation] = nil
333
407
  end
408
+ return listen_type
334
409
  end
335
410
 
336
411
  local function encode_component(server: Server, component: Entity): number
@@ -406,33 +481,31 @@ local function write_component_value(server: Server, c: Cursor, component: Entit
406
481
  cursor.write_vlq(c, #variants)
407
482
  end
408
483
  end
484
+ end
409
485
 
486
+ local function write_component(server: Server, c: Cursor, component: Entity, value: any, variants: { any })
487
+ write_component_value(server, c, component, value, variants)
410
488
  write_component_id(server, c, component)
411
489
  end
412
490
 
413
- local function write_entity_id(server: Server, c: Cursor, entity: Entity, variants: { any }, multiply: number?)
491
+ local function write_entity_id(server: Server, c: Cursor, entity: Entity, variants: { any })
414
492
  local custom = server.custom_ids[entity]
415
493
  local global_id = server.global_ids[entity]
416
494
 
417
495
  if global_id then
418
- if multiply then
419
- cursor.writei8(c, ENTITY_ID_TYPES.global * multiply)
420
- cursor.writeu8(c, global_id + GLOBAL_ID_OFFSET)
421
- else
422
- cursor.writei8(c, global_id + GLOBAL_ID_OFFSET)
423
- end
496
+ cursor.writeu8(c, global_id + GLOBAL_ID_OFFSET)
424
497
  elseif custom then
425
498
  local value = server.world:get(entity, custom)
426
- write_component_value(server, c, custom, value, variants)
427
- cursor.writei8(c, ENTITY_ID_TYPES.custom * (multiply or 1))
499
+ write_component(server, c, custom, value, variants)
500
+ cursor.writeu8(c, ENTITY_ID_TYPES.custom)
428
501
  else
429
502
  local shared_id = server.shared.ids[entity]
430
503
  if shared_id then
431
504
  cursor.writeu8(c, shared_id)
432
- cursor.writei8(c, ENTITY_ID_TYPES.shared * (multiply or 1))
505
+ cursor.writeu8(c, ENTITY_ID_TYPES.shared)
433
506
  else
434
507
  cursor.writeu40(c, entity :: any)
435
- cursor.writei8(c, ENTITY_ID_TYPES.entity * (multiply or 1), entity)
508
+ cursor.writeu8(c, ENTITY_ID_TYPES.entity, entity)
436
509
  end
437
510
  end
438
511
  end
@@ -455,6 +528,25 @@ local function write_entity_relations(
455
528
  write_component_id(server, c, relation)
456
529
  end
457
530
 
531
+ local function write_entity_relations_values(
532
+ server: Server,
533
+ storage: EntityStorage,
534
+ c: Cursor,
535
+ relation: Entity,
536
+ variants: { any }
537
+ )
538
+ local targets = storage.pairs_values[relation]
539
+ local total_targets = 0
540
+
541
+ for target, value in targets do
542
+ write_entity_id(server, c, target, variants)
543
+ write_component_value(server, c, relation, value, variants)
544
+ total_targets += 1
545
+ end
546
+ cursor.write_vlq(c, total_targets)
547
+ write_component_id(server, c, relation)
548
+ end
549
+
458
550
  local function write_entity(
459
551
  server: Server,
460
552
  c: Cursor,
@@ -464,6 +556,13 @@ local function write_entity(
464
556
  )
465
557
  local storage = server.storage[entity]
466
558
 
559
+ local all_pairs_values = 0
560
+ for relation in active.components[COMPONENT_TYPES.pair_value] do
561
+ write_entity_relations_values(server, storage, c, relation, variants)
562
+ all_pairs_values += 1
563
+ end
564
+ cursor.write_vlq(c, all_pairs_values)
565
+
467
566
  local all_pairs = 0
468
567
  for relation in active.components[COMPONENT_TYPES.pair] do
469
568
  write_entity_relations(server, storage, c, relation, variants)
@@ -478,7 +577,7 @@ local function write_entity(
478
577
  continue
479
578
  end
480
579
 
481
- write_component_value(server, c, component, value, variants)
580
+ write_component(server, c, component, value, variants)
482
581
  components += 1
483
582
  end
484
583
  cursor.write_vlq(c, components)
@@ -495,6 +594,13 @@ local function write_entity(
495
594
  write_entity_id(server, c, entity, variants)
496
595
  end
497
596
 
597
+ local function resolve_dirty(server: Server)
598
+ if server.is_dirty then
599
+ server.shared = utils.create_shared_lookup(server.world, server.components)
600
+ server.is_dirty = false :: true -- wtf
601
+ end
602
+ end
603
+
498
604
  type Packet = {
499
605
  buffer: buffer,
500
606
  variants: { { any } },
@@ -610,11 +716,13 @@ local function create_unreliable_packet_iterator(packets: { [Player]: MemberPack
610
716
  end) :: PacketIterator
611
717
  end
612
718
 
613
- local function get_full(server: Server, member: Player): (buffer, { { any } })
614
- local index = server.masking.member_indexes[member]
719
+ local function get_full(server: Server, client: Player): (buffer, { { any } })
720
+ resolve_dirty(server)
721
+ local index = server.masking.client_indexes[client]
615
722
  if index == nil then
616
- utils.logerror "attempted to replicate for a non registered member"
723
+ utils.logerror "attempted to replicate for a non registered client"
617
724
  end
725
+
618
726
  local packets: Array<Packet> = {}
619
727
  local total_size = 0
620
728
 
@@ -654,6 +762,7 @@ local function write_vlq_bitmask(c: Cursor, value: number, mask: number, bit: nu
654
762
  end
655
763
 
656
764
  local function collect_updates(server: Server)
765
+ resolve_dirty(server)
657
766
  local packets: { [Player]: MemberPackets } = {}
658
767
 
659
768
  for _, storage in server.masking.storages do
@@ -674,30 +783,28 @@ local function collect_updates(server: Server)
674
783
  local total_component_deleted = 0
675
784
  local component_deletions = storage.deletions.components
676
785
  for entity, deleted in component_deletions do
677
- local deleted_mask = 0
678
-
679
786
  local total_pairs = 0
787
+ for relation in deleted[COMPONENT_TYPES.pair_value] do
788
+ write_component_id(server, c, relation)
789
+ total_pairs += 1
790
+ end
680
791
  for relation in deleted[COMPONENT_TYPES.pair] do
681
792
  write_component_id(server, c, relation)
682
793
  total_pairs += 1
683
794
  end
684
- deleted_mask = write_vlq_bitmask(c, total_pairs, deleted_mask, 2)
795
+ cursor.write_vlq(c, total_pairs)
685
796
 
686
- local total_components = 0
797
+ local total_removed = 0
687
798
  for component in deleted[COMPONENT_TYPES.component] do
688
799
  write_component_id(server, c, component)
689
- total_components += 1
800
+ total_removed += 1
690
801
  end
691
- deleted_mask = write_vlq_bitmask(c, total_components, deleted_mask, 1)
692
-
693
- local total_tags = 0
694
802
  for tag in deleted[COMPONENT_TYPES.tag] do
695
803
  write_component_id(server, c, tag)
696
- total_tags += 1
804
+ total_removed += 1
697
805
  end
698
- deleted_mask = write_vlq_bitmask(c, total_tags, deleted_mask, 0)
806
+ cursor.write_vlq(c, total_removed)
699
807
 
700
- cursor.writeu8(c, deleted_mask)
701
808
  write_entity_id(server, c, entity, variants)
702
809
  total_component_deleted += 1
703
810
  end
@@ -709,22 +816,45 @@ local function collect_updates(server: Server)
709
816
  for entity, changes in storage_changes.changed do
710
817
  local changed_mask = 0
711
818
 
712
- local total_removed = 0
713
- for component in changes.removed do
714
- write_component_id(server, c, component)
715
- total_removed += 1
819
+ local total_pairs_values = 0
820
+ for relation, targets in changes.pairs_values.changed do
821
+ local total_targets = 0
822
+
823
+ for target, value in targets do
824
+ write_entity_id(server, c, target, variants)
825
+ write_component_value(server, c, relation, value, variants)
826
+ total_targets += 1
827
+ end
828
+ cursor.write_vlq(c, total_targets)
829
+ write_component_id(server, c, relation)
830
+ total_pairs_values += 1
716
831
  end
717
- changed_mask = write_vlq_bitmask(c, total_removed, changed_mask, 3)
832
+ changed_mask = write_vlq_bitmask(c, total_pairs_values, changed_mask, 5)
833
+
834
+ local total_pairs_values_removed = 0
835
+ for relation, targets in changes.pairs_values.removed do
836
+ local total_targets = 0
837
+
838
+ for target in targets do
839
+ write_entity_id(server, c, target, variants)
840
+ total_targets += 1
841
+ end
842
+ cursor.write_vlq(c, total_targets)
843
+ write_component_id(server, c, relation)
844
+ total_pairs_values_removed += 1
845
+ end
846
+ changed_mask = write_vlq_bitmask(c, total_pairs_values_removed, changed_mask, 4)
718
847
 
719
848
  local total_pairs = 0
720
849
  for relation, targets in changes.pairs do
721
850
  local total_targets = 0
722
851
 
723
852
  for target, added in targets do
853
+ write_entity_id(server, c, target, variants)
724
854
  if added then
725
- write_entity_id(server, c, target, variants, 1)
855
+ cursor.writei8(c, 1)
726
856
  else
727
- write_entity_id(server, c, target, variants, -1)
857
+ cursor.writei8(c, -1)
728
858
  end
729
859
  total_targets += 1
730
860
  end
@@ -732,11 +862,18 @@ local function collect_updates(server: Server)
732
862
  write_component_id(server, c, relation)
733
863
  total_pairs += 1
734
864
  end
735
- changed_mask = write_vlq_bitmask(c, total_pairs, changed_mask, 2)
865
+ changed_mask = write_vlq_bitmask(c, total_pairs, changed_mask, 3)
866
+
867
+ local total_removed = 0
868
+ for component in changes.removed do
869
+ write_component_id(server, c, component)
870
+ total_removed += 1
871
+ end
872
+ changed_mask = write_vlq_bitmask(c, total_removed, changed_mask, 2)
736
873
 
737
874
  local total_components = 0
738
875
  for component, value in changes.component do
739
- write_component_value(server, c, component, value, variants)
876
+ write_component(server, c, component, value, variants)
740
877
  total_components += 1
741
878
  end
742
879
  changed_mask = write_vlq_bitmask(c, total_components, changed_mask, 1)
@@ -760,6 +897,13 @@ local function collect_updates(server: Server)
760
897
  local entity_storage = server.storage[entity]
761
898
  local added_mask = 0
762
899
 
900
+ local total_pairs_values = 0
901
+ for relation in components[COMPONENT_TYPES.pair_value] do
902
+ write_entity_relations_values(server, entity_storage, c, relation, variants)
903
+ total_pairs_values += 1
904
+ end
905
+ added_mask = write_vlq_bitmask(c, total_pairs_values, added_mask, 3)
906
+
763
907
  local total_pairs = 0
764
908
  for relation in components[COMPONENT_TYPES.pair] do
765
909
  write_entity_relations(server, entity_storage, c, relation, variants)
@@ -773,7 +917,7 @@ local function collect_updates(server: Server)
773
917
  if value == nil then
774
918
  continue
775
919
  end
776
- write_component_value(server, c, component, value, variants)
920
+ write_component(server, c, component, value, variants)
777
921
  total_components += 1
778
922
  end
779
923
  added_mask = write_vlq_bitmask(c, total_components, added_mask, 1)
@@ -817,6 +961,7 @@ local function collect_updates(server: Server)
817
961
  end
818
962
 
819
963
  local function collect_unreliable(server: Server)
964
+ resolve_dirty(server)
820
965
  local world = server.world
821
966
  local packets: { [Player]: MemberPackets } = {}
822
967
 
@@ -871,7 +1016,7 @@ local function collect_unreliable(server: Server)
871
1016
  continue
872
1017
  end
873
1018
 
874
- write_component_value(server, c, component, value, variants)
1019
+ write_component(server, c, component, value, variants)
875
1020
  total_unreliable += 1
876
1021
  end
877
1022
 
@@ -952,12 +1097,13 @@ function init(server: Server, _world: World?)
952
1097
  masking:register_stop_entity(entity)
953
1098
  masking:stop_entity(entity)
954
1099
 
955
- server.additions[entity] = nil
956
- server.track_info.entities[entity] = nil
957
1100
  if server.pending_cleanups[entity] then
958
1101
  server.pending_cleanups[entity] = nil
959
1102
  cleanup_entity(server, entity)
960
1103
  end
1104
+
1105
+ server.additions[entity] = nil
1106
+ server.track_info.entities[entity] = nil
961
1107
  end))
962
1108
 
963
1109
  hook(hooks.added(world, components.reliable, function(entity, id, filter)
@@ -1010,13 +1156,14 @@ function init(server: Server, _world: World?)
1010
1156
  utils.logerror "pair should be used with a relationship"
1011
1157
  end
1012
1158
  local relation = PAIR_SECOND(world, id)
1013
- track_entity_pair(server, entity, relation)
1014
- masking:unregister_stop_component(entity, relation, COMPONENT_TYPES.pair)
1015
- masking:start_component(entity, relation, COMPONENT_TYPES.pair, filter)
1159
+
1160
+ local component_type = track_entity_pair(server, entity, relation)
1161
+ masking:unregister_stop_component(entity, relation, component_type)
1162
+ masking:start_component(entity, relation, component_type, filter)
1016
1163
  if server.additions[entity] then
1017
- masking:allocate_entity_addition(entity, relation, COMPONENT_TYPES.pair)
1164
+ masking:allocate_entity_addition(entity, relation, component_type)
1018
1165
  elseif server.track_info.entities[entity] then
1019
- masking:register_component_addition(entity, relation, COMPONENT_TYPES.pair)
1166
+ masking:register_component_addition(entity, relation, component_type)
1020
1167
  end
1021
1168
  end))
1022
1169
  hook(hooks.changed(world, components.pair, function(entity, id, filter)
@@ -1024,7 +1171,12 @@ function init(server: Server, _world: World?)
1024
1171
  utils.logerror "reliable should be used with a pair relationship"
1025
1172
  end
1026
1173
  local relation = PAIR_SECOND(world, id)
1027
- masking:set_component(entity, relation, COMPONENT_TYPES.pair, filter)
1174
+
1175
+ if world:has(relation, ECS_COMPONENT) then
1176
+ masking:set_component(entity, relation, COMPONENT_TYPES.pair_value, filter)
1177
+ else
1178
+ masking:set_component(entity, relation, COMPONENT_TYPES.pair, filter)
1179
+ end
1028
1180
  end))
1029
1181
  hook(hooks.removed(world, components.pair, function(entity, id)
1030
1182
  if not IS_PAIR(id) then
@@ -1035,10 +1187,13 @@ function init(server: Server, _world: World?)
1035
1187
  end
1036
1188
 
1037
1189
  local relation = PAIR_SECOND(world, id)
1038
- untrack_entity_pair(server, entity, relation)
1039
- masking:unregister_component_addition(entity, relation, COMPONENT_TYPES.pair)
1040
- masking:register_stop_component(entity, relation, COMPONENT_TYPES.pair)
1041
- masking:stop_component(entity, relation, COMPONENT_TYPES.pair)
1190
+ local component_type = untrack_entity_pair(server, entity, relation)
1191
+ if not component_type then
1192
+ return
1193
+ end
1194
+ masking:unregister_component_addition(entity, relation, component_type)
1195
+ masking:register_stop_component(entity, relation, component_type)
1196
+ masking:stop_component(entity, relation, component_type)
1042
1197
  end))
1043
1198
 
1044
1199
  hook(hooks.added(world, components.unreliable, function(entity, id, filter)
@@ -1114,12 +1269,21 @@ function init(server: Server, _world: World?)
1114
1269
  end
1115
1270
  end))
1116
1271
 
1272
+ for _, component in server.requires_shared_lookup do
1273
+ hook(hooks.added(world, component, function()
1274
+ server.is_dirty = true
1275
+ end))
1276
+ hook(hooks.removed(world, component, function()
1277
+ server.is_dirty = true
1278
+ end))
1279
+ end
1280
+
1117
1281
  if game and game:GetService("RunService"):IsServer() then
1118
1282
  local added = game:GetService("Players").PlayerAdded:Connect(function(player)
1119
- server.masking:register_member(player)
1283
+ server.masking:register_client(player)
1120
1284
  end)
1121
1285
  local removed = game:GetService("Players").PlayerRemoving:Connect(function(player)
1122
- server.masking:unregister_member(player)
1286
+ server.masking:register_client(player)
1123
1287
  end)
1124
1288
 
1125
1289
  table.insert(server.connections, added)
@@ -1128,13 +1292,21 @@ function init(server: Server, _world: World?)
1128
1292
  end
1129
1293
 
1130
1294
  local function mark_player_ready(server: Server, player: Player)
1131
- server.masking:activate_member(player)
1295
+ server.masking:activate_client(player)
1132
1296
  end
1133
1297
 
1134
1298
  local function is_player_ready(server: Server, player: Player): boolean
1135
1299
  return server.masking:member_is_active(player)
1136
1300
  end
1137
1301
 
1302
+ local function add_player_alias(server: Server, client: Player, alias: any)
1303
+ server.masking.client_aliases[alias] = client
1304
+ end
1305
+
1306
+ local function remove_player_alias(server: Server, alias: any)
1307
+ server.masking.client_aliases[alias] = nil
1308
+ end
1309
+
1138
1310
  local function destroy(server: Server)
1139
1311
  if server.inited == nil then
1140
1312
  return warn "attempted to destroy a server twice"
@@ -1160,6 +1332,8 @@ server.encode_component = encode_component
1160
1332
  server.decode_component = decode_component
1161
1333
  server.mark_player_ready = mark_player_ready
1162
1334
  server.is_player_ready = is_player_ready
1335
+ server.add_player_alias = add_player_alias
1336
+ server.remove_player_alias = remove_player_alias
1163
1337
 
1164
1338
  local function create(world: World?, components: common.Components): Server
1165
1339
  local self = {} :: Server
@@ -1171,6 +1345,7 @@ local function create(world: World?, components: common.Components): Server
1171
1345
  self.additions = {}
1172
1346
  self.storage = {}
1173
1347
  self.hooked = {}
1348
+ self.is_dirty = false
1174
1349
  self.global_ids = {}
1175
1350
  self.pending_cleanups = {}
1176
1351
  self.track_info = {
@@ -1182,6 +1357,12 @@ local function create(world: World?, components: common.Components): Server
1182
1357
  self.masking = masking_controller.create()
1183
1358
  self.alive_tracked = {}
1184
1359
  self.custom_ids = {}
1360
+ self.requires_shared_lookup = {
1361
+ self.components.shared,
1362
+ self.components.serdes,
1363
+ self.components.bytespan,
1364
+ jecs.Name,
1365
+ }
1185
1366
 
1186
1367
  return setmetatable(self, server) :: any
1187
1368
  end