@rbxts/replecs 0.3.1 → 0.4.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/replecs/client/init.luau +1760 -0
- package/out/replecs/common.luau +17 -3
- package/out/replecs/cursor.luau +268 -0
- package/out/replecs/handshake.luau +108 -0
- package/out/replecs/init.luau +59 -15
- package/out/replecs/server/bitmasks.luau +322 -0
- package/out/replecs/server/filter_group.luau +196 -0
- package/out/replecs/server/init.luau +3937 -0
- package/out/replecs/server/registry.luau +178 -0
- package/out/replecs/server/utils.luau +20 -0
- package/out/replecs/shared.luau +70 -0
- package/out/replecs/types.luau +31 -16
- package/out/replecs/utils.luau +14 -784
- package/out/replecs/ver.luau +1 -1
- package/package.json +5 -3
- package/out/replecs/client.luau +0 -1673
- package/out/replecs/index.d.ts +0 -257
- package/out/replecs/masking/init.luau +0 -1695
- package/out/replecs/masking/mask_generator.luau +0 -106
- package/out/replecs/server.luau +0 -2216
- package/out/tsconfig.tsbuildinfo +0 -1
package/out/replecs/client.luau
DELETED
|
@@ -1,1673 +0,0 @@
|
|
|
1
|
-
--!optimize 2
|
|
2
|
-
--!native
|
|
3
|
-
|
|
4
|
-
local common = require (script.Parent:WaitForChild('common'))
|
|
5
|
-
local types = require (script.Parent:WaitForChild('types'))
|
|
6
|
-
local customid = require (script.Parent:WaitForChild('customid'))
|
|
7
|
-
local utils = require (script.Parent:WaitForChild('utils'))
|
|
8
|
-
|
|
9
|
-
local cursor = utils.cursor
|
|
10
|
-
|
|
11
|
-
type Cursor = utils.Cursor
|
|
12
|
-
type CustomId = customid.CustomId
|
|
13
|
-
|
|
14
|
-
type Entity = common.Entity
|
|
15
|
-
type Component<T = any> = common.Component<T>
|
|
16
|
-
type World = common.World
|
|
17
|
-
|
|
18
|
-
type Array<T> = { T }
|
|
19
|
-
type Map<K, V> = { [K]: V }
|
|
20
|
-
type Set<T> = { [T]: boolean }
|
|
21
|
-
type Disconnect = () -> ()
|
|
22
|
-
|
|
23
|
-
type CommandBuffer = {
|
|
24
|
-
tags: Set<Component>,
|
|
25
|
-
components: Map<Component, { value: any }>,
|
|
26
|
-
unreliable_components: Map<Component, { value: any }>,
|
|
27
|
-
remove: Set<Component>,
|
|
28
|
-
|
|
29
|
-
pairs_add: { [Component]: Set<Entity> },
|
|
30
|
-
pairs_set: { [Component]: Map<Entity, { value: any }> },
|
|
31
|
-
pairs_unprocessed: {
|
|
32
|
-
[Component]: Map<Entity, {
|
|
33
|
-
cursor: Cursor,
|
|
34
|
-
variants: { any }?,
|
|
35
|
-
processed_value: { value: any }?,
|
|
36
|
-
}>,
|
|
37
|
-
},
|
|
38
|
-
pairs_remove: { [Component]: Set<Entity> },
|
|
39
|
-
relations_clear: Set<Component>,
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
type HookMethod =
|
|
43
|
-
& ((
|
|
44
|
-
self: Client,
|
|
45
|
-
action: "changed",
|
|
46
|
-
relation: Component,
|
|
47
|
-
callback: (entity: Entity, id: Component, value: any) -> ()
|
|
48
|
-
) -> Disconnect)
|
|
49
|
-
& ((
|
|
50
|
-
self: Client,
|
|
51
|
-
action: "removed",
|
|
52
|
-
relation: Component,
|
|
53
|
-
callback: (entity: Entity, id: Component) -> ()
|
|
54
|
-
) -> Disconnect)
|
|
55
|
-
& ((self: Client, action: "deleted", entity: Entity, callback: (entity: Entity) -> ()) -> Disconnect
|
|
56
|
-
)
|
|
57
|
-
type ChangedHooksEntry = {
|
|
58
|
-
overrides: boolean,
|
|
59
|
-
callbacks: Array<(entity: Entity, id: Component, value: any) -> ()>,
|
|
60
|
-
}
|
|
61
|
-
type RemovedHooksEntry = {
|
|
62
|
-
overrides: boolean,
|
|
63
|
-
callbacks: Array<(entity: Entity, id: Component) -> ()>,
|
|
64
|
-
}
|
|
65
|
-
type DeletedHookEntry = {
|
|
66
|
-
overrides: boolean,
|
|
67
|
-
callbacks: Array<(entity: Entity) -> ()>,
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
type CustomIdMap = { [Entity]: CustomId | Entity }
|
|
71
|
-
|
|
72
|
-
export type ClientImp = {
|
|
73
|
-
set_serdes: <T>(self: Client, id: Component<T>, serdes: types.Serdes<T>) -> (),
|
|
74
|
-
remove_serdes: (self: Client, id: Component) -> (),
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export type Client = ClientImp & {
|
|
78
|
-
world: World,
|
|
79
|
-
inited: boolean?,
|
|
80
|
-
|
|
81
|
-
is_replicating: boolean,
|
|
82
|
-
after_replication_callbacks: { () -> () },
|
|
83
|
-
|
|
84
|
-
is_shared_dirty: boolean,
|
|
85
|
-
requires_shared_lookup: { Entity },
|
|
86
|
-
components: types.Components,
|
|
87
|
-
shared: types.Shared,
|
|
88
|
-
global_handler: ((id: number) -> Entity)?,
|
|
89
|
-
server_ids: { [number]: Entity },
|
|
90
|
-
client_ids: { [Entity]: number },
|
|
91
|
-
command_buffers: { [Entity]: CommandBuffer }?,
|
|
92
|
-
command_buffers_active: boolean,
|
|
93
|
-
|
|
94
|
-
registered_custom_ids: { [CustomId]: boolean },
|
|
95
|
-
component_serdes: Map<Component, types.Serdes>,
|
|
96
|
-
|
|
97
|
-
init: (self: Client, world: World?) -> (),
|
|
98
|
-
destroy: (self: Client) -> (),
|
|
99
|
-
handle_global: (self: Client, handler: (id: number) -> Entity) -> (),
|
|
100
|
-
get_server_entity: (self: Client, client_entity: Entity) -> number?,
|
|
101
|
-
get_client_entity: (self: Client, server_entity: number) -> Entity?,
|
|
102
|
-
|
|
103
|
-
register_entity: (self: Client, entity: Entity, server_entity: number) -> (),
|
|
104
|
-
unregister_entity: (self: Client, entity: Entity) -> (),
|
|
105
|
-
|
|
106
|
-
hooked: Array<() -> ()>,
|
|
107
|
-
|
|
108
|
-
after_replication: (self: Client, callback: () -> ()) -> (),
|
|
109
|
-
added: (self: Client, callback: (entity: Entity) -> ()) -> Disconnect,
|
|
110
|
-
hook: HookMethod,
|
|
111
|
-
override: HookMethod,
|
|
112
|
-
addition_hooks: Array<(entity: Entity) -> ()>,
|
|
113
|
-
network_hooks: {
|
|
114
|
-
deleted: { [Entity]: DeletedHookEntry },
|
|
115
|
-
changed: { [Component]: ChangedHooksEntry },
|
|
116
|
-
removed: { [Component]: RemovedHooksEntry },
|
|
117
|
-
},
|
|
118
|
-
|
|
119
|
-
encode_component: (self: Client, component: Entity) -> number,
|
|
120
|
-
decode_component: (self: Client, component: number) -> Entity,
|
|
121
|
-
get_shared_count: (self: Client) -> number,
|
|
122
|
-
|
|
123
|
-
register_custom_id: (self: Client, custom_id: CustomId) -> (),
|
|
124
|
-
|
|
125
|
-
apply_full: (self: Client, buf: buffer, all_variants: { { any } }?) -> (),
|
|
126
|
-
apply_entity: (self: Client, buf: buffer, all_variants: { { any } }?) -> (),
|
|
127
|
-
apply_updates: (self: Client, buf: buffer, all_variants: { { any } }?) -> (),
|
|
128
|
-
apply_unreliable: (self: Client, buf: buffer, all_variants: { { any } }?) -> (),
|
|
129
|
-
|
|
130
|
-
generate_handshake: (self: Client) -> types.HandshakeInfo,
|
|
131
|
-
verify_handshake: (self: Client, handshake: types.HandshakeInfo) -> (boolean, string?),
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
local client_replicator = {}
|
|
135
|
-
client_replicator.__index = client_replicator
|
|
136
|
-
|
|
137
|
-
local GLOBAL_ID_OFFSET = 10
|
|
138
|
-
|
|
139
|
-
local ENTITY_ID_TYPES = {
|
|
140
|
-
entity = 1,
|
|
141
|
-
custom_handler = 2,
|
|
142
|
-
custom_id = 3,
|
|
143
|
-
shared = 4,
|
|
144
|
-
}
|
|
145
|
-
local PACKET_TYPES = {
|
|
146
|
-
full = 1,
|
|
147
|
-
entity = 2,
|
|
148
|
-
updates = 3,
|
|
149
|
-
unreliable = 4,
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
local ECS_NAME = common.ecs_name
|
|
153
|
-
local ECS_WILDCARD = common.wildcard
|
|
154
|
-
local PAIR = common.pair
|
|
155
|
-
local ITERATE_ALL_RELATIONS = common.iterate_all_relations
|
|
156
|
-
local WORLD_ENTITY = common.world_entity
|
|
157
|
-
local WORLD_ADD = common.world_add
|
|
158
|
-
local WORLD_SET = common.world_set
|
|
159
|
-
local WORLD_REMOVE = common.world_remove
|
|
160
|
-
local WORLD_GET = common.world_get
|
|
161
|
-
local WORLD_HAS = common.world_has
|
|
162
|
-
local WORLD_DELETE = common.world_delete
|
|
163
|
-
|
|
164
|
-
local HOOK_ADDED = common.hook_added
|
|
165
|
-
local HOOK_CHANGED = common.hook_changed
|
|
166
|
-
local HOOK_REMOVED = common.hook_removed
|
|
167
|
-
|
|
168
|
-
local function QUERY_CURRENT_COMPONENTS(client: Client)
|
|
169
|
-
for component, serdes in client.world:query(client.components.serdes):iter() do
|
|
170
|
-
client.component_serdes[component] = serdes
|
|
171
|
-
end
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
local function get_or_create_entity(client: Client, server_id: number): Entity
|
|
175
|
-
local world = client.world
|
|
176
|
-
|
|
177
|
-
local server_entity = client.server_ids[server_id]
|
|
178
|
-
if server_entity then
|
|
179
|
-
return server_entity
|
|
180
|
-
else
|
|
181
|
-
local entity = WORLD_ENTITY(world)
|
|
182
|
-
WORLD_ADD(world, entity, client.components.__alive_tracking__)
|
|
183
|
-
|
|
184
|
-
client.server_ids[server_id] = entity
|
|
185
|
-
client.client_ids[entity] = server_id
|
|
186
|
-
|
|
187
|
-
for _, callback in client.addition_hooks do
|
|
188
|
-
callback(entity)
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
return entity
|
|
192
|
-
end
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
local function get_or_create_command_buffer(client: Client, entity: Entity): CommandBuffer
|
|
196
|
-
local command_buffers = client.command_buffers
|
|
197
|
-
|
|
198
|
-
if not command_buffers then
|
|
199
|
-
error "attempted to use a command buffer without being active. (this should never happen)"
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
local command_buffer = command_buffers[entity :: any]
|
|
203
|
-
if not command_buffer then
|
|
204
|
-
command_buffer = {
|
|
205
|
-
tags = {},
|
|
206
|
-
components = {},
|
|
207
|
-
unreliable_components = {},
|
|
208
|
-
remove = {},
|
|
209
|
-
pairs_add = {},
|
|
210
|
-
pairs_set = {},
|
|
211
|
-
pairs_unprocessed = {},
|
|
212
|
-
pairs_remove = {},
|
|
213
|
-
relations_clear = {},
|
|
214
|
-
}
|
|
215
|
-
command_buffers[entity :: any] = command_buffer
|
|
216
|
-
end
|
|
217
|
-
return command_buffer
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
function client_replicator.entity_set(
|
|
221
|
-
client: Client,
|
|
222
|
-
entity: Entity,
|
|
223
|
-
id: Component,
|
|
224
|
-
value: any,
|
|
225
|
-
changed_hooks: ChangedHooksEntry?
|
|
226
|
-
)
|
|
227
|
-
if client.command_buffers_active then
|
|
228
|
-
local command_buffer = get_or_create_command_buffer(client, entity)
|
|
229
|
-
command_buffer.components[id] = { value = value }
|
|
230
|
-
else
|
|
231
|
-
if changed_hooks then
|
|
232
|
-
if not changed_hooks.overrides then
|
|
233
|
-
WORLD_SET(client.world, entity, id, value)
|
|
234
|
-
end
|
|
235
|
-
for _, callback in changed_hooks.callbacks do
|
|
236
|
-
callback(entity, id, value)
|
|
237
|
-
end
|
|
238
|
-
else
|
|
239
|
-
WORLD_SET(client.world, entity, id, value)
|
|
240
|
-
end
|
|
241
|
-
end
|
|
242
|
-
end
|
|
243
|
-
|
|
244
|
-
function client_replicator.entity_add(client: Client, entity: Entity, tag: Entity, changed_hooks: ChangedHooksEntry?)
|
|
245
|
-
if client.command_buffers_active then
|
|
246
|
-
local command_buffer = get_or_create_command_buffer(client, entity)
|
|
247
|
-
command_buffer.tags[tag] = true
|
|
248
|
-
else
|
|
249
|
-
if changed_hooks then
|
|
250
|
-
if not changed_hooks.overrides then
|
|
251
|
-
WORLD_ADD(client.world, entity, tag)
|
|
252
|
-
end
|
|
253
|
-
for _, callback in changed_hooks.callbacks do
|
|
254
|
-
callback(entity, tag)
|
|
255
|
-
end
|
|
256
|
-
else
|
|
257
|
-
WORLD_ADD(client.world, entity, tag)
|
|
258
|
-
end
|
|
259
|
-
end
|
|
260
|
-
end
|
|
261
|
-
|
|
262
|
-
function client_replicator.entity_set_unreliable(
|
|
263
|
-
client: Client,
|
|
264
|
-
entity: Entity,
|
|
265
|
-
id: Entity,
|
|
266
|
-
value: any,
|
|
267
|
-
changed_hooks: ChangedHooksEntry?
|
|
268
|
-
)
|
|
269
|
-
if client.command_buffers_active then
|
|
270
|
-
local command_buffer = get_or_create_command_buffer(client, entity)
|
|
271
|
-
command_buffer.unreliable_components[id] = { value = value }
|
|
272
|
-
else
|
|
273
|
-
if WORLD_HAS(client.world, entity, id) then
|
|
274
|
-
client_replicator.entity_set(client, entity, id, value, changed_hooks)
|
|
275
|
-
end
|
|
276
|
-
end
|
|
277
|
-
end
|
|
278
|
-
|
|
279
|
-
function client_replicator.entity_set_pair(
|
|
280
|
-
client: Client,
|
|
281
|
-
entity: Entity,
|
|
282
|
-
relation: Entity,
|
|
283
|
-
target: Entity,
|
|
284
|
-
value: any,
|
|
285
|
-
changed_hooks: ChangedHooksEntry?
|
|
286
|
-
)
|
|
287
|
-
if client.command_buffers_active then
|
|
288
|
-
local command_buffer = get_or_create_command_buffer(client, entity)
|
|
289
|
-
local pair_relation = command_buffer.pairs_set[relation]
|
|
290
|
-
|
|
291
|
-
if pair_relation then
|
|
292
|
-
pair_relation[target] = { value = value }
|
|
293
|
-
else
|
|
294
|
-
command_buffer.pairs_set[relation] = { [target] = { value = value } }
|
|
295
|
-
end
|
|
296
|
-
else
|
|
297
|
-
client_replicator.entity_set(client, entity, PAIR(relation, target), value, changed_hooks)
|
|
298
|
-
end
|
|
299
|
-
end
|
|
300
|
-
|
|
301
|
-
function client_replicator.entity_add_pair(
|
|
302
|
-
client: Client,
|
|
303
|
-
entity: Entity,
|
|
304
|
-
relation: Entity,
|
|
305
|
-
target: Entity,
|
|
306
|
-
changed_hooks: ChangedHooksEntry?
|
|
307
|
-
)
|
|
308
|
-
if client.command_buffers_active then
|
|
309
|
-
local command_buffer = get_or_create_command_buffer(client, entity)
|
|
310
|
-
local pair_relation = command_buffer.pairs_add[relation]
|
|
311
|
-
|
|
312
|
-
if pair_relation then
|
|
313
|
-
pair_relation[target] = true
|
|
314
|
-
else
|
|
315
|
-
command_buffer.pairs_add[relation] = { [target] = true }
|
|
316
|
-
end
|
|
317
|
-
else
|
|
318
|
-
client_replicator.entity_add(client, entity, PAIR(relation, target), changed_hooks)
|
|
319
|
-
end
|
|
320
|
-
end
|
|
321
|
-
|
|
322
|
-
function client_replicator.entity_set_postponed_pair(
|
|
323
|
-
client: Client,
|
|
324
|
-
entity: Entity,
|
|
325
|
-
relation: Component,
|
|
326
|
-
target: Entity,
|
|
327
|
-
c: Cursor,
|
|
328
|
-
variants: { any }?
|
|
329
|
-
): any
|
|
330
|
-
if client.command_buffers_active then
|
|
331
|
-
local commmand_buffer = get_or_create_command_buffer(client, entity)
|
|
332
|
-
local pairs_unprocessed = commmand_buffer.pairs_unprocessed
|
|
333
|
-
local pair_relation = pairs_unprocessed[relation]
|
|
334
|
-
if pair_relation then
|
|
335
|
-
pair_relation[target] = {
|
|
336
|
-
cursor = c,
|
|
337
|
-
variants = variants,
|
|
338
|
-
}
|
|
339
|
-
else
|
|
340
|
-
pairs_unprocessed[relation] = {
|
|
341
|
-
[target] = {
|
|
342
|
-
cursor = c,
|
|
343
|
-
variants = variants,
|
|
344
|
-
},
|
|
345
|
-
}
|
|
346
|
-
end
|
|
347
|
-
return nil
|
|
348
|
-
else
|
|
349
|
-
local pair_id, value = client_replicator.read_pair_value(client, relation, target, c, variants)
|
|
350
|
-
-- TODO: respect hooks
|
|
351
|
-
WORLD_SET(client.world, entity, pair_id, value)
|
|
352
|
-
return value
|
|
353
|
-
end
|
|
354
|
-
end
|
|
355
|
-
|
|
356
|
-
function client_replicator.entity_remove(client: Client, entity: Entity, id: Entity, removed_hooks: RemovedHooksEntry?)
|
|
357
|
-
if client.command_buffers_active then
|
|
358
|
-
local command_buffer = get_or_create_command_buffer(client, entity)
|
|
359
|
-
command_buffer.remove[id] = true
|
|
360
|
-
else
|
|
361
|
-
if removed_hooks then
|
|
362
|
-
for _, callback in removed_hooks.callbacks do
|
|
363
|
-
callback(entity, id)
|
|
364
|
-
end
|
|
365
|
-
if not removed_hooks.overrides then
|
|
366
|
-
WORLD_REMOVE(client.world, entity, id)
|
|
367
|
-
end
|
|
368
|
-
else
|
|
369
|
-
WORLD_REMOVE(client.world, entity, id)
|
|
370
|
-
end
|
|
371
|
-
end
|
|
372
|
-
end
|
|
373
|
-
|
|
374
|
-
function client_replicator.entity_remove_pair(
|
|
375
|
-
client: Client,
|
|
376
|
-
entity: Entity,
|
|
377
|
-
relation: Entity,
|
|
378
|
-
target: Entity,
|
|
379
|
-
removed_hooks: RemovedHooksEntry?
|
|
380
|
-
)
|
|
381
|
-
if client.command_buffers_active then
|
|
382
|
-
local command_buffer = get_or_create_command_buffer(client, entity)
|
|
383
|
-
local pair_relation = command_buffer.pairs_remove[relation]
|
|
384
|
-
|
|
385
|
-
if pair_relation then
|
|
386
|
-
pair_relation[target] = true
|
|
387
|
-
else
|
|
388
|
-
command_buffer.pairs_remove[relation] = { [target] = true }
|
|
389
|
-
end
|
|
390
|
-
else
|
|
391
|
-
client_replicator.entity_remove(client, entity, PAIR(relation, target), removed_hooks)
|
|
392
|
-
end
|
|
393
|
-
end
|
|
394
|
-
|
|
395
|
-
function client_replicator.entity_clear_relation(
|
|
396
|
-
client: Client,
|
|
397
|
-
entity: Entity,
|
|
398
|
-
relation: Entity,
|
|
399
|
-
removed_hooks: RemovedHooksEntry?
|
|
400
|
-
)
|
|
401
|
-
if client.command_buffers_active then
|
|
402
|
-
local command_buffer = get_or_create_command_buffer(client, entity)
|
|
403
|
-
command_buffer.relations_clear[relation] = true
|
|
404
|
-
else
|
|
405
|
-
local world = client.world
|
|
406
|
-
if removed_hooks then
|
|
407
|
-
ITERATE_ALL_RELATIONS(world, entity, relation, function(pair)
|
|
408
|
-
for _, callback in removed_hooks.callbacks do
|
|
409
|
-
callback(entity, pair)
|
|
410
|
-
end
|
|
411
|
-
if not removed_hooks.overrides then
|
|
412
|
-
WORLD_REMOVE(world, entity, pair)
|
|
413
|
-
end
|
|
414
|
-
end)
|
|
415
|
-
else
|
|
416
|
-
ITERATE_ALL_RELATIONS(world, entity, relation, function(pair)
|
|
417
|
-
WORLD_REMOVE(world, entity, pair)
|
|
418
|
-
end)
|
|
419
|
-
end
|
|
420
|
-
end
|
|
421
|
-
end
|
|
422
|
-
|
|
423
|
-
local function read_variant_value(c: Cursor, serdes: types.Serdes?, variants: { any }?)
|
|
424
|
-
if serdes then
|
|
425
|
-
local bytespan = serdes.bytespan or cursor.read_vlq(c)
|
|
426
|
-
|
|
427
|
-
local appended = cursor.read_buffer(c, bytespan)
|
|
428
|
-
local serdes_variants: { any }?
|
|
429
|
-
|
|
430
|
-
if serdes.includes_variants then
|
|
431
|
-
local start_variant = cursor.read_vlq(c)
|
|
432
|
-
|
|
433
|
-
if start_variant > 0 then
|
|
434
|
-
local size = cursor.read_vlq(c)
|
|
435
|
-
serdes_variants = table.move(variants :: { any }, start_variant, start_variant + size - 1, 1, {})
|
|
436
|
-
end
|
|
437
|
-
end
|
|
438
|
-
|
|
439
|
-
local output = serdes.deserialize(appended, serdes_variants :: any)
|
|
440
|
-
return output
|
|
441
|
-
else
|
|
442
|
-
local variant_id = cursor.read_vlq(c)
|
|
443
|
-
if variant_id == 0 then
|
|
444
|
-
return nil
|
|
445
|
-
end
|
|
446
|
-
local value = (variants :: { any })[variant_id]
|
|
447
|
-
return value
|
|
448
|
-
end
|
|
449
|
-
end
|
|
450
|
-
|
|
451
|
-
function client_replicator.read_pair_value(
|
|
452
|
-
client: Client,
|
|
453
|
-
relation: Component,
|
|
454
|
-
target: Entity,
|
|
455
|
-
c: Cursor,
|
|
456
|
-
variants: { any }?
|
|
457
|
-
)
|
|
458
|
-
local pair_id = PAIR(relation, target)
|
|
459
|
-
local pair_wildcard = PAIR(relation, ECS_WILDCARD)
|
|
460
|
-
local serdes = client.component_serdes[pair_id] or client.component_serdes[pair_wildcard]
|
|
461
|
-
local value = read_variant_value(c, serdes, variants)
|
|
462
|
-
return pair_id, value
|
|
463
|
-
end
|
|
464
|
-
|
|
465
|
-
function client_replicator.read_component_value(
|
|
466
|
-
client: Client,
|
|
467
|
-
component: Component,
|
|
468
|
-
c: Cursor,
|
|
469
|
-
variants: { any }?
|
|
470
|
-
): any
|
|
471
|
-
local serdes = client.shared.serdes[component]
|
|
472
|
-
|
|
473
|
-
if serdes then
|
|
474
|
-
local bytespan = serdes.bytespan or cursor.read_vlq(c)
|
|
475
|
-
|
|
476
|
-
local appended = cursor.read_buffer(c, bytespan)
|
|
477
|
-
local serdes_variants: { any }?
|
|
478
|
-
|
|
479
|
-
if serdes.includes_variants then
|
|
480
|
-
local start_variant = cursor.read_vlq(c)
|
|
481
|
-
|
|
482
|
-
if start_variant > 0 then
|
|
483
|
-
local size = cursor.read_vlq(c)
|
|
484
|
-
serdes_variants = table.move(variants :: { any }, start_variant, start_variant + size - 1, 1, {})
|
|
485
|
-
end
|
|
486
|
-
end
|
|
487
|
-
|
|
488
|
-
local output = serdes.deserialize(appended, serdes_variants :: any)
|
|
489
|
-
return output
|
|
490
|
-
else
|
|
491
|
-
local variant_id = cursor.read_vlq(c)
|
|
492
|
-
if variant_id == 0 then
|
|
493
|
-
return nil
|
|
494
|
-
end
|
|
495
|
-
local value = (variants :: { any })[variant_id]
|
|
496
|
-
return value
|
|
497
|
-
end
|
|
498
|
-
end
|
|
499
|
-
|
|
500
|
-
function client_replicator.read_component_id(client: Client, c: Cursor): Entity
|
|
501
|
-
local shared_components = client.shared.components
|
|
502
|
-
local shared_id = cursor.read_span(c, #shared_components.keys)
|
|
503
|
-
local component = shared_components.indexes[shared_id]
|
|
504
|
-
if not component then
|
|
505
|
-
print("NON SHARED COMPONENT", shared_id, client.shared.components)
|
|
506
|
-
error "received a non shared component"
|
|
507
|
-
end
|
|
508
|
-
return component
|
|
509
|
-
end
|
|
510
|
-
|
|
511
|
-
function client_replicator.resolve_global(client: Client, global_id: number): Entity
|
|
512
|
-
if not client.global_handler then
|
|
513
|
-
error "global id parser not set, consider using client:handle_global()"
|
|
514
|
-
end
|
|
515
|
-
local parsed = client.global_handler(global_id)
|
|
516
|
-
return parsed
|
|
517
|
-
end
|
|
518
|
-
|
|
519
|
-
-- returns entity, server_id, id_type
|
|
520
|
-
function client_replicator.read_entity_id(client: Client, c: Cursor): (Entity?, number?, number?)
|
|
521
|
-
local id_type = cursor.readu8(c)
|
|
522
|
-
|
|
523
|
-
if id_type <= GLOBAL_ID_OFFSET then
|
|
524
|
-
if
|
|
525
|
-
id_type == ENTITY_ID_TYPES.entity
|
|
526
|
-
or id_type == ENTITY_ID_TYPES.custom_id
|
|
527
|
-
or id_type == ENTITY_ID_TYPES.custom_handler
|
|
528
|
-
then
|
|
529
|
-
local server_id = cursor.readu40(c)
|
|
530
|
-
return client.server_ids[server_id], server_id, id_type
|
|
531
|
-
elseif id_type == ENTITY_ID_TYPES.shared then
|
|
532
|
-
return client_replicator.read_component_id(client, c), nil, id_type
|
|
533
|
-
end
|
|
534
|
-
error(`malformed entity type {id_type} ` .. cursor.readu32(c))
|
|
535
|
-
else
|
|
536
|
-
return client_replicator.resolve_global(client, id_type - GLOBAL_ID_OFFSET), nil, id_type
|
|
537
|
-
end
|
|
538
|
-
end
|
|
539
|
-
|
|
540
|
-
local function read_vlq_bitmask(c: Cursor, mask: number, bit: number): number
|
|
541
|
-
if utils.checkbit(mask, bit) then
|
|
542
|
-
return cursor.read_vlq(c)
|
|
543
|
-
else
|
|
544
|
-
return 0
|
|
545
|
-
end
|
|
546
|
-
end
|
|
547
|
-
|
|
548
|
-
function client_replicator.process_entity_id(
|
|
549
|
-
client: Client,
|
|
550
|
-
c: Cursor,
|
|
551
|
-
custom_ids: CustomIdMap,
|
|
552
|
-
process: (entity: Entity) -> ()
|
|
553
|
-
)
|
|
554
|
-
local entity, server_id, id_type = client_replicator.read_entity_id(client, c)
|
|
555
|
-
|
|
556
|
-
if entity then
|
|
557
|
-
-- skip customid, keep cursor offset
|
|
558
|
-
if id_type == ENTITY_ID_TYPES.custom_id then
|
|
559
|
-
client_replicator.read_component_id(client, c)
|
|
560
|
-
elseif id_type == ENTITY_ID_TYPES.custom_handler then
|
|
561
|
-
cursor.readu8(c)
|
|
562
|
-
end
|
|
563
|
-
|
|
564
|
-
return process(entity)
|
|
565
|
-
else
|
|
566
|
-
if id_type == ENTITY_ID_TYPES.custom_id or id_type == ENTITY_ID_TYPES.custom_handler then
|
|
567
|
-
if id_type == ENTITY_ID_TYPES.custom_id then
|
|
568
|
-
local component_id = client_replicator.read_component_id(client, c)
|
|
569
|
-
custom_ids[server_id :: any] = component_id
|
|
570
|
-
elseif id_type == ENTITY_ID_TYPES.custom_handler then
|
|
571
|
-
local shared_custom_id = cursor.readu8(c)
|
|
572
|
-
local handler = client.shared.custom_ids.indexes[shared_custom_id]
|
|
573
|
-
|
|
574
|
-
if not handler then
|
|
575
|
-
common.log_error "attempted to use a custom id that wasn't registered"
|
|
576
|
-
end
|
|
577
|
-
custom_ids[server_id :: any] = handler
|
|
578
|
-
end
|
|
579
|
-
|
|
580
|
-
if client.command_buffers_active then
|
|
581
|
-
-- negative id means it's a custom id,
|
|
582
|
-
-- it needs to be translated first
|
|
583
|
-
process(-server_id :: any)
|
|
584
|
-
else
|
|
585
|
-
client.command_buffers_active = true
|
|
586
|
-
process(-server_id :: any)
|
|
587
|
-
client.command_buffers_active = false
|
|
588
|
-
end
|
|
589
|
-
else
|
|
590
|
-
local new_entity = get_or_create_entity(client, server_id :: number)
|
|
591
|
-
process(new_entity)
|
|
592
|
-
end
|
|
593
|
-
end
|
|
594
|
-
end
|
|
595
|
-
|
|
596
|
-
function client_replicator.process_entity_relations(client: Client, entity: Entity, c: Cursor, custom_ids: CustomIdMap)
|
|
597
|
-
local components = client.components
|
|
598
|
-
local relation = client_replicator.read_component_id(client, c)
|
|
599
|
-
local total_targets = cursor.read_vlq(c)
|
|
600
|
-
local pair_hooks = client.network_hooks.changed[PAIR(components.relation, relation)]
|
|
601
|
-
|
|
602
|
-
for _ = 1, total_targets do
|
|
603
|
-
client_replicator.process_entity_id(client, c, custom_ids, function(target)
|
|
604
|
-
client_replicator.entity_add_pair(client, entity, relation, target, pair_hooks)
|
|
605
|
-
end)
|
|
606
|
-
end
|
|
607
|
-
end
|
|
608
|
-
|
|
609
|
-
function client_replicator.process_entity_relation_values(
|
|
610
|
-
client: Client,
|
|
611
|
-
entity: Entity,
|
|
612
|
-
c: Cursor,
|
|
613
|
-
custom_ids: CustomIdMap,
|
|
614
|
-
variants: { any }?
|
|
615
|
-
)
|
|
616
|
-
local relation = client_replicator.read_component_id(client, c)
|
|
617
|
-
local total_targets = cursor.read_vlq(c)
|
|
618
|
-
local components = client.components
|
|
619
|
-
local relation_hooks = client.network_hooks.changed[PAIR(components.relation, relation)]
|
|
620
|
-
|
|
621
|
-
for _ = 1, total_targets do
|
|
622
|
-
local value = client_replicator.read_component_value(client, relation, c, variants)
|
|
623
|
-
client_replicator.process_entity_id(client, c, custom_ids, function(target)
|
|
624
|
-
client_replicator.entity_set_pair(client, entity, relation, target, value, relation_hooks)
|
|
625
|
-
end)
|
|
626
|
-
end
|
|
627
|
-
end
|
|
628
|
-
|
|
629
|
-
function client_replicator.process_entity_pair_value(
|
|
630
|
-
client: Client,
|
|
631
|
-
entity: Entity,
|
|
632
|
-
c: Cursor,
|
|
633
|
-
custom_ids: CustomIdMap,
|
|
634
|
-
variants: { any }?
|
|
635
|
-
)
|
|
636
|
-
local relation = client_replicator.read_component_id(client, c)
|
|
637
|
-
client_replicator.process_entity_id(client, c, custom_ids, function(target)
|
|
638
|
-
if (target :: any) > 0 then
|
|
639
|
-
local pointer_offset = cursor.read_vlq(c)
|
|
640
|
-
local jump_offset = c.offset - pointer_offset
|
|
641
|
-
|
|
642
|
-
local _, value = client_replicator.read_pair_value(client, relation, target, c, variants)
|
|
643
|
-
client_replicator.entity_set_pair(client, entity, relation, target, value)
|
|
644
|
-
|
|
645
|
-
c.offset = jump_offset
|
|
646
|
-
else
|
|
647
|
-
local frozen_cursor = cursor.from_offset(c.buffer, c.offset)
|
|
648
|
-
|
|
649
|
-
local pointer_offset = cursor.read_vlq(c)
|
|
650
|
-
c.offset -= pointer_offset
|
|
651
|
-
|
|
652
|
-
client_replicator.entity_set_postponed_pair(client, entity, relation, target, frozen_cursor, variants)
|
|
653
|
-
end
|
|
654
|
-
end)
|
|
655
|
-
end
|
|
656
|
-
|
|
657
|
-
function client_replicator.process_entity_pair(client: Client, entity: Entity, c: Cursor, custom_ids: CustomIdMap)
|
|
658
|
-
local relation = client_replicator.read_component_id(client, c)
|
|
659
|
-
client_replicator.process_entity_id(client, c, custom_ids, function(target)
|
|
660
|
-
-- TODO: respect hooks/overrides
|
|
661
|
-
client_replicator.entity_add_pair(client, entity, relation, target)
|
|
662
|
-
end)
|
|
663
|
-
end
|
|
664
|
-
|
|
665
|
-
function client_replicator.process_entity(
|
|
666
|
-
client: Client,
|
|
667
|
-
entity: Entity,
|
|
668
|
-
c: Cursor,
|
|
669
|
-
custom_ids: CustomIdMap,
|
|
670
|
-
variants: { any }?
|
|
671
|
-
)
|
|
672
|
-
local mask = cursor.readu8(c)
|
|
673
|
-
local changed_hooks = client.network_hooks.changed
|
|
674
|
-
local components = client.components
|
|
675
|
-
|
|
676
|
-
local total_tags = read_vlq_bitmask(c, mask, 0)
|
|
677
|
-
for _ = 1, total_tags do
|
|
678
|
-
local tag = client_replicator.read_component_id(client, c)
|
|
679
|
-
local tag_hooks = changed_hooks[PAIR(components.reliable, tag)]
|
|
680
|
-
client_replicator.entity_add(client, entity, tag, tag_hooks)
|
|
681
|
-
end
|
|
682
|
-
|
|
683
|
-
local total_components = read_vlq_bitmask(c, mask, 1)
|
|
684
|
-
for _ = 1, total_components do
|
|
685
|
-
local component = client_replicator.read_component_id(client, c)
|
|
686
|
-
local value = client_replicator.read_component_value(client, component, c, variants)
|
|
687
|
-
local component_hooks = changed_hooks[PAIR(components.reliable, component)]
|
|
688
|
-
client_replicator.entity_set(client, entity, component, value, component_hooks)
|
|
689
|
-
end
|
|
690
|
-
|
|
691
|
-
local total_pairs = read_vlq_bitmask(c, mask, 2)
|
|
692
|
-
for _ = 1, total_pairs do
|
|
693
|
-
client_replicator.process_entity_pair(client, entity, c, custom_ids)
|
|
694
|
-
end
|
|
695
|
-
|
|
696
|
-
local total_pair_values = read_vlq_bitmask(c, mask, 3)
|
|
697
|
-
for _ = 1, total_pair_values do
|
|
698
|
-
client_replicator.process_entity_pair_value(client, entity, c, custom_ids, variants)
|
|
699
|
-
end
|
|
700
|
-
|
|
701
|
-
local total_relations = read_vlq_bitmask(c, mask, 4)
|
|
702
|
-
for _ = 1, total_relations do
|
|
703
|
-
client_replicator.process_entity_relations(client, entity, c, custom_ids)
|
|
704
|
-
end
|
|
705
|
-
|
|
706
|
-
local total_relation_values = read_vlq_bitmask(c, mask, 5)
|
|
707
|
-
for _ = 1, total_relation_values do
|
|
708
|
-
client_replicator.process_entity_relation_values(client, entity, c, custom_ids, variants)
|
|
709
|
-
end
|
|
710
|
-
end
|
|
711
|
-
|
|
712
|
-
function client_replicator.finish_replication(client: Client)
|
|
713
|
-
client.is_replicating = false
|
|
714
|
-
for _, callback in client.after_replication_callbacks do
|
|
715
|
-
callback()
|
|
716
|
-
end
|
|
717
|
-
table.clear(client.after_replication_callbacks)
|
|
718
|
-
end
|
|
719
|
-
|
|
720
|
-
function client_replicator.resolve_dirty(client: Client)
|
|
721
|
-
if client.is_shared_dirty then
|
|
722
|
-
-- stylua: ignore
|
|
723
|
-
client.shared = utils.resolved_shared(
|
|
724
|
-
client.world,
|
|
725
|
-
client.components,
|
|
726
|
-
client.registered_custom_ids,
|
|
727
|
-
client.component_serdes
|
|
728
|
-
)
|
|
729
|
-
client.is_shared_dirty = false
|
|
730
|
-
end
|
|
731
|
-
end
|
|
732
|
-
|
|
733
|
-
local function check_packet_type(c: Cursor, expected_byte: number)
|
|
734
|
-
local got_byte = cursor.readu8(c)
|
|
735
|
-
if got_byte ~= expected_byte then
|
|
736
|
-
local got_type: string?
|
|
737
|
-
local expected_type: string?
|
|
738
|
-
|
|
739
|
-
for packet_type, byte in PACKET_TYPES :: { [string]: number } do
|
|
740
|
-
if byte == got_byte then
|
|
741
|
-
got_type = packet_type
|
|
742
|
-
elseif byte == expected_byte then
|
|
743
|
-
expected_type = packet_type
|
|
744
|
-
end
|
|
745
|
-
end
|
|
746
|
-
common.log_error(
|
|
747
|
-
`packet type mismatch, expected: {expected_type or "(unknown)"} got: {got_type or "(unknown)"} instead`
|
|
748
|
-
)
|
|
749
|
-
end
|
|
750
|
-
end
|
|
751
|
-
|
|
752
|
-
function client_replicator.apply_command_buffer(
|
|
753
|
-
client: Client,
|
|
754
|
-
entity: Entity,
|
|
755
|
-
command_buffer: CommandBuffer,
|
|
756
|
-
request: (e: Entity,...any) -> Entity?
|
|
757
|
-
)
|
|
758
|
-
local components = client.components
|
|
759
|
-
|
|
760
|
-
for tag in command_buffer.tags do
|
|
761
|
-
local tag_hooks = client.network_hooks.changed[PAIR(components.reliable, tag)]
|
|
762
|
-
client_replicator.entity_add(client, entity, tag, tag_hooks)
|
|
763
|
-
end
|
|
764
|
-
for component, value in command_buffer.components do
|
|
765
|
-
local component_hooks = client.network_hooks.changed[PAIR(components.reliable, component)]
|
|
766
|
-
client_replicator.entity_set(client, entity, component, value.value, component_hooks)
|
|
767
|
-
end
|
|
768
|
-
for component, value in command_buffer.unreliable_components do
|
|
769
|
-
local component_hooks = client.network_hooks.changed[PAIR(components.unreliable, component)]
|
|
770
|
-
client_replicator.entity_set(client, entity, component, value.value, component_hooks)
|
|
771
|
-
end
|
|
772
|
-
for component in command_buffer.remove do
|
|
773
|
-
local component_hooks = client.network_hooks.removed[PAIR(components.reliable, component)]
|
|
774
|
-
client_replicator.entity_remove(client, entity, component, component_hooks)
|
|
775
|
-
end
|
|
776
|
-
for relation, targets in command_buffer.pairs_add do
|
|
777
|
-
local relation_hooks = client.network_hooks.changed[PAIR(components.relation, relation)]
|
|
778
|
-
for target in targets do
|
|
779
|
-
local client_target = request(target)
|
|
780
|
-
if client_target then
|
|
781
|
-
client_replicator.entity_add_pair(client, entity, relation, client_target, relation_hooks)
|
|
782
|
-
end
|
|
783
|
-
end
|
|
784
|
-
end
|
|
785
|
-
for relation, targets in command_buffer.pairs_set do
|
|
786
|
-
local relation_hooks = client.network_hooks.changed[PAIR(components.relation, relation)]
|
|
787
|
-
for target, value in targets do
|
|
788
|
-
local client_target = request(target)
|
|
789
|
-
if client_target then
|
|
790
|
-
client_replicator.entity_set_pair(client, entity, relation, client_target, value.value, relation_hooks)
|
|
791
|
-
end
|
|
792
|
-
end
|
|
793
|
-
end
|
|
794
|
-
for relation, targets in command_buffer.pairs_unprocessed do
|
|
795
|
-
-- TODO: respect hooks
|
|
796
|
-
for target, unprocessed in targets do
|
|
797
|
-
local client_target = request(target)
|
|
798
|
-
if client_target then
|
|
799
|
-
local processed_value = unprocessed.processed_value
|
|
800
|
-
if processed_value then
|
|
801
|
-
client_replicator.entity_set_pair(client, entity, relation, client_target, processed_value.value)
|
|
802
|
-
else
|
|
803
|
-
local value = client_replicator.entity_set_postponed_pair(
|
|
804
|
-
client,
|
|
805
|
-
entity,
|
|
806
|
-
relation,
|
|
807
|
-
client_target,
|
|
808
|
-
unprocessed.cursor,
|
|
809
|
-
unprocessed.variants
|
|
810
|
-
)
|
|
811
|
-
unprocessed.processed_value = { value = value }
|
|
812
|
-
end
|
|
813
|
-
end
|
|
814
|
-
end
|
|
815
|
-
end
|
|
816
|
-
|
|
817
|
-
for relation, targets in command_buffer.pairs_remove do
|
|
818
|
-
local relation_hooks = client.network_hooks.removed[PAIR(components.relation, relation)]
|
|
819
|
-
for target in targets do
|
|
820
|
-
local client_target = request(target)
|
|
821
|
-
if client_target then
|
|
822
|
-
client_replicator.entity_remove_pair(client, entity, relation, client_target, relation_hooks)
|
|
823
|
-
end
|
|
824
|
-
end
|
|
825
|
-
end
|
|
826
|
-
for relation in command_buffer.relations_clear do
|
|
827
|
-
local relation_hooks = client.network_hooks.removed[PAIR(components.relation, relation)]
|
|
828
|
-
client_replicator.entity_clear_relation(client, entity, relation, relation_hooks)
|
|
829
|
-
end
|
|
830
|
-
end
|
|
831
|
-
|
|
832
|
-
function client_replicator.find_component_in_buffer(command_buffer: CommandBuffer, component: Entity): { value: any }?
|
|
833
|
-
return command_buffer.components[component] or command_buffer.unreliable_components[component]
|
|
834
|
-
end
|
|
835
|
-
|
|
836
|
-
function client_replicator.find_has_in_buffer(command_buffer: CommandBuffer, tag: Entity): boolean
|
|
837
|
-
return (command_buffer.tags[tag] ~= nil)
|
|
838
|
-
or (command_buffer.components[tag] ~= nil)
|
|
839
|
-
or (command_buffer.unreliable_components[tag] ~= nil)
|
|
840
|
-
end
|
|
841
|
-
|
|
842
|
-
function client_replicator.find_pair_in_buffer(
|
|
843
|
-
command_buffer: CommandBuffer,
|
|
844
|
-
relation: Entity,
|
|
845
|
-
target: Entity,
|
|
846
|
-
find: (unprocessed_entity: Entity) -> (Entity?, Entity)
|
|
847
|
-
): (boolean, any)
|
|
848
|
-
local value_relations = command_buffer.pairs_set[relation]
|
|
849
|
-
if value_relations then
|
|
850
|
-
for buffer_target, value in value_relations do
|
|
851
|
-
local found = find(buffer_target)
|
|
852
|
-
if found == target then
|
|
853
|
-
return true, value.value
|
|
854
|
-
end
|
|
855
|
-
end
|
|
856
|
-
end
|
|
857
|
-
|
|
858
|
-
local relations = command_buffer.pairs_add[relation]
|
|
859
|
-
if relations then
|
|
860
|
-
for buffer_target in relations do
|
|
861
|
-
local found = find(buffer_target)
|
|
862
|
-
if found == target then
|
|
863
|
-
return true, nil
|
|
864
|
-
end
|
|
865
|
-
end
|
|
866
|
-
end
|
|
867
|
-
|
|
868
|
-
local unprocessed_relations = command_buffer.pairs_unprocessed[relation]
|
|
869
|
-
if unprocessed_relations then
|
|
870
|
-
for buffer_target, unprocessed in unprocessed_relations do
|
|
871
|
-
local found = find(buffer_target)
|
|
872
|
-
if found == target then
|
|
873
|
-
local processed_value = unprocessed.processed_value
|
|
874
|
-
return true, processed_value and processed_value.value
|
|
875
|
-
end
|
|
876
|
-
end
|
|
877
|
-
end
|
|
878
|
-
|
|
879
|
-
return false, nil
|
|
880
|
-
end
|
|
881
|
-
|
|
882
|
-
function client_replicator.find_target_in_buffer(
|
|
883
|
-
command_buffer: CommandBuffer,
|
|
884
|
-
relation: Entity,
|
|
885
|
-
index: number?
|
|
886
|
-
): Entity?
|
|
887
|
-
local i = 0
|
|
888
|
-
|
|
889
|
-
local pairs = command_buffer.pairs_add[relation]
|
|
890
|
-
if pairs then
|
|
891
|
-
for target in pairs do
|
|
892
|
-
if i == (index or 0) then
|
|
893
|
-
return target
|
|
894
|
-
end
|
|
895
|
-
i += 1
|
|
896
|
-
end
|
|
897
|
-
end
|
|
898
|
-
|
|
899
|
-
local pairs_values = command_buffer.pairs_set[relation]
|
|
900
|
-
if pairs_values then
|
|
901
|
-
for target in pairs_values do
|
|
902
|
-
if i == (index or 0) then
|
|
903
|
-
return target
|
|
904
|
-
end
|
|
905
|
-
i += 1
|
|
906
|
-
end
|
|
907
|
-
end
|
|
908
|
-
|
|
909
|
-
local unprocessed_pairs = command_buffer.pairs_unprocessed[relation]
|
|
910
|
-
if unprocessed_pairs then
|
|
911
|
-
for target in unprocessed_pairs do
|
|
912
|
-
if i == (index or 0) then
|
|
913
|
-
return target
|
|
914
|
-
end
|
|
915
|
-
i += 1
|
|
916
|
-
end
|
|
917
|
-
end
|
|
918
|
-
|
|
919
|
-
return nil
|
|
920
|
-
end
|
|
921
|
-
|
|
922
|
-
function client_replicator.finish_custom_ids(
|
|
923
|
-
client: Client,
|
|
924
|
-
custom_ids: CustomIdMap,
|
|
925
|
-
command_buffers: { [Entity]: CommandBuffer }
|
|
926
|
-
)
|
|
927
|
-
local world = client.world
|
|
928
|
-
local funcs = {} -- this is so process can use create_context even if its defined after
|
|
929
|
-
local processed: { [Entity]: boolean } = {}
|
|
930
|
-
|
|
931
|
-
local function find(unprocessed_entity: Entity): (Entity?, Entity)
|
|
932
|
-
-- negative entities means they are still server ids that haven't been processed yet
|
|
933
|
-
if (unprocessed_entity :: any) > 0 then
|
|
934
|
-
return unprocessed_entity, unprocessed_entity
|
|
935
|
-
end
|
|
936
|
-
local server_entity = -(unprocessed_entity :: any)
|
|
937
|
-
local client_entity = client.server_ids[server_entity]
|
|
938
|
-
if client_entity then
|
|
939
|
-
return client_entity, server_entity
|
|
940
|
-
end
|
|
941
|
-
return nil, server_entity
|
|
942
|
-
end
|
|
943
|
-
|
|
944
|
-
local function process(unprocessed_entity: Entity, custom_handler: (CustomId | Entity)?): Entity?
|
|
945
|
-
local client_entity, server_entity = find(unprocessed_entity)
|
|
946
|
-
if client_entity then
|
|
947
|
-
return client_entity
|
|
948
|
-
end
|
|
949
|
-
|
|
950
|
-
if processed[server_entity] then
|
|
951
|
-
return nil
|
|
952
|
-
end
|
|
953
|
-
|
|
954
|
-
local new_entity: Entity?
|
|
955
|
-
local command_buffer = command_buffers[unprocessed_entity :: any]
|
|
956
|
-
custom_handler = custom_handler or custom_ids[server_entity]
|
|
957
|
-
|
|
958
|
-
if type(custom_handler) == "number" then
|
|
959
|
-
local component: Entity = custom_handler :: any
|
|
960
|
-
|
|
961
|
-
local handler = WORLD_GET(world, component, client.components.custom_handler)
|
|
962
|
-
if not handler then
|
|
963
|
-
return common.log_error(
|
|
964
|
-
`received a custom id for a non custom component, consider adding custom_handler to component: {common.log_component(
|
|
965
|
-
world,
|
|
966
|
-
component
|
|
967
|
-
)}`
|
|
968
|
-
)
|
|
969
|
-
end
|
|
970
|
-
if command_buffer then
|
|
971
|
-
local value = client_replicator.find_component_in_buffer(command_buffer, component)
|
|
972
|
-
if value then
|
|
973
|
-
new_entity = handler(value.value)
|
|
974
|
-
else
|
|
975
|
-
common.log_warn(`No component found for custom id handler: {common.log_component(world, component)}`)
|
|
976
|
-
new_entity = handler(nil)
|
|
977
|
-
end
|
|
978
|
-
else
|
|
979
|
-
common.log_warn(`No component found for custom id handler: {common.log_component(world, component)}`)
|
|
980
|
-
new_entity = handler(nil)
|
|
981
|
-
end
|
|
982
|
-
else
|
|
983
|
-
local handle_callback = (custom_handler :: CustomId).handle_callback
|
|
984
|
-
if not handle_callback then
|
|
985
|
-
return common.log_error(
|
|
986
|
-
"no handler callback was set for custom id:",
|
|
987
|
-
(custom_handler :: CustomId).identifier
|
|
988
|
-
)
|
|
989
|
-
end
|
|
990
|
-
new_entity = handle_callback(funcs.create_context(unprocessed_entity))
|
|
991
|
-
end
|
|
992
|
-
|
|
993
|
-
if new_entity then
|
|
994
|
-
WORLD_ADD(world, new_entity, client.components.__alive_tracking__)
|
|
995
|
-
|
|
996
|
-
client.server_ids[server_entity :: any] = new_entity
|
|
997
|
-
client.client_ids[new_entity] = server_entity :: any
|
|
998
|
-
|
|
999
|
-
if command_buffer then
|
|
1000
|
-
client_replicator.apply_command_buffer(client, new_entity, command_buffer, process)
|
|
1001
|
-
command_buffers[unprocessed_entity] = nil
|
|
1002
|
-
end
|
|
1003
|
-
end
|
|
1004
|
-
|
|
1005
|
-
processed[server_entity] = true
|
|
1006
|
-
return new_entity
|
|
1007
|
-
end
|
|
1008
|
-
|
|
1009
|
-
local function create_context(unprocessed_entity: Entity)
|
|
1010
|
-
local command_buffer = command_buffers[unprocessed_entity]
|
|
1011
|
-
|
|
1012
|
-
local function component(component: Entity): any
|
|
1013
|
-
if not command_buffer then
|
|
1014
|
-
return nil
|
|
1015
|
-
end
|
|
1016
|
-
local val = client_replicator.find_component_in_buffer(command_buffer, component)
|
|
1017
|
-
return val and val.value
|
|
1018
|
-
end
|
|
1019
|
-
local function target(relation: Entity, index: number?): Entity
|
|
1020
|
-
if not command_buffer then
|
|
1021
|
-
return nil :: any
|
|
1022
|
-
end
|
|
1023
|
-
local server_target = client_replicator.find_target_in_buffer(command_buffer, relation, index)
|
|
1024
|
-
if server_target then
|
|
1025
|
-
return process(server_target :: any) :: Entity
|
|
1026
|
-
end
|
|
1027
|
-
return nil :: any
|
|
1028
|
-
end
|
|
1029
|
-
local function pair_value(relation: Entity, target: Entity): any
|
|
1030
|
-
if not command_buffer then
|
|
1031
|
-
return nil :: any
|
|
1032
|
-
end
|
|
1033
|
-
local _, value = client_replicator.find_pair_in_buffer(command_buffer, relation, target, find)
|
|
1034
|
-
return value
|
|
1035
|
-
end
|
|
1036
|
-
local function has_pair(relation: Entity, target: Entity): boolean
|
|
1037
|
-
if not command_buffer then
|
|
1038
|
-
return nil :: any
|
|
1039
|
-
end
|
|
1040
|
-
local has = client_replicator.find_pair_in_buffer(command_buffer, relation, target, find)
|
|
1041
|
-
return has
|
|
1042
|
-
end
|
|
1043
|
-
local function has(tag: Entity): boolean
|
|
1044
|
-
if not command_buffer then
|
|
1045
|
-
return nil :: any
|
|
1046
|
-
end
|
|
1047
|
-
return client_replicator.find_has_in_buffer(command_buffer, tag)
|
|
1048
|
-
end
|
|
1049
|
-
local function entity(server_entity: number): Entity
|
|
1050
|
-
return process(-server_entity :: any) :: Entity
|
|
1051
|
-
end
|
|
1052
|
-
|
|
1053
|
-
local context: customid.HandleContext = {
|
|
1054
|
-
entity_id = math.abs(unprocessed_entity :: any),
|
|
1055
|
-
has = has,
|
|
1056
|
-
component = component,
|
|
1057
|
-
target = target,
|
|
1058
|
-
pair_value = pair_value,
|
|
1059
|
-
has_pair = has_pair,
|
|
1060
|
-
entity = entity,
|
|
1061
|
-
}
|
|
1062
|
-
|
|
1063
|
-
return context
|
|
1064
|
-
end
|
|
1065
|
-
funcs.create_context = create_context
|
|
1066
|
-
|
|
1067
|
-
for entity, custom_handler in custom_ids do
|
|
1068
|
-
process(-(entity :: any), custom_handler)
|
|
1069
|
-
end
|
|
1070
|
-
|
|
1071
|
-
for entity, command_buffer in command_buffers do
|
|
1072
|
-
if (entity :: any) < 0 then
|
|
1073
|
-
continue
|
|
1074
|
-
end
|
|
1075
|
-
client_replicator.apply_command_buffer(client, entity, command_buffer, process)
|
|
1076
|
-
end
|
|
1077
|
-
end
|
|
1078
|
-
|
|
1079
|
-
function client_replicator.apply_full(client: Client, buf: buffer, all_variants: { { any } }?)
|
|
1080
|
-
client_replicator.resolve_dirty(client)
|
|
1081
|
-
client.is_replicating = true
|
|
1082
|
-
|
|
1083
|
-
local c = cursor.from(buf)
|
|
1084
|
-
check_packet_type(c, PACKET_TYPES.full)
|
|
1085
|
-
|
|
1086
|
-
local total_packets = cursor.read_vlq(c)
|
|
1087
|
-
local variant_start = (all_variants and #all_variants + 1) :: number
|
|
1088
|
-
|
|
1089
|
-
local command_buffers: { [Entity]: CommandBuffer } = {}
|
|
1090
|
-
local custom_ids: CustomIdMap = {}
|
|
1091
|
-
|
|
1092
|
-
client.command_buffers = command_buffers
|
|
1093
|
-
|
|
1094
|
-
for a = 1, total_packets do
|
|
1095
|
-
local total_entities = cursor.read_vlq(c)
|
|
1096
|
-
local variants = all_variants and all_variants[variant_start - a]
|
|
1097
|
-
|
|
1098
|
-
for _ = 1, total_entities do
|
|
1099
|
-
client_replicator.process_entity_id(client, c, custom_ids, function(entity)
|
|
1100
|
-
client_replicator.process_entity(client, entity, c, custom_ids, variants)
|
|
1101
|
-
end)
|
|
1102
|
-
end
|
|
1103
|
-
end
|
|
1104
|
-
|
|
1105
|
-
client_replicator.finish_custom_ids(client, custom_ids, command_buffers)
|
|
1106
|
-
client_replicator.finish_replication(client)
|
|
1107
|
-
end
|
|
1108
|
-
|
|
1109
|
-
function client_replicator.apply_entity(client: Client, buf: buffer, all_variants: { { any } })
|
|
1110
|
-
client_replicator.resolve_dirty(client)
|
|
1111
|
-
client.is_replicating = true
|
|
1112
|
-
|
|
1113
|
-
local c = cursor.from(buf)
|
|
1114
|
-
check_packet_type(c, PACKET_TYPES.entity)
|
|
1115
|
-
|
|
1116
|
-
local total_packets = cursor.read_vlq(c)
|
|
1117
|
-
local variant_start = (all_variants and #all_variants + 1) :: number
|
|
1118
|
-
|
|
1119
|
-
local command_buffers: { [Entity]: CommandBuffer } = {}
|
|
1120
|
-
local custom_ids: CustomIdMap = {}
|
|
1121
|
-
|
|
1122
|
-
client.command_buffers = command_buffers
|
|
1123
|
-
|
|
1124
|
-
for a = 1, total_packets do
|
|
1125
|
-
local variants = all_variants and all_variants[variant_start - a]
|
|
1126
|
-
|
|
1127
|
-
client_replicator.process_entity_id(client, c, custom_ids, function(entity)
|
|
1128
|
-
client_replicator.process_entity(client, entity, c, custom_ids, variants)
|
|
1129
|
-
end)
|
|
1130
|
-
end
|
|
1131
|
-
|
|
1132
|
-
client_replicator.finish_custom_ids(client, custom_ids, command_buffers)
|
|
1133
|
-
client_replicator.finish_replication(client)
|
|
1134
|
-
end
|
|
1135
|
-
|
|
1136
|
-
function client_replicator.apply_updates(client: Client, buf: buffer, all_variants: { { any } }?)
|
|
1137
|
-
client_replicator.resolve_dirty(client)
|
|
1138
|
-
client.is_replicating = true
|
|
1139
|
-
|
|
1140
|
-
local c = cursor.from(buf)
|
|
1141
|
-
check_packet_type(c, PACKET_TYPES.updates)
|
|
1142
|
-
|
|
1143
|
-
local world = client.world
|
|
1144
|
-
local components = client.components
|
|
1145
|
-
local total_packets = cursor.read_vlq(c)
|
|
1146
|
-
local variant_start = (all_variants and #all_variants + 1) :: number
|
|
1147
|
-
local changed_hooks = client.network_hooks.changed
|
|
1148
|
-
local removed_hooks = client.network_hooks.removed
|
|
1149
|
-
local deleted_hooks = client.network_hooks.deleted
|
|
1150
|
-
|
|
1151
|
-
local command_buffers: { [Entity]: CommandBuffer } = {}
|
|
1152
|
-
local custom_ids: CustomIdMap = {}
|
|
1153
|
-
|
|
1154
|
-
client.command_buffers = command_buffers
|
|
1155
|
-
|
|
1156
|
-
for a = 1, total_packets do
|
|
1157
|
-
local variants = all_variants and all_variants[variant_start - a]
|
|
1158
|
-
local storage_mask = cursor.readu8(c)
|
|
1159
|
-
|
|
1160
|
-
local total_added = read_vlq_bitmask(c, storage_mask, 0)
|
|
1161
|
-
for _ = 1, total_added do
|
|
1162
|
-
client_replicator.process_entity_id(client, c, custom_ids, function(entity)
|
|
1163
|
-
client_replicator.process_entity(client, entity, c, custom_ids, variants)
|
|
1164
|
-
end)
|
|
1165
|
-
end
|
|
1166
|
-
|
|
1167
|
-
local total_components_added = read_vlq_bitmask(c, storage_mask, 1)
|
|
1168
|
-
for _ = 1, total_components_added do
|
|
1169
|
-
client_replicator.process_entity_id(client, c, custom_ids, function(entity)
|
|
1170
|
-
local added_mask = cursor.readu8(c)
|
|
1171
|
-
|
|
1172
|
-
local total_tags = read_vlq_bitmask(c, added_mask, 0)
|
|
1173
|
-
for _ = 1, total_tags do
|
|
1174
|
-
local tag = client_replicator.read_component_id(client, c)
|
|
1175
|
-
local tag_hooks = changed_hooks[PAIR(components.reliable, tag)]
|
|
1176
|
-
client_replicator.entity_add(client, entity, tag, tag_hooks)
|
|
1177
|
-
end
|
|
1178
|
-
|
|
1179
|
-
local total_components = read_vlq_bitmask(c, added_mask, 1)
|
|
1180
|
-
for _ = 1, total_components do
|
|
1181
|
-
local component = client_replicator.read_component_id(client, c)
|
|
1182
|
-
local value = client_replicator.read_component_value(client, component, c, variants)
|
|
1183
|
-
local component_hooks = changed_hooks[PAIR(components.reliable, component)]
|
|
1184
|
-
client_replicator.entity_set(client, entity, component, value, component_hooks)
|
|
1185
|
-
end
|
|
1186
|
-
|
|
1187
|
-
local total_pairs = read_vlq_bitmask(c, added_mask, 2)
|
|
1188
|
-
for _ = 1, total_pairs do
|
|
1189
|
-
client_replicator.process_entity_pair(client, entity, c, custom_ids)
|
|
1190
|
-
end
|
|
1191
|
-
|
|
1192
|
-
local total_pair_values = read_vlq_bitmask(c, added_mask, 3)
|
|
1193
|
-
for _ = 1, total_pair_values do
|
|
1194
|
-
client_replicator.process_entity_pair_value(client, entity, c, custom_ids, variants)
|
|
1195
|
-
end
|
|
1196
|
-
|
|
1197
|
-
local total_relations = read_vlq_bitmask(c, added_mask, 4)
|
|
1198
|
-
for _ = 1, total_relations do
|
|
1199
|
-
client_replicator.process_entity_relations(client, entity, c, custom_ids)
|
|
1200
|
-
end
|
|
1201
|
-
|
|
1202
|
-
local total_relation_values = read_vlq_bitmask(c, added_mask, 5)
|
|
1203
|
-
for _ = 1, total_relation_values do
|
|
1204
|
-
client_replicator.process_entity_relation_values(client, entity, c, custom_ids, variants)
|
|
1205
|
-
end
|
|
1206
|
-
end)
|
|
1207
|
-
end
|
|
1208
|
-
|
|
1209
|
-
local total_changed = read_vlq_bitmask(c, storage_mask, 2)
|
|
1210
|
-
for _ = 1, total_changed do
|
|
1211
|
-
client_replicator.process_entity_id(client, c, custom_ids, function(entity)
|
|
1212
|
-
local changed_mask = cursor.readu8(c)
|
|
1213
|
-
|
|
1214
|
-
local total_tagged = read_vlq_bitmask(c, changed_mask, 0)
|
|
1215
|
-
for _ = 1, total_tagged do
|
|
1216
|
-
local tag = client_replicator.read_component_id(client, c)
|
|
1217
|
-
local tag_hooks = changed_hooks[PAIR(components.reliable, tag)]
|
|
1218
|
-
client_replicator.entity_add(client, entity, tag, tag_hooks)
|
|
1219
|
-
end
|
|
1220
|
-
|
|
1221
|
-
local total_components = read_vlq_bitmask(c, changed_mask, 1)
|
|
1222
|
-
for _ = 1, total_components do
|
|
1223
|
-
local component = client_replicator.read_component_id(client, c)
|
|
1224
|
-
local value = client_replicator.read_component_value(client, component, c, variants)
|
|
1225
|
-
local component_hooks = changed_hooks[PAIR(components.reliable, component)]
|
|
1226
|
-
client_replicator.entity_set(client, entity, component, value, component_hooks)
|
|
1227
|
-
end
|
|
1228
|
-
|
|
1229
|
-
local total_removed = read_vlq_bitmask(c, changed_mask, 2)
|
|
1230
|
-
for _ = 1, total_removed do
|
|
1231
|
-
local component = client_replicator.read_component_id(client, c)
|
|
1232
|
-
local component_hooks = removed_hooks[PAIR(components.reliable, component)]
|
|
1233
|
-
client_replicator.entity_remove(client, entity, component, component_hooks)
|
|
1234
|
-
end
|
|
1235
|
-
|
|
1236
|
-
local total_pairs_added = read_vlq_bitmask(c, changed_mask, 3)
|
|
1237
|
-
for _ = 1, total_pairs_added do
|
|
1238
|
-
client_replicator.process_entity_pair(client, entity, c, custom_ids)
|
|
1239
|
-
end
|
|
1240
|
-
|
|
1241
|
-
local total_pairs_set = read_vlq_bitmask(c, changed_mask, 4)
|
|
1242
|
-
for _ = 1, total_pairs_set do
|
|
1243
|
-
client_replicator.process_entity_pair_value(client, entity, c, custom_ids, variants)
|
|
1244
|
-
end
|
|
1245
|
-
|
|
1246
|
-
local total_pairs_removed = read_vlq_bitmask(c, changed_mask, 5)
|
|
1247
|
-
for _ = 1, total_pairs_removed do
|
|
1248
|
-
local relation = client_replicator.read_component_id(client, c)
|
|
1249
|
-
client_replicator.process_entity_id(client, c, custom_ids, function(target)
|
|
1250
|
-
-- TODO: respect hooks/overrides
|
|
1251
|
-
client_replicator.entity_remove_pair(client, entity, relation, target)
|
|
1252
|
-
end)
|
|
1253
|
-
end
|
|
1254
|
-
|
|
1255
|
-
local total_relations_added = read_vlq_bitmask(c, changed_mask, 6)
|
|
1256
|
-
for _ = 1, total_relations_added do
|
|
1257
|
-
local relation = client_replicator.read_component_id(client, c)
|
|
1258
|
-
local total_targets = cursor.read_vlq(c)
|
|
1259
|
-
local pair_changed_hooks = changed_hooks[PAIR(components.relation, relation)]
|
|
1260
|
-
|
|
1261
|
-
for _ = 1, total_targets do
|
|
1262
|
-
client_replicator.process_entity_id(client, c, custom_ids, function(target)
|
|
1263
|
-
client_replicator.entity_add_pair(client, entity, relation, target, pair_changed_hooks)
|
|
1264
|
-
end)
|
|
1265
|
-
end
|
|
1266
|
-
end
|
|
1267
|
-
|
|
1268
|
-
local total_relation_values = read_vlq_bitmask(c, changed_mask, 7)
|
|
1269
|
-
for _ = 1, total_relation_values do
|
|
1270
|
-
local relation = client_replicator.read_component_id(client, c)
|
|
1271
|
-
local total_targets = cursor.read_vlq(c)
|
|
1272
|
-
local pair_changed_hooks = changed_hooks[PAIR(components.relation, relation)]
|
|
1273
|
-
|
|
1274
|
-
for _ = 1, total_targets do
|
|
1275
|
-
local value = client_replicator.read_component_value(client, relation, c, variants)
|
|
1276
|
-
client_replicator.process_entity_id(client, c, custom_ids, function(target)
|
|
1277
|
-
client_replicator.entity_set_pair(client, entity, relation, target, value, pair_changed_hooks)
|
|
1278
|
-
end)
|
|
1279
|
-
end
|
|
1280
|
-
end
|
|
1281
|
-
|
|
1282
|
-
-- using a normal vlq here sadly
|
|
1283
|
-
-- cause I ran out of bitmask space for this one :/
|
|
1284
|
-
local total_relations_removed = cursor.read_vlq(c)
|
|
1285
|
-
for _ = 1, total_relations_removed do
|
|
1286
|
-
local relation = client_replicator.read_component_id(client, c)
|
|
1287
|
-
local total_targets = cursor.read_vlq(c)
|
|
1288
|
-
local pair_removed_hooks = removed_hooks[PAIR(components.relation, relation)]
|
|
1289
|
-
|
|
1290
|
-
for _ = 1, total_targets do
|
|
1291
|
-
client_replicator.process_entity_id(client, c, custom_ids, function(target)
|
|
1292
|
-
client_replicator.entity_remove_pair(client, entity, relation, target, pair_removed_hooks)
|
|
1293
|
-
end)
|
|
1294
|
-
end
|
|
1295
|
-
end
|
|
1296
|
-
end)
|
|
1297
|
-
end
|
|
1298
|
-
|
|
1299
|
-
local total_component_deletions = read_vlq_bitmask(c, storage_mask, 3)
|
|
1300
|
-
for _ = 1, total_component_deletions do
|
|
1301
|
-
client_replicator.process_entity_id(client, c, custom_ids, function(entity)
|
|
1302
|
-
local total_components = cursor.read_vlq(c)
|
|
1303
|
-
for _ = 1, total_components do
|
|
1304
|
-
local component = client_replicator.read_component_id(client, c)
|
|
1305
|
-
local component_hooks = removed_hooks[PAIR(components.reliable, component)]
|
|
1306
|
-
client_replicator.entity_remove(client, entity, component, component_hooks)
|
|
1307
|
-
end
|
|
1308
|
-
|
|
1309
|
-
local total_pairs = cursor.read_vlq(c)
|
|
1310
|
-
for _ = 1, total_pairs do
|
|
1311
|
-
local relation = client_replicator.read_component_id(client, c)
|
|
1312
|
-
client_replicator.process_entity_id(client, c, custom_ids, function(target)
|
|
1313
|
-
-- TODO: respect hooks/overrides
|
|
1314
|
-
client_replicator.entity_remove_pair(client, entity, relation, target)
|
|
1315
|
-
end)
|
|
1316
|
-
end
|
|
1317
|
-
|
|
1318
|
-
local total_relations = cursor.read_vlq(c)
|
|
1319
|
-
for _ = 1, total_relations do
|
|
1320
|
-
local relation = client_replicator.read_component_id(client, c)
|
|
1321
|
-
local pair_hooks = removed_hooks[PAIR(components.relation, relation)]
|
|
1322
|
-
client_replicator.entity_clear_relation(client, entity, relation, pair_hooks)
|
|
1323
|
-
end
|
|
1324
|
-
end)
|
|
1325
|
-
end
|
|
1326
|
-
|
|
1327
|
-
local total_deleted = read_vlq_bitmask(c, storage_mask, 4)
|
|
1328
|
-
for _ = 1, total_deleted do
|
|
1329
|
-
local entity, server_id = client_replicator.read_entity_id(client, c)
|
|
1330
|
-
if entity then
|
|
1331
|
-
local deleted_hook = deleted_hooks[entity]
|
|
1332
|
-
if deleted_hook then
|
|
1333
|
-
for _, callback in deleted_hook.callbacks do
|
|
1334
|
-
callback(entity)
|
|
1335
|
-
end
|
|
1336
|
-
if not deleted_hook.overrides then
|
|
1337
|
-
WORLD_DELETE(world, entity)
|
|
1338
|
-
end
|
|
1339
|
-
else
|
|
1340
|
-
WORLD_DELETE(world, entity)
|
|
1341
|
-
end
|
|
1342
|
-
end
|
|
1343
|
-
if server_id then
|
|
1344
|
-
client.server_ids[server_id] = nil
|
|
1345
|
-
end
|
|
1346
|
-
end
|
|
1347
|
-
end
|
|
1348
|
-
|
|
1349
|
-
client_replicator.finish_custom_ids(client, custom_ids, command_buffers)
|
|
1350
|
-
client_replicator.finish_replication(client)
|
|
1351
|
-
end
|
|
1352
|
-
|
|
1353
|
-
function client_replicator.apply_unreliable(client: Client, buf: buffer, all_variants: { { any } }?)
|
|
1354
|
-
client_replicator.resolve_dirty(client)
|
|
1355
|
-
client.is_replicating = true
|
|
1356
|
-
|
|
1357
|
-
local c = cursor.from(buf)
|
|
1358
|
-
check_packet_type(c, PACKET_TYPES.unreliable)
|
|
1359
|
-
|
|
1360
|
-
local components = client.components
|
|
1361
|
-
local total_packets = cursor.read_vlq(c)
|
|
1362
|
-
local variant_start = (all_variants and #all_variants + 1) :: number
|
|
1363
|
-
local changed_hooks = client.network_hooks.changed
|
|
1364
|
-
|
|
1365
|
-
for a = 1, total_packets do
|
|
1366
|
-
local total_entities = cursor.read_vlq(c)
|
|
1367
|
-
local variants = all_variants and all_variants[variant_start - a]
|
|
1368
|
-
|
|
1369
|
-
for _ = 1, total_entities do
|
|
1370
|
-
local entity = client_replicator.read_entity_id(client, c)
|
|
1371
|
-
local total_unreliable = cursor.read_vlq(c)
|
|
1372
|
-
|
|
1373
|
-
if entity then
|
|
1374
|
-
for _ = 1, total_unreliable do
|
|
1375
|
-
local component = client_replicator.read_component_id(client, c)
|
|
1376
|
-
local value = client_replicator.read_component_value(client, component, c, variants)
|
|
1377
|
-
|
|
1378
|
-
local unreliable_hooks = changed_hooks[PAIR(components.unreliable, component)]
|
|
1379
|
-
client_replicator.entity_set_unreliable(client, entity, component, value, unreliable_hooks)
|
|
1380
|
-
end
|
|
1381
|
-
else
|
|
1382
|
-
-- dont apply unreliable updates to entities that dont exist in the client yet
|
|
1383
|
-
-- but we still need to process the values to keep the cursor in the right place
|
|
1384
|
-
for _ = 1, total_unreliable do
|
|
1385
|
-
local component = client_replicator.read_component_id(client, c)
|
|
1386
|
-
client_replicator.read_component_value(client, component, c, variants)
|
|
1387
|
-
end
|
|
1388
|
-
end
|
|
1389
|
-
end
|
|
1390
|
-
end
|
|
1391
|
-
|
|
1392
|
-
client_replicator.finish_replication(client)
|
|
1393
|
-
end
|
|
1394
|
-
|
|
1395
|
-
function client_replicator.set_serdes(client: Client, component: Component, serdes: types.Serdes)
|
|
1396
|
-
client.component_serdes[component] = serdes
|
|
1397
|
-
client.is_shared_dirty = true
|
|
1398
|
-
end
|
|
1399
|
-
|
|
1400
|
-
function client_replicator.remove_serdes(client: Client, component: Component)
|
|
1401
|
-
client.component_serdes[component] = nil
|
|
1402
|
-
client.is_shared_dirty = true
|
|
1403
|
-
end
|
|
1404
|
-
|
|
1405
|
-
-- TODO: Deserialize pairs in client
|
|
1406
|
-
|
|
1407
|
-
function client_replicator.init(client: Client, wrd: World?)
|
|
1408
|
-
if client.inited == true then
|
|
1409
|
-
return warn "attempted to init a client twice"
|
|
1410
|
-
end
|
|
1411
|
-
if client.inited == nil then
|
|
1412
|
-
return warn "attempted to re-init a destroyed client"
|
|
1413
|
-
end
|
|
1414
|
-
client.inited = true :: any
|
|
1415
|
-
|
|
1416
|
-
local world = wrd or client.world
|
|
1417
|
-
client.world = world
|
|
1418
|
-
|
|
1419
|
-
if not world then
|
|
1420
|
-
error "Providing a world is required to start replecs"
|
|
1421
|
-
end
|
|
1422
|
-
|
|
1423
|
-
if not client.components then
|
|
1424
|
-
client.components = utils.create_components(utils.tag_factory(world), utils.component_factory(world))
|
|
1425
|
-
utils.add_component_names(client.components, function(component, name)
|
|
1426
|
-
common.add_name(world, component, name)
|
|
1427
|
-
end)
|
|
1428
|
-
end
|
|
1429
|
-
|
|
1430
|
-
local components = client.components
|
|
1431
|
-
|
|
1432
|
-
local function hook(unhook: () -> ())
|
|
1433
|
-
table.insert(client.hooked, unhook)
|
|
1434
|
-
end
|
|
1435
|
-
|
|
1436
|
-
hook(HOOK_REMOVED(world, components.__alive_tracking__, function(entity)
|
|
1437
|
-
local server_id = client.client_ids[entity]
|
|
1438
|
-
if server_id then
|
|
1439
|
-
client.server_ids[server_id] = nil
|
|
1440
|
-
client.client_ids[entity] = nil
|
|
1441
|
-
end
|
|
1442
|
-
client.network_hooks.deleted[entity] = nil
|
|
1443
|
-
end))
|
|
1444
|
-
|
|
1445
|
-
hook(HOOK_ADDED(world, components.serdes, function(component, _, serdes)
|
|
1446
|
-
client_replicator.set_serdes(client, component, serdes)
|
|
1447
|
-
end))
|
|
1448
|
-
hook(HOOK_CHANGED(world, components.serdes, function(component, _, serdes)
|
|
1449
|
-
client_replicator.set_serdes(client, component, serdes)
|
|
1450
|
-
end))
|
|
1451
|
-
hook(HOOK_REMOVED(world, components.serdes, function(component)
|
|
1452
|
-
client_replicator.remove_serdes(client, component)
|
|
1453
|
-
end))
|
|
1454
|
-
|
|
1455
|
-
for _, component in client.requires_shared_lookup do
|
|
1456
|
-
hook(HOOK_ADDED(world, component, function()
|
|
1457
|
-
client.is_shared_dirty = true
|
|
1458
|
-
end))
|
|
1459
|
-
hook(HOOK_REMOVED(world, component, function()
|
|
1460
|
-
client.is_shared_dirty = true
|
|
1461
|
-
end))
|
|
1462
|
-
end
|
|
1463
|
-
|
|
1464
|
-
QUERY_CURRENT_COMPONENTS(client)
|
|
1465
|
-
|
|
1466
|
-
client.shared = utils.resolved_shared(world, components, client.registered_custom_ids, client.component_serdes)
|
|
1467
|
-
end
|
|
1468
|
-
|
|
1469
|
-
function client_replicator.after_replication(client: Client, callback: () -> ())
|
|
1470
|
-
if client.is_replicating then
|
|
1471
|
-
table.insert(client.after_replication_callbacks, callback)
|
|
1472
|
-
else
|
|
1473
|
-
callback()
|
|
1474
|
-
end
|
|
1475
|
-
end
|
|
1476
|
-
|
|
1477
|
-
function client_replicator.added(client: Client, callback: (entity: Entity) -> ())
|
|
1478
|
-
table.insert(client.addition_hooks, callback)
|
|
1479
|
-
return function()
|
|
1480
|
-
local index = table.find(client.addition_hooks, callback)
|
|
1481
|
-
if index then
|
|
1482
|
-
table.remove(client.addition_hooks, index)
|
|
1483
|
-
end
|
|
1484
|
-
end
|
|
1485
|
-
end
|
|
1486
|
-
|
|
1487
|
-
local function add_hook_entry(client: Client, action: string, ...): ({ overrides: boolean }, () -> ())
|
|
1488
|
-
if action == "changed" or action == "removed" then
|
|
1489
|
-
local relation = select(1, ...) :: Entity
|
|
1490
|
-
local callback = select(2, ...) :: (entity: Entity, id: Component, value: any) -> ()
|
|
1491
|
-
local hooks = action == "changed" and client.network_hooks.changed or client.network_hooks.removed
|
|
1492
|
-
local entries = hooks[relation] :: ChangedHooksEntry
|
|
1493
|
-
|
|
1494
|
-
if not entries then
|
|
1495
|
-
entries = {
|
|
1496
|
-
overrides = false,
|
|
1497
|
-
callbacks = {},
|
|
1498
|
-
}
|
|
1499
|
-
hooks[relation] = entries
|
|
1500
|
-
end
|
|
1501
|
-
table.insert(entries.callbacks, callback)
|
|
1502
|
-
|
|
1503
|
-
local function disconnect()
|
|
1504
|
-
local callbacks = entries.callbacks
|
|
1505
|
-
local index = table.find(callbacks, callback)
|
|
1506
|
-
if index then
|
|
1507
|
-
table.remove(callbacks, index)
|
|
1508
|
-
if #callbacks == 0 then
|
|
1509
|
-
hooks[relation] = nil
|
|
1510
|
-
end
|
|
1511
|
-
end
|
|
1512
|
-
end
|
|
1513
|
-
return entries, disconnect
|
|
1514
|
-
elseif action == "deleted" then
|
|
1515
|
-
local entity = select(1, ...) :: Entity
|
|
1516
|
-
local callback = select(2, ...) :: (entity: Entity) -> ()
|
|
1517
|
-
local hooks = client.network_hooks.deleted
|
|
1518
|
-
local entries = hooks[entity]
|
|
1519
|
-
|
|
1520
|
-
if not entries then
|
|
1521
|
-
entries = {
|
|
1522
|
-
overrides = false,
|
|
1523
|
-
callbacks = {},
|
|
1524
|
-
}
|
|
1525
|
-
hooks[entity] = entries
|
|
1526
|
-
end
|
|
1527
|
-
table.insert(entries.callbacks, callback)
|
|
1528
|
-
|
|
1529
|
-
local function disconnect()
|
|
1530
|
-
local callbacks = entries.callbacks
|
|
1531
|
-
local index = table.find(callbacks, callback)
|
|
1532
|
-
if index then
|
|
1533
|
-
table.remove(callbacks, index)
|
|
1534
|
-
if #callbacks == 0 then
|
|
1535
|
-
hooks[entity] = nil
|
|
1536
|
-
end
|
|
1537
|
-
end
|
|
1538
|
-
end
|
|
1539
|
-
return entries, disconnect
|
|
1540
|
-
else
|
|
1541
|
-
error("invalid hook action: " .. action)
|
|
1542
|
-
end
|
|
1543
|
-
end
|
|
1544
|
-
|
|
1545
|
-
function client_replicator.hook(client: Client, action: string, ...)
|
|
1546
|
-
local entry, disconnect = add_hook_entry(client, action, ...)
|
|
1547
|
-
entry.overrides = false
|
|
1548
|
-
return disconnect
|
|
1549
|
-
end
|
|
1550
|
-
function client_replicator.override(client: Client, action: string, ...)
|
|
1551
|
-
local entry, disconnect = add_hook_entry(client, action, ...)
|
|
1552
|
-
entry.overrides = true
|
|
1553
|
-
return disconnect
|
|
1554
|
-
end
|
|
1555
|
-
|
|
1556
|
-
function client_replicator.encode_component(client: Client, component: Entity): number
|
|
1557
|
-
client_replicator.resolve_dirty(client)
|
|
1558
|
-
local encoded = client.shared.components.members[component]
|
|
1559
|
-
if not encoded then
|
|
1560
|
-
common.log_error(`attempted to encode a non-shared component `, common.log_component(client.world, component))
|
|
1561
|
-
return 0
|
|
1562
|
-
end
|
|
1563
|
-
return encoded
|
|
1564
|
-
end
|
|
1565
|
-
|
|
1566
|
-
function client_replicator.decode_component(client: Client, encoded: number): Entity
|
|
1567
|
-
client_replicator.resolve_dirty(client)
|
|
1568
|
-
local component = client.shared.components.indexes[encoded]
|
|
1569
|
-
if not component then
|
|
1570
|
-
print("NON SHARED COMPONENT", encoded, client.shared.components)
|
|
1571
|
-
error "attemped to decode a non shared component"
|
|
1572
|
-
end
|
|
1573
|
-
return component
|
|
1574
|
-
end
|
|
1575
|
-
|
|
1576
|
-
function client_replicator.get_shared_count(client: Client): number
|
|
1577
|
-
client_replicator.resolve_dirty(client)
|
|
1578
|
-
return #client.shared.components.keys
|
|
1579
|
-
end
|
|
1580
|
-
|
|
1581
|
-
function client_replicator.get_server_entity(client: Client, client_entity: Entity): number?
|
|
1582
|
-
return client.client_ids[client_entity]
|
|
1583
|
-
end
|
|
1584
|
-
|
|
1585
|
-
function client_replicator.get_client_entity(client: Client, client_entity: number): Entity?
|
|
1586
|
-
return client.server_ids[client_entity]
|
|
1587
|
-
end
|
|
1588
|
-
|
|
1589
|
-
function client_replicator.register_entity(client: Client, entity: Entity, server_entity: number)
|
|
1590
|
-
client.server_ids[server_entity] = entity
|
|
1591
|
-
client.client_ids[entity] = server_entity
|
|
1592
|
-
WORLD_ADD(client.world, entity, client.components.__alive_tracking__)
|
|
1593
|
-
end
|
|
1594
|
-
|
|
1595
|
-
function client_replicator.unregister_entity(client: Client, entity: Entity)
|
|
1596
|
-
local server_id = client.client_ids[entity]
|
|
1597
|
-
if server_id then
|
|
1598
|
-
client.server_ids[server_id] = nil
|
|
1599
|
-
client.client_ids[entity] = nil
|
|
1600
|
-
end
|
|
1601
|
-
end
|
|
1602
|
-
|
|
1603
|
-
function client_replicator.register_custom_id(client: Client, custom_id: CustomId)
|
|
1604
|
-
client.registered_custom_ids[custom_id] = true
|
|
1605
|
-
client.is_shared_dirty = true
|
|
1606
|
-
end
|
|
1607
|
-
|
|
1608
|
-
function client_replicator.generate_handshake(client: Client): types.HandshakeInfo
|
|
1609
|
-
client_replicator.resolve_dirty(client)
|
|
1610
|
-
return utils.generate_handshake(client.shared)
|
|
1611
|
-
end
|
|
1612
|
-
|
|
1613
|
-
function client_replicator.verify_handshake(client: Client, handshake: types.HandshakeInfo): (boolean, string?)
|
|
1614
|
-
client_replicator.resolve_dirty(client)
|
|
1615
|
-
return utils.verify_handshake(client.shared, handshake, "server", "client")
|
|
1616
|
-
end
|
|
1617
|
-
|
|
1618
|
-
function client_replicator.destroy(client: Client)
|
|
1619
|
-
if client.inited == nil then
|
|
1620
|
-
return warn "attempted to destroy a client twice"
|
|
1621
|
-
end
|
|
1622
|
-
client.inited = nil :: any
|
|
1623
|
-
for _, unhook in client.hooked do
|
|
1624
|
-
unhook()
|
|
1625
|
-
end
|
|
1626
|
-
end
|
|
1627
|
-
|
|
1628
|
-
function client_replicator.handle_global(client: Client, handler: (id: number) -> Entity)
|
|
1629
|
-
client.global_handler = handler
|
|
1630
|
-
end
|
|
1631
|
-
|
|
1632
|
-
local function create(world: World?, components: types.Components?): Client
|
|
1633
|
-
local self = {} :: Client
|
|
1634
|
-
|
|
1635
|
-
if components then
|
|
1636
|
-
self.components = components
|
|
1637
|
-
elseif world then
|
|
1638
|
-
self.components = utils.create_components(utils.tag_factory(world), utils.component_factory(world))
|
|
1639
|
-
utils.add_component_names(self.components, function(component, name)
|
|
1640
|
-
common.add_name(world, component, name)
|
|
1641
|
-
end)
|
|
1642
|
-
end
|
|
1643
|
-
|
|
1644
|
-
self.server_ids = {}
|
|
1645
|
-
self.client_ids = {}
|
|
1646
|
-
self.is_shared_dirty = false
|
|
1647
|
-
self.component_serdes = {}
|
|
1648
|
-
self.requires_shared_lookup = {
|
|
1649
|
-
self.components.shared,
|
|
1650
|
-
ECS_NAME,
|
|
1651
|
-
}
|
|
1652
|
-
self.global_handler = nil
|
|
1653
|
-
self.world = world :: any
|
|
1654
|
-
self.inited = false
|
|
1655
|
-
self.is_replicating = false
|
|
1656
|
-
self.hooked = {}
|
|
1657
|
-
self.registered_custom_ids = {}
|
|
1658
|
-
|
|
1659
|
-
self.addition_hooks = {}
|
|
1660
|
-
self.network_hooks = {
|
|
1661
|
-
deleted = {},
|
|
1662
|
-
changed = {},
|
|
1663
|
-
removed = {},
|
|
1664
|
-
}
|
|
1665
|
-
self.after_replication_callbacks = {}
|
|
1666
|
-
|
|
1667
|
-
return setmetatable(self, client_replicator) :: any
|
|
1668
|
-
end
|
|
1669
|
-
|
|
1670
|
-
return {
|
|
1671
|
-
create = create,
|
|
1672
|
-
client_replicator = client_replicator,
|
|
1673
|
-
}
|