@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.
- package/LICENSE +21 -0
- package/out/replecs/client.luau +77 -40
- package/out/replecs/common.luau +2 -1
- package/out/replecs/index.d.ts +24 -15
- package/out/replecs/init.luau +88 -83
- package/out/replecs/masking/init.luau +258 -104
- package/out/replecs/masking/mask_generator.luau +8 -5
- package/out/replecs/server.luau +1065 -918
- package/out/replecs/utils.luau +66 -13
- package/package.json +1 -1
package/out/replecs/server.luau
CHANGED
|
@@ -1,918 +1,1065 @@
|
|
|
1
|
-
--!optimize 2
|
|
2
|
-
--!native
|
|
3
|
-
|
|
4
|
-
local jecs = require
|
|
5
|
-
local utils = require
|
|
6
|
-
local common = require
|
|
7
|
-
local masking_controller = require
|
|
8
|
-
|
|
9
|
-
type Cursor = utils.Cursor
|
|
10
|
-
|
|
11
|
-
type World = jecs.World
|
|
12
|
-
type Entity<T = any> = jecs.Entity<T>
|
|
13
|
-
|
|
14
|
-
type Set<T> = { [T]: boolean }
|
|
15
|
-
type Map<K, V> = { [K]: V }
|
|
16
|
-
type Array<T> = { T }
|
|
17
|
-
|
|
18
|
-
type
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
local
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
local
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
local
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
local
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
targets
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
if track_type
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
entity_storage
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
local
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
local
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
local
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
if
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
end
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
)
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
end
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
local
|
|
482
|
-
local
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
local
|
|
644
|
-
for
|
|
645
|
-
local
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
end
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
masking:
|
|
824
|
-
masking:
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
server.
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
local
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
end
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
server
|
|
917
|
-
|
|
918
|
-
|
|
1
|
+
--!optimize 2
|
|
2
|
+
--!native
|
|
3
|
+
|
|
4
|
+
local jecs = require "../jecs"
|
|
5
|
+
local utils = require "./utils"
|
|
6
|
+
local common = require "./common"
|
|
7
|
+
local masking_controller = require "./masking"
|
|
8
|
+
|
|
9
|
+
type Cursor = utils.Cursor
|
|
10
|
+
|
|
11
|
+
type World = jecs.World
|
|
12
|
+
type Entity<T = any> = jecs.Entity<T>
|
|
13
|
+
|
|
14
|
+
type Set<T> = { [T]: boolean }
|
|
15
|
+
type Map<K, V> = { [K]: V }
|
|
16
|
+
type Array<T> = { T }
|
|
17
|
+
|
|
18
|
+
type FunctionFilter = (player: Player) -> boolean
|
|
19
|
+
|
|
20
|
+
type TrackInfo = {
|
|
21
|
+
entities: Map<Entity, boolean>,
|
|
22
|
+
components: { [Entity]: { [Entity]: number } },
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type EntityStorage = {
|
|
26
|
+
tags: { [Entity]: boolean },
|
|
27
|
+
values: { [Entity]: any },
|
|
28
|
+
pairs: { [Entity]: Set<Entity> },
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
type Storage = { [Entity]: EntityStorage }
|
|
32
|
+
|
|
33
|
+
export type Server = {
|
|
34
|
+
world: World,
|
|
35
|
+
inited: boolean?,
|
|
36
|
+
|
|
37
|
+
shared: common.Shared,
|
|
38
|
+
|
|
39
|
+
components: common.Components,
|
|
40
|
+
hooks: common.WorldHooks,
|
|
41
|
+
alive_tracked: Set<Entity>,
|
|
42
|
+
|
|
43
|
+
track_info: TrackInfo,
|
|
44
|
+
additions: Set<Entity>,
|
|
45
|
+
custom_ids: Map<Entity, Entity<any>>,
|
|
46
|
+
global_ids: Map<Entity, number>,
|
|
47
|
+
storage: Storage,
|
|
48
|
+
hooked: Array<() -> ()>,
|
|
49
|
+
masking: masking_controller.MaskingController,
|
|
50
|
+
pending_cleanups: Set<Entity>,
|
|
51
|
+
connections: Array<RBXScriptConnection>,
|
|
52
|
+
function_filters: masking_controller.EntityComponentIndex<FunctionFilter>,
|
|
53
|
+
|
|
54
|
+
init: (self: Server, world: World?) -> (),
|
|
55
|
+
destroy: (self: Server) -> (),
|
|
56
|
+
|
|
57
|
+
get_full: (self: Server, player: Player) -> (buffer, { { any } }),
|
|
58
|
+
collect_updates: (self: Server) -> () -> (Player, buffer, { { any } }),
|
|
59
|
+
collect_unreliable: (self: Server) -> () -> (Player, buffer, { { any } }),
|
|
60
|
+
mark_player_ready: (self: Server, player: Player) -> (),
|
|
61
|
+
is_player_ready: (self: Server, player: Player) -> boolean,
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
local cursor = utils.cursor
|
|
65
|
+
|
|
66
|
+
local NIL_COMPONENT_VALUE = newproxy()
|
|
67
|
+
local GLOBAL_ID_OFFSET = 10
|
|
68
|
+
|
|
69
|
+
local COMPONENT_TYPES = masking_controller.COMPONENT_TYPES
|
|
70
|
+
local TRACK_TYPES = {
|
|
71
|
+
component = 1,
|
|
72
|
+
tag = 2,
|
|
73
|
+
pair = 3,
|
|
74
|
+
}
|
|
75
|
+
local MAX_PACKET_SIZE = 900
|
|
76
|
+
local ENTITY_ID_TYPES = {
|
|
77
|
+
entity = 1,
|
|
78
|
+
custom = 2,
|
|
79
|
+
shared = 3,
|
|
80
|
+
global = 4,
|
|
81
|
+
}
|
|
82
|
+
local ECS_COMPONENT = jecs.Component
|
|
83
|
+
|
|
84
|
+
local function IS_PAIR(id: Entity): boolean
|
|
85
|
+
return jecs.IS_PAIR(id)
|
|
86
|
+
end
|
|
87
|
+
local function PAIR_SECOND(world: World, id: Entity): Entity
|
|
88
|
+
return jecs.pair_second(world, id)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
local function track_entity_lifetime(server: Server, entity: Entity)
|
|
92
|
+
if server.alive_tracked[entity] then
|
|
93
|
+
return
|
|
94
|
+
end
|
|
95
|
+
server.alive_tracked[entity] = true
|
|
96
|
+
server.world:add(entity, server.components.__alive_tracking__)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
local function get_or_set_entity_storage(server: Server, entity: Entity)
|
|
100
|
+
local storage = server.storage[entity]
|
|
101
|
+
|
|
102
|
+
if not storage then
|
|
103
|
+
storage = {
|
|
104
|
+
tags = {},
|
|
105
|
+
values = {},
|
|
106
|
+
pairs = {},
|
|
107
|
+
}
|
|
108
|
+
server.storage[entity] = storage
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
return storage
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
local function allocate_component_change(server: Server, entity: Entity, component: Entity, value: any)
|
|
115
|
+
local storage = get_or_set_entity_storage(server, entity)
|
|
116
|
+
|
|
117
|
+
local non_nil = if value == nil then NIL_COMPONENT_VALUE else value
|
|
118
|
+
|
|
119
|
+
storage.values[component] = non_nil
|
|
120
|
+
if not server.additions[entity] and server.track_info.entities[entity] then
|
|
121
|
+
server.masking:allocate_component_change(entity, component, non_nil)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
local function allocate_tag_addition(server: Server, entity: Entity, tag: Entity)
|
|
125
|
+
local storage = get_or_set_entity_storage(server, entity)
|
|
126
|
+
storage.tags[tag] = true
|
|
127
|
+
|
|
128
|
+
if not server.additions[entity] and server.track_info.entities[entity] then
|
|
129
|
+
server.masking:allocate_tag_addition(entity, tag)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
local function allocate_pair_addition(server: Server, entity: Entity, relation: Entity, target: Entity)
|
|
133
|
+
local storage = get_or_set_entity_storage(server, entity)
|
|
134
|
+
local targets = storage.pairs[relation]
|
|
135
|
+
if targets == nil then
|
|
136
|
+
targets = {}
|
|
137
|
+
storage.pairs[relation] = targets
|
|
138
|
+
end
|
|
139
|
+
targets[target] = true
|
|
140
|
+
|
|
141
|
+
if not server.additions[entity] and server.track_info.entities[entity] then
|
|
142
|
+
server.masking:allocate_pair_addition(entity, relation, target)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
local function allocate_component_removal(server: Server, entity: Entity, component: Entity)
|
|
147
|
+
local storage = get_or_set_entity_storage(server, entity)
|
|
148
|
+
storage.values[component] = nil
|
|
149
|
+
|
|
150
|
+
if not server.additions[entity] and server.track_info.entities[entity] then
|
|
151
|
+
server.masking:allocate_component_removal(entity, component)
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
local function allocate_tag_removal(server: Server, entity: Entity, tag: Entity)
|
|
155
|
+
local storage = get_or_set_entity_storage(server, entity)
|
|
156
|
+
storage.tags[tag] = nil
|
|
157
|
+
|
|
158
|
+
if not server.additions[entity] and server.track_info.entities[entity] then
|
|
159
|
+
server.masking:allocate_tag_removal(entity, tag)
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
local function allocate_pair_removal(server: Server, entity: Entity, relation: Entity, target: Entity)
|
|
163
|
+
local storage = get_or_set_entity_storage(server, entity)
|
|
164
|
+
local targets = storage.pairs[relation]
|
|
165
|
+
if targets then
|
|
166
|
+
targets[target] = nil
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
if not server.additions[entity] and server.track_info.entities[entity] then
|
|
170
|
+
server.masking:allocate_pair_removal(entity, relation, target)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
local function cleanup_entity(server: Server, entity: Entity)
|
|
175
|
+
server.alive_tracked[entity] = nil
|
|
176
|
+
server.storage[entity] = nil
|
|
177
|
+
server.additions[entity] = nil
|
|
178
|
+
server.masking:cleanup_entity(entity)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
local function track_component(server: Server, component: Entity<any>)
|
|
182
|
+
local world = server.world
|
|
183
|
+
local hooks = server.hooks
|
|
184
|
+
|
|
185
|
+
local info = {}
|
|
186
|
+
server.track_info.components[component] = info
|
|
187
|
+
|
|
188
|
+
local function hook(unhook: () -> ())
|
|
189
|
+
table.insert(server.hooked, unhook)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
hook(hooks.added(world, component, function(entity, id, value)
|
|
193
|
+
local track_type = info[entity]
|
|
194
|
+
if not track_type then
|
|
195
|
+
return
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
if track_type == TRACK_TYPES.component then
|
|
199
|
+
allocate_component_change(server, entity, component, value)
|
|
200
|
+
elseif track_type == TRACK_TYPES.tag then
|
|
201
|
+
allocate_tag_addition(server, entity, component)
|
|
202
|
+
else
|
|
203
|
+
if not IS_PAIR(id) then
|
|
204
|
+
utils.logerror "a non-pair tag was added to a pair tracked component"
|
|
205
|
+
end
|
|
206
|
+
allocate_pair_addition(server, entity, component, PAIR_SECOND(world, id))
|
|
207
|
+
end
|
|
208
|
+
end))
|
|
209
|
+
hook(hooks.changed(world, component, function(entity, _id, value)
|
|
210
|
+
local track_type = info[entity]
|
|
211
|
+
if not track_type then
|
|
212
|
+
return
|
|
213
|
+
end
|
|
214
|
+
-- no check here because only components can trigger changed (I think?)
|
|
215
|
+
allocate_component_change(server, entity, component, value)
|
|
216
|
+
end))
|
|
217
|
+
hook(hooks.removed(world, component, function(entity, id)
|
|
218
|
+
local track_type = info[entity]
|
|
219
|
+
if not track_type then
|
|
220
|
+
return
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
if track_type == TRACK_TYPES.component then
|
|
224
|
+
allocate_component_removal(server, entity, component)
|
|
225
|
+
elseif track_type == TRACK_TYPES.tag then
|
|
226
|
+
allocate_tag_removal(server, entity, component)
|
|
227
|
+
else
|
|
228
|
+
if not IS_PAIR(id) then
|
|
229
|
+
utils.logerror "a non-pair tag was removed for a pair tracked component"
|
|
230
|
+
end
|
|
231
|
+
allocate_pair_removal(server, entity, component, PAIR_SECOND(world, id))
|
|
232
|
+
end
|
|
233
|
+
end))
|
|
234
|
+
|
|
235
|
+
return info
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
local function track_entity_component(server: Server, entity: Entity, component: Entity<any>)
|
|
239
|
+
local world = server.world
|
|
240
|
+
|
|
241
|
+
local info = server.track_info.components[component]
|
|
242
|
+
if not info then
|
|
243
|
+
info = track_component(server, component)
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
local entity_storage = get_or_set_entity_storage(server, entity)
|
|
247
|
+
|
|
248
|
+
if world:has(component, ECS_COMPONENT) then
|
|
249
|
+
-- component
|
|
250
|
+
if world:has(entity, component) then
|
|
251
|
+
local value = world:get(entity, component)
|
|
252
|
+
|
|
253
|
+
if value == nil then
|
|
254
|
+
entity_storage.values[component] = NIL_COMPONENT_VALUE
|
|
255
|
+
else
|
|
256
|
+
entity_storage.values[component] = value
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
info[entity] = TRACK_TYPES.component
|
|
261
|
+
|
|
262
|
+
return COMPONENT_TYPES.component
|
|
263
|
+
else
|
|
264
|
+
-- tag
|
|
265
|
+
if world:has(entity, component) then
|
|
266
|
+
entity_storage.tags[component] = true
|
|
267
|
+
end
|
|
268
|
+
info[entity] = TRACK_TYPES.tag
|
|
269
|
+
|
|
270
|
+
return COMPONENT_TYPES.tag
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
local function track_entity_pair(server: Server, entity: Entity, relation: Entity)
|
|
275
|
+
local world = server.world
|
|
276
|
+
local info = server.track_info.components[relation]
|
|
277
|
+
if not info then
|
|
278
|
+
info = track_component(server, relation)
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
local entity_storage = get_or_set_entity_storage(server, entity)
|
|
282
|
+
local targets = {}
|
|
283
|
+
local index = 0
|
|
284
|
+
|
|
285
|
+
while true do
|
|
286
|
+
local target = world:target(entity, relation, index)
|
|
287
|
+
if not target then
|
|
288
|
+
break
|
|
289
|
+
end
|
|
290
|
+
index += 1
|
|
291
|
+
targets[target] = true
|
|
292
|
+
end
|
|
293
|
+
entity_storage.pairs[relation] = targets
|
|
294
|
+
|
|
295
|
+
info[entity] = TRACK_TYPES.pair
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
local function untrack_entity_component(server: Server, entity: Entity, component: Entity<any>): number?
|
|
299
|
+
local info = server.track_info.components[component]
|
|
300
|
+
if not info then
|
|
301
|
+
return nil
|
|
302
|
+
end
|
|
303
|
+
local listen_type = info[entity]
|
|
304
|
+
info[entity] = nil
|
|
305
|
+
|
|
306
|
+
local storage = server.storage[entity]
|
|
307
|
+
if storage then
|
|
308
|
+
storage.values[component] = nil
|
|
309
|
+
storage.tags[component] = nil
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
return listen_type
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
local function untrack_entity_pair(server: Server, entity: Entity, relation: Entity)
|
|
316
|
+
local info = server.track_info.components[relation]
|
|
317
|
+
if not info then
|
|
318
|
+
return
|
|
319
|
+
end
|
|
320
|
+
info[entity] = nil
|
|
321
|
+
|
|
322
|
+
local storage = server.storage[entity]
|
|
323
|
+
if storage then
|
|
324
|
+
storage.pairs[relation] = nil
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
local function write_component_id(server: Server, c: Cursor, component: Entity)
|
|
329
|
+
local encoded = server.shared.ids[component]
|
|
330
|
+
if not encoded then
|
|
331
|
+
utils.logerror(`attempted to replicate a non-shared component `, utils.logcomponent(server.world, component))
|
|
332
|
+
return
|
|
333
|
+
end
|
|
334
|
+
cursor.writeu8(c, encoded)
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
local function write_component_value(server: Server, c: Cursor, component: Entity, value: any, variants: { any })
|
|
338
|
+
local serdes = server.shared.serdes[component]
|
|
339
|
+
if serdes then
|
|
340
|
+
local output = serdes.serialize(if value == NIL_COMPONENT_VALUE then nil else value)
|
|
341
|
+
|
|
342
|
+
local bytespan = server.shared.bytespan[component]
|
|
343
|
+
cursor.write_buffer(c, output)
|
|
344
|
+
if bytespan then
|
|
345
|
+
if bytespan ~= buffer.len(output) then
|
|
346
|
+
utils.logerror(
|
|
347
|
+
`bytespan: {bytespan} mismatch for buffer lenght: {buffer.len(output)} in component`,
|
|
348
|
+
utils.logcomponent(server.world, component)
|
|
349
|
+
)
|
|
350
|
+
end
|
|
351
|
+
else
|
|
352
|
+
local len = buffer.len(output)
|
|
353
|
+
cursor.write_vlq(c, len)
|
|
354
|
+
end
|
|
355
|
+
else
|
|
356
|
+
if value == NIL_COMPONENT_VALUE then
|
|
357
|
+
-- this is zero for vlq
|
|
358
|
+
cursor.writeu8(c, 128)
|
|
359
|
+
else
|
|
360
|
+
table.insert(variants, value :: any)
|
|
361
|
+
cursor.write_vlq(c, #variants)
|
|
362
|
+
end
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
write_component_id(server, c, component)
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
local function write_entity_id(server: Server, c: Cursor, entity: Entity, variants: { any }, multiply: number?)
|
|
369
|
+
local custom = server.custom_ids[entity]
|
|
370
|
+
local global_id = server.global_ids[entity]
|
|
371
|
+
|
|
372
|
+
if global_id then
|
|
373
|
+
if multiply then
|
|
374
|
+
cursor.writei8(c, ENTITY_ID_TYPES.global * multiply)
|
|
375
|
+
cursor.writeu8(c, global_id + GLOBAL_ID_OFFSET)
|
|
376
|
+
else
|
|
377
|
+
cursor.writei8(c, global_id + GLOBAL_ID_OFFSET)
|
|
378
|
+
end
|
|
379
|
+
elseif custom then
|
|
380
|
+
local value = server.world:get(entity, custom)
|
|
381
|
+
write_component_value(server, c, custom, value, variants)
|
|
382
|
+
cursor.writei8(c, ENTITY_ID_TYPES.custom * (multiply or 1))
|
|
383
|
+
else
|
|
384
|
+
local shared_id = server.shared.ids[entity]
|
|
385
|
+
if shared_id then
|
|
386
|
+
cursor.writeu8(c, shared_id)
|
|
387
|
+
cursor.writei8(c, ENTITY_ID_TYPES.shared * (multiply or 1))
|
|
388
|
+
else
|
|
389
|
+
cursor.writeu40(c, entity :: any)
|
|
390
|
+
cursor.writei8(c, ENTITY_ID_TYPES.entity * (multiply or 1), entity)
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
local function write_entity(
|
|
396
|
+
server: Server,
|
|
397
|
+
c: Cursor,
|
|
398
|
+
entity: Entity,
|
|
399
|
+
active: masking_controller.ActiveEntity,
|
|
400
|
+
variants: { any }
|
|
401
|
+
)
|
|
402
|
+
local storage = server.storage[entity]
|
|
403
|
+
|
|
404
|
+
local all_pairs = 0
|
|
405
|
+
for relation in active.components[COMPONENT_TYPES.pair] do
|
|
406
|
+
local targets = storage.pairs[relation]
|
|
407
|
+
local total_targets = 0
|
|
408
|
+
|
|
409
|
+
for target in targets do
|
|
410
|
+
write_entity_id(server, c, target, variants)
|
|
411
|
+
total_targets += 1
|
|
412
|
+
end
|
|
413
|
+
cursor.write_vlq(c, total_targets)
|
|
414
|
+
write_component_id(server, c, relation)
|
|
415
|
+
all_pairs += 1
|
|
416
|
+
end
|
|
417
|
+
cursor.write_vlq(c, all_pairs)
|
|
418
|
+
|
|
419
|
+
local components = 0
|
|
420
|
+
for component in active.components[COMPONENT_TYPES.component] do
|
|
421
|
+
local value = storage.values[component]
|
|
422
|
+
write_component_value(server, c, component, value, variants)
|
|
423
|
+
components += 1
|
|
424
|
+
end
|
|
425
|
+
cursor.write_vlq(c, components)
|
|
426
|
+
|
|
427
|
+
local tags = 0
|
|
428
|
+
for tag in active.components[COMPONENT_TYPES.tag] do
|
|
429
|
+
local has_tag = storage.tags[tag]
|
|
430
|
+
if has_tag then
|
|
431
|
+
write_component_id(server, c, tag)
|
|
432
|
+
tags += 1
|
|
433
|
+
end
|
|
434
|
+
end
|
|
435
|
+
cursor.write_vlq(c, tags)
|
|
436
|
+
write_entity_id(server, c, entity, variants)
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
type Packet = {
|
|
440
|
+
buffer: buffer,
|
|
441
|
+
variants: { { any } },
|
|
442
|
+
}
|
|
443
|
+
type MemberPackets = {
|
|
444
|
+
packets: Array<Packet>,
|
|
445
|
+
variants: { { any } },
|
|
446
|
+
total_size: number,
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
local function append_packet(
|
|
450
|
+
packets: { [Player]: MemberPackets },
|
|
451
|
+
members: { any },
|
|
452
|
+
output: buffer,
|
|
453
|
+
variants: { { any } }
|
|
454
|
+
)
|
|
455
|
+
local len = buffer.len(output)
|
|
456
|
+
for _, member in members do
|
|
457
|
+
local member_packets = packets[member]
|
|
458
|
+
|
|
459
|
+
if member_packets then
|
|
460
|
+
table.insert(member_packets.packets, {
|
|
461
|
+
buffer = output,
|
|
462
|
+
variants = variants,
|
|
463
|
+
})
|
|
464
|
+
member_packets.total_size += len
|
|
465
|
+
else
|
|
466
|
+
member_packets = {
|
|
467
|
+
packets = {
|
|
468
|
+
{
|
|
469
|
+
buffer = output,
|
|
470
|
+
variants = variants,
|
|
471
|
+
},
|
|
472
|
+
},
|
|
473
|
+
total_size = len,
|
|
474
|
+
}
|
|
475
|
+
packets[member] = member_packets :: MemberPackets
|
|
476
|
+
end
|
|
477
|
+
end
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
local function combine_packet_outputs(outputs: Array<Packet>, total_size: number): (buffer, { { any } })
|
|
481
|
+
local combined = buffer.create(total_size + utils.vlq_span(#outputs))
|
|
482
|
+
local offset = 0
|
|
483
|
+
local variants = table.create(#outputs) :: { { any } }
|
|
484
|
+
|
|
485
|
+
for _, output in outputs do
|
|
486
|
+
buffer.copy(combined, offset, output.buffer)
|
|
487
|
+
offset += buffer.len(output.buffer)
|
|
488
|
+
table.insert(variants, output.variants)
|
|
489
|
+
end
|
|
490
|
+
cursor.write_vlq({
|
|
491
|
+
offset = offset,
|
|
492
|
+
buffer = combined,
|
|
493
|
+
}, #outputs)
|
|
494
|
+
|
|
495
|
+
return combined, variants
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
type PacketIterator = () -> (Player, buffer, { { any } })
|
|
499
|
+
|
|
500
|
+
local function create_packet_iterator(packets: { [Player]: MemberPackets })
|
|
501
|
+
local iterated: Player? = nil
|
|
502
|
+
local function iterator()
|
|
503
|
+
local player, data = next(packets, iterated)
|
|
504
|
+
if not player then
|
|
505
|
+
return nil :: any
|
|
506
|
+
end
|
|
507
|
+
iterated = player
|
|
508
|
+
|
|
509
|
+
local combined, variants = combine_packet_outputs(data.packets, data.total_size)
|
|
510
|
+
return player, combined, variants
|
|
511
|
+
end
|
|
512
|
+
return iterator :: PacketIterator
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
local function create_unreliable_packet_iterator(packets: { [Player]: MemberPackets })
|
|
516
|
+
return coroutine.wrap(function()
|
|
517
|
+
for player, data in packets do
|
|
518
|
+
table.sort(data.packets, function(a, b)
|
|
519
|
+
return buffer.len(a.buffer) < buffer.len(b.buffer)
|
|
520
|
+
end)
|
|
521
|
+
local total_packets = #data.packets
|
|
522
|
+
|
|
523
|
+
local current_packet_index = 1
|
|
524
|
+
while current_packet_index <= total_packets do
|
|
525
|
+
local sending = {} :: { Packet }
|
|
526
|
+
local total_size = 0
|
|
527
|
+
|
|
528
|
+
while current_packet_index <= total_packets do
|
|
529
|
+
local packet = data.packets[current_packet_index]
|
|
530
|
+
local buffer_size = buffer.len(packet.buffer)
|
|
531
|
+
|
|
532
|
+
if total_size + buffer_size > MAX_PACKET_SIZE and #sending > 0 then
|
|
533
|
+
break
|
|
534
|
+
end
|
|
535
|
+
|
|
536
|
+
table.insert(sending, packet)
|
|
537
|
+
total_size += buffer_size
|
|
538
|
+
current_packet_index += 1
|
|
539
|
+
|
|
540
|
+
if total_size >= MAX_PACKET_SIZE then
|
|
541
|
+
break
|
|
542
|
+
end
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
if #sending > 0 then
|
|
546
|
+
coroutine.yield(player, combine_packet_outputs(sending, total_size))
|
|
547
|
+
end
|
|
548
|
+
end
|
|
549
|
+
end
|
|
550
|
+
end) :: PacketIterator
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
local function get_full(server: Server, member: Player): (buffer, { { any } })
|
|
554
|
+
local index = server.masking.member_indexes[member]
|
|
555
|
+
if index == nil then
|
|
556
|
+
utils.logerror "attempted to replicate for a non registered member"
|
|
557
|
+
end
|
|
558
|
+
local packets: Array<Packet> = {}
|
|
559
|
+
local total_size = 0
|
|
560
|
+
|
|
561
|
+
-- maybe edges to quickly find all relevant storages improves performance?
|
|
562
|
+
for _, storage in server.masking.storages do
|
|
563
|
+
if not storage.mask.bitmask:get(index) then
|
|
564
|
+
continue
|
|
565
|
+
end
|
|
566
|
+
local c = cursor.new()
|
|
567
|
+
local variants = {}
|
|
568
|
+
|
|
569
|
+
local total_entities = 0
|
|
570
|
+
for entity, active in storage.active do
|
|
571
|
+
write_entity(server, c, entity, active, variants)
|
|
572
|
+
total_entities += 1
|
|
573
|
+
end
|
|
574
|
+
cursor.write_vlq(c, total_entities)
|
|
575
|
+
|
|
576
|
+
local output = cursor.close(c)
|
|
577
|
+
table.insert(packets, {
|
|
578
|
+
buffer = output,
|
|
579
|
+
variants = variants,
|
|
580
|
+
})
|
|
581
|
+
total_size += buffer.len(output)
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
return combine_packet_outputs(packets, total_size)
|
|
585
|
+
end
|
|
586
|
+
|
|
587
|
+
local function collect_updates(server: Server)
|
|
588
|
+
local packets: { [Player]: MemberPackets } = {}
|
|
589
|
+
|
|
590
|
+
for _, storage in server.masking.storages do
|
|
591
|
+
local c = cursor.new()
|
|
592
|
+
local variants = {}
|
|
593
|
+
|
|
594
|
+
local total_deleted = 0
|
|
595
|
+
local entity_deletions = storage.deletions.entities
|
|
596
|
+
for entity in entity_deletions do
|
|
597
|
+
write_entity_id(server, c, entity, variants)
|
|
598
|
+
total_deleted += 1
|
|
599
|
+
end
|
|
600
|
+
table.clear(entity_deletions)
|
|
601
|
+
cursor.write_vlq(c, total_deleted)
|
|
602
|
+
|
|
603
|
+
local total_component_deleted = 0
|
|
604
|
+
local component_deletions = storage.deletions.components
|
|
605
|
+
for entity, deleted in component_deletions do
|
|
606
|
+
local total_pairs = 0
|
|
607
|
+
for relation in deleted[COMPONENT_TYPES.pair] do
|
|
608
|
+
write_component_id(server, c, relation)
|
|
609
|
+
total_pairs += 1
|
|
610
|
+
end
|
|
611
|
+
cursor.write_vlq(c, total_pairs)
|
|
612
|
+
|
|
613
|
+
local total_components = 0
|
|
614
|
+
for component in deleted[COMPONENT_TYPES.component] do
|
|
615
|
+
write_component_id(server, c, component)
|
|
616
|
+
total_components += 1
|
|
617
|
+
end
|
|
618
|
+
cursor.write_vlq(c, total_components)
|
|
619
|
+
|
|
620
|
+
local total_tags = 0
|
|
621
|
+
for tag in deleted[COMPONENT_TYPES.tag] do
|
|
622
|
+
write_component_id(server, c, tag)
|
|
623
|
+
total_tags += 1
|
|
624
|
+
end
|
|
625
|
+
cursor.write_vlq(c, total_tags)
|
|
626
|
+
|
|
627
|
+
write_entity_id(server, c, entity, variants)
|
|
628
|
+
total_component_deleted += 1
|
|
629
|
+
end
|
|
630
|
+
table.clear(component_deletions)
|
|
631
|
+
cursor.write_vlq(c, total_component_deleted)
|
|
632
|
+
|
|
633
|
+
local storage_changes = storage.changes
|
|
634
|
+
local changed = 0
|
|
635
|
+
for entity, changes in storage_changes.changed do
|
|
636
|
+
local total_removed = 0
|
|
637
|
+
for component in changes.removed do
|
|
638
|
+
write_component_id(server, c, component)
|
|
639
|
+
total_removed += 1
|
|
640
|
+
end
|
|
641
|
+
cursor.write_vlq(c, total_removed)
|
|
642
|
+
|
|
643
|
+
local total_pairs = 0
|
|
644
|
+
for relation, targets in changes.pairs do
|
|
645
|
+
local total_targets = 0
|
|
646
|
+
|
|
647
|
+
for target, added in targets do
|
|
648
|
+
if added then
|
|
649
|
+
write_entity_id(server, c, target, variants, 1)
|
|
650
|
+
else
|
|
651
|
+
write_entity_id(server, c, target, variants, -1)
|
|
652
|
+
end
|
|
653
|
+
total_targets += 1
|
|
654
|
+
end
|
|
655
|
+
cursor.write_vlq(c, total_targets)
|
|
656
|
+
write_component_id(server, c, relation)
|
|
657
|
+
total_pairs += 1
|
|
658
|
+
end
|
|
659
|
+
cursor.write_vlq(c, total_pairs)
|
|
660
|
+
|
|
661
|
+
local total_components = 0
|
|
662
|
+
for component, value in changes.component do
|
|
663
|
+
write_component_value(server, c, component, value, variants)
|
|
664
|
+
total_components += 1
|
|
665
|
+
end
|
|
666
|
+
cursor.write_vlq(c, total_components)
|
|
667
|
+
|
|
668
|
+
local total_tagged = 0
|
|
669
|
+
for tag in changes.tagged do
|
|
670
|
+
write_component_id(server, c, tag)
|
|
671
|
+
total_tagged += 1
|
|
672
|
+
end
|
|
673
|
+
cursor.write_vlq(c, total_tagged)
|
|
674
|
+
|
|
675
|
+
write_entity_id(server, c, entity, variants)
|
|
676
|
+
changed += 1
|
|
677
|
+
end
|
|
678
|
+
table.clear(storage_changes.changed)
|
|
679
|
+
cursor.write_vlq(c, changed)
|
|
680
|
+
|
|
681
|
+
local total_added = 0
|
|
682
|
+
for entity in storage_changes.added do
|
|
683
|
+
local active = storage.active[entity]
|
|
684
|
+
if not active then
|
|
685
|
+
continue
|
|
686
|
+
end
|
|
687
|
+
|
|
688
|
+
write_entity(server, c, entity, active, variants)
|
|
689
|
+
total_added += 1
|
|
690
|
+
end
|
|
691
|
+
table.clear(storage_changes.added)
|
|
692
|
+
cursor.write_vlq(c, total_added)
|
|
693
|
+
|
|
694
|
+
local output = cursor.close(c)
|
|
695
|
+
append_packet(packets, storage.mask.members, output, variants)
|
|
696
|
+
end
|
|
697
|
+
table.clear(server.additions)
|
|
698
|
+
|
|
699
|
+
return create_packet_iterator(packets)
|
|
700
|
+
end
|
|
701
|
+
|
|
702
|
+
local function collect_unreliable(server: Server)
|
|
703
|
+
local world = server.world
|
|
704
|
+
local packets: { [Player]: MemberPackets } = {}
|
|
705
|
+
|
|
706
|
+
for _, mask_storage in server.masking.storages do
|
|
707
|
+
local active = mask_storage.active
|
|
708
|
+
|
|
709
|
+
local c = cursor.new()
|
|
710
|
+
local variants = {} :: { { any } }
|
|
711
|
+
local total_entities = 0
|
|
712
|
+
|
|
713
|
+
local checkpoint_offset = 0
|
|
714
|
+
local checkpoint_variants_count = 0
|
|
715
|
+
local checkpoint_total_entities = 0
|
|
716
|
+
|
|
717
|
+
local function create_checkpoint()
|
|
718
|
+
checkpoint_offset = c.offset
|
|
719
|
+
checkpoint_variants_count = #variants
|
|
720
|
+
checkpoint_total_entities = total_entities
|
|
721
|
+
end
|
|
722
|
+
|
|
723
|
+
local function rollback_checkpoint()
|
|
724
|
+
local new_cursor = cursor.new()
|
|
725
|
+
cursor.write_buffer(new_cursor, c.buffer, checkpoint_offset, c.offset - checkpoint_offset)
|
|
726
|
+
c.offset = checkpoint_offset
|
|
727
|
+
c = new_cursor
|
|
728
|
+
|
|
729
|
+
local new_variants = {} :: { { any } }
|
|
730
|
+
for _ = #variants, checkpoint_variants_count + 1, -1 do
|
|
731
|
+
table.insert(new_variants, 1, table.remove(variants))
|
|
732
|
+
end
|
|
733
|
+
variants = new_variants
|
|
734
|
+
total_entities = total_entities - checkpoint_total_entities
|
|
735
|
+
end
|
|
736
|
+
|
|
737
|
+
local function commit_checkpoint(commit_c, commit_variants, commit_total_entities)
|
|
738
|
+
if commit_total_entities <= 0 then
|
|
739
|
+
return
|
|
740
|
+
end
|
|
741
|
+
|
|
742
|
+
cursor.write_vlq(commit_c, commit_total_entities)
|
|
743
|
+
local output = cursor.close(commit_c)
|
|
744
|
+
append_packet(packets, mask_storage.mask.members, output, commit_variants)
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
for entity, actives in active do
|
|
748
|
+
create_checkpoint()
|
|
749
|
+
|
|
750
|
+
local total_unreliable = 0
|
|
751
|
+
for component in actives.components[COMPONENT_TYPES.unreliable] do
|
|
752
|
+
local value = world:get(entity, component)
|
|
753
|
+
if value == nil then
|
|
754
|
+
continue
|
|
755
|
+
end
|
|
756
|
+
|
|
757
|
+
write_component_value(server, c, component, value, variants)
|
|
758
|
+
total_unreliable += 1
|
|
759
|
+
end
|
|
760
|
+
|
|
761
|
+
if total_unreliable <= 0 then
|
|
762
|
+
continue
|
|
763
|
+
end
|
|
764
|
+
total_entities += 1
|
|
765
|
+
cursor.write_vlq(c, total_unreliable)
|
|
766
|
+
write_entity_id(server, c, entity, variants)
|
|
767
|
+
|
|
768
|
+
if c.offset > MAX_PACKET_SIZE then
|
|
769
|
+
local commit_cursor = c
|
|
770
|
+
local commit_variants = variants
|
|
771
|
+
rollback_checkpoint()
|
|
772
|
+
commit_checkpoint(commit_cursor, commit_variants, checkpoint_total_entities)
|
|
773
|
+
end
|
|
774
|
+
end
|
|
775
|
+
commit_checkpoint(c, variants, total_entities)
|
|
776
|
+
end
|
|
777
|
+
|
|
778
|
+
return create_unreliable_packet_iterator(packets)
|
|
779
|
+
end
|
|
780
|
+
|
|
781
|
+
local function check_created(server: Server)
|
|
782
|
+
if server.inited == true then
|
|
783
|
+
warn "attempted to init a server twice"
|
|
784
|
+
return false
|
|
785
|
+
end
|
|
786
|
+
if server.inited == nil then
|
|
787
|
+
warn "attempted to create a server twice"
|
|
788
|
+
return false
|
|
789
|
+
end
|
|
790
|
+
return true
|
|
791
|
+
end
|
|
792
|
+
|
|
793
|
+
function init(server: Server, _world: World?)
|
|
794
|
+
if not check_created(server) then
|
|
795
|
+
return
|
|
796
|
+
end
|
|
797
|
+
server.inited = true :: any
|
|
798
|
+
|
|
799
|
+
local world = _world or server.world
|
|
800
|
+
server.world = world
|
|
801
|
+
|
|
802
|
+
if not world then
|
|
803
|
+
error "Providing a world is required to start replecs"
|
|
804
|
+
end
|
|
805
|
+
|
|
806
|
+
local hooks = {
|
|
807
|
+
added = (world :: any).added,
|
|
808
|
+
changed = (world :: any).changed,
|
|
809
|
+
removed = (world :: any).removed,
|
|
810
|
+
}
|
|
811
|
+
server.hooks = hooks
|
|
812
|
+
|
|
813
|
+
local components = server.components
|
|
814
|
+
local masking = server.masking
|
|
815
|
+
|
|
816
|
+
server.shared = utils.create_shared_lookup(world, components)
|
|
817
|
+
|
|
818
|
+
local function hook(unhook: () -> ())
|
|
819
|
+
table.insert(server.hooked, unhook)
|
|
820
|
+
end
|
|
821
|
+
|
|
822
|
+
hook(hooks.added(world, components.networked, function(entity, _id, filter)
|
|
823
|
+
masking:unregister_stop_entity(entity)
|
|
824
|
+
masking:start_entity(entity, filter)
|
|
825
|
+
masking:propagate_entity_addition(entity)
|
|
826
|
+
|
|
827
|
+
server.additions[entity] = true
|
|
828
|
+
server.track_info.entities[entity] = true
|
|
829
|
+
track_entity_lifetime(server, entity)
|
|
830
|
+
end))
|
|
831
|
+
hook(hooks.changed(world, components.networked, function(entity, _id, filter)
|
|
832
|
+
masking:set_entity(entity, filter)
|
|
833
|
+
end))
|
|
834
|
+
hook(hooks.removed(world, components.networked, function(entity)
|
|
835
|
+
masking:register_stop_entity(entity)
|
|
836
|
+
masking:stop_entity(entity)
|
|
837
|
+
|
|
838
|
+
server.additions[entity] = nil
|
|
839
|
+
server.track_info.entities[entity] = nil
|
|
840
|
+
if server.pending_cleanups[entity] then
|
|
841
|
+
server.pending_cleanups[entity] = nil
|
|
842
|
+
cleanup_entity(server, entity)
|
|
843
|
+
end
|
|
844
|
+
end))
|
|
845
|
+
|
|
846
|
+
hook(hooks.added(world, components.reliable, function(entity, id, filter)
|
|
847
|
+
if not IS_PAIR(id) then
|
|
848
|
+
utils.logerror "reliable should be used with a pair relationship"
|
|
849
|
+
end
|
|
850
|
+
local component = PAIR_SECOND(world, id)
|
|
851
|
+
|
|
852
|
+
local component_type = track_entity_component(server :: Server, entity, component)
|
|
853
|
+
masking:unregister_stop_component(entity, component, component_type)
|
|
854
|
+
masking:start_component(entity, component, component_type, filter)
|
|
855
|
+
if server.additions[entity] then
|
|
856
|
+
masking:allocate_entity_addition(entity, component, component_type)
|
|
857
|
+
end
|
|
858
|
+
end))
|
|
859
|
+
hook(hooks.changed(world, components.reliable, function(entity, id, filter)
|
|
860
|
+
if not IS_PAIR(id) then
|
|
861
|
+
utils.logerror "reliable should be used with a pair relationship"
|
|
862
|
+
end
|
|
863
|
+
local component = PAIR_SECOND(world, id)
|
|
864
|
+
|
|
865
|
+
if world:has(component, ECS_COMPONENT) then
|
|
866
|
+
masking:set_component(entity, component, COMPONENT_TYPES.component, filter)
|
|
867
|
+
else
|
|
868
|
+
masking:set_component(entity, component, COMPONENT_TYPES.tag, filter)
|
|
869
|
+
end
|
|
870
|
+
end))
|
|
871
|
+
hook(hooks.removed(world, components.reliable, function(entity, id)
|
|
872
|
+
if not IS_PAIR(id) then
|
|
873
|
+
utils.logerror "reliable should be used with a pair relationship"
|
|
874
|
+
end
|
|
875
|
+
if not server.track_info.entities[entity] then
|
|
876
|
+
return
|
|
877
|
+
end
|
|
878
|
+
|
|
879
|
+
local component = PAIR_SECOND(world, id)
|
|
880
|
+
local component_type = untrack_entity_component(server, entity, component)
|
|
881
|
+
if not component_type then
|
|
882
|
+
return
|
|
883
|
+
end
|
|
884
|
+
masking:register_stop_component(entity, component, component_type)
|
|
885
|
+
masking:stop_component(entity, component, component_type)
|
|
886
|
+
end))
|
|
887
|
+
|
|
888
|
+
hook(hooks.added(world, components.pair, function(entity, id, filter)
|
|
889
|
+
if not IS_PAIR(id) then
|
|
890
|
+
utils.logerror "pair should be used with a relationship"
|
|
891
|
+
end
|
|
892
|
+
local relation = PAIR_SECOND(world, id)
|
|
893
|
+
track_entity_pair(server, entity, relation)
|
|
894
|
+
masking:unregister_stop_component(entity, relation, COMPONENT_TYPES.pair)
|
|
895
|
+
masking:start_component(entity, relation, COMPONENT_TYPES.pair, filter)
|
|
896
|
+
if server.additions[entity] then
|
|
897
|
+
masking:allocate_entity_addition(entity, relation, COMPONENT_TYPES.pair)
|
|
898
|
+
end
|
|
899
|
+
end))
|
|
900
|
+
hook(hooks.changed(world, components.pair, function(entity, id, filter)
|
|
901
|
+
if not IS_PAIR(id) then
|
|
902
|
+
utils.logerror "reliable should be used with a pair relationship"
|
|
903
|
+
end
|
|
904
|
+
local relation = PAIR_SECOND(world, id)
|
|
905
|
+
masking:set_component(entity, relation, COMPONENT_TYPES.pair, filter)
|
|
906
|
+
end))
|
|
907
|
+
hook(hooks.removed(world, components.pair, function(entity, id)
|
|
908
|
+
if not IS_PAIR(id) then
|
|
909
|
+
utils.logerror "reliable should be used with a pair relationship"
|
|
910
|
+
end
|
|
911
|
+
if not server.track_info.entities[entity] then
|
|
912
|
+
return
|
|
913
|
+
end
|
|
914
|
+
|
|
915
|
+
local relation = PAIR_SECOND(world, id)
|
|
916
|
+
untrack_entity_pair(server, entity, relation)
|
|
917
|
+
masking:register_stop_component(entity, relation, COMPONENT_TYPES.pair)
|
|
918
|
+
masking:stop_component(entity, relation, COMPONENT_TYPES.pair)
|
|
919
|
+
end))
|
|
920
|
+
|
|
921
|
+
hook(hooks.added(world, components.unreliable, function(entity, id, filter)
|
|
922
|
+
if not IS_PAIR(id) then
|
|
923
|
+
utils.logerror "unreliable should be used with a pair relationship"
|
|
924
|
+
end
|
|
925
|
+
local component = PAIR_SECOND(world, id)
|
|
926
|
+
masking:unregister_stop_component(entity, component, COMPONENT_TYPES.unreliable)
|
|
927
|
+
masking:start_component(entity, component, COMPONENT_TYPES.unreliable, filter)
|
|
928
|
+
if server.additions[entity] then
|
|
929
|
+
masking:allocate_entity_addition(entity, component, COMPONENT_TYPES.unreliable)
|
|
930
|
+
end
|
|
931
|
+
end))
|
|
932
|
+
hook(hooks.changed(world, components.unreliable, function(entity, id, filter)
|
|
933
|
+
if not IS_PAIR(id) then
|
|
934
|
+
utils.logerror "unreliable should be used with a pair relationship"
|
|
935
|
+
end
|
|
936
|
+
local component = PAIR_SECOND(world, id)
|
|
937
|
+
masking:set_component(entity, component, COMPONENT_TYPES.unreliable, filter)
|
|
938
|
+
end))
|
|
939
|
+
hook(hooks.removed(world, components.unreliable, function(entity, id)
|
|
940
|
+
if not IS_PAIR(id) then
|
|
941
|
+
utils.logerror "unreliable should be used with a pair relationship"
|
|
942
|
+
end
|
|
943
|
+
if not server.track_info.entities[entity] then
|
|
944
|
+
return
|
|
945
|
+
end
|
|
946
|
+
|
|
947
|
+
local component = PAIR_SECOND(world, id)
|
|
948
|
+
untrack_entity_component(server, entity, component)
|
|
949
|
+
masking:register_stop_component(entity, component, COMPONENT_TYPES.unreliable)
|
|
950
|
+
masking:stop_component(entity, component, COMPONENT_TYPES.unreliable)
|
|
951
|
+
end))
|
|
952
|
+
|
|
953
|
+
hook(hooks.added(world, components.custom_id, function(entity, id)
|
|
954
|
+
if not IS_PAIR(id) then
|
|
955
|
+
utils.logerror "custom_id should be used with a relationship in the server"
|
|
956
|
+
end
|
|
957
|
+
local target = PAIR_SECOND(world, id)
|
|
958
|
+
if server.custom_ids[entity] then
|
|
959
|
+
utils.logwarn("attempted to register a custom_id twice for the same entity", debug.traceback())
|
|
960
|
+
return
|
|
961
|
+
end
|
|
962
|
+
|
|
963
|
+
server.custom_ids[entity] = target
|
|
964
|
+
end))
|
|
965
|
+
hook(hooks.removed(world, components.custom_id, function(entity)
|
|
966
|
+
server.custom_ids[entity] = nil
|
|
967
|
+
end))
|
|
968
|
+
hook(hooks.added(world, components.global_id, function(entity, id, value)
|
|
969
|
+
if value > 245 then
|
|
970
|
+
utils.logerror "global id size exceeded, max is 245"
|
|
971
|
+
end
|
|
972
|
+
server.global_ids[entity] = value
|
|
973
|
+
end))
|
|
974
|
+
hook(hooks.changed(world, components.global_id, function(entity, id, value)
|
|
975
|
+
if value > 245 then
|
|
976
|
+
utils.logerror "global id size exceeded, max is 245"
|
|
977
|
+
end
|
|
978
|
+
server.global_ids[entity] = value
|
|
979
|
+
end))
|
|
980
|
+
hook(hooks.removed(world, components.global_id, function(entity)
|
|
981
|
+
server.global_ids[entity] = nil
|
|
982
|
+
end))
|
|
983
|
+
|
|
984
|
+
hook(hooks.removed(world, components.__alive_tracking__, function(entity)
|
|
985
|
+
if server.track_info.entities[entity] then
|
|
986
|
+
-- This is in case alive tracking removal is called before networked removal
|
|
987
|
+
server.pending_cleanups[entity] = true
|
|
988
|
+
else
|
|
989
|
+
cleanup_entity(server, entity)
|
|
990
|
+
end
|
|
991
|
+
end))
|
|
992
|
+
|
|
993
|
+
if game and game:GetService("RunService"):IsServer() then
|
|
994
|
+
local added = game:GetService("Players").PlayerAdded:Connect(function(player)
|
|
995
|
+
server.masking:register_member(player)
|
|
996
|
+
end)
|
|
997
|
+
local removed = game:GetService("Players").PlayerRemoving:Connect(function(player)
|
|
998
|
+
server.masking:unregister_member(player)
|
|
999
|
+
end)
|
|
1000
|
+
|
|
1001
|
+
table.insert(server.connections, added)
|
|
1002
|
+
table.insert(server.connections, removed)
|
|
1003
|
+
end
|
|
1004
|
+
end
|
|
1005
|
+
|
|
1006
|
+
local function mark_player_ready(server: Server, player: Player)
|
|
1007
|
+
server.masking:activate_member(player)
|
|
1008
|
+
end
|
|
1009
|
+
|
|
1010
|
+
local function is_player_ready(server: Server, player: Player): boolean
|
|
1011
|
+
return server.masking:member_is_active(player)
|
|
1012
|
+
end
|
|
1013
|
+
|
|
1014
|
+
local function destroy(server: Server)
|
|
1015
|
+
if server.inited == nil then
|
|
1016
|
+
return warn "attempted to destroy a server twice"
|
|
1017
|
+
end
|
|
1018
|
+
server.inited = nil :: any
|
|
1019
|
+
|
|
1020
|
+
for _, unhook in server.hooked do
|
|
1021
|
+
unhook()
|
|
1022
|
+
end
|
|
1023
|
+
for _, connection in server.connections do
|
|
1024
|
+
connection:Disconnect()
|
|
1025
|
+
end
|
|
1026
|
+
end
|
|
1027
|
+
|
|
1028
|
+
local server = {}
|
|
1029
|
+
server.__index = server
|
|
1030
|
+
server.init = init
|
|
1031
|
+
server.destroy = destroy
|
|
1032
|
+
server.get_full = get_full
|
|
1033
|
+
server.collect_updates = collect_updates
|
|
1034
|
+
server.collect_unreliable = collect_unreliable
|
|
1035
|
+
server.mark_player_ready = mark_player_ready
|
|
1036
|
+
server.is_player_ready = is_player_ready
|
|
1037
|
+
|
|
1038
|
+
local function create(world: World?, components: common.Components): Server
|
|
1039
|
+
local self = {} :: Server
|
|
1040
|
+
|
|
1041
|
+
self.components = components
|
|
1042
|
+
|
|
1043
|
+
self.shared = {} :: common.Shared
|
|
1044
|
+
self.world = world :: any
|
|
1045
|
+
self.additions = {}
|
|
1046
|
+
self.storage = {}
|
|
1047
|
+
self.hooked = {}
|
|
1048
|
+
self.global_ids = {}
|
|
1049
|
+
self.pending_cleanups = {}
|
|
1050
|
+
self.track_info = {
|
|
1051
|
+
entities = {},
|
|
1052
|
+
components = {},
|
|
1053
|
+
}
|
|
1054
|
+
self.connections = {}
|
|
1055
|
+
self.inited = false
|
|
1056
|
+
self.masking = masking_controller.create()
|
|
1057
|
+
self.alive_tracked = {}
|
|
1058
|
+
self.custom_ids = {}
|
|
1059
|
+
|
|
1060
|
+
return setmetatable(self, server) :: any
|
|
1061
|
+
end
|
|
1062
|
+
|
|
1063
|
+
server.create = create
|
|
1064
|
+
|
|
1065
|
+
return server :: { create: typeof(create) }
|