@rbxts/replecs 0.1.0-alpha9-test5 → 0.2.0-cdtest.1
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.luau +816 -345
- package/out/replecs/common.luau +40 -23
- package/out/replecs/customid.luau +39 -0
- package/out/replecs/index.d.ts +116 -26
- package/out/replecs/init.luau +45 -17
- package/out/replecs/masking/init.luau +40 -35
- package/out/replecs/masking/mask_generator.luau +1 -1
- package/out/replecs/server.luau +547 -280
- package/out/replecs/utils.luau +188 -31
- package/out/replecs/ver.luau +2 -0
- package/package.json +1 -1
- package/out/replecs/masking/filter_group.luau +0 -1
package/out/replecs/client.luau
CHANGED
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
|
|
4
4
|
local jecs = require "../jecs"
|
|
5
5
|
local common = require "./common"
|
|
6
|
+
local customid = require "./customid"
|
|
6
7
|
local utils = require "./utils"
|
|
7
8
|
|
|
8
9
|
local cursor = utils.cursor
|
|
10
|
+
|
|
9
11
|
type Cursor = utils.Cursor
|
|
12
|
+
type CustomId = customid.CustomId
|
|
10
13
|
|
|
11
14
|
type Entity<T = any> = jecs.Entity<T>
|
|
12
15
|
type Id<T = any> = jecs.Id<T>
|
|
@@ -14,24 +17,29 @@ type World = jecs.World
|
|
|
14
17
|
|
|
15
18
|
type Array<T> = { T }
|
|
16
19
|
type Map<K, V> = { [K]: V }
|
|
20
|
+
type Set<T> = { [T]: boolean }
|
|
17
21
|
type Disconnect = () -> ()
|
|
18
22
|
|
|
23
|
+
type CommandBuffer = {
|
|
24
|
+
tags: { [Entity]: boolean },
|
|
25
|
+
components: { [Entity]: { value: any } },
|
|
26
|
+
unreliable_components: { [Entity]: { value: any } },
|
|
27
|
+
remove: { [Entity]: boolean },
|
|
28
|
+
pairs: { [Entity]: Set<Entity> },
|
|
29
|
+
pairs_values: { [Entity]: { [Entity]: { value: any } } },
|
|
30
|
+
pairs_remove: { [Entity]: Set<Entity> },
|
|
31
|
+
pairs_clear: Set<Entity>,
|
|
32
|
+
}
|
|
33
|
+
|
|
19
34
|
type HookMethod =
|
|
20
35
|
& ((
|
|
21
36
|
self: Client,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
relation: Entity,
|
|
37
|
+
action: "changed",
|
|
38
|
+
relation: Id,
|
|
25
39
|
callback: (entity: Entity, id: Id, value: any) -> ()
|
|
26
40
|
) -> Disconnect)
|
|
27
|
-
& ((
|
|
28
|
-
|
|
29
|
-
entity: Entity,
|
|
30
|
-
action: "removed",
|
|
31
|
-
relation: Entity,
|
|
32
|
-
callback: (entity: Entity, id: Id) -> ()
|
|
33
|
-
) -> Disconnect)
|
|
34
|
-
& (self: Client, entity: Entity, action: "deleted", callback: (entity: Entity) -> ()) -> Disconnect
|
|
41
|
+
& ((self: Client, action: "removed", relation: Id, callback: (entity: Entity, id: Id) -> ()) -> Disconnect)
|
|
42
|
+
& (self: Client, action: "deleted", entity: Entity, callback: (entity: Entity) -> ()) -> Disconnect
|
|
35
43
|
|
|
36
44
|
type ChangedHooksEntry = {
|
|
37
45
|
overrides: boolean,
|
|
@@ -46,6 +54,8 @@ type DeletedHookEntry = {
|
|
|
46
54
|
callbacks: Array<(entity: Entity) -> ()>,
|
|
47
55
|
}
|
|
48
56
|
|
|
57
|
+
type CustomIdMap = { [Entity]: CustomId | Entity }
|
|
58
|
+
|
|
49
59
|
export type Client = {
|
|
50
60
|
world: World,
|
|
51
61
|
inited: boolean?,
|
|
@@ -53,7 +63,7 @@ export type Client = {
|
|
|
53
63
|
is_replicating: boolean,
|
|
54
64
|
after_replication_callbacks: { () -> () },
|
|
55
65
|
|
|
56
|
-
|
|
66
|
+
is_shared_dirty: boolean,
|
|
57
67
|
requires_shared_lookup: { Entity },
|
|
58
68
|
components: common.Components,
|
|
59
69
|
shared: common.Shared,
|
|
@@ -61,7 +71,9 @@ export type Client = {
|
|
|
61
71
|
server_ids: { [number]: Entity },
|
|
62
72
|
client_ids: { [Entity]: number },
|
|
63
73
|
ordered_creation: boolean,
|
|
64
|
-
|
|
74
|
+
registered_custom_ids: { [CustomId]: boolean },
|
|
75
|
+
command_buffers: { [Entity]: CommandBuffer }?,
|
|
76
|
+
command_buffers_active: boolean,
|
|
65
77
|
|
|
66
78
|
init: (self: Client, world: World?) -> (),
|
|
67
79
|
destroy: (self: Client) -> (),
|
|
@@ -69,6 +81,9 @@ export type Client = {
|
|
|
69
81
|
get_server_entity: (self: Client, client_entity: Entity) -> number?,
|
|
70
82
|
get_client_entity: (self: Client, server_entity: number) -> Entity?,
|
|
71
83
|
|
|
84
|
+
register_entity: (self: Client, entity: Entity, server_entity: number) -> (),
|
|
85
|
+
unregister_entity: (self: Client, entity: Entity) -> (),
|
|
86
|
+
|
|
72
87
|
hooks: common.WorldHooks,
|
|
73
88
|
hooked: Array<() -> ()>,
|
|
74
89
|
|
|
@@ -77,27 +92,34 @@ export type Client = {
|
|
|
77
92
|
hook: HookMethod,
|
|
78
93
|
override: HookMethod,
|
|
79
94
|
addition_hooks: Array<(entity: Entity) -> ()>,
|
|
80
|
-
|
|
81
|
-
[Entity]:
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
deleted: DeletedHookEntry?,
|
|
85
|
-
},
|
|
95
|
+
network_hooks: {
|
|
96
|
+
deleted: { [Entity]: DeletedHookEntry },
|
|
97
|
+
changed: { [Id]: ChangedHooksEntry },
|
|
98
|
+
removed: { [Id]: RemovedHooksEntry },
|
|
86
99
|
},
|
|
87
100
|
|
|
88
101
|
encode_component: (self: Client, component: Entity) -> number,
|
|
89
102
|
decode_component: (self: Client, component: number) -> Entity,
|
|
103
|
+
register_custom_id: (self: Client, custom_id: CustomId) -> (),
|
|
90
104
|
|
|
91
105
|
apply_updates: (self: Client, buf: buffer, all_variants: { { any } }?) -> (),
|
|
92
106
|
apply_unreliable: (self: Client, buf: buffer, all_variants: { { any } }?) -> (),
|
|
93
107
|
apply_full: (self: Client, buf: buffer, all_variants: { { any } }?) -> (),
|
|
108
|
+
|
|
109
|
+
generate_handshake: (self: Client) -> common.HandshakeInfo,
|
|
110
|
+
verify_handshake: (self: Client, handshake: common.HandshakeInfo) -> (boolean, string?),
|
|
94
111
|
}
|
|
95
112
|
|
|
113
|
+
local client_replicator = {}
|
|
114
|
+
client_replicator.__index = client_replicator
|
|
115
|
+
|
|
96
116
|
local GLOBAL_ID_OFFSET = 10
|
|
117
|
+
|
|
97
118
|
local ENTITY_ID_TYPES = {
|
|
98
119
|
entity = 1,
|
|
99
|
-
|
|
100
|
-
|
|
120
|
+
custom_handler = 2,
|
|
121
|
+
custom_id = 3,
|
|
122
|
+
shared = 4,
|
|
101
123
|
}
|
|
102
124
|
local PACKET_TYPES = {
|
|
103
125
|
full = 1,
|
|
@@ -105,7 +127,6 @@ local PACKET_TYPES = {
|
|
|
105
127
|
reliable = 3,
|
|
106
128
|
}
|
|
107
129
|
|
|
108
|
-
local ECS_NAME = jecs.Name
|
|
109
130
|
local WILDCARD = jecs.Wildcard
|
|
110
131
|
|
|
111
132
|
local function PAIR(first: Entity, second: Entity): Entity
|
|
@@ -131,20 +152,97 @@ local function get_or_create_entity(client: Client, server_id: number): Entity
|
|
|
131
152
|
end
|
|
132
153
|
end
|
|
133
154
|
|
|
134
|
-
local function
|
|
135
|
-
|
|
136
|
-
|
|
155
|
+
local function get_command_buffer(client: Client, entity: Entity): CommandBuffer
|
|
156
|
+
local command_buffers = client.command_buffers
|
|
157
|
+
|
|
158
|
+
if not command_buffers then
|
|
159
|
+
error "attempted to use a command buffer without having one. (this should never happen)"
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
local command_buffer = command_buffers[entity :: any]
|
|
163
|
+
if not command_buffer then
|
|
164
|
+
command_buffer = {
|
|
165
|
+
tags = {},
|
|
166
|
+
components = {},
|
|
167
|
+
unreliable_components = {},
|
|
168
|
+
remove = {},
|
|
169
|
+
pairs = {},
|
|
170
|
+
pairs_values = {},
|
|
171
|
+
pairs_remove = {},
|
|
172
|
+
pairs_clear = {},
|
|
173
|
+
}
|
|
174
|
+
command_buffers[entity :: any] = command_buffer
|
|
175
|
+
end
|
|
176
|
+
return command_buffer
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
function client_replicator.entity_set(
|
|
180
|
+
client: Client,
|
|
181
|
+
entity: Entity,
|
|
182
|
+
id: Id,
|
|
183
|
+
value: any,
|
|
184
|
+
changed_hooks: ChangedHooksEntry?
|
|
185
|
+
)
|
|
186
|
+
if client.command_buffers_active then
|
|
187
|
+
local command_buffer = get_command_buffer(client, entity)
|
|
188
|
+
command_buffer.components[id] = { value = value }
|
|
189
|
+
else
|
|
190
|
+
if changed_hooks then
|
|
191
|
+
if not changed_hooks.overrides then
|
|
192
|
+
client.world:set(entity, id, value)
|
|
193
|
+
end
|
|
194
|
+
for _, callback in changed_hooks.callbacks do
|
|
195
|
+
callback(entity, id, value)
|
|
196
|
+
end
|
|
197
|
+
else
|
|
137
198
|
client.world:set(entity, id, value)
|
|
138
199
|
end
|
|
139
|
-
|
|
140
|
-
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
function client_replicator.entity_set_unreliable(
|
|
204
|
+
client: Client,
|
|
205
|
+
entity: Entity,
|
|
206
|
+
component: Entity,
|
|
207
|
+
value: any,
|
|
208
|
+
changed_hooks: ChangedHooksEntry?
|
|
209
|
+
)
|
|
210
|
+
if client.command_buffers_active then
|
|
211
|
+
local command_buffer = get_command_buffer(client, entity)
|
|
212
|
+
command_buffer.unreliable_components[component] = value
|
|
213
|
+
else
|
|
214
|
+
client_replicator.entity_set(client, entity, component, value, changed_hooks)
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
function client_replicator.entity_set_pair(
|
|
219
|
+
client: Client,
|
|
220
|
+
entity: Entity,
|
|
221
|
+
relation: Entity,
|
|
222
|
+
target: Entity,
|
|
223
|
+
value: any,
|
|
224
|
+
changed_hooks: ChangedHooksEntry?
|
|
225
|
+
)
|
|
226
|
+
if client.command_buffers_active then
|
|
227
|
+
local command_buffer = get_command_buffer(client, entity)
|
|
228
|
+
local pair_relation = command_buffer.pairs_values[relation]
|
|
229
|
+
|
|
230
|
+
if pair_relation then
|
|
231
|
+
pair_relation[target] = { value = value }
|
|
232
|
+
else
|
|
233
|
+
command_buffer.pairs_values[relation] = { [target] = value }
|
|
141
234
|
end
|
|
142
235
|
else
|
|
143
|
-
|
|
236
|
+
client_replicator.entity_set(client, entity, PAIR(relation, target), value, changed_hooks)
|
|
144
237
|
end
|
|
145
238
|
end
|
|
146
239
|
|
|
147
|
-
|
|
240
|
+
function client_replicator.entity_add(
|
|
241
|
+
client: Client,
|
|
242
|
+
entity: Entity,
|
|
243
|
+
component: Entity,
|
|
244
|
+
changed_hooks: ChangedHooksEntry?
|
|
245
|
+
)
|
|
148
246
|
if changed_hooks then
|
|
149
247
|
if not changed_hooks.overrides then
|
|
150
248
|
client.world:add(entity, component)
|
|
@@ -157,77 +255,129 @@ local function network_entity_add(client: Client, entity: Entity, component: Ent
|
|
|
157
255
|
end
|
|
158
256
|
end
|
|
159
257
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
258
|
+
function client_replicator.entity_add_pair(
|
|
259
|
+
client: Client,
|
|
260
|
+
entity: Entity,
|
|
261
|
+
relation: Entity,
|
|
262
|
+
target: Entity,
|
|
263
|
+
changed_hooks: ChangedHooksEntry?
|
|
264
|
+
)
|
|
265
|
+
if client.command_buffers_active then
|
|
266
|
+
local command_buffer = get_command_buffer(client, entity)
|
|
267
|
+
local pair_relation = command_buffer.pairs[relation]
|
|
268
|
+
|
|
269
|
+
if pair_relation then
|
|
270
|
+
pair_relation[target] = true
|
|
271
|
+
else
|
|
272
|
+
command_buffer.pairs[relation] = { [target] = true }
|
|
164
273
|
end
|
|
165
|
-
|
|
274
|
+
else
|
|
275
|
+
client_replicator.entity_add(client, entity, PAIR(relation, target), changed_hooks)
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
function client_replicator.entity_remove(client: Client, entity: Entity, id: Entity, removed_hooks: RemovedHooksEntry?)
|
|
280
|
+
if client.command_buffers_active then
|
|
281
|
+
local command_buffer = get_command_buffer(client, entity)
|
|
282
|
+
command_buffer.remove[id] = true
|
|
283
|
+
else
|
|
284
|
+
if removed_hooks then
|
|
285
|
+
for _, callback in removed_hooks.callbacks do
|
|
286
|
+
callback(entity, id)
|
|
287
|
+
end
|
|
288
|
+
if not removed_hooks.overrides then
|
|
289
|
+
client.world:remove(entity, id)
|
|
290
|
+
end
|
|
291
|
+
else
|
|
166
292
|
client.world:remove(entity, id)
|
|
167
293
|
end
|
|
168
|
-
else
|
|
169
|
-
client.world:remove(entity, id)
|
|
170
294
|
end
|
|
171
295
|
end
|
|
172
296
|
|
|
173
|
-
|
|
297
|
+
function client_replicator.entity_remove_pair(
|
|
174
298
|
client: Client,
|
|
175
299
|
entity: Entity,
|
|
176
300
|
relation: Entity,
|
|
301
|
+
target: Entity,
|
|
177
302
|
removed_hooks: RemovedHooksEntry?
|
|
178
303
|
)
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
304
|
+
if client.command_buffers_active then
|
|
305
|
+
local command_buffer = get_command_buffer(client, entity)
|
|
306
|
+
local pair_relation = command_buffer.pairs_remove[relation]
|
|
307
|
+
|
|
308
|
+
if pair_relation then
|
|
309
|
+
pair_relation[target] = true
|
|
310
|
+
else
|
|
311
|
+
command_buffer.pairs_remove[relation] = { [target] = true }
|
|
312
|
+
end
|
|
313
|
+
else
|
|
314
|
+
client_replicator.entity_remove(client, entity, PAIR(relation, target), removed_hooks)
|
|
183
315
|
end
|
|
184
|
-
|
|
316
|
+
end
|
|
185
317
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
318
|
+
function client_replicator.entity_remove_relations(
|
|
319
|
+
client: Client,
|
|
320
|
+
entity: Entity,
|
|
321
|
+
relation: Entity,
|
|
322
|
+
removed_hooks: RemovedHooksEntry?
|
|
323
|
+
)
|
|
324
|
+
if client.command_buffers_active then
|
|
325
|
+
local command_buffer = get_command_buffer(client, entity)
|
|
326
|
+
command_buffer.pairs_clear[relation] = true
|
|
327
|
+
else
|
|
328
|
+
local world = client.world
|
|
329
|
+
local entity_index = jecs.entity_index_try_get_fast(world.entity_index :: any, entity :: any)
|
|
330
|
+
if not entity_index then
|
|
331
|
+
return
|
|
332
|
+
end
|
|
333
|
+
local archetype = entity_index.archetype
|
|
191
334
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
335
|
+
local wildcard = PAIR(relation, WILDCARD) :: any
|
|
336
|
+
local idr = world.component_index[wildcard]
|
|
337
|
+
if not idr then
|
|
338
|
+
return
|
|
339
|
+
end
|
|
197
340
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
341
|
+
local archetype_id = archetype.id
|
|
342
|
+
local count = idr.counts[archetype_id]
|
|
343
|
+
if not count then
|
|
344
|
+
return
|
|
345
|
+
end
|
|
202
346
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
347
|
+
local start = idr.records[archetype_id]
|
|
348
|
+
if not start then
|
|
349
|
+
return
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
if removed_hooks then
|
|
353
|
+
for i = start, start + count - 1 do
|
|
354
|
+
local pair = archetype.types[i]
|
|
355
|
+
for _, callback in removed_hooks.callbacks do
|
|
356
|
+
callback(entity, pair)
|
|
357
|
+
end
|
|
358
|
+
if not removed_hooks.overrides then
|
|
359
|
+
world:remove(entity, pair :: any)
|
|
360
|
+
end
|
|
208
361
|
end
|
|
209
|
-
|
|
362
|
+
else
|
|
363
|
+
for i = start, start + count - 1 do
|
|
364
|
+
local pair = archetype.types[i]
|
|
210
365
|
world:remove(entity, pair :: any)
|
|
211
366
|
end
|
|
212
367
|
end
|
|
213
|
-
else
|
|
214
|
-
for i = start, start + count - 1 do
|
|
215
|
-
local pair = archetype.types[i]
|
|
216
|
-
world:remove(entity, pair :: any)
|
|
217
|
-
end
|
|
218
368
|
end
|
|
219
369
|
end
|
|
220
370
|
|
|
221
|
-
|
|
222
|
-
local encoded = client.shared.
|
|
371
|
+
function client_replicator.encode_component(client: Client, component: Entity): number
|
|
372
|
+
local encoded = client.shared.components.members[component]
|
|
223
373
|
if not encoded then
|
|
224
374
|
utils.logerror(`attempted to encode a non-shared component `, utils.logcomponent(client.world, component))
|
|
225
375
|
return 0
|
|
226
376
|
end
|
|
227
377
|
return encoded
|
|
228
378
|
end
|
|
229
|
-
|
|
230
|
-
local component = client.shared.components[encoded]
|
|
379
|
+
function client_replicator.decode_component(client: Client, encoded: number): Entity
|
|
380
|
+
local component = client.shared.components.indexes[encoded]
|
|
231
381
|
if not component then
|
|
232
382
|
print("NON SHARED COMPONENT", encoded, client.shared.components)
|
|
233
383
|
error "attemped to decode a non shared component"
|
|
@@ -235,9 +385,10 @@ local function decode_component(client: Client, encoded: number): Entity
|
|
|
235
385
|
return component
|
|
236
386
|
end
|
|
237
387
|
|
|
238
|
-
|
|
239
|
-
local
|
|
240
|
-
local
|
|
388
|
+
function client_replicator.read_component_id(client: Client, c: Cursor): Entity
|
|
389
|
+
local shared_components = client.shared.components
|
|
390
|
+
local shared_id = cursor.read_span(c, #shared_components.keys)
|
|
391
|
+
local component = shared_components.indexes[shared_id]
|
|
241
392
|
if not component then
|
|
242
393
|
print("NON SHARED COMPONENT", shared_id, client.shared.components)
|
|
243
394
|
error "received a non shared component"
|
|
@@ -245,11 +396,11 @@ local function read_component_id(client: Client, c: Cursor): Entity
|
|
|
245
396
|
return component
|
|
246
397
|
end
|
|
247
398
|
|
|
248
|
-
|
|
399
|
+
function client_replicator.read_component_value(client: Client, component: Entity, c: Cursor, variants: { any }?): any
|
|
249
400
|
local serdes = client.shared.serdes[component]
|
|
250
401
|
|
|
251
402
|
if serdes then
|
|
252
|
-
local bytespan =
|
|
403
|
+
local bytespan = serdes.bytespan or cursor.read_vlq(c)
|
|
253
404
|
|
|
254
405
|
local appended = cursor.read_buffer(c, bytespan)
|
|
255
406
|
local serdes_variants: { any }? = nil
|
|
@@ -275,13 +426,13 @@ local function read_component_value(client: Client, component: Entity, c: Cursor
|
|
|
275
426
|
end
|
|
276
427
|
end
|
|
277
428
|
|
|
278
|
-
|
|
279
|
-
local component = read_component_id(client, c)
|
|
280
|
-
local value = read_component_value(client, component, c, variants)
|
|
429
|
+
function client_replicator.read_component(client: Client, c: Cursor, variants: { any }?): (Entity, any)
|
|
430
|
+
local component = client_replicator.read_component_id(client, c)
|
|
431
|
+
local value = client_replicator.read_component_value(client, component, c, variants)
|
|
281
432
|
return component, value
|
|
282
433
|
end
|
|
283
434
|
|
|
284
|
-
|
|
435
|
+
function client_replicator.resolve_global(client: Client, global_id: number): Entity
|
|
285
436
|
if not client.global_handler then
|
|
286
437
|
error "global id parser not set, consider using client:handle_global()"
|
|
287
438
|
end
|
|
@@ -289,112 +440,145 @@ local function resolve_global(client: Client, global_id: number): Entity
|
|
|
289
440
|
return parsed
|
|
290
441
|
end
|
|
291
442
|
|
|
292
|
-
|
|
443
|
+
-- returns entity, server_id, id_type
|
|
444
|
+
function client_replicator.read_entity_id(client: Client, c: Cursor): (Entity?, number?, number?)
|
|
293
445
|
local id_type = cursor.readu8(c)
|
|
294
446
|
|
|
295
447
|
if id_type <= GLOBAL_ID_OFFSET then
|
|
296
|
-
if
|
|
448
|
+
if
|
|
449
|
+
id_type == ENTITY_ID_TYPES.entity
|
|
450
|
+
or id_type == ENTITY_ID_TYPES.custom_id
|
|
451
|
+
or id_type == ENTITY_ID_TYPES.custom_handler
|
|
452
|
+
then
|
|
297
453
|
local server_id = cursor.readu40(c)
|
|
298
|
-
return client.server_ids[server_id], server_id
|
|
299
|
-
elseif id_type == ENTITY_ID_TYPES.custom then
|
|
300
|
-
local component, value = read_component(client, c, variants)
|
|
301
|
-
local custom_getter = client.custom_ids[component]
|
|
302
|
-
if not custom_getter then
|
|
303
|
-
error(
|
|
304
|
-
`received a custom id for a non custom component, consider adding custom_id to component: {client.world:get(
|
|
305
|
-
component,
|
|
306
|
-
ECS_NAME
|
|
307
|
-
) or "(no name)"} id: {component}`
|
|
308
|
-
)
|
|
309
|
-
end
|
|
310
|
-
return custom_getter(value), nil
|
|
454
|
+
return client.server_ids[server_id], server_id, id_type
|
|
311
455
|
elseif id_type == ENTITY_ID_TYPES.shared then
|
|
312
|
-
return read_component_id(client, c), nil
|
|
456
|
+
return client_replicator.read_component_id(client, c), nil, id_type
|
|
313
457
|
end
|
|
314
|
-
error(`malformed entity
|
|
458
|
+
error(`malformed entity type {id_type} ` .. cursor.readu32(c))
|
|
315
459
|
else
|
|
316
|
-
return resolve_global(client, id_type - GLOBAL_ID_OFFSET), nil
|
|
460
|
+
return client_replicator.resolve_global(client, id_type - GLOBAL_ID_OFFSET), nil, id_type
|
|
317
461
|
end
|
|
318
462
|
end
|
|
319
463
|
|
|
320
|
-
|
|
321
|
-
|
|
464
|
+
function client_replicator.process_entity_id(
|
|
465
|
+
client: Client,
|
|
466
|
+
c: Cursor,
|
|
467
|
+
custom_ids: CustomIdMap,
|
|
468
|
+
process: (entity: Entity) -> ()
|
|
469
|
+
)
|
|
470
|
+
local entity, server_id, id_type = client_replicator.read_entity_id(client, c)
|
|
471
|
+
|
|
322
472
|
if entity then
|
|
323
|
-
|
|
473
|
+
-- skip customid, keep cursor offset
|
|
474
|
+
if id_type == ENTITY_ID_TYPES.custom_id then
|
|
475
|
+
client_replicator.read_component_id(client, c)
|
|
476
|
+
elseif id_type == ENTITY_ID_TYPES.custom_handler then
|
|
477
|
+
cursor.readu8(c)
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
return process(entity)
|
|
324
481
|
else
|
|
325
|
-
|
|
482
|
+
if id_type == ENTITY_ID_TYPES.custom_id or id_type == ENTITY_ID_TYPES.custom_handler then
|
|
483
|
+
if id_type == ENTITY_ID_TYPES.custom_id then
|
|
484
|
+
local component_id = client_replicator.read_component_id(client, c)
|
|
485
|
+
custom_ids[server_id :: any] = component_id
|
|
486
|
+
elseif id_type == ENTITY_ID_TYPES.custom_handler then
|
|
487
|
+
local shared_custom_id = cursor.readu8(c)
|
|
488
|
+
local handler = client.shared.custom_ids.indexes[shared_custom_id]
|
|
489
|
+
|
|
490
|
+
if not handler then
|
|
491
|
+
utils.logerror "attempted to use a custom id that wasn't registered"
|
|
492
|
+
end
|
|
493
|
+
custom_ids[server_id :: any] = handler
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
if client.command_buffers_active then
|
|
497
|
+
-- negative id means it's a custom id,
|
|
498
|
+
-- it needs to be translated first
|
|
499
|
+
process(-server_id :: any)
|
|
500
|
+
else
|
|
501
|
+
client.command_buffers_active = true
|
|
502
|
+
process(-server_id :: any)
|
|
503
|
+
client.command_buffers_active = false
|
|
504
|
+
end
|
|
505
|
+
else
|
|
506
|
+
local new_entity = get_or_create_entity(client, server_id :: number)
|
|
507
|
+
process(new_entity)
|
|
508
|
+
end
|
|
326
509
|
end
|
|
327
510
|
end
|
|
328
511
|
|
|
329
|
-
|
|
512
|
+
function client_replicator.process_entity_relations(
|
|
330
513
|
client: Client,
|
|
331
514
|
entity: jecs.Entity,
|
|
332
|
-
changed_hooks: Map<Entity, ChangedHooksEntry>?,
|
|
333
515
|
c: Cursor,
|
|
334
|
-
|
|
516
|
+
custom_ids: CustomIdMap
|
|
335
517
|
)
|
|
336
518
|
local components = client.components
|
|
337
|
-
local relation = read_component_id(client, c)
|
|
519
|
+
local relation = client_replicator.read_component_id(client, c)
|
|
338
520
|
local total_targets = cursor.read_vlq(c)
|
|
339
|
-
local pair_hooks =
|
|
521
|
+
local pair_hooks = client.network_hooks.changed[PAIR(components.pair, relation)]
|
|
340
522
|
|
|
341
523
|
for _ = 1, total_targets do
|
|
342
|
-
|
|
343
|
-
|
|
524
|
+
client_replicator.process_entity_id(client, c, custom_ids, function(target)
|
|
525
|
+
client_replicator.entity_add_pair(client, entity, relation, target, pair_hooks)
|
|
526
|
+
end)
|
|
344
527
|
end
|
|
345
528
|
end
|
|
346
529
|
|
|
347
|
-
|
|
530
|
+
function client_replicator.process_entity_relation_values(
|
|
348
531
|
client: Client,
|
|
349
532
|
entity: jecs.Entity,
|
|
350
|
-
changed_hooks: Map<Entity, ChangedHooksEntry>?,
|
|
351
533
|
c: Cursor,
|
|
534
|
+
custom_ids: CustomIdMap,
|
|
352
535
|
variants: { any }?
|
|
353
536
|
)
|
|
354
|
-
local relation = read_component_id(client, c)
|
|
537
|
+
local relation = client_replicator.read_component_id(client, c)
|
|
355
538
|
local total_targets = cursor.read_vlq(c)
|
|
356
539
|
local components = client.components
|
|
357
|
-
local pair_hooks =
|
|
540
|
+
local pair_hooks = client.network_hooks.changed[PAIR(components.pair, relation)]
|
|
358
541
|
|
|
359
542
|
for _ = 1, total_targets do
|
|
360
|
-
local value = read_component_value(client, relation, c, variants)
|
|
361
|
-
|
|
362
|
-
|
|
543
|
+
local value = client_replicator.read_component_value(client, relation, c, variants)
|
|
544
|
+
client_replicator.process_entity_id(client, c, custom_ids, function(target)
|
|
545
|
+
client_replicator.entity_set_pair(client, entity, relation, target, value, pair_hooks)
|
|
546
|
+
end)
|
|
363
547
|
end
|
|
364
548
|
end
|
|
365
549
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
local components = client.components
|
|
550
|
+
function client_replicator.process_entity(client: Client, c: Cursor, custom_ids: CustomIdMap, variants: { any }?)
|
|
551
|
+
client_replicator.process_entity_id(client, c, custom_ids, function(entity)
|
|
552
|
+
local changed_hooks = client.network_hooks.changed
|
|
553
|
+
local components = client.components
|
|
371
554
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
555
|
+
local total_tags = cursor.read_vlq(c)
|
|
556
|
+
for _ = 1, total_tags do
|
|
557
|
+
local tag = client_replicator.read_component_id(client, c)
|
|
558
|
+
local tag_hooks = changed_hooks[PAIR(components.reliable, tag)]
|
|
559
|
+
client_replicator.entity_add(client, entity, tag, tag_hooks)
|
|
560
|
+
end
|
|
378
561
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
562
|
+
local total_components = cursor.read_vlq(c)
|
|
563
|
+
for _ = 1, total_components do
|
|
564
|
+
local component, value = client_replicator.read_component(client, c, variants)
|
|
565
|
+
local component_hooks = changed_hooks[PAIR(components.reliable, component)]
|
|
566
|
+
client_replicator.entity_set(client, entity, component, value, component_hooks)
|
|
567
|
+
end
|
|
385
568
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
569
|
+
local total_pairs = cursor.read_vlq(c)
|
|
570
|
+
for _ = 1, total_pairs do
|
|
571
|
+
client_replicator.process_entity_relations(client, entity, c, custom_ids)
|
|
572
|
+
end
|
|
390
573
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
574
|
+
local total_pairs_values = cursor.read_vlq(c)
|
|
575
|
+
for _ = 1, total_pairs_values do
|
|
576
|
+
client_replicator.process_entity_relation_values(client, entity, c, custom_ids, variants)
|
|
577
|
+
end
|
|
578
|
+
end)
|
|
395
579
|
end
|
|
396
580
|
|
|
397
|
-
|
|
581
|
+
function client_replicator.finish_replication(client: Client)
|
|
398
582
|
client.is_replicating = false
|
|
399
583
|
for _, callback in client.after_replication_callbacks do
|
|
400
584
|
callback()
|
|
@@ -402,10 +586,10 @@ local function finish_replication(client: Client)
|
|
|
402
586
|
table.clear(client.after_replication_callbacks)
|
|
403
587
|
end
|
|
404
588
|
|
|
405
|
-
|
|
406
|
-
if client.
|
|
407
|
-
client.shared = utils.
|
|
408
|
-
client.
|
|
589
|
+
function client_replicator.resolve_dirty(client: Client)
|
|
590
|
+
if client.is_shared_dirty then
|
|
591
|
+
client.shared = utils.resolved_shared(client.world, client.components, client.registered_custom_ids)
|
|
592
|
+
client.is_shared_dirty = false :: true -- wtf
|
|
409
593
|
end
|
|
410
594
|
end
|
|
411
595
|
|
|
@@ -433,15 +617,300 @@ local function read_vlq_bitmask(c: Cursor, mask: number, bit: number): number
|
|
|
433
617
|
end
|
|
434
618
|
end
|
|
435
619
|
|
|
436
|
-
|
|
620
|
+
function client_replicator.apply_command_buffer(
|
|
621
|
+
client: Client,
|
|
622
|
+
entity: Entity,
|
|
623
|
+
command_buffer: CommandBuffer,
|
|
624
|
+
request: (e: Entity, ...any) -> Entity?
|
|
625
|
+
)
|
|
626
|
+
local components = client.components
|
|
627
|
+
|
|
628
|
+
for tag in command_buffer.tags do
|
|
629
|
+
local tag_hooks = client.network_hooks.changed[PAIR(components.reliable, tag)]
|
|
630
|
+
client_replicator.entity_add(client, entity, tag, tag_hooks)
|
|
631
|
+
end
|
|
632
|
+
for component, value in command_buffer.components do
|
|
633
|
+
local component_hooks = client.network_hooks.changed[PAIR(components.reliable, component)]
|
|
634
|
+
client_replicator.entity_set(client, entity, component, value, component_hooks)
|
|
635
|
+
end
|
|
636
|
+
for component, value in command_buffer.unreliable_components do
|
|
637
|
+
local component_hooks = client.network_hooks.changed[PAIR(components.unreliable, component)]
|
|
638
|
+
client_replicator.entity_set(client, entity, component, value, component_hooks)
|
|
639
|
+
end
|
|
640
|
+
for component in command_buffer.remove do
|
|
641
|
+
local component_hooks = client.network_hooks.removed[PAIR(components.reliable, component)]
|
|
642
|
+
client_replicator.entity_remove(client, entity, component, component_hooks)
|
|
643
|
+
end
|
|
644
|
+
for relation, targets in command_buffer.pairs do
|
|
645
|
+
local pair_hooks = client.network_hooks.changed[PAIR(components.pair, relation)]
|
|
646
|
+
for target in targets do
|
|
647
|
+
local client_target = request(target)
|
|
648
|
+
if client_target then
|
|
649
|
+
client_replicator.entity_add_pair(client, entity, relation, client_target, pair_hooks)
|
|
650
|
+
end
|
|
651
|
+
end
|
|
652
|
+
end
|
|
653
|
+
for relation, targets in command_buffer.pairs_values do
|
|
654
|
+
local pair_hooks = client.network_hooks.changed[PAIR(components.pair, relation)]
|
|
655
|
+
for target, value in targets do
|
|
656
|
+
local client_target = request(target)
|
|
657
|
+
if client_target then
|
|
658
|
+
client_replicator.entity_set_pair(client, entity, relation, client_target, value.value, pair_hooks)
|
|
659
|
+
end
|
|
660
|
+
end
|
|
661
|
+
end
|
|
662
|
+
for relation, targets in command_buffer.pairs_remove do
|
|
663
|
+
local pair_hooks = client.network_hooks.removed[PAIR(components.pair, relation)]
|
|
664
|
+
for target in targets do
|
|
665
|
+
local client_target = request(target)
|
|
666
|
+
if client_target then
|
|
667
|
+
client_replicator.entity_remove_pair(client, entity, relation, client_target, pair_hooks)
|
|
668
|
+
end
|
|
669
|
+
end
|
|
670
|
+
end
|
|
671
|
+
for relation in command_buffer.pairs_clear do
|
|
672
|
+
local pair_hooks = client.network_hooks.removed[PAIR(components.pair, relation)]
|
|
673
|
+
client_replicator.entity_remove_relations(client, entity, relation, pair_hooks)
|
|
674
|
+
end
|
|
675
|
+
end
|
|
676
|
+
|
|
677
|
+
function client_replicator.find_component_in_buffer(command_buffer: CommandBuffer, component: Entity): { value: any }?
|
|
678
|
+
return command_buffer.components[component] or command_buffer.unreliable_components[component]
|
|
679
|
+
end
|
|
680
|
+
|
|
681
|
+
function client_replicator.find_has_in_buffer(command_buffer: CommandBuffer, tag: Entity): boolean
|
|
682
|
+
return (command_buffer.tags[tag] ~= nil)
|
|
683
|
+
or (command_buffer.components[tag] ~= nil)
|
|
684
|
+
or (command_buffer.unreliable_components[tag] ~= nil)
|
|
685
|
+
end
|
|
686
|
+
function client_replicator.find_pair_in_buffer(
|
|
687
|
+
command_buffer: CommandBuffer,
|
|
688
|
+
relation: Entity,
|
|
689
|
+
target: Entity,
|
|
690
|
+
find: (unprocessed_entity: Entity) -> (Entity?, Entity)
|
|
691
|
+
): (boolean, any)
|
|
692
|
+
local value_relations = command_buffer.pairs_values[relation]
|
|
693
|
+
|
|
694
|
+
if value_relations then
|
|
695
|
+
for unprocessed_target, value in value_relations do
|
|
696
|
+
local found = find(unprocessed_target)
|
|
697
|
+
if found == target then
|
|
698
|
+
return true, value.value
|
|
699
|
+
end
|
|
700
|
+
end
|
|
701
|
+
end
|
|
702
|
+
|
|
703
|
+
local relations = command_buffer.pairs[relation]
|
|
704
|
+
if relations then
|
|
705
|
+
for unprocessed_target in relations do
|
|
706
|
+
local found = find(unprocessed_target)
|
|
707
|
+
if found == target then
|
|
708
|
+
return true, nil
|
|
709
|
+
end
|
|
710
|
+
end
|
|
711
|
+
end
|
|
712
|
+
return false, nil
|
|
713
|
+
end
|
|
714
|
+
|
|
715
|
+
function client_replicator.find_target_in_buffer(
|
|
716
|
+
command_buffer: CommandBuffer,
|
|
717
|
+
relation: Entity,
|
|
718
|
+
index: number?
|
|
719
|
+
): Entity?
|
|
720
|
+
local i = 0
|
|
721
|
+
|
|
722
|
+
local pairs = command_buffer.pairs[relation]
|
|
723
|
+
if pairs then
|
|
724
|
+
for target in pairs do
|
|
725
|
+
if i == (index or 0) then
|
|
726
|
+
return target
|
|
727
|
+
end
|
|
728
|
+
i += 1
|
|
729
|
+
end
|
|
730
|
+
end
|
|
731
|
+
local pairs_values = command_buffer.pairs_values[relation]
|
|
732
|
+
if pairs_values then
|
|
733
|
+
for target in pairs_values do
|
|
734
|
+
if i == (index or 0) then
|
|
735
|
+
return target
|
|
736
|
+
end
|
|
737
|
+
i += 1
|
|
738
|
+
end
|
|
739
|
+
end
|
|
740
|
+
return nil
|
|
741
|
+
end
|
|
742
|
+
|
|
743
|
+
function client_replicator.finish_custom_ids(
|
|
744
|
+
client: Client,
|
|
745
|
+
custom_ids: CustomIdMap,
|
|
746
|
+
command_buffers: { [Entity]: CommandBuffer }
|
|
747
|
+
)
|
|
748
|
+
local funcs = {} -- this is so process can use create_context even if its defined after
|
|
749
|
+
local processed: { [Entity]: boolean } = {}
|
|
750
|
+
|
|
751
|
+
local function find(unprocessed_entity: Entity): (Entity?, Entity)
|
|
752
|
+
-- negative entities means they are still server ids that haven't been processed yet
|
|
753
|
+
if (unprocessed_entity :: any) > 0 then
|
|
754
|
+
return unprocessed_entity, unprocessed_entity
|
|
755
|
+
end
|
|
756
|
+
local server_entity = -(unprocessed_entity :: any)
|
|
757
|
+
local client_entity = client.server_ids[server_entity]
|
|
758
|
+
if client_entity then
|
|
759
|
+
return client_entity, server_entity
|
|
760
|
+
end
|
|
761
|
+
return nil, server_entity
|
|
762
|
+
end
|
|
763
|
+
|
|
764
|
+
local function process(unprocessed_entity: Entity, custom_handler: (CustomId | Entity)?): Entity?
|
|
765
|
+
local client_entity, server_entity = find(unprocessed_entity)
|
|
766
|
+
if client_entity then
|
|
767
|
+
return client_entity
|
|
768
|
+
end
|
|
769
|
+
|
|
770
|
+
if processed[server_entity] then
|
|
771
|
+
return nil
|
|
772
|
+
end
|
|
773
|
+
|
|
774
|
+
local new_entity: Entity? = nil
|
|
775
|
+
local command_buffer = command_buffers[unprocessed_entity :: any]
|
|
776
|
+
custom_handler = custom_handler or custom_ids[server_entity]
|
|
777
|
+
|
|
778
|
+
if type(custom_handler) == "number" then
|
|
779
|
+
local component: Entity = custom_handler :: any
|
|
780
|
+
|
|
781
|
+
local handler = client.world:get(component, client.components.custom_handler)
|
|
782
|
+
if not handler then
|
|
783
|
+
return utils.logerror(
|
|
784
|
+
`received a custom id for a non custom component, consider adding custom_handler to component: {utils.logcomponent(
|
|
785
|
+
client.world,
|
|
786
|
+
component
|
|
787
|
+
)}`
|
|
788
|
+
)
|
|
789
|
+
end
|
|
790
|
+
if command_buffer then
|
|
791
|
+
local value = client_replicator.find_component_in_buffer(command_buffer, component)
|
|
792
|
+
if value then
|
|
793
|
+
new_entity = handler(value.value)
|
|
794
|
+
else
|
|
795
|
+
utils.logwarn(
|
|
796
|
+
`No component found for custom id handler: {utils.logcomponent(client.world, component)}`
|
|
797
|
+
)
|
|
798
|
+
new_entity = handler(nil)
|
|
799
|
+
end
|
|
800
|
+
else
|
|
801
|
+
utils.logwarn(`No component found for custom id handler: {utils.logcomponent(client.world, component)}`)
|
|
802
|
+
new_entity = handler(nil)
|
|
803
|
+
end
|
|
804
|
+
else
|
|
805
|
+
local handle_callback = (custom_handler :: CustomId).handle_callback
|
|
806
|
+
if not handle_callback then
|
|
807
|
+
return utils.logerror(
|
|
808
|
+
"no handler callback was set for custom id:",
|
|
809
|
+
(custom_handler :: CustomId).identifier
|
|
810
|
+
)
|
|
811
|
+
end
|
|
812
|
+
new_entity = handle_callback(funcs.create_context(unprocessed_entity))
|
|
813
|
+
end
|
|
814
|
+
|
|
815
|
+
if new_entity then
|
|
816
|
+
client.server_ids[server_entity :: any] = new_entity
|
|
817
|
+
if command_buffer then
|
|
818
|
+
client_replicator.apply_command_buffer(client, new_entity, command_buffer, process)
|
|
819
|
+
command_buffers[unprocessed_entity] = nil
|
|
820
|
+
end
|
|
821
|
+
end
|
|
822
|
+
|
|
823
|
+
processed[server_entity] = true
|
|
824
|
+
return new_entity
|
|
825
|
+
end
|
|
826
|
+
|
|
827
|
+
local function create_context(unprocessed_entity: Entity)
|
|
828
|
+
local command_buffer = command_buffers[unprocessed_entity]
|
|
829
|
+
|
|
830
|
+
local function component(component: Entity): any
|
|
831
|
+
if not command_buffer then
|
|
832
|
+
return nil
|
|
833
|
+
end
|
|
834
|
+
local val = client_replicator.find_component_in_buffer(command_buffer, component)
|
|
835
|
+
return val and val.value
|
|
836
|
+
end
|
|
837
|
+
local function target(relation: Entity, index: number?): Entity
|
|
838
|
+
if not command_buffer then
|
|
839
|
+
return nil :: any
|
|
840
|
+
end
|
|
841
|
+
local server_target = client_replicator.find_target_in_buffer(command_buffer, relation, index)
|
|
842
|
+
if server_target then
|
|
843
|
+
return process(server_target :: any) :: Entity
|
|
844
|
+
end
|
|
845
|
+
return nil :: any
|
|
846
|
+
end
|
|
847
|
+
local function pair_value(relation: Entity, target: Entity): any
|
|
848
|
+
if not command_buffer then
|
|
849
|
+
return nil :: any
|
|
850
|
+
end
|
|
851
|
+
local _, value = client_replicator.find_pair_in_buffer(command_buffer, relation, target, find)
|
|
852
|
+
return value
|
|
853
|
+
end
|
|
854
|
+
local function has_pair(relation: Entity, target: Entity): boolean
|
|
855
|
+
if not command_buffer then
|
|
856
|
+
return nil :: any
|
|
857
|
+
end
|
|
858
|
+
local has = client_replicator.find_pair_in_buffer(command_buffer, relation, target, find)
|
|
859
|
+
return has
|
|
860
|
+
end
|
|
861
|
+
local function has(tag: Entity): boolean
|
|
862
|
+
if not command_buffer then
|
|
863
|
+
return nil :: any
|
|
864
|
+
end
|
|
865
|
+
return client_replicator.find_has_in_buffer(command_buffer, tag)
|
|
866
|
+
end
|
|
867
|
+
local function entity(server_entity: number): Entity
|
|
868
|
+
return process(-server_entity :: any) :: Entity
|
|
869
|
+
end
|
|
870
|
+
|
|
871
|
+
local context: customid.HandleContext = {
|
|
872
|
+
entity_id = math.abs(unprocessed_entity :: any),
|
|
873
|
+
has = has,
|
|
874
|
+
component = component,
|
|
875
|
+
target = target,
|
|
876
|
+
pair_value = pair_value,
|
|
877
|
+
has_pair = has_pair,
|
|
878
|
+
entity = entity,
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
return context
|
|
882
|
+
end
|
|
883
|
+
funcs.create_context = create_context
|
|
884
|
+
|
|
885
|
+
for entity, custom_handler in custom_ids do
|
|
886
|
+
process(-(entity :: any), custom_handler)
|
|
887
|
+
end
|
|
888
|
+
|
|
889
|
+
for entity, command_buffer in command_buffers do
|
|
890
|
+
if (entity :: any) < 0 then
|
|
891
|
+
continue
|
|
892
|
+
end
|
|
893
|
+
client_replicator.apply_command_buffer(client, entity, command_buffer, process)
|
|
894
|
+
end
|
|
895
|
+
end
|
|
896
|
+
|
|
897
|
+
function client_replicator.apply_updates(client: Client, buf: buffer, all_variants: { { any } }?)
|
|
437
898
|
local c = cursor.from(buf)
|
|
438
899
|
check_packet_type(c, "reliable")
|
|
439
|
-
resolve_dirty(client)
|
|
900
|
+
client_replicator.resolve_dirty(client)
|
|
440
901
|
client.is_replicating = true
|
|
441
902
|
|
|
442
903
|
local components = client.components
|
|
443
904
|
local total_packets = cursor.read_vlq(c)
|
|
444
905
|
local variant_start = (all_variants and #all_variants + 1) :: number
|
|
906
|
+
local changed_hooks = client.network_hooks.changed
|
|
907
|
+
local removed_hooks = client.network_hooks.removed
|
|
908
|
+
local deleted_hooks = client.network_hooks.deleted
|
|
909
|
+
|
|
910
|
+
local command_buffers: { [Entity]: CommandBuffer } = {}
|
|
911
|
+
local custom_ids: CustomIdMap = {}
|
|
912
|
+
|
|
913
|
+
client.command_buffers = command_buffers
|
|
445
914
|
|
|
446
915
|
for a = 1, total_packets do
|
|
447
916
|
local variants = all_variants and all_variants[variant_start - a]
|
|
@@ -449,154 +918,152 @@ local function apply_updates(client: Client, buf: buffer, all_variants: { { any
|
|
|
449
918
|
|
|
450
919
|
local total_added = read_vlq_bitmask(c, storage_mask, 0)
|
|
451
920
|
for _ = 1, total_added do
|
|
452
|
-
process_entity(client, c, variants)
|
|
921
|
+
client_replicator.process_entity(client, c, custom_ids, variants)
|
|
453
922
|
end
|
|
454
923
|
|
|
455
924
|
local total_components_added = read_vlq_bitmask(c, storage_mask, 1)
|
|
456
925
|
for _ = 1, total_components_added do
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
local tag_hooks = changed_hooks and changed_hooks[PAIR(components.reliable, tag)]
|
|
467
|
-
network_entity_add(client, entity, tag, tag_hooks)
|
|
468
|
-
end
|
|
926
|
+
client_replicator.process_entity_id(client, c, custom_ids, function(entity)
|
|
927
|
+
local added_mask = cursor.readu8(c)
|
|
928
|
+
|
|
929
|
+
local total_tags = read_vlq_bitmask(c, added_mask, 0)
|
|
930
|
+
for _ = 1, total_tags do
|
|
931
|
+
local tag = client_replicator.read_component_id(client, c)
|
|
932
|
+
local tag_hooks = changed_hooks[PAIR(components.reliable, tag)]
|
|
933
|
+
client_replicator.entity_add(client, entity, tag, tag_hooks)
|
|
934
|
+
end
|
|
469
935
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
936
|
+
local total_components = read_vlq_bitmask(c, added_mask, 1)
|
|
937
|
+
for _ = 1, total_components do
|
|
938
|
+
local component, value = client_replicator.read_component(client, c, variants)
|
|
939
|
+
local component_hooks = changed_hooks[PAIR(components.reliable, component)]
|
|
940
|
+
client_replicator.entity_set(client, entity, component, value, component_hooks)
|
|
941
|
+
end
|
|
476
942
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
943
|
+
local total_pairs = read_vlq_bitmask(c, added_mask, 2)
|
|
944
|
+
for _ = 1, total_pairs do
|
|
945
|
+
client_replicator.process_entity_relations(client, entity, c, custom_ids)
|
|
946
|
+
end
|
|
481
947
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
948
|
+
local total_pairs_values = read_vlq_bitmask(c, added_mask, 3)
|
|
949
|
+
for _ = 1, total_pairs_values do
|
|
950
|
+
client_replicator.process_entity_relation_values(client, entity, c, custom_ids, variants)
|
|
951
|
+
end
|
|
952
|
+
end)
|
|
486
953
|
end
|
|
487
954
|
|
|
488
955
|
local total_changed = read_vlq_bitmask(c, storage_mask, 2)
|
|
489
956
|
for _ = 1, total_changed do
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
local
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
local
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
local
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
957
|
+
client_replicator.process_entity_id(client, c, custom_ids, function(entity)
|
|
958
|
+
local changed_mask = cursor.readu8(c)
|
|
959
|
+
|
|
960
|
+
local total_tagged = read_vlq_bitmask(c, changed_mask, 0)
|
|
961
|
+
for _ = 1, total_tagged do
|
|
962
|
+
local tag = client_replicator.read_component_id(client, c)
|
|
963
|
+
local tag_hooks = changed_hooks[PAIR(components.reliable, tag)]
|
|
964
|
+
client_replicator.entity_add(client, entity, tag, tag_hooks)
|
|
965
|
+
end
|
|
966
|
+
|
|
967
|
+
local total_components = read_vlq_bitmask(c, changed_mask, 1)
|
|
968
|
+
for _ = 1, total_components do
|
|
969
|
+
local component, value = client_replicator.read_component(client, c, variants)
|
|
970
|
+
local component_hooks = changed_hooks[PAIR(components.reliable, component)]
|
|
971
|
+
client_replicator.entity_set(client, entity, component, value, component_hooks)
|
|
972
|
+
end
|
|
973
|
+
|
|
974
|
+
local total_removed = read_vlq_bitmask(c, changed_mask, 2)
|
|
975
|
+
for _ = 1, total_removed do
|
|
976
|
+
local component = client_replicator.read_component_id(client, c)
|
|
977
|
+
local component_hooks = removed_hooks[PAIR(components.reliable, component)]
|
|
978
|
+
client_replicator.entity_remove(client, entity, component, component_hooks)
|
|
979
|
+
end
|
|
980
|
+
|
|
981
|
+
local total_pairs = read_vlq_bitmask(c, changed_mask, 3)
|
|
982
|
+
for _ = 1, total_pairs do
|
|
983
|
+
local relation = client_replicator.read_component_id(client, c)
|
|
984
|
+
local pair_changed_hooks = changed_hooks[PAIR(components.pair, relation)]
|
|
985
|
+
local pair_removed_hooks = removed_hooks[PAIR(components.pair, relation)]
|
|
986
|
+
local total_targets = cursor.read_vlq(c)
|
|
987
|
+
|
|
988
|
+
for _ = 1, total_targets do
|
|
989
|
+
local action_type = cursor.readi8(c)
|
|
990
|
+
|
|
991
|
+
if action_type == 1 then -- add pair
|
|
992
|
+
client_replicator.process_entity_id(client, c, custom_ids, function(target)
|
|
993
|
+
client_replicator.entity_add_pair(client, entity, relation, target, pair_changed_hooks)
|
|
994
|
+
end)
|
|
995
|
+
elseif action_type == -1 then -- remove pair
|
|
996
|
+
client_replicator.process_entity_id(client, c, custom_ids, function(target)
|
|
997
|
+
client_replicator.entity_remove_pair(
|
|
998
|
+
client,
|
|
999
|
+
entity,
|
|
1000
|
+
relation,
|
|
1001
|
+
target,
|
|
1002
|
+
pair_removed_hooks
|
|
1003
|
+
)
|
|
1004
|
+
end)
|
|
535
1005
|
end
|
|
536
1006
|
end
|
|
537
1007
|
end
|
|
538
|
-
end
|
|
539
1008
|
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
1009
|
+
local total_pairs_values_removed = read_vlq_bitmask(c, changed_mask, 4)
|
|
1010
|
+
for _ = 1, total_pairs_values_removed do
|
|
1011
|
+
local relation = client_replicator.read_component_id(client, c)
|
|
1012
|
+
local pair_hooks = removed_hooks[PAIR(components.pair, relation)]
|
|
1013
|
+
local total_targets = cursor.read_vlq(c)
|
|
545
1014
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
1015
|
+
for _ = 1, total_targets do
|
|
1016
|
+
client_replicator.process_entity_id(client, c, custom_ids, function(target)
|
|
1017
|
+
client_replicator.entity_remove_pair(client, entity, relation, target, pair_hooks)
|
|
1018
|
+
end)
|
|
550
1019
|
end
|
|
551
1020
|
end
|
|
552
|
-
end
|
|
553
|
-
|
|
554
|
-
local total_pairs_values = read_vlq_bitmask(c, changed_mask, 5)
|
|
555
|
-
for _ = 1, total_pairs_values do
|
|
556
|
-
local relation = read_component_id(client, c)
|
|
557
|
-
local pair_hooks = changed_hooks and changed_hooks[PAIR(components.pair, relation)]
|
|
558
|
-
local total_targets = cursor.read_vlq(c)
|
|
559
1021
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
local
|
|
563
|
-
|
|
1022
|
+
local total_pairs_values = read_vlq_bitmask(c, changed_mask, 5)
|
|
1023
|
+
for _ = 1, total_pairs_values do
|
|
1024
|
+
local relation = client_replicator.read_component_id(client, c)
|
|
1025
|
+
local pair_hooks = changed_hooks[PAIR(components.pair, relation)]
|
|
1026
|
+
local total_targets = cursor.read_vlq(c)
|
|
1027
|
+
|
|
1028
|
+
for _ = 1, total_targets do
|
|
1029
|
+
local value = client_replicator.read_component_value(client, relation, c, variants)
|
|
1030
|
+
client_replicator.process_entity_id(client, c, custom_ids, function(target)
|
|
1031
|
+
client_replicator.entity_set_pair(client, entity, relation, target, value, pair_hooks)
|
|
1032
|
+
end)
|
|
1033
|
+
end
|
|
564
1034
|
end
|
|
565
|
-
end
|
|
1035
|
+
end)
|
|
566
1036
|
end
|
|
567
1037
|
|
|
568
1038
|
local total_component_deletions = read_vlq_bitmask(c, storage_mask, 3)
|
|
569
1039
|
for _ = 1, total_component_deletions do
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
local component_hooks = removed_hooks and removed_hooks[PAIR(components.reliable, component)]
|
|
578
|
-
network_entity_remove(client, entity, component, component_hooks)
|
|
579
|
-
end
|
|
1040
|
+
client_replicator.process_entity_id(client, c, custom_ids, function(entity)
|
|
1041
|
+
local total_removed = cursor.read_vlq(c)
|
|
1042
|
+
for _ = 1, total_removed do
|
|
1043
|
+
local component = client_replicator.read_component_id(client, c)
|
|
1044
|
+
local component_hooks = removed_hooks[PAIR(components.reliable, component)]
|
|
1045
|
+
client_replicator.entity_remove(client, entity, component, component_hooks)
|
|
1046
|
+
end
|
|
580
1047
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
1048
|
+
local total_pairs = cursor.read_vlq(c)
|
|
1049
|
+
for _ = 1, total_pairs do
|
|
1050
|
+
local relation = client_replicator.read_component_id(client, c)
|
|
1051
|
+
local pair_hooks = removed_hooks[PAIR(components.pair, relation)]
|
|
1052
|
+
client_replicator.entity_remove_relations(client, entity, relation, pair_hooks)
|
|
1053
|
+
end
|
|
1054
|
+
end)
|
|
587
1055
|
end
|
|
588
1056
|
|
|
589
1057
|
local total_deleted = read_vlq_bitmask(c, storage_mask, 4)
|
|
590
1058
|
for _ = 1, total_deleted do
|
|
591
|
-
local entity, server_id = read_entity_id(client, c
|
|
1059
|
+
local entity, server_id = client_replicator.read_entity_id(client, c)
|
|
592
1060
|
if entity then
|
|
593
|
-
local
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
for _, callback in deleted_hooks.callbacks do
|
|
1061
|
+
local deleted_hook = deleted_hooks[entity]
|
|
1062
|
+
if deleted_hook then
|
|
1063
|
+
for _, callback in deleted_hook.callbacks do
|
|
597
1064
|
callback(entity)
|
|
598
1065
|
end
|
|
599
|
-
if not
|
|
1066
|
+
if not deleted_hook.overrides then
|
|
600
1067
|
client.world:delete(entity)
|
|
601
1068
|
end
|
|
602
1069
|
else
|
|
@@ -609,72 +1076,76 @@ local function apply_updates(client: Client, buf: buffer, all_variants: { { any
|
|
|
609
1076
|
end
|
|
610
1077
|
end
|
|
611
1078
|
|
|
612
|
-
|
|
1079
|
+
client_replicator.finish_custom_ids(client, custom_ids, command_buffers)
|
|
1080
|
+
client_replicator.finish_replication(client)
|
|
613
1081
|
end
|
|
614
1082
|
|
|
615
|
-
|
|
1083
|
+
function client_replicator.apply_unreliable(client: Client, buf: buffer, all_variants: { { any } }?)
|
|
616
1084
|
local c = cursor.from(buf)
|
|
617
1085
|
check_packet_type(c, "unreliable")
|
|
618
|
-
resolve_dirty(client)
|
|
1086
|
+
client_replicator.resolve_dirty(client)
|
|
619
1087
|
client.is_replicating = true
|
|
620
1088
|
|
|
621
1089
|
local components = client.components
|
|
622
1090
|
local total_packets = cursor.read_vlq(c)
|
|
623
1091
|
local variant_start = (all_variants and #all_variants + 1) :: number
|
|
1092
|
+
local changed_hooks = client.network_hooks.changed
|
|
624
1093
|
|
|
625
1094
|
for a = 1, total_packets do
|
|
626
1095
|
local total_entities = cursor.read_vlq(c)
|
|
627
1096
|
local variants = all_variants and all_variants[variant_start - a]
|
|
628
1097
|
|
|
629
1098
|
for _ = 1, total_entities do
|
|
630
|
-
local entity = read_entity_id(client, c
|
|
631
|
-
|
|
1099
|
+
local entity = client_replicator.read_entity_id(client, c)
|
|
632
1100
|
local total_unreliable = cursor.read_vlq(c)
|
|
633
1101
|
|
|
634
1102
|
if entity then
|
|
635
|
-
local entity_hooks = client.entity_hooks[entity]
|
|
636
|
-
local changed_hooks = entity_hooks and entity_hooks.changed
|
|
637
|
-
|
|
638
1103
|
for _ = 1, total_unreliable do
|
|
639
|
-
local component_id, value = read_component(client, c, variants)
|
|
640
|
-
local unreliable_hooks = changed_hooks
|
|
641
|
-
|
|
1104
|
+
local component_id, value = client_replicator.read_component(client, c, variants)
|
|
1105
|
+
local unreliable_hooks = changed_hooks[PAIR(components.unreliable, component_id)]
|
|
1106
|
+
client_replicator.entity_set_unreliable(client, entity, component_id, value, unreliable_hooks)
|
|
642
1107
|
end
|
|
643
1108
|
else
|
|
644
1109
|
-- dont apply unreliable updates to entities that dont exist in the client yet
|
|
645
1110
|
-- but we still need to process the values to keep the cursor in the right place
|
|
646
1111
|
for _ = 1, total_unreliable do
|
|
647
|
-
read_component(client, c, variants)
|
|
1112
|
+
client_replicator.read_component(client, c, variants)
|
|
648
1113
|
end
|
|
649
1114
|
end
|
|
650
1115
|
end
|
|
651
1116
|
end
|
|
652
1117
|
|
|
653
|
-
finish_replication(client)
|
|
1118
|
+
client_replicator.finish_replication(client)
|
|
654
1119
|
end
|
|
655
1120
|
|
|
656
|
-
|
|
1121
|
+
function client_replicator.apply_full(client: Client, buf: buffer, all_variants: { { any } }?)
|
|
657
1122
|
local c = cursor.from(buf)
|
|
658
1123
|
check_packet_type(c, "full")
|
|
659
|
-
resolve_dirty(client)
|
|
1124
|
+
client_replicator.resolve_dirty(client)
|
|
660
1125
|
client.is_replicating = true
|
|
661
1126
|
|
|
662
1127
|
local total_packets = cursor.read_vlq(c)
|
|
663
1128
|
local variant_start = (all_variants and #all_variants + 1) :: number
|
|
664
1129
|
|
|
1130
|
+
local command_buffers: { [Entity]: CommandBuffer } = {}
|
|
1131
|
+
local custom_ids: CustomIdMap = {}
|
|
1132
|
+
|
|
1133
|
+
client.command_buffers = command_buffers
|
|
1134
|
+
|
|
665
1135
|
for a = 1, total_packets do
|
|
666
1136
|
local total_entities = cursor.read_vlq(c)
|
|
667
1137
|
local variants = all_variants and all_variants[variant_start - a]
|
|
668
1138
|
|
|
669
1139
|
for _ = 1, total_entities do
|
|
670
|
-
process_entity(client, c, variants)
|
|
1140
|
+
client_replicator.process_entity(client, c, custom_ids, variants)
|
|
671
1141
|
end
|
|
672
1142
|
end
|
|
673
1143
|
|
|
674
|
-
|
|
1144
|
+
client_replicator.finish_custom_ids(client, custom_ids, command_buffers)
|
|
1145
|
+
client_replicator.finish_replication(client)
|
|
675
1146
|
end
|
|
676
1147
|
|
|
677
|
-
|
|
1148
|
+
function client_replicator.init(client: Client, _world: World?)
|
|
678
1149
|
if client.inited == true then
|
|
679
1150
|
return warn "attempted to init a client twice"
|
|
680
1151
|
end
|
|
@@ -699,11 +1170,7 @@ local function init(client: Client, _world: World?)
|
|
|
699
1170
|
|
|
700
1171
|
local components = client.components
|
|
701
1172
|
|
|
702
|
-
client.shared = utils.
|
|
703
|
-
|
|
704
|
-
for component, custom_get in world:query(components.custom_handler):with(components.shared, ECS_NAME) do
|
|
705
|
-
client.custom_ids[component] = custom_get
|
|
706
|
-
end
|
|
1173
|
+
client.shared = utils.resolved_shared(world, components, client.registered_custom_ids)
|
|
707
1174
|
|
|
708
1175
|
local alive_unhook = hooks.removed(world, components.__alive_tracking__, function(entity)
|
|
709
1176
|
local server_id = client.client_ids[entity]
|
|
@@ -711,23 +1178,23 @@ local function init(client: Client, _world: World?)
|
|
|
711
1178
|
client.server_ids[server_id] = nil
|
|
712
1179
|
client.client_ids[entity] = nil
|
|
713
1180
|
end
|
|
714
|
-
client.
|
|
1181
|
+
client.network_hooks.deleted[entity] = nil
|
|
715
1182
|
end)
|
|
716
1183
|
table.insert(client.hooked, alive_unhook)
|
|
717
1184
|
|
|
718
1185
|
for _, component in client.requires_shared_lookup do
|
|
719
1186
|
local added_hook = hooks.added(world, component, function()
|
|
720
|
-
client.
|
|
1187
|
+
client.is_shared_dirty = true
|
|
721
1188
|
end)
|
|
722
1189
|
local removed_hook = hooks.removed(world, component, function()
|
|
723
|
-
client.
|
|
1190
|
+
client.is_shared_dirty = true
|
|
724
1191
|
end)
|
|
725
1192
|
table.insert(client.hooked, added_hook)
|
|
726
1193
|
table.insert(client.hooked, removed_hook)
|
|
727
1194
|
end
|
|
728
1195
|
end
|
|
729
1196
|
|
|
730
|
-
|
|
1197
|
+
function client_replicator.after_replication(client: Client, callback: () -> ())
|
|
731
1198
|
if client.is_replicating then
|
|
732
1199
|
table.insert(client.after_replication_callbacks, callback)
|
|
733
1200
|
else
|
|
@@ -735,7 +1202,7 @@ local function after_replication(client: Client, callback: () -> ())
|
|
|
735
1202
|
end
|
|
736
1203
|
end
|
|
737
1204
|
|
|
738
|
-
|
|
1205
|
+
function client_replicator.added(client: Client, callback: (entity: Entity) -> ())
|
|
739
1206
|
table.insert(client.addition_hooks, callback)
|
|
740
1207
|
return function()
|
|
741
1208
|
local index = table.find(client.addition_hooks, callback)
|
|
@@ -745,24 +1212,11 @@ local function added(client: Client, callback: (entity: Entity) -> ())
|
|
|
745
1212
|
end
|
|
746
1213
|
end
|
|
747
1214
|
|
|
748
|
-
local function
|
|
749
|
-
local entity_hooks = client.entity_hooks[entity]
|
|
750
|
-
if not entity_hooks then
|
|
751
|
-
entity_hooks = {
|
|
752
|
-
changed = {},
|
|
753
|
-
removed = {},
|
|
754
|
-
deleted = nil :: DeletedHookEntry?,
|
|
755
|
-
}
|
|
756
|
-
client.entity_hooks[entity] = entity_hooks
|
|
757
|
-
end
|
|
758
|
-
return entity_hooks
|
|
759
|
-
end
|
|
760
|
-
|
|
761
|
-
local function add_hook_entry(client: Client, entity: Entity, action: string, ...): ({ overrides: boolean }, () -> ())
|
|
1215
|
+
local function add_hook_entry(client: Client, action: string, ...): ({ overrides: boolean }, () -> ())
|
|
762
1216
|
if action == "changed" or action == "removed" then
|
|
763
1217
|
local relation = select(1, ...) :: Entity
|
|
764
1218
|
local callback = select(2, ...) :: (entity: Entity, id: number, value: any) -> ()
|
|
765
|
-
local hooks =
|
|
1219
|
+
local hooks = action == "changed" and client.network_hooks.changed or client.network_hooks.removed
|
|
766
1220
|
local entries = hooks[relation] :: ChangedHooksEntry
|
|
767
1221
|
|
|
768
1222
|
if not entries then
|
|
@@ -786,16 +1240,17 @@ local function add_hook_entry(client: Client, entity: Entity, action: string, ..
|
|
|
786
1240
|
end
|
|
787
1241
|
return entries, disconnect
|
|
788
1242
|
elseif action == "deleted" then
|
|
789
|
-
local
|
|
790
|
-
local
|
|
791
|
-
local
|
|
1243
|
+
local entity = select(1, ...) :: Entity
|
|
1244
|
+
local callback = select(2, ...) :: (entity: Entity) -> ()
|
|
1245
|
+
local hooks = client.network_hooks.deleted
|
|
1246
|
+
local entries = hooks[entity]
|
|
792
1247
|
|
|
793
1248
|
if not entries then
|
|
794
1249
|
entries = {
|
|
795
1250
|
overrides = false,
|
|
796
1251
|
callbacks = {},
|
|
797
1252
|
}
|
|
798
|
-
hooks
|
|
1253
|
+
hooks[entity] = entries
|
|
799
1254
|
end
|
|
800
1255
|
table.insert(entries.callbacks, callback)
|
|
801
1256
|
|
|
@@ -805,7 +1260,7 @@ local function add_hook_entry(client: Client, entity: Entity, action: string, ..
|
|
|
805
1260
|
if index then
|
|
806
1261
|
table.remove(callbacks, index)
|
|
807
1262
|
if #callbacks == 0 then
|
|
808
|
-
hooks
|
|
1263
|
+
hooks[entity] = nil
|
|
809
1264
|
end
|
|
810
1265
|
end
|
|
811
1266
|
end
|
|
@@ -815,26 +1270,55 @@ local function add_hook_entry(client: Client, entity: Entity, action: string, ..
|
|
|
815
1270
|
end
|
|
816
1271
|
end
|
|
817
1272
|
|
|
818
|
-
|
|
819
|
-
local entry, disconnect = add_hook_entry(client,
|
|
1273
|
+
function client_replicator.hook(client: Client, action: string, ...)
|
|
1274
|
+
local entry, disconnect = add_hook_entry(client, action, ...)
|
|
820
1275
|
entry.overrides = false
|
|
821
1276
|
return disconnect
|
|
822
1277
|
end
|
|
823
|
-
|
|
824
|
-
local entry, disconnect = add_hook_entry(client,
|
|
1278
|
+
function client_replicator.override(client: Client, action: string, ...)
|
|
1279
|
+
local entry, disconnect = add_hook_entry(client, action, ...)
|
|
825
1280
|
entry.overrides = true
|
|
826
1281
|
return disconnect
|
|
827
1282
|
end
|
|
828
1283
|
|
|
829
|
-
|
|
1284
|
+
function client_replicator.get_server_entity(client: Client, client_entity: Entity): number?
|
|
830
1285
|
return client.client_ids[client_entity]
|
|
831
1286
|
end
|
|
832
1287
|
|
|
833
|
-
|
|
1288
|
+
function client_replicator.get_client_entity(client: Client, client_entity: number): Entity?
|
|
834
1289
|
return client.server_ids[client_entity]
|
|
835
1290
|
end
|
|
836
1291
|
|
|
837
|
-
|
|
1292
|
+
function client_replicator.register_entity(client: Client, entity: Entity, server_entity: number)
|
|
1293
|
+
client.server_ids[server_entity] = entity
|
|
1294
|
+
client.client_ids[entity] = server_entity
|
|
1295
|
+
client.world:add(entity, client.components.__alive_tracking__)
|
|
1296
|
+
end
|
|
1297
|
+
|
|
1298
|
+
function client_replicator.unregister_entity(client: Client, entity: Entity)
|
|
1299
|
+
local server_id = client.client_ids[entity]
|
|
1300
|
+
if server_id then
|
|
1301
|
+
client.server_ids[server_id] = nil
|
|
1302
|
+
client.client_ids[entity] = nil
|
|
1303
|
+
end
|
|
1304
|
+
end
|
|
1305
|
+
|
|
1306
|
+
function client_replicator.register_custom_id(client: Client, custom_id: CustomId)
|
|
1307
|
+
client.registered_custom_ids[custom_id] = true
|
|
1308
|
+
client.is_shared_dirty = true
|
|
1309
|
+
end
|
|
1310
|
+
|
|
1311
|
+
function client_replicator.generate_handshake(client: Client): common.HandshakeInfo
|
|
1312
|
+
client_replicator.resolve_dirty(client)
|
|
1313
|
+
return utils.generate_handshake(client.world, client.shared)
|
|
1314
|
+
end
|
|
1315
|
+
|
|
1316
|
+
function client_replicator.verify_handshake(client: Client, handshake: common.HandshakeInfo): (boolean, string?)
|
|
1317
|
+
client_replicator.resolve_dirty(client)
|
|
1318
|
+
return utils.verify_handshake(client.world, client.shared, handshake, "server", "client")
|
|
1319
|
+
end
|
|
1320
|
+
|
|
1321
|
+
function client_replicator.destroy(client: Client)
|
|
838
1322
|
if client.inited == nil then
|
|
839
1323
|
return warn "attempted to destroy a client twice"
|
|
840
1324
|
end
|
|
@@ -844,40 +1328,21 @@ local function destroy(client: Client)
|
|
|
844
1328
|
end
|
|
845
1329
|
end
|
|
846
1330
|
|
|
847
|
-
|
|
1331
|
+
function client_replicator.handle_global(client: Client, handler: (id: number) -> Entity)
|
|
848
1332
|
client.global_handler = handler
|
|
849
1333
|
end
|
|
850
1334
|
|
|
851
|
-
local client = {}
|
|
852
|
-
client.__index = client
|
|
853
|
-
client.init = init
|
|
854
|
-
client.destroy = destroy
|
|
855
|
-
client.apply_updates = apply_updates
|
|
856
|
-
client.apply_unreliable = apply_unreliable
|
|
857
|
-
client.apply_full = apply_full
|
|
858
|
-
client.encode_component = encode_component
|
|
859
|
-
client.decode_component = decode_component
|
|
860
|
-
client.get_server_entity = get_server_entity
|
|
861
|
-
client.get_client_entity = get_client_entity
|
|
862
|
-
client.handle_global = handle_global
|
|
863
|
-
client.after_replication = after_replication
|
|
864
|
-
client.hook = hook
|
|
865
|
-
client.override = override
|
|
866
|
-
client.added = added
|
|
867
|
-
|
|
868
1335
|
local function create(world: World?, components: common.Components): Client
|
|
869
1336
|
local self = {} :: Client
|
|
870
1337
|
|
|
871
1338
|
self.components = components
|
|
872
1339
|
self.ordered_creation = true
|
|
873
|
-
self.custom_ids = {}
|
|
874
1340
|
self.server_ids = {}
|
|
875
1341
|
self.client_ids = {}
|
|
876
|
-
self.
|
|
1342
|
+
self.is_shared_dirty = false
|
|
877
1343
|
self.requires_shared_lookup = {
|
|
878
1344
|
self.components.shared,
|
|
879
1345
|
self.components.serdes,
|
|
880
|
-
self.components.bytespan,
|
|
881
1346
|
jecs.Name,
|
|
882
1347
|
}
|
|
883
1348
|
self.global_handler = nil
|
|
@@ -885,14 +1350,20 @@ local function create(world: World?, components: common.Components): Client
|
|
|
885
1350
|
self.inited = false
|
|
886
1351
|
self.is_replicating = false
|
|
887
1352
|
self.hooked = {}
|
|
1353
|
+
self.registered_custom_ids = {}
|
|
888
1354
|
|
|
889
1355
|
self.addition_hooks = {}
|
|
890
|
-
self.
|
|
1356
|
+
self.network_hooks = {
|
|
1357
|
+
deleted = {},
|
|
1358
|
+
changed = {},
|
|
1359
|
+
removed = {},
|
|
1360
|
+
}
|
|
891
1361
|
self.after_replication_callbacks = {}
|
|
892
1362
|
|
|
893
|
-
return setmetatable(self,
|
|
1363
|
+
return setmetatable(self, client_replicator) :: any
|
|
894
1364
|
end
|
|
895
1365
|
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
1366
|
+
return {
|
|
1367
|
+
create = create,
|
|
1368
|
+
client_replicator = client_replicator,
|
|
1369
|
+
}
|