@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/utils.luau
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--!optimize 2
|
|
2
2
|
--!native
|
|
3
3
|
|
|
4
|
-
local
|
|
4
|
+
local jecs = require (script.Parent.Parent:WaitForChild('jecs'))
|
|
5
5
|
local common = require (script.Parent:WaitForChild('common'))
|
|
6
6
|
local types = require (script.Parent:WaitForChild('types'))
|
|
7
7
|
|
|
@@ -9,175 +9,10 @@ type World = common.World
|
|
|
9
9
|
type Entity = common.Entity
|
|
10
10
|
type Component = common.Component
|
|
11
11
|
|
|
12
|
-
export type Cursor = {
|
|
13
|
-
offset: number,
|
|
14
|
-
buffer: buffer,
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
local ECS_NAME = common.ecs_name
|
|
18
12
|
local RELATIONSHPIS = common.relationships
|
|
19
13
|
|
|
20
14
|
local utils = {}
|
|
21
15
|
|
|
22
|
-
function utils.create_shared_lookup<T>(lookup: { [string]: T }): types.SharedInfo<T>
|
|
23
|
-
local keys = {}
|
|
24
|
-
local indexes = {}
|
|
25
|
-
local members = {}
|
|
26
|
-
|
|
27
|
-
for name in lookup do
|
|
28
|
-
table.insert(keys, name)
|
|
29
|
-
end
|
|
30
|
-
table.sort(keys)
|
|
31
|
-
|
|
32
|
-
for index, name in keys do
|
|
33
|
-
local member = lookup[name]
|
|
34
|
-
members[member] = index
|
|
35
|
-
indexes[index] = member
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
return {
|
|
39
|
-
lookup = lookup,
|
|
40
|
-
keys = keys,
|
|
41
|
-
indexes = indexes,
|
|
42
|
-
members = members,
|
|
43
|
-
}
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
function utils.generate_handshake(shared: types.Shared): types.HandshakeInfo
|
|
47
|
-
local component_to_name: { [Entity]: string } = {}
|
|
48
|
-
local handshake: types.HandshakeInfo = {
|
|
49
|
-
components = {},
|
|
50
|
-
custom_ids = {},
|
|
51
|
-
serdes = {},
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
for component_name, component in shared.components.lookup do
|
|
55
|
-
handshake.components[component_name] = true
|
|
56
|
-
component_to_name[component] = component_name
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
for custom_id in shared.custom_ids.lookup do
|
|
60
|
-
handshake.custom_ids[custom_id] = true
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
for component, serdes in shared.serdes do
|
|
64
|
-
local name = component_to_name[component]
|
|
65
|
-
if not name then
|
|
66
|
-
continue
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
handshake.serdes[name] = {
|
|
70
|
-
includes_variants = serdes.includes_variants,
|
|
71
|
-
bytespan = serdes.bytespan,
|
|
72
|
-
}
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
return handshake
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
function utils.verify_handshake(
|
|
79
|
-
shared: types.Shared,
|
|
80
|
-
handshake: types.HandshakeInfo,
|
|
81
|
-
handshake_side: string,
|
|
82
|
-
verify_side: string
|
|
83
|
-
): (boolean, string?)
|
|
84
|
-
local component_to_name: { [Entity]: string } = {}
|
|
85
|
-
|
|
86
|
-
for component_name in handshake.components do
|
|
87
|
-
if not shared.components.lookup[component_name] then
|
|
88
|
-
return false, `missing shared component "{component_name}" in {verify_side}`
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
for component_name, component in shared.components.lookup do
|
|
92
|
-
if not handshake.components[component_name] then
|
|
93
|
-
return false, `missing shared component "{component_name}" in {handshake_side}`
|
|
94
|
-
end
|
|
95
|
-
component_to_name[component] = component_name
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
for custom_id in handshake.custom_ids do
|
|
99
|
-
if not shared.custom_ids.lookup[custom_id] then
|
|
100
|
-
return false, `missing custom id "{custom_id}" in {verify_side}`
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
for custom_id in shared.custom_ids.lookup do
|
|
104
|
-
if not handshake.custom_ids[custom_id] then
|
|
105
|
-
return false, `missing custom id "{custom_id}" in {handshake_side}`
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
for component_name, serdes_info in handshake.serdes do
|
|
110
|
-
local component = shared.components.lookup[component_name]
|
|
111
|
-
if not component then
|
|
112
|
-
warn(`{handshake_side} registered a serdes for "{component_name}" that {verify_side} doesn't have`)
|
|
113
|
-
continue
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
local serdes = shared.serdes[component]
|
|
117
|
-
if not serdes then
|
|
118
|
-
return false, `missing serdes for component "{component_name}" in {verify_side}`
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
if (serdes_info.includes_variants or false) ~= (serdes.includes_variants or false) then
|
|
122
|
-
return false,
|
|
123
|
-
`mismatched includes_variants for component "{component_name}": ({serdes_info.includes_variants} ~= {serdes.includes_variants})`
|
|
124
|
-
end
|
|
125
|
-
if serdes_info.bytespan ~= serdes.bytespan then
|
|
126
|
-
return false,
|
|
127
|
-
`mismatched bytespan for component "{component_name}": ({serdes_info.bytespan} ~= {serdes.bytespan})`
|
|
128
|
-
end
|
|
129
|
-
end
|
|
130
|
-
for component in shared.serdes do
|
|
131
|
-
local component_name = component_to_name[component]
|
|
132
|
-
if not component_name then
|
|
133
|
-
continue
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
if not handshake.serdes[component_name] then
|
|
137
|
-
warn(`{verify_side} registered a serdes for "{component_name}" that {handshake_side} doesn't have`)
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
return true, nil
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
function utils.resolved_shared(
|
|
145
|
-
world: World,
|
|
146
|
-
components: types.Components,
|
|
147
|
-
registered_custom_ids: { [customid.CustomId]: boolean },
|
|
148
|
-
serdes: { [Component]: types.Serdes }
|
|
149
|
-
): types.Shared
|
|
150
|
-
local shared = {} :: types.Shared
|
|
151
|
-
|
|
152
|
-
local components_lookup: { [string]: Entity } = table.clone(common.implicitly_shared)
|
|
153
|
-
local custom_ids_lookup = {}
|
|
154
|
-
|
|
155
|
-
for component, name in world:query(ECS_NAME):with(components.shared):iter() do
|
|
156
|
-
if components_lookup[name] then
|
|
157
|
-
common.log_error(`detected two components with the same {name} name: ({components_lookup[name]}, {component})`)
|
|
158
|
-
end
|
|
159
|
-
components_lookup[name] = component
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
for component in world:query(components.shared):without(ECS_NAME):iter() do
|
|
163
|
-
common.log_warn(`shared component: {component} has no name assigned.`)
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
for custom in registered_custom_ids do
|
|
167
|
-
custom_ids_lookup[custom.identifier] = custom
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
for custom in registered_custom_ids do
|
|
171
|
-
custom_ids_lookup[custom.identifier] = custom
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
shared.serdes = serdes
|
|
175
|
-
shared.components = utils.create_shared_lookup(components_lookup)
|
|
176
|
-
shared.custom_ids = utils.create_shared_lookup(custom_ids_lookup)
|
|
177
|
-
|
|
178
|
-
return shared
|
|
179
|
-
end
|
|
180
|
-
|
|
181
16
|
function utils.create_components(tag: () -> Component, component: () -> Component, push: types.Components?)
|
|
182
17
|
local components = push or {} :: types.Components
|
|
183
18
|
components.shared = tag()
|
|
@@ -186,13 +21,13 @@ function utils.create_components(tag: () -> Component, component: () -> Componen
|
|
|
186
21
|
if RELATIONSHPIS then
|
|
187
22
|
components.reliable = component()
|
|
188
23
|
components.unreliable = component()
|
|
24
|
+
components.once = component()
|
|
189
25
|
components.relation = component()
|
|
190
26
|
|
|
191
27
|
components.custom = tag()
|
|
192
28
|
end
|
|
193
29
|
components.custom_handler = component()
|
|
194
30
|
components.serdes = component()
|
|
195
|
-
components.global = component()
|
|
196
31
|
components.__alive_tracking__ = tag()
|
|
197
32
|
|
|
198
33
|
components.Shared = components.shared
|
|
@@ -200,13 +35,13 @@ function utils.create_components(tag: () -> Component, component: () -> Componen
|
|
|
200
35
|
if RELATIONSHPIS then
|
|
201
36
|
components.Reliable = components.reliable
|
|
202
37
|
components.Unreliable = components.unreliable
|
|
38
|
+
components.Once = components.once
|
|
203
39
|
components.Relation = components.relation
|
|
204
40
|
|
|
205
41
|
components.Custom = components.custom
|
|
206
42
|
end
|
|
207
43
|
components.CustomHandler = components.custom_handler
|
|
208
44
|
components.Serdes = components.serdes
|
|
209
|
-
components.Global = components.global
|
|
210
45
|
return components
|
|
211
46
|
end
|
|
212
47
|
|
|
@@ -216,13 +51,13 @@ function utils.add_component_names(components: types.Components, set: (component
|
|
|
216
51
|
set(components.networked, "replecs.networked")
|
|
217
52
|
set(components.reliable, "replecs.reliable")
|
|
218
53
|
set(components.unreliable, "replecs.unreliable")
|
|
54
|
+
set(components.once, "replecs.once")
|
|
219
55
|
set(components.relation, "replecs.relation")
|
|
220
56
|
|
|
221
57
|
set(components.custom, "replecs.custom")
|
|
222
58
|
end
|
|
223
59
|
set(components.custom_handler, "replecs.custom_handler")
|
|
224
60
|
set(components.serdes, "replecs.serdes")
|
|
225
|
-
set(components.global, "replecs.global")
|
|
226
61
|
|
|
227
62
|
set(components.__alive_tracking__, "replecs.__alive_tracking__")
|
|
228
63
|
end
|
|
@@ -239,584 +74,18 @@ function utils.tag_factory(world: World)
|
|
|
239
74
|
end
|
|
240
75
|
end
|
|
241
76
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
end
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
return {
|
|
253
|
-
buffer = buf,
|
|
254
|
-
offset = buffer.len(buf),
|
|
255
|
-
}
|
|
256
|
-
end
|
|
257
|
-
|
|
258
|
-
function cursor.from_offset(buf: buffer, offset: number): Cursor
|
|
259
|
-
return {
|
|
260
|
-
buffer = buf,
|
|
261
|
-
offset = offset,
|
|
262
|
-
}
|
|
263
|
-
end
|
|
264
|
-
|
|
265
|
-
function cursor.tryalloc(c: Cursor, bytes: number)
|
|
266
|
-
local buf = c.buffer
|
|
267
|
-
local offset = c.offset
|
|
268
|
-
local len = buffer.len(buf)
|
|
269
|
-
|
|
270
|
-
if len < offset + bytes then
|
|
271
|
-
local exponent = math.ceil(math.log((bytes + offset) / len, 1.5))
|
|
272
|
-
local new = buffer.create(len * 1.5 ^ exponent)
|
|
273
|
-
buffer.copy(new, 0, buf, 0)
|
|
274
|
-
c.buffer = new
|
|
275
|
-
end
|
|
276
|
-
end
|
|
277
|
-
|
|
278
|
-
function cursor.write_buffer(c: Cursor, buf: buffer, start: number?, count: number?)
|
|
279
|
-
if start == nil and count == nil then
|
|
280
|
-
cursor.tryalloc(c, buffer.len(buf))
|
|
281
|
-
buffer.copy(c.buffer, c.offset, buf, 0, buffer.len(buf))
|
|
282
|
-
c.offset += buffer.len(buf)
|
|
283
|
-
else
|
|
284
|
-
local len = buffer.len(buf)
|
|
285
|
-
local available = len - (start or 0)
|
|
286
|
-
local write_count = count and math.min(available, count) or available
|
|
287
|
-
|
|
288
|
-
cursor.tryalloc(c, write_count)
|
|
289
|
-
buffer.copy(c.buffer, c.offset, buf, start or 0, write_count)
|
|
290
|
-
c.offset += write_count
|
|
291
|
-
end
|
|
292
|
-
end
|
|
293
|
-
|
|
294
|
-
function cursor.print(c: Cursor)
|
|
295
|
-
local bytes: { any } = { string.byte(buffer.tostring(c.buffer), 1, -1) }
|
|
296
|
-
local offset = 7
|
|
297
|
-
for i = 1, c.offset do
|
|
298
|
-
local byte = bytes[i] :: number
|
|
299
|
-
local digits = if byte == 0 then 1 else math.ceil(math.log10(1 + byte))
|
|
300
|
-
offset += digits + 1
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
local last_byte = bytes[c.offset + 1]
|
|
304
|
-
if last_byte then
|
|
305
|
-
local lastDigits = if last_byte == 0 then 1 else math.ceil(math.log10(1 + last_byte))
|
|
306
|
-
offset += lastDigits // 2
|
|
307
|
-
end
|
|
308
|
-
bytes[c.offset + 1] = `[{bytes[c.offset + 1] :: number}]` :: any
|
|
309
|
-
|
|
310
|
-
if #bytes == 0 or c.offset == buffer.len(c.buffer) then
|
|
311
|
-
table.insert(bytes, " ")
|
|
312
|
-
end
|
|
313
|
-
|
|
314
|
-
return `Pos: {c.offset} / {buffer.len(c.buffer)}\nBuf: \{ {table.concat(bytes, " ")} \}`
|
|
315
|
-
end
|
|
316
|
-
|
|
317
|
-
function cursor.writeu8(c: Cursor, value: number)
|
|
318
|
-
cursor.tryalloc(c, 1)
|
|
319
|
-
buffer.writeu8(c.buffer, c.offset, value)
|
|
320
|
-
c.offset += 1
|
|
321
|
-
end
|
|
322
|
-
|
|
323
|
-
function cursor.writeu16(c: Cursor, value: number)
|
|
324
|
-
cursor.tryalloc(c, 2)
|
|
325
|
-
buffer.writeu16(c.buffer, c.offset, value)
|
|
326
|
-
c.offset += 2
|
|
327
|
-
end
|
|
328
|
-
function cursor.writeu24(c: Cursor, value: number)
|
|
329
|
-
cursor.tryalloc(c, 3)
|
|
330
|
-
buffer.writeu8(c.buffer, c.offset, value)
|
|
331
|
-
buffer.writeu16(c.buffer, c.offset + 1, value // 256)
|
|
332
|
-
c.offset += 3
|
|
333
|
-
end
|
|
334
|
-
|
|
335
|
-
function cursor.writeu32(c: Cursor, value: number)
|
|
336
|
-
cursor.tryalloc(c, 4)
|
|
337
|
-
buffer.writeu32(c.buffer, c.offset, value :: any)
|
|
338
|
-
c.offset += 4
|
|
339
|
-
end
|
|
340
|
-
|
|
341
|
-
function cursor.writeu40(c: Cursor, value: number)
|
|
342
|
-
cursor.tryalloc(c, 5)
|
|
343
|
-
buffer.writeu8(c.buffer, c.offset, value)
|
|
344
|
-
buffer.writeu32(c.buffer, c.offset + 1, value // 256)
|
|
345
|
-
c.offset += 5
|
|
346
|
-
end
|
|
347
|
-
|
|
348
|
-
function cursor.writei8(c: Cursor, value: number)
|
|
349
|
-
cursor.tryalloc(c, 1)
|
|
350
|
-
buffer.writei8(c.buffer, c.offset, value)
|
|
351
|
-
c.offset += 1
|
|
352
|
-
end
|
|
353
|
-
|
|
354
|
-
function cursor.writei16(c: Cursor, value: number)
|
|
355
|
-
cursor.tryalloc(c, 2)
|
|
356
|
-
buffer.writei16(c.buffer, c.offset, value)
|
|
357
|
-
c.offset += 2
|
|
358
|
-
end
|
|
359
|
-
|
|
360
|
-
function cursor.writei32(c: Cursor, value: number)
|
|
361
|
-
cursor.tryalloc(c, 4)
|
|
362
|
-
buffer.writeu32(c.buffer, c.offset, value :: any)
|
|
363
|
-
c.offset += 4
|
|
364
|
-
end
|
|
365
|
-
|
|
366
|
-
function cursor.write_span(c: Cursor, value: number, span: number)
|
|
367
|
-
if span <= 0xFF then
|
|
368
|
-
cursor.writeu8(c, value)
|
|
369
|
-
elseif span <= 0xFFFF then
|
|
370
|
-
cursor.writeu16(c, value)
|
|
371
|
-
elseif span <= 0xFFFFFF then
|
|
372
|
-
cursor.writeu24(c, value)
|
|
373
|
-
elseif span <= 0xFFFFFFFF then
|
|
374
|
-
cursor.writeu32(c, value)
|
|
375
|
-
else
|
|
376
|
-
error "span too large"
|
|
377
|
-
end
|
|
378
|
-
end
|
|
379
|
-
|
|
380
|
-
function cursor.read_buffer(c: Cursor, len: number)
|
|
381
|
-
local retrieved = buffer.create(len)
|
|
382
|
-
buffer.copy(retrieved, 0, c.buffer, c.offset - len, len)
|
|
383
|
-
c.offset -= len
|
|
384
|
-
return retrieved
|
|
385
|
-
end
|
|
386
|
-
|
|
387
|
-
function cursor.readu8(c: Cursor): number
|
|
388
|
-
c.offset -= 1
|
|
389
|
-
return buffer.readu8(c.buffer, c.offset)
|
|
390
|
-
end
|
|
391
|
-
|
|
392
|
-
function cursor.readu16(c: Cursor): number
|
|
393
|
-
c.offset -= 2
|
|
394
|
-
return buffer.readu16(c.buffer, c.offset)
|
|
395
|
-
end
|
|
396
|
-
|
|
397
|
-
function cursor.readu24(c: Cursor): number
|
|
398
|
-
c.offset -= 3
|
|
399
|
-
local one = buffer.readu8(c.buffer, c.offset)
|
|
400
|
-
local two = buffer.readu16(c.buffer, c.offset + 1)
|
|
401
|
-
return one + two * 256
|
|
402
|
-
end
|
|
403
|
-
|
|
404
|
-
function cursor.readu32(c: Cursor): number
|
|
405
|
-
c.offset -= 4
|
|
406
|
-
return buffer.readu32(c.buffer, c.offset)
|
|
407
|
-
end
|
|
408
|
-
|
|
409
|
-
function cursor.readu40(c: Cursor): number
|
|
410
|
-
c.offset -= 5
|
|
411
|
-
local one = buffer.readu8(c.buffer, c.offset)
|
|
412
|
-
local two = buffer.readu32(c.buffer, c.offset + 1)
|
|
413
|
-
return one + two * 256
|
|
414
|
-
end
|
|
415
|
-
|
|
416
|
-
function cursor.read_span(c: Cursor, span: number): number
|
|
417
|
-
if span <= 0xFF then
|
|
418
|
-
return cursor.readu8(c)
|
|
419
|
-
elseif span <= 0xFFFF then
|
|
420
|
-
return cursor.readu16(c)
|
|
421
|
-
elseif span <= 0xFFFFFF then
|
|
422
|
-
return cursor.readu24(c)
|
|
423
|
-
elseif span <= 0xFFFFFFFF then
|
|
424
|
-
return cursor.readu32(c)
|
|
425
|
-
else
|
|
426
|
-
error "span too large"
|
|
427
|
-
end
|
|
428
|
-
end
|
|
429
|
-
|
|
430
|
-
function cursor.readi8(c: Cursor): number
|
|
431
|
-
c.offset -= 1
|
|
432
|
-
return buffer.readi8(c.buffer, c.offset)
|
|
433
|
-
end
|
|
434
|
-
|
|
435
|
-
function cursor.readi16(c: Cursor): number
|
|
436
|
-
c.offset -= 2
|
|
437
|
-
return buffer.readi16(c.buffer, c.offset)
|
|
438
|
-
end
|
|
439
|
-
function cursor.readi32(c: Cursor): number
|
|
440
|
-
c.offset -= 4
|
|
441
|
-
return buffer.readi32(c.buffer, c.offset)
|
|
442
|
-
end
|
|
443
|
-
|
|
444
|
-
function cursor.write_vlq(c: Cursor, value: number)
|
|
445
|
-
local x0 = value // 1% 128
|
|
446
|
-
local x1 = value // 128% 128
|
|
447
|
-
local x2 = value // 16384% 128
|
|
448
|
-
local x3 = value // 2097152% 128
|
|
449
|
-
|
|
450
|
-
if x3 ~= 0 then
|
|
451
|
-
cursor.tryalloc(c, 4)
|
|
452
|
-
cursor.writeu32(c, x0 * 16777216+ x1 * 65536+ x2 * 256 + x3 + 128)
|
|
453
|
-
elseif x2 ~= 0 then
|
|
454
|
-
cursor.tryalloc(c, 3)
|
|
455
|
-
cursor.writeu24(c, x0 * 65536+ x1 * 256 + x2 + 128)
|
|
456
|
-
elseif x1 ~= 0 then
|
|
457
|
-
cursor.tryalloc(c, 2)
|
|
458
|
-
cursor.writeu16(c, x0 * 256 + x1 + 128)
|
|
459
|
-
else
|
|
460
|
-
cursor.tryalloc(c, 1)
|
|
461
|
-
cursor.writeu8(c, x0 + 128)
|
|
462
|
-
end
|
|
463
|
-
end
|
|
464
|
-
|
|
465
|
-
function cursor.read_vlq(c: Cursor): number
|
|
466
|
-
local b = cursor.readu8(c)
|
|
467
|
-
if b >= 128 then
|
|
468
|
-
return b - 128
|
|
469
|
-
end
|
|
470
|
-
local x = b
|
|
471
|
-
|
|
472
|
-
b = cursor.readu8(c)
|
|
473
|
-
if b >= 128 then
|
|
474
|
-
return x + (b - 128) * 128
|
|
475
|
-
end
|
|
476
|
-
x += b * 128
|
|
477
|
-
|
|
478
|
-
b = cursor.readu8(c)
|
|
479
|
-
if b >= 128 then
|
|
480
|
-
return x + (b - 128) * 16384
|
|
481
|
-
end
|
|
482
|
-
x += b * 16384
|
|
483
|
-
|
|
484
|
-
b = cursor.readu8(c)
|
|
485
|
-
if b >= 128 then
|
|
486
|
-
return x + (b - 128) * 2097152
|
|
487
|
-
end
|
|
488
|
-
x += b * 2097152
|
|
489
|
-
|
|
490
|
-
error "vlq length too large"
|
|
491
|
-
end
|
|
492
|
-
|
|
493
|
-
function cursor.close(c: Cursor): buffer
|
|
494
|
-
local final = buffer.create(c.offset)
|
|
495
|
-
buffer.copy(final, 0, c.buffer, 0, c.offset)
|
|
496
|
-
c.buffer = final
|
|
497
|
-
return final
|
|
498
|
-
end
|
|
499
|
-
|
|
500
|
-
function utils.print_buffer(buf: buffer)
|
|
501
|
-
local bytes = { string.byte(buffer.tostring(buf), 1, -1) }
|
|
502
|
-
return `\{ {buffer.len(buf)}\n Buf: \{ {table.concat(bytes, " ")} \}`
|
|
503
|
-
end
|
|
504
|
-
|
|
505
|
-
utils.cursor = cursor
|
|
506
|
-
|
|
507
|
-
local bitmask = {}
|
|
508
|
-
bitmask.__index = bitmask
|
|
509
|
-
|
|
510
|
-
export type Bitmask = {
|
|
511
|
-
buffer: buffer,
|
|
512
|
-
capacity: number,
|
|
513
|
-
entries: number,
|
|
514
|
-
} & typeof(bitmask)
|
|
515
|
-
|
|
516
|
-
local BITS_PER_ENTRY = 32
|
|
517
|
-
local BYTES_PER_ENTRY = 4
|
|
518
|
-
|
|
519
|
-
function get_entry_bit(index: number): (number, number)
|
|
520
|
-
local entry_index = math.floor(index / BITS_PER_ENTRY)
|
|
521
|
-
local bit_position = index % BITS_PER_ENTRY
|
|
522
|
-
return entry_index, bit_position
|
|
523
|
-
end
|
|
524
|
-
|
|
525
|
-
function bitmask.create(capacity: number?): Bitmask
|
|
526
|
-
local entries_needed = math.ceil(capacity :: number / BITS_PER_ENTRY)
|
|
527
|
-
local buffer_size = entries_needed * BYTES_PER_ENTRY
|
|
528
|
-
|
|
529
|
-
local self = {
|
|
530
|
-
buffer = buffer.create(buffer_size),
|
|
531
|
-
capacity = capacity,
|
|
532
|
-
entries = entries_needed,
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
return setmetatable(self, bitmask) :: any
|
|
536
|
-
end
|
|
537
|
-
|
|
538
|
-
function bitmask.from_set(indexes: { [any]: number }, filter: { [any]: boolean }, capacity: number?): Bitmask
|
|
539
|
-
local newmask = bitmask.create(capacity or 32)
|
|
540
|
-
for player in filter do
|
|
541
|
-
local index = indexes[player]
|
|
542
|
-
if index == nil then
|
|
543
|
-
continue
|
|
544
|
-
end
|
|
545
|
-
bitmask.set(newmask, index)
|
|
546
|
-
end
|
|
547
|
-
return newmask
|
|
548
|
-
end
|
|
549
|
-
|
|
550
|
-
function bitmask.expand(self: Bitmask, capacity: number)
|
|
551
|
-
if capacity <= self.capacity then
|
|
552
|
-
return
|
|
553
|
-
end
|
|
554
|
-
|
|
555
|
-
local new_entries = math.ceil(capacity / BITS_PER_ENTRY)
|
|
556
|
-
local new_buffer_size = new_entries * BYTES_PER_ENTRY
|
|
557
|
-
local new_buffer = buffer.create(new_buffer_size)
|
|
558
|
-
|
|
559
|
-
buffer.copy(new_buffer, 0, self.buffer, 0)
|
|
560
|
-
|
|
561
|
-
for i = self.entries * BYTES_PER_ENTRY, new_buffer_size - 1 do
|
|
562
|
-
buffer.writeu8(new_buffer, i, 0)
|
|
563
|
-
end
|
|
564
|
-
|
|
565
|
-
self.buffer = new_buffer
|
|
566
|
-
self.capacity = capacity
|
|
567
|
-
self.entries = new_entries
|
|
568
|
-
end
|
|
569
|
-
|
|
570
|
-
function bitmask.read(self: Bitmask, index: number): number
|
|
571
|
-
if index >= self.entries then
|
|
572
|
-
return 0
|
|
573
|
-
end
|
|
574
|
-
return buffer.readu32(self.buffer, index * BYTES_PER_ENTRY)
|
|
575
|
-
end
|
|
576
|
-
|
|
577
|
-
function bitmask.write(self: Bitmask, index: number, value: number)
|
|
578
|
-
if index >= self.entries then
|
|
579
|
-
--
|
|
580
|
-
bitmask.expand(self, (index + 1) * BITS_PER_ENTRY)
|
|
581
|
-
end
|
|
582
|
-
buffer.writeu32(self.buffer, index * BYTES_PER_ENTRY, value)
|
|
583
|
-
end
|
|
584
|
-
|
|
585
|
-
-- BIT MANIPULATIONS
|
|
586
|
-
|
|
587
|
-
function bitmask.set(self: Bitmask, index: number)
|
|
588
|
-
if index < 0 then
|
|
589
|
-
error "Bit index cannot be negative"
|
|
590
|
-
end
|
|
591
|
-
|
|
592
|
-
local entry_index, bit_position = get_entry_bit(index)
|
|
593
|
-
local current_value = bitmask.read(self, entry_index)
|
|
594
|
-
local new_value = bit32.bor(current_value, bit32.lshift(1, bit_position))
|
|
595
|
-
bitmask.write(self, entry_index, new_value)
|
|
596
|
-
end
|
|
597
|
-
|
|
598
|
-
function bitmask.get(self: Bitmask, index: number): boolean
|
|
599
|
-
if index < 0 then
|
|
600
|
-
error "Bit index cannot be negative"
|
|
601
|
-
end
|
|
602
|
-
|
|
603
|
-
local entry_index, bit_position = get_entry_bit(index)
|
|
604
|
-
if entry_index >= self.entries then
|
|
605
|
-
return false
|
|
606
|
-
end
|
|
607
|
-
|
|
608
|
-
local current_value = bitmask.read(self, entry_index)
|
|
609
|
-
return bit32.band(current_value, bit32.lshift(1, bit_position)) ~= 0
|
|
610
|
-
end
|
|
611
|
-
|
|
612
|
-
function bitmask.clear(self: Bitmask, index: number)
|
|
613
|
-
if index < 0 then
|
|
614
|
-
error "Bit index cannot be negative"
|
|
615
|
-
end
|
|
616
|
-
|
|
617
|
-
local entry_index, bit_position = get_entry_bit(index)
|
|
618
|
-
if entry_index >= self.entries then
|
|
619
|
-
return
|
|
620
|
-
end
|
|
621
|
-
|
|
622
|
-
local current_value = bitmask.read(self, entry_index)
|
|
623
|
-
local mask = bit32.bnot(bit32.lshift(1, bit_position))
|
|
624
|
-
local new_value = bit32.band(current_value, mask)
|
|
625
|
-
bitmask.write(self, entry_index, new_value)
|
|
626
|
-
end
|
|
627
|
-
|
|
628
|
-
-- BITWISE OPERATIONS
|
|
629
|
-
|
|
630
|
-
function bitmask.band(self: Bitmask, other: Bitmask): Bitmask
|
|
631
|
-
local max_entries = math.max(self.entries, other.entries)
|
|
632
|
-
local result = bitmask.create(max_entries * BITS_PER_ENTRY)
|
|
633
|
-
|
|
634
|
-
for i = 0, max_entries - 1 do
|
|
635
|
-
local value1 = bitmask.read(self, i)
|
|
636
|
-
local value2 = bitmask.read(other, i)
|
|
637
|
-
bitmask.write(result, i, bit32.band(value1, value2))
|
|
638
|
-
end
|
|
639
|
-
|
|
640
|
-
return result
|
|
641
|
-
end
|
|
642
|
-
|
|
643
|
-
function bitmask.bor(self: Bitmask, other: Bitmask): Bitmask
|
|
644
|
-
local max_entries = math.max(self.entries, other.entries)
|
|
645
|
-
local result = bitmask.create(max_entries * BITS_PER_ENTRY)
|
|
646
|
-
|
|
647
|
-
for i = 0, max_entries - 1 do
|
|
648
|
-
local value1 = bitmask.read(self, i)
|
|
649
|
-
local value2 = bitmask.read(other, i)
|
|
650
|
-
bitmask.write(result, i, bit32.bor(value1, value2))
|
|
651
|
-
end
|
|
652
|
-
|
|
653
|
-
return result
|
|
654
|
-
end
|
|
655
|
-
|
|
656
|
-
function bitmask.bxor(self: Bitmask, other: Bitmask): Bitmask
|
|
657
|
-
local max_entries = math.max(self.entries, other.entries)
|
|
658
|
-
local result = bitmask.create(max_entries * BITS_PER_ENTRY)
|
|
659
|
-
|
|
660
|
-
for i = 0, max_entries - 1 do
|
|
661
|
-
local value1 = bitmask.read(self, i)
|
|
662
|
-
local value2 = bitmask.read(other, i)
|
|
663
|
-
bitmask.write(result, i, bit32.bxor(value1, value2))
|
|
664
|
-
end
|
|
665
|
-
|
|
666
|
-
return result
|
|
667
|
-
end
|
|
668
|
-
|
|
669
|
-
function bitmask.bnot(self: Bitmask): Bitmask
|
|
670
|
-
local result = bitmask.create(self.capacity)
|
|
671
|
-
|
|
672
|
-
for i = 0, self.entries - 1 do
|
|
673
|
-
local value = bitmask.read(self, i)
|
|
674
|
-
bitmask.write(result, i, bit32.bnot(value))
|
|
675
|
-
end
|
|
676
|
-
|
|
677
|
-
return result
|
|
678
|
-
end
|
|
679
|
-
|
|
680
|
-
function bitmask.clone(self: Bitmask): Bitmask
|
|
681
|
-
local result = bitmask.create(self.capacity)
|
|
682
|
-
buffer.copy(result.buffer, 0, self.buffer, 0, self.entries * BYTES_PER_ENTRY)
|
|
683
|
-
return result
|
|
684
|
-
end
|
|
685
|
-
|
|
686
|
-
function bitmask.remap(self: Bitmask, from: { [any]: number }, to: { [any]: number }, new_capacity: number?): Bitmask
|
|
687
|
-
local result = bitmask.create(new_capacity or BITS_PER_ENTRY)
|
|
688
|
-
for member, index in to do
|
|
689
|
-
local old_index = from[member]
|
|
690
|
-
if old_index then
|
|
691
|
-
local old_bit = bitmask.get(self, old_index)
|
|
692
|
-
if old_bit then
|
|
693
|
-
bitmask.set(result, index)
|
|
694
|
-
else
|
|
695
|
-
bitmask.clear(result, index)
|
|
696
|
-
end
|
|
697
|
-
end
|
|
698
|
-
end
|
|
699
|
-
return result
|
|
700
|
-
end
|
|
701
|
-
|
|
702
|
-
function bitmask.lshift(self: Bitmask, n: number): Bitmask
|
|
703
|
-
if n <= 0 then
|
|
704
|
-
return bitmask.clone(self)
|
|
705
|
-
end
|
|
706
|
-
|
|
707
|
-
local entry_shift = math.floor(n / BITS_PER_ENTRY)
|
|
708
|
-
local bit_shift = n % BITS_PER_ENTRY
|
|
709
|
-
|
|
710
|
-
local result = bitmask.create(self.capacity + n)
|
|
711
|
-
|
|
712
|
-
if bit_shift == 0 then
|
|
713
|
-
for i = 0, self.entries - 1 do
|
|
714
|
-
local value = bitmask.read(self, i)
|
|
715
|
-
bitmask.write(result, i + entry_shift, value)
|
|
716
|
-
end
|
|
717
|
-
else
|
|
718
|
-
local carry = 0
|
|
719
|
-
for i = 0, self.entries - 1 do
|
|
720
|
-
local value = bitmask.read(self, i)
|
|
721
|
-
local shifted_value = bit32.lshift(value, bit_shift)
|
|
722
|
-
local new_carry = bit32.rshift(value, BITS_PER_ENTRY - bit_shift)
|
|
723
|
-
|
|
724
|
-
bitmask.write(result, i + entry_shift, bit32.bor(shifted_value, carry))
|
|
725
|
-
carry = new_carry
|
|
726
|
-
end
|
|
727
|
-
|
|
728
|
-
if carry ~= 0 then
|
|
729
|
-
bitmask.write(result, self.entries + entry_shift, carry)
|
|
730
|
-
end
|
|
731
|
-
end
|
|
732
|
-
|
|
733
|
-
return result
|
|
734
|
-
end
|
|
735
|
-
|
|
736
|
-
function bitmask.rshift(self: Bitmask, n: number): Bitmask
|
|
737
|
-
if n <= 0 then
|
|
738
|
-
return bitmask.clone(self)
|
|
739
|
-
end
|
|
740
|
-
|
|
741
|
-
local entry_shift = math.floor(n / BITS_PER_ENTRY)
|
|
742
|
-
local bit_shift = n % BITS_PER_ENTRY
|
|
743
|
-
|
|
744
|
-
if entry_shift >= self.entries then
|
|
745
|
-
return bitmask.create(32)
|
|
746
|
-
end
|
|
747
|
-
|
|
748
|
-
local result = bitmask.create(self.capacity)
|
|
749
|
-
|
|
750
|
-
if bit_shift == 0 then
|
|
751
|
-
for i = entry_shift, self.entries - 1 do
|
|
752
|
-
local value = bitmask.read(self, i)
|
|
753
|
-
bitmask.write(result, i - entry_shift, value)
|
|
754
|
-
end
|
|
755
|
-
else
|
|
756
|
-
for i = entry_shift, self.entries - 1 do
|
|
757
|
-
local value = bitmask.read(self, i)
|
|
758
|
-
local shifted_value = bit32.rshift(value, bit_shift)
|
|
759
|
-
|
|
760
|
-
local next_value = 0
|
|
761
|
-
if i + 1 < self.entries then
|
|
762
|
-
next_value = bitmask.read(self, i + 1)
|
|
763
|
-
end
|
|
764
|
-
local overflow = bit32.lshift(next_value, BITS_PER_ENTRY - bit_shift)
|
|
765
|
-
|
|
766
|
-
bitmask.write(result, i - entry_shift, bit32.bor(shifted_value, overflow))
|
|
767
|
-
end
|
|
768
|
-
end
|
|
769
|
-
|
|
770
|
-
return result
|
|
771
|
-
end
|
|
772
|
-
|
|
773
|
-
local function tobinary(n: number): string
|
|
774
|
-
if n == 0 then
|
|
775
|
-
return "0"
|
|
776
|
-
end
|
|
777
|
-
|
|
778
|
-
local result = ""
|
|
779
|
-
while n > 0 do
|
|
780
|
-
result = (n % 2) .. result
|
|
781
|
-
n = math.floor(n / 2)
|
|
782
|
-
end
|
|
783
|
-
return string.rep("0", 8 - #result) .. result
|
|
784
|
-
end
|
|
785
|
-
|
|
786
|
-
local BYTES = table.create(6)
|
|
787
|
-
|
|
788
|
-
function bitmask.tostring(self: Bitmask): string
|
|
789
|
-
local buf = self.buffer
|
|
790
|
-
|
|
791
|
-
local highest_entry = -1
|
|
792
|
-
for i = self.entries - 1, 0, -1 do
|
|
793
|
-
local value = buffer.readu32(buf, i * BYTES_PER_ENTRY)
|
|
794
|
-
if value ~= 0 then
|
|
795
|
-
highest_entry = i
|
|
796
|
-
break
|
|
797
|
-
end
|
|
798
|
-
end
|
|
799
|
-
|
|
800
|
-
if highest_entry == -1 then
|
|
801
|
-
return ""
|
|
802
|
-
end
|
|
803
|
-
|
|
804
|
-
table.clear(BYTES)
|
|
805
|
-
local str = ""
|
|
806
|
-
for i = 0, highest_entry do
|
|
807
|
-
str = str .. tobinary(buffer.readu32(buf, i * BYTES_PER_ENTRY))
|
|
808
|
-
--table.insert(BYTES, buffer.readu32(buf, i * BYTES_PER_ENTRY))
|
|
809
|
-
end
|
|
810
|
-
|
|
811
|
-
--return table.concat(BYTES, "-")
|
|
812
|
-
return str
|
|
77
|
+
-- without preregistration the replecs components live in the world itself;
|
|
78
|
+
-- created once the world is known (create or init), named and given the same
|
|
79
|
+
-- metadata the preregistered set gets
|
|
80
|
+
function utils.create_world_components(world: World): types.Components
|
|
81
|
+
local components = utils.create_components(utils.tag_factory(world), utils.component_factory(world))
|
|
82
|
+
utils.add_component_names(components, function(component, name)
|
|
83
|
+
common.add_name(world, component, name)
|
|
84
|
+
end)
|
|
85
|
+
jecs.meta(components.custom, jecs.Exclusive)
|
|
86
|
+
return components
|
|
813
87
|
end
|
|
814
88
|
|
|
815
|
-
utils.bitmask = {
|
|
816
|
-
create = bitmask.create,
|
|
817
|
-
from_set = bitmask.from_set,
|
|
818
|
-
}
|
|
819
|
-
|
|
820
89
|
function utils.is_client_valid(player: any): boolean
|
|
821
90
|
if game then
|
|
822
91
|
if typeof(player) == "Instance" then
|
|
@@ -828,43 +97,4 @@ function utils.is_client_valid(player: any): boolean
|
|
|
828
97
|
return true
|
|
829
98
|
end
|
|
830
99
|
|
|
831
|
-
function utils.vlq_span(length: number): number
|
|
832
|
-
if length < 0x80 then
|
|
833
|
-
return 1
|
|
834
|
-
elseif length < 0x4000 then
|
|
835
|
-
return 2
|
|
836
|
-
elseif length < 0x200000 then
|
|
837
|
-
return 3
|
|
838
|
-
else
|
|
839
|
-
return 4
|
|
840
|
-
end
|
|
841
|
-
end
|
|
842
|
-
|
|
843
|
-
function utils.number_span(n: number): number
|
|
844
|
-
if n <= 0xFF then
|
|
845
|
-
return 1
|
|
846
|
-
elseif n <= 0xFFFF then
|
|
847
|
-
return 2
|
|
848
|
-
else
|
|
849
|
-
return 4 -- cant read 24 bits
|
|
850
|
-
end
|
|
851
|
-
end
|
|
852
|
-
|
|
853
|
-
function utils.read_number(buf: buffer, offset: number, span: number): (number, number)
|
|
854
|
-
if span == 1 then
|
|
855
|
-
return buffer.readu8(buf, offset), offset + 1
|
|
856
|
-
elseif span == 2 then
|
|
857
|
-
return buffer.readu16(buf, offset), offset + 2
|
|
858
|
-
else
|
|
859
|
-
return buffer.readu32(buf, offset), offset + 4
|
|
860
|
-
end
|
|
861
|
-
end
|
|
862
|
-
|
|
863
|
-
function utils.setbit(mask: number, bit: number)
|
|
864
|
-
return bit32.bor(mask, bit32.lshift(1, bit))
|
|
865
|
-
end
|
|
866
|
-
function utils.checkbit(mask: number, bit: number)
|
|
867
|
-
return bit32.band(mask, bit32.lshift(1, bit)) ~= 0
|
|
868
|
-
end
|
|
869
|
-
|
|
870
100
|
return utils
|