@rbxts/replecs 0.0.1-rc.1 → 0.1.0-alpha2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/out/replecs/client.luau +77 -40
- package/out/replecs/common.luau +2 -1
- package/out/replecs/index.d.ts +24 -15
- package/out/replecs/init.luau +88 -83
- package/out/replecs/masking/init.luau +258 -104
- package/out/replecs/masking/mask_generator.luau +8 -5
- package/out/replecs/server.luau +1065 -918
- package/out/replecs/utils.luau +66 -13
- package/package.json +1 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 replecs authors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/out/replecs/client.luau
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
--!native
|
|
2
2
|
--!optimize 2
|
|
3
3
|
|
|
4
|
-
local jecs = require
|
|
5
|
-
local common = require
|
|
6
|
-
local utils = require
|
|
4
|
+
local jecs = require "../jecs"
|
|
5
|
+
local common = require "./common"
|
|
6
|
+
local utils = require "./utils"
|
|
7
7
|
|
|
8
8
|
local cursor = utils.cursor
|
|
9
9
|
type Cursor = utils.Cursor
|
|
@@ -19,6 +19,7 @@ export type Client = {
|
|
|
19
19
|
|
|
20
20
|
components: common.Components,
|
|
21
21
|
shared: common.Shared,
|
|
22
|
+
global_id_parser: ((id: number) -> Entity)?,
|
|
22
23
|
server_ids: { [number]: Entity },
|
|
23
24
|
client_ids: { [Entity]: number },
|
|
24
25
|
ordered_creation: boolean,
|
|
@@ -27,16 +28,21 @@ export type Client = {
|
|
|
27
28
|
init: (self: Client, world: World?) -> (),
|
|
28
29
|
destroy: (self: Client) -> (),
|
|
29
30
|
after_replication: (self: Client, callback: () -> ()) -> (),
|
|
31
|
+
parse_global_id: (self: Client, parser: (id: number) -> Entity) -> (),
|
|
32
|
+
get_server_entity: (self: Client, client_entity: Entity) -> number?,
|
|
33
|
+
get_client_entity: (self: Client, server_entity: number) -> Entity?,
|
|
30
34
|
|
|
31
35
|
apply_updates: (self: Client, buf: buffer, all_variants: { { any } }?) -> (),
|
|
32
36
|
apply_unreliable: (self: Client, buf: buffer, all_variants: { { any } }?) -> (),
|
|
33
37
|
apply_full: (self: Client, buf: buffer, all_variants: { { any } }?) -> (),
|
|
34
38
|
}
|
|
35
39
|
|
|
40
|
+
local GLOBAL_ID_OFFSET = 10
|
|
36
41
|
local ENTITY_ID_TYPES = {
|
|
37
|
-
|
|
42
|
+
entity = 1,
|
|
38
43
|
custom = 2,
|
|
39
44
|
shared = 3,
|
|
45
|
+
global = 4,
|
|
40
46
|
}
|
|
41
47
|
|
|
42
48
|
local ECS_NAME = jecs.Name
|
|
@@ -87,31 +93,46 @@ local function read_component_value(client: Client, c: Cursor, variants: { any }
|
|
|
87
93
|
end
|
|
88
94
|
end
|
|
89
95
|
|
|
96
|
+
local function resolve_global_id(client: Client, global_id: number): Entity
|
|
97
|
+
if not client.global_id_parser then
|
|
98
|
+
error "global id parser not set, consider using client:parse_global_id()"
|
|
99
|
+
end
|
|
100
|
+
local parsed = client.global_id_parser(global_id)
|
|
101
|
+
return parsed
|
|
102
|
+
end
|
|
103
|
+
|
|
90
104
|
local function read_entity_id(client: Client, c: Cursor, variants: { any }?): (Entity?, number?)
|
|
91
105
|
local id_type = cursor.readi8(c)
|
|
92
106
|
|
|
93
|
-
if id_type
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
component,
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
107
|
+
if id_type <= 10 then
|
|
108
|
+
if id_type == ENTITY_ID_TYPES.entity then
|
|
109
|
+
local server_id = cursor.readu40(c)
|
|
110
|
+
return client.server_ids[server_id], server_id
|
|
111
|
+
elseif id_type == ENTITY_ID_TYPES.custom then
|
|
112
|
+
local component, value = read_component_value(client, c, variants)
|
|
113
|
+
local custom_getter = client.custom_ids[component]
|
|
114
|
+
if not custom_getter then
|
|
115
|
+
error(
|
|
116
|
+
`received a custom id for a non custom component, consider adding custom_id to component: {client.world:get(
|
|
117
|
+
component,
|
|
118
|
+
ECS_NAME
|
|
119
|
+
) or "(no name)"} id: {component}`
|
|
120
|
+
)
|
|
121
|
+
end
|
|
122
|
+
return custom_getter(value), nil
|
|
123
|
+
elseif id_type == ENTITY_ID_TYPES.shared then
|
|
124
|
+
return read_component_id(client, c), nil
|
|
125
|
+
elseif id_type == ENTITY_ID_TYPES.global then
|
|
126
|
+
local global_id = cursor.readu8(c) - GLOBAL_ID_OFFSET
|
|
127
|
+
return resolve_global_id(client, global_id), nil
|
|
106
128
|
end
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
return
|
|
129
|
+
error(`malformed entity id {id_type} ` .. cursor.readu32(c))
|
|
130
|
+
else
|
|
131
|
+
return resolve_global_id(client, id_type - GLOBAL_ID_OFFSET), nil
|
|
110
132
|
end
|
|
111
|
-
error("malformed entity id" .. cursor.readu32(c))
|
|
112
133
|
end
|
|
113
134
|
|
|
114
|
-
local function process_entity_id(client: Client, c: Cursor, variants: { any }?)
|
|
135
|
+
local function process_entity_id(client: Client, c: Cursor, variants: { any }?, v: boolean?)
|
|
115
136
|
local entity, server_id = read_entity_id(client, c, variants)
|
|
116
137
|
if entity then
|
|
117
138
|
return entity
|
|
@@ -124,23 +145,23 @@ local function process_entity(client: Client, c: Cursor, variants: { any }?)
|
|
|
124
145
|
local entity = process_entity_id(client, c, variants)
|
|
125
146
|
|
|
126
147
|
local total_tags = cursor.read_vlq(c)
|
|
127
|
-
for
|
|
148
|
+
for _ = 1, total_tags do
|
|
128
149
|
local tag = read_component_id(client, c)
|
|
129
150
|
client.world:add(entity, tag)
|
|
130
151
|
end
|
|
131
152
|
|
|
132
153
|
local total_components = cursor.read_vlq(c)
|
|
133
|
-
for
|
|
154
|
+
for _ = 1, total_components do
|
|
134
155
|
local component, value = read_component_value(client, c, variants)
|
|
135
156
|
client.world:set(entity, component, value)
|
|
136
157
|
end
|
|
137
158
|
|
|
138
159
|
local total_pairs = cursor.read_vlq(c)
|
|
139
|
-
for
|
|
160
|
+
for _ = 1, total_pairs do
|
|
140
161
|
local relation = read_component_id(client, c)
|
|
141
162
|
local total_targets = cursor.read_vlq(c)
|
|
142
163
|
|
|
143
|
-
for
|
|
164
|
+
for _ = 1, total_targets do
|
|
144
165
|
local target = process_entity_id(client, c, variants)
|
|
145
166
|
client.world:add(entity, PAIR(relation, target))
|
|
146
167
|
end
|
|
@@ -161,26 +182,26 @@ local function apply_updates(client: Client, buf: buffer, all_variants: { { any
|
|
|
161
182
|
end
|
|
162
183
|
|
|
163
184
|
local total_changed = cursor.read_vlq(c)
|
|
164
|
-
for
|
|
185
|
+
for _ = 1, total_changed do
|
|
165
186
|
local entity = process_entity_id(client, c, variants)
|
|
166
187
|
local total_tagged = cursor.read_vlq(c)
|
|
167
|
-
for
|
|
188
|
+
for _ = 1, total_tagged do
|
|
168
189
|
local tag = read_component_id(client, c)
|
|
169
190
|
client.world:add(entity, tag)
|
|
170
191
|
end
|
|
171
192
|
|
|
172
193
|
local total_components = cursor.read_vlq(c)
|
|
173
|
-
for
|
|
194
|
+
for _ = 1, total_components do
|
|
174
195
|
local component, value = read_component_value(client, c, variants)
|
|
175
196
|
client.world:set(entity, component, value)
|
|
176
197
|
end
|
|
177
198
|
|
|
178
199
|
local total_pairs = cursor.read_vlq(c)
|
|
179
|
-
for
|
|
200
|
+
for _ = 1, total_pairs do
|
|
180
201
|
local relation = read_component_id(client, c)
|
|
181
202
|
local total_targets = cursor.read_vlq(c)
|
|
182
203
|
|
|
183
|
-
for
|
|
204
|
+
for _ = 1, total_targets do
|
|
184
205
|
local id_type = cursor.readi8(c)
|
|
185
206
|
-- here I use negative numbers to indicate removals
|
|
186
207
|
-- but "process_entity_id" expects a positive value
|
|
@@ -198,37 +219,37 @@ local function apply_updates(client: Client, buf: buffer, all_variants: { { any
|
|
|
198
219
|
end
|
|
199
220
|
|
|
200
221
|
local total_removed = cursor.read_vlq(c)
|
|
201
|
-
for
|
|
222
|
+
for _ = 1, total_removed do
|
|
202
223
|
local component = read_component_id(client, c)
|
|
203
224
|
client.world:remove(entity, component)
|
|
204
225
|
end
|
|
205
226
|
end
|
|
206
227
|
|
|
207
228
|
local total_component_deleted = cursor.read_vlq(c)
|
|
208
|
-
for
|
|
229
|
+
for _ = 1, total_component_deleted do
|
|
209
230
|
local entity = process_entity_id(client, c, variants)
|
|
210
231
|
|
|
211
232
|
local total_tags = cursor.read_vlq(c)
|
|
212
|
-
for
|
|
233
|
+
for _ = 1, total_tags do
|
|
213
234
|
local tag = read_component_id(client, c)
|
|
214
235
|
client.world:remove(entity, tag)
|
|
215
236
|
end
|
|
216
237
|
|
|
217
238
|
local total_components = cursor.read_vlq(c)
|
|
218
|
-
for
|
|
239
|
+
for _ = 1, total_components do
|
|
219
240
|
local component = read_component_id(client, c)
|
|
220
241
|
client.world:remove(entity, component)
|
|
221
242
|
end
|
|
222
243
|
|
|
223
244
|
local total_pairs = cursor.read_vlq(c)
|
|
224
|
-
for
|
|
245
|
+
for _ = 1, total_pairs do
|
|
225
246
|
local relation = read_component_id(client, c)
|
|
226
247
|
utils.remove_all_relations(client.world, entity, relation)
|
|
227
248
|
end
|
|
228
249
|
end
|
|
229
250
|
|
|
230
251
|
local total_deleted = cursor.read_vlq(c)
|
|
231
|
-
for
|
|
252
|
+
for _ = 1, total_deleted do
|
|
232
253
|
local entity, server_id = read_entity_id(client, c, variants)
|
|
233
254
|
if entity then
|
|
234
255
|
client.world:delete(entity)
|
|
@@ -249,7 +270,7 @@ local function apply_unreliable(client: Client, buf: buffer, all_variants: { { a
|
|
|
249
270
|
local total_entities = cursor.read_vlq(c)
|
|
250
271
|
local variants = all_variants and all_variants[variant_start - a]
|
|
251
272
|
|
|
252
|
-
for
|
|
273
|
+
for _ = 1, total_entities do
|
|
253
274
|
local entity = read_entity_id(client, c, variants)
|
|
254
275
|
local total_unreliable = cursor.read_vlq(c)
|
|
255
276
|
|
|
@@ -259,7 +280,7 @@ local function apply_unreliable(client: Client, buf: buffer, all_variants: { { a
|
|
|
259
280
|
else
|
|
260
281
|
-- dont apply unreliable updates to entities that dont exist in the client yet
|
|
261
282
|
-- but we still need to process the values to keep the cursor in the right place
|
|
262
|
-
for
|
|
283
|
+
for _ = 1, total_unreliable do
|
|
263
284
|
read_component_value(client, c, variants)
|
|
264
285
|
end
|
|
265
286
|
end
|
|
@@ -276,7 +297,7 @@ local function apply_full(client: Client, buf: buffer, all_variants: { { any } }
|
|
|
276
297
|
local total_entities = cursor.read_vlq(c)
|
|
277
298
|
local variants = all_variants and all_variants[variant_start - a]
|
|
278
299
|
|
|
279
|
-
for
|
|
300
|
+
for _ = 1, total_entities do
|
|
280
301
|
process_entity(client, c, variants)
|
|
281
302
|
end
|
|
282
303
|
end
|
|
@@ -315,6 +336,14 @@ local function after_replication(client: Client, callback: () -> ())
|
|
|
315
336
|
end
|
|
316
337
|
end
|
|
317
338
|
|
|
339
|
+
local function get_server_entity(client: Client, client_entity: Entity): number?
|
|
340
|
+
return client.client_ids[client_entity]
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
local function get_client_entity(client: Client, client_entity: number): Entity?
|
|
344
|
+
return client.server_ids[client_entity]
|
|
345
|
+
end
|
|
346
|
+
|
|
318
347
|
local function destroy(client: Client)
|
|
319
348
|
if client.inited == nil then
|
|
320
349
|
return warn "attempted to destroy a client twice"
|
|
@@ -324,6 +353,10 @@ local function destroy(client: Client)
|
|
|
324
353
|
-- right now this is kind of useless
|
|
325
354
|
end
|
|
326
355
|
|
|
356
|
+
local function parse_global_id(client: Client, parser: (id: number) -> Entity)
|
|
357
|
+
client.global_id_parser = parser
|
|
358
|
+
end
|
|
359
|
+
|
|
327
360
|
local client = {}
|
|
328
361
|
client.__index = client
|
|
329
362
|
client.init = init
|
|
@@ -332,6 +365,9 @@ client.after_replication = after_replication
|
|
|
332
365
|
client.apply_updates = apply_updates
|
|
333
366
|
client.apply_unreliable = apply_unreliable
|
|
334
367
|
client.apply_full = apply_full
|
|
368
|
+
client.get_server_entity = get_server_entity
|
|
369
|
+
client.get_client_entity = get_client_entity
|
|
370
|
+
client.parse_global_id = parse_global_id
|
|
335
371
|
|
|
336
372
|
local function create(world: World?, components: common.Components): Client
|
|
337
373
|
local self = {} :: Client
|
|
@@ -341,6 +377,7 @@ local function create(world: World?, components: common.Components): Client
|
|
|
341
377
|
self.custom_ids = {}
|
|
342
378
|
self.server_ids = {}
|
|
343
379
|
self.client_ids = {}
|
|
380
|
+
self.global_id_parser = nil
|
|
344
381
|
self.world = world :: any
|
|
345
382
|
self.inited = false
|
|
346
383
|
self.is_replicating = false
|
package/out/replecs/common.luau
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
local jecs = require
|
|
1
|
+
local jecs = require "../jecs"
|
|
2
2
|
|
|
3
3
|
export type PlayerFilter = {
|
|
4
4
|
[Player]: boolean,
|
|
@@ -19,6 +19,7 @@ export type Components = {
|
|
|
19
19
|
serdes: jecs.Entity<Serdes>,
|
|
20
20
|
bytespan: jecs.Entity<number>,
|
|
21
21
|
custom_id: jecs.Entity<(value: any) -> jecs.Entity>,
|
|
22
|
+
global_id: jecs.Entity<number>,
|
|
22
23
|
__alive_tracking__: jecs.Entity,
|
|
23
24
|
}
|
|
24
25
|
|
package/out/replecs/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ declare namespace Replecs {
|
|
|
10
10
|
added<T>(
|
|
11
11
|
this: ObserverWorld,
|
|
12
12
|
component: Id<T>,
|
|
13
|
-
callback: (e: Entity, id: Id<T>, value
|
|
13
|
+
callback: (e: Entity, id: Id<T>, value: T) => void
|
|
14
14
|
): () => void;
|
|
15
15
|
removed<T>(
|
|
16
16
|
this: ObserverWorld,
|
|
@@ -20,40 +20,43 @@ declare namespace Replecs {
|
|
|
20
20
|
changed<T>(
|
|
21
21
|
this: ObserverWorld,
|
|
22
22
|
component: Id<T>,
|
|
23
|
-
callback: (e: Entity, id: Id<T>, value
|
|
23
|
+
callback: (e: Entity, id: Id<T>, value: T) => void
|
|
24
24
|
): () => void;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
type
|
|
27
|
+
type MemberFilterMap = Map<Player, boolean>;
|
|
28
|
+
type MemberFilter = Player | MemberFilterMap | undefined;
|
|
28
29
|
type Member = unknown;
|
|
29
30
|
|
|
30
31
|
interface MaskingController {
|
|
31
32
|
register_member(member: Member): void;
|
|
32
33
|
unregister_member(member: Member): void;
|
|
33
34
|
active_member(member: Member): void;
|
|
34
|
-
member_is_active(member: Member): boolean
|
|
35
|
+
member_is_active(member: Member): boolean;
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
export interface Components {
|
|
38
39
|
shared: Tag;
|
|
39
|
-
networked: Entity<MemberFilter
|
|
40
|
-
reliable: Entity<MemberFilter
|
|
41
|
-
unreliable: Entity<MemberFilter
|
|
42
|
-
pair: Entity<MemberFilter
|
|
40
|
+
networked: Entity<MemberFilter>;
|
|
41
|
+
reliable: Entity<MemberFilter>;
|
|
42
|
+
unreliable: Entity<MemberFilter>;
|
|
43
|
+
pair: Entity<MemberFilter>;
|
|
43
44
|
|
|
44
45
|
serdes: Entity<SerdesTable>;
|
|
45
46
|
bytespan: Entity<number>;
|
|
46
47
|
custom_id: Entity<((value: any) => Entity) | undefined>;
|
|
48
|
+
global_id: Entity<number>;
|
|
47
49
|
|
|
48
50
|
Shared: Tag;
|
|
49
|
-
Networked: Entity<MemberFilter
|
|
50
|
-
Reliable: Entity<MemberFilter
|
|
51
|
-
Unreliable: Entity<MemberFilter
|
|
52
|
-
Pair: Entity<MemberFilter
|
|
51
|
+
Networked: Entity<MemberFilter>;
|
|
52
|
+
Reliable: Entity<MemberFilter>;
|
|
53
|
+
Unreliable: Entity<MemberFilter>;
|
|
54
|
+
Pair: Entity<MemberFilter>;
|
|
53
55
|
|
|
54
56
|
Serdes: Entity<SerdesTable>;
|
|
55
57
|
Bytespan: Entity<number>;
|
|
56
|
-
CustomId: Entity<(
|
|
58
|
+
CustomId: Entity<(value: any) => Entity>;
|
|
59
|
+
GlobalId: Entity<number>;
|
|
57
60
|
}
|
|
58
61
|
|
|
59
62
|
export interface Client {
|
|
@@ -67,6 +70,10 @@ declare namespace Replecs {
|
|
|
67
70
|
apply_updates(buf: buffer, all_variants?: any[][]): void;
|
|
68
71
|
apply_unreliable(buf: buffer, all_variants?: any[][]): void;
|
|
69
72
|
apply_full(buf: buffer, all_variants?: any[][]): void;
|
|
73
|
+
parse_global_id(parser: (id: number) => Entity): void;
|
|
74
|
+
|
|
75
|
+
get_server_entity(client_entity: Entity): number | undefined;
|
|
76
|
+
get_client_entity(server_entity: number): Entity | undefined;
|
|
70
77
|
}
|
|
71
78
|
|
|
72
79
|
export interface Server {
|
|
@@ -78,7 +85,9 @@ declare namespace Replecs {
|
|
|
78
85
|
|
|
79
86
|
get_full(player: Player): LuaTuple<[buffer, any[][]]>;
|
|
80
87
|
collect_updates(): IterableFunction<LuaTuple<[Player, buffer, any[][]]>>;
|
|
81
|
-
collect_unreliable(): IterableFunction<
|
|
88
|
+
collect_unreliable(): IterableFunction<
|
|
89
|
+
LuaTuple<[Player, buffer, any[][]]>
|
|
90
|
+
>;
|
|
82
91
|
mark_player_ready(player: Player): void;
|
|
83
92
|
is_player_ready(player: Player): boolean;
|
|
84
93
|
|
|
@@ -89,7 +98,7 @@ declare namespace Replecs {
|
|
|
89
98
|
client: Client;
|
|
90
99
|
server: Server;
|
|
91
100
|
|
|
92
|
-
after_replication(
|
|
101
|
+
after_replication(callback: () => void): void;
|
|
93
102
|
}
|
|
94
103
|
|
|
95
104
|
export interface Replecs extends Components {
|
package/out/replecs/init.luau
CHANGED
|
@@ -1,83 +1,88 @@
|
|
|
1
|
-
local
|
|
2
|
-
local
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
local
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export type
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
__alive_tracking__ = jecs.tag(),
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
replecs.
|
|
36
|
-
replecs.
|
|
37
|
-
replecs.
|
|
38
|
-
replecs.
|
|
39
|
-
replecs.
|
|
40
|
-
replecs.
|
|
41
|
-
replecs.
|
|
42
|
-
replecs.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
jecs.meta(replecs.
|
|
47
|
-
jecs.meta(replecs.
|
|
48
|
-
jecs.meta(replecs.
|
|
49
|
-
jecs.meta(replecs.
|
|
50
|
-
jecs.meta(replecs.
|
|
51
|
-
jecs.meta(replecs.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
1
|
+
local jecs = require "./jecs"
|
|
2
|
+
local common = require "@self/common"
|
|
3
|
+
|
|
4
|
+
local client = require "@self/client"
|
|
5
|
+
local server = require "@self/server"
|
|
6
|
+
|
|
7
|
+
export type Server = server.Server
|
|
8
|
+
export type Client = client.Client
|
|
9
|
+
|
|
10
|
+
export type ReplecsLib = {
|
|
11
|
+
server: Server,
|
|
12
|
+
client: Client,
|
|
13
|
+
|
|
14
|
+
after_replication: (self: ReplecsLib, callback: () -> ()) -> (),
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
type MemberFilter = {
|
|
18
|
+
[Player]: boolean,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
local replecs = {
|
|
22
|
+
shared = jecs.tag(),
|
|
23
|
+
networked = jecs.component() :: jecs.Entity<(MemberFilter | Player)?>,
|
|
24
|
+
reliable = jecs.component() :: jecs.Entity<(MemberFilter | Player)?>,
|
|
25
|
+
unreliable = jecs.component() :: jecs.Entity<(MemberFilter | Player)?>,
|
|
26
|
+
pair = jecs.tag(),
|
|
27
|
+
|
|
28
|
+
serdes = jecs.component() :: jecs.Entity<common.Serdes>,
|
|
29
|
+
bytespan = jecs.component() :: jecs.Entity<number>,
|
|
30
|
+
custom_id = jecs.component() :: jecs.Entity<(any) -> jecs.Entity>,
|
|
31
|
+
global_id = jecs.component() :: jecs.Entity<number>,
|
|
32
|
+
__alive_tracking__ = jecs.tag(),
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
replecs.__index = replecs
|
|
36
|
+
replecs.Serdes = replecs.serdes
|
|
37
|
+
replecs.Bytespan = replecs.bytespan
|
|
38
|
+
replecs.CustomId = replecs.custom_id
|
|
39
|
+
replecs.Networked = replecs.networked
|
|
40
|
+
replecs.Reliable = replecs.reliable
|
|
41
|
+
replecs.Unreliable = replecs.unreliable
|
|
42
|
+
replecs.Pair = replecs.pair
|
|
43
|
+
replecs.Shared = replecs.shared
|
|
44
|
+
replecs.GlobalId = replecs.global_id
|
|
45
|
+
|
|
46
|
+
jecs.meta(replecs.serdes, jecs.Name, "replecs.serdes")
|
|
47
|
+
jecs.meta(replecs.bytespan, jecs.Name, "replecs.bytespan")
|
|
48
|
+
jecs.meta(replecs.custom_id, jecs.Name, "replecs.custom_id")
|
|
49
|
+
jecs.meta(replecs.networked, jecs.Name, "replecs.networked")
|
|
50
|
+
jecs.meta(replecs.reliable, jecs.Name, "replecs.reliable")
|
|
51
|
+
jecs.meta(replecs.unreliable, jecs.Name, "replecs.unreliable")
|
|
52
|
+
jecs.meta(replecs.pair, jecs.Name, "replecs.pair")
|
|
53
|
+
jecs.meta(replecs.shared, jecs.Name, "replecs.shared")
|
|
54
|
+
|
|
55
|
+
function replecs.create_server(world: jecs.World?): Server
|
|
56
|
+
return server.create(world, replecs)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
function replecs.create_client(world: jecs.World?): Client
|
|
60
|
+
return client.create(world, replecs)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
function replecs.create(world: jecs.World?): ReplecsLib
|
|
64
|
+
assert(game, "This is a Roblox specific function")
|
|
65
|
+
|
|
66
|
+
local RunService = game:GetService "RunService"
|
|
67
|
+
local lib = {} :: ReplecsLib
|
|
68
|
+
|
|
69
|
+
if RunService:IsServer() then
|
|
70
|
+
lib.server = server.create(world, replecs)
|
|
71
|
+
end
|
|
72
|
+
if RunService:IsClient() then
|
|
73
|
+
lib.client = client.create(world, replecs)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
return setmetatable(lib, replecs) :: any
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
function replecs.after_replication(lib: ReplecsLib, callback: () -> ())
|
|
80
|
+
local lib_client = lib.client
|
|
81
|
+
if lib_client then
|
|
82
|
+
lib_client:after_replication(callback)
|
|
83
|
+
else
|
|
84
|
+
callback()
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
return replecs
|