@axpecter/lync 2.2.0 → 2.3.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.
Files changed (62) hide show
  1. package/README.md +95 -143
  2. package/package.json +1 -1
  3. package/src/Types.luau +22 -16
  4. package/src/api/Group.luau +40 -33
  5. package/src/api/Packet.luau +95 -72
  6. package/src/api/Query.luau +128 -79
  7. package/src/api/Scope.luau +26 -10
  8. package/src/api/Signal.luau +43 -52
  9. package/src/codec/Base.luau +21 -14
  10. package/src/codec/composite/Array.luau +56 -134
  11. package/src/codec/composite/Map.luau +103 -72
  12. package/src/codec/composite/Optional.luau +6 -2
  13. package/src/codec/composite/Shared.luau +160 -69
  14. package/src/codec/composite/Struct.luau +283 -42
  15. package/src/codec/composite/Tagged.luau +13 -16
  16. package/src/codec/composite/Tuple.luau +21 -15
  17. package/src/codec/datatype/Buffer.luau +6 -4
  18. package/src/codec/datatype/CFrame.luau +56 -44
  19. package/src/codec/datatype/Color.luau +10 -10
  20. package/src/codec/datatype/Instance.luau +15 -12
  21. package/src/codec/datatype/IntVector.luau +2 -2
  22. package/src/codec/datatype/NumberRange.luau +15 -8
  23. package/src/codec/datatype/Ray.luau +13 -14
  24. package/src/codec/datatype/Rect.luau +12 -12
  25. package/src/codec/datatype/Region.luau +13 -14
  26. package/src/codec/datatype/Sequence.luau +87 -65
  27. package/src/codec/datatype/String.luau +17 -10
  28. package/src/codec/datatype/UDim.luau +10 -8
  29. package/src/codec/datatype/Vector.luau +20 -59
  30. package/src/codec/meta/Auto.luau +94 -126
  31. package/src/codec/meta/Bitfield.luau +12 -14
  32. package/src/codec/meta/Custom.luau +3 -1
  33. package/src/codec/meta/Enum.luau +9 -9
  34. package/src/codec/meta/Float.luau +6 -28
  35. package/src/codec/meta/Nothing.luau +1 -1
  36. package/src/codec/meta/Unknown.luau +10 -7
  37. package/src/codec/primitive/Bool.luau +6 -4
  38. package/src/codec/primitive/Float16.luau +5 -2
  39. package/src/codec/primitive/Int.luau +5 -6
  40. package/src/codec/primitive/Number.luau +6 -4
  41. package/src/codec/primitive/Signed.luau +2 -2
  42. package/src/codec/primitive/Varint.luau +69 -38
  43. package/src/index.d.ts +161 -53
  44. package/src/init.luau +123 -102
  45. package/src/internal/Baseline.luau +9 -1
  46. package/src/internal/Channel.luau +153 -154
  47. package/src/internal/Middleware.luau +22 -6
  48. package/src/internal/Pool.luau +12 -4
  49. package/src/internal/Registry.luau +25 -16
  50. package/src/internal/Transport.luau +1 -1
  51. package/src/transport/Bridge.luau +47 -33
  52. package/src/transport/Client.luau +25 -21
  53. package/src/transport/Gate.luau +227 -172
  54. package/src/transport/Reader.luau +162 -105
  55. package/src/transport/Server.luau +46 -57
  56. package/src/util/Array.luau +18 -0
  57. package/src/util/Buffer.luau +92 -0
  58. package/src/util/Constants.luau +30 -0
  59. package/src/util/Log.luau +68 -0
  60. package/src/util/Player.luau +14 -0
  61. package/src/util/Quantize.luau +60 -0
  62. package/src/internal/Util.luau +0 -26
@@ -0,0 +1,30 @@
1
+ --!strict
2
+ --!optimize 2
3
+ -- Wire-format constants and integer limits shared across codecs.
4
+
5
+ -- Public -----------------------------------------------------------------
6
+
7
+ local Constants = {}
8
+
9
+ Constants.U8_MAX = 0xFF
10
+ Constants.U16_MAX = 0xFFFF
11
+ Constants.U32_MAX = 0xFFFFFFFF
12
+
13
+ Constants.I8_MIN = -0x80
14
+ Constants.I8_MAX = 0x7F
15
+ Constants.I16_MIN = -0x8000
16
+ Constants.I16_MAX = 0x7FFF
17
+ Constants.I32_MIN = -0x80000000
18
+ Constants.I32_MAX = 0x7FFFFFFF
19
+
20
+ --[[
21
+ Frame header byte: MSB = single-item (no count cell); cleared = multi-item
22
+ (u16 count follows). Low 7 bits = registration id (caps registry at 128).
23
+ ]]
24
+ Constants.FRAME_MSB = 0x80
25
+ Constants.FRAME_ID_MASK = 0x7F
26
+
27
+ -- u16 count cell.
28
+ Constants.MAX_BATCH_ITEMS = 0xFFFF
29
+
30
+ return table.freeze(Constants)
@@ -0,0 +1,68 @@
1
+ --!strict
2
+ --!optimize 2
3
+ -- Centralized warn/error/assert. Project name + caller source come from here.
4
+
5
+ -- State ------------------------------------------------------------------
6
+
7
+ -- Module-level so tests mute the whole library without threading a flag.
8
+ local _silent = false
9
+
10
+ -- Constants --------------------------------------------------------------
11
+
12
+ local PREFIX = "[Lync]"
13
+
14
+ -- Private ----------------------------------------------------------------
15
+
16
+ --[[
17
+ Stack levels: 1=this fn, 2=Log.warn/error/assert, 3=user. We want #3 so
18
+ the source/line/name point at the actual caller, not at Log.
19
+
20
+ Source comes back as a dotted Roblox path (e.g. "ServerScriptService.
21
+ MainModule.Lync.codec.primitive.Int" or "...test.unit.api.Packet.spec").
22
+ `.spec` is a literal dot in test ModuleScript names, so split-on-dot
23
+ would yield the meaningless tail "spec"; check the .spec suffix first
24
+ and recover the meaningful segment, then fall back to the last segment.
25
+ ]]
26
+ local function format(message: string): string
27
+ local source, line, name = debug.info(3, "sln")
28
+ local file = source:match("([^.]+)%.spec$") or source:match("[^./\\]+$") or source
29
+ if name and name ~= "" then
30
+ return `{PREFIX} {file}:{line} ({name}) {message}`
31
+ end
32
+ return `{PREFIX} {file}:{line} {message}`
33
+ end
34
+
35
+ -- Public -----------------------------------------------------------------
36
+
37
+ local Log = {}
38
+
39
+ function Log.warn(message: string): ()
40
+ if not _silent then
41
+ warn(format(message))
42
+ end
43
+ end
44
+
45
+ -- level 2 so the runtime traceback points at the caller, not at Log.
46
+ function Log.error(message: string): never
47
+ error(format(message), 2)
48
+ end
49
+
50
+ --[[
51
+ NOTE: Luau evaluates args eagerly. `format(message)` runs even when cond
52
+ is true, paying one debug.info call per Log.assert call. Use only with
53
+ LITERAL strings (no interpolation). For interpolated messages prefer
54
+ `if cond then Log.error(...) end`.
55
+ ]]
56
+ function Log.assert<T>(cond: T, message: string): T
57
+ return assert(cond, format(message))
58
+ end
59
+
60
+ function Log.setSilent(silent: boolean): ()
61
+ _silent = silent
62
+ end
63
+
64
+ function Log.reset(): ()
65
+ _silent = false
66
+ end
67
+
68
+ return table.freeze(Log)
@@ -0,0 +1,14 @@
1
+ --!strict
2
+ --!optimize 2
3
+ -- Player Instance type guard.
4
+
5
+ -- Public -----------------------------------------------------------------
6
+
7
+ local Player = {}
8
+
9
+ -- typeof first: :IsA errors on non-Instances.
10
+ function Player.is(value: any): boolean
11
+ return typeof(value) == "Instance" and value:IsA("Player")
12
+ end
13
+
14
+ return table.freeze(Player)
@@ -0,0 +1,60 @@
1
+ --!strict
2
+ --!optimize 2
3
+ -- Fixed-point range quantizer setup shared by float and vector codecs.
4
+
5
+ local Log = require(script.Parent.Log)
6
+
7
+ -- Private ----------------------------------------------------------------
8
+
9
+ local ceil = math.ceil
10
+ local maxN = math.max
11
+ local minN = math.min
12
+
13
+ -- Public -----------------------------------------------------------------
14
+
15
+ local Quantize = {}
16
+
17
+ --[[
18
+ Pick the narrowest u8/u16/u32 wire form for [rangeMin, rangeMax] at
19
+ `precision`. Returns (compBytes, wfn, rfn, scale, invScale, delta).
20
+ `apiName` shows in error messages so callers see their public surface.
21
+ ]]
22
+ function Quantize.setup(
23
+ apiName: string,
24
+ rangeMin: number,
25
+ rangeMax: number,
26
+ precision: number
27
+ ): (
28
+ number,
29
+ (buffer, number, number) -> (),
30
+ (buffer, number) -> number,
31
+ number,
32
+ number,
33
+ number
34
+ )
35
+ if rangeMin > rangeMax then
36
+ Log.error(`{apiName}: min ({rangeMin}) must be <= max ({rangeMax})`)
37
+ end
38
+ if precision <= 0 then
39
+ Log.error(`{apiName}: precision must be positive, got {precision}`)
40
+ end
41
+
42
+ local delta = rangeMax - rangeMin
43
+ -- Clamp to [1, U32_MAX] so wire-form selection has a valid value.
44
+ local maxInt = minN(0xFFFFFFFF, maxN(1, ceil(delta / precision)))
45
+
46
+ local compBytes: number
47
+ local wfn: (buffer, number, number) -> ()
48
+ local rfn: (buffer, number) -> number
49
+ if maxInt <= 0xFF then
50
+ compBytes, wfn, rfn = 1, buffer.writeu8, buffer.readu8
51
+ elseif maxInt <= 0xFFFF then
52
+ compBytes, wfn, rfn = 2, buffer.writeu16, buffer.readu16
53
+ else
54
+ compBytes, wfn, rfn = 4, buffer.writeu32, buffer.readu32
55
+ end
56
+
57
+ return compBytes, wfn, rfn, maxInt / delta, delta / maxInt, delta
58
+ end
59
+
60
+ return table.freeze(Quantize)
@@ -1,26 +0,0 @@
1
- --!strict
2
- --!optimize 2
3
- -- Cross-module utility helpers.
4
-
5
- -- Public -----------------------------------------------------------------
6
-
7
- local Util = {}
8
-
9
- function Util.isPlayer(value: any): boolean
10
- return typeof(value) == "Instance" and (value :: Instance):IsA("Player")
11
- end
12
-
13
- --[[
14
- O(1) array remove via swap with last element. The slot becomes nil
15
- after this returns; callers that track an external count must
16
- decrement it themselves.
17
- ]]
18
- function Util.swapRemove<T>(arr: { T }, idx: number): ()
19
- local last = #arr
20
- if idx ~= last then
21
- arr[idx] = arr[last]
22
- end
23
- arr[last] = nil
24
- end
25
-
26
- return table.freeze(Util)