@rbxts/replecs 0.2.3 → 0.3.0-test1

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,71 +1,85 @@
1
1
  --!optimize 2
2
2
  --!native
3
3
 
4
- local jecs = require "../jecs"
5
- local utils = require "./utils"
6
- local common = require "./common"
7
- local customid = require "./customid"
8
- local masking_controller = require "./masking"
4
+ local utils = require (script.Parent:WaitForChild('utils'))
5
+ local common = require (script.Parent:WaitForChild('common'))
6
+ local types = require (script.Parent:WaitForChild('types'))
7
+ local customid = require (script.Parent:WaitForChild('customid'))
8
+ local masking_controller = require (script.Parent:WaitForChild('masking'))
9
9
 
10
10
  local cursor = utils.cursor
11
11
 
12
12
  type Cursor = utils.Cursor
13
13
  type CustomId = customid.CustomId
14
+ type StorageGroup = masking_controller.StorageGroup
14
15
 
15
- type World = jecs.World
16
- type Entity<T = any> = jecs.Entity<T>
17
- type Component = Entity
16
+ type World = common.World
17
+ type Entity = common.Entity
18
+ type Component<T = any> = common.Component<T>
18
19
 
19
20
  type Set<T> = { [T]: boolean }
20
21
  type Map<K, V> = { [K]: V }
21
22
  type Array<T> = { T }
22
23
 
23
- type FunctionFilter = common.FunctionFilter
24
- type AnyFilter = common.AnyFilter
24
+ type FunctionFilter = types.FunctionFilter
25
+ type AnyFilter = types.AnyFilter
25
26
 
26
27
  type CustomIdSerialization = {
27
28
  required: Map<Entity, CustomId>,
28
29
  cursor_skip: number,
29
30
  }
30
31
 
32
+ type EntityTrackInfo = {
33
+ components: Map<Component, number>,
34
+ pairs: Map<Component, number>,
35
+ }
36
+
31
37
  type TrackInfo = {
32
38
  networked: Set<Entity>,
33
- entities: Map<Entity, Map<Component, number>>,
39
+ entities: Map<Entity, EntityTrackInfo>,
34
40
  components: Map<Component, Map<Entity, number>>,
41
+ pairs: Map<Component, Map<Entity, number>>,
35
42
  }
36
43
 
37
44
  type EntityStorage = {
38
45
  tags: { [Component]: boolean },
39
- values: { [Component]: any },
40
- pairs: { [Component]: Set<Entity> },
41
- pairs_values: { [Component]: Map<Entity, any> },
46
+ components: { [Component]: any },
47
+ pair_tags: { [Component]: boolean },
48
+ pair_components: { [Component]: any },
49
+
50
+ relations: { [Component]: Set<Entity> },
51
+ relation_values: { [Component]: Map<Entity, any> },
42
52
  }
43
53
 
44
54
  type Storage = { [Entity]: EntityStorage }
45
55
 
46
56
  export type ServerImp = {
47
- set_networked: (server: Server, entity: Entity, filter: AnyFilter?) -> (),
48
- stop_networked: (server: Server, entity: Entity) -> (),
49
-
50
- set_reliable: (server: Server, entity: Entity, component: Component, filter: AnyFilter?) -> (),
51
- set_unreliable: (server: Server, entity: Entity, component: Component, filter: AnyFilter?) -> (),
52
- set_pair: (server: Server, entity: Entity, relation: Component, filter: AnyFilter?) -> (),
53
- set_custom: (server: Server, entity: Entity, component: Component | CustomId) -> (),
54
-
55
- stop_reliable: (server: Server, entity: Entity, component: Component) -> (),
56
- stop_unreliable: (server: Server, entity: Entity, component: Component) -> (),
57
- stop_pair: (server: Server, entity: Entity, relation: Component) -> (),
58
- remove_custom: (server: Server, entity: Entity) -> (),
57
+ set_networked: (self: Server, entity: Entity, filter: AnyFilter?) -> (),
58
+ set_reliable: (self: Server, entity: Entity, component: Component, filter: AnyFilter?) -> (),
59
+ set_unreliable: (self: Server, entity: Entity, component: Component, filter: AnyFilter?) -> (),
60
+ set_pair: (self: Server, entity: Entity, id: Component, filter: AnyFilter?) -> (),
61
+ set_relation: (self: Server, entity: Entity, relation: Component, filter: AnyFilter?) -> (),
62
+
63
+ stop_networked: (self: Server, entity: Entity, keep: boolean?) -> (),
64
+ stop_reliable: (self: Server, entity: Entity, component: Component, keep: boolean?) -> (),
65
+ stop_unreliable: (self: Server, entity: Entity, component: Component, keep: boolean?) -> (),
66
+ stop_pair: (self: Server, entity: Entity, id: Component, keep: boolean?) -> (),
67
+ stop_relation: (self: Server, entity: Entity, relation: Component, keep: boolean?) -> (),
68
+
69
+ set_custom: (self: Server, entity: Entity, component: Component | CustomId) -> (),
70
+ remove_custom: (self: Server, entity: Entity) -> (),
71
+
72
+ set_serdes: <T>(self: Server, id: Component<T>, serdes: types.Serdes<T>) -> (),
73
+ remove_serdes: (self: Server, id: Component) -> (),
59
74
  }
60
75
 
61
76
  export type Server = ServerImp & {
62
77
  world: World,
63
78
  inited: boolean?,
64
79
 
65
- shared: common.Shared,
80
+ shared: types.Shared,
66
81
 
67
- components: common.Components,
68
- hooks: common.WorldHooks,
82
+ components: types.Components,
69
83
  alive_tracked: Set<Entity>,
70
84
 
71
85
  is_shared_dirty: boolean,
@@ -83,15 +97,18 @@ export type Server = ServerImp & {
83
97
  function_filters: masking_controller.EntityComponentIndex<FunctionFilter>,
84
98
 
85
99
  registered_custom_ids: Map<CustomId, boolean>,
100
+ component_serdes: Map<Component, types.Serdes>,
86
101
 
87
102
  init: (self: Server, world: World?) -> (),
88
103
  destroy: (self: Server) -> (),
89
104
 
90
105
  encode_component: (self: Server, component: Component) -> number,
91
- decode_component: (self: Server, component: number) -> Component,
106
+ decode_component: (self: Server, component: number) -> Component?,
107
+ get_shared_count: (self: Server) -> number,
92
108
  register_custom_id: (self: Server, custom_id: CustomId) -> (),
93
109
 
94
110
  get_full: (self: Server, player: Player) -> (buffer, { { any } }),
111
+ collect_entity: (self: Server, entity: Entity) -> () -> (Player, buffer, { { any } }),
95
112
  collect_updates: (self: Server) -> () -> (Player, buffer, { { any } }),
96
113
  collect_unreliable: (self: Server) -> () -> (Player, buffer, { { any } }),
97
114
 
@@ -101,8 +118,8 @@ export type Server = ServerImp & {
101
118
  add_player_alias: (self: Server, client: Player, alias: any) -> (),
102
119
  remove_player_alias: (self: Server, alias: any) -> (),
103
120
 
104
- generate_handshake: (self: Server) -> common.HandshakeInfo,
105
- verify_handshake: (self: Server, handshake: common.HandshakeInfo) -> (boolean, string?),
121
+ generate_handshake: (self: Server) -> types.HandshakeInfo,
122
+ verify_handshake: (self: Server, handshake: types.HandshakeInfo) -> (boolean, string?),
106
123
  }
107
124
 
108
125
  local server_replicator = {}
@@ -111,18 +128,22 @@ server_replicator.__index = server_replicator
111
128
  local NIL_COMPONENT_VALUE = newproxy()
112
129
  local GLOBAL_ID_OFFSET = 10
113
130
 
114
- local COMPONENT_TYPES = masking_controller.COMPONENT_TYPES
115
- local TRACK_TYPES = {
116
- component = 1,
117
- tag = 2,
118
- pair = 3,
119
- pair_value = 4,
131
+ local COMPONENT_TYPES = {
132
+ tag = 1,
133
+ component = 2,
134
+ pair_tag = 3,
135
+ pair_component = 4,
136
+ relation = 5,
137
+ relation_component = 6,
138
+ unreliable = 7,
139
+ unreliable_pair = 8,
120
140
  }
121
141
 
122
142
  local PACKET_TYPES = {
123
143
  full = 1,
124
- unreliable = 2,
125
- reliable = 3,
144
+ entity = 2,
145
+ updates = 3,
146
+ unreliable = 4,
126
147
  }
127
148
 
128
149
  local MAX_PACKET_SIZE = 900
@@ -133,22 +154,93 @@ local ENTITY_ID_TYPES = {
133
154
  shared = 4,
134
155
  }
135
156
 
136
- local ECS_COMPONENT = jecs.Component
137
- local WILDCARD = jecs.Wildcard
157
+ local RELATIONSHIPS = common.relationships
158
+ local WILDCARD = common.wildcard
159
+ local ECS_NAME = common.ecs_name
160
+
161
+ local IS_PAIR = common.is_pair
162
+ local PAIR = common.pair
163
+ local PAIR_FIRST = common.pair_first
164
+ local PAIR_SECOND = common.pair_second
165
+ local WORLD_ADD = common.world_add
166
+ local WORLD_HAS = common.world_has
167
+ local WORLD_GET = common.world_get
168
+ local WORLD_TARGET = common.world_target
169
+ local IS_COMPONENT = common.is_component
170
+
171
+ local LISTEN_RELATION = common.listen_relation
172
+
173
+ local HOOK_ADDED = common.hook_added
174
+ local HOOK_CHANGED = common.hook_changed
175
+ local HOOK_REMOVED = common.hook_removed
176
+
177
+ local function HOOK_PAIR_ADDED(world: World, pair_id: Entity, callback: (Entity, Component, any) -> ())
178
+ local relation = PAIR_FIRST(world, pair_id)
179
+
180
+ return HOOK_ADDED(world, relation, function(entity, id, value)
181
+ if id ~= pair_id then
182
+ return
183
+ end
184
+ callback(entity, id, value)
185
+ end)
186
+ end
187
+
188
+ local function HOOK_PAIR_CHANGED(world: World, pair_id: Entity, callback: (Entity, Component, any) -> ())
189
+ local relation = PAIR_FIRST(world, pair_id)
138
190
 
139
- local function IS_PAIR(id: Component): boolean
140
- return jecs.IS_PAIR(id)
191
+ return HOOK_CHANGED(world, relation, function(entity, id, value)
192
+ if id ~= pair_id then
193
+ return
194
+ end
195
+ callback(entity, id, value)
196
+ end)
141
197
  end
142
198
 
143
- local function PAIR(relation: Entity, target: Entity): Entity
144
- return jecs.pair(relation, target)
199
+ local function HOOK_PAIR_REMOVED(world: World, pair_id: Entity, callback: (Entity, Component) -> ())
200
+ local relation = PAIR_FIRST(world, pair_id)
201
+
202
+ return HOOK_REMOVED(world, relation, function(entity, id)
203
+ if id ~= pair_id then
204
+ return
205
+ end
206
+ callback(entity, id)
207
+ end)
145
208
  end
146
209
 
147
- local function PAIR_SECOND(world: World, id: Entity): Entity
148
- if not IS_PAIR(id) then
149
- error(`expected a pair, got: {utils.logcomponent(world, id)}`)
210
+ local function QUERY_TRACKING_TYPE(server: Server, track_type: Component)
211
+ local world = server.world
212
+ for entity in world:query(PAIR(track_type, WILDCARD)):iter() do
213
+ local index = 0
214
+ while true do
215
+ local target = WORLD_TARGET(world, entity, track_type, index)
216
+ if not target then
217
+ break
218
+ end
219
+ server.set_reliable(server, entity, target, WORLD_GET(world, entity, PAIR(track_type, target)))
220
+ index += 1
221
+ end
222
+ end
223
+ end
224
+
225
+ local function QUERY_CURRENT_NETWORKED(server: Server)
226
+ for entity, filter in server.world:query(server.components.networked):iter() do
227
+ server.set_networked(server, entity, filter)
228
+ end
229
+
230
+ if RELATIONSHIPS then
231
+ QUERY_TRACKING_TYPE(server, server.components.reliable)
232
+ QUERY_TRACKING_TYPE(server, server.components.unreliable)
233
+ QUERY_TRACKING_TYPE(server, server.components.relation)
234
+ end
235
+ end
236
+
237
+ local function QUERY_CURRENT_COMPONENTS(server: Server)
238
+ for component, serdes in server.world:query(server.components.serdes):iter() do
239
+ server.component_serdes[component] = serdes
240
+ end
241
+ for entity, id in server.world:query(server.components.global):iter() do
242
+ server.global_ids[entity] = id
150
243
  end
151
- return jecs.pair_second(world, id)
152
244
  end
153
245
 
154
246
  local function track_entity_lifetime(server: Server, entity: Entity)
@@ -156,18 +248,20 @@ local function track_entity_lifetime(server: Server, entity: Entity)
156
248
  return
157
249
  end
158
250
  server.alive_tracked[entity] = true
159
- server.world:add(entity, server.components.__alive_tracking__)
251
+ WORLD_ADD(server.world, entity, server.components.__alive_tracking__)
160
252
  end
161
253
 
162
254
  local function get_or_set_entity_storage(server: Server, entity: Entity): EntityStorage
163
- local storage = server.storage[entity]
255
+ local storage: EntityStorage = server.storage[entity]
164
256
 
165
257
  if not storage then
166
258
  storage = {
167
259
  tags = {},
168
- values = {},
169
- pairs = {},
170
- pairs_values = {},
260
+ components = {},
261
+ pair_tags = {},
262
+ pair_components = {},
263
+ relations = {},
264
+ relation_values = {},
171
265
  }
172
266
  server.storage[entity] = storage
173
267
  end
@@ -175,36 +269,54 @@ local function get_or_set_entity_storage(server: Server, entity: Entity): Entity
175
269
  return storage
176
270
  end
177
271
 
178
- local function add_entity_tracked(server: Server, entity: Entity, component: Component, track_type: number)
179
- local track = server.track_info.entities[entity]
180
- if track == nil then
181
- track = {
182
- [component] = track_type,
183
- }
184
- server.track_info.entities[entity] = track
185
- else
186
- track[component] = track_type
272
+ local function allocate_component_change(server: Server, entity: Entity, component: Component, value: any)
273
+ local storage = get_or_set_entity_storage(server, entity)
274
+
275
+ local non_nil = if value == nil then NIL_COMPONENT_VALUE else value
276
+ storage.components[component] = non_nil
277
+
278
+ if not server.additions[entity] and server.track_info.networked[entity] then
279
+ server.masking:allocate_component_change(entity, component, non_nil)
187
280
  end
188
281
  end
189
282
 
190
- local function remove_entity_tracked(server: Server, entity: Entity, component: Component)
191
- local track = server.track_info.entities[entity]
192
- if track then
193
- track[component] = nil
283
+ local function allocate_unreliable_addition(server: Server, entity: Entity, component: Component)
284
+ -- we dont modify the storage because changes are not tracked
285
+ if not server.additions[entity] and server.track_info.networked[entity] then
286
+ server.masking:allocate_unreliable_addition(entity, component)
194
287
  end
195
288
  end
196
289
 
197
- local function allocate_component_change(server: Server, entity: Entity, component: Component, value: any)
290
+ local function allocate_tag_addition(server: Server, entity: Entity, tag: Component)
291
+ local storage = get_or_set_entity_storage(server, entity)
292
+ storage.tags[tag] = true
293
+
294
+ if not server.additions[entity] and server.track_info.networked[entity] then
295
+ server.masking:allocate_tag_addition(entity, tag)
296
+ end
297
+ end
298
+
299
+ local function allocate_pair_tag_addition(server: Server, entity: Entity, id: Component)
300
+ local storage = get_or_set_entity_storage(server, entity)
301
+ storage.pair_tags[id] = true
302
+
303
+ if not server.additions[entity] and server.track_info.networked[entity] then
304
+ server.masking:allocate_pair_tag_addition(entity, id)
305
+ end
306
+ end
307
+
308
+ local function allocate_pair_component_change(server: Server, entity: Entity, id: Component, value: any)
198
309
  local storage = get_or_set_entity_storage(server, entity)
199
310
 
200
311
  local non_nil = if value == nil then NIL_COMPONENT_VALUE else value
312
+ storage.pair_components[id] = non_nil
201
313
 
202
- storage.values[component] = non_nil
203
314
  if not server.additions[entity] and server.track_info.networked[entity] then
204
- server.masking:allocate_component_change(entity, component, non_nil)
315
+ server.masking:allocate_pair_component_change(entity, id, non_nil)
205
316
  end
206
317
  end
207
- local function allocate_pair_value_change(
318
+
319
+ local function allocate_relation_component_change(
208
320
  server: Server,
209
321
  entity: Entity,
210
322
  relation: Component,
@@ -213,59 +325,46 @@ local function allocate_pair_value_change(
213
325
  )
214
326
  local storage = get_or_set_entity_storage(server, entity)
215
327
 
216
- local non_nil = if value == nil then NIL_COMPONENT_VALUE else value
217
-
218
- local values = storage.pairs_values[relation]
328
+ local values = storage.relation_values[relation]
219
329
  if values == nil then
220
330
  values = {}
221
- storage.pairs_values[relation] = values
331
+ storage.relation_values[relation] = values
222
332
  end
333
+
334
+ local non_nil = if value == nil then NIL_COMPONENT_VALUE else value
223
335
  values[target] = non_nil
224
336
 
225
337
  if not server.additions[entity] and server.track_info.networked[entity] then
226
- server.masking:allocate_pair_value_change(entity, relation, target, non_nil)
338
+ server.masking:allocate_relation_component_change(entity, relation, target, non_nil)
227
339
  end
228
340
  end
229
341
 
230
- local function allocate_tag_addition(server: Server, entity: Entity, tag: Component)
342
+ local function allocate_relation_tag_addition(server: Server, entity: Entity, relation: Component, target: Entity)
231
343
  local storage = get_or_set_entity_storage(server, entity)
232
- storage.tags[tag] = true
233
-
234
- if not server.additions[entity] and server.track_info.networked[entity] then
235
- server.masking:allocate_tag_addition(entity, tag)
236
- end
237
- end
238
- local function allocate_pair_addition(server: Server, entity: Entity, relation: Component, target: Entity)
239
- local storage = get_or_set_entity_storage(server, entity)
240
- local targets = storage.pairs[relation]
344
+ local targets = storage.relations[relation]
241
345
  if targets == nil then
242
346
  targets = {}
243
- storage.pairs[relation] = targets
347
+ storage.relations[relation] = targets
244
348
  end
245
349
  targets[target] = true
246
350
 
247
351
  if not server.additions[entity] and server.track_info.networked[entity] then
248
- server.masking:allocate_pair_addition(entity, relation, target)
352
+ server.masking:allocate_relation_tag_addition(entity, relation, target)
249
353
  end
250
354
  end
251
355
 
252
356
  local function allocate_component_removal(server: Server, entity: Entity, component: Component)
253
357
  local storage = get_or_set_entity_storage(server, entity)
254
- storage.values[component] = nil
358
+ storage.components[component] = nil
255
359
 
256
360
  if not server.additions[entity] and server.track_info.networked[entity] then
257
361
  server.masking:allocate_component_removal(entity, component)
258
362
  end
259
363
  end
260
- local function allocate_pair_value_removal(server: Server, entity: Entity, relation: Component, target: Entity)
261
- local storage = get_or_set_entity_storage(server, entity)
262
- local values = storage.pairs_values[relation]
263
- if values then
264
- values[target] = nil
265
- end
266
364
 
365
+ local function allocate_unreliable_removal(server: Server, entity: Entity, component: Component)
267
366
  if not server.additions[entity] and server.track_info.networked[entity] then
268
- server.masking:allocate_pair_value_removal(entity, relation, target)
367
+ server.masking:allocate_unreliable_removal(entity, component)
269
368
  end
270
369
  end
271
370
 
@@ -277,15 +376,46 @@ local function allocate_tag_removal(server: Server, entity: Entity, tag: Compone
277
376
  server.masking:allocate_tag_removal(entity, tag)
278
377
  end
279
378
  end
280
- local function allocate_pair_removal(server: Server, entity: Entity, relation: Component, target: Entity)
379
+
380
+ local function allocate_pair_tag_removal(server: Server, entity: Entity, id: Component)
381
+ local storage = get_or_set_entity_storage(server, entity)
382
+ storage.pair_tags[id] = nil
383
+
384
+ if not server.additions[entity] and server.track_info.networked[entity] then
385
+ server.masking:allocate_pair_tag_removal(entity, id)
386
+ end
387
+ end
388
+
389
+ local function allocate_pair_component_removal(server: Server, entity: Entity, id: Component)
390
+ local storage = get_or_set_entity_storage(server, entity)
391
+ storage.pair_components[id] = nil
392
+
393
+ if not server.additions[entity] and server.track_info.networked[entity] then
394
+ server.masking:allocate_pair_component_removal(entity, id)
395
+ end
396
+ end
397
+
398
+ local function allocate_relation_component_removal(server: Server, entity: Entity, relation: Component, target: Entity)
399
+ local storage = get_or_set_entity_storage(server, entity)
400
+ local values = storage.relation_values[relation]
401
+ if values then
402
+ values[target] = nil
403
+ end
404
+
405
+ if not server.additions[entity] and server.track_info.networked[entity] then
406
+ server.masking:allocate_relation_component_removal(entity, relation, target)
407
+ end
408
+ end
409
+
410
+ local function allocate_relation_tag_removal(server: Server, entity: Entity, relation: Component, target: Entity)
281
411
  local storage = get_or_set_entity_storage(server, entity)
282
- local targets = storage.pairs[relation]
412
+ local targets = storage.relations[relation]
283
413
  if targets then
284
414
  targets[target] = nil
285
415
  end
286
416
 
287
417
  if not server.additions[entity] and server.track_info.networked[entity] then
288
- server.masking:allocate_pair_removal(entity, relation, target)
418
+ server.masking:allocate_relation_tag_removal(entity, relation, target)
289
419
  end
290
420
  end
291
421
 
@@ -299,22 +429,77 @@ local function cleanup_entity(server: Server, entity: Entity)
299
429
 
300
430
  local track_info = server.track_info.entities[entity]
301
431
  if track_info then
302
- for component in track_info do
432
+ for component in track_info.components do
303
433
  local track_component = server.track_info.components[component]
304
434
  if track_component then
305
435
  track_component[entity] = nil
306
436
  end
307
437
  end
438
+ for id in track_info.pairs do
439
+ local track_pair = server.track_info.pairs[id]
440
+ if track_pair then
441
+ track_pair[entity] = nil
442
+ end
443
+ end
308
444
  server.track_info.entities[entity] = nil
309
445
  end
310
446
  end
311
447
 
312
- local function track_component(server: Server, component: Component)
448
+ local function hook_pair(server: Server, pair_id: Component)
449
+ local world = server.world
450
+
451
+ if server.track_info.pairs[pair_id] then
452
+ error(`attemped to track a pair twice: {common.log_component(server.world, PAIR_SECOND(world, pair_id))}`)
453
+ end
454
+
455
+ local info = {} :: Map<Entity, number>
456
+ server.track_info.pairs[pair_id] = info
457
+
458
+ local function hook(unhook: () -> ())
459
+ table.insert(server.hooked, unhook)
460
+ end
461
+
462
+ hook(HOOK_PAIR_ADDED(world, pair_id, function(entity, id, value)
463
+ local track_type = info[entity]
464
+ if not track_type then
465
+ return
466
+ end
467
+
468
+ if track_type == COMPONENT_TYPES.pair_component then
469
+ allocate_pair_component_change(server, entity, id, value)
470
+ else
471
+ allocate_pair_tag_addition(server, entity, id)
472
+ end
473
+ end))
474
+ hook(HOOK_PAIR_CHANGED(world, pair_id, function(entity, id, value)
475
+ local track_type = info[entity]
476
+ if not track_type then
477
+ return
478
+ end
479
+
480
+ allocate_pair_component_change(server, entity, id, value)
481
+ end))
482
+ hook(HOOK_PAIR_REMOVED(world, pair_id, function(entity, id)
483
+ local track_type = info[entity]
484
+ if not track_type then
485
+ return
486
+ end
487
+
488
+ if track_type == COMPONENT_TYPES.pair_component then
489
+ allocate_pair_component_removal(server, entity, id)
490
+ else
491
+ allocate_pair_tag_removal(server, entity, id)
492
+ end
493
+ end))
494
+
495
+ return info
496
+ end
497
+
498
+ local function hook_component(server: Server, component: Component)
313
499
  local world = server.world
314
- local hooks = server.hooks
315
500
 
316
501
  if server.track_info.components[component] then
317
- error(`attemped to track a component twice: {utils.logcomponent(server.world, component)}`)
502
+ error(`attemped to track a component twice: {common.log_component(server.world, component)}`)
318
503
  end
319
504
 
320
505
  local info = {} :: Map<Entity, number>
@@ -324,138 +509,228 @@ local function track_component(server: Server, component: Component)
324
509
  table.insert(server.hooked, unhook)
325
510
  end
326
511
 
327
- hook(hooks.added(world, component, function(entity, id, value)
512
+ hook(HOOK_ADDED(world, component, function(entity, id, value)
328
513
  local track_type = info[entity]
329
514
  if not track_type then
330
515
  return
331
516
  end
332
517
 
333
- if track_type == TRACK_TYPES.component then
518
+ if track_type == COMPONENT_TYPES.component then
334
519
  allocate_component_change(server, entity, component, value)
335
- elseif track_type == TRACK_TYPES.tag then
520
+ elseif track_type == COMPONENT_TYPES.tag then
336
521
  allocate_tag_addition(server, entity, component)
337
- elseif track_type == TRACK_TYPES.pair then
522
+ elseif track_type == COMPONENT_TYPES.relation then
338
523
  if not IS_PAIR(id) then
339
524
  return
340
525
  end
341
- allocate_pair_addition(server, entity, component, PAIR_SECOND(world, id))
342
- elseif track_type == TRACK_TYPES.pair_value then
526
+ allocate_relation_tag_addition(server, entity, component, PAIR_SECOND(world, id))
527
+ elseif track_type == COMPONENT_TYPES.relation_component then
343
528
  if not IS_PAIR(id) then
344
529
  return
345
530
  end
346
- allocate_pair_value_change(server, entity, component, PAIR_SECOND(world, id), value)
531
+ allocate_relation_component_change(server, entity, component, PAIR_SECOND(world, id), value)
532
+ elseif track_type == COMPONENT_TYPES.unreliable then
533
+ allocate_unreliable_addition(server, entity, component)
347
534
  end
348
535
  end))
349
- hook(hooks.changed(world, component, function(entity, id, value)
536
+ hook(HOOK_CHANGED(world, component, function(entity, id, value)
350
537
  local track_type = info[entity]
351
538
  if not track_type then
352
539
  return
353
540
  end
354
- if track_type == TRACK_TYPES.component then
541
+ if track_type == COMPONENT_TYPES.component then
355
542
  allocate_component_change(server, entity, component, value)
356
- elseif track_type == TRACK_TYPES.pair_value then
543
+ elseif track_type == COMPONENT_TYPES.relation_component then
357
544
  if not IS_PAIR(id) then
358
545
  return
359
546
  end
360
- allocate_pair_value_change(server, entity, component, PAIR_SECOND(world, id), value)
547
+ allocate_relation_component_change(server, entity, component, PAIR_SECOND(world, id), value)
361
548
  end
362
549
  end))
363
- hook(hooks.removed(world, component, function(entity, id)
550
+ hook(HOOK_REMOVED(world, component, function(entity, id)
364
551
  local track_type = info[entity]
365
552
  if not track_type then
366
553
  return
367
554
  end
368
555
 
369
- if track_type == TRACK_TYPES.component then
556
+ if track_type == COMPONENT_TYPES.component then
370
557
  allocate_component_removal(server, entity, component)
371
- elseif track_type == TRACK_TYPES.tag then
558
+ elseif track_type == COMPONENT_TYPES.tag then
372
559
  allocate_tag_removal(server, entity, component)
373
- elseif track_type == TRACK_TYPES.pair then
560
+ elseif track_type == COMPONENT_TYPES.relation then
374
561
  if not IS_PAIR(id) then
375
562
  return
376
563
  end
377
- allocate_pair_removal(server, entity, component, PAIR_SECOND(world, id))
378
- elseif track_type == TRACK_TYPES.pair_value then
564
+ allocate_relation_tag_removal(server, entity, component, PAIR_SECOND(world, id))
565
+ elseif track_type == COMPONENT_TYPES.relation_component then
379
566
  if not IS_PAIR(id) then
380
567
  return
381
568
  end
382
- allocate_pair_value_removal(server, entity, component, PAIR_SECOND(world, id))
569
+ allocate_relation_component_removal(server, entity, component, PAIR_SECOND(world, id))
570
+ elseif track_type == COMPONENT_TYPES.unreliable then
571
+ allocate_unreliable_removal(server, entity, component)
383
572
  end
384
573
  end))
385
574
 
386
575
  return info
387
576
  end
388
577
 
389
- local function track_entity_component(server: Server, entity: Entity, component: Entity<any>)
578
+ local function add_entity_component_tracked(server: Server, entity: Entity, component: Component, track_type: number)
579
+ local track: EntityTrackInfo = server.track_info.entities[entity]
580
+ if track == nil then
581
+ track = {
582
+ components = { [component] = track_type },
583
+ pairs = {},
584
+ }
585
+ server.track_info.entities[entity] = track
586
+ else
587
+ track.components[component] = track_type
588
+ end
589
+ end
590
+
591
+ local function add_entity_pair_tracked(server: Server, entity: Entity, id: Component, track_type: number)
592
+ local track: EntityTrackInfo = server.track_info.entities[entity]
593
+ if track == nil then
594
+ track = {
595
+ components = {},
596
+ pairs = { [id] = track_type },
597
+ }
598
+ server.track_info.entities[entity] = track
599
+ else
600
+ track.pairs[id] = track_type
601
+ end
602
+ end
603
+
604
+ local function remove_entity_component_tracked(server: Server, entity: Entity, component: Component)
605
+ local track = server.track_info.entities[entity]
606
+ if track then
607
+ track.components[component] = nil
608
+ end
609
+ end
610
+
611
+ local function remove_entity_pair_tracked(server: Server, entity: Entity, id: Component)
612
+ local track = server.track_info.entities[entity]
613
+ if track then
614
+ track.pairs[id] = nil
615
+ end
616
+ end
617
+
618
+ local function track_entity_unreliable(server: Server, entity: Entity, component: Component)
619
+ local info = server.track_info.components[component]
620
+ if not info then
621
+ info = hook_component(server, component)
622
+ end
623
+
624
+ info[entity] = COMPONENT_TYPES.unreliable
625
+ add_entity_component_tracked(server, entity, component, COMPONENT_TYPES.unreliable)
626
+ end
627
+
628
+ local function track_entity_component(server: Server, entity: Entity, component: Component)
390
629
  local world = server.world
391
630
  local info = server.track_info.components[component]
392
631
  if not info then
393
- info = track_component(server, component)
632
+ info = hook_component(server, component)
394
633
  end
395
634
 
396
635
  local entity_storage = get_or_set_entity_storage(server, entity)
397
636
 
398
- if world:has(component, ECS_COMPONENT) then
399
- if world:has(entity, component) then
400
- local value = world:get(entity, component)
637
+ if IS_COMPONENT(world, component) then
638
+ if WORLD_HAS(world, entity, component) then
639
+ local value = WORLD_GET(world, entity, component)
401
640
 
402
641
  if value == nil then
403
- entity_storage.values[component] = NIL_COMPONENT_VALUE
642
+ entity_storage.components[component] = NIL_COMPONENT_VALUE
404
643
  else
405
- entity_storage.values[component] = value
644
+ entity_storage.components[component] = value
406
645
  end
407
646
  end
408
647
 
409
- info[entity] = TRACK_TYPES.component
410
- add_entity_tracked(server, entity, component, TRACK_TYPES.component)
648
+ info[entity] = COMPONENT_TYPES.component
649
+ add_entity_component_tracked(server, entity, component, COMPONENT_TYPES.component)
411
650
 
412
651
  return COMPONENT_TYPES.component
413
652
  else
414
- if world:has(entity, component) then
653
+ if WORLD_HAS(world, entity, component) then
415
654
  entity_storage.tags[component] = true
416
655
  end
417
656
 
418
- info[entity] = TRACK_TYPES.tag
419
- add_entity_tracked(server, entity, component, TRACK_TYPES.tag)
657
+ info[entity] = COMPONENT_TYPES.tag
658
+ add_entity_component_tracked(server, entity, component, COMPONENT_TYPES.tag)
420
659
 
421
660
  return COMPONENT_TYPES.tag
422
661
  end
423
662
  end
424
663
 
425
- local function track_entity_pair(server: Server, entity: Entity, relation: Entity)
664
+ local function track_entity_pair(server: Server, entity: Entity, id: Component)
665
+ local world = server.world
666
+ local info = server.track_info.pairs[id]
667
+ if not info then
668
+ info = hook_pair(server, id)
669
+ end
670
+
671
+ local entity_storage = get_or_set_entity_storage(server, entity)
672
+
673
+ if IS_COMPONENT(world, id) then
674
+ if WORLD_HAS(world, entity, id) then
675
+ local value = WORLD_GET(world, entity, id)
676
+
677
+ if value == nil then
678
+ entity_storage.pair_components[id] = NIL_COMPONENT_VALUE
679
+ else
680
+ entity_storage.pair_components[id] = value
681
+ end
682
+ end
683
+
684
+ info[entity] = COMPONENT_TYPES.pair_component
685
+ add_entity_pair_tracked(server, entity, id, COMPONENT_TYPES.pair_component)
686
+
687
+ return COMPONENT_TYPES.pair_component
688
+ else
689
+ if WORLD_HAS(world, entity, id) then
690
+ entity_storage.pair_tags[id] = true
691
+ end
692
+
693
+ info[entity] = COMPONENT_TYPES.pair_tag
694
+ add_entity_pair_tracked(server, entity, id, COMPONENT_TYPES.pair_tag)
695
+
696
+ return COMPONENT_TYPES.pair_tag
697
+ end
698
+ end
699
+
700
+ local function track_entity_relation(server: Server, entity: Entity, relation: Component)
426
701
  local world = server.world
427
702
  local info = server.track_info.components[relation]
428
703
  if not info then
429
- info = track_component(server, relation)
704
+ info = hook_component(server, relation)
430
705
  end
431
706
 
432
707
  local entity_storage = get_or_set_entity_storage(server, entity)
433
708
 
434
- if world:has(relation, ECS_COMPONENT) then
709
+ if IS_COMPONENT(world, relation) then
435
710
  local targets = {} :: Map<Entity, any>
436
711
 
437
712
  local index = 0
438
713
  while true do
439
- local target = world:target(entity, relation, index)
714
+ local target = WORLD_TARGET(world, entity, relation, index)
440
715
  if not target then
441
716
  break
442
717
  end
443
718
  index += 1
444
- local value = world:get(entity, jecs.pair(relation, target))
719
+ local value = WORLD_GET(world, entity, PAIR(relation, target))
445
720
  targets[target] = if value == nil then NIL_COMPONENT_VALUE else value :: any
446
721
  end
447
722
 
448
- entity_storage.pairs_values[relation] = targets
449
- info[entity] = TRACK_TYPES.pair_value
450
- add_entity_tracked(server, entity, relation, TRACK_TYPES.pair_value)
723
+ entity_storage.relation_values[relation] = targets
724
+ info[entity] = COMPONENT_TYPES.relation_component
725
+ add_entity_component_tracked(server, entity, relation, COMPONENT_TYPES.relation_component)
451
726
 
452
- return COMPONENT_TYPES.pair_value
727
+ return COMPONENT_TYPES.relation_component
453
728
  else
454
729
  local targets = {} :: Set<Entity>
455
730
 
456
731
  local index = 0
457
732
  while true do
458
- local target = world:target(entity, relation, index)
733
+ local target = WORLD_TARGET(world, entity, relation, index)
459
734
  if not target then
460
735
  break
461
736
  end
@@ -463,15 +738,15 @@ local function track_entity_pair(server: Server, entity: Entity, relation: Entit
463
738
  targets[target] = true
464
739
  end
465
740
 
466
- entity_storage.pairs[relation] = targets
467
- info[entity] = TRACK_TYPES.pair
468
- add_entity_tracked(server, entity, relation, TRACK_TYPES.pair)
741
+ entity_storage.relations[relation] = targets
742
+ info[entity] = COMPONENT_TYPES.relation
743
+ add_entity_component_tracked(server, entity, relation, COMPONENT_TYPES.relation)
469
744
 
470
- return COMPONENT_TYPES.pair
745
+ return COMPONENT_TYPES.relation
471
746
  end
472
747
  end
473
748
 
474
- local function untrack_entity_component(server: Server, entity: Entity, component: Entity<any>): number?
749
+ local function untrack_entity_component(server: Server, entity: Entity, component: Component): number?
475
750
  local info = server.track_info.components[component]
476
751
  if not info then
477
752
  return nil
@@ -481,21 +756,33 @@ local function untrack_entity_component(server: Server, entity: Entity, componen
481
756
 
482
757
  local storage = server.storage[entity]
483
758
  if storage then
484
- storage.values[component] = nil
759
+ storage.components[component] = nil
485
760
  storage.tags[component] = nil
486
761
  end
487
762
 
488
- local entity_tracked = server.track_info.entities[entity]
489
- if entity_tracked then
490
- entity_tracked[component] = nil
763
+ remove_entity_component_tracked(server, entity, component)
764
+ return listen_type
765
+ end
766
+
767
+ local function untrack_entity_pair(server: Server, entity: Entity, id: Entity): number?
768
+ local info = server.track_info.pairs[id]
769
+ if not info then
770
+ return nil
491
771
  end
772
+ local listen_type = info[entity]
773
+ info[entity] = nil
492
774
 
493
- remove_entity_tracked(server, entity, component)
775
+ local storage = server.storage[entity]
776
+ if storage then
777
+ storage.pair_tags[id] = nil
778
+ storage.pair_components[id] = nil
779
+ end
494
780
 
781
+ remove_entity_pair_tracked(server, entity, id)
495
782
  return listen_type
496
783
  end
497
784
 
498
- local function untrack_entity_pair(server: Server, entity: Entity, relation: Entity): number?
785
+ local function untrack_entity_relation(server: Server, entity: Entity, relation: Entity): number?
499
786
  local info = server.track_info.components[relation]
500
787
  if not info then
501
788
  return nil
@@ -505,55 +792,41 @@ local function untrack_entity_pair(server: Server, entity: Entity, relation: Ent
505
792
 
506
793
  local storage = server.storage[entity]
507
794
  if storage then
508
- storage.pairs[relation] = nil
509
- storage.pairs_values[relation] = nil
795
+ storage.relations[relation] = nil
796
+ storage.relation_values[relation] = nil
510
797
  end
511
798
 
512
- local entity_tracked = server.track_info.entities[entity]
513
- if entity_tracked then
514
- entity_tracked[relation] = nil
515
- end
516
-
517
- remove_entity_tracked(server, entity, relation)
799
+ remove_entity_component_tracked(server, entity, relation)
518
800
  return listen_type
519
801
  end
520
802
 
521
- function server_replicator.encode_component(server: Server, component: Entity): number
522
- local encoded = server.shared.components.members[component]
523
- if not encoded then
524
- utils.logerror(`attempted to encode a non-shared component `, utils.logcomponent(server.world, component))
525
- return 0
526
- end
527
- return encoded
528
- end
529
-
530
- function server_replicator.decode_component(server: Server, encoded: number): Entity
531
- local component = server.shared.components.indexes[encoded]
532
- if not component then
533
- print("NON SHARED COMPONENTS", encoded, server.shared.components)
534
- error "attemped to decode a non shared component"
803
+ local function write_vlq_bitmask(c: Cursor, value: number, mask: number, bit: number): number
804
+ if value > 0 then
805
+ cursor.write_vlq(c, value)
806
+ return utils.setbit(mask, bit)
807
+ else
808
+ return mask
535
809
  end
536
- return component
537
810
  end
538
811
 
539
812
  function server_replicator.write_component_id(server: Server, c: Cursor, component: Entity)
540
813
  local shared_componens = server.shared.components
541
814
  local encoded = shared_componens.members[component]
542
815
  if not encoded then
543
- utils.logerror(`attempted to replicate a non-shared component `, utils.logcomponent(server.world, component))
816
+ common.log_error(`attempted to replicate a non-shared component `, common.log_component(server.world, component))
544
817
  return
545
818
  end
546
819
  cursor.write_span(c, encoded, #shared_componens.keys)
547
820
  end
548
821
 
549
- function server_replicator.write_component_value(
822
+ function server_replicator.write_variant_value(
550
823
  server: Server,
551
824
  c: Cursor,
552
- component: Entity,
825
+ log_component: Component,
826
+ serdes: types.Serdes?,
553
827
  value: any,
554
- variants: { any }
828
+ variants: any
555
829
  )
556
- local serdes = server.shared.serdes[component]
557
830
  if serdes then
558
831
  local output, serdes_variants = serdes.serialize(if value == NIL_COMPONENT_VALUE then nil else value)
559
832
 
@@ -570,9 +843,9 @@ function server_replicator.write_component_value(
570
843
  cursor.write_vlq(c, start_variants + 1)
571
844
  end
572
845
  elseif serdes_variants ~= nil then
573
- utils.logerror(
574
- "serdes: serializer provided variants yet includes_variants is not set to true for component",
575
- utils.logcomponent(server.world, component)
846
+ common.log_error(
847
+ "serdes: serializer provided variants yet includes_variants is not set to true for component: ",
848
+ common.log_component(server.world, log_component)
576
849
  )
577
850
  end
578
851
 
@@ -580,9 +853,9 @@ function server_replicator.write_component_value(
580
853
  cursor.write_buffer(c, output)
581
854
  if bytespan then
582
855
  if bytespan ~= buffer.len(output) then
583
- utils.logerror(
584
- `bytespan: {bytespan} mismatch for buffer lenght: {buffer.len(output)} in component`,
585
- utils.logcomponent(server.world, component)
856
+ common.log_error(
857
+ `bytespan: {bytespan} mismatch for buffer lenght: {buffer.len(output)} in component: `,
858
+ common.log_component(server.world, log_component)
586
859
  )
587
860
  end
588
861
  else
@@ -590,7 +863,7 @@ function server_replicator.write_component_value(
590
863
  cursor.write_vlq(c, len)
591
864
  end
592
865
  else
593
- if value == NIL_COMPONENT_VALUE then
866
+ if value == nil or value == NIL_COMPONENT_VALUE then
594
867
  -- 128 is zero for vlq
595
868
  cursor.writeu8(c, 128)
596
869
  else
@@ -600,9 +873,27 @@ function server_replicator.write_component_value(
600
873
  end
601
874
  end
602
875
 
603
- function server_replicator.write_component(server: Server, c: Cursor, component: Entity, value: any, variants: { any })
604
- server_replicator.write_component_value(server, c, component, value, variants)
605
- server_replicator.write_component_id(server, c, component)
876
+ function server_replicator.write_component_value(
877
+ server: Server,
878
+ c: Cursor,
879
+ component: Component,
880
+ value: any,
881
+ variants: { any }
882
+ )
883
+ local serdes = server.shared.serdes[component]
884
+ server_replicator.write_variant_value(server, c, component, serdes, value, variants)
885
+ end
886
+
887
+ function server_replicator.write_pair_value(
888
+ server: Server,
889
+ c: Cursor,
890
+ relation: Component,
891
+ id: Entity,
892
+ value: any,
893
+ variants: { any }
894
+ )
895
+ local serdes = server.shared.serdes[id] or server.shared.serdes[PAIR(relation, WILDCARD)]
896
+ server_replicator.write_variant_value(server, c, relation, serdes, value, variants)
606
897
  end
607
898
 
608
899
  function server_replicator.write_entity_id(server: Server, c: Cursor, entity: Entity)
@@ -634,7 +925,7 @@ function server_replicator.write_entity_id(server: Server, c: Cursor, entity: En
634
925
  end
635
926
 
636
927
  function server_replicator.write_entity_relations(server: Server, storage: EntityStorage, c: Cursor, relation: Entity)
637
- local targets = storage.pairs[relation]
928
+ local targets = storage.relations[relation]
638
929
  local total_targets = 0
639
930
 
640
931
  for target in targets do
@@ -652,7 +943,7 @@ function server_replicator.write_entity_relations_values(
652
943
  relation: Entity,
653
944
  variants: { any }
654
945
  )
655
- local targets = storage.pairs_values[relation]
946
+ local targets = storage.relation_values[relation]
656
947
  local total_targets = 0
657
948
 
658
949
  for target, value in targets do
@@ -664,6 +955,35 @@ function server_replicator.write_entity_relations_values(
664
955
  server_replicator.write_component_id(server, c, relation)
665
956
  end
666
957
 
958
+ function server_replicator.write_entity_pair_value(
959
+ server: Server,
960
+ world: World,
961
+ c: Cursor,
962
+ id: Component,
963
+ value: any,
964
+ variants: { any }
965
+ )
966
+ local first, second = PAIR_FIRST(world, id), PAIR_SECOND(world, id)
967
+ local pointer_start = c.offset
968
+
969
+ server_replicator.write_pair_value(server, c, first, id, value, variants)
970
+
971
+ -- if the entity is a custom id, we dont know if this has a serdes in the client, as it needs to be processed first
972
+ -- we write a vlq so the client can jump in the cursor to skip this value entirely and process it later
973
+ local pointer_offset = c.offset - pointer_start
974
+ cursor.write_vlq(c, pointer_offset)
975
+
976
+ server_replicator.write_entity_id(server, c, second)
977
+ server_replicator.write_component_id(server, c, first)
978
+ end
979
+
980
+ function server_replicator.write_entity_pair(server: Server, world: World, c: Cursor, id: Component)
981
+ local first, second = PAIR_FIRST(world, id), PAIR_SECOND(world, id)
982
+
983
+ server_replicator.write_entity_id(server, c, second)
984
+ server_replicator.write_component_id(server, c, first)
985
+ end
986
+
667
987
  function server_replicator.write_entity(
668
988
  server: Server,
669
989
  c: Cursor,
@@ -671,56 +991,99 @@ function server_replicator.write_entity(
671
991
  active: masking_controller.ActiveEntity,
672
992
  variants: { any }
673
993
  )
994
+ local world = server.world
674
995
  local storage = server.storage[entity]
996
+ local entity_mask = 0
997
+
998
+ local total_relation_values = 0
999
+ for relation in active.components[COMPONENT_TYPES.relation_component] do
1000
+ server_replicator.write_entity_relations_values(server, storage, c, relation, variants)
1001
+ total_relation_values += 1
1002
+ end
1003
+ entity_mask = write_vlq_bitmask(c, total_relation_values, entity_mask, 5)
1004
+
1005
+ local total_relations = 0
1006
+ for relation in active.components[COMPONENT_TYPES.relation] do
1007
+ server_replicator.write_entity_relations(server, storage, c, relation)
1008
+ total_relations += 1
1009
+ end
1010
+ entity_mask = write_vlq_bitmask(c, total_relations, entity_mask, 4)
1011
+
1012
+ local total_pair_values = 0
1013
+ for id in active.components[COMPONENT_TYPES.pair_component] do
1014
+ local value = storage.pair_components[id]
1015
+ if value == nil then
1016
+ continue
1017
+ end
675
1018
 
676
- local all_pairs_values = 0
677
- for relation in active.components[COMPONENT_TYPES.pair_value] do
678
- server_replicator.write_entity_relations_values(server, storage, c, relation, variants)
679
- all_pairs_values += 1
1019
+ server_replicator.write_entity_pair_value(server, world, c, id, value, variants)
1020
+ total_pair_values += 1
680
1021
  end
681
- cursor.write_vlq(c, all_pairs_values)
1022
+ entity_mask = write_vlq_bitmask(c, total_pair_values, entity_mask, 3)
682
1023
 
683
- local all_pairs = 0
684
- for relation in active.components[COMPONENT_TYPES.pair] do
685
- server_replicator.write_entity_relations(server, storage, c, relation)
686
- all_pairs += 1
1024
+ local total_pairs = 0
1025
+ for id in active.components[COMPONENT_TYPES.pair_tag] do
1026
+ local has_pair = storage.pair_tags[id]
1027
+ if has_pair then
1028
+ server_replicator.write_entity_pair(server, world, c, id)
1029
+ total_pairs += 1
1030
+ end
687
1031
  end
688
- cursor.write_vlq(c, all_pairs)
1032
+ entity_mask = write_vlq_bitmask(c, total_pairs, entity_mask, 2)
689
1033
 
690
- local components = 0
1034
+ local total_components = 0
691
1035
  for component in active.components[COMPONENT_TYPES.component] do
692
- local value = storage.values[component]
1036
+ local value = storage.components[component]
693
1037
  if value == nil then
694
1038
  continue
695
1039
  end
696
1040
 
697
- server_replicator.write_component(server, c, component, value, variants)
698
- components += 1
1041
+ server_replicator.write_component_value(server, c, component, value, variants)
1042
+ server_replicator.write_component_id(server, c, component)
1043
+ total_components += 1
1044
+ end
1045
+ for component in active.components[COMPONENT_TYPES.unreliable] do
1046
+ local has = WORLD_HAS(world, entity, component)
1047
+ if not has then
1048
+ continue
1049
+ end
1050
+ local value = WORLD_GET(world, entity, component)
1051
+
1052
+ server_replicator.write_component_value(server, c, component, value, variants)
1053
+ server_replicator.write_component_id(server, c, component)
1054
+
1055
+ total_components += 1
699
1056
  end
700
- cursor.write_vlq(c, components)
1057
+ entity_mask = write_vlq_bitmask(c, total_components, entity_mask, 1)
701
1058
 
702
- local tags = 0
1059
+ local total_tags = 0
703
1060
  for tag in active.components[COMPONENT_TYPES.tag] do
704
1061
  local has_tag = storage.tags[tag]
705
1062
  if has_tag then
706
1063
  server_replicator.write_component_id(server, c, tag)
707
- tags += 1
1064
+ total_tags += 1
708
1065
  end
709
1066
  end
710
- cursor.write_vlq(c, tags)
711
- server_replicator.write_entity_id(server, c, entity)
1067
+ entity_mask = write_vlq_bitmask(c, total_tags, entity_mask, 0)
1068
+ cursor.writeu8(c, entity_mask)
712
1069
  end
713
1070
 
714
1071
  function server_replicator.resolve_dirty(server: Server)
715
1072
  if server.is_shared_dirty then
716
- server.shared = utils.resolved_shared(server.world, server.components, server.registered_custom_ids)
1073
+ -- stylua: ignore
1074
+ server.shared = utils.resolved_shared(
1075
+ server.world,
1076
+ server.components,
1077
+ server.registered_custom_ids,
1078
+ server.component_serdes
1079
+ )
717
1080
  server.is_shared_dirty = false
718
1081
  end
719
1082
  end
720
1083
 
721
1084
  type Packet = {
722
1085
  buffer: buffer,
723
- variants: { { any } },
1086
+ variants: { any },
724
1087
  }
725
1088
  type MemberPackets = {
726
1089
  packets: Array<Packet>,
@@ -728,12 +1091,7 @@ type MemberPackets = {
728
1091
  total_size: number,
729
1092
  }
730
1093
 
731
- local function append_packet(
732
- packets: { [Player]: MemberPackets },
733
- members: { any },
734
- output: buffer,
735
- variants: { { any } }
736
- )
1094
+ local function append_packet(packets: { [Player]: MemberPackets }, members: { any }, output: buffer, variants: { any })
737
1095
  local len = buffer.len(output)
738
1096
  for _, member in members do
739
1097
  if not utils.is_client_valid(member) then
@@ -783,14 +1141,14 @@ end
783
1141
  type PacketIterator = () -> (Player, buffer, { { any } })
784
1142
 
785
1143
  local function create_packet_iterator(packets: { [Player]: MemberPackets }, id: number)
786
- local iterated: Player? = nil
787
- local function iterator()
1144
+ local iterated: Player?
1145
+ local function iterator()
788
1146
  local player, data = next(packets, iterated)
789
1147
  while not utils.is_client_valid(player) do
790
1148
  if not player and not data then
791
1149
  break
792
1150
  end
793
- player, data = next(packets, iterated)
1151
+ player, data = next(packets, player)
794
1152
  end
795
1153
  if not player then
796
1154
  return nil :: any
@@ -849,7 +1207,7 @@ function server_replicator.get_full(server: Server, client: Player): (buffer, {
849
1207
  server_replicator.resolve_dirty(server)
850
1208
  local index = server.masking.client_indexes[client]
851
1209
  if index == nil then
852
- utils.logerror "attempted to replicate for a non registered client"
1210
+ common.log_error "attempted to replicate for a non registered client"
853
1211
  end
854
1212
 
855
1213
  local packets: Array<Packet> = {}
@@ -864,11 +1222,12 @@ function server_replicator.get_full(server: Server, client: Player): (buffer, {
864
1222
  continue
865
1223
  end
866
1224
  local c = cursor.new()
867
- local variants = {}
1225
+ local variants: { any } = {}
868
1226
 
869
1227
  local total_entities = 0
870
1228
  for entity, active in storage.active do
871
1229
  server_replicator.write_entity(server, c, entity, active, variants)
1230
+ server_replicator.write_entity_id(server, c, entity)
872
1231
  total_entities += 1
873
1232
  end
874
1233
  cursor.write_vlq(c, total_entities)
@@ -884,22 +1243,49 @@ function server_replicator.get_full(server: Server, client: Player): (buffer, {
884
1243
  return combine_packet_outputs(packets, total_size, PACKET_TYPES.full)
885
1244
  end
886
1245
 
887
- local function write_vlq_bitmask(c: Cursor, value: number, mask: number, bit: number): number
888
- if value > 0 then
889
- cursor.write_vlq(c, value)
890
- return utils.setbit(mask, bit)
891
- else
892
- return mask
1246
+ function server_replicator.collect_entity(server: Server, entity: Entity)
1247
+ server_replicator.resolve_dirty(server)
1248
+ local packets: { [Player]: MemberPackets } = {}
1249
+ local processed_storages: Set<StorageGroup> = {}
1250
+
1251
+ local lookup = server.masking.lookups.entities[entity]
1252
+ local entity_storage = lookup.storage_group
1253
+
1254
+ local c_main = cursor.new()
1255
+ local variants_main = {}
1256
+
1257
+ server_replicator.write_entity(server, c_main, entity, entity_storage.active[entity], variants_main)
1258
+ server_replicator.write_entity_id(server, c_main, entity)
1259
+ append_packet(packets, entity_storage.mask.members, cursor.close(c_main), variants_main)
1260
+ processed_storages[entity_storage] = true
1261
+
1262
+ for _, filtered in lookup.filtered_components do
1263
+ for _, component in filtered do
1264
+ local storage = component.storage_group
1265
+ if processed_storages[storage] then
1266
+ continue
1267
+ end
1268
+
1269
+ local c = cursor.new()
1270
+ local variants = {}
1271
+
1272
+ server_replicator.write_entity(server, c, entity, storage.active[entity], variants)
1273
+ server_replicator.write_entity_id(server, c_main, entity)
1274
+ append_packet(packets, storage.mask.members, cursor.close(c), variants)
1275
+ processed_storages[storage] = true
1276
+ end
893
1277
  end
1278
+
1279
+ return create_packet_iterator(packets, PACKET_TYPES.entity)
894
1280
  end
895
1281
 
896
1282
  function server_replicator.collect_updates(server: Server)
897
1283
  server_replicator.resolve_dirty(server)
1284
+ local world = server.world
898
1285
  local packets: { [Player]: MemberPackets } = {}
899
1286
 
900
1287
  for _, storage in server.masking.storages do
901
1288
  local c = cursor.new()
902
-
903
1289
  local variants = {}
904
1290
 
905
1291
  local storage_mask = 0
@@ -916,28 +1302,43 @@ function server_replicator.collect_updates(server: Server)
916
1302
  local total_component_deleted = 0
917
1303
  local component_deletions = storage.deletions.components
918
1304
  for entity, deleted in component_deletions do
919
- local total_pairs = 0
1305
+ local total_relations = 0
920
1306
 
921
- for relation in deleted[COMPONENT_TYPES.pair_value] do
1307
+ for relation in deleted[COMPONENT_TYPES.relation_component] do
922
1308
  server_replicator.write_component_id(server, c, relation)
923
- total_pairs += 1
1309
+ total_relations += 1
924
1310
  end
925
- for relation in deleted[COMPONENT_TYPES.pair] do
1311
+ for relation in deleted[COMPONENT_TYPES.relation] do
926
1312
  server_replicator.write_component_id(server, c, relation)
1313
+ total_relations += 1
1314
+ end
1315
+ cursor.write_vlq(c, total_relations)
1316
+
1317
+ local total_pairs = 0
1318
+ for id in deleted[COMPONENT_TYPES.pair_component] do
1319
+ server_replicator.write_entity_pair(server, world, c, id)
1320
+ total_pairs += 1
1321
+ end
1322
+ for id in deleted[COMPONENT_TYPES.pair_tag] do
1323
+ server_replicator.write_entity_pair(server, world, c, id)
927
1324
  total_pairs += 1
928
1325
  end
929
1326
  cursor.write_vlq(c, total_pairs)
930
1327
 
931
- local total_removed = 0
1328
+ local total_components = 0
932
1329
  for component in deleted[COMPONENT_TYPES.component] do
933
1330
  server_replicator.write_component_id(server, c, component)
934
- total_removed += 1
1331
+ total_components += 1
1332
+ end
1333
+ for component in deleted[COMPONENT_TYPES.unreliable] do
1334
+ server_replicator.write_component_id(server, c, component)
1335
+ total_components += 1
935
1336
  end
936
1337
  for tag in deleted[COMPONENT_TYPES.tag] do
937
1338
  server_replicator.write_component_id(server, c, tag)
938
- total_removed += 1
1339
+ total_components += 1
939
1340
  end
940
- cursor.write_vlq(c, total_removed)
1341
+ cursor.write_vlq(c, total_components)
941
1342
 
942
1343
  server_replicator.write_entity_id(server, c, entity)
943
1344
  total_component_deleted += 1
@@ -948,25 +1349,21 @@ function server_replicator.collect_updates(server: Server)
948
1349
  local storage_changes = storage.changes
949
1350
  local changed = 0
950
1351
  for entity, changes in storage_changes.changed do
951
- local changed_mask = 0
1352
+ -- relations remove
952
1353
 
953
- local total_pairs_values = 0
954
- for relation, targets in changes.pairs_values.changed do
1354
+ local total_relations_removed = 0
1355
+ for relation, targets in changes.relation_component_removed do
955
1356
  local total_targets = 0
956
1357
 
957
- for target, value in targets do
1358
+ for target in targets do
958
1359
  server_replicator.write_entity_id(server, c, target)
959
- server_replicator.write_component_value(server, c, relation, value, variants)
960
1360
  total_targets += 1
961
1361
  end
962
1362
  cursor.write_vlq(c, total_targets)
963
1363
  server_replicator.write_component_id(server, c, relation)
964
- total_pairs_values += 1
1364
+ total_relations_removed += 1
965
1365
  end
966
- changed_mask = write_vlq_bitmask(c, total_pairs_values, changed_mask, 5)
967
-
968
- local total_pairs_values_removed = 0
969
- for relation, targets in changes.pairs_values.removed do
1366
+ for relation, targets in changes.relation_tag_removed do
970
1367
  local total_targets = 0
971
1368
 
972
1369
  for target in targets do
@@ -975,51 +1372,116 @@ function server_replicator.collect_updates(server: Server)
975
1372
  end
976
1373
  cursor.write_vlq(c, total_targets)
977
1374
  server_replicator.write_component_id(server, c, relation)
978
- total_pairs_values_removed += 1
1375
+ total_relations_removed += 1
979
1376
  end
980
- changed_mask = write_vlq_bitmask(c, total_pairs_values_removed, changed_mask, 4)
1377
+ -- using a normal vlq here sadly
1378
+ -- cause I ran out of bitmask space for this one :/
1379
+ cursor.write_vlq(c, total_relations_removed)
981
1380
 
982
- local total_pairs = 0
983
- for relation, targets in changes.pairs do
1381
+ local changed_mask = 0
1382
+
1383
+ -- relations add/set
1384
+
1385
+ local total_relation_components = 0
1386
+ for relation, targets in changes.relation_component_changed do
984
1387
  local total_targets = 0
985
1388
 
986
- for target, added in targets do
1389
+ for target, value in targets do
987
1390
  server_replicator.write_entity_id(server, c, target)
988
- if added then
989
- cursor.writei8(c, 1)
990
- else
991
- cursor.writei8(c, -1)
992
- end
1391
+ server_replicator.write_component_value(server, c, relation, value, variants)
993
1392
  total_targets += 1
994
1393
  end
995
1394
  cursor.write_vlq(c, total_targets)
996
1395
  server_replicator.write_component_id(server, c, relation)
997
- total_pairs += 1
1396
+ total_relation_components += 1
1397
+ end
1398
+ changed_mask = write_vlq_bitmask(c, total_relation_components, changed_mask, 7)
1399
+
1400
+ local total_relation_tags = 0
1401
+ for relation, targets in changes.relation_tag_added do
1402
+ local total_targets = 0
1403
+
1404
+ for target in targets do
1405
+ server_replicator.write_entity_id(server, c, target)
1406
+ total_targets += 1
1407
+ end
1408
+ cursor.write_vlq(c, total_targets)
1409
+ server_replicator.write_component_id(server, c, relation)
1410
+ total_relation_tags += 1
1411
+ end
1412
+ changed_mask = write_vlq_bitmask(c, total_relation_tags, changed_mask, 6)
1413
+
1414
+ -- pairs removed
1415
+
1416
+ local total_pairs_removed = 0
1417
+ for id in changes.pair_component_removed do
1418
+ server_replicator.write_entity_pair(server, world, c, id)
1419
+ total_pairs_removed += 1
1420
+ end
1421
+ for id in changes.pair_tag_removed do
1422
+ server_replicator.write_entity_pair(server, world, c, id)
1423
+ total_pairs_removed += 1
1424
+ end
1425
+ changed_mask = write_vlq_bitmask(c, total_pairs_removed, changed_mask, 5)
1426
+
1427
+ -- pairs add/set
1428
+
1429
+ local total_pair_components = 0
1430
+ for id, value in changes.pair_component_changed do
1431
+ server_replicator.write_entity_pair_value(server, world, c, id, value, variants)
1432
+ total_pair_components += 1
1433
+ end
1434
+ changed_mask = write_vlq_bitmask(c, total_pair_components, changed_mask, 4)
1435
+
1436
+ local total_pair_tags = 0
1437
+ for id in changes.pair_tag_added do
1438
+ server_replicator.write_entity_pair(server, world, c, id)
1439
+ total_pair_tags += 1
998
1440
  end
999
- changed_mask = write_vlq_bitmask(c, total_pairs, changed_mask, 3)
1441
+ changed_mask = write_vlq_bitmask(c, total_pair_tags, changed_mask, 3)
1442
+
1443
+ -- tags/components removed
1000
1444
 
1001
1445
  local total_removed = 0
1002
- for component in changes.removed do
1446
+ for component in changes.component_removed do
1447
+ server_replicator.write_component_id(server, c, component)
1448
+ total_removed += 1
1449
+ end
1450
+ for component in changes.unreliable_removed do
1451
+ server_replicator.write_component_id(server, c, component)
1452
+ total_removed += 1
1453
+ end
1454
+ for component in changes.tag_removed do
1003
1455
  server_replicator.write_component_id(server, c, component)
1004
1456
  total_removed += 1
1005
1457
  end
1006
1458
  changed_mask = write_vlq_bitmask(c, total_removed, changed_mask, 2)
1007
1459
 
1460
+ -- tags/components set
1461
+
1008
1462
  local total_components = 0
1009
- for component, value in changes.component do
1010
- server_replicator.write_component(server, c, component, value, variants)
1463
+ for component, value in changes.component_changed do
1464
+ server_replicator.write_component_value(server, c, component, value, variants)
1465
+ server_replicator.write_component_id(server, c, component)
1466
+ total_components += 1
1467
+ end
1468
+ for component in changes.unreliable_added do
1469
+ local value = WORLD_GET(world, entity, component)
1470
+
1471
+ server_replicator.write_component_value(server, c, component, value, variants)
1472
+ server_replicator.write_component_id(server, c, component)
1011
1473
  total_components += 1
1012
1474
  end
1013
1475
  changed_mask = write_vlq_bitmask(c, total_components, changed_mask, 1)
1014
1476
 
1015
1477
  local total_tagged = 0
1016
- for tag in changes.tagged do
1478
+ for tag in changes.tag_added do
1017
1479
  server_replicator.write_component_id(server, c, tag)
1018
1480
  total_tagged += 1
1019
1481
  end
1020
1482
  changed_mask = write_vlq_bitmask(c, total_tagged, changed_mask, 0)
1021
1483
 
1022
- if changed_mask ~= 0 then
1484
+ if changed_mask + total_relations_removed ~= 0 then
1023
1485
  cursor.writeu8(c, changed_mask)
1024
1486
  server_replicator.write_entity_id(server, c, entity)
1025
1487
  changed += 1
@@ -1033,27 +1495,49 @@ function server_replicator.collect_updates(server: Server)
1033
1495
  local entity_storage = server.storage[entity]
1034
1496
  local added_mask = 0
1035
1497
 
1036
- local total_pairs_values = 0
1037
- for relation in components[COMPONENT_TYPES.pair_value] do
1498
+ local total_relation_values = 0
1499
+ for relation in components[COMPONENT_TYPES.relation_component] do
1038
1500
  server_replicator.write_entity_relations_values(server, entity_storage, c, relation, variants)
1039
- total_pairs_values += 1
1501
+ total_relation_values += 1
1040
1502
  end
1041
- added_mask = write_vlq_bitmask(c, total_pairs_values, added_mask, 3)
1503
+ added_mask = write_vlq_bitmask(c, total_relation_values, added_mask, 5)
1042
1504
 
1043
- local total_pairs = 0
1044
- for relation in components[COMPONENT_TYPES.pair] do
1505
+ local total_relations = 0
1506
+ for relation in components[COMPONENT_TYPES.relation] do
1045
1507
  server_replicator.write_entity_relations(server, entity_storage, c, relation)
1508
+ total_relations += 1
1509
+ end
1510
+ added_mask = write_vlq_bitmask(c, total_relations, added_mask, 4)
1511
+
1512
+ local total_pair_values = 0
1513
+ for id in components[COMPONENT_TYPES.pair_component] do
1514
+ local value = entity_storage.pair_components[id]
1515
+
1516
+ server_replicator.write_entity_pair_value(server, world, c, id, value, variants)
1517
+ total_pair_values += 1
1518
+ end
1519
+ added_mask = write_vlq_bitmask(c, total_pair_values, added_mask, 3)
1520
+
1521
+ local total_pairs = 0
1522
+ for id in components[COMPONENT_TYPES.pair_tag] do
1523
+ server_replicator.write_entity_pair(server, world, c, id)
1046
1524
  total_pairs += 1
1047
1525
  end
1048
1526
  added_mask = write_vlq_bitmask(c, total_pairs, added_mask, 2)
1049
1527
 
1050
1528
  local total_components = 0
1051
1529
  for component in components[COMPONENT_TYPES.component] do
1052
- local value = entity_storage.values[component]
1053
- if value == nil then
1054
- continue
1055
- end
1056
- server_replicator.write_component(server, c, component, value, variants)
1530
+ local value = entity_storage.components[component]
1531
+
1532
+ server_replicator.write_component_value(server, c, component, value, variants)
1533
+ server_replicator.write_component_id(server, c, component)
1534
+ total_components += 1
1535
+ end
1536
+ for component in components[COMPONENT_TYPES.unreliable] do
1537
+ local value = WORLD_GET(world, entity, component)
1538
+
1539
+ server_replicator.write_component_value(server, c, component, value, variants)
1540
+ server_replicator.write_component_id(server, c, component)
1057
1541
  total_components += 1
1058
1542
  end
1059
1543
  added_mask = write_vlq_bitmask(c, total_components, added_mask, 1)
@@ -1085,6 +1569,7 @@ function server_replicator.collect_updates(server: Server)
1085
1569
  end
1086
1570
 
1087
1571
  server_replicator.write_entity(server, c, entity, active, variants)
1572
+ server_replicator.write_entity_id(server, c, entity)
1088
1573
  total_added += 1
1089
1574
  end
1090
1575
  table.clear(storage_changes.added)
@@ -1097,7 +1582,7 @@ function server_replicator.collect_updates(server: Server)
1097
1582
  end
1098
1583
  end
1099
1584
  table.clear(server.additions)
1100
- return create_packet_iterator(packets, PACKET_TYPES.reliable)
1585
+ return create_packet_iterator(packets, PACKET_TYPES.updates)
1101
1586
  end
1102
1587
 
1103
1588
  function server_replicator.collect_unreliable(server: Server)
@@ -1112,20 +1597,17 @@ function server_replicator.collect_unreliable(server: Server)
1112
1597
  local active = mask_storage.active
1113
1598
 
1114
1599
  local c = cursor.new()
1115
- local variants = {} :: { { any } }
1116
- local custom_ids: Set<Entity> = {}
1600
+ local variants = {} :: Array<{ any }>
1117
1601
  local total_entities = 0
1118
1602
 
1119
1603
  local checkpoint_offset = 0
1120
1604
  local checkpoint_variants_count = 0
1121
1605
  local checkpoint_total_entities = 0
1122
- local checkpoint_entity: Entity? = nil
1123
1606
 
1124
- local function create_checkpoint(entity: Entity)
1607
+ local function create_checkpoint()
1125
1608
  checkpoint_offset = c.offset
1126
1609
  checkpoint_variants_count = #variants
1127
1610
  checkpoint_total_entities = total_entities
1128
- checkpoint_entity = entity
1129
1611
  end
1130
1612
 
1131
1613
  local function rollback_checkpoint()
@@ -1134,17 +1616,10 @@ function server_replicator.collect_unreliable(server: Server)
1134
1616
  c.offset = checkpoint_offset
1135
1617
  c = new_cursor
1136
1618
 
1137
- local new_variants = {} :: { { any } }
1619
+ local new_variants = {} :: Array<{ any }>
1138
1620
  for _ = #variants, checkpoint_variants_count + 1, -1 do
1139
- table.insert(new_variants, 1, table.remove(variants))
1140
- end
1141
-
1142
- local new_custom_ids = {} :: Set<Entity>
1143
- if checkpoint_entity then
1144
- new_custom_ids[checkpoint_entity] = true
1145
- custom_ids[checkpoint_entity] = nil
1621
+ table.insert(new_variants, 1, table.remove(variants) :: { any })
1146
1622
  end
1147
- custom_ids = new_custom_ids
1148
1623
 
1149
1624
  variants = new_variants
1150
1625
  total_entities = total_entities - checkpoint_total_entities
@@ -1161,16 +1636,19 @@ function server_replicator.collect_unreliable(server: Server)
1161
1636
  end
1162
1637
 
1163
1638
  for entity, actives in active do
1164
- create_checkpoint(entity)
1639
+ create_checkpoint()
1165
1640
 
1166
1641
  local total_unreliable = 0
1167
1642
  for component in actives.components[COMPONENT_TYPES.unreliable] do
1168
- local value = world:get(entity, component)
1169
- if value == nil then
1643
+ local has = WORLD_HAS(world, entity, component)
1644
+ if not has then
1170
1645
  continue
1171
1646
  end
1647
+ local value = WORLD_GET(world, entity, component)
1648
+
1649
+ server_replicator.write_component_value(server, c, component, value, variants)
1650
+ server_replicator.write_component_id(server, c, component)
1172
1651
 
1173
- server_replicator.write_component(server, c, component, value, variants)
1174
1652
  total_unreliable += 1
1175
1653
  end
1176
1654
 
@@ -1198,47 +1676,69 @@ end
1198
1676
  function server_replicator.start_networked(server: Server, entity: Entity, filter: AnyFilter?)
1199
1677
  local masking = server.masking
1200
1678
 
1201
- masking:unregister_stop_entity(entity)
1679
+ masking:deallocate_entity_stop(entity)
1202
1680
  masking:start_entity(entity, filter)
1203
- masking:propagate_entity_addition(entity)
1681
+ masking:allocate_propagated_entity_start(entity)
1204
1682
 
1205
1683
  server.additions[entity] = true
1206
1684
  server.track_info.networked[entity] = true
1207
1685
  track_entity_lifetime(server, entity)
1208
1686
  end
1687
+
1209
1688
  function server_replicator.start_reliable(server: Server, entity: Entity, component: Component, filter: AnyFilter?)
1210
1689
  local masking = server.masking
1211
1690
 
1212
- local component_type = track_entity_component(server :: Server, entity, component)
1213
- masking:unregister_stop_component(entity, component, component_type)
1214
- masking:start_component(entity, component, component_type, filter)
1691
+ local track_type = track_entity_component(server, entity, component)
1692
+ masking:deallocate_component_stop(entity, component, track_type)
1693
+ masking:start_component(entity, component, track_type, filter)
1694
+
1215
1695
  if server.additions[entity] then
1216
- masking:allocate_entity_addition(entity, component, component_type)
1696
+ masking:allocate_shared_entity_start(entity, component, track_type)
1217
1697
  elseif server.track_info.networked[entity] then
1218
- masking:register_component_addition(entity, component, component_type)
1698
+ masking:allocate_component_start(entity, component, track_type)
1219
1699
  end
1220
1700
  end
1221
1701
 
1222
1702
  function server_replicator.start_unreliable(server: Server, entity: Entity, component: Component, filter: AnyFilter?)
1223
1703
  local masking = server.masking
1704
+ local UNRELIABLE_TYPE = COMPONENT_TYPES.unreliable
1705
+
1706
+ track_entity_unreliable(server, entity, component)
1707
+ masking:deallocate_component_stop(entity, component, UNRELIABLE_TYPE)
1708
+ masking:start_component(entity, component, UNRELIABLE_TYPE, filter)
1709
+
1710
+ if server.additions[entity] then
1711
+ masking:allocate_shared_entity_start(entity, component, UNRELIABLE_TYPE)
1712
+ elseif server.track_info.networked[entity] then
1713
+ masking:allocate_component_start(entity, component, UNRELIABLE_TYPE)
1714
+ end
1715
+ end
1716
+
1717
+ function server_replicator.start_pair(server: Server, entity: Entity, id: Component, filter: AnyFilter?)
1718
+ local masking = server.masking
1719
+
1720
+ local track_type = track_entity_pair(server :: Server, entity, id)
1721
+ masking:deallocate_component_stop(entity, id, track_type)
1722
+ masking:start_component(entity, id, track_type, filter)
1224
1723
 
1225
- masking:unregister_stop_component(entity, component, COMPONENT_TYPES.unreliable)
1226
- masking:start_component(entity, component, COMPONENT_TYPES.unreliable, filter)
1227
1724
  if server.additions[entity] then
1228
- masking:allocate_entity_addition(entity, component, COMPONENT_TYPES.unreliable)
1725
+ masking:allocate_shared_entity_start(entity, id, track_type)
1726
+ elseif server.track_info.networked[entity] then
1727
+ masking:allocate_component_start(entity, id, track_type)
1229
1728
  end
1230
1729
  end
1231
1730
 
1232
- function server_replicator.start_pair(server: Server, entity: Entity, relation: Component, filter: AnyFilter?)
1731
+ function server_replicator.start_relation(server: Server, entity: Entity, relation: Component, filter: AnyFilter?)
1233
1732
  local masking = server.masking
1234
1733
 
1235
- local component_type = track_entity_pair(server, entity, relation)
1236
- masking:unregister_stop_component(entity, relation, component_type)
1237
- masking:start_component(entity, relation, component_type, filter)
1734
+ local track_type = track_entity_relation(server, entity, relation)
1735
+ masking:deallocate_component_stop(entity, relation, track_type)
1736
+ masking:start_component(entity, relation, track_type, filter)
1737
+
1238
1738
  if server.additions[entity] then
1239
- masking:allocate_entity_addition(entity, relation, component_type)
1739
+ masking:allocate_shared_entity_start(entity, relation, track_type)
1240
1740
  elseif server.track_info.networked[entity] then
1241
- masking:register_component_addition(entity, relation, component_type)
1741
+ masking:allocate_component_start(entity, relation, track_type)
1242
1742
  end
1243
1743
  end
1244
1744
 
@@ -1246,92 +1746,127 @@ function server_replicator.change_networked(server: Server, entity: Entity, filt
1246
1746
  local masking = server.masking
1247
1747
  masking:set_entity(entity, filter)
1248
1748
  end
1749
+
1249
1750
  function server_replicator.change_reliable(server: Server, entity: Entity, component: Component, filter: AnyFilter?)
1250
1751
  local world = server.world
1251
1752
  local masking = server.masking
1252
1753
 
1253
- if world:has(component, ECS_COMPONENT) then
1754
+ if IS_COMPONENT(world, component) then
1254
1755
  masking:set_component(entity, component, COMPONENT_TYPES.component, filter)
1255
1756
  else
1256
1757
  masking:set_component(entity, component, COMPONENT_TYPES.tag, filter)
1257
1758
  end
1258
1759
  end
1760
+
1259
1761
  function server_replicator.change_unreliable(server: Server, entity: Entity, component: Component, filter: AnyFilter?)
1260
1762
  local masking = server.masking
1261
1763
  masking:set_component(entity, component, COMPONENT_TYPES.unreliable, filter)
1262
1764
  end
1263
- function server_replicator.change_pair(server: Server, entity: Entity, relation: Component, filter: AnyFilter?)
1765
+
1766
+ function server_replicator.change_pair(server: Server, entity: Entity, id: Component, filter: AnyFilter?)
1767
+ local world = server.world
1768
+ local masking = server.masking
1769
+
1770
+ if IS_COMPONENT(world, id) then
1771
+ masking:set_component(entity, id, COMPONENT_TYPES.pair_component, filter)
1772
+ else
1773
+ masking:set_component(entity, id, COMPONENT_TYPES.pair_tag, filter)
1774
+ end
1775
+ end
1776
+
1777
+ function server_replicator.change_relation(server: Server, entity: Entity, relation: Component, filter: AnyFilter?)
1264
1778
  local world = server.world
1265
1779
  local masking = server.masking
1266
1780
 
1267
- if world:has(relation, ECS_COMPONENT) then
1268
- masking:set_component(entity, relation, COMPONENT_TYPES.pair_value, filter)
1781
+ if IS_COMPONENT(world, relation) then
1782
+ masking:set_component(entity, relation, COMPONENT_TYPES.relation_component, filter)
1269
1783
  else
1270
- masking:set_component(entity, relation, COMPONENT_TYPES.pair, filter)
1784
+ masking:set_component(entity, relation, COMPONENT_TYPES.relation, filter)
1785
+ end
1786
+ end
1787
+
1788
+ local function stop_tracked_component(
1789
+ server: Server,
1790
+ entity: Entity,
1791
+ component: Component,
1792
+ track_type: number,
1793
+ keep: boolean?
1794
+ )
1795
+ local masking = server.masking
1796
+ if server.track_info.networked[entity] then
1797
+ masking:deallocate_component_start(entity, component, track_type)
1798
+ if not keep then
1799
+ masking:allocate_component_stop(entity, component, track_type)
1800
+ end
1271
1801
  end
1802
+ masking:stop_component(entity, component, track_type)
1272
1803
  end
1273
1804
 
1274
- function server_replicator.stop_networked(server: Server, entity: Entity)
1805
+ function server_replicator.stop_networked(server: Server, entity: Entity, keep: boolean?)
1275
1806
  if not server.track_info.networked[entity] then
1276
1807
  return
1277
1808
  end
1278
1809
 
1279
1810
  local masking = server.masking
1280
- masking:register_stop_entity(entity)
1811
+ if not keep then
1812
+ masking:allocate_entity_stop(entity)
1813
+ end
1281
1814
  masking:stop_entity(entity)
1282
1815
 
1283
1816
  server.additions[entity] = nil
1284
1817
  server.track_info.networked[entity] = nil
1285
1818
  end
1286
- function server_replicator.stop_reliable(server: Server, entity: Entity, component: Component)
1287
- local masking = server.masking
1819
+
1820
+ function server_replicator.stop_reliable(server: Server, entity: Entity, component: Component, keep: boolean?)
1288
1821
  if not server.track_info.entities[entity] then
1289
1822
  return
1290
1823
  end
1291
1824
 
1292
- local component_type = untrack_entity_component(server, entity, component)
1293
- if not component_type then
1825
+ local track_type = untrack_entity_component(server, entity, component)
1826
+ if not track_type then
1294
1827
  return
1295
1828
  end
1296
1829
 
1297
- if server.track_info.networked[entity] then
1298
- masking:unregister_component_addition(entity, component, component_type)
1299
- masking:register_stop_component(entity, component, component_type)
1300
- end
1301
- masking:stop_component(entity, component, component_type)
1830
+ stop_tracked_component(server, entity, component, track_type, keep)
1302
1831
  end
1303
- function server_replicator.stop_unreliable(server: Server, entity: Entity, component: Component)
1304
- local masking = server.masking
1832
+
1833
+ function server_replicator.stop_unreliable(server: Server, entity: Entity, component: Component, keep: boolean?)
1305
1834
  if not server.track_info.entities[entity] then
1306
1835
  return
1307
1836
  end
1308
1837
 
1309
- local component_type = untrack_entity_component(server, entity, component)
1310
- if not component_type then
1838
+ local track_type = untrack_entity_component(server, entity, component)
1839
+ if not track_type then
1311
1840
  return
1312
1841
  end
1313
1842
 
1314
- if server.track_info.networked[entity] then
1315
- masking:register_stop_component(entity, component, COMPONENT_TYPES.unreliable)
1316
- end
1317
- masking:stop_component(entity, component, COMPONENT_TYPES.unreliable)
1843
+ stop_tracked_component(server, entity, component, COMPONENT_TYPES.unreliable, keep)
1318
1844
  end
1319
- function server_replicator.stop_pair(server: Server, entity: Entity, relation: Component)
1320
- local masking = server.masking
1845
+
1846
+ function server_replicator.stop_pair(server: Server, entity: Entity, id: Component, keep: boolean?)
1321
1847
  if not server.track_info.entities[entity] then
1322
1848
  return
1323
1849
  end
1324
1850
 
1325
- local component_type = untrack_entity_pair(server, entity, relation)
1326
- if not component_type then
1851
+ local track_type = untrack_entity_pair(server, entity, id)
1852
+ if not track_type then
1327
1853
  return
1328
1854
  end
1329
1855
 
1330
- if server.track_info.networked[entity] then
1331
- masking:unregister_component_addition(entity, relation, component_type)
1332
- masking:register_stop_component(entity, relation, component_type)
1856
+ stop_tracked_component(server, entity, id, track_type, keep)
1857
+ end
1858
+
1859
+ function server_replicator.stop_relation(server: Server, entity: Entity, relation: Component, keep: boolean?)
1860
+ if not server.track_info.entities[entity] then
1861
+ return
1862
+ end
1863
+
1864
+ local track_type = untrack_entity_relation(server, entity, relation)
1865
+ if not track_type then
1866
+ return
1333
1867
  end
1334
- masking:stop_component(entity, relation, component_type)
1868
+
1869
+ stop_tracked_component(server, entity, relation, track_type, keep)
1335
1870
  end
1336
1871
 
1337
1872
  function server_replicator.set_networked(server: Server, entity: Entity, filter: AnyFilter?)
@@ -1341,33 +1876,46 @@ function server_replicator.set_networked(server: Server, entity: Entity, filter:
1341
1876
  server_replicator.start_networked(server, entity, filter)
1342
1877
  end
1343
1878
  end
1879
+
1344
1880
  function server_replicator.set_reliable(server: Server, entity: Entity, component: Component, filter: AnyFilter?)
1345
1881
  local entity_tracked = server.track_info.entities[entity]
1346
- if entity_tracked and entity_tracked[component] then
1882
+ if entity_tracked and entity_tracked.components[component] then
1347
1883
  server_replicator.change_reliable(server, entity, component, filter)
1348
1884
  else
1349
1885
  server_replicator.start_reliable(server, entity, component, filter)
1350
1886
  end
1351
1887
  end
1888
+
1352
1889
  function server_replicator.set_unreliable(server: Server, entity: Entity, component: Component, filter: AnyFilter?)
1353
1890
  local entity_tracked = server.track_info.entities[entity]
1354
- if entity_tracked and entity_tracked[component] then
1891
+ if entity_tracked and entity_tracked.components[component] then
1355
1892
  server_replicator.change_unreliable(server, entity, component, filter)
1356
1893
  else
1357
1894
  server_replicator.start_unreliable(server, entity, component, filter)
1358
1895
  end
1359
1896
  end
1360
- function server_replicator.set_pair(server: Server, entity: Entity, relation: Component, filter: AnyFilter?)
1897
+
1898
+ function server_replicator.set_pair(server: Server, entity: Entity, id: Component, filter: AnyFilter?)
1899
+ local entity_tracked = server.track_info.entities[entity]
1900
+ if entity_tracked and entity_tracked.pairs[id] then
1901
+ server_replicator.change_pair(server, entity, id, filter)
1902
+ else
1903
+ server_replicator.start_pair(server, entity, id, filter)
1904
+ end
1905
+ end
1906
+
1907
+ function server_replicator.set_relation(server: Server, entity: Entity, relation: Component, filter: AnyFilter?)
1361
1908
  local entity_tracked = server.track_info.entities[entity]
1362
- if entity_tracked and entity_tracked[relation] then
1363
- server_replicator.change_pair(server, entity, relation, filter)
1909
+ if entity_tracked and entity_tracked.components[relation] then
1910
+ server_replicator.change_relation(server, entity, relation, filter)
1364
1911
  else
1365
- server_replicator.start_pair(server, entity, relation, filter)
1912
+ server_replicator.start_relation(server, entity, relation, filter)
1366
1913
  end
1367
1914
  end
1915
+
1368
1916
  function server_replicator.set_custom(server: Server, entity: Entity, handler: Component | CustomId)
1369
1917
  if server.custom_ids[entity] then
1370
- utils.logwarn("attempted to register a custom_id twice for the same entity", debug.traceback())
1918
+ common.log_warn("attempted to register a custom_id twice for the same entity", debug.traceback())
1371
1919
  return
1372
1920
  end
1373
1921
  server.custom_ids[entity] = handler
@@ -1377,42 +1925,28 @@ function server_replicator.remove_custom(server: Server, entity: Entity)
1377
1925
  server.custom_ids[entity] = nil
1378
1926
  end
1379
1927
 
1928
+ function server_replicator.set_serdes(server: Server, component: Component, serdes: types.Serdes)
1929
+ server.component_serdes[component] = serdes
1930
+ server.is_shared_dirty = true
1931
+ end
1932
+
1933
+ function server_replicator.remove_serdes(server: Server, component: Component)
1934
+ server.component_serdes[component] = nil
1935
+ server.is_shared_dirty = true
1936
+ end
1937
+
1380
1938
  local function check_created(server: Server)
1381
1939
  if server.inited == true then
1382
1940
  warn "attempted to init a server twice"
1383
1941
  return false
1384
1942
  end
1385
1943
  if server.inited == nil then
1386
- warn "attempted to create a server twice"
1944
+ warn "attempted to init a destroyed server"
1387
1945
  return false
1388
1946
  end
1389
1947
  return true
1390
1948
  end
1391
1949
 
1392
- local function query_tracking_type(server: Server, track_type: Component)
1393
- for entity in server.world:query(PAIR(track_type, WILDCARD)):iter() do
1394
- local index = 0
1395
- while true do
1396
- local target = server.world:target(entity, track_type, index)
1397
- if not target then
1398
- break
1399
- end
1400
- server.set_reliable(server, entity, target, server.world:get(entity, PAIR(track_type, target)))
1401
- index += 1
1402
- end
1403
- end
1404
- end
1405
-
1406
- local function query_current_networked(server: Server)
1407
- for entity, filter in server.world:query(server.components.networked):iter() do
1408
- server.set_networked(server, entity, filter)
1409
- end
1410
-
1411
- query_tracking_type(server, server.components.reliable)
1412
- query_tracking_type(server, server.components.unreliable)
1413
- query_tracking_type(server, server.components.pair)
1414
- end
1415
-
1416
1950
  function server_replicator.init(server: Server, wrd: World?)
1417
1951
  if not check_created(server) then
1418
1952
  return
@@ -1426,100 +1960,108 @@ function server_replicator.init(server: Server, wrd: World?)
1426
1960
  error "Providing a world is required to start replecs"
1427
1961
  end
1428
1962
 
1429
- local hooks = server.hooks
1430
- if not hooks then
1431
- hooks = {
1432
- added = (world :: any).added,
1433
- changed = (world :: any).changed,
1434
- removed = (world :: any).removed,
1435
- }
1436
- server.hooks = hooks
1963
+ if not server.components then
1964
+ server.components = utils.create_components(utils.tag_factory(world), utils.component_factory(world))
1965
+ utils.add_component_names(server.components, function(component, name)
1966
+ common.add_name(world, component, name)
1967
+ end)
1437
1968
  end
1438
1969
 
1439
1970
  local components = server.components
1440
- server.shared = utils.resolved_shared(world, components, server.registered_custom_ids)
1441
1971
 
1442
1972
  local function hook(unhook: () -> ())
1443
1973
  table.insert(server.hooked, unhook)
1444
1974
  end
1445
1975
 
1446
- hook(hooks.added(world, components.networked, function(entity, _, filter)
1976
+ hook(HOOK_ADDED(world, components.networked, function(entity, _, filter)
1447
1977
  server_replicator.start_networked(server, entity, filter)
1448
1978
  end))
1449
- hook(hooks.changed(world, components.networked, function(entity, _, filter)
1979
+ hook(HOOK_CHANGED(world, components.networked, function(entity, _, filter)
1450
1980
  server_replicator.change_networked(server, entity, filter)
1451
1981
  end))
1452
- hook(hooks.removed(world, components.networked, function(entity)
1982
+ hook(HOOK_REMOVED(world, components.networked, function(entity)
1453
1983
  server_replicator.stop_networked(server, entity)
1454
1984
  end))
1455
1985
 
1456
- hook(hooks.added(world, components.reliable, function(entity, id, filter)
1457
- local component = PAIR_SECOND(world, id)
1458
- server_replicator.start_reliable(server, entity, component, filter)
1459
- end))
1460
- hook(hooks.changed(world, components.reliable, function(entity, id, filter)
1461
- local component = PAIR_SECOND(world, id)
1462
- server_replicator.change_reliable(server, entity, component, filter)
1463
- end))
1464
- hook(hooks.removed(world, components.reliable, function(entity, id)
1465
- local component = PAIR_SECOND(world, id)
1466
- server_replicator.stop_reliable(server, entity, component)
1467
- end))
1986
+ if RELATIONSHIPS then
1987
+ hook(HOOK_ADDED(world, LISTEN_RELATION(components.reliable), function(entity, id, filter)
1988
+ local component = PAIR_SECOND(world, id)
1989
+ server_replicator.start_reliable(server, entity, component, filter)
1990
+ end))
1991
+ hook(HOOK_CHANGED(world, LISTEN_RELATION(components.reliable), function(entity, id, filter)
1992
+ local component = PAIR_SECOND(world, id)
1993
+ server_replicator.change_reliable(server, entity, component, filter)
1994
+ end))
1995
+ hook(HOOK_REMOVED(world, LISTEN_RELATION(components.reliable), function(entity, id)
1996
+ local component = PAIR_SECOND(world, id)
1997
+ server_replicator.stop_reliable(server, entity, component)
1998
+ end))
1468
1999
 
1469
- hook(hooks.added(world, components.pair, function(entity, id, filter)
1470
- local relation = PAIR_SECOND(world, id)
1471
- server_replicator.start_pair(server, entity, relation, filter)
1472
- end))
1473
- hook(hooks.changed(world, components.pair, function(entity, id, filter)
1474
- local relation = PAIR_SECOND(world, id)
1475
- server_replicator.change_pair(server, entity, relation, filter)
1476
- end))
1477
- hook(hooks.removed(world, components.pair, function(entity, id)
1478
- local relation = PAIR_SECOND(world, id)
1479
- server_replicator.stop_pair(server, entity, relation)
1480
- end))
2000
+ hook(HOOK_ADDED(world, LISTEN_RELATION(components.relation), function(entity, id, filter)
2001
+ local relation = PAIR_SECOND(world, id)
2002
+ server_replicator.start_relation(server, entity, relation, filter)
2003
+ end))
2004
+ hook(HOOK_CHANGED(world, LISTEN_RELATION(components.relation), function(entity, id, filter)
2005
+ local relation = PAIR_SECOND(world, id)
2006
+ server_replicator.change_relation(server, entity, relation, filter)
2007
+ end))
2008
+ hook(HOOK_REMOVED(world, LISTEN_RELATION(components.relation), function(entity, id)
2009
+ local relation = PAIR_SECOND(world, id)
2010
+ server_replicator.stop_relation(server, entity, relation)
2011
+ end))
1481
2012
 
1482
- hook(hooks.added(world, components.unreliable, function(entity, id, filter)
1483
- local component = PAIR_SECOND(world, id)
1484
- server_replicator.start_unreliable(server, entity, component, filter)
1485
- end))
1486
- hook(hooks.changed(world, components.unreliable, function(entity, id, filter)
1487
- local component = PAIR_SECOND(world, id)
1488
- server_replicator.change_unreliable(server, entity, component, filter)
1489
- end))
1490
- hook(hooks.removed(world, components.unreliable, function(entity, id)
1491
- local component = PAIR_SECOND(world, id)
1492
- server_replicator.stop_unreliable(server, entity, component)
1493
- end))
2013
+ hook(HOOK_ADDED(world, LISTEN_RELATION(components.unreliable), function(entity, id, filter)
2014
+ local component = PAIR_SECOND(world, id)
2015
+ server_replicator.start_unreliable(server, entity, component, filter)
2016
+ end))
2017
+ hook(HOOK_CHANGED(world, LISTEN_RELATION(components.unreliable), function(entity, id, filter)
2018
+ local component = PAIR_SECOND(world, id)
2019
+ server_replicator.change_unreliable(server, entity, component, filter)
2020
+ end))
2021
+ hook(HOOK_REMOVED(world, LISTEN_RELATION(components.unreliable), function(entity, id)
2022
+ local component = PAIR_SECOND(world, id)
2023
+ server_replicator.stop_unreliable(server, entity, component)
2024
+ end))
1494
2025
 
1495
- hook(hooks.added(world, components.custom, function(entity, id)
1496
- if not IS_PAIR(id) then
1497
- utils.logerror "replecs.custom should be used with a relationship in the server"
1498
- end
1499
- local target = PAIR_SECOND(world, id)
1500
- server_replicator.set_custom(server, entity, target)
1501
- end))
1502
- hook(hooks.removed(world, components.custom, function(entity)
1503
- server_replicator.remove_custom(server, entity)
1504
- end))
1505
- hook(hooks.added(world, components.global, function(entity, _, value)
2026
+ hook(HOOK_ADDED(world, LISTEN_RELATION(components.custom), function(entity, id)
2027
+ if not IS_PAIR(id) then
2028
+ common.log_error "replecs.custom should be used with a relationship in the server"
2029
+ end
2030
+ local target = PAIR_SECOND(world, id)
2031
+ server_replicator.set_custom(server, entity, target)
2032
+ end))
2033
+ hook(HOOK_REMOVED(world, LISTEN_RELATION(components.custom), function(entity)
2034
+ server_replicator.remove_custom(server, entity)
2035
+ end))
2036
+ end
2037
+ hook(HOOK_ADDED(world, components.global, function(entity, _, value)
1506
2038
  if value > 245 then
1507
- utils.logerror "global id size exceeded, max is 245"
2039
+ common.log_error "global id size exceeded, max is 245"
1508
2040
  end
1509
2041
  server.global_ids[entity] = value
1510
2042
  end))
1511
2043
 
1512
- hook(hooks.changed(world, components.global, function(entity, _, value)
2044
+ hook(HOOK_CHANGED(world, components.global, function(entity, _, value)
1513
2045
  if value > 245 then
1514
- utils.logerror "global id size exceeded, max is 245"
2046
+ common.log_error "global id size exceeded, max is 245"
1515
2047
  end
1516
2048
  server.global_ids[entity] = value
1517
2049
  end))
1518
- hook(hooks.removed(world, components.global, function(entity)
2050
+ hook(HOOK_REMOVED(world, components.global, function(entity)
1519
2051
  server.global_ids[entity] = nil
1520
2052
  end))
1521
2053
 
1522
- hook(hooks.removed(world, components.__alive_tracking__, function(entity)
2054
+ hook(HOOK_ADDED(world, components.serdes, function(component, _, serdes)
2055
+ server_replicator.set_serdes(server, component, serdes)
2056
+ end))
2057
+ hook(HOOK_CHANGED(world, components.serdes, function(component, _, serdes)
2058
+ server_replicator.set_serdes(server, component, serdes)
2059
+ end))
2060
+ hook(HOOK_REMOVED(world, components.serdes, function(component)
2061
+ server_replicator.remove_serdes(server, component)
2062
+ end))
2063
+
2064
+ hook(HOOK_REMOVED(world, components.__alive_tracking__, function(entity)
1523
2065
  if server.track_info.networked[entity] then
1524
2066
  server_replicator.stop_networked(server, entity)
1525
2067
  end
@@ -1527,18 +2069,21 @@ function server_replicator.init(server: Server, wrd: World?)
1527
2069
  end))
1528
2070
 
1529
2071
  for _, component in server.requires_shared_lookup do
1530
- hook(hooks.added(world, component, function()
2072
+ hook(HOOK_ADDED(world, component, function()
1531
2073
  server.is_shared_dirty = true
1532
2074
  end))
1533
- hook(hooks.changed(world, component, function()
2075
+ hook(HOOK_CHANGED(world, component, function()
1534
2076
  server.is_shared_dirty = true
1535
2077
  end))
1536
- hook(hooks.removed(world, component, function()
2078
+ hook(HOOK_REMOVED(world, component, function()
1537
2079
  server.is_shared_dirty = true
1538
2080
  end))
1539
2081
  end
1540
2082
 
1541
- query_current_networked(server)
2083
+ QUERY_CURRENT_COMPONENTS(server)
2084
+ QUERY_CURRENT_NETWORKED(server)
2085
+
2086
+ server.shared = utils.resolved_shared(world, components, server.registered_custom_ids, server.component_serdes)
1542
2087
 
1543
2088
  if game and game:GetService("RunService"):IsServer() then
1544
2089
  local Players = game:GetService "Players"
@@ -1558,6 +2103,27 @@ function server_replicator.init(server: Server, wrd: World?)
1558
2103
  end
1559
2104
  end
1560
2105
 
2106
+ function server_replicator.encode_component(server: Server, component: Entity): number
2107
+ server_replicator.resolve_dirty(server)
2108
+ local encoded = server.shared.components.members[component]
2109
+ if not encoded then
2110
+ common.log_error(`attempted to encode a non-shared component `, common.log_component(server.world, component))
2111
+ return 0
2112
+ end
2113
+ return encoded
2114
+ end
2115
+
2116
+ function server_replicator.decode_component(server: Server, encoded: number): Entity?
2117
+ server_replicator.resolve_dirty(server)
2118
+ local component = server.shared.components.indexes[encoded]
2119
+ return component
2120
+ end
2121
+
2122
+ function server_replicator.get_shared_count(server: Server): number
2123
+ server_replicator.resolve_dirty(server)
2124
+ return #server.shared.components.keys
2125
+ end
2126
+
1561
2127
  function server_replicator.mark_player_ready(server: Server, player: Player)
1562
2128
  server.masking:activate_client(player)
1563
2129
  end
@@ -1579,14 +2145,14 @@ function server_replicator.register_custom_id(server: Server, custom_id: CustomI
1579
2145
  server.is_shared_dirty = true
1580
2146
  end
1581
2147
 
1582
- function server_replicator.generate_handshake(server: Server): common.HandshakeInfo
2148
+ function server_replicator.generate_handshake(server: Server): types.HandshakeInfo
1583
2149
  server_replicator.resolve_dirty(server)
1584
- return utils.generate_handshake(server.world, server.shared)
2150
+ return utils.generate_handshake(server.shared)
1585
2151
  end
1586
2152
 
1587
- function server_replicator.verify_handshake(server: Server, handshake: common.HandshakeInfo): (boolean, string?)
2153
+ function server_replicator.verify_handshake(server: Server, handshake: types.HandshakeInfo): (boolean, string?)
1588
2154
  server_replicator.resolve_dirty(server)
1589
- return utils.verify_handshake(server.world, server.shared, handshake, "client", "server")
2155
+ return utils.verify_handshake(server.shared, handshake, "client", "server")
1590
2156
  end
1591
2157
 
1592
2158
  function server_replicator.destroy(server: Server)
@@ -1603,12 +2169,19 @@ function server_replicator.destroy(server: Server)
1603
2169
  end
1604
2170
  end
1605
2171
 
1606
- local function create(world: World?, components: common.Components): Server
2172
+ local function create(world: World?, components: types.Components?): Server
1607
2173
  local self = {} :: Server
1608
2174
 
1609
- self.components = components
2175
+ if components then
2176
+ self.components = components
2177
+ elseif world then
2178
+ self.components = utils.create_components(utils.tag_factory(world), utils.component_factory(world))
2179
+ utils.add_component_names(self.components, function(component, name)
2180
+ common.add_name(world, component, name)
2181
+ end)
2182
+ end
1610
2183
 
1611
- self.shared = {} :: common.Shared
2184
+ self.shared = {} :: types.Shared
1612
2185
  self.world = world :: any
1613
2186
  self.additions = {}
1614
2187
  self.storage = {}
@@ -1620,6 +2193,7 @@ local function create(world: World?, components: common.Components): Server
1620
2193
  networked = {},
1621
2194
  entities = {},
1622
2195
  components = {},
2196
+ pairs = {},
1623
2197
  }
1624
2198
  self.connections = {}
1625
2199
  self.inited = false
@@ -1627,21 +2201,12 @@ local function create(world: World?, components: common.Components): Server
1627
2201
  self.alive_tracked = {}
1628
2202
  self.custom_ids = {}
1629
2203
  self.registered_custom_ids = {}
2204
+ self.component_serdes = {}
1630
2205
  self.requires_shared_lookup = {
1631
2206
  self.components.shared,
1632
- self.components.serdes,
1633
- jecs.Name,
2207
+ ECS_NAME,
1634
2208
  }
1635
2209
 
1636
- if world then
1637
- local hooks = {
1638
- added = (world :: any).added,
1639
- changed = (world :: any).changed,
1640
- removed = (world :: any).removed,
1641
- }
1642
- self.hooks = hooks
1643
- end
1644
-
1645
2210
  return setmetatable(self, server_replicator) :: any
1646
2211
  end
1647
2212