@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/common.luau
CHANGED
|
@@ -109,7 +109,7 @@ local function WORLD_GET<T>(world: World, entity: Entity, id: Component<T>): T
|
|
|
109
109
|
return world:get(entity, id) :: T
|
|
110
110
|
end
|
|
111
111
|
|
|
112
|
-
local function WORLD_TARGET(world: World, entity: Entity, rel: Component, index: number?):
|
|
112
|
+
local function WORLD_TARGET(world: World, entity: Entity, rel: Component, index: number?): Entity?
|
|
113
113
|
return world:target(entity, rel, index)
|
|
114
114
|
end
|
|
115
115
|
|
|
@@ -131,8 +131,22 @@ end
|
|
|
131
131
|
local PREREGISTER_COMPONENT = jecs.component
|
|
132
132
|
local PREREGISTER_TAG = jecs.tag
|
|
133
133
|
|
|
134
|
-
local
|
|
135
|
-
|
|
134
|
+
local ECS_COMPONENT = jecs.Component
|
|
135
|
+
|
|
136
|
+
-- jecs.is_tag misreports pairs that have not been used in the world yet, so
|
|
137
|
+
-- component-ness is resolved by hand: a plain id is a component when it has
|
|
138
|
+
-- jecs.Component; a pair takes its data from the relation, or from the
|
|
139
|
+
-- target when the relation is a tag
|
|
140
|
+
local function IS_COMPONENT(world: World, id: Component): boolean
|
|
141
|
+
if IS_PAIR(id) then
|
|
142
|
+
local relation = jecs.pair_first(world, id)
|
|
143
|
+
if world:has(relation, ECS_COMPONENT) then
|
|
144
|
+
return true
|
|
145
|
+
end
|
|
146
|
+
local target = jecs.pair_second(world, id)
|
|
147
|
+
return world:has(target, ECS_COMPONENT)
|
|
148
|
+
end
|
|
149
|
+
return world:has(id, ECS_COMPONENT)
|
|
136
150
|
end
|
|
137
151
|
|
|
138
152
|
local function HOOK_ADDED(world: World, id: Component, callback: (e: Entity, id: Component, value: any) -> ()): () -> ()
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
export type Cursor = {
|
|
2
|
+
offset: number,
|
|
3
|
+
buffer: buffer,
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
local cursor = {}
|
|
7
|
+
|
|
8
|
+
function cursor.new(): Cursor
|
|
9
|
+
return {
|
|
10
|
+
buffer = buffer.create(100),
|
|
11
|
+
offset = 0,
|
|
12
|
+
}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
function cursor.from(buf: buffer): Cursor
|
|
16
|
+
return {
|
|
17
|
+
buffer = buf,
|
|
18
|
+
offset = buffer.len(buf),
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
function cursor.from_offset(buf: buffer, offset: number): Cursor
|
|
23
|
+
return {
|
|
24
|
+
buffer = buf,
|
|
25
|
+
offset = offset,
|
|
26
|
+
}
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
function cursor.tryalloc(c: Cursor, bytes: number)
|
|
30
|
+
local buf = c.buffer
|
|
31
|
+
local offset = c.offset
|
|
32
|
+
local len = buffer.len(buf)
|
|
33
|
+
|
|
34
|
+
if len < offset + bytes then
|
|
35
|
+
local exponent = math.ceil(math.log((bytes + offset) / len, 1.5))
|
|
36
|
+
local new_len = math.floor(len * 1.5 ^ exponent)
|
|
37
|
+
if new_len < offset + bytes then
|
|
38
|
+
new_len = offset + bytes
|
|
39
|
+
end
|
|
40
|
+
local new = buffer.create(new_len)
|
|
41
|
+
buffer.copy(new, 0, buf, 0)
|
|
42
|
+
c.buffer = new
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
function cursor.write_buffer(c: Cursor, buf: buffer, start: number?, count: number?)
|
|
47
|
+
if start == nil and count == nil then
|
|
48
|
+
cursor.tryalloc(c, buffer.len(buf))
|
|
49
|
+
buffer.copy(c.buffer, c.offset, buf, 0, buffer.len(buf))
|
|
50
|
+
c.offset += buffer.len(buf)
|
|
51
|
+
else
|
|
52
|
+
local len = buffer.len(buf)
|
|
53
|
+
local available = len - (start or 0)
|
|
54
|
+
local write_count = count and math.min(available, count) or available
|
|
55
|
+
|
|
56
|
+
cursor.tryalloc(c, write_count)
|
|
57
|
+
buffer.copy(c.buffer, c.offset, buf, start or 0, write_count)
|
|
58
|
+
c.offset += write_count
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
function cursor.print(c: Cursor)
|
|
63
|
+
local bytes: { any } = { string.byte(buffer.tostring(c.buffer), 1, -1) }
|
|
64
|
+
local offset = 7
|
|
65
|
+
for i = 1, c.offset do
|
|
66
|
+
local byte = bytes[i] :: number
|
|
67
|
+
local digits = if byte == 0 then 1 else math.ceil(math.log10(1 + byte))
|
|
68
|
+
offset += digits + 1
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
local last_byte = bytes[c.offset + 1]
|
|
72
|
+
if last_byte then
|
|
73
|
+
local lastDigits = if last_byte == 0 then 1 else math.ceil(math.log10(1 + last_byte))
|
|
74
|
+
offset += lastDigits // 2
|
|
75
|
+
end
|
|
76
|
+
bytes[c.offset + 1] = `[{bytes[c.offset + 1] :: number}]` :: any
|
|
77
|
+
|
|
78
|
+
if #bytes == 0 or c.offset == buffer.len(c.buffer) then
|
|
79
|
+
table.insert(bytes, " ")
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
return `Pos: {c.offset} / {buffer.len(c.buffer)}\nBuf: \{ {table.concat(bytes, " ")} \}`
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
function cursor.writeu8(c: Cursor, value: number)
|
|
86
|
+
cursor.tryalloc(c, 1)
|
|
87
|
+
buffer.writeu8(c.buffer, c.offset, value)
|
|
88
|
+
c.offset += 1
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
function cursor.writeu16(c: Cursor, value: number)
|
|
92
|
+
cursor.tryalloc(c, 2)
|
|
93
|
+
buffer.writeu16(c.buffer, c.offset, value)
|
|
94
|
+
c.offset += 2
|
|
95
|
+
end
|
|
96
|
+
function cursor.writeu24(c: Cursor, value: number)
|
|
97
|
+
cursor.tryalloc(c, 3)
|
|
98
|
+
buffer.writeu8(c.buffer, c.offset, value)
|
|
99
|
+
buffer.writeu16(c.buffer, c.offset + 1, value // 256)
|
|
100
|
+
c.offset += 3
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
function cursor.writeu32(c: Cursor, value: number)
|
|
104
|
+
cursor.tryalloc(c, 4)
|
|
105
|
+
buffer.writeu32(c.buffer, c.offset, value :: any)
|
|
106
|
+
c.offset += 4
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
function cursor.writeu40(c: Cursor, value: number)
|
|
110
|
+
cursor.tryalloc(c, 5)
|
|
111
|
+
buffer.writeu8(c.buffer, c.offset, value)
|
|
112
|
+
buffer.writeu32(c.buffer, c.offset + 1, value // 256)
|
|
113
|
+
c.offset += 5
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
function cursor.writei8(c: Cursor, value: number)
|
|
117
|
+
cursor.tryalloc(c, 1)
|
|
118
|
+
buffer.writei8(c.buffer, c.offset, value)
|
|
119
|
+
c.offset += 1
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
function cursor.writei16(c: Cursor, value: number)
|
|
123
|
+
cursor.tryalloc(c, 2)
|
|
124
|
+
buffer.writei16(c.buffer, c.offset, value)
|
|
125
|
+
c.offset += 2
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
function cursor.writei32(c: Cursor, value: number)
|
|
129
|
+
cursor.tryalloc(c, 4)
|
|
130
|
+
buffer.writeu32(c.buffer, c.offset, value :: any)
|
|
131
|
+
c.offset += 4
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
function cursor.write_span(c: Cursor, value: number, span: number)
|
|
135
|
+
if span <= 0xFF then
|
|
136
|
+
cursor.writeu8(c, value)
|
|
137
|
+
elseif span <= 0xFFFF then
|
|
138
|
+
cursor.writeu16(c, value)
|
|
139
|
+
elseif span <= 0xFFFFFF then
|
|
140
|
+
cursor.writeu24(c, value)
|
|
141
|
+
elseif span <= 0xFFFFFFFF then
|
|
142
|
+
cursor.writeu32(c, value)
|
|
143
|
+
else
|
|
144
|
+
error "span too large"
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
function cursor.read_buffer(c: Cursor, len: number)
|
|
149
|
+
local retrieved = buffer.create(len)
|
|
150
|
+
buffer.copy(retrieved, 0, c.buffer, c.offset - len, len)
|
|
151
|
+
c.offset -= len
|
|
152
|
+
return retrieved
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
function cursor.readu8(c: Cursor): number
|
|
156
|
+
c.offset -= 1
|
|
157
|
+
return buffer.readu8(c.buffer, c.offset)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
function cursor.readu16(c: Cursor): number
|
|
161
|
+
c.offset -= 2
|
|
162
|
+
return buffer.readu16(c.buffer, c.offset)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
function cursor.readu24(c: Cursor): number
|
|
166
|
+
c.offset -= 3
|
|
167
|
+
local one = buffer.readu8(c.buffer, c.offset)
|
|
168
|
+
local two = buffer.readu16(c.buffer, c.offset + 1)
|
|
169
|
+
return one + two * 256
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
function cursor.readu32(c: Cursor): number
|
|
173
|
+
c.offset -= 4
|
|
174
|
+
return buffer.readu32(c.buffer, c.offset)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
function cursor.readu40(c: Cursor): number
|
|
178
|
+
c.offset -= 5
|
|
179
|
+
local one = buffer.readu8(c.buffer, c.offset)
|
|
180
|
+
local two = buffer.readu32(c.buffer, c.offset + 1)
|
|
181
|
+
return one + two * 256
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
function cursor.read_span(c: Cursor, span: number): number
|
|
185
|
+
if span <= 0xFF then
|
|
186
|
+
return cursor.readu8(c)
|
|
187
|
+
elseif span <= 0xFFFF then
|
|
188
|
+
return cursor.readu16(c)
|
|
189
|
+
elseif span <= 0xFFFFFF then
|
|
190
|
+
return cursor.readu24(c)
|
|
191
|
+
elseif span <= 0xFFFFFFFF then
|
|
192
|
+
return cursor.readu32(c)
|
|
193
|
+
else
|
|
194
|
+
error "span too large"
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
function cursor.readi8(c: Cursor): number
|
|
199
|
+
c.offset -= 1
|
|
200
|
+
return buffer.readi8(c.buffer, c.offset)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
function cursor.readi16(c: Cursor): number
|
|
204
|
+
c.offset -= 2
|
|
205
|
+
return buffer.readi16(c.buffer, c.offset)
|
|
206
|
+
end
|
|
207
|
+
function cursor.readi32(c: Cursor): number
|
|
208
|
+
c.offset -= 4
|
|
209
|
+
return buffer.readi32(c.buffer, c.offset)
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
function cursor.write_vlq(c: Cursor, value: number)
|
|
213
|
+
local x0 = value // 1% 128
|
|
214
|
+
local x1 = value // 128% 128
|
|
215
|
+
local x2 = value // 16384% 128
|
|
216
|
+
local x3 = value // 2097152% 128
|
|
217
|
+
|
|
218
|
+
if x3 ~= 0 then
|
|
219
|
+
cursor.tryalloc(c, 4)
|
|
220
|
+
cursor.writeu32(c, x0 * 16777216+ x1 * 65536+ x2 * 256 + x3 + 128)
|
|
221
|
+
elseif x2 ~= 0 then
|
|
222
|
+
cursor.tryalloc(c, 3)
|
|
223
|
+
cursor.writeu24(c, x0 * 65536+ x1 * 256 + x2 + 128)
|
|
224
|
+
elseif x1 ~= 0 then
|
|
225
|
+
cursor.tryalloc(c, 2)
|
|
226
|
+
cursor.writeu16(c, x0 * 256 + x1 + 128)
|
|
227
|
+
else
|
|
228
|
+
cursor.tryalloc(c, 1)
|
|
229
|
+
cursor.writeu8(c, x0 + 128)
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
function cursor.read_vlq(c: Cursor): number
|
|
234
|
+
local b = cursor.readu8(c)
|
|
235
|
+
if b >= 128 then
|
|
236
|
+
return b - 128
|
|
237
|
+
end
|
|
238
|
+
local x = b
|
|
239
|
+
|
|
240
|
+
b = cursor.readu8(c)
|
|
241
|
+
if b >= 128 then
|
|
242
|
+
return x + (b - 128) * 128
|
|
243
|
+
end
|
|
244
|
+
x += b * 128
|
|
245
|
+
|
|
246
|
+
b = cursor.readu8(c)
|
|
247
|
+
if b >= 128 then
|
|
248
|
+
return x + (b - 128) * 16384
|
|
249
|
+
end
|
|
250
|
+
x += b * 16384
|
|
251
|
+
|
|
252
|
+
b = cursor.readu8(c)
|
|
253
|
+
if b >= 128 then
|
|
254
|
+
return x + (b - 128) * 2097152
|
|
255
|
+
end
|
|
256
|
+
x += b * 2097152
|
|
257
|
+
|
|
258
|
+
error "vlq length too large"
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
function cursor.close(c: Cursor): buffer
|
|
262
|
+
local final = buffer.create(c.offset)
|
|
263
|
+
buffer.copy(final, 0, c.buffer, 0, c.offset)
|
|
264
|
+
c.buffer = final
|
|
265
|
+
return final
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
return cursor
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
local types = require (script.Parent:WaitForChild('types'))
|
|
2
|
+
local common = require (script.Parent:WaitForChild('common'))
|
|
3
|
+
|
|
4
|
+
type Component = common.Component
|
|
5
|
+
type Entity = common.Entity
|
|
6
|
+
type World = common.World
|
|
7
|
+
|
|
8
|
+
local handshake = {}
|
|
9
|
+
|
|
10
|
+
function handshake.generate_handshake(shared: types.Shared): types.HandshakeInfo
|
|
11
|
+
local component_to_name: { [Entity]: string } = {}
|
|
12
|
+
local handshake: types.HandshakeInfo = {
|
|
13
|
+
components = {},
|
|
14
|
+
custom_ids = {},
|
|
15
|
+
serdes = {},
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
for component_name, component in shared.components.lookup do
|
|
19
|
+
handshake.components[component_name] = true
|
|
20
|
+
component_to_name[component] = component_name
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
for custom_id in shared.custom_ids.lookup do
|
|
24
|
+
handshake.custom_ids[custom_id] = true
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
for component, serdes in shared.serdes do
|
|
28
|
+
local name = component_to_name[component]
|
|
29
|
+
if not name then
|
|
30
|
+
continue
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
handshake.serdes[name] = {
|
|
34
|
+
includes_variants = serdes.includes_variants,
|
|
35
|
+
bytespan = serdes.bytespan,
|
|
36
|
+
}
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
return handshake
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
function handshake.verify_handshake(
|
|
43
|
+
shared: types.Shared,
|
|
44
|
+
handshake: types.HandshakeInfo,
|
|
45
|
+
handshake_side: string,
|
|
46
|
+
verify_side: string
|
|
47
|
+
): (boolean, string?)
|
|
48
|
+
local component_to_name: { [Entity]: string } = {}
|
|
49
|
+
|
|
50
|
+
for component_name in handshake.components do
|
|
51
|
+
if not shared.components.lookup[component_name] then
|
|
52
|
+
return false, `missing shared component "{component_name}" in {verify_side}`
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
for component_name, component in shared.components.lookup do
|
|
56
|
+
if not handshake.components[component_name] then
|
|
57
|
+
return false, `missing shared component "{component_name}" in {handshake_side}`
|
|
58
|
+
end
|
|
59
|
+
component_to_name[component] = component_name
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
for custom_id in handshake.custom_ids do
|
|
63
|
+
if not shared.custom_ids.lookup[custom_id] then
|
|
64
|
+
return false, `missing custom id "{custom_id}" in {verify_side}`
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
for custom_id in shared.custom_ids.lookup do
|
|
68
|
+
if not handshake.custom_ids[custom_id] then
|
|
69
|
+
return false, `missing custom id "{custom_id}" in {handshake_side}`
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
for component_name, serdes_info in handshake.serdes do
|
|
74
|
+
local component = shared.components.lookup[component_name]
|
|
75
|
+
if not component then
|
|
76
|
+
common.log_warn(`{handshake_side} registered a serdes for "{component_name}" that {verify_side} doesn't have`)
|
|
77
|
+
continue
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
local serdes = shared.serdes[component]
|
|
81
|
+
if not serdes then
|
|
82
|
+
return false, `missing serdes for component "{component_name}" in {verify_side}`
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
if (serdes_info.includes_variants or false) ~= (serdes.includes_variants or false) then
|
|
86
|
+
return false,
|
|
87
|
+
`mismatched includes_variants for component "{component_name}": ({serdes_info.includes_variants} ~= {serdes.includes_variants})`
|
|
88
|
+
end
|
|
89
|
+
if serdes_info.bytespan ~= serdes.bytespan then
|
|
90
|
+
return false,
|
|
91
|
+
`mismatched bytespan for component "{component_name}": ({serdes_info.bytespan} ~= {serdes.bytespan})`
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
for component in shared.serdes do
|
|
95
|
+
local component_name = component_to_name[component]
|
|
96
|
+
if not component_name then
|
|
97
|
+
continue
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
if not handshake.serdes[component_name] then
|
|
101
|
+
common.log_warn(`{verify_side} registered a serdes for "{component_name}" that {handshake_side} doesn't have`)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
return true, nil
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
return handshake
|
package/out/replecs/init.luau
CHANGED
|
@@ -30,11 +30,17 @@ export type ReplecsLib = {
|
|
|
30
30
|
|
|
31
31
|
set_serdes: <T>(self: ReplecsLib, id: Component<T>, serdes: types.Serdes<T>) -> (),
|
|
32
32
|
remove_serdes: (self: ReplecsLib, id: Component) -> (),
|
|
33
|
+
set_preprocessor: <B, A>(self: ReplecsLib, id: Component<B>, preprocessor: types.Preprocessor<B, A>) -> (),
|
|
34
|
+
remove_preprocessor: (self: ReplecsLib, id: Component) -> (),
|
|
35
|
+
set_delta_serializer: <T, D>(self: ReplecsLib, id: Component<T>, delta: types.DeltaSerializer<T, D>) -> (),
|
|
36
|
+
remove_delta_serializer: (self: ReplecsLib, id: Component) -> (),
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
type Replecs = types.Components & {
|
|
36
40
|
__index: any,
|
|
37
41
|
VERSION: string,
|
|
42
|
+
MAX_CLIENTS: number,
|
|
43
|
+
|
|
38
44
|
create: (world: World?) -> ReplecsLib,
|
|
39
45
|
|
|
40
46
|
create_server: (world: World?) -> Server,
|
|
@@ -44,6 +50,7 @@ type Replecs = types.Components & {
|
|
|
44
50
|
|
|
45
51
|
local replecs = {}
|
|
46
52
|
replecs.VERSION = VERSION
|
|
53
|
+
replecs.MAX_CLIENTS = 128
|
|
47
54
|
replecs.__index = replecs
|
|
48
55
|
|
|
49
56
|
local PREREGISTRATION = common.preregistration
|
|
@@ -54,13 +61,12 @@ if PREREGISTRATION then
|
|
|
54
61
|
utils.add_component_names(components, common.add_preregistered_name)
|
|
55
62
|
|
|
56
63
|
jecs.meta(components.custom, jecs.Exclusive)
|
|
57
|
-
jecs.meta(components.global, jecs.Exclusive)
|
|
58
64
|
end
|
|
59
65
|
|
|
60
|
-
local COMPONENTS = if PREREGISTRATION then replecs
|
|
66
|
+
local COMPONENTS: Replecs = if PREREGISTRATION then replecs else nil :: any
|
|
61
67
|
|
|
62
68
|
function replecs.create_server(world: World?): Server
|
|
63
|
-
return server.create(world, COMPONENTS)
|
|
69
|
+
return server.create(world, COMPONENTS, replecs.MAX_CLIENTS)
|
|
64
70
|
end
|
|
65
71
|
|
|
66
72
|
function replecs.create_client(world: World?): Client
|
|
@@ -68,25 +74,27 @@ function replecs.create_client(world: World?): Client
|
|
|
68
74
|
end
|
|
69
75
|
|
|
70
76
|
function replecs.create(world: World?): ReplecsLib
|
|
71
|
-
assert(
|
|
77
|
+
assert(
|
|
78
|
+
game,
|
|
79
|
+
"replecs.create() is only for roblox, call create_client or create_server manually depending on your setup"
|
|
80
|
+
)
|
|
81
|
+
|
|
72
82
|
local RunService = game:GetService "RunService"
|
|
73
83
|
local self = {} :: ReplecsLib
|
|
74
84
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
self.components = utils.create_components(utils.tag_factory(world), utils.component_factory(world))
|
|
79
|
-
utils.add_component_names(self.components, function(component, name)
|
|
80
|
-
common.add_name(world, component, name)
|
|
81
|
-
end)
|
|
82
|
-
end
|
|
85
|
+
-- without preregistration the components come from the world: shared by
|
|
86
|
+
-- both sides when it is known here, else created by whichever inits first
|
|
87
|
+
local components = COMPONENTS or (if world then utils.create_world_components(world) else nil) :: any
|
|
83
88
|
|
|
84
89
|
if RunService:IsServer() then
|
|
85
|
-
self.server = server.create(world,
|
|
90
|
+
self.server = server.create(world, components, replecs.MAX_CLIENTS)
|
|
91
|
+
components = self.server.components
|
|
86
92
|
end
|
|
87
93
|
if RunService:IsClient() then
|
|
88
|
-
self.client = client.create(world,
|
|
94
|
+
self.client = client.create(world, components)
|
|
95
|
+
components = self.client.components
|
|
89
96
|
end
|
|
97
|
+
self.components = components
|
|
90
98
|
|
|
91
99
|
return setmetatable(self, replecs) :: any
|
|
92
100
|
end
|
|
@@ -131,4 +139,40 @@ function replecs.remove_serdes(lib: ReplecsLib, id: Component)
|
|
|
131
139
|
end
|
|
132
140
|
end
|
|
133
141
|
|
|
134
|
-
|
|
142
|
+
function replecs.set_preprocessor(lib: ReplecsLib, id: Component, preprocessor: types.Preprocessor)
|
|
143
|
+
if lib.server then
|
|
144
|
+
lib.server:set_preprocessor(id, preprocessor)
|
|
145
|
+
end
|
|
146
|
+
if lib.client then
|
|
147
|
+
lib.client:set_preprocessor(id, preprocessor)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
function replecs.remove_preprocessor(lib: ReplecsLib, id: Component)
|
|
152
|
+
if lib.server then
|
|
153
|
+
lib.server:remove_preprocessor(id)
|
|
154
|
+
end
|
|
155
|
+
if lib.client then
|
|
156
|
+
lib.client:remove_preprocessor(id)
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
function replecs.set_delta_serializer(lib: ReplecsLib, id: Component, delta_serializer: types.DeltaSerializer)
|
|
161
|
+
if lib.server then
|
|
162
|
+
lib.server:set_delta_serializer(id, delta_serializer)
|
|
163
|
+
end
|
|
164
|
+
if lib.client then
|
|
165
|
+
lib.client:set_delta_serializer(id, delta_serializer)
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
function replecs.remove_delta_serializer(lib: ReplecsLib, id: Component)
|
|
170
|
+
if lib.server then
|
|
171
|
+
lib.server:remove_delta_serializer(id)
|
|
172
|
+
end
|
|
173
|
+
if lib.client then
|
|
174
|
+
lib.client:remove_delta_serializer(id)
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
return (replecs :: any) :: Replecs
|